Skip to content

Commit eb0f01f

Browse files
committed
Rework MAC TX error handling to streamline logic; pad errored frames to avoid generating runt frames
Signed-off-by: Alex Forencich <alex@alexforencich.com>
1 parent e24f887 commit eb0f01f

File tree

4 files changed

+203
-287
lines changed

4 files changed

+203
-287
lines changed

rtl/axis_baser_tx_64.v

Lines changed: 61 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -171,8 +171,8 @@ localparam [2:0]
171171
STATE_PAD = 3'd2,
172172
STATE_FCS_1 = 3'd3,
173173
STATE_FCS_2 = 3'd4,
174-
STATE_IFG = 3'd5,
175-
STATE_WAIT_END = 3'd6;
174+
STATE_ERR = 3'd5,
175+
STATE_IFG = 3'd6;
176176

177177
reg [2:0] state_reg = STATE_IDLE, state_next;
178178

@@ -198,6 +198,8 @@ reg [3:0] fcs_output_type_1;
198198

199199
reg [7:0] ifg_offset;
200200

201+
reg frame_reg = 1'b0, frame_next;
202+
reg frame_error_reg = 1'b0, frame_error_next;
201203
reg [MIN_LEN_WIDTH-1:0] frame_min_count_reg = 0, frame_min_count_next;
202204

203205
reg [7:0] ifg_count_reg = 8'd0, ifg_count_next;
@@ -353,6 +355,8 @@ always @* begin
353355

354356
swap_lanes_next = swap_lanes_reg;
355357

358+
frame_next = frame_reg;
359+
frame_error_next = frame_error_reg;
356360
frame_min_count_next = frame_min_count_reg;
357361

358362
ifg_count_next = ifg_count_reg;
@@ -376,6 +380,10 @@ always @* begin
376380
start_packet_next = 2'b00;
377381
error_underflow_next = 1'b0;
378382

383+
if (s_axis_tvalid && s_axis_tready) begin
384+
frame_next = !s_axis_tlast;
385+
end
386+
379387
if (PTP_TS_ENABLE && PTP_TS_WIDTH == 96) begin
380388
m_axis_ptp_ts_valid_next = m_axis_ptp_ts_valid_int_reg;
381389
m_axis_ptp_ts_adj_next[15:0] = m_axis_ptp_ts_reg[15:0];
@@ -387,6 +395,7 @@ always @* begin
387395
case (state_reg)
388396
STATE_IDLE: begin
389397
// idle state - wait for data
398+
frame_error_next = 1'b0;
390399
frame_min_count_next = MIN_FRAME_LENGTH-4-KEEP_WIDTH;
391400
reset_crc = 1'b1;
392401
s_axis_tready_next = 1'b1;
@@ -467,44 +476,39 @@ always @* begin
467476
s_tdata_next = s_axis_tdata_masked;
468477
s_empty_next = keep2empty(s_axis_tkeep);
469478

470-
if (s_axis_tvalid) begin
471-
if (s_axis_tlast) begin
472-
s_axis_tready_next = 1'b0;
473-
if (s_axis_tuser[0]) begin
474-
output_type_next = OUTPUT_TYPE_ERROR;
475-
ifg_count_next = 8'd8;
476-
state_next = STATE_IFG;
479+
if (!s_axis_tvalid || s_axis_tlast) begin
480+
s_axis_tready_next = frame_next; // drop frame
481+
frame_error_next = !s_axis_tvalid || s_axis_tuser[0];
482+
error_underflow_next = !s_axis_tvalid;
483+
484+
if (ENABLE_PADDING && frame_min_count_reg) begin
485+
if (frame_min_count_reg > KEEP_WIDTH) begin
486+
s_empty_next = 0;
487+
state_next = STATE_PAD;
477488
end else begin
478-
s_axis_tready_next = 1'b0;
479-
480-
if (ENABLE_PADDING && frame_min_count_reg) begin
481-
if (frame_min_count_reg > KEEP_WIDTH) begin
482-
s_empty_next = 0;
483-
state_next = STATE_PAD;
484-
end else begin
485-
if (keep2empty(s_axis_tkeep) > KEEP_WIDTH-frame_min_count_reg) begin
486-
s_empty_next = KEEP_WIDTH-frame_min_count_reg;
487-
end
488-
state_next = STATE_FCS_1;
489-
end
489+
if (keep2empty(s_axis_tkeep) > KEEP_WIDTH-frame_min_count_reg) begin
490+
s_empty_next = KEEP_WIDTH-frame_min_count_reg;
491+
end
492+
if (frame_error_next) begin
493+
state_next = STATE_ERR;
490494
end else begin
491495
state_next = STATE_FCS_1;
492496
end
493497
end
494498
end else begin
495-
state_next = STATE_PAYLOAD;
499+
if (frame_error_next) begin
500+
state_next = STATE_ERR;
501+
end else begin
502+
state_next = STATE_FCS_1;
503+
end
496504
end
497505
end else begin
498-
// tvalid deassert, fail frame
499-
output_type_next = OUTPUT_TYPE_ERROR;
500-
ifg_count_next = 8'd8;
501-
error_underflow_next = 1'b1;
502-
state_next = STATE_WAIT_END;
506+
state_next = STATE_PAYLOAD;
503507
end
504508
end
505509
STATE_PAD: begin
506510
// pad frame to MIN_FRAME_LENGTH
507-
s_axis_tready_next = 1'b0;
511+
s_axis_tready_next = frame_next; // drop frame
508512

