aboutsummaryrefslogtreecommitdiffstats
path: root/simple_gemac/flow_ctrl_rx.v
diff options
context:
space:
mode:
authorMatt Ettus <matt@ettus.com>2009-09-04 22:23:27 -0700
committerMatt Ettus <matt@ettus.com>2009-09-04 22:23:27 -0700
commitc21464b1107295575afa958e34f915f7d9985c14 (patch)
treed129daeeb1af64465858aaca126ec9923742e7fb /simple_gemac/flow_ctrl_rx.v
parent71babf966d8cd340eb62122a297c2cc3b1294b82 (diff)
downloaduhd-c21464b1107295575afa958e34f915f7d9985c14.tar.gz
uhd-c21464b1107295575afa958e34f915f7d9985c14.tar.bz2
uhd-c21464b1107295575afa958e34f915f7d9985c14.zip
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.
Diffstat (limited to 'simple_gemac/flow_ctrl_rx.v')
-rw-r--r--simple_gemac/flow_ctrl_rx.v105
1 files changed, 40 insertions, 65 deletions
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