OpenCores
URL https://opencores.org/ocsvn/openhmc/openhmc/trunk

Subversion Repositories openhmc

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 1 to Rev 2
    Reverse comparison

Rev 1 → Rev 2

/openhmc/trunk/openHMC/rtl/include/hmc_field_functions.h
0,0 → 1,189
/*
* .--------------. .----------------. .------------.
* | .------------. | .--------------. | .----------. |
* | | ____ ____ | | | ____ ____ | | | ______ | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| |
* | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' |
* '--------------' '----------------' '------------'
*
* openHMC - An Open Source Hybrid Memory Cube Controller
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg
* www.ziti.uni-heidelberg.de
* B6, 26
* 68159 Mannheim
* Germany
*
* Contact: openhmc@ziti.uni-heidelberg.de
* http://ra.ziti.uni-heidelberg.de/openhmc
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This source file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* 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/>.
*
*
* File name: hmc_field_functions.h
*
*/
 
//------------------------------------------------------------------------HMC HEADER FIELDS
function [5:0] cmd;
input [127:0] flit;
 
begin
cmd = flit[5:0];
end
endfunction
 
function [5:0] num_requested_flits;
input [127:0] flit;
 
begin
num_requested_flits = flit[2:0] + 2; //+1 for the encoding
end
endfunction
function [2:0] flow_cmd;
input [127:0] flit;
 
begin
flow_cmd = flit[2:0];
end
endfunction
 
function [2:0] cmd_type;
input [127:0] flit;
 
begin
cmd_type = flit[5:3];
end
endfunction
 
function is_flow;
input [127:0] flit;
begin
if(flit[5:3]) begin
is_flow = 0;
end else begin
is_flow = 1;
end
end
endfunction
 
function irtry_start_retry_flag;
input [127:0] flit;
 
begin
irtry_start_retry_flag = flit[64+8];
end
endfunction
 
function irtry_clear_error_flag;
input [127:0] flit;
 
begin
irtry_clear_error_flag = flit[64+8+1];
end
endfunction
function [3:0] lng;
input [127:0] flit;
 
begin
lng = flit[10:7];
end
endfunction
function [3:0] dln;
input [127:0] flit;
 
begin
dln = flit[14:11];
end
endfunction
function [8:0] tag;
input [127:0] flit;
 
begin
tag = flit[23:15];
end
endfunction
function [57:24] adrs;
input [127:0] flit;
 
begin
adrs = flit[57:24];
end
endfunction
 
function [2:0] cub;
input [127:0] flit;
 
begin
cub = flit[63:61];
end
endfunction
//------------------------------------------------------------------------HMC TAIL FIELDS
function [7:0] rrp;
input [127:0] flit;
 
begin
rrp = flit[64+8-1:64];
end
endfunction
 
function [7:0] frp;
input [127:0] flit;
 
begin
frp = flit[64+8+8-1:64+8];
end
endfunction
function [2:0] seq;
input [127:0] flit;
 
begin
seq = flit[64+8+8+3-1:64+8+8];
end
endfunction
function [4:0] rtc;
input [127:0] flit;
 
begin
rtc = flit[64+31:64+27];
end
endfunction
function [31:0] crc;
input [127:0] flit;
 
begin
crc = flit[127:128-32];
end
endfunction
 
/openhmc/trunk/openHMC/rtl/building_blocks/counter/counter48.v
0,0 → 1,86
/*
* .--------------. .----------------. .------------.
* | .------------. | .--------------. | .----------. |
* | | ____ ____ | | | ____ ____ | | | ______ | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| |
* | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' |
* '--------------' '----------------' '------------'
*
* openHMC - An Open Source Hybrid Memory Cube Controller
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg
* www.ziti.uni-heidelberg.de
* B6, 26
* 68159 Mannheim
* Germany
*
* Contact: openhmc@ziti.uni-heidelberg.de
* http://ra.ziti.uni-heidelberg.de/openhmc
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This source file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* 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/>.
*
*
* Module name: counter48
*
*/
 
`default_nettype none
 
module counter48 #(
parameter DATASIZE = 16 // width of the counter, must be <=48 bits!
) (
input wire clk,
input wire res_n,
input wire increment,
input wire [DATASIZE-1:0] load,
input wire load_enable,
output wire [DATASIZE-1:0] value
);
 
reg [DATASIZE-1:0] value_reg;
reg load_enable_reg;
 
assign value = value_reg;
 
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) `else
always @(posedge clk) `endif
begin
if (!res_n)
begin
value_reg <= {DATASIZE{1'b0}};
load_enable_reg <= 1'b0;
end
else
begin
load_enable_reg <= load_enable;
case ({load_enable_reg,increment})
2'b00:
value_reg <= value_reg;
2'b01:
value_reg <= (value_reg + 1'b1);
2'b10:
value_reg <= {DATASIZE{1'b0}};
2'b11:
value_reg <= {DATASIZE{1'b0}} + 1'b1;
endcase
end
end
 
endmodule
`default_nettype wire
/openhmc/trunk/openHMC/rtl/building_blocks/rams/hmc_ram.v
0,0 → 1,116
/*
* .--------------. .----------------. .------------.
* | .------------. | .--------------. | .----------. |
* | | ____ ____ | | | ____ ____ | | | ______ | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| |
* | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' |
* '--------------' '----------------' '------------'
*
* openHMC - An Open Source Hybrid Memory Cube Controller
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg
* www.ziti.uni-heidelberg.de
* B6, 26
* 68159 Mannheim
* Germany
*
* Contact: openhmc@ziti.uni-heidelberg.de
* http://ra.ziti.uni-heidelberg.de/openhmc
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This source file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* 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/>.
*
*
* Module name: hmc_ram
*
*/
 
`default_nettype none
 
module hmc_ram #(
parameter DATASIZE = 78, // Memory data word width
parameter ADDRSIZE = 9, // Number of memory address bits
parameter PIPELINED = 0
) (
//----------------------------------
//----SYSTEM INTERFACE
//----------------------------------
input wire clk,
 
//----------------------------------
//----Signals
//----------------------------------
input wire wen,
input wire [DATASIZE-1:0] wdata,
input wire [ADDRSIZE-1:0] waddr,
input wire ren,
input wire [ADDRSIZE-1:0] raddr,
output wire [DATASIZE-1:0] rdata
);
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------WIRING AND SIGNAL STUFF---------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
 
wire [DATASIZE-1:0] rdata_ram;
 
generate
if (PIPELINED == 0)
begin
assign rdata = rdata_ram;
end
else
begin
reg [DATASIZE-1:0] rdata_dly;
reg ren_dly;
 
assign rdata = rdata_dly;
 
always @(posedge clk)
begin
ren_dly <= ren;
 
if (ren_dly)
rdata_dly <= rdata_ram;
end
end
endgenerate
 
reg [DATASIZE-1:0] MEM [0:(2**ADDRSIZE)-1];
reg [DATASIZE-1:0] data_out;
 
assign rdata_ram = data_out;
 
 
 
always @(posedge clk)
begin
if (wen)
MEM[waddr] <= wdata;
end
 
always @(posedge clk)
begin
if (ren)
data_out <= MEM[raddr];
end
 
endmodule
 
`default_nettype wire
/openhmc/trunk/openHMC/rtl/building_blocks/fifos/sync/sync_fifo.v
0,0 → 1,264
/*
* .--------------. .----------------. .------------.
* | .------------. | .--------------. | .----------. |
* | | ____ ____ | | | ____ ____ | | | ______ | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| |
* | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' |
* '--------------' '----------------' '------------'
*
* openHMC - An Open Source Hybrid Memory Cube Controller
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg
* www.ziti.uni-heidelberg.de
* B6, 26
* 68159 Mannheim
* Germany
*
* Contact: openhmc@ziti.uni-heidelberg.de
* http://ra.ziti.uni-heidelberg.de/openhmc
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This source file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* 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/>.
*
*
* Module name: sync_fifo
*
*/
 
`default_nettype none
 
module sync_fifo #(
parameter DATASIZE = 8,
parameter ADDRSIZE = 8,
parameter GATE_SHIFT_IN = 0,
parameter CHAIN_ENABLE = 0
) (
//----------------------------------
//----SYSTEM INTERFACE
//----------------------------------
input wire clk,
input wire res_n,
 
//----------------------------------
//----Signals
//----------------------------------
input wire [DATASIZE-1:0] d_in,
input wire shift_in,
input wire shift_out,
input wire next_stage_full, // Set to 1 if not chained
output wire [DATASIZE-1:0] d_out,
output wire empty
);
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------WIRING AND SIGNAL STUFF---------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
 
wire si, so; // internal gated shift signals
reg full, full_r1, full_r2;
wire full_1, full_2, full_3;
reg full_m2, full_m1;
 
reg [DATASIZE-1:0] d_out_r1, d_out_r2;
wire [DATASIZE-1:0] d_out_m2, d_out_2, d_out_3;
wire mux_rm_2;
 
reg [ADDRSIZE -1:0] ra_m, wa_m; //addr after register similar to signal internal to sram
reg [ADDRSIZE -1:0] ra, wa; // address calculated for the next read
wire wen, ren;
 
wire m_empty;
 
assign full_1 = full_r1 || full_m1 || (full_m2 && full_r2);
assign full_2 = full_r2 || full_m2;
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------LOGIC STARTS HERE---------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
 
always @ (posedge clk or negedge res_n) begin
if (!res_n) begin
d_out_r1 <= {DATASIZE {1'b0}};
d_out_r2 <= {DATASIZE {1'b0}};
full_r1 <= 1'b0;
full_r2 <= 1'b0;
end else begin
 
// Register stage 1 (conditions shouldn't overlap)
if ((full_2 && !full_1 && si && !so) || // fill stage
(full_1 && m_empty && si && so)) begin // shift through
d_out_r1 <= d_in;
full_r1 <= 1'b1;
end
if (full_r1 && so && (!si || !m_empty)) begin // shift out
full_r1 <= 1'b0;
end
 
// Register stage 2 (conditions shouldn't overlap)
if (full_3 && ((!full_2 && si && !so) || // fill stage
(full_2 && !full_1 && si && so))) begin // shift through
d_out_r2 <= d_in;
full_r2 <= 1'b1;
end
if (full_r1 && so) begin // shift through
d_out_r2 <= d_out_r1;
full_r2 <= 1'b1;
end
if (full_m2 && ((!full_r2 && !so) || // Rescue
(full_r2 && so))) begin
d_out_r2 <= d_out_m2;
full_r2 <= 1'b1;
end
if (full_r2 &&
((!full_r1 && !full_m2 && so && !si) || // shift out
(full_m1 && si && so))) begin // shift through with RAM
full_r2 <= 1'b0;
end
end
end
 
// assign outputs and inputs to module interface
assign d_out = d_out_3;
 
assign empty = !full_3; // if the last stage is empty, the fifo is empty
 
generate // gating of si and so, just for compatability!!!
if (GATE_SHIFT_IN) begin : shift_in_gated
assign si = shift_in && !full;
end
else begin : shift_in_raw
assign si = shift_in;
end
 
assign so = shift_out;
endgenerate
 
wire [ADDRSIZE:0] fifo_ram_count = wa_m - ra_m;
 
assign mux_rm_2 = full_r2; // mux control of SRAM data bypass if only one value in stage r2
assign d_out_2 = mux_rm_2 ? d_out_r2 : d_out_m2; // additional data mux for SRAM bypass
 
// write port control of SRAM
assign wen = si && !so && full_1 // enter new value into SRAM, because regs are filled
|| si && !m_empty; // if a value is in the SRAM, then we have to shift through or shift in
 
// read port control of SRAM
assign ren = so && !m_empty;
 
assign m_empty = (wa_m == ra_m);
 
always @ (posedge clk or negedge res_n) begin
if (!res_n) begin
full_m1 <= 1'b0;
full_m2 <= 1'b0;
end else begin
full_m1 <= ren; // no control of m1
full_m2 <= full_m1
|| full_m2 && !so && full_r2; // no rescue possible
end
end
 
// pointer management
always @(*) begin
wa = wa_m + 1'b1; // wa_m is the address stored in mem addr register
ra = ra_m + 1'b1;
end
 
always @ (posedge clk or negedge res_n) begin
if (!res_n) begin
wa_m <= {ADDRSIZE {1'b0}};
ra_m <= {ADDRSIZE {1'b0}};
end else begin
if (wen) begin
wa_m <= wa; // next mem write addr to mem addr register
end
 
if (ren) begin
ra_m <= ra;
end
end
end
 
// Calculate full as two spaces left in the RAM before si and !so
wire [ADDRSIZE:0] const_f_next = -2; //After si the RAM will be full
 
always @ (posedge clk or negedge res_n) begin
if (!res_n) begin
full <= 1'b0;
end else begin
if ((fifo_ram_count[ADDRSIZE-1:0] == const_f_next[ADDRSIZE-1:0]) && si && !so) begin
full <= 1'b1;
end
if ((full == 1'b1) && !si && so) begin
full <= 1'b0;
end
end
end
 
wire stage4_full;
generate
if (CHAIN_ENABLE) begin : chaining_enabled
assign stage4_full = next_stage_full;
end
else begin : chaining_disabled
assign stage4_full = 1'b1; // this is the last stage
end
endgenerate
 
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------INSTANTIATIONS HERE-------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
sync_fifo_reg_stage #(.DWIDTH(DATASIZE))
sync_fifo_reg_stage_3_I (
.clk(clk),
.res_n(res_n),
.d_in(d_in),
.d_in_p(d_out_2),
.p_full(full_2),
.n_full(stage4_full),
.si(si),
.so(so),
.full(full_3),
.d_out(d_out_3)
);
 
hmc_ram #(
.DATASIZE(DATASIZE), // Memory data word width
.ADDRSIZE(ADDRSIZE), // Number of memory address bits
.PIPELINED(1)
)
ram(
.clk(clk),
.wen(wen),
.wdata(d_in),
.waddr(wa),
.ren(ren),
.raddr(ra),
.rdata(d_out_m2)
);
 
endmodule
 
`default_nettype wire
 
/openhmc/trunk/openHMC/rtl/building_blocks/fifos/sync/sync_fifo_reg_stage.v
0,0 → 1,100
/*
* .--------------. .----------------. .------------.
* | .------------. | .--------------. | .----------. |
* | | ____ ____ | | | ____ ____ | | | ______ | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| |
* | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' |
* '--------------' '----------------' '------------'
*
* openHMC - An Open Source Hybrid Memory Cube Controller
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg
* www.ziti.uni-heidelberg.de
* B6, 26
* 68159 Mannheim
* Germany
*
* Contact: openhmc@ziti.uni-heidelberg.de
* http://ra.ziti.uni-heidelberg.de/openhmc
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This source file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* 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/>.
*
*
* Module name: sync_fifo_reg_stage
*
*/
 
`default_nettype none
 
module sync_fifo_reg_stage #(parameter DWIDTH = 8)(
input wire clk,
input wire res_n,
input wire [DWIDTH-1:0] d_in,
input wire [DWIDTH-1:0] d_in_p,
input wire p_full, // full signal from the previous stage
input wire n_full, // full signal from the next stage
input wire si,
input wire so,
output reg full, // full = '1' -> this stage has a valid entry
output reg [DWIDTH-1:0] d_out
);
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------WIRING AND SIGNAL STUFF---------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
 
wire en, muxi;
 
assign en = (si & so & full) // so and si, shift through
| (si & ~so & ~full && n_full) // shift in new value
| (~si & so & p_full); // shift through
 
assign muxi = (si & ~so) | (si & so & ~p_full & full);
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------LOGIC STARTS HERE---------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
 
always @ (posedge clk or negedge res_n) begin
if (!res_n) begin
full <= 1'b0;
d_out <= {DWIDTH{1'b0}};
end else begin
if (en) begin
if (muxi) begin
d_out <= d_in; // enter new value when enabled
end else begin
d_out <= d_in_p; // shift through
end
end
 
full <= (full & si) // stay full while si to other stage
| (full & ~si & ~so) // hold full
| (~si & so & p_full) // keep full as long as prev stage is full
| (si & ~so & n_full); // fill this stage by si
end
end
 
endmodule
 
`default_nettype wire
 
/openhmc/trunk/openHMC/rtl/building_blocks/fifos/sync/sync_fifos.f
0,0 → 1,2
${OPENHMC_PATH}/rtl/building_blocks/fifos/sync/sync_fifo.v
${OPENHMC_PATH}/rtl/building_blocks/fifos/sync/sync_fifo_reg_stage.v
/openhmc/trunk/openHMC/rtl/building_blocks/fifos/async/hmc_async_fifo.v
0,0 → 1,256
/*
* .--------------. .----------------. .------------.
* | .------------. | .--------------. | .----------. |
* | | ____ ____ | | | ____ ____ | | | ______ | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| |
* | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' |
* '--------------' '----------------' '------------'
*
* openHMC - An Open Source Hybrid Memory Cube Controller
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg
* www.ziti.uni-heidelberg.de
* B6, 26
* 68159 Mannheim
* Germany
*
* Contact: openhmc@ziti.uni-heidelberg.de
* http://ra.ziti.uni-heidelberg.de/openhmc
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This source file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* 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/>.
*
*
* Module name: hmc_async_fifo
*
*/
 
