FPGA以太网篇之GMII/RGMII
作者:互联网
MII是英文Medium Independent Interface的缩写,翻译成中文就是“介质独立接口”,该接口一般应用于以太网硬件平台的MAC层和PHY层之间,MII接口的类型有很多,常见的有MII、RMII、SMII、SSMII、SSSMII、GMII、RGMII、SGMII等。下面笔者只对GMII与RGMII做些介绍,其他接口可以自行了解。
GMII(Gigabit Media Independent Interface)千兆MII接口。GMII采用8位接口数据,工作时钟125MHz,因此传输速率可达1000Mbps。同时兼容MII所规定的10/100 Mbps工作方式。GMII接口数据结构符合IEEE以太网标准,该接口定义见IEEE 802.3-2000。
GMII接口信号包括三类,分别为:
发送端信号:GTXCLK, TXCLK, TXD[7-0], TXEN, TXER
接收端信号:RXCLK, RXD[7-0], RXDV, RXER, CRS, COL
配置信号:MDIO, MDC
具体定义如下:
信号名称 描述 方向
GTX_CLK 1000M发送时钟 MAC → PHY
TX_CLK 100/10M发送时钟 MAC → PHY
TX_ER 发送数据错误 MAC → PHY
TX_EN 发送使能 MAC → PHY
TX_[7:0] 发送数据8bit MAC → PHY
RX_CLK 接收时钟 PHY → MAC
RX_DV 接收数据有效 PHY → MAC
RX_ER 接收数据错误 PHY → MAC
RX_[7:0] 接收数据8bit PHY → MAC
CRS 载波监测 PHY → MAC
COL 冲突碰撞监测 PHY → MAC
MDIO 管理数据 双向
MDC 管理数据时钟 MAC → PHY
RGMII(Reduced Gigabit Media Independant Interface),精简GMII接口。相比于上述的GMII有以下几点不同:
1.发送/接收数据线减半,由8条改为4条
2.TX_ER和TX_EN复用,通过TX_CTL传送
3.RX_ER与RX_DV复用,通过RX_CTL传送
4.1 Gbit/s速率下,时钟频率为125MHz
5.100 Mbit/s速率下,时钟频率为25MHz
6.10 Mbit/s速率下,时钟频率为2.5MHz
具体定义如下:
信号名称 描述 方向
TXC 发送时钟 MAC→PHY
TX_CTL 发送数据控制 MAC → PHY
TXD[3:0] 发送数据4bit MAC → PHY
RXC 接收时钟 PHY → MAC
RX_CTL 接收数据控制 PHY → MAC
RXD[3:0] 接收数据4bit PHY → MAC
MDIO 管理数据 双向
MDC 管理数据时钟 MAC → PHY
RGMII的发送接收的时序图如下:
笔者目前用的是xilinx的FPGA,虽说Verilog代码在所有的FPGA都适用,但是对于FPGA的底层资源还是有所区别的。
GMII转RGMII在vivado有相关的IP核,可以直接调用,可以参考IP核说明书进行配置,这里不多介绍。
想进一步了解数据的传输过程,可以自行编写GMII转RGMII的相关代码,难点在于要了解很多底层原语,而且不同的XILINX芯片使用的原语有差异;Z7跟Ultrascale系列的芯片原语相差很大,很多不能兼容。笔者下面的代码是Ultrascale系列的GMII转RGMII模块,写法挺多,笔者的这种写法也是参考了一些开发板厂商的DEMO。代码只支持1000MHz以太网,代码中发送时钟为接收时钟。
1 //************************************************************************** 2 // *** file name : Gmii_to_Rgmii.v 3 // *** version : 1.0 4 // *** Description : Gmii_to_Rgmii 5 // *** Blogs : https://www.cnblogs.com/WenGalois123/ 6 // *** Author : Galois_V 7 // *** Date : 2022.04.27 8 // *** Changes : Initial 9 //************************************************************************** 10 `timescale 1ns/1ps 11 module Gmii_to_Rgmii 12 ( 13 input wire rgmii_rxc , 14 input wire rstn , 15 output wire [3:0] rgmii_txd , 16 output wire rgmii_tx_ctl , 17 output wire rgmii_txc , 18 input wire [3:0] rgmii_rxd , 19 input wire rgmii_rx_ctl , 20 output wire gmii_rx_clk , 21 input wire [7:0] gmii_txd , 22 input wire gmii_tx_en , 23 input wire gmii_tx_er , 24 output wire gmii_tx_clk , 25 output reg [7:0] gmii_rxd , 26 output reg gmii_rx_dv 27 ); 28 29 wire [7:0] w_gmii_rxd ; 30 wire w_gmii_rx_dv ; 31 wire w_rgmii_rx_ctl ; 32 wire w_rgmii_tx_ctl ; 33 34 reg [1:0] r_rstn ; 35 reg [7:0] r_gmii_txd ; 36 reg [7:0] r_gmii_txd1 ; 37 reg r_gmii_tx_en ; 38 reg r_gmii_tx_en1 ; 39 reg r_gmii_tx_er ; 40 reg r_rgmii_tx_ctl ; 41 /******************************************************************************\ 42 Rgmii rx 43 \******************************************************************************/ 44 assign gmii_rx_clk = rgmii_rxc; 45 assign gmii_tx_clk = gmii_rx_clk; 46 47 always@(posedge gmii_rx_clk) 48 begin 49 gmii_rxd <= w_gmii_rxd; 50 gmii_rx_dv <= w_gmii_rx_dv; 51 end 52 53 generate 54 genvar i; 55 for (i = 0; i < 4; i = i + 1) 56 begin 57 IDDRE1 58 #( 59 .DDR_CLK_EDGE ("SAME_EDGE_PIPELINED" ), // IDDRE1 mode (OPPOSITE_EDGE, SAME_EDGE, SAME_EDGE_PIPELINED) 60 .IS_CB_INVERTED (1'b1 ), // Optional inversion for CB 61 .IS_C_INVERTED (1'b0 ) // Optional inversion for C 62 ) 63 u_rgmii_rxd 64 ( 65 .Q1 (w_gmii_rxd[i] ), // 1-bit output: Registered parallel output 1 66 .Q2 (w_gmii_rxd[i+4] ), // 1-bit output: Registered parallel output 2 67 .C (gmii_rx_clk ), // 1-bit input: High-speed clock 68 .CB (gmii_rx_clk ), // 1-bit input: Inversion of High-speed clock C 69 .D (rgmii_rxd[i] ), // 1-bit input: Serial Data Input 70 .R (0 ) // 1-bit input: Active High Async Reset 71 ); 72 end 73 endgenerate 74 75 IDDRE1 76 #( 77 .DDR_CLK_EDGE ("SAME_EDGE_PIPELINED" ), // IDDRE1 mode (OPPOSITE_EDGE, SAME_EDGE, SAME_EDGE_PIPELINED) 78 .IS_CB_INVERTED (1'b1 ), // Optional inversion for CB 79 .IS_C_INVERTED (1'b0 ) // Optional inversion for C 80 ) 81 u_rgmii_rx_ctl 82 ( 83 .Q1 (w_gmii_rx_dv ), // 1-bit output: Registered parallel output 1 84 .Q2 (w_rgmii_rx_ctl ), // 1-bit output: Registered parallel output 2 85 .C (gmii_rx_clk ), // 1-bit input: High-speed clock 86 .CB (gmii_rx_clk ), // 1-bit input: Inversion of High-speed clock C 87 .D (rgmii_rx_ctl ), // 1-bit input: Serial Data Input 88 .R (0 ) // 1-bit input: Active High Async Reset 89 ); 90 /******************************************************************************\ 91 Rgmii tx 92 \******************************************************************************/ 93 always@(posedge gmii_tx_clk) 94 begin 95 r_rstn <= {r_rstn[0],rstn}; 96 end 97 98 always@(posedge gmii_tx_clk) 99 begin 100 if(~r_rstn[1]) 101 begin 102 r_gmii_txd <= 'd0; 103 r_gmii_txd1 <= 'd0; 104 r_gmii_tx_en <= 'd0; 105 r_gmii_tx_en1 <= 'd0; 106 r_gmii_tx_er <= 'd0; 107 end 108 else 109 begin 110 r_gmii_txd <= gmii_txd ; 111 r_gmii_txd1 <= r_gmii_txd ; 112 r_gmii_tx_en <= gmii_tx_en ; 113 r_gmii_tx_en1 <= r_gmii_tx_en ; 114 r_gmii_tx_er <= gmii_tx_er ; 115 end 116 end 117 118 assign w_rgmii_tx_ctl = r_gmii_tx_en ^ r_gmii_tx_er; 119 120 always@(posedge gmii_tx_clk) 121 begin 122 r_rgmii_tx_ctl <= w_rgmii_tx_ctl; 123 end 124 125 ODDRE1 #( 126 .IS_C_INVERTED (1'b0 ), // Optional inversion for C 127 .IS_D1_INVERTED (1'b0 ), // Unsupported, do not use 128 .IS_D2_INVERTED (1'b0 ), // Unsupported, do not use 129 .SRVAL (1'b0 ) // Initializes the ODDRE1 Flip-Flops to the specified value (1'b0, 1'b1) 130 ) 131 u_rgmii_txc 132 ( 133 .Q (rgmii_txc ), // 1-bit output: Data output to IOB 134 .C (gmii_tx_clk ), // 1-bit input: High-speed clock input 135 .D1 (1 ), // 1-bit input: Parallel data input 1 136 .D2 (0 ), // 1-bit input: Parallel data input 2 137 .SR (0 ) // 1-bit input: Active High Async Reset 138 ); 139 140 generate 141 for (i = 0; i < 4; i = i + 1) 142 begin 143 ODDRE1 144 #( 145 .IS_C_INVERTED (1'b0 ), // Optional inversion for C 146 .IS_D1_INVERTED (1'b0 ), // Unsupported, do not use 147 .IS_D2_INVERTED (1'b0 ), // Unsupported, do not use 148 .SRVAL (1'b0 ) // Initializes the ODDRE1 Flip-Flops to the specified value (1'b0, 1'b1) 149 ) 150 u_rgmii_txd 151 ( 152 .Q (rgmii_txd[i] ), // 1-bit output: Data output to IOB 153 .C (gmii_tx_clk ), // 1-bit input: High-speed clock input 154 .D1 (r_gmii_txd1[i] ), // 1-bit input: Parallel data input 1 155 .D2 (r_gmii_txd1[4+i] ), // 1-bit input: Parallel data input 2 156 .SR (0 ) // 1-bit input: Active High Async Reset 157 ); 158 end 159 endgenerate 160 161 ODDRE1 #( 162 .IS_C_INVERTED (1'b0 ), // Optional inversion for C 163 .IS_D1_INVERTED (1'b0 ), // Unsupported, do not use 164 .IS_D2_INVERTED (1'b0 ), // Unsupported, do not use 165 .SRVAL (1'b0 ) // Initializes the ODDRE1 Flip-Flops to the specified value (1'b0, 1'b1) 166 ) 167 u_rgmii_tx_ctl 168 ( 169 .Q (rgmii_tx_ctl ), // 1-bit output: Data output to IOB 170 .C (gmii_tx_clk ), // 1-bit input: High-speed clock input 171 .D1 (r_gmii_tx_en1 ), // 1-bit input: Parallel data input 1 172 .D2 (r_rgmii_tx_ctl ), // 1-bit input: Parallel data input 2 173 .SR (0 ) // 1-bit input: Active High Async Reset 174 ); 175 endmodule
标签:wire,FPGA,MAC,GMII,PHY,gmii,以太网,时钟 来源: https://www.cnblogs.com/WenGalois123/p/16262788.html