ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

FPGA实现千兆以太网:TEMAC+裕太微YT8531SH的RGMII调试实战

FPGA实现千兆以太网:TEMAC+裕太微YT8531SH的RGMII调试实战 这块板子上一代用的还是进口PHY国产化之后换成了裕太微的YT8531SHFPGA侧依旧是Vivado 2018.3里现成的Tri-Mode Ethernet MAC IP核。当时想得比较简单PHY芯片换一换改一下复位引脚和PHY地址最多个别寄存器不兼容微调一下驱动就行。实际动手之后才发现问题远不止“换芯片”这么简单从MDIO读不到ID到RGMII时序怎么都不收敛再到百兆通千兆不通一路排下来我前后折腾了将近两周。我把这个组合下踩过的坑、排查思路和最终能跑通的完整配置流程整理出来。这个方案的适用场景很明确FPGA是Xilinx 7系列Artix-7/Kintex-7等Vivado版本2018.3MAC层用PL侧的TEMAC IP核PHY用YT8531SH的RGMII接口网口速率要求千兆。整个流程可以拆成硬件摸底、IP核配置、XDC时序约束、上板调试四个阶段每个阶段都有几个特别容易翻车的地方这篇就当是给准备做国产PHY替代的同行提个醒。1. 方案定位TEMAC IP核与YT8531SH的配合逻辑先用一句话讲清楚这个方案在做什么以太网通信链路里FPGA内部跑的是MAC层逻辑PHY芯片负责物理层的编码、并串转换和线缆驱动。Xilinx在Vivado里提供了现成的MAC软核也就是Tri-Mode Ethernet MAC简称TEMAC在纯PL逻辑里实现MAC层功能对外支持GMII、RGMII、MII这些物理接口。板子上的YT8531SH就是接到TEMAC的RGMMI接口上完成物理层收发。TEMAC这个IP核的定位和Zynq里的PS端GEM还不一样。Zynq PS自带GEM控制器那是ARM侧在做MAC而这个方案用的是PL可编程逻辑实现MAC不依赖PS所以它更适合纯FPGA平台或者是Zynq里不想占PS MIO的场合。Vivado 2018.3这个版本对应的TEMAC IP核界面和后续版本不太一样如果拿新版Vivado里Ethernet Subsystem的习惯去操作会发现对不上号这也是我建议先看清IP版本的原因。再来看YT8531SH本身。这是裕太微电子的一款单端口千兆以太网PHY支持10/100/1000Mbps三种速率接口有RGMII和MII等版本。它和常见的进口PHY比如88E1512、DP83867在功能上是同一类东西也提供标准的MDIO管理接口所以从MAC侧看寄存器读写、PHY地址配置、自动协商这些流程都是通用的。但“功能兼容”不等于“寄存器兼容”YT8531SH的寄存器映射、上电自举配置引脚、复位时序要求都有自己的细节直接用进口PHY那套初始化代码大概率不灵。我在方案选型时还踩过一个方向性的坑如果应用对接口带宽要求更高或者板上PCB走线限制了并行信号线数量更合适的可能是SGMII接口的PHY配合Vivado里的1G/2.5G Ethernet PCS/PMA IP核。但SGMII需要高速串行收发器对FPGA资源占用、参考时钟要求都不一样不是简单替换RGMII方案就能解决的。所以做选型评估时先想清楚板上是RGMII还是SGMII再决定IP核和PHY型号这一步千万别省。2. 上电之前的硬件细节时钟、复位与PHY地址很多人拿到板子第一件事就是打开Vivado开搞IP核我建议反过来先把硬件上的几个关键点确认清楚。RGMII接口在千兆模式下对时钟方向、电压域和复位时序极其敏感硬件细节没理顺后面所有调试都会变成猜谜。2.1 千兆模式下的GTX_CLK到底从哪里来RGMII在1000Mbps模式下TXC也就是发送时钟由MAC侧输出给PHY频率125MHz。这个125MHz不是PHY自己产生的而是由FPGA内部的时钟源产生后通过IO输出到TXC引脚。很多参考设计里把这个时钟叫作GTX_CLK或者TXC概念上指的是同一条路径。这里有个典型的错误做法有的板子设计想省一个FPGA时钟源直接用PHY的CLKOUT_125M引脚输出作为MAC侧的工作时钟。听起来很合理PHY反正要出125MHzFPGA直接借用一下不就行了但实际调试时会发现一个类似“鸡生蛋”的问题PHY没有完成初始化和自动协商之前这个CLKOUT引脚可能是高阻或者无输出而MAC侧要收发数据就必须先有稳定时钟结果就是整个链路起不来。就算PHY进入了正常状态这个时钟的相位噪声和抖动也很难保证MAC侧逻辑的时序余量。我的建议是TXC的125MHz时钟由FPGA内部MMCM/PLL产生经过BUFG之后一方面送给TEMAC IP核作为参考时钟另一方面通过ODDR原语输出到TXC引脚。板子上PHY的25MHz参考晶振是PHY自己用的和这个126MHz MAC侧时钟互不替代。25MHz管脚如果没有正常起振PHY完全无法工作这一点上电之后可以先拿示波器量一下。2.2 复位信号低电平时间不够就是link不起来的根源YT8531SH的复位引脚RESET_N低有效手册一般会明确最小复位脉冲宽度常见的是10ms级别有些PHY是1ms。保险起见我用的是上电后至少拉低100ms再释放的做法因为复位期间PHY会采样strap引脚配置如果复位释放时strap电平还没稳定PHY地址、延迟模式这些东西就会随机后面调试完全没法做。另一个容易忽略的点是FPGA配置期间这个复位引脚的电平状态。如果复位信号由FPGA的普通GPIO控制在FPGA未配置完成时这个引脚默认可能是高电平也就是PHY提前开始工作。这时候PHY采样的strap可能不对后面就算FPGA配置完了再拉一次复位时序也不够干净。我一般把PHY复位信号接到FPGA BANK上的一个普通IO并且在FPGA设计里用一个上电延时计数器至少在配置完成后等待100ms再释放PHY复位。有条件的话在复位信号上加一个RC延迟电路做硬件兜底更稳妥。2.3 PHY地址不是猜的是strap引脚配出来的PHY地址这个坑可以说是老生常谈但每次都有人踩。YT8531SH的PHY地址由PHYAD相关strap引脚的上下拉状态决定常见地址范围0x0到0x7。调试时先用万用表量一下strap引脚的上下拉电阻确认板上配置出来的是几号地址再把这个地址写进MDIO访问代码或者TEMAC的PHY地址寄存器。我遇到的情况是板子上strap默认配出来的PHY地址是0x3而习惯性代码里写的是0x1结果MDIO读回来全是0xFFFF。后面核对了原理图才发现问题。另外YT8531SH的strap引脚通常还同时控制RXDLY、TXDLY、LED工作模式等这些会影响RGMII时序和状态指示建议在硬件检查阶段就一并记录清楚。MDIO总线本身的硬件细节也要注意。MDC是推挽输出不需要上拉而MDIO是双向数据线必须要有上拉电阻否则读操作会一直读到高电平。这个上拉电阻放在PHY侧还是FPGA侧都行但不能没有。3. Vivado 2018.3中的IP核配置TEMAC的创建与参数选择硬件细节确定了接下来才轮到Vivado操作。IP核配置本身不复杂但参数选错会导致后面一系列连锁问题比如用户接口选了一个不确定怎么接的、时钟域选项理解错了最终综合出来的设计根本跑不起来。3.1 在IP Catalog里定位正确的IP核在Vivado 2018.3的IP Catalog里搜索“ethernet”会出现几个容易混淆的IP核包括Tri-Mode Ethernet MAC、AXI Ethernet、1G/2.5G Ethernet PCS/PMA or SGMII。这里要选的就是第一个Tri-Mode Ethernet MAC在7系列器件下它是软核实现MAC功能。AXI Ethernet更像是给嵌入式处理器集成用的内部其实也是TEMAC加AXI接口封装但直接定制时用TEMAC更灵活。SGMII那一个是配合高速串行收发器用的RGMII场景不适用。这个IP核在Vivado 2018.3里还是老界面和2019.2之后的Ethernet Subsystem完全不一样。如果之前只熟悉新版本很可能在配置页面里找不到对应选项这一点留意一下就好。3.2 物理接口、速率和用户侧接口的搭配双击Tri-Mode Ethernet MAC进入定制界面第一个要选的是Physical Interface这里必须选择RGMII。如果选成GMII或者MII后面引脚数量、时钟方向全部都会变。速率建议直接选10/100/1000Mbps自适应虽然只跑千兆可以选单一1000Mbps但保留低速率模式对调试很有利后面排查问题的时候可以降速验证。用户侧接口我建议选AXI4-Lite这是一个管理接口通过它读写TEMAC内部的寄存器以及MDIO控制器。数据通路方面如果不想额外接AXI DMA这类重量级模块可以选GMII接口作为用户侧数据输出自己写一个简单的MAC用户层逻辑来收发帧。这个方式结构最简单但也意味着用户侧时序要自己处理。如果想直接用AXI4-Stream接DMA数据通路会更规范不过工作量会大不少。MDIO控制器建议勾选Enable MDIO Master让TEMAC内部自带MDIO主机功能这样可以通过AXI4-Lite寄存器访问PHY调试阶段会非常方便。很多一开始说“MDIO没有信号”的问题往往不是接口问题而是IP核根本没配MDIO主模式。3.3 直接用IP的example design可以省掉一半工作量IP配置完成后在Vivado的Sources窗口右键点击生成的IP核选择Open IP Example Design会生成一个完整的参考设计工程。这个example design不只是拿来综合仿真看的更重要的是里面有现成的XDC约束文件针对RGMII接口的时钟、输入延迟、输出延迟约束都写好了。我后来在这类项目里的固定做法是先打开example design把里面的约束文件复制到自己工程改掉引脚位置和IOSTANDARD再重新跑综合实现。直接自己从零写RGMII时序约束很容易漏掉某个关键约束而Xilinx官方示例里的数值虽然是给标准RGMII场景准备的但思路一定是正确的基于它去调整远比从零开始高效。4. RGMII时序与XDC约束最容易翻车也最容易糊弄过去的部分RGMII接口在FPGA设计里是一个很有意思的东西表面上看只有8根数据线加上时钟和控制线好像不复杂但你如果只用顶层逻辑做数据缓冲完全不做时序约束仿真肯定一切正常上板之后各种随机错误就冒出来了。这个设计的核心难点不在逻辑功能而在时序RGMII的时序如果没收敛哪怕功能逻辑再正确也白搭。4.1 RGMII的双沿采样机制RGMII在千兆模式下TXD[3:0]和TX_CTL在TXC的上升沿和下降沿都会被采样等效数据率是125MHz乘2再乘4位也就是1Gbps。发送方向TXC、TXD、TX_CTL都从MAC输出要求在FPGA的IOB里用ODDR把并行数据转成双沿输出。接收方向RXC、RXD、RX_CTL都从PHY输入FPGA要在RXC的上下升沿用IDDR采样。Vivado的TEMAC IP核内部其实已经把ODDR和IDDR例化好了不需要使用者自己写原语。但如果哪一天你决定不走TEMAC自己用GMII逻辑加外部转换来实现RGMII那就必须自己写ODDR和IDDR原语而且要把它们放到IOB中。这也是很多人对RGMII实现疑惑的地方——到底要不要自己写IDDR、ODDR答案是看IP核内部是否已经集成。自己写IDDR原语大概是这个样子用SAME_EDGE_PIPELINED模式可以让上下沿采到的数据在同一个时钟沿之后稳定输出方便后续逻辑处理IDDR #( .DDR_CLK_EDGE(SAME_EDGE_PIPELINED), .INIT_Q1(1b0), .INIT_Q2(1b0), .SRTYPE(SYNC) ) u_iddr_rxd0 ( .Q1(rxd_r[0]), .Q2(rxd_f[0]), .C(rgmii_rxc), .CE(1b1), .D(rgmii_rxd[0]), .R(1b0), .S(1b0) );输出侧用ODDRODDR #( .DDR_CLK_EDGE(SAME_EDGE), .INIT(1b0), .SRTYPE(SYNC) ) u_oddr_txd0 ( .Q(rgmii_txd[0]), .C(gtx_clk), .CE(1b1), .D1(txd_r[0]), .D2(txd_f[0]), .R(1b0), .S(1b0) );4.2 时序约束的思路数据要落在采样窗口的中心RGMII时序约束的本质是告诉Vivado数据相对于时钟在PCB和PHY内部经历了多少延迟从而让布局布线工具知道要保证多大的建立时间和保持时间余量。TX方向的约束TEMAC把TXC、TXD、TX_CTL都作为ODDR输出TXC是时钟输出TXD是数据输出。对PHY来说它在TXC沿采样TXD所以FPGA需要保证TXD和TXC之间的相位关系满足PHY的建立保持时间要求。这就是set_output_delay要做的事情。RX方向的约束PHY输出的RXC和RXD是同步的FPGA的IDDR在RXC沿采样RXD所以需要告诉工具RXD相对RXC的输入延迟是多少也就是set_input_delay。以下是一份可用的示意约束具体数值要以YT8531SH数据手册里的时序参数为准。比如GTX_CLK周期8ns如果PHY的建立时间要求1nsPCB走线偏差约0.5ns那output delay的max大概在8-1-0.56.5ns左右。用这种方式反推会比网上随便抄一组数靠谱得多# 时钟约束 create_clock -period 8.000 -name gtx_clk [get_ports gtx_clk] create_clock -period 8.000 -name rgmii_rxc [get_ports rgmii_rxc] # TX方向数据在gtx_clk双沿输出 set_output_delay -clock [get_clocks gtx_clk] -max 2.0 [get_ports {rgmii_txd[*] rgmii_tx_ctl}] set_output_delay -clock [get_clocks gtx_clk] -min -1.0 [get_ports {rgmii_txd[*] rgmii_tx_ctl}] set_output_delay -clock [get_clocks gtx_clk] -clock_fall -max 2.0 [get_ports {rgmii_txd[*] rgmii_tx_ctl}] set_output_delay -clock [get_clocks gtx_clk] -clock_fall -min -1.0 [get_ports {rgmii_txd[*] rgmii_tx_ctl}] # RX方向在rgmii_rxc双沿采样 set_input_delay -clock [get_clocks rgmii_rxc] -max 2.5 [get_ports {rgmii_rxd[*] rgmii_rx_ctl}] set_input_delay -clock [get_clocks rgmii_rxc] -min 0.0 [get_ports {rgmii_rxd[*] rgmii_rx_ctl}] set_input_delay -clock [get_clocks rgmii_rxc] -clock_fall -max 2.5 [get_ports {rgmii_rxd[*] rgmii_rx_ctl}] set_input_delay -clock [get_clocks rgmii_rxc] -clock_fall -min 0.0 [get_ports {rgmii_rxd[*] rgmii_rx_ctl}]实际项目里我强烈建议把TEMAC的example design约束文件先考进来再根据YT8531SH手册调整数值。不要嫌麻烦RGMII的时序收敛在整个设计里是最容易出问题的一环而且一旦出了问题症状表现为随机丢包、CRC错误排查起来非常痛苦。4.3 RXDLY/TXDLY是YT8531SH上最关键的寄存器开关这里必须单独讲一下PHY内部的延迟配置因为这是国产PHY和不少进口PHY调试思路差异最大的地方。RGMII协议演进到2.0版本之后允许MAC或者PHY在发送/接收路径上插入延迟来保证数据在时钟沿中心对齐。YT8531SH通过strap引脚或者MDIO寄存器控制RXDLY和TXDLY两个选项TXDLY开启时PHY在发送路径上插入约2ns延迟这样MAC侧看到的TXD相对TXC会有更好的对齐。RXDLY开启时PHY在接收路径上插入约2ns延迟这样FPGA侧IDDR采样RXD时能采到稳定的数据窗口。我们板子上YT8531SH的strap默认把RXDLY配置为开启TXDLY配置为关闭。这个组合在多数情况下是合理的因为TEMAC IP核输出TXC时本身就能和TXD保持较好的对齐关系而PHY接收方向如果不插入延迟FPGA用IDDR采RXD很容易采到跳变沿。如果调试中发现1024字节大包不停CRC错误先把RXDLY确认一遍这是最常见的原因。如果strap已经固定无法改也可以通过MDIO寄存器动态改RXDLY/TXDLY。具体寄存器地址和位域需要对应到YT8531SH的数据手册不同批次可能略有差异调试时以手册为准不要套用其他PHY的寄存器地址。5. 管脚分配、电平标准与实现阶段的报错排查IP核和时序约束搞定之后进入实现阶段。这个阶段同样有坑很多错误信息看起来莫名其妙实际上都是管脚分配、电平标准、时钟专用引脚这些物理属性没有匹配好。5.1 电平标准VDDIO没对上一切白搭YT8531SH的IO电源VDDIO常见有2.5V和3.3V两种配置。FPGA这边7系列器件的管脚分成HR和HP两类bankHR bank支持2.5V/3.3V这类电平HP bank最高支持到1.8V。如果PHY的IO电压是3.3V而RGMII信号接到了FPGA的HP bank上那属于硬件设计问题管脚约束里再怎么设IOSTANDARD也没用因为电平根本不在一个域里。正确的做法是在XDC里根据PHY实际IO电压设置IOSTANDARDPHY侧VDDIO如果是2.5V就写LVCMOS25如果是3.3V就写LVCMOS33。这个一定要和硬件原理图核对不能想当然。5.2 rgmii_rxc必须进时钟专用引脚这是很多人在实现阶段第一次报错的地方。rgmii_rxc是PHY输出的时钟信号FPGA内部要拿它作为IDDR的采样时钟因此物理上必须连接到FPGA的MRCC或SRCC引脚。如果PCB布线时为了省事把rgmii_rxc接到了普通IO实现阶段会报CLOCK_DEDICATED_ROUTE错误提示时钟信号没有走专用时钟路径。有一个临时规避手段是在XDC里加set_property CLOCK_DEDICATED_ROUTE ANY_CMT_BUFG让工具绕过这个规则强行布线。但这个做法只适合临时调试产品上不建议用因为绕线时钟的skew和抖动不可控时序余量会很差。如果遇到类似Drc rtstat-2的报错本质上也和引脚分配、时钟树布局冲突相关先检查是不是有信号被错误分配到了专用资源冲突的位置。5.3 实现阶段的DRC和bitstream失败如果实现了但迟迟出不了bitstream或者报DRC错误排查顺序一般是这样的先看有没有未约束的输入输出端口这是最常见的问题再看有没有IOSTANDARD不一致同一个bank里混用了不同电压等级的电平标准会直接报错然后看时序报告如果WNS是负数说明时序约束没有满足RGMII双向时序是最先需要怀疑的地方。我记得有一次综合和实现都过了但generate bitstream一直失败查了半天发现只是有一个输出端口忘记加IOSTANDARDVivado默认给了个LVCMOS12和物理bank上3.3V电平完全不匹配。这类低级错误说多了都是泪但排查时往往最费时间。6. 上板调试从MDIO回读到PING通配置全部完成后进入上板阶段。调试必须按照从底层到上层的顺序来如果一上来就拿着PING工具去试网口一旦不通会根本不知道故障在哪一层。我的顺序是先验证MDIO链路再验证PHY状态接着做回环测试最后才是真正的网络通信。6.1 MDIO读PHY ID一切验证的基础上板后第一件事通过TEMAC的AXI4-Lite寄存器或者直接写一个简易MDIO控制器读取YT8531SH的PHY ID寄存器。读操作返回的数值应该和YT8531SH数据手册里的PHY ID一致。如果读到0xFFFF先检查PHY地址和MDIO上拉如果读到0x0000先检查PHY供电和复位释放。只有MDIO通路正常后面对PHY的寄存器配置才有意义。MDC时钟频率也值得注意。MDIO标准规定MDC最高一般不超过2.5MHz如果TEMAC内部配置MDC太快或者是通过软件模拟MDIO时序时延时不够PHY会表现出时好时坏、偶尔读不到的现象。6.2 link状态、PHY回环和MAC回环MDIO通了之后插上网线观察PHY的link状态寄存器。YT8531SH的BMSR寄存器地址0x01bit2表示link状态link up时这一位应该是1。如果link一直起不来除了检查网线和对端设备还要看PHY的自动协商状态、速率协商结果是不是千兆。然后做回环测试。PHY内部digital loopback是把PHY接收通路直接转发到发送通路这样不依赖外部网线就能验证MAC侧收发通路是否正常。操作方式是修改PHY寄存器0的bit14为1进入digital loopback模式。在这个模式下FPGA发出的数据经过PHY后直接回到FPGA的接收侧。如果数据能正常收到且CRC校验通过说明MAC到PHY之间的RGMII接口基本没问题。再恢复bit14为0进入正常模式。TEMAC IP内部也支持MAC级回环通过TEMAC寄存器配置可以在不经过PHY的情况下把发送数据回路接收出来。这个测试用来区分问题是出在MAC逻辑还是PHY/RGMII物理层。如果MAC回环通过但PHY回环失败问题多半在RGMII接口时序或者PHY配置上。6.3 从ARP到PING网络层验证和CRC排查当回环测试全部通过就可以接真实网络设备验证了。先用PC配置一个和板卡同一网段的静态IP板卡通过ARP请求获得PC的MAC地址然后PING板卡的IP确认双向链路正常。如果PING不通优先抓包看有没有ARP请求和响应。抓包工具推荐Wireshark把PC网口抓包和板上TX/RX统计寄存器对应起来很快能定位是哪一侧的帧没发出去。PING通之后建议再做一次大流量测试不要只测几个ICMP包。实际项目里很多问题在小包场景下不暴露一旦持续跑数据CRC错误、丢包率就开始显现。如果对端收到大量CRC错误说明本端TX路径上有问题如果本端rx_crc_error计数持续增长说明RX路径采样有问题。排查RX方向的首选操作是调整IODELAY或者修改PHY的RXDLY寄存器找到错误计数最低的配置点。这个调整过程本质上是在找数据采样窗口的位置多花一点时间耐心试值得。我在调试中还试过一次“PHY芯片背靠背”的方式用两个板卡A板的TXD直接连到B板的RXD绕过真实的网络变压器和网线用来验证两侧FPGA的RGMII逻辑是否兼容。这个方式对于摸底两端设计是否一致非常直观。如果两个板卡配置的是同一套逻辑但出现奇偶字节序不一致的问题排查起来效率会高很多。7. 最后再分享一点个人经验这套TEMAC加YT8531SH的方案经过完整调试之后其实非常稳定但前提是每一步都要按流程来。我给还没有开始的同行一个建议先把Vivado生成的example design完整跑一遍确认官方IP在这个板子上工作正常再往里面集成自己的业务逻辑。很多问题其实是出在自己的逻辑和IP交接上用example design做隔离能帮你划分责任边界。调试过程中记录好YT8531SH每个关键寄存器的默认值和最终配置值。特别是RXDLY/TXDLY、PHY地址、LED工作模式这些不同批次芯片的strap差异可能导致表现不一致有一份寄存器配置记录在手换板子或者换芯片批次后能省下大量重新排查的时间。这个项目做完之后我的体会是国产PHY芯片本身没有什么不靠谱的地方真正的问题是我们在开发时容易沿用旧硬件环境下的调试经验和思维定式。电阻位置、复位时序、PHY延迟开关这些细节一个不对都会带来看似玄学的网络故障。希望这篇踩坑记录能帮你少走点弯路。
返回列表