尧图精选

100G FPGA UDP开源方案移植实战:从GT时钟到线速收发全记录

🕒 发布时间:2026/9/7 18:01:33 📁 来源:尧图网络
最近把一套开源的100G FPGA UDP方案从参考工程里拆出来移植到我们手里的一块VU9P级别板卡上然后完整做完上板测试。前后折腾了两周多中间踩了不少坑从最开始的GT参考时钟不锁定到小包打到一半疯狂丢包最后总算把线速收发跑通CPU占用还压得很低。这篇就把整个过程做个复盘选型怎么考虑、代码改了什么、上板怎么一步步验、出了哪些怪问题又是怎么排查的能给正在评估100G UDP方案或者准备在FPGA上移植开源协议栈的朋友一个参考。先交代一下背景我们为什么要折腾100G UDP而不是直接买商业IP或者用服务器网卡。我们的实际场景是高速数据采集回传前端的ADC数据要经过FPGA做实时处理然后以UDP包形式从100G光口发出去。商业IP核授权费不低且锁器件如果用服务器网卡加内核协议栈延迟和吞吐都不够理想。所以开源FPGA网卡方案就成了最合适的切入点既能把转发时延压到微秒级又能省掉授权成本。这套方案适合谁参考呢一种是正在做FPGA高速网络协议栈移植的另一种是想在高端FPGA上跑100G UDP但不知道怎么验、怎么调的再有就是对开源网卡设计感兴趣、想在自己板卡上复现的。文章不涉及太深入的理论更多是实战过程、参数选择和踩坑心得。1. 为什么选开源方案需求拆解与选型逻辑1.1 100G UDP到底解决什么问题100G以太网的理论速率是100Gbps换算成线速大约每秒可以处理148.8M个64字节小包。这个量级远超普通CPU的处理能力也远超普通PCIe网卡在内核TCP/UDP协议栈下能达到的吞吐水平。FPGA的价值就在于用硬件逻辑直接完成以太网帧解析、IP/UDP头处理、校验和计算和DMA搬运把协议栈开销从CPU卸载到可编程逻辑里。我们的核心需求其实有三条。第一高吞吐单方向尽量跑满接近线速至少也要到80Gbps以上才算合格。第二低延迟从数据进入FPGA到UDP包发出光口端到端延迟尽量控制在几微秒级别这个用软件协议栈很难做到。第三可裁剪我们并不需要完整TCP协议栈UDP无连接、无重传状态简单非常适合FPGA实现。提一个容易被忽略的点虽然UDP协议本身简单但要让100G UDP能稳定跑起来工作重心反而在MAC / PCS / PMA这一层以及跨时钟域缓冲和流控反压机制上。协议栈那点逻辑很容易写真正难的是让数据在322MHz甚至更高的时钟域里流畅流动起来。1.2 主流开源方案对比与选型我粗略翻了市面上能拿到的开源100G UDP/NIC相关工程主流的有这么几类。第一类是Corundum这是一个比较完整的开源FPGA网卡实现支持10G/25G/40G/100G自带PCIe DMA、多队列、Linux驱动。它把MAC、UDP offload、DMA、PCIe硬核都串起来工程结构清晰代码风格也不错很适合拿来做底子。缺点是为了通用性牺牲了不少灵活性模块层级比较深寄存器配置较多刚开始可能容易看晕。第二类是Alex Forencich的verilog-ethernet这个库主要提供10G/25G/100G的MAC、MII接口和常用以太网组件。严格说它不算完整的网卡方案但是模块质量高独立性强如果你手里已经有自定义的数据通路只是想补一个100G MAC或者UDP/TCP offload引擎从这里面抽模块很方便。第三类是OpenCores上一些比较老的Gigabit UDP栈这类基本都是1G级别代码风格偏老想改成100G基本要重写数据通路不太建议直接拿来做基础最多参考头处理和校验和逻辑。我最后的选择是以Corundum的UDP offload逻辑和DMA框架为骨架MAC层换成Vivado里的CMAC硬核IP再针对自己板卡的GT位置和时钟资源重新约束和适配。这样做的好处是Corundum在协议栈层面已经有充分验证Linux驱动和主机侧软件栈都比较成熟CMAC硬核在UltraScale上本身是免费IP性能和资源都比软核MAC有优势时序也容易收敛。1.3 移植前必须想清楚的几件事移植不只是把代码拷过来改改管脚动手之前有几个问题必须先想明白否则容易白干。第一个是目标板卡的器件型号和封装。Corundum的参考设计一般是基于特定板卡做的GT位置、参考时钟输入、QSFP28的管脚分配都不一定匹配。最好先在Vivado里把目标板的约束文件整理好确认需要用的GTY channel在哪个bank、参考时钟走哪根引脚。第二个是Vivado和IP版本。不同版本对CMAC、PCIe、DMA IP的接口定义不完全一致尤其是AXI4-Stream的tkeep、tuser信号细节可能有差异。建议直接固定一个版本比如我用的是Vivado 2022.2后续所有IP都以这个版本为准避免做无谓的兼容性折腾。第三个是测试环境。上板之前最好先搭一个仿真环境把以太网发包模型和收包检查逻辑写好。Corundum源码里带了一些not Jar但针对你的UDP场景最好是自建testbench。后面你会发现很多问题如果先在仿真里暴露出来上板调试时间能省一半。2. 硬件平台与工程搭建细节2.1 目标板卡和光模块的摸底检查我手头这块板卡是标准的FPGA加速卡形态PCIe x16金手指板载QSFP28光口FPGA用的是VU9P级别GTY资源比较充裕。刚开始别急着写代码先把硬件摸清楚非常关键。首先是时钟。100G以太网需要一路156.25MHz的GT参考时钟我的板卡正好有这个频率是100G四路25.78125Gbps传输的标准参考时钟。如果板卡上没有就要看是否有可编程时钟芯片能生成或者用其他参考频率经过GT的时钟分频配置来凑但最省事还是按参考设计来。然后是光模块。QSFP28模块分SR4、LR4、CWDM4等多种对应不同传输距离和光功率。我们用短距SR4就行四路25G并行光纤和FPGA的四条GT lane一一对应。插上模块后从Vivado的硬件管理器里能读到光模块的DDM信息比如光功率、温度、电压、TX bias等如果读不到说明I2C链路有问题先别急着调逻辑。最后是电源和散热。100G满速跑的时候FPGA核心电流会明显上升PCB上VCINT的供电必须满足手册要求。散热也不能马虎长时间打流后芯片温度如果超过100度时序会劣化表现为随机丢包或者CRC错误。我这次测试前专门确认了散热片和风扇能够压住功耗避免测试中途因过热翻车。2.2 Vivado工程构建设置要点建工程的时候有几点值得注意。第一IP核选型。CMAC这个IP核在UltraScale系列里有两种形态一种是Vivado里的CMAC IP核直接调用即可另一种是使用IBERT调试后再切换到实际功能。我的建议是先用IBERT验证GT物理层再建CMAC。CMAC配置里需要重点关注的是“Lane Rate”选25.78125G、参考时钟频率选156.25MHz、数据接口位宽选择512-bit。接口位宽直接决定用户逻辑时钟512bit位宽对应322.265625MHz的AXI4-Stream时钟这个频率在VU9P上时序还算友好。第二DMA和PCIe部分。如果目标是做成完整的网卡PCIe硬核需要选择Gen3 x8或x16然后和DMA IP连接。Corundum的DMA框架在Linux驱动配合下可以做到多队列收发但这是一个比较复杂的子系统如果你只需要纯粹的UDP数据通路可以先把DMA部分简化用AXI4-Stream接口直接对接自己内部的数据源例如ADC采集模块或者DDR读出的数据这样工作量会小很多。我做第一版验证时就是这么干的先不碰PCIe用FPGA内部产生的测试pattern发包把UDP通路打通再接PCIe。第三文件的组织方式。建议把开源工程里的rtl目录完整拷贝下来保留原始代码结构自己新增的适配代码单独放一个目录。这样方便后续和上游更新做对比也方便定位自己改过的地方。2.3 时钟复位架构的重新梳理移植过程中最容易被忽略的就是时钟和复位恰恰也是问题最多的部分。在100G UDP通路里时钟域大概有这么几个GT收发器的并行时钟域CMAC内部和用户侧的AXI4-Stream时钟域以及用户逻辑的通用时钟域。CMAC输出的usr_clk是322.265625MHz这是最核心的时钟几乎所有的收发包逻辑都工作在这个域里。用户逻辑如果跑不同频率中间必须加异步FIFO做缓冲。Corundum自带了不少跨时钟域的FIFO模块可以直接复用但要注意FIFO深度必须考虑最大包长和突发情况。复位方面最稳妥的做法是每个模块使用独立的异步复位、同步释放电路由复位模块统一产生。开源的代码里不同的模块复位逻辑习惯不太一样有些直接用rst_n有些又加了一堆同步逻辑移植前最好统一封装。我踩过一个坑CMAC的复位释放太早导致GT还没有完成初始化就收到数据出现了一堆alignment marker错误。后来把CMAC的复位信号和gt_rxresetdone、gt_txresetdone拉起后再释放问题就解决了。2.4 仿真环境搭建别急着上板我把仿真看成移植成功的关键一步。开源工程在GitHub上一般自带仿真脚本但默认的testbench往往是针对参考板卡的环路测试。我建议自己写一个最小的testbench包含三个部分发包模型、待测DUT、收包检查模型。发包模型用来生成以太网帧要能配置源MAC、目的MAC、源IP、目的IP、UDP端口和payload长度还要能模拟组合包和连续发包。收包检查模型用来接收UDP包并做校验和和内容比对。仿真跑通后上板出现问题时可以用Vivado的ILA逻辑分析仪抓内部信号对照仿真波形很容易定位是逻辑问题还是时序问题。我记得第一次跑仿真就抓到一个很有意思的bugUDP校验和在仿真里算对了上板却出错。后来发现是因为发包模型给checksum字段预留的位置和协议栈实际计算的位置错位了一个索引偏了4字节。这种问题如果直接上板看抓包很容易让人误判成链路问题耽误很多时间。3. 协议栈移植与核心逻辑改造3.1 100G MAC/PCS的配置和适配MAC层是100G UDP跑起来的基础。我使用的是Vivado CMAC IP它在UltraScale GTP/GTY/GTM上有硬核实现支持100G以太网的标准功能包括64B/66B编码、前导码处理、FCS插入和校验、流控等。配置CMAC的时候有几个关键参数需要认真核对。速率选择100G参考时钟156.25MHz数据接口选择512-bit。同时要把RS-FEC这块配置清楚如果光模块支持开RS-FEC544,514可以显著改善链路误码率尤其是在较长光纤链路上。我这边开启后很长时间测不到误码关掉后长时间跑偶尔会出现CRC错误所以能开就开。CMAC的接口信号比较多有tx_axis、rx_axis、gt_rxp/gt_rxn、gt_txp/gt_txn、gt_ref_clk等。特别注意tx_tuser和rx_tuser的含义CMAC用这些信号传递错误标记。rx_tuser的有效信号如果被置位说明这一帧在物理层就有错误用户逻辑必须能够丢弃这些错误帧不能继续往上层传。这一点不处理好的话抓包软件会看到一堆CRC错误包主机侧也会因为校验失败而丢包。另外CMAC初始化完成后会有tx_resetdone/rx_resetdone信号这些信号要接回复位模块用户逻辑等这两个信号都拉高后才能开始收发。GT的tx/rx resetdone信号也类似建议全部串成一级状态机确保整个链路完成初始化和复位释放后再进入正常工作模式。3.2 UDP协议栈各功能模块的拆解协议栈部分我主要拿Corundum的UDP offload模块做改造它的整体框架可以拆成几个子模块。接收方向以太网帧进来后首先检查目的MAC是否为本机MAC或者广播MAC然后解析以太网type字段如果是0x0806就交给ARP模块处理如果是0x0800就进一步解析IP头。IP头解析重点是IP总长度、协议号、源IP、目的IP然后检查协议号是否为UDP0x11是则继续解析UDP头取得源端口、目的端口、UDP长度、校验和。如果校验和使能则对IP伪头部和UDP数据做校验和验证校验失败直接丢弃。只有当端口匹配本机监听的端口时才把payload交付给上层FIFO。发送方向上层模块把要发送的payload写入发送FIFO协议栈按顺序封装UDP头、IP头、MAC头。IP头的identification字段UDP头的length字段都需要根据实际包长动态填充。IP校验和采用增量校验或者每包计算UDP校验和在IPv4场景下可以填0表示不校验但为了兼容性和抓包工具的美观我默认还是计算了UDP校验和代价是每个包多几十个周期的处理延迟对吞吐影响不大。ARP模块也是必须的。主机要对FPGA发包必须先通过ARP得到FPGA的MAC地址。如果主机的ARP表里没有FPGA的MAC记录发第一个UDP包之前会先广播ARP请求协议栈需要响应这个请求返回自己的MAC地址。这个逻辑不复杂但必须实现不然就是能ping通网关却无法和FPGA通信的诡异现象。3.3 数据通路与缓冲反压才是100G是否稳的关键决定100G UDP能不能稳定跑满的除了协议栈本身还有数据通路的FIFO和管理机制。接收方向CMAC的rx_axis总线是512bit位宽每拍可以处理一个完整包的一段。如果包速率很高协议栈处理不过来就必须通过FIFO的almost_full信号向CMAC反向压数据。CMAC支持暂停发送用户侧只需要把almost_full反馈给rx_axis的tready即可。但要注意tready的反压有延迟CMAC可能在检测到反压之前已经多发了几拍数据所以FIFO深度不能太浅。我用的接收FIFO深度是32K×512bit可以缓冲很多个大包实测在突发流量下也没有溢出。发送方向协议栈从发送FIFO取数据封装MAC/IP/UDP头后送给CMAC。这里最关键的是FIFO空满状态的管理。如果发送FIFO为空协议栈应该停止读取不能让下游出现欠载。尤其是以太网帧之间的IFG帧间隔不能随意缩短CMAC在tx_axis上如果tvalid拉低再拉高会自动插入额外的IFG这样会影响线速吞吐。所以如果目标是满速打流发送FIFO尽量保持非空否则会出现速率抖动甚至掉速。我这次还做了一级包头加速处理part of payload只有在首拍需要填写以太网头、IP头、UDP头时才做完整的包头计算和拼接后续拍只需透传数据。这样可以将每包的额外处理周期控制在极小的范围实测64字节小包也能维持比较高的pps。4. 上板测试全流程从点亮到满速4.1 第一件事先验证物理层上板之后不要直接跑UDP先从底层开始验证这一步可以帮你把问题切分成“物理层问题”和“逻辑层问题”。我用Vivado的IBERT核做了GT眼图扫描。IBERT是Xilinx提供的高速串行链路调试工具能通过硬件管理器直接查看每条lane的眼图和BER。在工程里实例化一个IBERT核连接QSFP28的四路GTY设置线速25.78125Gbps选择PRBS31测试码型然后跑一段时间看误码率。如果四条lane都能达到零误码说明光模块、PCB走线、GT配置都没问题。如果某条lane误码高或者眼图闭合就检查光模块是否插好、光纤是否松动、参考时钟对不对、GT的TX预加重等参数是否需要调整。初次测试时我遇到一个问题两条lane的误码率明显偏高。排查了很久最后发现是板卡上这两条lane的参考时钟走线和另外两条不在同一个bank而IBERT里引用的参考时钟管脚选错了。修正约束并重新生成bit后四条lane全部零误码这算是这次移植过程中最大的一个坑也验证了先做物理层测试的重要性。4.2 逻辑回环测试近端把通路打通物理层没问题后先做逻辑回环。在CMAC的tx_axis和rx_axis之间直接接一根线让数据从发送侧进入CMAC再由接收侧回来验证MAC层的工作状态和自己的时序逻辑。这一步虽然没有真正经过光模块但能验证CMAC初始化、复位、FCS等基本功能。回环正常后我开始在FPGA内部构造UDP包送进协议栈的发送FIFO然后把接收FIFO的数据再直接回送到发送方向也就是做一个UDP回环服务器。主机端往FPGA发UDP包FPGA收到后再原样发回来。这样可以在不写复杂上位机程序的情况下用最简单的ping和UDP测试工具验证链路通不通。我使用的测试工具是常见的UDP网络调试助手设置好目的IP和端口点击发送就能看到回环回来的包。需要注意的是如果FPGA回环的是同一个目的端口抓包时看到源端口和目的端口一致可能有点奇怪但这不是问题只要主机收到的payload与发送payload一致即可。4.3 iperf3打流看吞吐上限回环正常后就是真正的数据面验证。我在服务器上装了一个DPDK版本的开源测试工具直接用DPDK PMD绑定FPGA网卡可以绕过内核协议栈测试FPGA网卡能做到的极限吞吐。如果只是用内核协议栈打流通常会受限于CPU中断和协议栈处理测出来的数字完全不能反映FPGA的能力。使用iperf3进行UDP打流时我习惯用如下参数iperf3 -u -c 192.168.1.10 -b 0 -l 1472 -t 30-b 0表示不限带宽-l 1472表示UDP payload尽量接近MTU-t 30表示跑30秒。这里payload为什么是1472因为以太网MTU一般是1500减去IP头20字节和UDP头8字节就是1472。在这个配置下FPGA收到UDP包后走了个回环iperf3的报告显示接收带宽能稳定到99Gbps以上也就是说几乎跑满了100G线速。如果去掉以太网前导码、帧间隙和包头开销实际上有效payload速率不可能到100G但iperf3统计的是UDP payload速率能到99Gbps左右已经说明帧间隔和包头处理对吞吐的影响非常小了。紧接着测试小包性能。把payload调到16字节甚至1字节此时包速率急剧上升主要考验协议栈每秒能处理多少个包。实测大约能到140Mpps离理论极限148.8Mpps还差一点主要丢在协议栈的包头解析流水线和FIFO反压延迟上。对于小包压力场景来说这个性能已经够用。4.4 Wireshark抓包从“看起来通”到“真的对”吞吐数字好看还不够必须用Wireshark抓包确认包内容正确、序号连续、时间戳均匀。抓包时有个常见现象值得说一下很多人习惯在Wireshark里设置过滤条件udp却仍然看到ICMP或者其他协议的包。这个其实不是bug而是抓包过滤capture filter和显示过滤display filter的区别。只有抓包过滤会在驱动层面过滤显示过滤只是把不符合条件的包隐藏。如果一开始设置的是udp这个显示过滤那么其实是抓到了所有包只是界面里只显示UDP但统计信息还是会包含其他协议。这里应使用BPF格式的抓包过滤比如tcpdump -i enp3s0 -w udp.pcap udp或者Wireshark捕捉界面里在“Capture Filter”一栏填udp才能真正过滤。抓包重点看几项一是UDP校验和是否通过Wireshark里校验和错误会有红色标记二是IP identification是否递增如果乱序或者重复说明协议栈维护的ID有bug三是包时间戳是否均匀如果出现明显抖动可能和发送FIFO的深度或者是DMA的burst配置有关。另外如果涉及丢包排查Linux下的netstat -su非常有用。它给出的统计里有一项packets to unknown port receive这个数值非零说明主机收到了UDP包但这个端口没有被任何进程监听UDP栈直接丢弃了。如果是从FPGA发往主机的方向出现这个问题往往是目的端口号配置没对上或者主机防火墙把端口拦了这时候不是FPGA的锅先检查端口和防火墙规则。4.5 长稳测试能扛过一小时才算合格跑满几分钟不能说明问题我习惯做至少一小时的长稳测试。长时间运行的目的是暴露两类问题一是温度上升后时序是否还收敛二是软件和硬件交互是否有累积性状态错误比如DMA描述符泄漏或者FIFO指针漂移。这次长稳测试期间我用ILA抓过几次内部信号期间没有发现丢包、CRC错误或校验和错误性能曲线也很平。温度稳定在75度左右光模块的光功率没有明显漂移。整体验证到这个程度才敢说移植是成功的。5. 常见问题与排查技巧实录5.1 速率上不去先查包大小和帧间隔如果打流发现吞吐远低于预期第一步看测试配置。很多人用iperf3打UDP时没有设置大包默认payload是8KB但UDP实际上会被IP层分片分片重组对吞吐本来就有影响测试结果不稳定。统一用1472字节作为UDP payload测试是排除分片干扰的最简单方法。如果大包性能正常但小包性能差就要看协议栈的每包处理开销。小包考验的是pps不是带宽。100G线速下64字节包的极限是148.8Mpps如果你的方案只有几十Mpps说明逻辑里某个地方每拍处理不了完整包头出现了流水线气泡需要通过增加预取或者优化状态机来压缩每包处理周期。5.2 抓包出现CRC错误或FCS错误这类问题优先考虑物理层。先看CMAC的rx_fault信号是否有拉高再看GT是否报出rxdisperr或rxnotintable错误。如果只是极少数包出错大概率是链路误码导致开启RS-FEC后会有明显改善。如果大量包出错那就要回头看IBERT的眼图测试了光路可能有问题比如光纤衰减过大、光模块发射功率不足、或者连接器污染。这里有个实操建议光纤插入QSFP28之前最好用一次性光纤清洁笔清洁一下端面。很多人测试时忽略这一点导致链路时好时坏其实是端面灰尘造成的。5.3 主机ping通但UDP不通ping走的是ICMP协议和UDP走的路径有区别。如果ICMP能通而UDP不通优先排查端口监听和防火墙。检查主机上UDP端口是否bind成功ss -ulnp | grep 9000没有输出就说明程序没有监听9000端口数据包发过去会被内核直接回ICMP Port Unreachable。这时netstat -su里的packets to unknown port会增长一下就能定位到原因。另外如果是FPGA端不回UDP包主机的ARP表可能过期。发送前先ping一下FPGA的IP再观察FPGA侧的ARP模块有没有正确回复ARP请求。很多开源UDP栈在不做ARP缓存老化处理时发送ARP request非常频繁如果FPGA没正确处理主机侧就会出现链路看起来是UP的但UDP发不出去的现象。5.4 校验和错误字节序和伪头部是两大元凶移植UDP校验和逻辑时最容易出错的是字段字节序和伪头部计算。UDP校验和需要计算伪头部包括源IP、目的IP、UDP长度、协议号再加上UDP头和payload。FPGA内部数据通常是大端字节序也就是网络字节序但软件端计算时如果处理成小端结果就不对。一个比较简单的验证方法是把同一个包用Wireshark抓出来看Wireshark显示的checksum值再和逻辑里计算的checksum做对比。如果每次算出来都差一个固定的数基本上是字节序处理问题。另外IPv4下UDP校验和的checksum字段可以置0表示不校验很多网卡硬件支持这个特性。但如果你的抓包工具会标红checksum错误最好还是把checksum算对避免测试时误判成链路故障。5.5 不定时丢包又抓不到错包这种情况最棘手因为表面上所有包都是好的只是计数少了。优先怀疑是缓冲区溢出或反压没生效。接收方向CMAC的rx_axis停顿时可能会丢包如果FIFO的almost_full信号没有提前拉高来不及反压CMAC就会丢弃后续来的帧。可以在ILA里观察almost_full触发时是否已经有丢包事件发生。发送方向则怀疑DMA描述符回收不及时软件还没来得及把buffer还给硬件硬件就没有空闲描述符可用于是只能丢包。这种情况下最好的工具是计数器和状态寄存器。我在调试版里加了一组计数器分别统计CMAC收包数、协议栈收包数、FIFO写入数、主机侧收到的包数通过这四级计数器的差值就能精确定位丢包发生在哪一级。这个调试思想比动不动就抓波形更高效强烈建议在正式工程里保留这些计数器对后续维护也有价值。6. 移植测试结果汇总与后续扩展方向6.1 性能数据与资源占用汇总简单列一下这次移植后的实测数据给大家一个直观参考。测试项测试条件实测结果UDP大包吞吐单向回环payload 1472B不限带宽99.2 GbpsUDP小包转发速率payload 64B约138 Mpps端到端时延FPGA内部回环不含软件栈约1.8微秒长时间稳定性90分钟满速打流无丢包、无错包CMAC/GT误码PRBS31, 30分钟零误码逻辑资源LUT/FF协议栈DMAMAC控制约150K LUT / 180K FF这里需要说明的是小包吞吐没有达到线速极限但离理论值已经很接近。如果要进一步优化可以把包头解析做成多级流水线并行处理或者增加多队列分发让多个包并行处理不过相应的资源消耗和时序压力也会上来。对于现阶段的应用场景这个性能已经远超预期。6.2 开源方案到底能顶到什么程度经过这次移植我对开源100G UDP方案的成熟度有了比较明确的判断。在可控的数据采集和高速互联场景里开源方案完全可以用代码透明、可控性强、性能达到线速级别。它和商业IP的差距主要体现在生态和自动化程度上比如商业IP往往自带完整的调试工具链、文档和工程支持而开源方案需要自己摸索调试方法。另外如果要做成标准的PCIe网卡形态Linux驱动的稳定性和各种边界条件的处理还是要花不少功夫。Corundum的驱动相对完整但如果你想改造DMA行为或者增加自定义寄存器还是需要深入理解Linux内核驱动框架的这部分工作量不见得比硬件逻辑小。6.3 还可以往哪些方向扩展这次移植的基础架构留有比较清晰的扩展空间今后如果有需要可以直接在现在的工程上做这些事情。第一个方向是增加RoCE或者类似的有损RDMA卸载逻辑让FPGA网卡既能做纯UDP高速数据面又能承担部分RDMA语义这对高性能分布式计算场景会很有帮助。第二个方向是把多队列和RSSReceive Side Scaling做完整让不同主机的数据流被分发到不同的队列配合PCIe DMA多队列机制可以充分利用多核CPU的并发能力。第三个方向是我们自己在做的在UDP数据面上叠加私有控制通道用于带内管理、固件升级和状态上报这样FPGA网卡就有了可远程管理的能力。从这次的整体经历来看工程性和耐心才是移植成功的关键。很多人拿到开源代码最先做的就是上板但我还是坚持从仿真、IBERT、回环、小包、大包、长稳一步步来。每个环节都跑通了再进入下一环节看上去多花了一两天实际上整个调试过程非常顺滑。好多次差点在物理层问题上深挖逻辑被这种分层验证的思路及时拉了回来。最后再分享一个我个人的小习惯在整个工程里尽量保留足够多的计数器和状态寄存器并且把它们统一映射到一个调试总线里。上板测试时一旦出现异常先读计数器再决定要不要上ILA抓波形。这套方法帮我节省了大量时间希望你也能用得上。
上一篇/下一篇内容由系统自动关联 返回资讯列表 →