1
0
mirror of https://github.com/corundum/corundum.git synced 2025-01-30 08:32:52 +08:00

Rework MAC frame padding logic

Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
Alex Forencich 2022-07-24 22:46:03 -07:00
parent 2ce89aec09
commit cb273970c3
4 changed files with 86 additions and 129 deletions

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;