rt_gmii2rgmii_interface

`timescale 1ns / 1ps


module rt_gmii2rgmii_interface #(
  parameter IO_DELAY_GROUP = "RGMII_IDELAY_GROUP",
  parameter integer IDELAY_VALUE = 18,
  parameter integer ODELAY_VALUE = 0
  )(
  input wire reset,
  input wire clk_125m,
  input wire clk_25m,
  input wire clk_20m,
  input wire io_refclk,

  input wire [1:0] speed,
  input wire half_duplex,

  input wire rgmii_rx_clk,
  input wire rgmii_rx_ctl,
  input wire [3:0] rgmii_rxd,
  output wire rgmii_tx_clk,
  output wire rgmii_tx_ctl,
  output wire [3:0] rgmii_txd,

  output wire gmii_rx_clk,
  output wire gmii_rx_dv,
  output wire gmii_rx_er,
  output wire [7:0] gmii_rxd,
  output wire gmii_tx_clk,
  input wire gmii_tx_en,
  input wire gmii_tx_er,
  input wire [7:0] gmii_txd,

  output wire gmii_crs,
  output wire gmii_col
  );
 
  wire [4:0] rgmii_rx_all;
  wire [4:0] rgmii_rx_all_delay;

  wire [4:0] rgmii_rx_pos;
  wire [4:0] rgmii_rx_neg;

  reg gmii_rx_dv_r = 1'b0;
  reg gmii_rx_er_r = 1'b0;
  reg [7:0] gmii_rxd_r = 8'h0;

  wire clk_2d5m;
  wire clk_2d5m_or_25m;
  wire tx_clk;

  (* ASYNC_REG="true" *)reg [3:0] tx_reset_resync = 4'b1111;
  wire tx_reset;

  reg gmii_tx_en_d;
  reg gmii_tx_er_d;
  reg [7:0] gmii_txd_d;

  wire gmii_tx_ctl_pos;
  wire gmii_tx_ctl_neg;
  wire [3:0] gmii_txd_pos;
  wire [3:0] gmii_txd_neg;

  wire rgmii_tx_clk_int;

  genvar var_i;
  
  // idelay ctrl
  (* IODELAY_GROUP = IO_DELAY_GROUP *) // Specifies group name for associated IDELAYs/ODELAYs and IDELAYCTRL
  IDELAYCTRL u_idelayctrl(
    .RDY(),       // 1-bit output: Ready output
    .REFCLK(io_refclk), // 1-bit input: Reference clock input
    .RST(reset)        // 1-bit input: Active high reset input
    );

  // rx 
  BUFG u_bufg_rx_clk(
    .I(rgmii_rx_clk),
    .O(gmii_rx_clk)
    );

  assign rgmii_rx_all = {rgmii_rxd, rgmii_rx_ctl};

  generate
    for (var_i = 0;var_i < 5;var_i = var_i + 1)
      begin: g_rx_delay
      (* IODELAY_GROUP = IO_DELAY_GROUP*) // Specifies group name for associated IDELAYs/ODELAYs and IDELAYCTRL
      IDELAYE2 #(
        .CINVCTRL_SEL("FALSE"),          // Enable dynamic clock inversion (FALSE, TRUE)
        .DELAY_SRC("IDATAIN"),           // Delay input (IDATAIN, DATAIN)
        .HIGH_PERFORMANCE_MODE("TRUE"), // Reduced jitter ("TRUE"), Reduced power ("FALSE")
        .IDELAY_TYPE("FIXED"),           // FIXED, VARIABLE, VAR_LOAD, VAR_LOAD_PIPE
        .IDELAY_VALUE(IDELAY_VALUE),                // Input delay tap setting (0-31)
        .PIPE_SEL("FALSE"),              // Select pipelined mode, FALSE, TRUE
        .REFCLK_FREQUENCY(200.0),        // IDELAYCTRL clock input frequency in MHz (190.0-210.0, 290.0-310.0).
        .SIGNAL_PATTERN("DATA")          // DATA, CLOCK input signal
        ) u_idelaye2_rx(
        .CNTVALUEOUT(), // 5-bit output: Counter value output
        .DATAOUT(rgmii_rx_all_delay[var_i]),         // 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(rgmii_rx_all[var_i]),         // 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(1'b0)            // 1-bit input: Active-high reset tap-delay input
        );

      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" 
        ) u_iddr_rx(
        .Q1(rgmii_rx_pos[var_i]), // 1-bit output for positive edge of clock
        .Q2(rgmii_rx_neg[var_i]), // 1-bit output for negative edge of clock
        .C(gmii_rx_clk),   // 1-bit clock input
        .CE(1'b1), // 1-bit clock enable input
        .D(rgmii_rx_all_delay[var_i]),   // 1-bit DDR data input
        .R(1'b0),   // 1-bit reset
        .S(1'b0)    // 1-bit set
        );
      end
  endgenerate

  always @(posedge gmii_rx_clk)
    begin
      gmii_rx_dv_r <= rgmii_rx_pos[0];
      gmii_rx_er_r <= rgmii_rx_pos[0] ^ rgmii_rx_neg[0];
      gmii_rxd_r <= {rgmii_rx_neg[4:1], rgmii_rx_pos[4:1]};
    end

  assign gmii_rx_dv = gmii_rx_dv_r;
  assign gmii_rx_er = gmii_rx_er_r;
  assign gmii_rxd = gmii_rxd_r;

  // tx
  // clock select
  BUFR #(
    .BUFR_DIVIDE("8"),   // Values: "BYPASS, 1, 2, 3, 4, 5, 6, 7, 8" 
    .SIM_DEVICE("7SERIES")  // Must be set to "7SERIES" 
    ) u_bufr_clk_2d5m(
    .O(clk_2d5m),     // 1-bit output: Clock output port
    .CE(1'b1),   // 1-bit input: Active high, clock enable (Divided modes only)
    .CLR(1'b0), // 1-bit input: Active high, asynchronous clear (Divided modes only)
    .I(clk_20m)      // 1-bit input: Clock buffer input driven by an IBUF, MMCM or local interconnect
    );


  BUFGMUX #(
    ) u_bufgmux_2d5m_25m(
    .O(clk_2d5m_or_25m),   // 1-bit output: Clock output
    .I0(clk_2d5m), // 1-bit input: Clock input (S=0)
    .I1(clk_25m), // 1-bit input: Clock input (S=1)
    .S(speed[0])    // 1-bit input: Clock select
    );

  BUFGMUX #(
    ) u_bufgmux_tx_clk(
    .O(tx_clk),   // 1-bit output: Clock output
    .I0(clk_2d5m_or_25m), // 1-bit input: Clock input (S=0)
    .I1(clk_125m), // 1-bit input: Clock input (S=1)
    .S(speed[1])    // 1-bit input: Clock select
    );  

  assign gmii_tx_clk = tx_clk;

  always @(posedge tx_clk)
    tx_reset_resync <= {tx_reset_resync[2:0], reset};

  assign tx_reset = tx_reset_resync[3];

  always @(posedge tx_clk)
    if (tx_reset)
      begin 
        gmii_tx_en_d <= 1'b0;
        gmii_tx_er_d <= 1'b0;
        gmii_txd_d <= 8'h0;
      end
    else 
      begin 
        gmii_tx_en_d <= gmii_tx_en;
        gmii_tx_er_d <= gmii_tx_er;
        gmii_txd_d <= gmii_txd;
      end

  assign gmii_txd_pos = gmii_txd_d[3:0];
  assign gmii_txd_neg = speed[1] == 1'b1 ? gmii_txd_d[7:4] : gmii_txd_d[3:0];

  generate 
    for (var_i = 0;var_i < 4;var_i = var_i + 1)
      begin: g_oddr
        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" 
          ) u_oddr_txd(
          .Q(rgmii_txd[var_i]),   // 1-bit DDR output
          .C(tx_clk),   // 1-bit clock input
          .CE(1'b1), // 1-bit clock enable input
          .D1(gmii_txd_pos[var_i]), // 1-bit data input (positive edge)
          .D2(gmii_txd_neg[var_i]), // 1-bit data input (negative edge)
          .R(tx_reset),   // 1-bit reset
          .S(1'b0)    // 1-bit set
          );
      end
  endgenerate

  assign gmii_tx_ctl_pos = gmii_tx_en_d;
  assign gmii_tx_ctl_neg = gmii_tx_en_d ^ gmii_tx_er_d;

  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" 
    ) u_oddr_tx_ctl(
    .Q(rgmii_tx_ctl),   // 1-bit DDR output
    .C(tx_clk),   // 1-bit clock input
    .CE(1'b1), // 1-bit clock enable input
    .D1(gmii_tx_ctl_pos), // 1-bit data input (positive edge)
    .D2(gmii_tx_ctl_neg), // 1-bit data input (negative edge)
    .R(tx_reset),   // 1-bit reset
    .S(1'b0)    // 1-bit set
    );

  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" 
    ) u_oddr_tx_clk(
    .Q(rgmii_tx_clk_int),   // 1-bit DDR output
    .C(tx_clk),   // 1-bit clock input
    .CE(1'b1), // 1-bit clock enable input
    .D1(1'b1), // 1-bit data input (positive edge)
    .D2(1'b0), // 1-bit data input (negative edge)
    .R(tx_reset),   // 1-bit reset
    .S(1'b0)    // 1-bit set
    );

  (* IODELAY_GROUP = IO_DELAY_GROUP *) // Specifies group name for associated IDELAYs/ODELAYs and IDELAYCTRL
  ODELAYE2 #(
    .CINVCTRL_SEL("FALSE"),          // Enable dynamic clock inversion (FALSE, TRUE)
    .DELAY_SRC("ODATAIN"),           // Delay input (ODATAIN, CLKIN)
    .HIGH_PERFORMANCE_MODE("TRUE"), // Reduced jitter ("TRUE"), Reduced power ("FALSE")
    .ODELAY_TYPE("FIXED"),           // FIXED, VARIABLE, VAR_LOAD, VAR_LOAD_PIPE
    .ODELAY_VALUE(0),                // Output delay tap setting (0-31)
    .PIPE_SEL("FALSE"),              // Select pipelined mode, FALSE, TRUE
    .REFCLK_FREQUENCY(200.0),        // IDELAYCTRL clock input frequency in MHz (190.0-210.0, 290.0-310.0).
    .SIGNAL_PATTERN("CLOCK")          // DATA, CLOCK input signal
    ) u_odelaye2_tx_clk(
    .CNTVALUEOUT(), // 5-bit output: Counter value output
    .DATAOUT(rgmii_tx_clk),         // 1-bit output: Delayed data/clock 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
    .CLKIN(1'b0),             // 1-bit input: Clock delay input
    .CNTVALUEIN(1'b0),   // 5-bit input: Counter value input
    .INC(1'b0),                 // 1-bit input: Increment / Decrement tap delay input
    .LD(1'b0),                   // 1-bit input: Loads ODELAY_VALUE tap delay in VARIABLE mode, in VAR_LOAD or
                                 // VAR_LOAD_PIPE mode, loads the value of CNTVALUEIN

    .LDPIPEEN(1'b0),       // 1-bit input: Enables the pipeline register to load data
    .ODATAIN(rgmii_tx_clk_int),         // 1-bit input: Output delay data input
    .REGRST(1'b0)            // 1-bit input: Active-high reset tap-delay input
    );

  ila_sig16 u_ila (
	  .clk(gmii_rx_clk), // input wire clk


	  .probe0({gmii_rx_dv, gmii_rx_er, gmii_rxd}) // input wire [15:0] probe0
    );

endmodule

--晓凡 2023922日于武汉书
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
1000Base-X是一种用于以太网的标准接口,支持传输速率为1 Gbps。它使用光纤作为传输介质,可以通过单模光纤(SMF)或多模光纤(MMF)进行数据传输。 SGMII是SerDes based代表识别符(serial 为串行,generous为慷慨的意思)。这是一种适用于以太网的接口定义,用于连接MAC层和PHY层设备。它通过4对差分信号进行传输,支持千兆速率的数据通信。 GMII(Gigabit Media Independent Interface)是一种标准接口,用于在MAC层和PHY层之间传输数据。它支持传输速率为1 Gbps,使用4对差分信号进行通信。 RGMII(Reduced Gigabit Media Independent Interface)是一种适用于以太网的接口定义,用于连接MAC层和PHY层设备。它使用2对差分信号进行数据传输,支持传输速率为1 Gbps。RGMII可以有效地减少所需的引脚数量,从而节省芯片空间。 MII(Media Independent Interface)是一种用于以太网的标准接口。它是一个物理层和介质访问控制层之间的接口,用于传输数据。MII支持传输速率为10 Mbps。 1000Base-T是一种以太网标准接口,支持传输速率为1 Gbps。它使用四对CAT5或CAT6双绞线作为传输介质,适用于距离较短的局域网连接。 总结:1000Base-X、SGMII、GMII、RGMII、MII和1000Base-T都是用于以太网的接口定义,支持1 Gbps的传输速率。它们使用不同的传输介质和通信方式,适用于不同的网络和应用场景。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值