From bb90cd5a089476411a3aaa1e7aa18af65bd7e8f9 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Tue, 8 Apr 2025 20:18:43 -0700 Subject: [PATCH] eth: Add MAC statistics module to 10G MAC Signed-off-by: Alex Forencich --- rtl/eth/taxi_eth_mac_10g.f | 1 + rtl/eth/taxi_eth_mac_10g.sv | 252 +++++++++++++----- rtl/eth/taxi_eth_mac_10g_fifo.sv | 82 ++++-- tb/eth/taxi_eth_mac_10g/Makefile | 5 + .../taxi_eth_mac_10g/test_taxi_eth_mac_10g.py | 40 ++- .../taxi_eth_mac_10g/test_taxi_eth_mac_10g.sv | 93 ++++++- tb/eth/taxi_eth_mac_10g_fifo/Makefile | 5 + .../test_taxi_eth_mac_10g_fifo.py | 24 +- .../test_taxi_eth_mac_10g_fifo.sv | 47 +++- 9 files changed, 437 insertions(+), 112 deletions(-) diff --git a/rtl/eth/taxi_eth_mac_10g.f b/rtl/eth/taxi_eth_mac_10g.f index 22db3e5..5d5508a 100644 --- a/rtl/eth/taxi_eth_mac_10g.f +++ b/rtl/eth/taxi_eth_mac_10g.f @@ -3,6 +3,7 @@ taxi_axis_xgmii_rx_64.sv taxi_axis_xgmii_tx_64.sv taxi_axis_xgmii_rx_32.sv taxi_axis_xgmii_tx_32.sv +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_10g.sv b/rtl/eth/taxi_eth_mac_10g.sv index 221c7bf..012aac7 100644 --- a/rtl/eth/taxi_eth_mac_10g.sv +++ b/rtl/eth/taxi_eth_mac_10g.sv @@ -26,7 +26,12 @@ module taxi_eth_mac_10g # parameter logic PTP_TS_FMT_TOD = 1'b1, parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64, 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 = 1, + parameter STAT_ID_BASE = 0, + parameter STAT_UPDATE_PERIOD = 1024 ) ( input wire logic rx_clk, @@ -84,14 +89,45 @@ module taxi_eth_mac_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 rx_error_bad_frame, - output wire logic rx_error_bad_fcs, + 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, @@ -114,8 +150,10 @@ module taxi_eth_mac_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 [47:0] cfg_mcf_rx_eth_dst_mcast = 48'h01_80_C2_00_00_01, input wire logic cfg_mcf_rx_check_eth_dst_mcast = 1'b1, @@ -200,28 +238,28 @@ if (DATA_W == 64) begin /* * Configuration */ - .cfg_rx_max_pkt_len(16'd9218), + .cfg_rx_max_pkt_len(cfg_rx_max_pkt_len), .cfg_rx_enable(cfg_rx_enable), /* * Status */ .rx_start_packet(rx_start_packet), - .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(), - .stat_rx_err_framing(), - .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) ); taxi_axis_xgmii_tx_64 #( @@ -259,25 +297,25 @@ if (DATA_W == 64) begin /* * 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), /* * 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) ); end else if (DATA_W == 32) begin @@ -311,31 +349,32 @@ end else if (DATA_W == 32) begin /* * Configuration */ - .cfg_rx_max_pkt_len(16'd9218), + .cfg_rx_max_pkt_len(cfg_rx_max_pkt_len), .cfg_rx_enable(cfg_rx_enable), /* * Status */ .rx_start_packet(rx_start_packet[0]), - .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(), - .stat_rx_err_framing(), - .stat_rx_err_preamble() + .stat_rx_byte(stat_rx_byte[2:0]), + .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) ); assign rx_start_packet[1] = 1'b0; + assign stat_rx_byte[3] = 1'b0; taxi_axis_xgmii_tx_32 #( .DATA_W(DATA_W), @@ -371,28 +410,29 @@ end else if (DATA_W == 32) begin /* * 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), /* * Status */ .tx_start_packet(tx_start_packet[0]), - .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[2:0]), + .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) ); assign tx_start_packet[1] = 1'b0; + assign stat_tx_byte[3] = 1'b0; end else begin @@ -400,6 +440,92 @@ end else begin end +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_10g_fifo.sv b/rtl/eth/taxi_eth_mac_10g_fifo.sv index 2aa7ee6..f445f58 100644 --- a/rtl/eth/taxi_eth_mac_10g_fifo.sv +++ b/rtl/eth/taxi_eth_mac_10g_fifo.sv @@ -25,6 +25,11 @@ module taxi_eth_mac_10g_fifo # parameter logic PTP_TS_EN = 1'b0, parameter logic PTP_TS_FMT_TOD = 1'b1, parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64, + 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, @@ -67,6 +72,19 @@ module taxi_eth_mac_10g_fifo # output wire logic [DATA_W-1:0] xgmii_txd, output wire logic [CTRL_W-1:0] xgmii_txc, + /* + * 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 */ @@ -80,17 +98,13 @@ module taxi_eth_mac_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 ); @@ -171,8 +185,6 @@ always_ff @(posedge logic_clk or posedge logic_rst) begin end // PTP timestamping -generate - if (PTP_TS_EN) begin : ptp taxi_ptp_clock_cdc #( @@ -223,7 +235,7 @@ end else begin end -endgenerate +wire stat_rx_fifo_drop; taxi_eth_mac_10g #( .DATA_W(DATA_W), @@ -235,7 +247,12 @@ taxi_eth_mac_10g #( .PTP_TS_FMT_TOD(PTP_TS_FMT_TOD), .PTP_TS_W(PTP_TS_W), .PFC_EN(1'b0), - .PAUSE_EN(1'b0) + .PAUSE_EN(1'b0), + .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_10g_inst ( .tx_clk(tx_clk), @@ -293,14 +310,45 @@ eth_mac_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_bad_frame(rx_error_bad_frame_int), - .rx_error_bad_fcs(rx_error_bad_fcs_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(), + .stat_rx_err_framing(), + .stat_rx_err_preamble(), + .stat_rx_fifo_drop(stat_rx_fifo_drop), .stat_tx_mcf(), .stat_rx_mcf(), .stat_tx_lfc_pkt(), @@ -323,8 +371,10 @@ eth_mac_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_mcf_rx_eth_dst_mcast('0), .cfg_mcf_rx_check_eth_dst_mcast('0), @@ -487,7 +537,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/tb/eth/taxi_eth_mac_10g/Makefile b/tb/eth/taxi_eth_mac_10g/Makefile index 509ed71..b75e627 100644 --- a/tb/eth/taxi_eth_mac_10g/Makefile +++ b/tb/eth/taxi_eth_mac_10g/Makefile @@ -38,6 +38,11 @@ export PARAM_PTP_TS_W := $(if $(filter-out 1,$(PARAM_PTP_TS_FMT_TOD)),64,96) export PARAM_TX_TAG_W := 16 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_10g/test_taxi_eth_mac_10g.py b/tb/eth/taxi_eth_mac_10g/test_taxi_eth_mac_10g.py index c7fad33..d081601 100644 --- a/tb/eth/taxi_eth_mac_10g/test_taxi_eth_mac_10g.py +++ b/tb/eth/taxi_eth_mac_10g/test_taxi_eth_mac_10g.py @@ -43,6 +43,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.xgmii_source = XgmiiSource(dut.xgmii_rxd, dut.xgmii_rxc, dut.rx_clk, dut.rx_rst) self.xgmii_sink = XgmiiSink(dut.xgmii_txd, dut.xgmii_txc, dut.tx_clk, dut.tx_rst) @@ -51,6 +52,8 @@ 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) @@ -67,8 +70,12 @@ class TB: dut.tx_lfc_pause_en.setimmediatevalue(0) dut.tx_pause_req.setimmediatevalue(0) - 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_mcf_rx_eth_dst_mcast.setimmediatevalue(0) dut.cfg_mcf_rx_check_eth_dst_mcast.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.xgmii_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() @@ -167,7 +178,8 @@ async def run_test_tx(dut, payload_lengths=None, payload_data=None, ifg=12): tb = TB(dut) tb.xgmii_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() @@ -213,7 +225,8 @@ async def run_test_tx_alignment(dut, payload_data=None, ifg=12): byte_width = tb.axis_source.width // 8 tb.xgmii_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() @@ -297,7 +310,8 @@ async def run_test_tx_underrun(dut, ifg=12): tb = TB(dut) tb.xgmii_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() @@ -340,7 +354,8 @@ async def run_test_tx_error(dut, ifg=12): tb = TB(dut) tb.xgmii_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() @@ -375,8 +390,10 @@ async def run_test_lfc(dut, ifg=12): tb = TB(dut) tb.xgmii_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 + tb.dut.cfg_rx_max_pkt_len.value = 9218 tb.dut.cfg_rx_enable.value = 1 await tb.reset() @@ -520,8 +537,10 @@ async def run_test_pfc(dut, ifg=12): tb = TB(dut) tb.xgmii_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 + tb.dut.cfg_rx_max_pkt_len.value = 9218 tb.dut.cfg_rx_enable.value = 1 await tb.reset() @@ -733,6 +752,11 @@ def test_taxi_eth_mac_10g(request, data_w, dic_en, pfc_en): parameters['TX_TAG_W'] = 16 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_10g/test_taxi_eth_mac_10g.sv b/tb/eth/taxi_eth_mac_10g/test_taxi_eth_mac_10g.sv index 24f073a..cd99cf3 100644 --- a/tb/eth/taxi_eth_mac_10g/test_taxi_eth_mac_10g.sv +++ b/tb/eth/taxi_eth_mac_10g/test_taxi_eth_mac_10g.sv @@ -27,7 +27,12 @@ module test_taxi_eth_mac_10g # parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64, parameter TX_TAG_W = 16, 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 */ ) (); @@ -69,11 +74,39 @@ logic tx_lfc_pause_en; logic tx_pause_req; logic tx_pause_ack; +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 [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 rx_error_bad_frame; -logic rx_error_bad_fcs; +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; @@ -93,8 +126,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 [47:0] cfg_mcf_rx_eth_dst_mcast; logic cfg_mcf_rx_check_eth_dst_mcast; @@ -138,7 +173,12 @@ taxi_eth_mac_10g #( .PTP_TS_FMT_TOD(PTP_TS_FMT_TOD), .PTP_TS_W(PTP_TS_W), .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), @@ -196,14 +236,45 @@ 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_bad_frame(rx_error_bad_frame), - .rx_error_bad_fcs(rx_error_bad_fcs), + .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), @@ -226,8 +297,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_mcf_rx_eth_dst_mcast(cfg_mcf_rx_eth_dst_mcast), .cfg_mcf_rx_check_eth_dst_mcast(cfg_mcf_rx_check_eth_dst_mcast), diff --git a/tb/eth/taxi_eth_mac_10g_fifo/Makefile b/tb/eth/taxi_eth_mac_10g_fifo/Makefile index 021d935..3fc7a86 100644 --- a/tb/eth/taxi_eth_mac_10g_fifo/Makefile +++ b/tb/eth/taxi_eth_mac_10g_fifo/Makefile @@ -37,6 +37,11 @@ export PARAM_PTP_TS_EN := 1 export PARAM_PTP_TS_FMT_TOD := 1 export PARAM_PTP_TS_W := $(if $(filter-out 1,$(PARAM_PTP_TS_FMT_TOD)),64,96) export PARAM_TX_TAG_W := 16 +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_10g_fifo/test_taxi_eth_mac_10g_fifo.py b/tb/eth/taxi_eth_mac_10g_fifo/test_taxi_eth_mac_10g_fifo.py index 65a3e93..a909bef 100644 --- a/tb/eth/taxi_eth_mac_10g_fifo/test_taxi_eth_mac_10g_fifo.py +++ b/tb/eth/taxi_eth_mac_10g_fifo/test_taxi_eth_mac_10g_fifo.py @@ -41,6 +41,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.xgmii_source = XgmiiSource(dut.xgmii_rxd, dut.xgmii_rxc, dut.rx_clk, dut.rx_rst) @@ -50,28 +51,35 @@ 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) async def reset(self): 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) @@ -81,7 +89,8 @@ async def run_test_rx(dut, payload_lengths=None, payload_data=None, ifg=12): tb = TB(dut) tb.xgmii_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() @@ -132,7 +141,8 @@ async def run_test_tx(dut, payload_lengths=None, payload_data=None, ifg=12): tb = TB(dut) tb.xgmii_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() @@ -184,7 +194,8 @@ async def run_test_tx_alignment(dut, payload_data=None, ifg=12): byte_width = tb.axis_source.width // 8 tb.xgmii_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() @@ -341,6 +352,11 @@ def test_taxi_eth_mac_10g_fifo(request, data_w, dic_en): parameters['PTP_TS_FMT_TOD'] = 1 parameters['PTP_TS_W'] = 96 if parameters['PTP_TS_FMT_TOD'] else 64 parameters['TX_TAG_W'] = 16 + 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_10g_fifo/test_taxi_eth_mac_10g_fifo.sv b/tb/eth/taxi_eth_mac_10g_fifo/test_taxi_eth_mac_10g_fifo.sv index 749a133..9b5f711 100644 --- a/tb/eth/taxi_eth_mac_10g_fifo/test_taxi_eth_mac_10g_fifo.sv +++ b/tb/eth/taxi_eth_mac_10g_fifo/test_taxi_eth_mac_10g_fifo.sv @@ -27,6 +27,11 @@ module test_taxi_eth_mac_10g_fifo # parameter logic PTP_TS_FMT_TOD = 1'b1, parameter PTP_TS_W = PTP_TS_FMT_TOD ? 96 : 64, parameter TX_TAG_W = 16, + 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, @@ -65,6 +70,13 @@ logic [CTRL_W-1:0] xgmii_rxc; logic [DATA_W-1:0] xgmii_txd; logic [CTRL_W-1:0] xgmii_txc; +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; @@ -75,11 +87,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; taxi_eth_mac_10g_fifo #( @@ -91,6 +102,11 @@ taxi_eth_mac_10g_fifo #( .PTP_TS_EN(PTP_TS_EN), .PTP_TS_FMT_TOD(PTP_TS_FMT_TOD), .PTP_TS_W(PTP_TS_W), + .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), @@ -133,6 +149,19 @@ uut ( .xgmii_txd(xgmii_txd), .xgmii_txc(xgmii_txc), + /* + * 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 */ @@ -146,17 +175,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) );