第1章 PCIe 概述:基本概念、版本演进与速率归纳

做高速串行总线这行十几年了,每次新项目拿来,第一件事就是看 PCIe 链路能不能正常协商。很多人觉得链路均衡啊、训练状态啊才是深水区,但说实话,如果连 PCIe 的基本概念和版本速率都搞不清,后面排查故障你会一头雾水。这一章我们就从根上捋一遍——什么是 PCIe,它经历了哪些版本,每个版本能跑多快。嗯,我会加一些自己踩过的坑,帮你少走弯路。

1.1 PCIe 是什么?为什么它不是 PCI 的简单升级?

PCIe 的全称是 Peripheral Component Interconnect Express,翻译过来就是“快捷外设互联”。我是觉得这名字挺直白的——快,而且是串行。

老一点的工程师应该记得 PCI 总线,那是并行架构,共享一条 32 位或 64 位的总线。所有设备挤在同一条线上,谁用谁申请,带宽大家一起分。我记得当年做 PCI 网卡,速率稍微上去一点,信号干扰就来了,调试起来真是头疼。

PCIe 彻底换了个思路:用差分信号(一对发送线、一对接收线)组成一个 Lane,每个 Lane 都是全双工、点对点的串行通道。这意味着什么?说白了,每个设备都有自己的专属通道,不用跟别人抢。多通道还可以捆绑成 x1、x4、x8、x16,带宽直接翻倍。

一个小提醒:虽然名字叫“Express”,但 PCIe 和 PCI 在软件层面是向前兼容的。你在系统里看到的配置空间、枚举方式,底层逻辑基本沿袭了 PCI 那套。所以学 PCIe 之前,懂点 PCI 基础会轻松很多。

1.2 核心概念:Lane、Link 与拓扑结构

要调试 PCIe 链路均衡,三个词你必须烂熟于心:Lane、Link、拓扑。

  • Lane:最基本的物理通道,由一对发送差分对(TX+ / TX-)和一对接收差分对(RX+ / RX-)组成。每个 Lane 都是独立的双向链路。
  • Link:把多个 Lane 捆绑到一起形成的逻辑链路。比如 x16 就是 16 个 Lane 同时工作。注意,Lane 的数量必须在链路训练时协商一致,两边必须对等。
  • 拓扑:典型的 PCIe 系统是一个树形结构。最上面是 Root Complex(根复合体,通常集成在 CPU 或芯片组里),下面接 Switch(交换器),再往下挂 Endpoint(端点设备,比如显卡、NVMe SSD)。

我曾经遇到过一个故障:一块 FPGA 加速卡在 x16 插槽上只能协商到 x2。排查了半天,发现是 FPGA 那边的物理 Lane 映射焊错了,把第 0 个 Lane 接到了第 3 个 Lane 上。所以,搞清楚拓扑里的 Lane 编号映射,是排故障的第一步。

1.3 PCIe 版本演进:从 1.0 到 6.0

PCIe 基本上每三四年更新一代,速率翻倍,编码方式也跟着变。我按时间线帮你理一理:

  • PCIe 1.0(2003):2.5 GT/s,每条 Lane 有效带宽 ~250 MB/s(8b/10b 编码,开销 20%)。那时候大家刚从 PCI 转过来,觉得这速度已经起飞了。
  • PCIe 2.0(2007):5 GT/s,有效带宽翻倍到 ~500 MB/s。编码还是 8b/10b。我记得当时显卡开始用 x16 2.0,游戏画面流畅很多。
  • PCIe 3.0(2010):8 GT/s,有效带宽 ~985 MB/s。编码换成 128b/130b,开销从 20% 降到 1.5%。这是一个里程碑——速率没翻倍(从 5 到 8),但有效吞吐接近翻倍。很多老设备到现在还在用 3.0。
  • PCIe 4.0(2017):16 GT/s,有效带宽 ~1.97 GB/s。编码延续 128b/130b。我替客户排查过一块 4.0 的 SSD 只在 3.0 下跑,结果是主板插槽的均衡参数没调好。
  • PCIe 5.0(2019):32 GT/s,有效带宽 ~3.94 GB/s。目前高端 CPU 和显卡已经标配 5.0。不过说实话,链路均衡的难度也上了一个台阶。
  • PCIe 6.0(2022):64 GT/s,但这次编码变成了 PAM4 信令(1b/1b 调制),有效带宽 ~7.56 GB/s。纠错机制也加入了 FLR(Forward Error Correction)。嗯,这个版本还在普及初期,但调试工具已经跟不上了。
避坑指南:我曾经在一款 5.0 的背板上测试,发现长走线后信号眼图闭合严重。原因是 32 GT/s 下,PCB 损耗和串扰远高于 4.0。很多工程师只看了协议速率,忘了算信道损耗,结果链路训练失败。记得算好插入损耗预算再做 PCB。

1.4 速率归纳总结:一张表看清所有版本

下面这张表我常用来做快速参考。你调试时看到 `lspci` 输出里的 `Speed 8GT/s` 就要知道这是 3.0;看到 `16GT/s` 是 4.0。别搞混。

版本 单 Lane 速率 (GT/s) x16 总带宽 (GB/s)
(双向)
编码方式 引入年份
PCIe 1.02.588b/10b2003
PCIe 2.05.0168b/10b2007
PCIe 3.08.031.5128b/130b2010
PCIe 4.016.063128b/130b2017
PCIe 5.032.0126128b/130b2019
PCIe 6.064.0252PAM4 + FLR2022
注意:GT/s 是每秒传输的 Giga Transfers,但实际有效带宽要乘以编码效率。8b/10b 效率 80%,128b/130b 效率约 98.5%,PAM4 因为 FLR 开销大概 96.8%。所以 x16 总带宽那一列我算的是 有效数据带宽(单向 ×2 得双向)。你如果看到有些文档写的是“原始带宽”,记得换算。

下面这张 SVG 图把版本演进画得更直观。我习惯把它贴在工位上,每次看着它就能想起哪个版本应该用什么均衡策略。

PCIe 版本演进与每 Lane 速率 (GT/s) PCIe 1.0 2.5 GT/s PCIe 2.0 5.0 GT/s PCIe 3.0 8.0 GT/s PCIe 4.0 16 GT/s PCIe 5.0 32 GT/s PCIe 6.0 64 GT/s 每代速率翻倍(3.0除外,编码效率提升) PCIe 6.0 采用 PAM4 调制,需要 FLR 纠错 虚线箭头表示版本迭代方向

1.5 一个实用小技巧:快速查看当前链路状态

不管你是做板卡调试还是系统集成,lspci 都是最趁手的工具。我个人习惯加三个 -v 来获取最详细的信息。

lspci -vvv -s 01:00.0 | grep -iE "Width|Speed"

输出可能像这样:

LnkCap: Port #0, Speed 16GT/s, Width x4, ASPM L1, Exit Latency L1 <8us
LnkSta: Speed 16GT/s (ok), Width x4 (ok)

里面的 Speed 16GT/s 就是 4.0 的速率。如果显示 Speed 8GT/s 但设备是 4.0 的,那就说明链路降级了。我遇到过好几次,原因是插槽金手指氧化,导致均衡训练失败,自动回退到 3.0。拿橡皮擦擦一擦就好了——你看,有时候故障排查就是这么朴实无华。

个人经验:如果你发现 Width 和 Speed 都标了 (downgraded),那就先别急着换设备。先检查一下供电是否足够,再量一下参考时钟的抖动。很多降级问题其实是时钟源不干净导致的。