📄 ecc_generate.cpp
字号:
// Copyright 2007 Altera Corporation. All rights reserved.
// Altera products are protected under numerous U.S. and foreign patents,
// maskwork rights, copyrights and other intellectual property laws.
//
// This reference design file, and your use thereof, is subject to and governed
// by the terms and conditions of the applicable Altera Reference Design
// License Agreement (either as signed by you or found at www.altera.com). By
// using this reference design file, you indicate your acceptance of such terms
// and conditions between you and Altera Corporation. In the event that you do
// not agree with such terms and conditions, you may not use the reference
// design file and please promptly destroy any copies you have made.
//
// This reference design file is being provided on an "as-is" basis and as an
// accommodation and therefore all warranties, representations or guarantees of
// any kind (whether express, implied or statutory) including, without
// limitation, warranties of merchantability, non-infringement, or fitness for
// a particular purpose, are specifically disclaimed. By making this reference
// design file available, Altera expressly does not recommend, suggest or
// require that this reference design file be used in combination with any
// other product not provided by Altera.
/////////////////////////////////////////////////////////////////////////////
// baeckler - 07-06-2006
// reved to be more parameterized 08-25-2006
//
// Build verilog factored XORs for error correction encode
// matrix. Not very fancy because there isn't any good reuse
// to be had on the depth 2 6-LUT solution. Needs a bit of
// hand balancing to reflect smaller luts being cheaper.
//
// And then the decoder and appropriate helper modules. Variable
// latency controlled by parameters.
#include <stdio.h>
// 64 -> 72 (8)
// 32 -> 39 (7)
// 16 -> 22 (6)
// 8 -> 13 (5)
int const DATA_BITS = 8;
int const SYN_BITS = 5;
int const TOTAL_BITS = DATA_BITS + SYN_BITS;
unsigned char matrix[64][72+1] =
{
"11100000000000000000000000000000000000000000000000000000000000000000000",
"10011000000000000000000000000000000000000000000000000000000000000000000",
"01010100000000000000000000000000000000000000000000000000000000000000000",
"11010010000000000000000000000000000000000000000000000000000000000000000",
"10000001100000000000000000000000000000000000000000000000000000000000000",
"01000001010000000000000000000000000000000000000000000000000000000000000",
"11000001001000000000000000000000000000000000000000000000000000000000000",
"00010001000100000000000000000000000000000000000000000000000000000000000",
"10010001000010000000000000000000000000000000000000000000000000000000000",
"01010001000001000000000000000000000000000000000000000000000000000000000",
"11010001000000100000000000000000000000000000000000000000000000000000000",
"10000000000000011000000000000000000000000000000000000000000000000000000",
"01000000000000010100000000000000000000000000000000000000000000000000000",
"11000000000000010010000000000000000000000000000000000000000000000000000",
"00010000000000010001000000000000000000000000000000000000000000000000000",
"10010000000000010000100000000000000000000000000000000000000000000000000",
"01010000000000010000010000000000000000000000000000000000000000000000000",
"11010000000000010000001000000000000000000000000000000000000000000000000",
"00000001000000010000000100000000000000000000000000000000000000000000000",
"10000001000000010000000010000000000000000000000000000000000000000000000",
"01000001000000010000000001000000000000000000000000000000000000000000000",
"11000001000000010000000000100000000000000000000000000000000000000000000",
"00010001000000010000000000010000000000000000000000000000000000000000000",
"10010001000000010000000000001000000000000000000000000000000000000000000",
"01010001000000010000000000000100000000000000000000000000000000000000000",
"11010001000000010000000000000010000000000000000000000000000000000000000",
"10000000000000000000000000000001100000000000000000000000000000000000000",
"01000000000000000000000000000001010000000000000000000000000000000000000",
"11000000000000000000000000000001001000000000000000000000000000000000000",
"00010000000000000000000000000001000100000000000000000000000000000000000",
"10010000000000000000000000000001000010000000000000000000000000000000000",
"01010000000000000000000000000001000001000000000000000000000000000000000",
"11010000000000000000000000000001000000100000000000000000000000000000000",
"00000001000000000000000000000001000000010000000000000000000000000000000",
"10000001000000000000000000000001000000001000000000000000000000000000000",
"01000001000000000000000000000001000000000100000000000000000000000000000",
"11000001000000000000000000000001000000000010000000000000000000000000000",
"00010001000000000000000000000001000000000001000000000000000000000000000",
"10010001000000000000000000000001000000000000100000000000000000000000000",
"01010001000000000000000000000001000000000000010000000000000000000000000",
"11010001000000000000000000000001000000000000001000000000000000000000000",
"00000000000000010000000000000001000000000000000100000000000000000000000",
"10000000000000010000000000000001000000000000000010000000000000000000000",
"01000000000000010000000000000001000000000000000001000000000000000000000",
"11000000000000010000000000000001000000000000000000100000000000000000000",
"00010000000000010000000000000001000000000000000000010000000000000000000",
"10010000000000010000000000000001000000000000000000001000000000000000000",
"01010000000000010000000000000001000000000000000000000100000000000000000",
"11010000000000010000000000000001000000000000000000000010000000000000000",
"00000001000000010000000000000001000000000000000000000001000000000000000",
"10000001000000010000000000000001000000000000000000000000100000000000000",
"01000001000000010000000000000001000000000000000000000000010000000000000",
"11000001000000010000000000000001000000000000000000000000001000000000000",
"00010001000000010000000000000001000000000000000000000000000100000000000",
"10010001000000010000000000000001000000000000000000000000000010000000000",
"01010001000000010000000000000001000000000000000000000000000001000000000",
"11010001000000010000000000000001000000000000000000000000000000100000000",
"10000000000000000000000000000000000000000000000000000000000000011000000",
"01000000000000000000000000000000000000000000000000000000000000010100000",
"11000000000000000000000000000000000000000000000000000000000000010010000",
"00010000000000000000000000000000000000000000000000000000000000010001000",
"10010000000000000000000000000000000000000000000000000000000000010000100",
"01010000000000000000000000000000000000000000000000000000000000010000010",
"11010000000000000000000000000000000000000000000000000000000000010000001"
};
void dump_ecc_coder (FILE * f)
{
int x=0,y=0;
int num_terms = 0;
int lutsize = 6;
int n=0,i=0,num_helpers=0,num_ins_this_helper=0;
fprintf (f,"// baeckler - 08-25-2006 \n\n");
fprintf (f,"//////////////////////////////////////////\n");
fprintf (f,"// %d bit to %d bit ECC encoder\n",DATA_BITS,TOTAL_BITS);
fprintf (f,"//////////////////////////////////////////\n\n");
fprintf (f,"module ecc_encode_%dbit (d,c);\n\n",DATA_BITS);
fprintf (f,"input [%d:0] d;\n",DATA_BITS-1);
fprintf (f,"output [%d:0] c;\n",TOTAL_BITS-1);
fprintf (f,"wire [%d:0] c;\n\n",TOTAL_BITS-1);
// the MSB of the code is the parity of the other code outs.
// re-express it in terms of the data inputs in the MSB postion
// of the matrix.
for (y=0; y<DATA_BITS; y++)
{
matrix[y][TOTAL_BITS-1] = '0';
matrix[y][TOTAL_BITS] = 0;
}
for (x=0; x<(TOTAL_BITS-1); x++)
{
for (y=0; y<DATA_BITS; y++)
{
if (matrix[y][x] == '1') matrix[y][TOTAL_BITS-1] ^= 1;
}
}
// the first TOTAL_BITS-1 bits are in the matrix, last is parity
for (x=0; x<TOTAL_BITS; x++)
{
// count the number of 1's
num_terms = 0;
for (y=0; y<DATA_BITS; y++)
{
if (matrix[y][x] == '1')
{
num_terms++;
}
}
if (num_terms < lutsize)
{
// this is fine - just dump it
num_terms = 0;
fprintf (f," assign c[%d] = ",x);
for (y=0; y<DATA_BITS; y++)
{
if (matrix[y][x] == '1')
{
if (num_terms != 0) fprintf (f," ^ ");
fprintf (f,"d[%d]",y);
num_terms++;
}
}
fprintf (f,";\n");
}
else
{
// create helpers
num_helpers = num_terms / lutsize;
if (num_helpers * lutsize < num_terms) num_helpers++;
fprintf (f," wire [%d:0] help_c%d;\n",num_helpers-1,x);
y = 0;
for (n=0; n<num_helpers; n++)
{
num_ins_this_helper = lutsize;
if (num_terms < num_ins_this_helper)
{
num_ins_this_helper = num_terms;
}
if (num_ins_this_helper == 1)
{
fprintf (f," assign help_c%d[%d] = ",x,n);
while (matrix[y][x] != '1') y++;
fprintf (f,"d[%d];\n",y);
y++;
num_terms--;
}
else
{
// build the next helper XOR gate
fprintf (f," xor6 help_c%d_%d (help_c%d[%d],",x,n,x,n);
for (i = 0; i<num_ins_this_helper; i++)
{
while (matrix[y][x] != '1') y++;
if (i != 0) fprintf (f,",");
fprintf (f,"d[%d]",y);
y++;
num_terms--;
}
while (i<lutsize)
{
fprintf (f,",1'b0");
i++;
}
fprintf (f,");\n");
}
}
// xor up the helpers for the result
fprintf (f," assign c[%d] = ^help_c%d;\n\n",x,x);
}
}
fprintf (f,"endmodule\n\n");
// put together the hamming distance matrix, which
// is a slightly odd counter
unsigned int matrix_h [TOTAL_BITS];
for (x=0;x<(TOTAL_BITS-1);x++)
{
matrix_h[x] = (1<<(SYN_BITS-1)) | (x+1);
}
matrix_h[TOTAL_BITS-1] = (1<<(SYN_BITS-1));
// spit out a syndrome generator
fprintf (f,"//////////////////////////////////////////\n");
fprintf (f,"// compute a syndrome from the code word\n");
fprintf (f,"//////////////////////////////////////////\n\n");
fprintf (f,"module ecc_syndrome_%dbit (clk,rst,c,s);\n\n",DATA_BITS);
fprintf (f,"// optional register on the outputs\n");
fprintf (f,"// of bits 0..6 and back one level in bit 7\n");
fprintf (f,"parameter REGISTER = 0;\n\n");
fprintf (f,"input clk,rst;\n");
fprintf (f,"input [%d:0] c;\n",TOTAL_BITS-1);
fprintf (f,"output [%d:0] s;\n",SYN_BITS-1);
fprintf (f,"reg [%d:0] s;\n\n",SYN_BITS-1);
for (y=0;y<SYN_BITS;y++)
{
num_terms = 0;
for (x=0;x<TOTAL_BITS;x++)
{
if ((matrix_h[x] & (1<<y)) != 0)
{
num_terms++;
}
}
fprintf (f," // %d terms\n",num_terms);
// create helpers
num_helpers = num_terms / lutsize;
if (num_helpers * lutsize < num_terms) num_helpers++;
fprintf (f," wire [%d:0] help_s%d;\n",num_helpers-1,y);
x = 0;
for (n=0; n<num_helpers; n++)
{
num_ins_this_helper = lutsize;
if (num_terms < num_ins_this_helper)
{
num_ins_this_helper = num_terms;
}
if (num_ins_this_helper == 1)
{
fprintf (f," assign help_s%d[%d] = ",y,n);
while ((matrix_h[x] & (1<<y)) == 0) x++;
fprintf (f,"c[%d];\n",x);
x++;
num_terms--;
}
else
{
// build the next helper XOR gate
fprintf (f," xor6 help_s%d_%d (help_s%d[%d],",y,n,y,n);
for (i = 0; i<num_ins_this_helper; i++)
{
while ((matrix_h[x] & (1<<y)) == 0) x++;
if (i != 0) fprintf (f,",");
fprintf (f,"c[%d]",x);
x++;
num_terms--;
}
while (i<lutsize)
{
fprintf (f,",1'b0");
i++;
}
fprintf (f,");\n");
}
}
// xor up the helpers for the result
// and optional register for the lower bits
if ((y != (SYN_BITS-1)) || DATA_BITS != 64)
{
fprintf (f," generate\n");
fprintf (f," if (REGISTER) begin\n");
fprintf (f," always @(posedge clk or posedge rst) begin\n");
fprintf (f," if (rst) s[%d] <= 0;\n",y);
fprintf (f," else s[%d] <= ^help_s%d;\n",y,y);
fprintf (f," end\n");
fprintf (f," end else begin\n");
fprintf (f," always @(help_s%d) begin\n",y);
fprintf (f," s[%d] = ^help_s%d;\n",y,y);
fprintf (f," end\n");
fprintf (f," end\n");
fprintf (f," endgenerate\n\n");
}
// the last parity bit for 64 data is special due to high input count
// register it a bit higher
else
{
fprintf (f,"\n");
fprintf (f," // the parity bit has too much fanin\n");
fprintf (f," // register it a bit higher for balance\n");
fprintf (f," reg [%d:0] help_s%d_r;\n",num_helpers-1,y);
fprintf (f," generate\n");
fprintf (f," if (REGISTER) begin\n");
fprintf (f," always @(posedge clk or posedge rst) begin\n");
fprintf (f," if (rst) help_s%d_r <= 0;\n",y);
fprintf (f," else help_s%d_r <= help_s%d;\n",y,y);
fprintf (f," end\n");
fprintf (f," end else begin\n");
fprintf (f," always @(help_s%d) begin\n",y);
fprintf (f," help_s%d_r = help_s%d;\n",y,y);
fprintf (f," end\n");
fprintf (f," end\n");
fprintf (f," endgenerate\n\n");
fprintf (f," // group the parity helper XORs\n");
fprintf (f," wire par_0, par_1;\n");
fprintf (f," xor6 par_0x (par_0");
for (n=0; n<6; n++)
{
fprintf (f,",help_s%d_r[%d]",y,n);
}
fprintf (f,");\n");
fprintf (f," xor6 par_1x (par_1");
for (n=6; n<12; n++)
{
fprintf (f,",help_s%d_r[%d]",y,n);
}
fprintf (f,");\n\n");
fprintf (f," always @(par_0 or par_1) begin\n",y);
fprintf (f," s[%d] = par_0 ^ par_1;\n",y);
fprintf (f," end\n\n");
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -