资讯动态

开源FPGA 100G UDP协议栈移植实战:从Verilog Ethernet到QSFP-DD上板

发布时间:2026/9/5 8:36:38 来源:尧图企业网站定制
事情要从一块带QSFP-DD接口的FPGA板卡说起。项目要用100G以太网口做高吞吐数据采集传输逻辑上要把采集到的数据包成UDP报文从光纤发到上位机。选型的时候被商业IP核的授权费吓了一跳一台License大几万美金起步而且不同FPGA厂商的IP核还不通用——今天用Altera明天换了Xilinx这笔钱就得再花一遍。于是我们把目光投向了开源方案Verilog Ethernet项目一套完全开源的10G/25G/40G/100G以太网MAC和PHY实现从RTL到仿真环境全部公开用起来不用看任何人脸色。项目最终在XCKU060上完成了移植和上板跑通了100G UDP收发链路Wireshark抓包和iperf3重负载测试都过了。这篇文章会把这套方案的完整实践过程写清楚包括为什么选这个开源代码、100G UDP的协议栈到底是怎么一层层搭起来的、上板测试前要做哪些准备、以及实测中踩过的那些坑。适合正在评估100G以太网方案、需要自研UDP协议栈、或者对开源FPGA网络实现感兴趣的工程师参考。1. 为什么选开源方案100G UDP的技术断档和成本账先把这个问题的背景交代清楚。100G以太网的速度是10G的十倍但复杂度远远不止十倍。10G以太网用XGMII接口一个时钟沿传8字节逻辑设计相对友好100G以太网用的是XLGMII接口一个时钟沿要传64字节意味着核心逻辑必须工作在322MHz左右的时钟域整个数据通路从位宽到时序都是另一个量级。对于FPGA工程师来说最大的挑战在于100G所需的PCS/PMA层和MAC层逻辑几乎不可能从零开始写。PCS层要做64B/66B编码、加扰、FEC前向纠错等功能MII接口的位宽和时钟关系也完全不同于10G/40G。这些模块的时序收敛难度极高没有足够的经验很容易在布线阶段卡死。市面上的商业方案主要有几种Xilinx的100G Ethernet SubsystemAltera的100G Ethernet IP还有一些半导体公司提供的独立IP核比如Synopsys、Cadence的产品。这些方案在功能和性能上都没有问题关键是贵而且绑定厂商。举个例子Xilinx的100G Ethernet IP需要UltraScale系列的部分型号才支持如果你用的是Kintex UltraScale可能连IP都用不了只能想办法自己做PCS。开源方案的代名词就是Alex Forencich维护的Verilog Ethernet项目。这个项目覆盖了从1G到100G的以太网MAC、PCS/PMA、ARP、UDP、TCP等几乎所有常见网络功能。其中最让我看重的是它严格遵循IEEE 802.3标准代码结构清晰注释到位而且支持在多个FPGA平台上跑。你在GitHub上看到的是一套活跃维护了十多年的代码社区用户群非常大遇到问题基本都能找到解决方案。成本账其实很好算。100G商业IP核授权费一般在3到8万美元之间而自己花一个月时间移植一个开源方案人力成本取决于工程师水平一般在一到三万元人民币之间。考虑到后续算法调试、二次开发的需求开源方案还能让你完全掌控每一个逻辑门的实现细节不用像用商业IP时那样只能看黑盒。对于创业团队和研究所来说开源方案的意义不只是省钱更是把网络协议栈的主动权握在自己手里。2. 100G UDP协议栈核心原理拆解从物理层到应用层理解开源代码之前得先把100G UDP这条链路每一层在FPGA里是怎么实现的搞清楚。很多人在移植的时候遇到困难深层次原因就是对链路层的衔接关系不清晰代码写着写着就断档了。2.1 物理层QSFP-DD光模块和PCS/PMA的关系100G的物理接口最常用的是QSFP-DD或OSFP光模块。这类光模块内部集成了光收发组件外部通过电接口和FPGA相连。电接口这一侧走的是标准的IEEE 802.3bj协议也就是100G以太网的电气规范。FPGA内部实现物理层功能的核心是PCS/PMA模块。PCSPhysical Coding Sublayer做的是64B/66B编码、加扰、块同步等操作PMAPhysical Medium Attachment负责串行化和解串行化把并行的数据转换成高速串行信号。在FPGA里PMA功能通常由高速收发器实现比如Xilinx的GTH/GTYAltera的Transceiver Native PHY。对于100G以太网PCS层的数据位宽是64字节512比特工作频率是322.265625MHz。64B/66B编码会把每64比特数据编码成66比特的码块其中前2比特是同步头用来识别是数据块还是控制块。这个2比特开销加上扰码器的复杂度决定了PCS层逻辑从资源占用和时序收敛角度都不可小觑。开源项目里PCS/PMA部分可以直接例化厂商原语。Xilinx平台下100G Ethernet Subsystem的PCS其实就是基于GTY收发器实现的。如果你想完全从RTL层面控制PCS那工作量会非常大一般不建议这么做。合理的折中方案是厂商的收发器IP做物理层开源代码做MAC层和上层协议。2.2 MAC层100G MAC核心逻辑的位宽与时钟MACMedia Access Control层实现的是以太网帧的封装和解析。FPGA内部以太网MAC接收来自PCS层的64字节位宽数据流然后做CRC校验、帧定界、地址过滤等操作。发送方向上MAC接收上层协议传来的数据加上前导码、帧起始定界符SFD、目的地址、源地址、长度/类型字段最后追加FCS校验。从数据流角度看100G MAC最核心的设计挑战在于FIFO的深度和背压机制。因为上层协议比如UDP的数据产生速率和物理层的发送速率不可能完全匹配MAC必须能消化上游的突发数据。开源项目使用独立的时钟域FIFO来处理跨时钟域问题写入侧时钟由用户逻辑产生读侧时钟锁定在PCS的输出时钟上。MAC层的另一个关键是流控。IEEE 802.3标准定义了几种流控方式pause帧流控、PFC优先级流控等。100G场景下因为速率太高pause帧的传播延迟就会成为瓶颈。一个标准pause帧只有64字节而64字节在100G链路上的传输时间只有5.12纳秒这意味着如果对端的FIFO快满了才发pause帧等对端收到这个帧时可能已经多发了成百上千个数据包。所以实际项目中更依赖上层协议如UDP的丢包重传机制来保证可靠性MAC层的流控只是辅助手段。2.3 UDP层校验和计算的并行化设计UDP层相对简单UDP头8字节加上数据载荷再交给IP层封装成IP报文。看起来简单但100G速率下的UDP处理有一个关键细节必须注意——校验和计算的并行化。UDP校验和计算的是伪首部伪IP头UDP头数据三部分的累加和这是一个典型的顺序依赖运算。如果每个时钟周期只处理1字节那100G速率下需要的时钟频率就是12.8GHz显然不可能。正确做法是将64字节的数据分成多个并行通道每个通道独立计算部分和最后再合并。64字节分成4个16字节通道每个通道运行在322MHz时钟下16字节的并行加法足够在单个时钟周期内完成。开源项目里专门有一个模块用于高速校验和计算它会根据输入数据位宽自动调整并行度。你不需要手动优化这部分逻辑只要把数据位宽和时钟频率配置正确它就能在上层逻辑无需感知的情况下完成校验和计算。2.4 ARP与ICMP让上位机“找到”FPGAUDP能跑通之前有一项容易被忽略的底层能力必须提前搞定——ARP协议。上位机知道要把数据发到FPGA的IP地址但以太网帧里填的实际是MAC地址。所以当上位机的ARP缓存里没有FPGA的信息时会先发送一个ARP广播请求“谁的IP是192.168.1.10告诉我你的MAC地址。”FPGA侧的ARP模块需要监听这个请求并自动回复自己的MAC地址。开源项目提供的ARP模块能维护一个小的MAC地址表默认支持8个条目它不仅能回复ARP请求还能主动缓存对端设备的MAC地址。这样FPGA向对端发UDP时不需要每次都等对端先发一个包过来目标MAC可以直接从缓存里取。ICMPping协议也值得提前实现。虽然UDP数据传输本身不需要ICMP但测试阶段ping通不通是最快的连通性检验手段。开源项目里提供了ICMP模块只要在UDP模块之前例化它FPGA就能响应ping请求排查网络配置问题的效率会高很多。3. 移植实战环境准备、代码适配和IP配置现在进入实操环节。我的开发平台是Xilinx KCU060板卡KU060芯片板上带QSFP-DD光模块接口。如果没有同样的板卡只要FPGA片内有支持100G的高速收发器移植路径是类似的重点在于把厂商IP的接口信号和开源代码的接口信号正确对接。3.1 开发环境搭建修改Makefile的正确姿势开源项目的代码用Verilog写成可以用Vivado直接作为工程源文件使用。不过项目本身附带了一套完整的仿真环境基于Icarus或者商用仿真器建议先跑一次仿真确认工具链没问题再进入综合阶段。如果从头建工程最省事的方式是直接利用项目自带的rtl目录下的所有.v文件。需要特别注意的是mac_phy_100g_driver这个模块它封装了MAC层和PCS层之间的握手逻辑。在你的工程中PCS层用Vivado的100G Ethernet IP替代或者用GTY原语实现均可。我建议先打开项目自带的Makefile仔细看一下它的编译选项。默认情况下目标文件会生成一份独立的仿真产物运行make命令即可完成编译。如果要修改仿真参数比如数据速率需要检查defines.vh文件中的宏定义。100G默认宏是ETH_100G或者MAC_100G数据位宽走的是DATA_WIDTH512这个参数。如果想把开源代码集成到非Linux环境的工程中省事的做法是直接从Vivado图形界面添加源文件并指定include目录。但要注意项目里的部分源文件之间存在路径依赖比如lfsr.v会被pcs_4lane.v引用所以添加源文件的时候不能漏掉任何一个否则综合阶段会报奇怪的错误。3.2 FPGA内部资源规划该不该用DDR怎么接PCIe100G UDP的项目基本都会涉及高速数据交互通常使用PCIe接口把FPGA连到上位机或者用DDR缓存数据。以我的项目为例数据源来自ADC采样经过简单的数字信号处理之后要经过DDR暂存再由UDP发送逻辑打包发出。这里有个重要决策数据通路是采用简单的FIFO直出还是DDR缓存。如果数据源速率不高于100G链路速率FIFO直出方案可以省掉DDR控制器的复杂度延迟也更低。但我的场景里ADC采样的突发速率远高于链路平均速率所以必须用DDR做平滑缓冲。DDR控制器我用的是Xilinx MIG IP将数据从DDR读出来之后送入UDP打包逻辑发送端在FIFO接近满时通过背压信号暂停DDR读操作。如果不需要PCIe接口那么FPGA和上位机的数据交互可以纯靠UDP完成。这种情况下重点是保证UDP包的顺序和丢包率。实测下来百G网络的瓶颈往往不在FPGA这边而在上位机的网卡和驱动侧——Linux默认的收发缓冲区较小50Gbps以上的UDP接收可能会丢包。解决方案是在上位机调大socket buffer并启用多队列RSSReceive Side Scaling尽量利用多核CPU处理收包中断。3.3 时钟和复位逻辑最容易埋坑的两个细节FPGA工程的时钟和复位设计没有小事100G场景下更是如此。时钟方面100G MAC的操作时钟可以由GTY的rxoutclk和txoutclk引出。假设使用MII接口连接PCS那么MAC的时钟频率和相位完全取决于PCS输出的参考时钟。Xilinx的100G Ethernet IP中有两个独立的时钟输出一个给TX路径一个给RX路径。在开源项目的mac模块里RX侧有自己的FIFOTX侧也有所以两侧可以用各自独立的时钟。复位逻辑的坑藏在异步复位的同步释放上。100G速率下任何一个复位信号如果出现毛刺可能导致PCS的状态机卡死。我的做法是自己写一个全局复位模块接收外部的sys_rst信号然后分别在TX时钟域和RX时钟域内做同步释放。这个模块生成的复位信号要保证高电平有效至少一个完整时钟周期否则部分寄存器的复位状态可能不稳定。还有一个容易被忽略的细节是GTY的复位顺序。Xilinx收发器的复位顺序要求先复位TX再复位RX最后释放PLL锁定。如果直接使用Vivado的Transceiver IP向导IP内部会处理好这个问题但如果直接用GTY原语半定制必须自己实现这个状态机否则上板后光模块经常会出现link训练失败的情况。3.4 模块例化和接口映射从tb到顶层文件开源项目的模块命名很规范但直接放到自己的工程里仍然需要适配。我以UDP发送链路为例看一下模块之间的接口关系- axis_eth_mac_tx把经过校验和计算后的UDP/IP数据打包成以太网帧输出到MAC层 - mii_100g_pcs_pma或者对应厂商PCSMAC层与物理层之间的MII接口适配 - eth_mac_100g100G MAC核心和PCS双向连接 - axis_arp处理ARP请求和响应 - axis_icmp处理ping - axis_udp_tx完成UDP头的填充、校验和计算从用户逻辑接收数据顶层文件中的例化顺序建议是先例化MAC和PCS确认物理链路跑通再例化ARP和ICMP确认网络层通最后例化UDP收发模块完成应用层功能。每层都先验证再往下走能大幅减少调试时间。关键的接口信号主要有以下几组用户发送接口axis_udp_txs_axis_udp_tx_tdata[511:0]512位数据s_axis_udp_tx_tkeep[63:0]字节有效位s_axis_udp_tx_tuser[47:0]目标MAC地址s_axis_udp_tx_tdest[31:0]目标IP地址s_axis_udp_tx_tid[15:0]目标UDP端口号s_axis_udp_tx_tvalid/tready握手信号用户接收接口axis_udp_rxm_axis_udp_rx_tdata[511:0]m_axis_udp_rx_tkeep[63:0]m_axis_udp_rx_tuser[47:0]源MAC地址m_axis_udp_rx_tdest[31:0]源IP地址m_axis_udp_rx_tid[15:0]源UDP端口号注意到发送接口的tuser和tdest尤其是目标MAC地址必须准确填写否则收发双方链路无论如何都通不了。ARP模块会缓存对端MAC地址但如果在发送方向硬编码了一个不存在的MAC那UDP包发出去就被交换机丢弃了。4. 上板测试从link训练到Wireshark抓包的全过程软件仿真跑通之后最紧张也最过瘾的环节就是上板。我把完整的测试步骤拆开来每一步该做什么、容易出现什么问题都列出来。4.1 硬件连接光模块、光缆和QT线缆的那些事100G光模块通常有多个电气通道。QSFP-DD光模块内部有8个独立的收发通道每通道速率约为25Gbps通过4个通道的绑定形成100G链路4x25G NRZ或者2个通道的PAM42x50G PAM4——这取决于你使用的是哪种光模块标准。最简单的接法是用一根QSFP或者QSFP28光缆直连两块板卡。如果手头没有直连光缆可以用一个100G交换机做中转但配置交换机的时候要确认端口模式是100G并确保两端光模块的FEC模式一致。FEC模式不匹配是一个非常隐蔽的坑——收发两端如果一边开了RS-FEC另一边没开会出现大量CRC错误但物理层状态却显示正常的情况。测试过程中建议准备至少两套长度的光缆一套短距离的比如1米用于验证一套2米以上的用于最终部署。光缆的弯曲半径千万注意过度弯曲会导致光功率下降严重时直接掉链路。4.2 第一步Link训练和PCS状态观察上电之后先观察PCS层的状态。如果用的是Xilinx 100G Ethernet IP通过Vivado的Hardware Manager可以读取GTY收发器的TX Alignment和RX Alignment状态。链路建立成功的标志是TX Alignment为1RX Alignment为1同时RX Link Status显示正常。如果出现RX侧一直无法对齐先检查光模块是否插紧、光路功率是否正常。很多情况下问题出在光模块的引脚定义上——QSFP-DD的LP/ModPrsL引脚如果没接好FPGA可能根本检测不到光模块的存在。使用ib_uverbs绑定GTY的调试端口可以读取光模块的module temperature和Tx power这些信息能帮助快速定位是光模块问题还是FPGA配置问题。链路训练正常的标志还可以通过GTY的眼图测量来确认。如果眼图裂开大概率是驱动电流配置不合适。在Transceiver IP中把TX swing设置为建议的典型值通常为900mVppd然后从眼图观察再微调。4.3 第二步ARP和ICMP验证PCS链路通了之后马上验证ARP和ICMP。先把上位机网卡的IP配置好比如192.168.1.100FPGA的IP设为192.168.1.10通过FPGA内部寄存器配置。然后在上位机执行ping 192.168.1.10。如果ping不通优先在FPGA逻辑里看ARP请求是否收到。你可以用ILA集成逻辑分析仪抓axis_arp模块的输入信号确认ARP请求是否成功从MAC层解析出来。有可能出现的情况是ARP模块本身没有问题但PHY层的错包太多导致MAC层丢弃了ARP请求。继续排查MAC层的接收错误计数看是不是有CRC错误或者FCS错误。ping通了之后下一步是用arp -a命令查看上位机的ARP缓存确认FPGA的MAC地址是否正确。有些板卡的MAC地址是随机生成的如果和预期不一致在FPGA代码里要重新配置一下MAC地址寄存器。4.4 第三步UDP回环测试和Wireshark抓包UDP最基础的验证方法是回环测试FPGA接收来自上位机的UDP包原样返回给上位机。这样可以同时验证收发两条链路。在上位机用Python脚本构造UDP包发给FPGAimport socket udp_send socket.socket(socket.AF_INET, socket.SOCK_DGRAM) udp_send.settimeout(2) for i in range(10): message bFPGA UDP echo test packet str(i).encode() udp_send.sendto(message, (192.168.1.10, 8080)) try: data, addr udp_send.recvfrom(2048) print(fReceived: {data} from {addr}) except socket.timeout: print(fPacket {i} timeout)同时在Wireshark里监听对应网卡过滤条件设为udp.port 8080。如果回环链路是通的Wireshark里会同时看到发送包和接收包的src/dst MAC和IP但需要注意观察UDP校验和是否正确——如果本端计算的checksum有误Wireshark会标记为[Checksum Incorrect]。一个常见的坑是上位机网卡的UDP checksum offload功能。Linux网卡默认会启用TCP/UDP checksum offload导致Wireshark抓到的包checksum可能是错误的但实际上网络传输是没问题的。遇到这种情况时用ethtool -K eth0 tx off rx off暂时关闭checksum offload再看Wireshark的报错是否消失。4.5 第四步iperf3重负载压测和丢包率统计回环测试通过以后用iperf3进行重负载测试。iperf3默认使用TCP协议指定-u参数改成UDPiperf3 -u -c 192.168.1.10 -b 10G -l 1400 -t 60 -i 1这个命令会用10Gbps的速率发UDP流包长1400字节持续60秒。观察输出中的Lost/Total Datagrams比例。在100G链路上如果丢包率超过万分之一优先检查FPGA的FIFO深度和上位机网卡的接收队列。实测下来50Gbps以上速率下丢包几乎都出在操作系统侧——网卡中断处理不过来时内核的UDP接收队列会溢出。如果想压到100G线速推荐用-b 100G但需要上位机有足够强的CPU至少8核以上并开启多队列入队ethtool -L eth0 rx 8 tx 8ugly这个丢包率数据是评估整套方案是否达标的关键指标。如果上位机侧的CPU不够强哪怕FPGA完全正常工作iperf3也会显示大量丢包——所以判断丢包原因时先确认是不是上位机瓶颈再去看FPGA逻辑。5. 上板实测中的三个隐蔽坑及定位思路这部分写点只有真实跑过才知道的教训希望能帮后来者少踩几个坑。5.1 光模块FEC模式不匹配物理层显示正常但大量错包的元凶第一次上板测试PCS链路状态正常但Wireshark里出现海量的TCP/UDP校验和错误ARP也无法通过。我以为是MAC或者UDP逻辑有bug花了整整两天排查FPGA侧代码最后才想到去看光模块的FEC配置。RS-FECReed Solomon Forward Error Correction是100G以太网标准推荐的前向纠错方式但如果对端设备没有开启FEC接收端在解FEC编码时就会把数据流解读成随机的噪声导致大量符号错误。Xilinx的100G Ethernet IP中有FEC模式的选项AutoOffRS-FEC。FPGA侧设为Auto模式能自适应对端的FEC配置但有些网卡或交换机的FEC配置与FPGA不一致时链路会出现“部分正常”的状态——物理层link up但是RX error计数不断增加。解决方案是通过IP的rx_error_count寄存器观察误码率并强制将FEC模式设为RS_FEC或Off同时保证对端设置完全一致。我在实测中碰到的就是两端FEC模式不一致导致的现象把FPGA侧设为Auto上位机网卡也开启FEC后问题就消失了。5.2 UDP校验和模块的时序瓶颈100G下复位瞬间出错开源项目的UDP校验和模块在高位宽配置下有一个时序收敛问题它内部是并行树形加法器结构如果综合工具没有把关键路径优化好在100G的322MHz时钟下容易出现建立时间违例。这种时序违例在仿真里发现不了上板后才表现为偶发性校验和错误。定位方法是用Vivado的Report Timing Summary查看axis_udp_tx_checksum相关路径的WNSWorst Negative Slack。如果出现负的slack不要急着调代码先在综合属性里对校验和模块施加dont_touch并设置更高的时序优化级别-directive Explore。如果问题依旧可考虑将校验和计算的流水级数从默认值增加1到2级多一个时钟周期的计算延迟对UDP整体吞吐的影响可以忽略。特别提醒不要忽略复位瞬间的校验和问题——如果校验和模块的复位没有和上游的数据产生逻辑同步可能在复位释放的一两个周期内计算到一个无效的中间结果导致这个周期对应的UDP包校验和错误。解决方法是给校验和模块的输出加一个额外的axis_register_slice把结果做一次寄存后再进FIFO。5.3 上位机UDP接收丢包FPGA无辜背锅的经典案例FPGA逻辑完全OK通过ILA观察FIFO从未满过但iperf3报告丢包上万。这种场景十有八九是上位机处理不过来了。一开始用iperf3测试看到丢包率高达3%一度怀疑是FPGA的TX调度问题后来用top查看CPU占用率发现软中断几乎占满了所有核心。处理方法分几步调大socket缓冲区大小sysctl -w net.core.rmem_max67108864然后在iperf3命令里加上-w 64M参数。启用网卡RSS多队列ethtool -L eth0 combined 8注意你的网卡要支持多队列。调整网卡的接收中断绑定把接收队列对应的IRQ中断平均分布到不同CPU核心上。关闭无关的CPU占用程序保证iperf3有足够的计算资源。经过这几步30Gbps速率下的丢包率降到了万分之二以下。但100G线速接收如果不是专用网络测试仪普通服务器很难做到完全不丢包。所以评测方案时要把“FPGA的发送能力”和“上位机的接收能力”分开来看用回环测试来证明FPGA的收发链路没有问题再用iperf3评估上位机的极限能力。6. 从100G UDP到100G TCP开源方案的扩展边界UDP方案跑通之后一个自然的疑问是能不能同样用开源方案实现100G TCP。答案是可以但复杂度成倍提升。TCP协议的难点在于连接管理、滑动窗口、拥塞控制、超时重传等一系列状态机的实现。开源项目里有TCP相关的代码但它的性能和资源消耗是UDP方案完全不能比的。对于100G以太网场景TCP的硬件卸载需要考虑几个问题一是每连接的内存占用非常大TCP发送和接收窗口加起来可能超过几十MBFPGA内部BRAM或URAM根本放不下必须用外部DDR二是时钟频率要求高TCP复杂状态机在322MHz下的综合收敛难度比UDP大很多三是重传和乱序处理在硬件里实现逻辑非常复杂稍不留神就会陷入死锁。所以在工业项目里100G场景更常见的做法是把TCP卸载给CPU处理——FPGA只负责UDP高性能转发上位机通过软件协议栈处理TCP控制面数据面则通过UDP或者RoCERDMA over Converged Ethernet完成。RoCE在FPGA里的实现也有很多开源方案不过它是基于InfiniBand协议的和原生以太网的UDP路径不太一样。如果非要实现100G TCP建议采用混合架构简单的小包控制帧通过CPU处理大流量的数据帧走硬件加速路径。这种设计能将大部分网络流量绕过CPU同时保留TCP的可靠性控制能力但工作量已经不是单篇博文能覆盖的范围了。7. 后续优化方向和性能调优清单项目已经能够稳定跑完100G UDP收发但“能用”和“好用”之间还有一段距离。这部分列出后续值得优化的方向以及我在性能调优时整理出来的检查清单。丢包率优化方面核心是从FPGA侧尽量消除一切可能导致FIFO溢出的因素。关键手段包括增加UDP发送通路FIFO的深度让突发数据有更大的缓冲空间。实现基于信用的流控机制credit-based flow control在DDR读侧和UDP发送侧之间做温度调节。在DDR控制器和UDP发送逻辑之间增加数据打包模块把小包聚合成大包再发送减少小包数量对MAC处理能力的消耗。时序收敛方面100G工程最常见的两个问题是校验和模块的长组合逻辑路径、以及FIFO的读写指针跨时钟域路径。针对校验和路径采用流水线结构针对FIFO跨时钟域路径用厂商原语如Xilinx的XPM_FIFO替代自研的异步FIFO可以省掉大量调时序的时间。资源优化方面如果FPGA资源紧张可以把PCS拆成4个25G通道分别处理再在上层逻辑里合并这样GTY的资源消耗会更均匀。此外URN存储的使用比BRAM有更好的功耗表现在高位宽FIFO设计里可以优先考虑URAM。最后是我的测试清单只要都能打勾基本可以认为100G UDP链路是稳定可靠的连续ping 1000个包零丢包。iperf3在10Gbps速率下运行10分钟丢包率小于0.001%。用Wireshark抓包验证至少10万个UDP数据包的校验和无误。在FPGA侧通过ILA观察发送FIFO从未出现过满状态。断掉光缆再插回链路能在2秒内自动重新建立且恢复后的前1000个包无错包。板卡长时间24小时跑满20Gbps稳定负载无复位、无锁死。从第一次翻开Verilog Ethernet的源码到性能达标前后用了差不多一个月时间。这个过程中最大的收获倒不是代码本身而是把百G以太网整个协议栈从物理层到应用层完整地通了一遍还顺便搞清楚了厂商商业IP背后的实现逻辑。如果大家手里的项目也需要在100G这条赛道上跑UDP开源方案确实是一条性价比极高的路径——有困惑或者遇到具体问题欢迎随时交流。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价