> 技术文档 > FPGA实现千兆网UDP协议(一):RGMII接口

FPGA实现千兆网UDP协议(一):RGMII接口


目录

一、RGMII接口介绍

二、RGMII接口定义

三、RGMII接口时序

1.FPGA接收数据时序

2.FPGA发送数据时序

四、RGMII模块设计

1.模块框图

2.顶层模块

3.rgmii_to_gmii模块

4.rgmii_rxd模块

5.rgmii_txd模块

6.运行结果

 


一、RGMII接口介绍

RGMII接口是FPGA芯片与PHY芯片进行通信的接口,全称Reduced Gigabit Media Independent Interface(吉比特介质独立接口),支持10 Mbps,100 Mbps和1000 Mbps的PHY层连接速度。

FPGA实现千兆网UDP协议(一):RGMII接口

 

 


二、RGMII接口定义

序号

引脚

方向

描述

1

TXC

MAC  →  PHY

发送时钟

2

TX_CTL

MAC  →  PHY

发送使能

3

TXD

MAC  →  PHY

发送数据

4

RXC

PHY  →  MAC

接收时钟

5

RX_CTL

PHY  →  MAC

接收使能

6

RXD

PHY  →  MAC

接收数据

7

MDC

MAC  →  PHY

PHY配置时钟

8

MDIO

MAC ←→ PHY

PHY配置读写

 

 

在1000 Mbps模式下,TXC和RXC为125 MHz,时钟的上升沿和下降沿同时传输数据,每次传输4bit数据。所以总速率为:125M*2*4bit / 1s = 1000Mbps。

本次实验FPGA开发板配套PHY芯片引脚定义如下:除去数据收发引脚,还有ETH_INT及PHYRSTB引脚, 用于初始化和复位,没有特殊需求一直给高电平芯片就能正常运行。

FPGA实现千兆网UDP协议(一):RGMII接口

 


三、RGMII接口时序

1.FPGA接收数据时序

FPGA实现千兆网UDP协议(一):RGMII接口

 

PHY芯片发送数据时,在时钟的上升沿发送字节的低4位,在下降沿发送字节的高4位。

当RX_CTL上升沿和下降沿均为1时,表示数据有效,无何何错误。

当RX_CTL上升沿为1,下降沿为0时,表示当前时钟周期的数据错误。

开发板卡在设计时通常会通过在PCB走线、在控制器端或在PHY芯片内部添加时钟偏移,让其工作在延时模式。

简言之就是PHY芯片发送的数据是在时钟的上升沿以及下降沿变化的,如下图。

FPGA实现千兆网UDP协议(一):RGMII接口

 

然后通过时钟偏移,偏移90度,让FPGA收到的时钟沿和数据的中心对齐,如下图。

FPGA实现千兆网UDP协议(一):RGMII接口

 

如果不做任何处理,FPGA是无法在时钟沿上正确的采集到每个数据。

本次实验所采用芯片为RTL8211E,如图2,根据芯片手册,如下表,16及32引脚均通过上拉电阻拉高,PHY芯片已经工作于延时模式。

 

PIN

PIN_NAME

DESCRIPTION

16

TXDLY

1: Add 2ns delay to TXC for TXD latching

32

RXDLY

1: Add 2ns delay to RXC for RXD latching

 

2.FPGA发送数据时序

FPGA实现千兆网UDP协议(一):RGMII接口

 

FPGA芯片发送数据时,在时钟的上升沿发送字节的低4位,在下降沿发送字节的高4位。

根据PHY芯片是否工作在延时模式,FPGA芯片对发送时钟进行调整。

如果PHY芯片是在延时模式,则发送时钟不做处理。

如果未在延时模式,则发送时钟偏移90度相位。

本次实验RTL8211芯片工作于延时模式,发送时钟不做处理。


四、RGMII模块设计

1.模块框图

主模块:rgmii_to_gmii模块

包含2个子模块:rgmii_rxd 模块, rgmii_txd 模块

FPGA实现千兆网UDP协议(一):RGMII接口

 

2.顶层模块

顶层按照原理图引入相关接口,MDC以及MDIO接口此处对PHY芯片无配置需求,暂不引入,引入clk_wiz IP核输出复位接口,引入ila IP核观测接口。

