ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

FPGA多光口网卡主从级联配置:共享GT收发器实现四光口方案

FPGA多光口网卡主从级联配置:共享GT收发器实现四光口方案 做多光口网卡的人都知道当你从单光口跳到四光口、八光口的时候第一个让你头疼的问题往往不是逻辑设计而是IP配置。Xilinx的AXI 1G/2.5G Ethernet Subsystem确实是目前FPGA上最常用的以太网软核但网上的资料大多是单通道demo一旦涉及到多个光口、多个MAC共享物理收发器尤其是我今天要讲的这套主从级联Master-Slave Cascading玩法能查到的中文资料基本为零英文论坛上也是零零散散有人问没人答。这就是我写这篇文章的动机。大概三个月前我拿到一块Artix-7平台的板卡做四光口交换机原型验证板子上只有两对MGT参考时钟和数量有限的GTX收发器。如果用常规思路四个光口就需要四个独立的Ethernet Subsystem IP核每个独立核都要占用一组收发器通道同时还得为每个GMII接口布一堆管脚到PHY芯片或者光模块。算下来资源和PIN脚都吃紧尤其是板子上还挂了一片DDR3和一颗PCIe硬核GT资源已经被吃掉了一部分。后来我翻UG和PG手册才想到用主从级联的方式把两个Ethernet Subsystem绑在一组MGT上用一套共享收发器资源驱动两个MAC物理管脚从四个光口需要的四组SerDes收敛到两组。这个方案跑通之后板卡的面积和功耗都下来一大截整个项目组都松了口气。这篇文章就是围绕这套配置方法写的。适合已经用过单通道AXI 1G/2.5G Ethernet Subsystem、想在多端口场景下省资源/省管脚的工程师也适合正在做FPGA交换机和多端口网卡方案选型的朋友。我会把主从级联的配置步骤、共享收发器的地址映射逻辑、时钟复位拓扑、以及我在仿真和上板调试过程中踩到的坑全部拿出来讲每一处都尽量讲清楚“为什么这么配”而不是只扔给你一个配好的TCL脚本。1. 为什么多光口必须走级联从RGMII管脚噩梦到GT共享先聊一个容易被新手忽略的常识问题为什么一个独立运行的AXI 1G/2.5G Ethernet Subsystem无法在物理层面直接扛起多个光口答案在MAC和PHY之间的接口类型上。这个IP核常见的内部接口有GMII/RGMII和AXI4-Stream两种不管选哪一种当线速率大于1Gbps时传统的并行接口在FPGA的IO上会面临严重的时序收敛问题。尤其是RGMII在DDR模式下PCB走线等长、FPGA的IO delay校准、以及跨时钟域的同步逻辑每加一个端口工作量是线性增长的但时序余量是指数级恶化的。我在之前的项目里做过四路RGMII到后期布局布线跑下来时序违例一天比一天多简直是在跟工具搏斗。RGMII管脚消耗也很吓人。单路RGMII需要12根信号线TXD[3:0]、RXD[3:0]、TX_CTL、RX_CTL、TXC、RXC四路就是48根Artix-7的HR bank一次性就吃掉大半如果还要挂LVDS摄像头接口和调试串口IO资源立刻告急。而这些还只是MAC到外部PHY芯片的接口假如你的板卡是光模块直连FPGA根本不存在外部PHY那MAC就必须通过内部SerDes和光模块通信这意味着每个端口都需要一组高速收发器。四光口就是至少四组MGT芯片自带的那点GTX资源瞬间就没了还要考虑参考时钟管脚的复用和电源完整性。主从级联的出现正是为了解决这个问题。它的本质是让一个Ethernet Subsystem IP核内的两组MAC共享同一个Shielded GT通道组通过内部TRI_MODE_ETH_MAC也就是1G/2.5G可切换MAC的级联能力在物理层只使用一对差分收发器的情况下同时为两个MAC提供串行数据通路。这样四个光口只需两对MGT八个光口只需四对MGT参考时钟的消耗也从“每端口一个”压缩到“每两个MAC共享一个”。对于交换机这种需要大量端口的设备省出来的GT和时钟资源可以直接拿去扩展PCIe、DDR或者第二组数据通路整板成本下降不是一点半点。当然级联不是免费的午餐。它带来的代价是MAC层的独立控制逻辑要自己做比如每个MAC的使能、速率切换、流量统计都需要通过AXI-Lite寄存器来动态管理而不是像独立模式那样每个MAC有自己独立的物理接口。而且在软件驱动层面Linux下的驱动默认是“一个以太网子系统对应一个net_device”级联模式下你会看到两个MAC对应同一个物理设备节点驱动需要自己写mux逻辑。这些我会在后面章节里详细展开。2. 主从级联的整体架构与IP配置差异AXI 1G/2.5G Ethernet Subsystem在Vivado里的配置界面第一眼看上去有点像个迷宫。Shared Logic选项、MGT Settings、TRI Mode、地址映射……很多人看到就头大。但如果你理解了它的内部架构其实配置逻辑是非常清晰的。2.1 主IP与从IP的职责划分主从级联的方案里需要例化两个Ethernet Subsystem IP核如果你要支持4个光口就是两组这样的“主从对”两组之间各自独立不互相影响。其中一个是Master一个是Slave。它们的关系是这样的Master主核物理连接GTX/GTH收发器拥有PMA/PCS层实例负责和外部光模块完成链路建立link training和速率协商。它内部自带一个完整的TRI_MODE_ETH_MAC也可以把另一个MAC的PMA/PCS数据通过内部总线共享出来。Slave从核不例化GT只通过共享总线和Master交换串行数据。它内部没有PMA/PCS只有MAC和地址映射寄存器所有和物理层有关的状态link up、速率、CRC错误计数都要从Master的寄存器里读取。从应用角度讲Master更像是一个“物理层代理”Slave像是挂在代理后面的“逻辑终端”。我们在寄存器手册里看到的共享逻辑Shared Logic配置就是在定义谁拥有GT、谁只访问GT。2.2 Vivado界面里的关键配置项在Vivado中创建IP核时你一定要按这个顺序来配置。先配置Master IP选择“Shared Logic including GT”选项有些版本显示为“Shared Logic in core”这一项决定了IP会例化出一整套完整的GTX/GTH收发器逻辑包括MGT参考时钟的MMCM、复位和状态监测逻辑。内部接口选择“AXI4-Stream”或“GMII”取决于你的用户侧设计。如果后级是DMA引擎或者要做协议卸载走AXI-S主线更顺如果要对接MAC层定制逻辑选GMII更灵活。速度和PHY类型配置为“1G/2.5G Ethernet”可选模式不要选固定的1G SGMII这样后续才能用寄存器动态切换速率。再配置Slave IP选择“Shared Logic in core且不包含GT”或者直接选“Standalone in Core”选项下关闭GT例化实际写法是Shared Logic Options里设为“Include shared logic in core”但“GT instance”不被选中。其他设置和Master保持一致但不需要配置物理层参数。最后在IP例化时Master的某个输出总线比如gt_rx_data、gt_tx_data要连接到Slave的对应输入而不是各自外接MGT。这个连接通常通过IP的“mgt_rx_p”等端口完成——如果你配的是从核你会看到这类端口不见或被内部短路。这种配置差异很多人一开始容易配反。尤其是刚接触的人容易把两个IP都配成“Shared Logic in core”结果每个IP都试图例化一套GT不仅在布局时直接报错“too many GT instances”而且仿真时两个IP的复位信号互相打架。记住主从级联里GT只能有一个主人那就是Master。Slave老老实实不碰电平接口就行。2.3 为什么从IP的AXI-Lite寄存器仍然重要有人可能会问Slave没有GT那它到底做了什么答案是它负责把自己那一路MAC的独立寄存器空间暴露给软件。每个MAC都有自己的一组状态寄存器和控制寄存器包括PHY控制、包过滤、流控、MAC地址过滤等。即使物理层是共享的但MAC层的流量控制、VLAN过滤、统计计数都是独立维护的。级联后软件通过不同基地址访问Master和Slave的寄存器来实现对两个MAC口的管理。我在实际项目里就是在Linux驱动中为Master和Slave分别分配了独立的映射地址段然后用一个Mutex保护避免并发访问时串扰。这个处理方式在后面调试多口上网卡的时候特别重要后面会细讲。3. TRI/共享收发器的地址映射与寄存器配置最容易翻车的部分说真的如果主从级联配置里只能选一个最容易踩坑的环节我一定选地址映射Address Mapping和TRI模式的共享收发器寄存器配置。这一部分在UG和PG手册里写得极其晦涩仿真和上板出问题也基本都出在这里。3.1 TRI_MODE_ETH_MAC的地址偏移机制打开AXI 1G/2.5G Ethernet Subsystem的数据手册PG160你会看到关于“TRI_MODE_ETH_MAC”配置的复杂说明。TRI模式的意思是这个子系统可以在1GbpsSGMII或1000BASE-X和2.5Gbps2500BASE-X之间切换它是这个IP核的核心工作模式。在级联场景下TRI模式还有一个隐含功能内部有两个MAC物理通道一个。为了区分这两个MAC的寄存器空间地址映射字段就起作用了。每个MAC在AXI-Lite地址空间里占据一段偏移量例如Master MAC的收发控制寄存器位于偏移0x0000-0x03FFSlave MAC的收发控制寄存器位于偏移0x0400-0x07FF。共享MGT的配置寄存器被放在另一个共享区间有时由Master独占例如0x2000之后的空间。具体偏移要看版本不同Vivado版本的基地址可能不一样务必查询你本地的PG160生成文档。如果你只配置一个IP核软件读写这些偏移可能没感觉但在级联模式下一个IP核要同时管理两个MAC段的寄存器地址一旦映射错你测速时会发现两个口的统计计数全混在一起甚至出现“改A口的MAC地址B口也变了”的灵异现象。3.2 MGT共享配置的寄存器字段MGT共享配置寄存器里有两个字段我一直觉得大家应该刻在脑子里一个是“PHY Reset”的控制位另一个是“速率切换”字段Speed Selection。在级联模式下主从两个MAC的速率必须是相同的因为物理收发器只有一个线速率是全局的。比如你的光模块是千兆SFP那你两个MAC都必须配置成1G模式如果插的是2.5G模块两个MAC要切换成2.5G模式。软件在切换速率时需要做以下动作将两个MAC的接收/发送路径全部暂停通过各自的TX/RX Enable寄存器清零等待数据路径上有几个空闲周期确保没有在途数据写Master的共享MGT速率切换寄存器把PMA/PCS切换到目标速率等待MGT的复位完成状态寄存器置位重新使能两个MAC的收发路径。如果跳过第一步直接在跑流量的时候切速率大概率会遇到CRC错误、对齐丢失甚至MGT通道锁定失败的问题。我有一次在测试中就是没关tx/rx使能就切速率结果MGT的RX buffer overflow标志位直接被拉高之后整个通道进入了死锁状态必须冷启动板卡才恢复。3.3 包过滤与VLAN感知的逻辑归属在交换机场景下包过滤和VLAN处理是MAC层的重要功能。级联模式下每个MAC仍然有自己的VLAN过滤和地址表逻辑但这些逻辑都是独立于MGT运行的用户侧逻辑。也就是说物理层进来的帧先被Master的接收MAC解析然后被分发到不同的用户侧FIFO一部分走本地CPU一部分通过交换逻辑转发到其他端口。我这里特别提醒一点如果两个MAC口都使能了“VLAN Tag Aware”模式软件在初始化时必须为每个MAC单独设置VLAN ID不能复用。否则在交换场景下一个带Tag的广播帧会被两个MAC自身同时接收造成本地CPU出现重复报文交换机学习表也会被搞乱。4. 时钟与复位拓扑link不亮的隐性杀手搞过高速串行接口的人都知道时钟和复位是所有灵异问题的第一嫌疑对象。AXI 1G/2.5G Ethernet Subsystem的主从级联配置对时钟和复位的敏感程度比单核配置至少高一个量级。4.1 MGT参考时钟的共享规则主从级联下Master IP需要外部提供一对MGT参考时钟比如常见的125MHz用于1G SGMII或156.25MHz用于2.5G。这对时钟从MBUFG或GTREFCLK管脚进入芯片后会同时供给Master和Slave的PMA/PCS逻辑。Slave IP本身不需要也不能再外接参考时钟它只是从共享总线上拿到这个时钟信号。我在第一次配置时就是从IP的时钟端口把refclk同时接到了Master和Slave上结果上板后发现Slave的link始终起不来。后来查PG里关于时钟需求的描述才意识到从核的参考时钟输入在级联模式下应该保持悬空因为它用的是主核分发下来的内部时钟。两个IP都接入同一对物理参考时钟管脚会造成输入缓冲冲突和时钟偏斜。正确做法是物理MGT参考时钟只接入Master的GTREFCLK端口Slave的GTREFCLK端口保持未连接或者按IP生成的示例代码里的默认悬空处理如果在一个bank内的两对GT需要同时工作注意给每组主从对配置独立的参考时钟来源不要交叉使用MBUFG的同一个输出。4.2 复位信号的正确握手方式这个IP核的复位行为比较特殊它的复位信号是“高电平有效”并且需要满足释放时序。在级联模式下复位同步电路常常被设计成“Master复位完成后再释放Slave复位”的方式。也就是Slave的复位输入不是直接接外部复位按键或者CPU复位线而是接Master的reset_done信号。这样做的原因在于从核的PMA/PCS状态机和MGT逻辑状态机需要跟随主核的复位状态如果从核在主核尚未完成GT初始化之前就开始工作它去读MGT状态寄存器拿到的是垃圾值后续所有状态判断全会乱掉。在Vivado的Block Design里我用了一个AXI-4 GPIO IP外加几行Verilog逻辑来完成这个时序外部复位信号先对Master IP复位Master IP的reset_done输出作为Slave IP的外部复位输入Slave IP的reset_done作为整个子系统可以开始收发的总复位完成标志。这样三级串联的复位树上板一次就link up了比费力去调外部的毛刺滤波和延时值靠谱得多。4.3 缓存的时钟域交叉如果你在用户侧使用的是AXI4-Stream接口需要特别注意跨时钟域的FIFO深度。级联模式下Master和Slave的发送/接收FIFO数据速率会有细微差异比如Master走的是MGT提供的125MHz而Slave的MAC可能因为内部资源共享稍有一两个周期的偏斜。这种微小偏斜虽然不影响长期平均吞吐但会造成FIFO的偶尔上溢/下溢。我在测试时设计好把收发FIFO的深度都设置为至少512字data width 64确保极端突发帧比如超长巨型帧9KB也能顺畅通过。5. 仿真验证阶段不让demo工程坑上板的细节很多人觉得仿真这种事情只要工程能跑出波形就万事大吉了。但级联配置的仿真有一个很坑的地方Vivado生成的example design是按照“每IP独立的GT”来搭建的不是级联模式的。你如果偷懒直接用example design的行为模型去跑仿真根本验证不了级联逻辑。5.1 必须自己搭主从间的数据环回在级联配置下TCP/IP协议栈的验证需要完整回环路径。我的做法是在testbench里把两个Ethernet Subsystem的GMII接口或AXI-S接口都接到自己的回环FIFO上但数据通路需要从Master的发送端ring到Slave的接收端再从Slave的发送端ring回Master的接收端。这样仿真才能模拟数据在两个MAC口之间的真实流转。如果只是做单向环回得到的结果没有任何意义——因为你在实际板卡上要跑的是双MAC之间的交换不是单个MAC的自收自发。5.2 GMII包格式的参考模板在仿真里产生以太网帧时很多人喜欢从网上抄一个简单的帧格式但往往忘了CRC。AXI 1G/2.5G Ethernet Subsystem支持MAC层自动生成CRC但你的testbench也要设置好“CRC pass through”和“FCS check enable”这两个选项。我的建议是不要让testbench产生CRC直接置0填充靠IP核自动补全这样波形上的包更容易看清因为数据长度固定为64字节以上。仿真中用到的关键时序参数我也建议按下面这个表来设置避免出现因为testbench时序不标准导致的IP核内部超时参数推荐值说明GMII时钟频率125MHz1Gbps模式帧间空隙IFG96 bit time最小标准值前导码帧头8字节7字节前导1字节SFD最小帧长64字节不含CRC最大帧长1522字节含VLAN Tag5.3 寄存器级别的行为仿真不可忽略除了数据通路寄存器访问也要在仿真里覆盖。主从级联的寄存器访问跨越两个IP核但软件是透过同一个AXI-Lite接口来访问的。仿真时一定要验证以下操作通过AXI-Lite读取Master的PHY status寄存器确认link状态读取Slave的MAC控制寄存器确认它已经退出复位向Master写速率切换寄存器同时读两个MAC的速率状态字段确认同步更新。如果这些场景不仿真上板后你写驱动时基本就是“盲人摸象”一个字段一个字段地试特别浪费时间。6. 上板调试经验link up之后真正的战斗很多人以为仿真通过之后上板调试就是水到渠成的事。实际上仿真和上板之间的差异就像游泳池和大海。真到单板上你才会遇到我接下来要讲的这些神坑。6.1 现象一个口link up另一个口死活不亮我遇到的最常见的故障现象就是两个级联MAC口Master口与对端交换机正常协商并link up但从Slave口插上光模块无论怎么插拔光模块链路就是起不来。排查第一步我先用ILA抓了Slave的link状态寄存器和MGT RX状态寄存器发现MAC层的接收状态机一直停在“等待对齐”状态。然后我对比了Master和Slave的寄存器值发现Slave的“MGT PCS reset done”标志从未置位。说明Slave的PCS一直没完成复位问题出在复位链路上。我检查了Block Design果然发现我把外部复位信号同时接到了Master和Slave的复位端口上而没有给两者复位留出等待时间。修正成前面说的“Master reset_done → Slave复位”之后Slave的link马上就亮了。这个坑提醒大家级联模式下复位链路的正确性比任何寄存器配置都优先。6.2 现象link有但ping不通第二个坑是link已经up但电脑或交换机端一直ping不通FPGA的IP。这种情况多半出在MAC地址和包过滤配置上。在级联模式里两个MAC口都在同一块物理板卡上如果你给两个MAC配置了相同的MAC地址交换机的CAM表只会把流量送到其中一个端口因为交换机认为同一个MAC地址只能出现在一个物理端口上。解决办法就是给每个MAC口分配不同的MAC地址并且软件初始化时把它们写入各自的MAC地址寄存器。这一点和在独立网卡上的习惯不同很多人第一次搞就会踩雷。另外由于两个MAC共享同一个物理MGTIP核对入站PAUSE帧的处理会同时作用于两个口如果软件没有正确配置流控策略有可能导致一侧收到反压后另一侧的流量出不去。建议初期调试时把两边的流控全部关掉等基本转发正常后再一条一条打开。6.3 现象速率切换后丢包率高到离谱在之前的测试中我从1G模式切换到2.5G模式后跑iperf发现丢包率一下子到了30%以上。查了半天发现问题是切换速率后两个MAC的TX/RX FIFO深度发生了变化但软件没有把所有相关寄存器重新配置一遍。速率切换时不仅MGT的时钟频率变了MAC层的IPG帧间距参数、随机数种子、以及FIFO的中断阈值都需要重新赋值。尤其要注意“TX PAUSE quanta”这个字段它在1G和2.5G模式下的默认值是不同的需要按新速率重新计算。我后来在Linux驱动里加了一个完整的速率切换函数执行顺序是保存当前MAC设置 → 关收/发使能 → 置位MGT速率切换 → 轮询link状态寄存器 → 依次恢复MAC的IPG、PAUSE和FIFO阈值 → 重新打开收发使能。这样切换之后跑iperf的丢包率终于下降到了万分之一的级别基本验证可行。6.4 多主从对并行时的全局一致性当你扩展到一个四光口交换机也就是两组主从级联同时工作时还有一个容易忽视的问题两组的速率切换必须同步执行。否则就会出现“前两个口工作在1G后两个口工作在2.5G”的混合状态这对交换机的背板交换逻辑是个灾难因为不同端口的速率不同中间需要速率匹配缓冲这会让MAC层的时序变得极其复杂。我的做法是在软件里用一个互斥体Mutex把两组的速率切换包在一起要么全部切1G要么全部切2.5G。只有当所有端口都确认完成速率切换后才允许用户态重新打开网络接口。这个“全局同步”思路对我们这种做原型验证的板卡已经够用如果是正式产品更推荐在硬件设计时直接用QSGMII或者用多通道SGMII聚合从根上避免速率不一致的问题但那已经是另一个话题了。7. 一些额外的心得与建议关于主从级联配置我最后再补充几个自己摸索出来的小经验看起来不起眼但关键时刻能帮你省下两三天。第一时钟结构一定要尽早确定。我在项目初期偷懒想着反正主从级联不影响时钟拓扑就在综合之后才去检查参考时钟结果发现需要额外引入一个BUFG来分发时钟布局工具直接抱怨时钟资源不够最后不得不推翻重来。这个IP的时钟资源规划最好在创建Block Design时就画好尤其是多个bank同时使用GT时要提前确认每个bank的GTREFCLK管脚编号。第二共享逻辑的Debug要利用“gt_loopback”功能。不用花里胡哨的外部回环线缆IP核内建了“PCS loopback”和“PMA loopback”寄存器位上板前先在回环模式下跑通FIFO和MAC层逻辑再切换到“normal mode”接外部光模块。这样能快速区分问题出在物理层还是MAC层调试效率能提升一大截。第三ILA采样点要放对位置。建议在AXI4-Stream总线的TDATA和TVALID上挂ILA而不是全部挂在GMII并行总线上因为并行总线信号太多ILA深度很快被占满。如果你想看MGT的关键状态可以直接监测用户侧提取出来的“link_up”和“rx_error”这两个综合信号不用去抓IP核内部寄存器减少组合逻辑对触发条件的干扰。我在这次四光口交换机原型的整个调试过程中最大的感受就是——主从级联这个功能设计得相当巧妙只要你理解了它的本质是“物理层单通道逻辑层双MAC复用”后面所有配置和调试都有章可循。尤其是对于资源有限的板卡这个方案能让你在不大幅改动硬件的前提下把可用网口数量翻倍对原型验证来说简直是一个免费的福利。但也要提醒一句越底层的复用逻辑对驱动和软件的协同要求就越高与纯硬件工程师合作时一定要在项目一开始就把寄存器映射表和复位时序图定义清楚不然后期扯皮会非常痛苦。如果这篇文章能让你少走一两条弯路那就是值得的。希望手里的光口板卡早日link up。
返回列表