ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

FPGA以太网接口调试实战:基于Vivado 2019.1的RGMII MAC设计

2026/10/5 12:14:43 拓冰建站 浏览量
FPGA以太网接口调试实战:基于Vivado 2019.1的RGMII MAC设计 作为一个常年用Xilinx平台做FPGA开发的人我接到过不少“把板子上的网口跑起来”的活儿。大部分时候需求方对以太网接口的理解就是“能ping通就算成功”但真到了调试现场从IP配置、管脚约束到时钟复位、回环测试每一步都藏着坑。这篇文章我就用Vivado 2019.1这个版本完整走一遍以太网接口的搭建流程把方案选型、IP配置、逻辑设计、板级调试和常见问题全串起来给正在做类似项目的朋友一个可以直接参考的路线。文章会覆盖从硬件环境准备到最终用Wireshark抓到回环报文的完整过程。无论你是刚接触FPGA网口开发还是已经调通过但想梳理一下细节都可以对照着查漏补缺。我会尽量说清楚每一步背后的设计考虑而不是只给出“点哪里”的操作步骤。1. 整体设计与思路拆解1.1 为什么选Vivado 2019.1以及什么项目适合它Xilinx的Vivado版本更迭很快2019.1放在今天看确实不算新但它仍然是一个很有存在感的版本。原因在于Xilinx 7系列和UltraScale系列的绝大多数IP核在2019.1上都有稳定可用的版本而且这个版本对Windows和Linux的兼容性都处理得比较成熟。相比更早的2018.x2019.1在布局布线算法和IP Catalog的完整性上有明显改进相比2020以后的新版本它又不需要升级到最新的Vitis统一工具链学习成本低很多。如果你手头的板子是Artix-7或者Kintex-7并且项目里不涉及Versal、RFSoC这些新器件那2019.1完全可以作为主力版本。我在实际项目中遇到过好几次因为用了过新的Vivado版本导致旧IP核无法迁移的问题反而在2019.1上一切正常。做以太网接口这类相对成熟的功能稳定压倒一切。1.2 软件MAC核与硬核MAC的取舍搭建以太网接口首先要回答一个问题用FPGA内部的逻辑资源实现MAC媒体访问控制层还是用芯片内嵌的硬核MAC在7系列和UltraScale系列上Xilinx提供了两种路线硬核MAC比如Zynq-7000的GEMGigabit Ethernet MAC或者某些器件上集成的Ethernet MAC硬核。这类方案不占用可编程逻辑资源MII接口的信号时序也由硬件保证适合处理复杂协议栈。软核MAC通过IP Catalog里的Tri-Mode Ethernet MAC IP实现数据通路和控制逻辑都在可编程逻辑里构建。优点是灵活可以自定义数据位宽、FIFO深度、管理接口方式代价是消耗逻辑资源时序需要自己约束。我这次选择的是Tri-Mode Ethernet MAC软核方案因为任务是基于纯FPGA逻辑实现以太网接口不带处理器或者只带MicroBlaze软核。用软核可以把MAC、DMA、用户逻辑全部放在一片可编程逻辑里后续扩展也方便。另外还需要决定是否使用AXI接口。如果你的设计里带有MicroBlaze或者Zynq PS那么AXI Ethernet IP是更好的选择它内置了DMA可以直接对接系统的内存映射。如果是不带处理器的纯逻辑设计Tri-Mode Ethernet MAC更轻量控制和数据接口都简单得多。我在这个项目里的场景就是纯FPGA所以选后者避免引入不必要的AXI总线复杂度。1.3 回环验证把复杂网络协议先放一边第一次搭建以太网接口最容易犯的错误是一上来就想实现完整的TCP/IP协议栈。实际上协议栈软件化程度很高很多功能可以放到处理器上跑FPGA这边更关注的是MAC层的正确性。我的思路是先实现一个MAC层的内部回环用户逻辑发送的数据帧在MAC内部直接回到接收通路通过以太网调试工具或者逻辑分析仪能看到完整的数据帧结构确认MAC的配置和时序都没有问题。然后再做板级外部回环用网线连接板子的PHY芯片电脑端发一个Ping命令FPGA侧用ILA抓RGMII引脚上的信号确认真实物理链路上的字节流是正常的。最后一层才上ARP协议让FPGA能响应网络里的ARP请求这时候电脑就能ping通板子。每一步都有明确的验证目标和排查手段出了问题也容易定位。很多人在第一步就卡住往往是因为MAC内部的时钟复位还没理清楚。2. 环境准备与工程建立2.1 安装Vivado 2019.1时需要留意的点Vivado 2019.1的安装包有好几种WEBSIT版是下载安装工具再从线上拉取组件对网络环境要求比较高Self Extracting Web Installer也是网络安装的方式。我建议有条件直接下载Complete Installer的离线安装包一次性包含所有器件支持和IP省去后续安装到一半失败重来的麻烦。安装过程中有几个实际问题容易被忽略安装路径建议不要带中文也不建议带空格否则后续编译工程时可能因为路径解析出问题。安装时选择器件支持如果你是做纯逻辑设计勾选7 Series和UltraScale就够了Zynq的SOC支持也建议一起勾上因为很多调试工具和IP会依赖它。许可证方面如果用的是免费WebPACK License要确认目标器件是否在支持列表内。7系列里的Artix-7大部分在WebPACK范围内但Kintex-7、Virtex-7的部分型号需要Site License才能综合实现。还有个很多人会遇到的坑安装完成后第一次打开License Manager有时候会弹不出来。这种情况通常和Java运行环境有关Vivado自带的JRE在某些系统版本上会出问题。最简单的处理办法是重新运行Vivado安装包的“Repair”功能或者手动安装对应版本的Java SE Runtime Environment。2.2 新建工程与外部接口规划打开Vivado 2019.1创建一个新的RTL工程。我习惯在工程名上标注日期和版本比如eth_test_2019方便以后多个版本对比。器件型号最好和实际板卡一致不要随便选一个相近型号凑合因为管脚约束文件和IP核的可用资源会因器件不同而变化。工程建好后第一步要明确以太网接口在板子上的物理连接情况。FPGA和PHY芯片之间采用什么接口决定了IP核配置和约束方式MII接口4位数据25MHz时钟100Mbps。RMII接口2位数据50MHz时钟100Mbps这种接口常出现在低成本的MCUPHY方案里。GMII接口8位数据125MHz时钟1000Mbps。RGMII接口4位数据125MHz时钟DDR双沿采样1000Mbps目前最常见引脚少布线方便。我这次用的是RGMII接口搭配一颗常见的千兆PHY芯片。规划管脚时特别要注意RGMII的发送时钟和接收时钟不是同一个时钟源发送时钟由FPGA内部产生接收时钟则是从PHY芯片恢复出来的要分别约束。另外PHY芯片的复位引脚、管理接口MDIO/MDC、以及链路状态LED指示引脚都要在工程建立阶段就预留出来。尤其是MDIO接口调试时读取PHY芯片寄存器非常有用比如查询协商速率、检查链路状态、强制指定工作模式。2.3 MDIO管理接口的必要性如果不接MDIO接口PHY会以默认模式工作这在环回测试时问题不大但你无法得知链路的实际协商结果也无法确定PHY是否进入了千兆模式。RGMII接口相当特殊如果速率不匹配比如FPGA侧工作在1G而PHY协商到100M引脚上的数据解析就全乱了。我在设计里总是把MDIO接口单独拎出来接到一个简单的状态机模块至少得能支持读取PHY寄存器0控制寄存器和寄存器1状态寄存器。通过这两个寄存器可以明确看到PHY是否完成了自动协商以及协商速率是1000M还是100M。很多时候FPGA侧代码看着没问题但网络就是不通最后定位到的原因就是PHY协商到了100M而FPGA这边还在期盼1G时序。3. 核心IP配置与细节解析3.1 Tri-Mode Ethernet MAC IP的配置路径在Vivado 2019.1的IP Catalog里搜索“Tri Mode Ethernet MAC”选到Xilinx官方IP后双击即可打开配置界面。第一个需要确定的是MAC的接口模式。在配置界面里可以选择Gigabit or 10/100 Mbps模式8位或16位客户侧数据总线。对于1G速度我倾向于选择8位接口125MHz时钟这样时钟频率和RGMII的125MHz时钟同频数据信号跨时钟域的逻辑会简单一些。16位接口需要GMII接口跑在125MHz但数据侧跑在62.5MHz对于纯逻辑设计意义不大徒增跨时钟域复杂度。第二个配置项是物理接口类型。这里选择RGMII v2.0或者RGMII v1.3具体取决于PHY芯片的支持版本。RGMII v1.3和v2.0的时序差异在于时钟相对数据的位置如果PHY芯片手册明确指出兼容RGMII v2.0那就选v2.0否则选v1.3更通用。实际收发信号时还需要在引脚上做延迟约束这个后面在时序小节详细说。第三个配置项是管理接口。建议勾选“Enable Management Interface”也就是MDIO接口。这个接口连接PHY芯片的MDIO/MDC引脚用于读写PHY寄存器。调试阶段作用非常大不要省。还有个容易被忽略的选项Shared Logic。Tri-Mode Ethernet MAC IP可以把收发时钟生成逻辑放在IP内部也可以外部共享。如果只有一个以太网口选“Include Shared Logic in core”就行如果有多个MAC建议把共享逻辑放在外部时钟管理资源可以共用。共享逻辑通常包含IDELAYCTRL、MMCM混合模式时钟管理器这些原语外部共享可以节省大量时钟资源。3.2 RGMII引脚与时钟关系RGMII接口在FPGA引脚上有三组时钟数据GTX_CLK125MHz发送时钟由FPGA提供给PHY芯片所有发送数据以该时钟为基准。TXD[x:0]、TX_CTL发送数据和控制信号与GTX_CLK同步。RXC接收时钟由PHY芯片从线路上恢复出来频率由当前速率决定千兆时125MHz百兆时25MHz。RXD[x:0]、RX_CTL接收数据和控制信号与RXC同步。RGMII的核心特点是DDR双沿采样4根数据线在RXC/GTX_CLK的上升沿和下降沿分别传输低字节和高字节控制信号也在双沿传输有效位和错误位。因此在代码里必须处理IDDR逻辑把双沿数据转换为单沿的8位数据再送到MAC核内部去处理。Xilinx Tri-Mode Ethernet MAC IP在设计上已经处理了RGMII转GMII的逻辑。如果配置物理接口为RGMII那么IP会自动例化IDDR/ODDR逻辑你不需要在外层额外编写双沿转换代码。但需要注意收发时钟的相位关系发送时钟GTX_CLK必须与数据的关系满足Tskew要求接收时钟RXC进入FPGA后通常需要IDELAY来补偿PCB走线的时钟数据偏斜。3.3 时钟复位模块和异步复位同步释放以太网MAC核需要多个时钟域比如客户侧接口时钟125MHz或62.5MHz、RGMII收发时钟125MHz或25MHz、MDIO管理时钟2.5MHz或12.5MHz。每次新建IPVivado都会生成对应的时钟复位模块但如果你在多个模块里各自例化时钟原语容易造成时钟树混乱。我的经验是使用一个顶层时钟模块ClkGen统一管理所有以太网相关时钟。用MMCM产生125MHz和同步复位信号用BUFG全局缓冲后分发到MAC的RX、TX和客户侧逻辑。复位信号务必做异步复位同步释放处理FPGA上电或PHY复位时各路复位释放时间不一致如果直接使用异步复位状态机会进入不确定状态。分享一个我常用的同步复位代码片段// 同步复位释放避免复位释放时间不一致导致亚稳态 reg [3:0] reset_sync; always (posedge clk_125m or negedge reset_n) begin if (!reset_n) begin reset_sync 4b0; end else begin reset_sync {reset_sync[2:0], 1b1}; end end assign reset_125m_n reset_sync[3];类似的同步逻辑要分别做在125MHz时钟域和2.5MHz MDIO时钟域里。别嫌代码啰嗦多几级同步器换来的是调试时少掉几根头发。3.4 核对IP生成后的端口列表配置完成后点击Generate输出IP。生成的IP文件会包含一个例化模板最好仔细读一遍端口列表尤其是gtx_clkRGMII发送时钟输入125MHz。refclk125MHz参考时钟通常和gtx_clk同源。s_axi接口管理配置接口可以在里面配置MAC地址、帧过滤等。rx_axis和tx_axis接口这是AXI4-Stream接口如果配置了AXI接口的话数据从这里进出。我用的是Tri-Mode Ethernet MAC的原始接口不是AXI Ethernet所以客户侧接口是gmii_rxd、gmii_rx_dv、gmii_txd、gmii_tx_en这些信号。两者区别在于AXI Ethernet带DMA可以直接往内存里塞数据而Tri-Mode Ethernet MAC需要自己写FIFO和状态机来处理收发。如果配置时选择了AXI接口需要注意AXI数据总线和MAC核心时钟域的跨时钟域问题。IP内部已经做好了异步FIFO不需要额外处理但这个FIFO的深度是可以在配置界面里选的优先级丢包率高的场景选深一些。4. 逻辑设计实操4.1 发送通路从FIFO到MAC发送方向用户逻辑要往MAC核的发送端口写入以太网帧。Tri-Mode Ethernet MAC的发送接口时序比较简单拉高tx_axis_tvalid表示有数据要发送。每个时钟周期tx_axis_tdata上出现8位数据tx_axis_tlast表示最后一个字节tx_axis_tuser表示错误标志。在回环测试阶段我直接构造了一个简单的以太网帧目标MAC地址广播地址或指定地址、源MAC地址、以太网类型字段0x0800表示IPv4后面填充一层UDP报文。数据包长度是64字节这是以太网最短帧长低于这个长度MAC核会填充到64字节。发送状态机不需要太复杂用计数器控制发送一个固定帧即可// 发送帧状态机简化版 localparam IDLE 3d0; localparam PREAMBLE 3d1; localparam DATA 3d2; localparam FCS 3d3; // 关键是拉高tvalid后数据要连续到达tready拉低时暂停需要注意MAC核内部会自动生成前导码和帧校验序列FCS不需要用户自己添加CRC校验。用户侧提供的数据从目标MAC地址开始到数据负载最后一位结束即可。4.2 接收通路有些人会忽略的帧校验状态接收方向相对简单MAC核会把前导码剥掉输出完整的以太网帧给用户。需要注意两个控制信号rx_axis_tvalid数据有效。rx_axis_tlast帧结束。rx_axis_tuser接收错误标志通常表示FCS校验失败、长度错误、或者RGMII接收通路上的数据错误。调试阶段我一般把接收到的整帧数据存进BRAM里再用UART或者ILA把数据导出来分析。如果rx_axis_tuser拉高以太网帧会被标记为错误帧如果用户逻辑不做处理直接丢弃就行。第一次调试时还容易忽略一个点接收通路的MAC支持广播帧和多播帧过滤如果不配置接收帧过滤所有接收到的帧都会送到用户逻辑。有时候测试环境里网络上有大量无关的广播报文比如ARP请求它们会出现在接收数据里容易让刚开始调试的人误以为是自己的数据。我习惯配置MAC地址过滤来忽略非目标帧这样调试更清晰。4.3 内部回环配置Tri-Mode Ethernet MAC IP配置界面里有一项“Internal Loopback”选项勾选后MAC会把发送的数据直接内部回环到接收通路完全不经过物理引脚。这个功能在逻辑调试阶段非常有用因为它隔离了FPGA外部电路的影响如果回环数据正确说明MAC核配置和用户逻辑是正确的如果回环数据都错就要检查时钟复位和配置接口。IP配置里的内部回环需要的是配置MAC控制寄存器。如果你在IP配置界面里勾选了“Enable Internal Loopback”会发现在生成的顶层模块里多了一个配置端口用于控制回环模式。要注意的是回环模式会产生一个假的接收时钟频率和发送时钟一致但不会经过PHY芯片此时rx_axis的时序所有信号都会以gtx_clk为参考时钟。调试时我会设计一个切换开关让板子可以一键切换到内部回环或外部回环模式。这样上板后先确认内部通路再切换到外环分步定位问题非常高效。4.4 引入ILA观察收发明细ILA集成逻辑分析仪是调试FPGA逻辑最常用的工具。Vivado 2019.1的ILA IP核可以插入任意内部信号设置触发条件后把采样数据实时上传到Vivado的波形窗口查看。以太网调试时我建议至少采样以下信号gtx_clk和rx_clk确认时钟频率和相位关系。gmii_txd、gmii_tx_en、gmii_tx_er发送数据。gmii_rxd、gmii_rx_dv、gmii_rx_er接收数据。用户侧的状态机状态信号看状态跳转是否正常。rx_axis_tuser一旦拉高立刻捕获错误帧信息。ILA的采样深度一般设1024或4096采样时钟用125MHz。如果采样深度太小抓不到完整的以太网帧64字节最短帧都要512个采样点1518字节的巨型帧需要12000多个采样点。最好先抓短帧调试确认无误后再抓长帧。关于“ILA采样频率是不是有范围限制”这个常见问题ILA的采样时钟必须比被测信号快至少要大于被测信号最高频率的两倍否则违反奈奎斯特采样定理。125MHz的以太网信号用125MHz ILA采样是临界状态想看清楚数据边沿建议用250MHz以上时钟采样。如果板子上没有250MHz时钟可以先用MMCM倍频产生。5. 综合、实现与板级调试5.1 管脚约束文件编写要点管脚约束是板级调试能否成功的前提。RGMII接口管脚约束文件里除了基本的管脚位置约束PACKAGE_PIN还需要IO标准约束。对于RGMII大部分PHY芯片使用LVCMOS或LVTTL电平但需要注意的是电平标准要完全匹配PHY芯片的VDDIO电压。常见的是3.3V或1.8V接口如果约束写错信号波形会被拉垮传输根本不可能稳定。RGMII还有个经验值需要给数据引脚添加输入延迟约束。如果用的是RGMII v1.3标准数据相对于时钟是中心对齐的如果是RGMII v2.0发送数据由内部延迟调整接收数据需要在引脚上做延迟。Vivado里可以用set_input_delay/set_output_delay约束来指定延迟值具体数值取决于PCB走线长度和PHY芯片的Tskew参数。我曾经在一个项目里忽略了set_input_delay约束结果链路偶发性丢包抓了三天波形才定位到问题。这些约束看起来繁琐但直接影响可靠性一定要对照原理图和PHY手册的时序参数来写。RGMII管脚约束示例set_property -dict { PACKAGE_PIN H14 IOSTANDARD LVCMOS33 } [get_ports GTX_CLK] set_property -dict { PACKAGE_PIN H15 IOSTANDARD LVCMOS33 } [get_ports {TXD[0]}] set_property -dict { PACKAGE_PIN J16 IOSTANDARD LVCMOS33 } [get_ports {TXD[1]}] set_property -dict { PACKAGE_PIN J15 IOSTANDARD LVCMOS33 } [get_ports {TXD[2]}] set_property -dict { PACKAGE_PIN K14 IOSTANDARD LVCMOS33 } [get_ports {TXD[3]}] set_property -dict { PACKAGE_PIN K15 IOSTANDARD LVCMOS33 } [get_ports TX_CTL] set_property -dict { PACKAGE_PIN L17 IOSTANDARD LVCMOS33 } [get_ports {RXD[0]}] set_property -dict { PACKAGE_PIN M16 IOSTANDARD LVCMOS33 } [get_ports {RXD[1]}] set_property -dict { PACKAGE_PIN M15 IOSTANDARD LVCMOS33 } [get_ports {RXD[2]}] set_property -dict { PACKAGE_PIN N17 IOSTANDARD LVCMOS33 } [get_ports {RXD[3]}] set_property -dict { PACKAGE_PIN N16 IOSTANDARD LVCMOS33 } [get_ports RX_CTL]每个板卡的引脚位置都不同一定要对照原理图填写。我在这一步骤上花的时间最多因为检查管脚约束错误需要反复看原理图和PCB走线一不留神就会写错方向。5.2 时序约束与set_input_delay/set_output_delay以太网接口有明确的时序要求尤其是源同步接口。RGMII的接收时钟和数据都由PHY芯片产生是典型的源同步接口需要在约束文件里告诉Vivado时钟和数据之间的相位关系否则工具无法正确满足时序。Vivado里处理RGMII接收时序有两种常见方法一种是使用set_input_delay基于RXC时钟定义接收数据的到达时间。RGMII规格里要求数据在时钟中心对齐也就是数据在接收时钟的上升沿前后各一个setup/hold时间有效。实际写约束时需要配合set_clock_groups等命令隔离异步时钟域然后对每个接收引脚定义input_delay。另一种是使用IDELAY原语调整延迟值。在IP核配置界面里选择“Reference Clock”和“IDELAYCTRL”通过MDIO接口在运行时动态调整延迟值这种方法应对不同PCB走线长度特别有效。Vivado 2019.1的Tri-Mode Ethernet MAC IP也支持在配置界面里选择“Use IDELAYCTRL”来自动管理接收延迟。举个例子如果PHY芯片的Tskew为1.5nsPCB走线差异导致数据比时钟慢0.5ns那么实际输入延迟约为2ns。在125MHz下一个时钟周期是8ns2ns的延迟相当于四分之一周期左右。这时需要在约束中设定set_input_delay -clock [get_clocks RXC_CLK] -max 2.0 [get_ports {RXD[*]}] set_input_delay -clock [get_clocks RXC_CLK] -min 1.0 [get_ports {RXD[*]}]关于“Vivado里clk没有引脚可选”的问题实际上是因为没有在XDC中创建对应的端口时钟约束。只要在约束文件里额外定义create_clock管脚上就会自动出现这个时钟信号可以在物理约束窗口里选择了。这个知识点对做RGMII接口很重要因为RGMII的接收时钟和发送时钟是独立的两组时钟都要逐一约束清楚。5.3 生成比特流失败与解决方案“生成比特流失败”是最常见的Vivado报错之一很多初学者在这里就放弃了。我遇到的失败原因大概能分成几类第一类是布局布线失败报错信息里会提示High Fanout或者Hold Time Violation。这类问题在以太网设计中尤其容易出现在跨时钟域信号上。检查代码确保跨时钟域的同步器每个至少有两级FF检查管脚约束确保RGMII的时钟引脚分配到了时钟专用引脚上。第二类是LUT和FF资源不足报错在MAP阶段。这类问题只能通过降低IP核的资源占用、优化用户逻辑面积或换更大规模的芯片来解决。不过以太网MAC核本身占的资源不多出现资源不足通常意味着用户逻辑写得太浪费了。第三类是Bitstream Generation失败报错信息类似“ERROR: [DRC RTSTAT]”。这种往往是管脚约束冲突比如同一个管脚被约束成两个信号或者输入输出方向设置错误。看DRC报告根据报错信息逐一排查管脚分配即可。还有一类比较隐蔽的路径是IP核配置时选的物理接口类型和实际引脚电平不匹配。比如IP内部配置成RGMII但引脚标准选了LVDS后端的IO buffer都会怪怪的。检查IP配置界面里物理接口类型和XDC里引脚标准的匹配关系。5.4 上板实测电脑连不上板子的排查顺序把所有配置和约束都做完生成比特流下载到板子后开始真正的板级调试。我用一根网线把板子接到电脑上电脑的IP设置成静态地址192.168.1.10FPGA的内部逻辑准备响应ARP请求。第一步查看PHY芯片的Link状态寄存器。如果PHY没有产生Link Up信号说明物理链路不通可能原因有网络变压器或RJ45座虚焊用万用表都能量出来。PHY芯片复位引脚拉得太长时间低电平导致PHY一直处于复位状态。PHY芯片的时钟晶体没有起振用示波器量一下PHY的时钟引脚。第二步确认MDIO接口能够正常读写PHY寄存器。MDIO接口是慢速管理接口如果一直读不到有效数据优先检查MDC时钟的频率必须小于2.5MHz检查MDIO引脚的上下拉电阻有些PHY芯片的MDIO引脚需要外部上拉。第三步在FPGA内部做一个计数器每收到一个合法帧就加1用ILA查看接收计数。如果计数器不动检查接收通路上的rx_axis_tvalid和rx_axis_tlast时序用ILA抓波形确认PHY芯片输出的RX_DV信号是否拉高RXC时钟是否存在。这里马上要踩的坑是RGMII接收时钟是PHY提供的如果PHY没有正确协商出千兆模式RXC的频率不是125MHz而是2.5MHz接收数据就会以极慢的速率出现看起来像没有数据。我的经验是物理层问题占整个以太网调试过程中的一大半。FPGA逻辑部分只要综合实现没有时序问题基本一次就能跑通真正花时间的是和PHY芯片联调的部分。6. 常见问题与排查技巧实录6.1 一张问题速查表我把实际调试中遇到过的典型问题整理成一张表遇到类似问题可以对照排查问题现象可能原因排查方法IP核配置界面打不开Vivado 2019.1的Java运行环境异常重装Java或修复Vivado安装中文注释乱码Vivado编辑器默认编码不支持中文修改Vivado的编码配置将注释改为UTF-8或ASCII仿真闪退Modelsim版本和Vivado 2019.1不兼容换用Vivado自带的XSim仿真器ILA采样数据全是X状态ILA采样时钟设置错误确认采样时钟频率大于被测信号频率RGMII不工作PRBS错误RGMII时序相位关系错误检查RGMII v1.3/v2.0配置调整IDELAY生成比特流失败DRC管脚约束冲突或未约束查看DRC报告逐一修复约束PHY寄存器读取返回0xFFMDIO时序错误用示波器抓MDIO波形确认intrusive read时序ARP请求无响应MAC地址过滤配置错误暂时关闭MAC地址过滤用抓包软件确认ARP请求是否到达MAC核6.2 关于Vivado安装驱动无法识别板子的问题有搜索词提到“vivado安装驱动无法识别板子”这个是JTAG调试场景下特别常见的问题。Xilinx下载器比如Platform Cable USB II或者板载JTAG电路在Windows系统上经常会出现驱动安装失败或者被其它程序占用的情况。解决办法打开设备管理器找到带黄色感叹号的设备更新驱动并手动指向Vivado安装目录下的驱动文件夹。如果是用的是Digilent的板卡需要单独安装Digilent的驱动插件。在Vivado 2019.1里驱动路径通常是Vivado安装路径\data\xicom\cable_drivers\nt64\dlc10_win7\目录。还有个偏门原因电脑上安装了某些虚拟串口或者保护程序会占用JTAG相关的USB设备导致Vivado总是识别不了板子。这个时候可以换个USB接口或者在任务管理器里关闭冲突进程。6.3 关于“vivado时钟800M怎么设置”的延展有搜索词提到“vivado时钟800m怎么设置800m视频教程”这个和以太网关系也大因为MMCM混合模式时钟管理器最大输出频率是有上限的。在7系列Artix-7上MMCM的最大输出频率取决于速度等级和输出资源800MHz这个频率明显已经超出了大多数7系列器件的MMCM输出上限整个时钟树需要仔细设计。以太网功能中用不到800MHz这么高的频率125MHz就够用了。但如果你确实需要在FPGA里产生高频时钟比如用于SerDes或高速ADC采样那就要走GTX Transceiver的参考时钟通道而不是用普通的MMCM。GTX参考时钟可以通过外部晶振或内部PLL生成但需要单独约束和初始化。另外MMCM的输出时钟抖动和电源噪声有关。做高速接口时模拟电源脚要单独滤波数字供电和模拟供电不要混接否则采样时钟抖动会直接影响接口误码率。6.4 补充Vivado 2019.1的License问题处理有搜索词提到“vivado注册 2035”和“license manager打不开”。Vivado 2019.1用的License机制是FlexNet在Windows上偶尔会出现License Manager服务和Vivado主程序不兼容的情况特别是电脑上装了多个版本的Vivado时License环境变量互相覆盖导致找不到许可。解决方法检查环境变量XILINXD_LICENSE_FILE和LM_LICENSE_FILE确保指向有效的License文件或服务器地址。如果License Manager打不开可以先在命令行运行lmutil lmdiag查看License诊断信息确认License没有过期、MAC地址和主机名匹配。WebPACK License绑定的是网卡MAC地址如果你的电脑换了网卡或者启用了虚拟网卡有可能导致License失效。遇到这种情况可以用lmutil lmhostid查看当前机器的主机ID对比License文件里是否一致。7. 从MAC到协议踩过的坑与理解7.1 真的有必要了解IP协议栈吗很多人觉得FPGA开发不需要懂TCP/IP协议栈只要调通MAC层的收发就行。这个观点对了一半。如果你的产品最后要接入互联网比如做数据采集卡、工业网关、视觉控制器那你必须要理解至少ARP、ICMP、UDP、IP这几个协议的工作流程。因为FPGA侧的协议栈通常很精简不跑完整的操作系统你需要自己决定哪些报文要处理哪些要丢弃。我在做以太网接口时最常被问到的一个问题是FPGA能不能直接ping通答案是如果实现了ARP响应和ICMP Echo响应就能ping通。这在调试时非常有用因为它只需要一个简单的状态机。7.2 ARP响应状态机的编写思路ARP地址解析协议用于把IP地址解析成MAC地址。当电脑要向FPGA发送数据时会先广播一个ARP请求问“谁是192.168.1.20请告诉我你的MAC地址”。FPGA收到ARP请求后如果目标IP是自己就回一个ARP应答把自己的MAC地址告诉电脑。这样电脑就知道该往哪个MAC地址发数据了。编写ARP响应的状态机本质上就是识别接收帧的以太网类型字段是否为0x0806如果目标IP等于本地IP则交换源目MAC地址和IP地址把应答帧发出去。这个状态机在逻辑上非常清晰但要注意校验网络序问题IP地址和MAC地址在以太网帧中都是大端序传输从帧里提取的字节顺序要和本地的IP配置一致。我来举个具体流程接收帧到达MAC核用户逻辑解析以太网类型字段。如果是0x0806继续判断ARP头部的操作码1表示请求2表示应答。提取发送端IP地址和MAC地址判断目标IP是否等于本地配置的IP。如果匹配则构造ARP应答帧以太网目标MAC等于请求帧的发送端MAC源MAC等于本地MACARP操作码置为2目标IP等于请求帧的发送端IP目标MAC等于请求帧的发送端MAC。把应答帧发送出去。这里用一个配置寄存器来存本地IP地址和MAC地址可以从MDIO接口写入也可以用Vivado的调试探针VIO在线修改非常方便测试不同IP场景。7.3 UDP数据收发与校验和实现UDP收发是很多数据采集应用的需求。UDP头很简洁源端口、目的端口、长度、校验和。校验和的计算覆盖伪首部源IP、目的IP、协议号、UDP长度、UDP头和UDP数据。FPGA侧如果用纯逻辑计算校验和可以选择不计算而写0但在跨网段传输时某些交换机或路由器会丢弃校验和为0的UDP报文所以稳妥做法还是把校验和算出来。我的经验是在纯逻辑里快速计算UDP校验和可以采用累加和减的方法把所有16位字相加如果发生进位则回卷再加最后按位取反。这个过程可以用组合逻辑或流水线实现。数据量不大的场景直接用LUT实现累加器就够了大流量场景再用多个加法器并行加速。只是做本机回环测试时UDP校验和都可以不填因为测试环境没有路由器不会去检查校验和。但如果你要把FPGA接入公司网络或公网最好严格实现否则到现场调试会遇到网络不稳定的怪问题。7.4 MAC地址、VLAN和帧过滤以太网帧结构从链路层看标准帧是前导码7字节SFD1字节目标MAC6字节源MAC6字节长度/类型2字节数据46到1500字节FCS4字节。VLAN标签存在时帧头会多出4字节类型字段变为0x8100实际的位置在标签内部。很多以太网常见问题最后都能追溯到MAC地址过滤、VLAN标签处理上。比如网络里存在大量带VLAN Tag的帧如果你不做VLAN剥离用户逻辑解析时会发现源MAC地址错位数据全乱。所以如果你在公司或学校网络里调试建议先用一台普通交换机隔离或者直接在PC端设置静态IP避免无关的VLAN流量干扰。Tri-Mode Ethernet MAC IP里可以配置接收帧的VLAN处理方式可以选择穿透pass-through或剥离strip。如果只是本地回环测试选择穿透模式不处理VLAN标签调试更简单。8. 基于SDK的裸机驱动方案扩展8.1 MicroBlaze与AXI Ethernet的联动当逻辑验证完毕数据通路稳定之后很多项目会希望把FPGA接入一个处理器系统用软件来处理协议栈。这时就需要升级方案从Tri-Mode Ethernet MAC升级为AXI Ethernet IP并加上MicroBlaze软核。在Vivado 2019.1的Block Design里添加MicroBlaze然后加入AXI Ethernet IP。AXI Ethernet IP内部整合了MAC和DMA还有收发描述符环形缓冲区CPU可以通过AXI-Lite接口配置MAC通过AXI4接口访问数据缓冲区。Vivado在生成Block Design时会自动连接中断控制器MicroBlaze通过中断知道数据到达然后从DMA缓冲区里取数处理。这种方案最大的优势是协议栈可以用现成的lwIP开源库在SDK里跑起来开发效率比纯逻辑实现高一个数量级。如果你只是在做产品验证这种模式最务实。缺点是资源占用比纯逻辑方案高很多尤其是AXI DMA和中断控制器会吃掉不少LUT和BRAM。8.2 SDK中的BSP配置和lwIP移植在Vivado 2019.1中SDK和Vivado安装在一起。生成硬件平台后在SDK里新建应用工程时可以选择“lwIP Echo Server”模板它会自动生成一个基于lwIP协议栈的TCP服务器示例。修改一下MAC地址和IP地址编译下载就可以通过网线直接连电脑测试了。lwIP的移植过程中最常遇到的问题是内存分配不足。lwIP默认用内存池管理如果TCP数据包处理不过来缓冲池会被耗尽表现为网络吞吐量突然下降或者连接不稳定。在lwipopts.h里调大MEM_SIZE和PBUF_POOL_SIZE同时确保MicroBlaze的本地存储器Local Memory Bus足够大至少128KB否则系统根本跑不起来。使用Zynq平台时硬件集成还有一套完整流程PS端的MIO或EMIO引脚连接内部MAC控制器SDK里直接例化gmac驱动。Zynq的GEM硬核天然支持千兆以太网配合DMA和中断性能非常强劲是真正的量产级方案。纯FPGA平台的MicroBlaze方案适合原型验证量产建议优先考虑带硬核MAC的SoC系列。8.3 调试工具链配合使用心得从上板调试到协议栈跑通我常用的工具组合是Vivado ILA抓FPGA内部信号的时域波形。Wireshark抓网线上的网络包分析帧格式和协议流程。Nmap快速扫描FPGA端口测试TCP连接是否正常。简单Python脚本构造自定义UDP/TCP包发给FPGA验证协议处理。在电脑端抓包时建议用USB转RJ45的独立网卡来抓包或者直接在电脑上启用抓包驱动的虚拟接口。这样FPGA发出的所有数据帧都能被看到方便对照分析。很多网络问题FPGA侧逻辑自以为做对了实际上帧在PHY芯片就出错了一抓包就能看出来。9. 关于Vivado使用体验的个人补充用了这么长时间Vivado 2019.1有几条心得体会值得说一说。工程管理方面整个工程文件夹里最核心的就是.srcs源码、.xpr工程文件和.xdc约束文件。如果你用Git管理代码建议只提交这些文本类文件不要提交整个工程目录因为生成的中间文件动辄几个GB每次拉分支都很痛苦。.srcs目录下的IP源码也不要手动修改IP核重新生成时会覆盖正确的修改方式是在IP配置界面里调整后再Generate。代码风格方面以太网逻辑设计建议遵循“一个时钟域一个模块”的原则。125MHz发送数据、RGMII的IDDR逻辑、MDIO管理时钟这三者尽量分开放在不同模块里时钟域交叉的地方只允许同步器出现。这样无论是仿真还是上板调试逻辑都一目了然也不容易引起时序违规。关于“vivado sdk是什么”这类不时有人问的问题它全称是Xilinx Software Development Kit历史版本里常和Vivado一起安装用于软件开发。2020以后的版本被Vitis取代了但2019.1里的SDK功能已经非常成熟做MicroBlaze和Zynq的裸机开发完全够用。很多人在安装Vivado后还会问“为什么我的Vivado总是卡死”。2019.1对内存的占用比较大建议至少16GB内存SSD硬盘留出至少100GB空间。设计工程很大时综合跑几个小时都正常这时候可以开启多个任务并行或者合理设置综合的策略为Flow_RuntimeOptimized加快综合速度。最后说一个和以太网关系不大的小技巧Vivado 2019.1的多线程编译功能默认是打开的但在某些Windows版本上可能不生效。可以在工程设置里找到“Number of jobs”调整线程数4核8线程的机器设置成6到8能明显缩短综合和实现时间。曾经有一个设计综合需要40多分钟调整后降到25分钟左右节省的时间相当可观。以太网接口的调试本质上是个系统联调的过程从FPGA逻辑到PHY芯片再到上位机网络协议每一层都有自己的“坑”。把这些坑一个个趟平你不仅能把网口调通还会对整个网络数据流有更深的理解。后面做视频传输、数据采集、工业控制都会有直接帮助。