From f37bb1fc8dad8d44afa9a6911da79347641b797f Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Sat, 27 Jan 2024 14:06:32 -0800 Subject: [PATCH] Rework termination character handling in XGMII RX modules Signed-off-by: Alex Forencich --- rtl/axis_xgmii_rx_32.v | 105 ++++++++------------------ rtl/axis_xgmii_rx_64.v | 162 +++++++++++++++-------------------------- 2 files changed, 88 insertions(+), 179 deletions(-) diff --git a/rtl/axis_xgmii_rx_32.v b/rtl/axis_xgmii_rx_32.v index 0241ad56..0c25825a 100644 --- a/rtl/axis_xgmii_rx_32.v +++ b/rtl/axis_xgmii_rx_32.v @@ -111,10 +111,9 @@ reg [1:0] state_reg = STATE_IDLE, state_next; // datapath control signals reg reset_crc; -reg [3:0] last_cycle_tkeep_reg = 4'd0, last_cycle_tkeep_next; - -reg [DATA_WIDTH-1:0] xgmii_rxd_masked = {DATA_WIDTH{1'b0}}; -reg [CTRL_WIDTH-1:0] xgmii_term = {CTRL_WIDTH{1'b0}}; +reg [1:0] term_lane_reg = 0, term_lane_d0_reg = 0; +reg term_present_reg = 1'b0; +reg framing_error_reg = 1'b0; reg [DATA_WIDTH-1:0] xgmii_rxd_d0 = {DATA_WIDTH{1'b0}}; reg [DATA_WIDTH-1:0] xgmii_rxd_d1 = {DATA_WIDTH{1'b0}}; @@ -176,63 +175,11 @@ eth_crc ( .state_out(crc_next) ); -// Mask input data -integer j; - -always @* begin - for (j = 0; j < 4; j = j + 1) begin - xgmii_rxd_masked[j*8 +: 8] = xgmii_rxc[j] ? 8'd0 : xgmii_rxd[j*8 +: 8]; - xgmii_term[j] = xgmii_rxc[j] && (xgmii_rxd[j*8 +: 8] == XGMII_TERM); - end -end - -// detect control characters -reg [3:0] detect_term = 4'd0; - -reg [3:0] detect_term_save; - -integer i; - -// mask errors to within packet -reg [3:0] control_masked; -reg [3:0] tkeep_mask; - -always @* begin - casez (detect_term) - 4'b0000: begin - control_masked = xgmii_rxc_d0; - tkeep_mask = 4'b1111; - end - 4'bzzz1: begin - control_masked = 0; - tkeep_mask = 4'b0000; - end - 4'bzz10: begin - control_masked = xgmii_rxc_d0[0]; - tkeep_mask = 4'b0001; - end - 4'bz100: begin - control_masked = xgmii_rxc_d0[1:0]; - tkeep_mask = 4'b0011; - end - 4'b1000: begin - control_masked = xgmii_rxc_d0[2:0]; - tkeep_mask = 4'b0111; - end - default: begin - control_masked = xgmii_rxc_d0; - tkeep_mask = 4'b1111; - end - endcase -end - always @* begin state_next = STATE_IDLE; reset_crc = 1'b0; - last_cycle_tkeep_next = last_cycle_tkeep_reg; - m_axis_tdata_next = {DATA_WIDTH{1'b0}}; m_axis_tkeep_next = {KEEP_WIDTH{1'b1}}; m_axis_tvalid_next = 1'b0; @@ -251,7 +198,7 @@ always @* begin if (xgmii_start_d2 && cfg_rx_enable) begin // start condition - if (control_masked) begin + if (framing_error_reg) begin // control or error characters in first data word m_axis_tdata_next = {DATA_WIDTH{1'b0}}; m_axis_tkeep_next = 4'h1; @@ -284,25 +231,20 @@ always @* begin m_axis_tlast_next = 1'b0; m_axis_tuser_next[0] = 1'b0; - last_cycle_tkeep_next = tkeep_mask; - - if (detect_term) begin - reset_crc = 1'b1; - end - - if (control_masked) begin + if (framing_error_reg) begin // control or error characters in packet m_axis_tlast_next = 1'b1; m_axis_tuser_next[0] = 1'b1; error_bad_frame_next = 1'b1; reset_crc = 1'b1; state_next = STATE_IDLE; - end else if (detect_term) begin - if (detect_term[0]) begin + end else if (term_present_reg) begin + reset_crc = 1'b1; + if (term_lane_reg == 0) begin // end this cycle m_axis_tkeep_next = 4'b1111; m_axis_tlast_next = 1'b1; - if (detect_term[0] && crc_valid_save[3]) begin + if (term_lane_reg == 0 && crc_valid_save[3]) begin // CRC valid end else begin m_axis_tuser_next[0] = 1'b1; @@ -321,16 +263,16 @@ always @* begin STATE_LAST: begin // last cycle of packet m_axis_tdata_next = xgmii_rxd_d2; - m_axis_tkeep_next = last_cycle_tkeep_reg; + m_axis_tkeep_next = {KEEP_WIDTH{1'b1}} >> (CTRL_WIDTH-term_lane_d0_reg); m_axis_tvalid_next = 1'b1; m_axis_tlast_next = 1'b1; m_axis_tuser_next[0] = 1'b0; reset_crc = 1'b1; - if ((detect_term_save[1] && crc_valid_save[0]) || - (detect_term_save[2] && crc_valid_save[1]) || - (detect_term_save[3] && crc_valid_save[2])) begin + if ((term_lane_d0_reg == 1 && crc_valid_save[0]) || + (term_lane_d0_reg == 2 && crc_valid_save[1]) || + (term_lane_d0_reg == 3 && crc_valid_save[2])) begin // CRC valid end else begin m_axis_tuser_next[0] = 1'b1; @@ -343,6 +285,8 @@ always @* begin endcase end +integer i; + always @(posedge clk) begin state_reg <= state_next; @@ -356,10 +300,19 @@ always @(posedge clk) begin error_bad_frame_reg <= error_bad_frame_next; error_bad_fcs_reg <= error_bad_fcs_next; - last_cycle_tkeep_reg <= last_cycle_tkeep_next; + term_lane_reg <= 0; + term_present_reg <= 1'b0; + framing_error_reg <= xgmii_rxc != 0; - detect_term <= xgmii_term; - detect_term_save <= detect_term; + for (i = CTRL_WIDTH-1; i >= 0; i = i - 1) begin + if (xgmii_rxc[i] && (xgmii_rxd[i*8 +: 8] == XGMII_TERM)) begin + term_lane_reg <= i; + term_present_reg <= 1'b1; + framing_error_reg <= (xgmii_rxc & ({CTRL_WIDTH{1'b1}} >> (CTRL_WIDTH-i))) != 0; + end + end + + term_lane_d0_reg <= term_lane_reg; if (reset_crc) begin crc_state <= 32'hFFFFFFFF; @@ -369,7 +322,9 @@ always @(posedge clk) begin crc_valid_save <= crc_valid; - xgmii_rxd_d0 <= xgmii_rxd_masked; + for (i = 0; i < CTRL_WIDTH; i = i + 1) begin + xgmii_rxd_d0[i*8 +: 8] <= xgmii_rxc[i] ? 8'd0 : xgmii_rxd[i*8 +: 8]; + end xgmii_rxc_d0 <= xgmii_rxc; xgmii_rxd_d1 <= xgmii_rxd_d0; xgmii_rxd_d2 <= xgmii_rxd_d1; diff --git a/rtl/axis_xgmii_rx_64.v b/rtl/axis_xgmii_rx_64.v index 32856b36..c8832690 100644 --- a/rtl/axis_xgmii_rx_64.v +++ b/rtl/axis_xgmii_rx_64.v @@ -112,8 +112,6 @@ reg [1:0] state_reg = STATE_IDLE, state_next; // datapath control signals reg reset_crc; -reg [7:0] last_cycle_tkeep_reg = 8'd0, last_cycle_tkeep_next; - reg lanes_swapped = 1'b0; reg [31:0] swap_rxd = 32'd0; reg [3:0] swap_rxc = 4'd0; @@ -121,6 +119,9 @@ reg [3:0] swap_rxc_term = 4'd0; reg [DATA_WIDTH-1:0] xgmii_rxd_masked = {DATA_WIDTH{1'b0}}; reg [CTRL_WIDTH-1:0] xgmii_term = {CTRL_WIDTH{1'b0}}; +reg [2:0] term_lane_reg = 0, term_lane_d0_reg = 0; +reg term_present_reg = 1'b0; +reg framing_error_reg = 1'b0; reg [DATA_WIDTH-1:0] xgmii_rxd_d0 = {DATA_WIDTH{1'b0}}; reg [DATA_WIDTH-1:0] xgmii_rxd_d1 = {DATA_WIDTH{1'b0}}; @@ -197,69 +198,11 @@ always @* begin end end -// detect control characters -reg [7:0] detect_term = 8'd0; - -reg [7:0] detect_term_save = 8'd0; - -integer i; - -// mask errors to within packet -reg [7:0] control_masked; -reg [7:0] tkeep_mask; - -always @* begin - casez (detect_term) - 8'b00000000: begin - control_masked = xgmii_rxc_d0; - tkeep_mask = 8'b11111111; - end - 8'bzzzzzzz1: begin - control_masked = 0; - tkeep_mask = 8'b00000000; - end - 8'bzzzzzz10: begin - control_masked = xgmii_rxc_d0[0]; - tkeep_mask = 8'b00000001; - end - 8'bzzzzz100: begin - control_masked = xgmii_rxc_d0[1:0]; - tkeep_mask = 8'b00000011; - end - 8'bzzzz1000: begin - control_masked = xgmii_rxc_d0[2:0]; - tkeep_mask = 8'b00000111; - end - 8'bzzz10000: begin - control_masked = xgmii_rxc_d0[3:0]; - tkeep_mask = 8'b00001111; - end - 8'bzz100000: begin - control_masked = xgmii_rxc_d0[4:0]; - tkeep_mask = 8'b00011111; - end - 8'bz1000000: begin - control_masked = xgmii_rxc_d0[5:0]; - tkeep_mask = 8'b00111111; - end - 8'b10000000: begin - control_masked = xgmii_rxc_d0[6:0]; - tkeep_mask = 8'b01111111; - end - default: begin - control_masked = xgmii_rxc_d0; - tkeep_mask = 8'b11111111; - end - endcase -end - always @* begin state_next = STATE_IDLE; reset_crc = 1'b0; - last_cycle_tkeep_next = last_cycle_tkeep_reg; - m_axis_tdata_next = {DATA_WIDTH{1'b0}}; m_axis_tkeep_next = {KEEP_WIDTH{1'b1}}; m_axis_tvalid_next = 1'b0; @@ -282,7 +225,7 @@ always @* begin m_axis_tuser_next[1 +: PTP_TS_WIDTH] = (PTP_TS_WIDTH != 96 || ptp_ts_borrow_reg) ? ptp_ts_reg : ptp_ts_adj_reg; end - if (control_masked) begin + if (framing_error_reg) begin // control or error characters in first data word m_axis_tdata_next = {DATA_WIDTH{1'b0}}; m_axis_tkeep_next = 8'h01; @@ -307,29 +250,24 @@ always @* begin m_axis_tlast_next = 1'b0; m_axis_tuser_next[0] = 1'b0; - last_cycle_tkeep_next = {4'b0000, tkeep_mask[7:4]}; - - if (detect_term) begin - reset_crc = 1'b1; - end - - if (control_masked) begin + if (framing_error_reg) begin // control or error characters in packet m_axis_tlast_next = 1'b1; m_axis_tuser_next[0] = 1'b1; error_bad_frame_next = 1'b1; reset_crc = 1'b1; state_next = STATE_IDLE; - end else if (detect_term) begin - if (detect_term[4:0]) begin + end else if (term_present_reg) begin + reset_crc = 1'b1; + if (term_lane_reg <= 4) begin // end this cycle - m_axis_tkeep_next = {tkeep_mask[3:0], 4'b1111}; + m_axis_tkeep_next = {KEEP_WIDTH{1'b1}} >> (CTRL_WIDTH-4-term_lane_reg); m_axis_tlast_next = 1'b1; - if ((detect_term[0] && crc_valid_save[7]) || - (detect_term[1] && crc_valid[0]) || - (detect_term[2] && crc_valid[1]) || - (detect_term[3] && crc_valid[2]) || - (detect_term[4] && crc_valid[3])) begin + if ((term_lane_reg == 0 && crc_valid_save[7]) || + (term_lane_reg == 1 && crc_valid[0]) || + (term_lane_reg == 2 && crc_valid[1]) || + (term_lane_reg == 3 && crc_valid[2]) || + (term_lane_reg == 4 && crc_valid[3])) begin // CRC valid end else begin m_axis_tuser_next[0] = 1'b1; @@ -348,16 +286,16 @@ always @* begin STATE_LAST: begin // last cycle of packet m_axis_tdata_next = xgmii_rxd_d1; - m_axis_tkeep_next = last_cycle_tkeep_reg; + m_axis_tkeep_next = {KEEP_WIDTH{1'b1}} >> (CTRL_WIDTH+4-term_lane_d0_reg); m_axis_tvalid_next = 1'b1; m_axis_tlast_next = 1'b1; m_axis_tuser_next[0] = 1'b0; reset_crc = 1'b1; - if ((detect_term_save[5] && crc_valid_save[4]) || - (detect_term_save[6] && crc_valid_save[5]) || - (detect_term_save[7] && crc_valid_save[6])) begin + if ((term_lane_d0_reg == 5 && crc_valid_save[4]) || + (term_lane_d0_reg == 6 && crc_valid_save[5]) || + (term_lane_d0_reg == 7 && crc_valid_save[6])) begin // CRC valid end else begin m_axis_tuser_next[0] = 1'b1; @@ -367,7 +305,7 @@ always @* begin if (xgmii_start_d1) begin // start condition - if (control_masked) begin + if (framing_error_reg) begin // control or error characters in first data word m_axis_tdata_next = {DATA_WIDTH{1'b0}}; m_axis_tkeep_next = 8'h01; @@ -387,6 +325,8 @@ always @* begin endcase end +integer i; + always @(posedge clk) begin state_reg <= state_next; @@ -400,10 +340,6 @@ always @(posedge clk) begin error_bad_frame_reg <= error_bad_frame_next; error_bad_fcs_reg <= error_bad_fcs_next; - last_cycle_tkeep_reg <= last_cycle_tkeep_next; - - detect_term_save <= detect_term; - swap_rxd <= xgmii_rxd_masked[63:32]; swap_rxc <= xgmii_rxc[7:4]; swap_rxc_term <= xgmii_term[7:4]; @@ -419,15 +355,47 @@ always @(posedge clk) begin ptp_ts_adj_reg[95:48] <= ptp_ts_reg[95:48] + 1; end - if (xgmii_rxc[0] && xgmii_rxd[7:0] == XGMII_START) begin - lanes_swapped <= 1'b0; - start_packet_reg <= 2'b01; + if (lanes_swapped) begin + xgmii_rxd_d0 <= {xgmii_rxd_masked[31:0], swap_rxd}; + xgmii_rxc_d0 <= {xgmii_rxc[3:0], swap_rxc}; + + term_lane_reg <= 0; + term_present_reg <= 1'b0; + framing_error_reg <= {xgmii_rxc[3:0], swap_rxc} != 0; + + for (i = CTRL_WIDTH-1; i >= 0; i = i - 1) begin + if ({xgmii_term[3:0], swap_rxc_term} & (1 << i)) begin + term_lane_reg <= i; + term_present_reg <= 1'b1; + framing_error_reg <= ({xgmii_rxc[3:0], swap_rxc} & ({CTRL_WIDTH{1'b1}} >> (CTRL_WIDTH-i))) != 0; + lanes_swapped <= 1'b0; + end + end + end else begin xgmii_rxd_d0 <= xgmii_rxd_masked; xgmii_rxc_d0 <= xgmii_rxc; + term_lane_reg <= 0; + term_present_reg <= 1'b0; + framing_error_reg <= xgmii_rxc != 0; + + for (i = CTRL_WIDTH-1; i >= 0; i = i - 1) begin + if (xgmii_rxc[i] && (xgmii_rxd[i*8 +: 8] == XGMII_TERM)) begin + term_lane_reg <= i; + term_present_reg <= 1'b1; + framing_error_reg <= (xgmii_rxc & ({CTRL_WIDTH{1'b1}} >> (CTRL_WIDTH-i))) != 0; + lanes_swapped <= 1'b0; + end + end + end + + term_lane_d0_reg <= term_lane_reg; + + if (xgmii_rxc[0] && xgmii_rxd[7:0] == XGMII_START) begin + lanes_swapped <= 1'b0; + start_packet_reg <= 2'b01; + xgmii_start_d0 <= 1'b1; - - detect_term <= xgmii_term; if (PTP_TS_WIDTH == 96) begin ptp_ts_reg[45:0] <= ptp_ts[45:0] + (PTP_PERIOD_NS * 2**16 + PTP_PERIOD_FNS); @@ -438,29 +406,15 @@ always @(posedge clk) begin end else if (xgmii_rxc[4] && xgmii_rxd[39:32] == XGMII_START) begin lanes_swapped <= 1'b1; start_packet_reg <= 2'b10; - xgmii_rxd_d0 <= {xgmii_rxd_masked[31:0], swap_rxd}; - xgmii_rxc_d0 <= {xgmii_rxc[3:0], swap_rxc}; xgmii_start_swap <= 1'b1; - detect_term <= {xgmii_term[3:0], swap_rxc_term}; - if (PTP_TS_WIDTH == 96) begin ptp_ts_reg[45:0] <= ptp_ts[45:0] + (((PTP_PERIOD_NS * 2**16 + PTP_PERIOD_FNS) * 3) >> 1); ptp_ts_reg[95:48] <= ptp_ts[95:48]; end else begin ptp_ts_reg <= ptp_ts + (((PTP_PERIOD_NS * 2**16 + PTP_PERIOD_FNS) * 3) >> 1); end - end else if (lanes_swapped) begin - xgmii_rxd_d0 <= {xgmii_rxd_masked[31:0], swap_rxd}; - xgmii_rxc_d0 <= {xgmii_rxc[3:0], swap_rxc}; - - detect_term <= {xgmii_term[3:0], swap_rxc_term}; - end else begin - xgmii_rxd_d0 <= xgmii_rxd_masked; - xgmii_rxc_d0 <= xgmii_rxc; - - detect_term <= xgmii_term; end if (reset_crc) begin