test: add sample top for axis loopback test
This commit is contained in:
333
rtl/ethernet-udp/tests/eth_axis/ethernet_test_minimal.v
Normal file
333
rtl/ethernet-udp/tests/eth_axis/ethernet_test_minimal.v
Normal file
@ -0,0 +1,333 @@
|
||||
`timescale 1 ns / 1 ns
|
||||
|
||||
module ethernet_test_minimal
|
||||
(
|
||||
input sys_clk_p,
|
||||
input sys_clk_n,
|
||||
input rst_n,
|
||||
output [3:0] led,
|
||||
output e_reset,
|
||||
output e_mdc,
|
||||
inout e_mdio,
|
||||
output [3:0] rgmii_txd,
|
||||
output rgmii_txctl,
|
||||
output rgmii_txc,
|
||||
input [3:0] rgmii_rxd,
|
||||
input rgmii_rxctl,
|
||||
input rgmii_rxc
|
||||
);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// Internal GMII-side signals
|
||||
// ------------------------------------------------------------
|
||||
wire [7:0] gmii_txd;
|
||||
wire gmii_tx_en;
|
||||
wire gmii_tx_er;
|
||||
wire gmii_tx_clk;
|
||||
wire gmii_crs;
|
||||
wire gmii_col;
|
||||
wire [7:0] gmii_rxd_i;
|
||||
wire gmii_rx_dv;
|
||||
wire gmii_rx_er;
|
||||
wire gmii_rx_clk;
|
||||
|
||||
wire [31:0] pack_total_len;
|
||||
|
||||
wire e_rx_dv;
|
||||
wire [7:0] e_rxd;
|
||||
wire e_tx_en;
|
||||
wire [7:0] e_txd;
|
||||
wire e_rst_n;
|
||||
wire sys_clk;
|
||||
|
||||
wire duplex_mode;
|
||||
|
||||
assign duplex_mode = 1'b1;
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// System clock buffer
|
||||
// ------------------------------------------------------------
|
||||
IBUFDS sys_clk_ibufgds
|
||||
(
|
||||
.O (sys_clk),
|
||||
.I (sys_clk_p),
|
||||
.IB (sys_clk_n)
|
||||
);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// IDELAYCTRL
|
||||
// ------------------------------------------------------------
|
||||
(* IODELAY_GROUP = "rgmii_idelay_group" *)
|
||||
IDELAYCTRL IDELAYCTRL_inst (
|
||||
.RDY(),
|
||||
.REFCLK(sys_clk),
|
||||
.RST(1'b0)
|
||||
);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// GMII <-> RGMII conversion
|
||||
// ------------------------------------------------------------
|
||||
util_gmii_to_rgmii util_gmii_to_rgmii_m0
|
||||
(
|
||||
.reset (1'b0),
|
||||
.rgmii_td (rgmii_txd),
|
||||
.rgmii_tx_ctl (rgmii_txctl),
|
||||
.rgmii_txc (rgmii_txc),
|
||||
.rgmii_rd (rgmii_rxd),
|
||||
.rgmii_rx_ctl (rgmii_rxctl),
|
||||
.gmii_rx_clk (gmii_rx_clk),
|
||||
.gmii_txd (e_txd),
|
||||
.gmii_tx_en (e_tx_en),
|
||||
.gmii_tx_er (1'b0),
|
||||
.gmii_tx_clk (gmii_tx_clk),
|
||||
.gmii_crs (gmii_crs),
|
||||
.gmii_col (gmii_col),
|
||||
.gmii_rxd (gmii_rxd_i),
|
||||
.rgmii_rxc (rgmii_rxc),
|
||||
.gmii_rx_dv (gmii_rx_dv),
|
||||
.gmii_rx_er (gmii_rx_er),
|
||||
.speed_selection (2'b10),
|
||||
.duplex_mode (duplex_mode)
|
||||
);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// GMII arbitration / adaptation
|
||||
// ------------------------------------------------------------
|
||||
gmii_arbi arbi_inst
|
||||
(
|
||||
.clk (gmii_tx_clk),
|
||||
.rst_n (rst_n),
|
||||
.speed (2'b10),
|
||||
.link (1'b1),
|
||||
.pack_total_len (pack_total_len),
|
||||
.e_rst_n (e_rst_n),
|
||||
.gmii_rx_dv (gmii_rx_dv),
|
||||
.gmii_rxd (gmii_rxd_i),
|
||||
.gmii_tx_en (gmii_tx_en),
|
||||
.gmii_txd (gmii_txd),
|
||||
.e_rx_dv (e_rx_dv),
|
||||
.e_rxd (e_rxd),
|
||||
.e_tx_en (e_tx_en),
|
||||
.e_txd (e_txd)
|
||||
);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// axis_mac interface
|
||||
// ------------------------------------------------------------
|
||||
(* MARK_DEBUG="true" *)wire req_ready;
|
||||
|
||||
(* MARK_DEBUG="true" *)reg send_req;
|
||||
reg [15:0] data_length;
|
||||
|
||||
reg [7:0] s_axis_tx_tdata;
|
||||
reg s_axis_tx_tvalid;
|
||||
wire s_axis_tx_tready;
|
||||
reg s_axis_tx_tlast;
|
||||
|
||||
wire [7:0] m_axis_rx_tdata;
|
||||
wire m_axis_rx_tvalid;
|
||||
reg m_axis_rx_tready;
|
||||
wire m_axis_rx_tlast;
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// axis_mac
|
||||
// ------------------------------------------------------------
|
||||
axis_mac axis_mac0
|
||||
(
|
||||
.gmii_tx_clk (gmii_tx_clk),
|
||||
.gmii_rx_clk (gmii_rx_clk),
|
||||
.rst_n (e_rst_n),
|
||||
|
||||
.gmii_rx_dv (e_rx_dv),
|
||||
.gmii_rxd (e_rxd),
|
||||
.gmii_tx_en (gmii_tx_en),
|
||||
.gmii_txd (gmii_txd),
|
||||
|
||||
.send_req (send_req),
|
||||
.data_length (data_length),
|
||||
.req_ready (req_ready),
|
||||
|
||||
.s_axis_tx_tdata (s_axis_tx_tdata),
|
||||
.s_axis_tx_tvalid (s_axis_tx_tvalid),
|
||||
.s_axis_tx_tready (s_axis_tx_tready),
|
||||
.s_axis_tx_tlast (s_axis_tx_tlast),
|
||||
|
||||
.m_axis_rx_tdata (m_axis_rx_tdata),
|
||||
.m_axis_rx_tvalid (m_axis_rx_tvalid),
|
||||
.m_axis_rx_tready (m_axis_rx_tready),
|
||||
.m_axis_rx_tlast (m_axis_rx_tlast)
|
||||
);
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// LEDs
|
||||
// Просто чтобы не висели в воздухе
|
||||
// ------------------------------------------------------------
|
||||
assign led[0] = req_ready;
|
||||
assign led[1] = !m_axis_rx_tvalid;
|
||||
assign led[2] = !s_axis_tx_tvalid;
|
||||
assign led[3] = e_rst_n;
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// Minimal one-packet echo buffer
|
||||
// ------------------------------------------------------------
|
||||
localparam BUFFER_SIZE = 256;
|
||||
|
||||
reg [7:0] pkt_mem [0:BUFFER_SIZE-1];
|
||||
|
||||
// ---------------- RX domain ----------------
|
||||
reg [15:0] rx_wr_ptr;
|
||||
reg [15:0] rx_pkt_len;
|
||||
reg rx_pkt_toggle;
|
||||
|
||||
// TX->RX "done" toggle synchronizer
|
||||
reg tx_done_toggle;
|
||||
reg tx_done_toggle_rx_d0, tx_done_toggle_rx_d1;
|
||||
wire tx_done_pulse_rx;
|
||||
|
||||
assign tx_done_pulse_rx = tx_done_toggle_rx_d1 ^ tx_done_toggle_rx_d0;
|
||||
|
||||
always @(posedge gmii_rx_clk or negedge e_rst_n) begin
|
||||
if (!e_rst_n) begin
|
||||
tx_done_toggle_rx_d0 <= 1'b0;
|
||||
tx_done_toggle_rx_d1 <= 1'b0;
|
||||
end else begin
|
||||
tx_done_toggle_rx_d0 <= tx_done_toggle;
|
||||
tx_done_toggle_rx_d1 <= tx_done_toggle_rx_d0;
|
||||
end
|
||||
end
|
||||
|
||||
always @(posedge gmii_rx_clk or negedge e_rst_n) begin
|
||||
if (!e_rst_n) begin
|
||||
rx_wr_ptr <= 16'd0;
|
||||
rx_pkt_len <= 16'd0;
|
||||
rx_pkt_toggle <= 1'b0;
|
||||
m_axis_rx_tready <= 1'b0;
|
||||
end else begin
|
||||
// accept only one packet at a time
|
||||
m_axis_rx_tready <= 1'b1;
|
||||
|
||||
if (tx_done_pulse_rx) begin
|
||||
rx_pkt_toggle <= 1'b0;
|
||||
rx_wr_ptr <= 16'd0;
|
||||
end
|
||||
|
||||
if (m_axis_rx_tvalid && m_axis_rx_tready) begin
|
||||
pkt_mem[rx_wr_ptr] <= m_axis_rx_tdata;
|
||||
|
||||
if (m_axis_rx_tlast) begin
|
||||
rx_pkt_len <= rx_wr_ptr + 16'd1;
|
||||
rx_pkt_toggle <= 1'b1;
|
||||
end
|
||||
|
||||
rx_wr_ptr <= rx_wr_ptr + 16'd1;
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
// ---------------- RX->TX toggle sync ----------------
|
||||
reg rx_pkt_toggle_tx_d0, rx_pkt_toggle_tx_d1;
|
||||
(* MARK_DEBUG="true" *) wire rx_pkt_pulse_tx;
|
||||
|
||||
assign rx_pkt_pulse_tx = rx_pkt_toggle_tx_d1 ^ rx_pkt_toggle_tx_d0;
|
||||
|
||||
always @(posedge gmii_tx_clk or negedge e_rst_n) begin
|
||||
if (!e_rst_n) begin
|
||||
rx_pkt_toggle_tx_d0 <= 1'b0;
|
||||
rx_pkt_toggle_tx_d1 <= 1'b0;
|
||||
end else begin
|
||||
rx_pkt_toggle_tx_d0 <= rx_pkt_toggle;
|
||||
rx_pkt_toggle_tx_d1 <= rx_pkt_toggle_tx_d0;
|
||||
end
|
||||
end
|
||||
|
||||
// ---------------- TX domain ----------------
|
||||
localparam TX_IDLE = 2'd0;
|
||||
localparam TX_REQ = 2'd1;
|
||||
localparam TX_STREAM = 2'd2;
|
||||
|
||||
(* MARK_DEBUG="true" *)reg [1:0] test_state;
|
||||
reg tx_pkt_pending;
|
||||
reg [15:0] tx_pkt_len;
|
||||
reg [15:0] tx_rd_ptr;
|
||||
|
||||
always @(posedge gmii_tx_clk or negedge e_rst_n) begin
|
||||
if (!e_rst_n) begin
|
||||
test_state <= TX_IDLE;
|
||||
tx_pkt_pending <= 1'b0;
|
||||
tx_pkt_len <= 16'd0;
|
||||
tx_rd_ptr <= 16'd0;
|
||||
|
||||
send_req <= 1'b0;
|
||||
data_length <= 16'd0;
|
||||
|
||||
s_axis_tx_tdata <= 8'd0;
|
||||
s_axis_tx_tvalid <= 1'b0;
|
||||
s_axis_tx_tlast <= 1'b0;
|
||||
|
||||
tx_done_toggle <= 1'b0;
|
||||
end else begin
|
||||
send_req <= 1'b0;
|
||||
|
||||
if (rx_pkt_pulse_tx) begin
|
||||
tx_pkt_pending <= 1'b1;
|
||||
tx_pkt_len <= rx_pkt_len;
|
||||
tx_rd_ptr <= 16'd0;
|
||||
end
|
||||
|
||||
case (test_state)
|
||||
TX_IDLE: begin
|
||||
s_axis_tx_tvalid <= 1'b0;
|
||||
s_axis_tx_tlast <= 1'b0;
|
||||
tx_rd_ptr <= 16'd0;
|
||||
|
||||
if (tx_pkt_pending && req_ready) begin
|
||||
data_length <= tx_pkt_len;
|
||||
send_req <= 1'b1;
|
||||
test_state <= TX_REQ;
|
||||
end
|
||||
end
|
||||
|
||||
TX_REQ: begin
|
||||
if (s_axis_tx_tready) begin
|
||||
s_axis_tx_tdata <= pkt_mem[0];
|
||||
s_axis_tx_tvalid <= 1'b1;
|
||||
s_axis_tx_tlast <= (tx_pkt_len == 16'd1);
|
||||
tx_rd_ptr <= 16'd0;
|
||||
test_state <= TX_STREAM;
|
||||
end
|
||||
end
|
||||
|
||||
TX_STREAM: begin
|
||||
if (s_axis_tx_tvalid && s_axis_tx_tready) begin
|
||||
if (tx_rd_ptr == tx_pkt_len - 16'd1) begin
|
||||
s_axis_tx_tvalid <= 1'b0;
|
||||
s_axis_tx_tlast <= 1'b0;
|
||||
tx_pkt_pending <= 1'b0;
|
||||
tx_done_toggle <= 1'b1;
|
||||
test_state <= TX_IDLE;
|
||||
end else begin
|
||||
tx_rd_ptr <= tx_rd_ptr + 16'd1;
|
||||
s_axis_tx_tdata <= pkt_mem[tx_rd_ptr + 16'd1];
|
||||
s_axis_tx_tlast <= (tx_rd_ptr + 16'd1 == tx_pkt_len - 16'd1);
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
default: begin
|
||||
test_state <= TX_IDLE;
|
||||
end
|
||||
endcase
|
||||
end
|
||||
end
|
||||
|
||||
// ------------------------------------------------------------
|
||||
// PHY reset generation
|
||||
// ------------------------------------------------------------
|
||||
reset reset_m0
|
||||
(
|
||||
.clk (sys_clk),
|
||||
.key1 (rst_n),
|
||||
.rst_n (e_reset)
|
||||
);
|
||||
|
||||
endmodule
|
||||
Reference in New Issue
Block a user