《FPGA以太网MAC收发链路设计与实现》

2、以太网基础:OSI模型与IEEE 802.3标准,MAC层功能与帧格式

以太网自诞生以来,经过四十余年发展,已成为有线局域网的事实标准。对于FPGA开发者而言,要在可编程逻辑中实现MAC(Media Access Control,介质访问控制)收发链路,首先必须透彻理解两个核心问题:以太网在OSI参考模型中处于什么位置?一个标准的以太网帧在MAC层究竟由哪些字段构成、每个字段的字节序和时序如何?本章将从OSI模型与IEEE 802.3标准的映射关系出发,深入剖析MAC层的功能边界,并以字节级精度拆解以太网帧格式,为后续FPGA中的RTL设计打下坚实的协议基础。

OSI 参考模型 应用层 (L7) 表示层 (L6) 会话层 (L5) 传输层 (L4) TCP/UDP 网络层 (L3) IP 数据链路层 (L2) LLC 子层 MAC 子层 ← FPGA实现 物理层 (L1) PHY IEEE 802.3 以太网帧结构(MAC层视角) 前导码 7字节 0x55 SFD 1字节 0xD5 目的MAC 6字节 源MAC 6字节 长度/类型 2字节 数据 46~1500字节 FCS 4字节 CRC32 帧间隙 IFG ≥96 bit-time 最小帧长 64 字节(不含前导码和SFD) 对应 MII/GMII FPGA MAC 设计关注点: • 前导码与SFD:接收时用于字节对齐与帧起始检测 • 目的/源MAC:地址过滤与匹配逻辑 • 长度/类型:区分Ethernet II 与 802.3 帧 • FCS:CRC32 校验,发送时生成、接收时验证 发送时序(从左到右): 前导码(7B) → SFD(1B) → 目的MAC(6B) → 源MAC(6B) → 长度/类型(2B) → 数据(46~1500B) → FCS(4B) 接收时序:检测SFD → 逐字节接收 → 地址匹配 → 长度/类型解析 → 数据提取 → CRC校验 注:前导码与SFD由PHY或MAC生成/去除,FPGA内部通常只处理从目的MAC开始的帧内容

2.1 OSI模型与IEEE 802.3标准的映射关系

核心原理:分层模型与协议栈定位

OSI(Open Systems Interconnection)参考模型将网络通信划分为七层,每一层只向上一层提供服务,并只依赖下一层提供的服务。在以太网中,IEEE 802.3标准实际上只定义了物理层(L1)和数据链路层(L2)中的MAC子层。数据链路层被进一步拆分为两个子层:逻辑链路控制子层(LLC,Logical Link Control)和介质访问控制子层(MAC)。LLC子层负责复用/解复用上层协议(如IP、ARP),而MAC子层则负责帧的封装/解封装、介质访问控制(CSMA/CD)、地址寻址和差错检测。

对于FPGA开发者而言,MAC层是必须用硬件逻辑实现的核心模块。MAC层向上通过LLC或直接与IP层交互,向下通过MII(Media Independent Interface)、GMII、RGMII等接口与PHY芯片连接。PHY芯片负责物理信号的编码、调制、串并转换等模拟域工作,而FPGA中的MAC逻辑则处理纯数字域的帧收发。

判断方法:区分帧类型与协议层次

在实际开发中,判断一个数据帧属于哪种类型(Ethernet II 或 IEEE 802.3)是MAC层设计的基本功。判断依据是长度/类型字段的数值:

  • Ethernet II帧(DIX帧):长度/类型字段值大于等于0x0600(1536),表示上层协议类型。例如0x0800表示IPv4,0x0806表示ARP,0x86DD表示IPv6。
  • IEEE 802.3帧:长度/类型字段值小于等于0x05DC(1500),表示后续数据字段的实际长度。此时需要LLC头(DSAP、SSAP、Control)来进一步区分上层协议。

FPGA实现时,通常只需支持Ethernet II帧格式,因为现代以太网设备几乎全部使用该格式。但MAC设计仍需保留对长度字段的解析能力,以便兼容旧设备或特殊应用场景。

案例拆解:一个ARP请求帧的层次解析

假设FPGA设备收到一个ARP请求帧,其十六进制前段为:FF FF FF FF FF FF 00 11 22 33 44 55 08 06 00 01 08 00 06 04 00 01 ...。逐字段解析:

字段值含义
目的MACFF:FF:FF:FF:FF:FF广播地址
源MAC00:11:22:33:44:55发送方MAC
长度/类型0x0806ARP协议(Ethernet II)
ARP头0x0001 0x0800 0x06 0x04 0x0001以太网+IPv4+MAC+IP+请求

