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_PAD = 3'd2,
|
||||||
STATE_FCS_1 = 3'd3,
|
STATE_FCS_1 = 3'd3,
|
||||||
STATE_FCS_2 = 3'd4,
|
STATE_FCS_2 = 3'd4,
|
||||||
STATE_IFG = 3'd5,
|
STATE_ERR = 3'd5,
|
||||||
STATE_WAIT_END = 3'd6;
|
STATE_IFG = 3'd6;
|
||||||
|
|
||||||
reg [2:0] state_reg = STATE_IDLE, state_next;
|
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 [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 [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 [7:0] ifg_count_reg = 8'd0, ifg_count_next;
|
||||||
@ -353,6 +355,8 @@ always @* begin
|
|||||||
|
|
||||||
swap_lanes_next = swap_lanes_reg;
|
swap_lanes_next = swap_lanes_reg;
|
||||||
|
|
||||||
|
frame_next = frame_reg;
|
||||||
|
frame_error_next = frame_error_reg;
|
||||||
frame_min_count_next = frame_min_count_reg;
|
frame_min_count_next = frame_min_count_reg;
|
||||||
|
|
||||||
ifg_count_next = ifg_count_reg;
|
ifg_count_next = ifg_count_reg;
|
||||||
@ -376,6 +380,10 @@ always @* begin
|
|||||||
start_packet_next = 2'b00;
|
start_packet_next = 2'b00;
|
||||||
error_underflow_next = 1'b0;
|
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
|
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_valid_next = m_axis_ptp_ts_valid_int_reg;
|
||||||
m_axis_ptp_ts_adj_next[15:0] = m_axis_ptp_ts_reg[15:0];
|
m_axis_ptp_ts_adj_next[15:0] = m_axis_ptp_ts_reg[15:0];
|
||||||
@ -387,6 +395,7 @@ always @* begin
|
|||||||
case (state_reg)
|
case (state_reg)
|
||||||
STATE_IDLE: begin
|
STATE_IDLE: begin
|
||||||
// idle state - wait for data
|
// idle state - wait for data
|
||||||
|
frame_error_next = 1'b0;
|
||||||
frame_min_count_next = MIN_FRAME_LENGTH-4-KEEP_WIDTH;
|
frame_min_count_next = MIN_FRAME_LENGTH-4-KEEP_WIDTH;
|
||||||
reset_crc = 1'b1;
|
reset_crc = 1'b1;
|
||||||
s_axis_tready_next = 1'b1;
|
s_axis_tready_next = 1'b1;
|
||||||
@ -467,44 +476,39 @@ always @* begin
|
|||||||
s_tdata_next = s_axis_tdata_masked;
|
s_tdata_next = s_axis_tdata_masked;
|
||||||
s_empty_next = keep2empty(s_axis_tkeep);
|
s_empty_next = keep2empty(s_axis_tkeep);
|
||||||
|
|
||||||
if (s_axis_tvalid) begin
|
if (!s_axis_tvalid || s_axis_tlast) begin
|
||||||
if (s_axis_tlast) begin
|
s_axis_tready_next = frame_next; // drop frame
|
||||||
s_axis_tready_next = 1'b0;
|
frame_error_next = !s_axis_tvalid || s_axis_tuser[0];
|
||||||
if (s_axis_tuser[0]) begin
|
error_underflow_next = !s_axis_tvalid;
|
||||||
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 (ENABLE_PADDING && frame_min_count_reg) begin
|
if (ENABLE_PADDING && frame_min_count_reg) begin
|
||||||
if (frame_min_count_reg > KEEP_WIDTH) begin
|
if (frame_min_count_reg > KEEP_WIDTH) begin
|
||||||
s_empty_next = 0;
|
s_empty_next = 0;
|
||||||
state_next = STATE_PAD;
|
state_next = STATE_PAD;
|
||||||
end else begin
|
end else begin
|
||||||
if (keep2empty(s_axis_tkeep) > KEEP_WIDTH-frame_min_count_reg) begin
|
if (keep2empty(s_axis_tkeep) > KEEP_WIDTH-frame_min_count_reg) begin
|
||||||
s_empty_next = KEEP_WIDTH-frame_min_count_reg;
|
s_empty_next = KEEP_WIDTH-frame_min_count_reg;
|
||||||
end
|
end
|
||||||
state_next = STATE_FCS_1;
|
if (frame_error_next) begin
|
||||||
end
|
state_next = STATE_ERR;
|
||||||
end else begin
|
end else begin
|
||||||
state_next = STATE_FCS_1;
|
state_next = STATE_FCS_1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end else begin
|
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
|
||||||
end else begin
|
end else begin
|
||||||
// tvalid deassert, fail frame
|
state_next = STATE_PAYLOAD;
|
||||||
output_type_next = OUTPUT_TYPE_ERROR;
|
|
||||||
ifg_count_next = 8'd8;
|
|
||||||
error_underflow_next = 1'b1;
|
|
||||||
state_next = STATE_WAIT_END;
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
STATE_PAD: begin
|
STATE_PAD: begin
|
||||||
// pad frame to MIN_FRAME_LENGTH
|
// 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_data_next = s_tdata_reg;
|
||||||
output_type_next = OUTPUT_TYPE_DATA;
|
output_type_next = OUTPUT_TYPE_DATA;
|
||||||
@ -520,12 +524,16 @@ always @* begin
|
|||||||
end else begin
|
end else begin
|
||||||
frame_min_count_next = 0;
|
frame_min_count_next = 0;
|
||||||
s_empty_next = KEEP_WIDTH-frame_min_count_reg;
|
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
|
||||||
end
|
end
|
||||||
STATE_FCS_1: begin
|
STATE_FCS_1: begin
|
||||||
// last cycle
|
// last cycle
|
||||||
s_axis_tready_next = 1'b0;
|
s_axis_tready_next = frame_next; // drop frame
|
||||||
|
|
||||||
output_data_next = fcs_output_data_0;
|
output_data_next = fcs_output_data_0;
|
||||||
output_type_next = fcs_output_type_0;
|
output_type_next = fcs_output_type_0;
|
||||||
@ -541,7 +549,7 @@ always @* begin
|
|||||||
end
|
end
|
||||||
STATE_FCS_2: begin
|
STATE_FCS_2: begin
|
||||||
// last cycle
|
// last cycle
|
||||||
s_axis_tready_next = 1'b0;
|
s_axis_tready_next = frame_next; // drop frame
|
||||||
|
|
||||||
output_data_next = fcs_output_data_1;
|
output_data_next = fcs_output_data_1;
|
||||||
output_type_next = fcs_output_type_1;
|
output_type_next = fcs_output_type_1;
|
||||||
@ -573,8 +581,24 @@ always @* begin
|
|||||||
end
|
end
|
||||||
end
|
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
|
STATE_IFG: begin
|
||||||
// send IFG
|
// 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
|
if (ifg_count_reg > 8'd8) begin
|
||||||
ifg_count_next = ifg_count_reg - 8'd8;
|
ifg_count_next = ifg_count_reg - 8'd8;
|
||||||
end else begin
|
end else begin
|
||||||
@ -584,7 +608,7 @@ always @* begin
|
|||||||
reset_crc = 1'b1;
|
reset_crc = 1'b1;
|
||||||
|
|
||||||
if (ENABLE_DIC) begin
|
if (ENABLE_DIC) begin
|
||||||
if (ifg_count_next > 8'd7) begin
|
if (ifg_count_next > 8'd7 || frame_reg) begin
|
||||||
state_next = STATE_IFG;
|
state_next = STATE_IFG;
|
||||||
end else begin
|
end else begin
|
||||||
if (ifg_count_next >= 8'd4) begin
|
if (ifg_count_next >= 8'd4) begin
|
||||||
@ -599,7 +623,7 @@ always @* begin
|
|||||||
state_next = STATE_IDLE;
|
state_next = STATE_IDLE;
|
||||||
end
|
end
|
||||||
end else begin
|
end else begin
|
||||||
if (ifg_count_next > 8'd4) begin
|
if (ifg_count_next > 8'd4 || frame_reg) begin
|
||||||
state_next = STATE_IFG;
|
state_next = STATE_IFG;
|
||||||
end else begin
|
end else begin
|
||||||
s_axis_tready_next = 1'b1;
|
s_axis_tready_next = 1'b1;
|
||||||
@ -608,53 +632,6 @@ always @* begin
|
|||||||
end
|
end
|
||||||
end
|
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
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -663,6 +640,8 @@ always @(posedge clk) begin
|
|||||||
|
|
||||||
swap_lanes_reg <= swap_lanes_next;
|
swap_lanes_reg <= swap_lanes_next;
|
||||||
|
|
||||||
|
frame_reg <= frame_next;
|
||||||
|
frame_error_reg <= frame_error_next;
|
||||||
frame_min_count_reg <= frame_min_count_next;
|
frame_min_count_reg <= frame_min_count_next;
|
||||||
|
|
||||||
ifg_count_reg <= ifg_count_next;
|
ifg_count_reg <= ifg_count_next;
|
||||||
@ -788,6 +767,8 @@ always @(posedge clk) begin
|
|||||||
if (rst) begin
|
if (rst) begin
|
||||||
state_reg <= STATE_IDLE;
|
state_reg <= STATE_IDLE;
|
||||||
|
|
||||||
|
frame_reg <= 1'b0;
|
||||||
|
|
||||||
swap_lanes_reg <= 1'b0;
|
swap_lanes_reg <= 1'b0;
|
||||||
|
|
||||||
ifg_count_reg <= 8'd0;
|
ifg_count_reg <= 8'd0;
|
||||||
|
@ -111,8 +111,7 @@ localparam [2:0]
|
|||||||
STATE_LAST = 3'd3,
|
STATE_LAST = 3'd3,
|
||||||
STATE_PAD = 3'd4,
|
STATE_PAD = 3'd4,
|
||||||
STATE_FCS = 3'd5,
|
STATE_FCS = 3'd5,
|
||||||
STATE_WAIT_END = 3'd6,
|
STATE_IFG = 3'd6;
|
||||||
STATE_IFG = 3'd7;
|
|
||||||
|
|
||||||
reg [2:0] state_reg = STATE_IDLE, state_next;
|
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 mii_odd_reg = 1'b0, mii_odd_next;
|
||||||
reg [3:0] mii_msn_reg = 4'b0, mii_msn_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 [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 [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_odd_next = mii_odd_reg;
|
||||||
mii_msn_next = mii_msn_reg;
|
mii_msn_next = mii_msn_reg;
|
||||||
|
|
||||||
|
frame_next = frame_reg;
|
||||||
|
frame_error_next = frame_error_reg;
|
||||||
frame_ptr_next = frame_ptr_reg;
|
frame_ptr_next = frame_ptr_reg;
|
||||||
frame_min_count_next = frame_min_count_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_tag_next = m_axis_ptp_ts_tag_reg;
|
||||||
m_axis_ptp_ts_valid_next = 1'b0;
|
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
|
if (start_packet_reg && PTP_TS_ENABLE) begin
|
||||||
m_axis_ptp_ts_next = ptp_ts;
|
m_axis_ptp_ts_next = ptp_ts;
|
||||||
if (PTP_TS_CTRL_IN_TUSER) begin
|
if (PTP_TS_CTRL_IN_TUSER) begin
|
||||||
@ -209,10 +208,18 @@ always @* begin
|
|||||||
end
|
end
|
||||||
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_int_next = start_packet_int_reg;
|
||||||
start_packet_next = 1'b0;
|
start_packet_next = 1'b0;
|
||||||
error_underflow_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
|
if (!clk_enable) begin
|
||||||
// clock disabled - hold state and outputs
|
// clock disabled - hold state and outputs
|
||||||
gmii_txd_next = gmii_txd_reg;
|
gmii_txd_next = gmii_txd_reg;
|
||||||
@ -239,6 +246,7 @@ always @* begin
|
|||||||
mii_odd_next = 1'b0;
|
mii_odd_next = 1'b0;
|
||||||
frame_ptr_next = 1;
|
frame_ptr_next = 1;
|
||||||
|
|
||||||
|
frame_error_next = 1'b0;
|
||||||
frame_min_count_next = MIN_FRAME_LENGTH-4-1;
|
frame_min_count_next = MIN_FRAME_LENGTH-4-1;
|
||||||
|
|
||||||
if (s_axis_tvalid && cfg_tx_enable) begin
|
if (s_axis_tvalid && cfg_tx_enable) begin
|
||||||
@ -299,29 +307,21 @@ always @* begin
|
|||||||
|
|
||||||
s_tdata_next = s_axis_tdata;
|
s_tdata_next = s_axis_tdata;
|
||||||
|
|
||||||
if (s_axis_tvalid) begin
|
if (!s_axis_tvalid || s_axis_tlast) begin
|
||||||
if (s_axis_tlast) begin
|
s_axis_tready_next = frame_next; // drop frame
|
||||||
s_axis_tready_next = !s_axis_tready_reg;
|
frame_error_next = !s_axis_tvalid || s_axis_tuser[0];
|
||||||
if (s_axis_tuser[0]) begin
|
error_underflow_next = !s_axis_tvalid;
|
||||||
gmii_tx_er_next = 1'b1;
|
|
||||||
state_next = STATE_IFG;
|
state_next = STATE_LAST;
|
||||||
end else begin
|
|
||||||
state_next = STATE_LAST;
|
|
||||||
end
|
|
||||||
end else begin
|
|
||||||
state_next = STATE_PAYLOAD;
|
|
||||||
end
|
|
||||||
end else begin
|
end else begin
|
||||||
// tvalid deassert, fail frame
|
state_next = STATE_PAYLOAD;
|
||||||
gmii_tx_er_next = 1'b1;
|
|
||||||
error_underflow_next = 1'b1;
|
|
||||||
state_next = STATE_WAIT_END;
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
STATE_LAST: begin
|
STATE_LAST: begin
|
||||||
// last payload word
|
// last payload word
|
||||||
|
|
||||||
update_crc = 1'b1;
|
update_crc = 1'b1;
|
||||||
|
s_axis_tready_next = 1'b0;
|
||||||
|
|
||||||
mii_odd_next = 1'b1;
|
mii_odd_next = 1'b1;
|
||||||
|
|
||||||
@ -339,6 +339,7 @@ always @* begin
|
|||||||
end
|
end
|
||||||
STATE_PAD: begin
|
STATE_PAD: begin
|
||||||
// send padding
|
// send padding
|
||||||
|
s_axis_tready_next = frame_next; // drop frame
|
||||||
|
|
||||||
update_crc = 1'b1;
|
update_crc = 1'b1;
|
||||||
mii_odd_next = 1'b1;
|
mii_odd_next = 1'b1;
|
||||||
@ -358,6 +359,7 @@ always @* begin
|
|||||||
end
|
end
|
||||||
STATE_FCS: begin
|
STATE_FCS: begin
|
||||||
// send FCS
|
// send FCS
|
||||||
|
s_axis_tready_next = frame_next; // drop frame
|
||||||
|
|
||||||
mii_odd_next = 1'b1;
|
mii_odd_next = 1'b1;
|
||||||
frame_ptr_next = frame_ptr_reg + 1;
|
frame_ptr_next = frame_ptr_reg + 1;
|
||||||
@ -369,6 +371,7 @@ always @* begin
|
|||||||
2'd3: gmii_txd_next = ~crc_state[31:24];
|
2'd3: gmii_txd_next = ~crc_state[31:24];
|
||||||
endcase
|
endcase
|
||||||
gmii_tx_en_next = 1'b1;
|
gmii_tx_en_next = 1'b1;
|
||||||
|
gmii_tx_er_next = frame_error_reg;
|
||||||
|
|
||||||
if (frame_ptr_reg < 3) begin
|
if (frame_ptr_reg < 3) begin
|
||||||
state_next = STATE_FCS;
|
state_next = STATE_FCS;
|
||||||
@ -377,35 +380,14 @@ always @* begin
|
|||||||
state_next = STATE_IFG;
|
state_next = STATE_IFG;
|
||||||
end
|
end
|
||||||
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
|
STATE_IFG: begin
|
||||||
// send IFG
|
// send IFG
|
||||||
|
s_axis_tready_next = frame_next; // drop frame
|
||||||
|
|
||||||
mii_odd_next = 1'b1;
|
mii_odd_next = 1'b1;
|
||||||
frame_ptr_next = frame_ptr_reg + 1;
|
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;
|
state_next = STATE_IFG;
|
||||||
end else begin
|
end else begin
|
||||||
state_next = STATE_IDLE;
|
state_next = STATE_IDLE;
|
||||||
@ -423,6 +405,8 @@ end
|
|||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
state_reg <= state_next;
|
state_reg <= state_next;
|
||||||
|
|
||||||
|
frame_reg <= frame_next;
|
||||||
|
frame_error_reg <= frame_error_next;
|
||||||
frame_ptr_reg <= frame_ptr_next;
|
frame_ptr_reg <= frame_ptr_next;
|
||||||
frame_min_count_reg <= frame_min_count_next;
|
frame_min_count_reg <= frame_min_count_next;
|
||||||
|
|
||||||
@ -454,6 +438,8 @@ always @(posedge clk) begin
|
|||||||
if (rst) begin
|
if (rst) begin
|
||||||
state_reg <= STATE_IDLE;
|
state_reg <= STATE_IDLE;
|
||||||
|
|
||||||
|
frame_reg <= 1'b0;
|
||||||
|
|
||||||
s_axis_tready_reg <= 1'b0;
|
s_axis_tready_reg <= 1'b0;
|
||||||
|
|
||||||
m_axis_ptp_ts_valid_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_1 = 4'd4,
|
||||||
STATE_FCS_2 = 4'd5,
|
STATE_FCS_2 = 4'd5,
|
||||||
STATE_FCS_3 = 4'd6,
|
STATE_FCS_3 = 4'd6,
|
||||||
STATE_IFG = 4'd7,
|
STATE_ERR = 4'd7,
|
||||||
STATE_WAIT_END = 4'd8;
|
STATE_IFG = 4'd8;
|
||||||
|
|
||||||
reg [3:0] state_reg = STATE_IDLE, state_next;
|
reg [3:0] state_reg = STATE_IDLE, state_next;
|
||||||
|
|
||||||
@ -144,6 +144,8 @@ reg [7:0] ifg_offset;
|
|||||||
|
|
||||||
reg extra_cycle;
|
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 [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 [7:0] ifg_count_reg = 8'd0, ifg_count_next;
|
||||||
@ -263,6 +265,8 @@ always @* begin
|
|||||||
reset_crc = 1'b0;
|
reset_crc = 1'b0;
|
||||||
update_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;
|
frame_min_count_next = frame_min_count_reg;
|
||||||
|
|
||||||
ifg_count_next = ifg_count_reg;
|
ifg_count_next = ifg_count_reg;
|
||||||
@ -295,9 +299,14 @@ always @* begin
|
|||||||
start_packet_next = 1'b0;
|
start_packet_next = 1'b0;
|
||||||
error_underflow_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)
|
case (state_reg)
|
||||||
STATE_IDLE: begin
|
STATE_IDLE: begin
|
||||||
// idle state - wait for data
|
// idle state - wait for data
|
||||||
|
frame_error_next = 1'b0;
|
||||||
frame_min_count_next = MIN_FRAME_LENGTH-4-CTRL_WIDTH;
|
frame_min_count_next = MIN_FRAME_LENGTH-4-CTRL_WIDTH;
|
||||||
reset_crc = 1'b1;
|
reset_crc = 1'b1;
|
||||||
|
|
||||||
@ -351,46 +360,31 @@ always @* begin
|
|||||||
s_tdata_next = s_axis_tdata_masked;
|
s_tdata_next = s_axis_tdata_masked;
|
||||||
s_empty_next = keep2empty(s_axis_tkeep);
|
s_empty_next = keep2empty(s_axis_tkeep);
|
||||||
|
|
||||||
if (s_axis_tvalid) begin
|
if (!s_axis_tvalid || s_axis_tlast) begin
|
||||||
if (s_axis_tlast) begin
|
s_axis_tready_next = frame_next; // drop frame
|
||||||
s_axis_tready_next = 1'b0;
|
frame_error_next = !s_axis_tvalid || s_axis_tuser[0];
|
||||||
if (s_axis_tuser[0]) begin
|
error_underflow_next = !s_axis_tvalid;
|
||||||
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 (ENABLE_PADDING && frame_min_count_reg) begin
|
if (ENABLE_PADDING && frame_min_count_reg) begin
|
||||||
if (frame_min_count_reg > CTRL_WIDTH) begin
|
if (frame_min_count_reg > CTRL_WIDTH) begin
|
||||||
s_empty_next = 0;
|
s_empty_next = 0;
|
||||||
state_next = STATE_PAD;
|
state_next = STATE_PAD;
|
||||||
end else begin
|
end else begin
|
||||||
if (keep2empty(s_axis_tkeep) > CTRL_WIDTH-frame_min_count_reg) begin
|
if (keep2empty(s_axis_tkeep) > CTRL_WIDTH-frame_min_count_reg) begin
|
||||||
s_empty_next = CTRL_WIDTH-frame_min_count_reg;
|
s_empty_next = CTRL_WIDTH-frame_min_count_reg;
|
||||||
end
|
|
||||||
state_next = STATE_FCS_1;
|
|
||||||
end
|
|
||||||
end else begin
|
|
||||||
state_next = STATE_FCS_1;
|
|
||||||
end
|
end
|
||||||
|
state_next = STATE_FCS_1;
|
||||||
end
|
end
|
||||||
end else begin
|
end else begin
|
||||||
state_next = STATE_PAYLOAD;
|
state_next = STATE_FCS_1;
|
||||||
end
|
end
|
||||||
end else begin
|
end else begin
|
||||||
// tvalid deassert, fail frame
|
state_next = STATE_PAYLOAD;
|
||||||
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;
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
STATE_PAD: begin
|
STATE_PAD: begin
|
||||||
// pad frame to MIN_FRAME_LENGTH
|
// 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_txd_next = s_tdata_reg;
|
||||||
xgmii_txc_next = {CTRL_WIDTH{1'b0}};
|
xgmii_txc_next = {CTRL_WIDTH{1'b0}};
|
||||||
@ -411,7 +405,7 @@ always @* begin
|
|||||||
end
|
end
|
||||||
STATE_FCS_1: begin
|
STATE_FCS_1: begin
|
||||||
// last cycle
|
// last cycle
|
||||||
s_axis_tready_next = 1'b0;
|
s_axis_tready_next = frame_next; // drop frame
|
||||||
|
|
||||||
xgmii_txd_next = fcs_output_txd_0;
|
xgmii_txd_next = fcs_output_txd_0;
|
||||||
xgmii_txc_next = fcs_output_txc_0;
|
xgmii_txc_next = fcs_output_txc_0;
|
||||||
@ -419,11 +413,15 @@ always @* begin
|
|||||||
update_crc = 1'b1;
|
update_crc = 1'b1;
|
||||||
|
|
||||||
ifg_count_next = (cfg_ifg > 8'd12 ? cfg_ifg : 8'd12) - ifg_offset + deficit_idle_count_reg;
|
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
|
end
|
||||||
STATE_FCS_2: begin
|
STATE_FCS_2: begin
|
||||||
// last cycle
|
// last cycle
|
||||||
s_axis_tready_next = 1'b0;
|
s_axis_tready_next = frame_next; // drop frame
|
||||||
|
|
||||||
xgmii_txd_next = fcs_output_txd_1;
|
xgmii_txd_next = fcs_output_txd_1;
|
||||||
xgmii_txc_next = fcs_output_txc_1;
|
xgmii_txc_next = fcs_output_txc_1;
|
||||||
@ -436,7 +434,7 @@ always @* begin
|
|||||||
end
|
end
|
||||||
STATE_FCS_3: begin
|
STATE_FCS_3: begin
|
||||||
// last cycle
|
// 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_txd_next = {{3{XGMII_IDLE}}, XGMII_TERM};
|
||||||
xgmii_txc_next = {CTRL_WIDTH{1'b1}};
|
xgmii_txc_next = {CTRL_WIDTH{1'b1}};
|
||||||
@ -458,8 +456,21 @@ always @* begin
|
|||||||
end
|
end
|
||||||
end
|
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
|
STATE_IFG: begin
|
||||||
// send IFG
|
// send IFG
|
||||||
|
s_axis_tready_next = frame_next; // drop frame
|
||||||
|
|
||||||
// XGMII idle
|
// XGMII idle
|
||||||
xgmii_txd_next = {CTRL_WIDTH{XGMII_IDLE}};
|
xgmii_txd_next = {CTRL_WIDTH{XGMII_IDLE}};
|
||||||
@ -472,7 +483,7 @@ always @* begin
|
|||||||
end
|
end
|
||||||
|
|
||||||
if (ENABLE_DIC) begin
|
if (ENABLE_DIC) begin
|
||||||
if (ifg_count_next > 8'd3) begin
|
if (ifg_count_next > 8'd3 || frame_reg) begin
|
||||||
state_next = STATE_IFG;
|
state_next = STATE_IFG;
|
||||||
end else begin
|
end else begin
|
||||||
deficit_idle_count_next = ifg_count_next;
|
deficit_idle_count_next = ifg_count_next;
|
||||||
@ -480,59 +491,21 @@ always @* begin
|
|||||||
state_next = STATE_IDLE;
|
state_next = STATE_IDLE;
|
||||||
end
|
end
|
||||||
end else begin
|
end else begin
|
||||||
if (ifg_count_next > 8'd0) begin
|
if (ifg_count_next > 8'd0 || frame_reg) begin
|
||||||
state_next = STATE_IFG;
|
state_next = STATE_IFG;
|
||||||
end else begin
|
end else begin
|
||||||
state_next = STATE_IDLE;
|
state_next = STATE_IDLE;
|
||||||
end
|
end
|
||||||
end
|
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
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
always @(posedge clk) begin
|
always @(posedge clk) begin
|
||||||
state_reg <= state_next;
|
state_reg <= state_next;
|
||||||
|
|
||||||
|
frame_reg <= frame_next;
|
||||||
|
frame_error_reg <= frame_error_next;
|
||||||
frame_min_count_reg <= frame_min_count_next;
|
frame_min_count_reg <= frame_min_count_next;
|
||||||
|
|
||||||
ifg_count_reg <= ifg_count_next;
|
ifg_count_reg <= ifg_count_next;
|
||||||
@ -568,6 +541,8 @@ always @(posedge clk) begin
|
|||||||
if (rst) begin
|
if (rst) begin
|
||||||
state_reg <= STATE_IDLE;
|
state_reg <= STATE_IDLE;
|
||||||
|
|
||||||
|
frame_reg <= 1'b0;
|
||||||
|
|
||||||
ifg_count_reg <= 8'd0;
|
ifg_count_reg <= 8'd0;
|
||||||
deficit_idle_count_reg <= 2'd0;
|
deficit_idle_count_reg <= 2'd0;
|
||||||
|
|
||||||
|
@ -121,8 +121,8 @@ localparam [2:0]
|
|||||||
STATE_PAD = 3'd2,
|
STATE_PAD = 3'd2,
|
||||||
STATE_FCS_1 = 3'd3,
|
STATE_FCS_1 = 3'd3,
|
||||||
STATE_FCS_2 = 3'd4,
|
STATE_FCS_2 = 3'd4,
|
||||||
STATE_IFG = 3'd5,
|
STATE_ERR = 3'd5,
|
||||||
STATE_WAIT_END = 3'd6;
|
STATE_IFG = 3'd6;
|
||||||
|
|
||||||
reg [2:0] state_reg = STATE_IDLE, state_next;
|
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 [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 [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 [7:0] ifg_count_reg = 8'd0, ifg_count_next;
|
||||||
@ -298,6 +300,8 @@ always @* begin
|
|||||||
|
|
||||||
swap_lanes_next = swap_lanes_reg;
|
swap_lanes_next = swap_lanes_reg;
|
||||||
|
|
||||||
|
frame_next = frame_reg;
|
||||||
|
frame_error_next = frame_error_reg;
|
||||||
frame_min_count_next = frame_min_count_reg;
|
frame_min_count_next = frame_min_count_reg;
|
||||||
|
|
||||||
ifg_count_next = ifg_count_reg;
|
ifg_count_next = ifg_count_reg;
|
||||||
@ -322,6 +326,10 @@ always @* begin
|
|||||||
start_packet_next = 2'b00;
|
start_packet_next = 2'b00;
|
||||||
error_underflow_next = 1'b0;
|
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
|
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_valid_next = m_axis_ptp_ts_valid_int_reg;
|
||||||
m_axis_ptp_ts_adj_next[15:0] = m_axis_ptp_ts_reg[15:0];
|
m_axis_ptp_ts_adj_next[15:0] = m_axis_ptp_ts_reg[15:0];
|
||||||
@ -333,6 +341,7 @@ always @* begin
|
|||||||
case (state_reg)
|
case (state_reg)
|
||||||
STATE_IDLE: begin
|
STATE_IDLE: begin
|
||||||
// idle state - wait for data
|
// idle state - wait for data
|
||||||
|
frame_error_next = 1'b0;
|
||||||
frame_min_count_next = MIN_FRAME_LENGTH-4-CTRL_WIDTH;
|
frame_min_count_next = MIN_FRAME_LENGTH-4-CTRL_WIDTH;
|
||||||
reset_crc = 1'b1;
|
reset_crc = 1'b1;
|
||||||
s_axis_tready_next = cfg_tx_enable;
|
s_axis_tready_next = cfg_tx_enable;
|
||||||
@ -414,46 +423,39 @@ always @* begin
|
|||||||
s_tdata_next = s_axis_tdata_masked;
|
s_tdata_next = s_axis_tdata_masked;
|
||||||
s_empty_next = keep2empty(s_axis_tkeep);
|
s_empty_next = keep2empty(s_axis_tkeep);
|
||||||
|
|
||||||
if (s_axis_tvalid) begin
|
if (!s_axis_tvalid || s_axis_tlast) begin
|
||||||
if (s_axis_tlast) begin
|
s_axis_tready_next = frame_next; // drop frame
|
||||||
s_axis_tready_next = 1'b0;
|
frame_error_next = !s_axis_tvalid || s_axis_tuser[0];
|
||||||
if (s_axis_tuser[0]) begin
|
error_underflow_next = !s_axis_tvalid;
|
||||||
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 (ENABLE_PADDING && frame_min_count_reg) begin
|
if (ENABLE_PADDING && frame_min_count_reg) begin
|
||||||
if (frame_min_count_reg > CTRL_WIDTH) begin
|
if (frame_min_count_reg > CTRL_WIDTH) begin
|
||||||
s_empty_next = 0;
|
s_empty_next = 0;
|
||||||
state_next = STATE_PAD;
|
state_next = STATE_PAD;
|
||||||
end else begin
|
end else begin
|
||||||
if (keep2empty(s_axis_tkeep) > CTRL_WIDTH-frame_min_count_reg) begin
|
if (keep2empty(s_axis_tkeep) > CTRL_WIDTH-frame_min_count_reg) begin
|
||||||
s_empty_next = CTRL_WIDTH-frame_min_count_reg;
|
s_empty_next = CTRL_WIDTH-frame_min_count_reg;
|
||||||
end
|
end
|
||||||
state_next = STATE_FCS_1;
|
if (frame_error_next) begin
|
||||||
end
|
state_next = STATE_ERR;
|
||||||
end else begin
|
end else begin
|
||||||
state_next = STATE_FCS_1;
|
state_next = STATE_FCS_1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end else begin
|
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
|
||||||
end else begin
|
end else begin
|
||||||
// tvalid deassert, fail frame
|
state_next = STATE_PAYLOAD;
|
||||||
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;
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
STATE_PAD: begin
|
STATE_PAD: begin
|
||||||
// pad frame to MIN_FRAME_LENGTH
|
// 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_txd_next = s_tdata_reg;
|
||||||
xgmii_txc_next = {CTRL_WIDTH{1'b0}};
|
xgmii_txc_next = {CTRL_WIDTH{1'b0}};
|
||||||
@ -469,12 +471,16 @@ always @* begin
|
|||||||
end else begin
|
end else begin
|
||||||
frame_min_count_next = 0;
|
frame_min_count_next = 0;
|
||||||
s_empty_next = CTRL_WIDTH-frame_min_count_reg;
|
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
|
||||||
end
|
end
|
||||||
STATE_FCS_1: begin
|
STATE_FCS_1: begin
|
||||||
// last cycle
|
// last cycle
|
||||||
s_axis_tready_next = 1'b0;
|
s_axis_tready_next = frame_next; // drop frame
|
||||||
|
|
||||||
xgmii_txd_next = fcs_output_txd_0;
|
xgmii_txd_next = fcs_output_txd_0;
|
||||||
xgmii_txc_next = fcs_output_txc_0;
|
xgmii_txc_next = fcs_output_txc_0;
|
||||||
@ -490,7 +496,7 @@ always @* begin
|
|||||||
end
|
end
|
||||||
STATE_FCS_2: begin
|
STATE_FCS_2: begin
|
||||||
// last cycle
|
// last cycle
|
||||||
s_axis_tready_next = 1'b0;
|
s_axis_tready_next = frame_next; // drop frame
|
||||||
|
|
||||||
xgmii_txd_next = fcs_output_txd_1;
|
xgmii_txd_next = fcs_output_txd_1;
|
||||||
xgmii_txc_next = fcs_output_txc_1;
|
xgmii_txc_next = fcs_output_txc_1;
|
||||||
@ -520,8 +526,21 @@ always @* begin
|
|||||||
end
|
end
|
||||||
end
|
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
|
STATE_IFG: begin
|
||||||
// send IFG
|
// send IFG
|
||||||
|
s_axis_tready_next = frame_next; // drop frame
|
||||||
|
|
||||||
// XGMII idle
|
// XGMII idle
|
||||||
xgmii_txd_next = {CTRL_WIDTH{XGMII_IDLE}};
|
xgmii_txd_next = {CTRL_WIDTH{XGMII_IDLE}};
|
||||||
@ -534,7 +553,7 @@ always @* begin
|
|||||||
end
|
end
|
||||||
|
|
||||||
if (ENABLE_DIC) begin
|
if (ENABLE_DIC) begin
|
||||||
if (ifg_count_next > 8'd7) begin
|
if (ifg_count_next > 8'd7 || frame_reg) begin
|
||||||
state_next = STATE_IFG;
|
state_next = STATE_IFG;
|
||||||
end else begin
|
end else begin
|
||||||
if (ifg_count_next >= 8'd4) begin
|
if (ifg_count_next >= 8'd4) begin
|
||||||
@ -549,7 +568,7 @@ always @* begin
|
|||||||
state_next = STATE_IDLE;
|
state_next = STATE_IDLE;
|
||||||
end
|
end
|
||||||
end else begin
|
end else begin
|
||||||
if (ifg_count_next > 8'd4) begin
|
if (ifg_count_next > 8'd4 || frame_reg) begin
|
||||||
state_next = STATE_IFG;
|
state_next = STATE_IFG;
|
||||||
end else begin
|
end else begin
|
||||||
s_axis_tready_next = cfg_tx_enable;
|
s_axis_tready_next = cfg_tx_enable;
|
||||||
@ -558,55 +577,6 @@ always @* begin
|
|||||||
end
|
end
|
||||||
end
|
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
|
endcase
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -615,6 +585,8 @@ always @(posedge clk) begin
|
|||||||
|
|
||||||
swap_lanes_reg <= swap_lanes_next;
|
swap_lanes_reg <= swap_lanes_next;
|
||||||
|
|
||||||
|
frame_reg <= frame_next;
|
||||||
|
frame_error_reg <= frame_error_next;
|
||||||
frame_min_count_reg <= frame_min_count_next;
|
frame_min_count_reg <= frame_min_count_next;
|
||||||
|
|
||||||
ifg_count_reg <= ifg_count_next;
|
ifg_count_reg <= ifg_count_next;
|
||||||
@ -665,6 +637,8 @@ always @(posedge clk) begin
|
|||||||
if (rst) begin
|
if (rst) begin
|
||||||
state_reg <= STATE_IDLE;
|
state_reg <= STATE_IDLE;
|
||||||
|
|
||||||
|
frame_reg <= 1'b0;
|
||||||
|
|
||||||
swap_lanes_reg <= 1'b0;
|
swap_lanes_reg <= 1'b0;
|
||||||
|
|
||||||
ifg_count_reg <= 8'd0;
|
ifg_count_reg <= 8'd0;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user