4. 链路训练状态机:初始化和链路建立过程
链路训练状态机,说白了两边的SerDes怎么从“谁也不认识谁”,一步步变成“可以愉快地收发数据”的过程。我刚开始看这个状态机的时候,觉得挺绕的。后来自己动手调过一次板子,才真正明白——这玩意儿就是串行链路的心脏起搏器。
4.1 状态机总览
链路训练状态机通常包含这几个核心状态:Detect、Polling、Configuration、Idle、Recovery。嗯,咱们一个个来看。
4.2 Detect 状态
上电后,链路训练的第一步就是 Detect。说白了就是:对面的接收器还活着吗?
发送端会发出一个很短的脉冲,看能不能检测到接收端的终端电阻。我个人习惯把这个过程叫作“打个招呼”。如果没回应,就一直在这儿转悠。我记得有一回调试,链路死活起不来,最后发现是PCB走线断裂,Detect阶段就卡死了。
4.3 Polling 状态
Detect 成功之后,进入 Polling。这个阶段要干三件事:
- 信号检测:确认接收端能正常收到差分信号
- 时钟对齐:发送端开始发送训练序列,接收端用CDR锁定时钟
- 极性校准:有些SerDes会自动纠正P/N反接
你想想看,如果CDR没锁定,后面所有数据都是错的。我曾经遇到过一个问题,Polling 阶段时钟能锁上,但误码率高得离谱。排查了半天,发现是参考时钟的抖动太大了。
4.4 Configuration 状态
到了 Configuration,才开始真正交换链路参数。这个过程分成两个子阶段:
| 子阶段 | 做什么 | 关键词 |
|---|---|---|
| Config 0 | 识别通道数量,建立位宽映射 | lane deskew |
| Config 1 | 交换预加重、均衡、速率等信息 | PMA 自适应参数 |
我刚开始做PCIe的时候,觉得Configuration 0很简单,就是对齐几个lane嘛。结果发现不同lane之间的skew有的能差好几个UI,不用deskew根本没法工作。嗯,这个坑踩过一次就记住了。
4.5 Idle 状态
链路建立完成后,就进入 Idle 状态。这时候两边开始传正常的业务数据。
但注意,Idle并不是空闲不动。链路在Idle状态下仍然会定期发送特定码型,保持CDR的锁定状态。说白了就是:“嘿,我还在呢,你别失锁了。”
4.6 Recovery 状态
Recovery 是链路出问题后的自我修复机制。比如出现位错误、时钟失锁、或者信号质量恶化,链路会自动回到Recovery状态进行重新训练。
Recovery 比重新从Detect开始要快得多——它直接从Polling或者Configuration阶段开始尝试恢复。我曾经在高速背板上遇到一个case,板卡热插拔后链路5秒才恢复,就是因为Recovery逻辑没写好,每次都回到了Detect。
4.7 链路建立的典型流程
- 上电/复位:链路进入Detect状态
- 检测通道:确认对端存在
- 信号训练:Polling阶段完成时钟和极性校准
- 参数协商:Configuration阶段交换链路参数
- 正常传输:进入Idle状态
- 异常恢复:错误发生时进入Recovery,完成后回到Idle
4.8 避坑指南
我整理了几个常见的坑,都是我亲手踩过的:
- 时钟源不一致:发送端和接收端不用同一个参考时钟源时,CDR训练可能超时
- 预加重过度:在某些短走线上,预加重反而会加剧ISI,导致训练失败
- 温度漂移:链路在冷启动时训练通过,预热后却进入Recovery——这是温度导致均衡参数失效了
- 电源噪声:PMA对电源敏感,噪声大的时候训练序列解不出来
我曾经在一个项目里,设备在常温下跑得好好的,一进高温箱就掉链子。排查到最后,发现是PMA的均衡器参数太刚性了,没有自适应更新。换成更灵活的算法后,问题就解决了。
你看,链路训练状态机看起来就那么几个状态,但每个状态背后都有很多细节。理解清楚这些细节,调试的时候才能少走弯路。