1. 复位基础概念:为什么是 PCIe 链路训练的起点?

我们先从最基础的问题开始——为什么要讲复位?

很多人觉得复位嘛,就是拉低一个引脚,或者写个寄存器位。但你要是做过几块高速板卡,就会明白:复位是整个 PCIe 链路能否顺利走到 L0 状态的第一道关卡。复位搞不好,后面什么训练序列、速率协商统统没戏。

1.1 复位的作用

说白了,复位就是让系统中的所有设备回到一个已知、确定、可预测的初始状态。你想想看,PCIe 链路两侧的设备上电时,它们内部的寄存器值、状态机、PHY 层的 PLL 锁相环、SerDes 通道,全都是随机态。没有复位来统一“归零”,两侧根本没法开始握手。

我个人习惯把复位的作用总结为三点:

  • 初始化硬件逻辑:把所有内部寄存器和状态机强行推到预设的复位值。
  • 建立确定性的时序起点:确保链路两侧从同一个时间坐标开始启动训练过程。
  • 释放安全状态:在复位期间,所有输出驱动都处于高阻或弱上拉,避免总线冲突。

这里有个关键认知:PCIe 链路训练状态机 (LTSSM) 的第一个状态就是 Detect,但进入 Detect 的先决条件是复位解除 (de-assertion)。所以,复位是链路训练的真正“起跑线”。

1.2 三种复位类型:硬、软、热

PCIe 规范里定义了三种复位。很多初学者容易搞混,尤其是软复位和热复位。我当年第一次看 Spec 时也被绕进去了。我们一个个拆开讲。

PCIe 复位类型对比
复位类型 触发源 影响范围 对 LTSSM 的影响
硬复位 (Fundamental Reset) PERST# 引脚电平变化 整个设备,包括所有逻辑和 PHY 设备彻底回到初始状态,必须重新做 Detect
软复位 (Soft Reset) 软件写配置空间的复位位 大多数内部逻辑,但 PHY 层保留部分状态 设备内部状态机复位,但 Link 可能仍然训练到 L0
热复位 (Hot Reset) DLLP 消息 (TS1/TS2 有序集) 整个链路的两侧设备 保持链路连接,重新从 Recovery 进入 Detect

1.2.1 硬复位 (Fundamental Reset)

这是最“暴力”的复位方式。我记得最早做一块 FPGA 的 PCIe 板卡时,冷启动总是能正常训练,但 warm reboot 就不行。排查到最后发现是 PERST# 的释放时序没配合好电源稳定信号。

硬复位的特征:

  • 由 PERST# (PCI Express Reset) 引脚直接控制。
  • 复位期间,设备必须将所有 I/O 输出置为高阻态。
  • 复位解除后,设备内部的 PLL 需要重新锁定,状态机从 Detect 状态开始跑。
  • 整个复位到 L0 的过程最慢,但最可靠。

避坑指南:我曾经碰到过一个案例,复位信号 PERST# 的下降沿和上升沿斜率不够陡(>100ns),导致 FPGA 内部复位检测逻辑误触发,链路训练时好时坏。所以建议在原理图设计时,给 PERST# 加一个施密特触发器缓冲器,保证边沿够陡。

1.2.2 软复位 (Soft Reset)

软复位不是通过物理引脚,而是通过软件配置空间写操作触发的。具体来说,是对设备配置空间的桥控制寄存器 (Bridge Control Register) 的 Bit 6 (Secondary Bus Reset) 写入 1。

它的特点:

  • 只复位内部逻辑,不强制复位 PHY 层的 PLL 和 SerDes 电路。
  • 复位后,设备内部的配置空间大部分字段回到默认值,但部分状态 (如 Link Status) 可能保持。
  • LTSSM 的行为取决于实现:有些控制器会直接进入 Detect,有些则允许从 Recovery 重训。

嗯,这里要注意。很多 FPGA 的 PCIe IP 核在软复位后,需要额外写一个复位控制寄存器的确认位才能真正生效。否则你以为复位了,其实还在跑旧状态。

1.3.3 热复位 (Hot Reset)

热复位是最有意思的一种。它不是靠硬件信号或软件配置,而是靠链路对端发送的 TS1/TS2 有序集,里面携带了 Hot Reset 标识。

为什么会需要热复位?

你想想看,系统在正常运行时,突然有一台设备需要整个链路重新初始化,但又不能拔卡或断电。热复位就是干这个的。它能在不改变电气连接的前提下,让链路两侧的状态机一起回退到 Detect,重新训练。

热复位的关键点:

  • 只能在 L0 或 Recovery 状态下发起。
  • 发起热复位的设备会连续发送 TS1 Ordered Set,其中 Lane 0 的 PAD 字段写入 Hot Reset 编码。
  • 接收端检测到连续的数据序列后,进入 Hot Reset 状态,然后一起跳到 Detect。

小经验:在做兼容性测试时,我见过某款 Switch 芯片对热复位的响应特别慢,需要等上几十微秒才开始重新传输 TS1。如果两端设备的计时器不匹配,容易导致链路上报 Training Error。解决办法通常是在 Root Port 的链路控制寄存器里增加热复位的超时容限值。

1.3 复位与链路训练的全局关系

三种复位虽然触发方式不同,但最终目标一致——让 LTSSM 走到 Detect 状态,开始新一轮训练。但它们的路径和速度差异很大。

为了直观展示,我画了下面这个图:

PCIe 复位与链路训练状态机关系图 硬复位 (PERST#) 软复位 (配置写) 热复位 (DLLP) 复位解除 (Reset Deasserted) LTSSM: Detect Polling → Config → L0 三种复位最终都使 LTSSM 回到 Detect 状态,但时序路径和内部影响范围差异很大

1.4 实践中的避坑清单

从项目经验来说,复位这块最常出现问题的地方,我列了一个清单,供你参考:

  1. PERST# 与电源的时序关系:PCIe 规范要求 PERST# 必须在所有电源稳定之后至少延迟 100ms 才能释放。这个延时在示波器上一定要量到,否则链路训练大概率失败。
  2. 热复位的误触发:我之前遇到过一个 bug,某设备在链路正常工作时,偶尔会收到带 Hot Reset 标记的 TS1 有序集。后来定位到是对端发送器的 PAD 编码在特定温度下发生了位翻转。解决办法是在接收端增加计数过滤功能——连续收到 3 个以上才视为有效热复位。
  3. 软复位后 PHY 状态残留:有些 PHY 在软复位后不会自动重锁 PLL,需要软件额外写一个复位确认位来触发重新校准。这个细节在芯片手册里通常藏在 Notes 里,很容易漏掉。
  4. 跨时钟域复位同步:如果复位信号跨时钟域传递但没有做两级同步,很容易产生亚稳态,导致状态机跑飞。建议所有异步复位信号在进入时钟域后,都经过一个双寄存器同步器。

最后,我个人的设计习惯:在调试阶段,我会在 PCIe IP 核内部例化一个复位状态监测模块,用逻辑分析仪把硬复位、软复位、热复位分别拉出来观察。能看到到底触发了哪种复位、解除时刻、到 Detect 的延时。这个信息对排查链路训练问题非常有用。

好了,这一章我们讲清楚了复位到底是什么,以及三种复位类型各自怎么工作。下一轮我们要一头扎进真正的链路训练过程,先从 Link Training and Status State Machine (LTSSM) 的最初状态——Detect 开始。