
拿到“深入剖析10/100Mbps 10BASE-T ETHERNET PHY”这个项目时我第一反应不是翻原理图而是先把项目名拆开看。10/100Mbps代表双速自适应能力10BASE-T代表10M双绞线以太网PHY代表物理层收发器。项目名里那个ETHERENT其实就是ETHERNET的笔误不影响理解但恰好说明这类项目往往是半学习半工程的性质——你需要自己把链路从底层啃起来而不是直接调库调协议栈。这类项目通常有两条路线一条是在FPGA里自己实现PHY的PCS/PMA逻辑另一条是外挂一颗商用PHY芯片通过MII/RMII接口把MAC和物理层对接起来。无论走哪条路本质都是要搞清楚以太网最底层那段链路是怎么工作的编码、电平、时钟、协商、信号完整性问题全在这一层爆发。这篇文章我把整个项目的技术脉络、关键设计和现场调试经验按条理重新串一遍适合正在做网络接口板卡、FPGA以太网项目、或者单纯想把PHY啃透的嵌入式开发者。内容不算短但每一段都有实际项目里的对应场景可以直接对照自己的板子看。1. 项目核心定位PHY在以太网链路里到底管什么1.1 标题拆解10M、100M、双绞线、物理层是四件事项目标题里最有价值的信息是“10/100Mbps”和“10BASE-T”连在一起。很多人容易误读成10BASE-T是10M标准、100M就是100BASE-TX两者关系不大——实际上10BASE-T和100BASE-TX在物理层共享了接口形态都是使用双绞线中两对线都通过RJ45连接器接入都依赖PHY芯片完成信号收发。不同的是编码方式、信号速率、传输电平和链路建立机制完全不同。我在做这个项目时第一步不是在代码里建工程而是在文档里把四条链路状态写清楚10BASE-T数据速率10Mbps信号速率也是10MHz量级曼彻斯特编码发送电平为±2.2V对线间差分约2.5V一对线发送一对线接收。早期的HUB网络都是基于这种物理机制。100BASE-TX数据速率100Mbps线路信号速率125Mbps采用4B5B编码加MLT-3三电平传输信号能量集中在31.25MHz以上带宽需求比10M高得多。同样使用两对线却能做到全双工同时收发。物理层收发器也就是PHY负责把MAC送来的并行数据变成串行比特流调制到线对上同时把线对收到的模拟信号解调成数字位流交给MAC。相当于网线和MAC之间的翻译官。自协商双速PHY必须处理10M和100M设备互联。两边速度不一致时通过协商脉冲交换能力最终确定双方都支持的最高速度链路才算建立。标题说“深入剖析”本质上就是要把这四件事放在一条链路上打通。没有PHY芯片做黑盒你得能看到寄存器、眼图、误码和波形才算真正“剖析”了。1.2 PHY和MAC怎么分工整条链路是谁在干体力活要理解PHY项目先得把以太网分层拉出来。软件工程师平时接触的是TCP/IP、网卡驱动而PHY位于OSI第一层——物理层。硬件上PHY芯片一端连接MAC媒体访问控制层另一端连接RJ45和变压器。具体到信号路径MAC发送方向MAC把帧数据通过MII接口并发送出提供TX_CLK、TX_EN、TXD[3:0]信号。PHY接收这些并行数据拼成串行比特流加上前导码、帧界定符编码成线路信号送到线对。PHY接收方向线对上的差分信号经过变压器进入PHYPHY完成均衡、时钟恢复、解码、去扰还原出MII信号再通过RX_CLK、RX_DV、RXD[3:0]交回MAC。所以MAC管的是“帧”PHY管的是“比特和符号”。很多调试问题很隐蔽就是因为责任边界混淆。CRC错误可能是MAC组帧错误也可能是PHY解码时引入跳变FCS错误但信号质量很好可能问题出在MII时钟采样沿信号完全不通但寄存器正常可能卡在自协商或变压器极性。我做这个项目时有一条铁律无论问题多诡异先把PHY侧能力验证干净。具体说就是用MDIO/MDC总线读PHY寄存器确认能够读到PHY ID然后看链路状态寄存器有没有显示协商完成。如果PHY自己状态都不对就不要去查驱动和协议栈那是在错误楼层找错误房间。1.3 双速PHY的硬件“最小系统”构成一个标准的10/100M双速PHY项目硬件上必须有这几样东西模块作用关键点PHY芯片物理层收发支持10/100M自适应25MHz晶振提供PHY参考时钟频率精度要求50ppm以内网络变压器隔离、共模抑制中心抽头处理影响信号质量RJ45连接器线缆接入可带屏蔽或带灯MAC接口并串转换MII/RMII二选一MDIO/MDC寄存器管理上电初始化必须的通道忽略其中任何一块链路都可能反复出问题。我见过有人只接了PHY和RJ45但网络变压器中心抽头悬空结果能够协商上千兆位却完全不通——这种问题用示波器是能看出来的但如果你没有这个概念会白白排查一整天。2. 关键链路底层10BASE-T与100BASE-TX是怎么在物理上跑起来的2.1 曼彻斯特编码10M速率看上像一串脉冲10BASE-T最核心的概念是曼彻斯特编码也是这个项目里第一个要摆脱“玄学”窠臼的地方。曼彻斯特编码把每个比特拆成两个half-bit逻辑1表现为先高后低的跳变逻辑0表现为先低后高的跳变。在10MHz时钟下每个比特周期的中间必然有一次跳变用来携带数据和时钟。这意味着线路有效信号速率其实高于10Mbps一个数据比特占100ns宽度但跳变密度让频谱更宽。接收端可以从跳变中恢复时钟不需要独立的时钟线。空闲状态无数据时线对呈现空闲电平并每16ms发送一个正常链路脉冲Normal Link Pulse来探测对端。后续自协商就是在这套脉冲基础上做的扩展。实测10BASE-T波形时你会看到一串宽度约100ns的脉冲簇中间是正负交替。不要直接用普通IO去采用差分探头或者经过变压器次级测试否则看到的是共模信号混着差模信号很难判断。我在FPGA里模拟实现过10BASE-T的接收端踩过一个坑数据中间跳变之后还可能出现因为线路反射带来的抖动导致采样点落在跳变沿附近。解决方法是接收端用自己的本地时钟锁相用数字PLL调整采样相位而不是简单过零检测。这说明即便是10M这么老的速率也不代表没有信号质量工程。2.2 100BASE-TX4B5B加MLT-3三电平传输100M链路是项目里另一个大块。100BASE-TX标准其实是借用FDDI的物理层定义了4B5B编码和MLT-3线路编码。4B5B是为了保证线路信号足够多跳变把每4比特数据映射成5比特码组一些码组还承担控制功能如流开始、流结束、空闲。MLT-3则有三个电平正电平、负电平和零电平。它通过状态机在三个电平间跳转且每个比特周期只可能从当前状态变到相邻状态这就降低了信号带宽。看似100M数据速率线路实际符号速率125MBaud而基波大概在31.25MHz左右。100M以太网不是“每秒传100M个符号”而是“每秒传100M个数据比特外加25M编码冗余”。4B5B码表要在项目初期就整理出来发送端查表输出、接收端逆映射。不要试图用状态机硬推直接上查找表时序好收敛。我见过有人用if-else级联判断码型结果综合后组合逻辑太大时序跑不过。改成ROM查表后问题立即解决。2.3 自协商机制FLP脉冲包怎么决定双方速度双速项目里最容易被挑战的是自协商。自协商的核心是一组快速链路脉冲FLP由一串间隔不同的link pulse组成。设备发送自己的能力字包括10BASE-T半双工、10BASE-T全双工、100BASE-TX半双工、100BASE-TX全双工以及流控能力两端通过交换能力字按优先级表取双方最高公共交集。实际调试中自协商有不少“反直觉”点提示自协商FLP优先级表中100BASE-TX全双工最高然后是100BASE-TX半双工再是10BASE-T全双工最后是10BASE-T半双工。如果对端是只支持10M的老旧设备它会回送只有10M能力的字双方最终落在10M上。自协商不成功大多数情况是双方能力字不匹配或电气质量差导致FLP被冲掉。排查时先用寄存器看本端能力字是否写正确再检查对端能力寄存器通过MDIO读到的Autonegotiation Link Partner Ability寄存器可以直接看到对方通告的能力。读不到对端能力说明物理层根本没起来先去查变压器和端接电阻。我处理过一块板子一直协商不上最后发现RJ45连接到变压器之间的一颗共模电阻虚焊导致发送端回波干扰了接收端。补充一个经验即使双方都支持100M有时也会故意降级到10M。比如对端设备驱动强制了10M模式或者线缆只有两对线但质量很差PHY的DSP判断线缆状态后主动降低速率。这种情况看PHY状态寄存器里的速度指示别只信对端驱动的报告。3. 硬件接口与调试准备MII、寄存器、变压器三板斧3.1 MII接口时序25MHz与2.5MHz的切换是灵魂10/100M双速PHY和MAC之间最经典的接口是MII4位并行数据发送时钟TX_CLK在100M下25MHz在10M下变成2.5MHz。接收时钟RX_CLK同样跟随链路速度变化。这个细节特别重要——很多人代码里把时钟频率写死切速率后时序全乱。MII关键信号一览信号方向作用TX_CLK输入发送时钟25/2.5MHzTX_EN输入发送使能有效期间数据有效TXD[3:0]输入发送数据RX_CLK输出接收时钟25/2.5MHzRX_DV输出接收数据有效RXD[3:0]输出接收数据CRS输出载波侦听COL输出冲突检测半双工用MDC输入管理时钟MDIO双向管理数据FPGA里做MAC连接MII时建议直接用PHY提供的TX_CLK作为发送域时钟。如果用本地PLL生成独立的发送时钟相位与PHY期望不一致很容易采样错数据。我踩过这个坑同样的逻辑在不同板卡上表现不一样就是因为时钟来源不同导致建立保持时间裕量不同。改成直接用外部时钟后问题消失。10M模式下2.5MHz时钟低得可怜做时序约束时容易掉以轻心。但要注意时钟频率降低不代表组合逻辑能无限加大因为计数器位宽变大后依然可能超时。这条在仿真里看不出来上板后才暴露。3.2 寄存器初始化MDIO读回PHY ID是首个里程碑PHY的寄存器地图里最重要的前几个固定寄存器是寄存器0控制寄存器复位、速度选择、自协商使能、全双工设置。寄存器1状态寄存器链路状态、协商完成、能力指示。寄存器2、3PHY标识符读回后可以确认MDIO通道和芯片型号。寄存器4本端自协商能力通告。寄存器5对端自协商能力通告。首次调试时我习惯先做一个最小化MDIO读写测试。上电、给PHY复位释放、等待一段时间然后通过MDIO连读寄存器2和3如果读回特定ID值至少说明两条结论电源正常、MDIO时序正常。这个里程碑比尝试ping通来得更关键。曾经有一块板子怎么都ping不通但PHY ID能读查下来是MAC侧时钟配置错误导致MII没干活。如果当时直接从PHY开始怀疑会绕很大一圈。MDIO协议本身是串行管理接口写寄存器时先发控制码、地址再发数据读寄存器时最后两个字节为高阻态。如果MCU的GPIO模拟MDIO注意MDIO是双向口读时序要切换方向。我建议用逻辑分析仪抓一拍看总线上有没有12位的寄存器地址字段。很多人时序方向切换慢半拍导致读回全为1。3.3 变压器选型和端接信号能不能过眼图全看这里PHY项目经常有个误区以为变压器是标准件随便选。实际上网络变压器除了隔离还承担共模抑制、浪涌防护和阻抗变换的角色。10/100M双速项目里变压器变比通常1:1线圈中心抽头用于偏置。关键设计点有三个中心抽头处理很多PHY要求发送端中心抽头接VCC通常3.3V或2.5V接收端通过端接电阻连接到地或公共点。具体按PHY手册要求接不要凭经验套。Bob Smith端接RJ45侧线对间会有端接电阻和电容网络用于电磁兼容。漏掉这部分辐射会偏高轻微干扰会造成丢包。共模电感线对输入端通常串共模扼流圈抑制外部共模干扰。布局时尽量靠近连接器。我调试过一块板子和交换机连接后速率协商正常但长时间运行偶尔出现CRC错误。用频谱仪看到192MHz频点能量异常高最后定位到变压器次级端接电容值选错谐振峰落在噪声频段。换回推荐值后异常消失。如果项目是自研PHY逻辑而不是外挂芯片变压器后端的模拟前端一样需要仔细匹配。PHY芯片的发射电流、摆率、平衡度都影响辐射和接收灵敏性。10BASE-T时代平衡度要求没有100M那么苛刻但既然做双速还是要留出测试点至少能把PHY差分输出引到测试夹具上。4. 实操过程从上电到ping通一个10/100M PHY要几步4.1 搭建最小系统FPGAPHY变压器的接线顺序假设项目是基于某FPGA加外挂百兆PHY的形态最小系统搭建顺序可以这样走。先保证供电PHY的数字电源和模拟电源通常分开有些PHY有内部LDO但多数要求外接精度不低于3%的电源。上电顺序上先给PHY主电源再给I/O电源。同时确认复位信号有效时间和释放时电源已经稳定。然后连MII把PHY的TXD/RXD连接到FPGA引脚中间建议预留串阻22欧姆左右方便调试时断开或调整。注意时钟引脚要接在专用时钟引脚上不要随意放在普通IO。MII时钟25MHz并不快但若FPGA内部走线不均匀还是有风险。接着接管理接口MDIO上拉电阻一般2.2k欧姆到1.8V或3.3VMDC时钟频率建议不超过2.5MHz早期标准上限2.5MHz用GPIO模拟时不要太快。MDC太快容易遇到PHY内部寄存器访问时序不满足的情况莫名读到错误值。最后接RJ45模块变压器和RJ45尽量一体化或者紧邻。启动前用万用表量一下线对正负防止交叉线对。我实际操作时会用一块转接板把MII信号引接到逻辑分析仪上。刚开始不追求跑通协议只观察TX_CLK是否在切换速率后变成预期频率。这是判断PHY初始化有没有成功的最快速方法。4.2 上电检查顺序先用寄存器说话别急着调驱动上电后第一件事读PHY ID。如果读回不一致检查MDIO时序和PHY地址。PHY地址通常由引脚上下拉决定不要想当然硬编码。部分芯片默认地址不是0而是通过LED或CONFIG引脚设定。第二件事读寄存器1检查bit2链接状态和bit5自动协商完成。如果链接状态为0说明物理层没有和对端握手先看自协商有没有使能。寄存器0的bit12为自协商使能如果手册默认值不是1需要手动置位。配置完自协商后重置PHY单片机先写寄存器0 bit15为1等待自清链路会重新建立。第三件事读寄存器4和寄存器5确认本端通告能力和对端通告能力。很多链路失败实际是能力字不一致造成。例如本端只通告了100M全双工而对端只支持半双工双方没有共同点链路始终是down的。改成通告全速全双工后协商立刻成功。整个过程中我不碰MAC驱动和协议栈先把PHY状态确认到位。这个顺序能避免很多“按下葫芦浮起瓢”的问题。因为PHY状态不正确时上层再怎么调都是假象。4.3 从10M跑到100M速度切换时MAC侧要跟着动当自协商完成后PHY速度变化MAC侧必须跟着变。外置PHYMII接口下MAC检测到RX_CLK频率变化就知道链路速度变了。但FPGA内部逻辑不能写死发送时钟域和接收时钟域都要做动态适配。我碰到过一个具体案例10M模式下收发都正常切换到100M后丢包严重。查了很久最后发现FPGA内部FIFO的深度写死了10M模式下数据量小FIFO不溢出100M模式下突发帧连续进来FIFO溢出丢帧。这不是PHY问题是MAC设计没考虑带宽变化。速度切换另一个注意点是自协商完成后PHY会有一个“远端故障”Remote Fault标志位短暂出现如果驱动不处理可能导致链路被强制断开。代码里要在链接状态从down到up的过程中连续读取寄存器确认稳定不要只采一次状态就认为成功。调试中常用的命令和工具# Linux下查看PHY链路状态 ethtool eth0 mii-tool eth0 # MDIO直接读PHY寄存器需要root权限不同驱动路径有差异 # 假设使用mdio-tools mdio read eth0 2 mdio read eth0 3 mdio read eth0 1在FPGA项目中我习惯用在线逻辑分析仪触发MII信号。触发条件设为TX_EN上升沿或RX_DV上升沿观察一组完整帧的数据是否有错位。如果MAC连接的是RTL8211或者LAN8720这种常见PHY对应寄存器地址可能不同一定先查手册确认地址映射别套通用寄存器假设。4.4 用示波器看线对波形Manchester和MLT-3长什么样子示波器是PHY项目的王牌工具。直接把探头接到变压器次级或RJ45引脚用差分探头最理想。如果只有单端探头就接其中一根线对地看重点看跳变密度和幅度是否正常。10BASE-T波形典型样子空闲时为0V到某个电平发送数据时出现正负交替的脉冲簇。用示波器单次触发抓取正常波形应该是每个比特中间都有跳变脉冲宽度均匀。如果看到脉冲宽度抖动明显说明发送端时钟不准或铁氧体端接不合适。100BASE-TX波形MLT-3三电平输出正电平、零电平、负电平依次切换。示波器上看起来像一串梯形波幅度大概在±1V差分线对上的电压。如果波形幅度不足检查发送端电流设置和变压器抽头电压是否正常。MLT-3对连接器阻抗很敏感线缆过长或者接触不良会造成信号回波波形上表现为边沿台阶。我调试时习惯用示波器测量眼图。100M链路直接用高速示波器做眼图模板测试要求眼高、眼宽满足模板。但普通工程师手头未必有模板测试功能退而求其次看RX_CLK的抖动也可以。RX_CLK抖动过大说明远端信号质量或时钟恢复环路有问题。如果示波器带宽不够比如只有100MHz看不出细节那就退回到上寄存器法。10/100M PHY内部通常会提供信号质量指示位或接收能量等级位不同芯片名称不同。通过这些间接指标判断线缆质量和连接状态。5. 常见问题与排查实录PHY项目里的坑基本都在这些地方5.1 链路协商不上的共性原因协商不上是最常见的现象具体表现PHY状态寄存器bit20或者ethtool显示“Link detected: no”。我按概率排序排查线缆/接口问题用了只有两对线的线缆质量差或者线序做错。检查RJ45线对是否按照T568A/T568B打好并且两端一致或为交叉线。对端设备关闭了自动协商某些工业交换机端口强制模式PHY端如果还开着自协商不会连接。这种情况下可以强制本地PHY速度、双工模式与对端一致绕过协商。PHY寄存器里能力字丢了一部分例如只通告了10M能力。用寄存器4和5对比看看两端能力交集为空。MDI/MDIX极性反转现在很多PHY支持自动翻转但部分老芯片需要手动配置。如果线路直连不配对自动交叉没开启链路就是down的。变压器焊接不良某些开发板变压器焊盘虚焊间歇性导致协商失败。用力按压变压器外壳时链路恢复基本就是虚焊。提示协商不上时先把PHY配置成“自协商模式并回退到10M半双工”如果这能连接说明物理层基本没问题再逐级往上试100M全双工。二分法在这里非常管用。5.2 链路正常但数据不通MAC侧和PHY侧的接缝问题链路能协商成功说明PHY自身物理层OK。但数据不通问题就集中在MAC和PHY的接缝处。按经验排序MII接口信号极性接反TXD[3:0]顺序错位。用示波器或者逻辑分析仪抓MII总线比对MAC发出数据和PHY接收数据能否对上。接收时钟采样沿不对MAC用上升沿采样还是下降沿采样必须和PHY输出一致。如果采样沿选错偶尔能通但丢包严重。TX_CLK切换速度后MAC锁相环没跟上10M切100M时TX_CLK从2.5MHz变25MHz如果MAC时钟路径有PLLPLL重新锁定期间会丢很多帧。FIFO深度不够100M突发数据流下FIFO溢出。这个在上层看是丢帧但根因在MAC内部缓冲管理不在PHY。抓MII总线时我用逻辑分析仪采样率设置至少100MSa/s触发条件设为帧头。如果MAC发出的TXD和PHY驱动回读一致但RX方向错乱问题往往在PHY到MAC的接收数据通路。可以短接PHY的环回模式寄存器0 bit14为1PHY会把发送数据直接环回给接收端这样能快速判断是MAC发端错误还是PHY收端错误。5.3 一组板子偶发不通电源纹波和地弹是隐形杀手量产或小批量项目中偶发不通最磨人。假设10块板子9块跑通1块上电后协商失败换一块PHY芯片比如又好了。排除PHY芯片本身问题我强烈建议测电源纹波。用示波器交流耦合带宽限制20MHz测PHY供电管脚和MAC供电管脚。数字电路和模拟电路混在一起时地弹噪声最容易在PHY接收端表现为BER升高。10M信号冗余度大受影响小100M信号裕量小很可能协商失败或CRC错误。我处理过一次某板卡偶尔无法连接千兆交换机但连接百兆设备稳定。查下来是PHY电源和FPGA电源共用了同一颗DC-DC突发数据时IO翻转电流造成电源纹波超100mVPHY的模拟电路在这种噪声下拉不起稳定电平。解决方法是把PHY电源换到低噪声LDO并在靠近PHY电源引脚处加10uF陶瓷电容和磁珠隔离。所以项目一开始原理图评审就要检查PHY电源有没有独立滤波网络。另外布局上PHY芯片引脚去耦电容必须紧靠引脚走线不要先过孔再接电容——这个细节很多人忽略但影响很大。5.4 排查速查表现象可能原因排查顺序协商不上线序、自协商关闭、能力字不匹配查寄存器4/5换线测试能协商但ping不通MII采样沿错、数据线序错抓MII总线比对帧CRC错误多电源纹波、变压器端接不良、时钟抖动测电源、换变压器测试偶发断链干扰、虚焊、连接器接触不良压测逻辑分析仪长时间监测只有10M能通100M不行MLT-3信号质量差、DSP均衡问题看100M眼图调整PCB布线MDIO读不回PHY ID地址错、上拉缺失、时序过快检查PHY地址引脚和MDC频率6. 项目延展和个人经验做完这个PHY项目后路还能往哪走6.1 从10/100M PHY到千兆、到交换、到网卡设计的可复用逻辑做完10/100M PHY项目之后很多概念是能直接复用到千兆链路的。千兆PHY使用四对线、每对线速率达到125MBaud且采用5电平PAM5编码DSP均衡复杂度大幅增加。但基本分工还是MACPHY变压器管理接口还是MDIO只是寄存器扩展功能更多MDC频率要求可能不一样。有了双速PHY底子转过去并不难。FPGA里做MAC侧逻辑MII接口的时序约束、FIFO管理、状态机设计思路可以复用到RGMII接口。RGMII在百兆下时钟25MHz数据以DDR方式在上升沿和下降沿同时采样。接触了MII之后RGMII的问题主要集中在DDR时序上概念上是相通的。另外单独PHY项目还可以扩展成一个小型交换设计多个PHY加一个交换核心实现端口间帧转发。你会发现交换核心的学习、过滤、转发逻辑正是MAC层知识的延伸。从PHY往MAC、往上走脉络完全顺。6.2 自研PHY逻辑FPGA实现简化PCS/PMA的可行性如果你精力足够可以试着在FPGA内部实现一个简化版PHY替代外购芯片。实现10BASE-T是可行的曼彻斯特编码和解码都相对简单难点在模拟前端所以通常还是外挂收发器自己写数字部分。100BASE-TX难度会明显上升因为4B5B编码、MLT-3状态机、加扰/解扰器都是可以数字实现的。但时钟恢复需要模拟锁相环或高速采样这个在普通FPGA里做比较吃力。许多实验项目用LVDS接口加外部模拟前端也跑通过但这属于进阶方向需要充分评估工作量。我的建议是数字部分可以先做一遍彻底掌握模拟部分保留外置方案。这样项目目标明确又不会卡在模拟设计上太久。6.3 关于这个项目最后再分享几个身体力行攒下来的想法如果我重新做一次这个项目第一步一定不会是连网线而是花半天时间把PHY寄存器手册通读一遍。别觉得手册枯燥很多坑都写在你没看的那一页。就我见过的案例数据手册里的“时钟间关系”“最小复位时间”常被人跳过去结果成了后续调试的隐患。另外示波器探头地线尽量短。测试高速信号时地线长意味着探头形成回路电感测出来的波形带着振铃容易误判信号质量问题。我用的是弹簧地线比大风还要麻烦但测出来的波形成真。这个细节我提醒每一个做PHY项目的朋友。最后任何改动后先读PHY寄存器确认状态再跑协议栈测试。这个顺序可以帮你把变量隔离开物理层问题找电气数据链路问题找时序上层问题找软件。PHY项目天然适合这种分层debug法。把边界画清楚再复杂的网络问题也能一步步逼出真相。