第二章 以太网基础与PHY芯片:MII/RMII/GMII/RGMII接口详解、PHY芯片配置与管理(MDIO)、自动协商与链路建立
各位同学,咱们今天聊聊以太网最底层的那些事。说实话,很多做FPGA的朋友一上来就撸MAC层、撸ARP,结果板子调不通,最后发现是PHY芯片没配好。嗯,这种坑我踩过不止一次。
以太网物理层,说白了就是解决两个问题:怎么把数据变成电信号发出去,以及怎么把收到的电信号变回数据。而PHY芯片就是干这个活的。FPGA和PHY之间怎么通信?靠的就是MII、RMII这些接口。
核心要点:FPGA内部实现MAC层,PHY芯片处理物理层。两者之间的接口标准决定了你的设计能跑多快、占多少引脚。
2.1 MII/RMII/GMII/RGMII接口详解
先看一张图,这是我个人习惯画的接口对比图,能帮你快速建立整体认知。
2.1.1 MII - 媒体独立接口
MII是IEEE 802.3u定义的标准接口。为什么叫"媒体独立"?因为它不关心底层用的是什么物理介质——双绞线、光纤都行。你想想看,这对FPGA设计者来说多友好。
MII的数据线是4位宽的。在100M模式下,时钟跑25MHz,一个时钟周期传4位,正好100Mbps。10M模式时钟就降到2.5MHz。
关键信号:
- TXD[3:0] - 发送数据,4位并行
- RXD[3:0] - 接收数据,4位并行
- TX_CLK / RX_CLK - 发送/接收时钟,由PHY提供
- TX_EN - 发送使能
- RX_DV - 接收数据有效
- CRS / COL - 载波检测/冲突检测(半双工用)
我的经验:MII接口虽然引脚多,但时序相对宽松。我在一个百兆项目中用过,调试起来很直观。缺点是16根线占FPGA引脚太多,现在新设计很少用了。
2.1.2 RMII - 精简MII
RMII是MII的"瘦身版"。数据线从4位砍到2位,时钟统一用50MHz。引脚数从16降到9,省引脚效果立竿见影。
为什么能省?因为RMII把时钟统一了,不再区分TX_CLK和RX_CLK。数据在50MHz时钟下,每个时钟传2位,100Mbps刚好。
RMII的坑:
- 需要外部50MHz时钟源,或者由PHY提供
- CRS和COL信号被编码到RX_DV里了,半双工处理稍麻烦
- 参考时钟必须同源,否则会有跨时钟域问题
我曾经踩过的坑:有一次用RMII接一个国产PHY,时钟抖动偏大,导致数据采样出错。后来加了PLL做时钟整形才解决。所以选PHY芯片时,时钟质量一定要看datasheet里的jitter指标。
2.1.3 GMII - 千兆MII
到了千兆时代,MII的4位数据线不够用了。GMII把数据线扩展到8位,时钟跑到125MHz。8位×125MHz = 1000Mbps,数学上很完美。
GMII的引脚数高达24根,这在PCB布局时简直是噩梦。我记得第一次画千兆板子,光GMII的走线等长就调了一整天。
2.1.4 RGMII - 精简千兆MII
RGMII是现在最流行的千兆接口。它用DDR技术——时钟的上升沿和下降沿各采一次数据。4位数据线×125MHz×2 = 1000Mbps。引脚数降到12根,比GMII少了一半。
RGMII时序要点:
- 时钟和数据之间有固定的相位关系
- 发送方向:FPGA提供时钟,数据与时钟对齐
- 接收方向:PHY提供时钟,数据与时钟有90度偏移
重要:RGMII的接收端,数据相对于时钟有90度相位偏移。很多FPGA的IOB里自带延迟链,可以用来调整这个相位。如果不用,你得在逻辑里手动做相位补偿。
2.2 PHY芯片配置与管理(MDIO)
PHY芯片不是焊上去就能用的。你得告诉它:工作在什么模式?要不要开自动协商?LED怎么闪?这些配置都通过MDIO总线来完成。
MDIO全称Management Data Input/Output,只有两根线:
- MDC - 管理时钟,由MAC侧提供,最高频率2.5MHz
- MDIO - 管理数据,双向传输
MDIO的帧格式是这样的:
| 前导码(32个1) | 起始码(01) | 操作码 | PHY地址(5位) | 寄存器地址(5位) | 转向(2位) | 数据(16位) |
操作码有两种:
- 01 - 写操作
- 10 - 读操作
举个例子,读PHY的寄存器0(基本控制寄存器):
// MDIO读操作时序(Verilog伪代码)
// 1. 发送32个1作为前导码
// 2. 发送起始码 01
// 3. 发送操作码 10(读)
// 4. 发送PHY地址,比如 00001(PHY地址1)
// 5. 发送寄存器地址 00000(寄存器0)
// 6. 等待2个转向位
// 7. PHY返回16位数据
我建议:写MDIO驱动时,最好把前导码做够32个时钟。有些PHY芯片要求严格,少了前导码就不响应。我遇到过一颗芯片,非得发满32个1才肯理你,少一个都不行。
常用PHY寄存器:
| 寄存器地址 | 名称 | 功能 |
|---|---|---|
| 0x00 | 基本控制寄存器 | 软件复位、环回、速率选择、自动协商使能 |
| 0x01 | 基本状态寄存器 | 链接状态、自动协商完成、能力检测 |
| 0x02 | PHY标识符高16位 | 芯片型号识别 |
| 0x03 | PHY标识符低16位 | 芯片型号识别 |
| 0x04 | 自动协商通告能力 | 通告本端支持的速率和工作模式 |
| 0x05 | 链路伙伴能力 | 读取对端通告的能力 |
2.3 自动协商与链路建立
自动协商是PHY芯片最智能的功能。两个PHY连在一起,它们会自动商量:用最快的共同速率、最好的工作模式。
过程是这样的:
- 上电后,PHY发送FLP(快速链路脉冲)
- FLP里包含本端支持的能力信息
- 双方交换能力信息后,选择最优的共同配置
- 链路建立,Link Up指示灯亮起
自动协商的优先级:
- 1000BASE-T全双工(最高优先级)
- 1000BASE-T半双工
- 100BASE-TX全双工
- 100BASE-TX半双工
- 10BASE-T全双工
- 10BASE-T半双工(最低优先级)
我曾经遇到的一个问题:有次设备连不上交换机,查了半天发现是自动协商没成功。原因是PHY的寄存器4(通告能力)里没使能100M全双工。写代码时漏了这一位,结果两边协商失败,链路起不来。所以调试时,先读寄存器1看看自动协商完成位有没有置1。
调试自动协商的步骤:
- 读寄存器1,检查链接状态位(bit 2)
- 读寄存器1,检查自动协商完成位(bit 5)
- 读寄存器5,看对端支持什么能力
- 读寄存器6,看最终协商结果
如果自动协商失败,可以强制设置速率和双工模式。写寄存器0的bit 12(禁止自动协商),然后设置bit 13(速率选择)和bit 8(双工模式)。
总结一下:PHY芯片的配置,说白了就是通过MDIO读写十几个寄存器。但就是这十几个寄存器,搞不定的话板子就哑巴了。我的习惯是:先读寄存器2和3确认PHY型号,再读寄存器1看状态,最后根据需求配寄存器0和4。按这个顺序来,基本不会出大问题。
嗯,以太网物理层的内容就这些。接口选型、MDIO配置、自动协商,这三块搞明白了,PHY芯片这块你就拿下了。下次咱们聊MAC层的实现,到时候你会发现在PHY上花的时间都是值得的。
个人建议:初学者可以先从RGMII入手,它兼顾了性能和引脚数。选一颗主流PHY芯片,比如Realtek的RTL8211系列,datasheet写得清楚,网上资料也多。调通了RGMII,其他接口就是换汤不换药。