ARTICLE DETAIL

资讯详情

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

AXI 1G/2.5G以太网IP核参数配置与上板调试避坑

AXI 1G/2.5G以太网IP核参数配置与上板调试避坑 1. 先搞清楚这颗核在你的板子上到底扮演什么角色AXI 1G/2.5G Ethernet Subsystem 这个 IP 核是很多人做 FPGA 网络通信时绕不开的一站。它把 1G/2.5G 以太网的 MAC、可选的 PCS/PMA、AXI4-Stream 数据接口和 AXI4-Lite 寄存器接口打包成一个可配置的软核挂在 AXI 总线上上位机或软核处理器写几个寄存器就能收发以太网帧。听起来很省事但真正上手的人多半都经历过同一个阶段IP 核生成出来综合布线全过上板一测链路起不来或者能通但丢包丢得莫名其妙。折腾半天发现问题不在代码而在生成 IP 时那几个下拉框选错了。参数配置这件事之所以让人头疼是因为它不是孤立的一步。Physical Interface 选什么直接决定参考时钟要多少兆参考时钟错了GT 就没法锁定GT 锁不住MDIO 读不到 PHY 的 ID后面寄存器怎么配都是白搭。几个选项之间是环环相扣的任何一环选错现象都表现为网络不通你很难一眼看出是哪一环出的问题。所以这篇内容不打散仗我按先定位角色、再逐页拆参数、最后上板排错的顺序把这条链路从头到尾捋一遍。内容适合三类人看一是第一次用这颗核、还在对着配置向导逐项犹豫的二是已经能通但想搞清楚每个参数为什么这么选的三是遇到具体故障想快速定位的。代码示例我用 C 和 Verilog 为主也会给一段 Vivado 的 Tcl方便你把配置脚本化。所有寄存器名和参数名都以你本地 IP 版本的文档表格和头文件为准我在关键处会提醒你怎么自己核对一遍这比背我的数字可靠得多。1.1 MAC 模式还是 PCS/PMA 模式这是第一个必须走对的岔路口这颗核最核心的一个分裂点就是它到底要不要接管高速串行部分。你可以把它当成一个纯 MAC 用外面自己接一颗 RGMII 或 GMII 的 PHY 芯片PHY 负责把并行的 GMII 信号变成模拟的网口信号中间所有 SerDes、编码、时钟恢复的活都是 PHY 干的。这种用法最简单IP 侧只需要一组发送时钟和接收时钟加上几个数据和控制信号时序也相对宽松。绝大多数用开发板自带网口的场景选的就是这条路。另一条路是让 IP 把 PCS/PMA 也一起做了也就是 SGMII 或 1000BASE-X 模式。这时候 IP 直接输出高速差分串行信号速率为 1.25 Gbps1G或 3.125 Gbps2.5G经过 8b/10b 编码可以接 SFP 光模块也可以接一颗 SGMII 的 PHY 芯片的串行侧。走这条路你必须在 IP 里选上 GT 收发器并且提供正确的参考时钟整个设计的时钟结构会复杂不少但也省掉了外部 PHY 的并口走线和时序约束。我个人判断的标准很直白板上已经有现成的 RJ45 网口连着 PHY而 PHY 到 FPGA 之间走的是 RGMII/GMII那就选 MAC 模式板上有 SFP 笼子、或者你的 PHY 是 SGMII 接口的比如常见的 Marvell 系列配置成 SGMII 模式那就走 SGMII 模式。选错的话波形上根本看不到任何东西因为一边在等并行数据另一边在等串行码流鸡同鸭讲。提示如果你不确定板子上 PHY 的接口类型去看原理图上 PHY 和 FPGA 之间的连线数量。4 根数据线加 1 根时钟一般是 RGMII8 根数据线是 GMII只有一对或两对差分线那就是串行接口。1.2 2.5G 到底值不值得上2.5G 模式是个很诱人的选项尤其是做数据采集或者图像传输的时候带宽直接翻 1.5 倍。但它有几个现实约束值得先算一笔账。首先2.5G 只能走 GT 的串行路径也就是必须选 SGMII 或 1000BASE-X 类的物理接口纯 RGMII 是做不到 2.5G 的。其次你的对端设备要支持 2.5G普通千兆交换机是不认的接上去链路会协商到 1G 甚至协商失败。第三2.5G 的 GT 参考时钟通常是 312.5 MHz这个频率在板上不一定有现成的时钟源可能需要额外加一颗晶振或者用时钟芯片产生。还有个容易被忽略的点2.5G 的 SGMII 内部速率协商机制和 1G 不完全一样某些 PHY 芯片的寄存器默认配置下会把 2.5G 关掉得手动打开。我在一个项目里就踩过这个坑IP 侧明明选了 2.5G链路死活起不来最后查出来是 PHY 的扩展寄存器里 2.5G 能力位没使能MDIO 写一下就通了。所以上 2.5G 之前先把 PHY 的数据手册翻到速率能力那一页确认它的寄存器默认值是什么心里有底再动手。2. 生成 IP 时的参数怎么选逐页拆给你看打开配置向导参数页其实就那么几页但每一页都有几个决定性的选项。我按实际影响大小排序讲把最容易选错的放前面。2.1 Physical Interface选错这一项后面全白搭配置向导第一页通常就是物理接口类型。可选项一般包括 MII、GMII、RGMII、SGMII、1000BASE-X 这几类。它们对应的场景差别很大我整理成一张表对比你对着自己的板子挑。接口类型数据形式典型速率参考时钟适用场景MII4 位并行25/2.5 MHz10/100M25 MHz老式 PHY低速率GMII8 位并行125 MHz1G125 MHz带 GMII 的 PHYRGMII4 位 DDR125 MHz10/100/1000M125 MHz最常见的开发板网口SGMII串行差分1.25/3.125 Gbps1G/2.5G125/312.5 MHzSFP 模块或 SGMII PHY1000BASE-X串行差分1.25 Gbps1G125 MHz光模块直连、背板选完接口类型之后向导里会出现配套的选项。比如选了 SGMII它就会问你用不用 GT以及线速率是 1G 还是 2.5G。选了 RGMII它会问你需不需要内部延迟有些 PHY 需要 RXC 上做 2ns 延迟补偿有些不需要这个一定要看 PHY 手册做错了接收侧会采到眼图边缘。2.2 SGMII 和 1000BASE-X 长得像用起来完全不是一回事这两个选项在配置向导里挨着很多人随手选了。但它们的协议层差别不小。1000BASE-X 是纯粹的光纤以太网物理层只有 1G 一个速率链路建立靠的是 8b/10b 的同步和 IDLE 码流没有速率协商这一说。SGMII 则是在 MAC 和 PHY 之间的接口协议它带了一套自协商机制可以在 10M、100M、1G 之间切换速率所以它的数据流里会周期性插入控制字来传递速率信息。踩坑的重灾区就在这里如果你接的是 SFP 光模块对端是交换机光口那应该选 1000BASE-X如果你接的是一颗 SGMII 的 PHY 芯片它的另一侧接 RJ45那应该选 SGMII。两者的 8b/10b 编码是一样的电气上也基本兼容但协议层的控制字不一样混用的话现象是链路能够亮起来因为比特同步能建立但数据帧进不去出不来抓波形能看到码流但抓不到有效帧。这个现象特别迷惑人因为你会以为链路已经通了。还有一个细节SGMII 模式下 IP 会自动提供 MDIO 接口用于配置对端 PHY。1000BASE-X 模式一般不需要 MDIO因为光模块没什么可配的。所以如果你发现 IP 没有给出 MDIO 管脚回头看看物理接口是不是选成了 1000BASE-X。2.3 时钟这一页先做除法再做选择时钟配置是整颗核里最需要动笔算的地方。核心原则是GT 的参考时钟要和线速率整除出合适的倍频关系。1G 的 SGMII 线速率是 1.25 Gbps8b/10b 编码意味着内部时钟是 1.25 GHz用 CPLL 的 ×10 模式需要 125 MHz 参考时钟2.5G 的线速率是 3.125 Gbps内部 3.125 GHz可以用 312.5 MHz 的 ×10也可以用 156.25 MHz 的 ×20具体哪个可用取决于你选的 GT 型号和它的 PLL 分频范围。AXI4-Stream 侧的时钟是独立的可以选择与 GT 时钟同源也可以完全异步IP 内部有异步 FIFO 做跨时钟域。这里有个算术1 Gbps 的有效载荷如果数据位宽是 8 位就需要 125 MHz 的时钟如果位宽是 32 位理论最低只要 31.25 MHz但考虑到帧间隔和握手开销实际会留一些余量跑 40 到 50 MHz 比较舒服。位宽越宽时钟压力越小但消耗的逻辑资源越多布线也越难。我一般 1G 场景用 8 位或 16 位2.5G 场景用 32 位这是比较平衡的选择。AXI4-Lite 寄存器时钟又可以是另一个独立时钟常见 50 MHz 或 100 MHz跟数据通路完全无关。很多人在这一页偷懒把三个时钟都接成同一个如果频率差得多时序会很难收敛尤其是 GT 时钟那个 312.5 MHz 带一堆高速逻辑压到布线器喘不过气。我的做法是让 GT 时钟只驱动 GT 相关逻辑数据通路用一个相对低的时钟寄存器接口再单独一个各自约束各的收敛起来轻松很多。2.4 Shared Logic 放在核里还是放在示例工程里这个选项叫 Shared Logic本质上是把 GT 的公共资源比如 QPLL、复位控制器、时钟缓冲放在哪个层次。单核设计直接选放在核里就行IP 内部自己搞定。但如果你一个 FPGA 里要实例化多个以太网核共享同一组 GT那就得选放在示例工程里然后手动把这部分公共逻辑提到顶层多个核去复用它。选错了会导致资源重复例化或者在综合时报 GT 资源冲突。多核场景建议先例化一个核的示例工程看看共享逻辑长什么样再照葫芦画瓢往上提。用 Tcl 批量配置的时候你可以先把这一页的参数 dump 出来看看真实名字report_property [get_ips axi_ethernet_0]输出里带CONFIG.前缀的那些就是可配置属性。常见的有物理接口类型、线速率、是否包含 GT、共享逻辑位置、数据位宽、地址宽度等等。拿到准确名字之后再写脚本比如set_property -dict [list \ CONFIG.C_PHY_TYPE {SGMII} \ CONFIG.C_LINE_RATE {1} \ CONFIG.C_INCLUDE_SHARED_LOGIC {1} \ ] [get_ips axi_ethernet_0]注意属性名和取值范围在不同 IP 版本之间会有变化尤其大版本升级时。脚本化配置之前先在图形界面里配一遍然后把属性导出来对比别直接抄别人的脚本。3. AXI4-Stream 数据通路的几个关键细节IP 生成出来之后你会看到两组 AXI4-Stream发送TX和接收RX。这两组接口的时序规则和边带信号是写 RTL 时最容易出问题的地方。3.1 tvalid 和 tready 的握手规则别自己发明AXI4-Stream 的握手规则很简单但违反它的方式五花八门。核心两条发送侧拉高 tvalid 之后必须等 tready 拉高才能改变数据或者撤销 tvalid中间不允许反悔接收侧拉 tready 的时机没有限制可以一直拉高也可以等 tvalid 拉高再拉。违反第一条的典型写法是用 tready 去做 tvalid 的组合逻辑输入比如tvalid 要等 tready 来了才拉高这在功能仿真里可能看不出问题因为仿真里 tready 很快就来了但一旦下游出现背压整个链路就会死锁。我见过更隐蔽的一种有人在 tlast 那一拍上做了特殊处理等 tready 来了才拉 tlast结果帧的最后一个数据被吞掉了。正确做法是 tlast 和最后一个数据的 tvalid 在同一拍拉高它们是一体的不能拆开。写完之后一定要跑一个带随机背压的仿真把 tready 随机拉低几拍看看数据有没有丢、帧尾有没有错位。这个测试花不了多少时间能省掉上板后几天的抓瞎。还有一种情况是跨时钟域的握手。当发送逻辑的时钟和 IP 的 AXI4-Stream 时钟不同源时你得自己加异步 FIFO。这里要注意 FIFO 的深度和 nearly_full 阈值的设置阈值留得太小上游还在发数据FIFO 就满了只能靠反压硬顶吞吐会掉得很难看留得太大又容易溢出。我的经验是阈值设在深度的 3/4 左右配合上游一个足够快的响应机制。3.2 tuser 携带的边带信息每次都要核对位定义AXI4-Stream 上的 tuser 信号承载的是帧级别的边带信息比如这一帧是好帧还是坏帧、有没有错误标志、是不是需要特殊处理。问题是这个信号的位定义跟数据位宽强相关8 位数据宽度下 tuser 可能只有 1 位32 位数据宽度下可能有 4 位甚至更多而且每个版本的定义细节都可能调整。所以我的建议是不要凭记忆写 RTL。打开你本地 IP 版本的文档翻到 AXI4-Stream 接口信号那一页把 tuser 的位定义抄下来然后在仿真里抓一次波形实际发一帧好帧和一帧坏帧看看 tuser 的变化是否符合预期。这一步花十分钟能避免后面因为误判帧状态而丢掉大量正常数据。特别是接收侧如果你把坏帧的标识位搞反了要么把错帧当对的往上送要么把对的全扔了两种都很难查。3.3 背压场景下的缓冲设计背压在这条通路上是常态尤其是接收方向。以太网帧到达的节奏是不确定的而你的上层处理逻辑可能有时快有时慢中间必须有个缓冲区。缓冲放在哪里、放多深直接决定了丢包率。如果放在 AXI4-Stream 接口之后那么 IP 内部收到帧之后会立刻往上推你来不及取它就丢了如果 IP 允许在内部 FIFO 加深度那就把深度调大一些给上层争取反应时间。一个实用的办法是给接收通路加一级大容量 FIFO深度按你的最坏处理延迟来估算。假设你的处理逻辑最慢要 10 微秒才能取一帧而以太网满速到达的帧间隔是 12 字节时间1G 下大约 0.1 微秒那你的 FIFO 至少要能存下 100 帧的突发量按每帧 1.5 KB 算是 150 KB 左右。这个数字听起来吓人但如果用片内 BRAM 实现实际占用的块数是可以接受的。当然更聪明的做法是提高处理速度或者用流控机制让对端慢点发这就涉及到后面要讲的流控寄存器配置。4. AXI4-Lite 寄存器配置的实操要点数据通路通了之后很多功能要靠寄存器来打开或调整。这一部分是纯软件活但名字和地址对不上就白干。4.1 地址空间的划分这颗核的 AXI4-Lite 空间一般分成几块MAC 配置寄存器、统计计数器、以及可选的附加功能寄存器比如时间戳、VLAN 过滤表。MAC 配置寄存器在低地址段统计计数器在另一段具体偏移量一定要以你所用版本的文档为准因为不同版本做过调整。在驱动代码里我习惯用头文件里的宏名而不是硬编码地址。Xilinx 提供的驱动里有类似XAE_前缀的偏移量定义直接引用它们比你自己算偏移安全得多。如果你用的是裸机环境没有现成驱动那就自己定义一份/* 偏移量请以本地版本的寄存器手册为准这里仅示意命名方式 */ #define XAE_MAC_CONFIG_OFFSET 0x00000000u #define XAE_TX_CONFIG_OFFSET 0x00000008u #define XAE_FLOW_CTRL_OFFSET 0x0000000Cu #define XAE_RX_CONFIG_OFFSET 0x00000010u static inline void ae_write32(uintptr_t base, uint32_t off, uint32_t val) { *(volatile uint32_t *)(base off) val; } static inline uint32_t ae_read32(uintptr_t base, uint32_t off) { return *(volatile uint32_t *)(base off); }读写都要用volatile否则编译器优化可能把连续两次写合并掉或者把读缓存起来你会看到寄存器行为完全不符合预期。4.2 几个上电后必配的寄存器上电之后有几件事基本是每次都要做的。第一是复位释放顺序GT 的复位和 MAC 的复位是有先后依赖的先放 GT 相关复位、等 GT 锁定、再放 MAC 复位顺序反了 MAC 可能一直处于异常状态。第二是使能发送和接收有些版本默认是关闭的得手动打开。第三是配置流控决定收到拥塞时是丢包还是发暂停帧。流控这块值得多说两句。暂停帧Pause Frame机制是让对端在你处理不过来的时候暂时停发避免丢包。但它要求对端也支持并且打开这个功能如果对端是个不认暂停帧的设备你发了也没用。另外暂停帧有全双工和半双工两种模式半双工下的背压机制是搞出冲突让对端退避效率很低现在基本不用了。配上流控之后还要设置好触发阈值也就是你的接收 FIFO 用到什么程度开始发暂停帧这个阈值要和你 FIFO 的实际深度匹配。4.3 地址过滤、VLAN 和多播的处理默认情况下MAC 只接收目的地址是自己的单播帧、广播帧和它订阅的多播帧其他帧直接丢掉。这个过滤表可以通过寄存器配置。做协议测试或者抓包分析的时候经常需要打开混杂模式让它把所有帧都收上来这时候要注意上层软件得自己判断帧的归属否则会收到一堆别的设备的流量。VLAN 的处理分两种情况如果你的应用需要识别 VLAN 标签那就打开 VLAN 使能让 MAC 把标签透传上来你在软件里解析如果不需要那就让它过滤掉带标签的帧省得干扰。这里有个细节打开 VLAN 透传之后帧的长度会多 4 个字节你的缓冲区大小和长度判断逻辑要相应调整否则会莫名其妙截断。提示切换过滤模式之后最好把统计计数器清零再开始测不然新旧数据混在一起你分不清丢包是新配置造成的还是切换过程中的正常抖动。4.4 统计计数器怎么用才不浪费IP 内部带了一组统计计数器能告诉你收到了多少帧、多少字节、有多少 CRC 错误、多少丢包。这些数据是做性能分析和故障定位的金矿但很多人配完就忘了。我的用法是在关键节点比如压力测试开始、配置切换之后定时读一次快照做差值得出这一段时间的增量再算丢包率。直接读绝对值意义不大因为计数器是累积的。有一点要留意计数器本身也可能溢出尤其是字节计数器位宽有限高速跑久了会绕回。做长时间测试的话要么定期清零要么在软件里做溢出检测和累积。还有某些计数器在链路重新协商或者复位时会被清零测试过程中如果链路抖动过数据就断了得重来。5. 上板调试按这个顺序查少走冤枉路链路不通的时候最忌讳东一榔头西一棒子。按层次从下往上查能最快定位问题在哪一层。5.1 链路起不来从物理层开始逐级往上第一步看 GT 有没有锁定。如果你用了 GT先确认参考时钟频率和相位都对用示波器或者芯片内部的时钟监测功能看一下有没有时钟。GT 没锁后面全是白搭。第二步看 8b/10b 同步有没有建立通常有状态位可以读或者有信号可以引到 LED 上。如果同步建立不了检查线速率配置和参考时钟是否匹配这是最常见的错配点。第三步是 MDIO 能不能读到 PHY 的 ID。读不到说明 MDIO 的时钟分频、PHY 地址或者电气连接有问题。PHY 地址在硬件上是由几个引脚拉高拉低决定的原理图上写着 0 到 31 之间的某个值配置错了就读不到。第四步看自协商有没有完成SGMII 模式下自协商结果会反映在 PHY 的寄存器里读出来看看协商到了什么速率和你期望的是否一致。第五步才是看 MAC 层有没有收到帧。这个顺序的核心逻辑是每一层都依赖下面一层正常工作跳过任何一层去查上面都会得到误导性的结论。我见过有人链路起不来直接去查 IP 的寄存器配置折腾了一整天最后发现是参考时钟的晶振没焊。5.2 能通但丢包问题通常在缓冲和时钟链路能通说明物理层和协议层都没问题丢包一般出在数据通路或者时钟约束上。先看统计计数器的丢包计数区分是接收侧丢的还是发送侧丢的。接收侧丢包大概率是 FIFO 溢出要么加深 FIFO 要么开启流控发送侧丢包可能是上游给的帧本身就有问题或者发送 FIFO 欠载underrun后者常见于上游数据供给不稳定需要加缓冲。时钟问题表现得更隐蔽通常是间歇性的错误跑几分钟出一次或者温度变化的时候才出现。这类问题要重点检查时序约束有没有覆盖到跨时钟域的所有路径尤其是 IP 内部的异步 FIFO 边界和 GT 相关的时钟。缺约束的话布线工具会按默认方式处理能不能跑通全看运气跑通了也可能在不同批次的板子上表现不一样。5.3 常见问题速查表现象可能原因排查动作GT 不锁定参考时钟频率不对或缺失测时钟频率核对线速率与参考时钟的倍频关系8b/10b 不同步线速率配置与实际不符检查 IP 里的速率设置与对端是否一致MDIO 读不到 PHYPHY 地址错、时钟分频过大核对原理图上的地址引脚降低 MDIO 时钟链路亮但不通SGMII 与 1000BASE-X 选反确认对端是 PHY 还是光模块改物理接口类型收不到任何帧MAC 收发未使能、过滤表过严读配置寄存器临时打开混杂模式验证大量丢包FIFO 溢出、背压响应慢看统计计数器加深缓冲或开流控间歇性错误时序约束缺失、跨时钟域处理不当补全约束跑随机背压仿真复现帧长度被截断VLAN 透传后长度判断未更新检查缓冲区大小与长度阈值配置这张表我建议打印出来贴在工位上遇到问题先对一遍比重新翻文档快得多。当然表里的原因不是穷举但覆盖了八成以上的常见故障。6. 几个我踩过之后才记住的点最后说几个不太容易从文档里读出来、但实际很影响效率的经验。第一个是仿真环境里先把背压测透再上板。IP 的示例工程提供的仿真激励通常是很理想的流tready 一直高数据一路畅通跑通了不代表实际能用。我在自己的测试平台里加了一个随机拉低 tready 的模块还有随机插入错误的帧跑几万帧不出问题心里才踏实。这个改动不到五十行代码回报率极高。第二个是版本升级要重新核对参数。IP 大版本升级的时候配置向导的默认值和选项会有变化原来能跑的配置搬到新版本可能就不对了。我做过的项目里从旧版本迁到新版本之后最常出问题的是时钟相关的默认值你不动它它悄悄改了默认结果就是链路起不来。所以升级之后别急着改代码先把配置向导每一项跟旧版本对比一遍。第三个是善用内部逻辑分析仪抓内部信号。很多人只抓外部引脚其实 AXI4-Stream 上的 tvalid、tready、tlast 和几个状态位引出来抓一次问题的定位效率会高一个数量级。抓的时候设置触发条件为连续多少拍 tvalid 高但 tready 低一下就能看出背压卡在哪里。第四个是把配置过程脚本化。以太网相关的参数项多手工点容易漏。我用 Tcl 把整套配置写下来跟着工程一起进版本管理换机器、重新生成工程、交付给同事一条命令就能复现同样的配置。这个习惯在多人协作的项目里价值特别大能避免在我机器上能跑这种经典扯皮。这套核本身的设计是成熟的绝大多数问题都出在配置和用法上而不是 IP 本身有 bug。把每一层的关系想清楚把参数和时钟的算术做对剩下的就是按部就班地验证。真遇到卡住的地方退回到最底层从时钟和复位开始重新检查一遍往往比在高层乱猜要快。
返回列表