☰
Xilinx FPGA 10G Ethernet Subsystem 从 Example Design 到上板调试全攻略
2026/10/8 9:01:52 网站建设 项目流程

先说句实在话:Xilinx FPGA 的 10G Ethernet Subsystem,是我做高速接口这么久以来,觉得“文档最全、但上手门槛依然不低”的 IP 之一。如果你直接双击 IP 开始配参数,大概率在 example design 阶段就会被一堆复位信号和时钟约束搞懵。这篇文章我把这套 Subsystem 的 example design 从创建、仿真到上板的完整路径写一遍,顺便把那些文档里不写、但实际调板一定会踩的坑也翻出来。不管你是在做图像传输、高速数据采集,还是想通过 SFP+ 口把 FPGA 接进一台万兆交换机,这套经验都适用。

1. 为什么从 Example Design 入手:设计思路与方案选型

1.1 10G Ethernet Subsystem 到底是个什么东西

很多人第一次看到“Subsystem”这个词,容易误以为它只是一个简单的以太网 MAC 核。实际上,Xilinx 的 10G Ethernet Subsystem 是把一整条 10G 以太网数据链路打包成了一个大 IP:从用户侧的标准 AXI4-Stream 接口,到内部 MAC 核处理以太网帧,再到 PCS/PMA 层完成 64B/66B 编解码,最后落到 GT 高速收发器上。也就是说,你不需要自己把 MAC、PCS、GT 初始化、回环状态机一层一层拼起来,Vivado 里这个 IP 已经把协议栈帮你串好了。

如果不用这个 Subsystem,自己从零写一套 10G 以太网 MAC+PCS,工作量有多大呢?10GBASE-R 这一层光 64B/66B 编解码、加扰、对齐、误码率监控这几个模块,就能让一个熟手写几个星期,而且大概率第一版还调不通。用独立 PHY 芯片的方案倒是省心,但 BOM 成本和 PCB 布线压力又上来了。所以对绝大多数 FPGA 工程师来说,用 Xilinx 这套 Subsystem 是当前最平衡的方案。

但在实际项目里,这个 IP 不是“配个参数就能直接跑到 10G 带宽”的。官方之所以给每个 IP 都配套 example design,就是因为它默认你并不清楚 GT 怎么初始化、复位怎么释放、数据怎么灌进去。Example design 相当于一台“已经装好的样车”,你先把这台样车点火跑起来,再研究发动机内部结构。

1.2 为什么第一步必须是 Example Design

我自己带过好几个做万兆接口的同事,大家普遍有一个习惯:拿到新 IP,喜欢直接往自己工程里塞,上来就写 AXI4-Stream 数据源,结果出了问题也不知道是 MAC 的问题、GT 的问题,还是自己逻辑的问题。这就是典型的分不清“链路是否已经通”的状态。

Example design 最大的价值,是它给了你一个最小的可运行闭环。它内部已经包含了 Frame Generator(发帧模块)和 Frame Checker(收帧校验模块),以及整套 GT 复位管理逻辑。综合完直接下载,就可以通过内部环回验证数据通路。你不需要写一行应用逻辑,就能确认三件事:

  1. GT 收发器所在的硬件通道是否健康。
  2. 10G Ethernet Subsystem 的 IP 配置是否正确。
  3. 时钟和复位约束是否和板卡实际布线匹配。

我在实际调试中的习惯是:任何带 GT 的高速 IP,第一件事永远是先把 example design 跑通,再谈业务逻辑。这个习惯帮我省下了无数排查时间。你可以把 example design 当成“安全的边界”:只有它跑通了,之后所有业务问题才能放心地归因到自己的逻辑上。

1.3 动手前的环境检查清单

在打开 Vivado 之前,先确认几个硬性条件,否则后面会卡在各种奇怪的地方:

  • Vivado 版本:不同版本生成的 example design 结构和 IP 版本有差异,我自己用的是 2021.2,下面的操作步骤都以这个版本为例。
  • License 授权:10G Ethernet Subsystem 在部分器件和部分 Vivado 版本下需要单独的 IP License,有的版本则随器件支持包提供。如果打开 IP 配置界面时提示 license 问题,先去 Xilinx 官网申请评估 License,不要硬着头皮往下点。
  • 开发板:带 SFP+ 或 QSFP 接口的 Xilinx 开发板都可以。VCU118、KCU105、Alveo 系列我都试过,操作流程基本一致。
  • 光模块和线缆:准备一个 SFP+ 模块,如果是短距离调试,买一对光模块加一根光纤跳线;或者直接用 SFP+ 直连铜缆(DAC)也方便。

