第3章:链路初始化与Detect状态机制

3.1 先从物理层握手开始

链路初始化,说白了就是LTSSM把两个PCIe设备拉到一起的过程。从上电复位开始,到链路能传输数据,全靠这套状态机在运作。

我记得第一次调试PCIe链路时,系统死活Link Up不上。翻来覆去查Code,最后发现是Detect阶段的电气参数没配好。从那以后,我对LTSSM的初始化细节就再也不敢马虎了。

LTSSM的初始化从Detect状态开始。这个状态的目的很简单——检测对端有没有设备。但实际做起来,要考虑的细节可不少。

3.2 Detect状态:如何知道对面有人?

Detect状态分为两个子状态:Detect.Quiet和Detect.Active。先静默,再试探,这是硬件通用的套路。

核心目标:通过发送周期性的Electrical Idle Exit Sequences(EIES),检测接收端是否看到连续的阻抗变化。如果看到,说明对面有设备。

我曾经遇到过一个Case:某款FPGA作为Endpoint,在Detect.Quiet阶段发呆太久,导致Root Port检测超时。后来发现是PHY层的复位逻辑没对齐。这个坑,我印象很深。

Detect.Quiet

在Detect.Quiet状态下,发送端保持电气空闲(Electrical Idle)。接收端则开启接收检测电路(Rx Detection Circuit),监控线路上的阻抗变化。

  • 持续时间:至少12ms,但具体由SoC的PHY实现决定。
  • 关键操作:发送端不主动驱动线路,接收端被动监听。
  • 退出条件:检测到对端设备的接收器阻抗,或者超时进入下一步。

我的习惯:在仿真时,我会把Rx Detection Circuit的模型换成真正的负载模型,而不是简单的开路/短路。否则容易漏掉Receiver Detection的时序问题。

Detect.Active

Detect.Quiet完毕,状态机跳入Detect.Active。这个阶段,发送端开始主动发送EIES序列。EIES说白了就是一串特定的差分翻转信号,用来验证对面是不是真的在侦听。

  • EIES序列长度:Gen1中至少需要发送2个TS1序列。Gen3/Gen4会变成更复杂的Ordered Set。
  • 检测结果:如果对端收到了EIES并回应正确的TS1,说明链路存在。如果收不到,则重试或进入Disable状态。
Detect子状态 持续时间 发送端动作 接收端动作
Detect.Quiet ≥12ms 保持Electrical Idle 主动检测接收器阻抗
Detect.Active 连续发送EIES,直到收到回应 发出TS1序列 等待接收TS1,然后回送TS1

3.3 从Detect走向Polling

Detect成功不等于万事大吉。它只告诉你对面有接收器。但双方的通道宽度、数据速率、链路编号还没对齐。这些是Polling和Configuration阶段要干的活。

不过,如果你在Detect阶段发现链路始终无法进入Polling,先别急着怀疑后端逻辑。我个人习惯先检查PHY层的PLL锁定状态。PLL不稳,Detect.Active发出的EIES会被抖掉,对面根本看不到。

曾经踩过的坑:做过一个GaN功放验证板,PCIe走线长度超出Spec规定10%。结果在Detect.Active阶段,EIES信号衰减太大,对端收不到。后来加了一级Repeater才搞定。记住,Detect阶段的灵敏度和信号完整性高度相关。

3.4 链路初始化全流程速览

为了帮助大家建立整体认识,我画了一张链路初始化的状态转换图。从Detect开始,到L0结束,中间每一步都有对应的测试点和调试方法。

LTSSM 链路初始化状态转换图 LTSSM 链路初始化状态转换图 Detect Polling Configuration L0 检测失败,回退重试 速率协商失败,重试 配置失败,链路降级 Detect → Polling:需要双方成功交换 TS1/TS2; 否则返回 Detect.Quiet Polling → Configuration:链路宽度协商; Configuration → L0:完成链路编号和电源管理配置

这张图其实是个简化版。实际FSM里还有Loopback、Recovery、Hot Reset这些旁路状态。但在初始化这条主线上,Detect、Polling、Configuration、L0就是四个关键锚点。

Detect阶段的具体参数

你可能会问我,Detect到底要测多久?答案不固定,但PCIe Spec给了清晰的时间约束。

  • Detect.Quiet 最小时间: 12 ms (这是Gen1/Gen2的标准。Gen4/Gen5有更短的替代方案,但不常用).
  • Detect.Active 持续期: 最多可以连续发送512个TS1序列,之后如果没回应,LTSSM会认为对端不存在,重新回到Detect.Quiet.
  • 退出条件: 只要在Detect.Active期间收到一个有效的TS1序列,立即跳转到Polling.

调试小技巧:在仿真中,我会在Detect.Active后加一个硬件断点,监控接收到的TS1序列数量。如果收不到,检查PHY的CDR(时钟数据恢复)是否锁定。没锁定,EIES序列就是废的。

3.5 实际项目中的Detect问题案例

我在维护一个老式服务器平台时,碰过一件怪事:某批次PCIe SSD插入主机后,系统偶尔识别不到。换槽位又正常。用逻辑分析仪抓Detect阶段的波形,发现Root Port发送的EIES序列在Slot与SSD之间有反射。因为连接器的寄生电容太大,EIES的第一个沿被削平了。对端的Receiver Detection电路误判为电气空闲,直接忽略。

解决方案也简单:在PHY侧调整EIES的驱动强度,让上升沿更快。或者,在PCB布局时给差分对加个小串阻。这类问题在高速设计里很常见,根源往往就是信号完整性,不是LTSSM逻辑有Bug。

3.6 本章小结

Detect状态是LTSSM的门神,也是整个链路训练的基础。从Detect.Quiet到Detect.Active,每一步都涉及PHY层的电气特性和状态机的同步。我个人总结了一个三字诀:静、发、收。先静默(Quiet)等对端准备好,再发(Active)EIES试探,最后收(Receive)TS1确认。顺序错了,或者时序跑了,链路就别想起来。

如果你在项目里遇到链路初始化失败,先从Detect阶段查起。查看PHY的Rx Detection电路是否使能、CDR是否锁定、EIES的幅度是否达标。很多时候,问题就出在这些看起来简单的环节上。