509513
output_data_next = s_tdata_reg;
510514
output_type_next = OUTPUT_TYPE_DATA;
@@ -520,12 +524,16 @@ always @* begin
520524
end else begin
521525
frame_min_count_next = 0;
522526
s_empty_next = KEEP_WIDTH-frame_min_count_reg;
523-
state_next = STATE_FCS_1;
527+
if (frame_error_reg) begin
528+
state_next = STATE_ERR;
529+
end else begin
530+
state_next = STATE_FCS_1;
531+
end
524532
end
525533
end
526534
STATE_FCS_1: begin
527535
// last cycle
528-
s_axis_tready_next = 1'b0;
536+
s_axis_tready_next = frame_next; // drop frame
529537

530538
output_data_next = fcs_output_data_0;
531539
output_type_next = fcs_output_type_0;
@@ -541,7 +549,7 @@ always @* begin
541549
end
542550
STATE_FCS_2: begin
543551
// last cycle
544-
s_axis_tready_next = 1'b0;
552+
s_axis_tready_next = frame_next; // drop frame
545553

546554
output_data_next = fcs_output_data_1;
547555
output_type_next = fcs_output_type_1;
@@ -573,8 +581,24 @@ always @* begin
573581
end
574582
end
575583
end
584+
STATE_ERR: begin
585+
// terminate packet with error
586+
s_axis_tready_next = frame_next; // drop frame
587+
588+
output_data_next = s_tdata_reg;
589+
output_type_next = OUTPUT_TYPE_ERROR;
590+
591+
ifg_count_next = 8'd12;
592+
593+
state_next = STATE_IFG;
594+
end
576595
STATE_IFG: begin
577596
// send IFG
597+
s_axis_tready_next = frame_next; // drop frame
598+
599+
output_data_next = s_tdata_reg;
600+
output_type_next = OUTPUT_TYPE_IDLE;
601+
578602
if (ifg_count_reg > 8'd8) begin
579603
ifg_count_next = ifg_count_reg - 8'd8;
580604
end else begin
@@ -584,7 +608,7 @@ always @* begin
584608
reset_crc = 1'b1;
585609

586610
if (ENABLE_DIC) begin
587-
if (ifg_count_next > 8'd7) begin
611+
if (ifg_count_next > 8'd7 || frame_reg) begin
588612
state_next = STATE_IFG;
589613
end else begin
590614
if (ifg_count_next >= 8'd4) begin
@@ -599,7 +623,7 @@ always @* begin
599623
state_next = STATE_IDLE;
600624
end
601625
end else begin
602-
if (ifg_count_next > 8'd4) begin
626+
if (ifg_count_next > 8'd4 || frame_reg) begin
603627
state_next = STATE_IFG;
604628
end else begin
605629
s_axis_tready_next = 1'b1;
@@ -608,53 +632,6 @@ always @* begin
608632
end
609633
end
610634
end
611-
STATE_WAIT_END: begin
612-
// wait for end of frame
613-
s_axis_tready_next = 1'b1;
614-
615-
if (ifg_count_reg > 8'd4) begin
616-
ifg_count_next = ifg_count_reg - 8'd4;
617-
end else begin
618-
ifg_count_next = 8'd0;
619-
end
620-
621-
reset_crc = 1'b1;
622-
623-
if (s_axis_tvalid) begin
624-
if (s_axis_tlast) begin
625-
s_axis_tready_next = 1'b0;
626-
627-
if (ENABLE_DIC) begin
628-
if (ifg_count_next > 8'd7) begin
629-
state_next = STATE_IFG;
630-
end else begin
631-
if (ifg_count_next >= 8'd4) begin
632-
deficit_idle_count_next = ifg_count_next - 8'd4;
633-
swap_lanes_next = 1'b1;
634-
end else begin
635-
deficit_idle_count_next = ifg_count_next;
636-
ifg_count_next = 8'd0;
637-
swap_lanes_next = 1'b0;
638-
end
639-
s_axis_tready_next = 1'b1;
640-
state_next = STATE_IDLE;
641-
end
642-
end else begin
643-
if (ifg_count_next > 8'd4) begin
644-
state_next = STATE_IFG;
645-
end else begin
646-
s_axis_tready_next = 1'b1;
647-
swap_lanes_next = ifg_count_next != 0;
648-
state_next = STATE_IDLE;
649-
end
650-
end
651-
end else begin
652-
state_next = STATE_WAIT_END;
653-
end
654-
end else begin
655-
state_next = STATE_WAIT_END;
656-
end
657-
end
658635
endcase
659636
end
660637

@@ -663,6 +640,8 @@ always @(posedge clk) begin
663640

664641
swap_lanes_reg <= swap_lanes_next;
665642

643+
frame_reg <= frame_next;
644+
frame_error_reg <= frame_error_next;
666645
frame_min_count_reg <= frame_min_count_next;
667646

668647
ifg_count_reg <= ifg_count_next;
@@ -788,6 +767,8 @@ always @(posedge clk) begin
788767
if (rst) begin
789768
state_reg <= STATE_IDLE;
790769

770+
frame_reg <= 1'b0;
771+
791772
swap_lanes_reg <= 1'b0;
792773

793774
ifg_count_reg <= 8'd0;

0 commit comments

Comments
 (0)