From 93d9c8c9f616639b386372dd1c20a38ab43348e4 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Wed, 9 Apr 2025 12:18:42 -0700 Subject: [PATCH] eth: Add MAC statistics module to 10G MAC+PCS Signed-off-by: Alex Forencich --- rtl/eth/taxi_eth_mac_phy_10g.f | 1 + rtl/eth/taxi_eth_mac_phy_10g.sv | 192 ++++++++++++++---- rtl/eth/taxi_eth_mac_phy_10g_fifo.sv | 82 ++++++-- rtl/eth/us/taxi_eth_mac_25g_us.sv | 141 +++++++++++-- rtl/eth/us/taxi_eth_mac_25g_us_ch.sv | 100 +++++++-- tb/eth/taxi_eth_mac_phy_10g/Makefile | 5 + .../test_taxi_eth_mac_phy_10g.py | 43 +++- .../test_taxi_eth_mac_phy_10g.sv | 97 +++++++-- tb/eth/taxi_eth_mac_phy_10g_fifo/Makefile | 5 + .../test_taxi_eth_mac_phy_10g_fifo.py | 24 ++- .../test_taxi_eth_mac_phy_10g_fifo.sv | 47 ++++- 11 files changed, 621 insertions(+), 116 deletions(-) diff --git a/rtl/eth/taxi_eth_mac_phy_10g.f b/rtl/eth/taxi_eth_mac_phy_10g.f index ca1bc5b..6749f8a 100644 --- a/rtl/eth/taxi_eth_mac_phy_10g.f +++ b/rtl/eth/taxi_eth_mac_phy_10g.f @@ -1,6 +1,7 @@ taxi_eth_mac_phy_10g.sv taxi_eth_mac_phy_10g_rx.f taxi_eth_mac_phy_10g_tx.f +taxi_eth_mac_stats.f taxi_mac_ctrl_tx.sv taxi_mac_ctrl_rx.sv taxi_mac_pause_ctrl_tx.sv diff --git a/rtl/eth/taxi_eth_mac_phy_10g.sv b/rtl/eth/taxi_eth_mac_phy_10g.sv index 2f32239..6cf5eba 100644 --- a/rtl/eth/taxi_eth_mac_phy_10g.sv +++ b/rtl/eth/taxi_eth_mac_phy_10g.sv @@ -33,6 +33,11 @@ module taxi_eth_mac_phy_10g # parameter BITSLIP_HIGH_CYCLES = 0, parameter BITSLIP_LOW_CYCLES = 7, parameter COUNT_125US = 125000/6.4, + parameter logic STAT_EN = 1'b0, + parameter STAT_TX_LEVEL = 1, + parameter STAT_RX_LEVEL = 1, + parameter STAT_ID_BASE = 0, + parameter STAT_UPDATE_PERIOD = 1024, parameter logic PFC_EN = 1'b0, parameter logic PAUSE_EN = PFC_EN ) @@ -94,20 +99,49 @@ module taxi_eth_mac_phy_10g # input wire logic tx_pause_req = 1'b0, output wire logic tx_pause_ack, + /* + * Statistics + */ + input wire logic stat_clk, + input wire logic stat_rst, + taxi_axis_if.src m_axis_stat, + /* * Status */ output wire logic [1:0] tx_start_packet, - output wire logic tx_error_underflow, + output wire logic [3:0] stat_tx_byte, + output wire logic [15:0] stat_tx_pkt_len, + output wire logic stat_tx_pkt_ucast, + output wire logic stat_tx_pkt_mcast, + output wire logic stat_tx_pkt_bcast, + output wire logic stat_tx_pkt_vlan, + output wire logic stat_tx_pkt_good, + output wire logic stat_tx_pkt_bad, + output wire logic stat_tx_err_oversize, + output wire logic stat_tx_err_user, + output wire logic stat_tx_err_underflow, output wire logic [1:0] rx_start_packet, output wire logic [6:0] rx_error_count, - output wire logic rx_error_bad_frame, - output wire logic rx_error_bad_fcs, - output wire logic rx_bad_block, - output wire logic rx_sequence_error, output wire logic rx_block_lock, output wire logic rx_high_ber, output wire logic rx_status, + output wire logic [3:0] stat_rx_byte, + output wire logic [15:0] stat_rx_pkt_len, + output wire logic stat_rx_pkt_fragment, + output wire logic stat_rx_pkt_jabber, + output wire logic stat_rx_pkt_ucast, + output wire logic stat_rx_pkt_mcast, + output wire logic stat_rx_pkt_bcast, + output wire logic stat_rx_pkt_vlan, + output wire logic stat_rx_pkt_good, + output wire logic stat_rx_pkt_bad, + output wire logic stat_rx_err_oversize, + output wire logic stat_rx_err_bad_fcs, + output wire logic stat_rx_err_bad_block, + output wire logic stat_rx_err_framing, + output wire logic stat_rx_err_preamble, + input wire logic stat_rx_fifo_drop = 1'b0, output wire logic stat_tx_mcf, output wire logic stat_rx_mcf, output wire logic stat_tx_lfc_pkt, @@ -130,8 +164,10 @@ module taxi_eth_mac_phy_10g # /* * Configuration */ - input wire logic [7:0] cfg_ifg = 8'd12, + input wire logic [15:0] cfg_tx_max_pkt_len = 16'd1518, + input wire logic [7:0] cfg_tx_ifg = 8'd12, input wire logic cfg_tx_enable = 1'b1, + input wire logic [15:0] cfg_rx_max_pkt_len = 16'd1518, input wire logic cfg_rx_enable = 1'b1, input wire logic cfg_tx_prbs31_enable = 1'b0, input wire logic cfg_rx_prbs31_enable = 1'b0, @@ -223,26 +259,26 @@ eth_mac_phy_10g_rx_inst ( .rx_block_lock(rx_block_lock), .rx_high_ber(rx_high_ber), .rx_status(rx_status), - .stat_rx_byte(), - .stat_rx_pkt_len(), - .stat_rx_pkt_fragment(), - .stat_rx_pkt_jabber(), - .stat_rx_pkt_ucast(), - .stat_rx_pkt_mcast(), - .stat_rx_pkt_bcast(), - .stat_rx_pkt_vlan(), - .stat_rx_pkt_good(), - .stat_rx_pkt_bad(rx_error_bad_frame), - .stat_rx_err_oversize(), - .stat_rx_err_bad_fcs(rx_error_bad_fcs), - .stat_rx_err_bad_block(rx_bad_block), - .stat_rx_err_framing(rx_sequence_error), - .stat_rx_err_preamble(), + .stat_rx_byte(stat_rx_byte), + .stat_rx_pkt_len(stat_rx_pkt_len), + .stat_rx_pkt_fragment(stat_rx_pkt_fragment), + .stat_rx_pkt_jabber(stat_rx_pkt_jabber), + .stat_rx_pkt_ucast(stat_rx_pkt_ucast), + .stat_rx_pkt_mcast(stat_rx_pkt_mcast), + .stat_rx_pkt_bcast(stat_rx_pkt_bcast), + .stat_rx_pkt_vlan(stat_rx_pkt_vlan), + .stat_rx_pkt_good(stat_rx_pkt_good), + .stat_rx_pkt_bad(stat_rx_pkt_bad), + .stat_rx_err_oversize(stat_rx_err_oversize), + .stat_rx_err_bad_fcs(stat_rx_err_bad_fcs), + .stat_rx_err_bad_block(stat_rx_err_bad_block), + .stat_rx_err_framing(stat_rx_err_framing), + .stat_rx_err_preamble(stat_rx_err_preamble), /* * Configuration */ - .cfg_rx_max_pkt_len(16'd9218), + .cfg_rx_max_pkt_len(cfg_rx_max_pkt_len), .cfg_rx_enable(cfg_rx_enable), .cfg_rx_prbs31_enable(cfg_rx_prbs31_enable) ); @@ -287,27 +323,113 @@ eth_mac_phy_10g_tx_inst ( * Status */ .tx_start_packet(tx_start_packet), - .stat_tx_byte(), - .stat_tx_pkt_len(), - .stat_tx_pkt_ucast(), - .stat_tx_pkt_mcast(), - .stat_tx_pkt_bcast(), - .stat_tx_pkt_vlan(), - .stat_tx_pkt_good(), - .stat_tx_pkt_bad(), - .stat_tx_err_oversize(), - .stat_tx_err_user(), - .stat_tx_err_underflow(tx_error_underflow), + .stat_tx_byte(stat_tx_byte), + .stat_tx_pkt_len(stat_tx_pkt_len), + .stat_tx_pkt_ucast(stat_tx_pkt_ucast), + .stat_tx_pkt_mcast(stat_tx_pkt_mcast), + .stat_tx_pkt_bcast(stat_tx_pkt_bcast), + .stat_tx_pkt_vlan(stat_tx_pkt_vlan), + .stat_tx_pkt_good(stat_tx_pkt_good), + .stat_tx_pkt_bad(stat_tx_pkt_bad), + .stat_tx_err_oversize(stat_tx_err_oversize), + .stat_tx_err_user(stat_tx_err_user), + .stat_tx_err_underflow(stat_tx_err_underflow), /* * Configuration */ - .cfg_tx_max_pkt_len(16'd9218), - .cfg_tx_ifg(cfg_ifg), + .cfg_tx_max_pkt_len(cfg_tx_max_pkt_len), + .cfg_tx_ifg(cfg_tx_ifg), .cfg_tx_enable(cfg_tx_enable), .cfg_tx_prbs31_enable(cfg_tx_prbs31_enable) ); +if (STAT_EN) begin : stats + + taxi_eth_mac_stats #( + .STAT_TX_LEVEL(STAT_TX_LEVEL), + .STAT_RX_LEVEL(STAT_RX_LEVEL), + .STAT_ID_BASE(STAT_ID_BASE), + .STAT_UPDATE_PERIOD(STAT_UPDATE_PERIOD), + .INC_W(4) + ) + mac_stats_inst ( + .rx_clk(rx_clk), + .rx_rst(rx_rst), + .tx_clk(tx_clk), + .tx_rst(tx_rst), + + /* + * Statistics + */ + .stat_clk(stat_clk), + .stat_rst(stat_rst), + .m_axis_stat(m_axis_stat), + + /* + * Status + */ + .tx_start_packet(|tx_start_packet), + .stat_tx_byte(stat_tx_byte), + .stat_tx_pkt_len(stat_tx_pkt_len), + .stat_tx_pkt_ucast(stat_tx_pkt_ucast), + .stat_tx_pkt_mcast(stat_tx_pkt_mcast), + .stat_tx_pkt_bcast(stat_tx_pkt_bcast), + .stat_tx_pkt_vlan(stat_tx_pkt_vlan), + .stat_tx_pkt_good(stat_tx_pkt_good), + .stat_tx_pkt_bad(stat_tx_pkt_bad), + .stat_tx_err_oversize(stat_tx_err_oversize), + .stat_tx_err_user(stat_tx_err_user), + .stat_tx_err_underflow(stat_tx_err_underflow), + .rx_start_packet(|rx_start_packet), + .stat_rx_byte(stat_rx_byte), + .stat_rx_pkt_len(stat_rx_pkt_len), + .stat_rx_pkt_fragment(stat_rx_pkt_fragment), + .stat_rx_pkt_jabber(stat_rx_pkt_jabber), + .stat_rx_pkt_ucast(stat_rx_pkt_ucast), + .stat_rx_pkt_mcast(stat_rx_pkt_mcast), + .stat_rx_pkt_bcast(stat_rx_pkt_bcast), + .stat_rx_pkt_vlan(stat_rx_pkt_vlan), + .stat_rx_pkt_good(stat_rx_pkt_good), + .stat_rx_pkt_bad(stat_rx_pkt_bad), + .stat_rx_err_oversize(stat_rx_err_oversize), + .stat_rx_err_bad_fcs(stat_rx_err_bad_fcs), + .stat_rx_err_bad_block(stat_rx_err_bad_block), + .stat_rx_err_framing(stat_rx_err_framing), + .stat_rx_err_preamble(stat_rx_err_preamble), + .stat_rx_fifo_drop(stat_rx_fifo_drop), + .stat_tx_mcf(stat_tx_mcf), + .stat_rx_mcf(stat_rx_mcf), + .stat_tx_lfc_pkt(stat_tx_lfc_pkt), + .stat_tx_lfc_xon(stat_tx_lfc_xon), + .stat_tx_lfc_xoff(stat_tx_lfc_xoff), + .stat_tx_lfc_paused(stat_tx_lfc_paused), + .stat_tx_pfc_pkt(stat_tx_pfc_pkt), + .stat_tx_pfc_xon(stat_tx_pfc_xon), + .stat_tx_pfc_xoff(stat_tx_pfc_xoff), + .stat_tx_pfc_paused(stat_tx_pfc_paused), + .stat_rx_lfc_pkt(stat_rx_lfc_pkt), + .stat_rx_lfc_xon(stat_rx_lfc_xon), + .stat_rx_lfc_xoff(stat_rx_lfc_xoff), + .stat_rx_lfc_paused(stat_rx_lfc_paused), + .stat_rx_pfc_pkt(stat_rx_pfc_pkt), + .stat_rx_pfc_xon(stat_rx_pfc_xon), + .stat_rx_pfc_xoff(stat_rx_pfc_xoff), + .stat_rx_pfc_paused(stat_rx_pfc_paused) + ); + +end else begin + + assign m_axis_stat.tdata = '0; + assign m_axis_stat.tkeep = '0; + assign m_axis_stat.tlast = '0; + assign m_axis_stat.tvalid = '0; + assign m_axis_stat.tid = '0; + assign m_axis_stat.tdest = '0; + assign m_axis_stat.tuser = '0; + +end + if (MAC_CTRL_EN) begin : mac_ctrl localparam MCF_PARAMS_SIZE = PFC_EN ? 18 : 2; diff --git a/rtl/eth/taxi_eth_mac_phy_10g_fifo.sv b/rtl/eth/taxi_eth_mac_phy_10g_fifo.sv index 1971b0b..c319a00 100644 --- a/rtl/eth/taxi_eth_mac_phy_10g_fifo.sv +++ b/rtl/eth/taxi_eth_mac_phy_10g_fifo.sv @@ -33,6 +33,11 @@ module taxi_eth_mac_phy_10g_fifo # parameter BITSLIP_HIGH_CYCLES = 0, parameter BITSLIP_LOW_CYCLES = 7, parameter COUNT_125US = 125000/6.4, + parameter logic STAT_EN = 1'b0, + parameter STAT_TX_LEVEL = 1, + parameter STAT_RX_LEVEL = 1, + parameter STAT_ID_BASE = 0, + parameter STAT_UPDATE_PERIOD = 1024, parameter TX_FIFO_DEPTH = 4096, parameter TX_FIFO_RAM_PIPELINE = 1, parameter logic TX_FRAME_FIFO = 1'b1, @@ -77,6 +82,19 @@ module taxi_eth_mac_phy_10g_fifo # output wire logic serdes_rx_bitslip, output wire logic serdes_rx_reset_req, + /* + * PTP clock + */ + input wire logic [PTP_TS_W-1:0] ptp_ts = '0, + input wire logic ptp_ts_step = 1'b0, + + /* + * Statistics + */ + input wire logic stat_clk, + input wire logic stat_rst, + taxi_axis_if.src m_axis_stat, + /* * Status */ @@ -95,17 +113,13 @@ module taxi_eth_mac_phy_10g_fifo # output wire logic rx_fifo_bad_frame, output wire logic rx_fifo_good_frame, - /* - * PTP clock - */ - input wire logic [PTP_TS_W-1:0] ptp_ts = '0, - input wire logic ptp_ts_step = 1'b0, - /* * Configuration */ - input wire logic [7:0] cfg_ifg = 8'd12, + input wire logic [15:0] cfg_tx_max_pkt_len = 16'd1518, + input wire logic [7:0] cfg_tx_ifg = 8'd12, input wire logic cfg_tx_enable = 1'b1, + input wire logic [15:0] cfg_rx_max_pkt_len = 16'd1518, input wire logic cfg_rx_enable = 1'b1, input wire logic cfg_tx_prbs31_enable = 1'b0, input wire logic cfg_rx_prbs31_enable = 1'b0 @@ -254,6 +268,8 @@ end else begin end +wire stat_rx_fifo_drop; + taxi_eth_mac_phy_10g #( .DATA_W(DATA_W), .HDR_W(HDR_W), @@ -270,7 +286,12 @@ taxi_eth_mac_phy_10g #( .RX_SERDES_PIPELINE(RX_SERDES_PIPELINE), .BITSLIP_HIGH_CYCLES(BITSLIP_HIGH_CYCLES), .BITSLIP_LOW_CYCLES(BITSLIP_LOW_CYCLES), - .COUNT_125US(COUNT_125US) + .COUNT_125US(COUNT_125US), + .STAT_EN(STAT_EN), + .STAT_TX_LEVEL(STAT_TX_LEVEL), + .STAT_RX_LEVEL(STAT_RX_LEVEL), + .STAT_ID_BASE(STAT_ID_BASE), + .STAT_UPDATE_PERIOD(STAT_UPDATE_PERIOD) ) eth_mac_phy_10g_inst ( .tx_clk(tx_clk), @@ -330,20 +351,49 @@ eth_mac_phy_10g_inst ( .tx_pause_req(0), .tx_pause_ack(), + /* + * Statistics + */ + .stat_clk(stat_clk), + .stat_rst(stat_rst), + .m_axis_stat(m_axis_stat), + /* * Status */ .tx_start_packet(), - .tx_error_underflow(tx_error_underflow_int), + .stat_tx_byte(), + .stat_tx_pkt_len(), + .stat_tx_pkt_ucast(), + .stat_tx_pkt_mcast(), + .stat_tx_pkt_bcast(), + .stat_tx_pkt_vlan(), + .stat_tx_pkt_good(), + .stat_tx_pkt_bad(), + .stat_tx_err_oversize(), + .stat_tx_err_user(), + .stat_tx_err_underflow(tx_error_underflow_int), .rx_start_packet(), .rx_error_count(), - .rx_error_bad_frame(rx_error_bad_frame_int), - .rx_error_bad_fcs(rx_error_bad_fcs_int), - .rx_bad_block(rx_bad_block_int), - .rx_sequence_error(rx_sequence_error_int), .rx_block_lock(rx_block_lock_int), .rx_high_ber(rx_high_ber_int), .rx_status(rx_status_int), + .stat_rx_byte(), + .stat_rx_pkt_len(), + .stat_rx_pkt_fragment(), + .stat_rx_pkt_jabber(), + .stat_rx_pkt_ucast(), + .stat_rx_pkt_mcast(), + .stat_rx_pkt_bcast(), + .stat_rx_pkt_vlan(), + .stat_rx_pkt_good(), + .stat_rx_pkt_bad(rx_error_bad_frame_int), + .stat_rx_err_oversize(), + .stat_rx_err_bad_fcs(rx_error_bad_fcs_int), + .stat_rx_err_bad_block(rx_bad_block_int), + .stat_rx_err_framing(rx_sequence_error_int), + .stat_rx_err_preamble(), + .stat_rx_fifo_drop(stat_rx_fifo_drop), .stat_tx_mcf(), .stat_rx_mcf(), .stat_tx_lfc_pkt(), @@ -366,8 +416,10 @@ eth_mac_phy_10g_inst ( /* * Configuration */ - .cfg_ifg(cfg_ifg), + .cfg_tx_max_pkt_len(cfg_tx_max_pkt_len), + .cfg_tx_ifg(cfg_tx_ifg), .cfg_tx_enable(cfg_tx_enable), + .cfg_rx_max_pkt_len(cfg_rx_max_pkt_len), .cfg_rx_enable(cfg_rx_enable), .cfg_tx_prbs31_enable(cfg_tx_prbs31_enable), .cfg_rx_prbs31_enable(cfg_rx_prbs31_enable), @@ -532,7 +584,7 @@ rx_fifo ( */ .s_status_depth(), .s_status_depth_commit(), - .s_status_overflow(), + .s_status_overflow(stat_rx_fifo_drop), .s_status_bad_frame(), .s_status_good_frame(), .m_status_depth(), diff --git a/rtl/eth/us/taxi_eth_mac_25g_us.sv b/rtl/eth/us/taxi_eth_mac_25g_us.sv index 5157d6d..3902118 100644 --- a/rtl/eth/us/taxi_eth_mac_25g_us.sv +++ b/rtl/eth/us/taxi_eth_mac_25g_us.sv @@ -42,7 +42,12 @@ module taxi_eth_mac_25g_us # parameter RX_SERDES_PIPELINE = 1, parameter BITSLIP_HIGH_CYCLES = 0, parameter BITSLIP_LOW_CYCLES = 7, - parameter COUNT_125US = 125000/6.4 + parameter COUNT_125US = 125000/6.4, + parameter logic STAT_EN = 1'b0, + parameter STAT_TX_LEVEL = 1, + parameter STAT_RX_LEVEL = 1, + parameter STAT_ID_BASE = 0, + parameter STAT_UPDATE_PERIOD = 1024 ) ( input wire logic xcvr_ctrl_clk, @@ -120,20 +125,49 @@ module taxi_eth_mac_25g_us # input wire logic [CNT-1:0] tx_pause_req = '0, output wire logic [CNT-1:0] tx_pause_ack, + /* + * Statistics + */ + input wire logic stat_clk, + input wire logic stat_rst, + taxi_axis_if.src m_axis_stat, + /* * Status */ output wire logic [1:0] tx_start_packet[CNT], - output wire logic [CNT-1:0] tx_error_underflow, + output wire logic [3:0] stat_tx_byte[CNT], + output wire logic [15:0] stat_tx_pkt_len[CNT], + output wire logic [CNT-1:0] stat_tx_pkt_ucast, + output wire logic [CNT-1:0] stat_tx_pkt_mcast, + output wire logic [CNT-1:0] stat_tx_pkt_bcast, + output wire logic [CNT-1:0] stat_tx_pkt_vlan, + output wire logic [CNT-1:0] stat_tx_pkt_good, + output wire logic [CNT-1:0] stat_tx_pkt_bad, + output wire logic [CNT-1:0] stat_tx_err_oversize, + output wire logic [CNT-1:0] stat_tx_err_user, + output wire logic [CNT-1:0] stat_tx_err_underflow, output wire logic [1:0] rx_start_packet[CNT], output wire logic [6:0] rx_error_count[CNT], - output wire logic [CNT-1:0] rx_error_bad_frame, - output wire logic [CNT-1:0] rx_error_bad_fcs, - output wire logic [CNT-1:0] rx_bad_block, - output wire logic [CNT-1:0] rx_sequence_error, output wire logic [CNT-1:0] rx_block_lock, output wire logic [CNT-1:0] rx_high_ber, output wire logic [CNT-1:0] rx_status, + output wire logic [3:0] stat_rx_byte[CNT], + output wire logic [15:0] stat_rx_pkt_len[CNT], + output wire logic [CNT-1:0] stat_rx_pkt_fragment, + output wire logic [CNT-1:0] stat_rx_pkt_jabber, + output wire logic [CNT-1:0] stat_rx_pkt_ucast, + output wire logic [CNT-1:0] stat_rx_pkt_mcast, + output wire logic [CNT-1:0] stat_rx_pkt_bcast, + output wire logic [CNT-1:0] stat_rx_pkt_vlan, + output wire logic [CNT-1:0] stat_rx_pkt_good, + output wire logic [CNT-1:0] stat_rx_pkt_bad, + output wire logic [CNT-1:0] stat_rx_err_oversize, + output wire logic [CNT-1:0] stat_rx_err_bad_fcs, + output wire logic [CNT-1:0] stat_rx_err_bad_block, + output wire logic [CNT-1:0] stat_rx_err_framing, + output wire logic [CNT-1:0] stat_rx_err_preamble, + input wire logic [CNT-1:0] stat_rx_fifo_drop = '0, output wire logic [CNT-1:0] stat_tx_mcf, output wire logic [CNT-1:0] stat_rx_mcf, output wire logic [CNT-1:0] stat_tx_lfc_pkt, @@ -156,9 +190,12 @@ module taxi_eth_mac_25g_us # /* * Configuration */ - input wire logic [7:0] cfg_ifg[CNT] = '{CNT{8'd12}}, + input wire logic [15:0] cfg_tx_max_pkt_len[CNT] = '{CNT{16'd1518}}, + input wire logic [7:0] cfg_tx_ifg[CNT] = '{CNT{8'd12}}, input wire logic [CNT-1:0] cfg_tx_enable = '1, + input wire logic [15:0] cfg_rx_max_pkt_len[CNT] = '{CNT{16'd1518}}, input wire logic [CNT-1:0] cfg_rx_enable = '1, + input wire logic [7:0] cfg_ifg[CNT] = '{CNT{8'd12}}, input wire logic [CNT-1:0] cfg_tx_prbs31_enable = '0, input wire logic [CNT-1:0] cfg_rx_prbs31_enable = '0, input wire logic [47:0] cfg_mcf_rx_eth_dst_mcast[CNT] = '{CNT{48'h01_80_C2_00_00_01}}, @@ -194,6 +231,46 @@ module taxi_eth_mac_25g_us # input wire logic [CNT-1:0] cfg_rx_pfc_en = '0 ); +// statistics +localparam STAT_TX_CNT = STAT_TX_LEVEL == 0 ? 8 : (STAT_TX_LEVEL == 1 ? 16: 32); +localparam STAT_RX_CNT = STAT_RX_LEVEL == 0 ? 8 : (STAT_RX_LEVEL == 1 ? 16: 32); + +taxi_axis_if #( + .DATA_W(m_axis_stat.DATA_W), + .KEEP_W(1), + .LAST_EN(0), + .ID_W(m_axis_stat.ID_W), + .ID_EN(m_axis_stat.ID_EN), + .USER_W(1), + .USER_EN(1) +) +axis_stat_int[CNT](); + +if (STAT_EN) begin : stats + + taxi_axis_arb_mux #( + .S_COUNT(CNT), + .UPDATE_TID(1'b0), + .ARB_ROUND_ROBIN(1'b1), + .ARB_LSB_HIGH_PRIO(1'b0) + ) + stat_mux_inst ( + .clk(stat_clk), + .rst(stat_rst), + + /* + * AXI4-Stream inputs (sink) + */ + .s_axis(axis_stat_int), + + /* + * AXI4-Stream output (source) + */ + .m_axis(m_axis_stat) + ); + +end + for (genvar n = 0; n < CNT; n = n + 1) begin : ch localparam HAS_COMMON = n == 0; @@ -239,7 +316,12 @@ for (genvar n = 0; n < CNT; n = n + 1) begin : ch .RX_SERDES_PIPELINE(RX_SERDES_PIPELINE), .BITSLIP_HIGH_CYCLES(BITSLIP_HIGH_CYCLES), .BITSLIP_LOW_CYCLES(BITSLIP_LOW_CYCLES), - .COUNT_125US(COUNT_125US) + .COUNT_125US(COUNT_125US), + .STAT_EN(STAT_EN), + .STAT_TX_LEVEL(STAT_TX_LEVEL), + .STAT_RX_LEVEL(STAT_RX_LEVEL), + .STAT_ID_BASE(STAT_ID_BASE + n*(STAT_TX_CNT+STAT_RX_CNT)), + .STAT_UPDATE_PERIOD(STAT_UPDATE_PERIOD) ) ch_inst ( .xcvr_ctrl_clk(xcvr_ctrl_clk), @@ -329,20 +411,49 @@ for (genvar n = 0; n < CNT; n = n + 1) begin : ch .tx_pause_req(tx_pause_req[n]), .tx_pause_ack(tx_pause_ack[n]), + /* + * Statistics + */ + .stat_clk(stat_clk), + .stat_rst(stat_rst), + .m_axis_stat(axis_stat_int[n]), + /* * Status */ .tx_start_packet(tx_start_packet[n]), - .tx_error_underflow(tx_error_underflow[n]), + .stat_tx_byte(stat_tx_byte[n]), + .stat_tx_pkt_len(stat_tx_pkt_len[n]), + .stat_tx_pkt_ucast(stat_tx_pkt_ucast[n]), + .stat_tx_pkt_mcast(stat_tx_pkt_mcast[n]), + .stat_tx_pkt_bcast(stat_tx_pkt_bcast[n]), + .stat_tx_pkt_vlan(stat_tx_pkt_vlan[n]), + .stat_tx_pkt_good(stat_tx_pkt_good[n]), + .stat_tx_pkt_bad(stat_tx_pkt_bad[n]), + .stat_tx_err_oversize(stat_tx_err_oversize[n]), + .stat_tx_err_user(stat_tx_err_user[n]), + .stat_tx_err_underflow(stat_tx_err_underflow[n]), .rx_start_packet(rx_start_packet[n]), .rx_error_count(rx_error_count[n]), - .rx_error_bad_frame(rx_error_bad_frame[n]), - .rx_error_bad_fcs(rx_error_bad_fcs[n]), - .rx_bad_block(rx_bad_block[n]), - .rx_sequence_error(rx_sequence_error[n]), .rx_block_lock(rx_block_lock[n]), .rx_high_ber(rx_high_ber[n]), .rx_status(rx_status[n]), + .stat_rx_byte(stat_rx_byte[n]), + .stat_rx_pkt_len(stat_rx_pkt_len[n]), + .stat_rx_pkt_fragment(stat_rx_pkt_fragment[n]), + .stat_rx_pkt_jabber(stat_rx_pkt_jabber[n]), + .stat_rx_pkt_ucast(stat_rx_pkt_ucast[n]), + .stat_rx_pkt_mcast(stat_rx_pkt_mcast[n]), + .stat_rx_pkt_bcast(stat_rx_pkt_bcast[n]), + .stat_rx_pkt_vlan(stat_rx_pkt_vlan[n]), + .stat_rx_pkt_good(stat_rx_pkt_good[n]), + .stat_rx_pkt_bad(stat_rx_pkt_bad[n]), + .stat_rx_err_oversize(stat_rx_err_oversize[n]), + .stat_rx_err_bad_fcs(stat_rx_err_bad_fcs[n]), + .stat_rx_err_bad_block(stat_rx_err_bad_block[n]), + .stat_rx_err_framing(stat_rx_err_framing[n]), + .stat_rx_err_preamble(stat_rx_err_preamble[n]), + .stat_rx_fifo_drop(stat_rx_fifo_drop[n]), .stat_tx_mcf(stat_tx_mcf[n]), .stat_rx_mcf(stat_rx_mcf[n]), .stat_tx_lfc_pkt(stat_tx_lfc_pkt[n]), @@ -365,8 +476,10 @@ for (genvar n = 0; n < CNT; n = n + 1) begin : ch /* * Configuration */ - .cfg_ifg(cfg_ifg[n]), + .cfg_tx_max_pkt_len(cfg_tx_max_pkt_len[n]), + .cfg_tx_ifg(cfg_tx_ifg[n]), .cfg_tx_enable(cfg_tx_enable[n]), + .cfg_rx_max_pkt_len(cfg_rx_max_pkt_len[n]), .cfg_rx_enable(cfg_rx_enable[n]), .cfg_tx_prbs31_enable(cfg_tx_prbs31_enable[n]), .cfg_rx_prbs31_enable(cfg_rx_prbs31_enable[n]), diff --git a/rtl/eth/us/taxi_eth_mac_25g_us_ch.sv b/rtl/eth/us/taxi_eth_mac_25g_us_ch.sv index c88c4bb..e05552b 100644 --- a/rtl/eth/us/taxi_eth_mac_25g_us_ch.sv +++ b/rtl/eth/us/taxi_eth_mac_25g_us_ch.sv @@ -42,7 +42,12 @@ module taxi_eth_mac_25g_us_ch # parameter RX_SERDES_PIPELINE = 1, parameter BITSLIP_HIGH_CYCLES = 0, parameter BITSLIP_LOW_CYCLES = 7, - parameter COUNT_125US = 125000/6.4 + parameter COUNT_125US = 125000/6.4, + parameter logic STAT_EN = 1'b0, + parameter STAT_TX_LEVEL = 1, + parameter STAT_RX_LEVEL = 1, + parameter STAT_ID_BASE = 0, + parameter STAT_UPDATE_PERIOD = 1024 ) ( input wire logic xcvr_ctrl_clk, @@ -132,20 +137,49 @@ module taxi_eth_mac_25g_us_ch # input wire logic tx_pause_req = 1'b0, output wire logic tx_pause_ack, + /* + * Statistics + */ + input wire logic stat_clk, + input wire logic stat_rst, + taxi_axis_if.src m_axis_stat, + /* * Status */ output wire logic [1:0] tx_start_packet, - output wire logic tx_error_underflow, + output wire logic [3:0] stat_tx_byte, + output wire logic [15:0] stat_tx_pkt_len, + output wire logic stat_tx_pkt_ucast, + output wire logic stat_tx_pkt_mcast, + output wire logic stat_tx_pkt_bcast, + output wire logic stat_tx_pkt_vlan, + output wire logic stat_tx_pkt_good, + output wire logic stat_tx_pkt_bad, + output wire logic stat_tx_err_oversize, + output wire logic stat_tx_err_user, + output wire logic stat_tx_err_underflow, output wire logic [1:0] rx_start_packet, output wire logic [6:0] rx_error_count, - output wire logic rx_error_bad_frame, - output wire logic rx_error_bad_fcs, - output wire logic rx_bad_block, - output wire logic rx_sequence_error, output wire logic rx_block_lock, output wire logic rx_high_ber, output wire logic rx_status, + output wire logic [3:0] stat_rx_byte, + output wire logic [15:0] stat_rx_pkt_len, + output wire logic stat_rx_pkt_fragment, + output wire logic stat_rx_pkt_jabber, + output wire logic stat_rx_pkt_ucast, + output wire logic stat_rx_pkt_mcast, + output wire logic stat_rx_pkt_bcast, + output wire logic stat_rx_pkt_vlan, + output wire logic stat_rx_pkt_good, + output wire logic stat_rx_pkt_bad, + output wire logic stat_rx_err_oversize, + output wire logic stat_rx_err_bad_fcs, + output wire logic stat_rx_err_bad_block, + output wire logic stat_rx_err_framing, + output wire logic stat_rx_err_preamble, + input wire logic stat_rx_fifo_drop = 1'b0, output wire logic stat_tx_mcf, output wire logic stat_rx_mcf, output wire logic stat_tx_lfc_pkt, @@ -168,8 +202,10 @@ module taxi_eth_mac_25g_us_ch # /* * Configuration */ - input wire logic [7:0] cfg_ifg = 8'd12, + input wire logic [15:0] cfg_tx_max_pkt_len = 16'd1518, + input wire logic [7:0] cfg_tx_ifg = 8'd12, input wire logic cfg_tx_enable = 1'b1, + input wire logic [15:0] cfg_rx_max_pkt_len = 16'd1518, input wire logic cfg_rx_enable = 1'b1, input wire logic cfg_tx_prbs31_enable = 1'b0, input wire logic cfg_rx_prbs31_enable = 1'b0, @@ -693,7 +729,12 @@ taxi_eth_mac_phy_10g #( .RX_SERDES_PIPELINE(RX_SERDES_PIPELINE), .BITSLIP_HIGH_CYCLES(BITSLIP_HIGH_CYCLES), .BITSLIP_LOW_CYCLES(BITSLIP_LOW_CYCLES), - .COUNT_125US(COUNT_125US) + .COUNT_125US(COUNT_125US), + .STAT_EN(STAT_EN), + .STAT_TX_LEVEL(STAT_TX_LEVEL), + .STAT_RX_LEVEL(STAT_RX_LEVEL), + .STAT_ID_BASE(STAT_ID_BASE), + .STAT_UPDATE_PERIOD(STAT_UPDATE_PERIOD) ) eth_mac_phy_10g_inst ( .tx_clk(tx_clk), @@ -753,20 +794,49 @@ eth_mac_phy_10g_inst ( .tx_pause_req(tx_pause_req), .tx_pause_ack(tx_pause_ack), + /* + * Statistics + */ + .stat_clk(stat_clk), + .stat_rst(stat_rst), + .m_axis_stat(m_axis_stat), + /* * Status */ .tx_start_packet(tx_start_packet), - .tx_error_underflow(tx_error_underflow), + .stat_tx_byte(stat_tx_byte), + .stat_tx_pkt_len(stat_tx_pkt_len), + .stat_tx_pkt_ucast(stat_tx_pkt_ucast), + .stat_tx_pkt_mcast(stat_tx_pkt_mcast), + .stat_tx_pkt_bcast(stat_tx_pkt_bcast), + .stat_tx_pkt_vlan(stat_tx_pkt_vlan), + .stat_tx_pkt_good(stat_tx_pkt_good), + .stat_tx_pkt_bad(stat_tx_pkt_bad), + .stat_tx_err_oversize(stat_tx_err_oversize), + .stat_tx_err_user(stat_tx_err_user), + .stat_tx_err_underflow(stat_tx_err_underflow), .rx_start_packet(rx_start_packet), .rx_error_count(rx_error_count), - .rx_error_bad_frame(rx_error_bad_frame), - .rx_error_bad_fcs(rx_error_bad_fcs), - .rx_bad_block(rx_bad_block), - .rx_sequence_error(rx_sequence_error), .rx_block_lock(rx_block_lock), .rx_high_ber(rx_high_ber), .rx_status(rx_status), + .stat_rx_byte(stat_rx_byte), + .stat_rx_pkt_len(stat_rx_pkt_len), + .stat_rx_pkt_fragment(stat_rx_pkt_fragment), + .stat_rx_pkt_jabber(stat_rx_pkt_jabber), + .stat_rx_pkt_ucast(stat_rx_pkt_ucast), + .stat_rx_pkt_mcast(stat_rx_pkt_mcast), + .stat_rx_pkt_bcast(stat_rx_pkt_bcast), + .stat_rx_pkt_vlan(stat_rx_pkt_vlan), + .stat_rx_pkt_good(stat_rx_pkt_good), + .stat_rx_pkt_bad(stat_rx_pkt_bad), + .stat_rx_err_oversize(stat_rx_err_oversize), + .stat_rx_err_bad_fcs(stat_rx_err_bad_fcs), + .stat_rx_err_bad_block(stat_rx_err_bad_block), + .stat_rx_err_framing(stat_rx_err_framing), + .stat_rx_err_preamble(stat_rx_err_preamble), + .stat_rx_fifo_drop(stat_rx_fifo_drop), .stat_tx_mcf(stat_tx_mcf), .stat_rx_mcf(stat_rx_mcf), .stat_tx_lfc_pkt(stat_tx_lfc_pkt), @@ -789,8 +859,10 @@ eth_mac_phy_10g_inst ( /* * Configuration */ - .cfg_ifg(cfg_ifg), + .cfg_tx_max_pkt_len(cfg_tx_max_pkt_len), + .cfg_tx_ifg(cfg_tx_ifg), .cfg_tx_enable(cfg_tx_enable), + .cfg_rx_max_pkt_len(cfg_rx_max_pkt_len), .cfg_rx_enable(cfg_rx_enable), .cfg_tx_prbs31_enable(cfg_tx_prbs31_enable), .cfg_rx_prbs31_enable(cfg_rx_prbs31_enable), diff --git a/tb/eth/taxi_eth_mac_phy_10g/Makefile b/tb/eth/taxi_eth_mac_phy_10g/Makefile index 91efde8..eaf36d3 100644 --- a/tb/eth/taxi_eth_mac_phy_10g/Makefile +++ b/tb/eth/taxi_eth_mac_phy_10g/Makefile @@ -47,6 +47,11 @@ export PARAM_BITSLIP_LOW_CYCLES := 7 export PARAM_COUNT_125US := 195 export PARAM_PFC_EN := 1 export PARAM_PAUSE_EN := $(PARAM_PFC_EN) +export PARAM_STAT_EN := 1 +export PARAM_STAT_TX_LEVEL := 2 +export PARAM_STAT_RX_LEVEL := $(PARAM_STAT_TX_LEVEL) +export PARAM_STAT_ID_BASE := 0 +export PARAM_STAT_UPDATE_PERIOD := 1024 ifeq ($(SIM), icarus) PLUSARGS += -fst diff --git a/tb/eth/taxi_eth_mac_phy_10g/test_taxi_eth_mac_phy_10g.py b/tb/eth/taxi_eth_mac_phy_10g/test_taxi_eth_mac_phy_10g.py index 56e499e..3c273f6 100644 --- a/tb/eth/taxi_eth_mac_phy_10g/test_taxi_eth_mac_phy_10g.py +++ b/tb/eth/taxi_eth_mac_phy_10g/test_taxi_eth_mac_phy_10g.py @@ -54,6 +54,7 @@ class TB: cocotb.start_soon(Clock(dut.rx_clk, self.clk_period, units="ns").start()) cocotb.start_soon(Clock(dut.tx_clk, self.clk_period, units="ns").start()) + cocotb.start_soon(Clock(dut.stat_clk, self.clk_period, units="ns").start()) self.serdes_source = BaseRSerdesSource(dut.serdes_rx_data, dut.serdes_rx_hdr, dut.rx_clk, slip=dut.serdes_rx_bitslip) self.serdes_sink = BaseRSerdesSink(dut.serdes_tx_data, dut.serdes_tx_hdr, dut.tx_clk) @@ -62,11 +63,17 @@ class TB: self.tx_cpl_sink = AxiStreamSink(AxiStreamBus.from_entity(dut.m_axis_tx_cpl), dut.tx_clk, dut.tx_rst) self.axis_sink = AxiStreamSink(AxiStreamBus.from_entity(dut.m_axis_rx), dut.rx_clk, dut.rx_rst) + self.stat_sink = AxiStreamSink(AxiStreamBus.from_entity(dut.m_axis_stat), dut.stat_clk, dut.stat_rst) + self.rx_ptp_clock = PtpClockSimTime(ts_tod=dut.rx_ptp_ts, clock=dut.rx_clk) self.tx_ptp_clock = PtpClockSimTime(ts_tod=dut.tx_ptp_ts, clock=dut.tx_clk) - dut.cfg_ifg.setimmediatevalue(0) + dut.stat_rx_fifo_drop.setimmediatevalue(0) + + dut.cfg_tx_max_pkt_len.setimmediatevalue(0) + dut.cfg_tx_ifg.setimmediatevalue(0) dut.cfg_tx_enable.setimmediatevalue(0) + dut.cfg_rx_max_pkt_len.setimmediatevalue(0) dut.cfg_rx_enable.setimmediatevalue(0) dut.cfg_tx_prbs31_enable.setimmediatevalue(0) dut.cfg_rx_prbs31_enable.setimmediatevalue(0) @@ -105,14 +112,17 @@ class TB: async def reset(self): self.dut.rx_rst.setimmediatevalue(0) self.dut.tx_rst.setimmediatevalue(0) + self.dut.stat_rst.setimmediatevalue(0) await RisingEdge(self.dut.rx_clk) await RisingEdge(self.dut.rx_clk) self.dut.rx_rst.value = 1 self.dut.tx_rst.value = 1 + self.dut.stat_rst.value = 1 await RisingEdge(self.dut.rx_clk) await RisingEdge(self.dut.rx_clk) self.dut.rx_rst.value = 0 self.dut.tx_rst.value = 0 + self.dut.stat_rst.value = 0 await RisingEdge(self.dut.rx_clk) await RisingEdge(self.dut.rx_clk) @@ -122,7 +132,8 @@ async def run_test_rx(dut, payload_lengths=None, payload_data=None, ifg=12): tb = TB(dut) tb.serdes_source.ifg = ifg - tb.dut.cfg_ifg.value = ifg + tb.dut.cfg_tx_ifg.value = ifg + tb.dut.cfg_rx_max_pkt_len.value = 9218 await tb.reset() @@ -176,11 +187,13 @@ async def run_test_tx(dut, payload_lengths=None, payload_data=None, ifg=12): tb = TB(dut) tb.serdes_source.ifg = ifg - tb.dut.cfg_ifg.value = ifg - tb.dut.cfg_tx_enable.value = 1 + tb.dut.cfg_tx_max_pkt_len.value = 9218 + tb.dut.cfg_tx_ifg.value = ifg await tb.reset() + tb.dut.cfg_tx_enable.value = 1 + test_frames = [payload_data(x) for x in payload_lengths()] for test_data in test_frames: @@ -222,7 +235,8 @@ async def run_test_tx_alignment(dut, payload_data=None, ifg=12): byte_width = tb.axis_source.width // 8 tb.serdes_source.ifg = ifg - tb.dut.cfg_ifg.value = ifg + tb.dut.cfg_tx_max_pkt_len.value = 9218 + tb.dut.cfg_tx_ifg.value = ifg await tb.reset() @@ -307,7 +321,8 @@ async def run_test_tx_underrun(dut, ifg=12): tb = TB(dut) tb.serdes_source.ifg = ifg - tb.dut.cfg_ifg.value = ifg + tb.dut.cfg_tx_max_pkt_len.value = 9218 + tb.dut.cfg_tx_ifg.value = ifg await tb.reset() @@ -351,7 +366,8 @@ async def run_test_tx_error(dut, ifg=12): tb = TB(dut) tb.serdes_source.ifg = ifg - tb.dut.cfg_ifg.value = ifg + tb.dut.cfg_tx_max_pkt_len.value = 9218 + tb.dut.cfg_tx_ifg.value = ifg await tb.reset() @@ -425,7 +441,9 @@ async def run_test_lfc(dut, ifg=12): tb = TB(dut) tb.serdes_source.ifg = ifg - tb.dut.cfg_ifg.value = ifg + tb.dut.cfg_tx_max_pkt_len.value = 9218 + tb.dut.cfg_tx_ifg.value = ifg + tb.dut.cfg_rx_max_pkt_len.value = 9218 await tb.reset() @@ -575,7 +593,9 @@ async def run_test_pfc(dut, ifg=12): tb = TB(dut) tb.serdes_source.ifg = ifg - tb.dut.cfg_ifg.value = ifg + tb.dut.cfg_tx_max_pkt_len.value = 9218 + tb.dut.cfg_tx_ifg.value = ifg + tb.dut.cfg_rx_max_pkt_len.value = 9218 await tb.reset() @@ -805,6 +825,11 @@ def test_taxi_eth_mac_phy_10g(request, data_w, dic_en, pfc_en): parameters['COUNT_125US'] = int(1250/6.4) parameters['PFC_EN'] = pfc_en parameters['PAUSE_EN'] = parameters['PFC_EN'] + parameters['STAT_EN'] = 1 + parameters['STAT_TX_LEVEL'] = 2 + parameters['STAT_RX_LEVEL'] = parameters['STAT_TX_LEVEL'] + parameters['STAT_ID_BASE'] = 0 + parameters['STAT_UPDATE_PERIOD'] = 1024 extra_env = {f'PARAM_{k}': str(v) for k, v in parameters.items()} diff --git a/tb/eth/taxi_eth_mac_phy_10g/test_taxi_eth_mac_phy_10g.sv b/tb/eth/taxi_eth_mac_phy_10g/test_taxi_eth_mac_phy_10g.sv index 7f12318..6375d9d 100644 --- a/tb/eth/taxi_eth_mac_phy_10g/test_taxi_eth_mac_phy_10g.sv +++ b/tb/eth/taxi_eth_mac_phy_10g/test_taxi_eth_mac_phy_10g.sv @@ -36,7 +36,12 @@ module test_taxi_eth_mac_phy_10g # parameter BITSLIP_LOW_CYCLES = 7, parameter COUNT_125US = 125000/6.4, parameter logic PFC_EN = 1'b0, - parameter logic PAUSE_EN = PFC_EN + parameter logic PAUSE_EN = PFC_EN, + parameter logic STAT_EN = 1'b0, + parameter STAT_TX_LEVEL = 1, + parameter STAT_RX_LEVEL = STAT_TX_LEVEL, + parameter STAT_ID_BASE = 0, + parameter STAT_UPDATE_PERIOD = 1024 /* verilator lint_on WIDTHTRUNC */ ) (); @@ -79,17 +84,43 @@ logic tx_lfc_pause_en; logic tx_pause_req; logic tx_pause_ack; +logic stat_clk; +logic stat_rst; +taxi_axis_if #(.DATA_W(24), .KEEP_W(1), .LAST_EN(0), .USER_EN(1), .USER_W(1), .ID_EN(1), .ID_W(8)) m_axis_stat(); + logic [1:0] tx_start_packet; -logic tx_error_underflow; +logic [3:0] stat_tx_byte; +logic [15:0] stat_tx_pkt_len; +logic stat_tx_pkt_ucast; +logic stat_tx_pkt_mcast; +logic stat_tx_pkt_bcast; +logic stat_tx_pkt_vlan; +logic stat_tx_pkt_good; +logic stat_tx_pkt_bad; +logic stat_tx_err_oversize; +logic stat_tx_err_user; +logic stat_tx_err_underflow; logic [1:0] rx_start_packet; logic [6:0] rx_error_count; -logic rx_error_bad_frame; -logic rx_error_bad_fcs; -logic rx_bad_block; -logic rx_sequence_error; logic rx_block_lock; logic rx_high_ber; logic rx_status; +logic [3:0] stat_rx_byte; +logic [15:0] stat_rx_pkt_len; +logic stat_rx_pkt_fragment; +logic stat_rx_pkt_jabber; +logic stat_rx_pkt_ucast; +logic stat_rx_pkt_mcast; +logic stat_rx_pkt_bcast; +logic stat_rx_pkt_vlan; +logic stat_rx_pkt_good; +logic stat_rx_pkt_bad; +logic stat_rx_err_oversize; +logic stat_rx_err_bad_fcs; +logic stat_rx_err_bad_block; +logic stat_rx_err_framing; +logic stat_rx_err_preamble; +logic stat_rx_fifo_drop; logic stat_tx_mcf; logic stat_rx_mcf; logic stat_tx_lfc_pkt; @@ -109,8 +140,10 @@ logic [7:0] stat_rx_pfc_xon; logic [7:0] stat_rx_pfc_xoff; logic [7:0] stat_rx_pfc_paused; -logic [7:0] cfg_ifg; +logic [15:0] cfg_tx_max_pkt_len; +logic [7:0] cfg_tx_ifg; logic cfg_tx_enable; +logic [15:0] cfg_rx_max_pkt_len; logic cfg_rx_enable; logic cfg_tx_prbs31_enable; logic cfg_rx_prbs31_enable; @@ -164,7 +197,12 @@ taxi_eth_mac_phy_10g #( .BITSLIP_LOW_CYCLES(BITSLIP_LOW_CYCLES), .COUNT_125US(COUNT_125US), .PFC_EN(PFC_EN), - .PAUSE_EN(PAUSE_EN) + .PAUSE_EN(PAUSE_EN), + .STAT_EN(STAT_EN), + .STAT_TX_LEVEL(STAT_TX_LEVEL), + .STAT_RX_LEVEL(STAT_RX_LEVEL), + .STAT_ID_BASE(STAT_ID_BASE), + .STAT_UPDATE_PERIOD(STAT_UPDATE_PERIOD) ) uut ( .rx_clk(rx_clk), @@ -224,20 +262,49 @@ uut ( .tx_pause_req(tx_pause_req), .tx_pause_ack(tx_pause_ack), + /* + * Statistics + */ + .stat_clk(stat_clk), + .stat_rst(stat_rst), + .m_axis_stat(m_axis_stat), + /* * Status */ .tx_start_packet(tx_start_packet), - .tx_error_underflow(tx_error_underflow), + .stat_tx_byte(stat_tx_byte), + .stat_tx_pkt_len(stat_tx_pkt_len), + .stat_tx_pkt_ucast(stat_tx_pkt_ucast), + .stat_tx_pkt_mcast(stat_tx_pkt_mcast), + .stat_tx_pkt_bcast(stat_tx_pkt_bcast), + .stat_tx_pkt_vlan(stat_tx_pkt_vlan), + .stat_tx_pkt_good(stat_tx_pkt_good), + .stat_tx_pkt_bad(stat_tx_pkt_bad), + .stat_tx_err_oversize(stat_tx_err_oversize), + .stat_tx_err_user(stat_tx_err_user), + .stat_tx_err_underflow(stat_tx_err_underflow), .rx_start_packet(rx_start_packet), .rx_error_count(rx_error_count), - .rx_error_bad_frame(rx_error_bad_frame), - .rx_error_bad_fcs(rx_error_bad_fcs), - .rx_bad_block(rx_bad_block), - .rx_sequence_error(rx_sequence_error), .rx_block_lock(rx_block_lock), .rx_high_ber(rx_high_ber), .rx_status(rx_status), + .stat_rx_byte(stat_rx_byte), + .stat_rx_pkt_len(stat_rx_pkt_len), + .stat_rx_pkt_fragment(stat_rx_pkt_fragment), + .stat_rx_pkt_jabber(stat_rx_pkt_jabber), + .stat_rx_pkt_ucast(stat_rx_pkt_ucast), + .stat_rx_pkt_mcast(stat_rx_pkt_mcast), + .stat_rx_pkt_bcast(stat_rx_pkt_bcast), + .stat_rx_pkt_vlan(stat_rx_pkt_vlan), + .stat_rx_pkt_good(stat_rx_pkt_good), + .stat_rx_pkt_bad(stat_rx_pkt_bad), + .stat_rx_err_oversize(stat_rx_err_oversize), + .stat_rx_err_bad_fcs(stat_rx_err_bad_fcs), + .stat_rx_err_bad_block(stat_rx_err_bad_block), + .stat_rx_err_framing(stat_rx_err_framing), + .stat_rx_err_preamble(stat_rx_err_preamble), + .stat_rx_fifo_drop(stat_rx_fifo_drop), .stat_tx_mcf(stat_tx_mcf), .stat_rx_mcf(stat_rx_mcf), .stat_tx_lfc_pkt(stat_tx_lfc_pkt), @@ -260,8 +327,10 @@ uut ( /* * Configuration */ - .cfg_ifg(cfg_ifg), + .cfg_tx_max_pkt_len(cfg_tx_max_pkt_len), + .cfg_tx_ifg(cfg_tx_ifg), .cfg_tx_enable(cfg_tx_enable), + .cfg_rx_max_pkt_len(cfg_rx_max_pkt_len), .cfg_rx_enable(cfg_rx_enable), .cfg_tx_prbs31_enable(cfg_tx_prbs31_enable), .cfg_rx_prbs31_enable(cfg_rx_prbs31_enable), diff --git a/tb/eth/taxi_eth_mac_phy_10g_fifo/Makefile b/tb/eth/taxi_eth_mac_phy_10g_fifo/Makefile index 7c8d739..b41391c 100644 --- a/tb/eth/taxi_eth_mac_phy_10g_fifo/Makefile +++ b/tb/eth/taxi_eth_mac_phy_10g_fifo/Makefile @@ -46,6 +46,11 @@ export PARAM_RX_SERDES_PIPELINE := 2 export PARAM_BITSLIP_HIGH_CYCLES := 0 export PARAM_BITSLIP_LOW_CYCLES := 7 export PARAM_COUNT_125US := 195 +export PARAM_STAT_EN := 1 +export PARAM_STAT_TX_LEVEL := 2 +export PARAM_STAT_RX_LEVEL := $(PARAM_STAT_TX_LEVEL) +export PARAM_STAT_ID_BASE := 0 +export PARAM_STAT_UPDATE_PERIOD := 1024 export PARAM_TX_FIFO_DEPTH := 16384 export PARAM_TX_FIFO_RAM_PIPELINE := 1 export PARAM_TX_FRAME_FIFO := 1 diff --git a/tb/eth/taxi_eth_mac_phy_10g_fifo/test_taxi_eth_mac_phy_10g_fifo.py b/tb/eth/taxi_eth_mac_phy_10g_fifo/test_taxi_eth_mac_phy_10g_fifo.py index 1eea140..d19aa48 100644 --- a/tb/eth/taxi_eth_mac_phy_10g_fifo/test_taxi_eth_mac_phy_10g_fifo.py +++ b/tb/eth/taxi_eth_mac_phy_10g_fifo/test_taxi_eth_mac_phy_10g_fifo.py @@ -52,6 +52,7 @@ class TB: cocotb.start_soon(Clock(dut.logic_clk, self.clk_period, units="ns").start()) cocotb.start_soon(Clock(dut.rx_clk, self.clk_period, units="ns").start()) cocotb.start_soon(Clock(dut.tx_clk, self.clk_period, units="ns").start()) + cocotb.start_soon(Clock(dut.stat_clk, self.clk_period, units="ns").start()) cocotb.start_soon(Clock(dut.ptp_sample_clk, 9.9, units="ns").start()) self.serdes_source = BaseRSerdesSource(dut.serdes_rx_data, dut.serdes_rx_hdr, dut.rx_clk, slip=dut.serdes_rx_bitslip) @@ -61,12 +62,16 @@ class TB: self.tx_cpl_sink = AxiStreamSink(AxiStreamBus.from_entity(dut.m_axis_tx_cpl), dut.logic_clk, dut.logic_rst) self.axis_sink = AxiStreamSink(AxiStreamBus.from_entity(dut.m_axis_rx), dut.logic_clk, dut.logic_rst) + self.stat_sink = AxiStreamSink(AxiStreamBus.from_entity(dut.m_axis_stat), dut.stat_clk, dut.stat_rst) + self.ptp_clock = PtpClockSimTime(ts_tod=dut.ptp_ts, clock=dut.logic_clk) dut.ptp_ts_step.setimmediatevalue(0) - dut.cfg_ifg.setimmediatevalue(0) + dut.cfg_tx_max_pkt_len.setimmediatevalue(0) + dut.cfg_tx_ifg.setimmediatevalue(0) dut.cfg_tx_enable.setimmediatevalue(0) + dut.cfg_rx_max_pkt_len.setimmediatevalue(0) dut.cfg_rx_enable.setimmediatevalue(0) dut.cfg_tx_prbs31_enable.setimmediatevalue(0) dut.cfg_rx_prbs31_enable.setimmediatevalue(0) @@ -75,16 +80,19 @@ class TB: self.dut.logic_rst.setimmediatevalue(0) self.dut.rx_rst.setimmediatevalue(0) self.dut.tx_rst.setimmediatevalue(0) + self.dut.stat_rst.setimmediatevalue(0) await RisingEdge(self.dut.logic_clk) await RisingEdge(self.dut.logic_clk) self.dut.logic_rst.value = 1 self.dut.rx_rst.value = 1 self.dut.tx_rst.value = 1 + self.dut.stat_rst.value = 1 await RisingEdge(self.dut.logic_clk) await RisingEdge(self.dut.logic_clk) self.dut.logic_rst.value = 0 self.dut.rx_rst.value = 0 self.dut.tx_rst.value = 0 + self.dut.stat_rst.value = 0 await RisingEdge(self.dut.logic_clk) await RisingEdge(self.dut.logic_clk) @@ -94,7 +102,8 @@ async def run_test_rx(dut, payload_lengths=None, payload_data=None, ifg=12): tb = TB(dut) tb.serdes_source.ifg = ifg - tb.dut.cfg_ifg.value = ifg + tb.dut.cfg_tx_ifg.value = ifg + tb.dut.cfg_rx_max_pkt_len.value = 9218 tb.dut.cfg_rx_enable.value = 1 await tb.reset() @@ -152,7 +161,8 @@ async def run_test_tx(dut, payload_lengths=None, payload_data=None, ifg=12): tb = TB(dut) tb.serdes_source.ifg = ifg - tb.dut.cfg_ifg.value = ifg + tb.dut.cfg_tx_max_pkt_len.value = 9218 + tb.dut.cfg_tx_ifg.value = ifg tb.dut.cfg_tx_enable.value = 1 await tb.reset() @@ -204,7 +214,8 @@ async def run_test_tx_alignment(dut, payload_data=None, ifg=12): byte_width = tb.axis_source.width // 8 tb.serdes_source.ifg = ifg - tb.dut.cfg_ifg.value = ifg + tb.dut.cfg_tx_max_pkt_len.value = 9218 + tb.dut.cfg_tx_ifg.value = ifg tb.dut.cfg_tx_enable.value = 1 await tb.reset() @@ -411,6 +422,11 @@ def test_taxi_eth_mac_phy_10g_fifo(request, data_w, dic_en): parameters['BITSLIP_HIGH_CYCLES'] = 0 parameters['BITSLIP_LOW_CYCLES'] = 7 parameters['COUNT_125US'] = int(1250/6.4) + parameters['STAT_EN'] = 1 + parameters['STAT_TX_LEVEL'] = 2 + parameters['STAT_RX_LEVEL'] = parameters['STAT_TX_LEVEL'] + parameters['STAT_ID_BASE'] = 0 + parameters['STAT_UPDATE_PERIOD'] = 1024 parameters['TX_FIFO_DEPTH'] = 16384 parameters['TX_FIFO_RAM_PIPELINE'] = 1 parameters['TX_FRAME_FIFO'] = 1 diff --git a/tb/eth/taxi_eth_mac_phy_10g_fifo/test_taxi_eth_mac_phy_10g_fifo.sv b/tb/eth/taxi_eth_mac_phy_10g_fifo/test_taxi_eth_mac_phy_10g_fifo.sv index d19af62..9e10971 100644 --- a/tb/eth/taxi_eth_mac_phy_10g_fifo/test_taxi_eth_mac_phy_10g_fifo.sv +++ b/tb/eth/taxi_eth_mac_phy_10g_fifo/test_taxi_eth_mac_phy_10g_fifo.sv @@ -36,6 +36,11 @@ module test_taxi_eth_mac_phy_10g_fifo # parameter BITSLIP_HIGH_CYCLES = 0, parameter BITSLIP_LOW_CYCLES = 7, parameter COUNT_125US = 125000/6.4, + parameter logic STAT_EN = 1'b0, + parameter STAT_TX_LEVEL = 1, + parameter STAT_RX_LEVEL = STAT_TX_LEVEL, + parameter STAT_ID_BASE = 0, + parameter STAT_UPDATE_PERIOD = 1024, parameter TX_FIFO_DEPTH = 4096, parameter TX_FIFO_RAM_PIPELINE = 1, parameter logic TX_FRAME_FIFO = 1'b1, @@ -75,6 +80,13 @@ logic [HDR_W-1:0] serdes_rx_hdr; logic serdes_rx_bitslip; logic serdes_rx_reset_req; +logic [PTP_TS_W-1:0] ptp_ts; +logic ptp_ts_step; + +logic stat_clk; +logic stat_rst; +taxi_axis_if #(.DATA_W(16), .KEEP_W(1), .KEEP_EN(0), .LAST_EN(0), .USER_EN(1), .USER_W(1), .ID_EN(1), .ID_W(8)) m_axis_stat(); + logic tx_error_underflow; logic tx_fifo_overflow; logic tx_fifo_bad_frame; @@ -90,11 +102,10 @@ logic rx_fifo_overflow; logic rx_fifo_bad_frame; logic rx_fifo_good_frame; -logic [PTP_TS_W-1:0] ptp_ts; -logic ptp_ts_step; - -logic [7:0] cfg_ifg; +logic [15:0] cfg_tx_max_pkt_len; +logic [7:0] cfg_tx_ifg; logic cfg_tx_enable; +logic [15:0] cfg_rx_max_pkt_len; logic cfg_rx_enable; logic cfg_tx_prbs31_enable; logic cfg_rx_prbs31_enable; @@ -116,6 +127,11 @@ taxi_eth_mac_phy_10g_fifo #( .BITSLIP_HIGH_CYCLES(BITSLIP_HIGH_CYCLES), .BITSLIP_LOW_CYCLES(BITSLIP_LOW_CYCLES), .COUNT_125US(COUNT_125US), + .STAT_EN(STAT_EN), + .STAT_TX_LEVEL(STAT_TX_LEVEL), + .STAT_RX_LEVEL(STAT_RX_LEVEL), + .STAT_ID_BASE(STAT_ID_BASE), + .STAT_UPDATE_PERIOD(STAT_UPDATE_PERIOD), .TX_FIFO_DEPTH(TX_FIFO_DEPTH), .TX_FIFO_RAM_PIPELINE(TX_FIFO_RAM_PIPELINE), .TX_FRAME_FIFO(TX_FRAME_FIFO), @@ -160,6 +176,19 @@ uut ( .serdes_rx_bitslip(serdes_rx_bitslip), .serdes_rx_reset_req(serdes_rx_reset_req), + /* + * PTP clock + */ + .ptp_ts(ptp_ts), + .ptp_ts_step(ptp_ts_step), + + /* + * Statistics + */ + .stat_clk(stat_clk), + .stat_rst(stat_rst), + .m_axis_stat(m_axis_stat), + /* * Status */ @@ -178,17 +207,13 @@ uut ( .rx_fifo_bad_frame(rx_fifo_bad_frame), .rx_fifo_good_frame(rx_fifo_good_frame), - /* - * PTP clock - */ - .ptp_ts(ptp_ts), - .ptp_ts_step(ptp_ts_step), - /* * Configuration */ - .cfg_ifg(cfg_ifg), + .cfg_tx_max_pkt_len(cfg_tx_max_pkt_len), + .cfg_tx_ifg(cfg_tx_ifg), .cfg_tx_enable(cfg_tx_enable), + .cfg_rx_max_pkt_len(cfg_rx_max_pkt_len), .cfg_rx_enable(cfg_rx_enable), .cfg_tx_prbs31_enable(cfg_tx_prbs31_enable), .cfg_rx_prbs31_enable(cfg_rx_prbs31_enable)