`default_nettype none
 
module hmc_async_fifo #(
parameter DWIDTH = 8,
parameter ENTRIES = 2
) (
// interface for shift_in side
input wire si_clk,
input wire si_res_n,
input wire shift_in,
input wire [DWIDTH-1:0] d_in,
 
output reg full,
output reg almost_full,
 
// interface for shift_out side
input wire so_clk,
input wire so_res_n,
input wire shift_out,
 
output reg [DWIDTH-1:0] d_out,
output reg empty,
output reg almost_empty
);
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------WIRING AND SIGNAL STUFF---------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
 
// the FIFO currently can only have up to 2048 entries
localparam LG_ENTRIES = (ENTRIES <= 2) ? 1 :
(ENTRIES <= 4) ? 2 :
(ENTRIES <= 8) ? 3 :
(ENTRIES <= 16) ? 4 :
(ENTRIES <= 32) ? 5 :
(ENTRIES <= 64) ? 6 :
(ENTRIES <= 128) ? 7 :
(ENTRIES <= 256) ? 8 :
(ENTRIES <= 512) ? 9 :
(ENTRIES <= 1024) ? 10 : 11;
 
reg [DWIDTH-1:0] entry [0:ENTRIES-1];
 
reg [LG_ENTRIES-1:0] wp;
reg [LG_ENTRIES-1:0] rp;
 
// asynchronous thermo wp
reg [ENTRIES-1:0] thermo_wp_w;
reg [ENTRIES-1:0] thermo_rp_w;
 
reg [ENTRIES-1:0] thermo_wp;
reg [ENTRIES-1:0] thermo_rp;
 
reg [ENTRIES-1:0] thermo_wp_synced_0;
 
reg [ENTRIES-1:0] thermo_wp_synced_1;
 
reg [ENTRIES-1:0] thermo_rp_synced_0;
 
reg [ENTRIES-1:0] thermo_rp_synced_1;
 
wire [LG_ENTRIES-1:0] next_rp;
wire [LG_ENTRIES-1:0] next_rp_p1;
 
wire set_empty_w;
wire set_a_empty_0_w;
wire set_a_empty_1_w;
wire set_a_empty_2_w;
 
wire set_full_w;
wire set_a_full_0_w;
wire set_a_full_1_w;
wire set_a_full_2_w;
 
wire [LG_ENTRIES-1:0] upper_bound;
 
assign next_rp = (rp == upper_bound) ? {LG_ENTRIES {1'b0}} : rp + 1'b1;
assign next_rp_p1 = (next_rp == upper_bound) ? {LG_ENTRIES {1'b0}} : next_rp + 1'b1;
 
assign set_empty_w = (thermo_rp == thermo_wp_synced_1);
assign set_a_empty_0_w = (thermo_rp == {~thermo_wp_synced_1[0], thermo_wp_synced_1[ENTRIES-1:1]});
assign set_a_empty_1_w = (thermo_rp == {~thermo_wp_synced_1[1:0], thermo_wp_synced_1[ENTRIES-1:2]});
assign set_a_empty_2_w = (thermo_rp == {~thermo_wp_synced_1[2:0], thermo_wp_synced_1[ENTRIES-1:3]});
 
assign set_full_w = &(thermo_wp ^ thermo_rp_synced_1);
assign set_a_full_0_w = &(thermo_wp ^ {~thermo_rp_synced_1[0], thermo_rp_synced_1[ENTRIES-1:1]});
assign set_a_full_1_w = &(thermo_wp ^ {~thermo_rp_synced_1[1:0], thermo_rp_synced_1[ENTRIES-1:2]});
assign set_a_full_2_w = &(thermo_wp ^ {~thermo_rp_synced_1[2:0], thermo_rp_synced_1[ENTRIES-1:3]});
 
assign upper_bound = ENTRIES[LG_ENTRIES-1:0] - {{LG_ENTRIES-1 {1'b0}}, 1'b1};
 
always @ (*)
begin
if (shift_in && !full)
thermo_wp_w = {thermo_wp[ENTRIES-2:0], !thermo_wp[ENTRIES-1]};
else
thermo_wp_w = thermo_wp;
end
 
always @ (*)
begin
if (shift_out && !empty)
thermo_rp_w = {thermo_rp[ENTRIES-2:0], !thermo_rp[ENTRIES-1]};
else
thermo_rp_w = thermo_rp;
end
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------LOGIC STARTS HERE---------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
 
// shift_in side:
`ifdef ASYNC_RES
always @(posedge si_clk or negedge si_res_n) `else
always @(posedge si_clk) `endif
begin
if (!si_res_n)
begin
wp <= {LG_ENTRIES {1'b0}};
thermo_wp <= {ENTRIES {1'b0}};
full <= 1'b0;
almost_full <= 1'b0;
end
else
begin
full <= set_full_w || (set_a_full_0_w && shift_in) ;
almost_full <= set_full_w || (set_a_full_0_w) || (set_a_full_1_w && shift_in) ;
 
thermo_wp <= thermo_wp_w;
 
if (shift_in && !full)
begin
entry[wp] <= d_in;
 
if (wp == upper_bound)
wp <= {LG_ENTRIES {1'b0}};
else
wp <= wp + 1'b1;
end
end
end
 
// shift_out side
`ifdef ASYNC_RES
always @(posedge so_clk or negedge so_res_n) `else
always @(posedge so_clk) `endif
begin
if (!so_res_n)
begin
rp <= {LG_ENTRIES {1'b0}};
thermo_rp <= {ENTRIES {1'b0}};
empty <= 1'b1;
almost_empty <= 1'b1;
 
end
else
begin
empty <= (set_empty_w || (set_a_empty_0_w && shift_out && !empty));
almost_empty <= empty || set_empty_w || set_a_empty_0_w || (set_a_empty_1_w && shift_out && !empty);
 
thermo_rp <= thermo_rp_w;
// shift out and not empty or empty but a new word just finished synchronizing (like almost empty)
if (shift_out && !empty)
begin
rp <= next_rp;
d_out <= entry[next_rp];
end
else
begin
d_out <= entry[rp];
end
end
end
 
// syncing thermp_rp to shift_in domain
`ifdef ASYNC_RES
always @(posedge si_clk or negedge si_res_n) `else
always @(posedge si_clk) `endif
begin
if (!si_res_n)
begin
thermo_rp_synced_0 <= {ENTRIES {1'b0}};
thermo_rp_synced_1 <= {ENTRIES {1'b0}};
end
else
begin
thermo_rp_synced_0 <= thermo_rp;
thermo_rp_synced_1 <= thermo_rp_synced_0;
end
end
 
// syncing write pointer to shift_out domain
`ifdef ASYNC_RES
always @(posedge so_clk or negedge so_res_n) `else
always @(posedge so_clk) `endif
begin
if (!so_res_n)
begin
thermo_wp_synced_0 <= {ENTRIES {1'b0}};
thermo_wp_synced_1 <= {ENTRIES {1'b0}};
end
else
begin
thermo_wp_synced_0 <= thermo_wp;
thermo_wp_synced_1 <= thermo_wp_synced_0;
end
end
 
endmodule
 
`default_nettype wire
/openhmc/trunk/openHMC/rtl/hmc_controller/hmc_controller_top.f
0,0 → 1,34
### Make sure to source the path variable first.
#use: export OPENHMC_PATH=path_to_openhmc_main_folder
 
####HEADER
-incdir ${OPENHMC_PATH}/rtl/include/
 
####Top
${OPENHMC_PATH}/rtl/hmc_controller/hmc_controller_top.v
 
####Controller TX
${OPENHMC_PATH}/rtl/hmc_controller/tx/tx_link.v
${OPENHMC_PATH}/rtl/hmc_controller/tx/tx_run_length_limiter.v
${OPENHMC_PATH}/rtl/hmc_controller/tx/tx_scrambler.v
${OPENHMC_PATH}/rtl/hmc_controller/tx/tx_crc_combine.v
 
####Controller RX
${OPENHMC_PATH}/rtl/hmc_controller/rx/rx_link.v
${OPENHMC_PATH}/rtl/hmc_controller/rx/rx_lane_logic.v
${OPENHMC_PATH}/rtl/hmc_controller/rx/rx_descrambler.v
${OPENHMC_PATH}/rtl/hmc_controller/rx/rx_crc_compare.v
 
####CRC
${OPENHMC_PATH}/rtl/hmc_controller/crc/crc_128_init.v
${OPENHMC_PATH}/rtl/hmc_controller/crc/crc_accu.v
 
####Register File
${OPENHMC_PATH}/rtl/hmc_controller/register_file/hmc_controller_8x_rf.v
${OPENHMC_PATH}/rtl/hmc_controller/register_file/hmc_controller_16x_rf.v
 
####Building blocks
-f ${OPENHMC_PATH}/rtl/building_blocks/fifos/sync/sync_fifos.f
${OPENHMC_PATH}/rtl/building_blocks/fifos/async/hmc_async_fifo.v
${OPENHMC_PATH}/rtl/building_blocks/counter/counter48.v
${OPENHMC_PATH}/rtl/building_blocks/rams/hmc_ram.v
/openhmc/trunk/openHMC/rtl/hmc_controller/hmc_controller_top.v
0,0 → 1,520
/*
* .--------------. .----------------. .------------.
* | .------------. | .--------------. | .----------. |
* | | ____ ____ | | | ____ ____ | | | ______ | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| |
* | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' |
* '--------------' '----------------' '------------'
*
* openHMC - An Open Source Hybrid Memory Cube Controller
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg
* www.ziti.uni-heidelberg.de
* B6, 26
* 68159 Mannheim
* Germany
*
* Contact: openhmc@ziti.uni-heidelberg.de
* http://ra.ziti.uni-heidelberg.de/openhmc
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This source file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* 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/>.
*
*
* Module name: hmc_controller_top
*
*/
 
`default_nettype none
 
module hmc_controller_top #(
//Define width of the datapath
parameter LOG_FPW = 2,
parameter FPW = 4,
parameter DWIDTH = FPW*128,
//Define HMC interface width
parameter LOG_NUM_LANES = 3,
parameter NUM_LANES = 2**LOG_NUM_LANES,
parameter NUM_DATA_BYTES = FPW*16,
//Define width of the register file
parameter HMC_RF_WWIDTH = 64,
parameter HMC_RF_RWIDTH = 64,
parameter HMC_RF_AWIDTH = 4,
//Misc defines
parameter LOG_MAX_RTC = 8,
//Synthesis params
parameter HMC_RX_AC_COUPLED = 1
) (
//----------------------------------
//----SYSTEM INTERFACES
//----------------------------------
input wire clk_user,
input wire clk_hmc,
input wire res_n_user,
input wire res_n_hmc,
 
//----------------------------------
//----Connect AXI Ports
//----------------------------------
//From AXI to HMC Ctrl TX
input wire s_axis_tx_TVALID,
output wire s_axis_tx_TREADY,
input wire [DWIDTH-1:0] s_axis_tx_TDATA,
input wire [NUM_DATA_BYTES-1:0] s_axis_tx_TUSER,
//From HMC Ctrl RX to AXI
output wire m_axis_rx_TVALID,
input wire m_axis_rx_TREADY,
output wire [DWIDTH-1:0] m_axis_rx_TDATA,
output wire [NUM_DATA_BYTES-1:0] m_axis_rx_TUSER,
 
//----------------------------------
//----Connect Transceiver
//----------------------------------
output wire [DWIDTH-1:0] phy_data_tx_link2phy,
input wire [DWIDTH-1:0] phy_data_rx_phy2link,
output wire [NUM_LANES-1:0] phy_bit_slip,
input wire phy_ready,
 
//----------------------------------
//----Connect HMC
//----------------------------------
output wire P_RST_N,
output wire hmc_LxRXPS,
input wire hmc_LxTXPS,
input wire FERR_N, //Not connected
 
//----------------------------------
//----Connect RF
//----------------------------------
input wire [HMC_RF_AWIDTH-1:0] rf_address,
output wire [HMC_RF_RWIDTH-1:0] rf_read_data,
output wire rf_invalid_address,
output wire rf_access_complete,
input wire rf_read_en,
input wire rf_write_en,
input wire [HMC_RF_WWIDTH-1:0] rf_write_data
 
);
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------WIRING AND SIGNAL STUFF---------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
 
// ----Assign AXI interface wires
wire [3*FPW-1:0] m_axis_rx_TUSER_temp;
assign m_axis_rx_TUSER = {{NUM_DATA_BYTES-(3*FPW){1'b0}}, m_axis_rx_TUSER_temp};
 
wire s_axis_tx_TREADY_n;
assign s_axis_tx_TREADY = ~s_axis_tx_TREADY_n;
 
wire m_axis_rx_TVALID_n;
assign m_axis_rx_TVALID = ~m_axis_rx_TVALID_n;
 
 
// ----TX FIFO Wires
wire [DWIDTH-1:0] tx_d_in_data;
wire tx_shift_out;
wire tx_empty;
wire tx_a_empty;
wire [3*FPW-1:0] tx_d_in_ctrl;
 
// ----RX FIFO Wires
wire [DWIDTH-1:0] rx_d_in_data;
wire rx_shift_in;
wire rx_full;
wire rx_a_full;
wire [3*FPW-1:0] rx_d_in_ctrl;
 
// ----RX LINK TO TX LINK
wire rx2tx_link_retry;
wire rx2tx_error_abort_mode;
wire rx2tx_error_abort_mode_cleared;
wire [7:0] rx2tx_hmc_frp;
wire [7:0] rx2tx_rrp;
wire [7:0] rx2tx_returned_tokens;
wire [LOG_FPW:0] rx2tx_hmc_tokens_to_be_returned;
 
// ----Register File
//Counter
wire rf_cnt_retry;
wire rf_run_length_bit_flip;
wire [HMC_RF_RWIDTH-1:0] rf_cnt_poisoned;
wire [HMC_RF_RWIDTH-1:0] rf_cnt_p;
wire [HMC_RF_RWIDTH-1:0] rf_cnt_np;
wire [HMC_RF_RWIDTH-1:0] rf_cnt_r;
wire [HMC_RF_RWIDTH-1:0] rf_cnt_rsp_rcvd;
//Status
wire [1:0] rf_link_status;
wire [2:0] rf_hmc_init_status;
wire [1:0] rf_tx_init_status;
wire [9:0] rf_hmc_tokens_av;
wire [9:0] rf_rx_tokens_av;
wire rf_hmc_sleep;
//Init Status
wire rf_all_descramblers_aligned;
wire [NUM_LANES-1:0] rf_descrambler_aligned;
wire [NUM_LANES-1:0] rf_descrambler_part_aligned;
//Control
wire [7:0] rf_bit_slip_time;
wire rf_hmc_init_cont_set;
wire rf_set_hmc_sleep;
wire rf_dbg_dont_send_tret;
//wire rf_warm_reset;
wire rf_scrambler_disable;
wire [NUM_LANES-1:0] rf_lane_polarity;
wire [NUM_LANES-1:0] rf_descramblers_locked;
wire [9:0] rf_rx_buffer_rtc;
wire rf_lane_reversal_detected;
wire [4:0] rf_irtry_received_threshold;
wire [4:0] rf_irtry_to_send;
wire rf_run_length_enable;
wire rf_run_length_enable_to_tx;
assign rf_run_length_enable_to_tx = HMC_RX_AC_COUPLED ? rf_run_length_enable : 1'b0;
wire [2:0] rf_first_cube_ID;
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------INSTANTIATIONS HERE-------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
//----------------------------------------------------------------------
//-----TX-----TX-----TX-----TX-----TX-----TX-----TX-----TX-----TX-----TX
//----------------------------------------------------------------------
 
hmc_async_fifo #(
.DWIDTH(DWIDTH+(FPW*3)),
.ENTRIES(8)
) fifo_tx_data (
//System
.si_clk(clk_user),
.so_clk(clk_hmc),
.si_res_n(res_n_user),
.so_res_n(res_n_hmc),
 
//From AXI-4 TX IF
.d_in({s_axis_tx_TUSER[(FPW*3)-1:0],s_axis_tx_TDATA}),
.shift_in(s_axis_tx_TVALID && s_axis_tx_TREADY),
.full(s_axis_tx_TREADY_n),
.almost_full(),
 
//To TX Link Logic
.d_out({tx_d_in_ctrl,tx_d_in_data}),
.shift_out(tx_shift_out),
.empty(tx_empty),
.almost_empty(tx_a_empty)
);
 
tx_link #(
.LOG_FPW(LOG_FPW),
.FPW(FPW),
.DWIDTH(DWIDTH),
.NUM_LANES(NUM_LANES),
.HMC_PTR_SIZE(8),
.HMC_RF_RWIDTH(HMC_RF_RWIDTH)
) hmc_tx_link_I(
 
//----------------------------------
//----SYSTEM INTERFACE
//----------------------------------
.clk(clk_hmc),
.res_n(res_n_hmc),
 
//----------------------------------
//----TO HMC PHY
//----------------------------------
.phy_scrambled_data_out(phy_data_tx_link2phy),
 
//----------------------------------
//----HMC IF
//----------------------------------
.hmc_LxRXPS(hmc_LxRXPS),
.hmc_LxTXPS(hmc_LxTXPS),
 
//----------------------------------
//----FROM HMC_TX_HTAX_LOGIC
//----------------------------------
.d_in_data(tx_d_in_data),
.d_in_flit_is_valid(tx_d_in_ctrl[FPW-1:0]),
.d_in_flit_is_hdr(tx_d_in_ctrl[(2*FPW)-1:1*FPW]),
.d_in_flit_is_tail(tx_d_in_ctrl[(3*FPW)-1:(2*FPW)]),
.d_in_empty(tx_empty),
.d_in_a_empty(tx_a_empty),
.d_in_shift_out(tx_shift_out),
 
//----------------------------------
//----RX Block
//----------------------------------
.rx_force_tx_retry(rx2tx_link_retry),
.rx_error_abort_mode(rx2tx_error_abort_mode),
.rx_error_abort_mode_cleared(rx2tx_error_abort_mode_cleared),
.rx_hmc_frp(rx2tx_hmc_frp),
.rx_rrp(rx2tx_rrp),
.rx_returned_tokens(rx2tx_returned_tokens),
.rx_hmc_tokens_to_be_returned(rx2tx_hmc_tokens_to_be_returned),
 
//----------------------------------
//----RF
//----------------------------------
//Monitoring 1-cycle set to increment
.rf_cnt_retry(rf_cnt_retry),
.rf_sent_p(rf_cnt_p),
.rf_sent_np(rf_cnt_np),
.rf_sent_r(rf_cnt_r),
.rf_run_length_bit_flip(rf_run_length_bit_flip),
//Status
.rf_hmc_is_in_sleep(rf_hmc_sleep),
.rf_hmc_received_init_null(rf_hmc_init_status[0]),
.rf_link_is_up(rf_link_status[1]),
.rf_descramblers_aligned(rf_all_descramblers_aligned),
.rf_tx_init_status(rf_tx_init_status),
.rf_hmc_tokens_av(rf_hmc_tokens_av),
.rf_rx_tokens_av(rf_rx_tokens_av),
//Control
//.rf_warm_reset(rf_warm_reset),
.rf_hmc_sleep_requested(rf_set_hmc_sleep),
.rf_dbg_dont_send_tret(rf_dbg_dont_send_tret),
.rf_hmc_init_cont_set(rf_hmc_init_cont_set),
.rf_scrambler_disable(rf_scrambler_disable),
.rf_rx_buffer_rtc(rf_rx_buffer_rtc),
.rf_first_cube_ID(rf_first_cube_ID),
.rf_irtry_to_send(rf_irtry_to_send),
.rf_run_length_enable(rf_run_length_enable_to_tx)
);
 
//----------------------------------------------------------------------
//-----RX-----RX-----RX-----RX-----RX-----RX-----RX-----RX-----RX-----RX
//----------------------------------------------------------------------
rx_link #(
.LOG_FPW(LOG_FPW),
.FPW(FPW),
.DWIDTH(DWIDTH),
.LOG_NUM_LANES(LOG_NUM_LANES),
.NUM_LANES(NUM_LANES),
.LOG_MAX_RTC(LOG_MAX_RTC),
.HMC_RF_RWIDTH(HMC_RF_RWIDTH)
) hmc_rx_link_I (
 
//----------------------------------
//----SYSTEM INTERFACE
//----------------------------------
.clk(clk_hmc),
.res_n(res_n_hmc),
 
//----------------------------------
//----TO HMC PHY
//----------------------------------
.phy_scrambled_data_in(phy_data_rx_phy2link),
.init_bit_slip(phy_bit_slip),
 
//----------------------------------
//----FROM TO RX HTAX FIFO
//----------------------------------
.d_out_fifo_data(rx_d_in_data),
.d_out_fifo_full(rx_full),
.d_out_fifo_a_full(rx_a_full),
.d_out_fifo_shift_in(rx_shift_in),
.d_out_fifo_ctrl(rx_d_in_ctrl),
 
//----------------------------------
//----TO TX Block
//----------------------------------
.tx_link_retry(rx2tx_link_retry),
.tx_error_abort_mode(rx2tx_error_abort_mode),
.tx_error_abort_mode_cleared(rx2tx_error_abort_mode_cleared),
.tx_hmc_frp(rx2tx_hmc_frp),
.tx_rrp(rx2tx_rrp),
.tx_returned_tokens(rx2tx_returned_tokens),
.tx_hmc_tokens_to_be_returned(rx2tx_hmc_tokens_to_be_returned),
 
//----------------------------------
//----RF
//----------------------------------
//Monitoring 1-cycle set to increment
.rf_cnt_poisoned(rf_cnt_poisoned),
.rf_cnt_rsp(rf_cnt_rsp_rcvd),
//Status
.rf_link_status(rf_link_status),
.rf_hmc_init_status(rf_hmc_init_status),
.rf_hmc_sleep(rf_hmc_sleep),
//Init Status
.rf_all_descramblers_aligned(rf_all_descramblers_aligned),
.rf_descrambler_aligned(rf_descrambler_aligned),
.rf_descrambler_part_aligned(rf_descrambler_part_aligned),
.rf_descramblers_locked(rf_descramblers_locked),
.rf_tx_sends_ts1(rf_tx_init_status[1] && !rf_tx_init_status[0]),
//Control
.rf_bit_slip_time(rf_bit_slip_time),
.rf_hmc_init_cont_set(rf_hmc_init_cont_set),
.rf_lane_polarity(rf_lane_polarity),
.rf_scrambler_disable(rf_scrambler_disable),
.rf_lane_reversal_detected(rf_lane_reversal_detected),
.rf_irtry_received_threshold(rf_irtry_received_threshold)
);
 
hmc_async_fifo #(
.DWIDTH(DWIDTH+(FPW*3)),
.ENTRIES(8)
) fifo_rx_data(
//System
.si_clk(clk_hmc),
.so_clk(clk_user),
.si_res_n(res_n_hmc),
.so_res_n(res_n_user),
 
//To RX LINK Logic
.d_in({rx_d_in_ctrl,rx_d_in_data}),
.shift_in(rx_shift_in),
.full(rx_full),
.almost_full(rx_a_full),
 
//AXI-4 RX IF
.d_out({m_axis_rx_TUSER_temp,m_axis_rx_TDATA}),
.shift_out(m_axis_rx_TVALID && m_axis_rx_TREADY),
.empty(m_axis_rx_TVALID_n),
.almost_empty()
 
);
 
//----------------------------------------------------------------------
//---Register File---Register File---Register File---Register File---Reg
//----------------------------------------------------------------------
//Instantiate register file depending on the number of lanes
generate
if(NUM_LANES==8) begin : register_file_8x
hmc_controller_8x_rf hmc_controller_rf_I (
//system IF
.res_n(res_n_hmc),
.clk(clk_hmc),
//rf access
.address(rf_address),
.read_data(rf_read_data),
.invalid_address(rf_invalid_address),
.access_complete(rf_access_complete),
.read_en(rf_read_en),
.write_en(rf_write_en),
.write_data(rf_write_data),
//status registers
.status_general_link_up_next(rf_link_status[1]),
.status_general_link_training_next(rf_link_status[0]),
.status_general_sleep_mode_next(rf_hmc_sleep),
.status_general_lanes_reversed_next(rf_lane_reversal_detected),
//.status_general_hmc_signals_fatal_error(~FERR_N),
.status_general_hmc_tokens_remaining_next(rf_hmc_tokens_av),
.status_general_rx_tokens_remaining_next(rf_rx_tokens_av),
.status_general_lane_polarity_reversed_next(rf_lane_polarity),
.status_general_phy_ready_next(phy_ready),
 
//init status
.status_init_lane_descramblers_locked_next(rf_descramblers_locked),
.status_init_descrambler_part_aligned_next(rf_descrambler_part_aligned),
.status_init_descrambler_aligned_next(rf_descrambler_aligned),
.status_init_all_descramblers_aligned_next(rf_all_descramblers_aligned),
.status_init_tx_init_status_next(rf_tx_init_status),
.status_init_hmc_init_TS1_next(rf_hmc_init_status[0]),
 
//counters
.sent_np_cnt_next(rf_cnt_np),
.sent_p_cnt_next(rf_cnt_p),
.sent_r_cnt_next(rf_cnt_r),
.poisoned_packets_cnt_next(rf_cnt_poisoned),
.rcvd_rsp_cnt_next(rf_cnt_rsp_rcvd),
 
//Single bit counter
.tx_link_retries_count_countup(rf_cnt_retry),
.errors_on_rx_count_countup(rx2tx_error_abort_mode_cleared),
.run_length_bit_flip_count_countup(rf_run_length_bit_flip),
 
//control
.control_set_hmc_sleep(rf_set_hmc_sleep),
//.control_set_warm_reset(rf_warm_reset),
.control_hmc_init_cont_set(rf_hmc_init_cont_set),
.control_debug_dont_send_tret(rf_dbg_dont_send_tret),
.control_scrambler_disable(rf_scrambler_disable),
.control_bit_slip_time(rf_bit_slip_time),
.control_p_rst_n(P_RST_N),
.control_rx_token_count(rf_rx_buffer_rtc),
.control_irtry_received_threshold(rf_irtry_received_threshold),
.control_irtry_to_send(rf_irtry_to_send),
.control_run_length_enable(rf_run_length_enable),
.control_first_cube_ID(rf_first_cube_ID)
);
end else begin : register_file_16x
hmc_controller_16x_rf hmc_controller_rf_I (
//system IF
.res_n(res_n_hmc),
.clk(clk_hmc),
//rf access
.address(rf_address),
.read_data(rf_read_data),
.invalid_address(rf_invalid_address),
.access_complete(rf_access_complete),
.read_en(rf_read_en),
.write_en(rf_write_en),
.write_data(rf_write_data),
//status registers
.status_general_link_up_next(rf_link_status[1]),
.status_general_link_training_next(rf_link_status[0]),
.status_general_sleep_mode_next(rf_hmc_sleep),
.status_general_lanes_reversed_next(rf_lane_reversal_detected),
//.status_general_hmc_signals_fatal_error(~FERR_N),
.status_general_hmc_tokens_remaining_next(rf_hmc_tokens_av),
.status_general_rx_tokens_remaining_next(rf_rx_tokens_av),
.status_general_lane_polarity_reversed_next(rf_lane_polarity),
.status_general_phy_ready_next(phy_ready),
 
//init status
.status_init_lane_descramblers_locked_next(rf_descramblers_locked),
.status_init_descrambler_part_aligned_next(rf_descrambler_part_aligned),
.status_init_descrambler_aligned_next(rf_descrambler_aligned),
.status_init_all_descramblers_aligned_next(rf_all_descramblers_aligned),
.status_init_tx_init_status_next(rf_tx_init_status),
.status_init_hmc_init_TS1_next(rf_hmc_init_status[0]),
 
//counters
.sent_np_cnt_next(rf_cnt_np),
.sent_p_cnt_next(rf_cnt_p),
.sent_r_cnt_next(rf_cnt_r),
.poisoned_packets_cnt_next(rf_cnt_poisoned),
.rcvd_rsp_cnt_next(rf_cnt_rsp_rcvd),
 
//Single bit counter
.tx_link_retries_count_countup(rf_cnt_retry),
.errors_on_rx_count_countup(rx2tx_error_abort_mode_cleared),
.run_length_bit_flip_count_countup(rf_run_length_bit_flip),
 
//control
.control_set_hmc_sleep(rf_set_hmc_sleep),
//.control_set_warm_reset(rf_warm_reset),
.control_hmc_init_cont_set(rf_hmc_init_cont_set),
.control_debug_dont_send_tret(rf_dbg_dont_send_tret),
.control_scrambler_disable(rf_scrambler_disable),
.control_bit_slip_time(rf_bit_slip_time),
.control_p_rst_n(P_RST_N),
.control_rx_token_count(rf_rx_buffer_rtc),
.control_irtry_received_threshold(rf_irtry_received_threshold),
.control_irtry_to_send(rf_irtry_to_send),
.control_run_length_enable(rf_run_length_enable),
.control_first_cube_ID(rf_first_cube_ID)
);
end
endgenerate
 
endmodule
 
`default_nettype wire
/openhmc/trunk/openHMC/rtl/hmc_controller/register_file/hmc_controller_16x_rf.v
0,0 → 1,524
/*
* .--------------. .----------------. .------------.
* | .------------. | .--------------. | .----------. |
* | | ____ ____ | | | ____ ____ | | | ______ | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| |
* | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' |
* '--------------' '----------------' '------------'
*
* openHMC - An Open Source Hybrid Memory Cube Controller
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg
* www.ziti.uni-heidelberg.de
* B6, 26
* 68159 Mannheim
* Germany
*
* Contact: openhmc@ziti.uni-heidelberg.de
* http://ra.ziti.uni-heidelberg.de/openhmc
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This source file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* 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/>.
*
*
* Module name: hmc_controller_16x_rf
*
*
*/
 
module hmc_controller_16x_rf
(
///\defgroup sys
///@{
input wire res_n,
input wire clk,
///}@
///\defgroup rw_if
///@{
input wire[6:3] address,
output reg[63:0] read_data,
output reg invalid_address,
output reg access_complete,
input wire read_en,
input wire write_en,
input wire[63:0] write_data,
///}@
input wire status_general_link_up_next,
input wire status_general_link_training_next,
input wire status_general_sleep_mode_next,
input wire status_general_lanes_reversed_next,
input wire status_general_phy_ready_next,
input wire[9:0] status_general_hmc_tokens_remaining_next,
input wire[9:0] status_general_rx_tokens_remaining_next,
input wire[15:0] status_general_lane_polarity_reversed_next,
input wire[15:0] status_init_lane_descramblers_locked_next,
input wire[15:0] status_init_descrambler_part_aligned_next,
input wire[15:0] status_init_descrambler_aligned_next,
input wire status_init_all_descramblers_aligned_next,
input wire[1:0] status_init_tx_init_status_next,
input wire status_init_hmc_init_TS1_next,
output reg control_p_rst_n,
output reg control_hmc_init_cont_set,
output reg control_set_hmc_sleep,
output reg control_scrambler_disable,
output reg control_run_length_enable,
output reg[2:0] control_first_cube_ID,
output reg control_debug_dont_send_tret,
output reg[9:0] control_rx_token_count,
output reg[4:0] control_irtry_received_threshold,
output reg[4:0] control_irtry_to_send,
output reg[7:0] control_bit_slip_time,
input wire[63:0] sent_p_cnt_next,
input wire[63:0] sent_np_cnt_next,
input wire[63:0] sent_r_cnt_next,
input wire[63:0] poisoned_packets_cnt_next,
input wire[63:0] rcvd_rsp_cnt_next,
input wire tx_link_retries_count_countup,
input wire errors_on_rx_count_countup,
input wire run_length_bit_flip_count_countup
 
);
 
reg status_general_link_up;
reg status_general_link_training;
reg status_general_sleep_mode;
reg status_general_lanes_reversed;
reg[3:0] status_general_rsvd_status_general_0;
reg status_general_phy_ready;
reg[6:0] status_general_rsvd_status_general_1;
reg[9:0] status_general_hmc_tokens_remaining;
reg[5:0] status_general_rsvd_status_general_2;
reg[9:0] status_general_rx_tokens_remaining;
reg[5:0] status_general_rsvd_status_general_3;
reg[15:0] status_general_lane_polarity_reversed;
reg[15:0] status_init_lane_descramblers_locked;
reg[15:0] status_init_descrambler_part_aligned;
reg[15:0] status_init_descrambler_aligned;
reg status_init_all_descramblers_aligned;
reg[1:0] status_init_tx_init_status;
reg status_init_hmc_init_TS1;
reg[6:0] control_rsvd_control_0;
reg[5:0] control_rsvd_control_1;
reg[2:0] control_rsvd_control_2;
reg[2:0] control_rsvd_control_3;
reg[63:0] sent_p_cnt;
reg[63:0] sent_np_cnt;
reg[63:0] sent_r_cnt;
reg[63:0] poisoned_packets_cnt;
reg[63:0] rcvd_rsp_cnt;
reg rreinit;
wire[31:0] tx_link_retries_count;
wire[31:0] errors_on_rx_count;
wire[31:0] run_length_bit_flip_count;
 
counter48 #(
.DATASIZE(32)
) tx_link_retries_count_I (
.clk(clk),
.res_n(res_n),
.increment(tx_link_retries_count_countup),
.load(32'b0),
.load_enable(rreinit),
.value(tx_link_retries_count)
);
 
counter48 #(
.DATASIZE(32)
) errors_on_rx_count_I (
.clk(clk),
.res_n(res_n),
.increment(errors_on_rx_count_countup),
.load(32'b0),
.load_enable(rreinit),
.value(errors_on_rx_count)
);
 
counter48 #(
.DATASIZE(32)
) run_length_bit_flip_count_I (
.clk(clk),
.res_n(res_n),
.increment(run_length_bit_flip_count_countup),
.load(32'b0),
.load_enable(rreinit),
.value(run_length_bit_flip_count)
);
 
 
/* register status_general */
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) `else
always @(posedge clk) `endif
begin
if (!res_n)
begin
status_general_link_up <= 1'h0;
status_general_link_training <= 1'h0;
status_general_sleep_mode <= 1'h0;
status_general_lanes_reversed <= 1'h0;
status_general_rsvd_status_general_0 <= 4'h0;
status_general_phy_ready <= 1'h0;
status_general_rsvd_status_general_1 <= 7'h0;
status_general_hmc_tokens_remaining <= 1'h0;
status_general_rsvd_status_general_2 <= 6'h0;
status_general_rx_tokens_remaining <= 1'h0;
status_general_rsvd_status_general_3 <= 6'h0;
status_general_lane_polarity_reversed <= 0;
end
else
begin
 
status_general_link_up <= status_general_link_up_next;
status_general_link_training <= status_general_link_training_next;
status_general_sleep_mode <= status_general_sleep_mode_next;
status_general_lanes_reversed <= status_general_lanes_reversed_next;
status_general_phy_ready <= status_general_phy_ready_next;
status_general_hmc_tokens_remaining <= status_general_hmc_tokens_remaining_next;
status_general_rx_tokens_remaining <= status_general_rx_tokens_remaining_next;
status_general_lane_polarity_reversed <= status_general_lane_polarity_reversed_next;
end
end
 
/* register status_init */
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) `else
always @(posedge clk) `endif
begin
if (!res_n)
begin
status_init_lane_descramblers_locked <= 0;
status_init_descrambler_part_aligned <= 0;
status_init_descrambler_aligned <= 0;
status_init_all_descramblers_aligned <= 1'h0;
status_init_tx_init_status <= 2'h0;
status_init_hmc_init_TS1 <= 1'h0;
end
else
begin
 
status_init_lane_descramblers_locked <= status_init_lane_descramblers_locked_next;
status_init_descrambler_part_aligned <= status_init_descrambler_part_aligned_next;
status_init_descrambler_aligned <= status_init_descrambler_aligned_next;
status_init_all_descramblers_aligned <= status_init_all_descramblers_aligned_next;
status_init_tx_init_status <= status_init_tx_init_status_next;
status_init_hmc_init_TS1 <= status_init_hmc_init_TS1_next;
end
end
 
/* register control */
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) `else
always @(posedge clk) `endif
begin
if (!res_n)
begin
control_p_rst_n <= 1'h0;
control_hmc_init_cont_set <= 1'b0;
control_set_hmc_sleep <= 1'h0;
control_scrambler_disable <= 1'h0;
control_run_length_enable <= 1'h0;
control_first_cube_ID <= 3'h0;
control_debug_dont_send_tret <= 1'h0;
control_rsvd_control_0 <= 7'h0;
control_rx_token_count <= 100;
control_rsvd_control_1 <= 6'h0;
control_irtry_received_threshold <= 5'h10;
control_rsvd_control_2 <= 3'h0;
control_irtry_to_send <= 5'h14;
control_rsvd_control_3 <= 3'h0;
control_bit_slip_time <= 8'h24;
end
else
begin
 
if((address[6:3]== 2) && write_en)
begin
control_p_rst_n <= write_data[0:0];
end
if((address[6:3]== 2) && write_en)
begin
control_hmc_init_cont_set <= write_data[1:1];
end
if((address[6:3]== 2) && write_en)
begin
control_set_hmc_sleep <= write_data[2:2];
end
if((address[6:3]== 2) && write_en)
begin
control_scrambler_disable <= write_data[3:3];
end
if((address[6:3]== 2) && write_en)
begin
control_run_length_enable <= write_data[4:4];
end
if((address[6:3]== 2) && write_en)
begin
control_first_cube_ID <= write_data[7:5];
end
if((address[6:3]== 2) && write_en)
begin
control_debug_dont_send_tret <= write_data[8:8];
end
if((address[6:3]== 2) && write_en)
begin
control_rx_token_count <= write_data[25:16];
end
if((address[6:3]== 2) && write_en)
begin
control_irtry_received_threshold <= write_data[36:32];
end
if((address[6:3]== 2) && write_en)
begin
control_irtry_to_send <= write_data[44:40];
end
if((address[6:3]== 2) && write_en)
begin
control_bit_slip_time <= write_data[55:48];
end
end
end
 
/* register sent_p */
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) `else
always @(posedge clk) `endif
begin
if (!res_n)
begin
sent_p_cnt <= 64'h0;
end
else
begin
 
sent_p_cnt <= sent_p_cnt_next;
end
end
 
/* register sent_np */
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) `else
always @(posedge clk) `endif
begin
if (!res_n)
begin
sent_np_cnt <= 64'h0;
end
else
begin
 
sent_np_cnt <= sent_np_cnt_next;
end
end
 
/* register sent_r */
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) `else
always @(posedge clk) `endif
begin
if (!res_n)
begin
sent_r_cnt <= 64'h0;
end
else
begin
 
sent_r_cnt <= sent_r_cnt_next;
end
end
 
/* register poisoned_packets */
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) `else
always @(posedge clk) `endif
begin
if (!res_n)
begin
poisoned_packets_cnt <= 64'h0;
end
else
begin
 
poisoned_packets_cnt <= poisoned_packets_cnt_next;
end
end
 
/* register rcvd_rsp */
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) `else
always @(posedge clk) `endif
begin
if (!res_n)
begin
rcvd_rsp_cnt <= 64'h0;
end
else
begin
 
rcvd_rsp_cnt <= rcvd_rsp_cnt_next;
end
end
 
/* register counter_reset */
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) `else
always @(posedge clk) `endif
begin
if (!res_n)
begin
rreinit <= 1'b0;
end
else
begin
 
if((address[6:3]== 8) && write_en)
begin
rreinit <= 1'b1;
end
else
begin
rreinit <= 1'b0;
end
end
end
 
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) `else
always @(posedge clk) `endif
begin
if (!res_n)
begin
invalid_address <= 1'b0;
access_complete <= 1'b0;
`ifdef ASIC
read_data <= 64'b0;
`endif
 
end
else
begin
 
casex(address[6:3])
4'h0:
begin
read_data[0:0] <= status_general_link_up;
read_data[1:1] <= status_general_link_training;
read_data[2:2] <= status_general_sleep_mode;
read_data[3:3] <= status_general_lanes_reversed;
read_data[7:4] <= status_general_rsvd_status_general_0;
read_data[8:8] <= status_general_phy_ready;
read_data[15:9] <= status_general_rsvd_status_general_1;
read_data[25:16] <= status_general_hmc_tokens_remaining;
read_data[31:26] <= status_general_rsvd_status_general_2;
read_data[41:32] <= status_general_rx_tokens_remaining;
read_data[47:42] <= status_general_rsvd_status_general_3;
read_data[63:48] <= status_general_lane_polarity_reversed;
invalid_address <= 1'b0;
access_complete <= write_en || read_en;
end
4'h1:
begin
read_data[15:0] <= status_init_lane_descramblers_locked;
read_data[31:16] <= status_init_descrambler_part_aligned;
read_data[47:32] <= status_init_descrambler_aligned;
read_data[48:48] <= status_init_all_descramblers_aligned;
read_data[50:49] <= status_init_tx_init_status;
read_data[51:51] <= status_init_hmc_init_TS1;
read_data[63:52] <= 12'b0;
invalid_address <= 1'b0;
access_complete <= write_en || read_en;
end
4'h2:
begin
read_data[0:0] <= control_p_rst_n;
read_data[1:1] <= control_hmc_init_cont_set;
read_data[2:2] <= control_set_hmc_sleep;
read_data[3:3] <= control_scrambler_disable;
read_data[4:4] <= control_run_length_enable;
read_data[7:5] <= control_first_cube_ID;
read_data[8:8] <= control_debug_dont_send_tret;
read_data[15:9] <= control_rsvd_control_0;
read_data[25:16] <= control_rx_token_count;
read_data[31:26] <= control_rsvd_control_1;
read_data[36:32] <= control_irtry_received_threshold;
read_data[39:37] <= control_rsvd_control_2;
read_data[44:40] <= control_irtry_to_send;
read_data[47:45] <= control_rsvd_control_3;
read_data[55:48] <= control_bit_slip_time;
read_data[63:56] <= 8'b0;
invalid_address <= 1'b0;
access_complete <= write_en || read_en;
end
4'h3:
begin
read_data[63:0] <= sent_p_cnt;
invalid_address <= 1'b0;
access_complete <= write_en || read_en;
end
4'h4:
begin
read_data[63:0] <= sent_np_cnt;
invalid_address <= 1'b0;
access_complete <= write_en || read_en;
end
4'h5:
begin
read_data[63:0] <= sent_r_cnt;
invalid_address <= 1'b0;
access_complete <= write_en || read_en;
end
4'h6:
begin
read_data[63:0] <= poisoned_packets_cnt;
invalid_address <= 1'b0;
access_complete <= write_en || read_en;
end
4'h7:
begin
read_data[63:0] <= rcvd_rsp_cnt;
invalid_address <= 1'b0;
access_complete <= write_en || read_en;
end
4'h9:
begin
read_data[31:0] <= tx_link_retries_count;
read_data[63:32] <= 32'b0;
invalid_address <= 1'b0;
access_complete <= write_en || read_en;
end
4'ha:
begin
read_data[31:0] <= errors_on_rx_count;
read_data[63:32] <= 32'b0;
invalid_address <= 1'b0;
access_complete <= write_en || read_en;
end
4'hb:
begin
read_data[31:0] <= run_length_bit_flip_count;
read_data[63:32] <= 32'b0;
invalid_address <= 1'b0;
access_complete <= write_en || read_en;
end
default:
begin
invalid_address <= read_en || write_en;
access_complete <= read_en || write_en;
end
endcase
end
end
endmodule
/openhmc/trunk/openHMC/rtl/hmc_controller/register_file/hmc_controller_8x_rf.v
0,0 → 1,525
/*
* .--------------. .----------------. .------------.
* | .------------. | .--------------. | .----------. |
* | | ____ ____ | | | ____ ____ | | | ______ | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| |
* | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' |
* '--------------' '----------------' '------------'
*
* openHMC - An Open Source Hybrid Memory Cube Controller
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg
* www.ziti.uni-heidelberg.de
* B6, 26
* 68159 Mannheim
* Germany
*
* Contact: openhmc@ziti.uni-heidelberg.de
* http://ra.ziti.uni-heidelberg.de/openhmc
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This source file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* 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/>.
*
*
* Module name: hmc_controller_8x_rf
*
*
*/
module hmc_controller_8x_rf
(
///\defgroup sys
///@{
input wire res_n,
input wire clk,
///}@
///\defgroup rw_if
///@{
input wire[6:3] address,
output reg[63:0] read_data,
output reg invalid_address,
output reg access_complete,
input wire read_en,
input wire write_en,
input wire[63:0] write_data,
///}@
input wire status_general_link_up_next,
input wire status_general_link_training_next,
input wire status_general_sleep_mode_next,
input wire status_general_lanes_reversed_next,
input wire status_general_phy_ready_next,
input wire[9:0] status_general_hmc_tokens_remaining_next,
input wire[9:0] status_general_rx_tokens_remaining_next,
input wire[7:0] status_general_lane_polarity_reversed_next,
input wire[7:0] status_init_lane_descramblers_locked_next,
input wire[7:0] status_init_descrambler_part_aligned_next,
input wire[7:0] status_init_descrambler_aligned_next,
input wire status_init_all_descramblers_aligned_next,
input wire[1:0] status_init_tx_init_status_next,
input wire status_init_hmc_init_TS1_next,
output reg control_p_rst_n,
output reg control_hmc_init_cont_set,
output reg control_set_hmc_sleep,
output reg control_scrambler_disable,
output reg control_run_length_enable,
output reg[2:0] control_first_cube_ID,
output reg control_debug_dont_send_tret,
output reg[9:0] control_rx_token_count,
output reg[4:0] control_irtry_received_threshold,
output reg[4:0] control_irtry_to_send,
output reg[7:0] control_bit_slip_time,
input wire[63:0] sent_p_cnt_next,
input wire[63:0] sent_np_cnt_next,
input wire[63:0] sent_r_cnt_next,
input wire[63:0] poisoned_packets_cnt_next,
input wire[63:0] rcvd_rsp_cnt_next,
input wire tx_link_retries_count_countup,
input wire errors_on_rx_count_countup,
input wire run_length_bit_flip_count_countup
 
);
 
reg status_general_link_up;
reg status_general_link_training;
reg status_general_sleep_mode;
reg status_general_lanes_reversed;
reg[3:0] status_general_rsvd_status_general_0;
reg status_general_phy_ready;
reg[6:0] status_general_rsvd_status_general_1;
reg[9:0] status_general_hmc_tokens_remaining;
reg[5:0] status_general_rsvd_status_general_2;
reg[9:0] status_general_rx_tokens_remaining;
reg[5:0] status_general_rsvd_status_general_3;
reg[7:0] status_general_lane_polarity_reversed;
reg[7:0] status_init_lane_descramblers_locked;
reg[7:0] status_init_descrambler_part_aligned;
reg[7:0] status_init_descrambler_aligned;
reg status_init_all_descramblers_aligned;
reg[1:0] status_init_tx_init_status;
reg status_init_hmc_init_TS1;
reg[6:0] control_rsvd_control_0;
reg[5:0] control_rsvd_control_1;
reg[2:0] control_rsvd_control_2;
reg[2:0] control_rsvd_control_3;
reg[63:0] sent_p_cnt;
reg[63:0] sent_np_cnt;
reg[63:0] sent_r_cnt;
reg[63:0] poisoned_packets_cnt;
reg[63:0] rcvd_rsp_cnt;
reg rreinit;
wire[31:0] tx_link_retries_count;
wire[31:0] errors_on_rx_count;
wire[31:0] run_length_bit_flip_count;
 
counter48 #(
.DATASIZE(32)
) tx_link_retries_count_I (
.clk(clk),
.res_n(res_n),
.increment(tx_link_retries_count_countup),
.load(32'b0),
.load_enable(rreinit),
.value(tx_link_retries_count)
);
 
counter48 #(
.DATASIZE(32)
) errors_on_rx_count_I (
.clk(clk),
.res_n(res_n),
.increment(errors_on_rx_count_countup),
.load(32'b0),
.load_enable(rreinit),
.value(errors_on_rx_count)
);
 
counter48 #(
.DATASIZE(32)
) run_length_bit_flip_count_I (
.clk(clk),
.res_n(res_n),
.increment(run_length_bit_flip_count_countup),
.load(32'b0),
.load_enable(rreinit),
.value(run_length_bit_flip_count)
);
 
 
/* register status_general */
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) `else
always @(posedge clk) `endif
begin
if (!res_n)
begin
status_general_link_up <= 1'h0;
status_general_link_training <= 1'h0;
status_general_sleep_mode <= 1'h0;
status_general_lanes_reversed <= 1'h0;
status_general_rsvd_status_general_0 <= 4'h0;
status_general_phy_ready <= 1'h0;
status_general_rsvd_status_general_1 <= 7'h0;
status_general_hmc_tokens_remaining <= 1'h0;
status_general_rsvd_status_general_2 <= 6'h0;
status_general_rx_tokens_remaining <= 1'h0;
status_general_rsvd_status_general_3 <= 6'h0;
status_general_lane_polarity_reversed <= 0;
end
else
begin
 
status_general_link_up <= status_general_link_up_next;
status_general_link_training <= status_general_link_training_next;
status_general_sleep_mode <= status_general_sleep_mode_next;
status_general_lanes_reversed <= status_general_lanes_reversed_next;
status_general_phy_ready <= status_general_phy_ready_next;
status_general_hmc_tokens_remaining <= status_general_hmc_tokens_remaining_next;
status_general_rx_tokens_remaining <= status_general_rx_tokens_remaining_next;
status_general_lane_polarity_reversed <= status_general_lane_polarity_reversed_next;
end
end
 
