blob: 79553a9b40a5529b17ff3c2a1aade51d39e5837f [file] [log] [blame]
/*
* m = power of field
* l = irreducable polynomial for m
* n = code word size (1 << m) - 1
* k = input size
* t = correctable bits
*/
`include "log2.vh"
localparam MAX_M = 16;
/* Trinomial */
function [MAX_M:0] P3;
input [31:0] p;
P3 = (1 << p) | 1;
endfunction
/* Pentanomial */
function [MAX_M:0] P5;
input [31:0] p1;
input [31:0] p2;
input [31:0] p3;
P5 = (1 << p3) | (1 << p2) | (1 << p1) | 1;
endfunction
/* Return irreducable polynomial */
/* VLSI Aspects on Inversion in Finite Fields, Mikael Olofsson */
function integer bch_polynomial;
input [31:0] m;
reg [(MAX_M+1)*(MAX_M-1)-1:0] p;
begin
p = {
P3(1), /* m=2 */
P3(1),
P3(1),
P3(2), /* m=5 */
P3(1),
P3(1),
P5(4, 3, 2),
P3(4),
P3(3), /* m=10 */
P3(2),
P5(6, 4, 1),
P5(4, 3, 1),
P5(5, 3, 1),
P3(1), /* m=15 */
P5(12, 3, 1)
};
bch_polynomial = p[(MAX_M+1)*(MAX_M-m)+:MAX_M+1];
end
endfunction
/*
* Non-zero if irreducible polynomial is of the form x^m + x^P1 + x^P2 + x^P3 + 1
* zero for x^m + x^P + 1
*/
function integer bch_is_pentanomial;
input [31:0] m;
integer p;
integer bits;
integer i;
begin
p = bch_polynomial(m);
bits = 1;
for (i = 0; i < m; i = i + 1) begin
if (p & 1)
bits = bits + 1;
p = p >> 1;
end
bch_is_pentanomial = bits == 5 ? 1 : 0;
end
endfunction
/* Degree (except highest), eg, m=5, (1)00101, x^5 + x^2 + 1 returns 2 */
function integer polyi;
input [31:0] m;
polyi = log2(bch_polynomial(m) >> 1);
endfunction
/* Berlekamp dual-basis multiplier for fixed values, returns value in dual basis */
function [MAX_M-1:0] fixed_mixed_multiplier;
input [31:0] m;
input [MAX_M-1:0] dual_in;
input [MAX_M-1:0] standard_in;
integer i;
integer poly;
integer aux;
integer ret;
begin
poly = bch_polynomial(m);
aux = dual_in;
for (i = 0; i < m - 1; i = i + 1)
aux[i+m] = ^((aux >> i) & poly);
ret = 0;
for (i = 0; i < m; i = i + 1)
ret[i] = ^((aux >> i) & standard_in);
fixed_mixed_multiplier = ret;
end
endfunction
function integer conversion_term;
input [31:0] m;
input [31:0] bit_pos;
integer pos;
begin
pos = polyi(m);
if (bch_is_pentanomial(m)) begin
/* FIXME */
end else begin
conversion_term = 1 << ((pos - bit_pos - 1) % m);
end
end
endfunction
/* Convert polynomial basis to dual basis */
function integer standard_to_dual;
input [31:0] m;
input [31:0] standard;
integer i;
integer ret;
begin
ret = 0;
for (i = 0; i < m; i = i + 1) begin
if (standard[i])
ret = ret ^ conversion_term(m, i);
end
standard_to_dual = ret;
end
endfunction
/* Multiply by alpha x*l^1 */
function [MAX_M-1:0] mul1;
input [31:0] m;
input [MAX_M-1:0] x;
begin
mul1 = m2n(m) & ((x << 1) ^ (bch_polynomial(m) & {MAX_M{x[m-1]}}));
end
endfunction
/* a * b for finite field */
function integer finite_mult;
input [31:0] m;
input [MAX_M:0] a;
input [MAX_M:0] b;
integer i;
integer p;
begin
p = 0;
if (a && b) begin
for (i = 0; i < m; i = i + 1) begin
p = p ^ (a & {MAX_M{b[i]}});
a = mul1(m, a);
end
end
finite_mult = p;
end
endfunction
/* L^x, convert and integer to standard polynomial basis */
function integer lpow;
input [31:0] m;
input [31:0] x;
integer i;
integer ret;
begin
ret = 1;
x = x % m2n(m); /* Answer would wrap around */
repeat (x)
ret = mul1(m, ret);
lpow = ret;
end
endfunction
function integer n2m;
input [31:0] n;
begin
n2m = log2(n+1) - 1;
end
endfunction
function integer m2n;
input [31:0] m;
begin
m2n = (1 << m) - 1;
end
endfunction
function integer calc_iteration;
input [31:0] n;
input [31:0] t;
input [31:0] is_serial;
integer ret;
integer m;
begin
m = n2m(n);
if (t == 2)
ret = 1;
else if (is_serial)
ret = m + 2;
else
ret = 3;
calc_iteration = ret;
end
endfunction
function integer calc_interleave;
input [31:0] n;
input [31:0] t;
input is_serial;
integer chpe;
integer vdout;
integer done;
integer m;
integer iteration;
integer ret;
begin
m = n2m(n);
iteration = calc_iteration(n, t, is_serial);
ret = 1;
done = 0;
while (!done) begin
chpe = t * iteration - 2;
vdout = chpe + ret + 2 - chpe % ret;
if (vdout - 2 < n * ret)
done = 1;
else
ret = ret + 1;
end
calc_interleave = ret;
end
endfunction
function integer lfsr_count;
input [31:0] m;
input [31:0] n;
begin
lfsr_count = lpow(m, n);
end
endfunction