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