GTY收发器复位序列:初始化流程与复位控制寄存器
各位工程师朋友,这一章咱们来聊聊GTY收发器的复位序列。说实话,这玩意儿我刚开始接触的时候也头大——复位信号多,时序要求细,稍不注意就容易出问题。但只要你把复位序列搞清楚了,后续的调试工作会顺畅很多。说白了,复位就是给收发器「按下开机键」,但这个过程比想象中要复杂得多。
为什么要设计这么复杂的复位流程?
你想想看,GTY收发器内部有PLL、有CDR、有串并转换、有FIFO缓冲,每个模块上电后都需要一定时间才能稳定工作。如果一股脑全部复位再释放,很可能某个模块还在抖动,另一个已经开始干活了,结果就是链路建立失败。我在一个40G光互联项目里就遇到过这种情况——复位顺序不对,眼图怎么调都张不开。
核心原则:GTY复位采用「分级、分步、可编程」的策略。写代码时一定要按顺序来,别想着一个复位信号搞定所有事。
复位序列的整体流程
我们先看一张总览图,把复位流程跑一遍。我个人习惯把复位分成三个阶段:初始化、PLL锁定、通道复位。
一步一步来:详细的复位步骤
下面我把每个阶段拆开来讲。这些步骤我在《高速接口设计实战》课程里反复强调过,你最好记在笔记本上。
1. 初始化复位
先拉低GTTX_RESET和GTRX_RESET。这里有个坑——这两个信号是低电平有效。我以前带过一个新人,写了个高电平复位,结果仿真过不了,查了半天才发现是极性搞反了。
- TX复位:assert GTTX_RESET = 1'b0,保持至少10μs
- RX复位:assert GTRX_RESET = 1'b0,保持至少10μs
- 释放时先释放TX再释放RX,间隔20μs以上
2. 等待PLL锁定
释放复位后,PLL开始工作。你需要轮询CPLL_LOCK或DPLL_LOCK信号。嗯,这里要注意一点——PLL锁定信号从拉高到真正稳定,中间还有个毛刺窗口期。我个人习惯是检测到锁定后再多等50μs再往下走。
经验技巧:如果用的是外部参考时钟,建议先确认参考时钟稳定后再启动PLL复位流程。我做过一个项目,参考时钟来自一个刚上电的振荡器,PLL怎么都锁不住——后来加了100ms延时才解决。
3. 通道数据通路复位
PLL锁定后,才能操作通道复位。这一步主要通过TX_FSM_RESET和RX_FSM_RESET来控制。复位时间不宜太短,我试验过,至少保持50μs才能保证内部状态机完全复位干净。
复位控制寄存器详解
咱们来看看主要的复位控制寄存器。这些寄存器都在GTY的DRP地址空间中,具体偏移地址请参考对应器件的手册。
| 寄存器名称 | 地址偏移 | 位域 | 功能描述 |
|---|---|---|---|
| GTTX_RESET | 0x000 | [0] | TX PLL及前端复位,低有效 |
| GTRX_RESET | 0x001 | [0] | RX PLL及前端复位,低有效 |
| TX_FSM_RESET | 0x002 | [0] | TX数据通路FSM复位,低有效 |
| RX_FSM_RESET | 0x003 | [0] | RX数据通路FSM复位,低有效 |
| CPLL_RESET | 0x004 | [0] | CPLL单独复位,高有效 |
| DPLL_RESET | 0x005 | [0] | DPLL单独复位,高有效 |
警告:在操作DRP寄存器时,必须等待前一次写操作完成(通过DRP_DONE信号确认)再发起下一次操作。我曾经因为连续快速写寄存器,导致复位配置没有正确加载,整个链路无法建链。
复位完成检测
复位流程走完后,需要通过状态信号来确认复位是否成功:
- TX_RESET_DONE:TX通道复位完成标志
- RX_RESET_DONE:RX通道复位完成标志
- CPLL_LOCK / DPLL_LOCK:PLL锁定状态
这几个信号都拉高后,才能认为复位成功。我建议你在代码里加个超时机制——比如等待5ms还没看到所有done信号,就报个错误并重新触发复位。
典型复位代码框架(Verilog 伪代码):
// 复位序列状态机
always @(posedge clk or posedge rst) begin
if (rst) begin
state <= IDLE;
gttx_reset <= 1'b0;
gtrx_reset <= 1'b0;
end else begin
case (state)
IDLE: begin
// 初始化复位
gttx_reset <= 1'b0;
gtrx_reset <= 1'b0;
state <= WAIT_PLL_LOCK;
end
WAIT_PLL_LOCK: begin
// 等待PLL锁定
if (cpll_lock) begin
state <= RELEASE_TX_RESET;
end
end
RELEASE_TX_RESET: begin
// 释放TX复位
gttx_reset <= 1'b1;
state <= RELEASE_RX_RESET;
end
// ... 后续状态
endcase
end
end
避坑指南
做复位设计这么多年,我踩过的坑真不少。这里挑几个最常见的分享给你:
- 不要同时复位TX和RX:我试过同时释放,结果两个通道的PLL互相干扰,都锁不定。分开操作,间隔100μs左右。
- 注意参考时钟的稳定性:如果参考时钟来自板级振荡器,上电后至少等100ms再操作GTY复位。这个值不算大,但在高速板卡上很实用。
- DRP写入后要检查done:不检查done直接写下一笔,很可能寄存器值没写进去——我当时在FPGA原型验证时抓了三天bug才发现这个问题。
- 复位状态机一定要有超时:万一某个复位信号一直拉不高,没有超时的话整个系统就卡死了。我一般设5ms超时,到了就报错重试。
好了,GTY收发器的复位序列就讲到这里。你实际调试的时候,建议先用chipscope抓一下RESET_DONE和LOCK信号,确认时序对不对。复位如果搞不定,后面的高速链路调试更是白搭。