以太网基础回顾:OSI模型与TCP/IP协议栈,MAC帧格式,以太网PHY芯片接口
各位同学,咱们今天聊点基础的,但也是最重要的东西。做UDP解析引擎,说白了就是在跟以太网打交道。你要是连以太网怎么传数据都不清楚,那后面的设计肯定要踩坑。我当年刚入行时,就吃过这个亏——上来就写RTL,结果MAC层和PHY层的时序怎么都对不上,折腾了两周才发现是接口理解错了。
好,咱们从头捋一遍。先看这张图,把整个知识体系串起来。
OSI模型与TCP/IP协议栈
先说说OSI七层模型。教科书上把它分成了物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。但说实话,咱们做FPGA的,真正打交道的就下面四层。上面三层,那是软件工程师的活。
TCP/IP协议栈更实在,直接给你浓缩成四层:
- 应用层:HTTP、FTP、TFTP这些。咱们的UDP解析引擎,最终服务的就是这层。
- 传输层:TCP和UDP。咱们要做的UDP,就在这里。UDP头只有8个字节,比TCP简单多了。
- 网络层:IP协议。负责路由和寻址。IP头20字节,里面有个总长度字段,咱们解析UDP时要用到。
- 数据链路层:MAC层。这是FPGA直接打交道的层。MAC帧怎么封装、怎么解封,全在这层。
我个人习惯:做硬件设计时,脑子里要时刻想着「数据流」。数据从PHY进来,经过MAC解帧,再到IP层解包,最后到UDP层提取数据。每一层都在做「剥洋葱」的工作。
你想想看,为什么我们要回顾这个?因为UDP解析引擎,本质上就是在FPGA里实现一个「硬件协议栈」。它要完成的工作,就是从物理层拿到原始比特流,然后一层层解析上去,直到把UDP数据提取出来。
MAC帧格式
好,重点来了。MAC帧格式,这是咱们写RTL时最常打交道的东西。我直接给你画个表格,一目了然。
| 字段 | 长度(字节) | 说明 |
|---|---|---|
| 前导码(Preamble) | 7 | 0x55重复7次,用于时钟同步 |
| 帧起始定界符(SFD) | 1 | 0xD5,标志帧开始 |
| 目的MAC地址 | 6 | 接收方MAC,全F为广播 |
| 源MAC地址 | 6 | 发送方MAC |
| 类型/长度(Type/Len) | 2 | 大于0x0600表示类型(如0x0800=IP),否则表示长度 |
| 数据(Payload) | 46~1500 | IP数据包,最小46字节(不足则填充) |
| 帧校验序列(FCS) | 4 | CRC32校验,覆盖目的MAC到数据字段 |
我曾经踩过一个坑:做千兆以太网时,前导码和SFD在GMII接口上是8个字节一起传的。但有些PHY芯片会把前导码吃掉,只给SFD。如果你没看数据手册,直接按标准帧格式去解析,第一个字节就对不上,整个帧就废了。
这里有个关键点:MAC层的最小帧长是64字节(从目的MAC到FCS)。为什么?因为要防止「冲突检测」出问题。如果帧太短,发送方还没检测到冲突就发完了,那CSMA/CD就失效了。虽然现在全双工模式已经不用CSMA/CD了,但这个约束一直保留着。
咱们做UDP解析时,IP头20字节 + UDP头8字节,所以UDP数据至少要有18字节才能凑够46字节的MAC数据段。如果数据不够,MAC层会自动填充0。这个细节,你在RTL设计时一定要处理。
以太网PHY芯片接口
PHY芯片,说白了就是把MAC层的数字信号转换成模拟信号,扔到网线上去。咱们FPGA和PHY芯片之间,通过GMII或RGMII接口通信。
GMII(千兆媒体独立接口)
GMII是并行接口,数据位宽8位,时钟频率125MHz。关键信号如下:
- TXD[7:0]:发送数据总线
- TX_CLK:发送时钟,125MHz
- TX_EN:发送使能,高电平表示TXD有效
- TX_ER:发送错误,用于插入错误码
- RXD[7:0]:接收数据总线
- RX_CLK:接收时钟,由PHY提供
- RX_DV:接收数据有效
- RX_ER:接收错误
GMII的时序很简单:每个时钟周期,TXD/RXD上就是1字节数据。TX_EN拉高时,数据有效。但要注意,GMII用了25根信号线,PCB布线时很占地方。所以现在主流都用RGMII。
RGMII(简化千兆媒体独立接口)
RGMII把数据位宽减半,变成4位,但用DDR(双沿采样)来保持吞吐量。时钟还是125MHz,但上升沿和下降沿各传4位,合起来还是1字节。
RGMII的关键信号更少:
- TXD[3:0]:发送数据,上升沿传低4位,下降沿传高4位
- TX_CTL:发送控制,上升沿是TX_EN,下降沿是TX_EN XOR TX_ER
- RXD[3:0]:接收数据,同样DDR
- RX_CTL:接收控制,上升沿是RX_DV,下降沿是RX_DV XOR RX_ER
我建议:新手做RGMII时,一定要在FPGA内部做IODELAY校准。因为PCB走线长度不同,时钟和数据的相位关系会偏移。我见过有人直接拿RGMII信号去采,结果10次有3次采错。加个IODELAY,调到眼图中心,稳得很。
为什么RGMII要把TX_EN和TX_ER编码到一根线上?说白了就是为了省引脚。TX_CTL在上升沿传TX_EN,下降沿传TX_EN XOR TX_ER。接收端解码时,先采上升沿得到TX_EN,再用TX_EN去异或下降沿的值,就得到TX_ER了。这个小技巧,在RTL里实现起来也就几行代码。
嗯,这里要注意:RGMII的时钟是源同步的。发送时钟由发送端提供,接收时钟由PHY提供。所以你在FPGA里做RGMII接口时,接收时钟域和发送时钟域是异步的。跨时钟域处理,那是基本功了。
好了,以太网基础就回顾到这里。这些内容看起来简单,但每一个细节都可能在你的UDP解析引擎设计中冒出来。记住一句话:硬件设计,细节是魔鬼。
公众号:蓝海资料掘金营,微信deep3321