PHY芯片的功能与架构

咱们做硬件设计的,几乎天天要和PHY打交道。尤其搞以太网,PHY就像是我们和物理世界的翻译官。我记得刚入行那会儿,总觉得PHY就是个黑盒子,能通就行。后来被眼图、误码率折磨了几回,才不得不静下心来,把它扒了个干净。

这一章,咱们就把PHY的底裤给掀了。不整那些虚头巴脑的理论,就说说它到底干啥,内部怎么搭的。只有把基础夯扎实了,后面调寄存器、改眼图才有底气。

1.1 PHY芯片到底在做什么?

说白了,PHY芯片就是负责数字信号和模拟信号之间的转换。MAC侧甩过来一堆并行的数字信号,PHY得把它串行化,然后再调制到物理介质上去。反过来,从网线上收到变形的模拟信号,PHY也得给它解调、恢复成干净的数字信号送给MAC。

我习惯把PHY的功能拆成三块:

  • 发送路径:把MAC给的并行数据编码、加扰、序列化,最后差分打出去。
  • 接收路径:把差分信号均衡、时钟恢复、解码,最后并行送回MAC。
  • 管理接口:通过MDIO/MDC让CPU或者控制器能读写内部寄存器,控制工作模式、查状态、调参数。

注意: 很多刚上手的朋友容易把PHY和MAC搞混。MAC管的是数据链路层,打包解包,跟协议打交道;而PHY只干体活,纯模拟+数字混合。我见过一次项目,工程师调了三天MAC的寄存器,说链路建立不起来。后来一看,PHY的复位引脚都没拉高。嗯,这种事在实验室里不算少见。

1.2 内部架构概览

PHY的内部架构其实很经典。不同厂商的寄存器或许布局不一样,但核心模块大差不差。我下面画了张图,把主要模块和它们之间的数据流理出来了。你一看就明白数据是怎么从MAC到网线的。

PHY芯片内部核心架构与数据流 PHY芯片内部核心架构与数据流 MAC / RGMII / SGMII 并行数据或 PCS编码帧 接收数据流向MAC PCS 编码/解码 8B/10B, 4B/5B PMA 串/并转换 CDR + 时钟恢复 PMD 符号映射/解映射 PAM调制,MLD 均衡器 / 滤波 FFE, DFE 噪声抑制 + 回波抵消 Auto MDI/MDIX 极性自动翻转 MDIO 管理接口 —— 寄存器配置、状态读取、协商控制 以太网线 / 光纤 MDIO: 由MAC侧控制器通过MDC时钟读写 Auto-MDIX: 自动交叉线/直连线检测,省心啊

读图小提示: 这张图里数据从左到右。MAC通过MII或SGMII把帧交给PHY,经过PCS编码、PMA串行化、PMD调制,最后从差分对或者光口出去。接收方向反过来,但多了均衡和CDR环节。我当年对着这张图硬啃了一个礼拜才把寄存器里的偏移量和眼图参数对上号,值得收藏。

1.3 内部关键模块

下面我把几个常打交道的模块拎出来,展开聊聊。调眼图改善信号质量,其实主要就在均衡器和PMD这两块做文章。

1.3.1 PMA 与 PCS

PCS(物理编码子层)负责把MAC给的数据按照协议编码。比如千兆时用8B/10B编码,百兆用4B/5B。为什么编码?说白了就是为了保证直流平衡、有足够的跳变沿给时钟恢复。我曾经碰到过一个案子,百兆一直不通,查了三天,最后发现PCS的编码方式配错了,百兆模式下误配成了千兆的8B/10B。设备正常才怪。

PMA(物理介质接入子层)更偏模拟。它负责串并转换和时钟恢复。CDR是里面的灵魂。如果你的PCB布线不好,或参考时钟抖动大,CDR就锁不住相位,直接反映为链路断连或者误码。

模块 主要职责 调试中需要关注的寄存器
PCS 数据编码、解码、同步头插入 PCS控制寄存器、编码模式选择
PMA 串行化、时钟恢复、信号检测 CDR锁定状态、信号检测阈值
PMD 符号映射、调制解调、PAM 输出幅度、预加重、TX摆幅
均衡器 信道补偿、噪声抑制、回波抵消 FFE/DFE系数、均衡强度、AGC增益