另外提醒一件事:如果你打算用电脑网卡直接连 FPGA,普通千兆网卡是肯定不行的,必须用万兆网卡或经过万兆交换机中转。这一点很多人一开始没留意,以为网线插上就能通,结果白白折腾半天。

2. 核心架构拆解:10G Subsystem 内部到底有什么

2.1 从 AXI 接口到光口:一条 10G 数据的旅行路径

要理解 example design 里那些信号是干什么的,先得知道一条以太网帧在 FPGA 里走了哪些路。我习惯把这套链路分成四层:

  • 用户逻辑层:你用自己的 RTL 逻辑产生数据,通过 AXI4-Stream 接口把数据包给 IP。
  • MAC 层:负责组以太网帧,包括帧头、目的 MAC、源 MAC、类型/长度、数据 payload、FCS 校验和。同时负责流量控制和统计信息收集。
  • PCS/PMA 层:把 MAC 层送过来的数据做 64B/66B 编码,加扰后变成串行比特流。
  • GT 收发器层:物理层,负责高速串并转换,通过 SFP+ 接口送出光纤。

这个 Subsystem 里,MAC 和 PCS/PMA 是在 FPGA 逻辑里实现的,GT 是硬核,三者拼成一条完整链路。实际调试的时候,不同层之间都有环回点,这也是 example design 能一步步定位问题的关键。

2.2 时钟和复位:最容易翻车的区域

整个 example design 里,最容易被忽略却又最致命的就是时钟和复位。我先给你一张我整理的对照表,调板时对着查会省很多事。

信号/时钟频率/来源作用注意事项
gt_ref_clk156.25MHz,来自板载可编程时钟GT 参考时钟,10GBASE-R 下标准值必须是低抖动时钟源,不能随便用普通 IO 拉一根线出来
core/clk(用户侧时钟)64bit 接口为 156.25MHz,256bit 接口约 39.0625MHz用户 AXIS 接口逻辑的工作时钟由 GT 的输出时钟或参考时钟经 MMCM/PLL 生成
dclk50MHz~100MHz给 DRP 动态重配置端口用的调试时钟不启用 DRP 时可以不管
gt_tx_resetdone / gt_rx_resetdone来自 GT 硬核指示 GT 发送/接收方向复位完成这是后续 MAC/PCS 复位能不能释放的前提
tx_axis_aresetn / rx_axis_aresetn用户逻辑复位AXIS 接口复位必须在 GT resetdone 拉高之后再释放

我在实际调试中遇到过最典型的情况:GT 一直 link 不上,查了半天,最后发现是板卡上那个给 MGTREFCLK 用的时钟芯片默认输出是 125MHz,而不是 156.25MHz。10GBASE-R 标准要求参考时钟必须和线速率匹配,125MHz 根本对不上。很多人以为参考时钟只是给 GT 一个工作节拍,频率差点也能 PLL 锁定,这种想法在低速接口上可能成立,在 10G 上基本是死路一条。

再讲复位。Example design 里有一个专门的复位管理模块,它会先等 GT 的 tx_resetdone 和 rx_resetdone 都拉高,再依次释放 MAC 和 AXIS 接口的复位。如果你后面自己写逻辑时把这个复位管理模块删了,或者自己拼了一个复位时序,极大概率会遇到“复位释放早了导致状态机卡住”的问题。所以如果你要裁剪 example design,复位这一块建议原封不动保留。

2.3 AXIS 数据接口和管理接口怎么看

10G Ethernet Subsystem 对外暴露的接口中,用户最关心的就是 AXI4-Stream 数据通路。以最常见的 64bit 接口为例:tdata 一次传 8 个字节,tvalid/tready 做握手,tkeep 表示哪几个字节有效,tlast 表示这是这一帧的最后一个拍,tuser 里面携带一些错误标记和帧起始信息。你可以把它想象成一条流水线:tvalid 代表“我这拍有货”,tready 代表“我这拍能接”,两边同时为高这一拍数据才算真正传过去。这也是 AXIS 协议最核心的握手规则。

