From 1f433365e6f9bb51aec3bade62577957418d3423 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Fri, 10 Jul 2026 01:09:50 -0700 Subject: [PATCH] eth: Add support for USXGMII symbol replication to 32-bit AXIS/BASE-R decode module Signed-off-by: Alex Forencich --- src/eth/rtl/taxi_axis_baser_rx_32.sv | 78 ++++++++++++++++--- src/eth/tb/taxi_axis_baser_rx_32/Makefile | 1 + .../test_taxi_axis_baser_rx_32.py | 45 ++++++++--- .../test_taxi_axis_baser_rx_32.sv | 8 ++ 4 files changed, 113 insertions(+), 19 deletions(-) diff --git a/src/eth/rtl/taxi_axis_baser_rx_32.sv b/src/eth/rtl/taxi_axis_baser_rx_32.sv index 2b2ba95..abc5fb7 100644 --- a/src/eth/rtl/taxi_axis_baser_rx_32.sv +++ b/src/eth/rtl/taxi_axis_baser_rx_32.sv @@ -20,6 +20,7 @@ module taxi_axis_baser_rx_32 # parameter DATA_W = 32, parameter HDR_W = 2, parameter logic GBX_IF_EN = 1'b0, + parameter logic USXGMII_EN = 1'b0, parameter logic PTP_TS_EN = 1'b0, parameter PTP_TS_W = 96 ) @@ -57,6 +58,9 @@ module taxi_axis_baser_rx_32 # */ input wire logic [15:0] cfg_rx_max_pkt_len = 16'd1518-1, input wire logic cfg_rx_enable, + input wire logic cfg_rx_usxgmii_en = 1'b1, + input wire logic cfg_rx_usxgmii_5g = 1'b0, + input wire logic [2:0] cfg_rx_usxgmii_speed = 3'b011, /* * Status @@ -155,6 +159,7 @@ state_t state_reg = STATE_IDLE, state_next; // datapath control signals logic reset_crc; +logic update_crc; logic term_present_alt_reg = 1'b0; logic term_present_reg = 1'b0; @@ -165,6 +170,9 @@ logic [1:0] term_lane_reg = 0; logic [1:0] term_lane_d0_reg = 0; logic framing_error_reg = 1'b0; +logic [9:0] rep_cnt_reg = '0; +logic rep_stall_reg = 1'b0; + logic [DATA_W-1:0] input_data_d0_reg = '0; logic [DATA_W-1:0] input_data_d1_reg = '0; logic [DATA_W-1:0] input_data_d2_reg = '0; @@ -292,6 +300,7 @@ always_comb begin state_next = STATE_IDLE; reset_crc = 1'b0; + update_crc = 1'b0; frame_oversize_next = frame_oversize_reg; pre_ok_next = pre_ok_reg; @@ -332,6 +341,9 @@ always_comb begin if (GBX_IF_EN && !encoded_rx_data_valid) begin // data from gearbox not valid - hold state state_next = state_reg; + end else if (USXGMII_EN && rep_stall_reg) begin + // USXGMII stall - hold state + state_next = state_reg; end else begin // counter to measure frame length if (&frame_len_reg[15:2] == 0) begin @@ -382,6 +394,7 @@ always_comb begin STATE_IDLE: begin // idle state - wait for packet reset_crc = 1'b1; + update_crc = 1'b1; frame_oversize_next = 1'b0; frame_len_next = 16'(KEEP_W); @@ -412,6 +425,7 @@ always_comb begin end STATE_PREAMBLE: begin // drop preamble + update_crc = 1'b1; hdr_ptr_next = 0; @@ -429,6 +443,8 @@ always_comb begin end STATE_PAYLOAD: begin // read payload + update_crc = 1'b1; + m_axis_rx_tdata_next = input_data_d2_reg; m_axis_rx_tkeep_next = {KEEP_W{1'b1}}; m_axis_rx_tvalid_next = 1'b1; @@ -611,16 +627,20 @@ always_ff @(posedge clk) begin term_first_cycle_reg <= term_first_cycle_alt_reg; term_lane_alt_reg <= 0; term_lane_reg <= term_lane_alt_reg; - term_lane_d0_reg <= term_lane_reg; - - input_data_d0_reg <= encoded_rx_data_reg; - input_data_d1_reg <= input_data_d0_reg; - input_data_d2_reg <= input_data_d1_reg; input_start_alt_reg <= 1'b0; - input_start_d0_reg <= input_start_alt_reg; - input_start_d1_reg <= input_start_d0_reg; - input_start_d2_reg <= input_start_d1_reg; + + if (!USXGMII_EN || !rep_stall_reg) begin + term_lane_d0_reg <= term_lane_reg; + + input_data_d0_reg <= encoded_rx_data_reg; + input_data_d1_reg <= input_data_d0_reg; + input_data_d2_reg <= input_data_d1_reg; + + input_start_d0_reg <= input_start_alt_reg; + input_start_d1_reg <= input_start_d0_reg; + input_start_d2_reg <= input_start_d1_reg; + end if (encoded_rx_hdr_valid_reg) begin // portion with header @@ -801,16 +821,54 @@ always_ff @(posedge clk) begin if (reset_crc) begin crc_state_reg <= '1; - end else begin + end else if (update_crc) begin crc_state_reg <= crc_state; end - crc_valid_reg <= crc_valid; + if (update_crc) begin + crc_valid_reg <= crc_valid; + end + + if (USXGMII_EN && cfg_rx_usxgmii_en) begin + if (rep_cnt_reg == 0 || (encoded_rx_hdr_valid_reg && encoded_rx_hdr_reg[0]) || input_start_alt_reg) begin + if (cfg_rx_usxgmii_5g) begin + case (cfg_rx_usxgmii_speed) + 3'b000: rep_cnt_reg <= 499; // 10 Mbps + 3'b001: rep_cnt_reg <= 49; // 100 Mbps + 3'b010: rep_cnt_reg <= 4; // 1 Gbps + 3'b100: rep_cnt_reg <= 1; // 2.5 Gbps + 3'b101: rep_cnt_reg <= 0; // 5 Gbps + default: rep_cnt_reg <= 0; + endcase + end else begin + case (cfg_rx_usxgmii_speed) + 3'b000: rep_cnt_reg <= 999; // 10 Mbps + 3'b001: rep_cnt_reg <= 99; // 100 Mbps + 3'b010: rep_cnt_reg <= 9; // 1 Gbps + 3'b011: rep_cnt_reg <= 0; // 10 Gbps + 3'b100: rep_cnt_reg <= 3; // 2.5 Gbps + 3'b101: rep_cnt_reg <= 1; // 5 Gbps + default: rep_cnt_reg <= 0; + endcase + end + + rep_stall_reg <= 1'b0; + end else begin + rep_cnt_reg <= rep_cnt_reg-1; + rep_stall_reg <= 1'b1; + end + end else begin + rep_cnt_reg <= '0; + rep_stall_reg <= 1'b0; + end end if (rst) begin state_reg <= STATE_IDLE; + rep_cnt_reg <= '0; + rep_stall_reg <= 1'b0; + m_axis_rx_tvalid_reg <= 1'b0; rx_os_0_reg <= 1'b0; diff --git a/src/eth/tb/taxi_axis_baser_rx_32/Makefile b/src/eth/tb/taxi_axis_baser_rx_32/Makefile index 051a8fa..543b3c9 100644 --- a/src/eth/tb/taxi_axis_baser_rx_32/Makefile +++ b/src/eth/tb/taxi_axis_baser_rx_32/Makefile @@ -37,6 +37,7 @@ VERILOG_SOURCES := $(call uniq_base,$(call process_f_files,$(VERILOG_SOURCES))) export PARAM_DATA_W := 32 export PARAM_HDR_W := 2 export PARAM_GBX_IF_EN := 1 +export PARAM_USXGMII_EN := 1 export PARAM_PTP_TS_EN := 1 export PARAM_PTP_TS_FMT_TOD := 1 diff --git a/src/eth/tb/taxi_axis_baser_rx_32/test_taxi_axis_baser_rx_32.py b/src/eth/tb/taxi_axis_baser_rx_32/test_taxi_axis_baser_rx_32.py index 8a36925..65a638d 100644 --- a/src/eth/tb/taxi_axis_baser_rx_32/test_taxi_axis_baser_rx_32.py +++ b/src/eth/tb/taxi_axis_baser_rx_32/test_taxi_axis_baser_rx_32.py @@ -38,7 +38,7 @@ except ImportError: class TB: - def __init__(self, dut, gbx_cfg=None): + def __init__(self, dut, gbx_cfg=None, usxgmii_speed=None): self.dut = dut self.log = logging.getLogger("cocotb.tb") @@ -66,6 +66,29 @@ class TB: dut.cfg_rx_max_pkt_len.setimmediatevalue(0) dut.cfg_rx_enable.setimmediatevalue(0) + if usxgmii_speed is not None: + dut.cfg_rx_usxgmii_en.setimmediatevalue(1) + dut.cfg_rx_usxgmii_5g.setimmediatevalue(0) + dut.cfg_rx_usxgmii_speed.setimmediatevalue(usxgmii_speed) + if usxgmii_speed == 0: + self.source.set_xgmii_rep_count(999) # 10 Mbps + elif usxgmii_speed == 1: + self.source.set_xgmii_rep_count(99) # 100 Mbps + elif usxgmii_speed == 2: + self.source.set_xgmii_rep_count(9) # 1 Gbps + elif usxgmii_speed == 3: + self.source.set_xgmii_rep_count(0) # 10 Gbps + elif usxgmii_speed == 4: + self.source.set_xgmii_rep_count(3) # 2.5 Gbps + elif usxgmii_speed == 5: + self.source.set_xgmii_rep_count(1) # 5 Gbps + else: + self.source.set_xgmii_rep_count(0) + else: + dut.cfg_rx_usxgmii_en.setimmediatevalue(0) + dut.cfg_rx_usxgmii_5g.setimmediatevalue(0) + dut.cfg_rx_usxgmii_speed.setimmediatevalue(0b011) + self.source.set_xgmii_rep_count(0) self.stats = {} self.stats["stat_rx_byte"] = 0 @@ -110,9 +133,9 @@ class TB: self.stats[stat] += int(getattr(self.dut, stat).value) -async def run_test(dut, gbx_cfg=None, payload_lengths=None, payload_data=None, ifg=12): +async def run_test(dut, gbx_cfg=None, usxgmii_speed=None, payload_lengths=None, payload_data=None, ifg=12): - tb = TB(dut, gbx_cfg) + tb = TB(dut, gbx_cfg, usxgmii_speed) tb.source.ifg = ifg tb.dut.cfg_rx_max_pkt_len.value = 9218-1 @@ -176,9 +199,9 @@ async def run_test(dut, gbx_cfg=None, payload_lengths=None, payload_data=None, i await RisingEdge(dut.clk) -async def run_test_oversize(dut, gbx_cfg=None, ifg=12): +async def run_test_oversize(dut, gbx_cfg=None, usxgmii_speed=None, ifg=12): - tb = TB(dut, gbx_cfg) + tb = TB(dut, gbx_cfg, usxgmii_speed) tb.source.ifg = ifg tb.dut.cfg_rx_max_pkt_len.value = 1518-1 @@ -265,9 +288,9 @@ async def run_test_oversize(dut, gbx_cfg=None, ifg=12): await RisingEdge(dut.clk) -async def run_test_os(dut, gbx_cfg=None): +async def run_test_os(dut, gbx_cfg=None, usxgmii_speed=None): - tb = TB(dut, gbx_cfg) + tb = TB(dut, gbx_cfg, usxgmii_speed) await tb.reset() @@ -315,16 +338,19 @@ if getattr(cocotb, 'top', None) is not None: factory = TestFactory(run_test) factory.add_option("payload_lengths", [size_list]) factory.add_option("payload_data", [incrementing_payload]) - factory.add_option("ifg", list(range(0, 13))) + factory.add_option("ifg", [0, 1, 11, 12]) + factory.add_option("usxgmii_speed", [None, 2, 4, 5, 3]) factory.add_option("gbx_cfg", gbx_cfgs) factory.generate_tests() factory = TestFactory(run_test_oversize) - factory.add_option("ifg", list(range(0, 13))) + factory.add_option("ifg", [0, 1, 11, 12]) + factory.add_option("usxgmii_speed", [None, 2, 4, 5, 3]) factory.add_option("gbx_cfg", gbx_cfgs) factory.generate_tests() factory = TestFactory(run_test_os) + factory.add_option("usxgmii_speed", [None, 2, 4, 5, 3]) factory.add_option("gbx_cfg", gbx_cfgs) factory.generate_tests() @@ -370,6 +396,7 @@ def test_taxi_axis_baser_rx_32(request, gbx_en): parameters['DATA_W'] = 32 parameters['HDR_W'] = 2 parameters['GBX_IF_EN'] = gbx_en + parameters['USXGMII_EN'] = 1 parameters['PTP_TS_EN'] = 1 parameters['PTP_TS_FMT_TOD'] = 1 parameters['PTP_TS_W'] = 96 if parameters['PTP_TS_FMT_TOD'] else 64 diff --git a/src/eth/tb/taxi_axis_baser_rx_32/test_taxi_axis_baser_rx_32.sv b/src/eth/tb/taxi_axis_baser_rx_32/test_taxi_axis_baser_rx_32.sv index 92f40c9..252af60 100644 --- a/src/eth/tb/taxi_axis_baser_rx_32/test_taxi_axis_baser_rx_32.sv +++ b/src/eth/tb/taxi_axis_baser_rx_32/test_taxi_axis_baser_rx_32.sv @@ -21,6 +21,7 @@ module test_taxi_axis_baser_rx_32 # parameter DATA_W = 32, parameter HDR_W = 2, parameter logic GBX_IF_EN = 1'b0, + parameter logic USXGMII_EN = 1'b1, 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 @@ -48,6 +49,9 @@ logic [PTP_TS_W-1:0] ptp_ts; logic [15:0] cfg_rx_max_pkt_len; logic cfg_rx_enable; +logic cfg_rx_usxgmii_en; +logic cfg_rx_usxgmii_5g; +logic [2:0] cfg_rx_usxgmii_speed; logic rx_start_packet; logic [2:0] stat_rx_byte; @@ -70,6 +74,7 @@ taxi_axis_baser_rx_32 #( .DATA_W(DATA_W), .HDR_W(HDR_W), .GBX_IF_EN(GBX_IF_EN), + .USXGMII_EN(USXGMII_EN), .PTP_TS_EN(PTP_TS_EN), .PTP_TS_W(PTP_TS_W) ) @@ -107,6 +112,9 @@ uut ( */ .cfg_rx_max_pkt_len(cfg_rx_max_pkt_len), .cfg_rx_enable(cfg_rx_enable), + .cfg_rx_usxgmii_en(cfg_rx_usxgmii_en), + .cfg_rx_usxgmii_5g(cfg_rx_usxgmii_5g), + .cfg_rx_usxgmii_speed(cfg_rx_usxgmii_speed), /* * Status