From cb273970c37348d3d8ed1dfb1eaff5d7db74b7ae Mon Sep 17 00:00:00 2001 From: Alex Forencich Date: Sun, 24 Jul 2022 22:46:03 -0700 Subject: [PATCH] Rework MAC frame padding logic Signed-off-by: Alex Forencich --- rtl/axis_baser_tx_64.v | 56 ++++++++++++++---------------------------- rtl/axis_gmii_tx.v | 51 +++++++++++++++++++++----------------- rtl/axis_xgmii_tx_32.v | 52 ++++++++++++++------------------------- rtl/axis_xgmii_tx_64.v | 56 +++++++++++++++--------------------------- 4 files changed, 86 insertions(+), 129 deletions(-) diff --git a/rtl/axis_baser_tx_64.v b/rtl/axis_baser_tx_64.v index 1ec4846a8..06a6b66fb 100644 --- a/rtl/axis_baser_tx_64.v +++ b/rtl/axis_baser_tx_64.v @@ -88,6 +88,7 @@ module axis_baser_tx_64 # ); localparam EMPTY_WIDTH = $clog2(KEEP_WIDTH); +localparam MIN_LEN_WIDTH = $clog2(MIN_FRAME_LENGTH-4-KEEP_WIDTH+1); // bus width assertions initial begin @@ -107,10 +108,6 @@ initial begin end end -localparam MIN_FL_NOCRC = MIN_FRAME_LENGTH-4; -localparam MIN_FL_NOCRC_MS = MIN_FL_NOCRC & 16'hfff8; -localparam MIN_FL_NOCRC_LS = MIN_FL_NOCRC & 16'h0007; - localparam [7:0] ETH_PRE = 8'h55, ETH_SFD = 8'hD5; @@ -202,7 +199,7 @@ reg [3:0] fcs_output_type_1; reg [7:0] ifg_offset; -reg [15:0] frame_ptr_reg = 16'd0, frame_ptr_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; reg [1:0] deficit_idle_count_reg = 2'd0, deficit_idle_count_next; @@ -262,21 +259,6 @@ generate endgenerate -function [3:0] keep2count; - input [7:0] k; - casez (k) - 8'bzzzzzzz0: keep2count = 4'd0; - 8'bzzzzzz01: keep2count = 4'd1; - 8'bzzzzz011: keep2count = 4'd2; - 8'bzzzz0111: keep2count = 4'd3; - 8'bzzz01111: keep2count = 4'd4; - 8'bzz011111: keep2count = 4'd5; - 8'bz0111111: keep2count = 4'd6; - 8'b01111111: keep2count = 4'd7; - 8'b11111111: keep2count = 4'd8; - endcase -endfunction - function [2:0] keep2empty; input [7:0] k; casez (k) @@ -372,7 +354,7 @@ always @* begin swap_lanes = 1'b0; unswap_lanes = 1'b0; - frame_ptr_next = frame_ptr_reg; + frame_min_count_next = frame_min_count_reg; ifg_count_next = ifg_count_reg; deficit_idle_count_next = deficit_idle_count_reg; @@ -405,7 +387,7 @@ always @* begin case (state_reg) STATE_IDLE: begin // idle state - wait for data - frame_ptr_next = 16'd8; + frame_min_count_next = MIN_FRAME_LENGTH-4-KEEP_WIDTH; reset_crc = 1'b1; s_axis_tready_next = 1'b1; @@ -458,7 +440,11 @@ always @* begin update_crc = 1'b1; s_axis_tready_next = 1'b1; - frame_ptr_next = frame_ptr_reg + 16'd8; + if (frame_min_count_reg > KEEP_WIDTH) begin + frame_min_count_next = frame_min_count_reg - KEEP_WIDTH; + end else begin + frame_min_count_next = 0; + end output_data_next = s_tdata_reg; output_type_next = OUTPUT_TYPE_DATA; @@ -468,7 +454,6 @@ always @* begin if (s_axis_tvalid) begin if (s_axis_tlast) begin - frame_ptr_next = frame_ptr_reg + keep2count(s_axis_tkeep); s_axis_tready_next = 1'b0; if (s_axis_tuser[0]) begin output_type_next = OUTPUT_TYPE_ERROR; @@ -477,15 +462,14 @@ always @* begin end else begin s_axis_tready_next = 1'b0; - if (ENABLE_PADDING && (frame_ptr_reg < MIN_FL_NOCRC_MS || (frame_ptr_reg == MIN_FL_NOCRC_MS && keep2count(s_axis_tkeep) < MIN_FL_NOCRC_LS))) begin - s_empty_next = 0; - frame_ptr_next = frame_ptr_reg + 16'd8; - - if (frame_ptr_reg < (MIN_FL_NOCRC_LS > 0 ? MIN_FL_NOCRC_MS : MIN_FL_NOCRC_MS-8)) begin + 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_empty_next = (8-MIN_FL_NOCRC_LS) % 8; - + 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 end else begin @@ -514,13 +498,13 @@ always @* begin s_empty_next = 0; update_crc = 1'b1; - frame_ptr_next = frame_ptr_reg + 16'd8; - if (frame_ptr_reg < (MIN_FL_NOCRC_LS > 0 ? MIN_FL_NOCRC_MS : MIN_FL_NOCRC_MS-8)) begin + if (frame_min_count_reg > KEEP_WIDTH) begin + frame_min_count_next = frame_min_count_reg - KEEP_WIDTH; state_next = STATE_PAD; end else begin - s_empty_next = (8-MIN_FL_NOCRC_LS) % 8; - + frame_min_count_next = 0; + s_empty_next = KEEP_WIDTH-frame_min_count_reg; state_next = STATE_FCS_1; end end @@ -651,8 +635,6 @@ end always @(posedge clk) begin state_reg <= state_next; - frame_ptr_reg <= frame_ptr_next; - ifg_count_reg <= ifg_count_next; deficit_idle_count_reg <= deficit_idle_count_next; diff --git a/rtl/axis_gmii_tx.v b/rtl/axis_gmii_tx.v index a76aa5d24..de86e8e99 100644 --- a/rtl/axis_gmii_tx.v +++ b/rtl/axis_gmii_tx.v @@ -88,6 +88,8 @@ module axis_gmii_tx # output wire error_underflow ); +localparam MIN_LEN_WIDTH = $clog2(MIN_FRAME_LENGTH-4-1+1); + // bus width assertions initial begin if (DATA_WIDTH != 8) begin @@ -121,7 +123,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 [15:0] frame_ptr_reg = 16'd0, frame_ptr_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; reg [7:0] gmii_txd_reg = 8'd0, gmii_txd_next; reg gmii_tx_en_reg = 1'b0, gmii_tx_en_next; @@ -178,6 +181,7 @@ always @* begin mii_msn_next = mii_msn_reg; frame_ptr_next = frame_ptr_reg; + frame_min_count_next = frame_min_count_reg; s_axis_tready_next = 1'b0; @@ -212,11 +216,14 @@ always @* begin STATE_IDLE: begin // idle state - wait for packet reset_crc = 1'b1; + mii_odd_next = 1'b0; + frame_ptr_next = 1; + + frame_min_count_next = MIN_FRAME_LENGTH-4-1; if (s_axis_tvalid) begin mii_odd_next = 1'b1; - frame_ptr_next = 16'd1; gmii_txd_next = ETH_PRE; gmii_tx_en_next = 1'b1; state_next = STATE_PREAMBLE; @@ -229,18 +236,18 @@ always @* begin reset_crc = 1'b1; mii_odd_next = 1'b1; - frame_ptr_next = frame_ptr_reg + 16'd1; + frame_ptr_next = frame_ptr_reg + 1; gmii_txd_next = ETH_PRE; gmii_tx_en_next = 1'b1; - if (frame_ptr_reg == 16'd6) begin + if (frame_ptr_reg == 6) begin s_axis_tready_next = 1'b1; s_tdata_next = s_axis_tdata; state_next = STATE_PREAMBLE; - end else if (frame_ptr_reg == 16'd7) begin + end else if (frame_ptr_reg == 7) begin // end of preamble; start payload - frame_ptr_next = 16'd0; + frame_ptr_next = 0; if (s_axis_tready_reg) begin s_axis_tready_next = 1'b1; s_tdata_next = s_axis_tdata; @@ -262,7 +269,10 @@ always @* begin s_axis_tready_next = 1'b1; mii_odd_next = 1'b1; - frame_ptr_next = frame_ptr_reg + 16'd1; + + if (frame_min_count_reg) begin + frame_min_count_next = frame_min_count_reg - 1; + end gmii_txd_next = s_tdata_reg; gmii_tx_en_next = 1'b1; @@ -274,7 +284,6 @@ always @* begin s_axis_tready_next = !s_axis_tready_reg; if (s_axis_tuser[0]) begin gmii_tx_er_next = 1'b1; - frame_ptr_next = 1'b0; state_next = STATE_IFG; end else begin state_next = STATE_LAST; @@ -285,7 +294,6 @@ always @* begin end else begin // tvalid deassert, fail frame gmii_tx_er_next = 1'b1; - frame_ptr_next = 16'd0; error_underflow_next = 1'b1; state_next = STATE_WAIT_END; end @@ -296,16 +304,16 @@ always @* begin update_crc = 1'b1; mii_odd_next = 1'b1; - frame_ptr_next = frame_ptr_reg + 16'd1; gmii_txd_next = s_tdata_reg; gmii_tx_en_next = 1'b1; - if (ENABLE_PADDING && frame_ptr_reg < MIN_FRAME_LENGTH-5) begin + if (ENABLE_PADDING && frame_min_count_reg) begin + frame_min_count_next = frame_min_count_reg - 1; s_tdata_next = 8'd0; state_next = STATE_PAD; end else begin - frame_ptr_next = 16'd0; + frame_ptr_next = 0; state_next = STATE_FCS; end end @@ -314,17 +322,17 @@ always @* begin update_crc = 1'b1; mii_odd_next = 1'b1; - frame_ptr_next = frame_ptr_reg + 16'd1; gmii_txd_next = 8'd0; gmii_tx_en_next = 1'b1; s_tdata_next = 8'd0; - if (frame_ptr_reg < MIN_FRAME_LENGTH-5) begin + if (frame_min_count_reg) begin + frame_min_count_next = frame_min_count_reg - 1; state_next = STATE_PAD; end else begin - frame_ptr_next = 16'd0; + frame_ptr_next = 0; state_next = STATE_FCS; end end @@ -332,7 +340,7 @@ always @* begin // send FCS mii_odd_next = 1'b1; - frame_ptr_next = frame_ptr_reg + 16'd1; + frame_ptr_next = frame_ptr_reg + 1; case (frame_ptr_reg) 2'd0: gmii_txd_next = ~crc_state[7:0]; @@ -345,17 +353,15 @@ always @* begin if (frame_ptr_reg < 3) begin state_next = STATE_FCS; end else begin - frame_ptr_next = 16'd0; + frame_ptr_next = 0; state_next = STATE_IFG; end end STATE_WAIT_END: begin // wait for end of frame - reset_crc = 1'b1; - mii_odd_next = 1'b1; - frame_ptr_next = frame_ptr_reg + 16'd1; + frame_ptr_next = frame_ptr_reg + 1; s_axis_tready_next = 1'b1; if (s_axis_tvalid) begin @@ -376,10 +382,8 @@ always @* begin STATE_IFG: begin // send IFG - reset_crc = 1'b1; - mii_odd_next = 1'b1; - frame_ptr_next = frame_ptr_reg + 16'd1; + frame_ptr_next = frame_ptr_reg + 1; if (frame_ptr_reg < ifg_delay-1) begin state_next = STATE_IFG; @@ -400,6 +404,7 @@ always @(posedge clk) begin state_reg <= state_next; frame_ptr_reg <= frame_ptr_next; + frame_min_count_reg <= frame_min_count_next; m_axis_ptp_ts_reg <= m_axis_ptp_ts_next; m_axis_ptp_ts_tag_reg <= m_axis_ptp_ts_tag_next; diff --git a/rtl/axis_xgmii_tx_32.v b/rtl/axis_xgmii_tx_32.v index 2f458acfe..dafd3a3ea 100644 --- a/rtl/axis_xgmii_tx_32.v +++ b/rtl/axis_xgmii_tx_32.v @@ -86,6 +86,7 @@ module axis_xgmii_tx_32 # ); localparam EMPTY_WIDTH = $clog2(KEEP_WIDTH); +localparam MIN_LEN_WIDTH = $clog2(MIN_FRAME_LENGTH-4-CTRL_WIDTH+1); // bus width assertions initial begin @@ -100,10 +101,6 @@ initial begin end end -localparam MIN_FL_NOCRC = MIN_FRAME_LENGTH-4; -localparam MIN_FL_NOCRC_MS = MIN_FL_NOCRC & 16'hfffc; -localparam MIN_FL_NOCRC_LS = MIN_FL_NOCRC & 16'h0003; - localparam [7:0] ETH_PRE = 8'h55, ETH_SFD = 8'hD5; @@ -145,7 +142,7 @@ reg [7:0] ifg_offset; reg extra_cycle; -reg [15:0] frame_ptr_reg = 16'd0, frame_ptr_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; reg [1:0] deficit_idle_count_reg = 2'd0, deficit_idle_count_next; @@ -201,17 +198,6 @@ generate endgenerate -function [2:0] keep2count; - input [3:0] k; - casez (k) - 4'bzzz0: keep2count = 3'd0; - 4'bzz01: keep2count = 3'd1; - 4'bz011: keep2count = 3'd2; - 4'b0111: keep2count = 3'd3; - 4'b1111: keep2count = 3'd4; - endcase -endfunction - function [1:0] keep2empty; input [3:0] k; casez (k) @@ -276,7 +262,7 @@ always @* begin reset_crc = 1'b0; update_crc = 1'b0; - frame_ptr_next = frame_ptr_reg; + frame_min_count_next = frame_min_count_reg; ifg_count_next = ifg_count_reg; deficit_idle_count_next = deficit_idle_count_reg; @@ -306,7 +292,7 @@ always @* begin case (state_reg) STATE_IDLE: begin // idle state - wait for data - frame_ptr_next = 16'd4; + frame_min_count_next = MIN_FRAME_LENGTH-4-CTRL_WIDTH; reset_crc = 1'b1; // XGMII idle @@ -345,7 +331,11 @@ always @* begin update_crc = 1'b1; s_axis_tready_next = 1'b1; - frame_ptr_next = frame_ptr_reg + 16'd4; + if (frame_min_count_reg > CTRL_WIDTH) begin + frame_min_count_next = frame_min_count_reg - CTRL_WIDTH; + end else begin + frame_min_count_next = 0; + end xgmii_txd_next = s_tdata_reg; xgmii_txc_next = 4'b0000; @@ -355,7 +345,6 @@ always @* begin if (s_axis_tvalid) begin if (s_axis_tlast) begin - frame_ptr_next = frame_ptr_reg + keep2count(s_axis_tkeep); s_axis_tready_next = 1'b0; if (s_axis_tuser[0]) begin xgmii_txd_next = {XGMII_TERM, {3{XGMII_ERROR}}}; @@ -365,15 +354,14 @@ always @* begin end else begin s_axis_tready_next = 1'b0; - if (ENABLE_PADDING && (frame_ptr_reg < MIN_FL_NOCRC_MS || (frame_ptr_reg == MIN_FL_NOCRC_MS && keep2count(s_axis_tkeep) < MIN_FL_NOCRC_LS))) begin - s_empty_next = 0; - frame_ptr_next = frame_ptr_reg + 16'd4; - - if (frame_ptr_reg < (MIN_FL_NOCRC_LS > 0 ? MIN_FL_NOCRC_MS : MIN_FL_NOCRC_MS-4)) begin + 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_empty_next = (4-MIN_FL_NOCRC_LS) % 4; - + 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 @@ -403,13 +391,13 @@ always @* begin s_empty_next = 0; update_crc = 1'b1; - frame_ptr_next = frame_ptr_reg + 16'd4; - if (frame_ptr_reg < (MIN_FL_NOCRC_LS > 0 ? MIN_FL_NOCRC_MS : MIN_FL_NOCRC_MS-4)) begin + if (frame_min_count_reg > CTRL_WIDTH) begin + frame_min_count_next = frame_min_count_reg - CTRL_WIDTH; state_next = STATE_PAD; end else begin - s_empty_next = (4-MIN_FL_NOCRC_LS) % 4; - + frame_min_count_next = 0; + s_empty_next = CTRL_WIDTH-frame_min_count_reg; state_next = STATE_FCS_1; end end @@ -532,8 +520,6 @@ end always @(posedge clk) begin state_reg <= state_next; - frame_ptr_reg <= frame_ptr_next; - ifg_count_reg <= ifg_count_next; deficit_idle_count_reg <= deficit_idle_count_next; diff --git a/rtl/axis_xgmii_tx_64.v b/rtl/axis_xgmii_tx_64.v index 8cb55da5d..2b634ff8c 100644 --- a/rtl/axis_xgmii_tx_64.v +++ b/rtl/axis_xgmii_tx_64.v @@ -88,6 +88,7 @@ module axis_xgmii_tx_64 # ); localparam EMPTY_WIDTH = $clog2(KEEP_WIDTH); +localparam MIN_LEN_WIDTH = $clog2(MIN_FRAME_LENGTH-4-CTRL_WIDTH+1); // bus width assertions initial begin @@ -102,10 +103,6 @@ initial begin end end -localparam MIN_FL_NOCRC = MIN_FRAME_LENGTH-4; -localparam MIN_FL_NOCRC_MS = MIN_FL_NOCRC & 16'hfff8; -localparam MIN_FL_NOCRC_LS = MIN_FL_NOCRC & 16'h0007; - localparam [7:0] ETH_PRE = 8'h55, ETH_SFD = 8'hD5; @@ -150,7 +147,7 @@ reg [CTRL_WIDTH-1:0] fcs_output_txc_1; reg [7:0] ifg_offset; -reg [15:0] frame_ptr_reg = 16'd0, frame_ptr_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; reg [1:0] deficit_idle_count_reg = 2'd0, deficit_idle_count_next; @@ -207,21 +204,6 @@ generate endgenerate -function [3:0] keep2count; - input [7:0] k; - casez (k) - 8'bzzzzzzz0: keep2count = 4'd0; - 8'bzzzzzz01: keep2count = 4'd1; - 8'bzzzzz011: keep2count = 4'd2; - 8'bzzzz0111: keep2count = 4'd3; - 8'bzzz01111: keep2count = 4'd4; - 8'bzz011111: keep2count = 4'd5; - 8'bz0111111: keep2count = 4'd6; - 8'b01111111: keep2count = 4'd7; - 8'b11111111: keep2count = 4'd8; - endcase -endfunction - function [2:0] keep2empty; input [7:0] k; casez (k) @@ -317,7 +299,7 @@ always @* begin swap_lanes = 1'b0; unswap_lanes = 1'b0; - frame_ptr_next = frame_ptr_reg; + frame_min_count_next = frame_min_count_reg; ifg_count_next = ifg_count_reg; deficit_idle_count_next = deficit_idle_count_reg; @@ -351,7 +333,7 @@ always @* begin case (state_reg) STATE_IDLE: begin // idle state - wait for data - frame_ptr_next = 16'd8; + frame_min_count_next = MIN_FRAME_LENGTH-4-CTRL_WIDTH; reset_crc = 1'b1; s_axis_tready_next = 1'b1; @@ -405,7 +387,11 @@ always @* begin update_crc = 1'b1; s_axis_tready_next = 1'b1; - frame_ptr_next = frame_ptr_reg + 16'd8; + if (frame_min_count_reg > CTRL_WIDTH) begin + frame_min_count_next = frame_min_count_reg - CTRL_WIDTH; + end else begin + frame_min_count_next = 0; + end xgmii_txd_next = s_tdata_reg; xgmii_txc_next = 8'b00000000; @@ -415,7 +401,6 @@ always @* begin if (s_axis_tvalid) begin if (s_axis_tlast) begin - frame_ptr_next = frame_ptr_reg + keep2count(s_axis_tkeep); s_axis_tready_next = 1'b0; if (s_axis_tuser[0]) begin xgmii_txd_next = {{3{XGMII_IDLE}}, XGMII_TERM, {4{XGMII_ERROR}}}; @@ -425,15 +410,14 @@ always @* begin end else begin s_axis_tready_next = 1'b0; - if (ENABLE_PADDING && (frame_ptr_reg < MIN_FL_NOCRC_MS || (frame_ptr_reg == MIN_FL_NOCRC_MS && keep2count(s_axis_tkeep) < MIN_FL_NOCRC_LS))) begin - s_empty_next = 0; - frame_ptr_next = frame_ptr_reg + 16'd8; - - if (frame_ptr_reg < (MIN_FL_NOCRC_LS > 0 ? MIN_FL_NOCRC_MS : MIN_FL_NOCRC_MS-8)) begin + 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_empty_next = (8-MIN_FL_NOCRC_LS) % 8; - + 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 @@ -463,13 +447,13 @@ always @* begin s_empty_next = 0; update_crc = 1'b1; - frame_ptr_next = frame_ptr_reg + 16'd8; - if (frame_ptr_reg < (MIN_FL_NOCRC_LS > 0 ? MIN_FL_NOCRC_MS : MIN_FL_NOCRC_MS-8)) begin + if (frame_min_count_reg > CTRL_WIDTH) begin + frame_min_count_next = frame_min_count_reg - CTRL_WIDTH; state_next = STATE_PAD; end else begin - s_empty_next = (8-MIN_FL_NOCRC_LS) % 8; - + frame_min_count_next = 0; + s_empty_next = CTRL_WIDTH-frame_min_count_reg; state_next = STATE_FCS_1; end end @@ -600,7 +584,7 @@ end always @(posedge clk) begin state_reg <= state_next; - frame_ptr_reg <= frame_ptr_next; + frame_min_count_reg <= frame_min_count_next; ifg_count_reg <= ifg_count_next; deficit_idle_count_reg <= deficit_idle_count_next;