☰
FPGA千兆光通信中Tri Mode Ethernet MAC IP核的配置与调试要点
2026/10/7 1:35:23 网站建设 项目流程

说明:这篇是本系列的第四篇,前三篇分别讲了 UDP 协议栈拆解、千兆光通信链路预算、以及 SGMII 与 PHY 芯片对接的要点。今天集中把 Tri Mode Ethernet MAC IP 核从配置到上板调试的完整链路梳理一遍,都是自己踩过坑之后留下的记录。

先说清楚这个 IP 核到底在整套系统里干哪一层的活。你写好的 UDP 报文(准确说是 IP 报文)从用户逻辑出来之后,Tri Mode Ethernet MAC 负责把报文封装成符合 IEEE 802.3 标准的以太网帧:补上前导码、帧起始定界符、MAC 地址、类型/长度字段,最后追加 CRC 校验,然后把数据一位一位地推给 PHY 芯片。在千兆光通信场景下,PHY 通常是 SFP 光模块内部自带的 SerDes,链路一端的 FPGA 通过 MAC 核把数据送到光模块,另一端再收回来,整个收发闭环就是从 MAC 核的用户侧接口开始的。

如果你已经是第二次、第三次做以太网通信,这个 IP 核的难点其实不在 IP 核本身,而在三件事:接口选型、复位时序、以及用户侧 FIFO 的读写水位控制。这三件事处理好了,后面调试基本一路顺风;处理不好,你会看到光口 link 正常、ARP 能通、但 UDP 大量丢包,或者干脆收不到任何数据。

这个项目我用的是 Xilinx 7 系列 FPGA,Vivado 里的 Tri Mode Ethernet MAC IP 核版本是 4.5 左右(不同版本界面略有差异,但关键配置项一致)。下面的内容全部基于千兆 SGMII + SFP 光模块的典型用法,如果你用的是 GMII/RGMII 的板载 PHY,也有参考价值,因为 MAC 核的用户侧接口是完全一样的。

1. 配置 IP 核时的几个关键决策点

1.1 接口选型先要想清楚:GMII、RGMII 还是 SGMII

Tri Mode Ethernet MAC 这个名字里的“Tri Mode”指的是 10/100/1000 Mbps 三速自适应能力。但速度只是其中一个维度,更关键的是 MAC 核怎么和 PHY 打交道,也就是物理接口类型。

接口类型数据位宽时钟频率引脚数量适用场景
GMII8 bit125 MHz约 24 根板内短距离走线,调试方便
RGMII4 bit125 MHz DDR约 12 根低成本板卡,走线少
SGMII1 bit 串行1.25 Gbps约 4 根光模块、高速背板,与 SFP 直接对接
1000BASE-X1 bit 串行1.25 Gbps约 4 根纯光口模式,不带自协商管理

这里有个特别容易迷糊的地方:SGMII 和 1000BASE-X。这两个物理层都是 1.25G 串行,也都是接到 SFP 光模块的,但协议有区别。SGMII 是 MAC 和 PHY 之间的接口标准,专门传输 MAC 数据帧外加链路状态协商信息;1000BASE-X 是直接定义了光口上的物理层编码方式(8B/10B)。实际使用的时候,Xilinx 的 MAC 核里面通常会有选项让你选 SGMII 还是 1000BASE-X,或者干脆让你配合外部 SGMII IP 核一起用。

我做光通信项目时用的方案是「Tri Mode Ethernet MAC IP 核内部配置成 SGMII MAC 模式」,外部再接一个独立的 SGMII IP 核,由它完成 8B/10B 编解码和串行化。这实际上就是 Xilinx 官方推荐的 SGMII 解决方案:MAC 核 + SGMII IP 核组合。一定要注意,这个组合里的 SGMII IP 核必须配置成 MAC 模式,换句话说它当成 PHY 侧的物理编码子层,而不是当成独立的 MAC。如果配错成 PHY 模式,它内部会再做一层 MAC 封装,数据直接乱套,表现就是光口能 link 上、但抓包全是坏帧。

如果你的板子上光模块是通过 GTX 高速收发器直连 FPGA,同样走 SGMII 方案。GTX 通道的角色是给 SGMII 提供 1.25G 串行通道,物理层(PCS/PMA)逻辑仍然由 SGMII IP 核或者 MAC 核内的 PCS/PMA 子模块完成。

