diff options
author | Andrew Moch <Andrew.Moch@ni.com> | 2020-07-29 19:26:40 +0100 |
---|---|---|
committer | Wade Fife <wade.fife@ettus.com> | 2020-07-31 13:32:59 -0500 |
commit | a68e7101167a4b5bf7b60ed90d963982aae735b8 (patch) | |
tree | a5180460f4cc746467a00ceaf27fae72b1effc71 | |
parent | 473b0f5abe882ca316a7fe1a59234676940ef26b (diff) | |
download | uhd-a68e7101167a4b5bf7b60ed90d963982aae735b8.tar.gz uhd-a68e7101167a4b5bf7b60ed90d963982aae735b8.tar.bz2 uhd-a68e7101167a4b5bf7b60ed90d963982aae735b8.zip |
fpga: lib: Add xge features for new xport_sv
- Made some things optional to reduce logic when
used with the new xport_sv:
(1) Clocking to sys_clk
(2) Preamble insertion
- New options to CUTTHROUGH faster on the TX path.
The new xport_sv already has a gate to accumulate at
its clock crossing.
-rw-r--r-- | fpga/usrp3/lib/xge_interface/xge_mac_wrapper.v | 291 |
1 files changed, 191 insertions, 100 deletions
diff --git a/fpga/usrp3/lib/xge_interface/xge_mac_wrapper.v b/fpga/usrp3/lib/xge_interface/xge_mac_wrapper.v index 136ff8dff..4b75897aa 100644 --- a/fpga/usrp3/lib/xge_interface/xge_mac_wrapper.v +++ b/fpga/usrp3/lib/xge_interface/xge_mac_wrapper.v @@ -1,6 +1,6 @@ ///////////////////////////////////////////////////////////////////// // -// Copyright 2013-2016 Ettus Research, A National Instruments Company +// Copyright 2013-2020 Ettus Research, A National Instruments Company // // SPDX-License-Identifier: LGPL-3.0-or-later // @@ -16,11 +16,20 @@ // *) On TX, to not start an Ethernet Tx until a complete packet is present in the // last Tx FIFO so that the MAC doesn't underrun. // +// Parameters: +// - PORTNUM: Refers to which ethernet port is being built. Added to padding but not used +// - WISHBONE: If set use wishbone implementation +// - ADD_PREAMBLE: If set add/remove 6 byte padding used in old ethernet_interface +// - CROSS_TO_SYSCLK: If set cross AXI streams to the sys_clk domain. +// - CUT_THROUGH: If > 0, how many words to wait before starting to transmit. ///////////////////////////////////////////////////////////////////// module xge_mac_wrapper #( parameter PORTNUM = 8'd0, - parameter WISHBONE = 1 + parameter WISHBONE = 1, + parameter ADD_PREAMBLE = 1, + parameter CROSS_TO_SYSCLK = 1, + parameter CUT_THROUGH = 0 )( // XGMII input xgmii_clk, @@ -83,20 +92,22 @@ module xge_mac_wrapper #( .clk(xgmii_clk), .rst(1'b0 /* no reset */), .in(phy_ready), .out(phy_ready_xgmiiclk) ); - synchronizer #( - .INITIAL_VAL(1'b1), .STAGES(3) - ) sys_rst_sync_i ( - .clk(xgmii_clk), .rst(1'b0 /* no reset */), .in(sys_rst), .out(sys_rst_xgmiiclk) - ); - + if (CROSS_TO_SYSCLK) begin : reset_cross + synchronizer #( + .INITIAL_VAL(1'b1), .STAGES(3) + ) sys_rst_sync_i ( + .clk(xgmii_clk), .rst(1'b0 /* no reset */), .in(sys_rst), .out(sys_rst_xgmiiclk) + ); + assign xgmii_reset = !phy_ready_xgmiiclk || sys_rst_xgmiiclk; + end else begin : reset_no_cross + assign xgmii_reset = !phy_ready_xgmiiclk; + end synchronizer #( .INITIAL_VAL(1'b1), .STAGES(3) ) tx_enabled_sync_i ( .clk(xgmii_clk), .rst(1'b0 /* no reset */), .in(ctrl_tx_enable), .out(ctrl_tx_enable_xclk) ); - assign xgmii_reset = !phy_ready_xgmiiclk || sys_rst_xgmiiclk; - // // 10G MAC // @@ -116,7 +127,7 @@ module xge_mac_wrapper #( wire eth_tx_sof; wire eth_tx_valid; - generate if (WISHBONE == 1) begin + generate if (WISHBONE == 1) begin : wishbone_mac xge_mac_wb xge_mac_wb ( // Clocks and Resets .clk_156m25 (xgmii_clk), @@ -175,7 +186,7 @@ module xge_mac_wrapper #( assign status_local_fault = 1'b0; assign status_remote_fault = 1'b0; - end else begin + end else begin : xge_mac xge_mac xge_mac ( // Clocks and Resets .clk_156m25 (xgmii_clk), @@ -227,7 +238,7 @@ module xge_mac_wrapper #( endgenerate /////////////////////////////////////////////////////////////////////////////////////// - // RX FIFO Chain + // RX FIFO Chain /////////////////////////////////////////////////////////////////////////////////////// wire [63:0] rx_tdata_int; wire [3:0] rx_tuser_int; @@ -246,52 +257,70 @@ module xge_mac_wrapper #( .pkt_rx_eop(eth_rx_eof) ); - // - // Add pad of 6 empty bytes before MAC addresses of new Rxed packet so that IP - // headers are alligned. Also put metadata in first octet of pad that shows - // ingress port. - // - xge64_to_axi64 #( - .LABEL(PORTNUM) - ) xge64_to_axi64 ( - .clk(xgmii_clk), - .reset(xgmii_reset), - .clear(1'b0), - .datain(eth_rx_data), - .occ(eth_rx_occ), - .sof(eth_rx_sof), - .eof(eth_rx_eof), - .err(eth_rx_err), - .valid(eth_rx_valid), - .axis_tdata(rx_tdata_int), - .axis_tuser(rx_tuser_int), - .axis_tlast(rx_tlast_int), - .axis_tvalid(rx_tvalid_int), - .axis_tready(rx_tready_int) - ); - // - // Large FIFO must be able to run input side at 64b@156MHz to sustain 10Gb Rx. - // - axi64_4k_2clk_fifo rxfifo_2clk ( - .s_aresetn(~xgmii_reset), - .s_aclk(xgmii_clk), - .s_axis_tvalid(rx_tvalid_int), - .s_axis_tready(rx_tready_int), - .s_axis_tdata(rx_tdata_int), - .s_axis_tlast(rx_tlast_int), - .s_axis_tuser(rx_tuser_int), - .axis_wr_data_count(), - - .m_aclk(sys_clk), - .m_axis_tvalid(rx_tvalid), - .m_axis_tready(rx_tready), - .m_axis_tdata(rx_tdata), - .m_axis_tlast(rx_tlast), - .m_axis_tuser(rx_tuser), - .axis_rd_data_count() - ); + if (ADD_PREAMBLE) begin : rx_preamble + // + // Add pad of 6 empty bytes before MAC addresses of new Rxed packet so that IP + // headers are aligned. Also put metadata in first octet of pad that shows + // ingress port. + // + xge64_to_axi64 #( + .LABEL(PORTNUM) + ) xge64_to_axi64 ( + .clk(xgmii_clk), + .reset(xgmii_reset), + .clear(1'b0), + .datain(eth_rx_data), + .occ(eth_rx_occ), + .sof(eth_rx_sof), + .eof(eth_rx_eof), + .err(eth_rx_err), + .valid(eth_rx_valid), + .axis_tdata(rx_tdata_int), + .axis_tuser(rx_tuser_int), + .axis_tlast(rx_tlast_int), + .axis_tvalid(rx_tvalid_int), + .axis_tready(rx_tready_int) + ); + end else begin : rx_no_preamble + assign rx_tdata_int = eth_rx_data; + assign rx_tuser_int[3] = eth_rx_err; + assign rx_tuser_int[2:0] = eth_rx_occ; + assign rx_tlast_int = eth_rx_eof; + assign rx_tvalid_int = eth_rx_valid; + // there is no holdoff so ignore rx_tready_int + end + + if (CROSS_TO_SYSCLK) begin : rx_cross + // + // Large FIFO must be able to run input side at 64b@156MHz to sustain 10Gb Rx. + // + axi64_4k_2clk_fifo rxfifo_2clk ( + .s_aresetn(~xgmii_reset), + .s_aclk(xgmii_clk), + .s_axis_tvalid(rx_tvalid_int), + .s_axis_tready(rx_tready_int), + .s_axis_tdata(rx_tdata_int), + .s_axis_tlast(rx_tlast_int), + .s_axis_tuser(rx_tuser_int), + .axis_wr_data_count(), + + .m_aclk(sys_clk), + .m_axis_tvalid(rx_tvalid), + .m_axis_tready(rx_tready), + .m_axis_tdata(rx_tdata), + .m_axis_tlast(rx_tlast), + .m_axis_tuser(rx_tuser), + .axis_rd_data_count() + ); + end else begin : rx_no_cross + assign rx_tdata = rx_tdata_int; + assign rx_tuser = rx_tuser_int; + assign rx_tlast = rx_tlast_int; + assign rx_tvalid = rx_tvalid_int; + assign rx_tready_int = rx_tready; + end /////////////////////////////////////////////////////////////////////////////////////// // TX FIFO Chain @@ -314,49 +343,82 @@ module xge_mac_wrapper #( wire tx_sof_int3; wire enable_tx; - axi64_4k_2clk_fifo txfifo_2clk_1x ( - .s_aresetn(~xgmii_reset), - .s_aclk(sys_clk), - .s_axis_tvalid(tx_tvalid), - .s_axis_tready(tx_tready), - .s_axis_tdata(tx_tdata), - .s_axis_tlast(tx_tlast), - .s_axis_tuser(tx_tuser), - .axis_wr_data_count(), - - .m_aclk(xgmii_clk), - .m_axis_tvalid(tx_tvalid_int), - .m_axis_tready(tx_tready_int), - .m_axis_tdata(tx_tdata_int), - .m_axis_tlast(tx_tlast_int), - .m_axis_tuser(tx_tuser_int), - .axis_rd_data_count() - ); + if (CROSS_TO_SYSCLK) begin : tx_cross + axi64_4k_2clk_fifo txfifo_2clk_1x ( + .s_aresetn(~xgmii_reset), + .s_aclk(sys_clk), + .s_axis_tvalid(tx_tvalid), + .s_axis_tready(tx_tready), + .s_axis_tdata(tx_tdata), + .s_axis_tlast(tx_tlast), + .s_axis_tuser(tx_tuser), + .axis_wr_data_count(), - // - // Strip the 6 octet ethernet padding we used internally. - // Put SOF into bit[3] of tuser. - // - axi64_to_xge64 axi64_to_xge64 ( - .clk(xgmii_clk), - .reset(xgmii_reset), - .clear(1'b0), - .s_axis_tdata(tx_tdata_int), - .s_axis_tuser(tx_tuser_int), - .s_axis_tlast(tx_tlast_int), - .s_axis_tvalid(tx_tvalid_int), - .s_axis_tready(tx_tready_int), - .m_axis_tdata(tx_tdata_int2), - .m_axis_tuser(tx_tuser_int2), - .m_axis_tlast(tx_tlast_int2), - .m_axis_tvalid(tx_tvalid_int2), - .m_axis_tready(tx_tready_int2) - ); + .m_aclk(xgmii_clk), + .m_axis_tvalid(tx_tvalid_int), + .m_axis_tready(tx_tready_int), + .m_axis_tdata(tx_tdata_int), + .m_axis_tlast(tx_tlast_int), + .m_axis_tuser(tx_tuser_int), + .axis_rd_data_count() + ); + end else begin : tx_no_cross + assign tx_tdata_int = tx_tdata; + assign tx_tuser_int = tx_tuser; + assign tx_tlast_int = tx_tlast; + assign tx_tvalid_int = tx_tvalid; + assign tx_tready = tx_tready_int; + end + + + if (ADD_PREAMBLE) begin : tx_preamble + // + // Strip the 6 octet ethernet padding we used internally. + // Put SOF into bit[3] of tuser. + // + axi64_to_xge64 axi64_to_xge64 ( + .clk(xgmii_clk), + .reset(xgmii_reset), + .clear(1'b0), + .s_axis_tdata(tx_tdata_int), + .s_axis_tuser(tx_tuser_int), + .s_axis_tlast(tx_tlast_int), + .s_axis_tvalid(tx_tvalid_int), + .s_axis_tready(tx_tready_int), + .m_axis_tdata(tx_tdata_int2), + .m_axis_tuser(tx_tuser_int2), + .m_axis_tlast(tx_tlast_int2), + .m_axis_tvalid(tx_tvalid_int2), + .m_axis_tready(tx_tready_int2) + ); + end else begin : tx_no_preamble + reg sof = 1'b1; + + // Add SOF + always @(posedge xgmii_clk) begin : add_sof + if (xgmii_reset) begin + sof <= 1'b1; + end else if (tx_tvalid_int && tx_tready_int) begin + sof <= tx_tlast_int; + end + end + + assign tx_tdata_int2 = tx_tdata_int; + assign tx_tuser_int2[3] = sof && tx_tvalid_int; + assign tx_tuser_int2[2:0] = tx_tuser_int[2:0]; + assign tx_tlast_int2 = tx_tlast_int; + assign tx_tvalid_int2 = tx_tvalid_int; + assign tx_tready_int = tx_tready_int2; + end // // Large FIFO can hold a max sized ethernet packet. // - axi_fifo #(.WIDTH(64+4+1), .SIZE(10)) txfifo_2 ( + wire [15:0] tx_occupied; + + localparam TX_FIFO_SIZE = CUT_THROUGH > 0 ? $clog2(CUT_THROUGH)+1 : 10; + + axi_fifo #(.WIDTH(64+4+1), .SIZE(TX_FIFO_SIZE)) txfifo ( .clk(xgmii_clk), .reset(xgmii_reset), .clear(1'b0), .i_tdata({tx_tlast_int2, tx_tuser_int2, tx_tdata_int2}), .i_tvalid(tx_tvalid_int2), @@ -364,10 +426,39 @@ module xge_mac_wrapper #( .o_tvalid(tx_tvalid_int3), .o_tready(tx_tready_int3), .o_tdata({eth_tx_eof,tx_sof_int3,eth_tx_occ,eth_tx_data}), - .space(), .occupied() + .space(), .occupied(tx_occupied) ); // + // add cut through if we have "enough" data buffered up + // + reg cut_through; + + if (CUT_THROUGH > 0) begin : yes_cut_through + + wire cut_start; + wire cut_end; + + assign cut_start = tx_occupied > CUT_THROUGH; + assign cut_end = eth_tx_eof && eth_tx_valid; + + // Add SOF + always @(posedge xgmii_clk) begin : cut_through_dff + if (xgmii_reset) begin + cut_through <= 1'b0; + end else begin + if (cut_start) begin + cut_through <= 1'b1; + end else if (cut_end) begin + cut_through <= 1'b0; + end + end + end + end else begin : no_cut_through + always @(*) cut_through <= 0; + end + + // // Monitor number of Ethernet packets in tx_fifo2 // axi_count_packets_in_fifo axi_count_packets_in_fifo ( @@ -385,10 +476,10 @@ module xge_mac_wrapper #( // // - // Supress FIFO flags to stop overflow of MAC in Tx direction + // Suppress FIFO flags to stop overflow of MAC in Tx direction // - assign eth_tx_valid = tx_tvalid_int3 & enable_tx; - assign tx_tready_int3 = enable_tx; - assign eth_tx_sof = tx_sof_int3 & enable_tx; + assign tx_tready_int3 = (enable_tx || cut_through); + assign eth_tx_valid = (enable_tx || cut_through) & tx_tvalid_int3; + assign eth_tx_sof = (enable_tx || cut_through) & tx_sof_int3; endmodule |