FPGA在接收该帧时,MAC层只需识别目的MAC是否为广播地址或本机地址,然后将长度/类型字段值0x0806连同数据部分一起上交给上层协议处理模块。MAC层本身不解析ARP内容,这体现了分层设计的职责单一原则。

经验提醒:在FPGA的MAC接收设计中,建议将长度/类型字段单独寄存并随数据一起输出,而不是在MAC层就丢弃。这样上层模块(如ARP、IP解析)可以直接使用该字段进行协议分发,避免重复解析。

2.2 MAC层功能与帧格式详解

核心原理:MAC层的六大核心功能

MAC子层在IEEE 802.3标准中承担以下功能,这些功能在FPGA中对应具体的硬件逻辑模块:

  1. 帧封装与解封装:发送时添加前导码、SFD、目的/源MAC、长度/类型、FCS;接收时去除这些字段并校验FCS。
  2. 介质访问控制:半双工模式下实现CSMA/CD(载波侦听多路访问/冲突检测),全双工模式下则无需此功能。
  3. 地址管理:维护本机MAC地址,接收时进行地址过滤,只接收目的地址为本机、广播地址或组播地址的帧。
  4. 差错检测:发送时计算CRC32并附加为FCS字段;接收时重新计算CRC并与接收到的FCS比较,不一致则丢弃该帧。
  5. 帧间隔管理:发送完一帧后必须等待至少96 bit-time的帧间隙(IFG),以确保接收方有足够时间处理。
  6. 流量控制:全双工模式下支持Pause帧(802.3x),当接收缓冲区满时向对端发送暂停请求。

帧格式逐字段拆解

一个完整的以太网帧(不含前导码和SFD)由以下字段组成,FPGA设计时必须精确理解每个字段的字节序和时序要求:

字段长度值/范围FPGA处理要点
前导码(Preamble)7字节0x55重复7次用于接收时钟同步,FPGA接收时通常由PHY处理,MAC可忽略
SFD(帧起始定界符)1字节0xD5标志帧的开始,FPGA检测到SFD后开始接收有效数据
目的MAC地址6字节单播/广播/组播接收时进行地址匹配,不匹配则丢弃
源MAC地址6字节本机MAC发送时填入本机地址,接收时可用于学习
长度/类型2字节≥0x0600为类型,≤0x05DC为长度决定帧类型,FPGA需寄存并输出
数据(Payload)46~1500字节不足46字节需填充最小帧长64字节,数据不足时填充0
FCS(帧校验序列)4字节CRC32校验值发送时计算,接收时校验,错误则丢弃

案例拆解:最小帧与最大帧的构造

假设FPGA需要发送一个仅包含6字节数据的UDP报文(不含IP/UDP头),MAC层构造过程如下:

  • 数据字段实际长度 = 6字节,但最小帧要求数据字段至少46字节,因此需填充40字节的0x00。
  • 帧总长度 = 6(目的MAC)+ 6(源MAC)+ 2(长度/类型)+ 46(填充后数据)+ 4(FCS)= 64字节,恰好满足最小帧长要求。
  • 长度/类型字段填入0x0800(IPv4类型),而不是实际数据长度6,因为这是Ethernet II帧。
  • FCS计算覆盖从目的MAC到数据字段末尾的所有字节,使用标准CRC32多项式0x04C11DB7。

在FPGA发送逻辑中,需要设计一个状态机:空闲→发送前导码→发送SFD→发送目的MAC→发送源MAC→发送长度/类型→发送数据(含填充)→计算并发送FCS→等待IFG→回到空闲。每个状态对应一个时钟周期或一组时钟周期,数据宽度通常为8位(GMII)或4位(MII)。

风险提示:FPGA接收FCS校验失败时,不能简单丢弃整个帧而不做任何处理。在调试阶段,建议将错误帧的源MAC、长度/类型、错误位置等信息记录下来,便于定位是PHY配置问题、PCB信号完整性问题还是MAC逻辑缺陷。此外,接收FIFO的溢出也会导致帧被截断,需区分CRC错误与溢出错误。

2.3 前导码、SFD与字节序的硬件实现要点

核心原理:为什么前导码是0x55而不是0xAA

前导码的7字节0x55(二进制10101010)和SFD的0xD5(二进制11010101)组合在一起,形成连续的曼彻斯特编码跳变,用于接收端恢复时钟并实现字节对齐。在100Mbps及以上速率中,PHY芯片负责前导码的生成和去除,FPGA通过MII/GMII接口接收到的数据通常已经去除了前导码和SFD。但在10Mbps速率下,某些PHY配置可能将前导码透传给MAC,此时FPGA需要自行检测SFD。

