
做PCIe调试这些年要我说最磨人的不是信号起不来而是链路起来了却不稳或者干脆卡在某个LTSSM状态里出不来。尤其是到了Gen38GT/s以上Recovery.Equalization几乎是每个人都会撞上的关卡。这个状态里干的事情说白了就是链路均衡Link Equalization发送端和接收端通过TS1/TS2报文来回拉扯把发送端的预冲、去加重系数调到匹配当前信道损耗的程度顺便让接收端的CTLE/DFE也完成自适应。这篇文章我打算用Synopsys DesignWare PCIe IP上实际调过的案例把链路均衡的原理、训练流程、寄存器配置以及调试时最容易踩的坑一次讲清楚。适合正在做板级Bring-up、FPGA原型验证或者被“Gen3协商不上”“跑起来就掉速”折磨的同学。1. 为什么Gen3之后一定要做链路均衡1.1 信号完整性问题从Gen2到Gen3的坎在PCIe Gen12.5GT/s和Gen25GT/s时代信号基频只有1.25GHz和2.5GHz。这个频率下FR-4板材的走线损耗虽然存在但还没到失控的地步。一块普通主板上的PCIe走线长度通常在5到15英寸之间插损不大回波损耗、串扰也在可控范围。所以Gen1/Gen2只靠发送端一个简单的去加重De-emphasis开关——-3.5dB或者-6dB二选一——就能把链路跑稳。到了Gen38GT/s情况完全变了。信号基频抬到了4GHz同样一段走线插入损耗可能比Gen2时翻了一倍还多。如果你在示波器上看过10英寸长走线末端的眼图那个眼基本是闭着的。更麻烦的是信道里除了衰减还有各种阻抗不连续点连接器、过孔、金手指、线缆每一个节点都会反射信号产生严重的符号间干扰ISI。此时再用固定去加重已经行不通了——你加重了主脉冲旁边的码间串扰可能更大你不加重眼图又打不开。所以PCIe从Gen3开始强制引入链路均衡机制。它不是简单预设一个系数而是让发送端和接收端在上电训练阶段通过握手报文把系数调出来。接收端告诉发送端“你的预冲给大一点”发送端就调整前标tap接收端说“去加重不够”发送端就增加后标tap。同时接收端自己也在调CTLE连续时间线性均衡和DFE判决反馈均衡。这套“两边配合、自动适配”的机制就是链路均衡。打个比方两个人隔着操场喊话。距离近的时候正常音量就行这就是Gen1/Gen2。距离远了一个人得改变喊话的节奏和音调发送端均衡另一个人得把手拢在耳朵边当助听器接收端均衡。所以均衡天生就是双向配合的。1.2 LTSSM中的Recovery状态均衡发生在哪里PCIe链路的状态机叫LTSSMLink Training and Status State Machine。从复位开始链路依次经历Detect、Polling、Configuration进入L0正常工作状态。L0是唯一能传数据的活跃状态。当链路需要从低速切换高速时比如从Gen2升到Gen3链路会跳进Recovery状态。Recovery不是一个单一状态它下面还拆了两个子状态Recovery.Equalization和Recovery.Transaction。Recovery.Equalization就是专门干均衡训练的训练完成后进入Recovery.Transaction然后返回L0。很多工程师第一次看LTSSM状态跳转会懵不是有个Configuration状态吗为什么均衡不在Configuration里做这里有个关键点Configuration阶段链路只跑在Gen1速率也就是2.5GT/s。而均衡是针对8GT/s及以上速率的需求所以必须等链路决定切高速之后在Recovery.Equalization里完成。换句话说Recovery.Equalization是高速率协商的必经之路也是Gen3及以上链路训练最容易卡住的地方。在真实调试中如果LTSSM一直停在Recovery.Equalization链路就像两个人同时张嘴却听不见对方谁都进不了下一步。这也是为什么大家一谈到Gen3协商失败首先就会怀疑均衡有没有跑通。1.3 均衡的“两端配合”思路链路均衡分为发送端均衡和接收端均衡。发送端均衡本质是一个可编程的多抽头FIR滤波器。常见的抽头包括C-1前标tap产生预冲、C0主光标、C1后标tap产生去加重。更高端的PHY还会有C-2、C2但基本原理一样。接收端均衡则是两段式先过CTLE做高通补偿把高频分量拉起来再过DFE做自适应判决消除长尾拖尾。Gen3的PHY里CTLE通常有几档可配DFE的tap数也可以调。这些参数在EK训练阶段由PHY内部自适应算法决定工程上也可以通过寄存器干预。理解这个“两端配合”的思路很重要。很多人总以为均衡就是调发送端的去加重实际上接收端的CTLE/DFE参与程度经常决定了最终眼图能不能过。比如遇到长走线、高损耗的情况如果接收端DFE没有开启或者配置不对即使发送端把预冲和去加重调到极致眼图也大概率不合格。2. 链路均衡训练的核心机制拆解2.1 TS1/TS2里的均衡控制字段均衡训练的消息载体是Training Sequence也就是我们常说的TS1和TS2。这两个报文是LTSSM里最基础的训练序列平时看LTSSM必看它们。TS1/TS2里除了链路号、通道号、速率标识这些常规字段还带了一组均衡控制位。关键的几个字段包括数据速率标识Data Rate Identifier用于协商目标是Gen3还是Gen4启动均衡请求位Request Equalization请求方用这一位告诉对端“开始训练发送系数”还有均衡系数相关的preset选择字段和系数更新标志。这些位的定义在PCIe Base Spec里有完整表格但调试时我更建议直接用协议分析仪看它会把这些位翻译成人话比对着Spec逐bit解析省事得多。不过理解含义仍然必要TS1报文中看到Request位一直被置1说明一侧一直在请求均衡如果另一侧迟迟不回应问题就出在响应侧。另外一个容易忽略的点TS1和TS2的均衡字段解析方式略有不同。TS1用于均衡训练阶段TS2更多在最后的完成阶段。协议分析仪抓到TS2出现往往说明均衡已经到了尾声。2.2 Phase 0到Phase 3四次握手完整走一遍PCIe的链路均衡训练在Recovery.Equalization状态下分四个阶段完成业内习惯叫Phase 0到Phase 3。这里说的Phase和PCIe电源管理里的P状态完全是两回事别混了。Phase 0初始化与速率锁定。两端进入Recovery.Equalization后先在Gen1速率下互发TS1然后协商跳到目标速率比如Gen3。接收端的CDR时钟数据恢复需要在新速率下重新锁定。这一阶段双方用的是固定的preset初始化值不需要做系数调整。Phase 0完成的标志是双方都成功收到足够数量的TS1且速率切换完成。Phase 1发送端均衡训练。这是最核心的环节。通常由Downstream Port主导向Upstream Port发送带请求的TS1要求对方调整发送端的预冲和去加重系数。Upstream侧收到请求后按请求调整自己的TX系数然后继续回TS1。Downstream侧持续评估接收信号质量直到认为够好为止。在实际抓包中这个阶段的TS1报文里的均衡控制字段变化最频繁。Phase 2反向训练与接收端均衡。角色互换。此时由Upstream Port训练Downstream Port的发送端。同时各个端口的接收端均衡CTLE/DFE也在同步自适应。Phase 2结束通常意味着双方向TX系数都调完了。Phase 3完成阶段。双方确认所有均衡参数都ok互发TS2或者带完成标志的TS1然后退出Recovery.Equalization进入Recovery.Transaction最后回到L0。理解这四步是调试的基础。因为不同阶段卡住排查方向完全不一样卡在Phase 0大概率是时钟或者CDR问题卡在Phase 1/2大概率是某个PHY的TX系数寄存器没生效卡在Phase 3则可能是最后的确认握手没完成。2.3 TX EQ系数怎么算TX均衡系数听起来玄乎其实就是一组权重。把发送端要输出的信号看成主脉冲、前一个bit和后一个bit的组合系数就是每个部分的缩放比例。以最常见的三个tap为例C-1控制前一个bit的影响预冲C0控制当前bit主光标C1控制后一个bit去加重。这三个系数通常需要归一化大致满足C-1 C0 C1的和接近1。去加重De-emphasis的计算公式是De-emphasis 20 × log10( C0 / (C0 C1) ) dB预冲Pre-shoot的计算公式是Pre-shoot 20 × log10( (C0 C-1) / C0 ) dB举个例子假设C-10.08C00.72C10.20那么去加重就是20×log10(0.72/0.92)≈-2.1dB预冲是20×log10(0.80/0.72)≈0.9dB。实际训练过程中PHY会尝试不同组合比如预设好的一组系数叫一个preset再在preset基础上做微调。很多PHY寄存器里的Tx Coefficient值就是直接往这三个tap里填数。调试时如果发现一端的TX输出没有信号先别急着怀疑硬件坏很可能就是C0被写成了0主光标没了。2.4 为什么调试时偏爱Preset自动均衡训练听着高级但真出问题的时候反而是手动指定preset更好使。PCIe规范定义了一组preset每个preset对应一套预先计算好的TX系数组合比如某个preset表示“主光标饱满、几乎不去加重、带一点预冲”另一个表示“强去加重、几乎没预冲”。调试时强制固定preset有两个明显好处。第一排除自适应算法的干扰。如果固定某个preset后眼图明显变好说明硬件信道本身没问题是自动训练收敛到了次优解。第二可以快速摸底硬件指标。比如拿几个典型preset都测一遍眼图记录哪组参数下VMA电压裕量最高后面再反推PHY自适应算法为什么没选到这组。不过要注意preset不是越多越好。PCIe Gen3里常见的preset就那么十来个Gen4才多了新的preset定义。具体到某颗PHY还需要看databook确认实际支持哪些。Synopsys的PHY一般都会在寄存器里列一个preset列表用索引号选择调试时非常方便。3. 基于Synopsys IP的实战调试流程3.1 Synopsys DesignWare PCIe IP整体结构用Synopsys的DesignWare Cores PCIe IP做开发通常会接触到两层Controller和PHY。Controller负责LTSSM状态机、TLP事务层报文收发、MSI中断这些协议逻辑PHY负责模拟信号收发、CDR、EQ训练这些物理层功能。两者之间通过PIPE接口连接。这套结构下的调试入口主要有三个。第一个是Controller的寄存器通过APB/AXI从机接口访问。第二个是PHY的寄存器通过PIPE接口扩展的PHY CSR接口访问。第三个是外接协议分析仪直接串联在链路上抓实物报文。我自己调试时习惯先读Controller的LTSSM状态寄存器确认卡在哪个状态再读PHY的EQ相关寄存器看训练细节最后才上协议分析仪抓TS1/TS2。这样能很快缩小范围。如果一上来就上分析仪信息量太大反而不好定位。3.2 寄存器配置让EQ训练跑起来在Synopsys DesignWare控制器中链路均衡相关的控制寄存器通常以GEN3_EQ开头比如GEN3_EQ_CONTROL。这些寄存器可以控制EQ训练的总开关、Phase超时时间、允许使用的preset集合等。PHY侧则有对应的TX系数寄存器和RX自适应配置寄存器。要让一条Gen3链路正常完成均衡最基本的配置流程是这样的通过Link Control 2寄存器把目标链路速率设成Gen3让链路有动力向上训练。在GEN3_EQ_CONTROL里使能EQ训练确认没有误disable EQ。配置PHY的初始TX系数通常先选定一个默认preset保证上电后链路上有正常信号。触发链路重新训练观察LTSSM是否能从Recovery.Equalization走出来。等链路进入L0后再读状态寄存器确认均衡完成。这段流程说起来简单实际操作中经常会遇到“寄存器写进去但没生效”的情况。比如GEN3_EQ_CONTROL里的某个位被固件在启动阶段盖回去了或者PHY侧的CSR地址映射配置错位。遇到这类问题一个笨但有效的办法是配完之后回读一遍确认写入值还在。3.3 用lspci一眼看出EQ跑没跑通在Linux系统下调试PCIe设备lspci -vvv是我必用的命令。它虽然没有协议分析仪那么细致但胜在方便能在不拆机器的情况下快速判断链路状态。打开lspci -vvv的输出重点看LnkCap和LnkSta字段。LnkSta里会显示当前速率和宽度比如“Speed 5GT/s, Width x4”。如果设备支持Gen3但这里显示5GT/s那就说明链路降速了大概率是均衡训练失败回退到了Gen2。再往下翻LnkSta2字段里会有和均衡相关的状态比如Equalization Complete、In Progress这些字眼。如果看到Equalization Complete说明上一次均衡训练完成了如果一直显示In Progress或者压根没出现说明卡在Recovery.Equalization里。在调试阶段我还会配合脚本周期性刷新lspci输出观察链路速率是不是稳定。曾经遇到过一个设备热机后偶尔从Gen3掉回Gen2脚本抓了一晚上才发现掉速有规律最后定位到是某颗电容在温度升高后寄生参数变化导致EQ余量不足。3.4 协议分析仪抓TS1判断EQ进行到哪一步协议分析仪是EQ调试的核心工具。我自己用的流程是把分析仪串联在RC和EP之间设置触发条件为进入Recovery状态然后抓取完整的TS1/TS2序列。实际案例有块板卡Gen3总是协商不上链路在Recovery.Equalization反复循环。抓包发现Downstream侧一直在发带Request Equalization位的TS1但Upstream侧回应的TS1里均衡控制字段始终是初始preset值压根没有跟着请求变。这说明Upstream根本没在响应均衡请求。顺着这个线索查Upstream侧的PHY发现是PHY的EQ enable位被固件配置成了0整个发送端均衡没有参与训练。把这个位改成1之后重新训练链路一次就过了。复盘来看如果不抓TS1光看LTSSM状态只能知道“卡在Recovery.Equalization”永远不知道是哪一端在装死。另外分析仪还能看到Phase 0到Phase 3的推进。比如你看到TS1里带有特定字段表示进入Phase 1后面又出现Phase 2的字段那说明训练在往前走。如果一直停在某个Phase就往对应方向查PHY配置和信号质量。3.5 示波器眼图验证寄存器配置正确、LTSSM能走出Recovery.Equalization只代表训练流程跑通了不代表信号质量一定好。要确认链路余量够不够还得看眼图。测PCIe Gen3的眼图需要用带宽足够的示波器至少13GHz建议25GHz以上搭配差分探头。测试点是TX端到连接器之间的走线有条件的话用SMA探棒直接点测。Gen3的眼图模版对眼高眼宽有明确要求但工程上我更关注VMA电压裕量和总抖动TJ。VMA低于多少、TJ高于多少不同板卡要求不一样但经验上如果VMA在90mV以下链路长时间运行大概率会有偶发误码。眼图测量要分别测两端Downstream的TX方向和Upstream的TX方向都要看。很多时候只测了一端认为没问题另一端其实眼图很差。有一次调一个FPGA原型板RC侧眼图完美EP侧眼图的一只眼睛明显偏小最后发现是EP侧PHY的某个电源滤波电容焊错了位置。这种问题不双向测眼图根本发现不了。4. 常见问题与排查技巧实录4.1 常见问题速查表现象可能原因优先排查方向链路只能跑到Gen2Gen3协商不上EQ训练失败自动降速看LTSSM是否卡在Recovery.Equalization抓TS1LTSSM长时间停在Recovery.Equalization一侧TS1无响应、CDR失锁、PHY EQ被disable协议分析仪抓TS1确认两侧是否都在发EQ训练成功但L0下层持续高误码TX/RX均衡余量不足测双向眼图检查DFE是否开启设备在热插拔或环境变化后重新训练失败插损变化后EQ没有完全收敛强制固定preset或延长EQ训练超时PCIe网卡/WiFi网卡运行中掉线多为ASPM电源管理问题少数为链路重训练先查dmesg看有没有PCIe Bus Error、“link down”日志读写寄存器后EQ配置不生效固件覆盖配置或PHY CSR映射错误写入后回读确认检查地址映射4.2 卡在Recovery.Equalization的排查流程第一次遇到卡住的时候很容易慌其实按步骤来很快能定位。我的固定排查流程是第一步确认LTSSM到底卡在哪个子状态。读Controller的LTSSM状态寄存器或者直接在Linux下看dmesg日志看有没有反复出现link down/up的信息。第二步上协议分析仪抓TS1/TS2。这一步最关键判断是单向请求无人响应还是双向都在发但参数对不上。如果一侧的TS1均衡字段压根不变化基本可以断定这一侧的PHY没有响应EQ请求。第三步检查时钟。Recovery.Equalization里有速率切换动作CDR在切换瞬间要重新锁定。如果使用的是SRIS独立参考时钟架构两侧时钟频率差不能太大否则CDR根本锁不住。检查时钟芯片的PPM偏差以及PHY的时钟检测寄存器。第四步确认PHY侧EQ功能没有被关掉。包括PHY的EQ enable、接收端DFE的enable、以及Controller侧GEN3_EQ_CONTROL里的相应开关。这个检查点看着基础但还真遇到过不止一次固件初始化顺序不对把EQ位关掉的情况。第五步把EQ训练超时时间拉长。有些PHY在信道损耗大时训练速度慢如果Controller的超时设得太短还没训完就被强制终止了。增大超时后往往能跑过。4.3 一个真实案例Gen3协商失败回退Gen2去年调一块带Synopsys IP的板卡时遇到一个典型的Gen3协商失败问题。上电后lspci显示链路稳定在Gen2一切正常但把它改成Gen3后LTSSM就一直在Recovery.Equalization来回跳。我先用协议分析仪抓包。Phase 0没问题双方都成功切换到8GT/s速率。但进入Phase 1后Downstream发出了请求均衡的TS1Upstream的TS1却一直保持固定preset不响应。按经验这种“单方面不响应”通常是PHY的发送系数没有被真正配置进去。于是我去读Upstream侧PHY的TX系数寄存器。结果发现C0默认值是0x000也就是主光标权重为0这相当于发送端根本没输出有效信号。接收端当然没法完成均衡。查了PHY的初始化代码发现上电默认值是从一个配置文件加载的这个文件里TX系数清零了导致PHY用了一组全零系数。修正配置文件把初始preset写进去重新训练的第一次就成功进了L0。这个案例给我的教训是看到REC Equalization卡住不要只盯着LTSSM状态多读PHY的系数寄存器经常能发现低级但致命的问题。4.4 关于“网卡测速中断”的一类问题提醒网上经常有人问Realtek RTL8852BE这类PCIe接口WiFi网卡用网页版测速时会中断、掉线。从PCIe调试角度看这类问题大多数不是链路均衡引起的而是电源管理中ASPM主动电源管理等导致的链路挂起。遇到PCIe设备运行中掉线我建议先查日志。dmesg里有没有“PCIe Port Link Down”或者“PCIe Bus Error”这类记录。如果有可以先把ASPM禁掉只测试数据通路是否稳定。禁掉ASPM后如果还掉线再考虑是不是PCIe链路本身的问题那时才需要去查均衡、查信号、查供电。但也不能完全排除EQ因素。比如一些设备在从L1省电状态唤醒时需要重新训练链路。如果EQ参数余量不足重训就会失败反映出来就是设备掉线又恢复。这种情况下手动加大发送端预冲或者在BIOS里关闭L1状态往往能明显改善。4.5 几个实用的小技巧调试EQ时掌握几个小技巧能快不少。第一学会用固定preset做隔离测试。先把自动训练关掉固定一个保守的preset如果链路能稳定工作说明硬件信道没问题问题出在自动训练算法如果固定preset都不稳说明板子本身的信号完整性需要优化。第二善用PHY的自适应状态寄存器。很多PHY会暴露DFE tap的收敛值、CTLE档位、自适应是否收敛的标志。训练完成后把这些值读出来能对比出某次训练是收敛到了极限还是留有余量。第三注意PCB走线损耗预估。Gen3的插损预算大约在20dB以内Gen4更严只有15dB左右。如果板卡走线明显超标再怎么调EQ也救不回来只能调整连接方案或者缩短走线。第四维护一张调试记录表。每块板卡的EQ完成状态、最终preset、眼图VMA值、是否出现过降速全记下来。等到下一版改板这些数据就是最宝贵的参考。PCIe链路均衡调试是门熟能生巧的活。抓包、看寄存器、测眼图三板斧用熟了大多数问题都能很快收敛。最后再分享一个我自己常用的技巧遇到EQ训练不稳定的新板卡先用最短的高质量线缆把两个PCIe设备直连起来跑一遍Gen3。如果直连都不稳先回头查PHY配置如果直连稳、上板卡不稳那才是走线和连接器的问题。这个隔离法能帮你避免在错误的层面浪费大量时间。