最近在项目里用 Lattice ECP5 做一块带以太网接口的板卡,MII 模式对接外部 PHY 芯片时,碰到一个说大不大、说小不小的坑:PHY 输出的 CRS 信号到底怎么处理。翻出 Lattice 的应用笔记 LAT1595 仔细看了一遍,又结合自己调试过程中的实测,发现这类问题其实在 MII 接口设计里非常典型,很多工程师第一次做以太网都会在这里卡一下。这篇就把 CRS、COL 这些信号的前因后果、处理方案和实操步骤完整梳理一遍,给正在做 Lattice FPGA 以太网接口的朋友做个参考。
这个问题之所以值得单独写一篇,是因为它牵扯到协议机制、PHY 芯片行为、FPGA IO 约束和 PCB 设计四个层面,任何一个环节处理不当,都会让板卡在功耗、稳定性或者兼容性上出问题。对于只跑全双工的板子来说,CRS 信号看起来"没用",但如果直接悬空不管,后面可能带来一堆莫名其妙的现象。下文会从信号原理讲起,逐步落到具体的 RTL 写法和约束配置,最后附带调试排查记录。
1. MII 接口与 CRS 信号的本质
1.1 MII 接口信号全景
MII(Media Independent Interface,介质无关接口)是 IEEE 802.3 标准定义的 MAC 与 PHY 之间的标准接口,工作在 10Mbps 或 100Mbps。它把 MAC 和 PHY 从逻辑上解耦,MAC 不需要关心底层到底走双绞线、光纤还是其他介质,只要面向 MII 收发数据即可。
一个完整的 MII 接口分三组信号。
第一组是数据与同步信号。发送方向包括 TX_CLK、TX_EN、TXD[3:0],接收方向包括 RX_CLK、RX_DV、RXD[3:0],外加 RX_ER 接收错误指示。TX_CLK 在 100M 模式下为 25MHz,10M 模式下为 2.5MHz,由 PHY 或 MAC 提供,具体取决于 PHY 芯片的实现;RX_CLK 始终由 PHY 从接收数据中恢复出来,送给 MAC。
第二组是载波侦听和冲突检测信号,就是本次重点讨论的 CRS(Carrier Sense,载波侦听)和 COL(Collision Detection,冲突检测)。这两个信号由 PHY 产生,方向是 PHY 到 MAC,用于在半双工模式下实现 CSMA/CD 介质访问控制。
第三组是管理接口 MDC 和 MDIO,用于 MAC 读写 PHY 内部的寄存器,配置 PHY 的工作模式、读取链路状态等。这组信号和 CRS 没有直接关系,但在排查 CRS 问题时经常要配合使用,后面会讲到。
MII 接口在不同速率下,数据有效窗口和信号时序不一样,但 CRS 的电平逻辑很简单:介质上有载波活动时 CRS 为高,介质空闲时 CRS 为低。在半双工模式下,发送和接收都会拉高 CRS;在全双工模式下,发送和接收是独立的通道,CRS 更多反映的是接收通道上的载波活动。
1.2 CRS 和 COL 在 CSMA/CD 机制中的角色
要理解 CRS 为什么需要处理,得先回顾半双工以太网的工作机制。早期的以太网是共享介质,同一时刻只能有一个节点在发送,否则信号会在共享介质上叠加冲突,数据就废了。CSMA/CD(载波侦听多路访问/冲突检测)协议就是为了解决这个问题。
CSMA/CD 的流程大致如下:节点要发送数据前,先侦听介质上有没有载波,也就是看 CRS 信号。如果 CRS 为高,说明其他节点在传输,就等待;如果 CRS 为低,说明介质空闲,可以开始发送。节点在发送过程中要时刻监视 COL 信号,如果 COL 变高,说明发送和自己的接收发生冲突,节点要立即停止发送,发一个 JAM 拥堵信号强化冲突,然后进入随机退避等待,之后重试。
在这个机制中,CRS 负责"先听后发"中的"听",COL 负责"边发边听"中的"听",两个信号联合实现了对共享介质的访问控制。对于 MII 接口来说,MAC 内部必须要有 CSMA/CD 状态机,并且把 CRS、COL 接入这个状态机,才能正确完成半双工通信。
这个机制在 10M/100M 时代是核心,因为那时候集线器(Hub)大量使用,半双工模式很常见。到了千兆以太网时代,交换机和全双工链路占了绝对主流,CSMA/CD 基本被淘汰,但协议规范里还保留着对半双工的支持。所以 PHY 芯片至今仍然会输出 CRS、COL 信号,只是多数情况下 MAC 侧根本不需要它们。
1.3 全双工模式下 CRS 的真实行为
全双工模式下,发送和接收使用各自的信号通道,不存在共享介质冲突的问题,因此 MAC 不需要 CSMA/CD 状态机,也不需要理会 CRS 和 COL。但是要注意,不需要理会,不等于 PHY 会停止输出。大多数 PHY 芯片在 MII 模式下,无论工作在半双工还是全双工,都会在接收通道检测到载波时拉高 CRS。
也就是说,即使你的 MAC 配置成全双工,PHY 的输出引脚上仍然会有 CRS 信号在跳动。特别是在有持续接收流量的情况下,CRS 会跟着 RX_DV 同步变化,表现为一个有一定频率翻转的方波信号。
这个特性是问题的主要来源。如果 MAC 侧的 FPGA 引脚没有正确端接,CRS 引脚会处于悬空状态,输入缓冲就会捕获到不确定电平,轻则产生额外功耗,重则引起逻辑误判,甚至影响整片 FPGA 的供电稳定性。Lattice 的 LAT1595 应用笔记专门讲这个问题,其实就是提醒设计者:MII 模式下即使你不用 CRS,也要给这个信号一个明确的归宿。
2. LAT1595 场景:CRS 信号三种典型处理路径
2.1 半双工方案:CRS 必须接入 MAC
如果你的项目必须支持半双工模式,那 CRS 和 COL 就不能忽略,必须把 PHY 的输出接到 FPGA 内部,并接入 MAC 核或自研 MAC 的 CSMA/CD 模块。这种情况下没有太多讨价还价的空间,信号完整性设计和逻辑设计都要认真对待。
在半双工模式下,CRS 的处理重点在于时序和逻辑验证。MII 的 CRS 信号是异步信号,从 PHY 输出到 FPGA 内部采样,需要做同步处理,否则很容易在跨时钟域时采到亚稳态。常见的做法是在 FPGA 内部用两级触发器同步 CRS,再做边沿检测,供 CSMA/CD 状态机使用。COL 信号同理。
还有一点容易被忽略:半双工模式下,CRS 从无效到有效的响应时间会直接影响发送延迟。CSMA/CD 要求节点在检测到介质空闲后才能发送,如果 CRS 的同步延迟太长,会白白浪费带宽;如果太短,又可能在前一个数据包还没发完时就开始发送,产生冲突。所以有经验的工程师会测量 PHY 的 CRS 有效到 FPGA 内部采样点之间的总延迟,再根据这个延迟调整退避窗口的计时精度。
不过说实话,现在做半双工以太网的场景极少,工业现场偶尔能看到,消费和通信类产品基本全是全双工。如果你的项目不是强制要求兼容半双工,我个人的建议是直接跳过 CSMA/CD 逻辑,专心处理全双工场景,把 CRS 信号妥善固定住就行了。
2.2 全双工方案:不接但不代表能悬空
全双工模式下,CRS 信号在逻辑上确实没有用处,MAC 核不需要它,自研 MAC 也可以不写相关逻辑。但问题恰恰出在这里:很多工程师觉得"没用就不接",结果 PCB 走线和 FPGA 引脚就悬空了。
悬空引脚在 FPGA 里是个隐患。CMOS 工艺的输入缓冲对悬空电平非常敏感,当引脚电压徘徊在阈值附近时,输入缓冲会进入线性区,产生较大的漏电流,导致该引脚功耗异常。如果引脚的寄生电容加上走线形成了一个微型振荡回路,还可能出现持续的高频振荡,干扰周围信号。实测下来,一个悬空的输入引脚在特定条件下多消耗几个毫安电流是常有的事。
所以正确的做法是:在全双工模式下,CRS 引脚要么在 PCB 上直接接固定电平,要么接到 FPGA 后通过内部或外部电阻拉到固定电平,总之不能悬空。具体选高还是低,要看 PHY 在空闲时 CRS 的默认状态。一般 CRS 在空闲时为低,所以通常选择下拉。但也不绝对,个别 PHY 的 CRS 引脚内部有弱上拉,空闲时输出高,这种就要改为上拉或者接 3.3V,避免和 PHY 内部的上拉打架。
LAT1595 应用笔记里推荐的思路就是:在 FPGA 侧把 CRS、COL 配置为输入引脚,内部使能下拉电阻,同时在 RTL 里引入固定常量的逻辑赋值,确保这两个信号被明确定义。这样 PHY 输出的 CRS 信号即便在翻转,FPGA 内部也不会因为悬空而采到乱电平。
2.3 PHY 芯片的 CRS 输出特性差异
不同厂商的 PHY 芯片,CRS 引脚的输出特性差异很大,处理方式也要随之调整。以市面上常见的几款 MII/RMII PHY 为例,Microchip LAN8720A、TI DP83848、Realtek RTL8201F,它们的 CRS 引脚在空闲状态下的驱动能力、内部上下拉情况都不一样。
LAN8720A 的 CRS_DV 引脚在 RMII 模式下合并了 CRS 和 RX_DV,空闲时被内部下拉,输出低电平。如果 FPGA 不接收这个信号,并且 PCB 上也没有额外处理,引脚本身不会出现明显的悬空状态,但要注意它是推挽输出,外部下拉电阻不会改变它的空闲电平。
DP83848 的 CRS 引脚在半双工和全双工下都会输出载波状态,空闲时为低。数据手册里专门提到,如果 MAC 不支持半双工,CRS 引脚可以悬空不接,但推荐通过一个 10kΩ 电阻下拉到地,避免任何潜在的噪声耦合。
RTL8201F 的情况又不一样,它的 CRS 引脚在配置为 MII 模式后,空闲时输出低电平,但引脚本身没有内部下拉,如果不接,外部必须给一个确定的电平。
这里想提醒一点:数据手册的推荐电路只是参考,实际设计时要以你用的具体 PHY 型号和封装为准。拿到 PHY 的数据手册后,第一件事就是翻引脚描述部分,看 CRS、COL 引脚的输出类型、默认输出电平、内部上下拉情况,再决定外部电路怎么处理。
3. 实操:从 RTL 到约束再到 PCB 的完整处理
3.1 RTL 层怎么把 CRS 消化掉
我在实际项目中采用的做法是:在顶层模块里把 mii_crs 和 mii_col 定义成输入端口,然后内部固定为常量赋值。这样综合后不会产生未定义输入,也方便后续如果需要挂调试逻辑,随时可以引用。下面是核心代码片段。
module eth_mii_top ( input wire clk_25m, input wire rst_n, // MII 接收通道 input wire mii_rx_clk, input wire [3:0] mii_rxd, input wire mii_rx_dv, input wire mii_rx_er, // MII 发送通道 output wire mii_tx_clk, output wire [3:0] mii_txd, output wire mii_tx_en, // 载波侦听与冲突检测 input wire mii_crs, input wire mii_col, // MDIO 管理接口 output wire mdc, inout wire mdio, // 用户侧接口 input wire [7:0] user_tx_data, input wire user_tx_valid, output wire user_tx_ready, output wire [7:0] user_rx_data, output wire user_rx_valid ); // 全双工模式下,CRS/COL 不参与 CSMA/CD // 但引脚必须被引用,禁止悬空后被综合器优化掉 (* KEEP = "TRUE" *) wire crs_sample; (* KEEP = "TRUE" *) wire col_sample; assign crs_sample = mii_crs; assign col_sample = mii_col; // 固定逻辑值,确保内部逻辑始终在可控状态 wire crs_fixed = 1'b0; wire col_fixed = 1'b0; // 实际 MAC 逻辑只使用 crs_fixed / col_fixed // crs_sample / col_sample 保留用于在线调试 ... endmodule这里有两个关键操作。第一,(* KEEP = "TRUE" *)属性强制综合器保留这两个内部信号,避免因为没被引用而被优化掉。第二,crs_sample和col_sample虽然只是采样了输入,但通过 KEEP 属性保留后,可以在在线逻辑分析仪里观察 PHY 实际的 CRS、COL 波形,这对调试非常有用。等到系统稳定运行后,再把这些保留信号去掉,减少 FPGA 资源占用。
如果你的设计里 MAC 核是现成的 IP,比如 Lattice 的 Soft Ethernet MAC IP,一般 IP 核内部已经处理好了 CRS/COL 的忽略逻辑,你只需要在顶层把端口接出来并按照上面方式处理即可。如果是我自研的轻量 MAC,则固定赋值后,CSMA/CD 相关逻辑可以完全不写。
3.2 约束文件配置下拉
RTL 层面处理完了,接下来是 FPGA 引脚约束。在 Lattice 的工程里,要根据使用的工具链来区分约束文件格式。
Diamond 工具使用 LPF 文件,一个典型的 CRS 引脚约束如下:
LOCATE COMP "mii_crs" SITE "A3"; IOATTR COMP "mii_crs" IO_TYPE=LVCMOS33; IOATTR COMP "mii_crs" PULLMODE=DOWN; LOCATE COMP "mii_col" SITE "B3"; IOATTR COMP "mii_col" IO_TYPE=LVCMOS33; IOATTR COMP "mii_col" PULLMODE=DOWN;Radiant 工具使用 PDC 文件,写法稍有不同:
io_attr -name IO_TYPE -value LVCMOS33 -port mii_crs io_attr -name PULLMODE -value DOWN -port mii_crs io_attr -name IO_TYPE -value LVCMOS33 -port mii_col io_attr -name PULLMODE -value DOWN -port mii_col这里PULLMODE=DOWN表示使能 FPGA 内部下拉电阻。Lattice FPGA 的内部下拉阻值一般在几十 kΩ 到一百 kΩ 之间,对于 CMOS 输入缓冲来说足够稳定电平。要注意,这个下拉电阻是在 FPGA 芯片内部的,不是外部可见的物理电阻,所以它只对 FPGA 引脚本身有效。如果 PCB 上 PHY 的 CRS 输出到 FPGA 引脚之间有串联电阻或其他器件,下拉效果会受影响,需要结合外部电路综合考虑。
约束里还有一个细节:IO_TYPE 必须根据你的板级电平标准设置。如果 PHY 的 IO 电压是 3.3V,就用 LVCMOS33;如果是 2.5V,就要改成 LVCMOS25。电平不匹配轻则信号采样错误,重则损坏器件。
配置好之后,可以在布局布线报告里检查这两个引脚最终是否被分配到了正确的位置,以及 PULLMODE 是否生效。Diamond 的报告里会列出每个引脚的 IO 属性,Radiant 则在 I/O Analysis 视图中可以看到。
3.3 PCB 级的电阻选择与 Layout
FPGA 内部下拉能解决大部分问题,但 PCB 层面的处理同样重要,尤其是当 PHY 和 FPGA 之间走线较长、环境干扰大时。我在实际项目中习惯的做法是:无论 FPGA 内部是否配置了下拉,在 PHY 的 CRS 和 COL 引脚附近各放一个 10kΩ 下拉电阻到地。
这个电阻的作用有两个。第一,在 PHY 上电复位期间、FPGA 尚未配置完成时,给 CRS 引脚一个确定的电平,避免 PHY 在复位过程中输出高阻或者不确定状态,被走线上的噪声干扰成随机电平。第二,方便调试。示波器探头直接夹在电阻两端,就能看到 PHY 输出的真实 CRS 波形,不需要去焊细密引脚。
选择 10kΩ 而不是更小的阻值,是为了避免影响 PHY 的推挽输出。如果下拉电阻太小,比如 1kΩ,那么当 PHY 输出高电平时,这个电阻上的电流就会达到 3.3mA,虽然不至于损坏 PHY,但增加了功耗,而且会在 CRS 高电平上产生额外的电压降。10kΩ 的电流大约 0.33mA,对整个系统的功耗影响可以忽略,同时足以保证空闲时引脚稳定为低。
Layout 上也有讲究。CRS 和 COL 属于慢速控制信号,不需要像数据线那样严格控制等长,但要注意远离时钟线和高频开关节点,避免耦合噪声造成误触发。尤其是如果 PHY 工作在 100M 模式,RX_CLK 和 TX_CLK 都是 25MHz 的方波,CRS 走线如果和时钟线靠得太近,时钟的边沿噪声可能被耦合到 CRS 上,导致 MAC 内部采集到错误的载波状态。所以布线时,CRS 和 COL 走线尽量短,并用地线屏蔽。
3.4 验证处理是否到位的方法
处理完之后,怎么确认效果?我的日常验证方法分三个阶段。
第一阶段是仿真验证。在 testbench 里给 mii_crs 和 mii_col 加随机激励,模拟 PHY 在各种状态下的输出,确认内部逻辑不会因为这些信号的变化而产生异常行为。对于全双工设计,期望的结果是 CRS 随机翻转时,MAC 收发数据完全不受影响。
第二阶段是板级功耗检查。用稳压电源给 FPGA 核心和 IO 供电,记录 FPGA 配置完成但不跑以太网流量时的静态功耗,然后把以太网链路插上,让 PHY 满负荷接收广播包,再记录一次功耗。如果 CRS 引脚处理得当,两次功耗差异应该很小,主要来自 IO 翻转功耗。如果 CRS 引脚悬空,这个差异可能会异常偏大,尤其在流量较大时。
第三阶段是长期稳定性测试。让板卡连续运行 24 小时以上,同时用逻辑分析仪持续监控 crs_sample 和 col_sample,观察有没有异常毛刺,以及 PHY 和 MAC 之间有没有出现 CRC 错误、丢包等问题。这一步可以验证信号完整性在长时间工作后的表现,特别是温度变化是否会导致引脚电平阈值漂移。
我遇到过一种情况:CRS 引脚悬空时,瞬时功耗和 CRC 错误率都正常,但设备在高温环境下运行一段时间后偶发网络断开。排查了很久,最后用示波器测 CRS 引脚,发现低温时引脚电平能正常稳定在低电平,高温时引脚上出现了小幅振荡。这就是典型的高温下悬空引脚引发的电平不稳定问题。所以验证时,高低温环境下的测试千万不能省。
4. 常见问题与排查实录
4.1 悬空导致功耗异常
这类问题最隐蔽,因为系统逻辑功能一切正常,只是功耗莫名其妙偏高。某次项目里,整板功耗比设计值多了 50mA,排查了很久,一个个引脚排查过去,最后发现是 MII 接口的 CRS 引脚悬空导致的。
当时 PHY 的 CRS 输出在空闲时是低电平,但 FPGA 引脚没有内部下拉,也没有外部电阻,引脚电压在 FPGA 输入阈值附近游走。输入缓冲的 PMOS 和 NMOS 同时微导通,形成贯穿电流,功耗就上去了。这个电流大小跟引脚数量有关,一个引脚可能只有几 mA,两个三个累积起来就明显了。解决办法很简单,配置内部下拉后功耗恢复正常。
这次经历让我学到一条经验:FPGA 所有不用的输入引脚,必须明确电平状态。尤其是来自外部 PHY、ADC 或接口芯片的控制信号,即使逻辑上不需要,也必须保证引脚不悬空。可以在设计规则检查里,把所有悬空输入引脚列为警告项。
4.2 仿真过了上板却不通的排查套路
仿真能验证逻辑功能,但仿真环境和真实硬件存在差异。最常见的差异就是真实信号存在上下拉电阻、RC 延迟、串扰和温度漂移,这些在仿真模型里不一定包含。
我遇到过一次很有趣的问题:仿真时 MAC 收数完全正常,上板后 RX 方向偶尔丢包,而且和流量大小相关。最开始怀疑是时钟问题或者数据采样窗口不对,查了一圈没结果。后来用示波器同时测 RX_DV 和 CRS,发现 CRS 的上拉毛刺正好出现在 RX_DV 的翻转沿附近。由于工程版本里 MAC 逻辑引用了 CRS(当时还在做半双工兼容),毛刺被采到后,CSMA/CD 状态机误判介质忙,直接丢弃了当前帧。
问题根源在于 PHY 附近的开关电源纹波耦合到了 CRS 走线上,而这个走线没有加端接电阻。解决方法是把 CRS 走线改成包地处理,同时在 FPGA 引脚端加一个 100pF 电容对地滤波。
这个案例说明,排查以太网问题时,CRS 这类"不起眼"的信号反而可能是隐藏炸弹。建议排查顺序是:先查 PHY 锁链和 MDIO 配置,再查时钟和复位,最后用示波器查所有 MII 控制信号的实际波形,不要只看数据线。
4.3 从 MII 迁移到 RMII 的 CRS 扩展
如果你后续把设计从 MII 切换到 RMII 模式,CRS 的处理逻辑需要相应调整。RMII 接口没有独立的 CRS 和 COL 信号,这两个信号合并成了 CRS_DV,由 PHY 输出给 MAC。
RMII 模式下 CRS_DV 的语义比 MII 的 CRS 更复杂一点。它在接收数据有效期间拉高,表示"载波存在且有有效数据",这个信号在高电平期间还需要配合 RXD[1:0] 上的数据来区分是载波事件还是数据事件。在全双工模式下,如果 MAC 不需要它,同样的处理原则适用:FPGA 引脚不能悬空,需要配置下拉或者接固定电平。
需要注意的是,有些 PHY 芯片的引脚是模式复用的。例如 LAN8720A 在 MII 模式下,某个引脚是 CRS;在 RMII 模式下,同一个引脚变成 CRS_DV。切换模式时,PCB 上的上下拉电阻可能需要调整,因为 CRS_DV 的默认驱动能力和空闲电平跟 CRS 不完全一样。所以设计时最好把 PHY 的模式配置引脚(比如 MODE0、MODE1)也考虑进去,确保切换模式后 CRS 相关引脚的端接仍然正确。
5. 个人经验小结与检查清单
5.1 设计阶段检查清单
综合自己这么多年的调试经验,我把 MII 接口设计中 CRS 相关问题的检查项整理成了一份清单,每次流片或者改版之前都会过一遍:
- 确认 PHY 工作模式。半双工还是全双工,决定 CRS/COL 是否需要接入 MAC 逻辑。
- 阅读 PHY 数据手册中 CRS/COL 引脚的描述,确认输出类型、空闲电平、内部上下拉情况。
- 检查 FPGA 引脚约束,未使用的 CRS/COL 引脚是否配置了 PULLMODE,推荐 DOWN。
- 检查 PCB 设计,CRS/COL 走线是否尽量短,是否包地处理,有没有接 10kΩ 下拉电阻。
- 确认 IO 电平标准匹配,PHY 的 IO 电压和 FPGA Bank 电压一致。
- 确认 FPGA 配置前的 PHY 引脚状态,避免上电瞬间 PHY 输出高阻导致 FPGA 引脚悬空。
- 在 RTL 里保留 CRS/COL 的采样信号,方便在线调试,后续再移除。
- 如果是自研 MAC,确认 CSMA/CD 相关逻辑没有被意外引入到全双工数据通路里。
- 半双工模式下,CRS/COL 必须做异步同步处理,不能用原始信号直接驱动状态机。
- 必要时,在 CRS 引脚靠近 FPGA 侧加一个小电容滤波,滤除高频噪声。
每一项看起来都很简单,但每一条背后都有对应的实际故障案例。特别是"FPGA 配置前的 PHY 引脚状态"这一条,很容易被忽略,但恰恰是上电时序不稳定时产生异常功耗的直接原因。
5.2 调试技巧补充分享
最后再分享一个调试小技巧。很多 Lattice FPGA 支持在线逻辑分析仪功能,比如 Reveal Analyzer,可以直接采样内部信号。我在调试以太网接口时,会同时采样 mii_rx_clk、mii_rx_dv、mii_rxd、crs_sample 这几个信号,触发条件设为 CRS 上升沿。这样每次 PHY 检测到载波时,都能抓拍到完整的前后波形,检查 CRS 和 RX_DV 的时序关系是否正常。
正常情况下,CRS 应该比 RX_DV 提前一点拉高,或者在 RX_DV 拉高的同一拍拉高。如果发现 CRS 拉高滞后于 RX_DV,说明 PHY 的载波检测延迟可能偏大,在极端的半双工兼容测试中可能导致发送过早开始。全双工模式下这种滞后影响不大,但要记录下来备查。
还有一个很实用的做法:把 CRS 信号引到 FPGA 的普通 GPIO,然后在 GPIO 上接一个 LED,通过示波器或者肉眼观察 LED 亮灭,快速判断链路是否有活动。这种方法在无头调试时非常高效,不需要额外的逻辑分析仪和电脑,就能初步判断链路状态。
这些经验看起来零碎,但在项目关键时刻真能省下几个晚上的调试时间。做硬件和逻辑设计就是这样,很多坑不是靠理论推出来的,而是靠一个个实测案例填出来的。MII 接口在当下已经是很成熟的低速接口了,但越成熟的接口越容易让人放松警惕,CRS 这种小信号就是典型的"不处理不知道,处理了才算懂"。