1.3.2 PMD 与均衡技术

PMD决定了最终线缆上信号的波形。你调眼图时看到的张开度、抖动,很大程度就是PMD模块的发力点。输出幅度、预加重/去加重、摆幅控制这些寄存器全在这里。你想想看,一个信号从芯片出去,先过连接器,再过变压器,再过线缆,每一步都在损耗。如果不做预加重,远端的信号早就塌成一条直线了。

我习惯的步骤是这样的:

  1. 先设 baseline:把输出幅度调到datasheet推荐的中值,关掉均衡。
  2. 测远端:在长线或者劣质线缆下测眼图,看闭合度和抖动。
  3. 一点一点加预加重:每加一档,重新抓眼图,看改善。别一次加满,容易过冲把信号搞坏。
  4. 收端补偿:调整接收侧的DFE系数,观察误码率。

我自己的经验: 做百兆产品的预加重时,每增加5%的幅度,眼高能提升15mV左右,但功耗也随之增加;千兆产品更敏感,要看好IEEE 802.3ab的模板。调寄存器不麻烦,麻烦的是不知道每档对应的实际效果。所以才需要在实验室一档一档测,记录数据。多留点时间给这个阶段,总比流片或量产后再改强。

1.3.3 MDIO 管理接口

这个接口是我们和PHY沟通的唯一窗口。两线制:MDC(时钟)和MDIO(数据)。通过它,我可以读写任何寄存器。每个PHY都有一个物理地址,由硬件引脚决定。一个MDIO总线最多挂32个PHY。

读寄存器最简单的一个例子:

// 伪代码示意:读取 PHY 地址 0x01 的 BMSR 寄存器(地址 0x01)
uint16_t read_phy_reg(uint8_t phy_addr, uint8_t reg_addr) {
    uint16_t data = 0;
    // 1. 发送前导码(32个连续1)
    // 2. 发送起始码(01)
    // 3. 发送操作码(10 表示读)
    // 4. 发送 PHY 地址(5bit)
    // 5. 发送寄存器地址(5bit)
    // 6. 插入第2个周期(Z态)
    // 7. 读取 PHY 返回的 16bit 数据
    // 8. 返回读取结果
    return data;
}
// 调用:status = read_phy_reg(0x01, 0x01);
// 如果 status bit.2 == 1,表示链路已建立(Link Status)

避坑提醒: 我曾经在一个工控项目上,MDC的时钟频率设到25MHz。手册上写最大能到25M,但在实际板子上干扰太大,读回来的寄存器值时不时跳一个位。后来我把MDC降到2.5MHz,一切稳定了。MDIO对时序并不敏感,不必追求高速,稳定才是硬道理。另外,读状态寄存器前最好连续读两次,确认结果一致,防止毛刺。

1.4 实战:怎么判断一颗PHY是否正常工作?

拿到一块新板子,或者换了一颗PHY,我通常按下面几个步骤确认基础功能:

  • 第一步:检查硬件——电压、复位时序、参考时钟。很多问题卡在这里。时钟如果差几百ppm,CDR大概率锁不住。
  • 第二步:读PHY ID寄存器(通常是寄存器2和3)。能读到厂商ID和型号,说明MDIO通。
  • 第三步:读BMSR(寄存器1)。看Link Status bit是否置位。如果不置位,查连接器和变压器。
  • 第四步:跑PMA/PMD loopback。数据在PHY内部打环,不经过线缆。通的话,证明PHY核心功能没问题。
  • 第五步:看眼图。有示波器的话,直接量RX差分对的信号,看眼高、眼宽、抖动。高信号质量是调试的基础。

一个小技巧: 如果你没有示波器抓眼图,可以读一些PHY提供的内部眼图寄存器(比如信号质量指示、SNR估算值)。虽然精度有限,但至少能告诉你现在信道好不好。我就是从这条路径开始,慢慢理解了眼图跟寄存器配置之间的关系。