/* register status_init */
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) `else
always @(posedge clk) `endif
begin
if (!res_n)
begin
status_init_lane_descramblers_locked <= 0;
status_init_descrambler_part_aligned <= 0;
status_init_descrambler_aligned <= 0;
status_init_all_descramblers_aligned <= 1'h0;
status_init_tx_init_status <= 2'h0;
status_init_hmc_init_TS1 <= 1'h0;
end
else
begin
 
status_init_lane_descramblers_locked <= status_init_lane_descramblers_locked_next;
status_init_descrambler_part_aligned <= status_init_descrambler_part_aligned_next;
status_init_descrambler_aligned <= status_init_descrambler_aligned_next;
status_init_all_descramblers_aligned <= status_init_all_descramblers_aligned_next;
status_init_tx_init_status <= status_init_tx_init_status_next;
status_init_hmc_init_TS1 <= status_init_hmc_init_TS1_next;
end
end
 
/* register control */
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) `else
always @(posedge clk) `endif
begin
if (!res_n)
begin
control_p_rst_n <= 1'h0;
control_hmc_init_cont_set <= 1'b0;
control_set_hmc_sleep <= 1'h0;
control_scrambler_disable <= 1'h0;
control_run_length_enable <= 1'h0;
control_first_cube_ID <= 3'h0;
control_debug_dont_send_tret <= 1'h0;
control_rsvd_control_0 <= 7'h0;
control_rx_token_count <= 100;
control_rsvd_control_1 <= 6'h0;
control_irtry_received_threshold <= 5'h10;
control_rsvd_control_2 <= 3'h0;
control_irtry_to_send <= 5'h14;
control_rsvd_control_3 <= 3'h0;
control_bit_slip_time <= 8'h24;
end
else
begin
 
if((address[6:3]== 2) && write_en)
begin
control_p_rst_n <= write_data[0:0];
end
if((address[6:3]== 2) && write_en)
begin
control_hmc_init_cont_set <= write_data[1:1];
end
if((address[6:3]== 2) && write_en)
begin
control_set_hmc_sleep <= write_data[2:2];
end
if((address[6:3]== 2) && write_en)
begin
control_scrambler_disable <= write_data[3:3];
end
if((address[6:3]== 2) && write_en)
begin
control_run_length_enable <= write_data[4:4];
end
if((address[6:3]== 2) && write_en)
begin
control_first_cube_ID <= write_data[7:5];
end
if((address[6:3]== 2) && write_en)
begin
control_debug_dont_send_tret <= write_data[8:8];
end
if((address[6:3]== 2) && write_en)
begin
control_rx_token_count <= write_data[25:16];
end
if((address[6:3]== 2) && write_en)
begin
control_irtry_received_threshold <= write_data[36:32];
end
if((address[6:3]== 2) && write_en)
begin
control_irtry_to_send <= write_data[44:40];
end
if((address[6:3]== 2) && write_en)
begin
control_bit_slip_time <= write_data[55:48];
end
end
end
 
/* register sent_p */
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) `else
always @(posedge clk) `endif
begin
if (!res_n)
begin
sent_p_cnt <= 64'h0;
end
else
begin
 
sent_p_cnt <= sent_p_cnt_next;
end
end
 
/* register sent_np */
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) `else
always @(posedge clk) `endif
begin
if (!res_n)
begin
sent_np_cnt <= 64'h0;
end
else
begin
 
sent_np_cnt <= sent_np_cnt_next;
end
end
 
/* register sent_r */
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) `else
always @(posedge clk) `endif
begin
if (!res_n)
begin
sent_r_cnt <= 64'h0;
end
else
begin
 
sent_r_cnt <= sent_r_cnt_next;
end
end
 
/* register poisoned_packets */
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) `else
always @(posedge clk) `endif
begin
if (!res_n)
begin
poisoned_packets_cnt <= 64'h0;
end
else
begin
 
poisoned_packets_cnt <= poisoned_packets_cnt_next;
end
end
 
/* register rcvd_rsp */
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) `else
always @(posedge clk) `endif
begin
if (!res_n)
begin
rcvd_rsp_cnt <= 64'h0;
end
else
begin
 
rcvd_rsp_cnt <= rcvd_rsp_cnt_next;
end
end
 
/* register counter_reset */
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) `else
always @(posedge clk) `endif
begin
if (!res_n)
begin
rreinit <= 1'b0;
end
else
begin
 
if((address[6:3]== 8) && write_en)
begin
rreinit <= 1'b1;
end
else
begin
rreinit <= 1'b0;
end
end
end
 
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) `else
always @(posedge clk) `endif
begin
if (!res_n)
begin
invalid_address <= 1'b0;
access_complete <= 1'b0;
`ifdef ASIC
read_data <= 64'b0;
`endif
 
end
else
begin
 
casex(address[6:3])
4'h0:
begin
read_data[0:0] <= status_general_link_up;
read_data[1:1] <= status_general_link_training;
read_data[2:2] <= status_general_sleep_mode;
read_data[3:3] <= status_general_lanes_reversed;
read_data[7:4] <= status_general_rsvd_status_general_0;
read_data[8:8] <= status_general_phy_ready;
read_data[15:9] <= status_general_rsvd_status_general_1;
read_data[25:16] <= status_general_hmc_tokens_remaining;
read_data[31:26] <= status_general_rsvd_status_general_2;
read_data[41:32] <= status_general_rx_tokens_remaining;
read_data[47:42] <= status_general_rsvd_status_general_3;
read_data[55:48] <= status_general_lane_polarity_reversed;
read_data[63:56] <= 8'b0;
invalid_address <= 1'b0;
access_complete <= write_en || read_en;
end
4'h1:
begin
read_data[7:0] <= status_init_lane_descramblers_locked;
read_data[15:8] <= status_init_descrambler_part_aligned;
read_data[23:16] <= status_init_descrambler_aligned;
read_data[24:24] <= status_init_all_descramblers_aligned;
read_data[26:25] <= status_init_tx_init_status;
read_data[27:27] <= status_init_hmc_init_TS1;
read_data[63:28] <= 36'b0;
invalid_address <= 1'b0;
access_complete <= write_en || read_en;
end
4'h2:
begin
read_data[0:0] <= control_p_rst_n;
read_data[1:1] <= control_hmc_init_cont_set;
read_data[2:2] <= control_set_hmc_sleep;
read_data[3:3] <= control_scrambler_disable;
read_data[4:4] <= control_run_length_enable;
read_data[7:5] <= control_first_cube_ID;
read_data[8:8] <= control_debug_dont_send_tret;
read_data[15:9] <= control_rsvd_control_0;
read_data[25:16] <= control_rx_token_count;
read_data[31:26] <= control_rsvd_control_1;
read_data[36:32] <= control_irtry_received_threshold;
read_data[39:37] <= control_rsvd_control_2;
read_data[44:40] <= control_irtry_to_send;
read_data[47:45] <= control_rsvd_control_3;
read_data[55:48] <= control_bit_slip_time;
read_data[63:56] <= 8'b0;
invalid_address <= 1'b0;
access_complete <= write_en || read_en;
end
4'h3:
begin
read_data[63:0] <= sent_p_cnt;
invalid_address <= 1'b0;
access_complete <= write_en || read_en;
end
4'h4:
begin
read_data[63:0] <= sent_np_cnt;
invalid_address <= 1'b0;
access_complete <= write_en || read_en;
end
4'h5:
begin
read_data[63:0] <= sent_r_cnt;
invalid_address <= 1'b0;
access_complete <= write_en || read_en;
end
4'h6:
begin
read_data[63:0] <= poisoned_packets_cnt;
invalid_address <= 1'b0;
access_complete <= write_en || read_en;
end
4'h7:
begin
read_data[63:0] <= rcvd_rsp_cnt;
invalid_address <= 1'b0;
access_complete <= write_en || read_en;
end
4'h9:
begin
read_data[31:0] <= tx_link_retries_count;
read_data[63:32] <= 32'b0;
invalid_address <= 1'b0;
access_complete <= write_en || read_en;
end
4'ha:
begin
read_data[31:0] <= errors_on_rx_count;
read_data[63:32] <= 32'b0;
invalid_address <= 1'b0;
access_complete <= write_en || read_en;
end
4'hb:
begin
read_data[31:0] <= run_length_bit_flip_count;
read_data[63:32] <= 32'b0;
invalid_address <= 1'b0;
access_complete <= write_en || read_en;
end
default:
begin
invalid_address <= read_en || write_en;
access_complete <= read_en || write_en;
end
endcase
end
end
endmodule
/openhmc/trunk/openHMC/rtl/hmc_controller/crc/crc_accu.v
0,0 → 1,148
/*
* .--------------. .----------------. .------------.
* | .------------. | .--------------. | .----------. |
* | | ____ ____ | | | ____ ____ | | | ______ | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| |
* | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' |
* '--------------' '----------------' '------------'
*
* openHMC - An Open Source Hybrid Memory Cube Controller
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg
* www.ziti.uni-heidelberg.de
* B6, 26
* 68159 Mannheim
* Germany
*
* Contact: openhmc@ziti.uni-heidelberg.de
* http://ra.ziti.uni-heidelberg.de/openhmc
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This source file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* 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/>.
*
*
* Module name: crc_accu
*/
 
module crc_accu #(parameter FPW=4)(
//----------------------------------
//----SYSTEM INTERFACE
//----------------------------------
input wire clk ,
input wire res_n ,
 
//----------------------------------
//----Input
//----------------------------------
input wire clear ,
input wire [(FPW*32)-1:0] d_in ,
input wire [FPW-1:0] valid ,
 
//----------------------------------
//----Output
//----------------------------------
output reg [31:0] crc_out
);
 
integer i_f;
 
reg [31:0] crc_temp [FPW:0];
reg [31:0] crc;
 
wire [31:0] in [FPW-1:0];
 
genvar f;
generate
for(f=0;f<FPW;f=f+1) begin
assign in[f] = d_in[(f*32)+32-1:(f*32)];
end
endgenerate
 
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) `else
always @(posedge clk) `endif
begin
if (!res_n) begin
crc <= {32{1'b0}};
end
else begin
for(i_f=0;i_f<FPW;i_f=i_f+1) begin
if(valid[i_f])begin
crc <= crc_temp[i_f+1];
end
end
end
end
 
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) `else
always @(posedge clk) `endif
begin
if (!res_n) begin
crc_out <= 32'h0;
end
else begin
crc_out <= crc;
end
end
 
always @(*)
begin
if(clear) begin
crc_temp[0] = 32'h0;
end else begin
crc_temp[0] = crc;
end
 
for(i_f=0;i_f<FPW;i_f=i_f+1) begin
crc_temp[i_f+1][31] = in[i_f][31] ^ crc_temp[i_f][3]^crc_temp[i_f][5]^crc_temp[i_f][6]^crc_temp[i_f][8]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][14]^crc_temp[i_f][15]^crc_temp[i_f][17]^crc_temp[i_f][18]^crc_temp[i_f][19]^crc_temp[i_f][21]^crc_temp[i_f][26]^crc_temp[i_f][29];
crc_temp[i_f+1][30] = in[i_f][30] ^ crc_temp[i_f][2]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][7]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][16]^crc_temp[i_f][17]^crc_temp[i_f][18]^crc_temp[i_f][20]^crc_temp[i_f][25]^crc_temp[i_f][28];
crc_temp[i_f+1][29] = in[i_f][29] ^ crc_temp[i_f][1]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][16]^crc_temp[i_f][18]^crc_temp[i_f][21]^crc_temp[i_f][24]^crc_temp[i_f][26]^crc_temp[i_f][27]^crc_temp[i_f][29];
crc_temp[i_f+1][28] = in[i_f][28] ^ crc_temp[i_f][0]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][6]^crc_temp[i_f][9]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][18]^crc_temp[i_f][19]^crc_temp[i_f][20]^crc_temp[i_f][21]^crc_temp[i_f][23]^crc_temp[i_f][25]^crc_temp[i_f][28]^crc_temp[i_f][29]^crc_temp[i_f][31];
crc_temp[i_f+1][27] = in[i_f][27] ^ crc_temp[i_f][4]^crc_temp[i_f][6]^crc_temp[i_f][10]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][15]^crc_temp[i_f][20]^crc_temp[i_f][21]^crc_temp[i_f][22]^crc_temp[i_f][24]^crc_temp[i_f][26]^crc_temp[i_f][27]^crc_temp[i_f][28]^crc_temp[i_f][29]^crc_temp[i_f][30]^crc_temp[i_f][31];
crc_temp[i_f+1][26] = in[i_f][26] ^ crc_temp[i_f][3]^crc_temp[i_f][5]^crc_temp[i_f][9]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][19]^crc_temp[i_f][20]^crc_temp[i_f][21]^crc_temp[i_f][23]^crc_temp[i_f][25]^crc_temp[i_f][26]^crc_temp[i_f][27]^crc_temp[i_f][28]^crc_temp[i_f][29]^crc_temp[i_f][30]^crc_temp[i_f][31];
crc_temp[i_f+1][25] = in[i_f][25] ^ crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][6]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][15]^crc_temp[i_f][17]^crc_temp[i_f][20]^crc_temp[i_f][21]^crc_temp[i_f][22]^crc_temp[i_f][24]^crc_temp[i_f][25]^crc_temp[i_f][27]^crc_temp[i_f][28]^crc_temp[i_f][30]^crc_temp[i_f][31];
crc_temp[i_f+1][24] = in[i_f][24] ^ crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][16]^crc_temp[i_f][19]^crc_temp[i_f][20]^crc_temp[i_f][21]^crc_temp[i_f][23]^crc_temp[i_f][24]^crc_temp[i_f][26]^crc_temp[i_f][27]^crc_temp[i_f][29]^crc_temp[i_f][30];
crc_temp[i_f+1][23] = in[i_f][23] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][4]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][15]^crc_temp[i_f][18]^crc_temp[i_f][19]^crc_temp[i_f][20]^crc_temp[i_f][22]^crc_temp[i_f][23]^crc_temp[i_f][25]^crc_temp[i_f][26]^crc_temp[i_f][28]^crc_temp[i_f][29];
crc_temp[i_f+1][22] = in[i_f][22] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][14]^crc_temp[i_f][17]^crc_temp[i_f][18]^crc_temp[i_f][19]^crc_temp[i_f][21]^crc_temp[i_f][22]^crc_temp[i_f][24]^crc_temp[i_f][25]^crc_temp[i_f][27]^crc_temp[i_f][28];
crc_temp[i_f+1][21] = in[i_f][21] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][8]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][13]^crc_temp[i_f][16]^crc_temp[i_f][17]^crc_temp[i_f][18]^crc_temp[i_f][20]^crc_temp[i_f][21]^crc_temp[i_f][23]^crc_temp[i_f][24]^crc_temp[i_f][26]^crc_temp[i_f][27];
crc_temp[i_f+1][20] = in[i_f][20] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][7]^crc_temp[i_f][8]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][12]^crc_temp[i_f][15]^crc_temp[i_f][16]^crc_temp[i_f][17]^crc_temp[i_f][19]^crc_temp[i_f][20]^crc_temp[i_f][22]^crc_temp[i_f][23]^crc_temp[i_f][25]^crc_temp[i_f][26]^crc_temp[i_f][31];
crc_temp[i_f+1][19] = in[i_f][19] ^ crc_temp[i_f][0]^crc_temp[i_f][3]^crc_temp[i_f][5]^crc_temp[i_f][7]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][16]^crc_temp[i_f][17]^crc_temp[i_f][22]^crc_temp[i_f][24]^crc_temp[i_f][25]^crc_temp[i_f][26]^crc_temp[i_f][29]^crc_temp[i_f][30];
crc_temp[i_f+1][18] = in[i_f][18] ^ crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][14]^crc_temp[i_f][16]^crc_temp[i_f][17]^crc_temp[i_f][18]^crc_temp[i_f][19]^crc_temp[i_f][23]^crc_temp[i_f][24]^crc_temp[i_f][25]^crc_temp[i_f][26]^crc_temp[i_f][28];
crc_temp[i_f+1][17] = in[i_f][17] ^ crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][4]^crc_temp[i_f][8]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][13]^crc_temp[i_f][15]^crc_temp[i_f][16]^crc_temp[i_f][17]^crc_temp[i_f][18]^crc_temp[i_f][22]^crc_temp[i_f][23]^crc_temp[i_f][24]^crc_temp[i_f][25]^crc_temp[i_f][27]^crc_temp[i_f][31];
crc_temp[i_f+1][16] = in[i_f][16] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][5]^crc_temp[i_f][6]^crc_temp[i_f][7]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][16]^crc_temp[i_f][18]^crc_temp[i_f][19]^crc_temp[i_f][22]^crc_temp[i_f][23]^crc_temp[i_f][24]^crc_temp[i_f][29]^crc_temp[i_f][30]^crc_temp[i_f][31];
crc_temp[i_f+1][15] = in[i_f][15] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][3]^crc_temp[i_f][4]^crc_temp[i_f][9]^crc_temp[i_f][14]^crc_temp[i_f][19]^crc_temp[i_f][22]^crc_temp[i_f][23]^crc_temp[i_f][26]^crc_temp[i_f][28]^crc_temp[i_f][30]^crc_temp[i_f][31];
crc_temp[i_f+1][14] = in[i_f][14] ^ crc_temp[i_f][0]^crc_temp[i_f][2]^crc_temp[i_f][5]^crc_temp[i_f][6]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][15]^crc_temp[i_f][17]^crc_temp[i_f][19]^crc_temp[i_f][22]^crc_temp[i_f][25]^crc_temp[i_f][26]^crc_temp[i_f][27]^crc_temp[i_f][30]^crc_temp[i_f][31];
crc_temp[i_f+1][13] = in[i_f][13] ^ crc_temp[i_f][1]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][16]^crc_temp[i_f][18]^crc_temp[i_f][21]^crc_temp[i_f][24]^crc_temp[i_f][25]^crc_temp[i_f][26]^crc_temp[i_f][29]^crc_temp[i_f][30];
crc_temp[i_f+1][12] = in[i_f][12] ^ crc_temp[i_f][0]^crc_temp[i_f][3]^crc_temp[i_f][4]^crc_temp[i_f][8]^crc_temp[i_f][9]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][15]^crc_temp[i_f][17]^crc_temp[i_f][20]^crc_temp[i_f][23]^crc_temp[i_f][24]^crc_temp[i_f][25]^crc_temp[i_f][28]^crc_temp[i_f][29]^crc_temp[i_f][31];
crc_temp[i_f+1][11] = in[i_f][11] ^ crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][7]^crc_temp[i_f][8]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][14]^crc_temp[i_f][16]^crc_temp[i_f][19]^crc_temp[i_f][22]^crc_temp[i_f][23]^crc_temp[i_f][24]^crc_temp[i_f][27]^crc_temp[i_f][28]^crc_temp[i_f][30];
crc_temp[i_f+1][10] = in[i_f][10] ^ crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][5]^crc_temp[i_f][7]^crc_temp[i_f][8]^crc_temp[i_f][9]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][17]^crc_temp[i_f][19]^crc_temp[i_f][22]^crc_temp[i_f][23]^crc_temp[i_f][27];
crc_temp[i_f+1][ 9] = in[i_f][ 9] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][7]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][15]^crc_temp[i_f][16]^crc_temp[i_f][17]^crc_temp[i_f][19]^crc_temp[i_f][22]^crc_temp[i_f][29]^crc_temp[i_f][31];
crc_temp[i_f+1][ 8] = in[i_f][ 8] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][4]^crc_temp[i_f][6]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][15]^crc_temp[i_f][16]^crc_temp[i_f][18]^crc_temp[i_f][21]^crc_temp[i_f][28]^crc_temp[i_f][30];
crc_temp[i_f+1][ 7] = in[i_f][ 7] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][5]^crc_temp[i_f][8]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][14]^crc_temp[i_f][15]^crc_temp[i_f][17]^crc_temp[i_f][20]^crc_temp[i_f][27]^crc_temp[i_f][29]^crc_temp[i_f][31];
crc_temp[i_f+1][ 6] = in[i_f][ 6] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][6]^crc_temp[i_f][7]^crc_temp[i_f][9]^crc_temp[i_f][12]^crc_temp[i_f][13]^crc_temp[i_f][15]^crc_temp[i_f][16]^crc_temp[i_f][17]^crc_temp[i_f][18]^crc_temp[i_f][21]^crc_temp[i_f][28]^crc_temp[i_f][29]^crc_temp[i_f][30]^crc_temp[i_f][31];
crc_temp[i_f+1][ 5] = in[i_f][ 5] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][4]^crc_temp[i_f][10]^crc_temp[i_f][12]^crc_temp[i_f][16]^crc_temp[i_f][18]^crc_temp[i_f][19]^crc_temp[i_f][20]^crc_temp[i_f][21]^crc_temp[i_f][26]^crc_temp[i_f][27]^crc_temp[i_f][28]^crc_temp[i_f][30];
crc_temp[i_f+1][ 4] = in[i_f][ 4] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][3]^crc_temp[i_f][9]^crc_temp[i_f][11]^crc_temp[i_f][15]^crc_temp[i_f][17]^crc_temp[i_f][18]^crc_temp[i_f][19]^crc_temp[i_f][20]^crc_temp[i_f][25]^crc_temp[i_f][26]^crc_temp[i_f][27]^crc_temp[i_f][29]^crc_temp[i_f][31];
crc_temp[i_f+1][ 3] = in[i_f][ 3] ^ crc_temp[i_f][0]^crc_temp[i_f][2]^crc_temp[i_f][3]^crc_temp[i_f][5]^crc_temp[i_f][6]^crc_temp[i_f][11]^crc_temp[i_f][15]^crc_temp[i_f][16]^crc_temp[i_f][21]^crc_temp[i_f][24]^crc_temp[i_f][25]^crc_temp[i_f][28]^crc_temp[i_f][29]^crc_temp[i_f][30]^crc_temp[i_f][31];
crc_temp[i_f+1][ 2] = in[i_f][ 2] ^ crc_temp[i_f][1]^crc_temp[i_f][2]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][10]^crc_temp[i_f][14]^crc_temp[i_f][15]^crc_temp[i_f][20]^crc_temp[i_f][23]^crc_temp[i_f][24]^crc_temp[i_f][27]^crc_temp[i_f][28]^crc_temp[i_f][29]^crc_temp[i_f][30]^crc_temp[i_f][31];
crc_temp[i_f+1][ 1] = in[i_f][ 1] ^ crc_temp[i_f][0]^crc_temp[i_f][1]^crc_temp[i_f][4]^crc_temp[i_f][5]^crc_temp[i_f][6]^crc_temp[i_f][8]^crc_temp[i_f][9]^crc_temp[i_f][10]^crc_temp[i_f][11]^crc_temp[i_f][13]^crc_temp[i_f][15]^crc_temp[i_f][17]^crc_temp[i_f][18]^crc_temp[i_f][21]^crc_temp[i_f][22]^crc_temp[i_f][23]^crc_temp[i_f][27]^crc_temp[i_f][28]^crc_temp[i_f][30]^crc_temp[i_f][31];
crc_temp[i_f+1][ 0] = in[i_f][ 0] ^ crc_temp[i_f][0]^crc_temp[i_f][4]^crc_temp[i_f][6]^crc_temp[i_f][7]^crc_temp[i_f][9]^crc_temp[i_f][11]^crc_temp[i_f][12]^crc_temp[i_f][15]^crc_temp[i_f][16]^crc_temp[i_f][18]^crc_temp[i_f][19]^crc_temp[i_f][20]^crc_temp[i_f][22]^crc_temp[i_f][27]^crc_temp[i_f][30];
end
end
 
endmodule
/openhmc/trunk/openHMC/rtl/hmc_controller/crc/crc_128_init.v
0,0 → 1,104
/*
* .--------------. .----------------. .------------.
* | .------------. | .--------------. | .----------. |
* | | ____ ____ | | | ____ ____ | | | ______ | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| |
* | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' |
* '--------------' '----------------' '------------'
*
* openHMC - An Open Source Hybrid Memory Cube Controller
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg
* www.ziti.uni-heidelberg.de
* B6, 26
* 68159 Mannheim
* Germany
*
* Contact: openhmc@ziti.uni-heidelberg.de
* http://ra.ziti.uni-heidelberg.de/openhmc
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This source file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* 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/>.
*
*
* Module name: crc_128_init
*
*/
 
module crc_128_init (
//----------------------------------
//----SYSTEM INTERFACE
//----------------------------------
input wire clk ,
input wire res_n ,
 
//----------------------------------
//----Input
//----------------------------------
input wire [127:0] inData ,
 
//----------------------------------
//----Output
//----------------------------------
output reg [31:0] crc
);
 
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) `else
always @(posedge clk) `endif
begin
if (!res_n) begin
crc <= 32'h0;
end
else begin
 
