PCIe 物理层基础:差分信号、8b/10b 编码、帧格式与符号结构
大家好。这一章咱们聊聊 PCIe 物理层的基础。嗯,别看这层名字带“物理”二字就觉得枯燥,其实理解它才能真正看懂 TS1/TS2 在干什么。我个人习惯是先摸透物理层再做协议分析,不然你会觉得链路训练像个黑盒子。
我记得刚接触 PCIe 时,有个项目信号走线没处理好,差分对等长差了十几 mil,结果链路死活上不去 Gen3。最后查了三天,发现是物理层问题。说白了,物理层不稳,上层协议再漂亮也没用。
差分信号:不是两根线那么简单
PCIe 用的是低压差分信号,也就是 LVDS。一对线,一个叫 S+,一个叫 S-。接收端看的不是单端电压,而是两个信号的差值。
- 抗共模干扰:外界噪声同时耦合到两根线上,差值不变。这个特性在实际项目中非常靠谱。
- 低摆幅:电压差只有几百毫伏,功耗低,速度快。
- 等长要求:两条走线长度必须一致。我在项目中遇到过,等长差 50 mil,眼图就明显闭合。
8b/10b 编码:效率与稳定性的平衡
为什么要编这个码?原始 8 位数据直接发,可能连串连续 0 或连续 1,接收端容易丢失时钟同步。8b/10b 编码把 8 位数据变成 10 位符号,保证直流平衡和足够多的跳变。
你想想看,原本 8 位只有 256 种组合,变成 10 位后多了 768 种冗余组合。这些冗余用来做控制符号,比如 TS1/TS2 里的 COM、STS 等。
| 原始 8 位数据 | 编码后 10 位符号 | 备注 |
|---|---|---|
| 0x00 | K28.1 | 逗号符号,用于字节对齐 |
| 0x1C | K28.5 | COM 符号,TS1/TS2 起始标志 |
| 0xBC | K28.7 | 符号边界检测用 |
| 任意数据 | D.x.y | 普通数据符号 |
帧格式与符号结构:数据的骨架
PCIe 的数据不是一股脑儿往外发,而是组织成一个个有序的符号序列。每个符号 10 位,经过串行化后发送。帧格式说白了就是这些符号的排列规则。
一个典型数据帧包括:STP(开始)、序列号、数据负载、CRC、END(结束)。但你得知道,TS1/TS2 这种链路管理序列没有数据负载,它们用的是特定的符号组合。
| 符号类型 | 长度 | 说明 |
|---|---|---|
| STP | 1 符号 | 帧开始,标识 TLP 起始 |
| SDP | 1 符号 | 数据负载开始,紧接在 STP 后 |
| END | 1 符号 | 帧结束,可能带错误标识 |
| COM | 1 符号 | 逗号符号,用于对齐和训练序列 |
| STS | 1 符号 | 训练序列中的控制符号 |
嗯,这里要注意:帧的起始和结束符号都是唯一的,接收端靠它们找到数据边界。我在做协议分析时,经常先抓一串原始符号,然后手工定位 COM 符号的位置。只要 COM 对了,后面的 TS1/TS2 结构就很好拆。
这张图展示了数据从原始字节到差分信号的完整路径。编码层做 8b/10b 转换,帧层把符号组织成帧结构,物理层最终通过差分对发出去。TS1/TS2 训练序列也走这条路径,只不过它们的符号是预设好的,不是普通数据。