diff options
Diffstat (limited to 'simple_gemac')
-rw-r--r-- | simple_gemac/delay_line.v | 2 | ||||
-rw-r--r-- | simple_gemac/eth_tasks_f36.v | 89 | ||||
-rw-r--r-- | simple_gemac/ll8_shortfifo.v | 13 | ||||
-rw-r--r-- | simple_gemac/rxmac_to_ll8.v | 14 | ||||
-rw-r--r-- | simple_gemac/simple_gemac_rx.v | 46 | ||||
-rw-r--r-- | simple_gemac/simple_gemac_tx.v | 16 | ||||
-rw-r--r-- | simple_gemac/simple_gemac_wrapper.v | 65 | ||||
-rw-r--r-- | simple_gemac/simple_gemac_wrapper_f36_tb.v | 243 |
8 files changed, 428 insertions, 60 deletions
diff --git a/simple_gemac/delay_line.v b/simple_gemac/delay_line.v index 3d76c4928..d371bb9c5 100644 --- a/simple_gemac/delay_line.v +++ b/simple_gemac/delay_line.v @@ -7,7 +7,7 @@ module delay_line input [WIDTH-1:0] din, output [WIDTH-1:0] dout); - integer i; + genvar i; generate for (i=0;i<WIDTH;i=i+1) begin : gen_delay diff --git a/simple_gemac/eth_tasks_f36.v b/simple_gemac/eth_tasks_f36.v new file mode 100644 index 000000000..b7fa52c07 --- /dev/null +++ b/simple_gemac/eth_tasks_f36.v @@ -0,0 +1,89 @@ + + +task SendFlowCtrl; + input [15:0] fc_len; + begin + $display("Sending Flow Control, quanta = %d, time = %d", fc_len,$time); + pause_time <= fc_len; + @(posedge clk); + pause_req <= 1; + @(posedge clk); + pause_req <= 0; + $display("Sent Flow Control"); + end +endtask // SendFlowCtrl + +task SendPacket_to_fifo36; + input [31:0] data_start; + input [15:0] data_len; + reg [15:0] count; + begin + $display("Sending Packet Len=%d, %d", data_len, $time); + count <= 2; + tx_f36_dat <= {2'b0, 1'b0, 1'b1, data_start}; + tx_f36_src_rdy <= 1; + #1; + while(count < data_len) + begin + while(~tx_f36_dst_rdy) + @(posedge clk); + @(posedge clk); + tx_f36_dat[31:0] = tx_f36_dat[31:0] + 32'h0101_0101; + count = count + 4; + tx_f36_dat[32] <= 0; + end + tx_f36_dat[3] <= 1; + while(~tx_f36_dst_rdy) + @(posedge clk); + @(posedge clk); + tx_f36_src_rdy <= 0; + end +endtask // SendPacket_to_fifo36 + + +task Waiter; + input [31:0] wait_length; + begin + tx_ll_src_rdy2 <= 0; + repeat(wait_length) + @(posedge clk); + tx_ll_src_rdy2 <= 1; + end +endtask // Waiter + +task SendPacketFromFile_f36; + input [31:0] data_len; + input [31:0] wait_length; + input [31:0] wait_time; + + integer count; + begin + $display("Sending Packet From File to LL8 Len=%d, %d",data_len,$time); + $readmemh("test_packet.mem",pkt_rom ); + + while(~tx_f36_dst_rdy) + @(posedge clk); + tx_f36_data2 <= pkt_rom[0]; + tx_f36_src_rdy <= 1; + tx_ll_eof2 <= 0; + @(posedge clk); + + for(i=1;i<data_len-1;i=i+1) + begin + while(~tx_ll_dst_rdy2) + @(posedge clk); + tx_ll_data2 <= pkt_rom[i]; + tx_ll_sof2 <= 0; + @(posedge clk); + if(i==wait_time) + Waiter(wait_length); + end + + while(~tx_ll_dst_rdy2) + @(posedge clk); + tx_ll_eof2 <= 1; + tx_ll_data2 <= pkt_rom[data_len-1]; + @(posedge clk); + tx_ll_src_rdy2 <= 0; + end +endtask diff --git a/simple_gemac/ll8_shortfifo.v b/simple_gemac/ll8_shortfifo.v index 39ada9a4f..e69de29bb 100644 --- a/simple_gemac/ll8_shortfifo.v +++ b/simple_gemac/ll8_shortfifo.v @@ -1,13 +0,0 @@ - - -module ll8_shortfifo - (input clk, input reset, input clear, - input [7:0] datain, input sof_i, input eof_i, input error_i, input src_rdy_i, output dst_rdy_o, - output [7:0] dataout, output sof_o, output eof_o, output error_o, output src_rdy_o, input dst_rdy_i); - - fifo_short #(.WIDTH(11)) fifo_short - (.clk(clk), .reset(reset), .clear(clear), - .datain({error_i,eof_i,sof_i,datain}), .src_rdy_i(src_rdy_i), .dst_rdy_o(dst_rdy_o), - .dataout({error_o,eof_o,sof_o,dataout}), .src_rdy_o(src_rdy_o), .dst_rdy_i(dst_rdy_i)); - -endmodule // ll8_shortfifo diff --git a/simple_gemac/rxmac_to_ll8.v b/simple_gemac/rxmac_to_ll8.v index d4015716e..5ec233d95 100644 --- a/simple_gemac/rxmac_to_ll8.v +++ b/simple_gemac/rxmac_to_ll8.v @@ -6,6 +6,13 @@ module rxmac_to_ll8 reg [2:0] xfer_state; + localparam XFER_IDLE = 0; + localparam XFER_ACTIVE = 1; + localparam XFER_ERROR = 2; + localparam XFER_ERROR2 = 3; + localparam XFER_OVERRUN = 4; + localparam XFER_OVERRUN2 = 5; + assign ll_data = rx_data; assign ll_src_rdy = ((rx_valid & (xfer_state != XFER_OVERRUN2) ) | (xfer_state == XFER_ERROR) @@ -14,13 +21,6 @@ module rxmac_to_ll8 assign ll_eof = (rx_ack | (xfer_state==XFER_ERROR) | (xfer_state==XFER_OVERRUN)); assign ll_error = (xfer_state == XFER_ERROR)|(xfer_state==XFER_OVERRUN); - localparam XFER_IDLE = 0; - localparam XFER_ACTIVE = 1; - localparam XFER_ERROR = 2; - localparam XFER_ERROR2 = 3; - localparam XFER_OVERRUN = 4; - localparam XFER_OVERRUN2 = 5; - always @(posedge clk) if(reset | clear) xfer_state <= XFER_IDLE; diff --git a/simple_gemac/simple_gemac_rx.v b/simple_gemac/simple_gemac_rx.v index 7daa9adad..c50791ff0 100644 --- a/simple_gemac/simple_gemac_rx.v +++ b/simple_gemac/simple_gemac_rx.v @@ -8,7 +8,24 @@ module simple_gemac_rx input pass_ucast, input pass_mcast, input pass_bcast, input pass_pause, input pass_all, output reg [15:0] pause_quanta_rcvd, output pause_rcvd ); - reg [7:0] rxd_d1; + localparam RX_IDLE = 0; + localparam RX_PREAMBLE = 1; + localparam RX_FRAME = 2; + localparam RX_GOODFRAME = 3; + localparam RX_DO_PAUSE = 4; + localparam RX_ERROR = 5; + localparam RX_DROP = 6; + + localparam RX_PAUSE = 16; + localparam RX_PAUSE_CHK88 = RX_PAUSE + 5; + localparam RX_PAUSE_CHK08 = RX_PAUSE_CHK88 + 1; + localparam RX_PAUSE_CHK00 = RX_PAUSE_CHK08 + 1; + localparam RX_PAUSE_CHK01 = RX_PAUSE_CHK00 + 1; + localparam RX_PAUSE_STORE_MSB = RX_PAUSE_CHK01 + 1; + localparam RX_PAUSE_STORE_LSB = RX_PAUSE_STORE_MSB + 1; + localparam RX_PAUSE_WAIT_CRC = RX_PAUSE_STORE_LSB + 1; + + reg [7:0] rxd_d1; reg rx_dv_d1, rx_er_d1; assign rx_clk = GMII_RX_CLK; @@ -19,10 +36,15 @@ module simple_gemac_rx rxd_d1 <= GMII_RXD; end + reg [7:0] rx_state; wire [7:0] rxd_del; wire rx_dv_del, rx_er_del; reg go_filt; + wire match_crc; + wire clear_crc = rx_state == RX_IDLE; + wire calc_crc = (rx_state == RX_FRAME) | rx_state[7:4]==4'h1; + localparam DELAY = 6; delay_line #(.WIDTH(10)) rx_delay (.clk(rx_clk), .delay(DELAY), .din({rx_dv_d1,rx_er_d1,rxd_d1}),.dout({rx_dv_del,rx_er_dl,rxd_del})); @@ -37,7 +59,6 @@ module simple_gemac_rx wire keep_packet = (pass_ucast & is_ucast) | (pass_mcast & is_mcast) | (pass_bcast & is_bcast) | (pass_pause & is_pause) | pass_all; - reg [7:0] rx_state; assign rx_data = rxd_del; assign rx_error = (rx_state == RX_ERROR); @@ -58,24 +79,6 @@ module simple_gemac_rx address_filter af_pause (.clk(rx_clk), .reset(reset), .go(go_filt), .data(rxd_d1), .address(48'h0180_c200_0001), .match(is_pause), .done()); - localparam RX_IDLE = 0; - localparam RX_PREAMBLE = 1; - localparam RX_FRAME = 2; - localparam RX_GOODFRAME = 3; - localparam RX_DO_PAUSE = 4; - localparam RX_ERROR = 5; - localparam RX_DROP = 6; - - localparam RX_PAUSE = 16; - localparam RX_PAUSE_CHK88 = RX_PAUSE + 5; - localparam RX_PAUSE_CHK08 = RX_PAUSE_CHK88 + 1; - localparam RX_PAUSE_CHK00 = RX_PAUSE_CHK08 + 1; - localparam RX_PAUSE_CHK01 = RX_PAUSE_CHK00 + 1; - localparam RX_PAUSE_STORE_MSB = RX_PAUSE_CHK01 + 1; - localparam RX_PAUSE_STORE_LSB = RX_PAUSE_STORE_MSB + 1; - localparam RX_PAUSE_WAIT_CRC = RX_PAUSE_STORE_LSB + 1; - - always @(posedge rx_clk) go_filt <= (rx_state==RX_PREAMBLE) & (rxd_d1 == 8'hD5); @@ -155,9 +158,6 @@ module simple_gemac_rx endcase // case (rx_state) assign pause_rcvd = (rx_state == RX_DO_PAUSE); - wire match_crc; - wire clear_crc = rx_state == RX_IDLE; - wire calc_crc = (rx_state == RX_FRAME) | rx_state[7:4]==4'h1; crc crc_check(.clk(rx_clk),.reset(reset),.clear(clear_crc), .data(rxd_d1),.calc(calc_crc),.crc_out(),.match(match_crc)); diff --git a/simple_gemac/simple_gemac_tx.v b/simple_gemac/simple_gemac_tx.v index 690fd5c37..dd870d04d 100644 --- a/simple_gemac/simple_gemac_tx.v +++ b/simple_gemac/simple_gemac_tx.v @@ -23,14 +23,6 @@ module simple_gemac_tx wire [31:0] crc_out; - localparam MIN_FRAME_LEN = 64 + 8 - 4; // Min frame length includes preamble but not CRC - localparam MAX_FRAME_LEN = 8192; // How big are the jumbo frames we want to handle? - always @(posedge tx_clk) - if(reset |(tx_state == TX_IDLE)) - frame_len_ctr <= 0; - else - frame_len_ctr <= frame_len_ctr + 1; - localparam TX_IDLE = 0; localparam TX_PREAMBLE = 1; localparam TX_SOF_DEL = TX_PREAMBLE + 7; @@ -48,6 +40,14 @@ module simple_gemac_tx localparam TX_PAUSE_FIRST = TX_PAUSE_SOF + 1; localparam TX_PAUSE_END = TX_PAUSE_SOF + 18; + localparam MIN_FRAME_LEN = 64 + 8 - 4; // Min frame length includes preamble but not CRC + localparam MAX_FRAME_LEN = 8192; // How big are the jumbo frames we want to handle? + always @(posedge tx_clk) + if(reset |(tx_state == TX_IDLE)) + frame_len_ctr <= 0; + else + frame_len_ctr <= frame_len_ctr + 1; + reg send_pause; reg [15:0] pause_time_held; diff --git a/simple_gemac/simple_gemac_wrapper.v b/simple_gemac/simple_gemac_wrapper.v index cd586ae5d..e21eafb80 100644 --- a/simple_gemac/simple_gemac_wrapper.v +++ b/simple_gemac/simple_gemac_wrapper.v @@ -8,13 +8,10 @@ module simple_gemac_wrapper // Flow Control Interface input pause_req, input [15:0] pause_time, - // RX Client Interface - output rx_clk, output [7:0] rx_ll_data, output rx_ll_sof, output rx_ll_eof, - output rx_ll_error, output rx_ll_src_rdy, input rx_ll_dst_rdy, - - // TX Client Interface - output tx_clk, input [7:0] tx_ll_data, input tx_ll_sof, input tx_ll_eof, - input tx_ll_src_rdy, output tx_ll_dst_rdy, + // Client FIFO Interfaces + input sys_clk, + output [35:0] rx_f36_data, output rx_f36_src_rdy, input rx_f36_dst_rdy, + input [35:0] tx_f36_data, input tx_f36_src_rdy, output tx_f36_dst_rdy, // Wishbone Interface input wb_clk, input wb_rst, input wb_stb, input wb_cyc, output wb_ack, input wb_we, @@ -59,14 +56,66 @@ module simple_gemac_wrapper .pass_ucast(pass_ucast), .pass_mcast(pass_mcast), .pass_bcast(pass_bcast), .pass_pause(pass_pause), .pass_all(pass_all), .pause_en(pause_en) ); + // RX FIFO Chain + wire rx_ll_sof, rx_ll_eof, rx_ll_src_rdy, rx_ll_dst_rdy; + wire rx_ll_sof2, rx_ll_eof2, rx_ll_src_rdy2_n, rx_ll_dst_rdy2; + wire [7:0] rx_ll_data, rx_ll_data2; + wire [35:0] rx_f36_data_int1; + wire rx_f36_src_rdy_int1, rx_f36_dst_rdy_int1; + rxmac_to_ll8 rx_adapt (.clk(rx_clk), .reset(rx_reset), .clear(0), .rx_data(rx_data), .rx_valid(rx_valid), .rx_error(rx_error), .rx_ack(rx_ack), .ll_data(rx_ll_data), .ll_sof(rx_ll_sof), .ll_eof(rx_ll_eof), .ll_error(rx_ll_error), .ll_src_rdy(rx_ll_src_rdy), .ll_dst_rdy(rx_ll_dst_rdy)); + + ll8_shortfifo rx_sfifo + (.clk(rx_clk), .reset(rx_reset), .clear(0), + .datain(rx_ll_data), .sof_i(rx_ll_sof), .eof_i(rx_ll_eof), + .error_i(rx_ll_error), .src_rdy_i(rx_ll_src_rdy), .dst_rdy_o(rx_ll_dst_rdy), + .dataout(rx_ll_data2), .sof_o(rx_ll_sof2), .eof_o(rx_ll_eof2), + .error_o(rx_ll_error2), .src_rdy_o(rx_ll_src_rdy2), .dst_rdy_i(~rx_ll_dst_rdy2_n)); + + ll8_to_fifo36 ll8_to_fifo36 + (.clk(rx_clk), .reset(rx_reset), .clear(0), + .ll_data(rx_ll_data2), .ll_sof_n(~rx_ll_sof2), .ll_eof_n(~rx_ll_eof2), + .ll_src_rdy_n(~rx_ll_src_rdy2), .ll_dst_rdy_n(rx_ll_dst_rdy2_n), + .f36_data(rx_f36_data_int1), .f36_src_rdy_o(rx_f36_src_rdy_int1), .f36_dst_rdy_i(rx_f36_dst_rdy_int1)); + + cascadefifo_2clock #(.DWIDTH(36), .AWIDTH(9)) rx_2clk_fifo + (.wclk(rx_clk), .datain(rx_f36_data_int1), + .src_rdy_i(rx_f36_src_rdy_int1), .dst_rdy_o(rx_f36_dst_rdy_int1), .level_wclk(), + .rclk(sys_clk), .dataout(rx_f36_data), + .src_rdy_o(rx_f36_src_rdy), .dst_rdy_i(rx_f36_dst_rdy), .level_rclk(), .arst(reset)); + + // TX FIFO Chain + wire tx_ll_sof, tx_ll_eof, tx_ll_src_rdy, tx_ll_dst_rdy; + wire tx_ll_sof2, tx_ll_eof2, tx_ll_src_rdy2, tx_ll_dst_rdy2; + wire [7:0] tx_ll_data, tx_ll_data2; + wire [35:0] tx_f36_data_int1; + wire tx_f36_src_rdy_int1, tx_f36_dst_rdy_int1; + + cascadefifo_2clock #(.DWIDTH(36), .AWIDTH(9)) tx_2clk_fifo + (.wclk(sys_clk), .datain(tx_f36_data), + .src_rdy_i(tx_f36_src_rdy), .dst_rdy_o(tx_f36_dst_rdy), .level_wclk(), + .rclk(tx_clk), .dataout(tx_f36_data_int1), + .src_rdy_o(tx_f36_src_rdy_int1), .dst_rdy_i(tx_f36_dst_rdy_int1), .level_rclk(), .arst(reset)); + + fifo36_to_ll8 fifo36_to_ll8 + (.clk(tx_clk), .reset(tx_reset), .clear(clear), + .f36_data(tx_f36_data_int1), .f36_src_rdy_i(tx_f36_src_rdy_int1), .f36_dst_rdy_o(tx_f36_dst_rdy_int1), + .ll_data(tx_ll_data2), .ll_sof_n(tx_ll_sof2_n), .ll_eof_n(tx_ll_eof2_n), + .ll_src_rdy_n(tx_ll_src_rdy2_n), .ll_dst_rdy_n(~tx_ll_dst_rdy2)); + + ll8_shortfifo tx_sfifo + (.clk(rx_clk), .reset(tx_reset), .clear(clear), + .datain(tx_ll_data2), .sof_i(tx_ll_sof2), .eof_i(tx_ll_eof2), + .error_i(0), .src_rdy_i(~tx_ll_src_rdy2_n), .dst_rdy_o(tx_ll_dst_rdy2), + .dataout(tx_ll_data), .sof_o(tx_ll_sof), .eof_o(tx_ll_eof), + .error_o(), .src_rdy_o(tx_ll_src_rdy), .dst_rdy_i(tx_ll_dst_rdy)); ll8_to_txmac ll8_to_txmac - (.clk(tx_clk), .reset(tx_reset), .clear(0), + (.clk(tx_clk), .reset(tx_reset), .clear(clear), .ll_data(tx_ll_data), .ll_sof(tx_ll_sof), .ll_eof(tx_ll_eof), .ll_src_rdy(tx_ll_src_rdy), .ll_dst_rdy(tx_ll_dst_rdy), .tx_data(tx_data), .tx_valid(tx_valid), .tx_error(tx_error), .tx_ack(tx_ack)); diff --git a/simple_gemac/simple_gemac_wrapper_f36_tb.v b/simple_gemac/simple_gemac_wrapper_f36_tb.v new file mode 100644 index 000000000..804fa8748 --- /dev/null +++ b/simple_gemac/simple_gemac_wrapper_f36_tb.v @@ -0,0 +1,243 @@ + + +module simple_gemac_wrapper_f36_tb; +`include "eth_tasks_f36.v" + + reg clk = 0; + reg reset = 1; + + initial #1000 reset = 0; + always #50 clk = ~clk; + + reg wb_clk = 0; + wire wb_rst = reset; + always #173 wb_clk = ~wb_clk; + + wire GMII_RX_DV, GMII_RX_ER, GMII_TX_EN, GMII_TX_ER, GMII_GTX_CLK; + wire [7:0] GMII_RXD, GMII_TXD; + + wire rx_valid, rx_error, rx_ack; + wire tx_ack, tx_valid, tx_error; + + wire [7:0] rx_data, tx_data; + + reg [15:0] pause_time; + reg pause_req = 0; + + wire GMII_RX_CLK = GMII_GTX_CLK; + + reg [7:0] FORCE_DAT_ERR = 0; + reg FORCE_ERR = 0; + + // Loopback + assign GMII_RX_DV = GMII_TX_EN; + assign GMII_RX_ER = GMII_TX_ER | FORCE_ERR; + assign GMII_RXD = GMII_TXD ^ FORCE_DAT_ERR; + + + wire rx_ll_sof, rx_ll_eof, rx_ll_src_rdy, rx_ll_dst_rdy; + wire rx_ll_sof2, rx_ll_eof2, rx_ll_src_rdy2; + wire rx_ll_dst_rdy2; + wire [7:0] rx_ll_data, rx_ll_data2; + wire rx_ll_error, rx_ll_error2; + + wire [31:0] wb_dat_o; + reg [31:0] wb_dat_i; + reg [7:0] wb_adr; + reg wb_stb=0, wb_cyc=0, wb_we=0; + wire wb_ack; + + reg [35:0] tx_f36_dat; + reg tx_f36_src_rdy; + wire tx_f36_dst_rdy; + + wire [35:0] rx_f36_dat; + wire rx_f36_src_rdy; + reg rx_f36_dst_rdy = 1; + + simple_gemac_wrapper simple_gemac_wrapper + (.clk125(clk), .reset(reset), + .GMII_GTX_CLK(GMII_GTX_CLK), .GMII_TX_EN(GMII_TX_EN), + .GMII_TX_ER(GMII_TX_ER), .GMII_TXD(GMII_TXD), + .GMII_RX_CLK(GMII_RX_CLK), .GMII_RX_DV(GMII_RX_DV), + .GMII_RX_ER(GMII_RX_ER), .GMII_RXD(GMII_RXD), + .pause_req(pause_req), .pause_time(pause_time), + .rx_clk(rx_clk), .rx_ll_data(rx_ll_data), .rx_ll_sof(rx_ll_sof), + .rx_ll_eof(rx_ll_eof), .rx_ll_src_rdy(rx_ll_src_rdy), .rx_ll_dst_rdy(rx_ll_dst_rdy), + .tx_clk(tx_clk), .tx_ll_data(tx_ll_data), .tx_ll_sof(tx_ll_sof), + .tx_ll_eof(tx_ll_eof), .tx_ll_src_rdy(tx_ll_src_rdy), .tx_ll_dst_rdy(tx_ll_dst_rdy), + .wb_clk(wb_clk), .wb_rst(wb_rst), .wb_stb(wb_stb), .wb_cyc(wb_cyc), .wb_ack(wb_ack), + .wb_we(wb_we), .wb_adr(wb_adr), .wb_dat_i(wb_dat_i), .wb_dat_o(wb_dat_o), + .mdio(mdio), .mdc(mdc) ); + + wire rx_ll_dst_rdy2_n; + assign rx_ll_dst_rdy2 = ~rx_ll_dst_rdy2_n; + + ll8_shortfifo rx_sfifo + (.clk(clk), .reset(reset), .clear(0), + .datain(rx_ll_data), .sof_i(rx_ll_sof), .eof_i(rx_ll_eof), + .error_i(rx_ll_error), .src_rdy_i(rx_ll_src_rdy), .dst_rdy_o(rx_ll_dst_rdy), + .dataout(rx_ll_data2), .sof_o(rx_ll_sof2), .eof_o(rx_ll_eof2), + .error_o(rx_ll_error2), .src_rdy_o(rx_ll_src_rdy2), .dst_rdy_i(rx_ll_dst_rdy2)); + + ll8_to_fifo36 ll8_to_fifo36 + (.clk(clk), .reset(reset), .clear(0), + .ll_data(rx_ll_data2), .ll_sof_n(~rx_ll_sof2), .ll_eof_n(~rx_ll_eof2), + .ll_src_rdy_n(~rx_ll_src_rdy2), .ll_dst_rdy_n(rx_ll_dst_rdy2_n), + .f36_data(rx_f36_dat), .f36_src_rdy_o(rx_f36_src_rdy), .f36_dst_rdy_i(rx_f36_dst_rdy)); + + wire tx_ll_sof, tx_ll_eof, tx_ll_src_rdy, tx_ll_dst_rdy; + wire tx_ll_sof2_n, tx_ll_eof2_n; + wire tx_ll_src_rdy2_n, tx_ll_dst_rdy2; + wire [7:0] tx_ll_data, tx_ll_data2; + wire tx_ll_error; + wire tx_ll_error2 = 0; + + fifo36_to_ll8 fifo36_to_ll8 + (.clk(clk), .reset(reset), .clear(clear), + .f36_data(tx_f36_dat), .f36_src_rdy_i(tx_f36_src_rdy), .f36_dst_rdy_o(tx_f36_dst_rdy), + .ll_data(tx_ll_data2), .ll_sof_n(tx_ll_sof2_n), .ll_eof_n(tx_ll_eof2_n), + .ll_src_rdy_n(tx_ll_src_rdy2_n), .ll_dst_rdy_n(~tx_ll_dst_rdy2)); + + ll8_shortfifo tx_sfifo + (.clk(clk), .reset(reset), .clear(clear), + .datain(tx_ll_data2), .sof_i(~tx_ll_sof2_n), .eof_i(~tx_ll_eof2_n), + .error_i(tx_ll_error2), .src_rdy_i(~tx_ll_src_rdy2_n), .dst_rdy_o(tx_ll_dst_rdy2), + .dataout(tx_ll_data), .sof_o(tx_ll_sof), .eof_o(tx_ll_eof), + .error_o(tx_ll_error), .src_rdy_o(tx_ll_src_rdy), .dst_rdy_i(tx_ll_dst_rdy)); + + initial $dumpfile("simple_gemac_wrapper_f36_tb.vcd"); + initial $dumpvars(0,simple_gemac_wrapper_f36_tb); + + integer i; + reg [7:0] pkt_rom[0:65535]; + reg [1023:0] ROMFile; + + initial + for (i=0;i<65536;i=i+1) + pkt_rom[i] <= 8'h0; + + initial + begin + @(negedge reset); + repeat (10) + @(posedge clk); + WishboneWR(0,6'b111001); + WishboneWR(4,16'hF1F2); + WishboneWR(8,32'hF3F4_F5F6); + WishboneWR(12,16'h0000); + WishboneWR(16,32'h0000_0000); + + @(posedge clk); + SendFlowCtrl(16'h0007); // Send flow control + @(posedge clk); + #30000; + @(posedge clk); + SendFlowCtrl(16'h0009); // Increase flow control before it expires + #10000; + @(posedge clk); + SendFlowCtrl(16'h0000); // Cancel flow control before it expires + @(posedge clk); + + SendPacket_to_fifo36(8'hAA,10); // This packet gets dropped by the filters + repeat (10) + @(posedge clk); + + SendPacketFromFile_fifo36(60,0,0); // The rest are valid packets + repeat (10) + @(posedge clk); + + SendPacketFromFile_fifo36(61,0,0); + repeat (10) + @(posedge clk); + SendPacketFromFile_fifo36(62,0,0); + repeat (10) + @(posedge clk); + SendPacketFromFile_fifo36(63,0,0); + repeat (1) + @(posedge clk); + SendPacketFromFile_fifo36(64,0,0); + repeat (10) + @(posedge clk); + SendPacketFromFile_fifo36(59,0,0); + repeat (1) + @(posedge clk); + SendPacketFromFile_fifo36(58,0,0); + repeat (1) + @(posedge clk); + SendPacketFromFile_fifo36(100,0,0); + repeat (1) + @(posedge clk); + SendPacketFromFile_fifo36(200,150,30); // waiting 14 empties the fifo, 15 underruns + repeat (1) + @(posedge clk); + SendPacketFromFile_fifo36(100,0,30); + #10000 $finish; + end +/* + // Force a CRC error + initial + begin + #90000; + @(posedge clk); + FORCE_DAT_ERR <= 8'h10; + @(posedge clk); + FORCE_DAT_ERR <= 8'h00; + end + + // Force an RX_ER error (i.e. link loss) + initial + begin + #116000; + @(posedge clk); + FORCE_ERR <= 1; + @(posedge clk); + FORCE_ERR <= 0; + end + + // Cause receive fifo to fill, causing an RX overrun + initial + begin + #126000; + @(posedge clk); + rx_f36_dst_rdy <= 0; + repeat (30) // Repeat of 14 fills the shortfifo, but works. 15 overflows + @(posedge clk); + rx_f36_dst_rdy <= 1; + end + */ + // Tests: Send and recv flow control, send and receive good packets, RX CRC err, RX_ER, RX overrun, TX underrun + // Still need to test: CRC errors on Pause Frames, MDIO, wishbone + + task WishboneWR; + input [7:0] adr; + input [31:0] value; + begin + wb_adr <= adr; + wb_dat_i <= value; + wb_stb <= 1; + wb_cyc <= 1; + wb_we <= 1; + while (~wb_ack) + @(posedge wb_clk); + @(posedge wb_clk); + wb_stb <= 0; + wb_cyc <= 0; + wb_we <= 0; + end + endtask // WishboneWR + + always @(posedge clk) + if(rx_f36_src_rdy & rx_f36_dst_rdy) + begin + if(rx_f36_dat[32] & ~rx_f36_dat[33]) + $display("RX-PKT-START %d",$time); + $display("RX-PKT SOF %d EOF %d ERR %d OCC %d DAT %x",rx_f36_dat[32],rx_f36_dat[33], + &rx_f36_dat[33:32],rx_f36_dat[35:34],rx_f36_dat[31:0]); + if(rx_f36_dat[33] & ~rx_f36_dat[32]) + $display("RX-PKT-END %d",$time); + if(rx_f36_dat[33] & rx_f36_dat[32]) + $display("RX-PKT-ERROR %d",$time); + end + +endmodule // simple_gemac_wrapper_tb |