//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
//// ////
|
//// ////
|
//// File name "rx_enqueue.v" ////
|
//// File name "rx_enqueue.v" ////
|
//// ////
|
//// ////
|
//// This file is part of the "10GE MAC" project ////
|
//// This file is part of the "10GE MAC" project ////
|
//// http://www.opencores.org/cores/xge_mac/ ////
|
//// http://www.opencores.org/cores/xge_mac/ ////
|
//// ////
|
//// ////
|
//// Author(s): ////
|
//// Author(s): ////
|
//// - A. Tanguay (antanguay@opencores.org) ////
|
//// - A. Tanguay (antanguay@opencores.org) ////
|
//// ////
|
//// ////
|
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
//// ////
|
//// ////
|
//// Copyright (C) 2008 AUTHORS. All rights reserved. ////
|
//// Copyright (C) 2008 AUTHORS. All rights reserved. ////
|
//// ////
|
//// ////
|
//// This source file may be used and distributed without ////
|
//// This source file may be used and distributed without ////
|
//// restriction provided that this copyright statement is not ////
|
//// restriction provided that this copyright statement is not ////
|
//// removed from the file and that any derivative work contains ////
|
//// removed from the file and that any derivative work contains ////
|
//// the original copyright notice and the associated disclaimer. ////
|
//// the original copyright notice and the associated disclaimer. ////
|
//// ////
|
//// ////
|
//// This source file is free software; you can redistribute it ////
|
//// This source file is free software; you can redistribute it ////
|
//// and/or modify it under the terms of the GNU Lesser General ////
|
//// and/or modify it under the terms of the GNU Lesser General ////
|
//// Public License as published by the Free Software Foundation; ////
|
//// Public License as published by the Free Software Foundation; ////
|
//// either version 2.1 of the License, or (at your option) any ////
|
//// either version 2.1 of the License, or (at your option) any ////
|
//// later version. ////
|
//// later version. ////
|
//// ////
|
//// ////
|
//// This source is distributed in the hope that it will be ////
|
//// This source is distributed in the hope that it will be ////
|
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
//// useful, but WITHOUT ANY WARRANTY; without even the implied ////
|
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
//// warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR ////
|
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
//// PURPOSE. See the GNU Lesser General Public License for more ////
|
//// details. ////
|
//// details. ////
|
//// ////
|
//// ////
|
//// You should have received a copy of the GNU Lesser General ////
|
//// You should have received a copy of the GNU Lesser General ////
|
//// Public License along with this source; if not, download it ////
|
//// Public License along with this source; if not, download it ////
|
//// from http://www.opencores.org/lgpl.shtml ////
|
//// from http://www.opencores.org/lgpl.shtml ////
|
//// ////
|
//// ////
|
//////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
|
`include "defines.v"
|
`include "defines.v"
|
|
|
module rx_enqueue(/*AUTOARG*/
|
module rx_enqueue(/*AUTOARG*/
|
// Outputs
|
// Outputs
|
rxdfifo_wdata, rxdfifo_wstatus, rxdfifo_wen, rxhfifo_ren,
|
rxdfifo_wdata, rxdfifo_wstatus, rxdfifo_wen, rxhfifo_ren,
|
rxhfifo_wdata, rxhfifo_wstatus, rxhfifo_wen, local_fault_msg_det,
|
rxhfifo_wdata, rxhfifo_wstatus, rxhfifo_wen, local_fault_msg_det,
|
remote_fault_msg_det, status_crc_error_tog,
|
remote_fault_msg_det, status_crc_error_tog,
|
status_fragment_error_tog, status_rxdfifo_ovflow_tog,
|
status_fragment_error_tog, status_lenght_error_tog,
|
status_pause_frame_rx_tog, rxsfifo_wen, rxsfifo_wdata,
|
status_rxdfifo_ovflow_tog, status_pause_frame_rx_tog, rxsfifo_wen,
|
|
rxsfifo_wdata,
|
// Inputs
|
// Inputs
|
clk_xgmii_rx, reset_xgmii_rx_n, xgmii_rxd, xgmii_rxc, rxdfifo_wfull,
|
clk_xgmii_rx, reset_xgmii_rx_n, xgmii_rxd, xgmii_rxc, rxdfifo_wfull,
|
rxhfifo_rdata, rxhfifo_rstatus, rxhfifo_rempty,
|
rxhfifo_rdata, rxhfifo_rstatus, rxhfifo_rempty,
|
rxhfifo_ralmost_empty
|
rxhfifo_ralmost_empty
|
);
|
);
|
|
|
`include "CRC32_D64.v"
|
`include "CRC32_D64.v"
|
`include "CRC32_D8.v"
|
`include "CRC32_D8.v"
|
`include "utils.v"
|
`include "utils.v"
|
|
|
input clk_xgmii_rx;
|
input clk_xgmii_rx;
|
input reset_xgmii_rx_n;
|
input reset_xgmii_rx_n;
|
|
|
input [63:0] xgmii_rxd;
|
input [63:0] xgmii_rxd;
|
input [7:0] xgmii_rxc;
|
input [7:0] xgmii_rxc;
|
|
|
input rxdfifo_wfull;
|
input rxdfifo_wfull;
|
|
|
input [63:0] rxhfifo_rdata;
|
input [63:0] rxhfifo_rdata;
|
input [7:0] rxhfifo_rstatus;
|
input [7:0] rxhfifo_rstatus;
|
input rxhfifo_rempty;
|
input rxhfifo_rempty;
|
input rxhfifo_ralmost_empty;
|
input rxhfifo_ralmost_empty;
|
|
|
output [63:0] rxdfifo_wdata;
|
output [63:0] rxdfifo_wdata;
|
output [7:0] rxdfifo_wstatus;
|
output [7:0] rxdfifo_wstatus;
|
output rxdfifo_wen;
|
output rxdfifo_wen;
|
|
|
output rxhfifo_ren;
|
output rxhfifo_ren;
|
|
|
output [63:0] rxhfifo_wdata;
|
output [63:0] rxhfifo_wdata;
|
output [7:0] rxhfifo_wstatus;
|
output [7:0] rxhfifo_wstatus;
|
output rxhfifo_wen;
|
output rxhfifo_wen;
|
|
|
output [1:0] local_fault_msg_det;
|
output [1:0] local_fault_msg_det;
|
output [1:0] remote_fault_msg_det;
|
output [1:0] remote_fault_msg_det;
|
|
|
output status_crc_error_tog;
|
output status_crc_error_tog;
|
output status_fragment_error_tog;
|
output status_fragment_error_tog;
|
|
output status_lenght_error_tog;
|
output status_rxdfifo_ovflow_tog;
|
output status_rxdfifo_ovflow_tog;
|
|
|
output status_pause_frame_rx_tog;
|
output status_pause_frame_rx_tog;
|
|
|
output rxsfifo_wen;
|
output rxsfifo_wen;
|
output [13:0] rxsfifo_wdata;
|
output [13:0] rxsfifo_wdata;
|
|
|
|
|
|
|
/*AUTOREG*/
|
/*AUTOREG*/
|
// Beginning of automatic regs (for this module's undeclared outputs)
|
// Beginning of automatic regs (for this module's undeclared outputs)
|
reg [1:0] local_fault_msg_det;
|
reg [1:0] local_fault_msg_det;
|
reg [1:0] remote_fault_msg_det;
|
reg [1:0] remote_fault_msg_det;
|
reg [63:0] rxdfifo_wdata;
|
reg [63:0] rxdfifo_wdata;
|
reg rxdfifo_wen;
|
reg rxdfifo_wen;
|
reg [7:0] rxdfifo_wstatus;
|
reg [7:0] rxdfifo_wstatus;
|
reg rxhfifo_ren;
|
reg rxhfifo_ren;
|
reg [63:0] rxhfifo_wdata;
|
reg [63:0] rxhfifo_wdata;
|
reg rxhfifo_wen;
|
reg rxhfifo_wen;
|
reg [7:0] rxhfifo_wstatus;
|
reg [7:0] rxhfifo_wstatus;
|
reg [13:0] rxsfifo_wdata;
|
reg [13:0] rxsfifo_wdata;
|
reg rxsfifo_wen;
|
reg rxsfifo_wen;
|
reg status_crc_error_tog;
|
reg status_crc_error_tog;
|
reg status_fragment_error_tog;
|
reg status_fragment_error_tog;
|
|
reg status_lenght_error_tog;
|
reg status_pause_frame_rx_tog;
|
reg status_pause_frame_rx_tog;
|
reg status_rxdfifo_ovflow_tog;
|
reg status_rxdfifo_ovflow_tog;
|
// End of automatics
|
// End of automatics
|
|
|
/*AUTOWIRE*/
|
/*AUTOWIRE*/
|
|
|
|
|
reg [63:32] xgmii_rxd_d1;
|
reg [63:32] xgmii_rxd_d1;
|
reg [7:4] xgmii_rxc_d1;
|
reg [7:4] xgmii_rxc_d1;
|
|
|
reg [63:0] xgxs_rxd_barrel;
|
reg [63:0] xgxs_rxd_barrel;
|
reg [7:0] xgxs_rxc_barrel;
|
reg [7:0] xgxs_rxc_barrel;
|
|
|
reg [63:0] xgxs_rxd_barrel_d1;
|
reg [63:0] xgxs_rxd_barrel_d1;
|
reg [7:0] xgxs_rxc_barrel_d1;
|
reg [7:0] xgxs_rxc_barrel_d1;
|
|
|
reg barrel_shift;
|
reg barrel_shift;
|
|
|
reg [31:0] crc32_d64;
|
reg [31:0] crc32_d64;
|
reg [31:0] crc32_d8;
|
reg [31:0] crc32_d8;
|
|
|
reg [3:0] crc_bytes;
|
reg [3:0] crc_bytes;
|
reg [3:0] next_crc_bytes;
|
reg [3:0] next_crc_bytes;
|
|
|
reg [63:0] crc_shift_data;
|
reg [63:0] crc_shift_data;
|
reg crc_start_8b;
|
reg crc_start_8b;
|
reg crc_done;
|
reg crc_done;
|
reg crc_good;
|
reg crc_good;
|
reg crc_clear;
|
reg crc_clear;
|
|
|
reg [31:0] crc_rx;
|
reg [31:0] crc_rx;
|
reg [31:0] next_crc_rx;
|
reg [31:0] next_crc_rx;
|
|
|
reg [2:0] curr_state;
|
reg [2:0] curr_state;
|
reg [2:0] next_state;
|
reg [2:0] next_state;
|
|
|
reg [13:0] curr_byte_cnt;
|
reg [13:0] curr_byte_cnt;
|
reg [13:0] next_byte_cnt;
|
reg [13:0] next_byte_cnt;
|
|
reg [13:0] frame_lenght;
|
|
|
reg frame_end_flag;
|
reg frame_end_flag;
|
reg next_frame_end_flag;
|
reg next_frame_end_flag;
|
|
|
reg [2:0] frame_end_bytes;
|
reg [2:0] frame_end_bytes;
|
reg [2:0] next_frame_end_bytes;
|
reg [2:0] next_frame_end_bytes;
|
|
|
reg fragment_error;
|
reg fragment_error;
|
reg rxd_ovflow_error;
|
reg rxd_ovflow_error;
|
|
|
|
reg lenght_error;
|
|
|
reg coding_error;
|
reg coding_error;
|
reg next_coding_error;
|
reg next_coding_error;
|
|
|
reg [7:0] addmask;
|
reg [7:0] addmask;
|
reg [7:0] datamask;
|
reg [7:0] datamask;
|
|
|
reg pause_frame;
|
reg pause_frame;
|
reg next_pause_frame;
|
reg next_pause_frame;
|
reg pause_frame_hold;
|
reg pause_frame_hold;
|
|
|
reg good_pause_frame;
|
reg good_pause_frame;
|
|
|
reg drop_data;
|
reg drop_data;
|
reg next_drop_data;
|
reg next_drop_data;
|
|
|
reg pkt_pending;
|
reg pkt_pending;
|
|
|
reg rxhfifo_ren_d1;
|
reg rxhfifo_ren_d1;
|
|
|
reg rxhfifo_ralmost_empty_d1;
|
reg rxhfifo_ralmost_empty_d1;
|
|
|
|
|
parameter [2:0]
|
parameter [2:0]
|
SM_IDLE = 3'd0,
|
SM_IDLE = 3'd0,
|
SM_RX = 3'd1;
|
SM_RX = 3'd1;
|
|
|
// count the number of set bits in a nibble
|
// count the number of set bits in a nibble
|
function [2:0] bit_cnt4;
|
function [2:0] bit_cnt4;
|
input [3:0] bits;
|
input [3:0] bits;
|
begin
|
begin
|
case (bits)
|
case (bits)
|
0: bit_cnt4 = 0;
|
0: bit_cnt4 = 0;
|
1: bit_cnt4 = 1;
|
1: bit_cnt4 = 1;
|
2: bit_cnt4 = 1;
|
2: bit_cnt4 = 1;
|
3: bit_cnt4 = 2;
|
3: bit_cnt4 = 2;
|
4: bit_cnt4 = 1;
|
4: bit_cnt4 = 1;
|
5: bit_cnt4 = 2;
|
5: bit_cnt4 = 2;
|
6: bit_cnt4 = 2;
|
6: bit_cnt4 = 2;
|
7: bit_cnt4 = 3;
|
7: bit_cnt4 = 3;
|
8: bit_cnt4 = 1;
|
8: bit_cnt4 = 1;
|
9: bit_cnt4 = 2;
|
9: bit_cnt4 = 2;
|
10: bit_cnt4 = 2;
|
10: bit_cnt4 = 2;
|
11: bit_cnt4 = 3;
|
11: bit_cnt4 = 3;
|
12: bit_cnt4 = 2;
|
12: bit_cnt4 = 2;
|
13: bit_cnt4 = 3;
|
13: bit_cnt4 = 3;
|
14: bit_cnt4 = 3;
|
14: bit_cnt4 = 3;
|
15: bit_cnt4 = 4;
|
15: bit_cnt4 = 4;
|
endcase
|
endcase
|
end
|
end
|
endfunction
|
endfunction
|
|
|
function [3:0] bit_cnt8;
|
function [3:0] bit_cnt8;
|
input [7:0] bits;
|
input [7:0] bits;
|
begin
|
begin
|
bit_cnt8 = bit_cnt4(bits[3:0]) + bit_cnt4(bits[7:4]);
|
bit_cnt8 = bit_cnt4(bits[3:0]) + bit_cnt4(bits[7:4]);
|
end
|
end
|
endfunction
|
endfunction
|
|
|
always @(posedge clk_xgmii_rx or negedge reset_xgmii_rx_n) begin
|
always @(posedge clk_xgmii_rx or negedge reset_xgmii_rx_n) begin
|
|
|
if (reset_xgmii_rx_n == 1'b0) begin
|
if (reset_xgmii_rx_n == 1'b0) begin
|
|
|
xgmii_rxd_d1 <= 32'b0;
|
xgmii_rxd_d1 <= 32'b0;
|
xgmii_rxc_d1 <= 4'b0;
|
xgmii_rxc_d1 <= 4'b0;
|
|
|
xgxs_rxd_barrel <= 64'b0;
|
xgxs_rxd_barrel <= 64'b0;
|
xgxs_rxc_barrel <= 8'b0;
|
xgxs_rxc_barrel <= 8'b0;
|
|
|
xgxs_rxd_barrel_d1 <= 64'b0;
|
xgxs_rxd_barrel_d1 <= 64'b0;
|
xgxs_rxc_barrel_d1 <= 8'b0;
|
xgxs_rxc_barrel_d1 <= 8'b0;
|
|
|
barrel_shift <= 1'b0;
|
barrel_shift <= 1'b0;
|
|
|
local_fault_msg_det <= 2'b0;
|
local_fault_msg_det <= 2'b0;
|
remote_fault_msg_det <= 2'b0;
|
remote_fault_msg_det <= 2'b0;
|
|
|
crc32_d64 <= 32'b0;
|
crc32_d64 <= 32'b0;
|
crc32_d8 <= 32'b0;
|
crc32_d8 <= 32'b0;
|
crc_bytes <= 4'b0;
|
crc_bytes <= 4'b0;
|
|
|
crc_shift_data <= 64'b0;
|
crc_shift_data <= 64'b0;
|
crc_done <= 1'b0;
|
crc_done <= 1'b0;
|
crc_rx <= 32'b0;
|
crc_rx <= 32'b0;
|
|
|
pause_frame_hold <= 1'b0;
|
pause_frame_hold <= 1'b0;
|
|
|
status_crc_error_tog <= 1'b0;
|
status_crc_error_tog <= 1'b0;
|
status_fragment_error_tog <= 1'b0;
|
status_fragment_error_tog <= 1'b0;
|
|
status_lenght_error_tog <= 1'b0;
|
status_rxdfifo_ovflow_tog <= 1'b0;
|
status_rxdfifo_ovflow_tog <= 1'b0;
|
|
|
status_pause_frame_rx_tog <= 1'b0;
|
status_pause_frame_rx_tog <= 1'b0;
|
|
|
rxsfifo_wen <= 1'b0;
|
rxsfifo_wen <= 1'b0;
|
rxsfifo_wdata <= 14'b0;
|
rxsfifo_wdata <= 14'b0;
|
|
|
datamask <= 8'b0;
|
datamask <= 8'b0;
|
|
|
|
lenght_error <= 1'b0;
|
|
|
end
|
end
|
else begin
|
else begin
|
|
|
rxsfifo_wen <= 1'b0;
|
rxsfifo_wen <= 1'b0;
|
rxsfifo_wdata <= curr_byte_cnt + {11'b0, frame_end_bytes};
|
rxsfifo_wdata <= frame_lenght;
|
|
|
|
lenght_error <= 1'b0;
|
|
|
//---
|
//---
|
// Link status RC layer
|
// Link status RC layer
|
// Look for local/remote messages on lower 4 lanes and upper
|
// Look for local/remote messages on lower 4 lanes and upper
|
// 4 lanes. This is a 64-bit interface but look at each 32-bit
|
// 4 lanes. This is a 64-bit interface but look at each 32-bit
|
// independantly.
|
// independantly.
|
|
|
local_fault_msg_det[1] <= (xgmii_rxd[63:32] ==
|
local_fault_msg_det[1] <= (xgmii_rxd[63:32] ==
|
{`LOCAL_FAULT, 8'h0, 8'h0, `SEQUENCE} &&
|
{`LOCAL_FAULT, 8'h0, 8'h0, `SEQUENCE} &&
|
xgmii_rxc[7:4] == 4'b0001);
|
xgmii_rxc[7:4] == 4'b0001);
|
|
|
local_fault_msg_det[0] <= (xgmii_rxd[31:0] ==
|
local_fault_msg_det[0] <= (xgmii_rxd[31:0] ==
|
{`LOCAL_FAULT, 8'h0, 8'h0, `SEQUENCE} &&
|
{`LOCAL_FAULT, 8'h0, 8'h0, `SEQUENCE} &&
|
xgmii_rxc[3:0] == 4'b0001);
|
xgmii_rxc[3:0] == 4'b0001);
|
|
|
remote_fault_msg_det[1] <= (xgmii_rxd[63:32] ==
|
remote_fault_msg_det[1] <= (xgmii_rxd[63:32] ==
|
{`REMOTE_FAULT, 8'h0, 8'h0, `SEQUENCE} &&
|
{`REMOTE_FAULT, 8'h0, 8'h0, `SEQUENCE} &&
|
xgmii_rxc[7:4] == 4'b0001);
|
xgmii_rxc[7:4] == 4'b0001);
|
|
|
remote_fault_msg_det[0] <= (xgmii_rxd[31:0] ==
|
remote_fault_msg_det[0] <= (xgmii_rxd[31:0] ==
|
{`REMOTE_FAULT, 8'h0, 8'h0, `SEQUENCE} &&
|
{`REMOTE_FAULT, 8'h0, 8'h0, `SEQUENCE} &&
|
xgmii_rxc[3:0] == 4'b0001);
|
xgmii_rxc[3:0] == 4'b0001);
|
|
|
|
|
//---
|
//---
|
// Rotating barrel. This function allow us to always align the start of
|
// Rotating barrel. This function allow us to always align the start of
|
// a frame with LANE0. If frame starts in LANE4, it will be shifted 4 bytes
|
// a frame with LANE0. If frame starts in LANE4, it will be shifted 4 bytes
|
// to LANE0, thus reducing the amount of logic needed at the next stage.
|
// to LANE0, thus reducing the amount of logic needed at the next stage.
|
|
|
xgmii_rxd_d1[63:32] <= xgmii_rxd[63:32];
|
xgmii_rxd_d1[63:32] <= xgmii_rxd[63:32];
|
xgmii_rxc_d1[7:4] <= xgmii_rxc[7:4];
|
xgmii_rxc_d1[7:4] <= xgmii_rxc[7:4];
|
|
|
if (xgmii_rxd[`LANE0] == `START && xgmii_rxc[0]) begin
|
if (xgmii_rxd[`LANE0] == `START && xgmii_rxc[0]) begin
|
|
|
xgxs_rxd_barrel <= xgmii_rxd;
|
xgxs_rxd_barrel <= xgmii_rxd;
|
xgxs_rxc_barrel <= xgmii_rxc;
|
xgxs_rxc_barrel <= xgmii_rxc;
|
|
|
barrel_shift <= 1'b0;
|
barrel_shift <= 1'b0;
|
|
|
end
|
end
|
else if (xgmii_rxd[`LANE4] == `START && xgmii_rxc[4]) begin
|
else if (xgmii_rxd[`LANE4] == `START && xgmii_rxc[4]) begin
|
|
|
xgxs_rxd_barrel[63:32] <= xgmii_rxd[31:0];
|
xgxs_rxd_barrel[63:32] <= xgmii_rxd[31:0];
|
xgxs_rxc_barrel[7:4] <= xgmii_rxc[3:0];
|
xgxs_rxc_barrel[7:4] <= xgmii_rxc[3:0];
|
|
|
if (barrel_shift) begin
|
if (barrel_shift) begin
|
xgxs_rxd_barrel[31:0] <= xgmii_rxd_d1[63:32];
|
xgxs_rxd_barrel[31:0] <= xgmii_rxd_d1[63:32];
|
xgxs_rxc_barrel[3:0] <= xgmii_rxc_d1[7:4];
|
xgxs_rxc_barrel[3:0] <= xgmii_rxc_d1[7:4];
|
end
|
end
|
else begin
|
else begin
|
xgxs_rxd_barrel[31:0] <= 32'h07070707;
|
xgxs_rxd_barrel[31:0] <= 32'h07070707;
|
xgxs_rxc_barrel[3:0] <= 4'hf;
|
xgxs_rxc_barrel[3:0] <= 4'hf;
|
end
|
end
|
|
|
barrel_shift <= 1'b1;
|
barrel_shift <= 1'b1;
|
|
|
end
|
end
|
else if (barrel_shift) begin
|
else if (barrel_shift) begin
|
|
|
xgxs_rxd_barrel <= {xgmii_rxd[31:0], xgmii_rxd_d1[63:32]};
|
xgxs_rxd_barrel <= {xgmii_rxd[31:0], xgmii_rxd_d1[63:32]};
|
xgxs_rxc_barrel <= {xgmii_rxc[3:0], xgmii_rxc_d1[7:4]};
|
xgxs_rxc_barrel <= {xgmii_rxc[3:0], xgmii_rxc_d1[7:4]};
|
|
|
end
|
end
|
else begin
|
else begin
|
|
|
xgxs_rxd_barrel <= xgmii_rxd;
|
xgxs_rxd_barrel <= xgmii_rxd;
|
xgxs_rxc_barrel <= xgmii_rxc;
|
xgxs_rxc_barrel <= xgmii_rxc;
|
|
|
end
|
end
|
|
|
xgxs_rxd_barrel_d1 <= xgxs_rxd_barrel;
|
xgxs_rxd_barrel_d1 <= xgxs_rxd_barrel;
|
xgxs_rxc_barrel_d1 <= xgxs_rxc_barrel;
|
xgxs_rxc_barrel_d1 <= xgxs_rxc_barrel;
|
|
|
//---
|
//---
|
// Mask for end-of-frame
|
// Mask for end-of-frame
|
|
|
datamask[0] <= addmask[0];
|
datamask[0] <= addmask[0];
|
datamask[1] <= &addmask[1:0];
|
datamask[1] <= &addmask[1:0];
|
datamask[2] <= &addmask[2:0];
|
datamask[2] <= &addmask[2:0];
|
datamask[3] <= &addmask[3:0];
|
datamask[3] <= &addmask[3:0];
|
datamask[4] <= &addmask[4:0];
|
datamask[4] <= &addmask[4:0];
|
datamask[5] <= &addmask[5:0];
|
datamask[5] <= &addmask[5:0];
|
datamask[6] <= &addmask[6:0];
|
datamask[6] <= &addmask[6:0];
|
datamask[7] <= &addmask[7:0];
|
datamask[7] <= &addmask[7:0];
|
|
|
//---
|
//---
|
// When final CRC calculation begins we capture info relevant to
|
// When final CRC calculation begins we capture info relevant to
|
// current frame CRC claculation continues while next frame is
|
// current frame CRC claculation continues while next frame is
|
// being received.
|
// being received.
|
|
|
if (crc_start_8b) begin
|
if (crc_start_8b) begin
|
|
|
pause_frame_hold <= pause_frame;
|
pause_frame_hold <= pause_frame;
|
|
|
end
|
end
|
|
|
//---
|
//---
|
// CRC Checking
|
// CRC Checking
|
|
|
crc_rx <= next_crc_rx;
|
crc_rx <= next_crc_rx;
|
|
|
if (crc_clear) begin
|
if (crc_clear) begin
|
|
|
// CRC is cleared at the beginning of the frame, calculate
|
// CRC is cleared at the beginning of the frame, calculate
|
// 64-bit at a time otherwise
|
// 64-bit at a time otherwise
|
|
|
crc32_d64 <= 32'hffffffff;
|
crc32_d64 <= 32'hffffffff;
|
|
|
end
|
end
|
else begin
|
else begin
|
|
|
crc32_d64 <= nextCRC32_D64(reverse_64b(xgxs_rxd_barrel_d1), crc32_d64);
|
crc32_d64 <= nextCRC32_D64(reverse_64b(xgxs_rxd_barrel_d1), crc32_d64);
|
|
|
end
|
end
|
|
|
if (crc_bytes != 4'b0) begin
|
if (crc_bytes != 4'b0) begin
|
|
|
// When reaching the end of the frame we switch from 64-bit mode
|
// When reaching the end of the frame we switch from 64-bit mode
|
// to 8-bit mode to accomodate odd number of bytes in the frame.
|
// to 8-bit mode to accomodate odd number of bytes in the frame.
|
// crc_bytes indicated the number of remaining payload byte to
|
// crc_bytes indicated the number of remaining payload byte to
|
// compute CRC on. Calculate and decrement until it reaches 0.
|
// compute CRC on. Calculate and decrement until it reaches 0.
|
|
|
if (crc_bytes == 4'b1) begin
|
if (crc_bytes == 4'b1) begin
|
crc_done <= 1'b1;
|
crc_done <= 1'b1;
|
end
|
end
|
|
|
crc32_d8 <= nextCRC32_D8(reverse_8b(crc_shift_data[7:0]), crc32_d8);
|
crc32_d8 <= nextCRC32_D8(reverse_8b(crc_shift_data[7:0]), crc32_d8);
|
crc_shift_data <= {8'h00, crc_shift_data[63:8]};
|
crc_shift_data <= {8'h00, crc_shift_data[63:8]};
|
crc_bytes <= crc_bytes - 4'b1;
|
crc_bytes <= crc_bytes - 4'b1;
|
|
|
end
|
end
|
else if (crc_bytes == 4'b0) begin
|
else if (crc_bytes == 4'b0) begin
|
|
|
// Per Clause 46. Control code during data must be reported
|
// Per Clause 46. Control code during data must be reported
|
// as a CRC error. Indicated here by coding_error. Corrupt CRC
|
// as a CRC error. Indicated here by coding_error. Corrupt CRC
|
// if coding error is detected.
|
// if coding error is detected.
|
|
|
if (coding_error || next_coding_error) begin
|
if (coding_error || next_coding_error) begin
|
crc32_d8 <= ~crc32_d64;
|
crc32_d8 <= ~crc32_d64;
|
end
|
end
|
else begin
|
else begin
|
crc32_d8 <= crc32_d64;
|
crc32_d8 <= crc32_d64;
|
end
|
end
|
|
|
crc_done <= 1'b0;
|
crc_done <= 1'b0;
|
|
|
crc_shift_data <= xgxs_rxd_barrel_d1;
|
crc_shift_data <= xgxs_rxd_barrel_d1;
|
crc_bytes <= next_crc_bytes;
|
crc_bytes <= next_crc_bytes;
|
|
|
end
|
end
|
|
|
//---
|
//---
|
// Error detection
|
// Error detection
|
|
|
if (crc_done && !crc_good) begin
|
if (crc_done && !crc_good) begin
|
status_crc_error_tog <= ~status_crc_error_tog;
|
status_crc_error_tog <= ~status_crc_error_tog;
|
end
|
end
|
|
|
if (fragment_error) begin
|
if (fragment_error) begin
|
status_fragment_error_tog <= ~status_fragment_error_tog;
|
status_fragment_error_tog <= ~status_fragment_error_tog;
|
end
|
end
|
|
|
if (rxd_ovflow_error) begin
|
if (rxd_ovflow_error) begin
|
status_rxdfifo_ovflow_tog <= ~status_rxdfifo_ovflow_tog;
|
status_rxdfifo_ovflow_tog <= ~status_rxdfifo_ovflow_tog;
|
end
|
end
|
|
|
//---
|
//---
|
// Frame receive indication
|
// Frame receive indication
|
|
|
if (good_pause_frame) begin
|
if (good_pause_frame) begin
|
status_pause_frame_rx_tog <= ~status_pause_frame_rx_tog;
|
status_pause_frame_rx_tog <= ~status_pause_frame_rx_tog;
|
end
|
end
|
|
|
if (frame_end_flag) begin
|
if (frame_end_flag) begin
|
rxsfifo_wen <= 1'b1;
|
rxsfifo_wen <= 1'b1;
|
end
|
end
|
|
|
|
//---
|
|
// Check frame lenght
|
|
|
|
if (frame_end_flag && frame_lenght > `MAX_FRAME_SIZE) begin
|
|
lenght_error <= 1'b1;
|
|
status_lenght_error_tog <= ~status_lenght_error_tog;
|
|
end
|
|
|
end
|
end
|
|
|
end
|
end
|
|
|
|
|
always @(/*AS*/crc32_d8 or crc_done or crc_rx or pause_frame_hold) begin
|
always @(/*AS*/crc32_d8 or crc_done or crc_rx or pause_frame_hold) begin
|
|
|
|
|
crc_good = 1'b0;
|
crc_good = 1'b0;
|
good_pause_frame = 1'b0;
|
good_pause_frame = 1'b0;
|
|
|
if (crc_done) begin
|
if (crc_done) begin
|
|
|
// Check CRC. If this is a pause frame, report it to cpu.
|
// Check CRC. If this is a pause frame, report it to cpu.
|
|
|
if (crc_rx == ~reverse_32b(crc32_d8)) begin
|
if (crc_rx == ~reverse_32b(crc32_d8)) begin
|
crc_good = 1'b1;
|
crc_good = 1'b1;
|
good_pause_frame = pause_frame_hold;
|
good_pause_frame = pause_frame_hold;
|
end
|
end
|
|
|
end
|
end
|
|
|
end
|
end
|
|
|
always @(posedge clk_xgmii_rx or negedge reset_xgmii_rx_n) begin
|
always @(posedge clk_xgmii_rx or negedge reset_xgmii_rx_n) begin
|
|
|
if (reset_xgmii_rx_n == 1'b0) begin
|
if (reset_xgmii_rx_n == 1'b0) begin
|
|
|
curr_state <= SM_IDLE;
|
curr_state <= SM_IDLE;
|
curr_byte_cnt <= 14'b0;
|
curr_byte_cnt <= 14'b0;
|
frame_end_flag <= 1'b0;
|
frame_end_flag <= 1'b0;
|
frame_end_bytes <= 3'b0;
|
frame_end_bytes <= 3'b0;
|
coding_error <= 1'b0;
|
coding_error <= 1'b0;
|
pause_frame <= 1'b0;
|
pause_frame <= 1'b0;
|
|
|
end
|
end
|
else begin
|
else begin
|
|
|
curr_state <= next_state;
|
curr_state <= next_state;
|
curr_byte_cnt <= next_byte_cnt;
|
curr_byte_cnt <= next_byte_cnt;
|
frame_end_flag <= next_frame_end_flag;
|
frame_end_flag <= next_frame_end_flag;
|
frame_end_bytes <= next_frame_end_bytes;
|
frame_end_bytes <= next_frame_end_bytes;
|
coding_error <= next_coding_error;
|
coding_error <= next_coding_error;
|
pause_frame <= next_pause_frame;
|
pause_frame <= next_pause_frame;
|
|
|
end
|
end
|
|
|
end
|
end
|
|
|
|
|
always @(/*AS*/coding_error or crc_rx or curr_byte_cnt or curr_state
|
always @(/*AS*/coding_error or crc_rx or curr_byte_cnt or curr_state
|
or datamask or pause_frame or xgxs_rxc_barrel
|
or datamask or frame_end_bytes or pause_frame
|
or xgxs_rxc_barrel_d1 or xgxs_rxd_barrel
|
or xgxs_rxc_barrel or xgxs_rxc_barrel_d1 or xgxs_rxd_barrel
|
or xgxs_rxd_barrel_d1) begin
|
or xgxs_rxd_barrel_d1) begin
|
|
|
next_state = curr_state;
|
next_state = curr_state;
|
|
|
rxhfifo_wdata = xgxs_rxd_barrel_d1;
|
rxhfifo_wdata = xgxs_rxd_barrel_d1;
|
rxhfifo_wstatus = `RXSTATUS_NONE;
|
rxhfifo_wstatus = `RXSTATUS_NONE;
|
rxhfifo_wen = 1'b0;
|
rxhfifo_wen = 1'b0;
|
|
|
next_crc_bytes = 4'b0;
|
next_crc_bytes = 4'b0;
|
next_crc_rx = crc_rx;
|
next_crc_rx = crc_rx;
|
crc_start_8b = 1'b0;
|
crc_start_8b = 1'b0;
|
crc_clear = 1'b0;
|
crc_clear = 1'b0;
|
|
|
next_byte_cnt = curr_byte_cnt;
|
next_byte_cnt = curr_byte_cnt;
|
next_frame_end_flag = 1'b0;
|
next_frame_end_flag = 1'b0;
|
next_frame_end_bytes = 3'b0;
|
next_frame_end_bytes = 3'b0;
|
|
|
fragment_error = 1'b0;
|
fragment_error = 1'b0;
|
|
|
|
frame_lenght = curr_byte_cnt + {11'b0, frame_end_bytes};
|
|
|
next_coding_error = coding_error;
|
next_coding_error = coding_error;
|
next_pause_frame = pause_frame;
|
next_pause_frame = pause_frame;
|
|
|
addmask[0] = !(xgxs_rxd_barrel[`LANE0] == `TERMINATE && xgxs_rxc_barrel[0]);
|
addmask[0] = !(xgxs_rxd_barrel[`LANE0] == `TERMINATE && xgxs_rxc_barrel[0]);
|
addmask[1] = !(xgxs_rxd_barrel[`LANE1] == `TERMINATE && xgxs_rxc_barrel[1]);
|
addmask[1] = !(xgxs_rxd_barrel[`LANE1] == `TERMINATE && xgxs_rxc_barrel[1]);
|
addmask[2] = !(xgxs_rxd_barrel[`LANE2] == `TERMINATE && xgxs_rxc_barrel[2]);
|
addmask[2] = !(xgxs_rxd_barrel[`LANE2] == `TERMINATE && xgxs_rxc_barrel[2]);
|
addmask[3] = !(xgxs_rxd_barrel[`LANE3] == `TERMINATE && xgxs_rxc_barrel[3]);
|
addmask[3] = !(xgxs_rxd_barrel[`LANE3] == `TERMINATE && xgxs_rxc_barrel[3]);
|
addmask[4] = !(xgxs_rxd_barrel[`LANE4] == `TERMINATE && xgxs_rxc_barrel[4]);
|
addmask[4] = !(xgxs_rxd_barrel[`LANE4] == `TERMINATE && xgxs_rxc_barrel[4]);
|
addmask[5] = !(xgxs_rxd_barrel[`LANE5] == `TERMINATE && xgxs_rxc_barrel[5]);
|
addmask[5] = !(xgxs_rxd_barrel[`LANE5] == `TERMINATE && xgxs_rxc_barrel[5]);
|
addmask[6] = !(xgxs_rxd_barrel[`LANE6] == `TERMINATE && xgxs_rxc_barrel[6]);
|
addmask[6] = !(xgxs_rxd_barrel[`LANE6] == `TERMINATE && xgxs_rxc_barrel[6]);
|
addmask[7] = !(xgxs_rxd_barrel[`LANE7] == `TERMINATE && xgxs_rxc_barrel[7]);
|
addmask[7] = !(xgxs_rxd_barrel[`LANE7] == `TERMINATE && xgxs_rxc_barrel[7]);
|
|
|
case (curr_state)
|
case (curr_state)
|
|
|
SM_IDLE:
|
SM_IDLE:
|
begin
|
begin
|
|
|
next_byte_cnt = 14'b0;
|
next_byte_cnt = 14'b0;
|
crc_clear = 1'b1;
|
crc_clear = 1'b1;
|
next_coding_error = 1'b0;
|
next_coding_error = 1'b0;
|
next_pause_frame = 1'b0;
|
next_pause_frame = 1'b0;
|
|
|
|
|
// Detect the start of a frame
|
// Detect the start of a frame
|
|
|
if (xgxs_rxd_barrel_d1[`LANE0] == `START && xgxs_rxc_barrel_d1[0] &&
|
if (xgxs_rxd_barrel_d1[`LANE0] == `START && xgxs_rxc_barrel_d1[0] &&
|
xgxs_rxd_barrel_d1[`LANE1] == `PREAMBLE && !xgxs_rxc_barrel_d1[1] &&
|
xgxs_rxd_barrel_d1[`LANE1] == `PREAMBLE && !xgxs_rxc_barrel_d1[1] &&
|
xgxs_rxd_barrel_d1[`LANE2] == `PREAMBLE && !xgxs_rxc_barrel_d1[2] &&
|
xgxs_rxd_barrel_d1[`LANE2] == `PREAMBLE && !xgxs_rxc_barrel_d1[2] &&
|
xgxs_rxd_barrel_d1[`LANE3] == `PREAMBLE && !xgxs_rxc_barrel_d1[3] &&
|
xgxs_rxd_barrel_d1[`LANE3] == `PREAMBLE && !xgxs_rxc_barrel_d1[3] &&
|
xgxs_rxd_barrel_d1[`LANE4] == `PREAMBLE && !xgxs_rxc_barrel_d1[4] &&
|
xgxs_rxd_barrel_d1[`LANE4] == `PREAMBLE && !xgxs_rxc_barrel_d1[4] &&
|
xgxs_rxd_barrel_d1[`LANE5] == `PREAMBLE && !xgxs_rxc_barrel_d1[5] &&
|
xgxs_rxd_barrel_d1[`LANE5] == `PREAMBLE && !xgxs_rxc_barrel_d1[5] &&
|
xgxs_rxd_barrel_d1[`LANE6] == `PREAMBLE && !xgxs_rxc_barrel_d1[6] &&
|
xgxs_rxd_barrel_d1[`LANE6] == `PREAMBLE && !xgxs_rxc_barrel_d1[6] &&
|
xgxs_rxd_barrel_d1[`LANE7] == `SFD && !xgxs_rxc_barrel_d1[7]) begin
|
xgxs_rxd_barrel_d1[`LANE7] == `SFD && !xgxs_rxc_barrel_d1[7]) begin
|
|
|
next_state = SM_RX;
|
next_state = SM_RX;
|
end
|
end
|
|
|
end
|
end
|
|
|
SM_RX:
|
SM_RX:
|
begin
|
begin
|
|
|
// Pause frames are filtered
|
// Pause frames are filtered
|
|
|
rxhfifo_wen = !pause_frame;
|
rxhfifo_wen = !pause_frame;
|
|
|
|
|
if (xgxs_rxd_barrel_d1[`LANE0] == `START && xgxs_rxc_barrel_d1[0] &&
|
if (xgxs_rxd_barrel_d1[`LANE0] == `START && xgxs_rxc_barrel_d1[0] &&
|
xgxs_rxd_barrel_d1[`LANE7] == `SFD && !xgxs_rxc_barrel_d1[7]) begin
|
xgxs_rxd_barrel_d1[`LANE7] == `SFD && !xgxs_rxc_barrel_d1[7]) begin
|
|
|
// Fragment received, if we are still at SOP stage don't store
|
// Fragment received, if we are still at SOP stage don't store
|
// the frame. If not, write a fake EOP and flag frame as bad.
|
// the frame. If not, write a fake EOP and flag frame as bad.
|
|
|
next_byte_cnt = 14'b0;
|
next_byte_cnt = 14'b0;
|
crc_clear = 1'b1;
|
crc_clear = 1'b1;
|
next_coding_error = 1'b0;
|
next_coding_error = 1'b0;
|
|
|
fragment_error = 1'b1;
|
fragment_error = 1'b1;
|
rxhfifo_wstatus[`RXSTATUS_ERR] = 1'b1;
|
rxhfifo_wstatus[`RXSTATUS_ERR] = 1'b1;
|
|
|
if (curr_byte_cnt == 14'b0) begin
|
if (curr_byte_cnt == 14'b0) begin
|
rxhfifo_wen = 1'b0;
|
rxhfifo_wen = 1'b0;
|
end
|
end
|
else begin
|
else begin
|
rxhfifo_wstatus[`RXSTATUS_EOP] = 1'b1;
|
rxhfifo_wstatus[`RXSTATUS_EOP] = 1'b1;
|
end
|
end
|
|
|
end
|
end
|
else if (curr_byte_cnt > 14'd9900) begin
|
else if (curr_byte_cnt > 14'd16100) begin
|
|
|
// Frame too long, TERMMINATE must have been corrupted.
|
// Frame too long, TERMMINATE must have been corrupted.
|
// Abort transfer, write a fake EOP, report as fragment.
|
// Abort transfer, write a fake EOP, report as fragment.
|
|
|
fragment_error = 1'b1;
|
fragment_error = 1'b1;
|
rxhfifo_wstatus[`RXSTATUS_ERR] = 1'b1;
|
rxhfifo_wstatus[`RXSTATUS_ERR] = 1'b1;
|
|
|
rxhfifo_wstatus[`RXSTATUS_EOP] = 1'b1;
|
rxhfifo_wstatus[`RXSTATUS_EOP] = 1'b1;
|
next_state = SM_IDLE;
|
next_state = SM_IDLE;
|
|
|
end
|
end
|
else begin
|
else begin
|
|
|
// Pause frame receive, these frame will be filtered
|
// Pause frame receive, these frame will be filtered
|
|
|
if (curr_byte_cnt == 14'd0 &&
|
if (curr_byte_cnt == 14'd0 &&
|
xgxs_rxd_barrel_d1[47:0] == `PAUSE_FRAME) begin
|
xgxs_rxd_barrel_d1[47:0] == `PAUSE_FRAME) begin
|
|
|
rxhfifo_wen = 1'b0;
|
rxhfifo_wen = 1'b0;
|
next_pause_frame = 1'b1;
|
next_pause_frame = 1'b1;
|
end
|
end
|
|
|
|
|
// Control character during data phase, force CRC error
|
// Control character during data phase, force CRC error
|
|
|
if (|(xgxs_rxc_barrel_d1 & datamask)) begin
|
if (|(xgxs_rxc_barrel_d1 & datamask)) begin
|
|
|
next_coding_error = 1'b1;
|
next_coding_error = 1'b1;
|
end
|
end
|
|
|
|
|
// Write SOP to status bits during first byte
|
// Write SOP to status bits during first byte
|
|
|
if (curr_byte_cnt == 14'b0) begin
|
if (curr_byte_cnt == 14'b0) begin
|
rxhfifo_wstatus[`RXSTATUS_SOP] = 1'b1;
|
rxhfifo_wstatus[`RXSTATUS_SOP] = 1'b1;
|
end
|
end
|
|
|
/* verilator lint_off WIDTH */
|
/* verilator lint_off WIDTH */
|
//next_byte_cnt = curr_byte_cnt +
|
//next_byte_cnt = curr_byte_cnt +
|
// addmask[0] + addmask[1] + addmask[2] + addmask[3] +
|
// addmask[0] + addmask[1] + addmask[2] + addmask[3] +
|
// addmask[4] + addmask[5] + addmask[6] + addmask[7];
|
// addmask[4] + addmask[5] + addmask[6] + addmask[7];
|
/* verilator lint_on WIDTH */
|
/* verilator lint_on WIDTH */
|
// don't infer a chain of adders
|
// don't infer a chain of adders
|
next_byte_cnt = curr_byte_cnt + {10'b0, bit_cnt8(datamask[7:0])};
|
next_byte_cnt = curr_byte_cnt + {10'b0, bit_cnt8(datamask[7:0])};
|
|
|
|
|
// We will not write to the fifo if all is left
|
// We will not write to the fifo if all is left
|
// are four or less bytes of crc. We also strip off the
|
// are four or less bytes of crc. We also strip off the
|
// crc, which requires looking one cycle ahead
|
// crc, which requires looking one cycle ahead
|
// wstatus:
|
// wstatus:
|
// [2:0] modulus of packet length
|
// [2:0] modulus of packet length
|
|
|
// Look one cycle ahead for TERMINATE in lanes 0 to 4
|
// Look one cycle ahead for TERMINATE in lanes 0 to 4
|
|
|
if (xgxs_rxd_barrel[`LANE4] == `TERMINATE && xgxs_rxc_barrel[4]) begin
|
if (xgxs_rxd_barrel[`LANE4] == `TERMINATE && xgxs_rxc_barrel[4]) begin
|
|
|
rxhfifo_wstatus[`RXSTATUS_EOP] = 1'b1;
|
rxhfifo_wstatus[`RXSTATUS_EOP] = 1'b1;
|
rxhfifo_wstatus[2:0] = 3'd0;
|
rxhfifo_wstatus[2:0] = 3'd0;
|
|
|
crc_start_8b = 1'b1;
|
crc_start_8b = 1'b1;
|
next_crc_bytes = 4'd8;
|
next_crc_bytes = 4'd8;
|
next_crc_rx = xgxs_rxd_barrel[31:0];
|
next_crc_rx = xgxs_rxd_barrel[31:0];
|
|
|
next_frame_end_flag = 1'b1;
|
next_frame_end_flag = 1'b1;
|
next_frame_end_bytes = 3'd4;
|
next_frame_end_bytes = 3'd4;
|
|
|
next_state = SM_IDLE;
|
next_state = SM_IDLE;
|
|
|
end
|
end
|
|
|
if (xgxs_rxd_barrel[`LANE3] == `TERMINATE && xgxs_rxc_barrel[3]) begin
|
if (xgxs_rxd_barrel[`LANE3] == `TERMINATE && xgxs_rxc_barrel[3]) begin
|
|
|
rxhfifo_wstatus[`RXSTATUS_EOP] = 1'b1;
|
rxhfifo_wstatus[`RXSTATUS_EOP] = 1'b1;
|
rxhfifo_wstatus[2:0] = 3'd7;
|
rxhfifo_wstatus[2:0] = 3'd7;
|
|
|
crc_start_8b = 1'b1;
|
crc_start_8b = 1'b1;
|
next_crc_bytes = 4'd7;
|
next_crc_bytes = 4'd7;
|
next_crc_rx = {xgxs_rxd_barrel[23:0], xgxs_rxd_barrel_d1[63:56]};
|
next_crc_rx = {xgxs_rxd_barrel[23:0], xgxs_rxd_barrel_d1[63:56]};
|
|
|
next_frame_end_flag = 1'b1;
|
next_frame_end_flag = 1'b1;
|
next_frame_end_bytes = 3'd3;
|
next_frame_end_bytes = 3'd3;
|
|
|
next_state = SM_IDLE;
|
next_state = SM_IDLE;
|
|
|
end
|
end
|
|
|
if (xgxs_rxd_barrel[`LANE2] == `TERMINATE && xgxs_rxc_barrel[2]) begin
|
if (xgxs_rxd_barrel[`LANE2] == `TERMINATE && xgxs_rxc_barrel[2]) begin
|
|
|
rxhfifo_wstatus[`RXSTATUS_EOP] = 1'b1;
|
rxhfifo_wstatus[`RXSTATUS_EOP] = 1'b1;
|
rxhfifo_wstatus[2:0] = 3'd6;
|
rxhfifo_wstatus[2:0] = 3'd6;
|
|
|
crc_start_8b = 1'b1;
|
crc_start_8b = 1'b1;
|
next_crc_bytes = 4'd6;
|
next_crc_bytes = 4'd6;
|
next_crc_rx = {xgxs_rxd_barrel[15:0], xgxs_rxd_barrel_d1[63:48]};
|
next_crc_rx = {xgxs_rxd_barrel[15:0], xgxs_rxd_barrel_d1[63:48]};
|
|
|
next_frame_end_flag = 1'b1;
|
next_frame_end_flag = 1'b1;
|
next_frame_end_bytes = 3'd2;
|
next_frame_end_bytes = 3'd2;
|
|
|
next_state = SM_IDLE;
|
next_state = SM_IDLE;
|
|
|
end
|
end
|
|
|
if (xgxs_rxd_barrel[`LANE1] == `TERMINATE && xgxs_rxc_barrel[1]) begin
|
if (xgxs_rxd_barrel[`LANE1] == `TERMINATE && xgxs_rxc_barrel[1]) begin
|
|
|
rxhfifo_wstatus[`RXSTATUS_EOP] = 1'b1;
|
rxhfifo_wstatus[`RXSTATUS_EOP] = 1'b1;
|
rxhfifo_wstatus[2:0] = 3'd5;
|
rxhfifo_wstatus[2:0] = 3'd5;
|
|
|
crc_start_8b = 1'b1;
|
crc_start_8b = 1'b1;
|
next_crc_bytes = 4'd5;
|
next_crc_bytes = 4'd5;
|
next_crc_rx = {xgxs_rxd_barrel[7:0], xgxs_rxd_barrel_d1[63:40]};
|
next_crc_rx = {xgxs_rxd_barrel[7:0], xgxs_rxd_barrel_d1[63:40]};
|
|
|
next_frame_end_flag = 1'b1;
|
next_frame_end_flag = 1'b1;
|
next_frame_end_bytes = 3'd1;
|
next_frame_end_bytes = 3'd1;
|
|
|
next_state = SM_IDLE;
|
next_state = SM_IDLE;
|
|
|
end
|
end
|
|
|
if (xgxs_rxd_barrel[`LANE0] == `TERMINATE && xgxs_rxc_barrel[0]) begin
|
if (xgxs_rxd_barrel[`LANE0] == `TERMINATE && xgxs_rxc_barrel[0]) begin
|
|
|
rxhfifo_wstatus[`RXSTATUS_EOP] = 1'b1;
|
rxhfifo_wstatus[`RXSTATUS_EOP] = 1'b1;
|
rxhfifo_wstatus[2:0] = 3'd4;
|
rxhfifo_wstatus[2:0] = 3'd4;
|
|
|
crc_start_8b = 1'b1;
|
crc_start_8b = 1'b1;
|
next_crc_bytes = 4'd4;
|
next_crc_bytes = 4'd4;
|
next_crc_rx = xgxs_rxd_barrel_d1[63:32];
|
next_crc_rx = xgxs_rxd_barrel_d1[63:32];
|
|
|
next_frame_end_flag = 1'b1;
|
next_frame_end_flag = 1'b1;
|
|
|
next_state = SM_IDLE;
|
next_state = SM_IDLE;
|
|
|
end
|
end
|
|
|
// Look at current cycle for TERMINATE in lanes 5 to 7
|
// Look at current cycle for TERMINATE in lanes 5 to 7
|
|
|
if (xgxs_rxd_barrel_d1[`LANE7] == `TERMINATE &&
|
if (xgxs_rxd_barrel_d1[`LANE7] == `TERMINATE &&
|
xgxs_rxc_barrel_d1[7]) begin
|
xgxs_rxc_barrel_d1[7]) begin
|
|
|
rxhfifo_wstatus[`RXSTATUS_EOP] = 1'b1;
|
rxhfifo_wstatus[`RXSTATUS_EOP] = 1'b1;
|
rxhfifo_wstatus[2:0] = 3'd3;
|
rxhfifo_wstatus[2:0] = 3'd3;
|
|
|
crc_start_8b = 1'b1;
|
crc_start_8b = 1'b1;
|
next_crc_bytes = 4'd3;
|
next_crc_bytes = 4'd3;
|
next_crc_rx = xgxs_rxd_barrel_d1[55:24];
|
next_crc_rx = xgxs_rxd_barrel_d1[55:24];
|
|
|
next_frame_end_flag = 1'b1;
|
next_frame_end_flag = 1'b1;
|
|
|
next_state = SM_IDLE;
|
next_state = SM_IDLE;
|
|
|
end
|
end
|
|
|
if (xgxs_rxd_barrel_d1[`LANE6] == `TERMINATE &&
|
if (xgxs_rxd_barrel_d1[`LANE6] == `TERMINATE &&
|
xgxs_rxc_barrel_d1[6]) begin
|
xgxs_rxc_barrel_d1[6]) begin
|
|
|
rxhfifo_wstatus[`RXSTATUS_EOP] = 1'b1;
|
rxhfifo_wstatus[`RXSTATUS_EOP] = 1'b1;
|
rxhfifo_wstatus[2:0] = 3'd2;
|
rxhfifo_wstatus[2:0] = 3'd2;
|
|
|
crc_start_8b = 1'b1;
|
crc_start_8b = 1'b1;
|
next_crc_bytes = 4'd2;
|
next_crc_bytes = 4'd2;
|
next_crc_rx = xgxs_rxd_barrel_d1[47:16];
|
next_crc_rx = xgxs_rxd_barrel_d1[47:16];
|
|
|
next_frame_end_flag = 1'b1;
|
next_frame_end_flag = 1'b1;
|
|
|
next_state = SM_IDLE;
|
next_state = SM_IDLE;
|
|
|
end
|
end
|
|
|
if (xgxs_rxd_barrel_d1[`LANE5] == `TERMINATE &&
|
if (xgxs_rxd_barrel_d1[`LANE5] == `TERMINATE &&
|
xgxs_rxc_barrel_d1[5]) begin
|
xgxs_rxc_barrel_d1[5]) begin
|
|
|
rxhfifo_wstatus[`RXSTATUS_EOP] = 1'b1;
|
rxhfifo_wstatus[`RXSTATUS_EOP] = 1'b1;
|
rxhfifo_wstatus[2:0] = 3'd1;
|
rxhfifo_wstatus[2:0] = 3'd1;
|
|
|
crc_start_8b = 1'b1;
|
crc_start_8b = 1'b1;
|
next_crc_bytes = 4'd1;
|
next_crc_bytes = 4'd1;
|
next_crc_rx = xgxs_rxd_barrel_d1[39:8];
|
next_crc_rx = xgxs_rxd_barrel_d1[39:8];
|
|
|
next_frame_end_flag = 1'b1;
|
next_frame_end_flag = 1'b1;
|
|
|
next_state = SM_IDLE;
|
next_state = SM_IDLE;
|
|
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
default:
|
default:
|
begin
|
begin
|
next_state = SM_IDLE;
|
next_state = SM_IDLE;
|
end
|
end
|
|
|
endcase
|
endcase
|
|
|
end
|
end
|
|
|
|
|
always @(posedge clk_xgmii_rx or negedge reset_xgmii_rx_n) begin
|
always @(posedge clk_xgmii_rx or negedge reset_xgmii_rx_n) begin
|
|
|
if (reset_xgmii_rx_n == 1'b0) begin
|
if (reset_xgmii_rx_n == 1'b0) begin
|
|
|
rxhfifo_ralmost_empty_d1 <= 1'b1;
|
rxhfifo_ralmost_empty_d1 <= 1'b1;
|
|
|
drop_data <= 1'b0;
|
drop_data <= 1'b0;
|
|
|
pkt_pending <= 1'b0;
|
pkt_pending <= 1'b0;
|
|
|
rxhfifo_ren_d1 <= 1'b0;
|
rxhfifo_ren_d1 <= 1'b0;
|
|
|
end
|
end
|
else begin
|
else begin
|
|
|
rxhfifo_ralmost_empty_d1 <= rxhfifo_ralmost_empty;
|
rxhfifo_ralmost_empty_d1 <= rxhfifo_ralmost_empty;
|
|
|
drop_data <= next_drop_data;
|
drop_data <= next_drop_data;
|
|
|
pkt_pending <= rxhfifo_ren;
|
pkt_pending <= rxhfifo_ren;
|
|
|
rxhfifo_ren_d1 <= rxhfifo_ren;
|
rxhfifo_ren_d1 <= rxhfifo_ren;
|
|
|
end
|
end
|
|
|
end
|
end
|
|
|
always @(/*AS*/crc_done or crc_good or drop_data or pkt_pending
|
always @(/*AS*/crc_done or crc_good or drop_data or lenght_error
|
or rxdfifo_wfull or rxhfifo_ralmost_empty_d1 or rxhfifo_rdata
|
or pkt_pending or rxdfifo_wfull or rxhfifo_ralmost_empty_d1
|
or rxhfifo_ren_d1 or rxhfifo_rstatus) begin
|
or rxhfifo_rdata or rxhfifo_ren_d1 or rxhfifo_rstatus) begin
|
|
|
rxd_ovflow_error = 1'b0;
|
rxd_ovflow_error = 1'b0;
|
|
|
rxdfifo_wdata = rxhfifo_rdata;
|
rxdfifo_wdata = rxhfifo_rdata;
|
rxdfifo_wstatus = rxhfifo_rstatus;
|
rxdfifo_wstatus = rxhfifo_rstatus;
|
|
|
next_drop_data = drop_data;
|
next_drop_data = drop_data;
|
|
|
|
|
// There must be at least 8 words in holding FIFO before we start reading.
|
// There must be at least 8 words in holding FIFO before we start reading.
|
// This provides enough time for CRC calculation.
|
// This provides enough time for CRC calculation.
|
|
|
rxhfifo_ren = !rxhfifo_ralmost_empty_d1 ||
|
rxhfifo_ren = !rxhfifo_ralmost_empty_d1 ||
|
(pkt_pending && !rxhfifo_rstatus[`RXSTATUS_EOP]);
|
(pkt_pending && !rxhfifo_rstatus[`RXSTATUS_EOP]);
|
|
|
|
|
if (rxhfifo_ren_d1 && rxhfifo_rstatus[`RXSTATUS_SOP]) begin
|
if (rxhfifo_ren_d1 && rxhfifo_rstatus[`RXSTATUS_SOP]) begin
|
|
|
// Reset drop flag on SOP
|
// Reset drop flag on SOP
|
|
|
next_drop_data = 1'b0;
|
next_drop_data = 1'b0;
|
|
|
end
|
end
|
|
|
if (rxhfifo_ren_d1 && rxdfifo_wfull && !next_drop_data) begin
|
if (rxhfifo_ren_d1 && rxdfifo_wfull && !next_drop_data) begin
|
|
|
// FIFO overflow, abort transfer. The rest of the frame
|
// FIFO overflow, abort transfer. The rest of the frame
|
// will be dropped. Since we can't put an EOP indication
|
// will be dropped. Since we can't put an EOP indication
|
// in a fifo already full, there will be no EOP and receive
|
// in a fifo already full, there will be no EOP and receive
|
// side will need to sync on next SOP.
|
// side will need to sync on next SOP.
|
|
|
rxd_ovflow_error = 1'b1;
|
rxd_ovflow_error = 1'b1;
|
next_drop_data = 1'b1;
|
next_drop_data = 1'b1;
|
|
|
end
|
end
|
|
|
|
|
rxdfifo_wen = rxhfifo_ren_d1 && !next_drop_data;
|
rxdfifo_wen = rxhfifo_ren_d1 && !next_drop_data;
|
|
|
|
|
|
|
if (crc_done && !crc_good) begin
|
if ((crc_done && !crc_good) || lenght_error) begin
|
|
|
// Flag packet with error when CRC error is detected
|
// Flag packet with error when CRC error is detected
|
|
|
rxdfifo_wstatus[`RXSTATUS_ERR] = 1'b1;
|
rxdfifo_wstatus[`RXSTATUS_ERR] = 1'b1;
|
|
|
end
|
end
|
|
|
end
|
end
|
|
|
endmodule
|
endmodule
|
|
|