除了数据通路,还有一组 AXI4-Lite 管理接口,用来配置 MAC 地址、清统计寄存器、控制流控开关等。Example design 里有一个 axi_lite_master 模块,上电后会自动完成初始化配置,所以你不需要手动去写寄存器,但要知道它的存在——如果以后自己实现管理逻辑,得兼容这套寄存器地址映射。

至于统计接口,tx_statistics_vector 和 rx_statistics_vector 这两个信号里藏了不少好东西:FCS 错误数、过短帧数、帧数、字节数都有。调板时遇到丢包,先别急着抓波形,看看统计向量里的 CRC error 是不是在涨,能少走很多弯路。

3. 完整实操:用 Vivado 跑通 10G Ethernet example design

3.1 创建工程并生成 Example Design

打开 Vivado,新建一个 RTL 工程,器件选你手上的开发板型号,这里我以 UltraScale+ 器件为例。工程建好后,在左侧 IP Catalog 里搜索“10G Ethernet”,会看到 10G Ethernet Subsystem 这个 IP,双击打开配置界面。

配置界面的关键选项我一个个说:

  • Shared Logic 选项:这里建议选“Include shared logic in example design”。这样生成的 example 会把 GT 的 common 逻辑、时钟模块放到 example 的顶层,而不是塞进 IP 内部。好处是结构清晰、方便加 ILA 调试,以后你自己工程里要集成多个以太网核时,也可以参考这套共享逻辑的写法。
  • 速率和协议:选 10GBASE-R,这是光口最常见的模式。其他选项比如 10GBASE-KR 是背板应用,咱们普通调试用 Base-R 就够了。
  • AXI4-Stream Data Width:第一次跑通建议选 64bit,接口简单、时序压力小。等完全跑通了,再换成 256bit 去追求更高吞吐。
  • 管理接口和统计接口:默认保留,这些不影响功能,但调板时非常有用。

配置完成后,点击 Generate 生成 IP。这一步结束之后还没完,真正关键的操作来了:在 Sources 窗口里找到这个 IP,右键选择 “Open IP Example Design”。Vivado 会自动生成并打开一个独立的示例工程,里面有完整的 RTL、仿真 testbench 和约束文件。

生成好之后,我建议你先别急着改任何东西,直接点综合(Synthesis),确认默认工程能编译过。这一步是验证你 Vivado 环境、License、目标器件三者是否正常的最快方式。

3.2 弄清楚 Example Design 里的文件结构

很多人在示例工程里迷路,是因为不熟悉文件结构。这里我帮你拆一下关键的几个部分:

  • 顶层文件:通常叫xxx_example_design.v,是例子工程的最顶层,里面例化了前面说的 Frame Generator、Frame Checker、复位管理、GT common、以及 10G Ethernet Subsystem 本身。
  • frame_gen 模块:按固定格式产生以太网帧,帧头里带入特殊的 pattern 标记,payload 是递增或固定数据,便于接收侧比对。
  • frame_check 模块:接收远端环回回来的数据,和本地期望的 pattern 做比对。一旦发现不匹配,bad_frame_count 就会增加。
  • axi_lite_master 模块:上电后自动通过 AXI4-Lite 写寄存器,完成 MAC 地址、FCS、流控等初始化。
  • 约束文件:锁定 MGTREFCLK 引脚和 SFP+ 相关的引脚。这里有个大坑:example design 的约束是照官方开发板来的,如果你用的是第三方板子,引脚肯定对不上,必须改成自己板卡的原理图。

拿到 example design 之后,我强烈建议你花半小时把这个工程的层次结构图(Open Design 之后的 Schematic)看一遍,把信号从 frame_gen 到 GT 再到 frame_check 的路径走一遍。这一步的价值,比你后面照着教程改代码大得多。

3.3 仿真:让环回先跑起来

Example design 自带的 testbench 可以直接跑,操作路径是 Flow Navigator → Run Simulation → Run Behavioral Simulation。仿真环境会自动完成复位、配置 GT、发送数据、环回校验整个流程。

仿真启动后,你会看到波形里一堆 GT 相关信号在慢慢初始化。这里有一点要提前做好心理建设:GT 仿真模型初始化很慢,经常要跑很长的仿真时间才开始发数据。我见过不少人以为仿真卡死了,直接关掉窗口。判断方法很简单:去看gt_tx_resetdone和gt_rx_resetdone这两个信号有没有拉高,如果拉高了,说明 GT 已经就绪,后面 state machine 才会启动。

