// RX side of flow control -- when we are running out of RX space, send a PAUSE\r
\r
module flow_ctrl_rx\r
- (input rst,\r
- //host processor\r
- input pause_frame_send_en,\r
- input [15:0] pause_quanta_set,\r
- input [15:0] fc_hwmark,\r
- input [15:0] fc_lwmark,\r
- // From MAC_rx_ctrl\r
- input rx_clk,\r
- input [15:0] rx_fifo_space,\r
- // MAC_tx_ctrl\r
- input tx_clk,\r
- output reg xoff_gen,\r
- output reg xon_gen,\r
- input xoff_gen_complete,\r
- input xon_gen_complete\r
+ (input pause_request_en, input [15:0] pause_time, input [15:0] pause_thresh,\r
+ input rx_clk, input rx_reset, input [15:0] rx_fifo_space,\r
+ input tx_clk, input tx_reset, output reg pause_req, output reg [15:0] pause_time_req\r
);\r
\r
// ****************************************************************************** \r
// Force our TX to send a PAUSE frame because our RX is nearly full\r
// ******************************************************************************\r
\r
- reg xon_int, xoff_int;\r
+ // RX Clock Domain\r
+ reg xon, xoff;\r
reg [21:0] countdown;\r
- \r
- always @(posedge rx_clk or posedge rst)\r
- if(rst)\r
- begin\r
- xon_int <= 0;\r
- xoff_int <= 0;\r
- end\r
- else \r
- begin\r
- xon_int <= 0;\r
- xoff_int <= 0;\r
- if(pause_frame_send_en)\r
- if(countdown == 0)\r
- if(rx_fifo_space < fc_lwmark)\r
- xoff_int <= 1;\r
- else\r
- ;\r
- else\r
- if(rx_fifo_space > fc_hwmark)\r
- xon_int <= 1;\r
- end // else: !if(rst)\r
- \r
- reg xoff_int_d1, xon_int_d1;\r
\r
- always @(posedge rx_clk)\r
- xon_int_d1 <= xon_int;\r
- always @(posedge rx_clk)\r
- xoff_int_d1 <= xoff_int;\r
+ wire [15:0] pause_low_thresh = pause_thresh;\r
+ wire [15:0] pause_hi_thresh = 16'hFFFF;\r
+ wire [21:0] pq_reduced = {pause_time,6'd0} - 1700;\r
\r
- always @ (posedge tx_clk or posedge rst)\r
- if (rst)\r
- xoff_gen <=0;\r
- else if (xoff_gen_complete)\r
- xoff_gen <=0;\r
- else if (xoff_int | xoff_int_d1)\r
- xoff_gen <=1;\r
+ always @(posedge rx_clk)\r
+ if(rx_reset)\r
+ xoff <= 0;\r
+ else\r
+ xoff <= (pause_request_en & (countdown==0) & (rx_fifo_space < pause_low_thresh));\r
\r
- always @ (posedge tx_clk or posedge rst)\r
- if (rst)\r
- xon_gen <=0;\r
- else if (xon_gen_complete)\r
- xon_gen <=0;\r
- else if (xon_int | xon_int_d1)\r
- xon_gen <=1; \r
-\r
- wire [15:0] pq_reduced = pause_quanta_set - 2;\r
+ always @(posedge rx_clk)\r
+ if(rx_reset)\r
+ xon <= 0;\r
+ else\r
+ xon <= ((countdown!=0) & (rx_fifo_space > pause_hi_thresh));\r
\r
- always @(posedge tx_clk or posedge rst)\r
- if(rst)\r
+ always @(posedge rx_clk)\r
+ if(rx_reset)\r
countdown <= 0;\r
- else if(xoff_gen)\r
- countdown <= {pq_reduced,6'd0};\r
- else if(xon_gen)\r
+ else if(xoff)\r
+ countdown <= pq_reduced;\r
+ else if(xon)\r
countdown <= 0;\r
else if(countdown != 0)\r
countdown <= countdown - 1;\r
+\r
+ // Cross clock domains\r
+ wire xon_tx, xoff_tx;\r
+ oneshot_2clk send_xon (.clk_in(rx_clk), .in(xon), .clk_out(tx_clk), .out(xon_tx));\r
+ oneshot_2clk send_xoff (.clk_in(rx_clk), .in(xoff), .clk_out(tx_clk), .out(xoff_tx));\r
+ \r
+ always @(posedge tx_clk)\r
+ if(xoff_tx)\r
+ pause_time_req <= pause_time;\r
+ else if(xon_tx)\r
+ pause_time_req <= 0;\r
+\r
+ always @(posedge tx_clk)\r
+ if(tx_reset)\r
+ pause_req <= 0;\r
+ else \r
+ pause_req <= xon_tx | xoff_tx;\r
\r
-endmodule // flow_ctrl\r
+endmodule // flow_ctrl_rx\r