1.2 三速自适应和固定千兆,我劝你根据场景做减法

Tri Mode 有核的名称里带“Tri Mode”,但我第一个项目直接选的1000 Mbps Only,没有开自适应。

原因有两个。第一是 UDP 传输场景下带宽和延迟是核心指标,自协商虽然方便但也引入了不确定的链路训练时间,板上场景明明是千兆光纤直连,根本不需要去协商 10M/100M。第二是自协商一旦出问题,排查链路比排查逻辑要痛苦得多——你可能要查 MDIO 通没通、PHY 状态寄存器对不对、自协商结果是不是 complete,这些跟 UDP 收发逻辑一点关系没有,纯属浪费时间。

如果你一定要用三速自适应,记住一个坑:MAC 核的在用户侧接口上有一堆速度指示信号(比如 tx_speed、rx_speed),但你的用户逻辑里写包频率和读包频率不能再按固定 125 MHz 算了。10M/100M 模式下,MAC 核内部 FIFO 写侧频率不降,但实际出包的速率会掉,你的 UDP 协议栈里的节流逻辑和超时重传机制必须跟着适配。我的态度很直接:千兆光通信就锁死千兆,减法做到位,稳定性自然上来。

1.3 MDIO、时钟和复位,配置页面里容易被忽略的角落

配置页面里除了数据接口,还有三个配套项:MDIO、时钟方案、复位方案。

MDIO(Management Data Input/Output)是 CPU/FPGA 去配置 PHY 芯片寄存器的通道。对于光模块,你通过 MDIO 去读写 SFP 模块内部的数字诊断寄存器(比如光功率、温度)。前提是你的 SFP 模块支持 MDIO 管理接口。配置页面里会让你选 MDIO 是否启用、PHY 地址是多少。这个地址必须和实际硬件上 PHY 的地址一致,不然读出来全是高阻态,甚至会造成总线冲突。

时钟方案里,MAC 核会要求你提供 client 时钟。SGMII 固定千兆模式下,一般给 125 MHz,来源可以是板载晶振,也可以是由 GTX 恢复时钟反推。我这边习惯用独立的 125 MHz 差分晶振直接进 FPGA 全局时钟,逻辑简单、时序干净,避免在调试早期混入 PLL 抖动变量。

复位这一块容易出幺蛾子。MAC 核官方要求复位信号至少保持几个时钟周期低电平,而且复位释放后要有一段同步处理时间。我踩过最狠的一个坑是:复位信号在仿真里看起来没问题,但上板因为按键没做异步复位同步化,导致 MAC 核内部状态偶发错乱,表现是跑了几个小时掉一次 link,查了三天最后发现是复位飘了。所以强烈建议,所有复位输入都用两级寄存器打拍后再进 IP 核:

reg [1:0] reset_r = 2'b11; always @(posedge clk or posedge ext_reset) begin if (ext_reset) reset_r <= 2'b11; else reset_r <= {reset_r[0], 1'b0}; end assign mac_reset_n = reset_r[1]; // 低有效复位

对了,Tri Mode Ethernet MAC 的复位是高有效还是低有效,不同版本/接口定义不一样。配 IP 的时候前面会有 reset 相关选项,如果你选的是 AXI4-Lite 管理接口方式,复位线通常是低有效;直接裸接口方式,也得看数据手册引脚定义。我的经验是统一在封装层做转换,外面全用高有效 rst,内部再取反,省得版本升级之后来回改。

2. 用户侧接口的收发通路,怎么跟 UDP 协议栈对齐

2.1 用户侧 AXI4-Stream FIFO:先读懂它再谈性能

Tri Mode Ethernet MAC IP 核的用户侧接口在绝大多数配置下是以 AXI4-Stream FIFO 形式暴露出来的,也就是每个方向一组独立的写 FIFO 和读 FIFO。写方向(Tx)你要做的动作是把完整的数据帧推给 MAC 核,读方向(Rx)你从 FIFO 里取回收到的数据帧。

写方向主要信号:

  • axis_wr_tdata:256 bit(8 个字节)数据总线
  • axis_wr_tkeep:字节使能信号,对应每周期 8 个字节里哪几个有效
  • axis_wr_tvalid / axis_wr_tready:写握手
  • axis_wr_tuser:携带首拍指示和末拍指示,某些配置下还会有错误标志位
  • axis_wr_tlast:帧结束标志

读方向主要信号:

  • axis_rd_tdata / axis_rd_tvalid / axis_rd_tready:读握手
  • axis_rd_tlast:帧结束标志
  • axis_rd_tuser:包含错误标志和状态信息

读 FIFO 这边的 tuser 非常重要。我建议一上来就把 tuser 的错误位解析出来,不要只拿 tdata 走。因为 MAC 核在内部做完 CRC 校验之后,如果发现帧错误,它会把错误帧标记在 tuser 上,你拿到 tlast 的时候检查 tuser,若异常,直接把这一帧丢弃,同时对外置一个 rx_error_cnt 计数器。这样,你在调试的时候能迅速判断「丢包是链路问题还是上层协议问题」:如果 rx_error_cnt 猛涨,那就是物理层或者 MAC 配置有问题,而不是 UDP 处理逻辑的问题。

这个 FIFO 是先进先出的完整帧缓冲,不是简单打拍。你一定要意识到:MAC 核对内是 RAM,对外是连续流式接口,够用。它的主要价值在于跨时钟域和速率转换。UDP 协议栈如果需要做跨时钟处理,利用这个 FIFO 是最省事的方案。

2.2 写侧时序:先发数据还是先发控制,顺序不能错

很多第一次用这个 IP 核的人会在 tx 时序上膨跟头。其实 AXI4-Stream FIOF 接口写作帧的要求很明确:你把一整帧丢进去,但它在第一步要看到 tuser 的首拍/末拍指示,然后才能完成组帧。

我用 256 bit 的位宽举例。写帧逻辑的状态机大致长这样:

// 状态机示意:发送一帧 UDP 报文到 MAC 核 localparam S_IDLE = 3'd0; localparam S_DATA = 3'd1; localparam S_LAST = 3'd2; always @(posedge clk) begin case (state) S_IDLE: if (frame_ready) begin state <= S_DATA; tx_data <= first_beat_data; tx_keep <= first_beat_keep; tx_users <= 8'h01; // 首拍标记 end S_DATA: if (axis_wr_tready) begin tx_data <= next_beat_data; tx_keep <= next_beat_keep; if (last_beat) begin tx_user <= 8'h03; // 首拍+末拍合并 state <= S_LAST; end end S_LAST: if (axis_wr_tready) begin state <= S_IDLE; end endcase end

注意几点。

第一,首拍标记要准确。MAC 核接收一帧的起点,就是 tuser 里对应的首拍标志。如果你丢了个发固定长度的 ARP 帧,帧头和以太网头都在同一个拍上,没问题;但发 UDP 大包时,IP 头可能跨两个时钟周期,首拍标志必须只打在真正是帧第一个字节的那个周期上。

第二,tkeep 的处理要费心思。UDP 报文的长度不一定是 8 的整数倍,最后一个周期可能只有几个字节有效。MAC 核会根据你最后一个周期的 tkeep 和 tlast 确定帧尾,并替你补上 CRC。假如把最后一个周期的 tkeep 搞错,比如把 4 字节的尾巴写成 8 字节,CRC 就算错了,抓包会看到长度不对、校验失败的帧。

第三,tready 是可能中途拉低的。不要以为 FIFO 空间足够就不用看 tready,MAC 核内部的缓冲在某些 burst 场景下依然会拉低 tready。你的状态机必须正确执行 AXIS 握手规则:valid 拉高之后,只有在 tready 拉高且本周期完成握手时,才切换到下一个数据拍。最常见的错误是把 tvalid 一直拉高、不看 tready,结果同一拍数据被写了两遍,帧就错乱了。

2.3 读侧时序:什么时候可以暂停、什么时候必须收

读方向相对简单:MAC 核把链路上收到的一整帧存进自己内部 FIFO,然后通过读接口往外吐。你要做的就是在 tvalid 拉高后立刻收数,如果能收就一直收,直到 tlast。

但读侧的暂停是会丢帧的。有些设计会在 UDP 协议栈忙着做校验计算的时候把读侧 tready 拉低几个周期,这个操作确实允许——AXIS 协议里有 backpressure 机制。但 MAC 核内部 FIFO 是有限的,如果长时间不读取,FIFO 溢出后新到的帧会被丢弃,而且不是丢半帧,是整个帧都不要了。

对于要做 UDP offload 的收发系统,我的建议是 RX 侧不要做任何阻塞操作。收到数据直接搬到一个大 SRAM 或 DDR 的环形缓冲里,上层的 UDP 解析、校验字段提取全部从这个缓冲里做,尽可能让读侧处于近乎全速的状态。实测下来,读侧从不拉低的实现方式,比偶尔卡顿的实现方式在多路 UDP 并发时丢包率能低一到两个数量级。

2.4 UDP 协议栈怎么跟 MAC 核协作:分层要靠约定

整个链路是:UDP 协议栈(用户逻辑) → Tri Mode Ethernet MAC → SGMII → SFP 光模块 → 光纤。

UDP 协议栈内部需要处理的逻辑是:构造 IP 头、UDP 头、计算校验和、处理 ARP、ICMP。MAC 核不需要关心这些,它只判断「来的是一个合法的以太网帧吗」,以及「用户推给我的是不是完整帧」。所以代码结构上,我强烈建议把 MAC 核封装成一个独立模块,对外只暴露四个东西:

  • mac_tx_axis_*(帧级别的写接口)
  • mac_rx_axis_*(帧级别的读接口)
  • link_status(链路状态)
  • mdio_*(可选管理接口)

这样,UDP 协议栈里的 ARP 发送逻辑、UDP 发送逻辑、ICMP 回复逻辑共用同一条写通道,只需要做一个仲裁——同一时刻只能有一个发送者往 MAC 写数据。仲裁粒度是一个完整帧,不是一拍一拍地切。千万不要在一个包的中间换源,否则 MAC 核会认为这是两帧,自动补齐 CRC 和填充字节,接收端完全对不上。

3. 光通信链路里,MAC 核和链路状态是怎么配合的

3.1 link 信号不等于数据能通,这是两码事

SGMII 方案里,MAC 核一般会输出一个sgmii_link_timer或者通过 MDIO 读到 PHY 状态寄存器。SFP 光模块的 link up 指的是光模块和交换机/对端光模块之间完成了物理层的握手,比如速率协商、信号同步。这一点非常容易迷惑新人。

我举一个真实场景:两块板卡通过光纤直连,板 A 的 MAC 核配置成 SGMII,板 B 的 MAC 核也配置成 SGMII,两端都工作在同一速率。结果发现 link 状态寄存器和link_status信号都能拉高,但发 UDP 数据对端收不到。这种问题往往是链路训练完成了,但数据通路的 PCS/PMA 配置有问题,比如时钟极性反了、极性不匹配、或者两端的 PHY 寄存器没有正确配置成 SGMII 模式。

调试这个问题的办法很简单:在 MAC 核用户侧发送一个预设的固定数据帧,比如全 AA、全 55 或者特定字符序列,然后在接收端看 RX 数据能否收到相同内容。如果这个都收不到,说明 MAC 核之后的物理通路有问题,跟 UDP 协议栈无关。这一步排查不干净,后面的调试就是大海捞针。

3.2 SGMII IP 核与 MAC 核之间,还有一个容易漏的约束

如果你和我一样是拆成两个 IP 核来用(Tri Mode Ethernet MAC + SGMII),那这两个 IP 核之间的逻辑连接通常不是普通 wire 那么简单,而是属于一组相对路径。Vivado 综合后可能不会自动给你的约束做得特别好,尤其是跨时钟域的处理。所以有两个事必须做:

第一,SGMII 的用户侧时钟和 MAC 核的用户侧时钟要显式关联。一般做法是用同一个 125 MHz 全局时钟作为两个 IP 核的用户时钟输入,这个时钟同时驱动 MAC 核、SGMII 核和 UDP 协议栈逻辑,规避跨时钟域问题。如果因为引脚限制做不到同一时钟源,就要特别注意 CDC 同步。

第二,两个 IP 之间的控制信号,比如 SGMII 的 link 状态返回给 MAC 核,要经过寄存器打拍之后再使用,避免组合逻辑产生毛刺。虽然 Xilinx 官方示例里可能没那么严格,但我加了两拍之后,高速传输的稳定性明显变好。

3.3 千兆光口打流测试怎么排序:先链路、再帧、后协议

UDP 千兆光通信调试最忌讳一上来就整 UDP 全套,链路底层还没有验证过就跑去查丢包。我的调试路径优先级:

  1. 光模块环回或直连,确认 SFP 光功率是否正常,用光功率计或 SFP 数字诊断寄存器读出来。
  2. MAC 核侧发送预设数据,接收端确认数据一模一样。
  3. 关闭 CRC 校验错帧统计,看是否有 CRC 错误计数上升。
  4. 用网络调试助手或者 iperf3 UDP 模式灌包,抓包验证。
  5. 最后才让 UDP 协议栈自己出数据。

尤其是第 4 步的iperf3 -u -b 1000M,我每次必跑。它能够快速看出一台设备实际能打多少吞吐、丢包率多少、抖动多少。如果 iperf3 UDP 打流时丢包率明显过高,就要回头查中断/HASH 相关的实现。在 FPGA 侧调试时,我的习惯是把 iperf3 的流镜像到抓包工具,再做两层确认:Wireshark 抓包角度、FPGA 内部计数器角度。

4. 仿真、上板与 Wireshark 验证的完整闭环

4.1 仿真阶段要准备的测试用例,宁可多不可少

这一节的内容是我吃过教训之后整理的。仿真时,UDP 协议栈和 Tri Mode Ethernet MAC 核的联合仿真,我至少会测这么几种情况:

合法 UDP 包:标准 UDP 报文,内容长度正常,校验和正确,验证发送端和接收端的完整回环。

畸形帧:长度小于 64 字节的帧、长度大于 1518 字节的帧、CRC 错误的帧(这个需要在 MAC 核外构造,或者用仿真模型注入)。确认 MAC 核是否正确丢帧或者打标记。

背压测试:仿真里人为拉低axis_wr_tready几个拍子,确认发送侧 FIFO 不会溢出;拉低axis_rd_tready,确认接收侧不会因为背压丢数据到协议层。

自适应/复位测试:在上电过程中随机拉高复位信号,确认 IP 核能稳定回到 idle 状态,不会卡死在半发帧的状态。

这些测完一遍,上板才不会被各种边角问题折磨到怀疑人生。

4.2 用 ILA 抓 MAC 核接口信号,触发条件要练出肌肉记忆

上板调试阶段,ILA(Integrated Logic Analyzer)是最强的武器。我的触发设置经验有三条:

首抓链路状态:把 SGMII 的link_status和 MAC 核的rx_reset、tx_reset拉进 ILA,触发条件设为 link_status 从 0 变 1 的上升沿。这个采集窗口能告诉你从复位到链路建立需要多少拍,期间有没有毛刺。

再抓错误计数:把rx_error_cnt放进 ILA,触发条件设为计数器值大于 0。出现之后再从出错那一帧往前回溯,查看 MAC 核 tuser 上的错误标志,快速定位是校验错还是帧长错。

后抓正常收发:抓 TX 和 RX 侧同时有效的时段,确认发送和接收的 tdata/tkeep/tlast 组合没有错位。比如一次完整的 UDP 收发,从 TX tlast 到 RX tfirst 的时间间隔到底是多少,这个数据对协议栈的性能分析很有用——尤其你想验证回环延迟的时候。

ILA 的采样深度,我的经验是 16K 起步。千兆速率下是 8 字节一拍,16K 深度只能抓 2MB 数据,也就是大概 1300 多个 1518 字节的帧,抓正常收发足够了。不过抓启动瞬间的话可能要 32K 深度,因为从那到链路稳定再到第一帧出现,中间跨度比较大。

4.3 Wireshark 是 FPGA 调试的免费照妖镜

FPGA 调试的终端证据链很长,但最终要落地到「这台设备在网络里是不是表现得像个正常节点」这个标准。我用 Wireshark 验证的时候,重点关注三个指标:

首先,UDP 报文的长度字段是否与实际载荷长度一致。MAC 核本身会填充最小帧长到 60 字节,但不改 UDP 头里的 length 字段。如果你协议栈里 length 填的是 20 字节,实际 payload 2 字节,抓包会看到 UDP length=22,但整个包长度被 MAC 核填充到更大,Wireshark 也能识别。

其次,IP header checksum 是否正确。IP 头校验和是 UDP 协议栈需要自己算的,MAC 核不管。如果 checksum 错误,抓包软件会直接标红,即便对端网卡不校验,也会在协议栈分析里暴露问题。

再次,UDP checksum。IPv4 下这个字段可选置 0,但在光纤链路直连场景下我喜欢顺手算好,减少对端系统的兼容性问题;IPv6 场景则必须算,否则有些板卡根本不接收。

Wireshark 里针对几万包做筛选,可以用udp.time_delta或者自定义列,查 UDP 前后两包的时间间隔分布,快速看出是否有周期性的丢包——比如每收到 10000 包就丢一包,这种规律性问题往往指向 FIFO 深度不够或者周期性背压,而不是随机的物理层误码。

4.4 两台电脑直连与网络调试助手:最糙但最有用的联调方法

如果条件允许,我会先把 FPGA 设备接到一台电脑的网口上,用网络调试助手建一个 UDP 连接,指定端口,然后互相收发。

这件事的价值在于:网络调试助手和 Wireshark 是不同层次的验证。网络调试助手验证的是「应用层数据对不对」,Wireshark 验证的是「报文结构对不对」。如果网络调试助手收到的数据内容对、但 Wireshark 里显示帧结构有奇怪的地方,那问题大概率出在 FPGA 发送侧对帧的封装细节上,而不是光路上。

两台电脑 UDP 通信的经典测试,是把一台电脑设成服务器 IP 192.168.1.10 端口 5000,另一台设成客户端 IP 192.168.1.20 端口 6000。但你让 FPGA 加入这个拓扑的时候,FPGA 的 MAC 地址、IP 地址、ARP 表都必须是同一网段内能解析的。我看到很多新手在联调时犯的错是:改了 FPGA IP 地址,却没改 ARP 缓存,导致 UDP 包发出去过了交换机但对方根本不认。所以联调前第一件事是arp -a,确认两端(含交换机)的 MAC 表都是新的。

5. 常见问题速查表,都是亲身踩过的坑

问题现象直接原因排查手段
光模块 link 灯亮,但 MAC 发送数据对端收不到SGMII IP 与 MAC 核配置不匹配,物理编码层数据错误先用 ILA 观察 MAC 核 tx 侧 tdata/tkeep,再用误码仪或预设数据测物理层
抓包看到 CRC 错误MAC 核自动追加 CRC,但你没配成自动;或 tkeep 在最后一拍不正确确认 CRC 使能选项;核对最后一拍 tuser 和 tkeep
所有 ARP 请求能回,但 UDP 大包发不出去UDP 校验和错误,对端直接丢弃;或 MTU 被超限后分片乱序Wireshark 过滤udp.checksum状态,核对 payload 长度
长时间运行后丢包,重启后恢复复位信号未同步或 FIFO 水位控制不良,长期运行后溢出检查复位打拍逻辑,确认读侧背压策略
端口通了但延迟抖动大发送侧 tready 经常拉低,数据被迫中断ILA 抓 tready 与 tvalid 的握手频率,降低发送端瞬时突发性
SGMII 1000M 模式下收到 10M 速率特征的数据三速自适应没有完全关,MAC 核仍在协商低速模式检查 MAC 核速度指示信号,改为固定 1000M Only 配置
MDIO 读 PHY 寄存器超时PHY 地址不匹配或时序不满足 MDC/MDIO 最小周期要求核对硬件原理图 phy_addr 引脚电平,调整 MDC 频率

还有一个我每次都要提醒自己的经验:Tri Mode Ethernet MAC 核里面的 FIFO 深度不是万能的,对外看起来它能应付突发,但持续高吞吐打流时,用户侧逻辑如果不控制瞬时发射带宽,照样溢出。我一般会在协议栈侧给发送通道加一个平滑缓冲,保证打流时候每个时间片的平均速率不超过链路线速,而不是让 MAC 核的 FIFO 去硬扛极端 traffic burst。

最后再说一个小细节。Tri Mode Ethernet MAC IP 核在配置完成后,Vivado 会生成一个 example design,里面有完整的约束文件和 top 模块。一开始别急着从头写自己的代码,直接把 example design 跑一个仿真、上板点个灯,确认这套链路在你的板子上能初始化成功,再在这个基础上增加 UDP 协议栈逻辑。这个习惯能省掉好多早期去重定位的时间。

UDP_千兆光通信这个系列写到第四篇,Tri Mode Ethernet MAC 的细节其实讲得差不多了。接下来如果要继续深入,方向会在 UDP 协议栈多通道并发、或把 TCP/IP offload 引擎做成 AXI 接口的通用模块,这两块我后面有项目验证完再单独写。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询