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.Compliance其实是一个调试入口。如果链路死活进不了Configuration,可以强制让对端进入Compliance模式,然后用示波器看发送的pattern是否合规。我遇到过几次板子layout走线过长导致信号变形,就是通过这个方法定位的。

Polling.Active – 位锁定

进入Polling后,先跑到Active。此时每个lane上都在连续发送TS1有序集。TS1是什么?是一串特定的26-bit符号序列(在8B/10B编码下是26个符号),接收器认识它。

接收器要做的事:

  1. 从进来的比特流中恢复出参考时钟和采样相位。
  2. 不断调整采样点,直到连续收到多个正确的10-bit符号(8B/10B的码字)。
  3. 一旦在特定时间窗口内误码率低于阈值,就算位锁定完成。

这里有个关键指标:接收器锁定时间。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;
    }
}
避坑指南:我曾经碰到过一块老旧的PCIe Gen2桥片,它在Configuration阶段总是报块对齐失败。深挖后发现它内部的ELEC_EVAGUATION时序处理有bug,导致进入配置时lane状态未完全清除。当时的临时方案是手动拉长Power State的转换延迟。

块对齐成功后,两端开始交换Link Control (LC) 和 Link Status (LS)信息。具体交换内容:

  • Lane极性是否反转(极性反转检测)
  • Lane到数据通道的映射(Lane reversal)
  • 是否启用Loopback
  • 当前链路的Gen版本协商

这些信息编码在TS1和TS2有序集的字段里。发几个回合彼此确认,然后进入L0。整个过程一般需要几百纳秒到几微秒。

Polling阶段状态机总览

下面这张图展示了Polling内部的子状态流转和失败回退路径,我画的时候把最常见的场景标粗了:

Polling 子状态机 Detect L0 Polling.Active 发送TS1,位锁定 Polling.Compliance Compliance Pattern Polling.Configuration 块对齐,参数交换 未锁定且超时 位锁定成功 锁定失败 完成 多次失败 → Detect 🔍 注意 • Polling.Active必须在24µs内完成位锁定,否则回退或进入Compliance • Configuration阶段块对齐通常只需几个符号周期,失败则回Detect重新训练

关键总结

  • Polling的本质是位同步 + 符号同步,为后续的配置和正常传输打基础。
  • 子状态链路:Active(位锁定) → Configuration(块对齐与参数交换) → L0。
  • Compliance是调试利器,正常训练不会走它。
  • 任何子状态长时间卡住,最终都会回退到Detect重新开始。