第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直接输出地址和数据,没有高阻切换。
具体来说:
- 前32位与读操作相同(除了操作码)
- 第33周期,STA把MDIO拉低(固定位,表示写操作有效)
- 第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 时序图:一张图看懂读/写差异
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,问题消失。所以,别太信任参数表上的最小值。