`timescale 1ns / 1psmodule top(input  sysclk ,output  eth_rst_n ,input  rgmii_rx_clk ,input[3:0]rgmii_rxd ,inputrgmii_rx_dv ,output  rgmii_tx_clk ,output[3:0]rgmii_txd ,outputrgmii_tx_en );wire rst_n;assign eth_rst_n = rst_n;clk_wiz_0 u0_clk_wiz_0 ( .reset (1\'d0 ), // input reset .locked (rst_n ), .clk_in1 (sysclk ) ); wire gmii_rx_clk ;wire gmii_rx_dv ;wire [7:0] gmii_rxd ;wire gmii_tx_clk ; wire gmii_tx_en ; wire [7:0] gmii_txd ;rgmii_to_gmii u1_rgmii_to_gmii(.gmii_rxc (gmii_rx_clk ),.gmii_rxdv (gmii_rx_dv ),.gmii_rxd (gmii_rxd ),.gmii_txc (gmii_tx_clk ),.gmii_txen (gmii_tx_en ),.gmii_txd (gmii_txd ),.rgmii_rxc (rgmii_rx_clk ),.rgmii_rx_ctrl (rgmii_rx_dv ),.rgmii_rxd (rgmii_rxd ),.rgmii_txc (rgmii_tx_clk ),.rgmii_tx_ctrl (rgmii_tx_en ),.rgmii_txd (rgmii_txd ) );ila_16 ila_u (.clk(gmii_rx_clk), // input wire clk.probe0({gmii_rx_dv,gmii_rxd}) // input wire [15:0] probe0);endmodule

3.rgmii_to_gmii模块

例化rgmii接口的收发模块

module rgmii_to_gmii( outputgmii_rxc ,  outputgmii_rxdv , output [7:0] gmii_rxd , outputgmii_txc ,  input gmii_txen , input  [7:0] gmii_txd , input rgmii_rxc , input rgmii_rx_ctrl ,  input  [3:0] rgmii_rxd , outputrgmii_txc , outputrgmii_tx_ctrl ,  output [3:0] rgmii_txd );assign gmii_txc = gmii_rxc; rgmii_rxd rgmii_rxd_inst( .rgmii_rxc (rgmii_rxc ), .rgmii_rx_ctrl (rgmii_rx_ctrl ), .rgmii_rxd (rgmii_rxd ), .gmii_rxc (gmii_rxc  ), .gmii_rxdv (gmii_rxdv ), .gmii_rxd (gmii_rxd  ) );rgmii_txd rgmii_txd_inst( .gmii_txc (gmii_txc ), .gmii_txen (gmii_txen ), .gmii_txd (gmii_txd ), .rgmii_txc (rgmii_txc ), .rgmii_tx_ctrl (rgmii_tx_ctrl ), .rgmii_txd (rgmii_txd ) );endmodule

4.rgmii_rxd模块

通过IDDR原语,对PHY芯片输入的双沿信号处理成单沿信号,包含使能信号以及4bit数据信号。

使能信号处理方式为:时钟的上下沿使能信号同时为高电平时,在下一个时钟输出高电平,只要有一个沿为低电平,最终就不会输出高电平。

数据信号处理方式为:时钟的上沿数据作为低4bit,下沿数据作为高4bit,在下一个时钟组合输出一个8bit数据。

module rgmii_rxd( input  rgmii_rxc , input  rgmii_rx_ctrl , input [3:0] rgmii_rxd , output gmii_rxc , output gmii_rxdv , output [7:0] gmii_rxd ); wire rgmii_rxc_bufio; //全局时钟IO缓存wire [1:0] gmii_rxdv_t;  //上下沿有效信号 BUFG BUFG_inst ( .I (rgmii_rxc), // 1-bit input: Clock input .O (gmii_rxc) // 1-bit output: Clock output);BUFIO BUFIO_inst ( .I (rgmii_rxc), // 1-bit input: Clock input .O (rgmii_rxc_bufio) // 1-bit output: Clock output);IDDR #( .DDR_CLK_EDGE(\"SAME_EDGE_PIPELINED\"),// \"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 (gmii_rxdv_t[0]), // 1-bit output for positive edge of clock .Q2 (gmii_rxdv_t[1]), // 1-bit output for negative edge of clock .C (rgmii_rxc_bufio), // 1-bit clock input .CE (1\'b1),  // 1-bit clock enable input .D (rgmii_rx_ctrl), // 1-bit DDR data input .R (1\'b0),  // 1-bit reset .S (1\'b0)  // 1-bit set);assign gmii_rxdv = gmii_rxdv_t[0]&gmii_rxdv_t[1];genvar i;generate for (i=0; i<4; i=i+1) begin : rxdata_bus  IDDR #( .DDR_CLK_EDGE(\"SAME_EDGE_PIPELINED\"),// \"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 (gmii_rxd[i]), // 1-bit output for positive edge of clock .Q2 (gmii_rxd[4+i]), // 1-bit output for negative edge of clock .C (rgmii_rxc_bufio), // 1-bit clock input rgmii_rxc_buf .CE (1\'b1),  // 1-bit clock enable input .D (rgmii_rxd[i]),  // 1-bit DDR data input .R (1\'b0),  // 1-bit reset .S (1\'b0)  // 1-bit set ); endendgenerateendmodule

仿真结果如下:

1.上下沿数据同时有效:

信号名称         信号定义 rgmii_rxc PHY芯片输入的时钟 rgmii_rx_ctrl   PHY芯片输入的使能信号 rgmii_rxd    PHY芯片输入的4bit数据 gmii_rxdv    模块输出的使能信号 gmii_rxdv 模块输出的8bit数据

 

 

在112ns时上升沿采样到低4位4’b0001,在116ns时下降沿采样到高4位0010,在120ns时将前两次采样的结果组合成8’b00100001输出。

FPGA实现千兆网UDP协议(一):RGMII接口

 

2.上下沿数据非同时有效:

在112ns时上升沿采样到低4位4’b0001,在116ns时使能信号消失,下降沿未采样高4位数据,在120ns时将不会有数据输出。

FPGA实现千兆网UDP协议(一):RGMII接口

 

5.rgmii_txd模块

    将输入的8bit信号以及使能信号处理成双沿信号,通过ODDR原语实现。

module rgmii_txd( input  gmii_txc , input  gmii_txen , input [7:0] gmii_txd , output rgmii_txc , output rgmii_tx_ctrl , output [3:0] rgmii_txd );assign rgmii_txc = gmii_txc;// TX CTRL DDR OUTPUTODDR #( .DDR_CLK_EDGE (\"SAME_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 (rgmii_tx_ctrl), // 1-bit DDR output .C (gmii_txc), // 1-bit clock input .CE (1\'b1), // 1-bit clock enable input .D1 (gmii_txen), // 1-bit data input (positive edge) .D2 (gmii_txen), // 1-bit data input (negative edge) .R (1\'b0), // 1-bit reset .S (1\'b0)  // 1-bit set); genvar i;generate for (i=0; i<4; i=i+1) //TXD DDR OUTPUT begin : txd_ddr ODDR #( .DDR_CLK_EDGE (\"SAME_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 (rgmii_txd[i]), // 1-bit DDR output .C (gmii_txc), // 1-bit clock input .CE (1\'b1), // 1-bit clock enable input .D1 (gmii_txd[i]), // 1-bit data input (positive edge) .D2 (gmii_txd[4+i]), // 1-bit data input (negative edge) .R (1\'b0), // 1-bit reset .S (1\'b0)  // 1-bit set ); endendgenerateendmodule

仿真结果如下:

信号名称 信号定义 gmii_txc  模块输入的时钟 gmii_tx_en 模块输入的使能信号 gmii_txd 模块输入的8bit数据 rgmii_tx_ctrl 向PHY芯片输出的使能信号 rgmii_txd 向PHY芯片输出的4bit数据

 

 

在112ns时上升沿采样到数据8’b00100001,在120ns时上升沿输出低4位4’b0001,在124ns时下降沿输出高4位4’b0010。

FPGA实现千兆网UDP协议(一):RGMII接口

 

6.运行结果

1.将开发板与PC通过网线连接,烧录好bit文件。

2.进入控制面板,查看当前网卡是否工作在千兆模式。

FPGA实现千兆网UDP协议(一):RGMII接口

 

3.配置网卡地址为192.168.10.49 ,掩码为255.255.255.0。

也可配置为其他地址,但后续为板卡分配地址时一定要和PC的网卡地址在同一网段。

FPGA实现千兆网UDP协议(一):RGMII接口

 

4.键入win+R,输入cmd打开PC控制台。

FPGA实现千兆网UDP协议(一):RGMII接口

 

5.输入ping 192.168.10.XXX 命令,PC网卡主动发出数据包。

FPGA实现千兆网UDP协议(一):RGMII接口

 

6.PHY芯片正常收到数据后将数据传给FPGA,FPGA可以正常抓取到输入的信号。

FPGA实现千兆网UDP协议(一):RGMII接口