尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

开源100G网卡Corundum向Altera Arria 10平台移植实录

发布时间:2026/9/27 23:20:18

资讯中心
01
ARTICLE

开源100G网卡Corundum向Altera Arria 10平台移植实录

开源100G网卡Corundum向Altera Arria 10平台移植实录
1. 为什么要把Corundum往Bittware VV4这样的Altera平台上搬Corundum这个开源100G NIC项目在FPGA网络加速圈子里基本属于绕不开的存在。它把一套完整的网卡数据面开源了出来PCIe DMA、发送调度、接收队列、包分类、100G MAC甚至还有基于P4的流表框架全部用SystemVerilog写成能跑在Xilinx的VCU110、VCU118这些板卡上。我过去两年在Xilinx平台上用它做了不少原型验证整体评价是模块划分干净总线接口统一代码比很多商业IP还规整。所以我刚开始接到把Corundum移植到Bittware VV4这个需求时第一反应是这事能成但绝对不像改改顶层管脚那么轻松。Bittware VV4用的是Intel Arria 10 GX 1150这片FPGA器件厂商完全不同。Xilinx平台的GT收发器、硬核PCIe IP、MMCM时钟管理、ODDR输出原语在Arria 10里对应的全是另一套东西。移植的本质不是改错而是换血——把和具体FPGA原语强绑定的部分全部替换成Intel平台的对等实现同时保证上层数据通路的行为完全一致。这篇文章是移植过程的第一篇先写给同样手里攥着Altera/Intel板卡、却想用开源网卡栈的工程师。我会把前期拆解、Quartus工程搭建、IP替换、首次PCIe枚举这几步完整过一遍每一步为什么这么做、踩了什么坑都讲清楚。内容会比较长因为我不想只扔结论更想把平台迁移时应该从哪里下手这个思路留下来。1.1 开源100G网卡的三条路线我最后选了Corundum做100G开源NIC圈子里其实有三条主要路线。第一条是OSNT它比较偏重流量回放和监控数据面结构相对简单第二条是N560那类偏交换/卸载的项目代码量和复杂度都很大适合做研究但不适合快速原型第三条就是Corundum。它最大的特点是完整PCIe端点、DMA引擎、多队列发送接收、MAC和PHY抽象全都有而且对外接口统一走AXI-Stream和AXI-Lite。这意味着上层逻辑不需要关心具体FPGA是哪家只要总线上行为正确就行。我在Xilinx平台上用Corundum做OVS卸载原型时最满意的是它的发送调度器。它用时间轮片的方式给每个队列分配带宽支持严格优先级和加权轮询这对网卡类应用非常关键。另一个优点是它把描述符环管理、中断聚合这些CPU侧逻辑做到了RTL层而不是依赖SDK调试起来能看见每个时钟周期的状态。选Corundum还有一个很实际的理由它不依赖商业100G MAC核。MAC层是自己写的RTL也就是说从DMA出来的包一直到串行收发器之前大部分代码是厂商中立的。真正需要动刀的是收发器那一层和PCIe硬核那一层。这让我觉得移植到Arria 10是可控的不需要重写整个网卡逻辑。1.2 Bittware VV4看着眼生但它的资源其实是正中靶心Bittware是一家老牌FPGA板卡厂商很多客户拿他们的板子做信号处理和网络加速。VV4这块板子用的Arria 10 GX 1150属于Altera时代的高端型号逻辑单元110万级别片上存储器足够跑完整的网卡描述符和大缓冲区硬核PCIe支持Gen3 x8最关键的是高速收发器数量够多能覆盖100G所需的4条25G串行链路还能留出裕量给未来扩展。从资源匹配度上讲它和Corundum原生支持的VCU110很像都是大逻辑、多收发器、单FPGA跑完整网卡。我列过一张资源对照表作为移植前的可行性判断依据。资源项Xilinx VCU110 (主流承载板)Bittware VV4逻辑单元约120万Arria 10 GX 1150约110万PCIe硬核Gen3 x8Gen3 x8高速收发器GTY/GTHArria 10 Transceiver片上存储大容量BRAM/URAMM20K块式存储网络接口QSFP28板载QSFP28参考时钟156.25MHz等由板级时钟树提供VV4还有一个优势板卡资料里提供了完整的Quartus管脚约束范例QSFP28、PCIe、时钟、LED的管脚分配都写得明明白白。这一点对移植工程来说是最实在的省去了拿着原理图一根一根查Pin的功夫。后面我会专门说管脚约束这块的细节。2. 移植前最值得花时间的事把Corundum拆解成能原样保留和必须替换两部分很多人拿到开源RTL项目后第一件事就是建工程、点编译然后被几十上百条报错淹没。我的习惯相反先花两三天读代码把项目的边界画清楚。对于平台移植这个步骤尤其重要因为FPGA工程里的报错往往是连锁反应——顶层缺一个信号下面能冒出两百条莫名其妙的错误。只有先在脑子里建立哪些模块碰不得、哪些模块必须换的地图编译报错才不会让你慌。2.1 Corundum的内部逻辑分区Corundum从结构上可以粗暴地分成四块。第一块是PCIe硬核包裹层它直接实例化Xilinx的PCIe IP对外输出AXI-Stream TLP接口、AXI-Lite配置接口、以及MSI中断相关信号。第二块是DMA引擎职责是把CPU侧描述符翻译成读写字请求管理PCIE地址和FPGA内部缓冲区地址的映射。第三块是网络数据面包括发送引擎、接收引擎、包头拆卸、MAC层以及PHY层。第四块是控制面包括寄存器地址译码、队列配置、流表管理。这四块里第二、第三块大部分是厂商中立的。DMA引擎不管底层是Xilinx PCIe IP还是Intel硬核对外接收的都应该是已经解码好的TLP语义MAC层更不用说了只要收到标准的XGMII/并行数据流逻辑完全可以原样保留。真正麻烦的是第一块和PHY层前者要吃掉不同厂商硬核IP的接口差异后者要适配Arria 10收发器的Native PHY接口。所以我给自己定的移植路线是先换PCIe硬核包装层和PHY层把编译通路打通再用寄存器读写自环验证两个硬核替换后的基础功能DMA和调度器这类逻辑密集、但接口标准的模块放到第二步调。2.2 真正需要动手的器件相关区域具体到Corundum源码里和Xilinx器件绑定最严重的地方有三处我逐个说。第一处是收发器实例。Corundum在Xilinx平台用的是GTY/GTH收发器配置里包含TX/RX并行接口、时钟核、复位控制。这些代码里的名称、位宽、握手时序都和Xilinx的transceiver IP严格对应没法直接在Quartus里用。Arria 10这边对应的替换方案是Native Transceiver PHY IP接口上是Avalon-ST风格而且需要自己拼出4条25G lane的通道组。这个替换是整个移植的硬骨头我后面第三章会展开。第二处是PCIe硬核。Corundum默认的PCIe包装层是为Xilinx Series 7/UltraScale硬核写的信号包括pcie_rq_tag、pcie_rc_*这类TLP流控制以及pl_eq_*这种物理层状态接口。Arria 10的Hard IP for PCI Express则是Avalon-ST接口TLP流的手握时序虽然也是标准的但寄存器、复位、中断映射全不一样。这一步不是简单改信号名而是要重写一个pcie_wrapper把Quartus硬核的Avalon-ST桥接成Corundum内部期望的TLP接口。第三处是普通原语替换。比如Corundum在输出差分信号时用到了Xilinx的ODDR原语在Arria 10里对应的是ALTDDIO_OUTQuartus甚至建议直接用ddio_out这个原语名。又如异步FIFO在不同平台上的IP名字完全不同Xilinx是xpm_fifo_asyncArria 10里可以选dcfifo。这类替换不涉及逻辑设计但数量多漏掉一个就编译不过。我在动手前还专门检查了一件事Corundum里大量使用SystemVerilog的接口、结构体、包定义Quartus对现代SystemVerilog的支持虽然不如Vivado顺滑但基本语法是认识的。只要把工程的语言标准设对源码本身不需要大规模改写。3. Quartus工程骨架搭建从IP替换到管脚锁定代码拆解完就可以正式搭工程了。这一步的目标很简单让Corundum主体源码在Quartus里顺利进入综合把IP替换和管脚约束都落下去。我强烈建议不要一上来就追求跑通全功能先把工具链源码IP管脚四件套跑顺后面的调试才有基础。3.1 工程目录与源码组织我的工程目录是这样组织的vv4_corundum/ ├── quartus/ │ ├── vv4_corundum.qpf │ ├── vv4_corundum.qsf │ └── ip/ # Quartus IP 生成目录 ├── src/ │ ├── lib/ # Corundum基础库axis、tlp、cksum等 │ ├── modules/ # 各功能模块 │ ├── fpga/ # 平台相关封装 │ └── vv4_top.sv # 新写的顶层 └── constr/ └── vv4_pins.sdc # 时序约束关键点是源码直接复用Corundum的Git仓库内容不要乱动内部目录结构。Quartus工程文件的组织方式由.qsf文件里的SOURCE条目决定我建议在.qsf里按目录加载源码而不是逐个文件添加否则日后加文件容易漏。具体写法就是set_global_assignment -name SYSTEMVERILOG_FILE -directory ../src/lib set_global_assignment -name VERILOG_FILE -directory ../src/modules然后把新写的vv4_top.sv单独加进去。这样Corundum原厂代码升级时我拉一个最新版替换src/目录工程文件基本不用动。Quartus版本我选了17.1之后支持Arria 10 GX稳定一点的版本具体装的是Quartus Prime Standard 20.1能完整支持Arria 10系列SystemVerilog的解析也比老版本稳。需要注意的是Arria 10器件包很大安装设备族时别漏选不然建工程时根本找不到1AX115N这个型号。3.2 用Arria 10 Native PHY替换Xilinx GT收发器这是整个移植里最贴近物理层的一步。Corundum在Xilinx侧的100G PHY由GTY/GTH收发器构成每条lane完成25Gbps串并转换4条lane聚合出约100Gbps的数据通路。Arria 10这边对应的方案是Native Transceiver PHY它在Quartus里以IP形式出现配置完成后会生成Avalon-ST接口。我在Quartus里创建Native PHY IP时选中Arria 10 GX协议方向不需要套用以太网模板选择Raw或者Basic模式更可控。原因是Corundum的MAC层自带PCS功能我需要透传原始的64B/66B编码数据路径让MAC层和收发器直接对接中间不能插进一个完整的Ethernet IP把包结构给变了。这个选择很多人会踩坑图省事选了Quartus里的100G Ethernet IP模板结果MAC层和IP层都做了一遍FEC、PCS延迟翻倍丢包率还不对。每条lane的有效数据接口位宽Arria 10 Native PHY支持多种配置25Gbps速率通常配成64位或32位并行数据总线。这里要特别注意位顺序问题Corundum的收发器接口里对lane位序、字节偏好有严格定义替换后必须通过自环测试确认收发字节序一致否则后面DMA收发会出现包内容莫名错位。4条lane的PHY配置完成后我在顶层把它们实例化然后单独写了一个vv4_phy_wrapper.sv把Quartus IP输出信号转换成Corundum的xgmii_tx_*、xgmii_rx_*这一层信号。转换的核心逻辑很简单就是对齐时钟域和总线位宽但这里的细节直接决定后面MAC层能否识别到空闲控制字符。3.3 硬核PCIe块替换从AXI-Stream TLP到Avalon-STCorundum的PCIe包装层为Xilinx硬核服务硬核内部已经把TLP拆成了多个数据流代码里面对应的是xilinx_pcie_ep_7x这类实例。Quartus里的Arria 10 Hard IP for PCI Express完全是另一套接口。它的TLP出入口是Avalon-ST接口收发各有自己的valid/ready/sop/eop信号配置空间和MSI中断也有独立的寄存器接口。我重写pcie_wrapper的思路是保留Corundum内部所有的TLP处理逻辑只替换对外信号部分。例如Xilinx侧提供pcie_rq_tag这样的请求标签信号而Arria 10硬核把TLP的标签放在Avalon-ST数据流里这个差异必须在wrapper层解开而不是改DMA引擎。Avalon-ST数据流通常有lp_cpl、lp_req、hp_rx等多个通道我通过查阅Arria 10 Hard IP文档把每个通道的功能和Corundum内部的TLP通道对齐。中断这块也值得单独说。Corundum默认使用MSI中断向CPU写一个特定地址触发中断。Arria 10硬核的MSI实现路径不太一样需要配置msi_*寄存器并确保MSI地址和数据在配置空间里能被正确解析。我在这一步花了不少时间最后是先让DMA引擎完全不依赖中断用轮询方式把寄存器读写跑通再回来补MSI这样能隔离变量。配置空间也是个隐藏差异点。Corundum内部会读取device_id、vendor_id这类信息做识别而Arria 10硬核默认的ID值需要额外配置或用自定义寄存器覆盖。我在quartus的.qsf里把PCIe设备的Device ID改成了和Corundum默认一致的值避免上层驱动认不出设备。3.4 时钟树与复位策略100G网卡对时钟质量极其敏感移植时最容易忽略的就是时钟树。Corundum的时钟域大致分三类PCIe用户时钟、串行收发器恢复时钟、MAC逻辑时钟。Xilinx平台常用MMCM生成多个频率而Arria 10的PLL资源和时钟结构完全不同必须重新规划。我在VV4工程里选的方案是PCIe用户时钟由Arria 10硬核直接输出通常是250MHz或125MHz取决于硬核配置100G MAC逻辑时钟为156.25MHz由板载可编程时钟芯片或收发器参考时钟源生成4条lane的收发器参考时钟必须同源保证lane间的时钟对齐。Quartus里我用ALTPLL生成MAC逻辑时钟输入选择了板载的25MHz基准晶振配置成156.25MHz输出。这里有个细节如果参考时钟直接来自QSFP侧的相同晶振自环时收发时钟同步会更容易但上联外界交换机后接收时钟会和发送参考时钟不同源MAC层的弹性缓冲必须能容忍这个频差。Corundum原生设计里已经有这个缓冲移植时只要保证时钟复位顺序正确即可。复位策略方面Arria 10的收发器和PCIe硬核都有自己的复位控制逻辑rx_is_lockedtoref这类状态信号需要被顶层使用不能用统一的一个全局复位把所有的全都拍一遍。我按Corundum原版逻辑做了一遍映射PCIe硬核的复位输出驱动DMA逻辑收发器的tx_digitalreset和rx_digitalreset分别由各自的锁定状态控制。这个顺序错了很容易出现寄存器能读、收发失灵的诡异现象。4. 第一次编译通过到PCIe枚举成功中间隔着什么整个工程量级不小Corundum的RTL加上IP文件综合一次大概要跑二十到四十分钟时序收敛阶段更久。我给了自己一个心理预期头三天就是在编译、看错误、改逻辑之间循环。4.1 编译阶段的一堆报错里最有代表性的三类第一类报错是原语缺失或名字不匹配。Xilinx的ODDR2、SRL16、MMCM这些原语在Arria 10下不存在Quartus会直接报Unknown primitive。解决方式分两种Cornium里面真正的ODDR只在少数高速接口用我直接改成ALTDDIO_OUTSRL16这类移位寄存器用altshift_taps替代。这里不要试图用纯RTL去重构原语时序很可能收敛不了老老实实换成Quartus原生原语最稳。第二类报错是SystemVerilog接口按引用传递的问题。Quartus对SystemVerilog的modport、interface支持比Vivado弱一些个别写法会解析失败。我遇到比较多的是接口数组的声明方式Quartus对interface数组的支持有时不稳定。解决办法不复杂——改用struct或扁平信号在顶层传递或者把接口数组拆成多个带编号的实例。这个工作很枯燥但是在平台迁移里躲不掉。第三类报错是IQ/引脚约束冲突。VV4板卡上同一个Bank可能既接了LED又接了下拉电阻Quartus会警告引脚分配与默认状态冲突。这类报错不能忽略因为轻则上板行为异常重则烧器件。解决办法是按板卡手册里给出的Assignment Editor配置逐项核对引脚方向、电流强度、片上终端。4.2 VV4管脚约束与板级启动流程管脚约束是移植里最容易低级失误的地方。Bittware VV4不像很多开发板那样所有外设全引出它是一块服务器用网卡PCIe和QSFP是主角调试口、LED只是辅助。我的管脚来源有两处一是板卡手册里的管脚分配表二是官方提供的Quartus范例工程。后者尤其好用因为范例里连Bank电压、终端方式都写好了。在.qsf里我用set_location_assignment从上到下锁定PCIe、QSFP、参考时钟、LED这些管脚。一个重点是PCIe的复位引脚VV4的PERST信号由主机槽位提供不能随便接一个板上逻辑否则PCIe枚举时设备可能时有时无。我反复确认这一点后才在顶层信号里暴露出来。板级启动流程也很关键。Arria 10的配置方式通常是主动串行AS模式固件存储在板载Flash里上电后由FPGA自行加载。如果在Quartus里没选对配置模式编译出来的.sof能下载但不能固化重开机之后板卡变砖。我调试阶段先加载.sof跑功能最后再生成.jic写进Flash这个顺序不要反过来。4.3 用寄存器读写自环确认通路可用当工程能编译通过、JTAG下载成功之后第一件验证的事不是收发百兆流量而是PCIe寄存器读写自环。Corundum里有一个寄存器管理模块通过AXI-Lite接口访问各子模块的配置寄存器。我在主机侧写了一个简单的PCIe驱动把BAR空间映射出来然后向一个已知寄存器写入固定值再读回来比对。这一步通过了说明三件事Arria 10硬核PCIe的枚举正常、pcie_wrapper的TLP转换方向正确、AXI-Lite地址译码无误。然后我再做物理层自环把发送侧的数据直接环回接收侧在FPGA内部通过收发器的Loopback模式让FPGA自己发自己收。不需要外部线缆就能验证PHY层的字节序、对齐和位同步这是调试效率最好的一步。我当时的验证方法是先利用Native PHY的串行自环模式把4条lane在内部环回然后在Corundum的MAC层发固定特征字看接收侧的计数器是否上涨。特征字建议用递增序列这样能顺带检查lane间的字节顺序是否错位。这一步通过后我才对PHY替换基本成立有了底。当然这只是第一步。PCIe枚举成功和寄存器自环通过只能证明门开了DMA引擎、描述符调度、中断路径这些核心网卡功能还没验证。这些内容属于移植的第二个阶段也是更硬的仗。5. 这一版做到了哪里以及我对后续步骤的判断很多移植项目死在第一步之后——以为联合编译通过就万事大吉结果上板跑真实流量才发现DMA描述符地址不对、中断丢失、调度器带宽分配失灵。所以我更愿意把进度切成小块每块都以可测的现象为完成标志。5.1 第一篇的完成度按这个标准目前这版工程拿到的里程碑是主板BIOS能识别到PCIe设备BAR空间映射成功通过寄存器自环可以读写配置空间FPGA内部各子模块的寄存器能正常访问Native PHY环回模式下发端和收端的特征字计数器同步增长说明PHY层数据通路已经通了。这个状态对应到一个可演示的动作其实是加载驱动后用lspci -vv看到设备然后在寄存器地址上做一轮非零回写读出。不要小看这个进度它说明器件层面和平台替换层面基本稳了。对于一篇系列文章的第一篇这个节点是合适的因为它把能不能在目标板卡上立住这个最大的不确定性解掉了。值得说明的是我没有改动Corundum的内部DMA引擎也没有碰调度器甚至没有让MAC层外连真实的QSFP光模块。原因不是回避而是不想在一次工程里堆积太多变量。编译器报错可以连坐但功能问题最适合逐个击破。5.2 下一阶段的DMA与调度面才是硬仗接下来的重点会落在三处。第一是DMA引擎与Arria 10硬核之间的TLP接口核对原生Corundum的DMA依赖的请求标签、完成通知语义和Avalon-ST场景存在差异需要写两个桥接模块做协议转换第二是MSI中断路径要在wrapper层把硬核的中断请求映射到Corundum的中断源保证CPU侧驱动能稳定收到收包完成通知第三是实际流量测试包括MAC层外环回、光模块上联、多队列并发用打流仪或者结合perf这类工具量出吞吐和延迟。这三块每一块都可能牵扯到pcie_wrapper的时序调整和逻辑修改所以我建议后面每一步都保持先活后快的顺序先保证功能正确再回头压时序。平台迁移里最忌讳的是复杂逻辑和复杂时序同时改那会让定位问题变成猜谜。就当前阶段来说工程骨架已经可以用了。如果你手里也有一块VV4或者类似的Arria 10板卡想接入Corundum这套开源网卡栈第一步的参考路径就在这里先把PHY和PCIe这两条腿换成Intel平台的、再把管脚约束配齐、让寄存器能读能写。做到这一步你手里的Corundum才算是真正在Altera平台上站稳了。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。