From bec324dc03d7c4bb939f03fd2f46354148193b21 Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Wed, 26 Mar 2025 23:03:57 -0700 Subject: [PATCH] eth: Fix bugs in 10G MAC RX related to short IFGs Signed-off-by: Alex Forencich --- rtl/eth/taxi_axis_baser_rx_64.sv | 41 +++++++++++-------- rtl/eth/taxi_axis_xgmii_rx_64.sv | 34 ++++++--------- .../test_taxi_axis_baser_rx_64.py | 4 +- .../test_taxi_axis_xgmii_rx_32.py | 4 +- .../test_taxi_axis_xgmii_rx_64.py | 4 +- 5 files changed, 43 insertions(+), 44 deletions(-) diff --git a/rtl/eth/taxi_axis_baser_rx_64.sv b/rtl/eth/taxi_axis_baser_rx_64.sv index 7747e71..7128a30 100644 --- a/rtl/eth/taxi_axis_baser_rx_64.sv +++ b/rtl/eth/taxi_axis_baser_rx_64.sv @@ -160,6 +160,10 @@ logic [DATA_W-1:0] input_data_d1 = '0; logic [3:0] input_type_d0 = INPUT_TYPE_IDLE; logic [3:0] input_type_d1 = INPUT_TYPE_IDLE; +logic input_start_swap = 1'b0; +logic input_start_d0 = 1'b0; +logic input_start_d1 = 1'b0; + logic [DATA_W-1:0] m_axis_rx_tdata_reg = '0, m_axis_rx_tdata_next; logic [KEEP_W-1:0] m_axis_rx_tkeep_reg = '0, m_axis_rx_tkeep_next; logic m_axis_rx_tvalid_reg = 1'b0, m_axis_rx_tvalid_next; @@ -279,7 +283,7 @@ always_comb begin // idle state - wait for packet reset_crc = 1'b1; - if (input_type_d1 == INPUT_TYPE_START_0 && cfg_rx_enable) begin + if (input_start_d1 && cfg_rx_enable) begin // start condition reset_crc = 1'b0; state_next = STATE_PAYLOAD; @@ -401,6 +405,9 @@ always_ff @(posedge clk) begin swap_data <= encoded_rx_data_masked[63:32]; + input_start_swap <= 1'b0; + input_start_d0 <= input_start_swap; + if (PTP_TS_EN && PTP_TS_FMT_TOD) begin // ns field rollover ptp_ts_adj_reg[15:0] <= ptp_ts_reg[15:0]; @@ -409,21 +416,17 @@ always_ff @(posedge clk) begin ptp_ts_adj_reg[95:48] <= ptp_ts_reg[95:48] + 1; end + // start control character detection if (encoded_rx_hdr == SYNC_CTRL && encoded_rx_data[7:0] == BLOCK_TYPE_START_0) begin lanes_swapped <= 1'b0; - input_type_d0 <= INPUT_TYPE_START_0; - input_data_d0 <= encoded_rx_data_masked; + input_start_d0 <= 1'b1; end else if (encoded_rx_hdr == SYNC_CTRL && (encoded_rx_data[7:0] == BLOCK_TYPE_START_4 || encoded_rx_data[7:0] == BLOCK_TYPE_OS_START)) begin lanes_swapped <= 1'b1; - delay_type_valid <= 1'b1; + input_start_swap <= 1'b1; + end - if (delay_type_valid) begin - input_type_d0 <= delay_type; - end else begin - input_type_d0 <= INPUT_TYPE_IDLE; - end - input_data_d0 <= {encoded_rx_data_masked[31:0], swap_data}; - end else if (lanes_swapped) begin + // lane swapping and termination character detection + if (lanes_swapped) begin if (delay_type_valid) begin input_type_d0 <= delay_type; end else if (encoded_rx_hdr == SYNC_DATA) begin @@ -616,7 +619,8 @@ always_ff @(posedge clk) begin input_type_d0 <= INPUT_TYPE_ERROR; end - if (delay_type == INPUT_TYPE_START_0 && delay_type_valid) begin + // capture timestamps + if (input_start_swap) begin start_packet_reg <= 2'b10; if (PTP_TS_FMT_TOD) begin ptp_ts_reg[45:0] <= ptp_ts[45:0] + 46'(ts_inc_reg >> 1); @@ -626,14 +630,13 @@ always_ff @(posedge clk) begin end end - if (input_type_d0 == INPUT_TYPE_START_0) begin - if (!lanes_swapped) begin - start_packet_reg <= 2'b01; - ptp_ts_reg <= ptp_ts; - end + if (input_start_d0 && !lanes_swapped) begin + start_packet_reg <= 2'b01; + ptp_ts_reg <= ptp_ts; end input_type_d1 <= input_type_d0; + input_start_d1 <= input_start_d0; input_data_d1 <= input_data_d0; if (reset_crc) begin @@ -662,6 +665,10 @@ always_ff @(posedge clk) begin input_type_d0 <= INPUT_TYPE_IDLE; input_type_d1 <= INPUT_TYPE_IDLE; + input_start_swap <= 1'b0; + input_start_d0 <= 1'b0; + input_start_d1 <= 1'b0; + lanes_swapped <= 1'b0; delay_type_valid <= 1'b0; diff --git a/rtl/eth/taxi_axis_xgmii_rx_64.sv b/rtl/eth/taxi_axis_xgmii_rx_64.sv index 6a21c43..27efbd7 100644 --- a/rtl/eth/taxi_axis_xgmii_rx_64.sv +++ b/rtl/eth/taxi_axis_xgmii_rx_64.sv @@ -326,6 +326,19 @@ always_ff @(posedge clk) begin ptp_ts_adj_reg[95:48] <= ptp_ts_reg[95:48] + 1; end + // start control character detection + if (xgmii_rxc[0] && xgmii_rxd[7:0] == XGMII_START) begin + lanes_swapped <= 1'b0; + xgmii_start_d0 <= 1'b1; + + framing_error_reg <= xgmii_rxc[7:1] != 0; + end else if (xgmii_rxc[4] && xgmii_rxd[39:32] == XGMII_START) begin + lanes_swapped <= 1'b1; + xgmii_start_swap <= 1'b1; + + framing_error_reg <= xgmii_rxc[7:5] != 0; + end + // lane swapping and termination character detection if (lanes_swapped) begin xgmii_rxd_d0 <= {xgmii_rxd_masked[31:0], swap_rxd}; @@ -340,7 +353,6 @@ always_ff @(posedge clk) begin term_lane_reg <= 3'(i); term_present_reg <= 1'b1; framing_error_reg <= ({xgmii_rxc[3:0], swap_rxc} & ({CTRL_W{1'b1}} >> (CTRL_W-i))) != 0; - lanes_swapped <= 1'b0; end end end else begin @@ -356,30 +368,10 @@ always_ff @(posedge clk) begin term_lane_reg <= 3'(i); term_present_reg <= 1'b1; framing_error_reg <= (xgmii_rxc & ({CTRL_W{1'b1}} >> (CTRL_W-i))) != 0; - lanes_swapped <= 1'b0; end end end - // start control character detection - if (xgmii_rxc[0] && xgmii_rxd[7:0] == XGMII_START) begin - lanes_swapped <= 1'b0; - - xgmii_start_d0 <= 1'b1; - - term_lane_reg <= 0; - term_present_reg <= 1'b0; - framing_error_reg <= xgmii_rxc[7:1] != 0; - end else if (xgmii_rxc[4] && xgmii_rxd[39:32] == XGMII_START) begin - lanes_swapped <= 1'b1; - - xgmii_start_swap <= 1'b1; - - term_lane_reg <= 0; - term_present_reg <= 1'b0; - framing_error_reg <= xgmii_rxc[7:5] != 0; - end - // capture timestamps if (xgmii_start_swap) begin start_packet_reg <= 2'b10; diff --git a/tb/eth/taxi_axis_baser_rx_64/test_taxi_axis_baser_rx_64.py b/tb/eth/taxi_axis_baser_rx_64/test_taxi_axis_baser_rx_64.py index d83f283..4bfa214 100644 --- a/tb/eth/taxi_axis_baser_rx_64/test_taxi_axis_baser_rx_64.py +++ b/tb/eth/taxi_axis_baser_rx_64/test_taxi_axis_baser_rx_64.py @@ -109,7 +109,7 @@ async def run_test(dut, payload_lengths=None, payload_data=None, ifg=12): def size_list(): - return list(range(60, 128)) + [512, 1514, 9214] + [60]*10 + return list(range(60, 128)) + [512, 1514, 9214] + [60]*10 + [i for i in range(64, 73) for k in range(8)] def incrementing_payload(length): @@ -125,7 +125,7 @@ if cocotb.SIM_NAME: factory = TestFactory(run_test) factory.add_option("payload_lengths", [size_list]) factory.add_option("payload_data", [incrementing_payload]) - factory.add_option("ifg", [12, 0]) + factory.add_option("ifg", list(range(0, 13))) factory.generate_tests() diff --git a/tb/eth/taxi_axis_xgmii_rx_32/test_taxi_axis_xgmii_rx_32.py b/tb/eth/taxi_axis_xgmii_rx_32/test_taxi_axis_xgmii_rx_32.py index 8af9431..fb7f5f6 100644 --- a/tb/eth/taxi_axis_xgmii_rx_32/test_taxi_axis_xgmii_rx_32.py +++ b/tb/eth/taxi_axis_xgmii_rx_32/test_taxi_axis_xgmii_rx_32.py @@ -94,7 +94,7 @@ async def run_test(dut, payload_lengths=None, payload_data=None, ifg=12): def size_list(): - return list(range(60, 128)) + [512, 1514, 9214] + [60]*10 + return list(range(60, 128)) + [512, 1514, 9214] + [60]*10 + [i for i in range(64, 73) for k in range(8)] def incrementing_payload(length): @@ -110,7 +110,7 @@ if cocotb.SIM_NAME: factory = TestFactory(run_test) factory.add_option("payload_lengths", [size_list]) factory.add_option("payload_data", [incrementing_payload]) - factory.add_option("ifg", [12, 0]) + factory.add_option("ifg", list(range(0, 13))) factory.generate_tests() diff --git a/tb/eth/taxi_axis_xgmii_rx_64/test_taxi_axis_xgmii_rx_64.py b/tb/eth/taxi_axis_xgmii_rx_64/test_taxi_axis_xgmii_rx_64.py index 451febc..51b8ba9 100644 --- a/tb/eth/taxi_axis_xgmii_rx_64/test_taxi_axis_xgmii_rx_64.py +++ b/tb/eth/taxi_axis_xgmii_rx_64/test_taxi_axis_xgmii_rx_64.py @@ -98,7 +98,7 @@ async def run_test(dut, payload_lengths=None, payload_data=None, ifg=12): def size_list(): - return list(range(60, 128)) + [512, 1514, 9214] + [60]*10 + return list(range(60, 128)) + [512, 1514, 9214] + [60]*10 + [i for i in range(64, 73) for k in range(8)] def incrementing_payload(length): @@ -114,7 +114,7 @@ if cocotb.SIM_NAME: factory = TestFactory(run_test) factory.add_option("payload_lengths", [size_list]) factory.add_option("payload_data", [incrementing_payload]) - factory.add_option("ifg", [12, 0]) + factory.add_option("ifg", list(range(0, 13))) factory.generate_tests()