/*
|
/*
|
* .--------------. .----------------. .------------.
|
* .--------------. .----------------. .------------.
|
* | .------------. | .--------------. | .----------. |
|
* | .------------. | .--------------. | .----------. |
|
* | | ____ ____ | | | ____ ____ | | | ______ | |
|
* | | ____ ____ | | | ____ ____ | | | ______ | |
|
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || |
|
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || |
|
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| |
|
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| |
|
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | |
|
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | |
|
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| |
|
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| |
|
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| |
|
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| |
|
* | | | | | | | | | | | |
|
* | | | | | | | | | | | |
|
* |_| | '------------' | '--------------' | '----------' |
|
* |_| | '------------' | '--------------' | '----------' |
|
* '--------------' '----------------' '------------'
|
* '--------------' '----------------' '------------'
|
*
|
*
|
* openHMC - An Open Source Hybrid Memory Cube Controller
|
* openHMC - An Open Source Hybrid Memory Cube Controller
|
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg
|
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg
|
* www.ziti.uni-heidelberg.de
|
* www.ziti.uni-heidelberg.de
|
* B6, 26
|
* B6, 26
|
* 68159 Mannheim
|
* 68159 Mannheim
|
* Germany
|
* Germany
|
*
|
*
|
* Contact: openhmc@ziti.uni-heidelberg.de
|
* Contact: openhmc@ziti.uni-heidelberg.de
|
* http://ra.ziti.uni-heidelberg.de/openhmc
|
* http://ra.ziti.uni-heidelberg.de/openhmc
|
*
|
*
|
* This source file is free software: you can redistribute it and/or modify
|
* This source file is free software: you can redistribute it and/or modify
|
* it under the terms of the GNU Lesser General Public License as published by
|
* it under the terms of the GNU Lesser General Public License as published by
|
* the Free Software Foundation, either version 3 of the License, or
|
* the Free Software Foundation, either version 3 of the License, or
|
* (at your option) any later version.
|
* (at your option) any later version.
|
*
|
*
|
* This source file is distributed in the hope that it will be useful,
|
* This source file is distributed in the hope that it will be useful,
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
* GNU Lesser General Public License for more details.
|
* GNU Lesser General Public License for more details.
|
*
|
*
|
* You should have received a copy of the GNU Lesser General Public License
|
* You should have received a copy of the GNU Lesser General Public License
|
* along with this source file. If not, see <http://www.gnu.org/licenses/>.
|
* along with this source file. If not, see <http://www.gnu.org/licenses/>.
|
*
|
*
|
*
|
*
|
* Module name: rx_crc_compare
|
* Module name: rx_crc_compare
|
*
|
*
|
*/
|
*/
|
|
|
`default_nettype none
|
`default_nettype none
|
|
|
module rx_crc_compare #(
|
module rx_crc_compare #(
|
parameter LOG_FPW = 2,
|
parameter LOG_FPW = 2,
|
parameter FPW = 4,
|
parameter FPW = 4,
|
parameter DWIDTH = 512
|
parameter DWIDTH = 512
|
) (
|
) (
|
|
|
//----------------------------------
|
//----------------------------------
|
//----SYSTEM INTERFACE
|
//----SYSTEM INTERFACE
|
//----------------------------------
|
//----------------------------------
|
input wire clk,
|
input wire clk,
|
input wire res_n,
|
input wire res_n,
|
|
|
//----------------------------------
|
//----------------------------------
|
//----Input data
|
//----Input data
|
//----------------------------------
|
//----------------------------------
|
input wire [FPW-1:0] d_in_hdr,
|
input wire [FPW-1:0] d_in_hdr,
|
input wire [FPW-1:0] d_in_tail,
|
input wire [FPW-1:0] d_in_tail,
|
input wire [FPW-1:0] d_in_valid,
|
input wire [FPW-1:0] d_in_valid,
|
input wire [DWIDTH-1:0] d_in_data,
|
input wire [DWIDTH-1:0] d_in_data,
|
input wire [(FPW*4)-1:0] d_in_lng,
|
input wire [(FPW*4)-1:0] d_in_lng,
|
|
|
//----------------------------------
|
//----------------------------------
|
//----Outputs
|
//----Outputs
|
//----------------------------------
|
//----------------------------------
|
output wire [DWIDTH-1:0] d_out_data,
|
output wire [DWIDTH-1:0] d_out_data,
|
output reg [FPW-1:0] d_out_hdr,
|
output reg [FPW-1:0] d_out_hdr,
|
output reg [FPW-1:0] d_out_tail,
|
output reg [FPW-1:0] d_out_tail,
|
output reg [FPW-1:0] d_out_valid,
|
output reg [FPW-1:0] d_out_valid,
|
output reg [FPW-1:0] d_out_error,
|
output reg [FPW-1:0] d_out_error,
|
output reg [FPW-1:0] d_out_poisoned,
|
output reg [FPW-1:0] d_out_poisoned,
|
output reg [FPW-1:0] d_out_rtc,
|
output reg [FPW-1:0] d_out_rtc,
|
output reg [FPW-1:0] d_out_flow
|
output reg [FPW-1:0] d_out_flow
|
|
|
);
|
);
|
|
|
//=====================================================================================================
|
//=====================================================================================================
|
//-----------------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------------
|
//---------WIRING AND SIGNAL STUFF---------------------------------------------------------------------
|
//---------WIRING AND SIGNAL STUFF---------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------------
|
//=====================================================================================================
|
//=====================================================================================================
|
|
|
`include "hmc_field_functions.h"
|
`include "hmc_field_functions.h"
|
//------------------------------------------------------------------------------------General Assignments
|
//------------------------------------------------------------------------------------General Assignments
|
integer i_f; //counts to FPW
|
integer i_f; //counts to FPW
|
integer i_f2; //counts to FPW inside another i_f loop
|
integer i_f2; //counts to FPW inside another i_f loop
|
integer i_c; //depth of the crc data pipeline
|
integer i_c; //depth of the crc data pipeline
|
|
|
genvar f, f2;
|
genvar f, f2;
|
|
|
localparam CMD_TRET = 6'b000010;
|
localparam CMD_TRET = 6'b000010;
|
localparam CMD_PRET = 6'b000001;
|
localparam CMD_PRET = 6'b000001;
|
|
|
//------------------------------------------------------------------------------------Split input data into FLITs
|
//------------------------------------------------------------------------------------Split input data into FLITs
|
wire [127:0] d_in_flit [FPW-1:0];
|
wire [127:0] d_in_flit [FPW-1:0];
|
wire [127:0] d_in_flit_removed_crc [FPW-1:0];
|
wire [127:0] d_in_flit_removed_crc [FPW-1:0];
|
generate
|
generate
|
for(f = 0; f < (FPW); f = f + 1) begin
|
for(f = 0; f < (FPW); f = f + 1) begin
|
assign d_in_flit[f] = d_in_data[(f*128)+128-1:f*128];
|
assign d_in_flit[f] = d_in_data[(f*128)+128-1:f*128];
|
assign d_in_flit_removed_crc[f][95:0] = d_in_flit[f][95:0];
|
assign d_in_flit_removed_crc[f][95:0] = d_in_flit[f][95:0];
|
assign d_in_flit_removed_crc[f][127:96] = d_in_tail[f] ? {32'h0} : d_in_flit[f][127:96];
|
assign d_in_flit_removed_crc[f][127:96] = d_in_tail[f] ? {32'h0} : d_in_flit[f][127:96];
|
end
|
end
|
endgenerate
|
endgenerate
|
|
|
reg [DWIDTH-1:0] d_in_data_dly;
|
reg [DWIDTH-1:0] d_in_data_dly;
|
reg [FPW-1:0] d_in_hdr_dly;
|
reg [FPW-1:0] d_in_hdr_dly;
|
reg [FPW-1:0] d_in_tail_dly;
|
reg [FPW-1:0] d_in_tail_dly;
|
reg [FPW-1:0] d_in_valid_dly;
|
reg [FPW-1:0] d_in_valid_dly;
|
reg [LOG_FPW-1:0] d_in_flit_target_crc [FPW-1:0];
|
reg [LOG_FPW-1:0] d_in_flit_target_crc [FPW-1:0];
|
|
|
wire [3:0] d_in_lng_per_flit [FPW-1:0];
|
wire [3:0] d_in_lng_per_flit [FPW-1:0];
|
reg [3:0] d_in_lng_per_flit_dly [FPW-1:0];
|
reg [3:0] d_in_lng_per_flit_dly [FPW-1:0];
|
generate
|
generate
|
for(f = 0; f < (FPW); f = f + 1) begin : retrieve_packet_lengths_for_crc_assignment
|
for(f = 0; f < (FPW); f = f + 1) begin : retrieve_packet_lengths_for_crc_assignment
|
assign d_in_lng_per_flit[f] = d_in_lng[(f*4)+4-1:f*4] ;
|
assign d_in_lng_per_flit[f] = d_in_lng[(f*4)+4-1:f*4] ;
|
end
|
end
|
endgenerate
|
endgenerate
|
|
|
//------------------------------------------------------------------------------------CRC Target Assignment
|
//------------------------------------------------------------------------------------CRC Target Assignment
|
reg swap_crc;
|
reg swap_crc;
|
|
|
//Retrieve the target crc from the header and assign to corresponding tail
|
//Retrieve the target crc from the header and assign to corresponding tail
|
reg [LOG_FPW-1:0] target_crc_per_tail [FPW-1:0];
|
reg [LOG_FPW-1:0] target_crc_per_tail [FPW-1:0];
|
reg [LOG_FPW-1:0] target_crc_per_tail1 [FPW-1:0];
|
reg [LOG_FPW-1:0] target_crc_per_tail1 [FPW-1:0];
|
reg [LOG_FPW-1:0] target_crc_per_tail_comb[FPW-1:0];
|
reg [LOG_FPW-1:0] target_crc_per_tail_comb[FPW-1:0];
|
reg [LOG_FPW-1:0] target_crc_comb;
|
reg [LOG_FPW-1:0] target_crc_comb;
|
reg [LOG_FPW-1:0] target_crc_temp;
|
reg [LOG_FPW-1:0] target_crc_temp;
|
|
|
//------------------------------------------------------------------------------------CRC Modules Input stage
|
//------------------------------------------------------------------------------------CRC Modules Input stage
|
wire [31:0] crc_init_out [FPW-1:0];
|
wire [31:0] crc_init_out [FPW-1:0];
|
reg [31:0] crc_accu_in [FPW-1:0];
|
reg [31:0] crc_accu_in [FPW-1:0];
|
reg [FPW-1:0] crc_accu_in_valid [FPW-1:0];
|
reg [FPW-1:0] crc_accu_in_valid [FPW-1:0];
|
reg [FPW-1:0] crc_accu_in_tail [FPW-1:0];
|
reg [FPW-1:0] crc_accu_in_tail [FPW-1:0];
|
wire [31:0] crc_per_flit [FPW-1:0];
|
wire [31:0] crc_per_flit [FPW-1:0];
|
|
|
//------------------------------------------------------------------------------------Inter CRC stage
|
//------------------------------------------------------------------------------------Inter CRC stage
|
reg [3:0] payload_remain [FPW-1:0];
|
reg [3:0] payload_remain [FPW-1:0];
|
|
|
wire [(FPW*32)-1:0] crc_accu_in_combined [FPW-1:0];
|
wire [(FPW*32)-1:0] crc_accu_in_combined [FPW-1:0];
|
generate
|
generate
|
for(f=0;f<FPW;f=f+1) begin
|
for(f=0;f<FPW;f=f+1) begin
|
for(f2=0;f2<FPW;f2=f2+1) begin
|
for(f2=0;f2<FPW;f2=f2+1) begin
|
assign crc_accu_in_combined[f][(f2*32)+31:(f2*32)] = crc_accu_in_valid[f][f2] ? crc_accu_in[f2] : 32'h0;
|
assign crc_accu_in_combined[f][(f2*32)+31:(f2*32)] = crc_accu_in_valid[f][f2] ? crc_accu_in[f2] : 32'h0;
|
end
|
end
|
end
|
end
|
endgenerate
|
endgenerate
|
|
|
|
|
//------------------------------------------------------------------------------------Data Pipeline signals
|
//------------------------------------------------------------------------------------Data Pipeline signals
|
reg [DWIDTH-1:0] crc_data_pipe_in_data [1:0];
|
reg [DWIDTH-1:0] crc_data_pipe_in_data [1:0];
|
reg [FPW-1:0] crc_data_pipe_in_hdr [1:0];
|
reg [FPW-1:0] crc_data_pipe_in_hdr [1:0];
|
reg [FPW-1:0] crc_data_pipe_in_tail [1:0];
|
reg [FPW-1:0] crc_data_pipe_in_tail [1:0];
|
reg [FPW-1:0] crc_data_pipe_in_valid [1:0];
|
reg [FPW-1:0] crc_data_pipe_in_valid [1:0];
|
wire [128-1:0] crc_data_pipe_out_data_flit [FPW-1:0];
|
wire [128-1:0] crc_data_pipe_out_data_flit [FPW-1:0];
|
|
|
generate
|
generate
|
for(f = 0; f < (FPW); f = f + 1) begin : assign_data_pipe_output
|
for(f = 0; f < (FPW); f = f + 1) begin : assign_data_pipe_output
|
assign crc_data_pipe_out_data_flit[f] = crc_data_pipe_in_data[1][(f*128)+128-1:f*128];
|
assign crc_data_pipe_out_data_flit[f] = crc_data_pipe_in_data[1][(f*128)+128-1:f*128];
|
end
|
end
|
endgenerate
|
endgenerate
|
|
|
|
|
reg [128-1:0] data_rdy_flit [FPW-1:0];
|
reg [128-1:0] data_rdy_flit [FPW-1:0];
|
generate
|
generate
|
for(f = 0; f < (FPW); f = f + 1) begin : reorder_flits_to_word
|
for(f = 0; f < (FPW); f = f + 1) begin : reorder_flits_to_word
|
assign d_out_data[(f*128)+128-1:(f*128)] = data_rdy_flit[f];
|
assign d_out_data[(f*128)+128-1:(f*128)] = data_rdy_flit[f];
|
end
|
end
|
endgenerate
|
endgenerate
|
|
|
//==================================================================================
|
//==================================================================================
|
//---------------------------------Retrieve the lengths to invalide FLITs
|
//---------------------------------Retrieve the lengths to invalide FLITs
|
//==================================================================================
|
//==================================================================================
|
always @(*) begin
|
always @(*) begin
|
//Retrieve the length from the header and assign it to the tail. This information will be used in the
|
//Retrieve the length from the header and assign it to the tail. This information will be used in the
|
//invalidation stage to the correct number of FLITs
|
//invalidation stage to the correct number of FLITs
|
|
|
target_crc_comb = target_crc_temp;
|
target_crc_comb = target_crc_temp;
|
|
|
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
|
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
|
|
|
if(d_in_hdr_dly[i_f]) begin
|
if(d_in_hdr_dly[i_f]) begin
|
target_crc_comb = d_in_flit_target_crc[i_f];
|
target_crc_comb = d_in_flit_target_crc[i_f];
|
end
|
end
|
|
|
if(d_in_tail_dly[i_f]) begin
|
if(d_in_tail_dly[i_f]) begin
|
target_crc_per_tail_comb[i_f] = target_crc_comb;
|
target_crc_per_tail_comb[i_f] = target_crc_comb;
|
end else begin
|
end else begin
|
target_crc_per_tail_comb[i_f] = {4{1'b0}};
|
target_crc_per_tail_comb[i_f] = {4{1'b0}};
|
end
|
end
|
|
|
end
|
end
|
end
|
end
|
|
|
//Register combinational values
|
//Register combinational values
|
`ifdef ASYNC_RES
|
`ifdef ASYNC_RES
|
always @(posedge clk or negedge res_n) begin `else
|
always @(posedge clk or negedge res_n) begin `else
|
always @(posedge clk) begin `endif
|
always @(posedge clk) begin `endif
|
if(!res_n) begin
|
if(!res_n) begin
|
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
|
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
|
target_crc_per_tail[i_f] <= 0;
|
target_crc_per_tail[i_f] <= 0;
|
end
|
end
|
target_crc_temp <= {4{1'b0}};
|
target_crc_temp <= {4{1'b0}};
|
end else begin
|
end else begin
|
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
|
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
|
target_crc_per_tail[i_f] <= target_crc_per_tail_comb[i_f];
|
target_crc_per_tail[i_f] <= target_crc_per_tail_comb[i_f];
|
end
|
end
|
target_crc_temp <= target_crc_comb;
|
target_crc_temp <= target_crc_comb;
|
end
|
end
|
end
|
end
|
|
|
//=====================================================================================================
|
//=====================================================================================================
|
//-----------------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------------
|
//---------LOGIC STARTS HERE---------------------------------------------------------------------------
|
//---------LOGIC STARTS HERE---------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------------
|
//=====================================================================================================
|
//=====================================================================================================
|
//====================================================================
|
//====================================================================
|
//---------------------------------Assign input data stream to target CRCs
|
//---------------------------------Assign input data stream to target CRCs
|
//====================================================================
|
//====================================================================
|
`ifdef ASYNC_RES
|
`ifdef ASYNC_RES
|
always @(posedge clk or negedge res_n) begin `else
|
always @(posedge clk or negedge res_n) begin `else
|
always @(posedge clk) begin `endif
|
always @(posedge clk) begin `endif
|
if(!res_n) begin
|
if(!res_n) begin
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
|
d_in_flit_target_crc[i_f] <= {LOG_FPW{1'b0}};
|
d_in_flit_target_crc[i_f] <= {LOG_FPW{1'b0}};
|
end
|
end
|
swap_crc <= 1'b0;
|
swap_crc <= 1'b0;
|
end else begin
|
end else begin
|
|
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
|
d_in_flit_target_crc[i_f] <= {LOG_FPW{1'b0}};
|
d_in_flit_target_crc[i_f] <= {LOG_FPW{1'b0}};
|
end
|
end
|
|
|
//Reset if seen a tail
|
//Reset if seen a tail
|
if(|d_in_tail) begin
|
if(|d_in_tail) begin
|
swap_crc <= 1'b0;
|
swap_crc <= 1'b0;
|
end
|
end
|
|
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
|
if(d_in_hdr[i_f])begin
|
if(d_in_hdr[i_f])begin
|
|
|
if((i_f+d_in_lng_per_flit[i_f])>FPW) begin
|
if((i_f+d_in_lng_per_flit[i_f])>FPW) begin
|
//If the current packet spreads over multiple cycles
|
//If the current packet spreads over multiple cycles
|
|
|
if(swap_crc) begin
|
if(swap_crc) begin
|
//If the last packet was swapped and the current packet also spreads over the more than 1 cycle use crc 0 now
|
//If the last packet was swapped and the current packet also spreads over the more than 1 cycle use crc 0 now
|
d_in_flit_target_crc[i_f] <= 3'h0;
|
d_in_flit_target_crc[i_f] <= 3'h0;
|
end else begin
|
end else begin
|
d_in_flit_target_crc[i_f] <= FPW-1'b1;
|
d_in_flit_target_crc[i_f] <= FPW-1'b1;
|
swap_crc <= 1'b1;
|
swap_crc <= 1'b1;
|
end
|
end
|
|
|
end else begin
|
end else begin
|
|
|
d_in_flit_target_crc[i_f] <= i_f;
|
d_in_flit_target_crc[i_f] <= i_f;
|
|
|
//If the highest order CRC contains a data packet that ends in this cycle, dont use this crc
|
//If the highest order CRC contains a data packet that ends in this cycle, dont use this crc
|
//It's ok always to decrement by 1 since we know the lowest order CRC would not be used (at least FLIT0 goes to highest order CRC)
|
//It's ok always to decrement by 1 since we know the lowest order CRC would not be used (at least FLIT0 goes to highest order CRC)
|
if(swap_crc && !(d_in_hdr > d_in_tail)) begin
|
if(swap_crc && !(d_in_hdr > d_in_tail)) begin
|
d_in_flit_target_crc[i_f] <= i_f-1;
|
d_in_flit_target_crc[i_f] <= i_f-1;
|
end
|
end
|
|
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
end
|
end
|
end
|
end
|
|
|
//Register input values to be used in CRC assignment logic after crc init stage
|
//Register input values to be used in CRC assignment logic after crc init stage
|
`ifdef ASYNC_RES
|
`ifdef ASYNC_RES
|
always @(posedge clk or negedge res_n) begin `else
|
always @(posedge clk or negedge res_n) begin `else
|
always @(posedge clk) begin `endif
|
always @(posedge clk) begin `endif
|
|
`ifdef RESET_ALL
|
|
if(!res_n) d_in_data_dly <= {DWIDTH{1'b0}};
|
|
else
|
|
`endif
|
|
begin
|
|
d_in_data_dly <= d_in_data;
|
|
end
|
|
|
|
`ifdef RESET_ALL
|
if(!res_n) begin
|
if(!res_n) begin
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
|
d_in_lng_per_flit_dly[i_f] <= 4'h0;
|
d_in_lng_per_flit_dly[i_f] <= 4'h0;
|
end
|
end
|
d_in_data_dly <= {DWIDTH{1'b0}};
|
|
d_in_hdr_dly <= {FPW{1'b0}};
|
d_in_hdr_dly <= {FPW{1'b0}};
|
d_in_tail_dly <= {FPW{1'b0}};
|
d_in_tail_dly <= {FPW{1'b0}};
|
d_in_valid_dly <= {FPW{1'b0}};
|
d_in_valid_dly <= {FPW{1'b0}};
|
end else begin
|
end else
|
|
`endif
|
|
begin
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
|
d_in_lng_per_flit_dly[i_f] <= d_in_lng_per_flit[i_f];
|
d_in_lng_per_flit_dly[i_f] <= d_in_lng_per_flit[i_f];
|
end
|
end
|
d_in_data_dly <= d_in_data;
|
d_in_hdr_dly <= d_in_hdr & d_in_valid;
|
d_in_hdr_dly <= d_in_hdr;
|
d_in_tail_dly <= d_in_tail & d_in_valid;
|
d_in_tail_dly <= d_in_tail;
|
|
d_in_valid_dly <= d_in_valid;
|
d_in_valid_dly <= d_in_valid;
|
end
|
end
|
end
|
end
|
|
|
//====================================================================
|
//====================================================================
|
//---------------------------------Inter CRC stage, CRC assignment Logic
|
//---------------------------------Inter CRC stage, CRC assignment Logic
|
//====================================================================
|
//====================================================================
|
`ifdef ASYNC_RES
|
`ifdef ASYNC_RES
|
always @(posedge clk or negedge res_n) begin `else
|
always @(posedge clk or negedge res_n) begin `else
|
always @(posedge clk) begin `endif
|
always @(posedge clk) begin `endif
|
|
|
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
|
|
`ifdef RESET_ALL
|
|
if (!res_n) crc_accu_in[i_f] <= {32{1'b0}};
|
|
else
|
|
`endif
|
|
begin
|
|
crc_accu_in[i_f] <= crc_init_out[i_f];
|
|
end
|
|
end
|
|
|
if(!res_n) begin
|
if(!res_n) begin
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
|
crc_accu_in[i_f] <= {32{1'b0}};
|
|
crc_accu_in_valid[i_f] <= {FPW{1'b0}};
|
crc_accu_in_valid[i_f] <= {FPW{1'b0}};
|
crc_accu_in_tail[i_f] <= {FPW{1'b0}};
|
crc_accu_in_tail[i_f] <= {FPW{1'b0}};
|
payload_remain[i_f] <= 4'h0;
|
payload_remain[i_f] <= 4'h0;
|
end
|
end
|
end else begin
|
end else begin
|
|
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
|
crc_accu_in[i_f] <= crc_init_out[i_f];
|
|
crc_accu_in_valid[i_f] <= 4'h0;
|
crc_accu_in_valid[i_f] <= 4'h0;
|
crc_accu_in_tail[i_f] <= 4'h0;
|
crc_accu_in_tail[i_f] <= 4'h0;
|
end
|
end
|
|
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
|
//First go through accu crcs
|
//First go through accu crcs
|
|
|
if(|payload_remain[i_f]) begin
|
if(|payload_remain[i_f]) begin
|
|
|
if(payload_remain[i_f] > FPW) begin
|
if(payload_remain[i_f] > FPW) begin
|
crc_accu_in_valid[i_f] <= {FPW{1'b1}};
|
crc_accu_in_valid[i_f] <= {FPW{1'b1}};
|
payload_remain[i_f] <= payload_remain[i_f]-FPW;
|
payload_remain[i_f] <= payload_remain[i_f]-FPW;
|
end else begin
|
end else begin
|
crc_accu_in_valid[i_f] <= {FPW{1'b1}} >> (FPW-payload_remain[i_f]);
|
crc_accu_in_valid[i_f] <= {FPW{1'b1}} >> (FPW-payload_remain[i_f]);
|
crc_accu_in_tail[i_f] <= 1'b1 << (payload_remain[i_f]-1);
|
crc_accu_in_tail[i_f] <= 1'b1 << (payload_remain[i_f]-1);
|
payload_remain[i_f] <= 4'h0;
|
payload_remain[i_f] <= 4'h0;
|
end
|
end
|
end
|
end
|
|
|
for(i_f2=0;i_f2<FPW;i_f2=i_f2+1)begin
|
for(i_f2=0;i_f2<FPW;i_f2=i_f2+1)begin
|
if(i_f==d_in_flit_target_crc[i_f2] && d_in_hdr_dly[i_f2]) begin
|
if(i_f==d_in_flit_target_crc[i_f2] && d_in_hdr_dly[i_f2]) begin
|
//Then go through all input crcs from the init crc and find the crc's that must be assigned to the currently selected crc
|
//Then go through all input crcs from the init crc and find the crc's that must be assigned to the currently selected crc
|
|
|
if( (i_f2+d_in_lng_per_flit_dly[i_f2]) >FPW ) begin
|
if( (i_f2+d_in_lng_per_flit_dly[i_f2]) >FPW ) begin
|
payload_remain[i_f] <= (d_in_lng_per_flit_dly[i_f2]-FPW+i_f2);
|
payload_remain[i_f] <= (d_in_lng_per_flit_dly[i_f2]-FPW+i_f2);
|
crc_accu_in_valid[i_f] <= {FPW{1'b1}} >> i_f2 << i_f2;
|
crc_accu_in_valid[i_f] <= {FPW{1'b1}} >> i_f2 << i_f2;
|
end else begin
|
end else begin
|
crc_accu_in_tail[i_f] <= 1'b1 << d_in_lng_per_flit_dly[i_f2]+i_f2-1;
|
crc_accu_in_tail[i_f] <= 1'b1 << d_in_lng_per_flit_dly[i_f2]+i_f2-1;
|
crc_accu_in_valid[i_f] <= ({FPW{1'b1}} >> (FPW-i_f2-d_in_lng_per_flit_dly[i_f2])) >> i_f2 << i_f2;
|
crc_accu_in_valid[i_f] <= ({FPW{1'b1}} >> (FPW-i_f2-d_in_lng_per_flit_dly[i_f2])) >> i_f2 << i_f2;
|
end
|
end
|
end
|
end
|
|
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
//====================================================================
|
//====================================================================
|
//---------------------------------Constant propagation of the data pipeline
|
//---------------------------------Constant propagation of the data pipeline
|
//====================================================================
|
//====================================================================
|
`ifdef ASYNC_RES
|
`ifdef ASYNC_RES
|
always @(posedge clk or negedge res_n) begin `else
|
always @(posedge clk or negedge res_n) begin `else
|
always @(posedge clk) begin `endif
|
always @(posedge clk) begin `endif
|
|
|
|
`ifdef ASYNC_RES
|
if(!res_n) begin
|
if(!res_n) begin
|
for(i_c=0;i_c<2;i_c=i_c+1)begin
|
for(i_c=0;i_c<2;i_c=i_c+1)begin
|
crc_data_pipe_in_data[i_c] <= {DWIDTH{1'b0}};
|
crc_data_pipe_in_data[i_c] <= {DWIDTH{1'b0}};
|
|
end
|
|
end else
|
|
`endif
|
|
begin
|
|
//Data forward
|
|
crc_data_pipe_in_data[0] <= d_in_data_dly;
|
|
crc_data_pipe_in_data[1] <= crc_data_pipe_in_data[0];
|
|
end
|
|
|
|
`ifdef RESET_ALL
|
|
if(!res_n) begin
|
|
for(i_c=0;i_c<2;i_c=i_c+1)begin
|
crc_data_pipe_in_hdr[i_c] <= {FPW{1'b0}};
|
crc_data_pipe_in_hdr[i_c] <= {FPW{1'b0}};
|
crc_data_pipe_in_tail[i_c] <= {FPW{1'b0}};
|
crc_data_pipe_in_tail[i_c] <= {FPW{1'b0}};
|
crc_data_pipe_in_valid[i_c] <= {FPW{1'b0}};
|
crc_data_pipe_in_valid[i_c] <= {FPW{1'b0}};
|
end
|
end
|
|
|
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
|
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
|
target_crc_per_tail1[i_f] <= 3'h0;
|
target_crc_per_tail1[i_f] <= 3'h0;
|
end
|
end
|
end else begin
|
end else
|
|
`endif
|
|
begin
|
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
|
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
|
target_crc_per_tail1[i_f] <= target_crc_per_tail[i_f];
|
target_crc_per_tail1[i_f] <= target_crc_per_tail[i_f];
|
end
|
end
|
|
|
//Set the first stage of the data pipeline
|
//Set the first stage of the data pipeline
|
crc_data_pipe_in_data[0] <= d_in_data_dly;
|
|
crc_data_pipe_in_hdr[0] <= d_in_hdr_dly;
|
crc_data_pipe_in_hdr[0] <= d_in_hdr_dly;
|
crc_data_pipe_in_tail[0] <= d_in_tail_dly;
|
crc_data_pipe_in_tail[0] <= d_in_tail_dly;
|
crc_data_pipe_in_valid[0] <= d_in_valid_dly;
|
crc_data_pipe_in_valid[0] <= d_in_valid_dly;
|
|
|
//Data Pipeline propagation
|
//Second Stage
|
for(i_c=0;i_c<(1);i_c=i_c+1)begin
|
crc_data_pipe_in_tail[1] <= crc_data_pipe_in_tail[0];
|
crc_data_pipe_in_data[i_c+1] <= crc_data_pipe_in_data[i_c];
|
crc_data_pipe_in_hdr[1] <= crc_data_pipe_in_hdr[0];
|
crc_data_pipe_in_tail[i_c+1] <= crc_data_pipe_in_tail[i_c];
|
crc_data_pipe_in_tail[1] <= crc_data_pipe_in_tail[0];
|
crc_data_pipe_in_hdr[i_c+1] <= crc_data_pipe_in_hdr[i_c];
|
crc_data_pipe_in_valid[1] <= crc_data_pipe_in_valid[0];
|
crc_data_pipe_in_tail[i_c+1] <= crc_data_pipe_in_tail[i_c];
|
|
crc_data_pipe_in_valid[i_c+1] <= crc_data_pipe_in_valid[i_c];
|
|
end
|
|
end
|
end
|
end
|
end
|
|
|
//====================================================================
|
//====================================================================
|
//---------------------------------At the end of the data pipeline get and compare the CRCs
|
//---------------------------------At the end of the data pipeline get and compare the CRCs
|
//====================================================================
|
//====================================================================
|
`ifdef ASYNC_RES
|
`ifdef ASYNC_RES
|
always @(posedge clk or negedge res_n) begin `else
|
always @(posedge clk or negedge res_n) begin `else
|
always @(posedge clk) begin `endif
|
always @(posedge clk) begin `endif
|
|
|
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
|
|
`ifdef ASYNC_RES
|
|
if(!res_n)data_rdy_flit[i_f] <= {128{1'b0}};
|
|
else
|
|
`endif
|
|
begin // Datapath
|
|
data_rdy_flit[i_f] <= crc_data_pipe_out_data_flit[i_f];
|
|
end
|
|
end
|
|
//Propagate
|
|
d_out_hdr <= crc_data_pipe_in_hdr[1];
|
|
d_out_tail <= crc_data_pipe_in_tail[1];
|
|
d_out_valid <= crc_data_pipe_in_valid[1];
|
|
|
if(!res_n) begin
|
if(!res_n) begin
|
|
|
//Reset the outputs
|
//Reset the outputs
|
d_out_hdr <= {FPW{1'b0}};
|
|
d_out_tail <= {FPW{1'b0}};
|
|
d_out_valid <= {FPW{1'b0}};
|
|
d_out_error <= {FPW{1'b0}};
|
d_out_error <= {FPW{1'b0}};
|
d_out_poisoned <= {FPW{1'b0}};
|
d_out_poisoned <= {FPW{1'b0}};
|
d_out_rtc <= {FPW{1'b0}};
|
d_out_rtc <= {FPW{1'b0}};
|
d_out_flow <= {FPW{1'b0}};
|
d_out_flow <= {FPW{1'b0}};
|
|
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
|
|
data_rdy_flit[i_f] <= {128{1'b0}};
|
|
end
|
|
|
|
end else begin
|
end else begin
|
|
|
d_out_rtc <= {FPW{1'b0}};
|
d_out_rtc <= {FPW{1'b0}};
|
d_out_error <= {FPW{1'b0}};
|
d_out_error <= {FPW{1'b0}};
|
d_out_poisoned <= {FPW{1'b0}};
|
d_out_poisoned <= {FPW{1'b0}};
|
d_out_flow <= {FPW{1'b0}};
|
d_out_flow <= {FPW{1'b0}};
|
|
|
//Propagate
|
|
d_out_hdr <= crc_data_pipe_in_hdr[1];
|
|
d_out_tail <= crc_data_pipe_in_tail[1];
|
|
d_out_valid <= crc_data_pipe_in_valid[1];
|
|
|
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
|
|
|
|
//Propagate data
|
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
|
data_rdy_flit[i_f] <= crc_data_pipe_out_data_flit[i_f];
|
d_out_error[i_f] <= crc_data_pipe_in_hdr[1][i_f] && ( ~|lng(crc_data_pipe_out_data_flit[i_f])
|
|
|| lng(crc_data_pipe_out_data_flit[i_f])>9
|
|
|| !lng_dln_equal(crc_data_pipe_out_data_flit[i_f]));
|
|
|
if(crc_data_pipe_in_tail[1][i_f])begin
|
if(crc_data_pipe_in_tail[1][i_f])begin
|
//Finally compare the CRC and add flow/rtc information if there is a tail
|
//Finally compare the CRC and add flow/rtc information if there is a tail
|
|
|
if(crc(crc_data_pipe_out_data_flit[i_f]) == ~crc_per_flit[target_crc_per_tail1[i_f]]) begin
|
if(crc(crc_data_pipe_out_data_flit[i_f]) == ~crc_per_flit[target_crc_per_tail1[i_f]]) begin
|
//Poisoned
|
//Poisoned
|
d_out_poisoned[i_f] <= 1'b1;
|
d_out_poisoned[i_f] <= 1'b1;
|
end else if(crc(crc_data_pipe_out_data_flit[i_f]) != crc_per_flit[target_crc_per_tail1[i_f]]) begin
|
end else if(crc(crc_data_pipe_out_data_flit[i_f]) != crc_per_flit[target_crc_per_tail1[i_f]]) begin
|
//Error
|
//Error
|
d_out_error[i_f] <= 1'b1;
|
d_out_error[i_f] <= 1'b1;
|
end
|
end
|
|
|
//Add the return token count indicator when the packet has rtc
|
//Add the return token count indicator when the packet has rtc
|
if(!crc_data_pipe_in_hdr[1][i_f]) begin
|
if(!crc_data_pipe_in_hdr[1][i_f]) begin
|
//Multi-FLIT packets always have a valid RTC
|
//Multi-FLIT packets always have a valid RTC
|
d_out_rtc[i_f] <= 1'b1;
|
d_out_rtc[i_f] <= 1'b1;
|
end else begin
|
end else begin
|
|
|
if((cmd(crc_data_pipe_out_data_flit[i_f]) == CMD_TRET) || !is_flow(crc_data_pipe_out_data_flit[i_f])) begin
|
if((cmd(crc_data_pipe_out_data_flit[i_f]) == CMD_TRET) || !is_rsp_flow(crc_data_pipe_out_data_flit[i_f])) begin
|
//All non-flow packets have a valid RTC
|
//All non-flow packets have a valid RTC, except TRET
|
d_out_rtc[i_f] <= 1'b1;
|
d_out_rtc[i_f] <= 1'b1;
|
end
|
end
|
if(is_flow(crc_data_pipe_out_data_flit[i_f])) begin
|
if(is_rsp_flow(crc_data_pipe_out_data_flit[i_f])) begin
|
//Set the flow packet indicator
|
|
d_out_flow[i_f] <= 1'b1;
|
d_out_flow[i_f] <= 1'b1;
|
|
|
//Check flow packets zero fields
|
|
if(|adrs(crc_data_pipe_out_data_flit[i_f]) || |tag(crc_data_pipe_out_data_flit[i_f])) begin
|
|
d_out_error[i_f] <= 1'b1;
|
|
end
|
|
if( (cmd(crc_data_pipe_out_data_flit[i_f]) != CMD_TRET) &&
|
|
(|rtc(crc_data_pipe_out_data_flit[i_f]) || |seq(crc_data_pipe_out_data_flit[i_f]))) begin
|
|
d_out_error[i_f] <= 1'b1;
|
|
end
|
|
if((cmd(crc_data_pipe_out_data_flit[i_f]) == CMD_PRET) && |frp(crc_data_pipe_out_data_flit[i_f])) begin
|
|
d_out_error[i_f] <= 1'b1;
|
|
end
|
|
end
|
end
|
end
|
end
|
|
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
end
|
|
|
//=====================================================================================================
|
//=====================================================================================================
|
//-----------------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------------
|
//---------INSTANTIATIONS HERE-------------------------------------------------------------------------
|
//---------INSTANTIATIONS HERE-------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------------------------------
|
//=====================================================================================================
|
//=====================================================================================================
|
//Init CRC: Calculate the remainders of each input FLIT individually
|
//Init CRC: Calculate the remainders of each input FLIT individually
|
generate
|
generate
|
for(f=0;f<FPW;f=f+1) begin : crc_init_gen
|
for(f=0;f<FPW;f=f+1) begin : crc_init_gen
|
crc_128_init crc_init_I
|
crc_128_init crc_init_I
|
(
|
(
|
.clk(clk),
|
.clk(clk),
|
|
`ifdef ASYNC_RES
|
.res_n(res_n),
|
.res_n(res_n),
|
|
`endif
|
.inData(d_in_flit_removed_crc[f]),
|
.inData(d_in_flit_removed_crc[f]),
|
.crc(crc_init_out[f])
|
.crc(crc_init_out[f])
|
);
|
);
|
end
|
end
|
endgenerate
|
endgenerate
|
|
|
//Calculate the actual CRC over all valid remainders
|
//Calculate the actual CRC over all valid remainders
|
generate
|
generate
|
for(f=0;f<FPW;f=f+1) begin : crc_accu_gen
|
for(f=0;f<FPW;f=f+1) begin : crc_accu_gen
|
crc_accu #(
|
crc_accu #(
|
.FPW(FPW)
|
.FPW(FPW)
|
)
|
)
|
crc_accu_I
|
crc_accu_I
|
(
|
(
|
.clk(clk),
|
.clk(clk),
|
.res_n(res_n),
|
.res_n(res_n),
|
.tail(crc_accu_in_tail[f]),
|
.tail(crc_accu_in_tail[f]),
|
.d_in(crc_accu_in_combined[f]),
|
.d_in(crc_accu_in_combined[f]),
|
.valid(crc_accu_in_valid[f]),
|
|
.crc_out(crc_per_flit[f])
|
.crc_out(crc_per_flit[f])
|
);
|
);
|
end
|
end
|
endgenerate
|
endgenerate
|
|
|
endmodule
|
endmodule
|
`default_nettype wire
|
`default_nettype wire
|
No newline at end of file
|
No newline at end of file
|
|
|
No newline at end of file
|
No newline at end of file
|