diff --git a/rtl/axis_baser_tx_64.v b/rtl/axis_baser_tx_64.v index dce320d7..1dcae600 100644 --- a/rtl/axis_baser_tx_64.v +++ b/rtl/axis_baser_tx_64.v @@ -171,8 +171,8 @@ localparam [2:0] STATE_PAD = 3'd2, STATE_FCS_1 = 3'd3, STATE_FCS_2 = 3'd4, - STATE_IFG = 3'd5, - STATE_WAIT_END = 3'd6; + STATE_ERR = 3'd5, + STATE_IFG = 3'd6; reg [2:0] state_reg = STATE_IDLE, state_next; @@ -198,6 +198,8 @@ reg [3:0] fcs_output_type_1; reg [7:0] ifg_offset; +reg frame_reg = 1'b0, frame_next; +reg frame_error_reg = 1'b0, frame_error_next; reg [MIN_LEN_WIDTH-1:0] frame_min_count_reg = 0, frame_min_count_next; reg [7:0] ifg_count_reg = 8'd0, ifg_count_next; @@ -353,6 +355,8 @@ always @* begin swap_lanes_next = swap_lanes_reg; + frame_next = frame_reg; + frame_error_next = frame_error_reg; frame_min_count_next = frame_min_count_reg; ifg_count_next = ifg_count_reg; @@ -376,6 +380,10 @@ always @* begin start_packet_next = 2'b00; error_underflow_next = 1'b0; + if (s_axis_tvalid && s_axis_tready) begin + frame_next = !s_axis_tlast; + end + if (PTP_TS_ENABLE && PTP_TS_WIDTH == 96) begin m_axis_ptp_ts_valid_next = m_axis_ptp_ts_valid_int_reg; m_axis_ptp_ts_adj_next[15:0] = m_axis_ptp_ts_reg[15:0]; @@ -387,6 +395,7 @@ always @* begin case (state_reg) STATE_IDLE: begin // idle state - wait for data + frame_error_next = 1'b0; frame_min_count_next = MIN_FRAME_LENGTH-4-KEEP_WIDTH; reset_crc = 1'b1; s_axis_tready_next = 1'b1; @@ -467,44 +476,39 @@ always @* begin s_tdata_next = s_axis_tdata_masked; s_empty_next = keep2empty(s_axis_tkeep); - if (s_axis_tvalid) begin - if (s_axis_tlast) begin - s_axis_tready_next = 1'b0; - if (s_axis_tuser[0]) begin - output_type_next = OUTPUT_TYPE_ERROR; - ifg_count_next = 8'd8; - state_next = STATE_IFG; + if (!s_axis_tvalid || s_axis_tlast) begin + s_axis_tready_next = frame_next; // drop frame + frame_error_next = !s_axis_tvalid || s_axis_tuser[0]; + error_underflow_next = !s_axis_tvalid; + + if (ENABLE_PADDING && frame_min_count_reg) begin + if (frame_min_count_reg > KEEP_WIDTH) begin + s_empty_next = 0; + state_next = STATE_PAD; end else begin - s_axis_tready_next = 1'b0; - - if (ENABLE_PADDING && frame_min_count_reg) begin - if (frame_min_count_reg > KEEP_WIDTH) begin - s_empty_next = 0; - state_next = STATE_PAD; - end else begin - if (keep2empty(s_axis_tkeep) > KEEP_WIDTH-frame_min_count_reg) begin - s_empty_next = KEEP_WIDTH-frame_min_count_reg; - end - state_next = STATE_FCS_1; - end + if (keep2empty(s_axis_tkeep) > KEEP_WIDTH-frame_min_count_reg) begin + s_empty_next = KEEP_WIDTH-frame_min_count_reg; + end + if (frame_error_next) begin + state_next = STATE_ERR; end else begin state_next = STATE_FCS_1; end end end else begin - state_next = STATE_PAYLOAD; + if (frame_error_next) begin + state_next = STATE_ERR; + end else begin + state_next = STATE_FCS_1; + end end end else begin - // tvalid deassert, fail frame - output_type_next = OUTPUT_TYPE_ERROR; - ifg_count_next = 8'd8; - error_underflow_next = 1'b1; - state_next = STATE_WAIT_END; + state_next = STATE_PAYLOAD; end end STATE_PAD: begin // pad frame to MIN_FRAME_LENGTH - s_axis_tready_next = 1'b0; + s_axis_tready_next = frame_next; // drop frame output_data_next = s_tdata_reg; output_type_next = OUTPUT_TYPE_DATA; @@ -520,12 +524,16 @@ always @* begin end else begin frame_min_count_next = 0; s_empty_next = KEEP_WIDTH-frame_min_count_reg; - state_next = STATE_FCS_1; + if (frame_error_reg) begin + state_next = STATE_ERR; + end else begin + state_next = STATE_FCS_1; + end end end STATE_FCS_1: begin // last cycle - s_axis_tready_next = 1'b0; + s_axis_tready_next = frame_next; // drop frame output_data_next = fcs_output_data_0; output_type_next = fcs_output_type_0; @@ -541,7 +549,7 @@ always @* begin end STATE_FCS_2: begin // last cycle - s_axis_tready_next = 1'b0; + s_axis_tready_next = frame_next; // drop frame output_data_next = fcs_output_data_1; output_type_next = fcs_output_type_1; @@ -573,8 +581,24 @@ always @* begin end end end + STATE_ERR: begin + // terminate packet with error + s_axis_tready_next = frame_next; // drop frame + + output_data_next = s_tdata_reg; + output_type_next = OUTPUT_TYPE_ERROR; + + ifg_count_next = 8'd12; + + state_next = STATE_IFG; + end STATE_IFG: begin // send IFG + s_axis_tready_next = frame_next; // drop frame + + output_data_next = s_tdata_reg; + output_type_next = OUTPUT_TYPE_IDLE; + if (ifg_count_reg > 8'd8) begin ifg_count_next = ifg_count_reg - 8'd8; end else begin @@ -584,7 +608,7 @@ always @* begin reset_crc = 1'b1; if (ENABLE_DIC) begin - if (ifg_count_next > 8'd7) begin + if (ifg_count_next > 8'd7 || frame_reg) begin state_next = STATE_IFG; end else begin if (ifg_count_next >= 8'd4) begin @@ -599,7 +623,7 @@ always @* begin state_next = STATE_IDLE; end end else begin - if (ifg_count_next > 8'd4) begin + if (ifg_count_next > 8'd4 || frame_reg) begin state_next = STATE_IFG; end else begin s_axis_tready_next = 1'b1; @@ -608,53 +632,6 @@ always @* begin end end end - STATE_WAIT_END: begin - // wait for end of frame - s_axis_tready_next = 1'b1; - - if (ifg_count_reg > 8'd4) begin - ifg_count_next = ifg_count_reg - 8'd4; - end else begin - ifg_count_next = 8'd0; - end - - reset_crc = 1'b1; - - if (s_axis_tvalid) begin - if (s_axis_tlast) begin - s_axis_tready_next = 1'b0; - - if (ENABLE_DIC) begin - if (ifg_count_next > 8'd7) begin - state_next = STATE_IFG; - end else begin - if (ifg_count_next >= 8'd4) begin - deficit_idle_count_next = ifg_count_next - 8'd4; - swap_lanes_next = 1'b1; - end else begin - deficit_idle_count_next = ifg_count_next; - ifg_count_next = 8'd0; - swap_lanes_next = 1'b0; - end - s_axis_tready_next = 1'b1; - state_next = STATE_IDLE; - end - end else begin - if (ifg_count_next > 8'd4) begin - state_next = STATE_IFG; - end else begin - s_axis_tready_next = 1'b1; - swap_lanes_next = ifg_count_next != 0; - state_next = STATE_IDLE; - end - end - end else begin - state_next = STATE_WAIT_END; - end - end else begin - state_next = STATE_WAIT_END; - end - end endcase end @@ -663,6 +640,8 @@ always @(posedge clk) begin swap_lanes_reg <= swap_lanes_next; + frame_reg <= frame_next; + frame_error_reg <= frame_error_next; frame_min_count_reg <= frame_min_count_next; ifg_count_reg <= ifg_count_next; @@ -788,6 +767,8 @@ always @(posedge clk) begin if (rst) begin state_reg <= STATE_IDLE; + frame_reg <= 1'b0; + swap_lanes_reg <= 1'b0; ifg_count_reg <= 8'd0; diff --git a/rtl/axis_gmii_tx.v b/rtl/axis_gmii_tx.v index 1f945f60..11047187 100644 --- a/rtl/axis_gmii_tx.v +++ b/rtl/axis_gmii_tx.v @@ -111,8 +111,7 @@ localparam [2:0] STATE_LAST = 3'd3, STATE_PAD = 3'd4, STATE_FCS = 3'd5, - STATE_WAIT_END = 3'd6, - STATE_IFG = 3'd7; + STATE_IFG = 3'd6; reg [2:0] state_reg = STATE_IDLE, state_next; @@ -125,6 +124,8 @@ reg [7:0] s_tdata_reg = 8'd0, s_tdata_next; reg mii_odd_reg = 1'b0, mii_odd_next; reg [3:0] mii_msn_reg = 4'b0, mii_msn_next; +reg frame_reg = 1'b0, frame_next; +reg frame_error_reg = 1'b0, frame_error_next; reg [7:0] frame_ptr_reg = 0, frame_ptr_next; reg [MIN_LEN_WIDTH-1:0] frame_min_count_reg = 0, frame_min_count_next; @@ -183,6 +184,8 @@ always @* begin mii_odd_next = mii_odd_reg; mii_msn_next = mii_msn_reg; + frame_next = frame_reg; + frame_error_next = frame_error_reg; frame_ptr_next = frame_ptr_reg; frame_min_count_next = frame_min_count_reg; @@ -194,10 +197,6 @@ always @* begin m_axis_ptp_ts_tag_next = m_axis_ptp_ts_tag_reg; m_axis_ptp_ts_valid_next = 1'b0; - gmii_txd_next = {DATA_WIDTH{1'b0}}; - gmii_tx_en_next = 1'b0; - gmii_tx_er_next = 1'b0; - if (start_packet_reg && PTP_TS_ENABLE) begin m_axis_ptp_ts_next = ptp_ts; if (PTP_TS_CTRL_IN_TUSER) begin @@ -209,10 +208,18 @@ always @* begin end end + gmii_txd_next = {DATA_WIDTH{1'b0}}; + gmii_tx_en_next = 1'b0; + gmii_tx_er_next = 1'b0; + start_packet_int_next = start_packet_int_reg; start_packet_next = 1'b0; error_underflow_next = 1'b0; + if (s_axis_tvalid && s_axis_tready) begin + frame_next = !s_axis_tlast; + end + if (!clk_enable) begin // clock disabled - hold state and outputs gmii_txd_next = gmii_txd_reg; @@ -239,6 +246,7 @@ always @* begin mii_odd_next = 1'b0; frame_ptr_next = 1; + frame_error_next = 1'b0; frame_min_count_next = MIN_FRAME_LENGTH-4-1; if (s_axis_tvalid && cfg_tx_enable) begin @@ -299,29 +307,21 @@ always @* begin s_tdata_next = s_axis_tdata; - if (s_axis_tvalid) begin - if (s_axis_tlast) begin - s_axis_tready_next = !s_axis_tready_reg; - if (s_axis_tuser[0]) begin - gmii_tx_er_next = 1'b1; - state_next = STATE_IFG; - end else begin - state_next = STATE_LAST; - end - end else begin - state_next = STATE_PAYLOAD; - end + if (!s_axis_tvalid || s_axis_tlast) begin + s_axis_tready_next = frame_next; // drop frame + frame_error_next = !s_axis_tvalid || s_axis_tuser[0]; + error_underflow_next = !s_axis_tvalid; + + state_next = STATE_LAST; end else begin - // tvalid deassert, fail frame - gmii_tx_er_next = 1'b1; - error_underflow_next = 1'b1; - state_next = STATE_WAIT_END; + state_next = STATE_PAYLOAD; end end STATE_LAST: begin // last payload word update_crc = 1'b1; + s_axis_tready_next = 1'b0; mii_odd_next = 1'b1; @@ -339,6 +339,7 @@ always @* begin end STATE_PAD: begin // send padding + s_axis_tready_next = frame_next; // drop frame update_crc = 1'b1; mii_odd_next = 1'b1; @@ -358,6 +359,7 @@ always @* begin end STATE_FCS: begin // send FCS + s_axis_tready_next = frame_next; // drop frame mii_odd_next = 1'b1; frame_ptr_next = frame_ptr_reg + 1; @@ -369,6 +371,7 @@ always @* begin 2'd3: gmii_txd_next = ~crc_state[31:24]; endcase gmii_tx_en_next = 1'b1; + gmii_tx_er_next = frame_error_reg; if (frame_ptr_reg < 3) begin state_next = STATE_FCS; @@ -377,35 +380,14 @@ always @* begin state_next = STATE_IFG; end end - STATE_WAIT_END: begin - // wait for end of frame - - mii_odd_next = 1'b1; - frame_ptr_next = frame_ptr_reg + 1; - s_axis_tready_next = 1'b1; - - if (s_axis_tvalid) begin - if (s_axis_tlast) begin - s_axis_tready_next = !s_axis_tready_reg; - if (frame_ptr_reg < cfg_ifg-1) begin - state_next = STATE_IFG; - end else begin - state_next = STATE_IDLE; - end - end else begin - state_next = STATE_WAIT_END; - end - end else begin - state_next = STATE_WAIT_END; - end - end STATE_IFG: begin // send IFG + s_axis_tready_next = frame_next; // drop frame mii_odd_next = 1'b1; frame_ptr_next = frame_ptr_reg + 1; - if (frame_ptr_reg < cfg_ifg-1) begin + if (frame_ptr_reg < cfg_ifg-1 || frame_reg) begin state_next = STATE_IFG; end else begin state_next = STATE_IDLE; @@ -423,6 +405,8 @@ end always @(posedge clk) begin state_reg <= state_next; + frame_reg <= frame_next; + frame_error_reg <= frame_error_next; frame_ptr_reg <= frame_ptr_next; frame_min_count_reg <= frame_min_count_next; @@ -454,6 +438,8 @@ always @(posedge clk) begin if (rst) begin state_reg <= STATE_IDLE; + frame_reg <= 1'b0; + s_axis_tready_reg <= 1'b0; m_axis_ptp_ts_valid_reg <= 1'b0; diff --git a/rtl/axis_xgmii_tx_32.v b/rtl/axis_xgmii_tx_32.v index 096248a4..b147f5a3 100644 --- a/rtl/axis_xgmii_tx_32.v +++ b/rtl/axis_xgmii_tx_32.v @@ -121,8 +121,8 @@ localparam [3:0] STATE_FCS_1 = 4'd4, STATE_FCS_2 = 4'd5, STATE_FCS_3 = 4'd6, - STATE_IFG = 4'd7, - STATE_WAIT_END = 4'd8; + STATE_ERR = 4'd7, + STATE_IFG = 4'd8; reg [3:0] state_reg = STATE_IDLE, state_next; @@ -144,6 +144,8 @@ reg [7:0] ifg_offset; reg extra_cycle; +reg frame_reg = 1'b0, frame_next; +reg frame_error_reg = 1'b0, frame_error_next; reg [MIN_LEN_WIDTH-1:0] frame_min_count_reg = 0, frame_min_count_next; reg [7:0] ifg_count_reg = 8'd0, ifg_count_next; @@ -263,6 +265,8 @@ always @* begin reset_crc = 1'b0; update_crc = 1'b0; + frame_next = frame_reg; + frame_error_next = frame_error_reg; frame_min_count_next = frame_min_count_reg; ifg_count_next = ifg_count_reg; @@ -295,9 +299,14 @@ always @* begin start_packet_next = 1'b0; error_underflow_next = 1'b0; + if (s_axis_tvalid && s_axis_tready) begin + frame_next = !s_axis_tlast; + end + case (state_reg) STATE_IDLE: begin // idle state - wait for data + frame_error_next = 1'b0; frame_min_count_next = MIN_FRAME_LENGTH-4-CTRL_WIDTH; reset_crc = 1'b1; @@ -351,46 +360,31 @@ always @* begin s_tdata_next = s_axis_tdata_masked; s_empty_next = keep2empty(s_axis_tkeep); - if (s_axis_tvalid) begin - if (s_axis_tlast) begin - s_axis_tready_next = 1'b0; - if (s_axis_tuser[0]) begin - xgmii_txd_next = {XGMII_TERM, {3{XGMII_ERROR}}}; - xgmii_txc_next = {CTRL_WIDTH{1'b1}}; - ifg_count_next = 8'd10; - state_next = STATE_IFG; + if (!s_axis_tvalid || s_axis_tlast) begin + s_axis_tready_next = frame_next; // drop frame + frame_error_next = !s_axis_tvalid || s_axis_tuser[0]; + error_underflow_next = !s_axis_tvalid; + + if (ENABLE_PADDING && frame_min_count_reg) begin + if (frame_min_count_reg > CTRL_WIDTH) begin + s_empty_next = 0; + state_next = STATE_PAD; end else begin - s_axis_tready_next = 1'b0; - - if (ENABLE_PADDING && frame_min_count_reg) begin - if (frame_min_count_reg > CTRL_WIDTH) begin - s_empty_next = 0; - state_next = STATE_PAD; - end else begin - if (keep2empty(s_axis_tkeep) > CTRL_WIDTH-frame_min_count_reg) begin - s_empty_next = CTRL_WIDTH-frame_min_count_reg; - end - state_next = STATE_FCS_1; - end - end else begin - state_next = STATE_FCS_1; + if (keep2empty(s_axis_tkeep) > CTRL_WIDTH-frame_min_count_reg) begin + s_empty_next = CTRL_WIDTH-frame_min_count_reg; end + state_next = STATE_FCS_1; end end else begin - state_next = STATE_PAYLOAD; + state_next = STATE_FCS_1; end end else begin - // tvalid deassert, fail frame - xgmii_txd_next = {XGMII_TERM, {3{XGMII_ERROR}}}; - xgmii_txc_next = {CTRL_WIDTH{1'b1}}; - ifg_count_next = 8'd10; - error_underflow_next = 1'b1; - state_next = STATE_WAIT_END; + state_next = STATE_PAYLOAD; end end STATE_PAD: begin // pad frame to MIN_FRAME_LENGTH - s_axis_tready_next = 1'b0; + s_axis_tready_next = frame_next; // drop frame xgmii_txd_next = s_tdata_reg; xgmii_txc_next = {CTRL_WIDTH{1'b0}}; @@ -411,7 +405,7 @@ always @* begin end STATE_FCS_1: begin // last cycle - s_axis_tready_next = 1'b0; + s_axis_tready_next = frame_next; // drop frame xgmii_txd_next = fcs_output_txd_0; xgmii_txc_next = fcs_output_txc_0; @@ -419,11 +413,15 @@ always @* begin update_crc = 1'b1; ifg_count_next = (cfg_ifg > 8'd12 ? cfg_ifg : 8'd12) - ifg_offset + deficit_idle_count_reg; - state_next = STATE_FCS_2; + if (frame_error_reg) begin + state_next = STATE_ERR; + end else begin + state_next = STATE_FCS_2; + end end STATE_FCS_2: begin // last cycle - s_axis_tready_next = 1'b0; + s_axis_tready_next = frame_next; // drop frame xgmii_txd_next = fcs_output_txd_1; xgmii_txc_next = fcs_output_txc_1; @@ -436,7 +434,7 @@ always @* begin end STATE_FCS_3: begin // last cycle - s_axis_tready_next = 1'b0; + s_axis_tready_next = frame_next; // drop frame xgmii_txd_next = {{3{XGMII_IDLE}}, XGMII_TERM}; xgmii_txc_next = {CTRL_WIDTH{1'b1}}; @@ -458,8 +456,21 @@ always @* begin end end end + STATE_ERR: begin + // terminate packet with error + s_axis_tready_next = frame_next; // drop frame + + // XGMII error + xgmii_txd_next = {XGMII_TERM, {3{XGMII_ERROR}}}; + xgmii_txc_next = {CTRL_WIDTH{1'b1}}; + + ifg_count_next = 8'd12; + + state_next = STATE_IFG; + end STATE_IFG: begin // send IFG + s_axis_tready_next = frame_next; // drop frame // XGMII idle xgmii_txd_next = {CTRL_WIDTH{XGMII_IDLE}}; @@ -472,7 +483,7 @@ always @* begin end if (ENABLE_DIC) begin - if (ifg_count_next > 8'd3) begin + if (ifg_count_next > 8'd3 || frame_reg) begin state_next = STATE_IFG; end else begin deficit_idle_count_next = ifg_count_next; @@ -480,59 +491,21 @@ always @* begin state_next = STATE_IDLE; end end else begin - if (ifg_count_next > 8'd0) begin + if (ifg_count_next > 8'd0 || frame_reg) begin state_next = STATE_IFG; end else begin state_next = STATE_IDLE; end end end - STATE_WAIT_END: begin - // wait for end of frame - s_axis_tready_next = 1'b1; - - // XGMII idle - xgmii_txd_next = {CTRL_WIDTH{XGMII_IDLE}}; - xgmii_txc_next = {CTRL_WIDTH{1'b1}}; - - if (ifg_count_reg > 8'd4) begin - ifg_count_next = ifg_count_reg - 8'd4; - end else begin - ifg_count_next = 8'd0; - end - - if (s_axis_tvalid) begin - if (s_axis_tlast) begin - s_axis_tready_next = 1'b0; - - if (ENABLE_DIC) begin - if (ifg_count_next > 8'd3) begin - state_next = STATE_IFG; - end else begin - deficit_idle_count_next = ifg_count_next; - ifg_count_next = 8'd0; - state_next = STATE_IDLE; - end - end else begin - if (ifg_count_next > 8'd0) begin - state_next = STATE_IFG; - end else begin - state_next = STATE_IDLE; - end - end - end else begin - state_next = STATE_WAIT_END; - end - end else begin - state_next = STATE_WAIT_END; - end - end endcase end always @(posedge clk) begin state_reg <= state_next; + frame_reg <= frame_next; + frame_error_reg <= frame_error_next; frame_min_count_reg <= frame_min_count_next; ifg_count_reg <= ifg_count_next; @@ -568,6 +541,8 @@ always @(posedge clk) begin if (rst) begin state_reg <= STATE_IDLE; + frame_reg <= 1'b0; + ifg_count_reg <= 8'd0; deficit_idle_count_reg <= 2'd0; diff --git a/rtl/axis_xgmii_tx_64.v b/rtl/axis_xgmii_tx_64.v index 5c5d69a3..4b45d64c 100644 --- a/rtl/axis_xgmii_tx_64.v +++ b/rtl/axis_xgmii_tx_64.v @@ -121,8 +121,8 @@ localparam [2:0] STATE_PAD = 3'd2, STATE_FCS_1 = 3'd3, STATE_FCS_2 = 3'd4, - STATE_IFG = 3'd5, - STATE_WAIT_END = 3'd6; + STATE_ERR = 3'd5, + STATE_IFG = 3'd6; reg [2:0] state_reg = STATE_IDLE, state_next; @@ -146,6 +146,8 @@ reg [CTRL_WIDTH-1:0] fcs_output_txc_1; reg [7:0] ifg_offset; +reg frame_reg = 1'b0, frame_next; +reg frame_error_reg = 1'b0, frame_error_next; reg [MIN_LEN_WIDTH-1:0] frame_min_count_reg = 0, frame_min_count_next; reg [7:0] ifg_count_reg = 8'd0, ifg_count_next; @@ -298,6 +300,8 @@ always @* begin swap_lanes_next = swap_lanes_reg; + frame_next = frame_reg; + frame_error_next = frame_error_reg; frame_min_count_next = frame_min_count_reg; ifg_count_next = ifg_count_reg; @@ -322,6 +326,10 @@ always @* begin start_packet_next = 2'b00; error_underflow_next = 1'b0; + if (s_axis_tvalid && s_axis_tready) begin + frame_next = !s_axis_tlast; + end + if (PTP_TS_ENABLE && PTP_TS_WIDTH == 96) begin m_axis_ptp_ts_valid_next = m_axis_ptp_ts_valid_int_reg; m_axis_ptp_ts_adj_next[15:0] = m_axis_ptp_ts_reg[15:0]; @@ -333,6 +341,7 @@ always @* begin case (state_reg) STATE_IDLE: begin // idle state - wait for data + frame_error_next = 1'b0; frame_min_count_next = MIN_FRAME_LENGTH-4-CTRL_WIDTH; reset_crc = 1'b1; s_axis_tready_next = cfg_tx_enable; @@ -414,46 +423,39 @@ always @* begin s_tdata_next = s_axis_tdata_masked; s_empty_next = keep2empty(s_axis_tkeep); - if (s_axis_tvalid) begin - if (s_axis_tlast) begin - s_axis_tready_next = 1'b0; - if (s_axis_tuser[0]) begin - xgmii_txd_next = {{3{XGMII_IDLE}}, XGMII_TERM, {4{XGMII_ERROR}}}; - xgmii_txc_next = {CTRL_WIDTH{1'b1}}; - ifg_count_next = 8'd8; - state_next = STATE_IFG; + if (!s_axis_tvalid || s_axis_tlast) begin + s_axis_tready_next = frame_next; // drop frame + frame_error_next = !s_axis_tvalid || s_axis_tuser[0]; + error_underflow_next = !s_axis_tvalid; + + if (ENABLE_PADDING && frame_min_count_reg) begin + if (frame_min_count_reg > CTRL_WIDTH) begin + s_empty_next = 0; + state_next = STATE_PAD; end else begin - s_axis_tready_next = 1'b0; - - if (ENABLE_PADDING && frame_min_count_reg) begin - if (frame_min_count_reg > CTRL_WIDTH) begin - s_empty_next = 0; - state_next = STATE_PAD; - end else begin - if (keep2empty(s_axis_tkeep) > CTRL_WIDTH-frame_min_count_reg) begin - s_empty_next = CTRL_WIDTH-frame_min_count_reg; - end - state_next = STATE_FCS_1; - end + if (keep2empty(s_axis_tkeep) > CTRL_WIDTH-frame_min_count_reg) begin + s_empty_next = CTRL_WIDTH-frame_min_count_reg; + end + if (frame_error_next) begin + state_next = STATE_ERR; end else begin state_next = STATE_FCS_1; end end end else begin - state_next = STATE_PAYLOAD; + if (frame_error_next) begin + state_next = STATE_ERR; + end else begin + state_next = STATE_FCS_1; + end end end else begin - // tvalid deassert, fail frame - xgmii_txd_next = {{3{XGMII_IDLE}}, XGMII_TERM, {4{XGMII_ERROR}}}; - xgmii_txc_next = {CTRL_WIDTH{1'b1}}; - ifg_count_next = 8'd8; - error_underflow_next = 1'b1; - state_next = STATE_WAIT_END; + state_next = STATE_PAYLOAD; end end STATE_PAD: begin // pad frame to MIN_FRAME_LENGTH - s_axis_tready_next = 1'b0; + s_axis_tready_next = frame_next; // drop frame xgmii_txd_next = s_tdata_reg; xgmii_txc_next = {CTRL_WIDTH{1'b0}}; @@ -469,12 +471,16 @@ always @* begin end else begin frame_min_count_next = 0; s_empty_next = CTRL_WIDTH-frame_min_count_reg; - state_next = STATE_FCS_1; + if (frame_error_reg) begin + state_next = STATE_ERR; + end else begin + state_next = STATE_FCS_1; + end end end STATE_FCS_1: begin // last cycle - s_axis_tready_next = 1'b0; + s_axis_tready_next = frame_next; // drop frame xgmii_txd_next = fcs_output_txd_0; xgmii_txc_next = fcs_output_txc_0; @@ -490,7 +496,7 @@ always @* begin end STATE_FCS_2: begin // last cycle - s_axis_tready_next = 1'b0; + s_axis_tready_next = frame_next; // drop frame xgmii_txd_next = fcs_output_txd_1; xgmii_txc_next = fcs_output_txc_1; @@ -520,8 +526,21 @@ always @* begin end end end + STATE_ERR: begin + // terminate packet with error + s_axis_tready_next = frame_next; // drop frame + + // XGMII error + xgmii_txd_next = {XGMII_TERM, {7{XGMII_ERROR}}}; + xgmii_txc_next = {CTRL_WIDTH{1'b1}}; + + ifg_count_next = 8'd12; + + state_next = STATE_IFG; + end STATE_IFG: begin // send IFG + s_axis_tready_next = frame_next; // drop frame // XGMII idle xgmii_txd_next = {CTRL_WIDTH{XGMII_IDLE}}; @@ -534,7 +553,7 @@ always @* begin end if (ENABLE_DIC) begin - if (ifg_count_next > 8'd7) begin + if (ifg_count_next > 8'd7 || frame_reg) begin state_next = STATE_IFG; end else begin if (ifg_count_next >= 8'd4) begin @@ -549,7 +568,7 @@ always @* begin state_next = STATE_IDLE; end end else begin - if (ifg_count_next > 8'd4) begin + if (ifg_count_next > 8'd4 || frame_reg) begin state_next = STATE_IFG; end else begin s_axis_tready_next = cfg_tx_enable; @@ -558,55 +577,6 @@ always @* begin end end end - STATE_WAIT_END: begin - // wait for end of frame - s_axis_tready_next = 1'b1; - - // XGMII idle - xgmii_txd_next = {CTRL_WIDTH{XGMII_IDLE}}; - xgmii_txc_next = {CTRL_WIDTH{1'b1}}; - - if (ifg_count_reg > 8'd8) begin - ifg_count_next = ifg_count_reg - 8'd8; - end else begin - ifg_count_next = 8'd0; - end - - if (s_axis_tvalid) begin - if (s_axis_tlast) begin - s_axis_tready_next = 1'b0; - - if (ENABLE_DIC) begin - if (ifg_count_next > 8'd7) begin - state_next = STATE_IFG; - end else begin - if (ifg_count_next >= 8'd4) begin - deficit_idle_count_next = ifg_count_next - 8'd4; - swap_lanes_next = 1'b1; - end else begin - deficit_idle_count_next = ifg_count_next; - ifg_count_next = 8'd0; - swap_lanes_next = 1'b0; - end - s_axis_tready_next = cfg_tx_enable; - state_next = STATE_IDLE; - end - end else begin - if (ifg_count_next > 8'd4) begin - state_next = STATE_IFG; - end else begin - s_axis_tready_next = cfg_tx_enable; - swap_lanes_next = ifg_count_next != 0; - state_next = STATE_IDLE; - end - end - end else begin - state_next = STATE_WAIT_END; - end - end else begin - state_next = STATE_WAIT_END; - end - end endcase end @@ -615,6 +585,8 @@ always @(posedge clk) begin swap_lanes_reg <= swap_lanes_next; + frame_reg <= frame_next; + frame_error_reg <= frame_error_next; frame_min_count_reg <= frame_min_count_next; ifg_count_reg <= ifg_count_next; @@ -665,6 +637,8 @@ always @(posedge clk) begin if (rst) begin state_reg <= STATE_IDLE; + frame_reg <= 1'b0; + swap_lanes_reg <= 1'b0; ifg_count_reg <= 8'd0;