尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Lattice FPGA MII接口CRS信号处理实战:从悬空隐患到完整方案

Lattice FPGA MII接口CRS信号处理实战:从悬空隐患到完整方案 最近在项目里用 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 接口信号全景MIIMedia 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 模式下为 25MHz10M 模式下为 2.5MHz由 PHY 或 MAC 提供具体取决于 PHY 芯片的实现RX_CLK 始终由 PHY 从接收数据中恢复出来送给 MAC。第二组是载波侦听和冲突检测信号就是本次重点讨论的 CRSCarrier Sense载波侦听和 COLCollision 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 1b0; wire col_fixed 1b0; // 实际 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_TYPELVCMOS33; IOATTR COMP mii_crs PULLMODEDOWN; LOCATE COMP mii_col SITE B3; IOATTR COMP mii_col IO_TYPELVCMOS33; IOATTR COMP mii_col PULLMODEDOWN;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这里PULLMODEDOWN表示使能 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 级的电阻选择与 LayoutFPGA 内部下拉能解决大部分问题但 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 这种小信号就是典型的不处理不知道处理了才算懂。
返回列表