📄 bms_eras_str_full.tdf
字号:
-------------------------------------------------------------------------
-------------------------------------------------------------------------
--
-- Revision Control Information
--
-- $Workfile: bms_eras_str_full.tdf $
-- $Archive: P:/RS/units/Dec_str/ahdl/bms_eras_str_full.tdv $
--
-- $Revision: 1.6 $
-- $Date: 29 Oct 1999 11:45:20 $
-- $Author : Alejandro Diaz-Manero
--
-- Project : RS
--
-- Description : Berlekamp-Massey algorithm for streaming RS decoder supporting
-- erasures and for full speed.
--
-- Copyright 1999 (c) Altera Corporation
-- All rights reserved
--
-------------------------------------------------------------------------
-------------------------------------------------------------------------
FUNCTION lpm_add_sub (cin, dataa[LPM_WIDTH-1..0], datab[LPM_WIDTH-1..0],
add_sub, clock, aclr)
RETURNS (result[LPM_WIDTH-1..0], cout, overflow);
FUNCTION lpm_counter (data[LPM_WIDTH-1..0], clock, clk_en, cnt_en, updown, aclr,
aset, aconst, aload, sclr, sset, sconst, sload)
RETURNS (q[LPM_WIDTH-1..0], eq[15..0]);
FUNCTION lpm_compare (dataa[LPM_WIDTH-1..0], datab[LPM_WIDTH-1..0], clock, aclr)
RETURNS (alb, aeb, agb, ageb, aneb, aleb);
FUNCTION gfmul (a[m..1], b[m..1])
RETURNS (c[m..1]);
FUNCTION gfdiv (a[m..1], d[m..1])
RETURNS (c[m..1]);
PARAMETERS
(
m = 4, -- GF size (2^m)
irrpol = 19, -- field polynomial
check = 4, -- number of check symbols (= # of syndromes)
inv_file = "inv_4_19.hex"
);
constant wide = ceil(log2(check+1));
subdesign bms_eras_str_full
(
sysclk, reset, latchsyn, syn[check..1][m..1], num_eras[wide..1], eras_pos[check..1][m..1] : INPUT;
bdout[check..1][m..1], omegaout[check..1][m..1], numerr[wide..1], done : OUTPUT;
)
VARIABLE
synreg[check..1][m..1], bd[check..1][m..1], bdprev[check..1][m..1], bdtemp[check..1][m..1] : dffe;
one[m..1] : node;
sh_sel[check..1], omsel[check..1] : dffe;
erasleft[check..1][m..1], erasright[check..1][m..1] : node;
onereg : dffe;
onenode[m..1] : node;
deltaleft[check..1][m..1], deltaright[check..1][m..1] : node;
bdleft[check..1][m..1], bdright[check..1][m..1] : node;
mulleft[check..1][m..1], mulright[check..1][m..1], deltamult[m..1] : dffe;
mulout[check..1][m..1] : node;
mulsum[check..1][m..1], addvec[check..1][m..1] : node;
deltazero[m..1] : node;
delta[m..1], deltaprev[m..1] : dffe;
mcount, omegacount : lpm_counter WITH (LPM_WIDTH = wide);
llnuma[wide..1], llnumb[wide..1] : node;
llnum[wide..1], num_eras_q[wide..1] : dffe;
llnumnode[wide..1] : node;
mloop[wide..1], omegaloop[wide..1] : node;
mchk[wide..1], mcmp[wide..1], omegachk[wide..1], omegacmp[wide..1] : node;
init_syn[wide..1], eras_zero[wide..1] : node;
mloop_plus_eras_num[wide+1..1] : node;
omegaleft[check..1][m..1], omegaright[check..1][m..1] : node;
loadbd, loadbdprev, loadbdtemp, load_llnum : node;
shiftsynleft, shiftsynright, clearbd, shiftbdprev_lm, shift_sh_sel : node;
deltacalc, newdelta, olddelta, shiftbdprev_ml : node;
incm, tlm : node;
incomega, initomega, calcomega, massdone : node;
add_sub1 : lpm_add_sub WITH (LPM_WIDTH = wide, LPM_DIRECTION = "SUB");
add_sub2, add_sub3 : lpm_add_sub WITH (LPM_WIDTH = wide, LPM_DIRECTION = "ADD");
add_sub4 : lpm_add_sub WITH (LPM_WIDTH = wide+1, LPM_DIRECTION = "ADD");
compare1 : lpm_compare WITH (LPM_WIDTH = wide+1);
mx : MACHINE OF BITS (mst[16..1])
WITH STATES
(s0 = B"0010000010000000",
s1 = B"0010000010000000", -- load syndromes, loadbdtemp (removed)
s1b = B"1010010010001001", -- shift syndrome as num erasures, incm, load bd, shiftbdprev_ml
s1c = B"0010000010000000", -- keep selecting deltacalc calomega
s1d = B"0010000010000000", -- keep selecting deltacalc calomega
s1e = B"0000000000000100", -- loadbdtemp
s2a = B"0000000000000010", -- load bdprev not inc mloop
s2b = B"0000000111000000", -- calc new delta = Sm + (series)B(j)*S(m-j), shiftBDprev_lm
s77 = B"0000000100000000", -- 1 pipe stage to top of gfmuls
s3 = B"0000000000000000", -- if new delta <> 0, calc new BD
s4 = B"0000000000000100", -- TD = BD, BD = BD - deltamult*(D^i)*BDprev
s5 = B"0000000000000001", -- load BD, check 2L <= m?
s6 = B"0000001000000010", -- L = m+1-L, i=1, BDprev = BDtemp, olddelta = delta
s8 = B"0000010000001000", -- inc mloop, shift synregs left
-- calc omega
s10 = B"0010000000100100", -- not initialize omega, loadbdtemp, clearbd
s11 = B"0011000000010010", -- shift syn right, loadbdprev, not loadbd , init omega
s12 = B"1010100000010001", -- shiftsynright, shiftbdprev_ml, incomega, loadbd
s99 = B"0100000000000000");
BEGIN
mcmp[] = check;
omegacmp[] = check-1;
one[] = 1;
--*********************
--*** STATE MACHINE ***
--*********************
mx.clk = sysclk;
mx.reset = GND;
CASE mx IS
WHEN s0 =>
IF (reset == VCC) THEN
mx = s0;
ELSE
mx = s1;
END IF;
WHEN s1 =>
IF (reset == VCC) THEN
mx = s0;
ELSIF (eras_zero[wide] == VCC) THEN
mx = S1b;
ELSE
mx = s2a;
END IF;
WHEN s1b =>
IF (reset == VCC) THEN
mx = s0;
ELSE
mx = s1c;
END IF;
WHEN s1c =>
IF (reset == VCC) THEN
mx = s0;
ELSIF (init_syn[wide] == VCC) THEN
mx = S1d;
ELSE
mx = s1e;
END IF;
WHEN s1d =>
IF (reset == VCC) THEN
mx = s0;
ELSE
mx = s1b;
END IF;
WHEN s1e =>
IF (reset == VCC) THEN
mx = s0;
ELSE
mx = s2a;
END IF;
WHEN s2a =>
IF (reset == VCC) THEN
mx = s0;
ELSE
mx = s2b;
END IF;
WHEN s2b =>
IF (reset == VCC) THEN
mx = s0;
ELSIF (mchk[wide] == VCC) THEN
mx = s77;
ELSE
mx = s10;
END IF;
WHEN s77 =>
IF (reset == VCC) THEN
mx = s0;
ELSE
mx = s3;
END IF;
WHEN s3 =>
IF (reset == VCC) THEN
mx = s0;
ELSIF (deltazero[m] == VCC) THEN
mx = s4;
ELSE
mx = s8;
END IF;
WHEN s4 =>
IF (reset == VCC) THEN
mx = s0;
ELSE
mx = s5;
END IF;
WHEN s5 =>
IF (reset == VCC) THEN
mx = s0;
ELSIF (tlm == VCC) THEN
mx = s6;
ELSE
mx = s8;
END IF;
WHEN s6 =>
IF (reset == VCC) THEN
mx = s0;
ELSE
mx = s8;
END IF;
WHEN s8 =>
IF (reset == VCC) THEN
mx = s0;
ELSE
mx = s2b;
END IF;
WHEN s10 =>
IF (reset == VCC) THEN
mx = s0;
ELSE
mx = s11;
END IF;
WHEN s11 =>
IF (reset == VCC) THEN
mx = s0;
ELSE
mx = s12;
END IF;
WHEN s12 =>
IF (reset == VCC) THEN
mx = s0;
ELSIF (omegachk[wide] == VCC) THEN
mx = s12;
ELSE
mx = s99;
END IF;
WHEN s99 =>
IF (reset == VCC) THEN
mx = s0;
ELSE
mx = s99;
END IF;
WHEN others =>
mx = s0;
END CASE;
loadbd = mst[1];
loadbdprev = mst[2];
loadbdtemp = mst[3];
shiftsynleft = mst[4];
shiftsynright = mst[5];
clearbd = mst[6];
shiftbdprev_lm = mst[7];
deltacalc = mst[8];
newdelta = mst[9];
olddelta = mst[10];
incm = mst[11];
incomega = mst[12];
initomega = mst[13];
calcomega = mst[14];
massdone = mst[15];
shiftbdprev_ml = mst[16];
load_llnum = olddelta;
shift_sh_sel = shiftbdprev_ml;
--************************
--*** SYNDROME SECTION ***
--************************
-- no resets required, loaded after sm reset
synreg[1][] = (syn[1][] & !shiftsynleft & !shiftsynright) #
(synreg[2][] & shiftsynleft) #
(synreg[check][] & shiftsynright);
FOR k IN 2 TO check-1 GENERATE
synreg[k][] = (syn[k][] & !shiftsynleft & !shiftsynright) #
(synreg[k+1][] & shiftsynleft) #
(synreg[k-1][] & shiftsynright);
END GENERATE;
synreg[check][] = (syn[check][] & !shiftsynleft & !shiftsynright) #
(synreg[1][] & shiftsynleft) #
(synreg[check-1][] & shiftsynright);
synreg[][].clk = sysclk;
synreg[1][].ena = latchsyn # shiftsynleft # reset;
FOR k IN 2 TO check GENERATE
synreg[k][].ena = latchsyn # shiftsynleft # shiftsynright # reset;
END GENERATE;
--******************
--*** BD-OMEGA SECTION ***
--******************
-- load onereg with zero after first shift
-- [m..2] bits always zero, use onenode[]
onereg = latchsyn # loadbdprev;
onereg.ena = shiftbdprev_lm # latchsyn # loadbdprev;
onereg.clk = sysclk;
onenode[1] = onereg;
onenode[m..2] = 0;
FOR k IN 1 TO check GENERATE
bd[k][] = (addvec[k][] & !clearbd & !reset);
bd[K][].ena = (!omsel[K] & loadbd) # clearbd # reset;
END GENERATE;
bd[][].clk = sysclk;
omsel[].clk = sysclk;
omsel[].ena = incomega # reset;
omsel[1] = !reset;
FOR k IN 2 TO check GENERATE
omsel[K] = omsel[K-1] & !reset;
end generate;
sh_sel[].clk = sysclk;
sh_sel[].ena = shift_sh_sel # reset;
bdprev[][].clk = sysclk;
bdprev[][].ena = loadbdprev # shiftbdprev_ml # shiftbdprev_lm # reset;
sh_sel[1] = !reset;
FOR k IN 2 TO check GENERATE
sh_sel[K] = sh_sel[K-1] & !reset;
end generate;
bdprev[1][] = ((bdtemp[1][] & !shiftbdprev_ml & !shiftbdprev_lm & !reset) #
(eras_pos[1][] & !shiftbdprev_ml & !shiftbdprev_lm & reset) #
(onenode[] & !shiftbdprev_ml & shiftbdprev_lm) #
(bdprev[2][] & shiftbdprev_ml & !shiftbdprev_lm));
FOR k IN 2 TO check-1 GENERATE
bdprev[k][] = ((bdtemp[K][] & !shiftbdprev_ml & !shiftbdprev_lm & !reset) #
(eras_pos[K][] & !shiftbdprev_ml & !shiftbdprev_lm & reset) #
(bdprev[K-1][] & !shiftbdprev_ml & shiftbdprev_lm) #
(bdprev[K+1][] & shiftbdprev_ml & !shiftbdprev_lm));
END GENERATE;
bdprev[check][] = ((bdtemp[check][] & !shiftbdprev_ml & !shiftbdprev_lm & !reset) #
(eras_pos[check][] & !shiftbdprev_ml & !shiftbdprev_lm & reset) #
(bdprev[check-1][] & !shiftbdprev_ml & shiftbdprev_lm) #
(bdprev[1][] & shiftbdprev_ml & !shiftbdprev_lm));
-- reset not needed, as initialized with eras_pos[][]
bdtemp[][] = (bd[][] & !reset) # (eras_pos[][] & reset);
bdtemp[][].clk = sysclk;
bdtemp[][].ena = loadbdtemp # reset;
--********************
--*** CORE SECTION ***
--********************
--*** calculate new delta ***
bdleft[][] = bdprev[][];
erasright[1][] = 1;
mulsum[1][] = mulout[1][] $ synreg[1][];
FOR K IN 2 TO check GENERATE
erasright[K][] = bd[K-1][];
-- calculate new delta
mulsum[k][] = mulout[k][] $ mulsum[k-1][];
END GENERATE;
-- expand_check
FOR k IN 1 to check GENERATE
erasleft[K][] = (bdprev[1][] & sh_sel[k]) # (bdtemp[k][] & !sh_sel[K]);
deltaleft[k][] = synreg[check+1-k][];
deltaright[k][] = bd[k][];
-- calculate new bd vector
bdright[k][] = deltamult[];
addvec[k][] = bd[k][] $ mulout[k][]; -- gfadd
-- calculate omega
omegaleft[k][] = synreg[k][];
omegaright[k][] = (bdprev[1][] & !initomega) # (one[] & initomega);
-- multiply
mulleft[k][] = ((erasleft[K][] & deltacalc & calcomega) #
(deltaleft[k][] & deltacalc & !calcomega) #
(bdleft[k][] & !deltacalc & !calcomega) #
(omegaleft[k][] & !deltacalc & calcomega));
mulright[k][] = ((erasright[K][] & deltacalc & calcomega) #
(deltaright[k][] & deltacalc & !calcomega) #
(bdright[k][] & !deltacalc & !calcomega) #
(omegaright[k][] & !deltacalc & calcomega));
mulout[k][] = gfmul (mulleft[k][], mulright[k][])
WITH (m = m, irrpol = irrpol);
END GENERATE;
mulleft[][].clk = sysclk;
mulright[][].clk = sysclk;
-- reset not needed
delta[] = mulsum[check][] & !reset;
delta[].clk = sysclk;
delta[].ena = newdelta # reset;
deltaprev[m..2] = delta[m..2] & !reset;
deltaprev[1] = delta[1] # reset;
deltaprev[].clk = sysclk;
deltaprev[].ena = olddelta # reset;
-- reset not needed, just for timing purposes
deltamult[] = gfdiv (delta[], deltaprev[])
WITH (m=m, irrpol=irrpol, inv_file = inv_file);
deltamult[].clk = sysclk;
deltazero[1] = delta[1];
FOR k IN 2 TO m GENERATE
deltazero[k] = delta[k] # deltazero[k-1];
END GENERATE;
--****************
--*** COUNTERS ***
--****************
mloop[] = mcount.q[];
mcount.clock = sysclk;
mcount.cnt_en = incm;
mcount.sclr = reset;
mchk[1] = mloop[1] $ mcmp[1];
eras_zero[1] = num_eras_q[1];
init_syn[1] = mloop[1] $ num_eras_q[1];
omegachk[1] = omegaloop[1] $ omegacmp[1];
FOR k IN 2 TO wide GENERATE
mchk[k] = mchk[k-1] # (mloop[k] $ mcmp[k]);
eras_zero[k] = num_eras_q[k] # eras_zero[k-1];
init_syn[k] = init_syn[k-1] # (mloop[k] $ num_eras_q[k]);
omegachk[k] = omegachk[k-1] # (omegaloop[k] $ omegacmp[k]);
END GENERATE;
--onewide[] = 1;
-- L = M+1-L
--(llnuma[],,) = lpm_add_sub ( VCC, mloop[], llnum[],,,)
-- WITH (LPM_WIDTH = wide, LPM_DIRECTION = "SUB");
add_sub1.cin = VCC;
add_sub1.dataa[] = mloop[];
add_sub1.datab[] = llnum[];
llnuma[] = add_sub1.result[];
--(llnumb[],,) = lpm_add_sub ( GND, num_eras_q[], onewide[],,,)
-- WITH (LPM_WIDTH = wide, LPM_DIRECTION = "ADD");
add_sub2.cin = GND;
add_sub2.dataa[] = num_eras_q[];
add_sub2.datab[] = 1;
llnumb[] = add_sub2.result[];
--(llnumnode[],,) = lpm_add_sub ( GND, llnuma[], llnumb[],,,)
-- WITH (LPM_WIDTH = wide, LPM_DIRECTION = "ADD");
add_sub3.cin = GND;
add_sub3.dataa[] = llnuma[];
add_sub3.datab[] = llnumb[];
llnumnode[] = add_sub3.result[];
llnum[] = (llnumnode[] & !reset) # (num_eras[] & reset);
llnum[].clk = sysclk;
llnum[].ena = load_llnum # reset;
num_eras_q[].clk = sysclk;
num_eras_q[].ena = reset;
num_eras_q[] = num_eras[];
-- 2L <= m + num_eras_q?
--(mloop_plus_eras_num[],,) = lpm_add_sub ( GND, (0,mloop[]), (0,num_eras_q[]),,,)
-- WITH (LPM_WIDTH = wide+1, LPM_DIRECTION = "ADD");
add_sub4.cin = GND;
add_sub4.dataa[] = (0,mloop[]);
add_sub4.datab[] = (0,num_eras_q[]);
mloop_plus_eras_num[] = add_sub4.result[];
--(,,,,,tlm) = lpm_compare ( (llnum[],0), mloop_plus_eras_num[],,)
-- WITH (LPM_WIDTH = (wide+1));
compare1.dataa[] = (llnum[],0);
compare1.datab[] = mloop_plus_eras_num[];
tlm = compare1.aleb;
omegaloop[] = omegacount.q[];
omegacount.clock = sysclk;
omegacount.cnt_en = incomega;
omegacount.sclr = reset;
--***************
--*** OUTPUTS ***
--***************
bdout[][] = bdprev[][];
omegaout[][] = bd[][];
numerr[] = llnum[];
done = massdone;
END;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -