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.


Original-commit: a68e7101167a4b5bf7b60ed90d963982aae735b8
This commit is contained in:
Andrew Moch
2020-07-31 13:32:59 -05:00
committed by Wade Fife
parent d5bbce58cb
commit 439c2af5e2
+189 -98
View File
@@ -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 // 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 // *) 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. // 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 #( module xge_mac_wrapper #(
parameter PORTNUM = 8'd0, parameter PORTNUM = 8'd0,
parameter WISHBONE = 1 parameter WISHBONE = 1,
parameter ADD_PREAMBLE = 1,
parameter CROSS_TO_SYSCLK = 1,
parameter CUT_THROUGH = 0
)( )(
// XGMII // XGMII
input xgmii_clk, 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) .clk(xgmii_clk), .rst(1'b0 /* no reset */), .in(phy_ready), .out(phy_ready_xgmiiclk)
); );
synchronizer #( if (CROSS_TO_SYSCLK) begin : reset_cross
.INITIAL_VAL(1'b1), .STAGES(3) synchronizer #(
) sys_rst_sync_i ( .INITIAL_VAL(1'b1), .STAGES(3)
.clk(xgmii_clk), .rst(1'b0 /* no reset */), .in(sys_rst), .out(sys_rst_xgmiiclk) ) 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 #( synchronizer #(
.INITIAL_VAL(1'b1), .STAGES(3) .INITIAL_VAL(1'b1), .STAGES(3)
) tx_enabled_sync_i ( ) tx_enabled_sync_i (
.clk(xgmii_clk), .rst(1'b0 /* no reset */), .in(ctrl_tx_enable), .out(ctrl_tx_enable_xclk) .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 // 10G MAC
// //
@@ -116,7 +127,7 @@ module xge_mac_wrapper #(
wire eth_tx_sof; wire eth_tx_sof;
wire eth_tx_valid; wire eth_tx_valid;
generate if (WISHBONE == 1) begin generate if (WISHBONE == 1) begin : wishbone_mac
xge_mac_wb xge_mac_wb ( xge_mac_wb xge_mac_wb (
// Clocks and Resets // Clocks and Resets
.clk_156m25 (xgmii_clk), .clk_156m25 (xgmii_clk),
@@ -175,7 +186,7 @@ module xge_mac_wrapper #(
assign status_local_fault = 1'b0; assign status_local_fault = 1'b0;
assign status_remote_fault = 1'b0; assign status_remote_fault = 1'b0;
end else begin end else begin : xge_mac
xge_mac xge_mac ( xge_mac xge_mac (
// Clocks and Resets // Clocks and Resets
.clk_156m25 (xgmii_clk), .clk_156m25 (xgmii_clk),
@@ -227,7 +238,7 @@ module xge_mac_wrapper #(
endgenerate endgenerate
/////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////
// RX FIFO Chain // RX FIFO Chain
/////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////
wire [63:0] rx_tdata_int; wire [63:0] rx_tdata_int;
wire [3:0] rx_tuser_int; wire [3:0] rx_tuser_int;
@@ -246,52 +257,70 @@ module xge_mac_wrapper #(
.pkt_rx_eop(eth_rx_eof) .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)
);
// if (ADD_PREAMBLE) begin : rx_preamble
// Large FIFO must be able to run input side at 64b@156MHz to sustain 10Gb Rx. //
// // Add pad of 6 empty bytes before MAC addresses of new Rxed packet so that IP
axi64_4k_2clk_fifo rxfifo_2clk ( // headers are aligned. Also put metadata in first octet of pad that shows
.s_aresetn(~xgmii_reset), // ingress port.
.s_aclk(xgmii_clk), //
.s_axis_tvalid(rx_tvalid_int), xge64_to_axi64 #(
.s_axis_tready(rx_tready_int), .LABEL(PORTNUM)
.s_axis_tdata(rx_tdata_int), ) xge64_to_axi64 (
.s_axis_tlast(rx_tlast_int), .clk(xgmii_clk),
.s_axis_tuser(rx_tuser_int), .reset(xgmii_reset),
.axis_wr_data_count(), .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
.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 (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 // TX FIFO Chain
@@ -314,49 +343,82 @@ module xge_mac_wrapper #(
wire tx_sof_int3; wire tx_sof_int3;
wire enable_tx; wire enable_tx;
axi64_4k_2clk_fifo txfifo_2clk_1x ( if (CROSS_TO_SYSCLK) begin : tx_cross
.s_aresetn(~xgmii_reset), axi64_4k_2clk_fifo txfifo_2clk_1x (
.s_aclk(sys_clk), .s_aresetn(~xgmii_reset),
.s_axis_tvalid(tx_tvalid), .s_aclk(sys_clk),
.s_axis_tready(tx_tready), .s_axis_tvalid(tx_tvalid),
.s_axis_tdata(tx_tdata), .s_axis_tready(tx_tready),
.s_axis_tlast(tx_tlast), .s_axis_tdata(tx_tdata),
.s_axis_tuser(tx_tuser), .s_axis_tlast(tx_tlast),
.axis_wr_data_count(), .s_axis_tuser(tx_tuser),
.axis_wr_data_count(),
.m_aclk(xgmii_clk), .m_aclk(xgmii_clk),
.m_axis_tvalid(tx_tvalid_int), .m_axis_tvalid(tx_tvalid_int),
.m_axis_tready(tx_tready_int), .m_axis_tready(tx_tready_int),
.m_axis_tdata(tx_tdata_int), .m_axis_tdata(tx_tdata_int),
.m_axis_tlast(tx_tlast_int), .m_axis_tlast(tx_tlast_int),
.m_axis_tuser(tx_tuser_int), .m_axis_tuser(tx_tuser_int),
.axis_rd_data_count() .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
//
// Strip the 6 octet ethernet padding we used internally. if (ADD_PREAMBLE) begin : tx_preamble
// Put SOF into bit[3] of tuser. //
// // Strip the 6 octet ethernet padding we used internally.
axi64_to_xge64 axi64_to_xge64 ( // Put SOF into bit[3] of tuser.
.clk(xgmii_clk), //
.reset(xgmii_reset), axi64_to_xge64 axi64_to_xge64 (
.clear(1'b0), .clk(xgmii_clk),
.s_axis_tdata(tx_tdata_int), .reset(xgmii_reset),
.s_axis_tuser(tx_tuser_int), .clear(1'b0),
.s_axis_tlast(tx_tlast_int), .s_axis_tdata(tx_tdata_int),
.s_axis_tvalid(tx_tvalid_int), .s_axis_tuser(tx_tuser_int),
.s_axis_tready(tx_tready_int), .s_axis_tlast(tx_tlast_int),
.m_axis_tdata(tx_tdata_int2), .s_axis_tvalid(tx_tvalid_int),
.m_axis_tuser(tx_tuser_int2), .s_axis_tready(tx_tready_int),
.m_axis_tlast(tx_tlast_int2), .m_axis_tdata(tx_tdata_int2),
.m_axis_tvalid(tx_tvalid_int2), .m_axis_tuser(tx_tuser_int2),
.m_axis_tready(tx_tready_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. // 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), .clk(xgmii_clk), .reset(xgmii_reset), .clear(1'b0),
.i_tdata({tx_tlast_int2, tx_tuser_int2, tx_tdata_int2}), .i_tdata({tx_tlast_int2, tx_tuser_int2, tx_tdata_int2}),
.i_tvalid(tx_tvalid_int2), .i_tvalid(tx_tvalid_int2),
@@ -364,9 +426,38 @@ module xge_mac_wrapper #(
.o_tvalid(tx_tvalid_int3), .o_tvalid(tx_tvalid_int3),
.o_tready(tx_tready_int3), .o_tready(tx_tready_int3),
.o_tdata({eth_tx_eof,tx_sof_int3,eth_tx_occ,eth_tx_data}), .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 // Monitor number of Ethernet packets in tx_fifo2
// //
@@ -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 || cut_through);
assign tx_tready_int3 = enable_tx; assign eth_tx_valid = (enable_tx || cut_through) & tx_tvalid_int3;
assign eth_tx_sof = tx_sof_int3 & enable_tx; assign eth_tx_sof = (enable_tx || cut_through) & tx_sof_int3;
endmodule endmodule