一.以太网硬件架构概述
前文讲述了以太网的一些相关知识,本文将详细讲解以太网的硬件架构
以太网的电路架构一般由MAC、PHY、变压器、RJ45和传输介质组成,示意图如下所示:
PHY:Physical Layer,即物理层。物理层定义了数据传送与接收所需要的电与光信号、线路状态、时钟基准、数据编码和电路等,并向数据链路层设备提供标准接口。简单来讲,就是PHY芯片决定了电信号/光信号如何传输。PHY主要是个模拟芯片,我们只要稍微了解一下就行。在千兆以太网设计中,PHY芯片一般都是独立的集成芯片,并不需要在FPGA层面上来设计PHY,我们只需要掌握好PHY和MAC之间的接口,以及PHY的一些常见寄存器配置即可。
MAC:Media Access Control,即媒体访问控制。MAC是数据链路层的芯片,它的功能是提供寻址机构、数据帧的构建、数据差错检查、传送控制、向网络层提供标准的数据接口等功能。
隔离变压器:Transformer,也叫网络变压器。它主要实现电气上的功能而不实现逻辑功能。比如增强信号从而使传输距离更远;使芯片端与外部隔离,大大增强抗干扰能力,同时对芯片起到了很大的保护作用(如雷击)。理论上变压器不是必需的,没有变压器以太网物理层也能正常工作,只是电气性能会下降,传输距离会受限。
RJ45:网络连接器,RJ是Registered Jack的缩写即 “注册的插座” 。网络连接器并不一定是RJ45,只是目前在千兆以太网中,RJ45是最常见的连接器。它实现的是连接不同主机的网络接口的功能。
传输介质:也就是俗称的 “网线” 。电信号/光信号在这上面以一定的规范进行传输,它是发送和接收信息的载体。传输介质可以分为有线和无线两个大类,有线就是我们日常生活中常见的网线,而无线则是电磁波,例如WIFI和手机通讯等。
1.PHY芯片
PHY是物理层的芯片,它负责实现数据在物理层的传输功能。PHY芯片将数字信号转换为模拟信号,并把它发送到通信介质上;同时从接收的模拟信号中恢复出数字信号,再传输到上层芯片处理。
PHY在发送数据的时候,收到MAC过来的数据(对PHY来说,没有帧的概念,对它来说,都是数据而不管什么地址、数据还是CRC校验值),然后把并行数据转化为串行流数据,再按照物理层的编码规则把数据编码,再变为模拟信号把数据送出去;收数据时的流程反之。
PHY芯片的主要作用是通过网络介质(例如双绞线或光纤)传输数据。具体地说,它需要完成以下任务:
- 将数字信号转换为模拟信号,并输出到网络介质上
- 监测网络介质上的信号质量,并根据需要调整发送功率、电流等参数
- 从网络介质上接收模拟信号,并将其还原为数字信号
- 根据协议规范和控制器芯片的指令,对接收到的数据进行错误检测、纠错、解码等处理
- 将处理后的数据输出到MAC芯片或其他高层芯片进行进一步处理
PHY芯片的类型有很多,以我的开发板上的RTL8211F为例,其工作时的框图如下所示:
其结构框图如下所示:
引脚分配组成如下:
这里只需要了解其比较重要的几个对外接口即可:
MDIO接口:即Management Data Input/Output,管理数据输入输出接口,也称为 SMI 接口(Serial Management Interface,串行管理接口)。它的主要功能是对PHY内部的寄存器进行读取和配置,速率比较低,一般在10M以下,协议也比较简单。现在的PHY其实都设计得比较先进了,一般上电就可以直接使用,比不需要对内部寄存器进行多余的配置,除非一些特殊的需求。但为了确保PHY的稳定运行,有时候也需要定时读取PHY的一些状态寄存器来确定其处于正常的运行状态。
MDI接口:即Medium Dependent Interface,介质相关接口。它连接的是物理层芯片即PHY和传输介质,也就是说发数据时,MAC把数据通过xMII接口传递到PHY,PHY进行编码等一系列处理后,通过MDI接口发送到传输介质,这样就把数据从主机传出去了;接收数据的过程类似。
RGMII接口:PHY 的 MII 接口有很多种, 例如 MII、 GMII、 RGMII、 SGMII、 XGMII、 TBI、 RTBI 等。其中 RGMII 的主要优势在于,它可同时适用于 1000M、 100M、 10M三种速率,而且接口占用引脚数较少。但也存在缺点,其一, PCB 布线时需要尽可能对数据、控制和时钟线进行等长布线。其二,对其时序约束较为严格。
2.RGMII接口信号
RGMII 使用 4bit 数据接口采用上下沿 DDR(Double Data Rate)的方式在一个时钟周期内传输 8bit 数据信号,即上 升沿发送或者接收数据的低 4 位[3:0],下降沿发送或者接收数据的高 4 位[7:4]。同理,使用1bit控制接口采用 DDR 的方式在一个时钟周期内传输 2bit 控制信号,即在上升沿发送或者接收数据使能信号(TX_EN、RX_DV),下降沿发送数据错误信号与使能信号的逻辑异或值(TX_ERR xor TX_EN、RX_ERR xor RX_DV),根据该信号可以计算出相应的数据错误信号。
发送端:
TXC:发送数据信号和控制信号对应的同步时钟信号(125M、25M、2.5M)
TXD[3:0]:发送数据信号,4bit位宽
TX_CTL:发送控制信号 发送端信号时序如下图所示。
接收端:
RXC:接收数据信号和控制信号对应的同步时钟信号(125M、25M、2.5M)
RXD[3:0]:接收数据信号,4bit位宽
RX_CTL:接收控制信号接收端信号的时序如下图所示。
发送端: 关于发送端 TX_EN(GMII_TX_EN)、TX_ERR(GMII_TX_ER)、TXD[7:0]信号不同组合对应的含义如下图表所示。
在大部分应用中,我们只需要关注最后两种即可。当 TX_CTL 上升沿和下降沿均为 1 时,表示数据有效,无任何错误。当TX_CTL上升沿为 1,下降沿为0时,表示当前时钟周期的8位数据错误。
接收端: 同理,接收端关于 RX_DV(GMII_RX_DV)、RX_ERR(GMII_RX_ER)、RXD[7:0]信号不同组合对应的含义如下图表所示。
与发送端类似,我们首先需要关注最后两种,即当 RX_CTL 上升沿和下降沿均为 1 时,表示数据有效,无任何错误。当 RX_CTL 上升沿为 1,下降沿为 0 时,表示当前时钟周期的数据错误。 除此之外,表中前三项是很有意义的组合类型,这也是为什么 RGMII 接口可以同时支持 1000/100/10M 三种速率的一个重要因素。它利用数据帧(frame)之间的 发送间隔传递当前连接的状态信息。通过这些信息可以判断当前链路的状态、速率、双工情况。
RGMII 接口适用于1000M、100M、10M三种传输速率。
当工作于 1000M 时,时钟信号 TXC 和 RXC 均为 125MHz,4bit 数据信号上下沿值均有效,控制信号上下沿值也 均有效。
当工作于 100M 时,时钟信号 TXC 和 RXC 均为 25MHz,4bit 数据信号只有上升沿值[3:0]有效,相当于此时数据信号切换为单沿 SDR(Single Data Rata)4 位传输模式。控制信号仍为上下沿有效。
当工作于 10M 时,时钟信号 TXC 和 RXC 均为 2.5MHz,数据信号和控制信号的使用不 100M 速率时完全相同。
3.RGMII接口时序
对于FPGA来说,这是一种典型的DDR源同步接口。当RGMII接口工作于1000M速率时,TXC 和 RXC 时钟信号都为 125MHz,那么单个接口的数据率便等同于 250Mbps,单个信号的有效数据窗最大为4ns。在 FPGA 中设计高速源同步接口的重点在于时序控制和时序约束。
一般的 PHY 芯片都支持两种 RGMII 发送端口的时序关系。一种称为非延时模式,如下图所示。
即要满足时钟信号 TXC 的边沿对准数据信号 TXD[3:0]和控制信号 TX_CTL 有效窗口中心附近的位置,也就是说TXC 比其他信号存在 2ns(90°相位)左右的延时。
另一种为延时模式,如下图所示。
这种时序要求 TXC 的边沿与其发送的数据 TXD 和控制信号 TX_CTL 边沿对齐,所有信号具有相同的相位。一般来说,大部分 PHY 芯片默认都是采用正常时序模式(非延时模式),可通过 MDIO 接口设置寄存器,或者芯片特殊功能引脚将其配置为延时模式。
RGMII 接收端口同样也存在两种时序关系,同为非延时和延时模式。非延时如下图所示。此时,时钟信号 RXC不跟RXD 和 RX_CTL的边沿对齐,具有相同的相位。
延时模式如下图所示:
RTL8211FD 通过设置引脚为上拉或者下拉来设置延迟,这里需要用户注意的是虽然开发板硬件上没有明确上拉和下拉,但是开发板上RTL8211依然工作在delay模式下,以下是发送或者接收接口的延迟设置:
-
4.原语使用
在 7 系列 FPGA 中实现 RGMII 接口需要借助 5 种原语,分别是:IDDR、ODDR、IDELAYE2、ODELAYE2(A7 中没有)、IDELAYCTRL。 其中,IDDR 和 ODDR 分别是输入和输出的双边沿寄存器,位于 IOB 中。IDELAYE2 和ODELAYE2,分别用于控制 IO 口输入和输出延时。同时,IDELAYE2 和 ODELAYE2 的延时值需要使用原语IDELAYCTRL 来进行校准。另外,需要注意的是,在 7 系列器件的 HR Bank 中没有 ODELAYE2,只有在 HP BANK 中才有 ODELAYE2)。 IDDR 将输入的双边沿 DDR 信号,在输出端恢复为两个并行单边沿 SDR 信号。IDDR 的原语如下。详细参数可参考 UG471。
IDDR #(
.DDR_CLK_EDGE("OPPOSITE_EDGE"), // "OPPOSITE_EDGE", "SAME_EDGE" // or "SAME_EDGE_PIPELINED"
.INIT_Q1(1'b0), // Initial value of Q1: 1'b0 or 1'b1
.INIT_Q2(1'b0), // Initial value of Q2: 1'b0 or 1'b1
.SRTYPE("SYNC") // Set/Reset type: "SYNC" or "ASYNC"
)
IDDR_inst (
.Q1(Q1), // 1-bit output for positive edge of clock
.Q2(Q2), // 1-bit output for negative edge of clock
.C(C), // 1-bit clock input .CE(CE), // 1-bit clock enable input
.D(D), // 1-bit DDR data input
.R(R), // 1-bit reset
.S(S) // 1-bit set
);
C 为同步时钟,Q1 和 Q2 则是分别从 C 上升沿和下降沿同步的输出的 SDR 数据,D 为 DDR 输入。参数DDR_CLK_EDGE 用来决定了 C、Q1、Q2 和 D 之间的时序关系。DDR_CLK_EDGE 有 3 种模式:OPPOSITE_EDGE、 SAME_EDGE 以及 SAME_EDGE_PIPELINED,3 种时序关系如下图所示。
一般来说,OPPOSITE_EDGE 模式使用较少。SAME_EDGE和SAME_EDGE_PIPELINED的区别在于,SAME_EDGE 模式时的Q1比SAME_EDGE_PIPELINED 模式时的 Q1 提前了一个时钟周期。显然,对 RGMII 接口来说使用SAME_EDGE 模式会造成两个相邻时钟周期之间的数据错位,因此,只能采用 SAME_EDGE_PIPELINED 模式。
ODDR 使用 ODDR 将 TXC 同一个时钟周期内的两个 SDR 信号分别通过上升沿和下降沿输出为 DDR 信号。
ODDR #(
.DDR_CLK_EDGE("OPPOSITE_EDGE"), // "OPPOSITE_EDGE" or "SAME_EDGE"
.INIT(1'b0), // Initial value of Q: 1'b0 or 1'b1
.SRTYPE("SYNC") // Set/Reset type: "SYNC" or "ASYNC"
)
ODDR_inst (
.Q(Q), // 1-bit DDR output
.C(C), // 1-bit clock input
.CE(CE), // 1-bit clock enable input
.D1(D1), // 1-bit data input (positive edge)
.D2(D2), // 1-bit data input (negative edge)
.R(R), // 1-bit reset
.S(S) // 1-bit set
);
ODDR 只需要 1 个时钟信号输入 C,D1 和 D2 则是分别在 C 的上升沿和下降沿同步的数据输入,Q 为 DDR 输出。参数DDR_CLK_EDGE 用来决定了 C、D1、D2 和 Q 之间的时序关系。DDR_CLK_EDGE 有两种模式:OPPOSITE_EDGE
和 SAME_EDGE,两种时序关系如下图所示。
对于 OPPOSITE_EDGE 模式,在 FPGA 内部也同样需要两个反相时钟来同步 D1 和 D2,较少使用。在设计 RGMII
接口时使用了 SAME_EDGE 模式。
IDELAYE2 IDELAYE2 用于在信号通过引脚进入芯片内部之前,进行延时调节。这里给出本方案中的用法,原语描述如下。详细参数可参考 UG471。
IDELAYE2 #(
.IDELAY_TYPE("FIXED"), // FIXED, VARIABLE, VAR_LOAD, VAR_LOAD_PIPE
.REFCLK_FREQUENCY(200.0),// IDELAYCTRL clock input frequency in MHz (190.0-210.0, 290.0-310.0)
.IDELAY_VALUE(0), // Input delay tap setting (0-31).
) IDELAYE2_inst (
.CNTVALUEOUT(), // 5-bit output: Counter value output
.DATAOUT(DATAOUT), // 1-bit output: Delayed data output
.C(1'b0), // 1-bit input: Clock input
.CE(1'b0), // 1-bit input: Active high enable increment/decrement input
.CINVCTRL(1'b0), // 1-bit input: Dynamic clock inversion input
.CNTVALUEIN(5'h0), // 5-bit input: Counter value input
.DATAIN(1'b0), // 1-bit input: Internal delay data input
.IDATAIN(IDATAIN), // 1-bit input: Data input from the I/O
.INC(1'b0), // 1-bit input: Increment / Decrement tap delay input
.LD(1'b0), // 1-bit input: Load IDELAY_VALUE input
.LDPIPEEN(1'b0), // 1-bit input: Enable PIPELINE register to load data input
.REGRST(REGRST) // 1-bit input: Active-high reset tap-delay input
);
IDATAIN 为延时前的输入,DATAOUT 为对应延时之后的输出。REFCLK_FREQUENCY 参数用来设置输入
IDELAYCTRL 的参考时钟频率,IDELAY_VALUE 参数用来设置延时的 tap 数。其余参数保持默认值即可。
IDELAYCTRL IDELAY2 和 ODELAY2 都需要 IDELAYCTRL 来迚行校准。IDELAYCTRL 原语如下。更多详细信息可参考 UG471。
IDELAYCTRL IDELAYCTRL_inst (
.RDY(RDY), // 1-bit output: Ready output
.REFCLK(REFCLK), // 1-bit input: Reference clock input
.RST(RST) // 1-bit input: Active high reset input
);
IDELAYCTRL 需要一个参考时钟信号 REFCLK 来校准 IDELAY2 和 ODELAY2 每个 tap 的延时值,可用的 REFCLK 频率为 200M、300M、400M。时钟越高对应的 tap 延时平均值越小,也就是说延时调节精度越高。大部分情况下使用 200M 的参考时钟就可以满足实际需求。
二.MAC芯片
关于以太网的帧结构前文就已经进行了讲解,如下图所示。
首先MAC需要提供一个前导码,这个前导码是用来实现数据同步的。其次MAC要在一帧数据中添加上源MAC地址和目的MAC地址,因为以太网是一个多主机构成的星型结构,如果不添加上源地址和目的地址,那发出去的数据是没法找到对应的主机的,而且对应的主机也不知道要给谁回复。
因为以太网上层还可以跑IP协议/ARP协议等其他协议,所以需要用一段数据来标识这一帧数据的上层协议是什么。最后为了保证数据传输的正确性,需要添加上一个CRC校验值。
在以太网数据这一段,里面的数据并不完全是有效数据,它还可能包含了IP协议的首部和UDP协议的首部,以UDP协议为例,它的数据结构是这样的:
可以看到,在MAC的以太网帧的数据段,它是由IP首部+数据段组成。IP首部是实现IP协议的关键,它封装的是一些网络层的信息,比如源IP地址和目的IP地址等。IP层的数据段又可以分成UDP首部+数据段。UDP首部是实现UDP协议的关键,它封装的是一些传输层的信息,比如源端口和目的端口等。UDP协议再往上一层就是应用层了,这一层的数据才是原始数据。
三.RJ45
以太网通信离不开连接端口的支持,网络数据连接的端口就是以太网接口。以太网接口类型有 RJ45 接口、RJ11 接口(电话线接口)、SC 光纤接口等。其中 RJ45 接口是我们现在最常见的网络设备接口 (如:电脑网口)。
RJ45 接口俗称“水晶头”,专业术语为 RJ45 连接器,由插头(接头、水晶头)和插座(母座)组成, 属于双绞线以太网接口类型。RJ45 插头只能沿固定方向插入,设有一个塑料弹片与 RJ45 插槽卡住以防止脱落。其示意图如下: