FPGA以太网调试:SGMII IP核角色配置与链路故障定位指南
做FPGA以太网最先卡人的往往不是RTL写得怎么样而是Vivado里这个自带IP——1G/2.5G Ethernet PCS/PMA or SGMII。名字又长又绕配置界面上还有SGMII、1000BASE-X、MAC、PHY、共享逻辑一堆选项看着都眼熟真等板子回来开始调才发现坑全藏在细节里。之前帮一个朋友查新板子的网络问题PHY是市面上很常见的千兆PHYFPGA这边直接把IP按默认的1000BASE-X生成了结果link始终起不来折腾了两天才定位到问题根本不在PCB和焊接上而是IP的角色配错了。当SGMII IP核和外部PHY芯片一起使用的时候IP应该配置成MAC模式而不是把自己当成PHY侧设备。这篇文章把这类问题的原理、配置逻辑和排查过程完整写出来适合那些做过GMII/RGMII、第一次切到SGMII的人也适合已经把IP跑起来但链路不稳定的朋友做参考。1. 先把这个IP的“分工”看清楚PCS和PMA到底替你扛了什么1.1 从MAC出来的数据为什么要过一道8B/10B很多人一开始都把以太网简化成了“MAC过来PHY出去”但实际上中间还有一大段逻辑。无论是SGMII还是1000BASE-X物理层都不是直接把GMII那8根数据线送上高速串行链路的这中间必须经过PCS和PMA两个子层。PCSPhysical Coding Sublayer做的是编码和握手把从MAC侧收到的8 bit并行数据编成10 bit码组也就是常说的8B/10B编码同时负责链路建立过程中的自动协商、码组对齐、错误码传播这些脏活。之所以要8B/10B是因为高速串行链路不能像并行总线那样带一个独立的时钟过去接收端必须从数据流里自己恢复出时钟这就要求数据流里必须有足够的跳变。8B/10B编码通过把连续的0或1控制在5位以内保证了接收端CDR不会“失锁”代价是多出25%的带宽开销。PMAPhysical Medium Attachment负责的是真正的模拟部分把PCS送来的并行码组串行化经过GT的TX引脚发出去接收方向则是对进来的差分信号做均衡、时钟恢复、串并转换。Xilinx这颗IP里的PMA并不是你理解的“外部PHY芯片”它只是FPGA内部GT收发器的那一层模拟前端。换句话说外部PHY芯片管的是网线上的差分信号而IP内部PMA管的是FPGA引脚到GT并行数据之间的转换。理解这层关系很重要因为后面遇到任何链路问题都要先想清楚问题出在FPGA内部GT到PCS这一段还是FPGA的SGMII引脚到外部PHY这一段的电气链路上还是外部PHY本身没有配置对。这三段故障的表现可能完全一样——都是link up不了但定位手段完全不同。1.2 SGMII和1000BASE-X名字像脾气完全不同这颗IP支持两种协议SGMII和1000BASE-X。很多第一次用的工程师会想都是8B/10B都是1.25Gbaud的线速率是不是随便选一个就行这恰恰是最大的坑。SGMII全称Serial Gigabit Media Independent Interface它本质上是MAC和PHY之间的芯片间接口不是给网线用的协议。它的对端通常是外部PHY芯片的SGMII引脚而不是线缆另一端的设备。SGMII的自动协商在MAC侧和PHY侧之间进行协商的内容很简单这个链路的速率是多少——10M、100M还是1000M。1000BASE-X不一样它是在物理介质上跑的光口或背板协议比如1000BASE-SX/LX光模块。它的自动协商是这台设备和对端设备之间的事协商的内容除了速率还包括双工模式、流控能力这些参数。两者线速率一样编码格式都是8B/10B但自动协商使用的有序集不同码组对齐的规则也不同。从示波器上看两个信号都像1.25G的高速差分波但协议层面它们互不兼容。对比项SGMII1000BASE-X典型用途FPGA与外置PHY芯片之间的接口光模块、背板链路协商对象MAC侧与PHY侧之间本设备与链路对端之间协商内容10/100/1000M速率速率、双工、流控能力线速率1.25G / 2.5G1.25G编码方式8B/10B8B/10B这里要给个非常直白的结论如果你板子上有一颗外部PHY芯片PHY的SGMII端口接到了FPGA那么FPGA这边的IP大概率应该选SGMII而不是1000BASE-X。选了1000BASE-X两边可能在电气上能收到码流但自动协商永远过不去PHY会一直停在“没找到有效对端”的状态。这种故障非常有迷惑性因为不是完全没信号而是协议层始终建立不起来。1.3 IP内部两条通道数据面和管理面要分开看这颗IP内部可以粗分成两条通道调试时脑子里一定要有这根弦数据面和管理面。数据面就是马上要跑的以太网报文通路。在发送方向GMII TX数据进来经过8B/10B编码、串行化从GT的TX引脚出去接收方向GT的RX引脚收到差分信号经过时钟恢复、8B/10B解码从GMII RX数据出去。这条通路上的核心信号包括txd、tx_en、rxd、rx_dv、rx_er这些。管理面则是用来配置和监控这条链路的核心是MDIO接口。通过MDIO可以读PCS内部的状态寄存器也可以访问外部PHY芯片的寄存器。如果配置成1000BASE-X模式还需要通过MDIO写自动协商的Advertised Ability字段告诉对端自己能做什么。管理面和数据面不是严格独立的自动协商的结果最终会决定PCS工作在哪个速率但这个结果不是凭空产生的而是通过管理面的寄存器配置一步步建立起来的。这意味着什么意味着你排查问题的时候不能只盯着数据信号。先问问自己MDIO通了吗自动协商完成了吗PHY寄存器读出来link status是什么如果管理面都没打通数据面再干净也白搭。2. 什么时候开内部MAC和外部PHY联调时的模式选择2.1 纯PCS/PMA的透传玩法先说不带内部MAC的用法。在IP配置界面里如果你不勾选“Enable Ethernet MAC”这类选项这颗IP就只是PCS/PMA不包含以太网MAC。这时候你的FPGA逻辑里必须自己有个MAC或者另外例化一个以太网MAC IP核然后把MAC的GMII接口接到这颗IP的GMII接口上。这种玩法看起来多此一举但实际上很常用。比如你已经在某个工程里有了一个成熟的MAC验证环境或者你需要对MAC做深度定制比如加自定义的FCS处理、做特定的帧过滤这种情况下就不想让IP内部再带一个MAC而是把PCS/PMA做成纯透传的“背板管道”。纯PCS/PMA模式下SGMII链路两端的MAC、PHY角色需要你自己搞清楚。如果对端是外部PHY芯片而你自己的MAC已经在跑SGMII自动协商那也可以工作但这时候链路是否起来既要看你的MAC侧实现是否完整也要看外部PHY有没有正确配置成SGMII模式。复杂度会比直接用IP自带MAC高不少。2.2 外部PHY芯片场景SGMII核就该当MAC用现在说整篇文章最核心的那个经验点。很多工程师在板上放了一颗千兆PHYFPGA通过SGMII和这颗PHY对接PHY的另一侧是网口变压器和RJ45。这种情况下链路要跑通FPGA里必须有一个完整的MAC和PHY进行SGMII协商。如果你不想自己写MAC那最简单、也最不容易出错的做法就是在这颗IP里打开内部的Ethernet MAC让整个IP作为数据链路层和物理编码层的合体。通俗地讲IP和外部PHY芯片一起使用的时候IP应该扮演MAC角色外部PHY扮演PHY角色两边通过SGMII接口握手。这样IP会自动完成SGMII自动协商序列的发送和接收你的FPGA逻辑只需要通过GMII或AXI4-Stream接口收发报文就行了。具体在Vivado里配置时建议这样选协议类型选择SGMII不要选1000BASE-X。速度根据你的实际场景选择1G或2.5G。打开Ethernet MAC相关选项让IP内部包含完整MAC。管理接口按需选择MDIO或AXI4-Lite至少保留MDIO用于访问外部PHY。Shared Logic选择方式根据单核还是多核场景决定后面会专门说。这里还要提醒一个容易忽略的步骤外部PHY芯片本身也要配置成SGMII模式。很多PHY支持RGMII和SGMII两种MAC侧接口具体用哪种是靠芯片的strap引脚在复位时采样的。比如有些PHY芯片的CONFIG引脚决定接口模式、PHY地址、AN模式如果你只把FPGA这边配对了PHY那边却因为strap问题工作在RGMII模式那FPGA的SGMII引脚上根本收不到有效信号。判断方法也很简单看PHY的寄存器。如果PHY的SGMII模式没打开有些PHY连MDIO访问都会表现出异常行为或者读出来的模式状态寄存器与你预期不符。调试这种问题不要一开始就怀疑FPGA代码先用万用表确认strap电阻的焊接和电平再读PHY寄存器确认模式。2.3 2.5G速率下该选2500BASE-X还是SGMII这颗IP名字里的2.5G并不是指线速率2.5G的千兆PHY而是指当以太网线速率提升到2.5G时SGMII也可以用2.5G的线速率来承载。这时候接口还叫SGMII但位时钟从1.25G变成了2.5GPCS部分逻辑会做相应的速率适配。有些型号的PHY芯片比如支持2.5G的NBASE-T PHY可以在SGMII接口上跑2.5G。这种场景下IP协议依然选SGMII只是速度档位选2.5G。还有一种是2500BASE-X这个一般用于光模块或背板直连比如两端都是FPGA或者FPGA和某个交换芯片通过光模块对连。这种情况下选2500BASE-X更符合协议定义。但如果你板子上有PHY芯片又是想走2.5G铜缆那就得确认PHY的SGMII口是否支持2.5G线速率。很多标称千兆的PHY并不支持2.5G SGMII硬拉到2.5G只会导致链路失败。选型阶段就出现这个问题其实挺烦的因为PHY数据手册里对SGMII最高速率的描述有时候藏在脚注里。我的习惯是拿到PHY型号先搜SGMII和2.5G这两个关键词如果没有明确支持2.5G的说明就当它不支持。省得后面板子回来再折腾。3. 时钟、复位、接口时序这三个不一起理清链路永远不干净3.1 GT参考时钟的接法与“共享逻辑”选项SGMII在物理上走的是FPGA的GT高速收发器所以必须给GT提供参考时钟。1G/2.5G Ethernet PCS/PMA IP这个场景下最常见也最推荐的做法是给GT提供125MHz参考时钟。1.25G线速率和2.5G线速率都可以从125MHz参考时钟倍频出来这是大多数板卡的标准做法。有些板卡设计为了省晶振会只提供一个156.25MHz或者100MHz的时钟给GT Bank想靠PLL分频倍频凑出SGMII需要的速率。理论上能算出来但实践中会引入额外的抖动和配置复杂度尤其是2.5G模式对参考时钟质量更敏感。所以除非有强烈的板级原因否则老老实实给125MHz。这里的坑在于Vivado里有个“Shared Logic”选项影响参考时钟的引脚约束方式。如果你选择把共享逻辑放在核内IP会直接管理GT的时钟引脚你可能需要约束一个类似IBUFDS_GTE4的专用参考时钟缓冲器如果你选择把共享逻辑放在核外IP会暴露出一个GT参考时钟输入端口你需要自己在顶层例化参考时钟缓冲并确保时钟进入正确的GT Bank。很多第一次用的人会忽略这个选项结果生成的示例工程里参考时钟引脚约束和自己板卡上的实际网络对不上上板后根本起不来。我的建议是先确定你的板卡上125MHz接到了哪个GT Bank然后要么按这个Bank的专用引脚位置去约束要么调整Shared Logic方式把参考时钟处理放到你能控制的层级。3.2 userclk和userclk2为什么会有两个IP会输出两个用户时钟userclk和userclk2。很多新手会问为什么不能就用一个时钟因为两个时钟服务于不同的位置。userclk是GT并行侧的时钟。对于1.25G线速率GT并行位宽通常配置成10 bit或者20 bit对应的并行时钟是62.5MHz或者更低的频率。PCS的8B/10B编解码和位对齐逻辑主要以这个时钟的域为基础。userclk2则是GMII接口侧的时钟标准GMII接口是125MHz。如果你使用的是内部MACMAC侧的GMII或AXI4-Stream接口都以userclk2为基准。如果你的设计里还有用户逻辑需要和GMII接口交互一定不要自己另外产生一个“看起来是125MHz”的时钟而要用IP输出的userclk2。这一点的重要性在10M/100M模式切换时体现得非常明显。SGMII在10M/100M下依然跑1.25G的物理线速率但通过重复或扩展的方式把有效数据率降下来MAC侧看到的GMII时钟并不会变成2.5MHz或25MHz而是依然保持125MHz靠数据有效信号来拉伸。如果你用外部自己生成的慢时钟去对接整个时序会彻底错乱。所以规则很简单时钟一律用IP输出的复位和有效信号标准处理。3.3 复位时序的先后顺序和典型失败这个IP的复位不是“给个低电平就完事”这么简单。GT收发器内部有完整的复位状态机上电后必须先做PLL复位、等待PLL锁定然后做TX/RX数据通路复位再等待各个reset done信号拉高。如果你在上电后太早把复位释放PLL还没锁定GT输出时钟就是乱的PCS这边根本没法工作。我踩过的一个典型坑是CPU复位信号给得特别短只有几十个微秒结果GT还没完成初始化复位就已经释放了。看起来整个IP好像启动了但tx_reset_done和rx_reset_done一直不拉高或者高一下又掉下来。后来在逻辑里加了一段延时确保复位至少保持几百微秒以上并且把gt_tx_resetdone和gt_rx_resetdone作为后续逻辑的启动条件问题才消失。推荐的复位处理顺序大致是等待电源电压稳定等待参考时钟有稳定输出。给整个IP一个足够长的复位至少覆盖GT PLL锁定时间。观察IP输出的tx_reset_done和rx_reset_done都变成高电平再去操作MAC。如果使能了自动协商复位后不要立刻去读link status要给协商留出时间。这个顺序在工程里通常用一个小的状态机或者序列器来做而不是靠一个简单的计数器。因为计数器只能延时不能感知GT内部真正的锁定状态一旦板卡温度变化导致PLL锁定时间变长固定延时就可能不够。3.4 自动协商期间的MAC侧行为自动协商不是瞬间完成的。SGMII自动协商有1.6ms左右的链路定时器实际链路建立时间还会受到外部PHY初始化时间的影响。可能你在复位完成后几百微秒去看状态寄存器发现link还是down其实不是出了问题而是协商还在进行中。这时候最忌讳反复复位。我就见过有人看到link没起来就把IP复位来复位去结果每次RESET都会打断正在进行的自动协商链路永远起不来。正确的做法是复位一次然后等足够长的时间比如1秒以上再去读状态。如果链路灯亮了说明自动协商已经完成如果还没亮再考虑是不是配置问题或硬件问题。内部MAC如果启用了自动协商它会在SGMII链路上发送自己的速率能力字段同时解析PHY返回的能力字段最终选出一致速率。如果FPGA和PHY之间自动协商不成功常见原因包括PHY的模式配置不对、MDIO地址不对导致IP根本没读到PHY状态、或者IP被配成了1000BASE-X导致双方协商协议不一致。4. 调试实战从灯不亮到轻松跑满带宽4.1 第一次上板最节省时间的自检顺序每次拿到一块全新的SGMII板子我不会直接就跑完整工程而是按顺序做一轮自检。这个顺序可以帮我快速把问题范围从“整条链路都未知”缩小到某一小段。第一步先确认GT参考时钟真的到了。用IBERT或者在Vivado里直接看GT的复位状态如果参考时钟没进来GT根本不会开始工作。第二步检查FPGA和外部PHY之间的引脚连接尤其是发送正负、接收正负有没有接反有没有串了AC耦合电容。SGMII通常需要100nF左右的AC耦合电容放在靠近发送端的位置。第三步检查PHY的strap配置确认PHY工作在SGMII模式而不是RGMII或其他模式。第四步通过MDIO去读PHY的基本状态寄存器看能不能正常回数据。这四步看着简单但能排除掉现场70%以上“链路起不来”的问题。很多时候问题根本不是FPGA逻辑而是板卡焊接、配置电阻贴错、或者引脚约束搞错了。4.2 回环测试的层次和选择回环测试是SGMII调试里最有效的手段但回环有很多层次用错了会误导自己。最底层的是GT串行回环也就是在GT收发器内部把TX数据直接回到RX通道。这种回环可以验证GT参考时钟、PLL、CDR是不是正常但是绕过了外部PHY和PCB走线。如果串行回环都是通的再考虑外部链路。更实用的是外部PHY的环回有些PHY支持在SGMII接口侧做数字环回FPGA发出去的数据经过PHY内部环回后回到FPGA。这种环回能验证FPGA与PHY之间的SGMII信号链路是很关键的一步。再往上是PHY的MAC侧环回和线路侧环回验证的是PHY内部和网口变压器部分。回环层次选择的基本原则是从最靠近FPGA的那一层开始逐级往外测。哪一层开始不通问题就定位在哪一层到上一层的边界上。不要一开始就在RJ45口上插着别人的交换机去ping那等于把无数个不确定变量全堆在一起。4.3 用MDIO看PHY状态链路问题定位最快路径MDIO是SGMII调试中最值钱的管理通道。外部PHY的状态寄存器里藏着大量信息不看就等于黑盒调板。通常第一步是访问PHY的寄存器0x0和0x1看基本控制与状态。寄存器0x0可以触发软复位、开关自动协商寄存器0x1里的link status位、自动协商完成位是判断链路是否建立的最直接依据。再往深一点大部分PHY还有扩展状态寄存器比如铜缆侧状态、SGMII侧状态、速率协商结果等。不同的PHY地址和寄存器布局不一样所以最好先去翻一下对应PHY的数据手册把该型号的寄存器映射打印出来。实际操作里最常遇到的问题是MDIO读回来全是0xffff。这不是PHY坏了而是MDIO地址和PHY地址不匹配或者MDIO管理时钟的频率配置不对或者PHY的复位一直没释放。遇到这种读数先不要怀疑PHY芯片先看地址、看复位、看MDIO时序。还有一个很隐蔽的点很多PHY的上电复位需要一定时间如果你在PHY还没完成初始化时就通过MDIO去配置它配置可能被忽略。所以上电后建议先等几十毫秒到几百毫秒再开始读PHY状态。4.4 一会儿通一会儿不通的典型坑如果你遇到的现象是板子刚上电时能ping通跑一会儿或者温度变化后链路就断然后过几秒自己恢复这种“一会儿通一会儿不通”的故障最折磨人。我在实际项目中遇到过一个这样的案例。FPGA和PHY之间的SGMII走线在PCB上跨了很长一段没有按差分阻抗控制过孔也比较多导致信号反射严重。刚开始工作正常是因为芯片温度低、驱动能力正常信号还能被PHY的接收端正确恢复但跑久了温度升高GT输出眼图变差PHY的CDR就开始频繁失锁表现出来就是链路断断续续。这种问题靠改逻辑是解决不了的只能改硬件。临时缓解的办法是降低GT的TX摆幅、调整预加重或者把SGMII速率从2.5G降到1.25G试试看。但根本办法还是要把PCB走线理顺保证100欧差分阻抗减少过孔残桩让走线尽量短。另外SGMII上的AC耦合电容不要太靠近接收端常规做法是靠近发送端放置两侧都要有完整的参考地平面。5. 最后再补两个容易被忽略的设定写完上面的调试部分还有两个项目里反复被问到的点我觉得值得单独拎出来讲。第一个是“共享逻辑”选项到底影响什么。如果你在一个FPGA里只用一个SGMII核那共享逻辑放在核内还是核外没太大区别但如果一个工程里同时用到了好几个以太网核共享逻辑放在核外就可以让多个核共用同一个GT参考时钟和复位逻辑节省资源和引脚。代价是你要自己在上一层把参考时钟处理好设计复杂度会高一些。我的经验是少于三个核直接用核内共享逻辑就行简单省事超过三个核再考虑把共享逻辑提取出来。第二个是10M/100M自适应时的FPGA侧接口表现。SGMII的一个优势是物理线速率恒定10M/100M/1000M切换对MAC侧的GMII时钟频率没有影响MAC侧依然是125MHz只是有效数据周期变少。这一点在调试时容易产生错觉明明PHY协商到了100M但FPGA侧看到的数据引脚还是125MHz的节奏。其实这是正常的。不要试图去改变userclk2的频率而是要根据MAC的状态寄存器或者PHY协商出的速率在MAC侧正确产生对应的使能信号。关于这个IP网上各种教程确实不少但很多都停留在“怎么生成IP”这一步真正到了板级调通的时候遇到问题的原因反倒是那些配置选项和角色理解。我自己也在这里面踩过不少次坑尤其是那个“IP当PHY用还是当MAC用”的经典混淆。后来想明白了本质就一句话这块IP放在FPGA里你就是要它替你做MAC侧该做的事外面接了PHY芯片你要做的不是再关心网线的电气细节而是确保两边都知道自己是谁。把这个想通后面的时钟复位时序问题其实都只是按部就班的事。