crc[31] <= inData[2]^inData[5]^inData[10]^inData[12]^inData[13]^inData[14]^inData[16]^inData[17]^inData[20]^inData[21]^inData[23]^inData[25]^inData[26]^inData[28]^inData[32]^inData[34]^inData[36]^inData[40]^inData[41]^inData[43]^inData[45]^inData[47]^inData[49]^inData[51]^inData[53]^inData[54]^inData[57]^inData[58]^inData[60]^inData[61]^inData[64]^inData[65]^inData[66]^inData[71]^inData[74]^inData[76]^inData[77]^inData[78]^inData[80]^inData[81]^inData[82]^inData[84]^inData[92]^inData[93]^inData[94]^inData[100]^inData[102]^inData[103]^inData[104]^inData[105]^inData[106]^inData[108]^inData[111]^inData[115]^inData[116]^inData[119]^inData[121]^inData[122]^inData[125]^inData[126];
crc[30] <= inData[3]^inData[6]^inData[11]^inData[13]^inData[14]^inData[15]^inData[17]^inData[18]^inData[21]^inData[22]^inData[24]^inData[26]^inData[27]^inData[29]^inData[33]^inData[35]^inData[37]^inData[41]^inData[42]^inData[44]^inData[46]^inData[48]^inData[50]^inData[52]^inData[54]^inData[55]^inData[58]^inData[59]^inData[61]^inData[62]^inData[65]^inData[66]^inData[67]^inData[72]^inData[75]^inData[77]^inData[78]^inData[79]^inData[81]^inData[82]^inData[83]^inData[85]^inData[93]^inData[94]^inData[95]^inData[101]^inData[103]^inData[104]^inData[105]^inData[106]^inData[107]^inData[109]^inData[112]^inData[116]^inData[117]^inData[120]^inData[122]^inData[123]^inData[126]^inData[127];
crc[29] <= inData[2]^inData[4]^inData[5]^inData[7]^inData[10]^inData[13]^inData[15]^inData[17]^inData[18]^inData[19]^inData[20]^inData[21]^inData[22]^inData[26]^inData[27]^inData[30]^inData[32]^inData[38]^inData[40]^inData[41]^inData[42]^inData[54]^inData[55]^inData[56]^inData[57]^inData[58]^inData[59]^inData[61]^inData[62]^inData[63]^inData[64]^inData[65]^inData[67]^inData[68]^inData[71]^inData[73]^inData[74]^inData[77]^inData[79]^inData[81]^inData[83]^inData[86]^inData[92]^inData[93]^inData[95]^inData[96]^inData[100]^inData[103]^inData[107]^inData[110]^inData[111]^inData[113]^inData[115]^inData[116]^inData[117]^inData[118]^inData[119]^inData[122]^inData[123]^inData[124]^inData[125]^inData[126]^inData[127];
crc[28] <= inData[0]^inData[2]^inData[3]^inData[6]^inData[8]^inData[10]^inData[11]^inData[12]^inData[13]^inData[17]^inData[18]^inData[19]^inData[22]^inData[25]^inData[26]^inData[27]^inData[31]^inData[32]^inData[33]^inData[34]^inData[36]^inData[39]^inData[40]^inData[42]^inData[45]^inData[47]^inData[49]^inData[51]^inData[53]^inData[54]^inData[55]^inData[56]^inData[59]^inData[61]^inData[62]^inData[63]^inData[68]^inData[69]^inData[71]^inData[72]^inData[75]^inData[76]^inData[77]^inData[81]^inData[87]^inData[92]^inData[96]^inData[97]^inData[100]^inData[101]^inData[102]^inData[103]^inData[105]^inData[106]^inData[112]^inData[114]^inData[115]^inData[117]^inData[118]^inData[120]^inData[121]^inData[122]^inData[123]^inData[124]^inData[127];
crc[27] <= inData[0]^inData[1]^inData[2]^inData[3]^inData[4]^inData[5]^inData[7]^inData[9]^inData[10]^inData[11]^inData[16]^inData[17]^inData[18]^inData[19]^inData[21]^inData[25]^inData[27]^inData[33]^inData[35]^inData[36]^inData[37]^inData[45]^inData[46]^inData[47]^inData[48]^inData[49]^inData[50]^inData[51]^inData[52]^inData[53]^inData[55]^inData[56]^inData[58]^inData[61]^inData[62]^inData[63]^inData[65]^inData[66]^inData[69]^inData[70]^inData[71]^inData[72]^inData[73]^inData[74]^inData[80]^inData[81]^inData[84]^inData[88]^inData[92]^inData[94]^inData[97]^inData[98]^inData[100]^inData[101]^inData[105]^inData[107]^inData[108]^inData[111]^inData[113]^inData[118]^inData[123]^inData[124]^inData[126];
crc[26] <= inData[0]^inData[1]^inData[2]^inData[3]^inData[4]^inData[5]^inData[6]^inData[8]^inData[10]^inData[11]^inData[12]^inData[17]^inData[18]^inData[19]^inData[20]^inData[22]^inData[26]^inData[28]^inData[34]^inData[36]^inData[37]^inData[38]^inData[46]^inData[47]^inData[48]^inData[49]^inData[50]^inData[51]^inData[52]^inData[53]^inData[54]^inData[56]^inData[57]^inData[59]^inData[62]^inData[63]^inData[64]^inData[66]^inData[67]^inData[70]^inData[71]^inData[72]^inData[73]^inData[74]^inData[75]^inData[81]^inData[82]^inData[85]^inData[89]^inData[93]^inData[95]^inData[98]^inData[99]^inData[101]^inData[102]^inData[106]^inData[108]^inData[109]^inData[112]^inData[114]^inData[119]^inData[124]^inData[125]^inData[127];
crc[25] <= inData[0]^inData[1]^inData[3]^inData[4]^inData[6]^inData[7]^inData[9]^inData[10]^inData[11]^inData[14]^inData[16]^inData[17]^inData[18]^inData[19]^inData[25]^inData[26]^inData[27]^inData[28]^inData[29]^inData[32]^inData[34]^inData[35]^inData[36]^inData[37]^inData[38]^inData[39]^inData[40]^inData[41]^inData[43]^inData[45]^inData[48]^inData[50]^inData[52]^inData[55]^inData[61]^inData[63]^inData[66]^inData[67]^inData[68]^inData[72]^inData[73]^inData[75]^inData[77]^inData[78]^inData[80]^inData[81]^inData[83]^inData[84]^inData[86]^inData[90]^inData[92]^inData[93]^inData[96]^inData[99]^inData[104]^inData[105]^inData[106]^inData[107]^inData[108]^inData[109]^inData[110]^inData[111]^inData[113]^inData[116]^inData[119]^inData[120]^inData[121]^inData[122];
crc[24] <= inData[1]^inData[2]^inData[4]^inData[5]^inData[7]^inData[8]^inData[10]^inData[11]^inData[12]^inData[15]^inData[17]^inData[18]^inData[19]^inData[20]^inData[26]^inData[27]^inData[28]^inData[29]^inData[30]^inData[33]^inData[35]^inData[36]^inData[37]^inData[38]^inData[39]^inData[40]^inData[41]^inData[42]^inData[44]^inData[46]^inData[49]^inData[51]^inData[53]^inData[56]^inData[62]^inData[64]^inData[67]^inData[68]^inData[69]^inData[73]^inData[74]^inData[76]^inData[78]^inData[79]^inData[81]^inData[82]^inData[84]^inData[85]^inData[87]^inData[91]^inData[93]^inData[94]^inData[97]^inData[100]^inData[105]^inData[106]^inData[107]^inData[108]^inData[109]^inData[110]^inData[111]^inData[112]^inData[114]^inData[117]^inData[120]^inData[121]^inData[122]^inData[123];
crc[23] <= inData[2]^inData[3]^inData[5]^inData[6]^inData[8]^inData[9]^inData[11]^inData[12]^inData[13]^inData[16]^inData[18]^inData[19]^inData[20]^inData[21]^inData[27]^inData[28]^inData[29]^inData[30]^inData[31]^inData[34]^inData[36]^inData[37]^inData[38]^inData[39]^inData[40]^inData[41]^inData[42]^inData[43]^inData[45]^inData[47]^inData[50]^inData[52]^inData[54]^inData[57]^inData[63]^inData[65]^inData[68]^inData[69]^inData[70]^inData[74]^inData[75]^inData[77]^inData[79]^inData[80]^inData[82]^inData[83]^inData[85]^inData[86]^inData[88]^inData[92]^inData[94]^inData[95]^inData[98]^inData[101]^inData[106]^inData[107]^inData[108]^inData[109]^inData[110]^inData[111]^inData[112]^inData[113]^inData[115]^inData[118]^inData[121]^inData[122]^inData[123]^inData[124];
crc[22] <= inData[3]^inData[4]^inData[6]^inData[7]^inData[9]^inData[10]^inData[12]^inData[13]^inData[14]^inData[17]^inData[19]^inData[20]^inData[21]^inData[22]^inData[28]^inData[29]^inData[30]^inData[31]^inData[32]^inData[35]^inData[37]^inData[38]^inData[39]^inData[40]^inData[41]^inData[42]^inData[43]^inData[44]^inData[46]^inData[48]^inData[51]^inData[53]^inData[55]^inData[58]^inData[64]^inData[66]^inData[69]^inData[70]^inData[71]^inData[75]^inData[76]^inData[78]^inData[80]^inData[81]^inData[83]^inData[84]^inData[86]^inData[87]^inData[89]^inData[93]^inData[95]^inData[96]^inData[99]^inData[102]^inData[107]^inData[108]^inData[109]^inData[110]^inData[111]^inData[112]^inData[113]^inData[114]^inData[116]^inData[119]^inData[122]^inData[123]^inData[124]^inData[125];
crc[21] <= inData[4]^inData[5]^inData[7]^inData[8]^inData[10]^inData[11]^inData[13]^inData[14]^inData[15]^inData[18]^inData[20]^inData[21]^inData[22]^inData[23]^inData[29]^inData[30]^inData[31]^inData[32]^inData[33]^inData[36]^inData[38]^inData[39]^inData[40]^inData[41]^inData[42]^inData[43]^inData[44]^inData[45]^inData[47]^inData[49]^inData[52]^inData[54]^inData[56]^inData[59]^inData[65]^inData[67]^inData[70]^inData[71]^inData[72]^inData[76]^inData[77]^inData[79]^inData[81]^inData[82]^inData[84]^inData[85]^inData[87]^inData[88]^inData[90]^inData[94]^inData[96]^inData[97]^inData[100]^inData[103]^inData[108]^inData[109]^inData[110]^inData[111]^inData[112]^inData[113]^inData[114]^inData[115]^inData[117]^inData[120]^inData[123]^inData[124]^inData[125]^inData[126];
crc[20] <= inData[0]^inData[5]^inData[6]^inData[8]^inData[9]^inData[11]^inData[12]^inData[14]^inData[15]^inData[16]^inData[19]^inData[21]^inData[22]^inData[23]^inData[24]^inData[30]^inData[31]^inData[32]^inData[33]^inData[34]^inData[37]^inData[39]^inData[40]^inData[41]^inData[42]^inData[43]^inData[44]^inData[45]^inData[46]^inData[48]^inData[50]^inData[53]^inData[55]^inData[57]^inData[60]^inData[66]^inData[68]^inData[71]^inData[72]^inData[73]^inData[77]^inData[78]^inData[80]^inData[82]^inData[83]^inData[85]^inData[86]^inData[88]^inData[89]^inData[91]^inData[95]^inData[97]^inData[98]^inData[101]^inData[104]^inData[109]^inData[110]^inData[111]^inData[112]^inData[113]^inData[114]^inData[115]^inData[116]^inData[118]^inData[121]^inData[124]^inData[125]^inData[126]^inData[127];
crc[19] <= inData[1]^inData[2]^inData[5]^inData[6]^inData[7]^inData[9]^inData[14]^inData[15]^inData[21]^inData[22]^inData[24]^inData[26]^inData[28]^inData[31]^inData[33]^inData[35]^inData[36]^inData[38]^inData[42]^inData[44]^inData[46]^inData[53]^inData[56]^inData[57]^inData[60]^inData[64]^inData[65]^inData[66]^inData[67]^inData[69]^inData[71]^inData[72]^inData[73]^inData[76]^inData[77]^inData[79]^inData[80]^inData[82]^inData[83]^inData[86]^inData[87]^inData[89]^inData[90]^inData[93]^inData[94]^inData[96]^inData[98]^inData[99]^inData[100]^inData[103]^inData[104]^inData[106]^inData[108]^inData[110]^inData[112]^inData[113]^inData[114]^inData[117]^inData[121]^inData[127];
crc[18] <= inData[3]^inData[5]^inData[6]^inData[7]^inData[8]^inData[12]^inData[13]^inData[14]^inData[15]^inData[17]^inData[20]^inData[21]^inData[22]^inData[26]^inData[27]^inData[28]^inData[29]^inData[37]^inData[39]^inData[40]^inData[41]^inData[49]^inData[51]^inData[53]^inData[60]^inData[64]^inData[67]^inData[68]^inData[70]^inData[71]^inData[72]^inData[73]^inData[76]^inData[82]^inData[83]^inData[87]^inData[88]^inData[90]^inData[91]^inData[92]^inData[93]^inData[95]^inData[97]^inData[99]^inData[101]^inData[102]^inData[103]^inData[106]^inData[107]^inData[108]^inData[109]^inData[113]^inData[114]^inData[116]^inData[118]^inData[119]^inData[121]^inData[125]^inData[126];
crc[17] <= inData[0]^inData[4]^inData[6]^inData[7]^inData[8]^inData[9]^inData[13]^inData[14]^inData[15]^inData[16]^inData[18]^inData[21]^inData[22]^inData[23]^inData[27]^inData[28]^inData[29]^inData[30]^inData[38]^inData[40]^inData[41]^inData[42]^inData[50]^inData[52]^inData[54]^inData[61]^inData[65]^inData[68]^inData[69]^inData[71]^inData[72]^inData[73]^inData[74]^inData[77]^inData[83]^inData[84]^inData[88]^inData[89]^inData[91]^inData[92]^inData[93]^inData[94]^inData[96]^inData[98]^inData[100]^inData[102]^inData[103]^inData[104]^inData[107]^inData[108]^inData[109]^inData[110]^inData[114]^inData[115]^inData[117]^inData[119]^inData[120]^inData[122]^inData[126]^inData[127];
crc[16] <= inData[0]^inData[1]^inData[2]^inData[7]^inData[8]^inData[9]^inData[12]^inData[13]^inData[15]^inData[19]^inData[20]^inData[21]^inData[22]^inData[24]^inData[25]^inData[26]^inData[29]^inData[30]^inData[31]^inData[32]^inData[34]^inData[36]^inData[39]^inData[40]^inData[42]^inData[45]^inData[47]^inData[49]^inData[54]^inData[55]^inData[57]^inData[58]^inData[60]^inData[61]^inData[62]^inData[64]^inData[65]^inData[69]^inData[70]^inData[71]^inData[72]^inData[73]^inData[75]^inData[76]^inData[77]^inData[80]^inData[81]^inData[82]^inData[85]^inData[89]^inData[90]^inData[95]^inData[97]^inData[99]^inData[100]^inData[101]^inData[102]^inData[106]^inData[109]^inData[110]^inData[118]^inData[119]^inData[120]^inData[122]^inData[123]^inData[125]^inData[126]^inData[127];
crc[15] <= inData[0]^inData[1]^inData[3]^inData[5]^inData[8]^inData[9]^inData[12]^inData[17]^inData[22]^inData[27]^inData[28]^inData[30]^inData[31]^inData[33]^inData[34]^inData[35]^inData[36]^inData[37]^inData[45]^inData[46]^inData[47]^inData[48]^inData[49]^inData[50]^inData[51]^inData[53]^inData[54]^inData[55]^inData[56]^inData[57]^inData[59]^inData[60]^inData[62]^inData[63]^inData[64]^inData[70]^inData[72]^inData[73]^inData[80]^inData[83]^inData[84]^inData[86]^inData[90]^inData[91]^inData[92]^inData[93]^inData[94]^inData[96]^inData[98]^inData[101]^inData[104]^inData[105]^inData[106]^inData[107]^inData[108]^inData[110]^inData[115]^inData[116]^inData[120]^inData[122]^inData[123]^inData[124]^inData[125]^inData[127];
crc[14] <= inData[0]^inData[1]^inData[4]^inData[5]^inData[6]^inData[9]^inData[12]^inData[14]^inData[16]^inData[17]^inData[18]^inData[20]^inData[21]^inData[25]^inData[26]^inData[29]^inData[31]^inData[35]^inData[37]^inData[38]^inData[40]^inData[41]^inData[43]^inData[45]^inData[46]^inData[48]^inData[50]^inData[52]^inData[53]^inData[55]^inData[56]^inData[63]^inData[66]^inData[73]^inData[76]^inData[77]^inData[78]^inData[80]^inData[82]^inData[85]^inData[87]^inData[91]^inData[95]^inData[97]^inData[99]^inData[100]^inData[103]^inData[104]^inData[107]^inData[109]^inData[115]^inData[117]^inData[119]^inData[122]^inData[123]^inData[124];
crc[13] <= inData[1]^inData[2]^inData[5]^inData[6]^inData[7]^inData[10]^inData[13]^inData[15]^inData[17]^inData[18]^inData[19]^inData[21]^inData[22]^inData[26]^inData[27]^inData[30]^inData[32]^inData[36]^inData[38]^inData[39]^inData[41]^inData[42]^inData[44]^inData[46]^inData[47]^inData[49]^inData[51]^inData[53]^inData[54]^inData[56]^inData[57]^inData[64]^inData[67]^inData[74]^inData[77]^inData[78]^inData[79]^inData[81]^inData[83]^inData[86]^inData[88]^inData[92]^inData[96]^inData[98]^inData[100]^inData[101]^inData[104]^inData[105]^inData[108]^inData[110]^inData[116]^inData[118]^inData[120]^inData[123]^inData[124]^inData[125];
crc[12] <= inData[0]^inData[2]^inData[3]^inData[6]^inData[7]^inData[8]^inData[11]^inData[14]^inData[16]^inData[18]^inData[19]^inData[20]^inData[22]^inData[23]^inData[27]^inData[28]^inData[31]^inData[33]^inData[37]^inData[39]^inData[40]^inData[42]^inData[43]^inData[45]^inData[47]^inData[48]^inData[50]^inData[52]^inData[54]^inData[55]^inData[57]^inData[58]^inData[65]^inData[68]^inData[75]^inData[78]^inData[79]^inData[80]^inData[82]^inData[84]^inData[87]^inData[89]^inData[93]^inData[97]^inData[99]^inData[101]^inData[102]^inData[105]^inData[106]^inData[109]^inData[111]^inData[117]^inData[119]^inData[121]^inData[124]^inData[125]^inData[126];
crc[11] <= inData[1]^inData[3]^inData[4]^inData[7]^inData[8]^inData[9]^inData[12]^inData[15]^inData[17]^inData[19]^inData[20]^inData[21]^inData[23]^inData[24]^inData[28]^inData[29]^inData[32]^inData[34]^inData[38]^inData[40]^inData[41]^inData[43]^inData[44]^inData[46]^inData[48]^inData[49]^inData[51]^inData[53]^inData[55]^inData[56]^inData[58]^inData[59]^inData[66]^inData[69]^inData[76]^inData[79]^inData[80]^inData[81]^inData[83]^inData[85]^inData[88]^inData[90]^inData[94]^inData[98]^inData[100]^inData[102]^inData[103]^inData[106]^inData[107]^inData[110]^inData[112]^inData[118]^inData[120]^inData[122]^inData[125]^inData[126]^inData[127];
crc[10] <= inData[4]^inData[8]^inData[9]^inData[12]^inData[14]^inData[17]^inData[18]^inData[22]^inData[23]^inData[24]^inData[26]^inData[28]^inData[29]^inData[30]^inData[32]^inData[33]^inData[34]^inData[35]^inData[36]^inData[39]^inData[40]^inData[42]^inData[43]^inData[44]^inData[50]^inData[51]^inData[52]^inData[53]^inData[56]^inData[58]^inData[59]^inData[61]^inData[64]^inData[65]^inData[66]^inData[67]^inData[70]^inData[71]^inData[74]^inData[76]^inData[78]^inData[86]^inData[89]^inData[91]^inData[92]^inData[93]^inData[94]^inData[95]^inData[99]^inData[100]^inData[101]^inData[102]^inData[105]^inData[106]^inData[107]^inData[113]^inData[115]^inData[116]^inData[122]^inData[123]^inData[125]^inData[127];
crc[ 9] <= inData[0]^inData[2]^inData[9]^inData[12]^inData[14]^inData[15]^inData[16]^inData[17]^inData[18]^inData[19]^inData[20]^inData[21]^inData[24]^inData[26]^inData[27]^inData[28]^inData[29]^inData[30]^inData[31]^inData[32]^inData[33]^inData[35]^inData[37]^inData[44]^inData[47]^inData[49]^inData[52]^inData[58]^inData[59]^inData[61]^inData[62]^inData[64]^inData[67]^inData[68]^inData[72]^inData[74]^inData[75]^inData[76]^inData[78]^inData[79]^inData[80]^inData[81]^inData[82]^inData[84]^inData[87]^inData[90]^inData[95]^inData[96]^inData[101]^inData[104]^inData[105]^inData[107]^inData[111]^inData[114]^inData[115]^inData[117]^inData[119]^inData[121]^inData[122]^inData[123]^inData[124]^inData[125];
crc[ 8] <= inData[1]^inData[3]^inData[10]^inData[13]^inData[15]^inData[16]^inData[17]^inData[18]^inData[19]^inData[20]^inData[21]^inData[22]^inData[25]^inData[27]^inData[28]^inData[29]^inData[30]^inData[31]^inData[32]^inData[33]^inData[34]^inData[36]^inData[38]^inData[45]^inData[48]^inData[50]^inData[53]^inData[59]^inData[60]^inData[62]^inData[63]^inData[65]^inData[68]^inData[69]^inData[73]^inData[75]^inData[76]^inData[77]^inData[79]^inData[80]^inData[81]^inData[82]^inData[83]^inData[85]^inData[88]^inData[91]^inData[96]^inData[97]^inData[102]^inData[105]^inData[106]^inData[108]^inData[112]^inData[115]^inData[116]^inData[118]^inData[120]^inData[122]^inData[123]^inData[124]^inData[125]^inData[126];
crc[ 7] <= inData[0]^inData[2]^inData[4]^inData[11]^inData[14]^inData[16]^inData[17]^inData[18]^inData[19]^inData[20]^inData[21]^inData[22]^inData[23]^inData[26]^inData[28]^inData[29]^inData[30]^inData[31]^inData[32]^inData[33]^inData[34]^inData[35]^inData[37]^inData[39]^inData[46]^inData[49]^inData[51]^inData[54]^inData[60]^inData[61]^inData[63]^inData[64]^inData[66]^inData[69]^inData[70]^inData[74]^inData[76]^inData[77]^inData[78]^inData[80]^inData[81]^inData[82]^inData[83]^inData[84]^inData[86]^inData[89]^inData[92]^inData[97]^inData[98]^inData[103]^inData[106]^inData[107]^inData[109]^inData[113]^inData[116]^inData[117]^inData[119]^inData[121]^inData[123]^inData[124]^inData[125]^inData[126]^inData[127];
crc[ 6] <= inData[0]^inData[1]^inData[2]^inData[3]^inData[10]^inData[13]^inData[14]^inData[15]^inData[16]^inData[18]^inData[19]^inData[22]^inData[24]^inData[25]^inData[26]^inData[27]^inData[28]^inData[29]^inData[30]^inData[31]^inData[33]^inData[35]^inData[38]^inData[41]^inData[43]^inData[45]^inData[49]^inData[50]^inData[51]^inData[52]^inData[53]^inData[54]^inData[55]^inData[57]^inData[58]^inData[60]^inData[62]^inData[66]^inData[67]^inData[70]^inData[74]^inData[75]^inData[76]^inData[79]^inData[80]^inData[83]^inData[85]^inData[87]^inData[90]^inData[92]^inData[94]^inData[98]^inData[99]^inData[100]^inData[102]^inData[103]^inData[105]^inData[106]^inData[107]^inData[110]^inData[111]^inData[114]^inData[115]^inData[116]^inData[117]^inData[118]^inData[119]^inData[120]^inData[121]^inData[124]^inData[127];
crc[ 5] <= inData[1]^inData[3]^inData[4]^inData[5]^inData[10]^inData[11]^inData[12]^inData[13]^inData[15]^inData[19]^inData[21]^inData[27]^inData[29]^inData[30]^inData[31]^inData[39]^inData[40]^inData[41]^inData[42]^inData[43]^inData[44]^inData[45]^inData[46]^inData[47]^inData[49]^inData[50]^inData[52]^inData[55]^inData[56]^inData[57]^inData[59]^inData[60]^inData[63]^inData[64]^inData[65]^inData[66]^inData[67]^inData[68]^inData[74]^inData[75]^inData[78]^inData[82]^inData[86]^inData[88]^inData[91]^inData[92]^inData[94]^inData[95]^inData[99]^inData[101]^inData[102]^inData[105]^inData[107]^inData[112]^inData[117]^inData[118]^inData[120]^inData[126];
crc[ 4] <= inData[0]^inData[2]^inData[4]^inData[5]^inData[6]^inData[11]^inData[12]^inData[13]^inData[14]^inData[16]^inData[20]^inData[22]^inData[28]^inData[30]^inData[31]^inData[32]^inData[40]^inData[41]^inData[42]^inData[43]^inData[44]^inData[45]^inData[46]^inData[47]^inData[48]^inData[50]^inData[51]^inData[53]^inData[56]^inData[57]^inData[58]^inData[60]^inData[61]^inData[64]^inData[65]^inData[66]^inData[67]^inData[68]^inData[69]^inData[75]^inData[76]^inData[79]^inData[83]^inData[87]^inData[89]^inData[92]^inData[93]^inData[95]^inData[96]^inData[100]^inData[102]^inData[103]^inData[106]^inData[108]^inData[113]^inData[118]^inData[119]^inData[121]^inData[127];
crc[ 3] <= inData[0]^inData[1]^inData[2]^inData[3]^inData[6]^inData[7]^inData[10]^inData[15]^inData[16]^inData[20]^inData[25]^inData[26]^inData[28]^inData[29]^inData[31]^inData[33]^inData[34]^inData[36]^inData[40]^inData[42]^inData[44]^inData[46]^inData[48]^inData[52]^inData[53]^inData[59]^inData[60]^inData[62]^inData[64]^inData[67]^inData[68]^inData[69]^inData[70]^inData[71]^inData[74]^inData[78]^inData[81]^inData[82]^inData[88]^inData[90]^inData[92]^inData[96]^inData[97]^inData[100]^inData[101]^inData[102]^inData[105]^inData[106]^inData[107]^inData[108]^inData[109]^inData[111]^inData[114]^inData[115]^inData[116]^inData[120]^inData[121]^inData[125]^inData[126];
crc[ 2] <= inData[0]^inData[1]^inData[2]^inData[3]^inData[4]^inData[7]^inData[8]^inData[11]^inData[16]^inData[17]^inData[21]^inData[26]^inData[27]^inData[29]^inData[30]^inData[32]^inData[34]^inData[35]^inData[37]^inData[41]^inData[43]^inData[45]^inData[47]^inData[49]^inData[53]^inData[54]^inData[60]^inData[61]^inData[63]^inData[65]^inData[68]^inData[69]^inData[70]^inData[71]^inData[72]^inData[75]^inData[79]^inData[82]^inData[83]^inData[89]^inData[91]^inData[93]^inData[97]^inData[98]^inData[101]^inData[102]^inData[103]^inData[106]^inData[107]^inData[108]^inData[109]^inData[110]^inData[112]^inData[115]^inData[116]^inData[117]^inData[121]^inData[122]^inData[126]^inData[127];
crc[ 1] <= inData[0]^inData[1]^inData[3]^inData[4]^inData[8]^inData[9]^inData[10]^inData[13]^inData[14]^inData[16]^inData[18]^inData[20]^inData[21]^inData[22]^inData[23]^inData[25]^inData[26]^inData[27]^inData[30]^inData[31]^inData[32]^inData[33]^inData[34]^inData[35]^inData[38]^inData[40]^inData[41]^inData[42]^inData[43]^inData[44]^inData[45]^inData[46]^inData[47]^inData[48]^inData[49]^inData[50]^inData[51]^inData[53]^inData[55]^inData[57]^inData[58]^inData[60]^inData[62]^inData[65]^inData[69]^inData[70]^inData[72]^inData[73]^inData[74]^inData[77]^inData[78]^inData[81]^inData[82]^inData[83]^inData[90]^inData[93]^inData[98]^inData[99]^inData[100]^inData[105]^inData[106]^inData[107]^inData[109]^inData[110]^inData[113]^inData[115]^inData[117]^inData[118]^inData[119]^inData[121]^inData[123]^inData[125]^inData[126]^inData[127];
crc[ 0] <= inData[1]^inData[4]^inData[9]^inData[11]^inData[12]^inData[13]^inData[15]^inData[16]^inData[19]^inData[20]^inData[22]^inData[24]^inData[25]^inData[27]^inData[31]^inData[33]^inData[35]^inData[39]^inData[40]^inData[42]^inData[44]^inData[46]^inData[48]^inData[50]^inData[52]^inData[53]^inData[56]^inData[57]^inData[59]^inData[60]^inData[63]^inData[64]^inData[65]^inData[70]^inData[73]^inData[75]^inData[76]^inData[77]^inData[79]^inData[80]^inData[81]^inData[83]^inData[91]^inData[92]^inData[93]^inData[99]^inData[101]^inData[102]^inData[103]^inData[104]^inData[105]^inData[107]^inData[110]^inData[114]^inData[115]^inData[118]^inData[120]^inData[121]^inData[124]^inData[125]^inData[127];
end
end
 
endmodule
/openhmc/trunk/openHMC/rtl/hmc_controller/rx/rx_descrambler.v
0,0 → 1,147
/*
* .--------------. .----------------. .------------.
* | .------------. | .--------------. | .----------. |
* | | ____ ____ | | | ____ ____ | | | ______ | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| |
* | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' |
* '--------------' '----------------' '------------'
*
* openHMC - An Open Source Hybrid Memory Cube Controller
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg
* www.ziti.uni-heidelberg.de
* B6, 26
* 68159 Mannheim
* Germany
*
* Contact: openhmc@ziti.uni-heidelberg.de
* http://ra.ziti.uni-heidelberg.de/openhmc
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This source file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* 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/>.
*
*
* Module name: rx_descrambler
*
* Scrambler Logic (HMC Spec version 1.0)
* This module implements a parallel scrambler based on the
* polynomial 1+ x^(-14) + x^(-15).
*
* Such Scrambler is typically shown as a 15 bit Linear Feedback Shift Register
* (LFSR) with bits shifting from register 1 on the left to register 15 on the
* right, with register 14 and 15 combining to shift into register 1.
* The HMC Serializer outputs data[0] first from parallel tx data[n:0],
* so if data[n:0] is to be bitwise scrambled with LFSR[n:0], we need the LFSR
* to shift from n -> 0, the opposite direction from the typical illustration.
* This implementation shifts data from LFSR[14] on the left to LFSR[0] on the
* right, with LFSR[1] and [0] combining to shift into LFSR[14]. This way
* LFSR[14:0] can bitwise scramble data[14:0] and be compatible with serializ-
* ation that shifts out on the data[0] side.
* Put otherwise: Polynomial 1+ x^(-14) + x^(-15) is equiv to
* x^15 + x^1 + x^0
*
* This parallelized version calculates the next DWIDTH steps of values for
* the LFSR. These bits are used to scramble the parallel input, and to
* choose the next value of lfsr (lfsr_steps[DWIDTH-1]).
*
* This is the descrambler. It is self-seeding. When lock is asserted it has
* successfully found the correct value for the LFSR. It is only implemented
* for DWIDTH > 14.
*
* Since we know that scrambled zeros are being translated, we can calculate
* what the seed will be in the next timestep. In order to simplify the
* calculation, we assume that the top bit is a one. That has the happy side-
* effect of letting us know that the seed didn't get stuck at all zeros.
*
* After the scrambler is locked, the input word may need to be aligned. The
* bit_slip input allows the scrambler to shift one bit with the serializer
* to keep the scrambler in sync.
*/
 
`default_nettype none
 
module rx_descrambler #(
parameter DWIDTH=16
)
(
input wire clk,
input wire res_n,
input wire bit_slip, // keep scrambler in sync with serializer
output reg locked,
input wire [DWIDTH-1:0] data_in,
output reg [DWIDTH-1:0] data_out
);
 
reg [14:0] lfsr; // LINEAR FEEDBACK SHIFT REGISTER
wire [14:0] lfsr_steps [DWIDTH-1:0]; // LFSR values for serial time steps
wire [14:0] calculated_seed;
wire [DWIDTH-1:0] data_out_tmp;
 
// SEQUENTIAL PROCESS
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if (!res_n) begin
locked <= 1'b0;
lfsr <= 15'h0;
data_out <= {DWIDTH {1'b0}};
end else begin
 
data_out <= data_out_tmp;
 
if (!locked && |data_in) begin
lfsr <= calculated_seed;
// Locked when the calculated seeds match
if (calculated_seed == lfsr_steps[DWIDTH-1]) begin
locked <= 1'b1;
end
end else begin
if (bit_slip) // lfsr_steps[DWIDTH]
lfsr[14:0] <= { (lfsr_steps[DWIDTH-1][1] ^ lfsr_steps[DWIDTH-1][0]) , lfsr_steps[DWIDTH-1][14:1] };
else
lfsr[14:0] <= lfsr_steps[DWIDTH-1];
end
end
end // serial shift right with left input
 
// SCRAMBLE
 
genvar j;
generate
localparam OFFSET = DWIDTH-15; // It breaks here if DWIDTH < 15
assign calculated_seed[14] = 1'b1; // Guess the top bit is 1
 
// data_in is the past state of the LFSR, so we can figure out
// the current value using a loop.
 
for(j = 0; j < 14; j = j + 1) begin : seed_calc
assign calculated_seed[j] = data_in[j+OFFSET] ^ data_in[j+OFFSET+1];
end
 
assign data_out_tmp [0] = data_in[0] ^ lfsr[0]; // single bit scrambled
assign lfsr_steps[0] = { (lfsr[1] ^ lfsr[0]) , lfsr[14:1] }; // lfsr at next bit clock
for(j = 1; j < DWIDTH; j = j + 1) begin : scrambler_gen
assign data_out_tmp[j] = data_in[j] ^ lfsr_steps[j-1][0];
assign lfsr_steps[j] = { (lfsr_steps[j-1][1] ^ lfsr_steps[j-1][0]) , lfsr_steps[j-1][14:1] };
end
endgenerate
 
endmodule
 
`default_nettype wire
 
/openhmc/trunk/openHMC/rtl/hmc_controller/rx/rx_lane_logic.v
0,0 → 1,112
/*
* .--------------. .----------------. .------------.
* | .------------. | .--------------. | .----------. |
* | | ____ ____ | | | ____ ____ | | | ______ | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| |
* | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' |
* '--------------' '----------------' '------------'
*
* openHMC - An Open Source Hybrid Memory Cube Controller
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg
* www.ziti.uni-heidelberg.de
* B6, 26
* 68159 Mannheim
* Germany
*
* Contact: openhmc@ziti.uni-heidelberg.de
* http://ra.ziti.uni-heidelberg.de/openhmc
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This source file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* 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/>.
*
*
* Module name: rx_lane_logic
*
*/
 
`default_nettype none
 
module rx_lane_logic #(
parameter DWIDTH = 512,
parameter NUM_LANES = 8,
parameter LANE_DWIDTH = (DWIDTH/NUM_LANES)
) (
 
//----------------------------------
//----SYSTEM INTERFACE
//----------------------------------
input wire clk,
input wire res_n,
 
//----------------------------------
//----CONNECT
//----------------------------------
input wire [LANE_DWIDTH-1:0] scrambled_data_in,
input wire bit_slip, //bit slip per lane
input wire lane_polarity,
output wire [LANE_DWIDTH-1:0] descrambled_data_out,
output wire descrambler_locked,
input wire descrambler_disable
 
);
 
reg [LANE_DWIDTH-1:0] scrambled_data_in_reg;
 
wire [LANE_DWIDTH-1:0] descrambled_data_out_tmp;
assign descrambled_data_out = descrambler_disable ? scrambled_data_in_reg : descrambled_data_out_tmp;
 
wire descrambler_locked_tmp;
assign descrambler_locked = descrambler_disable ? 1'b1 : descrambler_locked_tmp;
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------ACTUAL LOGIC STARTS HERE--------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
 
if(!res_n) begin
scrambled_data_in_reg <= {LANE_DWIDTH{1'b0}};
end
else begin
scrambled_data_in_reg <= scrambled_data_in^{LANE_DWIDTH{lane_polarity}};
end
end
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------INSTANTIATIONS HERE-------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
 
//Descrambler Init
rx_descrambler #(
.DWIDTH(LANE_DWIDTH)
) descrambler_I (
.clk(clk),
.res_n(res_n),
.bit_slip(bit_slip),
.locked(descrambler_locked_tmp),
.data_in(scrambled_data_in_reg),
.data_out(descrambled_data_out_tmp)
);
 
endmodule
`default_nettype wire
/openhmc/trunk/openHMC/rtl/hmc_controller/rx/rx_crc_compare.v
0,0 → 1,521
/*
* .--------------. .----------------. .------------.
* | .------------. | .--------------. | .----------. |
* | | ____ ____ | | | ____ ____ | | | ______ | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| |
* | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' |
* '--------------' '----------------' '------------'
*
* openHMC - An Open Source Hybrid Memory Cube Controller
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg
* www.ziti.uni-heidelberg.de
* B6, 26
* 68159 Mannheim
* Germany
*
* Contact: openhmc@ziti.uni-heidelberg.de
* http://ra.ziti.uni-heidelberg.de/openhmc
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This source file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* 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/>.
*
*
* Module name: rx_crc_compare
*
*/
 
`default_nettype none
 
module rx_crc_compare #(
parameter LOG_FPW = 2,
parameter FPW = 4,
parameter DWIDTH = 512
) (
 
//----------------------------------
//----SYSTEM INTERFACE
//----------------------------------
input wire clk,
input wire res_n,
 
//----------------------------------
//----Input data
//----------------------------------
input wire [FPW-1:0] d_in_hdr,
input wire [FPW-1:0] d_in_tail,
input wire [FPW-1:0] d_in_valid,
input wire [DWIDTH-1:0] d_in_data,
input wire [(FPW*4)-1:0] d_in_lng,
 
//----------------------------------
//----Outputs
//----------------------------------
output wire [DWIDTH-1:0] d_out_data,
output reg [FPW-1:0] d_out_hdr,
output reg [FPW-1:0] d_out_tail,
output reg [FPW-1:0] d_out_valid,
output reg [FPW-1:0] d_out_error,
output reg [FPW-1:0] d_out_poisoned,
output reg [FPW-1:0] d_out_rtc,
output reg [FPW-1:0] d_out_flow
 
);
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------WIRING AND SIGNAL STUFF---------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
 
`include "hmc_field_functions.h"
//------------------------------------------------------------------------------------General Assignments
integer i_f; //counts to FPW
integer i_f2; //counts to FPW inside another i_f loop
integer i_f3; //counts to FPW inside another i_f loop
integer i_c; //depth of the crc data pipeline
 
genvar f, f2;
 
localparam CMD_TRET = 6'b000010;
 
//------------------------------------------------------------------------------------Local params for parameterization
localparam CRC_WIDTH = 32;
localparam CRC_DATA_PIPE_DEPTH = 3;
localparam NUM_32BIT_CHUNKS = FPW*FPW;
 
//------------------------------------------------------------------------------------Split input data into FLITs
wire [128:0] d_in_flit [FPW-1:0];
wire [127:0] d_in_flit_removed_crc [FPW-1:0];
generate
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_removed_crc[f] = d_in_tail[f] ? d_in_flit[f][95:0] : d_in_flit[f];
end
endgenerate
 
reg [128-1:0] d_in_flit_dly [FPW-1:0];
reg [DWIDTH-1:0] d_in_data_dly;
reg [FPW-1:0] d_in_hdr_dly;
reg [FPW-1:0] d_in_tail_dly;
reg [FPW-1:0] d_in_valid_dly;
reg [LOG_FPW-1:0] d_in_flit_target_crc [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];
generate
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] ;
end
endgenerate
 
//------------------------------------------------------------------------------------CRC Target Assignment
reg swap_crc;
 
//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_tail1 [FPW-1:0];
reg [LOG_FPW-1:0] target_crc_per_tail2 [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_temp;
 
//------------------------------------------------------------------------------------CRC Modules Input stage
wire [CRC_WIDTH-1:0] crc_init_out [FPW-1:0];
reg [CRC_WIDTH-1:0] crc_accu_in [(FPW*FPW)-1:0];
reg [FPW-1:0] crc_accu_in_valid [FPW-1:0];
reg [FPW-1:0] crc_accu_clear;
wire [CRC_WIDTH-1:0] crc_per_flit [FPW-1:0];
 
 
//------------------------------------------------------------------------------------Inter CRC stage
reg [3:0] payload_remain [FPW-1:0];
 
wire [(FPW*CRC_WIDTH)-1:0] crc_accu_in_combined [FPW-1:0];
generate
for(f=0;f<FPW;f=f+1) begin
for(f2=0;f2<FPW;f2=f2+1) begin
assign crc_accu_in_combined[f][(f2*CRC_WIDTH)+CRC_WIDTH-1:(f2*CRC_WIDTH)] = crc_accu_in[(f*FPW)+f2];
end
end
endgenerate
 
 
//------------------------------------------------------------------------------------Data Pipeline signals
reg [DWIDTH-1:0] crc_data_pipe_in_data [CRC_DATA_PIPE_DEPTH-1:0];
reg [FPW-1:0] crc_data_pipe_in_hdr [CRC_DATA_PIPE_DEPTH-1:0];
reg [FPW-1:0] crc_data_pipe_in_tail [CRC_DATA_PIPE_DEPTH-1:0];
reg [FPW-1:0] crc_data_pipe_in_valid [CRC_DATA_PIPE_DEPTH-1:0];
wire [128-1:0] crc_data_pipe_out_data_flit [FPW-1:0];
 
generate
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[CRC_DATA_PIPE_DEPTH-1][(f*128)+128-1:f*128];
end
endgenerate
 
 
reg [128-1:0] data_rdy_flit [FPW-1:0];
generate
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];
end
endgenerate
 
