队伍第一次用紫光同创的盘古系列开发板做以太网项目,PHY用的是RTL8211,UDP回环测试时PC端Wireshark抓包全是乱序和重传。仿真里数据流完全正确,上板后ILA看MAC层发送使能也正常,但CRC校验错误计数一直在涨。想问问有经验的同学,这种情况一般先查RGMII接口的时序约束还是先查CRC模块的字节序?
2026年FPGA大赛用国产紫光同创盘古板做千兆以太网UDP回环,为什么PC端抓包全是乱序,是MAC层时序还是CRC校验没对齐?
5 个回答

先说结论:你这种情况八成不是CRC模块本身算错了,而是RGMII发送路径的时序没收敛,导致PHY侧采样到的数据/控制信号偶发错位。为什么这么说?因为CRC错误计数在涨、同时PC端表现为乱序和重传,说明帧确实发出去了、PHY也收到了,只是某些bit或某些字节在传输链路上被采错。如果CRC模块的字节序真的错了,那应该是每一帧都错、错误率接近100%,而不是「部分乱序」。
顺着这条线往下推:RGMII在千兆模式下是DDR,TX侧数据和TX_CTL都在时钟双边沿采样,FPGA内部逻辑到IOB再到PHY之间要走一段PCB。盘古板这类国产开发板,PHY到FPGA的走线延迟、IOB的时钟到输出延迟(Tco)如果没做约束,综合器默认按普通逻辑处理,很容易出现建立/保持违例。表现就是:ILA看MAC发送使能正常、数据看着也对,但PHY实际采到的已经偏了。
那CRC和字节序要不要查?要,但顺序上应该放在时序之后。判断依据很简单:先做静态时序分析,看TX路径有没有违例、有没有对RGMII接口加set_output_delay约束;如果约束齐全且时序干净,再去怀疑CRC。查字节序有个土办法:发一个固定内容的短帧,比如全0x55或递增序列,用ILA抓MAC输出和PHY输入端口,对比每一位是否对齐,能很快排除是大小端还是位序问题。
还有一个容易被忽略的点:RTL8211在千兆下需要TX时钟由FPGA提供(TXC),如果你用了内部逻辑分频而不是专用时钟资源,抖动会很大,也会造成偶发误码。建议先确认TXC是不是从PLL/MMCM出来的、有没有做相位调整。
排查顺序我建议这样:一,看时序报告和约束,确认RGMII TX有没有set_output_delay;二,用ILA对比MAC输出与PHY侧采样;三,用固定pattern验证字节序;四,最后才动CRC模块。你们现在CRC错误计数是一直涨还是偶尔涨?这个细节能帮判断是系统性错位还是随机误码。

先查RGMII时序约束吧。CRC要是字节序错了,基本每帧都挂,不会只是乱序重传。ILA看使能正常不代表PHY采到的对,千兆DDR下TX路径没约束很容易偏。

个人感觉先别急着怀疑CRC模块,CRC算错通常是整帧稳定错,而你们是乱序加重传,更像是链路层偶发误码。
一条主思路:把「谁在错」定位清楚。做法是发一段固定数据,比如0到255循环的payload,让MAC发出去,同时在FPGA侧用ILA抓MAC的TX接口,在PHY侧(如果能引出)或用一个已知正常的抓包工具对比。如果FPGA侧数据对、PC端收到的有固定bit翻转或字节错位,那就是物理链路/时序问题;如果PC端收到的数据规律性整体偏移,才去查字节序。
盘古板配RTL8211,RGMII接口的TX_CTL和TXD是DDR输出,约束没写全的话,综合工具根本不知道要满足PHY的建立保持要求。很多队伍第一次做都栽在这,仿真对、上板错,就是因为仿真不含IO延迟。
所以顺序建议:先补set_output_delay约束并看时序报告,再做固定pattern对比,最后才动CRC。你们用的是官方例程还是自己写的MAC?这个影响挺大。

先给你一个能立刻判断方向的土办法:把UDP回环改成最笨的固定小包,payload就发0到255循环,两边都不做任何协议栈处理,PC端用Wireshark看每一帧的字节。如果错的位置每次都一样、比如固定第3个字节翻了个bit,那大概率是RGMII的某根数据线或控制线时序没收敛;如果错得没规律、这帧错那帧不错,才轮到怀疑CRC模块本身。为什么这么判?因为CRC算错是逻辑问题,它是确定性的,同一段数据算出来永远是同一个错值,不会忽好忽坏。
盘古板配RTL8211这条路,很多队伍第一次踩的坑就是RGMII的TX约束。千兆下TXD和TX_CTL是DDR双边沿,工具默认按普通逻辑走,PCB上的走线延迟和IOB的Tco都没算进去,仿真当然对,上板就飘。所以我的建议是先别动CRC,先把set_output_delay和set_input_delay按PHY手册的建立保持窗口补上,跑一遍时序报告看TX路径有没有violation。
顺带说个容易被忽略的风险:有些板子的RTL8211时钟是PHY出的,如果FPGA侧约束里时钟定义错了,时序分析结果会骗你。另外CRC字节序的问题也不是完全没可能,但它的表现通常是整帧100%挂,跟你说的『乱序加重传』对不上。
你们现在是用ILA抓的MAC侧还是PHY侧?这个决定了下一步该往哪查。

这个问题我倾向于把它当成一次『信号完整性+时序』的排查,而不是软件逻辑的排查。理由很简单:仿真对、上板错,本身就是时序或物理层的典型特征。CRC模块是纯组合/时序逻辑,它的行为在仿真里和上板后应该完全一致,除非你的CRC用了跨时钟域或者复位没处理好——但那也会在仿真里暴露。
千兆以太网在盘古这类板子上,RGMII是绕不过去的坎。RGMII在1000M模式下,TXD[3:0]和TX_CTL都是DDR输出,也就是说数据在时钟的上升沿和下降沿都要稳定。FPGA内部逻辑到IOB、再到PCB走线、再到RTL8211的输入,这一整条路径的延迟必须被约束覆盖。如果你只写了create_clock,没写set_output_delay,综合工具会认为输出路径没有外部延迟要求,它就不会去优化这条路径的延迟,结果就是PHY采样时数据还没稳定或者已经变了。
表现上就是:ILA在FPGA内部看MAC的发送使能和数据都正常,因为ILA抓的是内部信号,它看不到IOB之后的延迟。但PHY那边采到的就是错的,于是CRC校验失败、PC端重传、Wireshark显示乱序。注意这里的『乱序』很可能是重传导致的序号跳跃,不是UDP本身乱序。
排查顺序我建议这样:第一步,确认RGMII的TX和RX约束都写了,尤其是TX,因为你是发送方向出问题。第二步,用ILA抓MAC的TX接口,同时用一个已知正常的抓包设备在PHY和PC之间对比,看错误是发生在FPGA到PHY还是PHY到PC。第三步,如果确认是FPGA到PHY这段,重点看时序报告里TX路径的slack,以及PCB上RGMII走线是否等长。
至于CRC字节序,我的经验是:如果字节序错了,那每一帧都会错,错误计数会线性增长且和帧数一一对应,不会出现『部分帧正常』的情况。你现在是乱序加重传,说明有些帧是能过的,这更像偶发误码。
最后提一句,如果时序约束补了还是不行,可以试着把千兆降到百兆跑一遍。百兆下RGMII是SDR,时序余量大很多,如果百兆能通,基本就锁定是千兆时序问题了。你们板子的RGMII约束是参考官方例程还是自己写的?这个很关键。
发表回答
登录后可在本页底部提交回答