UberDDR3/rtl/ecc/ecc_enc.sv

220 lines
7.9 KiB
Systemverilog

/////////////////////////////////////////////////////////////////////
// ,------. ,--. ,--. //
// | .--. ' ,---. ,--,--. | | ,---. ,---. `--' ,---. //
// | '--'.'| .-. |' ,-. | | | | .-. | .-. |,--.| .--' //
// | |\ \ ' '-' '\ '-' | | '--.' '-' ' '-' || |\ `--. //
// `--' '--' `---' `--`--' `-----' `---' `- /`--' `---' //
// `---' //
// Error Correction and Detection Encoder //
// Parameterized Extended Hamming Code Encoder //
// //
/////////////////////////////////////////////////////////////////////
// //
// Copyright (C) 2017 ROA Logic BV //
// www.roalogic.com //
// //
// This source file may be used and distributed without //
// restriction provided that this copyright statement is not //
// removed from the file and that any derivative work contains //
// the original copyright notice and the associated disclaimer. //
// //
// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY //
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED //
// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS //
// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR OR //
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, //
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT //
// NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; //
// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) //
// HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN //
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR //
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS //
// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. //
// //
/////////////////////////////////////////////////////////////////////
// +FHDR - Semiconductor Reuse Standard File Header Section -------
// FILE NAME : ecc_enc.sv
// DEPARTMENT :
// AUTHOR : rherveille
// AUTHOR'S EMAIL :
// ------------------------------------------------------------------
// RELEASE HISTORY
// VERSION DATE AUTHOR DESCRIPTION
// 1.0 2017-04-07 rherveille initial release
// ------------------------------------------------------------------
// KEYWORDS : HAMMING ERROR CORRECTION ENCODER
// ------------------------------------------------------------------
// PURPOSE : Adds ECC bits to incoming data
// ------------------------------------------------------------------
// PARAMETERS
// PARAM NAME RANGE DESCRIPTION DEFAULT UNITS
// K 1+ Information vector size 8
// P0_LSB 0,1 0: p0 located at MSB 1
// 1: p0 located at LSB
// ------------------------------------------------------------------
// REUSE ISSUES
// Reset Strategy : none
// Clock Domains : none
// Critical Timing :
// Test Features : na
// Asynchronous I/F : yes
// Scan Methodology : na
// Instantiations : none
// Synthesizable (y/n) : Yes
// Other :
// -FHDR-------------------------------------------------------------
//-----------------------------------------------------------------------------
// Hamming codes can detect and correct a single bit error.
// An extended Hamming code allows detection of double bit errors and
// correction of single bit errors.
// This is called SECDED; Single Error Correction, Double Error Detection
//
// Number of bits required by a Hamming code: n = m + k
// n = code length
// m = number of check bits
// k = number of information bits
//
// Information, parity, and syndrome expressed as vectors:
// u = Information bit vector
// p = Parity check bit vector
// s = Syndrome vector
//
// The parity vector is encoded in 'n'.
// The information bit vector is part of 'p'
// The syndrome vector needs to be calculated.
//
// Bits required:
// p ranges from 0 to m+k; or p_range=m+k+1
// As a result 2^m >= m+k+1
//-----------------------------------------------------------------------------
module ecc_enc #(
parameter K = 8, //Information bit vector size
parameter P0_LSB = 1, //0: p0 is located at MSB
//1: p0 is located at LSB
//these should be localparams
parameter m = calculate_m(K),
parameter n = m + K
)
(
input [K-1:0] d_i, //information bit vector input
output [n :0] q_o, //encoded data word output
output [m :1] p_o, //parity vector output
output p0_o //extended parity bit
);
//---------------------------------------------------------
// Functions
//---------------------------------------------------------
function integer calculate_m;
input integer k;
integer m_local;
begin
m_local=1;
while (2**m_local < m_local+k+1) m_local++;
calculate_m = m_local;
end
endfunction //calculate_m
function [n:1] store_dbits_in_codeword;
input [K-1:0] d;
integer bit_idx, cw_idx;
begin
//This function puts the information bits vector in the correct location
//Information bits are stored in non-power-of-2 locations
//clear all bits
store_dbits_in_codeword = 0;
bit_idx=0; //information vector bit index
for (cw_idx=1; cw_idx<=n; cw_idx++)
if (2**$clog2(cw_idx) != cw_idx)
/* verilator lint_off UNUSEDSIGNAL */
store_dbits_in_codeword[cw_idx] = d[bit_idx++];
/* verilator lint_on UNUSEDSIGNAL */
end
endfunction //store_dbits_in_codeword
function [m:1] calculate_p;
input [n:1] cw;
integer p_idx, cw_idx;
begin
//clear p
calculate_p = 0;
for (p_idx =1; p_idx <=m; p_idx++) //parity-index
for (cw_idx=1; cw_idx<=n; cw_idx++) //codeword-index
if (|(2**(p_idx-1) & cw_idx)) calculate_p[p_idx] = calculate_p[p_idx] ^ cw[cw_idx];
end
endfunction //calculate_p
function [n:1] store_p_in_codeword;
input [n:1] cw;
input [m:1] p;
integer i;
begin
//databits don't change ... copy into codeword
store_p_in_codeword = cw;
//put parity vector at power-of-2 locations
for (i=1; i<=m; i=i+1)
store_p_in_codeword[2**(i-1)] = p[i];
end
endfunction //store_p_in_codeword
//---------------------------------------------------------
// Variables
//---------------------------------------------------------
logic [n:1] cw_w_dbits; //codeword with loaded data bits
logic [n:1] cw; //codeword with information + parity bits
//---------------------------------------------------------
// Module Body
//---------------------------------------------------------
/*
Below diagram indicates the locations of the parity and data bits
in the final 'p' vector.
It also shows what databits each parity bit operates on
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
p1 p2 d1 p4 d2 d3 d4 p8 d5 d6 d7 d8 d9 d10 d11
p1 x x x x x x x x
p2 x x x x x x x x
p4 x x x x x x x x
p8 x x x x x x x x
*/
//Step 1: Load all databits in codeword
assign cw_w_dbits = store_dbits_in_codeword(d_i);
//Step 2: Calculate p-vector
assign p_o = calculate_p(cw_w_dbits);
//Step 3: Store p-vector in codeword
assign cw = store_p_in_codeword(cw_w_dbits, p_o);
//Step 4: Calculate p0 (extended parity bit)
// and store it in the codeword
assign p0_o = ^cw;
assign q_o = P0_LSB ? {cw,p0_o} : {p0_o,cw};
endmodule