From c21464b1107295575afa958e34f915f7d9985c14 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Fri, 4 Sep 2009 22:23:27 -0700 Subject: Implement Eth flow control using pause frames Not fully tested, but it seems to work without frame errors, sequence number errors or ethernet overruns. Still of course will get tx underruns on a slow machine, and the transmitted signal has some issues though. --- simple_gemac/flow_ctrl_rx.v | 105 +++++++++++++++++--------------------------- 1 file changed, 40 insertions(+), 65 deletions(-) (limited to 'simple_gemac/flow_ctrl_rx.v') diff --git a/simple_gemac/flow_ctrl_rx.v b/simple_gemac/flow_ctrl_rx.v index 7ded9e08b..b13334d0e 100644 --- a/simple_gemac/flow_ctrl_rx.v +++ b/simple_gemac/flow_ctrl_rx.v @@ -2,84 +2,59 @@ // RX side of flow control -- when we are running out of RX space, send a PAUSE module flow_ctrl_rx - (input rst, - //host processor - input pause_frame_send_en, - input [15:0] pause_quanta_set, - input [15:0] fc_hwmark, - input [15:0] fc_lwmark, - // From MAC_rx_ctrl - input rx_clk, - input [15:0] rx_fifo_space, - // MAC_tx_ctrl - input tx_clk, - output reg xoff_gen, - output reg xon_gen, - input xoff_gen_complete, - input xon_gen_complete + (input pause_request_en, input [15:0] pause_time, input [15:0] pause_thresh, + input rx_clk, input rx_reset, input [15:0] rx_fifo_space, + input tx_clk, input tx_reset, output reg pause_req, output reg [15:0] pause_time_req ); // ****************************************************************************** // Force our TX to send a PAUSE frame because our RX is nearly full // ****************************************************************************** - reg xon_int, xoff_int; + // RX Clock Domain + reg xon, xoff; reg [21:0] countdown; - - always @(posedge rx_clk or posedge rst) - if(rst) - begin - xon_int <= 0; - xoff_int <= 0; - end - else - begin - xon_int <= 0; - xoff_int <= 0; - if(pause_frame_send_en) - if(countdown == 0) - if(rx_fifo_space < fc_lwmark) - xoff_int <= 1; - else - ; - else - if(rx_fifo_space > fc_hwmark) - xon_int <= 1; - end // else: !if(rst) - - reg xoff_int_d1, xon_int_d1; - always @(posedge rx_clk) - xon_int_d1 <= xon_int; - always @(posedge rx_clk) - xoff_int_d1 <= xoff_int; + wire [15:0] pause_low_thresh = pause_thresh; + wire [15:0] pause_hi_thresh = 16'hFFFF; + wire [21:0] pq_reduced = {pause_time,6'd0} - 1700; - always @ (posedge tx_clk or posedge rst) - if (rst) - xoff_gen <=0; - else if (xoff_gen_complete) - xoff_gen <=0; - else if (xoff_int | xoff_int_d1) - xoff_gen <=1; + always @(posedge rx_clk) + if(rx_reset) + xoff <= 0; + else + xoff <= (pause_request_en & (countdown==0) & (rx_fifo_space < pause_low_thresh)); - always @ (posedge tx_clk or posedge rst) - if (rst) - xon_gen <=0; - else if (xon_gen_complete) - xon_gen <=0; - else if (xon_int | xon_int_d1) - xon_gen <=1; - - wire [15:0] pq_reduced = pause_quanta_set - 2; + always @(posedge rx_clk) + if(rx_reset) + xon <= 0; + else + xon <= ((countdown!=0) & (rx_fifo_space > pause_hi_thresh)); - always @(posedge tx_clk or posedge rst) - if(rst) + always @(posedge rx_clk) + if(rx_reset) countdown <= 0; - else if(xoff_gen) - countdown <= {pq_reduced,6'd0}; - else if(xon_gen) + else if(xoff) + countdown <= pq_reduced; + else if(xon) countdown <= 0; else if(countdown != 0) countdown <= countdown - 1; + + // Cross clock domains + oneshot_2clk send_xon (.clk_in(rx_clk), .in(xon), .clk_out(tx_clk), .out(xon_tx)); + oneshot_2clk send_xoff (.clk_in(rx_clk), .in(xoff), .clk_out(tx_clk), .out(xoff_tx)); + + always @(posedge tx_clk) + if(xoff_tx) + pause_time_req <= pause_time; + else if(xon_tx) + pause_time_req <= 0; + + always @(posedge tx_clk) + if(tx_reset) + pause_req <= 0; + else + pause_req <= xon_tx | xoff_tx; -endmodule // flow_ctrl +endmodule // flow_ctrl_rx -- cgit v1.2.3 From 42fc55415af499980901c7787f44c7e74b4a9ce1 Mon Sep 17 00:00:00 2001 From: Matt Ettus Date: Thu, 1 Oct 2009 01:02:25 -0700 Subject: Fix warnings, mostly from implicitly defined wires or unspecified widths --- serdes/serdes_tx.v | 2 +- simple_gemac/flow_ctrl_rx.v | 1 + simple_gemac/simple_gemac.v | 3 ++- simple_gemac/simple_gemac_rx.v | 2 +- simple_gemac/simple_gemac_wrapper.v | 10 ++++++---- top/u2_core/u2_core.v | 4 +++- 6 files changed, 14 insertions(+), 8 deletions(-) (limited to 'simple_gemac/flow_ctrl_rx.v') diff --git a/serdes/serdes_tx.v b/serdes/serdes_tx.v index c74414e92..2e5e3bd80 100644 --- a/serdes/serdes_tx.v +++ b/serdes/serdes_tx.v @@ -84,7 +84,7 @@ module serdes_tx wire rd_eop_i = rd_flags_i[1]; wire [1:0] rd_occ_i = rd_flags_i[3:2]; // Unused - wire have_data, empty; + wire have_data, empty, read; fifo_cascade #(.WIDTH(34),.SIZE(FIFOSIZE)) serdes_tx_fifo (.clk(clk),.reset(rst),.clear(0), .datain({rd_sop_i,rd_eop_i,rd_dat_i}), .src_rdy_i(rd_ready_i), .dst_rdy_o(rd_ready_o), diff --git a/simple_gemac/flow_ctrl_rx.v b/simple_gemac/flow_ctrl_rx.v index b13334d0e..d09bf377f 100644 --- a/simple_gemac/flow_ctrl_rx.v +++ b/simple_gemac/flow_ctrl_rx.v @@ -42,6 +42,7 @@ module flow_ctrl_rx countdown <= countdown - 1; // Cross clock domains + wire xon_tx, xoff_tx; oneshot_2clk send_xon (.clk_in(rx_clk), .in(xon), .clk_out(tx_clk), .out(xon_tx)); oneshot_2clk send_xoff (.clk_in(rx_clk), .in(xoff), .clk_out(tx_clk), .out(xoff_tx)); diff --git a/simple_gemac/simple_gemac.v b/simple_gemac/simple_gemac.v index 868a66819..e7f327358 100644 --- a/simple_gemac/simple_gemac.v +++ b/simple_gemac/simple_gemac.v @@ -26,7 +26,8 @@ module simple_gemac reset_sync reset_sync_rx (.clk(rx_clk),.reset_in(reset),.reset_out(rst_rxclk)); wire [15:0] pause_quanta_rcvd; - + wire pause_rcvd, pause_apply, paused; + simple_gemac_tx simple_gemac_tx (.clk125(clk125),.reset(rst_txclk), .GMII_GTX_CLK(GMII_GTX_CLK), .GMII_TX_EN(GMII_TX_EN), diff --git a/simple_gemac/simple_gemac_rx.v b/simple_gemac/simple_gemac_rx.v index bad43a607..45ddd6dfa 100644 --- a/simple_gemac/simple_gemac_rx.v +++ b/simple_gemac/simple_gemac_rx.v @@ -47,7 +47,7 @@ module simple_gemac_rx 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})); + (.clk(rx_clk), .delay(DELAY), .din({rx_dv_d1,rx_er_d1,rxd_d1}),.dout({rx_dv_del,rx_er_del,rxd_del})); always @(posedge rx_clk) if(reset) diff --git a/simple_gemac/simple_gemac_wrapper.v b/simple_gemac/simple_gemac_wrapper.v index 71ad0cf0f..efcf89276 100644 --- a/simple_gemac/simple_gemac_wrapper.v +++ b/simple_gemac/simple_gemac_wrapper.v @@ -19,13 +19,15 @@ module simple_gemac_wrapper // MIIM inout mdio, output mdc, output [31:0] debug); - + + wire clear = 0; wire [7:0] rx_data, tx_data; wire tx_clk, tx_valid, tx_error, tx_ack; wire rx_clk, rx_valid, rx_error, rx_ack; wire [47:0] ucast_addr, mcast_addr; wire pass_ucast, pass_mcast, pass_bcast, pass_pause, pass_all; + wire pause_req; wire pause_request_en, pause_respect_en; wire [15:0] pause_time, pause_thresh, pause_time_req, rx_fifo_space; @@ -75,15 +77,15 @@ module simple_gemac_wrapper 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_data(rx_ll_data), .ll_sof(rx_ll_sof), .ll_eof(rx_ll_eof), .ll_error(), // error also encoded in sof/eof .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), + .error_i(0), .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)); + .error_o(), .src_rdy_o(rx_ll_src_rdy2), .dst_rdy_i(rx_ll_dst_rdy2)); assign rx_ll_dst_rdy2 = ~rx_ll_dst_rdy2_n; assign rx_ll_src_rdy2_n = ~rx_ll_src_rdy2; diff --git a/top/u2_core/u2_core.v b/top/u2_core/u2_core.v index 1f78f6d3d..03016e9b3 100755 --- a/top/u2_core/u2_core.v +++ b/top/u2_core/u2_core.v @@ -525,9 +525,11 @@ module u2_core (.clk(wb_clk),.rst(wb_rst), .sd_clk(sd_clk),.sd_csn(sd_csn),.sd_mosi(sd_mosi),.sd_miso(sd_miso), .wb_cyc_i(sd_cyc),.wb_stb_i(sd_stb),.wb_we_i(sd_we), - .wb_adr_i(sd_adr[3:2]),.wb_dat_i(sd_dat_o),.wb_dat_o(sd_dat_i), + .wb_adr_i(sd_adr[3:2]),.wb_dat_i(sd_dat_o[7:0]),.wb_dat_o(sd_dat_i[7:0]), .wb_ack_o(sd_ack) ); + assign sd_dat_i[31:8] = 0; + // ///////////////////////////////////////////////////////////////////////// // DSP wire [31:0] sample_rx, sample_tx; -- cgit v1.2.3