diff --git a/src/eth/rtl/taxi_axis_basex_rx_16.sv b/src/eth/rtl/taxi_axis_basex_rx_16.sv index 4d1639e..1615699 100644 --- a/src/eth/rtl/taxi_axis_basex_rx_16.sv +++ b/src/eth/rtl/taxi_axis_basex_rx_16.sv @@ -20,7 +20,8 @@ module taxi_axis_basex_rx_16 # parameter DATA_W = 16, parameter CTRL_W = (DATA_W/8), parameter logic GBX_IF_EN = 1'b0, - parameter logic AN_EN = 1'b1, + parameter logic SGMII_EN = 1'b1, + parameter logic AN_EN = SGMII_EN, parameter logic PTP_TS_EN = 1'b0, parameter logic PTP_TS_FMT_TOD = 1'b1, parameter PTP_TS_W = 96 @@ -59,7 +60,9 @@ module taxi_axis_basex_rx_16 # * Configuration */ input wire logic [15:0] cfg_rx_max_pkt_len = 16'd1518-1, - input wire logic cfg_rx_enable, + input wire logic cfg_rx_enable = 1'b1, + input wire logic cfg_rx_sgmii_en = 1'b1, + input wire logic [1:0] cfg_rx_sgmii_speed = 2'b10, /* * Status @@ -138,6 +141,7 @@ state_t state_reg = STATE_IDLE, state_next; // datapath control signals logic reset_crc; +logic update_crc; logic [DATA_W-1:0] input_data_d0_reg = '0; logic [DATA_W-1:0] input_data_d1_reg = '0; @@ -146,6 +150,7 @@ logic [DATA_W-1:0] input_data_d2_reg = '0; logic input_k28p5_d0_reg = 1'b0; logic input_i_d0_reg = 1'b0; logic input_c_d0_reg = 1'b0; +logic input_start_int_reg = 1'b0; logic input_start_d0_reg = 1'b0; logic frame_oversize_reg = 1'b0, frame_oversize_next; @@ -159,6 +164,12 @@ logic [14:0] frame_len_lim_cyc_reg = '0, frame_len_lim_cyc_next; logic frame_len_lim_last_reg = '0, frame_len_lim_last_next; logic frame_len_lim_check_reg = '0, frame_len_lim_check_next; +logic [5:0] rep_cnt_reg = '0; +logic rep_stall_reg = 1'b0; +logic rep_en_reg = 1'b0; +logic rep_sel_reg = 1'b0; +logic rep_store_reg = 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; @@ -251,8 +262,28 @@ logic lanes_swapped_reg = 1'b0; logic [7:0] swap_data_reg = '0; logic swap_data_k_reg = '0; -wire [DATA_W-1:0] swap_rx_data = lanes_swapped_reg ? {encoded_rx_data[7:0], swap_data_reg} : encoded_rx_data; -wire [CTRL_W-1:0] swap_rx_data_k = lanes_swapped_reg ? {encoded_rx_data_k[0], swap_data_k_reg} : encoded_rx_data_k; +logic [DATA_W-1:0] swap_rx_data; +logic [CTRL_W-1:0] swap_rx_data_k; + +always_comb begin + swap_rx_data = encoded_rx_data; + swap_rx_data_k = encoded_rx_data_k; + + if (SGMII_EN && rep_en_reg) begin + if (lanes_swapped_reg) begin + swap_rx_data = {encoded_rx_data[15:8], swap_data_reg}; + swap_rx_data_k = {encoded_rx_data_k[1], swap_data_k_reg}; + end else begin + swap_rx_data = {encoded_rx_data[7:0], swap_data_reg}; + swap_rx_data_k = {encoded_rx_data_k[0], swap_data_k_reg}; + end + end else begin + if (lanes_swapped_reg) begin + swap_rx_data = {encoded_rx_data[7:0], swap_data_reg}; + swap_rx_data_k = {encoded_rx_data_k[0], swap_data_k_reg}; + end + end +end // Mask input data wire [DATA_W-1:0] swap_rx_data_masked; @@ -284,6 +315,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; @@ -322,6 +354,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 (SGMII_EN && rep_stall_reg) begin + // SGMII stall - hold state + state_next = state_reg; end else begin // counter to measure frame length if (&frame_len_reg[15:1] == 0) begin @@ -426,6 +461,7 @@ always_comb begin end STATE_PIPE: begin // wait for pipeline to fill + update_crc = 1'b1; hdr_ptr_next = 0; @@ -449,6 +485,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; @@ -636,17 +674,38 @@ always_ff @(posedge clk) begin if (!GBX_IF_EN || encoded_rx_data_valid) begin - swap_data_reg <= encoded_rx_data[15:8]; - swap_data_k_reg <= encoded_rx_data_k[1]; + if (!SGMII_EN || !rep_en_reg) begin + swap_data_reg <= encoded_rx_data[15:8]; + swap_data_k_reg <= encoded_rx_data_k[1]; - input_data_d0_reg <= swap_rx_data_masked; - input_data_d1_reg <= input_data_d0_reg; - input_data_d2_reg <= input_data_d1_reg; + input_data_d0_reg <= swap_rx_data_masked; + input_data_d1_reg <= input_data_d0_reg; + input_data_d2_reg <= input_data_d1_reg; + end else begin + if (rep_store_reg || encoded_rx_data_k != 0) begin + if (!encoded_rx_data_k[0]) begin + swap_data_reg <= encoded_rx_data[15:8]; + swap_data_k_reg <= encoded_rx_data_k[1]; + end else begin + swap_data_reg <= encoded_rx_data[7:0]; + swap_data_k_reg <= encoded_rx_data_k[0]; + end + end + + if (!rep_stall_reg) begin + input_data_d0_reg <= swap_rx_data_masked; + input_data_d1_reg <= input_data_d0_reg; + input_data_d2_reg <= input_data_d1_reg; + end + end input_k28p5_d0_reg <= 1'b0; input_i_d0_reg <= 1'b0; input_c_d0_reg <= 1'b0; - input_start_d0_reg <= 1'b0; + if (!SGMII_EN || !rep_stall_reg) begin + input_start_int_reg <= 1'b0; + input_start_d0_reg <= input_start_int_reg; + end if (PTP_TS_EN && PTP_TS_FMT_TOD) begin // ns field rollover @@ -698,7 +757,11 @@ always_ff @(posedge clk) begin // start control character detection if (encoded_rx_data_k[0] && encoded_rx_data[7:0] == CTRL_S) begin - input_start_d0_reg <= 1'b1; + if (rep_en_reg) begin + input_start_int_reg <= 1'b1; + end else begin + input_start_d0_reg <= 1'b1; + end in_pre_reg <= 1'b1; lanes_swapped_reg <= 1'b0; end @@ -710,43 +773,148 @@ always_ff @(posedge clk) begin end // SFD detection - start_packet_int_reg <= 1'b0; if (in_pre_reg) begin - if (encoded_rx_data[7]) begin - // truncated preamble - in_pre_reg <= 1'b0; - lanes_swapped_reg <= 1'b1; - input_data_d0_reg <= {ETH_SFD, ETH_PRE}; - start_packet_reg <= 2'b10; - if (PTP_TS_FMT_TOD) begin - // workaround for verilator lint bug: unreachable by parameter value - /* verilator lint_off SELRANGE */ - ptp_ts_reg[45:0] <= ptp_ts[45:0] + 46'(ts_inc_reg >> 1); - ptp_ts_reg[95:48] <= ptp_ts[95:48]; - /* verilator lint_on SELRANGE */ - end else begin - ptp_ts_reg <= ptp_ts + PTP_TS_W'(ts_inc_reg >> 1); + lanes_swapped_reg <= 1'b0; + if (SGMII_EN && rep_en_reg) begin + // SGMII repeated symbols + if (encoded_rx_data[7]) begin + // normal + in_pre_reg <= 1'b0; + start_packet_int_reg <= 1'b1; + end else if (encoded_rx_data[15]) begin + // truncated start + in_pre_reg <= 1'b0; + lanes_swapped_reg <= 1'b1; + start_packet_int_reg <= 1'b1; + end + end else begin + // full rate + if (encoded_rx_data[7]) begin + // truncated preamble + in_pre_reg <= 1'b0; + lanes_swapped_reg <= 1'b1; + input_data_d0_reg <= {ETH_SFD, ETH_PRE}; + start_packet_reg <= 2'b10; + if (PTP_TS_FMT_TOD) begin + // workaround for verilator lint bug: unreachable by parameter value + /* verilator lint_off SELRANGE */ + ptp_ts_reg[45:0] <= ptp_ts[45:0] + 46'(ts_inc_reg >> 1); + ptp_ts_reg[95:48] <= ptp_ts[95:48]; + /* verilator lint_on SELRANGE */ + end else begin + ptp_ts_reg <= ptp_ts + PTP_TS_W'(ts_inc_reg >> 1); + end + end else if (encoded_rx_data[15]) begin + // normal preamble + in_pre_reg <= 1'b0; + start_packet_int_reg <= 1'b1; end - end else if (encoded_rx_data[15]) begin - // normal preamble - in_pre_reg <= 1'b0; - lanes_swapped_reg <= 1'b0; - start_packet_int_reg <= 1'b1; end end if (start_packet_int_reg) begin - start_packet_reg <= 2'b01; - ptp_ts_reg <= ptp_ts; + if (SGMII_EN && rep_en_reg) begin + if (lanes_swapped_reg) begin + if (rep_store_reg) begin + start_packet_int_reg <= 1'b0; + start_packet_reg <= 2'b10; + end + if (PTP_TS_FMT_TOD) begin + // workaround for verilator lint bug: unreachable by parameter value + /* verilator lint_off SELRANGE */ + ptp_ts_reg[45:0] <= ptp_ts[45:0] + 46'(ts_inc_reg >> 1); + ptp_ts_reg[95:48] <= ptp_ts[95:48]; + /* verilator lint_on SELRANGE */ + end else begin + ptp_ts_reg <= ptp_ts + PTP_TS_W'(ts_inc_reg >> 1); + end + end else begin + if (rep_store_reg) begin + start_packet_int_reg <= 1'b0; + start_packet_reg <= 2'b01; + end + ptp_ts_reg <= ptp_ts; + end + end else begin + start_packet_int_reg <= 1'b0; + start_packet_reg <= 2'b01; + ptp_ts_reg <= ptp_ts; + end end 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 (SGMII_EN && cfg_rx_sgmii_en) begin + if (in_pre_reg && encoded_rx_data[15] && !encoded_rx_data[7]) begin + // truncated repetition + rep_stall_reg <= 1'b0; + rep_en_reg <= 1'b1; + rep_sel_reg <= 1'b1; + rep_store_reg <= 1'b0; + case (cfg_rx_sgmii_speed) + 2'b00: rep_cnt_reg <= 48; // 10 Mbps + 2'b01: rep_cnt_reg <= 3; // 100 Mbps + default: begin + rep_cnt_reg <= 0; // 1 Gbps + rep_stall_reg <= 1'b0; + rep_en_reg <= 1'b0; + rep_sel_reg <= 1'b0; + end + endcase + end else if (encoded_rx_data_k != 0) begin + // align to start (control character) + rep_stall_reg <= 1'b1; + rep_en_reg <= 1'b1; + rep_sel_reg <= 1'b0; + rep_store_reg <= 1'b0; + case (cfg_rx_sgmii_speed) + 2'b00: rep_cnt_reg <= 48; // 10 Mbps + 2'b01: rep_cnt_reg <= 3; // 100 Mbps + default: begin + rep_cnt_reg <= 0; // 1 Gbps + rep_stall_reg <= 1'b0; + rep_en_reg <= 1'b0; + rep_sel_reg <= 1'b0; + end + endcase + if (encoded_rx_data_k != 0 && !(encoded_rx_data_k[0] && encoded_rx_data[7:0] == CTRL_S)) begin + // have stored control character that isn't start, skip stall + rep_stall_reg <= 1'b0; + end + end else if (rep_cnt_reg == 0) begin + rep_stall_reg <= rep_sel_reg; + rep_en_reg <= 1'b1; + rep_sel_reg <= !rep_sel_reg; + rep_store_reg <= rep_sel_reg; + case (cfg_rx_sgmii_speed) + 2'b00: rep_cnt_reg <= 49; // 10 Mbps + 2'b01: rep_cnt_reg <= 4; // 100 Mbps + default: begin + rep_cnt_reg <= 0; // 1 Gbps + rep_stall_reg <= 1'b0; + rep_en_reg <= 1'b0; + rep_sel_reg <= 1'b0; + end + endcase + end else begin + rep_cnt_reg <= rep_cnt_reg-1; + rep_stall_reg <= 1'b1; + rep_en_reg <= 1'b1; + rep_store_reg <= 1'b0; + end + end else begin + rep_cnt_reg <= '0; + rep_stall_reg <= 1'b0; + rep_en_reg <= 1'b0; + rep_sel_reg <= 1'b0; + rep_store_reg <= 1'b0; + end end last_ts_reg <= (5+16)'(ptp_ts); @@ -762,6 +930,12 @@ always_ff @(posedge clk) begin an_ack_match_reg <= '0; an_idle_match_reg <= '0; + rep_cnt_reg <= '0; + rep_stall_reg <= 1'b0; + rep_en_reg <= 1'b0; + rep_sel_reg <= 1'b0; + rep_store_reg <= 1'b0; + start_packet_int_reg <= 1'b0; start_packet_reg <= '0; frame_reg <= 1'b0; diff --git a/src/eth/tb/taxi_axis_basex_rx_16/Makefile b/src/eth/tb/taxi_axis_basex_rx_16/Makefile index ddaa093..a350be4 100644 --- a/src/eth/tb/taxi_axis_basex_rx_16/Makefile +++ b/src/eth/tb/taxi_axis_basex_rx_16/Makefile @@ -36,7 +36,8 @@ VERILOG_SOURCES := $(call uniq_base,$(call process_f_files,$(VERILOG_SOURCES))) # module parameters export PARAM_DATA_W := 16 export PARAM_GBX_IF_EN := 0 -export PARAM_AN_EN := 1 +export PARAM_SGMII_EN := 1 +export PARAM_AN_EN := $(PARAM_SGMII_EN) export PARAM_PTP_TS_EN := 1 export PARAM_PTP_TS_FMT_TOD := 1 diff --git a/src/eth/tb/taxi_axis_basex_rx_16/test_taxi_axis_basex_rx_16.py b/src/eth/tb/taxi_axis_basex_rx_16/test_taxi_axis_basex_rx_16.py index c7763f2..c45a293 100644 --- a/src/eth/tb/taxi_axis_basex_rx_16/test_taxi_axis_basex_rx_16.py +++ b/src/eth/tb/taxi_axis_basex_rx_16/test_taxi_axis_basex_rx_16.py @@ -38,7 +38,7 @@ except ImportError: class TB: - def __init__(self, dut, gbx_cfg=None): + def __init__(self, dut, gbx_cfg=None, sgmii_speed=None): self.dut = dut self.log = logging.getLogger("cocotb.tb") @@ -65,6 +65,21 @@ class TB: dut.cfg_rx_max_pkt_len.setimmediatevalue(0) dut.cfg_rx_enable.setimmediatevalue(0) + if sgmii_speed is not None: + dut.cfg_rx_sgmii_en.setimmediatevalue(1) + dut.cfg_rx_sgmii_speed.setimmediatevalue(sgmii_speed) + if sgmii_speed == 0: + self.source.set_gmii_rep_count(99) # 10 Mbps + elif sgmii_speed == 1: + self.source.set_gmii_rep_count(9) # 100 Mbps + elif sgmii_speed == 2: + self.source.set_gmii_rep_count(0) # 1 Gbps + else: + self.source.set_gmii_rep_count(0) + else: + dut.cfg_rx_sgmii_en.setimmediatevalue(0) + dut.cfg_rx_sgmii_speed.setimmediatevalue(0b10) + self.source.set_gmii_rep_count(0) self.stats = {} self.stats["stat_rx_byte"] = 0 @@ -109,9 +124,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, pre_trunc=False): +async def run_test(dut, gbx_cfg=None, sgmii_speed=None, payload_lengths=None, payload_data=None, ifg=12, pre_trunc=False): - tb = TB(dut, gbx_cfg) + tb = TB(dut, gbx_cfg, sgmii_speed) tb.source.ifg = ifg tb.source.truncate_preamble = pre_trunc @@ -176,9 +191,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, sgmii_speed=None, ifg=12): - tb = TB(dut, gbx_cfg) + tb = TB(dut, gbx_cfg, sgmii_speed) tb.source.ifg = ifg tb.dut.cfg_rx_max_pkt_len.value = 1518-1 @@ -265,9 +280,9 @@ async def run_test_oversize(dut, gbx_cfg=None, ifg=12): await RisingEdge(dut.clk) -async def run_test_an(dut, gbx_cfg=None): +async def run_test_an(dut, gbx_cfg=None, sgmii_speed=None): - tb = TB(dut, gbx_cfg) + tb = TB(dut, gbx_cfg, sgmii_speed) await tb.reset() @@ -319,17 +334,20 @@ 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("pre_trunc", [False, True]) + factory.add_option("sgmii_speed", [None, 1, 2]) 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("sgmii_speed", [None, 1, 2]) factory.add_option("gbx_cfg", gbx_cfgs) factory.generate_tests() factory = TestFactory(run_test_an) + factory.add_option("sgmii_speed", [None, 1, 2]) factory.add_option("gbx_cfg", gbx_cfgs) factory.generate_tests() @@ -374,7 +392,8 @@ def test_taxi_axis_basex_rx_16(request, gbx_en): parameters['DATA_W'] = 16 parameters['GBX_IF_EN'] = gbx_en - parameters['AN_EN'] = 1 + parameters['SGMII_EN'] = 1 + parameters['AN_EN'] = parameters['SGMII_EN'] 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_basex_rx_16/test_taxi_axis_basex_rx_16.sv b/src/eth/tb/taxi_axis_basex_rx_16/test_taxi_axis_basex_rx_16.sv index 4477698..28732d5 100644 --- a/src/eth/tb/taxi_axis_basex_rx_16/test_taxi_axis_basex_rx_16.sv +++ b/src/eth/tb/taxi_axis_basex_rx_16/test_taxi_axis_basex_rx_16.sv @@ -21,7 +21,8 @@ module test_taxi_axis_basex_rx_16 # parameter DATA_W = 16, parameter CTRL_W = DATA_W / 8, parameter logic GBX_IF_EN = 1'b0, - parameter logic AN_EN = 1'b1, + parameter logic SGMII_EN = 1'b1, + parameter logic AN_EN = SGMII_EN, 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 @@ -50,6 +51,8 @@ logic [PTP_TS_W-1:0] ptp_ts; logic [15:0] cfg_rx_max_pkt_len; logic cfg_rx_enable; +logic cfg_rx_sgmii_en; +logic [1:0] cfg_rx_sgmii_speed; logic [1:0] rx_start_packet; logic [1:0] stat_rx_byte; @@ -72,6 +75,7 @@ taxi_axis_basex_rx_16 #( .DATA_W(DATA_W), .CTRL_W(CTRL_W), .GBX_IF_EN(GBX_IF_EN), + .SGMII_EN(SGMII_EN), .AN_EN(AN_EN), .PTP_TS_EN(PTP_TS_EN), .PTP_TS_W(PTP_TS_W) @@ -111,6 +115,8 @@ uut ( */ .cfg_rx_max_pkt_len(cfg_rx_max_pkt_len), .cfg_rx_enable(cfg_rx_enable), + .cfg_rx_sgmii_en(cfg_rx_sgmii_en), + .cfg_rx_sgmii_speed(cfg_rx_sgmii_speed), /* * Status