summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--simple_gemac/flow_ctrl_rx.v105
-rw-r--r--simple_gemac/simple_gemac.v6
-rw-r--r--simple_gemac/simple_gemac_wb.v20
-rw-r--r--simple_gemac/simple_gemac_wrapper.v7
-rw-r--r--top/u2_rev3/Makefile1
5 files changed, 66 insertions, 73 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
diff --git a/simple_gemac/simple_gemac.v b/simple_gemac/simple_gemac.v
index 5ec2fa2ba..868a66819 100644
--- a/simple_gemac/simple_gemac.v
+++ b/simple_gemac/simple_gemac.v
@@ -6,7 +6,7 @@ module simple_gemac
input GMII_RX_CLK, input GMII_RX_DV, input GMII_RX_ER, input [7:0] GMII_RXD,
// Flow Control Interface
- input pause_req, input [15:0] pause_time, input pause_en,
+ input pause_req, input [15:0] pause_time_req, input pause_respect_en,
// Settings
input [47:0] ucast_addr, input [47:0] mcast_addr,
@@ -33,7 +33,7 @@ module simple_gemac
.GMII_TX_ER(GMII_TX_ER), .GMII_TXD(GMII_TXD),
.tx_clk(tx_clk), .tx_data(tx_data), .tx_valid(tx_valid), .tx_error(tx_error), .tx_ack(tx_ack),
.ifg(SGE_IFG), .mac_addr(ucast_addr),
- .pause_req(pause_req), .pause_time(pause_time), // We request flow control
+ .pause_req(pause_req), .pause_time(pause_time_req), // We request flow control
.pause_apply(pause_apply), .paused(paused) // We respect flow control
);
@@ -50,7 +50,7 @@ module simple_gemac
flow_ctrl_tx flow_ctrl_tx
(.rst(rst_txclk), .tx_clk(tx_clk),
- .tx_pause_en(pause_en),
+ .tx_pause_en(pause_respect_en),
.pause_quanta(pause_quanta_rcvd), // 16 bit value
.pause_quanta_val(pause_rcvd),
.pause_apply(pause_apply),
diff --git a/simple_gemac/simple_gemac_wb.v b/simple_gemac/simple_gemac_wb.v
index cc2cdf7ec..6df277e3e 100644
--- a/simple_gemac/simple_gemac_wb.v
+++ b/simple_gemac/simple_gemac_wb.v
@@ -24,7 +24,9 @@ module simple_gemac_wb
inout mdio, output mdc,
output [47:0] ucast_addr, output [47:0] mcast_addr,
output pass_ucast, output pass_mcast, output pass_bcast,
- output pass_pause, output pass_all, output pause_en );
+ output pass_pause, output pass_all,
+ output pause_respect_en, output pause_request_en,
+ output [15:0] pause_time, output [15:0] pause_thresh );
wire acc = wb_cyc & wb_stb;
wire wr_acc = wb_cyc & wb_stb & wb_we;
@@ -36,10 +38,10 @@ module simple_gemac_wb
else
wb_ack <= acc & ~wb_ack;
- wire [5:0] misc_settings;
- assign {pass_ucast, pass_mcast, pass_bcast, pass_pause, pass_all, pause_en} = misc_settings;
+ wire [6:0] misc_settings;
+ assign {pause_request_en, pass_ucast, pass_mcast, pass_bcast, pass_pause, pass_all, pause_respect_en} = misc_settings;
- wb_reg #(.ADDR(0),.DEFAULT(6'b111001))
+ wb_reg #(.ADDR(0),.DEFAULT(7'b0111001))
wb_reg_settings (.clk(wb_clk), .rst(wb_rst), .adr(wb_adr[7:2]), .wr_acc(wr_acc),
.dat_i(wb_dat_i), .dat_o(misc_settings) );
wb_reg #(.ADDR(1),.DEFAULT(0))
@@ -131,6 +133,14 @@ module simple_gemac_wb
.WCtrlDataStart(WCtrlDataStart), .RStatStart(RStatStart),
.UpdateMIIRX_DATAReg(UpdateMIIRX_DATAReg) );
+ wb_reg #(.ADDR(11),.DEFAULT(0))
+ wb_reg_pausetime (.clk(wb_clk), .rst(wb_rst), .adr(wb_adr[7:2]), .wr_acc(wr_acc),
+ .dat_i(wb_dat_i), .dat_o(pause_time) );
+
+ wb_reg #(.ADDR(12),.DEFAULT(0))
+ wb_reg_pausethresh (.clk(wb_clk), .rst(wb_rst), .adr(wb_adr[7:2]), .wr_acc(wr_acc),
+ .dat_i(wb_dat_i), .dat_o(pause_thresh) );
+
always @(posedge wb_clk)
case(wb_adr[7:2])
0 : wb_dat_o <= misc_settings;
@@ -144,6 +154,8 @@ module simple_gemac_wb
8 : wb_dat_o <= MIICOMMAND;
9 : wb_dat_o <= MIISTATUS;
10: wb_dat_o <= MIIRX_DATA;
+ 11: wb_dat_o <= pause_time;
+ 12: wb_dat_o <= pause_thresh;
endcase // case (wb_adr[7:2])
endmodule // simple_gemac_wb
diff --git a/simple_gemac/simple_gemac_wrapper.v b/simple_gemac/simple_gemac_wrapper.v
index de445476c..7511f3fb9 100644
--- a/simple_gemac/simple_gemac_wrapper.v
+++ b/simple_gemac/simple_gemac_wrapper.v
@@ -140,7 +140,12 @@ module simple_gemac_wrapper
.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));
- wire [31:0] debug_tx, debug_rx;
+ flow_ctrl_rx flow_ctrl_rx
+ (.pause_request_en(pause_request_en), .pause_time(pause_time), .pause_thresh(pause_thresh),
+ .rx_clk(rx_clk), .rx_reset(rx_reset), .rx_fifo_space(rx_fifo_space),
+ .tx_clk(tx_clk), .tx_reset(tx_reset), .pause_req(pause_req), .pause_time_req(pause_time_req));
+
+ wire [31:0] debug_tx, debug_rx;
assign debug_tx = { { tx_ll_data },
{ tx_ll_sof, tx_ll_eof, tx_ll_src_rdy, tx_ll_dst_rdy,
diff --git a/top/u2_rev3/Makefile b/top/u2_rev3/Makefile
index 7847b8c72..94681f6cd 100644
--- a/top/u2_rev3/Makefile
+++ b/top/u2_rev3/Makefile
@@ -90,6 +90,7 @@ simple_gemac/simple_gemac_rx.v \
simple_gemac/crc.v \
simple_gemac/delay_line.v \
simple_gemac/flow_ctrl_tx.v \
+simple_gemac/flow_ctrl_rx.v \
simple_gemac/address_filter.v \
simple_gemac/ll8_to_txmac.v \
simple_gemac/rxmac_to_ll8.v \