一、RGMII特点
RGMII采用双沿传输(DDR接口),在CLK的上升沿和下降沿都各传输一次数据,同时,TX_ER 和RX_ER 信号编码进了TX_CTL 和RX_CTL 信号中,不再使用独立的信号线。这两个信号传输也是通过上升和下降沿来区分的。
二、RGMII 与 GMII 转换电路设计
RGMII的设计逻辑只需要在GMII逻辑的基础上增加单沿八位变双沿四位(双沿四位变单沿八位)的逻辑。
由于数据和时钟都是同时同向传输的,但是在接收端,需要时钟与数据的中心对齐。
这里有两种处理方式:
在发送端就将时钟和数据中心对齐
在发送端时钟和数据边沿对齐,通过PCB设计board delay或者在FPGA内部使用逻辑延迟或者PHY芯片内部有相应的延迟功能,使时钟和数据到达接受方时满足时序要求
1、FPGA通过RGMII发送
上图这个在altera FPGA中可以使用ALTDDIO_OUT IP 核,XILINX中使用的是IDDR和ODDR原语,将该接口使用任何支持双数据速率的I/O(DDIO)寄存器实现。
对于PHY,大多数支持RGMII 的PHY 芯片都提供了一个对发送时钟TX_CLK添加延迟的选项。可以根据设计要求启用或禁用此选项。当启用延迟PHY 设备内TX_CLK的选项时,FPGA 必须生成与数据和波形边缘对齐的时钟。
如果PHY的该功能被关闭,则FPGA必须对时钟信号进行一定的相位调整后再作为TX_CLK输出,以使TXD 和TX_CLK 成中心对齐关系。这时需要考虑PCB带来的延迟。
将源时钟与数据对齐的方法有多种。例如可以使用PLL 产生2 路相位相差90 度的时钟信号,一路作为DDIO_OUT 寄存器的工作时钟,一路作为TX_CLK 输出。当然,如果考虑到PCB 板上的TX_CLK 相对于TXD 的延迟值,该相位可以进一步调整以确保TX_CLK 到达PHY 时与TXD 呈中心对齐关系。如下图所示:
1、FPGA通过RGMII接收
大多数支持RGMII 的PHY 芯片都提供了一个对接收时钟RX_CLK 添加延迟的选项。可以根据设计要求启用或禁用此选项。当启用延迟PHY 设备内RX_CLK 的选项时,PHY 输出的RX_CLK 与RXD 会呈中心对齐的关系。在这种情况下,FPGA 就可以直接使用RX_CLK 来捕获输入的数据,而不需要再对RX_CLK 添加PCB 板级延迟,或者是在FPGA 内部对RX_CLK 添加延迟。
如果PHY 对RX_CLK 添加延迟的功能被关闭,则FPGA 必须对RX_CLK 时钟信号进行一定的相位调整后再用来捕获数据。这种情况,可以使用FPGA 内的PLL 将该信号进行一定的相位移动后再用来捕获数据。让RX_CLK 能够进入PLL,必须要求该信号是从FPGA 器件的专用时钟输入管脚或DQS 脚输入。
三、时钟设计
1、发送时
为了保证FPGA在发送数据和时钟时,到达PHY芯片时,时钟和数据的中心对齐,所以对传输到PHY的时钟tx_clk也经过一个DDIO_OUT核。调用了三个DDIO_OUT,一个4bit输入,一个一bit输入。
2、接收
对于RGMII接收,同样是调用两个ALTDDIO_IN 的IP 核就可以实现,其中一个ALTDDIO_IN核的端口位宽为4 位,用来接收4 位的RXD 信号;另一个ALTDDIO_IN 核的端口位宽为1位,用来接收RX_EN 和RX_ER 信号。下图为使用ALTDDIO_IN 核实现RGMII 接收的系统框图。
对于 RGMII接口来说,不仅需要作为 不仅需要作为 不仅需要作为 不仅需要作为时钟是由PHY产生的,此时钟作为FPGA内部接收rgmii_rx_data和rgmii_rx_ctl的,且它们之间必须满足前面所讲的时序要求。同时,rgmii_rx_clk不仅需要作为数据输入的时钟,而且还需要作为FPGA内部以太网解包逻辑的时钟。
所以rgmii_rx_ctl不能从普通的IO口接入FPGA,这样做可能导致时钟质量下降,或者使时钟和数据不满足时序要求。所以应该将该时钟信号接入FPGA的专用时钟管脚,使其能够接入FPGA内部的PLL,也能接入FPGA的全局时钟资源。并且万一rgmii_rx_clk不满足捕获要求,也能通过PLL进行相位调制。
四、verilog程序设计
首次应该设计出GMII接口的程序,使用状态机或者序列机将前导码、帧起始符、以太网帧头、ip数据依次通过8位数据端口发送出去。IP地址、MAC地址、端口等可以做成端口传输,也可以使用常量在顶层模块中重新赋值,然后在发送使能的时候将这些值赋给相应的暂存寄存器。
如果使用的是状态机的话,需要注意状态跳转的时序,每个状态中间数据发送没有间隙,所以若是使用两段或者是三段状态机的话需要注意提前将跳转条件置位。所以,可以考虑使用一段状态机,没有当前状态和下一状态跳转延迟,可以很简单的避免跳转不及时出错。
在发送之前需要将ip校验和先算出来,UDP校验和可以不用使用,赋0就行,最后在发送数据的时候,将发送的8位数据同时传输给CRC校验计算模块,待发送完所有的数据,CRC校验值同时也计算出来了,接着就可以发送CRC的值了。