436 lines
11 KiB
Verilog
436 lines
11 KiB
Verilog
|
|
//////////////////////////////////////////////////////////////////////////////////////
|
|
//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
|
|
|
|
|