字节序方面,以太网采用大端序(Big-Endian)传输,即最高有效字节先发送。MAC地址的传输顺序是从最高字节到最低字节,例如MAC地址00:11:22:33:44:55,先发送0x00,最后发送0x55。FCS字段的传输顺序则是CRC32结果的最高字节先发送。

判断方法:如何确定PHY是否已去除前导码

在FPGA调试中,可以通过以下方法判断PHY的行为:

  1. 查看PHY芯片的数据手册,确认其MII/GMII接口是否包含前导码。大多数现代PHY(如RTL8211、88E1512)默认去除前导码和SFD。
  2. 使用逻辑分析仪抓取GMII接口的TXD信号,观察帧起始时是否有连续的0x55。
  3. 检查PHY的寄存器配置,部分PHY提供"Transmit Preamble"或"Receive Preamble"使能位。

如果PHY透传前导码,FPGA接收逻辑必须包含SFD检测状态机:持续监测数据是否为0x55,当检测到0xD5时,下一字节即为目的MAC的第一个字节。

案例拆解:GMII接口上的帧时序

以GMII接口为例(8位数据,125MHz时钟),一个完整帧的发送时序如下:

时钟周期:  T0   T1   T2   T3   T4   T5   T6   T7   T8   T9   T10  T11  T12  T13  T14  T15
TXD[7:0]:  55   55   55   55   55   55   55   D5   DA   DA   DA   DA   DA   DA   SA   SA
TX_EN:     0    1    1    1    1    1    1    1    1    1    1    1    1    1    1    1

其中T0周期TX_EN为低,表示帧间隙;T1~T7发送前导码0x55;T8发送SFD 0xD5;T9~T14发送目的MAC(6字节);T15开始发送源MAC。FPGA发送逻辑需要精确控制TX_EN信号,确保在发送前导码的第一个字节时拉高,在FCS最后一个字节发送完成后拉低。

设计要点:在FPGA的MAC发送模块中,建议使用独立的计数器跟踪当前发送的字节序号,而不是依赖状态机的状态数量。例如,定义字节计数器byte_cnt,从0开始计数,0~6为前导码,7为SFD,8~13为目的MAC,14~19为源MAC,20~21为长度/类型,22~N为数据,N+1~N+4为FCS。这样便于灵活处理不同长度的数据帧,也方便添加填充字节。

2.4 常见误区与设计复盘

误区一:混淆最小帧长与数据字段长度

很多初学者将"最小帧长64字节"误解为"数据字段至少64字节"。实际上,64字节包含目的MAC(6)+源MAC(6)+长度/类型(2)+数据(46)+FCS(4)。当上层数据不足46字节时,MAC层必须填充到46字节。FPGA实现时,填充逻辑应在发送数据之前完成,且填充字节不计入上层协议的长度字段。

误区二:忽略FCS的计算范围

CRC32的计算范围是从目的MAC地址的第一个字节开始,到数据字段的最后一个字节(含填充字节)结束,不包括前导码、SFD和FCS本身。FPGA实现时,常见错误是将前导码也纳入CRC计算,导致发送端和接收端校验不一致。正确做法是:发送时在发送完数据字段后,立即输出CRC计算结果;接收时在接收完数据字段后,将本地计算的CRC与接收到的FCS逐字节比较。

误区三:地址过滤逻辑过于简单

有些设计只实现了单播地址匹配,忽略了广播地址(FF:FF:FF:FF:FF:FF)和组播地址(目的MAC最高字节最低位为1)。在FPGA接收逻辑中,地址过滤应支持三种模式:精确匹配、广播匹配、组播匹配(可选)。此外,还应支持混杂模式(接收所有帧),这在调试和网络分析中非常有用。

复盘总结:MAC层设计的核心清单

检查项设计要点验证方法
帧间隔IFG发送完成后至少等待96 bit-time用示波器测量两帧之间的间隔
FCS生成CRC32多项式0x04C11DB7,初始值0xFFFFFFFF,结果取反用Wireshark抓包验证
填充逻辑数据不足46字节时填充0x00构造短帧测试
地址过滤支持单播、广播、组播、混杂模式发送不同目的地址的帧验证
错误处理CRC错误、长度错误、溢出错误分别标记注入错误帧验证

以太网MAC层虽然协议简单,但FPGA实现中涉及大量时序细节。建议在RTL设计前,先用Python或C语言编写一个参考模型,逐字节模拟帧的封装和解析过程,生成测试向量。这样在FPGA验证阶段,可以直接用参考模型产生的标准帧作为激励,对比DUT输出,快速定位逻辑错误。