dev/ethernet #4

Merged
baulin.fa merged 21 commits from dev/ethernet into master 2026-04-14 15:42:09 +03:00
38 changed files with 10176 additions and 0 deletions
Showing only changes of commit 3544e3e2dc - Show all commits

View 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