ZYNQ PS-MAC+PL-EMIO的RGMII电平不匹配故障排查
说句实话ZYNQ上用PS自带的MACPS-MAC通过PL-EMIO把RGMII引脚引出来接PHY这个用法在板级设计里太常见了——省了在PL里自己写MAC逻辑的功夫PS侧跑Linux直接拿eth0用。但越常见的用法踩坑的时候越容易让人怀疑人生。我前阵子就碰上一个案子PHY的link状态正常协商速率也正确千兆也起来了可就是ping不通数据包零零散散地丢偶发还能通一两个。折腾了快两天最后拿示波器一量根因特别简单——RGMII电平给错了。这篇就把整个排查链路、原理和改法完整写出来给还在坑里的朋友一个参照。1. 异常现象复盘链路UP但数据不通典型的RGMII电平问题表象先说现场。平台上跑的是Linux内核里用的是ZYNQ官方GEM驱动设备树里配置的是gem0接口通过EMIO引到PL再从PL引脚连到一颗RTL8211 PHY上。正常情况下这种方案稳定的很跑个iperf吞吐满速没有压力。但那块板子上ifconfig eth0一看eth0 Link encap:Ethernet HWaddr 00:0A:35:00:01:22 inet addr:192.168.1.10 Bcast:192.168.1.255 Mask:255.255.255.0 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1 RX packets:0 errors:58 dropped:58 overruns:0 frame:58 TX packets:28 errors:0 dropped:0 overruns:0 carrier:0 collisions:0 txqueuelen:1000RX方向全是错误58个包全部是frame error一个都没收进来。TX方向倒是发了28个包没有任何错误计数。这个信息非常关键——它说明PS侧的MAC、DMA、EMIO通道很可能在正常工作问题大概率出在接收路径的物理层信号上。我当时第一反应是查PHY。mii-tool eth0或者ethtool eth0输出的是1000Mbps Full duplexlink up说明MDIO是通的PHY配置也协商成功了。网口插拔时也能看到link down/up的状态变化。所以排除了PHY地址错误、MDIO没通、PHY没复位这类基础问题。紧接着用ethtool -S eth0看详细统计rx_frame_errors、rx_crc_errors都在增长。这说明什么说明引脚上有信号进来但是信号质量差到让MAC侧的RGMII接收接口无法正确解析。当时我还怀疑是不是PCB走线问题毕竟RGMII的走线等长、阻抗匹配都有讲究。但问题是这块板子里RGMII信号从PHY到FPGA引脚的走线很短直连的而且测量阻抗也没发现断线短路。真正让我开始怀疑电压域的是这样一个细节把速率强制降到100Mbps丢包率有所好转但依然有错。而10Mbps时基本能ping通只是吞吐感人。这个规律非常符合电平不匹配的典型特征——速率越高信号上升沿时间和电压裕量问题越致命低速时因为建立时间宽松偶尔能蒙对。这里想先劝一句遇到这种link up但数据异常的情况别急着去调驱动、改DMA描述符、怀疑中断先检查物理层的电气特性。因为驱动错误通常表现为完全不通或者收发计数全挂很少会出现RX大量frame error但TX完全正常这种单方向毛病。2. RGMII电平问题的底层逻辑为什么不是网线、不是PHY也不是驱动想彻底理解这个坑得先回顾一下ZYNQ里PS-MAC和PL-EMIO的组合方式以及RGMII这个接口到底是什么脾性。2.1 ZYNQ的PS-MAC PL-EMIO是怎么组合的ZYNQ的PS里集成了GEMGigabit Ethernet MAC这玩意儿可以工作在两种引脚模式下MIO模式GMII/RGMII信号直接通过PS的MIO引脚引出不需要在PL里做任何约束。引脚固定走线固定配置最简单。EMIO模式MAC逻辑还在PS里但是RGMII信号经过EMIO桥进入PL由PL侧引脚引出。这种模式下设计者可以在PL里自由选择把信号绑到哪些物理引脚上扩展性更强但代价是需要自己处理引脚约束、bank电压、电平标准。我这次用的就是后者。PS里使能了GEM0接口选择RGMII引脚选择EMIO。于是MAC发出的RGMII_TXD、RGMII_TX_CTL、RGMII_TXC以及接收方向的RGMII_RXD、RGMII_RX_CTL、RGMII_RXC全部出现在PL侧等我分配引脚。这个模式下最容易忽略的就是PS侧只负责逻辑不管电气。信号到了PL引脚上到底以什么电平标准驱动取决于PL侧IO bank的配置——具体说就是引脚所在的bank的VCCO电压以及你在XDC里给引脚指定的IOSTANDARD。换句话说RGMII电平不是设置进去的而是由硬件电路决定的。这一点和ZYNQ的PS侧MIO完全不同——MIO的电平是固定的一般跟PS bank的MIO_VREF和MIO_3V3相关。而PL侧的EMIO引出就意味着你要自己为一个高速接口的电压域负责。2.2 RGMII信号的电气特性与电平标准匹配RGMII是个单端、DDR接口。以千兆为例RGMII_TXC/RXC是125MHz的时钟每根数据线同时承载两个bit一个在上升沿采样一个在下降沿采样。125MHz的DDR等效数据率是250Mbps每根线四根数据线加控制线发送方向有6根有效信号。单端DDR在嵌入式板上看起来不算特别快但它的电压裕量和时序裕量是强相关的。RGMII标准里接收端的逻辑阈值通常是电源电压的函数。绝大多数PHY手册上写的是VIH最小值0.7 × VDDIOVIL最大值0.3 × VDDIO这个比例关系很通用。如果PHY的VDDIO是2.5V那么VIH最小就是1.75V。如果此时ZYNQ的PL引脚用3.3V电平输出发射的高电平是3.3V接收端当然能识别——但你得反过来看PHY送过来的数据方向。PHY的输出高电平只有2.5VZYNQ侧如果配置成了LVCMOS33VIH就是2.31V。2.5V vs 2.31V看似过了阈值但余量只有不到0.2V。板子上一旦有点串扰、地弹、电源纹波这一路信号就会被踩到阈值附近产生大量亚稳态和错误采样。如果PHY VDDIO是1.8V而ZYNQ侧是3.3V情况更糟。PHY输出高电平只有1.8VZYNQ的LVCMOS33 VIH是2.31V接收端直接认为所有信号都是低电平一个包都收不进来。反过来ZYNQ发送3.3V给VDDIO1.8V的PHYPHY引脚耐压不够运气好只是识别错误运气不好直接烧PHY引脚。我这次板子上的情况属于中间态PHY的VDDIO引脚被拉到了2.5VZYNQ侧EMIO所在的bank VCCO是3.3VXDC里写的IOSTANDARD也是LVCMOS33。发送方向ZYNQ输出3.3VPHY勉强识别接收方向PHY输出2.5VZYNQ卡在阈值边界上于是RX错误一堆。这个组合最恶心的地方就在这里——它不是完全不通而是半通半不通干扰判断。2.3 为什么电平错误表现为数据异常而非完全不通这是我在这次排错里感受最深的一点。很多人以为电平错了就应该是完全不通、抓不到波形。实际上只要接收端的VIH/VIL阈值没有完全越过信号摆幅MAC依然能偶尔解出几个正确的bit就有可能出现link协商正常、少量ARP或者ping请求能通、DHCP偶尔成功、但持续流量完全不可用。更迷惑的是上升沿和下降沿分别采样的DDR信号如果信号波形在电平阈值附近振荡那么上升沿采样出来的bit正确、下降沿采样出来的bit错误这种概率是相等的。接收端会报CRC错误因为数据包内容解错了。但前导码可能有一小部分是对的于是MAC还能检测到有效信号、报frame error而不是完全silent。rx_frame_errors这个字段的疯狂增长就是这种半死半活状态的典型指纹。我用个直白的类比你在嘈杂的房间里喊话对方能听到你在说话link up但内容断断续续CRC错误偶尔听清一个词某个包通了大部分时候不知道你说啥丢包。这不是对方耳朵有问题也不是你嗓子坏了——而是你们俩一个用高八度、一个用低八度在对话频率对不上。RGMII电平问题做checklist的时候有四个检查点检查项正确状态错误表现PHY的VDDIO电压与FPGA侧bank VCCO一致两端不一致信号摆幅和阈值不匹配FPGA侧bank VCCO与PHY的VDDIO一致3.3V bank对2.5V PHY或反之XDC中IOSTANDARD与VCCO匹配LVCMOS25配2.5VLVCMOS33配3.3VIOSTANDARD和实际VCCO不匹配两边电平标准语义都指LVCMOS同一电压等级PHY手册写HSTL但FPGA侧用LVCMOS3. 完整排查链路复盘从配置到波形逐步逼近根因这一节说一下我实际的排查顺序。不是拿到结果倒推的那种马后炮而是真实踩过的弯路和判断逻辑照着这个流程走大概率能快速定位同类问题。3.1 第一步确认PHY的MDIO可访问、Link状态正常这一步其实是在排除PHY没工作这个方向。Linux下依次执行mii-tool eth0 ethtool eth0看速率和双工模式是不是协商正确。这一步没问题说明PHY已经上电、晶振工作、MDIO通信正常。如果链路协商出来是1000Mbps full duplex那PHY的核心功能基本是好的。同时检查PHY的复位信号很多ZYNQ板卡上PHY的RST引脚由PS的MIO或者PL的GPIO控制。如果复位时序不对PHY可能处于异常状态MDIO能读但数据通路不工作。检查方法就是看复位引脚电平、确认复位释放时间是否满足PHY手册要求大部分PHY要求复位释放后至少等几十毫秒才能访问MDIO。我这次确认了这三个都没问题。如果你在这步就发现link up不了那大概率不是电平问题先查PHY供电、晶振、时钟别往下跳。3.2 第二步区分TX方向和RX方向的异常这一步非常关键。用ethtool -S eth0看计数器如果RX的frame error、CRC error在涨但TX没有error那基本可以断定接收方向有问题。同理如果只有TX错误那关注点放在ZYNQ发送到PHY的路径上。为什么区分方向很重要因为RGMII是单向电平发送和接收各走各的电平域TX方向ZYNQ的PL引脚输出数据给PHY的RGMII RX引脚RX方向PHY的RGMII TX引脚输出数据给ZYNQ的PL引脚这两个方向都可能因为电平不匹配出问题而且可能一个方向好、一个方向坏。我这次的板子就是RX坏、TX好。所以用工具把方向先切出来缩小范围。如果RX方向错误可以做一个小实验在板子上找一个GPIO控制PHY的loopback模式。很多PHY支持MAC侧loopback把ZYNQ发的数据在PHY内部直接环回。如果开了PHY内部loopback之后TX/RX方向都正常了——那说明PHY和MAC的数字逻辑没问题问题出在外部引脚的物理信号上。我这个板子PHY支持loopback打开之后收发都正常当时心里基本有数了问题就在RGMII引脚电气特性上。3.3 第三步在PL里用ILA抓RGMII信号波形到了这一步基本要把逻辑分析能力用上了。因为RGMII信号是通过EMIO引到PL的所以PL里的ILA直接可以观察这些信号不需要外接逻辑分析仪。在Vivado工程里把RGMII_TX_CTL、RGMII_TX_CTL、RGMII_TXD[3:0]、RGMII_RX_CTL、RGMII_RXD[3:0]等信号引到ILA的探针里触发条件设为RGMII_RX_CTL的上升沿或者数据线变化抓一段数据。我当时抓完ILA后看到了非常典型的现象TX方向的数据波形清晰规整TXC和TXD的相位关系也正确。但RX方向的数据在电平不是干净的0或1中间出现很多毛刺和爬坡尤其是在高速跳变的地方。这个在ILA的二进制表示里看不出来但结合统计上大量frame error就很有说服力了。不过ILA有个盲区它看到的是FPGA引脚输入后的数字电平它只能告诉你是0还是1以及sample的时序对不对。它不能告诉你输入模拟信号的实际电压是多少。所以ILA帮你确认了信号在时序上不对、电平判读边缘化但无法直接告诉你根因是电压。3.4 第四步示波器实测RGMII引脚波形一锤定音这一步才是真正的根因判定。拿示波器探头打到PHY的RGMII_RXD[0]或者RGMII_RX_CTL引脚上看信号的高电平电压幅度。我测完之后血压就上来了PHY发出的RGMII_RX_CTL信号高电平稳定在2.5V而且这个PHY的VDDIO引脚上量的就是2.5V。再看FPGA侧对应的引脚配置XDC里绑的是LVCMOS33bank的VCCO量出来是3.3V。两边差了0.8V——在LVCMOS33阈值(VIH2.31V)附近2.5V的高电平刚刚擦着边上过任何一点噪声都能让信号掉进不确定区。拿同一个示波器再看TX方向ZYNQ输出的TXD信号高电平是3.3V给到PHY的VDDIO2.5V的接收端VIH1.75V3.3V给足了余量所以TX方向自然没问题。这时候根因非常清楚不需要再猜了。RGMII电平给错了具体说就是FPGA侧bank电压比PHY侧VDDIO高了0.8V导致PHY送往ZYNQ的信号被判读异常。我的建议是如果你手头没有示波器至少用万用表量一下PHY的VDDIO和FPGA bank的VCCO看看两个电压是否一致。不一致就可以直接确诊不必非等到上示波器。4. 修正与验证改电平配置的完整操作清单根因确认后修正反而不难但有几个细节必须同步处理少一个都可能白改。4.1 明确两侧的目标电平第一步是查PHY手册确认RGMII接口的VDDIO支持范围。RTL8211系列一般VDDIO可以支持2.5V或3.3V具体看型号尾缀和应用电路有些PHY还支持1.8V。AR8031、KSZ9031等也各有差异。必须直接看丝印和手册别想当然。我这边的PHY是VDDIO接在2.5V上所以目标电平确定为2.5V。如果你的PHY这边可以改硬件到3.3V另一个方案是改PHY侧的VDDIO供电——但一般不建议为了适配FPGA去改PHY电源因为PHY的其他LVDS、MDIO等引脚可能有不同电压要求。最稳妥的做法FPGA去向PHY看齐。4.2 修改硬件调整FPGA的bank VCCO找到RGMII信号所在的FPGA bank把该bank的VCCO从3.3V改为2.5V。这个改动通常在原理图阶段就应该确认但实际排错时也可以在后级电源模块上换LDO输出、改反馈电阻来实现。注意一个bank的所有IO共享一个VCCO。如果这个bank上还有其他信号比如其他PHY、LED、GPIO等它们的电平也会跟着变。改电压前要确认bank里没有3.3V-only的外设。这是很容易忽略的雷——我当时那个bank上碰巧只有一个PHY的RGMII信号没有其他外设所以改起来很干净。如果你是用开发板没有硬件修改空间那就要在选型时保证PHY和bank电压匹配。这也是在提醒所有自己layout的朋友ZYNQ EMIO引出RGMII时原理图阶段就要把PHY的VDDIO电压和对应FPGA bank的VCCO画在同一页旁边标注必须一致。这个习惯能救你后半生。4.3 在Vivado里修正IOSTANDARD约束硬件电压改了之后XDC里的IOSTANDARD必须同步改否则Vivado的DRC会报错或者就算能烧bitfile行为也是错的。在XDC中原来的约束可能是这样set_property PACKAGE_PIN U19 [get_ports eth_rgmii_rx_ctl] set_property IOSTANDARD LVCMOS33 [get_ports eth_rgmii_rx_ctl]现在要把所有RGMII相关的引脚改成LVCMOS25set_property IOSTANDARD LVCMOS25 [get_ports eth_rgmii_rx_ctl] set_property IOSTANDARD LVCMOS25 [get_ports eth_rgmii_rxc] set_property IOSTANDARD LVCMOS25 [get_ports eth_rgmii_rxd[0]] set_property IOSTANDARD LVCMOS25 [get_ports eth_rgmii_rxd[1]] set_property IOSTANDARD LVCMOS25 [get_ports eth_rgmii_rxd[2]] set_property IOSTANDARD LVCMOS25 [get_ports eth_rgmii_rxd[3]]TX方向同理。如果你在工程里把所有RGMII引脚集合成bus也可以用一条通配约束set_property IOSTANDARD LVCMOS25 [get_ports {eth_rgmii_*}]推荐用bus方式省得一条条写还容易漏。此外如果你的设计里RGMII引脚所在的bank是HP bank如Bank 500/501那注意HP bank最高只能到1.8V不支持LVCMOS25。这种情况只能选HR bank引脚或者换PHY。踩过一次这种坑的人应该都有印象Vivado里I/O planning那一栏HP bank根本不由你选LVCMOS25。4.4 重新综合实现并烧录验证修复效果硬件电压和XDC约束都改好后重新跑综合、实现、生成bitfile烧进板子。我这次改完后重新上电Linux下再看ifconfig eth0RX错误计数清零ping通了TCP吞吐恢复正常。用iperf跑双方向接近千兆线速。问题解决。但这里我多做了一个验证步骤建议你也做一下把TX和RX方向的loopback都测一遍确认PHY的外环、内环都稳定通过。因为只跑iperf大包可能掩盖偶发错误。我习惯用Linux的ping -f压一下小包延迟再跑一轮iperf双管齐下。小包更考验时序余量大包考验带宽和下溢处理两个都稳了才算真好了。还有一个细节改完硬件电压后PHY和FPGA之间如果存在耦合电容、ESD器件、串联电阻这些器件的电平特性也要扫一眼。尤其串联匹配电阻换电压域后阻值不变通常没问题但如果原本针对3.3V选了比较大的串阻改成2.5V后信号摆幅会进一步萎缩可能出现新的眼图问题。我在这次排查中没遇到但遇到过别人为这事折腾的案例写出来供参考。5. 避坑指南PS-MAC PL-EMIO工作流里的常见错误这次问题解决了但复盘整个项目把几个容易踩的坑列出来每一个都是能让人白加班两三天的级别。5.1 引脚分配和bank电压检查要在布局阶段做不要等PCB回来ZYNQ的EMIO引脚可以绑定到任意支持该接口的bank。但RGMII作为高速DDR信号引脚分配时就要考虑几个约束选择HR bank避免HP bank电压范围限制。ZYNQ-7000的HP bank不支持3.3V一般只到1.8V而绝大多数PHY的RGMII至少2.5V直接冲突。引脚尽量扎堆在一个bank内这样可以统一该bank的VCCO不用为了一两个信号额外加LDO或者电源域。RGMII有十来根信号分到两个bank就会带来跨bank电压不统一的麻烦。确认bank上不能有要求不同电压的其他信号。如果你为了省事把一个3.3V的控制信号塞进了2.5V的bank那就又是一个新坑。原理图阶段用Vivado的Device View或者板级规划工具把引脚Pin Assign先过一遍确认VCCO和IOSTANDARD匹配整套RGMII信号在同一个bank成本几乎为零却能省掉后期大把排错时间。5.2 RGMII的时钟和数据相位关系有时会被误判为电平问题排查过程中我差点误入的一个方向是RGMII内部延迟。RGMII标准下TXC相对于TXD需要有一个固定的延迟通常2ns左右以满足DDR采样要求。很多PHY用内部寄存器配置这个延迟ZYNQ的GEM也可以配置内部延迟。如果电平修正完之后仍然有错误不要急着怀疑还是电平——看看PHY中RGMII TX/RX skew相关寄存器配置是否正确。RTL8211的话RGMII TX delay和RX delay可以通过MDIO寄存器调整。这个和电平问题是两个独立变量但错误表现高度相似都会出现RX错误、CRC错误。我的习惯是电平自动用示波器量波形一锤定音delays则用ILA观察数据的稳定采样窗口两边分开查。5.3 PHY的复位时序和MDIO访问时序还有一个高频坑PHY复位释放后MDIO不能立刻访问。有些PHY需要几十毫秒的内部初始化时间如果Linux驱动或uboot在这个窗口内就去读PHY寄存器可能读到全0或者全F导致配置错误。这会和RGMII电平问题并发出现增加迷惑性。检查复位信号时注意两点一是复位脉冲宽度要满足PHY手册要求二是复位释放到MDIO首次访问之间的延时要足够。很多PHY数据手册给的参考值在10ms到100ms之间Linux的PHY驱动一般会做相关处理但如果你在uboot阶段提前访问过PHY就可能在系统启动后留下一个配置不对的PHY干扰链路状态。5.4 建立一套快速的RGMII信号健康自检流程最后分享一个我沉淀下来的自检流程。这个流程适合在每一块新板子Bring-up阶段跑一遍能提前把包括电平在内的多数RGMII问题拦下来上电后先量PHY的VDDIO和对应FPGA bank的VCCO确认电压一致。这一步30秒能杜绝50%的RGMII问题。Linux起来后看ethtool eth0确认link和速率。ethtool -S eth0看两侧counter是否有error递增。开PHY loopback确认MAC到PHY芯片的整个数字通路没问题。外环ping包iperf吞吐确认物理链路完整。如果有任何error迹象直接上示波器量RGMII数据线和控制线的Voh/Voh幅度看是否与PERI IO电压匹配。这套流程看起来简单但能避免你在驱动问题、DMA问题、中断问题这些方向上浪费无谓的时间。实际上RGMII这类并行单端高速接口大多数Bring-up阶段的数据异常都是电气层面的问题而电气问题里电压域不匹配又占了相当大的比例。这次这个案子给我最深的感受是很多问题不是玄学只是我们把检查的顺序搞反了。链路不通用就开始翻驱动代码的人很多但先去量电压、量波形的人很少。RGMII电平这个事儿就这么直接——量一下VCCO和VDDIO多大事儿都清楚了。
上一篇/下一篇内容由系统自动关联
返回资讯列表 →