最终判定仿真是否通过,就看 frame_check 模块的统计结果。你可以把bad_frame_count和good_frame_count加到波形窗口里观察,正常情况是 bad 永远为 0,good 在持续增加。

仿真跑通这一步,实际上已经把“逻辑正确性”验证掉了一大半。因为 example design 默认在仿真里用了 GT 内部环回,相当于数据在 GT 处就回头了,PCS、MAC、AXIS 数据路径全都被覆盖到。如果仿真都报错,大概率是 IP 配置或者 Vivado 环境的问题,去查硬件之前先把这个搞定。

3.4 上板调试:从环回到光口互通

仿真过了,接下来就是上板见真章的时候。先综合、实现、生成比特流,然后用 Hardware Manager 下载。第一次上板,我建议你严格按照下面这个顺序来:

第一步:GT 内部环回。在 example design 里,环回模式通常可以通过顶层参数或者 JTAG 虚拟 IO 控制。先把环回设置在 GT 层,也就是数据刚到 GT 发送端就立刻从接收端收回来。下载 bit 后,看 frame_check 的计数是否正常。这一项通过,说明 GT 通道、时钟、复位都没问题。

第二步:外部光模块环回。如果你有一个 SFP+ 光模块,可以用一根光纤把 TX 和 RX 短接,或者用一个支持环回的光模块,让光信号真正走一遍物理层。这里需要注意光模块的 TX_DISABLE 引脚,有的模块默认是拉高的,会导致光口不发光,检查一下有没有被正确拉低。

第三步:和对端设备互通。如果对端是一台万兆交换机或万兆网卡,你要清楚一个关键点:example design 本身没有 IP 层协议栈,它不会响应 ping,也不会主动发 ARP。所以你把 FPGA 接入交换机,发现 ping 不通是完全正常的。此时你需要的是用测试仪发包,或者让 PC 持续发送固定 UDP 帧到 FPGA,而 FPGA 侧要么做环回、要么做收包统计。

这一步很多人会误解,以为 10G Ethernet Subsystem 自带 TCP/IP 协议栈——它不是。它只解决了以太网 MAC 层和数据链路层的问题,IP 层以上都要用户自己实现。所以我在做和 PC 的互通验证时,通常会让 PC 通过 DPDK 或者专用发包工具打流,FPGA 帧检查计数器作为判断依据。

上板过程中,我强烈建议在 example design 里临时加一个 ILA(集成逻辑分析仪)核,挂在 AXIS 接收接口上。第一次抓数据时,重点看 tvalid/tready 的握手是否正常,以及以太网帧头的前 8 个字节是不是对端发来的目的 MAC。

4. 常见问题与排查技巧实录

4.1 GT 链路起不来:link 迟迟不 up

这个应该是我被问得最多的问题。现象是板子上 bit 下载完成后,link up 信号一直拉不高,或者 GT 的 resetdone 信号始终不出现。

排查路径就三步。第一,确认 gt_ref_clk 频率。10GBASE-R 必须是 156.25MHz,用示波器或者 ILA 抓一下频率对不对。很多板载可编程时钟芯片(比如 SI5328、CDCM6208)默认输出不是这个频率,需要写初始化代码或者通过 IIC 配置。第二,确认复位顺序。example design 的复位管理模块会自动处理,但你如果改动过,就要检查是不是在 resetdone 之前就松开了后级复位。第三,检查 SFP+ 模块。把光模块换一个试试,或者先用 GT loopback 模式绕过光模块,看链路能不能 up。如果 GT loopback 能 up,说明问题大概率在光模块或物理链路上。

实在不行,就走 IBERT。Vivado 里有独立的 IBERT example design,可以绕过整个以太网协议,直接测试 GT 收发通道。用 IBERT 扫描一下眼图,如果眼图都是糊的,那就是硬件设计问题——可能是参考时钟抖动太大,也可能是 SFP+ 连接器附近电源去耦没做好。记住,IBERT 是排除物理层问题最快的工具,比你在协议栈里猜来猜去高效得多。

4.2 link up 了但丢包、CRC 错误狂涨

如果你的 link 已经 up,但 frame_check 报错、或者统计向量里 CRC error 一直在增加,这属于第二类典型问题。

