mirror of
https://github.com/alexforencich/verilog-ethernet.git
synced 2025-01-28 07:03:08 +08:00
Rework MAC TX error handling to streamline logic; pad errored frames to avoid generating runt frames
Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
parent
e24f887009
commit
eb0f01f276
@ -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;
|
||||
end else begin
|
||||
s_axis_tready_next = 1'b0;
|
||||
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
|
||||
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 (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
|
||||
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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
end else begin
|
||||
s_axis_tready_next = 1'b0;
|
||||
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
|
||||
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 (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_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;
|
||||
|
||||
|
@ -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;
|
||||
end else begin
|
||||
s_axis_tready_next = 1'b0;
|
||||
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
|
||||
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 (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
|
||||
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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user