第2章:上电复位时序——电源稳定与复位释放条件

搞PCIe链路训练,第一步不是看LTSSM状态机,而是先把供电和复位搞定。要是电源没站稳就急着跑复位,或者复位释放得不对,后边的链路训练全白搭。我刚开始接触PCIe时,就吃过这个亏——板子焊好了,死活Link不起来,查了三天,最后发现是电源斜坡斜率太慢,复位释放的时候核心电压才1.7V(标称1.8V)。

所以这一章咱们把上电复位时序彻底说清楚。你想想看,PCBA上电之后,各个电压轨按什么顺序起来?Perst信号什么时候才能拉高?这些时序窗口到底谁约束谁?搞明白这些,后面的L0训练才有根基。

上电复位时序核心流程 主电源VMAIN稳定 3.3V / 1.8V 达到标称 ±3% 辅助电源VAUX稳定 VAUX 在 Perst 之前有效 电源排序完成 所有电压轨 OK Perst# 保持低电平 等待TPVPGL (≥100ms) REFCLK 稳定 频率容差 ±300ppm Perst# 释放条件满足? 电源OK & 时钟OK & TPVPGL Perst# 拉高 复位释放,设备开始初始化 ⚠ 关键时序参数见底色标识 Perst 低电平保持时间 TPVPGL

2.1 电源稳定的三个关键点

PCIe设备上电,不是简单的“电压到了就行”。我习惯把电源稳定性拆成三个维度来检查:

  1. 电压达到标称值的时间——从0到90%标称电压的上升时间,通常叫斜坡时间。PCIe规范没有卡死具体数值,但实际项目中乱设会有问题。比如某个FPGA PCIe硬核要求电源斜坡在10ms~50ms之间,太慢会导致内部POR(上电复位)误判。
  2. 电压过冲/下冲——稳定后不能超过±3%的容差。Core电压1.0V,最低不能掉到0.97V以下,最高1.03V。
  3. 时序关系——多个电压轨之间可能有先上后下的要求。比如有些Endpoint需要VAUX先稳定,再上VMAIN。

实战经验:我记得有一次调试M.2插槽的SSD,每次冷启动都能识别,热重启PCIe设备就掉。后来抓了Perst和电源波形,发现热重启时Perst释放太快,而VMAIN因为电容残压没有完全掉到零,导致内部POR逻辑状态混乱。最后加了一颗放电电阻解决。所以别以为“掉电”只是一个瞬间——残压有时候比你想的顽强。

2.2 复位释放的硬性条件

Perst#(PCI Express 复位信号)释放前,必须同时满足以下三个条件。少了任何一个,链路训练都可能异常。

条件 说明 典型参数
所有电源稳定 VMAIN、VAUX 在标称值±3%内 参考具体芯片手册
REFCLK稳定 100MHz差分时钟,频率容差±300ppm 抖动通常要求< 86ps p-p
Perst低电平保持时间 TPVPGL Perst# 必须保持低电平至少100μs(规范值),但很多芯片要求100ms 100μs~100ms,取决于平台

为什么Perst要等那么久?其实是为了让内部PLL锁相、偏置电路建立、模拟前端稳定。你不是把数字逻辑复位就行,高速SerDes需要时间来做眼图对齐和校准。我见过一个案例,某款PCIE Switch因为系统Power Manager在50μs后就释放了Perst,结果Switch的SerDes内部状态没有建立好,总是Training Error。后来把延时改成10ms就稳定了。

2.3 你需要注意的时序细节

到这里你可能觉得“哦,照做就好”,其实坑还不少。我顺带提几个容易翻车的地方:

  • 上升沿斜率——Perst从低到高的上升时间建议控制在1ms以内。太慢会导致设备在阈值区间反复跳变,带来毛刺。
  • Perst与电源的先后顺序——规范只要求Perst在电源稳定后才能释放,但很多控制器希望Perst在电源到位之后再过几十ms才拉高,避免竞争。
  • 多设备挂同一条Perst总线——如果有多个PCIe设备共享同一个Perst信号,要注意每个设备的de-assert时间窗口可能不同。有些设备延迟小,有些延迟大,容易造成上游RC侧误认为设备已就绪。

我的习惯:在Perst释放前加一级反相器加RC延时,或者在FPGA/CPLD中做一个可编程的延时计数器。这样调试的时候可以动态调整TPVPGL长度,不用改PCB。我曾经用这种方法快速定位了一个由于Perst时序导致链路不稳定的大坑。

2.4 参考波形与参数速查

拿典型的Root Complex平台举例子,从上电到L0整个复位序列大致如下:

时间轴(不按比例):
V_MAIN       ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
             | 斜坡期 ~10ms |       稳定期       
V_AUX        ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
             | 通常比V_MAIN早或同时 |
REFCLK       ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
             | 电源稳定后很快稳定 |
Perst#       ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
             | 保持低电平 >=100ms | 拉高 → 设备初始化 → 链路训练

注意上图只是一个理想场景。实际项目中你可以把Perst的保持时间设得保守一些,比如200ms。多出的这几百毫秒不影响用户体验,但能给电源和时钟更多的裕量。

2.5 避坑指南——我踩过的那些雷

警告:千万不要忽视Perst信号的毛刺。我曾经在项目测试中发现,服务器主板上的Perst因为走线过长、过孔太多,被电源噪声耦合出了一个100ns的正脉冲。这个毛刺正好落在设备内部数字滤波器的检测窗口之外——设备根本感知不到它。但搞笑的是下游PCIe交换机却因为这段毛刺触发了误复位,导致后级所有Endpoint同时断链。最后定位原因耗时两周。那以后我所有涉及Perst的设计都在靠近设备引脚处加一个RC低通滤波,时间常数约1μs,把窄毛刺滤掉。

再补充一个很多人忽略的点:热插拔场景下的复位时序。如果你做的是支持Hot-Plug的槽位,当设备插入时,电源上升和Perst的关系要重新考量。规范规定Perst必须在电源稳定后的100μs内拉低,再保持至少100ms。但如果你插进去的瞬间电源有抖振,控制器的检测逻辑可能会误判。过去我处理过一个案例:插卡时机械接触有抖动,电源在几十微秒内掉了三次,导致Perst控制失效。最后的解决方案是增加一个去抖电路,Perst释放之前先检测到电源连续稳定10ms才拉高。


好,电源稳定和复位释放的时序要求,大概就这些。这一块虽然看起来只是简单的“等电源再释放复位”,但实际项目中因为时序裕量不足、毛刺干扰、多电源轨序等问题踩进去的坑太多了。希望你带着这些经验去设计,能少走弯路。记住一个原则:宁可多等100ms,也不要抢那10μs。链路训练这件事,开局稳定才能跑得稳。