Polling状态:目的与子状态
Polling状态,说白了就是链路训练中的"握手磨合"阶段。之前我们在Detect状态确认了对方存在,现在要开始真正对上话了——把时钟对齐、把数据收进来,为后面的训练打好基础。
我记得多年前调试一块PCIe Gen3板卡时,卡在Polling状态三天没过去。最后发现是时钟恢复环路的带宽设得太窄,位锁定死活稳定不下来。嗯,从那以后我每次看Polling阶段的示波器波形,都会多盯一会儿。
Polling的核心目的
这个阶段要完成两件事:
- 位锁定 – 接收器从串行数据流中恢复时钟,找到每个bit的采样点
- 块对齐 – 把连续的bit流切成符合协议规范的符号边界(8B/10B或128B/130B的码组边界)
你想想看,在Detect阶段两端只是确认了"有人",但发送的比特率、时钟相位都是未知的。Polling要让两端在比特层面上同步,否则根本没法理解对方在说什么。
Polling的三个子状态
LTSSM把Polling拆成了三个子状态,一路走下来才能回退:
| 子状态 | 主要任务 | Exit条件(成功时) |
|---|---|---|
| Polling.Active | 发送TS1/TS2有序集,尝试位锁定 | 本地接收器锁定到远端TS1序列 |
| Polling.Compliance | 被动模式,发送Compliance Pattern | 接收器锁定到Compliance Pattern |
| Polling.Configuration | 交换链路配置参数(宽度、速率、极性) | 完成配置且确认对端也完成 |
Polling.Active – 位锁定
进入Polling后,先跑到Active。此时每个lane上都在连续发送TS1有序集。TS1是什么?是一串特定的26-bit符号序列(在8B/10B编码下是26个符号),接收器认识它。
接收器要做的事:
- 从进来的比特流中恢复出参考时钟和采样相位。
- 不断调整采样点,直到连续收到多个正确的10-bit符号(8B/10B的码字)。
- 一旦在特定时间窗口内误码率低于阈值,就算位锁定完成。
这里有个关键指标:接收器锁定时间。PCIe Base Spec规定Polling.Active必须在24 µs内完成位锁定,否则要回退到Detect或重置。实际芯片设计中这个时间通常比规范松很多——但咱们做板级调试时,如果卡在Active超过几十微秒,就要怀疑时钟抖动或差分幅度问题了。
Polling.Compliance – 合规性测试
这个子状态不是正常训练路径的必经路。它是一个可选调试模式:上游端口可以发Compliance Pattern(一串固定比特序列),下游端口用这个pattern来调整自身的接收均衡和时钟恢复。
为什么要有这个?
- 帮助那些没有收到有效TS1的接收器完成锁定
- 作为一致性测试入口(比如插拔测试、眼图余量测试)
说实话,大部分正常上电场景里你不会看到Compliance。我只有一次在实验室用协议分析仪强制进入Compliance,为了看某款芯片的Gen4 TX预加重效果——结果发现它的FFE tap系数和spec差了一档。
Polling.Configuration – 块对齐与参数交换
位锁定搞定之后,进入Configuration。此处核心任务是块对齐——也就是找到帧的起始位置。
对于8B/10B编码,块对齐就是找到码组边界。怎么做?发特殊的"K码"——例如COM符号(K28.5)。接收器在比特流里搜索这个固定图案,一旦找到,就用它作为参考把后续的bit划分成10-bit一组。
你可能会问:如果找不到呢?
它会在每个可能的10-bit窗口滑动,不断尝试匹配。最多滑动10次就能找到正确边界——这就是所谓的符号对齐。
// 伪代码示意:8B/10B 块对齐搜索
for (shift = 0; shift < 10; shift++) {
word = extract_10bit_window(bit_stream, shift);
if (word == COM_SYMBOL_10B) {
block_lock = true;
align_offset = shift;
break;
}
}
块对齐成功后,两端开始交换Link Control (LC) 和 Link Status (LS)信息。具体交换内容:
- Lane极性是否反转(极性反转检测)
- Lane到数据通道的映射(Lane reversal)
- 是否启用Loopback
- 当前链路的Gen版本协商
这些信息编码在TS1和TS2有序集的字段里。发几个回合彼此确认,然后进入L0。整个过程一般需要几百纳秒到几微秒。
Polling阶段状态机总览
下面这张图展示了Polling内部的子状态流转和失败回退路径,我画的时候把最常见的场景标粗了:
关键总结
- Polling的本质是位同步 + 符号同步,为后续的配置和正常传输打基础。
- 子状态链路:Active(位锁定) → Configuration(块对齐与参数交换) → L0。
- Compliance是调试利器,正常训练不会走它。
- 任何子状态长时间卡住,最终都会回退到Detect重新开始。