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

Optimize FCS verification in 10G/25G MAC modules

Signed-off-by: Alex Forencich <alex@alexforencich.com>
This commit is contained in:
Alex Forencich 2023-01-13 15:47:30 -08:00
parent 7a0e88ffea
commit cb1dc8fb15
3 changed files with 175 additions and 215 deletions

View File

@ -163,7 +163,6 @@ reg [1:0] state_reg = STATE_IDLE, state_next;
// datapath control signals
reg reset_crc;
reg update_crc_last;
reg lanes_swapped = 1'b0;
reg [31:0] swap_data = 32'd0;
@ -171,9 +170,10 @@ reg [31:0] swap_data = 32'd0;
reg delay_type_valid = 1'b0;
reg [3:0] delay_type = INPUT_TYPE_IDLE;
reg [DATA_WIDTH-1:0] encoded_rx_data_masked = {DATA_WIDTH{1'b0}};
reg [DATA_WIDTH-1:0] input_data_d0 = {DATA_WIDTH{1'b0}};
reg [DATA_WIDTH-1:0] input_data_d1 = {DATA_WIDTH{1'b0}};
reg [DATA_WIDTH-1:0] input_data_crc = {DATA_WIDTH{1'b0}};
reg [3:0] input_type_d0 = INPUT_TYPE_IDLE;
reg [3:0] input_type_d1 = INPUT_TYPE_IDLE;
@ -194,17 +194,20 @@ reg [PTP_TS_WIDTH-1:0] ptp_ts_adj_reg = 0;
reg ptp_ts_borrow_reg = 0;
reg [31:0] crc_state = 32'hFFFFFFFF;
reg [31:0] crc_state3 = 32'hFFFFFFFF;
wire [31:0] crc_next[7:0];
wire [31:0] crc_next;
wire crc_valid0 = crc_next[0] == ~32'h2144df1c;
wire crc_valid1 = crc_next[1] == ~32'h2144df1c;
wire crc_valid2 = crc_next[2] == ~32'h2144df1c;
wire crc_valid3 = crc_next[3] == ~32'h2144df1c;
wire crc_valid7 = crc_next[7] == ~32'h2144df1c;
wire [7:0] crc_valid;
reg [7:0] crc_valid_save;
reg crc_valid7_save = 1'b0;
assign crc_valid[7] = crc_next == ~32'h2144df1c;
assign crc_valid[6] = crc_next == ~32'hc622f71d;
assign crc_valid[5] = crc_next == ~32'hb1c2a1a3;
assign crc_valid[4] = crc_next == ~32'h9d6cdf7e;
assign crc_valid[3] = crc_next == ~32'h6522df69;
assign crc_valid[2] = crc_next == ~32'he60914ae;
assign crc_valid[1] = crc_next == ~32'he38a6876;
assign crc_valid[0] = crc_next == ~32'h6b87b1ec;
assign m_axis_tdata = m_axis_tdata_reg;
assign m_axis_tkeep = m_axis_tkeep_reg;
@ -217,29 +220,6 @@ assign error_bad_frame = error_bad_frame_reg;
assign error_bad_fcs = error_bad_fcs_reg;
assign rx_bad_block = rx_bad_block_reg;
generate
genvar n;
for (n = 0; n < 4; n = n + 1) begin : crc
lfsr #(
.LFSR_WIDTH(32),
.LFSR_POLY(32'h4c11db7),
.LFSR_CONFIG("GALOIS"),
.LFSR_FEED_FORWARD(0),
.REVERSE(1),
.DATA_WIDTH(8*(n+1)),
.STYLE("AUTO")
)
eth_crc (
.data_in(input_data_crc[0 +: 8*(n+1)]),
.state_in(crc_state3),
.data_out(),
.state_out(crc_next[n])
);
end
endgenerate
lfsr #(
.LFSR_WIDTH(32),
.LFSR_POLY(32'h4c11db7),
@ -249,18 +229,42 @@ lfsr #(
.DATA_WIDTH(64),
.STYLE("AUTO")
)
eth_crc_64 (
eth_crc (
.data_in(input_data_d0),
.state_in(crc_state),
.data_out(),
.state_out(crc_next[7])
.state_out(crc_next)
);
// Mask input data
integer j;
always @* begin
// minimal checks of control info to simplify datapath logic, full checks performed later
if (encoded_rx_hdr[0] == 0) begin
encoded_rx_data_masked = encoded_rx_data;
end else if (encoded_rx_data[7]) begin
// terminate
case (encoded_rx_data[6:4])
3'd0: encoded_rx_data_masked = 64'd0;
3'd1: encoded_rx_data_masked = {56'd0, encoded_rx_data[15:8]};
3'd2: encoded_rx_data_masked = {48'd0, encoded_rx_data[23:8]};
3'd3: encoded_rx_data_masked = {40'd0, encoded_rx_data[31:8]};
3'd4: encoded_rx_data_masked = {32'd0, encoded_rx_data[39:8]};
3'd5: encoded_rx_data_masked = {24'd0, encoded_rx_data[47:8]};
3'd6: encoded_rx_data_masked = {16'd0, encoded_rx_data[55:8]};
3'd7: encoded_rx_data_masked = {8'd0, encoded_rx_data[63:8]};
endcase
end else begin
// start, OS, etc.
encoded_rx_data_masked = {encoded_rx_data[63:8], 8'd0};
end
end
always @* begin
state_next = STATE_IDLE;
reset_crc = 1'b0;
update_crc_last = 1'b0;
m_axis_tdata_next = input_data_d1;
m_axis_tkeep_next = 8'd0;
@ -300,7 +304,6 @@ always @* begin
if (input_type_d0[3]) begin
// INPUT_TYPE_TERM_*
reset_crc = 1'b1;
update_crc_last = 1'b1;
end
if (input_type_d0 == INPUT_TYPE_DATA) begin
@ -317,11 +320,11 @@ always @* begin
INPUT_TYPE_TERM_4: m_axis_tkeep_next = 8'b11111111;
endcase
m_axis_tlast_next = 1'b1;
if ((input_type_d0 == INPUT_TYPE_TERM_0 && crc_valid7_save) ||
(input_type_d0 == INPUT_TYPE_TERM_1 && crc_valid0) ||
(input_type_d0 == INPUT_TYPE_TERM_2 && crc_valid1) ||
(input_type_d0 == INPUT_TYPE_TERM_3 && crc_valid2) ||
(input_type_d0 == INPUT_TYPE_TERM_4 && crc_valid3)) begin
if ((input_type_d0 == INPUT_TYPE_TERM_0 && crc_valid_save[7]) ||
(input_type_d0 == INPUT_TYPE_TERM_1 && crc_valid[0]) ||
(input_type_d0 == INPUT_TYPE_TERM_2 && crc_valid[1]) ||
(input_type_d0 == INPUT_TYPE_TERM_3 && crc_valid[2]) ||
(input_type_d0 == INPUT_TYPE_TERM_4 && crc_valid[3])) begin
// CRC valid
end else begin
m_axis_tuser_next[0] = 1'b1;
@ -358,9 +361,9 @@ always @* begin
INPUT_TYPE_TERM_7: m_axis_tkeep_next = 8'b00000111;
endcase
if ((input_type_d1 == INPUT_TYPE_TERM_5 && crc_valid0) ||
(input_type_d1 == INPUT_TYPE_TERM_6 && crc_valid1) ||
(input_type_d1 == INPUT_TYPE_TERM_7 && crc_valid2)) begin
if ((input_type_d1 == INPUT_TYPE_TERM_5 && crc_valid_save[4]) ||
(input_type_d1 == INPUT_TYPE_TERM_6 && crc_valid_save[5]) ||
(input_type_d1 == INPUT_TYPE_TERM_7 && crc_valid_save[6])) begin
// CRC valid
end else begin
m_axis_tuser_next[0] = 1'b1;
@ -389,11 +392,7 @@ always @(posedge clk) begin
delay_type_valid <= 1'b0;
if (encoded_rx_hdr == SYNC_DATA) begin
swap_data <= encoded_rx_data[63:32];
end else begin
swap_data <= {8'd0, encoded_rx_data[63:40]};
end
swap_data <= encoded_rx_data_masked[63:32];
if (PTP_TS_ENABLE && PTP_TS_WIDTH == 96) begin
// ns field rollover
@ -407,8 +406,7 @@ always @(posedge clk) begin
lanes_swapped <= 1'b0;
start_packet_reg <= 2'b01;
input_type_d0 <= INPUT_TYPE_START_0;
input_data_d0 <= encoded_rx_data;
input_data_crc <= encoded_rx_data;
input_data_d0 <= encoded_rx_data_masked;
if (PTP_TS_WIDTH == 96) begin
ptp_ts_reg[45:0] <= ptp_ts[45:0] + (PTP_PERIOD_NS * 2**16 + PTP_PERIOD_FNS);
@ -426,8 +424,7 @@ always @(posedge clk) begin
end else begin
input_type_d0 <= INPUT_TYPE_IDLE;
end
input_data_d0 <= {encoded_rx_data[31:0], swap_data};
input_data_crc <= {encoded_rx_data[31:0], swap_data};
input_data_d0 <= {encoded_rx_data_masked[31:0], swap_data};
if (PTP_TS_WIDTH == 96) begin
ptp_ts_reg[45:0] <= ptp_ts[45:0] + (((PTP_PERIOD_NS * 2**16 + PTP_PERIOD_FNS) * 3) >> 1);
@ -471,13 +468,7 @@ always @(posedge clk) begin
rx_bad_block_reg <= 1'b1;
input_type_d0 <= INPUT_TYPE_ERROR;
end
if (encoded_rx_hdr == SYNC_DATA) begin
input_data_d0 <= {encoded_rx_data[31:0], swap_data};
input_data_crc <= {encoded_rx_data[31:0], swap_data};
end else begin
input_data_d0 <= {encoded_rx_data[39:8], swap_data};
input_data_crc <= {encoded_rx_data[39:8], swap_data};
end
input_data_d0 <= {encoded_rx_data_masked[31:0], swap_data};
end else begin
if (encoded_rx_hdr == SYNC_DATA) begin
input_type_d0 <= INPUT_TYPE_DATA;
@ -500,13 +491,7 @@ always @(posedge clk) begin
rx_bad_block_reg <= 1'b1;
input_type_d0 <= INPUT_TYPE_ERROR;
end
if (encoded_rx_hdr == SYNC_DATA) begin
input_data_d0 <= encoded_rx_data;
input_data_crc <= encoded_rx_data;
end else begin
input_data_d0 <= {8'd0, encoded_rx_data[63:8]};
input_data_crc <= {8'd0, encoded_rx_data[63:8]};
end
input_data_d0 <= encoded_rx_data_masked;
end
if (encoded_rx_hdr == SYNC_DATA) begin
@ -534,20 +519,10 @@ always @(posedge clk) begin
if (reset_crc) begin
crc_state <= 32'hFFFFFFFF;
end else begin
crc_state <= crc_next[7];
crc_state <= crc_next;
end
if (update_crc_last) begin
crc_state3 <= crc_next[3];
end else begin
crc_state3 <= crc_next[7];
end
crc_valid7_save <= crc_valid7;
if (state_next == STATE_LAST) begin
input_data_crc[31:0] <= input_data_crc[63:32];
end
crc_valid_save <= crc_valid;
if (rst) begin
state_reg <= STATE_IDLE;

View File

@ -108,13 +108,18 @@ reg reset_crc;
reg [3:0] last_cycle_tkeep_reg = 4'd0, last_cycle_tkeep_next;
reg [DATA_WIDTH-1:0] xgmii_rxd_masked = {DATA_WIDTH{1'b0}};
reg [CTRL_WIDTH-1:0] xgmii_term = {CTRL_WIDTH{1'b0}};
reg [DATA_WIDTH-1:0] xgmii_rxd_d0 = {DATA_WIDTH{1'b0}};
reg [DATA_WIDTH-1:0] xgmii_rxd_d1 = {DATA_WIDTH{1'b0}};
reg [DATA_WIDTH-1:0] xgmii_rxd_d2 = {DATA_WIDTH{1'b0}};
reg [CTRL_WIDTH-1:0] xgmii_rxc_d0 = {CTRL_WIDTH{1'b0}};
reg [CTRL_WIDTH-1:0] xgmii_rxc_d1 = {CTRL_WIDTH{1'b0}};
reg [CTRL_WIDTH-1:0] xgmii_rxc_d2 = {CTRL_WIDTH{1'b0}};
reg xgmii_start_d0 = 1'b0;
reg xgmii_start_d1 = 1'b0;
reg xgmii_start_d2 = 1'b0;
reg [DATA_WIDTH-1:0] m_axis_tdata_reg = {DATA_WIDTH{1'b0}}, m_axis_tdata_next;
reg [KEEP_WIDTH-1:0] m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}, m_axis_tkeep_next;
@ -128,17 +133,15 @@ reg error_bad_fcs_reg = 1'b0, error_bad_fcs_next;
reg [31:0] crc_state = 32'hFFFFFFFF;
wire [31:0] crc_next[3:0];
wire [31:0] crc_next;
wire crc_valid0 = crc_next[0] == ~32'h2144df1c;
wire crc_valid1 = crc_next[1] == ~32'h2144df1c;
wire crc_valid2 = crc_next[2] == ~32'h2144df1c;
wire crc_valid3 = crc_next[3] == ~32'h2144df1c;
wire [3:0] crc_valid;
reg [3:0] crc_valid_save;
reg crc_valid0_save = 1'b0;
reg crc_valid1_save = 1'b0;
reg crc_valid2_save = 1'b0;
reg crc_valid3_save = 1'b0;
assign crc_valid[3] = crc_next == ~32'h2144df1c;
assign crc_valid[2] = crc_next == ~32'hc622f71d;
assign crc_valid[1] = crc_next == ~32'hb1c2a1a3;
assign crc_valid[0] = crc_next == ~32'h9d6cdf7e;
assign m_axis_tdata = m_axis_tdata_reg;
assign m_axis_tkeep = m_axis_tkeep_reg;
@ -152,28 +155,31 @@ assign error_bad_fcs = error_bad_fcs_reg;
wire last_cycle = state_reg == STATE_LAST;
generate
genvar n;
lfsr #(
.LFSR_WIDTH(32),
.LFSR_POLY(32'h4c11db7),
.LFSR_CONFIG("GALOIS"),
.LFSR_FEED_FORWARD(0),
.REVERSE(1),
.DATA_WIDTH(32),
.STYLE("AUTO")
)
eth_crc (
.data_in(xgmii_rxd_d0),
.state_in(crc_state),
.data_out(),
.state_out(crc_next)
);
for (n = 0; n < 4; n = n + 1) begin : crc
lfsr #(
.LFSR_WIDTH(32),
.LFSR_POLY(32'h4c11db7),
.LFSR_CONFIG("GALOIS"),
.LFSR_FEED_FORWARD(0),
.REVERSE(1),
.DATA_WIDTH(8*(n+1)),
.STYLE("AUTO")
)
eth_crc (
.data_in(xgmii_rxd_d0[0 +: 8*(n+1)]),
.state_in(crc_state),
.data_out(),
.state_out(crc_next[n])
);
// Mask input data
integer j;
always @* begin
for (j = 0; j < 4; j = j + 1) begin
xgmii_rxd_masked[j*8 +: 8] = xgmii_rxc[j] ? 8'd0 : xgmii_rxd[j*8 +: 8];
xgmii_term[j] = xgmii_rxc[j] && (xgmii_rxd[j*8 +: 8] == XGMII_TERM);
end
endgenerate
end
// detect control characters
reg [3:0] detect_term = 4'd0;
@ -238,7 +244,7 @@ always @* begin
// idle state - wait for packet
reset_crc = 1'b1;
if (xgmii_rxc_d2[0] && xgmii_rxd_d2[7:0] == XGMII_START) begin
if (xgmii_start_d2) begin
// start condition
if (control_masked) begin
// control or error characters in first data word
@ -291,7 +297,7 @@ always @* begin
// end this cycle
m_axis_tkeep_next = 4'b1111;
m_axis_tlast_next = 1'b1;
if (detect_term[0] && crc_valid3_save) begin
if (detect_term[0] && crc_valid_save[3]) begin
// CRC valid
end else begin
m_axis_tuser_next[0] = 1'b1;
@ -317,9 +323,9 @@ always @* begin
reset_crc = 1'b1;
if ((detect_term_save[1] && crc_valid0_save) ||
(detect_term_save[2] && crc_valid1_save) ||
(detect_term_save[3] && crc_valid2_save)) begin
if ((detect_term_save[1] && crc_valid_save[0]) ||
(detect_term_save[2] && crc_valid_save[1]) ||
(detect_term_save[3] && crc_valid_save[2])) begin
// CRC valid
end else begin
m_axis_tuser_next[0] = 1'b1;
@ -347,30 +353,26 @@ always @(posedge clk) begin
last_cycle_tkeep_reg <= last_cycle_tkeep_next;
for (i = 0; i < 4; i = i + 1) begin
detect_term[i] <= xgmii_rxc[i] && (xgmii_rxd[i*8 +: 8] == XGMII_TERM);
end
detect_term <= xgmii_term;
detect_term_save <= detect_term;
if (reset_crc) begin
crc_state <= 32'hFFFFFFFF;
end else begin
crc_state <= crc_next[3];
crc_state <= crc_next;
end
crc_valid0_save <= crc_valid0;
crc_valid1_save <= crc_valid1;
crc_valid2_save <= crc_valid2;
crc_valid3_save <= crc_valid3;
crc_valid_save <= crc_valid;
xgmii_rxd_d0 <= xgmii_rxd;
xgmii_rxd_d0 <= xgmii_rxd_masked;
xgmii_rxc_d0 <= xgmii_rxc;
xgmii_rxd_d1 <= xgmii_rxd_d0;
xgmii_rxc_d1 <= xgmii_rxc_d0;
xgmii_rxc_d2 <= xgmii_rxc_d1;
xgmii_rxd_d2 <= xgmii_rxd_d1;
xgmii_start_d0 <= xgmii_rxc[0] && xgmii_rxd[7:0] == XGMII_START;
xgmii_start_d1 <= xgmii_start_d0;
xgmii_start_d2 <= xgmii_start_d1;
if (rst) begin
state_reg <= STATE_IDLE;
@ -381,7 +383,10 @@ always @(posedge clk) begin
error_bad_fcs_reg <= 1'b0;
xgmii_rxc_d0 <= {CTRL_WIDTH{1'b0}};
xgmii_rxc_d1 <= {CTRL_WIDTH{1'b0}};
xgmii_start_d0 <= 1'b0;
xgmii_start_d1 <= 1'b0;
xgmii_start_d2 <= 1'b0;
end
end

View File

@ -106,20 +106,25 @@ reg [1:0] state_reg = STATE_IDLE, state_next;
// datapath control signals
reg reset_crc;
reg update_crc_last;
reg [7:0] last_cycle_tkeep_reg = 8'd0, last_cycle_tkeep_next;
reg lanes_swapped = 1'b0;
reg [31:0] swap_rxd = 32'd0;
reg [3:0] swap_rxc = 4'd0;
reg [3:0] swap_rxc_term = 4'd0;
reg [DATA_WIDTH-1:0] xgmii_rxd_masked = {DATA_WIDTH{1'b0}};
reg [CTRL_WIDTH-1:0] xgmii_term = {CTRL_WIDTH{1'b0}};
reg [DATA_WIDTH-1:0] xgmii_rxd_d0 = {DATA_WIDTH{1'b0}};
reg [DATA_WIDTH-1:0] xgmii_rxd_d1 = {DATA_WIDTH{1'b0}};
reg [DATA_WIDTH-1:0] xgmii_rxd_crc = {DATA_WIDTH{1'b0}};
reg [CTRL_WIDTH-1:0] xgmii_rxc_d0 = {CTRL_WIDTH{1'b0}};
reg [CTRL_WIDTH-1:0] xgmii_rxc_d1 = {CTRL_WIDTH{1'b0}};
reg xgmii_start_swap = 1'b0;
reg xgmii_start_d0 = 1'b0;
reg xgmii_start_d1 = 1'b0;
reg [DATA_WIDTH-1:0] m_axis_tdata_reg = {DATA_WIDTH{1'b0}}, m_axis_tdata_next;
reg [KEEP_WIDTH-1:0] m_axis_tkeep_reg = {KEEP_WIDTH{1'b0}}, m_axis_tkeep_next;
@ -136,17 +141,20 @@ reg [PTP_TS_WIDTH-1:0] ptp_ts_adj_reg = 0;
reg ptp_ts_borrow_reg = 0;
reg [31:0] crc_state = 32'hFFFFFFFF;
reg [31:0] crc_state3 = 32'hFFFFFFFF;
wire [31:0] crc_next[7:0];
wire [31:0] crc_next;
wire crc_valid0 = crc_next[0] == ~32'h2144df1c;
wire crc_valid1 = crc_next[1] == ~32'h2144df1c;
wire crc_valid2 = crc_next[2] == ~32'h2144df1c;
wire crc_valid3 = crc_next[3] == ~32'h2144df1c;
wire crc_valid7 = crc_next[7] == ~32'h2144df1c;
wire [7:0] crc_valid;
reg [7:0] crc_valid_save;
reg crc_valid7_save = 1'b0;
assign crc_valid[7] = crc_next == ~32'h2144df1c;
assign crc_valid[6] = crc_next == ~32'hc622f71d;
assign crc_valid[5] = crc_next == ~32'hb1c2a1a3;
assign crc_valid[4] = crc_next == ~32'h9d6cdf7e;
assign crc_valid[3] = crc_next == ~32'h6522df69;
assign crc_valid[2] = crc_next == ~32'he60914ae;
assign crc_valid[1] = crc_next == ~32'he38a6876;
assign crc_valid[0] = crc_next == ~32'h6b87b1ec;
assign m_axis_tdata = m_axis_tdata_reg;
assign m_axis_tkeep = m_axis_tkeep_reg;
@ -158,29 +166,6 @@ assign start_packet = start_packet_reg;
assign error_bad_frame = error_bad_frame_reg;
assign error_bad_fcs = error_bad_fcs_reg;
generate
genvar n;
for (n = 0; n < 4; n = n + 1) begin : crc
lfsr #(
.LFSR_WIDTH(32),
.LFSR_POLY(32'h4c11db7),
.LFSR_CONFIG("GALOIS"),
.LFSR_FEED_FORWARD(0),
.REVERSE(1),
.DATA_WIDTH(8*(n+1)),
.STYLE("AUTO")
)
eth_crc (
.data_in(xgmii_rxd_crc[0 +: 8*(n+1)]),
.state_in(crc_state3),
.data_out(),
.state_out(crc_next[n])
);
end
endgenerate
lfsr #(
.LFSR_WIDTH(32),
.LFSR_POLY(32'h4c11db7),
@ -190,13 +175,23 @@ lfsr #(
.DATA_WIDTH(64),
.STYLE("AUTO")
)
eth_crc_64 (
.data_in(xgmii_rxd_crc),
eth_crc (
.data_in(xgmii_rxd_d0),
.state_in(crc_state),
.data_out(),
.state_out(crc_next[7])
.state_out(crc_next)
);
// Mask input data
integer j;
always @* begin
for (j = 0; j < 8; j = j + 1) begin
xgmii_rxd_masked[j*8 +: 8] = xgmii_rxc[j] ? 8'd0 : xgmii_rxd[j*8 +: 8];
xgmii_term[j] = xgmii_rxc[j] && (xgmii_rxd[j*8 +: 8] == XGMII_TERM);
end
end
// detect control characters
reg [7:0] detect_term = 8'd0;
@ -257,7 +252,6 @@ always @* begin
state_next = STATE_IDLE;
reset_crc = 1'b0;
update_crc_last = 1'b0;
last_cycle_tkeep_next = last_cycle_tkeep_reg;
@ -276,7 +270,7 @@ always @* begin
// idle state - wait for packet
reset_crc = 1'b1;
if (xgmii_rxc_d1[0] && xgmii_rxd_d1[7:0] == XGMII_START) begin
if (xgmii_start_d1) begin
// start condition
if (PTP_TS_ENABLE) begin
@ -312,7 +306,6 @@ always @* begin
if (detect_term) begin
reset_crc = 1'b1;
update_crc_last = 1'b1;
end
if (control_masked) begin
@ -327,11 +320,11 @@ always @* begin
// end this cycle
m_axis_tkeep_next = {tkeep_mask[3:0], 4'b1111};
m_axis_tlast_next = 1'b1;
if ((detect_term[0] && crc_valid7_save) ||
(detect_term[1] && crc_valid0) ||
(detect_term[2] && crc_valid1) ||
(detect_term[3] && crc_valid2) ||
(detect_term[4] && crc_valid3)) begin
if ((detect_term[0] && crc_valid_save[7]) ||
(detect_term[1] && crc_valid[0]) ||
(detect_term[2] && crc_valid[1]) ||
(detect_term[3] && crc_valid[2]) ||
(detect_term[4] && crc_valid[3])) begin
// CRC valid
end else begin
m_axis_tuser_next[0] = 1'b1;
@ -357,9 +350,9 @@ always @* begin
reset_crc = 1'b1;
if ((detect_term_save[5] && crc_valid0) ||
(detect_term_save[6] && crc_valid1) ||
(detect_term_save[7] && crc_valid2)) begin
if ((detect_term_save[5] && crc_valid_save[4]) ||
(detect_term_save[6] && crc_valid_save[5]) ||
(detect_term_save[7] && crc_valid_save[6])) begin
// CRC valid
end else begin
m_axis_tuser_next[0] = 1'b1;
@ -367,7 +360,7 @@ always @* begin
error_bad_fcs_next = 1'b1;
end
if (xgmii_rxc_d1[0] && xgmii_rxd_d1[7:0] == XGMII_START) begin
if (xgmii_start_d1) begin
// start condition
if (control_masked) begin
// control or error characters in first data word
@ -406,8 +399,12 @@ always @(posedge clk) begin
detect_term_save <= detect_term;
swap_rxd <= xgmii_rxd[63:32];
swap_rxd <= xgmii_rxd_masked[63:32];
swap_rxc <= xgmii_rxc[7:4];
swap_rxc_term <= xgmii_term[7:4];
xgmii_start_swap <= 1'b0;
xgmii_start_d0 <= xgmii_start_swap;
if (PTP_TS_ENABLE && PTP_TS_WIDTH == 96) begin
// ns field rollover
@ -420,13 +417,12 @@ always @(posedge clk) begin
if (xgmii_rxc[0] && xgmii_rxd[7:0] == XGMII_START) begin
lanes_swapped <= 1'b0;
start_packet_reg <= 2'b01;
xgmii_rxd_d0 <= xgmii_rxd;
xgmii_rxd_crc <= xgmii_rxd;
xgmii_rxd_d0 <= xgmii_rxd_masked;
xgmii_rxc_d0 <= xgmii_rxc;
xgmii_start_d0 <= 1'b1;
for (i = 0; i < 8; i = i + 1) begin
detect_term[i] <= xgmii_rxc[i] && (xgmii_rxd[i*8 +: 8] == XGMII_TERM);
end
detect_term <= xgmii_term;
if (PTP_TS_WIDTH == 96) begin
ptp_ts_reg[45:0] <= ptp_ts[45:0] + (PTP_PERIOD_NS * 2**16 + PTP_PERIOD_FNS);
@ -437,14 +433,12 @@ always @(posedge clk) begin
end else if (xgmii_rxc[4] && xgmii_rxd[39:32] == XGMII_START) begin
lanes_swapped <= 1'b1;
start_packet_reg <= 2'b10;
xgmii_rxd_d0 <= {xgmii_rxd[31:0], swap_rxd};
xgmii_rxd_crc <= {xgmii_rxd[31:0], swap_rxd};
xgmii_rxd_d0 <= {xgmii_rxd_masked[31:0], swap_rxd};
xgmii_rxc_d0 <= {xgmii_rxc[3:0], swap_rxc};
for (i = 0; i < 4; i = i + 1) begin
detect_term[i] <= swap_rxc[i] && (swap_rxd[i*8 +: 8] == XGMII_TERM);
detect_term[i+4] <= xgmii_rxc[i] && (xgmii_rxd[i*8 +: 8] == XGMII_TERM);
end
xgmii_start_swap <= 1'b1;
detect_term <= {xgmii_term[3:0], swap_rxc_term};
if (PTP_TS_WIDTH == 96) begin
ptp_ts_reg[45:0] <= ptp_ts[45:0] + (((PTP_PERIOD_NS * 2**16 + PTP_PERIOD_FNS) * 3) >> 1);
@ -453,44 +447,27 @@ always @(posedge clk) begin
ptp_ts_reg <= ptp_ts + (((PTP_PERIOD_NS * 2**16 + PTP_PERIOD_FNS) * 3) >> 1);
end
end else if (lanes_swapped) begin
xgmii_rxd_d0 <= {xgmii_rxd[31:0], swap_rxd};
xgmii_rxd_crc <= {xgmii_rxd[31:0], swap_rxd};
xgmii_rxd_d0 <= {xgmii_rxd_masked[31:0], swap_rxd};
xgmii_rxc_d0 <= {xgmii_rxc[3:0], swap_rxc};
for (i = 0; i < 4; i = i + 1) begin
detect_term[i] <= swap_rxc[i] && (swap_rxd[i*8 +: 8] == XGMII_TERM);
detect_term[i+4] <= xgmii_rxc[i] && (xgmii_rxd[i*8 +: 8] == XGMII_TERM);
end
detect_term <= {xgmii_term[3:0], swap_rxc_term};
end else begin
xgmii_rxd_d0 <= xgmii_rxd;
xgmii_rxd_crc <= xgmii_rxd;
xgmii_rxd_d0 <= xgmii_rxd_masked;
xgmii_rxc_d0 <= xgmii_rxc;
for (i = 0; i < 8; i = i + 1) begin
detect_term[i] <= xgmii_rxc[i] && (xgmii_rxd[i*8 +: 8] == XGMII_TERM);
end
detect_term <= xgmii_term;
end
if (reset_crc) begin
crc_state <= 32'hFFFFFFFF;
end else begin
crc_state <= crc_next[7];
crc_state <= crc_next;
end
if (update_crc_last) begin
crc_state3 <= crc_next[3];
end else begin
crc_state3 <= crc_next[7];
end
crc_valid7_save <= crc_valid7;
if (state_next == STATE_LAST) begin
xgmii_rxd_crc[31:0] <= xgmii_rxd_crc[63:32];
end
crc_valid_save <= crc_valid;
xgmii_rxd_d1 <= xgmii_rxd_d0;
xgmii_rxc_d1 <= xgmii_rxc_d0;
xgmii_start_d1 <= xgmii_start_d0;
if (rst) begin
state_reg <= STATE_IDLE;
@ -502,7 +479,10 @@ always @(posedge clk) begin
error_bad_fcs_reg <= 1'b0;
xgmii_rxc_d0 <= {CTRL_WIDTH{1'b0}};
xgmii_rxc_d1 <= {CTRL_WIDTH{1'b0}};
xgmii_start_swap <= 1'b0;
xgmii_start_d0 <= 1'b0;
xgmii_start_d1 <= 1'b0;
lanes_swapped <= 1'b0;
end