1. PCIe 协议概述与层次结构归纳总结
我记得到公司第一天,前辈扔给我一本 PCIe 规范,厚得能垫显示器。他说:“搞信号完整性,先得知道协议长什么样。” 后来我踩了不少坑,才明白这句话有多重。
PCI Express,简称 PCIe,本质上是串行高速总线。它替代了并行的 PCI 和 PCI-X。为什么要串行?说白了,并行总线跑快了,信号歪得没法看。你想想看,几百根线同时翻转,串扰、时序偏差…… 我当年调试 PCI 时,光是等长布线就折腾了两周。
PCIe 的核心思路:用差分对传数据,一条发送、一条接收,跑在高速上,而且支持扩展。一传一收构成一条 lane,一个设备可以用 ×1、×4、×8、×16 甚至 ×32 条 lane 来提升带宽。
1.1 层次结构总览
PCIe 协议把通信拆成三个主要的层,外加一个配置管理层。每层只管自己的事,向上提供接口,向下屏蔽细节。好比快递公司:事务层管包裹种类和收件地址;数据链路层管运输包裹时不出错;物理层管车辆和路况。嗯,这个比喻我常用在培训课上。
我的一点经验:做 SI 仿真时,很多人只盯着物理层的眼图和抖动,忽略了数据链路层的重传机制。其实链路层 CRC 校验失败会触发重传,重传包又改变相位,间接影响眼图闭合。所以仿真时,最好把物理层和链路层的交互一起建模。
1.2 事务层(Transaction Layer)
事务层是 PCIe 的大脑。它把应用层发来的数据打包成 TLP(事务层包),然后交给下面。反过来,收到 TLP 后拆包,识别这是读请求还是写完成。
TLP 包含三类核心信息:
- Header:描述包类型、地址、长度、标签等
- Data Payload:实际数据,最大可达 4096 字节(Gen3 以上)
- 摘要 (可选):ECRC 等端到端校验
PCIe 定义了四种事务类型:
| 事务类型 | 用途 | 例子 |
|---|---|---|
| 存储器 (Memory) | 读写系统内存、显存 | GPU 读写帧缓冲 |
| IO (I/O) | 访问传统 IO 空间 | 旧设备控制寄存器 |
| 配置 (Configuration) | 枚举设备、配置 BAR 等 | BIOS 初始化 |
| 消息 (Message) | 中断、电源管理、错误报告 | MSI 中断 |
我记得有一次排查 NVMe SSD 不掉电场景下的数据损坏。抓 Link 上 TLP 发现有个写请求的地址写错了,导致数据写到了不该去的地方。后来才知道,事务层的地址翻译在虚拟化场景下很容易配错——这是纯协议问题,跟物理层眼图一点关系没有。
1.3 数据链路层(Data Link Layer)
这一层做的事很实在:确保 TLP 可靠传输。它给每个 TLP 加序列号和 LCRC(链路层 CRC),然后接收方要回 Ack 或 Nak DLLP。如果 Nak 或者超时没收到 Ack,发送方就会重传。
核心机制:Ack/Nak 重传 + 流控 (Flow Control)
流控不是调速度,而是信用量 (Credit) 管理。接收方告诉发送方:“我还有多少个 Buffer 能收。” 发送方没拿到信用,就不发。这能防止接收方被撑爆。
⚠ 避坑指南:我曾经在一款 FPGA 的 PCIe 核上调 OCN(片上网络)仲裁。发现数据链路层老是超时重传,带宽上不去。查了三天,居然是流控初期信用值没配够,导致发送方被自己憋死了。后来我把 VC0 的信用初始值改大,问题解决。所以做 SI 仿真前,先确认链路层配置参数是不是对的,否则眼图再好,协议层也会限速。
数据链路层还负责 DLLP(数据链路层包)。DLLP 不是 TLP,它只能在相邻设备间交换,不经过事务层。典型的 DLLP 有:Ack、Nak、InitFC1、UpdateFC 等。你如果想监控链路健康,看 DLLP 错误统计是个好入口。
1.4 物理层(Physical Layer)
物理层是 SI 仿真和测试的主战场。它分为两个子层:
- 逻辑子层:包括 8b/10b(Gen1/2)或 128b/130b(Gen3及以上)编码、加扰、弹性缓冲、符号对齐
- 电气子层:差分驱动、接收均衡、时钟恢复、去加重、LTI 行为等
编码的作用是什么?举个例,8b/10b 能把 1 和 0 的数量平衡,减少直流偏移,方便时钟恢复。我刚开始做 Gen2 仿真时,以为只要调好差分阻抗就够了,结果眼图张开度怎么也上不去。后来发现是编码后的码流里“连0”太多,锁相环丢失锁定。唉,当时要是早点关注编码改变后的频谱峰值就好了。
物理层还有 LTSSM(链路训练与状态机),它负责链路上电、复位、速率协商、宽度协商、电源状态转换。做一致性测试时,LTSSM 的各个状态跳转必须符合规范。比如从 L0 进入 L0s 时,如果发送端过早停掉 Refclk,接收端可能直接掉到 Detect——这问题我在某个 PCIe 背板上碰到过两次。
1.5 配置与管理
PCIe 每个功能都有一组配置空间,大小 4KB。软件通过配置读写来发现设备、分配内存地址(BAR)、设置中断等。我经常在测试中用 Bus/Pin/Function 三元组来定位问题,比用符号名快多了。配置空间里还有能力结构,比如 AER(高级错误报告)、ACS(访问控制服务),这些都是 SI 仿真不需要管,但系统级测试必须验证的内容。
1.6 层次间互动 —— 一个实际例子
假设 CPU 要读 GPU 的显存(内存读请求)。
- 事务层构建一个 Memory Read TLP,填写地址、长度、标签,加上 Header 和 ECRC,转给数据链路层。
- 数据链路层加上序列号和 LCRC,缓存一份副本(万一要重传),然后交给物理层。
- 物理层编码、加扰、串行化,从差分线发出去。接收端物理层恢复时钟、解码、去扰,往上送。
- 数据链路层收到后检查 CRC,回复 Ack,把 TLP 递交给事务层。
- 事务层解析 TLP,把数据给到应用层。
你做 SI 仿真时,通常只关心物理层的信号质量。但如果你发现链路层 CRC 错误率异常高,别急着换 PCB 材料——先查一下是不是流控信用耗尽导致的重传风暴。嗯,这个坑我替你们试过了。
1.7 到底什么是“层次化一致性测试”?
一致性测试不是只测眼图。协议栈有三个层,每一层都有合规点:
- 物理层:眼图模板、抖动、阻抗、S参数、预加重、TX/RX EQ
- 数据链路层:重传超时、信用更新周期、DLLP 格式
- 事务层:TLP 格式、完成超时、标签管理
很多公司只测物理层,觉得过了眼图就 OK。实际系统联调时,要么协议分析仪报链路层错误,要么事务层超时导致驱动蓝屏。所以我的建议是:至少把物理层和链路层的测试覆盖做全,事务层用软件仿真验证。
总结:PCIe 就是三段式结构:事务层 → 数据链路层 → 物理层。每层封装、各有职责。SI 仿真集中在物理层,但理解全栈才能定位真问题。希望这个开头没把你劝退。如果你熟悉了这三个层的协作,后面的仿真和测试你就知道该测什么、该怎么分析。