先说最容易犯的低级错误:对端设备的速率不匹配。10G 光模块不能直接和你电脑上的千兆光口通信,两边速率必须一致。还有就是要确认对端口是否强制 10G,而不是在跑自动协商(10GBASE-R 本身没有协商机制)。另外检查一下你的以太网帧是不是合法:FCS 校验是从目的 MAC 到 payload 整体做的,如果在内部环回时正确、接了外部设备就报 CRC 错,优先怀疑物理链路质量问题,换一根光纤、换一个模块试试。

还有一个比较隐蔽的问题:如果你用了 example design 自带的 frame_gen,它发的帧是固定 pattern。外部设备收到后一般不会关心内容,但如果对端设备也在做严格的帧校验,你要确保帧长在 64~1518 字节之间,过长或者过短都会报错。

4.3 复位与时钟相关的坑

这一类问题表现很奇葩,比如“每次上电第一次帧总是丢”、“复位后要等好一会才恢复”、“RX 正常 TX 死活不行”。这些基本都是复位和时钟域处理的问题。

我自己踩过最深的一个坑:在裁剪 example design 时,为了省资源把复位管理模块拆了,自己用 LUT 做了个简单的复位同步器。结果软复位一拉低,GT 还没准备好,MAC 就先开始跑了,于是第一帧必然丢。后来老老实实回到 example design 的复位时序,把 GT resetdone 信号接到自己逻辑的等待条件里,才解决。

时钟方面要注意跨时钟域。GT 输出的恢复时钟和你用户逻辑的工作时钟如果不在同一个来源,信号之间可能会有相位差和抖动,正确的做法是加异步 FIFO 去做缓冲。Example design 里的 AXIS 接口默认已经有 FIFO 缓冲,但你自己加的模块一般没有,别在这个问题上省事。

4.4 Vivado 版本和 IP 版本不同导致的问题

很多老教程写在 2020.1 或更早版本,照搬到新版本时经常编译报错或者信号名对不上。Xilinx 每年更新 IP 版本,10G Ethernet Subsystem 在不同 Vivado 版本下的 example design 文件结构、部分信号命名、复位逻辑都可能变化。我的建议是:以当前版本生成的 example design 为准,不要强行沿用旧工程的修改。

还有一种情况是工程从旧版本升级,Vivado 自动升级 IP 后,例子工程里有些文件没被正确更新,导致仿真和综合结果不一致。遇到这种情况,最简单的办法是删掉旧 IP,重新生成一个新的 example design,然后手动对比差异。不要怕重来,这比在未知的旧版本坑里浪费时间高效得多。

4.5 常见问题速查表

我把调板过程中高频出现的现象和解决办法整理成了一张表,顺手贴在调试笔记里:

现象可能原因处理方法
GT resetdone 始终拉不高参考时钟频率不对/没时钟检查 gt_ref_clk 是否为 156.25MHz
link 一直 up 不了光模块或线缆问题换模块/换线,或先开 GT loopback 隔离
link up 但 frame_check 报错环回模式不对或对端帧格式不合法确认环回层级,确认帧长在标准范围
统计向量 CRC error 增长物理链路质量差/对端速率不匹配IBERT 扫眼图,确认对端为 10G 速率
第一次上电丢第一帧复位释放过早等 GT resetdone 拉高后再释放 MAC 复位
仿真长时间不跑完GT 仿真模型初始化慢看 resetdone 信号是否拉高,耐心等待
换 Vivado 版本后编译报错IP 版本不匹配删除旧 IP,重新生成 example 再比对

最后再分享一点我的体会

这一套 10G Ethernet Subsystem 的 example design 跑下来,我最深的感受是:它不只是一个“演示工程”,更像是一张安全地图,告诉你在高速接口里哪些地方容易出错、哪些时序必须先满足。我后来做项目,凡是涉及高速串行接口,都会养成一个习惯——先把官方 example 的时钟树和复位树抄到笔记本上,画成框图,再动自己的代码。这样做的好处是,出了问题你知道是硬件的问题、GT 的问题,还是自己逻辑的问题,不会眉毛胡子一把抓。

另外一个实用小技巧:调试时把 GT resetdone、link up、PCS 状态这些关键信号引到板上的 LED,一眼就能看出系统卡在哪一级。别小看这几颗灯,调 10G 的时候它们比逻辑分析仪先帮你定位问题。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询