PCIe体系结构:层次化模型与拓扑结构

做硬件设计这些年,我遇到不少新人问:“PCIe到底长什么样?”

说白了,它就是一台精密的通信机器。这台机器有三层分工,外加一套成熟的连接体系。我个人习惯先理解层次化模型,再去看拓扑结构。今天我们就从内到外,把这套体系摸透。

层次化模型:三层架构

PCIe采用分层设计,从上到下分别是事务层、数据链路层、物理层。每层各司其职,又紧密配合。我在项目中调试链路时,最喜欢先看是哪层出了问题,能省不少时间。

层级 缩写 核心职责 处理的数据单位
事务层 TL 组装/解析事务层包(TLP),处理读写请求、完成消息 TLP
数据链路层 DLL 保证TLP无差错传输,管理链路状态 DLLP
物理层 PHY 串行化/解串,处理电气信号、链路训练 PLP / 有序集

事务层(Transaction Layer)

事务层是最贴近软件的一层。它接收来自设备核心或CPU的请求,把数据、地址、属性打包成TLP。

TLP有四种类型:Memory、IO、Configuration、Message。我个人做存储卡项目时,最常打交道的就是Memory读写TLP。

关键点:事务层不关心物理信号。它只负责“包装”和“拆包”。你想想看,就像一个快递分拣中心,只管贴单子、扫码,不管车子怎么开。

TLP的头部格式因类型而异,我列一个Memory读写TLP的简化头部结构供参考:

Byte 0-3:   Fmt + Type (指示格式和类型)
Byte 4-7:   Length (数据载荷长度,单位DW)
Byte 8-15:  Requester ID + Tag (请求者标识)
Byte 16-23: Address (目标地址) 或 First DW BE + Last DW BE
...         Data Payload (0~1024 DW)

注意,TLP最大数据载荷是1024个双字(4KB),但实际设备通常只支持128或256字节。我建议设计时先确认设备能力,否则链路上会出现分割传输,影响性能。

数据链路层(Data Link Layer)

这一层负责链路的可靠传输。它给每个TLP加上序列号和CRC校验码,生成DLLP(数据链路层包)进行确认、重传、电源管理。

  • ACK/NAK协议:发送端保存TLP副本,直到收到接收端的ACK。收到NAK则重发。我调试过一块老是丢包的FPGA板卡,最后发现是DLL层重传缓冲区溢出。嗯,这里要注意:重传缓冲区不能设太小。
  • 流量控制(Flow Control):接收端通过DLLP通告自己的缓冲区剩余大小,发送端按量发送,防止丢数据。
  • 错误检测:每收到一个TLP都做CRC校验,错误立即回复NAK。
我的经验:链路不稳定时,先查数据链路层的CRC错误计数和NAK重传次数。这两项数据通常直接暴露在配置空间里,很容易抓。

物理层(Physical Layer)

物理层是真正的“电线工”。它把并行的TLP数据串行化成差分信号,通过一对发送、一对接收的Lane传出去。同时,它还要负责链路训练、速率协商、极性反转、扩频时钟同步等杂活。

为什么需要链路训练?

PCIe支持多速率(2.5GT/s、5GT/s、8GT/s等)。上电后双方不知道对方能力,得通过物理层的训练序列(TS1/TS2有序集)一步步握手。我记得有一次做Gen3链路兼容性测试,某款老主板训练到Gen3会失败,最后锁定物理层协商逻辑的timing不达标。折腾好几天。

物理子层 功能
逻辑子层 编解码(8b/10b、128b/130b)、扰码、有序集处理
电气子层 差分驱动、接收均衡、时钟恢复

物理层的数据单位是PLP(物理层包)和有序集。这些结构对软件几乎透明,但硬件工程师必须清楚。

三层之间的协作

数据从应用层向下走,逐层加工。我画张图帮大家理解:

PCIe层次化模型与拓扑结构 事务层 数据链路层 物理层 RC Switch Endpoint 1 Endpoint 2 Endpoint 3 说明: RC和Endpoint内部都有完整的三层结构。 Switch没有事务层,只做转发,但需要数据链路层和物理层。
避坑指南:我曾经在集成一个PCIe Switch时,没给下游端口配足数据链路层缓冲区,结果高负载下疯狂重传。后来查规范才知道,每个端口必须独立维护一套流量控制信用。别想着共用资源能省钱。

拓扑结构:RC、Switch、Endpoint

PCIe的物理拓扑是一个树形结构。怎么理解呢?CPU端接一个根复合体(RC),RC下面挂Switch,Switch再分出去接多个Endpoint。简单、清晰、可扩展。

根复合体(Root Complex, RC)

RC是CPU和PCIe总线的桥梁。它内部集成了至少一个根端口(Root Port),每个根端口对应一个独立的PCIe域。

  • RC负责将CPU的存储器访问转换成PCIe事务。
  • 它生成配置请求,用于枚举总线上的所有设备。
  • RC还处理中断、错误报告等系统级事务。

我调试的服务器主板上通常有2-4个根端口,分别接显卡、NVMe硬盘、网卡。设计时要注意每个根端口的Lane数分配,错了会影响性能。

交换机(Switch)

Switch是PCIe网络的核心扩展设备。它有1个上游端口(Upstream Port)连接RC,多个下游端口(Downstream Port)连接Endpoint。

它内部其实由两个或者多个逻辑PCI-to-PCI桥(PPB)背靠背组成。工作时遵循基于ID的路由规则:根据总线号、设备号、功能号决定转发路径。

关于路由:PCIe有三种路由方式——基于ID的路由、地址路由、隐式路由。Switch主要用ID路由,RC和Endpoint用地址路由。我建议一开始把这三类路由搞清楚,很多调试问题都出在路由上。

端点(Endpoint)

Endpoint是PCIe树上的叶子节点。它不具备转发能力,只能作为请求者或完成者。

  • 传统Endpoint:挂在Switch下游。
  • 根端口集成Endpoint:直接挂在RC上(如显卡)。

端点内部必须实现完整的TL层、DLL层、PHY层。我见过一个做视频采集卡的客户,因为Endpoint的事务层没处理好Completer Abort,经常被操作系统报超时。

数据流动路径

举个例子,CPU从NVMe硬盘读数据:

  1. CPU发送内存读请求给RC。
  2. RC打包成Memory Read TLP,通过上游端口发往Switch。
  3. Switch解析TLP头部,根据目标地址把包转发到连接NVMe的下游端口。
  4. NVMe Endpoint收到TLP后解析,从闪存中读取数据,组装Completion with Data TLP原路返回。
  5. 一路上升,最终数据写入CPU指定的内存地址。

整个过程几乎没有软件介入,全靠硬件分层协作完成。为什么能做到?因为每一层都只处理自己的事。事务层不管路由,数据链路层不管地址,物理层只管传比特。真正做到了各扫门前雪。

总结一张速查表:
组件 常用功能 是否包含事务层
RC 系统集成、配置、中断处理 是
Switch 扩展端口数、隔离流量 否(无TL层,仅有DLL+PHY)
Endpoint 执行具体的I/O功能 是