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