//==================================================================================
//---------------------------------Retrieve the lengths to invalide FLITs
//==================================================================================
always @(*) begin
//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
 
target_crc_comb = target_crc_temp;
 
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
 
if(d_in_hdr_dly[i_f]) begin
target_crc_comb = d_in_flit_target_crc[i_f];
end
 
if(d_in_tail_dly[i_f]) begin
target_crc_per_tail_comb[i_f] = target_crc_comb;
end else begin
target_crc_per_tail_comb[i_f] = {4{1'b0}};
end
 
end
end
 
//Register combinational values
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
target_crc_per_tail[i_f] <= 0;
end
target_crc_temp <= {4{1'b0}};
end else 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];
end
target_crc_temp <= target_crc_comb;
end
end
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------LOGIC STARTS HERE---------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
//====================================================================
//---------------------------------Assign input data stream to target CRCs
//====================================================================
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) 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}};
end
swap_crc <= 1'b0;
end else 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}};
end
 
//Reset if seen a tail
if(|d_in_tail) begin
swap_crc <= 1'b0;
end
 
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
if(d_in_hdr[i_f])begin
if(i_f+lng(d_in_flit[i_f])>FPW) begin
//If the current packet spreads over multiple cycles
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
d_in_flit_target_crc[i_f] <= 3'h0;
end else begin
d_in_flit_target_crc[i_f] <= FPW-1'b1;
swap_crc <= 1'b1;
end
 
end else begin
 
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
//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
d_in_flit_target_crc[i_f] <= i_f-1;
end
end
end
end
 
end
end
 
