第一章 PCIe 基础回顾:从总线到分层模型,再到代际演进

咱们开篇先把地基夯实。PCIe 这套东西,你如果光啃 spec 会觉得很抽象,但结合我实际调试中的体会来讲,会好理解很多。

1.1 总线架构:从共享到点对点

早期的 PCI 总线是共享并行架构。什么意思呢?就是所有设备挂在同一条总线上,谁要说话先申请,总线仲裁器点头了你再发。设备一多,带宽就抢来抢去,延迟也上去了。

PCIe 彻底推翻了这种玩法。它换成了点对点串行差分总线。每个设备跟 Root Complex 之间,或者设备跟 Switch 之间,都有自己的专用通道。说白了,就是每条 Lane 都是一条独立的快车道,不再需要排队等仲裁了。我个人习惯把这种架构叫“专线制”,互不干扰。

避坑指南:很多工程师画原理图时,习惯性地把 PCIe 走线归在“总线组”里。我曾经就犯过这个错误——差分对内部的等长、对内 skew 控制,要求比并行总线严格得多,千万别按老思路做。

1.2 分层模型:事务层、数据链路层、物理层

PCIe 协议栈分三层:事务层(TL, Transaction Layer)、数据链路层(DLL, Data Link Layer)、物理层(PHY, Physical Layer)。说人话就是:

  • 事务层:负责把软件发出的读写请求打包成 TLP(Transaction Layer Packet)。你想想看,CPU 想读显卡里的一段数据,这个指令就是从这里变成数据包的。
  • 数据链路层:给 TLP 加上序列号和 CRC 校验,保证数据不丢不坏。它还管流控——告诉发端“我缓冲区还能收几个包,你先等会儿”。
  • 物理层:干脏活的。把数据编码、加扰、串化,然后差分信号发出去。接收端再解串、去扰、解码。Gen1/2 用 8b/10b 编码,Gen3 开始换成 128b/130b,效率高了很多。

我记得刚接触 PCIe 时,总觉得分层模型很抽象。后来在实际定位链路训练失败故障时才发现,每一层都有它独特的问题域:物理层出问题表现为链路无法“Up”,数据链路层出问题表现为 CRC 错误暴增,事务层出问题则可能是 Completion Timeout。你定位问题时,先判断是哪个层出了事,至少能省一半时间。

1.3 链路拓扑:RC、Switch、Endpoint 与树形结构

PCIe 的拓扑是 树形结构。Root Complex(RC)在树根,往下接 Switch,Switch 再接多个 Endpoint(EP)。RC 一般集成在 CPU 里,Switch 就是个大号的分线器。EP 就是显卡、NVMe SSD、网卡这些实际干活的设备。

为什么用树形而不是网状?因为 PCIe 的设计初衷是软件透明枚举。系统启动时,BIOS 从 RC 开始,一层层遍历,给每个设备分配 Bus Number、Device Number、Function Number,以及配置空间里的 MMIO 地址空间。拓扑越简单,枚举越不容易出岔子。

我在项目中遇到过一种奇葩现象:同一块板子,换一个型号的 NVMe SSD 就训练不上,换回原来品牌就正常。查到最后,是 Switch 的 Lane 极性翻转配置不兼容。那种问题,光看软件 log 根本看不出来,必须用示波器抓物理层信号才能找到。

链路拓扑核心要素:
  • RC (Root Complex) — 树根
  • Switch (交换器) — 分支节点
  • EP (Endpoint) — 叶片节点
  • 每对 EP 到 RC 的路径是点对点虚拟通道
  • 支持 Non-Transparent Bridge (NTB) 实现多主机互联
PCIe 系统拓扑结构(树形) Root Complex (RC) CPU 集成 / 芯片组 Switch (上游端口) Switch (上游端口) EP 1 (NVMe) EP 2 (显卡) EP 3 (网卡) EP 4 (FPGA) 数据路径示例:CPU 读 NVMe SSD EP1 (NVMe) → Switch 1 上游端口 → RC → 内存控制器 TLP 逐跳转发,每经过一个 Switch 都要进行路由和重新排队 训练失败往往出在 RC-Switch 或 Switch-EP 之间的某一段

1.4 Gen1/2/3/4/5/6 演进概述

PCIe 代际演进,核心就是两条线:单 Lane 速率和编码效率。我整理了一张表,把关键参数列出来,方便你做方案选型时快速查阅。

代际 单 Lane 速率 (GT/s) 编码方案 x16 总带宽 (GB/s) 信号摆幅 (mV) 均衡化
Gen1 2.5 8b/10b 4 800~1200 无
Gen2 5.0 8b/10b 8 800~1200 无 (可选项)
Gen3 8.0 128b/130b 16 800~1200 CTLE + DFE 必需
Gen4 16.0 128b/130b 32 800~1200 CTLE + DFE 必需
Gen5 32.0 128b/130b 64 800~1000 CTLE + DFE + TX FIR
Gen6 64.0 PAM-4 + 242b/257b 128 约 400~800 多抽头均衡化

几点体会:

  • Gen1 → Gen2:速率翻倍,但编码还是 8b/10b,有 20% 的编码开销。链路训练流程基本一致,兼容性很好。
  • Gen3:是个分水岭。128b/130b 编码让有效带宽大增,但代价是必须引入 CTLE 和 DFE 来对抗信道损耗。我有个朋友做服务器主板,Gen3 信号眼图总是张不开,最后发现是 PCB 过孔残桩没处理好,换了背钻工艺才解决。
  • Gen4:速率再翻倍,对 PCB 材料的要求更高了。低损耗的 Megtron 6 或更高级的材料是常态。做 Gen4 时,我个人习惯一定要做全通道仿真,尤其是包含连接器的链路。
  • Gen5:32 GT/s,NRZ 调制的巅峰。TX FIR 滤波器在这里成了标配,用于预加重和去加重。信道插损预算一般要求在 28 dB 以内(Nyquist 频率)。你想想看,28 dB 的衰减意味着接收到的信号幅度只有发射端的 1/25 左右,差一点都不行。
  • Gen6:改用 PAM-4 调制,每个符号携带 2 bit 信息,加上 242b/257b 编码。速率达到了 64 GT/s,但信号电压裕量大幅缩小,均衡化复杂度也成倍增加。我目前在做 Gen6 的预研项目,光是 CTLE 的离散极点配置就调了三个版本。
注意:Gen3 及以上代际的均衡化参数(Pre-shoot、De-emphasis、CTLE 增益、DFE 抽头系数)是通过链路训练期间的 Equalization Phase 来协商、调整的。如果协商失败,链路会降速到上一代或者彻底训练失败。这是后续章节会重点讲的内容,你先留个印象。