MDIO 物理层实现:SMI 接口信号与时序分析
MDIO 的物理层,说白了就是 SMI(串行管理接口)怎么在两根线上跑起来。我刚开始调试 MII 时,总觉得时序图看起来很简单,但一上示波器就发现毛刺满天飞。嗯,这一节我们把信号定义和时序参数拆开揉碎讲清楚。
SMI 接口信号
SMI 只有两根线:
- MDC(管理数据时钟)—— 由主设备驱动,频率不超过 2.5 MHz(标准模式下)。
- MDIO(管理数据输入输出)—— 双向数据线,需要上拉电阻。
你想想看,两根线就能读写所有 PHY 寄存器,挺神奇的。但代价就是速度慢,而且时序要求很严格。
关键点: MDIO 属于三态总线。读操作时 PHY 驱动数据,写操作时主设备驱动。空闲时 MDIO 保持高阻,靠外部上拉维持高电平。
时序参数对照表
我习惯在调试前先把规格书的时序参数列出来。下面是 IEEE 802.3 标准中 SMI 的主要时序要求(参考 100BASE-TX PHY):
| 参数 | 符号 | 最小值 | 最大值 | 单位 |
|---|---|---|---|---|
| MDC 时钟周期 | Tcyc | 400 | — | ns |
| MDC 高电平宽度 | Thigh | 160 | — | ns |
| MDC 低电平宽度 | Tlow | 160 | — | ns |
| MDIO 数据建立时间(写/读) | Tsetup | 10 | — | ns |
| MDIO 数据保持时间(写/读) | Thold | 10 | — | ns |
| MDIO 输出延迟(从 PHY) | Tdly | 0 | 100 | ns |
避坑指南:我曾经在 FPGA 上直接用 25 MHz 时钟分频做 MDC,结果分频后的占空比只有 20%。MDC 低电平时间过短,PHY 根本无法采样。后来老老实实加了个计数器,保证高、低电平都 ≥160 ns。
读写时序分析
SMI 的帧结构大家都熟:32 位前导码 + 起始位 + 操作码 + PHY 地址 + 寄存器地址 + 转向位 + 数据。但时序上有个小陷阱——转向位(TA)时钟周期。
读操作时,在 TA 的前半拍主设备释放总线,后半拍 PHY 开始驱动 MDIO。如果主设备释放不够快(比如三态门延迟),会和 PHY 的输出产生冲突。我用示波器抓到过总线竞争产生的毛刺,数据全错。
// 一个简化的 MDIO 读时序 Verilog 片段(仅供参考)
reg [4:0] phy_addr, reg_addr;
reg [15:0] read_data;
reg [31:0] clk_cnt;
always @(posedge mdc_2_5M) begin
case (state)
IDLE: begin
if (start) begin
mdio_out_en <= 1; // 主机驱动前导码和帧头
state <= PREAMBLE;
end
end
PREAMBLE: begin
// 32 个 1 后跳转
if (cnt == 31) state <= START;
end
// ...
TURN_AROUND: begin
if (cnt == 0) mdio_out_en <= 0; // 释放总线
if (cnt == 1) begin
mdio_out_en <= 0; // 读数据,由 PHY 驱动
read_data[15:0] <= {read_data[14:0], mdio_in};
end
end
endcase
end
个人经验:我建议在 TA 的前半周期插入一个 dummy 周期,让总线浮空更干净。很多商用 PHY 的 TA 窗口是 ±10 ns,留点余量总没错。
时序验证与常见问题
- MDC 时钟抖动过大: 如果 MDC 由软件产生(比如 GPIO 模拟),抖动可能超过 100 ns,导致 PHY 采样错误。解决办法:改用硬件定时器或 SPI 外设。
- MDIO 上拉电阻失效: 读操作时 MDIO 浮空,如果外部上拉太小(比如 1kΩ),总线电平可能被芯片内部下拉拉到低电平,读回全 0。
- 背靠背读写间隔: 有些 PHY 要求连续两次 SMI 操作之间至少间隔 1 个 MDC 周期,否则内部状态机未复位。
为什么要关注这些?因为 MDIO 是调试的第一步。如果连寄存器都读不到,后面链路分析无从谈起。
上图展示了读操作时的帧结构顺序。你看到 TA 之后数据段才由 PHY 驱动,所以之前主机必须把 MDIO 拉成高阻。调试时我习惯用逻辑分析仪抓整个帧,重点看 TA 处的电平变化是否干净。
小技巧:如果读回的寄存器值偶尔全 F,大概率是 MDIO 上拉没接好,或者主设备在 TA 后仍然保持输出。用示波器看 MDIO 波形,若 TA 后有不该出现的下降沿,就是冲突信号。
掌握 SMI 时序,你就有了调试 MDIO 的「眼睛」。后面章节我们会结合 D-PHY 链路,看看时序问题怎么通过 MDIO 读回的错误值反向定位。