aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew Moch <Andrew.Moch@ni.com>2020-07-29 19:26:40 +0100
committerWade Fife <wade.fife@ettus.com>2020-07-31 13:32:59 -0500
commita68e7101167a4b5bf7b60ed90d963982aae735b8 (patch)
treea5180460f4cc746467a00ceaf27fae72b1effc71
parent473b0f5abe882ca316a7fe1a59234676940ef26b (diff)
downloaduhd-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.v291
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