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     PHY →MAC
  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

 

posted on 2022-05-13 10:52  Galois_V  阅读(5225)  评论(2编辑  收藏  举报