//Register input values to be used in CRC assignment logic after crc init stage
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
d_in_flit_dly[i_f] <= {128{1'b0}};
d_in_lng_per_flit_dly[i_f] <= 4'h0;
end
d_in_data_dly <= {DWIDTH{1'b0}};
d_in_hdr_dly <= {FPW{1'b0}};
d_in_tail_dly <= {FPW{1'b0}};
d_in_valid_dly <= {FPW{1'b0}};
end else begin
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
d_in_flit_dly[i_f] <= d_in_flit[i_f];
d_in_lng_per_flit_dly[i_f] <= d_in_lng_per_flit[i_f];
end
d_in_data_dly <= d_in_data;
d_in_hdr_dly <= d_in_hdr;
d_in_tail_dly <= d_in_tail;
d_in_valid_dly <= d_in_valid;
end
end
 
//====================================================================
//---------------------------------Inter CRC stage, CRC assignment Logic
//====================================================================
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
crc_accu_clear <= 1'b0;
for(i_f=0;i_f<NUM_32BIT_CHUNKS;i_f=i_f+1)begin
crc_accu_in[i_f] <= {CRC_WIDTH{1'b0}};
end
 
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
crc_accu_in_valid[i_f] <= {CRC_WIDTH{1'b0}};
payload_remain[i_f] <= 4'h0;
end
 
end else begin
crc_accu_clear <= 1'b0;
 
for(i_f=0;i_f<NUM_32BIT_CHUNKS;i_f=i_f+1)begin
crc_accu_in[i_f] <= {CRC_WIDTH{1'b0}};
end
 
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
crc_accu_in_valid[i_f] <= {FPW{1'b0}};
end
 
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
//First go through accu crcs
 
if(|payload_remain[i_f]) begin
for(i_f2=0;i_f2<FPW;i_f2=i_f2+1)begin
crc_accu_in[(i_f*FPW)+i_f2] <= crc_init_out[i_f2];
end
 
if(payload_remain[i_f] > FPW) begin
crc_accu_in_valid[i_f] <= {FPW{1'b1}};
payload_remain[i_f] <= payload_remain[i_f]-FPW;
end else begin
crc_accu_in_valid[i_f] <= {FPW{1'b1}} >> (FPW-payload_remain[i_f]);
payload_remain[i_f] <= 4'h0;
end
end
 
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
//Then go through all input crcs from the init crc and find the crc's that must be assigned to the currently selected crc
 
for(i_f3=i_f2;i_f3<FPW;i_f3=i_f3+1)begin
crc_accu_in[(i_f*FPW)+i_f3-i_f2] <= crc_init_out[i_f3];
end
 
crc_accu_clear[i_f] <= 1'b1;
 
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;
crc_accu_in_valid[i_f] <= {FPW{1'b1}} >> i_f2;
end else begin
crc_accu_in_valid[i_f] <= ({FPW{1'b1}} >> (FPW - i_f2 - d_in_lng_per_flit_dly[i_f2]) )
>> i_f2;
end
end
 
end
end
end
end
 
//====================================================================
//---------------------------------Constant propagation of the data pipeline
//====================================================================
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
for(i_c=0;i_c<CRC_DATA_PIPE_DEPTH;i_c=i_c+1)begin
crc_data_pipe_in_data[i_c] <= {DWIDTH{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_valid[i_c] <= {FPW{1'b0}};
end
 
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
target_crc_per_tail1[i_f] <= 3'h0;
target_crc_per_tail2[i_f] <= 3'h0;
end
end else 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_tail2[i_f] <= target_crc_per_tail1[i_f];
end
 
//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_tail[0] <= d_in_tail_dly;
crc_data_pipe_in_valid[0] <= d_in_valid_dly;
 
//Data Pipeline propagation
for(i_c=0;i_c<(CRC_DATA_PIPE_DEPTH-1);i_c=i_c+1)begin
crc_data_pipe_in_data[i_c+1] <= crc_data_pipe_in_data[i_c];
crc_data_pipe_in_tail[i_c+1] <= crc_data_pipe_in_tail[i_c];
crc_data_pipe_in_hdr[i_c+1] <= crc_data_pipe_in_hdr[i_c];
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
 
//====================================================================
//---------------------------------At the end of the data pipeline get and compare the CRCs
//====================================================================
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
 
//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_poisoned <= {FPW{1'b0}};
d_out_rtc <= {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
 
d_out_rtc <= {FPW{1'b0}};
d_out_error <= {FPW{1'b0}};
d_out_poisoned <= {FPW{1'b0}};
d_out_flow <= {FPW{1'b0}};
 
//Propagate
d_out_hdr <= crc_data_pipe_in_hdr[CRC_DATA_PIPE_DEPTH-1];
d_out_tail <= crc_data_pipe_in_tail[CRC_DATA_PIPE_DEPTH-1];
d_out_valid <= crc_data_pipe_in_valid[CRC_DATA_PIPE_DEPTH-1];
 
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
 
//Propagate data
data_rdy_flit[i_f] <= crc_data_pipe_out_data_flit[i_f];
 
if(crc_data_pipe_in_tail[CRC_DATA_PIPE_DEPTH-1][i_f])begin
//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_tail2[i_f]]) begin
//Poisoned
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_tail2[i_f]]) begin
//Error
d_out_error[i_f] <= 1'b1;
end
 
//Add the return token count indicator when the packet has rtc
if(!crc_data_pipe_in_hdr[CRC_DATA_PIPE_DEPTH-1][i_f]) begin
//Multi-FLIT packets always have a valid RTC
d_out_rtc[i_f] <= 1'b1;
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
//All non-flow packets have a valid RTC
d_out_rtc[i_f] <= 1'b1;
end
if(is_flow(crc_data_pipe_out_data_flit[i_f])) begin
//Set the flow packet indicator
d_out_flow[i_f] <= 1'b1;
end
end
 
end
end
end
end
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------INSTANTIATIONS HERE-------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
//Init CRC: Calculate the remainders of each input FLIT individually
generate
for(f=0;f<FPW;f=f+1) begin : crc_init_gen
crc_128_init crc_init_I
(
.clk(clk),
.res_n(res_n),
.inData(d_in_flit_removed_crc[f]),
.crc(crc_init_out[f])
);
end
endgenerate
 
//Calculate the actual CRC over all valid remainders
generate
for(f=0;f<FPW;f=f+1) begin : crc_accu_gen
crc_accu #(
.FPW(FPW)
)
crc_accu_I
(
.clk(clk),
.res_n(res_n),
.clear(crc_accu_clear[f]),
.d_in(crc_accu_in_combined[f]),
.valid(crc_accu_in_valid[f]),
.crc_out(crc_per_flit[f])
);
end
endgenerate
 
endmodule
`default_nettype wire
/openhmc/trunk/openHMC/rtl/hmc_controller/rx/rx_link.v
0,0 → 1,1333
/*
* .--------------. .----------------. .------------.
* | .------------. | .--------------. | .----------. |
* | | ____ ____ | | | ____ ____ | | | ______ | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| |
* | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' |
* '--------------' '----------------' '------------'
*
* openHMC - An Open Source Hybrid Memory Cube Controller
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg
* www.ziti.uni-heidelberg.de
* B6, 26
* 68159 Mannheim
* Germany
*
* Contact: openhmc@ziti.uni-heidelberg.de
* http://ra.ziti.uni-heidelberg.de/openhmc
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This source file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* 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/>.
*
*
* Module name: rx_link
*
*/
 
`default_nettype none
 
module rx_link #(
parameter LOG_FPW = 2,
parameter FPW = 4,
parameter DWIDTH = 512,
parameter LOG_NUM_LANES = 3,
parameter NUM_LANES = 8,
parameter LOG_MAX_RTC = 8,
parameter HMC_PTR_SIZE = 8,
parameter HMC_RF_RWIDTH = 64
) (
 
//----------------------------------
//----SYSTEM INTERFACE
//----------------------------------
input wire clk,
input wire res_n,
 
//----------------------------------
//----TO HMC PHY
//----------------------------------
input wire [DWIDTH-1:0] phy_scrambled_data_in,
output reg [NUM_LANES-1:0] init_bit_slip, //bit slip per lane
 
//----------------------------------
//----TO RX HTAX FIFO
//----------------------------------
output reg [DWIDTH-1:0] d_out_fifo_data,
input wire d_out_fifo_full,
input wire d_out_fifo_a_full,
output reg d_out_fifo_shift_in,
output reg [3*FPW-1:0] d_out_fifo_ctrl,
 
 
//----------------------------------
//----TO TX Block
//----------------------------------
output reg tx_link_retry,
output reg tx_error_abort_mode,
output reg tx_error_abort_mode_cleared,
output reg [7:0] tx_hmc_frp,
output reg [7:0] tx_rrp,
output reg [7:0] tx_returned_tokens,
output reg [LOG_FPW:0] tx_hmc_tokens_to_be_returned,
 
//----------------------------------
//----RF
//----------------------------------
//Monitoring 1-cycle set to increment
output reg [HMC_RF_RWIDTH-1:0] rf_cnt_poisoned,
output reg [HMC_RF_RWIDTH-1:0] rf_cnt_rsp,
//Status
output reg [1:0] rf_link_status,
output reg [2:0] rf_hmc_init_status,
input wire rf_tx_sends_ts1,
input wire rf_hmc_sleep,
//Init Status
output wire [NUM_LANES-1:0] rf_descrambler_part_aligned,
output wire [NUM_LANES-1:0] rf_descrambler_aligned,
output wire rf_all_descramblers_aligned,
//Control
input wire [7:0] rf_bit_slip_time,
input wire rf_hmc_init_cont_set,
output reg [NUM_LANES-1:0] rf_lane_polarity,
input wire rf_scrambler_disable,
output reg rf_lane_reversal_detected,
output reg [NUM_LANES-1:0] rf_descramblers_locked,
input wire [4:0] rf_irtry_received_threshold
 
);
`include "hmc_field_functions.h"
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------WIRING AND SIGNAL STUFF---------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
 
//------------------------------------------------------------------------------------Some general things
//Link state
localparam HMC_DOWN = 3'b000;
localparam HMC_NULL = 3'b001;
localparam HMC_TS1 = 3'b010;
localparam HMC_UP = 3'b100;
 
//Commands
localparam CMD_NULL = 3'b000;
localparam CMD_PRET = 3'b001;
localparam CMD_TRET = 3'b010;
localparam CMD_IRTRY = 3'b011;
localparam CMD_W_RSP = 3'b001;
localparam CMD_FLOW = 3'b000;
localparam CMD_RSP = 3'b111;
 
//Other helpful defines
localparam WIDTH_PER_LANE = (DWIDTH/NUM_LANES);
 
//16 bits is a ts1, so the init seq number is incremented according to the lane size
localparam INIT_SEQ_INC_PER_CYCLE = WIDTH_PER_LANE/16;
 
//MISC
integer i_f; //counts to FPW
integer i_c; //counts to CYCLES_TO_COMPLETE_FULL_PACKET
 
genvar f; //Counts to FPW
genvar n; //Counts to NUM_LANES
genvar w; //Counts to WIDTH_PER_LANE
 
//------------------------------------------------------------------------------------DESCRAMBLER AND DATA ORDERING
reg [NUM_LANES-1:0] descrambler_part_aligned;
reg [NUM_LANES-1:0] descrambler_aligned;
assign rf_descrambler_part_aligned = descrambler_part_aligned;
assign rf_descrambler_aligned = descrambler_aligned;
 
//DATA and REORDERING: Pipeline d_in for timing closure
wire [WIDTH_PER_LANE-1:0] descrambled_data_on_lane [NUM_LANES-1:0];
reg [DWIDTH-1:0] d_in;
reg [DWIDTH-1:0] d_in_init;
wire [DWIDTH-1:0] d_in_temp;
wire [128-1:0] d_in_flit [FPW-1:0];
wire [128-1:0] d_in_flit_init [FPW-1:0];
 
//Valid FLIT sources. A FLIT is valid when the command is not zero
wire [FPW-1:0] valid_flit_src; //bit0 = flit0, ...
wire [FPW-1:0] valid_flit_src_init;//bit0 = flit0, ...
 
generate
 
//-- Apply lane reversal if detected
for(n = 0; n < NUM_LANES; n = n + 1) begin : apply_lane_reversal
for(w = 0; w < WIDTH_PER_LANE; w = w + 1) begin
assign d_in_temp[w*NUM_LANES+n] = rf_lane_reversal_detected ? descrambled_data_on_lane[NUM_LANES-1-n][w] : descrambled_data_on_lane[n][w];
end
end
 
 
for(f = 0; f < FPW; f = f + 1) begin : reorder_input_data
//-- Reorder the descrambled data for the init sequence
assign d_in_flit_init[f] = d_in_init[128-1+(f*128):f*128];
//-- Reorder the descrambled data to FLITs
assign d_in_flit[f] = d_in[128-1+(f*128):f*128];
//-- Generate valid flit positions for the init sequence
assign valid_flit_src_init[f] = (d_in_flit_init[f] == 0) ? 1'b0 : 1'b1;
//-- Generate valid flit positions for the init sequence
assign valid_flit_src[f] = (cmd(d_in_flit[f]) == 0) ? 1'b0 : 1'b1;
end
 
endgenerate
 
 
//------------------------------------------------------------------------------------INIT
localparam LINK_DOWN = 2'b00;
localparam LINK_INIT = 2'b01;
localparam LINK_UP = 2'b10;
 
reg [7:0] init_bit_slip_cnt;
reg [4:0] init_wait_time;
wire [NUM_LANES-1:0] init_descrambler_locked; //locked from the descrambler
wire link_is_up;
reg [3:0] init_tmp_seq;
 
assign link_is_up = rf_link_status[1];
assign rf_all_descramblers_aligned = &descrambler_aligned;
 
//--------------TS1 recognition
localparam ts1_independent_portion = {4'hF,4'h0};
localparam ts1_lanex_portion = {4'h5};
localparam ts1_lane7or15_portion = 4'hc;
localparam ts1_lane0_portion = 4'h3;
 
localparam ts1_per_cycle_and_lane = DWIDTH/NUM_LANES/16;
 
wire [NUM_LANES-1:0] init_lane_has_correct_ts1;
wire [ts1_per_cycle_and_lane-1:0] init_lane_has_correct_ts1_vec [NUM_LANES-1:0];
 
genvar t;
generate
//Make sure that the lanes have valid ts1 sequences throughout the entire data stream
for(n=0;n<NUM_LANES;n=n+1) begin : lane_has_correct_ts1_gen
 
assign init_lane_has_correct_ts1[n] = &init_lane_has_correct_ts1_vec[n];
 
for(t=0;t<ts1_per_cycle_and_lane;t=t+1) begin
if(n==0 || n==NUM_LANES-1) begin
assign init_lane_has_correct_ts1_vec[n][t] = (descrambled_data_on_lane[n][(t*16)+16-1:(t*16)+4] == {ts1_independent_portion,ts1_lane7or15_portion})
||
(descrambled_data_on_lane[n][(t*16)+16-1:(t*16)+4] == {ts1_independent_portion,ts1_lane0_portion});
end else begin
assign init_lane_has_correct_ts1_vec[n][t] = (descrambled_data_on_lane[n][(t*16)+16-1:(t*16)+4] == {ts1_independent_portion,ts1_lanex_portion});
end
end
end
endgenerate
 
//--------------Align the lanes, scan for the ts1 seq
reg [LOG_NUM_LANES-1:0] init_lane_cnt;
wire [3:0] init_seq_diff;
 
//If one of the descramblers is already partially aligned search for other lanes with their ts1 sequence number close this lane.
assign init_seq_diff = |descrambler_part_aligned ? (descrambled_data_on_lane[init_lane_cnt][3:0] - init_tmp_seq) : 0;
 
//------------------------------------------------------------------------------------Input Stage: Scan for Packets, Headers, Tails ...
reg [DWIDTH-1:0] data2crc;
reg [FPW-1:0] data2crc_hdr;
reg [FPW-1:0] data2crc_tail;
reg [FPW-1:0] data2crc_valid;
wire [(FPW*4)-1:0] data2crc_lng;
reg [3:0] data2crc_lng_per_flit [FPW-1:0];
reg [3:0] data2crc_payload_remain;
 
reg [FPW-1:0] data2crc_hdr_comb;
reg [FPW-1:0] data2crc_tail_comb;
reg [FPW-1:0] data2crc_valid_comb;
reg [3:0] data2crc_lng_per_flit_comb [FPW-1:0];
reg [3:0] data2crc_payload_remain_comb;
 
generate
for(f = 0; f < (FPW); f = f + 1) begin
assign data2crc_lng[(f*4)+4-1:(f*4)] = data2crc_lng_per_flit[f];
end
endgenerate
 
//------------------------------------------------------------------------------------CRC
wire [DWIDTH-1:0] crc_d_out_data;
wire [128-1:0] crc_d_out_flit [FPW-1:0];
wire [FPW-1:0] crc_d_out_flit_is_hdr;
wire [FPW-1:0] crc_d_out_flit_is_tail;
wire [FPW-1:0] crc_d_out_flit_is_valid;
wire [FPW-1:0] crc_d_out_flit_is_error;
wire [FPW-1:0] crc_d_out_flit_is_poisoned;
wire [FPW-1:0] crc_d_out_flit_has_rtc;
wire [FPW-1:0] crc_d_out_flit_is_flow;
 
generate
for(f=0;f<FPW;f=f+1) begin : reorder_crc_output
assign crc_d_out_flit[f] = crc_d_out_data[128-1+(f*128):f*128];
end
endgenerate
 
//------------------------------------------------------------------------------------LNG and DLN stage
reg [128-1:0] flit_after_lng_check [FPW-1:0];
reg [FPW-1:0] flit_after_lng_check_is_hdr;
reg [FPW-1:0] flit_after_lng_check_is_tail;
reg [FPW-1:0] flit_after_lng_check_is_valid;
reg [FPW-1:0] flit_after_lng_check_is_error;
reg [FPW-1:0] flit_after_lng_check_is_poisoned;
reg [FPW-1:0] flit_after_lng_check_is_flow;
reg [FPW-1:0] flit_after_lng_check_has_rtc;
 
//------------------------------------------------------------------------------------Start TX retry Stage
reg [128-1:0] flit_after_retry_stage [FPW-1:0];
reg [FPW-1:0] flit_after_retry_stage_is_hdr;
reg [FPW-1:0] flit_after_retry_stage_is_tail;
reg [FPW-1:0] flit_after_retry_stage_is_valid;
reg [FPW-1:0] flit_after_retry_stage_is_valid_mask_msb;
reg [FPW-1:0] flit_after_retry_stage_is_valid_mask_lsb;
reg [FPW-1:0] flit_after_retry_stage_is_error;
reg [FPW-1:0] flit_after_retry_stage_is_poisoned;
reg [FPW-1:0] flit_after_retry_stage_is_flow;
reg [FPW-1:0] flit_after_retry_stage_has_rtc;
reg [FPW-1:0] flit_after_retry_stage_is_start_retry;
reg [FPW-1:0] flit_after_retry_stage_is_start_retry_comb;
 
//------------------------------------------------------------------------------------SeqStage and Seqnum
reg [128-1:0] flit_after_seq_check [FPW-1:0];
reg [FPW-1:0] flit_after_seq_check_is_hdr;
reg [FPW-1:0] flit_after_seq_check_is_tail;
reg [FPW-1:0] flit_after_seq_check_is_valid;
reg [FPW-1:0] flit_after_seq_check_is_error;
reg [FPW-1:0] flit_after_seq_check_is_error_comb;
reg [FPW-1:0] flit_after_seq_check_is_poisoned;
reg [FPW-1:0] flit_after_seq_check_is_flow;
reg [FPW-1:0] flit_after_seq_check_has_rtc;
reg [FPW-1:0] flit_after_seq_check_is_start_retry;
 
reg [2:0] next_seqnum;
reg [2:0] next_seqnum_comb; //use param instead
reg [2:0] first_seq_after_error;
 
//------------------------------------------------------------------------------------Invalidation Stage
localparam CYCLES_TO_COMPLETE_FULL_PACKET = (FPW == 2) ? 5 :
(FPW == 4) ? 3 : //Assuming Max Pkt size = 9 FLITs
(FPW == 6) ? 3 :
(FPW == 8) ? 2 :
1;
 
//Regs to retrieve the pkt length, assign the length to correspoding tail. The packet will be invalidated then
reg [3:0] lng_per_tail [FPW-1:0] ;
reg [3:0] lng_per_tail_comb [FPW-1:0] ;
reg [3:0] lng_temp;
reg [3:0] lng_comb;
//Signal that an error was detected. Invalid all FLITs after
reg error_detected;
 
//Assign FLITs to word, necessary for the invalidation stage pipeline
wire [DWIDTH-1:0] flit_after_seq_check_word;
generate
for(f = 0; f < (FPW); f = f + 1) begin : reorder_flits_after_seq_to_word
assign flit_after_seq_check_word[(f*128)+128-1:(f*128)] = flit_after_seq_check[f];
end
endgenerate
 
reg [DWIDTH-1:0] flit_in_invalidation_data [CYCLES_TO_COMPLETE_FULL_PACKET-1:0];
reg [FPW-1:0] flit_in_invalidation_is_hdr [CYCLES_TO_COMPLETE_FULL_PACKET-1:0];
reg [FPW-1:0] flit_in_invalidation_is_tail [CYCLES_TO_COMPLETE_FULL_PACKET-1:0];
reg [FPW-1:0] flit_in_invalidation_is_valid [CYCLES_TO_COMPLETE_FULL_PACKET-1:0];
reg [FPW-1:0] flit_in_invalidation_mask_poison;
reg [FPW-1:0] flit_in_invalidation_mask_error;
reg [FPW-1:0] flit_in_invalidation_is_poisoned [CYCLES_TO_COMPLETE_FULL_PACKET-1:0];
reg [FPW-1:0] flit_in_invalidation_is_flow [CYCLES_TO_COMPLETE_FULL_PACKET-1:0];
reg [FPW-1:0] flit_in_invalidation_has_rtc [CYCLES_TO_COMPLETE_FULL_PACKET-1:0];
reg [FPW-1:0] flit_in_invalidation_is_start_retry[CYCLES_TO_COMPLETE_FULL_PACKET-1:0];
 
 
 
//------------------------------------------------------------------------------------Checked FLITs
wire [128-1:0] checked_flit [FPW-1:0];
wire [FPW-1:0] checked_flit_is_poisoned;
wire [FPW-1:0] checked_flit_is_valid;
wire [FPW-1:0] checked_flit_is_hdr;
wire [FPW-1:0] checked_flit_is_tail;
wire [FPW-1:0] checked_flit_has_rtc;
wire [FPW-1:0] checked_flit_is_flow;
wire [FPW-1:0] checked_flit_is_start_retry;
 
assign checked_flit_is_hdr = flit_in_invalidation_is_hdr [CYCLES_TO_COMPLETE_FULL_PACKET-1] & flit_in_invalidation_is_valid [CYCLES_TO_COMPLETE_FULL_PACKET-1];
assign checked_flit_is_tail = flit_in_invalidation_is_tail [CYCLES_TO_COMPLETE_FULL_PACKET-1] & flit_in_invalidation_is_valid [CYCLES_TO_COMPLETE_FULL_PACKET-1];
assign checked_flit_is_valid = flit_in_invalidation_is_valid [CYCLES_TO_COMPLETE_FULL_PACKET-1] ;
assign checked_flit_is_poisoned = flit_in_invalidation_is_poisoned [CYCLES_TO_COMPLETE_FULL_PACKET-1] ;
assign checked_flit_is_flow = flit_in_invalidation_is_flow [CYCLES_TO_COMPLETE_FULL_PACKET-1] & flit_in_invalidation_is_valid [CYCLES_TO_COMPLETE_FULL_PACKET-1];
assign checked_flit_has_rtc = flit_in_invalidation_has_rtc [CYCLES_TO_COMPLETE_FULL_PACKET-1] & flit_in_invalidation_is_valid [CYCLES_TO_COMPLETE_FULL_PACKET-1];
assign checked_flit_is_start_retry = flit_in_invalidation_is_start_retry[CYCLES_TO_COMPLETE_FULL_PACKET-1] & flit_in_invalidation_is_valid [CYCLES_TO_COMPLETE_FULL_PACKET-1];
generate
for(f = 0; f < (FPW); f = f + 1) begin : reorder_invalidation_word_back_to_flits
assign checked_flit[f] = flit_in_invalidation_data[CYCLES_TO_COMPLETE_FULL_PACKET-1][128-1+(f*128):f*128];
end
endgenerate
 
//------------------------------------------------------------------------------------Counter
reg [LOG_FPW:0] rf_cnt_poisoned_comb;
reg [LOG_FPW:0] rf_cnt_rsp_comb;
 
//------------------------------------------------------------------------------------Input Buffer
reg [LOG_FPW:0] tokens_out_of_fifo_sum_comb;
reg [7:0] rtc_sum_comb; //for 8 FLIT config, maximum 8*31 tokens will be returned per cycle
 
reg [128-1:0] input_buffer_d_in_flit [FPW-1:0];
reg [FPW-1:0] input_buffer_valid;
reg [FPW-1:0] input_buffer_is_hdr;
reg [FPW-1:0] input_buffer_is_tail;
reg [FPW-1:0] input_buffer_is_error_rsp;
wire [DWIDTH+(4*FPW)-1:0] input_buffer_d_in;
wire [DWIDTH+(4*FPW)-1:0] input_buffer_d_out;
wire input_buffer_empty;
reg input_buffer_shift_in;
wire input_buffer_shift_out;
assign input_buffer_shift_out = ~(input_buffer_empty || d_out_fifo_a_full);
 
generate
for(f = 0; f < (FPW); f = f + 1) begin : assign_flits_to_input_buffer_to_a_single_reg
assign input_buffer_d_in[f*128+128-1:f*128] = input_buffer_d_in_flit[f];
assign input_buffer_d_in[DWIDTH+f] = input_buffer_valid[f];
assign input_buffer_d_in[DWIDTH+f+FPW] = input_buffer_is_hdr[f];
assign input_buffer_d_in[DWIDTH+f+(2*FPW)] = input_buffer_is_tail[f];
assign input_buffer_d_in[DWIDTH+f+(3*FPW)] = input_buffer_is_error_rsp[f];
end
endgenerate
 
//------------------------------------------------------------------------------------LINK RETRY
reg [4:0] irtry_start_retry_cnt;
reg [4:0] irtry_clear_error_cnt;
reg [4:0] irtry_start_retry_cnt_comb;
reg [4:0] irtry_clear_error_cnt_comb;
reg irtry_clear_trig;
reg irtry_clear_trig_comb;
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------ACTUAL LOGIC STARTS HERE--------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
 
//========================================================================================================================================
//------------------------------------------------------------------INIT
//========================================================================================================================================
 
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
 
if(!res_n) begin
//----Misc
descrambler_aligned <= {NUM_LANES{1'b0}};
descrambler_part_aligned <= {NUM_LANES{1'b0}};
init_bit_slip <= {NUM_LANES{1'b0}};
init_bit_slip_cnt <= {8{1'b0}};
init_wait_time <= 5'h0;
rf_hmc_init_status <= HMC_DOWN;
rf_link_status <= LINK_DOWN;
rf_lane_polarity <= {NUM_LANES{1'b0}};
rf_lane_reversal_detected <= 1'b0;
rf_descramblers_locked <= {NUM_LANES{1'b0}};
 
init_tmp_seq <= 4'h0;
init_lane_cnt <= {LOG_NUM_LANES{1'b0}};
end
else begin
 
rf_descramblers_locked <= init_descrambler_locked;
init_bit_slip <= {NUM_LANES{1'b0}};
 
 
if(rf_hmc_sleep || !rf_hmc_init_cont_set) begin
rf_link_status <= LINK_DOWN;
end else if(rf_link_status == LINK_DOWN) begin
//Begin (Re-)Init
descrambler_aligned <= {NUM_LANES{1'b0}};
descrambler_part_aligned <= {NUM_LANES{1'b0}};
init_bit_slip <= {NUM_LANES{1'b0}};
init_wait_time <= 5'h1f;
rf_hmc_init_status <= HMC_DOWN;
rf_link_status <= LINK_INIT;
rf_lane_polarity <= {NUM_LANES{1'b0}};
rf_lane_reversal_detected <= 1'b0;
rf_descramblers_locked <= {NUM_LANES{1'b0}};
init_tmp_seq <= 4'h0;
init_lane_cnt <= {LOG_NUM_LANES{1'b0}};
end
 
//Detect Lane polarity when HMC is sending first NULLs
if(&rf_descramblers_locked && rf_link_status == LINK_INIT) begin
for(i_f = 0;i_f<NUM_LANES;i_f=i_f+1)begin
if(descrambled_data_on_lane[i_f] == {WIDTH_PER_LANE{1'b1}})begin
rf_lane_polarity[i_f] <= 1'b1;
end
end
end
 
if((rf_hmc_init_status == HMC_DOWN) && &rf_descramblers_locked) begin
if(!valid_flit_src_init)
rf_hmc_init_status <= HMC_NULL;
end
 
//When TX block sends ts1, start init process
if(rf_tx_sends_ts1 && &valid_flit_src_init) begin
rf_hmc_init_status <= HMC_TS1;
end
 
if(rf_hmc_init_status==HMC_TS1) begin
// -------------------------------------------------------------------------TS1 AND DESCRAMBLER SYNCHRONIZATION
if(!rf_all_descramblers_aligned) begin // repeat this until all descramblers are aligned !!
 
if(init_wait_time == 0)begin
 
init_tmp_seq <= init_tmp_seq + INIT_SEQ_INC_PER_CYCLE;
 
if(init_bit_slip_cnt == 0)begin
 
init_lane_cnt <= init_lane_cnt + 1;
 
if(~&descrambler_part_aligned) begin
descrambler_part_aligned[init_lane_cnt] <= init_lane_has_correct_ts1[init_lane_cnt];
if(!descrambler_part_aligned[init_lane_cnt])begin
init_bit_slip[init_lane_cnt] <= ~init_lane_has_correct_ts1[init_lane_cnt];
if(init_seq_diff < INIT_SEQ_INC_PER_CYCLE && init_lane_has_correct_ts1[init_lane_cnt]) begin
init_tmp_seq <= descrambled_data_on_lane[init_lane_cnt][3:0] + INIT_SEQ_INC_PER_CYCLE;
end
end
end else begin
if(init_seq_diff==0 && init_lane_has_correct_ts1[init_lane_cnt])begin
descrambler_aligned[init_lane_cnt] <= 1'b1;
end else begin
init_bit_slip[init_lane_cnt] <= 1'b1;
end
end
 
if(init_lane_cnt == NUM_LANES-1)begin
init_bit_slip_cnt <= rf_bit_slip_time;
end
 
end else begin
init_bit_slip_cnt <= init_bit_slip_cnt -1;
end
 
end else begin
// if(phy_rx_ready)
init_wait_time <= init_wait_time -1;
end
// -------------------------------------------------------------------------SECOND NULL SEQUENCE
end else begin // now that all is synchronized continue with NULL and TRET
 
//lane reversal detected, reverse the input stream lane by lane
if(descrambled_data_on_lane[0][7:4] == ts1_lane7or15_portion)begin
rf_lane_reversal_detected <= 1'b1;
end
 
//when received NULLs again, init done (initial TRETs are treated as normal packets)
if(valid_flit_src_init == 0)begin
rf_link_status <= LINK_UP;
rf_hmc_init_status <= HMC_UP;
end
end
end
end
end
 
//========================================================================================================================================
//------------------------------------------------------------------Packet Processing
//========================================================================================================================================
 
//==================================================================================
//---------------------------------Register Input data after reordering and link_up
//==================================================================================
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
d_in <= {DWIDTH{1'b0}};
d_in_init <= {DWIDTH{1'b0}};
end else begin
if(link_is_up) begin
d_in <= d_in_temp;
d_in_init <= {DWIDTH{1'b0}};
end else begin
d_in <= {DWIDTH{1'b0}};
d_in_init <= d_in_temp;
end
end
end
 
//==================================================================================
//---------------------------------Detect HDR,Tail,Valid Flits and provide to CRC logic
//==================================================================================
always @(*) begin
//Use the remaining payload from last cycle
data2crc_payload_remain_comb = data2crc_payload_remain;
 
data2crc_hdr_comb = {FPW{1'b0}};
data2crc_tail_comb = {FPW{1'b0}};
data2crc_valid_comb = {FPW{1'b0}};
 
for(i_f=0;i_f<FPW;i_f=i_f+1) begin
 
data2crc_lng_per_flit_comb[i_f] = {128{1'b0}};
 
if(data2crc_payload_remain_comb==1) begin
data2crc_tail_comb[i_f] = 1'b1;
end
 
if(data2crc_payload_remain_comb) begin
data2crc_valid_comb[i_f] = 1'b1;
data2crc_payload_remain_comb = data2crc_payload_remain_comb - 1;
end else if(valid_flit_src[i_f])begin
 
data2crc_hdr_comb[i_f] = 1'b1;
data2crc_valid_comb[i_f] = 1'b1;
 
if(lng(d_in_flit[i_f]) < 2 || lng(d_in_flit[i_f]) > 9) begin
//Treat false lng values as single FLIT packets which will force error abort mode
data2crc_tail_comb[i_f] = 1'b1;
data2crc_lng_per_flit_comb[i_f] = 1;
end else begin
data2crc_payload_remain_comb = lng(d_in_flit[i_f]) -1;
data2crc_lng_per_flit_comb[i_f] = lng(d_in_flit[i_f]);
end
end
 
end
end
 
//Register the combinational logic from previous stage
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
 
data2crc_hdr <= {FPW{1'b0}};
data2crc_tail <= {FPW{1'b0}};
data2crc_valid <= {FPW{1'b0}};
 
data2crc_payload_remain <= {4{1'b0}};
 
for(i_f=0;i_f<FPW;i_f=i_f+1) begin
data2crc_lng_per_flit[i_f] <= {128{1'b0}};
end
 
data2crc <= {DWIDTH{1'b0}};
 
end else begin
data2crc_hdr <= data2crc_hdr_comb;
data2crc_tail <= data2crc_tail_comb;
data2crc_valid <= data2crc_valid_comb;
 
data2crc_payload_remain <= data2crc_payload_remain_comb;
 
for(i_f=0;i_f<FPW;i_f=i_f+1) begin
data2crc_lng_per_flit[i_f] <= data2crc_lng_per_flit_comb[i_f];
end
 
data2crc <= d_in;
 
end
end
 
//==================================================================================
//---------------------------------LNG/DLN check
//==================================================================================
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
 
flit_after_lng_check_is_hdr <= {FPW{1'b0}};
flit_after_lng_check_is_tail <= {FPW{1'b0}};
flit_after_lng_check_is_valid <= {FPW{1'b0}};
flit_after_lng_check_is_poisoned <= {FPW{1'b0}};
flit_after_lng_check_is_flow <= {FPW{1'b0}};
flit_after_lng_check_has_rtc <= {FPW{1'b0}};
flit_after_lng_check_is_error <= {FPW{1'b0}};
 
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
flit_after_lng_check[i_f] <= {128{1'b0}};
end
 
end else begin
flit_after_lng_check_is_hdr <= crc_d_out_flit_is_hdr;
flit_after_lng_check_is_tail <= crc_d_out_flit_is_tail;
flit_after_lng_check_is_valid <= crc_d_out_flit_is_valid;
flit_after_lng_check_is_poisoned <= crc_d_out_flit_is_poisoned;
flit_after_lng_check_is_flow <= crc_d_out_flit_is_flow;
flit_after_lng_check_has_rtc <= crc_d_out_flit_has_rtc;
flit_after_lng_check_is_error <= crc_d_out_flit_is_error;
 
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
flit_after_lng_check[i_f] <= crc_d_out_flit[i_f];
end
 
//perform lng/dln check
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
if(crc_d_out_flit_is_hdr[i_f] && (lng(crc_d_out_flit[i_f]) != dln(crc_d_out_flit[i_f]))) begin
flit_after_lng_check_is_error[i_f] <= 1'b1;
end
end
 
end
end
 
//====================================================================
//---------------------------------Start TX Retry Stage
//====================================================================
//-- Count all types of IRTRY packets
always @(*) begin
 
//Set the lower bit mask for the next stage: Mask out all error FLITs
flit_after_retry_stage_is_valid_mask_lsb = {FPW{1'b1}};
for(i_f = FPW-1; i_f >=0; i_f = i_f - 1) begin
if(flit_after_lng_check_is_error[i_f])begin
//Pass the tail in case it is an crc error so that the corresponding FLITs of the packet can be invalidated
//but mask out single flit packets!
flit_after_retry_stage_is_valid_mask_lsb = {FPW{1'b1}} >> (FPW-i_f-(flit_after_lng_check_is_tail[i_f]&!flit_after_lng_check_is_hdr[i_f]));
end
end
 
//Next up, count both types of irtry packets and set the mask accordingly for irtry start packets in error abort mode and the
//final clear abort FLIT that reaches the threshold
 
flit_after_retry_stage_is_start_retry_comb = {FPW{1'b0}};
 
if( (tx_error_abort_mode && !irtry_clear_trig) ||
|(flit_after_retry_stage_is_error) ||
|(flit_after_seq_check_is_error)
)begin
flit_after_retry_stage_is_valid_mask_msb = {FPW{1'b0}};
end else begin
flit_after_retry_stage_is_valid_mask_msb = {FPW{1'b1}};
end
 
irtry_clear_trig_comb = 1'b0;
 
irtry_clear_error_cnt_comb = irtry_clear_error_cnt;
irtry_start_retry_cnt_comb = irtry_start_retry_cnt;
 
 
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
 
if( flit_after_lng_check_is_flow[i_f] &&
cmd(flit_after_lng_check[i_f]) == {CMD_FLOW,CMD_IRTRY} &&
!flit_after_lng_check_is_error[i_f]
) begin
 
if(irtry_start_retry_flag(flit_after_lng_check[i_f])) begin
//it's a start tx retry pkt
irtry_start_retry_cnt_comb = irtry_start_retry_cnt_comb + {{4{1'b0}},1'b1};
irtry_clear_error_cnt_comb = {5{1'b0}};
end else begin
//must be clear error pkt
irtry_clear_error_cnt_comb = irtry_clear_error_cnt_comb + {{4{1'b0}},1'b1};
irtry_start_retry_cnt_comb = {5{1'b0}};
end
 
if(irtry_start_retry_cnt_comb >= rf_irtry_received_threshold) begin
//The start retry packet that reaches the trehold is treated as valid and will trigger tx retry
flit_after_retry_stage_is_valid_mask_msb[i_f] = 1'b1;
flit_after_retry_stage_is_start_retry_comb[i_f] = 1'b1;
end
 
//Clear error abort when threshold reached, allow following FLITs to be valid
if(irtry_clear_error_cnt_comb >= rf_irtry_received_threshold) begin
irtry_clear_trig_comb = 1'b1;
flit_after_retry_stage_is_valid_mask_msb = {FPW{1'b1}} << (i_f);
end
 
end else begin
//Reset both counters when received a non-irtry packet
irtry_start_retry_cnt_comb = {5{1'b0}};
irtry_clear_error_cnt_comb = {5{1'b0}};
end
end
end
 
//Save the temporary counts to be re-used in the next cycle and register the clear trigger
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
irtry_clear_trig <= 1'b0;
 
irtry_clear_error_cnt <= {5{1'b0}};
irtry_start_retry_cnt <= {5{1'b0}};
 
end else begin
irtry_clear_trig <= irtry_clear_trig_comb;
 
irtry_clear_error_cnt <= irtry_clear_error_cnt_comb;
irtry_start_retry_cnt <= irtry_start_retry_cnt_comb;
end
end
 
//Propagate data and apply the valid masks
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
for(i_f = 0;i_f<(FPW);i_f=i_f+1) begin
flit_after_retry_stage[i_f] <= {128{1'b0}};
end
flit_after_retry_stage_is_hdr <= {FPW{1'b0}};
flit_after_retry_stage_is_tail <= {FPW{1'b0}};
flit_after_retry_stage_is_poisoned <= {FPW{1'b0}};
flit_after_retry_stage_is_flow <= {FPW{1'b0}};
flit_after_retry_stage_has_rtc <= {FPW{1'b0}};
flit_after_retry_stage_is_error <= {FPW{1'b0}};
flit_after_retry_stage_is_valid <= {FPW{1'b0}};
flit_after_retry_stage_is_start_retry <= 1'b0;
end else begin
 
for(i_f = 0;i_f<(FPW);i_f=i_f+1) begin
flit_after_retry_stage[i_f] <= flit_after_lng_check[i_f];
end
flit_after_retry_stage_is_hdr <= flit_after_lng_check_is_hdr;
flit_after_retry_stage_is_tail <= flit_after_lng_check_is_tail;
flit_after_retry_stage_is_poisoned <= flit_after_lng_check_is_poisoned &
flit_after_retry_stage_is_valid_mask_msb &
flit_after_retry_stage_is_valid_mask_lsb;
flit_after_retry_stage_is_flow <= flit_after_lng_check_is_flow;
flit_after_retry_stage_has_rtc <= flit_after_lng_check_has_rtc;
flit_after_retry_stage_is_error <= flit_after_lng_check_is_error;
flit_after_retry_stage_is_valid <= flit_after_lng_check_is_valid &
flit_after_retry_stage_is_valid_mask_msb &
flit_after_retry_stage_is_valid_mask_lsb;
flit_after_retry_stage_is_start_retry <= flit_after_retry_stage_is_start_retry_comb;
 
end
end
 
//-------------------------------------------Error abort mode handling
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
 
//retry counter
tx_error_abort_mode <= 1'b0;
tx_error_abort_mode_cleared <= 1'b0;
 
end else begin
 
tx_error_abort_mode_cleared <= 1'b0;
 
if(irtry_clear_trig ) begin
tx_error_abort_mode <= 1'b0;
tx_error_abort_mode_cleared <= 1'b1;
end
 
//Set error abort mode again if error detected
if(|flit_after_lng_check_is_error || flit_after_seq_check_is_error)begin
tx_error_abort_mode <= 1'b1;
end
 
end
end
 
//==================================================================================
//---------------------------------SEQ check
//==================================================================================
//Check the seqnum FLIT by FLIT. Assign the last received seqnum when error abort mode is cleared
//!Lots of logic levels for 8FLIT config
always @(*) begin
 
next_seqnum_comb = 3'h0;
flit_after_seq_check_is_error_comb = {FPW{1'b0}};
 
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
if(flit_after_retry_stage_has_rtc[i_f]) begin
//All packets that have an RTC also have a valid seqnum
if(seq(flit_after_retry_stage[i_f]) == next_seqnum + next_seqnum_comb) begin
next_seqnum_comb = next_seqnum_comb + 3'h1;
end else begin
flit_after_seq_check_is_error_comb[i_f] = 1'b1;
end
end
end
end
 
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
 
//We expect the first packet to have the seqnum 1
next_seqnum <= 3'h1;
 
flit_after_seq_check_is_hdr <= {FPW{1'b0}};
flit_after_seq_check_is_tail <= {FPW{1'b0}};
flit_after_seq_check_is_valid <= {FPW{1'b0}};
flit_after_seq_check_is_poisoned <= {FPW{1'b0}};
flit_after_seq_check_is_flow <= {FPW{1'b0}};
flit_after_seq_check_has_rtc <= {FPW{1'b0}};
flit_after_seq_check_is_error <= {FPW{1'b0}};
flit_after_seq_check_is_start_retry <= {FPW{1'b0}};
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
flit_after_seq_check[i_f] <= {128{1'b0}};
end
 
end else begin
 
//Set the expected sequence number to the first expected one after error abort mode if clear was triggered
//otherwise apply the last seqnum + combinatioanl offset
if(irtry_clear_trig_comb) begin
next_seqnum <= first_seq_after_error + next_seqnum_comb;
end else begin
next_seqnum <= next_seqnum + next_seqnum_comb;
end
 
//propage data to next stage and include any error bits that were detected during sequence number check
flit_after_seq_check_is_hdr <= flit_after_retry_stage_is_hdr;
flit_after_seq_check_is_tail <= flit_after_retry_stage_is_tail;
flit_after_seq_check_is_valid <= flit_after_retry_stage_is_valid;
flit_after_seq_check_is_poisoned <= flit_after_retry_stage_is_poisoned;
flit_after_seq_check_is_flow <= flit_after_retry_stage_is_flow;
flit_after_seq_check_has_rtc <= flit_after_retry_stage_has_rtc;
flit_after_seq_check_is_error <= flit_after_retry_stage_is_error |
flit_after_seq_check_is_error_comb;
flit_after_seq_check_is_start_retry <= flit_after_retry_stage_is_start_retry;
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
flit_after_seq_check[i_f] <= flit_after_retry_stage[i_f];
end
 
end
end
 
//==================================================================================
//---------------------------------Retrieve the lengths to invalide FLITs
//==================================================================================
always @(*) begin
//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
 
lng_comb = lng_temp;
 
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
 
if(flit_after_retry_stage_is_hdr[i_f]) begin
if( lng(flit_after_retry_stage[i_f]) < 2 ||
lng(flit_after_retry_stage[i_f]) > 9
) begin
lng_comb = 1;
end else begin
lng_comb = lng(flit_after_retry_stage[i_f]);
end
end
 
if(flit_after_retry_stage_is_tail[i_f]) begin
lng_per_tail_comb[i_f] = lng_comb;
end else begin
lng_per_tail_comb[i_f] = {4{1'b0}};
end
 
end
end
 
//Register combinational values
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
lng_per_tail[i_f] <= 0;
end
lng_temp <= {4{1'b0}};
end else begin
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
lng_per_tail[i_f] <= lng_per_tail_comb[i_f];
end
lng_temp <= lng_comb;
end
end
 
//==================================================================================
//---------------------------------FLIT Invalidation Stage
//==================================================================================
//Constant propagation for some parts of the invalidation stage
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
 
for(i_c=0; i_c<(CYCLES_TO_COMPLETE_FULL_PACKET); i_c=i_c+1) begin
flit_in_invalidation_data[i_c] <= {DWIDTH{1'b0}};
flit_in_invalidation_is_hdr[i_c] <= {FPW{1'b0}};
flit_in_invalidation_is_tail[i_c] <= {FPW{1'b0}};
flit_in_invalidation_is_poisoned[i_c] <= {FPW{1'b0}};
flit_in_invalidation_is_flow[i_c] <= {FPW{1'b0}};
flit_in_invalidation_has_rtc[i_c] <= {FPW{1'b0}};
flit_in_invalidation_is_start_retry[i_c] <= {FPW{1'b0}};
end
end else begin
flit_in_invalidation_data[0] <= flit_after_seq_check_word;
flit_in_invalidation_is_hdr[0] <= flit_after_seq_check_is_hdr;
flit_in_invalidation_is_tail[0] <= flit_after_seq_check_is_tail;
flit_in_invalidation_is_poisoned[0] <= flit_after_seq_check_is_poisoned &
~flit_after_seq_check_is_error;
flit_in_invalidation_is_flow[0] <= flit_after_seq_check_is_flow;
flit_in_invalidation_has_rtc[0] <= flit_after_seq_check_has_rtc;
flit_in_invalidation_is_start_retry[0] <= flit_after_seq_check_is_start_retry;
 
for(i_c=0; i_c<(CYCLES_TO_COMPLETE_FULL_PACKET-1); i_c=i_c+1) begin
flit_in_invalidation_data[i_c+1] <= flit_in_invalidation_data[i_c];
flit_in_invalidation_is_hdr[i_c+1] <= flit_in_invalidation_is_hdr[i_c];
flit_in_invalidation_is_tail[i_c+1] <= flit_in_invalidation_is_tail[i_c];
flit_in_invalidation_is_poisoned[i_c+1] <= flit_in_invalidation_is_poisoned[i_c];
flit_in_invalidation_is_flow[i_c+1] <= flit_in_invalidation_is_flow[i_c];
flit_in_invalidation_has_rtc[i_c+1] <= flit_in_invalidation_has_rtc[i_c];
flit_in_invalidation_is_start_retry[i_c+1] <= flit_in_invalidation_is_start_retry[i_c];
end
end
end
 
//Only the valid FLIT indicators must be set accordingly
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
 
for(i_c = 0; i_c < (CYCLES_TO_COMPLETE_FULL_PACKET); i_c = i_c + 1) begin
flit_in_invalidation_is_valid[i_c] <= 0;
end
 
error_detected <= 0;
 
flit_in_invalidation_mask_poison <= {FPW{1'b1}};
flit_in_invalidation_mask_error <= {FPW{1'b1}};
end else begin
 
//Reset the masks for invalidation stages
flit_in_invalidation_mask_poison <= {FPW{1'b1}};
flit_in_invalidation_mask_error <= {FPW{1'b1}};
 
if(irtry_clear_trig) begin
error_detected <= 0;
end
 
//Propate invalidation stages but apply error and poisoned masks to the second stage
for(i_c = 1; i_c < (CYCLES_TO_COMPLETE_FULL_PACKET-1); i_c = i_c + 1) begin
flit_in_invalidation_is_valid[i_c+1] <= flit_in_invalidation_is_valid[i_c];
end
flit_in_invalidation_is_valid[1] <= flit_in_invalidation_is_valid[0] & flit_in_invalidation_mask_poison & flit_in_invalidation_mask_error;
 
if(error_detected) begin
//There is no valid FLIT when an error was detected
flit_in_invalidation_is_valid[0] <= 0;
end else begin
//First apply valids from previous stage
flit_in_invalidation_is_valid[0] <= flit_after_seq_check_is_valid;
 
//If there is a poisoned packet mask out, but leave all FLITs before and after untouched
for(i_f = FPW-1; i_f>=0; i_f = i_f-1) begin
if(flit_after_seq_check_is_poisoned[i_f]) begin
flit_in_invalidation_mask_poison <= ({FPW{1'b1}} >> (FPW-i_f-1+lng_per_tail[i_f])) | ({FPW{1'b1}} << (i_f));
end
end
 
//At least one FLIT contained an error in its tail. Leave all FLITs before the error untouched
for(i_f = FPW-1; i_f>=0; i_f = i_f-1) begin
if(flit_after_seq_check_is_error[i_f] && flit_after_seq_check_is_tail[i_f]) begin
error_detected <= 1'b1;
flit_in_invalidation_mask_error <= {FPW{1'b1}} >> (FPW-i_f-1+lng_per_tail[i_f]);
end
end
 
//Now use the length of the packet to invalidate FLITs that may reside in the next stages already
for(i_f = FPW-1; i_f>=0; i_f = i_f-1) begin
if((flit_after_seq_check_is_error[i_f] && flit_after_seq_check_is_tail[i_f]) || flit_after_seq_check_is_poisoned[i_f]) begin
if(lng_per_tail[i_f] > i_f) begin
flit_in_invalidation_is_valid[1] <= flit_in_invalidation_is_valid[0] & flit_in_invalidation_mask_poison &
({FPW{1'b1}} >> lng_per_tail[i_f]-i_f-1);
end
for(i_c = 1; i_c < (CYCLES_TO_COMPLETE_FULL_PACKET-1); i_c = i_c + 1) begin
if(lng_per_tail[i_f] > ((i_c)*FPW)+i_f) begin
flit_in_invalidation_is_valid[i_c+1] <= flit_in_invalidation_is_valid[i_c] &
({FPW{1'b1}} >> lng_per_tail[i_f]-(i_c*FPW)-i_f-1);
end
end
end
end
 
end
 
end
end
 
//====================================================================
//---------------------------------FRP/RRP/RTC
//====================================================================
//Count the returned tokens
always @(*) begin
rtc_sum_comb = {8{1'b0}};
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
if(checked_flit_has_rtc[i_f])begin
rtc_sum_comb = rtc_sum_comb + rtc(checked_flit[i_f]);
end
end
end
 
//Extract FRP/RRP + last seq (which is necessary to check packets after error_abort_mode is cleared)
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
 
tx_hmc_frp <= {8{1'b0}};
tx_rrp <= {8{1'b0}};
tx_returned_tokens <= {8{1'b0}};
first_seq_after_error <= 3'h1;
 
tx_link_retry <= 1'b0;
 
end else begin
//Return tokens
tx_returned_tokens <= rtc_sum_comb;
 
//Process FLITs and extract frp/seq/rrp if applicable
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
 
if(checked_flit_is_tail[i_f]) begin
tx_rrp <= rrp(checked_flit[i_f]);
 
if(checked_flit_has_rtc[i_f])begin
tx_hmc_frp <= frp(checked_flit[i_f]);
first_seq_after_error <= seq(checked_flit[i_f]) + 3'h1;
end
end
end
 
//-------------------------------------------TX retry
tx_link_retry <= 1'b0;
 
//If there is a start_retry pulse signalize to tx link
if(|checked_flit_is_start_retry)begin
tx_link_retry <= 1'b1;
end
 
end
end
 
//==================================================================================
//---------------------------------Fill the input buffer with all response packets
//==================================================================================
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
 
input_buffer_shift_in <= 1'b0;
input_buffer_valid <= {FPW{1'b0}};
input_buffer_is_hdr <= {FPW{1'b0}};
input_buffer_is_tail <= {FPW{1'b0}};
input_buffer_is_error_rsp <= {FPW{1'b0}};
 
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
input_buffer_d_in_flit[i_f] <= {128{1'b0}};
end
 
end else begin
 
input_buffer_shift_in <= 1'b0;
input_buffer_is_error_rsp <= {FPW{1'b0}};
 
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
input_buffer_d_in_flit[i_f] <= {128{1'b0}};
 
//Flow and poisoned packets are not forwarded
if(checked_flit_is_valid[i_f]) begin
if(!checked_flit_is_flow[i_f] && !checked_flit_is_poisoned[i_f])begin
input_buffer_d_in_flit[i_f] <= checked_flit[i_f];
end
if(checked_flit_is_hdr[i_f] && (cmd(checked_flit[i_f])==6'b111110)) begin
input_buffer_is_error_rsp[i_f] <= 1'b1;
end
end
end
 
//Mask out any flow or poisoned packets
input_buffer_valid <= checked_flit_is_valid &
~checked_flit_is_flow &
~checked_flit_is_poisoned;
input_buffer_is_hdr <= checked_flit_is_hdr &
~checked_flit_is_flow;
input_buffer_is_tail <= checked_flit_is_tail &
~checked_flit_is_flow &
~checked_flit_is_poisoned;
 
//If there is still a valid packet remaining after applying the mask
if(|(checked_flit_is_valid & ~checked_flit_is_flow & ~checked_flit_is_poisoned))begin
input_buffer_shift_in <= 1'b1;
end
 
end
end
 
//==================================================================================
//---------------------------------Count responses and poisoned packets
//==================================================================================
always @(*) begin
rf_cnt_poisoned_comb = {LOG_FPW+1{1'b0}};
rf_cnt_rsp_comb = {LOG_FPW+1{1'b0}};
 
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
if(checked_flit_is_poisoned[i_f])begin
rf_cnt_poisoned_comb = rf_cnt_poisoned_comb + {{LOG_FPW{1'b0}},1'b1};
end
if(input_buffer_is_tail[i_f] && !input_buffer_is_error_rsp[i_f])begin
//if its a tail but not error response
rf_cnt_rsp_comb = rf_cnt_rsp_comb + {{LOG_FPW{1'b0}},1'b1};
end
end
end
 
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
rf_cnt_poisoned <= {HMC_RF_RWIDTH{1'b0}};
rf_cnt_rsp <= {HMC_RF_RWIDTH{1'b0}};
end else begin
rf_cnt_poisoned <= rf_cnt_poisoned + {{HMC_RF_RWIDTH-LOG_FPW-1{1'b0}},rf_cnt_poisoned_comb};
rf_cnt_rsp <= rf_cnt_rsp + {{HMC_RF_RWIDTH-LOG_FPW-1{1'b0}},rf_cnt_rsp_comb};
end
end
 
//==================================================================================
//---------------------------------Shift response packets into the output fifo, return a token for each processed FLIT
//==================================================================================
always @(*) begin
tokens_out_of_fifo_sum_comb = {LOG_FPW+1{1'b0}};
 
if(input_buffer_shift_out)begin
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
tokens_out_of_fifo_sum_comb = tokens_out_of_fifo_sum_comb +
(input_buffer_d_out[DWIDTH+i_f] &&
!input_buffer_d_out[DWIDTH+i_f+(3*FPW)]); //increment if there's a valid FLIT, but not an error response
end
end
end
 
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
tx_hmc_tokens_to_be_returned <= {LOG_FPW+1{1'b0}};
end else begin
tx_hmc_tokens_to_be_returned <= tokens_out_of_fifo_sum_comb;
end
end
 
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
//----FIFO
d_out_fifo_shift_in <= 1'b0;
d_out_fifo_ctrl <= {3*FPW{1'b0}};
d_out_fifo_data <= {DWIDTH{1'b0}};
 
end else begin
d_out_fifo_shift_in <= 1'b0;
d_out_fifo_ctrl <= {3*FPW{1'b0}};
 
 
if(input_buffer_shift_out)begin
d_out_fifo_data <= input_buffer_d_out[DWIDTH-1:0];
d_out_fifo_shift_in <= 1'b1;
d_out_fifo_ctrl <= input_buffer_d_out[DWIDTH+(3*FPW)-1:DWIDTH];
end
end
end
 
 
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------INSTANTIATIONS HERE-------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
 
wire res_n_lanes = ((rf_link_status == LINK_DOWN) || !rf_hmc_init_cont_set) ? 0 : 1'b1 ;
 
//Lane Init
genvar i;
generate
for(i=0;i<NUM_LANES;i=i+1)begin : lane_gen
rx_lane_logic #(
.DWIDTH(DWIDTH),
.NUM_LANES(NUM_LANES)
) rx_lane_I (
.clk(clk),
.res_n(res_n_lanes),
.bit_slip(init_bit_slip[i]),
.descrambler_locked(init_descrambler_locked[i]),
.descrambler_disable(rf_scrambler_disable),
.lane_polarity(rf_lane_polarity[i]),
.scrambled_data_in(phy_scrambled_data_in[i*WIDTH_PER_LANE+WIDTH_PER_LANE-1:i*WIDTH_PER_LANE]),
.descrambled_data_out(descrambled_data_on_lane[i])
);
end
endgenerate
 
//HMC CRC Logic
rx_crc_compare #(
.DWIDTH(DWIDTH),
.FPW(FPW),
.LOG_FPW(LOG_FPW)
)
rx_crc_compare
(
.clk(clk),
.res_n(res_n),
//input
.d_in_data(data2crc),
.d_in_hdr(data2crc_hdr),
.d_in_tail(data2crc_tail),
.d_in_valid(data2crc_valid),
.d_in_lng(data2crc_lng),
//output
.d_out_data(crc_d_out_data),
.d_out_hdr(crc_d_out_flit_is_hdr),
.d_out_tail(crc_d_out_flit_is_tail),
.d_out_valid(crc_d_out_flit_is_valid),
.d_out_error(crc_d_out_flit_is_error),
.d_out_poisoned(crc_d_out_flit_is_poisoned),
.d_out_rtc(crc_d_out_flit_has_rtc),
.d_out_flow(crc_d_out_flit_is_flow)
);
 
//Buffer Fifo - Depth = Max Tokens
sync_fifo #(
.DATASIZE(DWIDTH+(4*FPW)), //+4*FPW for header/tail/valid/error information -> AXi-4 TUSER signal
.ADDRSIZE(LOG_MAX_RTC)
) input_buffer_I(
.clk(clk),
.res_n(res_n),
.d_in(input_buffer_d_in),
.shift_in(input_buffer_shift_in),
.d_out(input_buffer_d_out),
.shift_out(input_buffer_shift_out),
.next_stage_full(1'b1), // Dont touch!
.empty(input_buffer_empty)
);
 
endmodule
`default_nettype wire
/openhmc/trunk/openHMC/rtl/hmc_controller/tx/tx_crc_combine.v
0,0 → 1,444
/*
* .--------------. .----------------. .------------.
* | .------------. | .--------------. | .----------. |
* | | ____ ____ | | | ____ ____ | | | ______ | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| |
* | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' |
* '--------------' '----------------' '------------'
*
* openHMC - An Open Source Hybrid Memory Cube Controller
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg
* www.ziti.uni-heidelberg.de
* B6, 26
* 68159 Mannheim
* Germany
*
* Contact: openhmc@ziti.uni-heidelberg.de
* http://ra.ziti.uni-heidelberg.de/openhmc
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This source file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* 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/>.
*
*
* Module name: tx_crc_combine
*
*/
 
`default_nettype none
 
module tx_crc_combine #(
parameter LOG_FPW = 2,
parameter FPW = 4,
parameter DWIDTH = 512
) (
 
//----------------------------------
//----SYSTEM INTERFACE
//----------------------------------
input wire clk,
input wire res_n,
 
//----------------------------------
//----Input data
//----------------------------------
input wire [FPW-1:0] d_in_hdr,
input wire [FPW-1:0] d_in_tail,
input wire [DWIDTH-1:0] d_in_data,
 
//----------------------------------
//----Outputs
//----------------------------------
output wire [DWIDTH-1:0] d_out_data
 
);
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------WIRING AND SIGNAL STUFF---------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
 
`include "hmc_field_functions.h"
//------------------------------------------------------------------------------------General Assignments
integer i_f; //counts to FPW
integer i_f2; //counts to FPW inside another i_f loop
integer i_f3; //counts to FPW inside another i_f loop
integer i_c; //depth of the crc data pipeline
 
genvar f, f2;
 
//------------------------------------------------------------------------------------Local params for parameterization
localparam CRC_WIDTH = 32;
localparam CRC_DATA_PIPE_DEPTH = 3;
localparam NUM_32BIT_CHUNKS = FPW*FPW;
 
//------------------------------------------------------------------------------------Split input data into FLITs
wire [128-1:0] d_in_flit [FPW-1:0];
generate
for(f = 0; f < (FPW); f = f + 1) begin
assign d_in_flit[f] = d_in_data[(f*128)+128-1:f*128];
end
endgenerate
 
reg [128-1:0] d_in_flit_dly [FPW-1:0];
reg [DWIDTH-1:0] d_in_data_dly;
reg [FPW-1:0] d_in_tail_dly;
reg [FPW-1:0] d_in_hdr_dly;
reg [LOG_FPW-1:0] d_in_flit_target_crc [FPW-1:0];
 
//------------------------------------------------------------------------------------CRC Target Assignment
reg swap_crc;
 
//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_tail1 [FPW-1:0];
reg [LOG_FPW-1:0] target_crc_per_tail2 [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_temp;
 
//------------------------------------------------------------------------------------CRC Modules Input stage
wire [CRC_WIDTH-1:0] crc_init_out [FPW-1:0];
reg [CRC_WIDTH-1:0] crc_accu_in [(FPW*FPW)-1:0];
reg [FPW-1:0] crc_accu_in_valid [FPW-1:0];
reg [FPW-1:0] crc_accu_clear;
wire [CRC_WIDTH-1:0] crc_per_flit [FPW-1:0];
 
 
//------------------------------------------------------------------------------------Inter CRC stage
reg [3:0] payload_remain [FPW-1:0];
 
wire [(FPW*CRC_WIDTH)-1:0] crc_accu_in_combined [FPW-1:0];
generate
for(f=0;f<FPW;f=f+1) begin
for(f2=0;f2<FPW;f2=f2+1) begin
assign crc_accu_in_combined[f][(f2*CRC_WIDTH)+CRC_WIDTH-1:(f2*CRC_WIDTH)] = crc_accu_in[(f*FPW)+f2];
end
end
endgenerate
 
 
//------------------------------------------------------------------------------------Data Pipeline signals
reg [DWIDTH-1:0] crc_data_pipe_in_data [CRC_DATA_PIPE_DEPTH-1:0];
reg [FPW-1:0] crc_data_pipe_in_tail [CRC_DATA_PIPE_DEPTH-1:0];
wire [128-1:0] crc_data_pipe_out_data_flit [FPW-1:0];
 
generate
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[CRC_DATA_PIPE_DEPTH-1][(f*128)+128-1:f*128];
end
endgenerate
 
 
reg [128-1:0] data_rdy_flit [FPW-1:0];
generate
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];
end
endgenerate
 
//==================================================================================
//---------------------------------Retrieve the lengths to invalide FLITs
//==================================================================================
always @(*) begin
//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
 
target_crc_comb = target_crc_temp;
 
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
 
if(d_in_hdr_dly[i_f]) begin
target_crc_comb = d_in_flit_target_crc[i_f];
end
 
if(d_in_tail_dly[i_f]) begin
target_crc_per_tail_comb[i_f] = target_crc_comb;
end else begin
target_crc_per_tail_comb[i_f] = {4{1'b0}};
end
 
end
end
 
//Register combinational values
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
target_crc_per_tail[i_f] <= 0;
end
target_crc_temp <= {4{1'b0}};
end else 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];
end
target_crc_temp <= target_crc_comb;
end
end
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------LOGIC STARTS HERE---------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
//====================================================================
//---------------------------------Assign input data stream to target CRCs
//====================================================================
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) 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}};
end
swap_crc <= 1'b0;
end else 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}};
end
 
//Reset if seen a tail
if(|d_in_tail) begin
swap_crc <= 1'b0;
end
 
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
if(d_in_hdr[i_f])begin
if(i_f+lng(d_in_flit[i_f])>FPW) begin
//If the current packet spreads over multiple cycles
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
d_in_flit_target_crc[i_f] <= 3'h0;
end else begin
d_in_flit_target_crc[i_f] <= FPW-1'b1;
swap_crc <= 1'b1;
end
 
end else begin
 
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
//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
d_in_flit_target_crc[i_f] <= i_f-1;
end
end
end
end
 
end
end
 
//Register input values to be used in CRC assignment logic after crc init stage
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
d_in_flit_dly[i_f] <= {128{1'b0}};
end
d_in_data_dly <= {DWIDTH{1'b0}};
d_in_tail_dly <= {FPW{1'b0}};
d_in_hdr_dly <= {FPW{1'b0}};
end else begin
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
d_in_flit_dly[i_f] <= d_in_flit[i_f];
end
d_in_data_dly <= d_in_data;
d_in_tail_dly <= d_in_tail;
d_in_hdr_dly <= d_in_hdr;
end
end
 
//====================================================================
//---------------------------------Inter CRC stage, CRC assignment Logic
//====================================================================
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
crc_accu_clear <= 1'b0;
 
for(i_f=0;i_f<NUM_32BIT_CHUNKS;i_f=i_f+1)begin
crc_accu_in[i_f] <= {CRC_WIDTH{1'b0}};
end
 
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
crc_accu_in_valid[i_f] <= {FPW{1'b0}};
payload_remain[i_f] <= 4'h0;
end
end else begin
//First reset
crc_accu_clear <= 1'b0;
 
for(i_f=0;i_f<NUM_32BIT_CHUNKS;i_f=i_f+1)begin
crc_accu_in[i_f] <= {CRC_WIDTH{1'b0}};
end
 
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
crc_accu_in_valid[i_f] <= 4'h0;
end
 
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
//First go through accu crcs
 
if(|payload_remain[i_f]) begin
for(i_f2=0;i_f2<FPW;i_f2=i_f2+1)begin
crc_accu_in[(i_f*FPW)+i_f2] <= crc_init_out[i_f2];
end
 
if(payload_remain[i_f] > FPW) begin
crc_accu_in_valid[i_f] <= {FPW{1'b1}};
payload_remain[i_f] <= payload_remain[i_f]-FPW;
end else begin
crc_accu_in_valid[i_f] <= {FPW{1'b1}} >> (FPW-payload_remain[i_f]);
payload_remain[i_f] <= 4'h0;
end
end
 
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
//Then go through all input crcs from the init crc and find the crc's that must be assigned to the currently selected crc
 
for(i_f3=i_f2;i_f3<FPW;i_f3=i_f3+1)begin
crc_accu_in[(i_f*FPW)+i_f3-i_f2] <= crc_init_out[i_f3];
end
 
crc_accu_clear[i_f] <= 1'b1;
 
if( (i_f2+lng(d_in_flit_dly[i_f2])) >FPW ) begin
payload_remain[i_f] <= lng(d_in_flit_dly[i_f2])-FPW+i_f2;
crc_accu_in_valid[i_f] <= {FPW{1'b1}} >> i_f2;
end else begin
crc_accu_in_valid[i_f] <= ({FPW{1'b1}} >> (FPW-i_f2-lng(d_in_flit_dly[i_f2])) )
>> i_f2;
end
end
 
end
end
end
end
 
//====================================================================
//---------------------------------Constant propagation of the data pipeline
//====================================================================
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
for(i_c=0;i_c<CRC_DATA_PIPE_DEPTH;i_c=i_c+1)begin
crc_data_pipe_in_data[i_c] <= {DWIDTH{1'b0}};
crc_data_pipe_in_tail[i_c] <= {FPW{1'b0}};
end
 
for(i_f = 0; i_f < (FPW); i_f = i_f + 1) begin
target_crc_per_tail1[i_f] <= 3'h0;
target_crc_per_tail2[i_f] <= 3'h0;
end
end else begin
 
//We keep the tails per FLIT so they are not part of the data pipe
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_tail2[i_f] <= target_crc_per_tail1[i_f];
end
 
//Set the first stage of the data pipeline
crc_data_pipe_in_data[0] <= d_in_data_dly;
crc_data_pipe_in_tail[0] <= d_in_tail_dly;
 
//Data Pipeline propagation
for(i_c=0;i_c<(CRC_DATA_PIPE_DEPTH-1);i_c=i_c+1)begin
crc_data_pipe_in_data[i_c+1] <= crc_data_pipe_in_data[i_c];
crc_data_pipe_in_tail[i_c+1] <= crc_data_pipe_in_tail[i_c];
end
end
end
 
//====================================================================
//---------------------------------At the end of the data pipeline get and add CRCs
//====================================================================
//Data Pipeline output stage to final FLIT reg
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
 
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
 
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];
 
if(crc_data_pipe_in_tail[CRC_DATA_PIPE_DEPTH-1][i_f])begin //Finally add the crc
data_rdy_flit[i_f][128-1:128-32] <= crc_per_flit[target_crc_per_tail2[i_f]];
end
end
end
end
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------INSTANTIATIONS HERE-------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
//Init CRC: Calculate the remainders of each input FLIT individually
generate
for(f=0;f<FPW;f=f+1) begin : crc_init_gen
crc_128_init crc_init_I
(
.clk(clk),
.res_n(res_n),
.inData(d_in_flit[f]),
.crc(crc_init_out[f])
);
end
endgenerate
 
//Calculate the actual CRC over all valid remainders
generate
for(f=0;f<FPW;f=f+1) begin : crc_accu_gen
crc_accu #(
.FPW(FPW)
)
crc_accu_I
(
.clk(clk),
.res_n(res_n),
.clear(crc_accu_clear[f]),
.d_in(crc_accu_in_combined[f]),
.valid(crc_accu_in_valid[f]),
.crc_out(crc_per_flit[f])
);
end
endgenerate
 
endmodule
`default_nettype wire
/openhmc/trunk/openHMC/rtl/hmc_controller/tx/tx_scrambler.v
0,0 → 1,142
/*
* .--------------. .----------------. .------------.
* | .------------. | .--------------. | .----------. |
* | | ____ ____ | | | ____ ____ | | | ______ | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| |
* | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' |
* '--------------' '----------------' '------------'
*
* openHMC - An Open Source Hybrid Memory Cube Controller
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg
* www.ziti.uni-heidelberg.de
* B6, 26
* 68159 Mannheim
* Germany
*
* Contact: openhmc@ziti.uni-heidelberg.de
* http://ra.ziti.uni-heidelberg.de/openhmc
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This source file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* 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/>.
*
*
* Module name: tx_scrambler
*
* Description:
*
* This module implements a parallel scrambler based on the
* polynomial 1+ x^(-14) + x^(-15).
* Such Scrambler is typically shown as a 15 bit Linear Feedback Shift Register
* (LFSR) with bits shifting from register 1 on the left to register 15 on the
* right, with register 14 and 15 combining to shift into register 1.
* The HMC Serializer outputs data[0] first from parallel tx data[n:0],
* so if data[n:0] is to be bitwise scrambled with LFSR[n:0], we need the LFSR
* to shift from n -> 0, the opposite direction from the typical illustration.
* This implementation shifts data from LFSR[14] on the left to LFSR[0] on the
* right, with LFSR[1] and [0] combining to shift into LFSR[14]. This way
* LFSR[14:0] can bitwise scramble data[14:0] and be compatible with serializ-
* ation that shifts out on the data[0] side.
* Put otherwise: Polynomial 1+ x^(-14) + x^(-15) is equiv to
* x^15 + x^1 + x^0
* This parallelized version calculates the next DWIDTH steps of values for
* the LFSR. These bits are used to scramble the parallel input, and to
* choose the next value of lfsr (lfsr_steps[DWIDTH-1]).
*/
 
`default_nettype none
 
module tx_scrambler #(
parameter DWIDTH=16
)
(
input wire clk,
input wire res_n,
input wire load_lfsr,
input wire [14:0] seed, // unique per lane
input wire [DWIDTH-1:0] data_in,
output reg [DWIDTH-1:0] data_out,
input wire rf_run_length_enable,
output wire rf_run_length_bit_flip
);
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------WIRING AND SIGNAL STUFF---------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
wire [DWIDTH-1:0] data_out_tmp;
wire [DWIDTH-1:0] run_length_d_out;
reg [14:0] lfsr; // LINEAR FEEDBACK SHIFT REGISTER
wire [14:0] lfsr_steps [DWIDTH-1:0]; // LFSR values for serial time steps
 
// SEQUENTIAL PROCESS
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if (!res_n) begin
lfsr[14:0] <= seed;
data_out <= {DWIDTH {1'b0}};
end
else
begin
data_out <= run_length_d_out;
if (load_lfsr) begin
lfsr[14:0] <= seed;
end
else
begin
lfsr[14:0] <= lfsr_steps[DWIDTH-1];
end
end
end // serial shift right with left input
 
// SCRAMBLE
genvar j;
generate
 
assign data_out_tmp [0] = data_in[0] ^ lfsr[0]; // single bit scrambled.
assign lfsr_steps[0] = { (lfsr[1] ^ lfsr[0]) , lfsr[14:1] }; // lfsr at next bit clock
for(j = 1; j < DWIDTH; j = j + 1) begin : scrambler_gen
assign data_out_tmp[j] = data_in[j] ^ lfsr_steps[j-1][0];
assign lfsr_steps[j] = { (lfsr_steps[j-1][1] ^ lfsr_steps[j-1][0]) , lfsr_steps[j-1][14:1] };
end
endgenerate
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------INSTANTIATIONS HERE-------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
 
tx_run_length_limiter #(
.DWIDTH(DWIDTH)
)
run_length_limiter_I
(
.clk(clk),
.res_n(res_n),
.enable(rf_run_length_enable),
.data_in(data_out_tmp),
.data_out(run_length_d_out),
.rf_bit_flip(rf_run_length_bit_flip)
);
 
endmodule
 
`default_nettype wire
 
/openhmc/trunk/openHMC/rtl/hmc_controller/tx/tx_run_length_limiter.v
0,0 → 1,153
/*
* .--------------. .----------------. .------------.
* | .------------. | .--------------. | .----------. |
* | | ____ ____ | | | ____ ____ | | | ______ | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| |
* | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' |
* '--------------' '----------------' '------------'
*
* openHMC - An Open Source Hybrid Memory Cube Controller
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg
* www.ziti.uni-heidelberg.de
* B6, 26
* 68159 Mannheim
* Germany
*
* Contact: openhmc@ziti.uni-heidelberg.de
* http://ra.ziti.uni-heidelberg.de/openhmc
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This source file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* 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/>.
*
*
* Module name: tx_run_length_limiter
*
* Description:
* The idea is to break the counts up into manageable chunks. FPGAs have 6-input LUTs, so a
* reasonable granularity is 5. This means that we check 5 bits + the previous bit in every chunk.
*
* Granularity 1 should be more accurate, but uses more resources.
*
* When there are no bit flips in the input, count_top and count_bottom should be equal.
* Calculating them separately is faster and uses fewer resources.
*/
 
`default_nettype none
 
module tx_run_length_limiter #(
parameter DWIDTH=64,
parameter GRANULARITY=4,
parameter RUN_LIMIT=85
)
(
input wire clk,
input wire res_n,
input wire enable,
input wire [DWIDTH-1:0] data_in,
output reg [DWIDTH-1:0] data_out,
output reg rf_bit_flip
);
 
localparam NUM_CHUNKS = (DWIDTH + GRANULARITY-1)/(GRANULARITY);
localparam REM_BITS = DWIDTH - (GRANULARITY * (DWIDTH/GRANULARITY));
localparam COUNT_BITS = 8;
 
wire [NUM_CHUNKS-1:0] no_flip;
wire [NUM_CHUNKS-1:0] still_counting_top;
wire [NUM_CHUNKS-1:0] still_counting_bottom;
 
wire [COUNT_BITS-1:0] count_top;
wire [COUNT_BITS-1:0] count_top_part [NUM_CHUNKS-1:0];
wire [COUNT_BITS-1:0] count_bottom;
wire [COUNT_BITS-1:0] count_bottom_part [NUM_CHUNKS-1:0];
 
wire bit_flip;
 
reg [COUNT_BITS-1:0] count_bottom_d1;
reg no_flip_bottom_d1;
reg data_in_bottom_d1;
 
genvar chunk;
genvar chunkT;
genvar chunkB;
generate
 
assign no_flip[0] = &( {data_in[GRANULARITY-1:0],data_in_bottom_d1}) ||
&(~{data_in[GRANULARITY-1:0],data_in_bottom_d1});
 
for(chunk=1; chunk<NUM_CHUNKS-1; chunk=chunk+1) begin : no_flip_gen
assign no_flip[chunk] = &( data_in[(chunk+1)*(GRANULARITY)-1:chunk*(GRANULARITY)-1]) ||
&(~data_in[(chunk+1)*(GRANULARITY)-1:chunk*(GRANULARITY)-1]);
end
 
assign no_flip[NUM_CHUNKS-1] = &( data_in[DWIDTH-1:(NUM_CHUNKS-1)*(GRANULARITY)-1]) ||
&(~data_in[DWIDTH-1:(NUM_CHUNKS-1)*(GRANULARITY)-1]);
 
 
// Start at the top and count until a flip is found
assign still_counting_top[0] = no_flip[0];
assign count_top_part[0] = (no_flip[0] ? GRANULARITY : 0);
 
for(chunkT=1; chunkT<NUM_CHUNKS; chunkT=chunkT+1) begin : count_top_gen
assign still_counting_top[chunkT] = still_counting_top[chunkT-1] && no_flip[chunkT];
assign count_top_part[chunkT] = (still_counting_top[chunkT] ? GRANULARITY : 0) + count_top_part[chunkT-1];
end
 
assign count_top = (still_counting_top[NUM_CHUNKS-1] ? DWIDTH : // No flips found
count_top_part[NUM_CHUNKS-2]) + // Take the last value
(no_flip[0] ? (count_bottom_d1 == 0 ? 1 : count_bottom_d1) : 0); // Add the saved count
 
// Start at the bottom and count until a flip is found
assign still_counting_bottom[0] = no_flip[NUM_CHUNKS-1];
assign count_bottom_part[0] = 0;
 
for(chunkB=1; chunkB<NUM_CHUNKS; chunkB=chunkB+1) begin : count_bottom_gen
assign still_counting_bottom[chunkB] = still_counting_bottom[chunkB-1] && no_flip[NUM_CHUNKS-1-chunkB];
assign count_bottom_part[chunkB] = (still_counting_bottom[chunkB] ? GRANULARITY : 0) + count_bottom_part[chunkB-1];
end
 
assign count_bottom = still_counting_bottom[NUM_CHUNKS-1] ? DWIDTH + (count_bottom_d1 == 0 ? 1 : count_bottom_d1) : // No flips found + saved count
count_bottom_part[NUM_CHUNKS-2] + // Take the last value
(no_flip[NUM_CHUNKS-1] ? (REM_BITS ? REM_BITS : GRANULARITY) + 1 : 0); // Add the remainder
 
endgenerate
 
assign bit_flip = count_top > (RUN_LIMIT - (GRANULARITY-1) - (REM_BITS ? REM_BITS-1 : GRANULARITY-1));
 
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if (!res_n) begin
count_bottom_d1 <= { COUNT_BITS {1'b0}};
no_flip_bottom_d1 <= 1'b0;
data_in_bottom_d1 <= 1'b0;
rf_bit_flip <= 1'b0;
end else begin
count_bottom_d1 <= count_bottom;
no_flip_bottom_d1 <= no_flip[NUM_CHUNKS-1];
data_in_bottom_d1 <= data_in[DWIDTH-1];
rf_bit_flip <= bit_flip;
 
if (enable && bit_flip)
data_out <= {data_in[DWIDTH-1:1], ~data_in[0]};
else
data_out <= data_in;
end
end
 
endmodule
/openhmc/trunk/openHMC/rtl/hmc_controller/tx/tx_link.v
0,0 → 1,1309
/*
* .--------------. .----------------. .------------.
* | .------------. | .--------------. | .----------. |
* | | ____ ____ | | | ____ ____ | | | ______ | |
* | ||_ || _|| | ||_ \ / _|| | | .' ___ || |
* ___ _ __ ___ _ __ | | | |__| | | | | | \/ | | | |/ .' \_|| |
* / _ \| '_ \ / _ \ '_ \ | | | __ | | | | | |\ /| | | | || | | |
* (_) | |_) | __/ | | || | _| | | |_ | | | _| |_\/_| |_ | | |\ `.___.'\| |
* \___/| .__/ \___|_| |_|| ||____||____|| | ||_____||_____|| | | `._____.'| |
* | | | | | | | | | | | |
* |_| | '------------' | '--------------' | '----------' |
* '--------------' '----------------' '------------'
*
* openHMC - An Open Source Hybrid Memory Cube Controller
* (C) Copyright 2014 Computer Architecture Group - University of Heidelberg
* www.ziti.uni-heidelberg.de
* B6, 26
* 68159 Mannheim
* Germany
*
* Contact: openhmc@ziti.uni-heidelberg.de
* http://ra.ziti.uni-heidelberg.de/openhmc
*
* 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
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This source file is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* 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/>.
*
*
* Module name: tx_link
*
*/
 
`default_nettype none
 
module tx_link #(
parameter LOG_FPW = 2,
parameter FPW = 4,
parameter DWIDTH = 512,
parameter NUM_LANES = 8,
parameter HMC_PTR_SIZE = 8,
parameter HMC_RF_RWIDTH = 64
) (
 
//----------------------------------
//----SYSTEM INTERFACE
//----------------------------------
input wire clk,
input wire res_n,
 
//----------------------------------
//----TO HMC PHY
//----------------------------------
output wire [DWIDTH-1:0] phy_scrambled_data_out,
 
//----------------------------------
//----HMC IF
//----------------------------------
output reg hmc_LxRXPS,
input wire hmc_LxTXPS,
 
//----------------------------------
//----Input data
//----------------------------------
input wire [DWIDTH-1:0] d_in_data,
input wire [FPW-1:0] d_in_flit_is_hdr,
input wire [FPW-1:0] d_in_flit_is_tail,
input wire [FPW-1:0] d_in_flit_is_valid,
input wire d_in_empty,
input wire d_in_a_empty,
output reg d_in_shift_out,
 
//----------------------------------
//----RX Block
//----------------------------------
input wire rx_force_tx_retry,
input wire rx_error_abort_mode,
input wire rx_error_abort_mode_cleared,
input wire [HMC_PTR_SIZE-1:0] rx_hmc_frp,
input wire [HMC_PTR_SIZE-1:0] rx_rrp,
input wire [7:0] rx_returned_tokens,
input wire [LOG_FPW:0] rx_hmc_tokens_to_be_returned,
 
//----------------------------------
//----RF
//----------------------------------
//Monitoring 1-cycle set to increment
output reg rf_cnt_retry,
output reg [HMC_RF_RWIDTH-1:0] rf_sent_p,
output reg [HMC_RF_RWIDTH-1:0] rf_sent_np,
output reg [HMC_RF_RWIDTH-1:0] rf_sent_r,
output reg rf_run_length_bit_flip,
 
//Status
input wire rf_link_is_up,
input wire rf_hmc_received_init_null,
input wire rf_descramblers_aligned,
output wire [1:0] rf_tx_init_status,
output reg [9:0] rf_hmc_tokens_av,
output reg rf_hmc_is_in_sleep,
output reg [9:0] rf_rx_tokens_av,
 
//Control
input wire rf_hmc_sleep_requested,
//input wire rf_warm_reset,
input wire rf_hmc_init_cont_set,
input wire rf_scrambler_disable,
input wire rf_dbg_dont_send_tret,
input wire [9:0] rf_rx_buffer_rtc,
input wire [2:0] rf_first_cube_ID,
input wire [4:0] rf_irtry_to_send,
input wire rf_run_length_enable
 
);
 
`include "hmc_field_functions.h"
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------WIRING AND SIGNAL STUFF---------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
//------------------------------------------------------------------------------------General Assignments
localparam LANE_WIDTH = (DWIDTH/NUM_LANES);
localparam NULL_FLIT = {128{1'b0}};
 
integer i_f; //counts to FPW
integer i_t; //counts to number of TS1 packets in a word
 
//Packet command 3-MSB definition
localparam PKT_WRITE = 3'b001;
localparam PKT_MISC_WRITE = 3'b010;
localparam PKT_READ = 3'b110;
localparam PKT_MODE_READ = 3'b101;
localparam PKT_P_WRITE = 3'b011;
localparam PKT_MISC_P_WRITE = 3'b100;
 
//------------------------------------------------------------------------------------Scrambler
wire [14:0] seed_lane [15:0];
assign seed_lane[0] = (rf_scrambler_disable == 1'b0) ? 15'h4D56 : 15'h0;
assign seed_lane[1] = (rf_scrambler_disable == 1'b0) ? 15'h47FF : 15'h0;
assign seed_lane[2] = (rf_scrambler_disable == 1'b0) ? 15'h75B8 : 15'h0;
assign seed_lane[3] = (rf_scrambler_disable == 1'b0) ? 15'h1E18 : 15'h0;
assign seed_lane[4] = (rf_scrambler_disable == 1'b0) ? 15'h2E10 : 15'h0;
assign seed_lane[5] = (rf_scrambler_disable == 1'b0) ? 15'h3EB2 : 15'h0;
assign seed_lane[6] = (rf_scrambler_disable == 1'b0) ? 15'h4302 : 15'h0;
assign seed_lane[7] = (rf_scrambler_disable == 1'b0) ? 15'h1380 : 15'h0;
assign seed_lane[8] = (rf_scrambler_disable == 1'b0) ? 15'h3EB3 : 15'h0;
assign seed_lane[9] = (rf_scrambler_disable == 1'b0) ? 15'h2769 : 15'h0;
assign seed_lane[10] = (rf_scrambler_disable == 1'b0) ? 15'h4580 : 15'h0;
assign seed_lane[11] = (rf_scrambler_disable == 1'b0) ? 15'h5665 : 15'h0;
assign seed_lane[12] = (rf_scrambler_disable == 1'b0) ? 15'h6318 : 15'h0;
assign seed_lane[13] = (rf_scrambler_disable == 1'b0) ? 15'h6014 : 15'h0;
assign seed_lane[14] = (rf_scrambler_disable == 1'b0) ? 15'h077B : 15'h0;
assign seed_lane[15] = (rf_scrambler_disable == 1'b0) ? 15'h261F : 15'h0;
 
wire [NUM_LANES-1:0] bit_was_flipped;
 
//------------------------------------------------------------------------------------FSM and States
reg [3:0] state;
localparam TX_NULL_1 = 4'b0001;
localparam TX_TS1 = 4'b0010;
localparam TX_NULL_2 = 4'b0011;
localparam IDLE = 4'b1000;
localparam TX = 4'b1001;
localparam HMC_RTRY = 4'b1010;
localparam SLEEP = 4'b1011;
localparam WAIT_FOR_HMC = 4'b1100;
localparam LNK_RTRY = 4'b1101;
localparam FATAL_ERROR = 4'b1110;
 
assign rf_tx_init_status = state[3] ? 0 : state[1:0];
 
reg rtc_rx_initialize;
 
//------------------------------------------------------------------------------------DATA and ORDERING
//reorder incoming data to FLITs
wire [128-1:0] d_in_flit [FPW-1:0];
genvar f;
generate
for(f = 0; f < (FPW); f = f + 1) begin : reorder_input_data_to_flits
assign d_in_flit[f] = d_in_data[128-1+(f*128):f*128];
end
endgenerate
 
//Create a mask and an input buffer that is necessary if packet transmission is interrupted and packets remain untransmitted
reg d_in_use_buf;
reg [128-1:0] d_in_buf_flit [FPW-1:0];
reg [FPW-1:0] d_in_buf_flit_is_hdr;
reg [FPW-1:0] d_in_buf_flit_is_tail;
reg [FPW-1:0] d_in_buf_flit_is_valid;
 
//Reorder the data per lane
wire [DWIDTH-1:0] data_rdy;
wire [DWIDTH-1:0] data_to_scrambler;
 
genvar l,n;
generate
for(n = 0; n < NUM_LANES; n = n + 1) begin : reorder_data_to_lanes
for(l = 0; l < LANE_WIDTH; l = l + 1) begin
assign data_to_scrambler[l+n*LANE_WIDTH] = data_rdy[l*NUM_LANES+n];
end
end
endgenerate
 
//------------------------------------------------------------------------------------Init Regs
localparam TS1_SEQ_INC_VAL_PER_CYCLE = (NUM_LANES==8) ? FPW : (FPW/2);
localparam NUM_NULL_TO_SEND_BEFORE_IDLE = 63; //see HMC spec
 
wire [(NUM_LANES*4)-1:0] ts1_seq_part_reordered [TS1_SEQ_INC_VAL_PER_CYCLE-1:0]; //ts1 seq is 4 bits
reg [3:0] ts1_seq_nr_per_flit [TS1_SEQ_INC_VAL_PER_CYCLE-1:0];
wire [128-1:0] ts1_flit [FPW-1:0];
reg [5:0] num_init_nulls_sent;
 
generate
for(f = 0; f < TS1_SEQ_INC_VAL_PER_CYCLE; f = f + 1) begin : generate_lane_dependent_ts1_sequence
 
for(n=0; n<4; n=n+1) begin
assign ts1_seq_part_reordered[f][(n*NUM_LANES)+NUM_LANES-1:(n*NUM_LANES)] = {NUM_LANES{ts1_seq_nr_per_flit[f][n]}};
end
 
if(NUM_LANES==8) begin
 
assign ts1_flit[f] = {
32'hffffffff,32'h0,1'h1,7'h0,7'b1111111,1'h0,7'h0,1'h1,1'h0,7'b1111111,ts1_seq_part_reordered[f]
};
 
end else begin
 
assign ts1_flit[f*2] = {
64'hffffffffffffffff,64'h0
};
assign ts1_flit[f*2+1] = {
15'h7fff,1'h0,1'h1,16'h0,15'h7fff,15'h0,1'h1,ts1_seq_part_reordered[f]
};
 
end
 
end
endgenerate
 
//------------------------------------------------------------------------------------SEQ and FRP Stage
reg [128-1:0] data2seq_frp_stage_flit [FPW-1:0];
reg [128-1:0] data2seq_frp_stage_flit_comb [FPW-1:0];
reg [FPW-1:0] data2seq_frp_stage_flit_is_hdr;
reg [FPW-1:0] data2seq_frp_stage_flit_is_tail;
reg [FPW-1:0] data2seq_frp_stage_flit_is_valid;
reg [FPW-1:0] data2seq_frp_stage_flit_is_flow;
reg data2seq_frp_stage_force_tx_retry;
 
//------------------------------------------------------------------------------------Counter variables
reg [LOG_FPW:0] rf_sent_p_comb;
reg [LOG_FPW:0] rf_sent_np_comb;
reg [LOG_FPW:0] rf_sent_r_comb;
 
 
//------------------------------------------------------------------------------------SEQ and FRP Stage
reg [128-1:0] data2rtc_stage_flit [FPW-1:0];
reg [FPW-1:0] data2rtc_stage_flit_is_hdr;
reg [FPW-1:0] data2rtc_stage_flit_is_tail;
reg [FPW-1:0] data2rtc_stage_flit_is_valid;
reg [FPW-1:0] data2rtc_stage_flit_is_flow;
reg data2rtc_stage_force_tx_retry;
 
//------------------------------------------------------------------------------------RETRY
//HMC
//Amount of cycles to wait until start HMC retry is issued again (when RX error abort is not cleared)
localparam CYCLES_TO_CLEAR_ERR_ABORT_MODE = 250;
reg [7:0] error_abort_mode_clr_cnt;
reg force_hmc_retry;
reg [5:0] irtry_start_retry_cnt;
 
//Memory Controller
reg [5:0] irtry_clear_error_cnt;
wire [63:0] irtry_hdr;
assign irtry_hdr = {rf_first_cube_ID,3'h0,34'h0,9'h0,4'h1,4'h1,1'h0,6'b000011};
 
//------------------------------------------------------------------------------------Retry Buffer
reg [128-1:0] data2ram_flit [FPW-1:0];
reg [128-1:0] data2ram_flit_temp [FPW-1:0];
reg [FPW-1:0] data2ram_flit_is_hdr;
reg [FPW-1:0] data2ram_flit_is_tail;
reg [FPW-1:0] data2ram_flit_is_valid;
reg [FPW-1:0] data2ram_flit_is_flow;
reg data2ram_force_tx_retry;
 
localparam RAM_ADDR_SIZE = (FPW == 2) ? 7 :
(FPW == 4) ? 6 :
(FPW == 6) ? 5 :
(FPW == 8) ? 5 :
1;
 
reg ram_w_en, ram_r_en;
reg [RAM_ADDR_SIZE-1:0] ram_w_addr;
wire [RAM_ADDR_SIZE-1:0] ram_w_addr_next;
assign ram_w_addr_next = ram_w_addr + 1;
reg [RAM_ADDR_SIZE-1:0] ram_r_addr_temp;
reg [FPW-1:0] ram_r_mask;
wire [128+4-1:0] ram_r_data [FPW-1:0];
reg [128+4-1:0] ram_w_data [FPW-1:0];
 
wire [RAM_ADDR_SIZE-1:0] ram_r_addr;
assign ram_r_addr = rx_rrp[HMC_PTR_SIZE-1:HMC_PTR_SIZE-RAM_ADDR_SIZE];
 
//Avoid overwriting not acknowleged FLITs in the retry buffer
wire [RAM_ADDR_SIZE-1:0] ram_result;
assign ram_result = ram_r_addr - ram_w_addr_next;
 
//A safe value since ram_w_addr is calculated some cycles after packets were accepted
wire ram_full;
assign ram_full = (ram_result<8 && ram_result>0) ? 1'b1 : 1'b0 ;
 
 
//Header/Tail fields, and at the same time form the RAM read pointer
reg [RAM_ADDR_SIZE-1:0] tx_frp_adr;
reg [2:0] tx_seqnum;
reg tx_frp_adr_incr_temp;
reg [LOG_FPW:0] tx_seqnum_temp;
 
//variable to construct the frp
wire [HMC_PTR_SIZE-RAM_ADDR_SIZE-1:0] tx_frp_ram [FPW-1:0];
 
generate
for(f = 0; f < (FPW); f = f + 1) begin : assign_ram_addresses
assign tx_frp_ram[f] = f;
end
endgenerate
 
//Regs for TX Link retry handling
reg tx_retry_finished;
reg tx_retry_ongoing;
reg tx_link_retry_request; //Sample the retry request
 
//------------------------------------------------------------------------------------RRP Stage
reg [128-1:0] data2rrp_stage_flit [FPW-1:0];
reg [FPW-1:0] data2rrp_stage_flit_is_hdr;
reg [FPW-1:0] data2rrp_stage_flit_is_tail;
reg [FPW-1:0] data2rrp_stage_flit_is_valid;
reg [FPW-1:0] data2rrp_stage_flit_is_flow;
 
reg [7:0] last_transmitted_rx_hmc_frp;
 
//------------------------------------------------------------------------------------CRC
reg [128-1:0] data2crc_flit [FPW-1:0];
wire [DWIDTH-1:0] data2crc;
reg [FPW-1:0] data2crc_flit_is_hdr;
reg [FPW-1:0] data2crc_flit_is_tail;
 
generate
for(f = 0; f < (FPW); f = f + 1) begin : concatenate_flits_to_single_reg
assign data2crc[(f*128)+128-1:(f*128)] = data2crc_flit[f];
end
endgenerate
 
//------------------------------------------------------------------------------------FLOW PACKETS
//TRET
wire [63:0] tret_hdr;
assign tret_hdr = {rf_first_cube_ID,3'h0,34'h0,9'h0,4'h1,4'h1,1'h0,6'b000010};
//PRET
wire [63:0] pret_hdr ;
assign pret_hdr = {rf_first_cube_ID,3'h0,34'h0,9'h0,4'h1,4'h1,1'h0,6'b000001};
 
//------------------------------------------------------------------------------------RTC HANDLING
//RX input buffer token monitoring -
reg [6:0] sum_requested_tokens; //Count the amount of tokens requested from the HMC
reg [6:0] sum_requested_tokens_temp; //Use this register for combinational logic
reg [9:0] remaining_tokens;
 
//Registers for the RTC field in request packets
reg rtc_return;
reg [4:0] rtc_return_val;
reg rtc_return_sent;
 
//Return a maximum of 31 tokens
wire [4:0] outstanding_tokens_to_return;
assign outstanding_tokens_to_return = remaining_tokens > 31 ? 31 : remaining_tokens;
 
//A safe value to not send more FLITs than the HMC can buffer
wire hmc_tokens_av;
assign hmc_tokens_av = (rf_hmc_tokens_av > 8+(2*FPW)) ? 1'b1 : 1'b0;
reg [LOG_FPW:0] flits_transmitted;
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------LOGIC STARTS HERE---------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
 
//====================================================================
//---------------------------------MISC
//====================================================================
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
rf_run_length_bit_flip <= 1'b0;
end else begin
rf_run_length_bit_flip <= |bit_was_flipped;
end
end
 
//====================================================================
//---------------------------------Monitor Remaining Tokens in the RX input buffer, just a debug help
//====================================================================
//Track the remaining tokens in the rx input buffer. This is optional since the HMC must make sure not to send more tokens than RX can buffer, useful for debugging
always @(*) begin
sum_requested_tokens_temp = {7{1'b0}};
 
for(i_f=0;i_f<FPW;i_f=i_f+1) begin
 
if(data2rtc_stage_flit_is_hdr[i_f] && !is_flow(data2rtc_stage_flit[i_f])) begin
 
if(cmd_type(data2rtc_stage_flit[i_f]) == PKT_READ ||
cmd_type(data2rtc_stage_flit[i_f]) == PKT_MODE_READ ) begin
//it is either a data read or mode read
sum_requested_tokens_temp = sum_requested_tokens_temp + num_requested_flits(data2rtc_stage_flit[i_f]);
end else if( (cmd_type(data2rtc_stage_flit[i_f]) == PKT_WRITE) ||
(cmd_type(data2rtc_stage_flit[i_f]) == PKT_MISC_WRITE) ) begin
//it is not a posted transaction, so 1 token will be returned as response
sum_requested_tokens_temp = sum_requested_tokens_temp + 1;
end
 
end
end
end
 
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
sum_requested_tokens <= {7{1'b0}};
end else begin
sum_requested_tokens <= sum_requested_tokens_temp;
end
end
 
//Make sure the HMC has enough tokens in its input buffer left
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
rf_rx_tokens_av <= {10{1'b0}};
end else begin
if(state==TX_NULL_1)begin
//initialize token counts when HMC init is not done
rf_rx_tokens_av <= rf_rx_buffer_rtc;
end else begin
//calculate remaining tokens in RX buffers
rf_rx_tokens_av <= rf_rx_tokens_av + rx_hmc_tokens_to_be_returned - sum_requested_tokens;
end
end
end
 
//=======================================================================================================================
//---------------------------------ALL OTHER LOGIC HERE
//=======================================================================================================================
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
//----Data
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
data2rtc_stage_flit[i_f] <= {128{1'b0}};
end
data2rtc_stage_flit_is_hdr <= {FPW{1'b0}};
data2rtc_stage_flit_is_tail <= {FPW{1'b0}};
data2rtc_stage_flit_is_valid <= {FPW{1'b0}};
data2rtc_stage_flit_is_flow <= {FPW{1'b0}};
 
data2rtc_stage_force_tx_retry <= 1'b0;
d_in_shift_out <= 1'b0;
 
//----Reset the input buffer reg
d_in_buf_flit_is_hdr <= {FPW{1'b0}};
d_in_buf_flit_is_tail <= {FPW{1'b0}};
d_in_buf_flit_is_valid <= {FPW{1'b0}};
d_in_use_buf <= 1'b0;
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
d_in_buf_flit[i_f] <= {128{1'b0}};
end
 
//----Init Regs
for(i_t=0;i_t<TS1_SEQ_INC_VAL_PER_CYCLE;i_t=i_t+1) begin
ts1_seq_nr_per_flit[i_t] <= i_t;
end
num_init_nulls_sent <= {6{1'b0}};
 
//General
state <= TX_NULL_1;
rtc_rx_initialize <= 1'b1;
 
//Token Flow Control
remaining_tokens <= {10{1'b0}};
rtc_return_val <= {5{1'b0}};
rtc_return <= 1'b0;
 
//Retry
irtry_start_retry_cnt <= {6{1'b0}};
irtry_clear_error_cnt <= {6{1'b0}};
 
//HMC Control
hmc_LxRXPS <= 1'b1;
rf_hmc_is_in_sleep <= 1'b0;
 
//Flow Control
tx_link_retry_request <= 1'b0;
 
 
end
else begin
//====================================================================
//---------------------------------INIT
//====================================================================
//Reset control signals
d_in_shift_out <= 1'b0;
rtc_rx_initialize <= 1'b0;
 
//HMC Control
hmc_LxRXPS <= 1'b1;
rf_hmc_is_in_sleep <= 1'b0;
 
if(rx_force_tx_retry)begin
tx_link_retry_request <= 1'b1;
end
 
//Warm Reset
// if(rf_warm_reset) begin
// //in case of a warm reset request, continue at TX_NULL_2 sequence and intialize tokens to be returned
// state <= TX_NULL_2;
// num_init_nulls_sent <= {6{1'b0}};
// rtc_rx_initialize <= 1'b1;
// end
 
//RTC
rtc_return <= 1'b0;
//Initialize rtc to be transmitted after reset and warm reset
if(rtc_rx_initialize) begin
remaining_tokens <= rf_rx_buffer_rtc;
end else begin
remaining_tokens <= remaining_tokens + rx_hmc_tokens_to_be_returned;
end
 
//Reset information bits
data2rtc_stage_flit_is_hdr <= {FPW{1'b0}};
data2rtc_stage_flit_is_tail <= {FPW{1'b0}};
data2rtc_stage_flit_is_valid <= {FPW{1'b0}};
data2rtc_stage_flit_is_flow <= {FPW{1'b0}};
data2rtc_stage_force_tx_retry <= 1'b0;
 
case(state)
 
//---------------------------------INIT. Refer to Initialization section in the specification
 
TX_NULL_1: begin
 
num_init_nulls_sent <= {6{1'b0}};
 
//---State---
if(rf_hmc_received_init_null)begin
state <= TX_TS1;
end
 
end
 
TX_TS1: begin
 
data2rtc_stage_flit_is_flow <= {FPW{1'b1}};
 
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
data2rtc_stage_flit[i_f] <= ts1_flit[i_f];
end
 
for(i_t=0;i_t<TS1_SEQ_INC_VAL_PER_CYCLE;i_t=i_t+1) begin
ts1_seq_nr_per_flit[i_t] <= ts1_seq_nr_per_flit[i_t] + TS1_SEQ_INC_VAL_PER_CYCLE;
end
 
//---State---
if(rf_descramblers_aligned)begin
state <= TX_NULL_2;
end
 
end
 
TX_NULL_2: begin
 
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
data2rtc_stage_flit[i_f] <= NULL_FLIT;
end
 
//Issue at least 32 NULL FLITs before going active
if(num_init_nulls_sent+FPW > NUM_NULL_TO_SEND_BEFORE_IDLE) begin
if(rf_link_is_up)begin
state <= IDLE;
end
end else begin
num_init_nulls_sent <= num_init_nulls_sent + FPW;
end
 
end
 
//====================================================================
//---------------------------------Normal operation (including init TRETs)
//====================================================================
// Some branches to other states may be removed in HMC_RTRY for instance.
// Saves logic if an additional cycle in IDLE is acceptable
 
IDLE: begin
//Issue NULL Flits if there's nothing else to do
 
//SEND TRET PACKET even if there are no tokens available
if(remaining_tokens && !ram_full && !tx_retry_ongoing && !rf_dbg_dont_send_tret)begin
//RTC will be added in the RTC stage
data2rtc_stage_flit[0] <= {{64{1'b0}},tret_hdr};
data2rtc_stage_flit_is_hdr[0] <= 1'b1;
data2rtc_stage_flit_is_tail[0] <= 1'b1;
data2rtc_stage_flit_is_valid[0] <= 1'b1;
 
remaining_tokens <= remaining_tokens + rx_hmc_tokens_to_be_returned - outstanding_tokens_to_return;
rtc_return_val <= outstanding_tokens_to_return;
rtc_return <= 1'b1;
end
 
//---State---
if(force_hmc_retry) begin
state <= HMC_RTRY;
end else if(tx_link_retry_request) begin
state <= LNK_RTRY;
end else if(rf_hmc_sleep_requested) begin
state <= SLEEP;
end else if(!d_in_empty && !ram_full && hmc_tokens_av) begin
state <= TX;
d_in_shift_out <= ~d_in_use_buf;
end
 
end
 
TX: begin
//Get and transmit data
 
//First set control signals
d_in_use_buf <= 1'b0;
d_in_shift_out <= 1'b1;
 
//Fill the buffer
d_in_buf_flit_is_hdr <= d_in_flit_is_hdr;
d_in_buf_flit_is_tail <= d_in_flit_is_tail;
d_in_buf_flit_is_valid <= d_in_flit_is_valid;
 
//If there is data buffered - use it
data2rtc_stage_flit_is_hdr <= d_in_use_buf ? d_in_buf_flit_is_hdr : d_in_flit_is_hdr;
data2rtc_stage_flit_is_tail <= d_in_use_buf ? d_in_buf_flit_is_tail : d_in_flit_is_tail;
data2rtc_stage_flit_is_valid <= d_in_use_buf ? d_in_buf_flit_is_valid : d_in_flit_is_valid;
 
//Set RTC to be added in the next step
if( remaining_tokens &&
//if buffer should be used -> take buffered tail information
((d_in_use_buf && |d_in_buf_flit_is_tail) ||
//otherwise use regular data input
(!d_in_use_buf && |d_in_flit_is_tail))
) begin
remaining_tokens <= remaining_tokens + rx_hmc_tokens_to_be_returned - outstanding_tokens_to_return;
rtc_return_val <= outstanding_tokens_to_return;
rtc_return <= 1'b1;
end
 
 
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
//Choose the data source
data2rtc_stage_flit[i_f] <= !d_in_use_buf ? d_in_flit[i_f] : d_in_buf_flit[i_f];
//No matter what, fill the buffer
d_in_buf_flit[i_f] <= d_in_flit[i_f];
end
 
 
//Exit state if seen a tail and exit condition occured
if( ((!d_in_use_buf && |d_in_flit_is_tail) || (d_in_use_buf && |d_in_buf_flit_is_tail)) &&
(force_hmc_retry || ram_full || tx_link_retry_request || !hmc_tokens_av || d_in_a_empty)) begin
 
d_in_shift_out <= 1'b0;
 
if(force_hmc_retry) begin
state <= HMC_RTRY;
end else if(tx_link_retry_request) begin
state <= LNK_RTRY;
end else begin
state <= IDLE;
end
 
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
if((d_in_use_buf && d_in_buf_flit_is_tail[i_f]) || (!d_in_use_buf && d_in_flit_is_tail[i_f]))begin
data2rtc_stage_flit_is_valid <= {FPW{1'b1}} >> {FPW-1-i_f};
d_in_buf_flit_is_hdr <= d_in_flit_is_hdr & ({FPW{1'b1}} << (i_f + 1));
d_in_buf_flit_is_tail <= d_in_flit_is_tail & ({FPW{1'b1}} << (i_f + 1));
d_in_buf_flit_is_valid <= d_in_flit_is_valid & ({FPW{1'b1}} << (i_f + 1));
end
end
 
//Use buf next time TX state is entered if there is a packet pending
if((!d_in_use_buf && (d_in_flit_is_hdr > d_in_flit_is_tail)) ||
(d_in_use_buf && (d_in_buf_flit_is_hdr > d_in_buf_flit_is_tail)) )begin
d_in_use_buf <= 1'b1;
end
 
end
end
 
//---------------------------------An error in RX path occured - send irtry start packets
HMC_RTRY: begin
 
data2rtc_stage_flit_is_hdr <= {FPW{1'b1}};
data2rtc_stage_flit_is_tail <= {FPW{1'b1}};
data2rtc_stage_flit_is_valid <= {FPW{1'b1}};
data2rtc_stage_flit_is_flow <= {FPW{1'b1}};
 
for(i_f=0;i_f<FPW;i_f=i_f+1)begin //Send IRTRY start retry
data2rtc_stage_flit[i_f] <= {48'h0,8'b00000001,8'h00,irtry_hdr};
end
 
irtry_start_retry_cnt <= irtry_start_retry_cnt + FPW;
 
if(irtry_start_retry_cnt+FPW >= rf_irtry_to_send)begin
irtry_start_retry_cnt <= {6{1'b0}};
 
//---State---
if(tx_link_retry_request) begin
state <= LNK_RTRY;
end else if(!d_in_empty && !ram_full && hmc_tokens_av)begin
state <= TX;
d_in_shift_out <= ~d_in_use_buf;
end else begin
state <= IDLE;
end
end
 
end
 
 
//---------------------------------HMC sent start retry packets -
// re-send all valid packets in RAM after sending clear error packets
LNK_RTRY: begin
 
tx_link_retry_request <= 1'b0;
 
if(tx_link_retry_request || irtry_clear_error_cnt>0) begin
for(i_f=0;i_f<FPW;i_f=i_f+1)begin //Send IRTRY clear error abort
data2rtc_stage_flit[i_f] <= {48'h0,8'b00000010,8'h00,irtry_hdr};
end
data2rtc_stage_flit_is_hdr <= {FPW{1'b1}};
data2rtc_stage_flit_is_tail <= {FPW{1'b1}};
data2rtc_stage_flit_is_valid <= {FPW{1'b1}};
data2rtc_stage_flit_is_flow <= {FPW{1'b1}};
 
if(irtry_clear_error_cnt+FPW >= rf_irtry_to_send)begin
irtry_clear_error_cnt <= {6{1'b0}};
data2rtc_stage_force_tx_retry <= 1'b1;
end else begin
irtry_clear_error_cnt <= irtry_clear_error_cnt + FPW;
end
end
 
if(tx_retry_finished) begin
//---State---
if(force_hmc_retry) begin
state <= HMC_RTRY;
end else if(!d_in_empty && !ram_full && hmc_tokens_av) begin
state <= TX;
d_in_shift_out <= ~d_in_use_buf;
end else begin
state <= IDLE;
end
end
end
 
//---------------------------------Power State Management
SLEEP: begin
 
hmc_LxRXPS <= 1'b0;
 
if(!hmc_LxTXPS) begin
rf_hmc_is_in_sleep <= 1'b1;
end
 
if(!rf_hmc_sleep_requested) begin
state <= WAIT_FOR_HMC;
hmc_LxRXPS <= 1'b1;
end
 
end
 
WAIT_FOR_HMC: begin
 
rf_hmc_is_in_sleep <= 1'b1;
 
if(hmc_LxTXPS) begin
state <= TX_NULL_1;
end
 
end
 
endcase
 
if(!rf_hmc_init_cont_set) begin
state <= TX_NULL_1;
num_init_nulls_sent <= {6{1'b0}};
rtc_rx_initialize <= 1'b1;
end
end
end
 
//====================================================================
//---------------------------------HMC input buffer Token Handling
//====================================================================
//Count the tokens that were used and make sure the HMC has enough tokens in its input buffer left
//This always block remains combinational to save one cycle
always @(*) begin
 
flits_transmitted = {LOG_FPW+1{1'b0}};
 
if(d_in_shift_out)begin
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
flits_transmitted = flits_transmitted + d_in_flit_is_valid[i_f];
end
end
end
 
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
rf_hmc_tokens_av <= {10{1'b0}};
end else begin
rf_hmc_tokens_av <= rf_hmc_tokens_av + rx_returned_tokens - flits_transmitted;
end
end
 
//====================================================================
//---------------------------------Counter in the RF , right now only data transactions are counted
//====================================================================
always @(*) begin
 
rf_sent_p_comb = {LOG_FPW+1{1'b0}};
rf_sent_np_comb = {LOG_FPW+1{1'b0}};
rf_sent_r_comb = {LOG_FPW+1{1'b0}};
 
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
if(data2rtc_stage_flit_is_hdr[i_f])begin
//split into independent cases to avoid dependencies
//Instead of comparing the entire cmd field, try to reduce logic effort
 
if( data2rtc_stage_flit[i_f][3] ^ data2rtc_stage_flit[i_f][4]
//All non-posted types have either bit 3 or 4 in the cmd set, equal to:
//cmd_type(data2rtc_stage_flit[i_f])==PKT_READ ||
//cmd_type(data2rtc_stage_flit[i_f])==PKT_WRITE ||
//cmd_type(data2rtc_stage_flit[i_f])==PKT_MISC_WRITE ||
//cmd_type(data2rtc_stage_flit[i_f])==PKT_MODE_READ
) begin
//it is a non posted transaction
rf_sent_np_comb = rf_sent_np_comb + {{LOG_FPW{1'b0}},1'b1};
end
 
if(data2rtc_stage_flit[i_f][4] && data2rtc_stage_flit[i_f][5]
//Only reads have bit 4 and 5 set, equal to:
//cmd_type(data2rtc_stage_flit[i_f])==PKT_READ
) begin
//read
rf_sent_r_comb = rf_sent_r_comb + {{LOG_FPW{1'b0}},1'b1};
end
 
if(cmd_type(data2rtc_stage_flit[i_f])==PKT_P_WRITE)begin
// posted write
rf_sent_p_comb = rf_sent_p_comb + {{LOG_FPW{1'b0}},1'b1};
end
 
end
end
end
 
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
rf_sent_p <= {HMC_RF_RWIDTH{1'b0}};
rf_sent_np <= {HMC_RF_RWIDTH{1'b0}};
rf_sent_r <= {HMC_RF_RWIDTH{1'b0}};
end else begin
rf_sent_p <= rf_sent_p + {{HMC_RF_RWIDTH-LOG_FPW-1{1'b0}},rf_sent_p_comb};
rf_sent_np <= rf_sent_np + {{HMC_RF_RWIDTH-LOG_FPW-1{1'b0}},rf_sent_np_comb};
rf_sent_r <= rf_sent_r + {{HMC_RF_RWIDTH-LOG_FPW-1{1'b0}},rf_sent_r_comb};
end
end
 
//====================================================================
//---------------------------------HMC Retry Logic
//====================================================================
//Monitor RX error abort mode - if the timer expires send another series of start retry packets
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
 
if(!res_n) begin
error_abort_mode_clr_cnt <= {8{1'b0}};
force_hmc_retry <= 1'b0;
end else begin
 
if(rx_error_abort_mode)begin
error_abort_mode_clr_cnt <= error_abort_mode_clr_cnt + 1;
end
 
if(rx_error_abort_mode_cleared || !rf_hmc_init_cont_set) begin
error_abort_mode_clr_cnt <= {8{1'b0}};
end
 
if((rx_error_abort_mode && state!=HMC_RTRY && error_abort_mode_clr_cnt==0) || (error_abort_mode_clr_cnt > CYCLES_TO_CLEAR_ERR_ABORT_MODE))begin
force_hmc_retry <= 1'b1;
error_abort_mode_clr_cnt <= {8{1'b0}};
end else begin
if(state==HMC_RTRY)begin
force_hmc_retry <= 1'b0;
end
end
 
end
end
 
//====================================================================
//---------------------------------RTC Stage
//====================================================================
always @(*) begin
rtc_return_sent = 0;
 
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
data2seq_frp_stage_flit_comb[i_f] = data2rtc_stage_flit[i_f];
 
if(data2rtc_stage_flit_is_tail[i_f] && !data2rtc_stage_flit_is_flow[i_f] && !rtc_return_sent && rtc_return) begin
//Return outstanding tokens, but only once per cycle
data2seq_frp_stage_flit_comb[i_f][64+31:64+27] = rtc_return_val;
rtc_return_sent = 1'b1;
end
end
end
 
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
data2seq_frp_stage_flit_is_hdr <= {FPW{1'b0}};
data2seq_frp_stage_flit_is_tail <= {FPW{1'b0}};
data2seq_frp_stage_flit_is_valid <= {FPW{1'b0}};
data2seq_frp_stage_flit_is_flow <= {FPW{1'b0}};
data2seq_frp_stage_force_tx_retry <= 1'b0;
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
data2seq_frp_stage_flit[i_f] <= {128{1'b0}};
end
end else begin
data2seq_frp_stage_flit_is_hdr <= data2rtc_stage_flit_is_hdr & data2rtc_stage_flit_is_valid;
data2seq_frp_stage_flit_is_tail <= data2rtc_stage_flit_is_tail & data2rtc_stage_flit_is_valid;
data2seq_frp_stage_flit_is_valid <= data2rtc_stage_flit_is_valid;
data2seq_frp_stage_flit_is_flow <= data2rtc_stage_flit_is_flow;
data2seq_frp_stage_force_tx_retry <= data2rtc_stage_force_tx_retry;
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
data2seq_frp_stage_flit[i_f] <= data2seq_frp_stage_flit_comb[i_f];
end
end
end
 
//====================================================================
//---------------------------------Seqnum and FRP Stage
//====================================================================
always @(*) begin
tx_seqnum_temp = {LOG_FPW+1{1'b0}};
 
//Set data flits
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
if(data2seq_frp_stage_flit_is_valid[i_f] | data2seq_frp_stage_flit_is_flow[i_f]) begin
data2ram_flit_temp[i_f] = data2seq_frp_stage_flit[i_f];
end else begin
data2ram_flit_temp[i_f] = {128{1'b0}};
end
end
 
//Increment ram addr(also frp) if there is a valid FLIT that is not flow
if(|(data2seq_frp_stage_flit_is_valid & ~data2seq_frp_stage_flit_is_flow))begin
tx_frp_adr_incr_temp = 1'b1;
end else begin
tx_frp_adr_incr_temp = 1'b0;
end
 
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
if(data2seq_frp_stage_flit_is_tail[i_f] && !data2seq_frp_stage_flit_is_flow[i_f] && data2seq_frp_stage_flit_is_valid[i_f])begin
tx_seqnum_temp = tx_seqnum_temp + 1;
//Assign the FRP, combined of the ram selected and the RAM address
data2ram_flit_temp[i_f][64+15+3:64+8] = {tx_seqnum+tx_seqnum_temp,tx_frp_adr+tx_frp_adr_incr_temp,tx_frp_ram[i_f]};
end
end
end
 
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
//Reset frp and seqnum
tx_frp_adr <= {LOG_FPW{1'b0}};
tx_seqnum <= {LOG_FPW{1'b0}};
end else begin
tx_frp_adr <= tx_frp_adr + tx_frp_adr_incr_temp;
tx_seqnum <= tx_seqnum + tx_seqnum_temp;
end
end
 
//Constant propagation, no need for reset condition
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
data2ram_flit_is_hdr <= {FPW{1'b0}};
data2ram_flit_is_tail <= {FPW{1'b0}};
data2ram_flit_is_valid <= {FPW{1'b0}};
data2ram_flit_is_flow <= {FPW{1'b0}};
data2ram_force_tx_retry <= 1'b0;
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
data2ram_flit[i_f] <= {128{1'b0}};
end
end else begin
data2ram_flit_is_hdr <= data2seq_frp_stage_flit_is_hdr;
data2ram_flit_is_tail <= data2seq_frp_stage_flit_is_tail;
data2ram_flit_is_valid <= data2seq_frp_stage_flit_is_valid;
data2ram_flit_is_flow <= data2seq_frp_stage_flit_is_flow ;
data2ram_force_tx_retry <= data2seq_frp_stage_force_tx_retry;
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
data2ram_flit[i_f] <= data2ram_flit_temp[i_f];
end
end
end
 
//====================================================================
//---------------------------------Fill RAM
//====================================================================
//-- Always assign FLITs to RAM write register
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
ram_w_data[i_f] <= {128+4{1'b0}};
end
 
end else begin
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
if(!data2ram_flit_is_flow[i_f])begin
ram_w_data[i_f] <= { data2ram_flit_is_flow[i_f],
data2ram_flit_is_valid[i_f],
data2ram_flit_is_tail[i_f],
data2ram_flit_is_hdr[i_f],
data2ram_flit[i_f]
};
end
end
end
end
 
//-- Write to RAM and increment the address if there are valid FLITs to be written
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
//Reset control signals
ram_w_addr <= {RAM_ADDR_SIZE{1'b0}};
ram_w_en <= 1'b1;
end else begin
 
//Reset control signals
ram_w_en <= 1'b0;
 
if(|(data2ram_flit_is_valid & ~data2ram_flit_is_flow)) begin
ram_w_addr <= ram_w_addr + 1;
ram_w_en <= 1'b1;
end
 
end
end
 
//====================================================================
//---------------------------------Select Data Source: Valid sources are the Retry Buffers or regular data stream.
//====================================================================
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
//Reset control signals
tx_retry_finished <= 1'b0;
tx_retry_ongoing <= 1'b0;
rf_cnt_retry <= 1'b0;
 
//Ram
ram_r_en <= 1'b0;
ram_r_addr_temp <= {RAM_ADDR_SIZE{1'b0}};
ram_r_mask <= {FPW{1'b1}};
 
//Data propagation
data2rrp_stage_flit_is_hdr <= {FPW{1'b0}};
data2rrp_stage_flit_is_tail <= {FPW{1'b0}};
data2rrp_stage_flit_is_valid <= {FPW{1'b0}};
data2rrp_stage_flit_is_flow <= {FPW{1'b0}};
 
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
data2rrp_stage_flit[i_f] <= {128{1'b0}};
end
 
end else begin
tx_retry_finished <= 1'b0;
rf_cnt_retry <= 1'b0;
 
//if there is a retry request coming set the ram address to last received rrp
if(data2rtc_stage_force_tx_retry) begin
ram_r_en <= 1'b1;
ram_r_addr_temp <= ram_r_addr;
ram_r_mask <= ({FPW{1'b1}}) << (rx_rrp[HMC_PTR_SIZE-RAM_ADDR_SIZE-1:0]);
end
 
if(!tx_retry_ongoing) begin
 
//Propagate data from normal packet stream
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
data2rrp_stage_flit[i_f] <= data2ram_flit[i_f];
end
data2rrp_stage_flit_is_hdr <= data2ram_flit_is_hdr;
data2rrp_stage_flit_is_tail <= data2ram_flit_is_tail;
data2rrp_stage_flit_is_valid <= data2ram_flit_is_valid;
data2rrp_stage_flit_is_flow <= data2ram_flit_is_flow;
 
 
//Switch to retry if requested
if(data2ram_force_tx_retry) begin
 
if(ram_r_addr_temp == ram_w_addr_next) begin //if the next address is the write address -> no retry. That should never happen
tx_retry_finished <= 1'b1;
tx_retry_ongoing <= 1'b0;
ram_r_en <= 1'b0;
end else begin
ram_r_addr_temp <= ram_r_addr_temp + 1;
rf_cnt_retry <= 1'b1;
tx_retry_ongoing <= 1'b1;
end
end
end else begin
//-- If there's a TX retry ongoing increment read addr until it equals the write address
 
ram_r_mask <= {FPW{1'b1}};
 
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
if(ram_r_mask[i_f])begin
//Within the first cycle of retry, choose only the proper flit sources
data2rrp_stage_flit[i_f] <= ram_r_data[i_f][128-1:0];
data2rrp_stage_flit_is_hdr[i_f] <= ram_r_data[i_f][128];
data2rrp_stage_flit_is_tail[i_f] <= ram_r_data[i_f][128+1];
data2rrp_stage_flit_is_valid[i_f] <= ram_r_data[i_f][128+2];
data2rrp_stage_flit_is_flow[i_f] <= ram_r_data[i_f][128+3];
end else begin
//And reset all other FLITs because they're not meant to be retransmitted
data2rrp_stage_flit[i_f] <= {128{1'b0}};
data2rrp_stage_flit_is_hdr[i_f] <= 1'b0;
data2rrp_stage_flit_is_tail[i_f] <= 1'b0;
data2rrp_stage_flit_is_valid[i_f] <= 1'b0;
data2rrp_stage_flit_is_flow[i_f] <= 1'b0;
end
end
 
//if the next address is the write address -> retry finished
if((ram_r_addr_temp) == ram_w_addr_next) begin
tx_retry_finished <= 1'b1;
tx_retry_ongoing <= 1'b0;
ram_r_en <= 1'b0;
end else begin
ram_r_addr_temp <= ram_r_addr_temp + 1;
end
 
end
 
end
end
 
//====================================================================
//---------------------------------Add RRP
//====================================================================
`ifdef ASYNC_RES
always @(posedge clk or negedge res_n) begin `else
always @(posedge clk) begin `endif
if(!res_n) begin
//----Reset control signals
last_transmitted_rx_hmc_frp <= {HMC_PTR_SIZE{1'b0}};
 
//----Data
data2crc_flit_is_hdr <= {FPW{1'b0}};
data2crc_flit_is_tail <= {FPW{1'b0}};
 
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
data2crc_flit[i_f] <= {128{1'b0}};
end
 
end else begin
 
//Propagate signals
data2crc_flit_is_hdr <= data2rrp_stage_flit_is_hdr;
data2crc_flit_is_tail <= data2rrp_stage_flit_is_tail;
 
for(i_f=0;i_f<FPW;i_f=i_f+1)begin
 
data2crc_flit[i_f] <= data2rrp_stage_flit[i_f];
 
//Add the RRP
if(data2rrp_stage_flit_is_tail[i_f])begin
data2crc_flit[i_f][64+7:64] <= rx_hmc_frp;
end
 
//Increment the FRP by 1, It points to the next possible FLIT position -> retry will start there
if(data2rrp_stage_flit_is_tail[i_f] && !data2rrp_stage_flit_is_flow[i_f])begin
data2crc_flit[i_f][64+15:64+8] <= data2rrp_stage_flit[i_f][64+15:64+8] + 1;
end
 
end
 
//If there is a tail, remember the last transmitted RRP. Otherwise generate PRET if there is a new RRP
if(|data2rrp_stage_flit_is_tail)begin
last_transmitted_rx_hmc_frp <= rx_hmc_frp;
end else if((last_transmitted_rx_hmc_frp != rx_hmc_frp) && !(|data2rrp_stage_flit_is_valid))begin //else send a PRET
data2crc_flit_is_hdr[0] <= 1'b1;
data2crc_flit_is_tail[0] <= 1'b1;
data2crc_flit[0][63:0] <= pret_hdr;
data2crc_flit[0][64+7:64] <= rx_hmc_frp;
last_transmitted_rx_hmc_frp <= rx_hmc_frp;
end
 
end
end
 
//=====================================================================================================
//-----------------------------------------------------------------------------------------------------
//---------INSTANTIATIONS HERE-------------------------------------------------------------------------
//-----------------------------------------------------------------------------------------------------
//=====================================================================================================
 
//Retry Buffer
generate
for(f=0;f<FPW;f=f+1)begin : retry_buffer_gen
hmc_ram #(
.DATASIZE(128+4), //FLIT + flow/valid/hdr/tail indicator
.ADDRSIZE(RAM_ADDR_SIZE)
)
retry_buffer_per_lane_I
(
.clk(clk),
.wen(ram_w_en),
.wdata(ram_w_data[f]),
.waddr(ram_w_addr),
.ren(ram_r_en),
.raddr(ram_r_addr_temp),
.rdata(ram_r_data[f])
);
end
endgenerate
 
//HMC CRC Logic
tx_crc_combine #(
.DWIDTH(DWIDTH),
.FPW(FPW),
.LOG_FPW(LOG_FPW)
)
tx_crc_combine_I
(
.clk(clk),
.res_n(res_n),
.d_in_hdr(data2crc_flit_is_hdr),
.d_in_tail(data2crc_flit_is_tail),
.d_in_data(data2crc),
.d_out_data(data_rdy)
);
 
//Scrambler
generate
for(n=0;n<NUM_LANES;n=n+1) begin : scrambler_gen
tx_scrambler #(
.DWIDTH(LANE_WIDTH)
)
scrambler_I
(
.clk(clk),
.res_n(res_n),
.load_lfsr(rf_scrambler_disable),
.seed(seed_lane[n]), // unique per lane
.data_in(data_to_scrambler[n*LANE_WIDTH+LANE_WIDTH-1:n*LANE_WIDTH]),
.data_out(phy_scrambled_data_out[n*LANE_WIDTH+LANE_WIDTH-1:n*LANE_WIDTH]),
.rf_run_length_enable(rf_run_length_enable),
.rf_run_length_bit_flip(bit_was_flipped[n])
);
end
endgenerate
 
 
 
endmodule
`default_nettype wire
/openhmc/trunk/openHMC/LICENSE
0,0 → 1,166
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
 
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
 
 
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
 
0. Additional Definitions.
 
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
 
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
 
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
 
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
 
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
 
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
 
1. Exception to Section 3 of the GNU GPL.
 
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
 
2. Conveying Modified Versions.
 
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
 
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
 
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
 
3. Object Code Incorporating Material from Library Header Files.
 
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
 
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
 
b) Accompany the object code with a copy of the GNU GPL and this license
document.
 
4. Combined Works.
 
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
 
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
 
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
 
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
 
d) Do one of the following:
 
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
 
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
 
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
 
5. Combined Libraries.
 
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
 
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
 
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
 
6. Revised Versions of the GNU Lesser General Public License.
 
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
 
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
 
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
 
/openhmc/trunk/openHMC/doc/openHMC_documentation_rev1_2.pdf Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
openhmc/trunk/openHMC/doc/openHMC_documentation_rev1_2.pdf Property changes : Added: svn:mime-type ## -0,0 +1 ## +application/octet-stream \ No newline at end of property

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.