Minor code cleanup for MT19937 and improve testbench.
* Optimized seeding strategy now synthesizes for Spartan 6 at 300 MHz.
This commit is contained in:
parent
46409ff163
commit
500d8e8b2a
|
@ -15,8 +15,7 @@
|
||||||
-- to initialize the generator at reset. The generator also supports
|
-- to initialize the generator at reset. The generator also supports
|
||||||
-- re-seeded at run time.
|
-- re-seeded at run time.
|
||||||
--
|
--
|
||||||
-- TODO : rewrite this thing about initialization
|
-- After reset, and after re-seeding, the generator needs 4 * 624 clock
|
||||||
-- After reset, and after re-seeding, the generator needs 625 clock
|
|
||||||
-- cycles to initialize its internal state. During this time, the generator
|
-- cycles to initialize its internal state. During this time, the generator
|
||||||
-- is unable to provide correct output.
|
-- is unable to provide correct output.
|
||||||
--
|
--
|
||||||
|
@ -185,7 +184,7 @@ begin
|
||||||
-- Enable state machine on next cycle
|
-- Enable state machine on next cycle
|
||||||
-- a) every 1st out of 4 cycles during reseeding, and
|
-- a) every 1st out of 4 cycles during reseeding, and
|
||||||
-- b) on-demand for new output.
|
-- b) on-demand for new output.
|
||||||
reg_enable <= reg_reseedstate(3) or
|
reg_enable <= (reg_reseeding and reg_reseedstate(3)) or
|
||||||
(not reg_reseeding and
|
(not reg_reseeding and
|
||||||
(out_ready or not reg_valid));
|
(out_ready or not reg_valid));
|
||||||
|
|
||||||
|
@ -196,17 +195,17 @@ begin
|
||||||
|
|
||||||
-- Reseed state 2: Multiply by constant.
|
-- Reseed state 2: Multiply by constant.
|
||||||
if force_const_mul then
|
if force_const_mul then
|
||||||
-- Multiply by 37.
|
-- Compute 37 * Mprev.
|
||||||
reg_seed_b <= std_logic_vector(
|
reg_seed_b <= std_logic_vector(
|
||||||
unsigned(reg_seed_a)
|
unsigned(reg_seed_a)
|
||||||
+ shift_left(unsigned(reg_seed_a), 2)
|
+ shift_left(unsigned(reg_seed_a), 2)
|
||||||
+ shift_left(unsigned(reg_seed_a), 5));
|
+ shift_left(unsigned(reg_seed_a), 5));
|
||||||
-- Multiply by (2**19 - 2**15).
|
-- Compute (2**19 - 2**15) * Mprev.
|
||||||
reg_seed_b2 <= std_logic_vector(
|
reg_seed_b2 <= std_logic_vector(
|
||||||
shift_left(unsigned(reg_seed_a), 19)
|
shift_left(unsigned(reg_seed_a), 19)
|
||||||
- shift_left(unsigned(reg_seed_a), 15));
|
- shift_left(unsigned(reg_seed_a), 15));
|
||||||
else
|
else
|
||||||
-- Multiply by 1812433253.
|
-- Compute 1812433253 * Mprev.
|
||||||
-- Let synthesizer choose a multiplier implementation.
|
-- Let synthesizer choose a multiplier implementation.
|
||||||
reg_seed_b <= std_logic_vector(
|
reg_seed_b <= std_logic_vector(
|
||||||
mulconst(unsigned(reg_seed_a)));
|
mulconst(unsigned(reg_seed_a)));
|
||||||
|
@ -214,12 +213,14 @@ begin
|
||||||
|
|
||||||
-- Reseed state 3: Continue multiplication by constant.
|
-- Reseed state 3: Continue multiplication by constant.
|
||||||
if force_const_mul then
|
if force_const_mul then
|
||||||
|
-- Compute (37 + 2**6 * 37 + 2**19 - 2**15) * Mprev.
|
||||||
-- Finalize multiplication by 1812433253 =
|
-- Finalize multiplication by 1812433253 =
|
||||||
-- (37 + 2**6*37 - 2**15 + 2**19 - 2**26*37)
|
-- (37 + 2**6*37 - 2**15 + 2**19 - 2**26*37)
|
||||||
reg_seed_c <= std_logic_vector(
|
reg_seed_c <= std_logic_vector(
|
||||||
unsigned(reg_seed_b)
|
unsigned(reg_seed_b)
|
||||||
+ shift_left(unsigned(reg_seed_b), 6)
|
+ shift_left(unsigned(reg_seed_b), 6)
|
||||||
+ unsigned(reg_seed_b2));
|
+ unsigned(reg_seed_b2));
|
||||||
|
-- Compute (2**32 - 2**26 * 37) * Mprev + reseed_cnt.
|
||||||
reg_seed_c2 <= std_logic_vector(
|
reg_seed_c2 <= std_logic_vector(
|
||||||
unsigned(reg_reseed_cnt)
|
unsigned(reg_reseed_cnt)
|
||||||
- shift_left(unsigned(reg_seed_b), 26));
|
- shift_left(unsigned(reg_seed_b), 26));
|
||||||
|
@ -229,11 +230,14 @@ begin
|
||||||
|
|
||||||
-- Reseed state 4: Prepare next element of initial state.
|
-- Reseed state 4: Prepare next element of initial state.
|
||||||
if reg_reseeding = '1' then
|
if reg_reseeding = '1' then
|
||||||
-- Add result of multiplication to reseed counter.
|
|
||||||
if force_const_mul then
|
if force_const_mul then
|
||||||
|
-- Compute (37 + 2**6 * 37 + 2**19 - 2**15) * Mprev
|
||||||
|
-- + (2**32 - 2**26 * 37) * Mprev + reseed_cnt
|
||||||
|
-- = 1812433253 * Mprev + reseed_cnt.
|
||||||
reg_seed_d <= std_logic_vector(unsigned(reg_seed_c) +
|
reg_seed_d <= std_logic_vector(unsigned(reg_seed_c) +
|
||||||
unsigned(reg_seed_c2));
|
unsigned(reg_seed_c2));
|
||||||
else
|
else
|
||||||
|
-- Compute 1812433253 * Mprev + reseed_cnt.
|
||||||
reg_seed_d <= std_logic_vector(unsigned(reg_seed_c) +
|
reg_seed_d <= std_logic_vector(unsigned(reg_seed_c) +
|
||||||
unsigned(reg_reseed_cnt));
|
unsigned(reg_reseed_cnt));
|
||||||
end if;
|
end if;
|
||||||
|
|
|
@ -58,6 +58,7 @@ begin
|
||||||
process is
|
process is
|
||||||
file outf1: text is out "sim_mt19937_seed1.dat";
|
file outf1: text is out "sim_mt19937_seed1.dat";
|
||||||
file outf2: text is out "sim_mt19937_seed2.dat";
|
file outf2: text is out "sim_mt19937_seed2.dat";
|
||||||
|
file outf3: text is out "sim_mt19937_seed3.dat";
|
||||||
variable lin: line;
|
variable lin: line;
|
||||||
variable nskip: integer;
|
variable nskip: integer;
|
||||||
variable v: std_logic_vector(31 downto 0);
|
variable v: std_logic_vector(31 downto 0);
|
||||||
|
@ -172,6 +173,57 @@ begin
|
||||||
-- Go to next cycle.
|
-- Go to next cycle.
|
||||||
wait until falling_edge(clk);
|
wait until falling_edge(clk);
|
||||||
|
|
||||||
|
end loop;
|
||||||
|
|
||||||
|
-- Re-seed generator.
|
||||||
|
report "Re-seed generator";
|
||||||
|
s_reseed <= '1';
|
||||||
|
s_newseed <= x"0f5a3c57";
|
||||||
|
s_ready <= '0';
|
||||||
|
wait until falling_edge(clk);
|
||||||
|
s_reseed <= '0';
|
||||||
|
s_newseed <= (others => '0');
|
||||||
|
|
||||||
|
-- Give generator more than enough time to complete initialization.
|
||||||
|
for i in 0 to 4*624 + 500 loop
|
||||||
|
wait until falling_edge(clk);
|
||||||
|
end loop;
|
||||||
|
|
||||||
|
s_ready <= '1';
|
||||||
|
|
||||||
|
-- Produce numbers
|
||||||
|
for i in 0 to 999 loop
|
||||||
|
|
||||||
|
-- Check that output is valid.
|
||||||
|
assert s_valid = '1' report "Output not VALID";
|
||||||
|
|
||||||
|
-- Write output to file.
|
||||||
|
write(lin, "0x" & to_hex_string(s_data));
|
||||||
|
writeline(outf3, lin);
|
||||||
|
|
||||||
|
-- Sometimes skip cycles.
|
||||||
|
if i mod 5 = 2 then
|
||||||
|
nskip := 1;
|
||||||
|
if i mod 3 = 0 then
|
||||||
|
nskip := nskip + 1;
|
||||||
|
end if;
|
||||||
|
if i mod 11 = 0 then
|
||||||
|
nskip := nskip + 1;
|
||||||
|
end if;
|
||||||
|
|
||||||
|
v := s_data;
|
||||||
|
s_ready <= '0';
|
||||||
|
for t in 1 to nskip loop
|
||||||
|
wait until falling_edge(clk);
|
||||||
|
assert s_valid = '1' report "Output not valid";
|
||||||
|
assert s_data = v report "Output changed while not ready";
|
||||||
|
end loop;
|
||||||
|
s_ready <= '1';
|
||||||
|
end if;
|
||||||
|
|
||||||
|
-- Go to next cycle.
|
||||||
|
wait until falling_edge(clk);
|
||||||
|
|
||||||
end loop;
|
end loop;
|
||||||
|
|
||||||
-- End simulation.
|
-- End simulation.
|
||||||
|
|
Loading…
Reference in New Issue