3. 物理层编码与加扰
各位做PCIe的同行,咱们今天聊聊物理层最底层的那些事——编码和加扰。说实话,很多工程师觉得这部分是芯片设计的事,跟自己关系不大。但我做了这么多年信号完整性,可以负责任地告诉你:不懂编码,你连眼图为什么闭合都分析不明白。
PCIe从Gen1到Gen5,编码方案经历了两次重大变革。咱们一个一个说。
3.1 8b/10b编码:Gen1/Gen2的基石
8b/10b编码,说白了就是把8位数据变成10位传输。为什么要多花25%的带宽做这件事?我刚开始接触时也觉得浪费,直到有一次在实验室里盯着示波器发呆……
核心目的有三个:
- 直流平衡:保证传输线上0和1的数量基本相等,避免电荷积累
- 时钟恢复:保证足够的跳变密度,接收端才能锁住时钟
- 特殊字符:预留K码用于链路管理(比如SKP、COM等)
8b/10b的编码表我就不全列了,几百行呢。但你要记住一个关键点:运行差异度(RD)。每个编码器都维护一个RD状态机,当前发送的1比0多,RD就是正;反之是负。编码时根据当前RD选择正负两种编码之一,保证长期直流平衡。
避坑指南:我曾经遇到过一个案例,某芯片的8b/10b编码器在RD状态机复位时没处理好,导致链路训练时连续发送了几个极性错误的码字。结果就是——链路能训练成功,但跑压力测试时随机出现CRC错误。查了整整两周,最后用逻辑分析仪抓K码序列才发现问题。
8b/10b的跳变密度保证在20%以上,这对Gen1(2.5GT/s)和Gen2(5GT/s)来说足够了。但到了Gen3(8GT/s),25%的开销就太奢侈了——于是128b/130b登场。
3.2 128b/130b编码:Gen3及以后的效率革命
128b/130b,顾名思义,128位数据只加2位同步头,开销从25%骤降到1.56%。效率提升是巨大的,但代价呢?
代价就是不再保证直流平衡和跳变密度。128b/130b只做两件事:
- 加2位同步头(01或10),用于帧边界锁定
- 配合加扰器保证数据随机性
同步头的含义很简单:
| 同步头 | 含义 |
|---|---|
| 01 | 数据块(Data Block) |
| 10 | 有序集块(Ordered Set Block) |
注意,11和00是非法组合。接收端通过检测同步头来恢复块边界。我调试Gen3链路时,最常遇到的就是同步头误判——尤其是信号质量差的时候,01和10可能被误判成00或11,导致块同步丢失。
重要提醒:128b/130b本身不保证直流平衡!它完全依赖加扰器来打散数据。如果加扰器失效(比如种子值错误),链路可能因为直流漂移而彻底断开。我在Gen3早期芯片上见过这个问题——加扰器种子在热复位后没正确加载,结果链路训练成功但一传数据就断。
3.3 加扰与解扰:数据随机化的艺术
加扰,说白了就是让数据看起来像随机数。为什么要这么做?
- 避免长串0或长串1(导致时钟恢复失败)
- 降低EMI(能量分散到更宽的频谱)
- 保证128b/130b的直流平衡
PCIe使用线性反馈移位寄存器(LFSR)实现加扰。多项式是:
G(x) = x^16 + x^5 + x^4 + x^3 + 1
初始种子值:0xFFFF(所有位为1)。
加扰过程很简单:发送端把原始数据与LFSR输出逐位异或,接收端用同样的LFSR再异或一次就恢复原数据。嗯,这里要注意——收发双方的LFSR必须完全同步,否则解出来全是错的。
个人经验:我调试Gen3链路时,习惯在测试模式下把加扰器旁路掉,先确认物理层基本通信没问题。然后再打开加扰,看解扰后的数据是否正确。这样能快速定位问题是出在加扰还是出在物理层。
加扰器在每个数据块(128位)后更新一次状态,有序集块不参与加扰。为什么有序集不加密?因为SKP、TS1这些控制序列需要被接收端直接识别,不能加扰。
3.4 数据完整性校验:CRC与LCRC
编码和加扰保证的是传输效率,但数据有没有传错,还得靠校验。
PCIe在物理层使用LCRC(链路层CRC),32位,多项式是:
G(x) = x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1
LCRC覆盖整个TLP(事务层包),包括头和数据。接收端计算LCRC并与发送端附加的LCRC比较,不一致就说明传错了。
但这里有个坑——LCRC只能检错,不能纠错。发现错误后,接收端发NAK要求重传。重传机制由数据链路层负责,物理层只管报错。
| 校验层级 | 覆盖范围 | 检错能力 |
|---|---|---|
| LCRC(链路层) | 整个TLP | 32位CRC,可检测所有1-2位错误、奇数位错误、突发错误≤32位 |
| ECRC(事务层) | TLP头+数据(可选) | 端到端校验,覆盖PCIe域间传输 |
你可能会问:既然有LCRC,为什么还要ECRC?我举个例子——数据从一个PCIe域传到另一个域(比如通过桥片),中间可能经过多个链路。LCRC在每个链路段都会被剥离和重新计算,只有ECRC能保证端到端的完整性。
实战建议:调试链路稳定性时,我习惯同时监控LCRC错误计数器和ECRC错误计数器。如果LCRC错但ECRC没错,说明错误发生在当前链路段且被重传修复了;如果ECRC也错,说明有数据损坏穿透了重传机制——这种情况很少见,但一旦出现,基本可以断定是芯片逻辑bug。
3.5 知识体系总览
下面这张图把编码、加扰、校验的关系梳理清楚了。我画图时习惯把发送路径和接收路径分开,这样调试时能快速定位问题出在哪一端。
这张图把发送路径(上)和接收路径(下)分开画了。你调试时遇到问题,先看是发送端还是接收端,再逐级排查——加扰、编码、校验,一级一级确认。我个人的习惯是:先确认加扰器同步,再确认块同步,最后看CRC。顺序搞反了,你会被各种表象迷惑。
好了,物理层编码这块就聊到这儿。记住一句话:编码解决的是能不能传,加扰解决的是传得好不好,校验解决的是传得对不对。三个环节环环相扣,缺一不可。