rtl: add sources for ethernet udp stack

This commit is contained in:
Phil
2026-03-31 12:53:16 +03:00
parent aa1d45fe15
commit ded2afc0db
28 changed files with 8535 additions and 0 deletions

View File

@ -0,0 +1,435 @@
//////////////////////////////////////////////////////////////////////////////////////
//Module Name : mac_top
//Description :
//
//////////////////////////////////////////////////////////////////////////////////////
//`define TEST_SPEED
`timescale 1 ns/1 ns
module mac_test
(
input rst_n ,
input [31:0] pack_total_len,
input gmii_tx_clk ,
input gmii_rx_clk ,
input gmii_rx_dv,
input [7:0] gmii_rxd,
output reg gmii_tx_en,
output reg [7:0] gmii_txd
);
localparam UDP_WIDTH = 32 ;
localparam UDP_DEPTH = 5 ;
reg gmii_rx_dv_d0 ;
reg [7:0] gmii_rxd_d0 ;
wire gmii_tx_en_tmp ;
wire [7:0] gmii_txd_tmp ;
reg [7:0] ram_wr_data ;
reg ram_wr_en ;
wire udp_ram_data_req ;
reg [15:0] udp_send_data_length ;
wire [7:0] tx_ram_wr_data ;
wire tx_ram_wr_en ;
wire udp_tx_req ;
wire arp_request_req ;
wire mac_send_end ;
reg write_end ;
wire [7:0] udp_rec_ram_rdata ;
reg [10:0] udp_rec_ram_read_addr ;
wire [15:0] udp_rec_data_length ;
wire udp_rec_data_valid ;
wire udp_tx_end ;
wire almost_full ;
reg udp_ram_wr_en ;
reg udp_write_end ;
wire write_ram_end ;
reg [31:0] wait_cnt ;
reg [UDP_WIDTH-1:0] udp_data [UDP_DEPTH-1:0];
reg [4:0] i;
reg [1:0] j ;
reg write_sel ;
wire button_negedge ;
wire mac_not_exist ;
wire arp_found ;
parameter IDLE = 9'b000_000_001 ;
parameter ARP_REQ = 9'b000_000_010 ;
parameter ARP_SEND = 9'b000_000_100 ;
parameter ARP_WAIT = 9'b000_001_000 ;
parameter GEN_REQ = 9'b000_010_000 ;
parameter WRITE_RAM = 9'b000_100_000 ;
parameter SEND = 9'b001_000_000 ;
parameter WAIT = 9'b010_000_000 ;
parameter CHECK_ARP = 9'b100_000_000 ;
reg [8:0] state ;
reg [8:0] next_state ;
reg [15:0] ram_cnt ;
reg almost_full_d0 ;
reg almost_full_d1 ;
always @(posedge gmii_tx_clk or negedge rst_n)
begin
if (~rst_n)
state <= IDLE ;
else
state <= next_state ;
end
always @(*)
begin
case(state)
IDLE :
begin
if (wait_cnt == pack_total_len)
next_state <= ARP_REQ ;
else
next_state <= IDLE ;
end
ARP_REQ :
next_state <= ARP_SEND ;
ARP_SEND :
begin
if (mac_send_end)
next_state <= ARP_WAIT ;
else
next_state <= ARP_SEND ;
end
ARP_WAIT :
begin
if (arp_found)
next_state <= WAIT ;
else if (wait_cnt == pack_total_len)
next_state <= ARP_REQ ;
else
next_state <= ARP_WAIT ;
end
GEN_REQ :
begin
if (udp_ram_data_req)
next_state <= WRITE_RAM ;
else
next_state <= GEN_REQ ;
end
WRITE_RAM :
begin
`ifdef TEST_SPEED
if (ram_cnt == udp_send_data_length - 1)
`else
if (write_ram_end)
`endif
next_state <= WAIT ;
else
next_state <= WRITE_RAM ;
end
SEND :
begin
if (udp_tx_end)
next_state <= WAIT ;
else
next_state <= SEND ;
end
WAIT :
begin
`ifdef TEST_SPEED
if (wait_cnt == 32'd90) //frame gap
`else
if (wait_cnt == pack_total_len)
`endif
next_state <= CHECK_ARP ;
else
next_state <= WAIT ;
end
CHECK_ARP :
begin
if (mac_not_exist)
next_state <= ARP_REQ ;
else if (almost_full_d1)
next_state <= CHECK_ARP ;
else
next_state <= GEN_REQ ;
end
default :
next_state <= IDLE ;
endcase
end
assign write_ram_end = (write_sel)? udp_write_end : write_end ;
assign tx_ram_wr_data = (write_sel)? udp_rec_ram_rdata : ram_wr_data ;
assign tx_ram_wr_en = (write_sel)? udp_ram_wr_en : ram_wr_en ;
always@(posedge gmii_rx_clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
gmii_rx_dv_d0 <= 1'b0 ;
gmii_rxd_d0 <= 8'd0 ;
end
else
begin
gmii_rx_dv_d0 <= gmii_rx_dv ;
gmii_rxd_d0 <= gmii_rxd ;
end
end
always@(posedge gmii_tx_clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
gmii_tx_en <= 1'b0 ;
gmii_txd <= 8'd0 ;
end
else
begin
gmii_tx_en <= gmii_tx_en_tmp ;
gmii_txd <= gmii_txd_tmp ;
end
end
mac_top mac_top0
(
.gmii_tx_clk (gmii_tx_clk) ,
.gmii_rx_clk (gmii_rx_clk) ,
.rst_n (rst_n) ,
.source_mac_addr (48'h00_0a_35_01_fe_c0) , //source mac address
.TTL (8'h80),
.source_ip_addr (32'hc0a80002),
.destination_ip_addr (32'hc0a80003),
.udp_send_source_port (16'h1f90),
.udp_send_destination_port (16'h1f90),
.ram_wr_data (tx_ram_wr_data) ,
.ram_wr_en (tx_ram_wr_en),
.udp_ram_data_req (udp_ram_data_req),
.udp_send_data_length (udp_send_data_length),
.udp_tx_end (udp_tx_end ),
.almost_full (almost_full ),
.udp_tx_req (udp_tx_req),
.arp_request_req (arp_request_req ),
.mac_send_end (mac_send_end),
.mac_data_valid (gmii_tx_en_tmp),
.mac_tx_data (gmii_txd_tmp),
.rx_dv (gmii_rx_dv_d0 ),
.mac_rx_datain (gmii_rxd_d0 ),
.udp_rec_ram_rdata (udp_rec_ram_rdata),
.udp_rec_ram_read_addr (udp_rec_ram_read_addr),
.udp_rec_data_length (udp_rec_data_length ),
.udp_rec_data_valid (udp_rec_data_valid),
.arp_found (arp_found ),
.mac_not_exist (mac_not_exist )
) ;
always @(*)
begin
udp_data[0] <={"H","E","L","L"};
udp_data[1] <={"O"," ","A","L"};
udp_data[2] <={"I","N","X"," "};
udp_data[3] <={"H","E","I","J"};
udp_data[4] <={"I","N","\r","\n"};
end
//reg almost_full_d0 ;
//reg almost_full_d1 ;
always@(posedge gmii_rx_clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
almost_full_d0 <= 1'b0 ;
almost_full_d1 <= 1'b0 ;
end
else
begin
almost_full_d0 <= almost_full ;
almost_full_d1 <= almost_full_d0 ;
end
end
always@(posedge gmii_rx_clk or negedge rst_n)
begin
if(rst_n == 1'b0)
udp_send_data_length <= 16'd0 ;
else if (write_sel)
udp_send_data_length <= udp_rec_data_length - 8 ;
else
`ifdef TEST_SPEED
udp_send_data_length <= 16'd1000 ;
`else
udp_send_data_length <= 4*UDP_DEPTH ;
`endif
end
always@(posedge gmii_tx_clk or negedge rst_n)
begin
if(rst_n == 1'b0)
write_sel <= 1'b0 ;
else if (state == WAIT)
begin
if (udp_rec_data_valid)
write_sel <= 1'b1 ;
else
write_sel <= 1'b0 ;
end
end
assign udp_tx_req = (state == GEN_REQ) ;
assign arp_request_req = (state == ARP_REQ) ;
always@(posedge gmii_tx_clk or negedge rst_n)
begin
if(rst_n == 1'b0)
wait_cnt <= 0 ;
else if ((state==IDLE||state == WAIT || state == ARP_WAIT) && state != next_state)
wait_cnt <= 0 ;
else if (state==IDLE||state == WAIT || state == ARP_WAIT)
wait_cnt <= wait_cnt + 1'b1 ;
else
wait_cnt <= 0 ;
end
`ifdef TEST_SPEED
/*************************************************************/
//Test ethernet speed
//reg [15:0] ram_cnt ;
always@(posedge gmii_tx_clk or negedge rst_n)
begin
if(rst_n == 1'b0)
ram_cnt <= 11'd0 ;
else if (state == WRITE_RAM)
ram_cnt <= ram_cnt + 1'b1 ;
else
ram_cnt <= 11'd0 ;
end
always@(posedge gmii_tx_clk or negedge rst_n)
begin
if(rst_n == 1'b0)
ram_wr_en <= 1'b0 ;
else if (state == WRITE_RAM)
ram_wr_en <= 1'b1 ;
else
ram_wr_en <= 1'b0 ;
end
always@(posedge gmii_tx_clk or negedge rst_n)
begin
if(rst_n == 1'b0)
ram_wr_data <= 8'd0 ;
else if (state == WRITE_RAM)
ram_wr_data <= ram_cnt[7:0] ;
else
ram_wr_data <= 8'd0 ;
end
/*************************************************************/
`else
always@(posedge gmii_tx_clk or negedge rst_n)
begin
if(rst_n == 1'b0)
begin
write_end <= 1'b0;
ram_wr_data <= 0;
ram_wr_en <= 0 ;
i <= 0 ;
j <= 0 ;
end
else if (state == WRITE_RAM)
begin
if(i == 5)
begin
ram_wr_en <=1'b0;
write_end <= 1'b1;
end
else
begin
ram_wr_en <= 1'b1 ;
write_end <= 1'b0 ;
j <= j + 1'b1 ;
case(j)
2'd0 : ram_wr_data <= udp_data[i][31:24] ;
2'd1 : ram_wr_data <= udp_data[i][23:16] ;
2'd2 : ram_wr_data <= udp_data[i][15:8] ;
2'd3 : ram_wr_data <= udp_data[i][7:0] ;
default : ram_wr_data <= 8'h00 ;
endcase
if (j == 3)
begin
j <= 0 ;
i <= i + 1'b1;
end
end
end
else
begin
write_end <= 1'b0;
ram_wr_data <= 0;
ram_wr_en <= 0 ;
i <= 0 ;
j <= 0 ;
end
end
`endif
//send udp received data to udp tx ram
always@(posedge gmii_tx_clk or negedge rst_n)
begin
if(rst_n == 1'b0)
udp_rec_ram_read_addr <= 11'd0 ;
else if (state == WRITE_RAM)
udp_rec_ram_read_addr <= udp_rec_ram_read_addr + 1'b1 ;
else
udp_rec_ram_read_addr <= 11'd0 ;
end
always@(posedge gmii_tx_clk or negedge rst_n)
begin
if(rst_n == 1'b0)
udp_ram_wr_en <= 1'b0 ;
else if (state == WRITE_RAM && udp_rec_ram_read_addr < udp_rec_data_length - 8)
udp_ram_wr_en <= 1'b1 ;
else
udp_ram_wr_en <= 1'b0 ;
end
always@(posedge gmii_tx_clk or negedge rst_n)
begin
if(rst_n == 1'b0)
udp_write_end <= 1'b0 ;
else if (state == WRITE_RAM && udp_rec_ram_read_addr == udp_rec_data_length - 8)
udp_write_end <= 1'b1 ;
else
udp_write_end <= 1'b0 ;
end
endmodule