第4章 MDIO时序分析:读时序、写时序,关键参数

上一章我们把MDIO的帧结构拆了个干净,但说实话,光看懂帧结构还不够。你想想看,协议说到底就是一堆高低电平在时钟边缘跳来跳去。真正让工程师头疼的,往往是时序——什么时候采样、什么时候驱动、什么时候该保持。我当年第一次用FPGA去读PHY的寄存器,波形抓出来自己都觉得离谱,后来才发现是保持时间差了那么一两个ns。嗯,这一章我们就专门把时序说清楚。

4.1 读时序:总线的“一问一答”

MDIO的读操作,说白了就是STA(主设备)先发命令帧,然后在 turnaround 阶段把总线让出来,由PHY(从设备)把数据送回来。整个过程完全由MDC时钟同步。

我习惯把读时序分成三段来看:

  • 命令阶段(前32个MDC周期):STA驱动MDIO,发送32位命令帧。包括前导码、起始码、操作码、PHY地址、寄存器地址,以及一轮turnaround的高阻态准备。
  • Turnaround阶段(第32~33个MDC周期):第一个周期STA把MDIO置为高阻,第二个周期PHY接管总线,把MDIO拉到低电平作为“我准备好了”的应答。
  • 数据阶段(第34~49个MDC周期):PHY在每个MDC上升沿输出数据,高位在前。STA在上升沿采样即可。

关键点:读操作中,turnaround的第二拍(第33周期)必须由PHY驱动为“0”。如果这个位不是0,说明PHY没有正确响应地址,你读回来的数据全是垃圾。我在调试一块TI的DP83822时遇到过——焊接虚焊导致MDIO引脚电压不稳,turnaround位老是1,折腾了两天才定位到问题。

4.2 写时序:全程由主设备驱动

写操作就简单多了——STA全程控制MDIO,PHY只管接收。命令阶段一样发32位帧,区别在于操作码是"01",并且在turnaround阶段STA直接输出地址和数据,没有高阻切换。

具体来说:

  1. 前32位与读操作相同(除了操作码)
  2. 第33周期,STA把MDIO拉低(固定位,表示写操作有效)
  3. 第34~49周期,STA逐位输出16位数据,在MDC上升沿被PHY锁存

写操作没有“应答”机制。你发出去,PHY就默默收了。所以调试写时序时,最稳妥的办法是写一个值,再读回来验证。嗯,这招很好用。

4.3 关键时序参数:最小周期、建立时间、保持时间

IEEE 802.3标准里对MDIO时序有明确约束。我把最常用的三个参数列在下面——说白了,这就是MDIO调试的底线,踩了必挂。

参数 符号 最小值 最大值 说明
MDC周期 tcyc 400 ns 无严格上限 对应最大频率2.5 MHz
MDC高/低脉冲宽度 thigh / tlow 160 ns — 占空比建议40%~60%
MDIO建立时间(相对MDC上升沿) tsetup 10 ns — 数据必须在时钟沿之前稳定
MDIO保持时间(相对MDC上升沿) thold 10 ns — 数据在时钟沿之后须维持有效

实战经验:很多微控制器自带的MDIO控制器跑400ns周期没问题,但当你用GPIO模拟时,很容易因为中断或任务调度导致周期抖动。我建议模拟时目标周期取1μs以上,留足余量。你想想看,多数PHY内部状态机切换本身就有几十ns延迟,时序越宽裕越不容易出诡异问题。

4.4 建立时间与保持时间的物理意义

建立时间,就是数据相对于时钟上升沿必须提前稳定的时间。保持时间,是时钟沿之后数据还要保持稳定的时间。这两个参数联合锁定了采样窗口——PHY内部寄存器在每个MDC上升沿处捕捉MDIO电平。如果数据在窗口边缘抖动,就可能读到错误值。

我在调试Marvell 88E1512时碰到过:用示波器看建立时间明明有8ns,但每读几次就出一个错位的数据。后来发现是MDC走线太长,反射导致上升沿附近有毛刺,等效地把建立时间压缩到了5ns以下。加了源端匹配电阻才解决。

警告:不要认为“只要主设备能跑,时序就没问题”。MDC和MDIO的PCB走线长度差、IO驱动强度、管脚寄生电容,都会影响实际时序。我曾经在一个项目中把MDIO从PHY拉到连接器,再通过扁平线到另一块板——结果保持时间被走线电容拖到了负值,读回来的寄存器永远不对。老老实实在PHY侧加缓冲器,或者降频到500kHz以下才稳。

4.5 时序图:一张图看懂读/写差异

MDIO读/写时序对比框架 MDC CLK 读命令帧 (32 bit) Turnaround 读数据 (16 bit) 读操作:第32周期结束前,STA释放MDIO;PHY在第33周期拉低应答 数据在MDC上升沿由PHY驱动,STA采样 MDC CLK 写命令帧 (32 bit) Turnaround 写数据 (16 bit) 写操作:全程由STA驱动MDIO;第33周期STA拉低作为写应答 数据在MDC上升沿由PHY锁存,需满足建立/保持时间 关键时序参数 t_cyc ≥ 400ns | t_high/t_low ≥ 160ns | t_setup ≥ 10ns | t_hold ≥ 10ns PCB走线长度、IO驱动强度、寄生电容都会影响实际窗口,建议至少留50%余量

4.6 实战中如何验证时序

我调试MDIO时序,通常用两个手段:

  • 示波器测量法:抓MDC和MDIO两路信号,测量上升沿附近的建立/保持时间。注意探头负载电容(10pF级)会影响高频测量,最好用有源探头或尽量将探头接地环缩短。
  • 回读验证法:写一个固定值(比如0xA5A5)到某个可读写的寄存器,再读回来。连着读100次,看有没有错误。如果有,缩小范围检查时序或者降频。

小技巧:有些调试工具(比如Xilinx的IBERT或Intel的In-System Sources)支持调整MDC的相位。你可以将MDC采样沿从上升沿改为下降沿,看读数据是否稳定。如果稳定了,说明原始时序窗口不够,需要调整走线或IO延时。我习惯在FPGA内部加一个可编程延迟链,用来微调MDIO输出相对于MDC的相位,这比改PCB快得多。

4.7 常见时序问题及排查思路

现象 可能原因 排查方向
读数据偶尔跳变 建立时间不足或MDC抖动 降频、检查MDC是否含毛刺、增加IO驱动强度
写操作后读回全为0 turnaround位错误或PHY未正确锁存 检查第33周期电平、核对PHY地址
所有读写操作无响应 MDC无时钟、MDIO上下拉电阻错误 示波器看两线电平、验证硬件连接
特定PHY寄存器总是旧值 写时序保持时间不够,PHY采样到的是前一拍数据 加大t_hold测量、调整数据输出时机

再次强调:我曾经用GPIO模拟MDIO在STM32上跑,MDC周期只有500ns,结果读某款Microchip PHY时,数据第三位永远错。查到最后发现是PHY内部需要额外的t_hold(标准要求10ns,该PHY实际需要15ns),GPIO翻转速度不够。最终把MDC周期拉到1μs,问题消失。所以,别太信任参数表上的最小值。