diff options
author | Andrew Moch <Andrew.Moch@ni.com> | 2021-02-05 10:48:24 -0600 |
---|---|---|
committer | Aaron Rossetto <aaron.rossetto@ni.com> | 2021-06-03 11:26:54 -0500 |
commit | d099fc3b032250bcc70e4c24f78d5eb6508850e1 (patch) | |
tree | 13ca2469b1aa6b52e85beb53f00d610d6d65bdfc /fpga/usrp3 | |
parent | 30b522b268aed6e7b4bc1a556e88d2a4b2fe6f77 (diff) | |
download | uhd-d099fc3b032250bcc70e4c24f78d5eb6508850e1.tar.gz uhd-d099fc3b032250bcc70e4c24f78d5eb6508850e1.tar.bz2 uhd-d099fc3b032250bcc70e4c24f78d5eb6508850e1.zip |
fpga: lib: add pause support to ethernet xport
Diffstat (limited to 'fpga/usrp3')
-rw-r--r-- | fpga/usrp3/lib/axi4s_sv/axi4s_fifo.sv | 2 | ||||
-rw-r--r-- | fpga/usrp3/lib/rfnoc/xport_sv/eth_ipv4_chdr_adapter.sv | 8 | ||||
-rw-r--r-- | fpga/usrp3/lib/rfnoc/xport_sv/eth_ipv4_chdr_dispatch.sv | 80 | ||||
-rw-r--r-- | fpga/usrp3/lib/rfnoc/xport_sv/eth_ipv4_interface.sv | 27 | ||||
-rw-r--r-- | fpga/usrp3/lib/rfnoc/xport_sv/eth_ipv4_internal.sv | 1 | ||||
-rw-r--r-- | fpga/usrp3/lib/rfnoc/xport_sv/eth_regs.vh | 1 |
6 files changed, 112 insertions, 7 deletions
diff --git a/fpga/usrp3/lib/axi4s_sv/axi4s_fifo.sv b/fpga/usrp3/lib/axi4s_sv/axi4s_fifo.sv index 0aa1daca0..d312b6f32 100644 --- a/fpga/usrp3/lib/axi4s_sv/axi4s_fifo.sv +++ b/fpga/usrp3/lib/axi4s_sv/axi4s_fifo.sv @@ -22,7 +22,7 @@ module axi4s_fifo #( ); `include "axi4s.vh" - + // Parameter Checks initial begin assert (i.DATA_WIDTH == o.DATA_WIDTH) else diff --git a/fpga/usrp3/lib/rfnoc/xport_sv/eth_ipv4_chdr_adapter.sv b/fpga/usrp3/lib/rfnoc/xport_sv/eth_ipv4_chdr_adapter.sv index 892e0a497..355cafb8b 100644 --- a/fpga/usrp3/lib/rfnoc/xport_sv/eth_ipv4_chdr_adapter.sv +++ b/fpga/usrp3/lib/rfnoc/xport_sv/eth_ipv4_chdr_adapter.sv @@ -65,11 +65,14 @@ module eth_ipv4_chdr_adapter #( input logic [47:0] my_mac, input logic [31:0] my_ip, input logic [15:0] my_udp_chdr_port, + input logic [15:0] my_pause_set, + input logic [15:0] my_pause_clear, output logic chdr_dropped, output logic cpu_dropped, // Ethernet MAC + output logic eth_pause_req, AxiStreamIf.master eth_tx, // tUser = {1'b0,trailing bytes}; AxiStreamIf.slave eth_rx, // tUser = {error,trailing bytes}; // CHDR router interface @@ -90,7 +93,7 @@ module eth_ipv4_chdr_adapter #( localparam CPU_USER_W = $clog2(CPU_W/8)+1; localparam CHDR_USER_W = $clog2(CHDR_W/8); localparam MAX_PACKET_BYTES = 2**16; - localparam DEBUG = 1; + localparam DEBUG = 0; `include "eth_constants.vh" @@ -137,12 +140,15 @@ module eth_ipv4_chdr_adapter #( .DROP_MIN_PACKET(DROP_MIN_PACKET), .ENET_W(ENET_W) ) eth_dispatch_i ( + .eth_pause_req (eth_pause_req), .eth_rx (eth_rx1), .e2v (e2v1), .e2c (e2c1), .my_mac (my_mac), .my_ip (my_ip), .my_udp_chdr_port (my_udp_chdr_port), + .my_pause_set (my_pause_set), + .my_pause_clear (my_pause_clear), .chdr_dropped (chdr_dropped), .cpu_dropped (cpu_dropped) ); diff --git a/fpga/usrp3/lib/rfnoc/xport_sv/eth_ipv4_chdr_dispatch.sv b/fpga/usrp3/lib/rfnoc/xport_sv/eth_ipv4_chdr_dispatch.sv index 578646640..17aaadc73 100644 --- a/fpga/usrp3/lib/rfnoc/xport_sv/eth_ipv4_chdr_dispatch.sv +++ b/fpga/usrp3/lib/rfnoc/xport_sv/eth_ipv4_chdr_dispatch.sv @@ -34,6 +34,9 @@ // - my_ip : The IPv4 address of this endpoint // - my_udp_chdr_port : The UDP port allocated for CHDR traffic on this endpoint // +// - my pause set : number of word of fullness on CHDR_FIFO before requesting a pause +// - my pause clear : number of word of fullness on CHDR_FIFO before clearing a pause request +// module eth_ipv4_chdr_dispatch #( int CPU_FIFO_SIZE = $clog2(8*1024), @@ -46,6 +49,7 @@ module eth_ipv4_chdr_dispatch #( )( // AXI-Stream interfaces + output logic eth_pause_req, AxiStreamIf.slave eth_rx, // tUser={error,trailing bytes}; AxiStreamIf.master e2v, // tUser={1'b0,trailing bytes}; AxiStreamIf.master e2c, // tUser={1'b0,trailing bytes}; @@ -54,6 +58,9 @@ module eth_ipv4_chdr_dispatch #( input logic [47:0] my_mac, input logic [31:0] my_ip, input logic [15:0] my_udp_chdr_port, + // Pause control + input logic [15:0] my_pause_set, + input logic [15:0] my_pause_clear, output logic chdr_dropped, output logic cpu_dropped @@ -63,15 +70,17 @@ module eth_ipv4_chdr_dispatch #( logic [47:0] e_my_mac; logic [31:0] e_my_ip; logic [15:0] e_my_udp_chdr_port; + logic [15:0] e_pause_set; + logic [15:0] e_pause_clear; // crossing clock boundaries. // my_mac, my_ip,,my_udp_chdr_port must be written // prior to traffic, or an inconsistent version will // exist for a clock period or 2. This would be better // done with a full handshake. - synchronizer #(.WIDTH(96),.STAGES(1)) + synchronizer #(.WIDTH(96+32),.STAGES(1)) e_info_sync (.clk(eth_rx.clk),.rst(eth_rx.rst), - .in({my_mac,my_ip,my_udp_chdr_port}), - .out({e_my_mac,e_my_ip,e_my_udp_chdr_port})); + .in({my_mac,my_ip,my_udp_chdr_port,my_pause_set,my_pause_clear}), + .out({e_my_mac,e_my_ip,e_my_udp_chdr_port,e_pause_set,e_pause_clear})); localparam ENET_USER_W = $clog2(ENET_W/8)+1; @@ -515,11 +524,72 @@ module eth_ipv4_chdr_dispatch #( // transferring a packet. To ensure that upstream logic is not // blocked, we instantiate at laeast one packet of buffering here. // The actual size is set by CHDR_FIFO_SIZE. + logic [15:0] chdr_occupied; + logic [15:0] chdr_occupied_q; + localparam CHDR_FIFO_WORD_SIZE = CHDR_FIFO_SIZE-$clog2(ENET_W/8); axi4s_fifo #( - .SIZE(CHDR_FIFO_SIZE-$clog2(ENET_W/8)) + .SIZE(CHDR_FIFO_WORD_SIZE) ) chdr_fifo_i ( - .clear(1'b0),.space(),.occupied(), + .clear(1'b0),.space(),.occupied(chdr_occupied), .i(chdr1),.o(e2v) ); + // documentation requires pause requests to be set for a minimum of 16 clocks. + // I'm providing the same gauranteed min time in the set and clear direction + logic [3:0] pause_timer; + typedef enum logic [1:0] { + ST_IDLE = 2'd0, + ST_MIN_DELAY_SET = 2'd1, + ST_REQUESTING = 2'd2, + ST_MIN_DELAY_CLR = 2'd3 + } pause_state_t; + pause_state_t pause_state = ST_IDLE; + + always_ff @(posedge eth_rx.clk) begin : pause_req_ff + if (eth_rx.rst) begin + chdr_occupied_q <= 0; + eth_pause_req <= 1'b0; + pause_state <= ST_IDLE; + pause_timer <= 0; + end else begin + chdr_occupied_q <= chdr_occupied; + + case (pause_state) + + ST_IDLE: begin + pause_timer <= 0; + if (chdr_occupied_q >= e_pause_set) begin + eth_pause_req <= 1'b1; + pause_state <= ST_MIN_DELAY_SET; + pause_timer <= pause_timer-1; // Wrap counter to max value + end + end + + ST_MIN_DELAY_SET: begin + pause_timer <= pause_timer-1; + if (pause_timer == 1) begin + pause_state <= ST_REQUESTING; + end + end + + ST_REQUESTING: begin + pause_timer <= 0; + if (chdr_occupied_q <= e_pause_clear) begin + eth_pause_req <= 1'b0; + pause_state <= ST_MIN_DELAY_CLR; + pause_timer <= pause_timer-1; // Wrap counter to max value + end + end + + ST_MIN_DELAY_CLR: begin + pause_timer <= pause_timer-1; + if (pause_timer == 1) begin + pause_state <= ST_IDLE; + end + end + endcase + end + end + + endmodule // eth_ipv4_chdr_dispatch diff --git a/fpga/usrp3/lib/rfnoc/xport_sv/eth_ipv4_interface.sv b/fpga/usrp3/lib/rfnoc/xport_sv/eth_ipv4_interface.sv index 80670e029..fe6fff8c8 100644 --- a/fpga/usrp3/lib/rfnoc/xport_sv/eth_ipv4_interface.sv +++ b/fpga/usrp3/lib/rfnoc/xport_sv/eth_ipv4_interface.sv @@ -38,6 +38,7 @@ module eth_ipv4_interface #( int PREAMBLE_BYTES = 6, bit ADD_SOF = 1, bit SYNC = 0, + bit PAUSE_EN = 0, int ENET_W = 64, int CPU_W = 64, int CHDR_W = 64 @@ -63,6 +64,7 @@ module eth_ipv4_interface #( output logic [15:0] my_udp_chdr_port, // Ethernet MAC + output logic eth_pause_req, AxiStreamIf.master eth_tx, // tUser = {1'b0,trailing bytes}; AxiStreamIf.slave eth_rx, // tUser = {error,trailing bytes}; // CHDR router interface @@ -77,6 +79,8 @@ module eth_ipv4_interface #( localparam [47:0] DEFAULT_MAC_ADDR = {8'h00, 8'h80, 8'h2f, 8'h16, 8'hc5, 8'h2f}; localparam [31:0] DEFAULT_IP_ADDR = {8'd192, 8'd168, 8'd10, 8'd2}; localparam [31:0] DEFAULT_UDP_PORT = 16'd49153; + localparam [15:0] DEFAULT_PAUSE_SET = 16'd00040; + localparam [15:0] DEFAULT_PAUSE_CLEAR = 16'd00020; //--------------------------------------------------------- // Registers @@ -102,6 +106,8 @@ module eth_ipv4_interface #( logic chdr_dropped; logic [31:0] chdr_drop_count = 0; logic [31:0] cpu_drop_count = 0; + logic [15:0] my_pause_set = DEFAULT_PAUSE_SET; + logic [15:0] my_pause_clear = DEFAULT_PAUSE_CLEAR; always_comb begin : bridge_mux my_mac = bridge_en ? bridge_mac_reg : mac_reg; @@ -118,6 +124,8 @@ module eth_ipv4_interface #( bridge_mac_reg <= DEFAULT_MAC_ADDR; bridge_ip_reg <= DEFAULT_IP_ADDR; bridge_udp_port <= DEFAULT_UDP_PORT; + my_pause_set <= DEFAULT_PAUSE_SET; + my_pause_clear <= DEFAULT_PAUSE_CLEAR; end else begin if (reg_wr_req) @@ -149,6 +157,14 @@ module eth_ipv4_interface #( REG_BRIDGE_ENABLE: bridge_en <= reg_wr_data[0]; + + REG_PAUSE: + begin + if (PAUSE_EN) begin + my_pause_set <= reg_wr_data[15:0]; + my_pause_clear <= reg_wr_data[31:16]; + end + end endcase end end @@ -210,6 +226,14 @@ module eth_ipv4_interface #( reg_rd_data <= cpu_drop_count; cpu_drop_count <= 0; // clear when read end + + REG_PAUSE: + begin + if (PAUSE_EN) begin + reg_rd_data[15:0] <= my_pause_set; + reg_rd_data[31:16] <= my_pause_clear; + end + end default: reg_rd_resp <= 1'b0; endcase @@ -256,6 +280,7 @@ module eth_ipv4_interface #( .CPU_W (CPU_W), .CHDR_W (CHDR_W) ) eth_adapter_i ( + .eth_pause_req (eth_pause_req), .eth_rx (eth_rx ), .eth_tx (eth_tx ), .v2e (v2e ), @@ -266,6 +291,8 @@ module eth_ipv4_interface #( .my_mac (my_mac ), .my_ip (my_ip ), .my_udp_chdr_port(my_udp_chdr_port), + .my_pause_set (my_pause_set), + .my_pause_clear (my_pause_clear), .chdr_dropped (e_chdr_dropped), .cpu_dropped (e_cpu_dropped) ); diff --git a/fpga/usrp3/lib/rfnoc/xport_sv/eth_ipv4_internal.sv b/fpga/usrp3/lib/rfnoc/xport_sv/eth_ipv4_internal.sv index c0af2a84d..d4bc9d355 100644 --- a/fpga/usrp3/lib/rfnoc/xport_sv/eth_ipv4_internal.sv +++ b/fpga/usrp3/lib/rfnoc/xport_sv/eth_ipv4_internal.sv @@ -365,6 +365,7 @@ module eth_ipv4_internal #( .reg_rd_addr (reg_rd_addr), .reg_rd_resp (reg_rd_resp_eth_if), .reg_rd_data (reg_rd_data_eth_if), + .eth_pause_req (), .eth_tx (e2h_chdr), .eth_rx (h2e_chdr), .e2v (e2v_chdr), diff --git a/fpga/usrp3/lib/rfnoc/xport_sv/eth_regs.vh b/fpga/usrp3/lib/rfnoc/xport_sv/eth_regs.vh index 1deb35aee..96e9ce53f 100644 --- a/fpga/usrp3/lib/rfnoc/xport_sv/eth_regs.vh +++ b/fpga/usrp3/lib/rfnoc/xport_sv/eth_regs.vh @@ -30,3 +30,4 @@ localparam [REG_AWIDTH-1:0] REG_BRIDGE_ENABLE = BASE + 'h1020; localparam [REG_AWIDTH-1:0] REG_CHDR_DROPPED = BASE + 'h1030; localparam [REG_AWIDTH-1:0] REG_CPU_DROPPED = BASE + 'h1034; +localparam [REG_AWIDTH-1:0] REG_PAUSE = BASE + 'h1038; |