Detect 状态详解

Detect 状态,说白了就是链路训练的第一道关卡。很多刚接触 PCIe 的同学以为它很简单——不就是看有没有设备插上吗?但我在项目中调试过不少 Link Up 失败的问题,十有八九都跟 Detect 阶段的信号检测有关。嗯,这一节咱们把它拆开揉碎了讲。

进入 Detect 的条件

Detect 是 LTSSM 的初始状态,也是唯一一个“主动”去发现下游的状态。什么情况下会跳进来?我用列表总结一下:

  • 复位或上电后:无论是 Fundamental Reset 还是 Hot Reset 退出,LTSSM 都会从 Detect 开始。
  • Link Down 恢复:当链路从 L2/L3 或 Disabled 退出时,也要重新进入 Detect。
  • 其他错误处理:比如 Recovery 失败、Electrical Idle 退出超时,某些设计也会强制返回 Detect。

我个人习惯在调试初期先确认一下:当前状态机到底是从哪里跳进 Detect 的?因为复位场景和 Recovery 失败的场景,后续行为差异很大。

两个子状态:Quiet 与 Active

Detect 内部又分成两个阶段:Detect.Quiet 和 Detect.Active。你可以理解为先“安静监听”,再“主动发送”。

Detect.Quiet

进入这个子状态后,发射器保持电气空闲(Electrical Idle),不发送任何差分信号。接收端则开始寻找接收检测(Receiver Detection)的脉冲。为什么需要先安静?说白了,就是先清空总线上的残留信号,否则检测结果会被干扰。

我记得有一次调试 PCIe 3.0 的板子,上游一直 Link Up 失败,用示波器抓波形发现 Detect.Quiet 阶段有毛刺——原来相邻的 PCIe 插槽用了同一个复位信号,电平变化耦合过来了。这个坑我踩过一次,后面就特别注意 Detect.Quiet 时的电源和去耦设计。

Detect.Active

Quiet 持续一段时间(一般是 12 ms 以内,具体由实现决定)后,进入 Detect.Active。此时发射器开始发送一连串的 Detect 信号序列:交替发送非归零码(NRZ)的 D+ 和 D− 脉冲,用来检测接收端是否存在。

接收端的 RX 检测电路怎么工作?原理是检测差分阻抗的变化。当接收端存在时,线路上的等效阻抗会从高阻变为 50Ω(或 100Ω 差模),从而改变脉冲的反射特性。发射端通过监测这些反射波形就能判断是否有设备挂在那里。

小技巧:实际调试时,可以看 Detect.Active 阶段有没有正常的“三角波”状的脉冲对。如果脉冲幅度明显偏小或形状畸变,多半是阻抗不连续或者接收端没上电。我曾用这个特征秒杀过几个假 Link Down 的 case。

信号检测机制详解

检测过程其实是一个简单的时域反射计(TDR)测量。发射端发出一个上升沿很快的脉冲,然后测量返回的反射波。我来画个流程,先看看标准要求的时序参数:

参数最小值最大值说明
T_Detect_Quiet12 μs12 msQuiet 持续时间(实际设计常用 1 ms)
T_Detect_Active12 μs12 msActive 内脉冲发送时间
脉冲宽度2 ns10 ns单脉冲持续时间
脉冲幅度800 mV1.2 V差分摆幅

你想想看,为什么需要这么宽的范围?因为不同链路速率(2.5 GT/s vs 5 GT/s)对应的 Detect 序列格式不一样,而且允许设计者按自己的时钟精度微调。我见过一个案例,某 FPGA 的 IP 把 T_Detect_Quiet 设成了 11 μs,略低于最小值,结果某些端点就是不认——后来改成 15 μs 就稳定了。

检测结果的判定

发射端在 Detect.Active 结束时,根据反射波形参数做判决:

  • 如果反射波幅值 > 阈值 → 判定为 Receiver Present,然后进入 Polling 状态。
  • 如果反射波幅值 ≤ 阈值 → 判定为 No Receiver,回到 Detect.Quiet 继续等。

这里有个常见的坑:阈值设计太保守,导致弱接收(比如长走线、高插损)被误判为不存在。我曾经在一个背板项目中遇到过:中间有级联交换芯片,收端的等效阻抗接近 50Ω 但边沿速度被电容拉慢了,反射信号幅值掉到阈值以下。后来不得不降低阈值,同时增加抗干扰滤波。

重要提醒:阈值不可随意调低,否则噪声可能触发误检。建议在配置文件里留一个寄存器写入口,方便现场调试时微调。

Detect 状态流程图

下面我用一张 SVG 图把整个 Detect 状态机的流向画出来。注意,它只是本章知识体系的骨架——从初始进入,到 Quiet/Active 交替,再到判决跳转。

Detect 状态迁移流程 复位 / Link Down / 错误返回 Detect.Quiet(发送器静默) Detect.Active(发送检测脉冲) 接收端存在? (反射幅值 > 阈值) 是 Polling 否 回 Quiet

从图上你就能看清完整的判定路径:如果检测失败,回到 Detect.Quiet 重新安静;如果成功,则跳入 Polling 准备速率协商。

常见问题与避坑指南

  1. 持续在 Detect.Quiet / Active 间循环,无法进入 Polling
    原因多半是接收端未上电或阻抗异常。可以先用示波器看脉冲波形——如果只有单边脉冲或幅度不足,检查差分对是否短路、接收端电源是否正常。
  2. Detect.Active 脉冲宽度超标
    有些 IP 实现的脉冲宽度可能接近 15 ns,超出规范上限(10 ns)。这种非标行为会导致对端误码或拒绝 Link。我建议在 PHY 初始化时先读回 Detect 计时器的默认值,跟规范核对一遍。
  3. 噪声环境干扰检测结果
    我曾经在一个多卡插槽的服务器上,发现相邻 PCIe 插槽在 Detect.Active 时串扰过来,导致本槽误判为自己有设备(其实空槽)。解决方案:在 PCB 布局时给每个 Lane 增加地孔屏蔽,并在 Detect.Quiet 期间拉长安静时间,避开邻居的 Active 窗口。
  4. Hot Reset 后不进入 Detect
    Hot Reset 会直接跳入 Detect.Quiet,但如果复位信号没有正确握手上电,某些 PHY 可能僵在原来的 L0 状态。需要检查复位信号的时序——Hot Reset 必须持续至少 2 ms,且链路必须处于 Electrical Idle 至少 100 μs 后再发 Reset。

经验总结:Detect 状态是链路训练的最脆弱环节,因为它在干“噪声中找信号”的活。我建议每个项目在 bring-up 阶段,先用 PCIe 分析仪抓一次 Detect 全过程的波形,保存下来作为基线。后面出了问题,对比基线就能快速定位是发射端问题还是接收端问题。

嗯,Detect 状态的核心就这些。记清楚 Quiet 和 Active 的交替逻辑,以及阈值判定原理,后面再碰 Polling、Configuration 就顺了。