`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
--晓凡 2023年9月22日于武汉书