Test bench for Xoroshiro128plus:
* Update tb_xoroshiro128plus for new interface. * Add Makefile for testbenches with GHDL.
This commit is contained in:
parent
b498a1e543
commit
404c307f62
|
@ -4,6 +4,7 @@
|
||||||
# This makefile works with GCC under Linux.
|
# This makefile works with GCC under Linux.
|
||||||
#
|
#
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
all: ref_xoroshiro ref_mt19937
|
all: ref_xoroshiro ref_mt19937
|
||||||
|
|
||||||
ref_xoroshiro: ref_xoroshiro.c
|
ref_xoroshiro: ref_xoroshiro.c
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
#
|
||||||
|
# Makefile for building test benches with GHDL (the free VHDL compiler).
|
||||||
|
#
|
||||||
|
|
||||||
|
GHDL = ghdl
|
||||||
|
GHDLFLAGS =
|
||||||
|
|
||||||
|
.PHONY: all
|
||||||
|
all: tb_xoroshiro128plus
|
||||||
|
|
||||||
|
tb_xoroshiro128plus: tb_xoroshiro128plus.o rng_xoroshiro128plus.o
|
||||||
|
tb_xoroshiro128plus.o: tb_xoroshiro128plus.vhdl rng_xoroshiro128plus.o
|
||||||
|
rng_xoroshiro128plus.o: ../rtl/rng_xoroshiro128plus.vhdl
|
||||||
|
|
||||||
|
tb_%: tb_%.o
|
||||||
|
$(GHDL) $(GHDLFLAGS) -e $@
|
||||||
|
|
||||||
|
%.o: %.vhdl
|
||||||
|
$(GHDL) $(GHDLFLAGS) -a $<
|
||||||
|
|
||||||
|
%.o: ../rtl/%.vhdl
|
||||||
|
$(GHDL) $(GHDLFLAGS) -a $<
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
$(GHDL) --remove
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
-- Test bench for PRNG "xoroshiro128+".
|
-- Test bench for PRNG "xoroshiro128+".
|
||||||
--
|
--
|
||||||
|
|
||||||
|
use std.textio.all;
|
||||||
|
|
||||||
library ieee;
|
library ieee;
|
||||||
use ieee.std_logic_1164.all;
|
use ieee.std_logic_1164.all;
|
||||||
use ieee.numeric_std.all;
|
use ieee.numeric_std.all;
|
||||||
|
@ -15,10 +17,11 @@ architecture arch of tb_xoroshiro128plus is
|
||||||
signal clock_active: boolean := false;
|
signal clock_active: boolean := false;
|
||||||
|
|
||||||
signal s_rst: std_logic;
|
signal s_rst: std_logic;
|
||||||
signal s_enable: std_logic;
|
|
||||||
signal s_reseed: std_logic;
|
signal s_reseed: std_logic;
|
||||||
signal s_newseed: std_logic_vector(127 downto 0);
|
signal s_newseed: std_logic_vector(127 downto 0);
|
||||||
signal s_output: std_logic_vector(63 downto 0);
|
signal s_ready: std_logic;
|
||||||
|
signal s_valid: std_logic;
|
||||||
|
signal s_data: std_logic_vector(63 downto 0);
|
||||||
|
|
||||||
function to_hex_string(s: std_logic_vector)
|
function to_hex_string(s: std_logic_vector)
|
||||||
return string
|
return string
|
||||||
|
@ -35,31 +38,37 @@ architecture arch of tb_xoroshiro128plus is
|
||||||
begin
|
begin
|
||||||
|
|
||||||
-- Instantiate PRNG.
|
-- Instantiate PRNG.
|
||||||
inst_prng: entity work.xoroshiro128plus
|
inst_prng: entity work.rng_xoroshiro128plus
|
||||||
generic map (
|
generic map (
|
||||||
init_seed => x"0123456789abcdef3141592653589793" )
|
init_seed => x"0123456789abcdef3141592653589793" )
|
||||||
port map (
|
port map (
|
||||||
clk => clk,
|
clk => clk,
|
||||||
rst => s_rst,
|
rst => s_rst,
|
||||||
enable => s_enable,
|
reseed => s_reseed,
|
||||||
reseed => s_reseed,
|
newseed => s_newseed,
|
||||||
newseed => s_newseed,
|
out_ready => s_ready,
|
||||||
output => s_output );
|
out_valid => s_valid,
|
||||||
|
out_data => s_data );
|
||||||
|
|
||||||
-- Generate clock.
|
-- Generate clock.
|
||||||
clk <= (not clk) after 10 ns when clock_active else '0';
|
clk <= (not clk) after 10 ns when clock_active else '0';
|
||||||
|
|
||||||
-- Main simulation process.
|
-- Main simulation process.
|
||||||
process is
|
process is
|
||||||
|
file outf1: text is out "sim_xoroshiro128plus_seed1.dat";
|
||||||
|
file outf2: text is out "sim_xoroshiro128plus_seed2.dat";
|
||||||
|
variable lin: line;
|
||||||
|
variable nskip: integer;
|
||||||
|
variable v: std_logic_vector(63 downto 0);
|
||||||
begin
|
begin
|
||||||
|
|
||||||
report "Start test bench";
|
report "Start test bench";
|
||||||
|
|
||||||
-- Reset.
|
-- Reset.
|
||||||
s_rst <= '1';
|
s_rst <= '1';
|
||||||
s_enable <= '0';
|
|
||||||
s_reseed <= '0';
|
s_reseed <= '0';
|
||||||
s_newseed <= (others => '0');
|
s_newseed <= (others => '0');
|
||||||
|
s_ready <= '0';
|
||||||
|
|
||||||
-- Start clock.
|
-- Start clock.
|
||||||
clock_active <= true;
|
clock_active <= true;
|
||||||
|
@ -69,42 +78,91 @@ begin
|
||||||
wait until falling_edge(clk);
|
wait until falling_edge(clk);
|
||||||
s_rst <= '0';
|
s_rst <= '0';
|
||||||
|
|
||||||
-- Produce numbers
|
-- Wait 1 clock cycle to initialize generator.
|
||||||
for i in 0 to 150 loop
|
wait until falling_edge(clk);
|
||||||
|
s_ready <= '1';
|
||||||
|
|
||||||
if i mod 5 = 0 or i mod 7 = 0 then
|
-- Produce numbers
|
||||||
s_enable <= '0';
|
for i in 0 to 999 loop
|
||||||
wait until falling_edge(clk);
|
|
||||||
else
|
-- Check that output is valid.
|
||||||
s_enable <= '1';
|
assert s_valid = '1' report "Output not valid";
|
||||||
wait until falling_edge(clk);
|
|
||||||
report "Got 0x" & to_hex_string(s_output);
|
-- Write output to file.
|
||||||
|
write(lin, "0x" & to_hex_string(s_data));
|
||||||
|
writeline(outf1, lin);
|
||||||
|
|
||||||
|
-- Sometimes skip cycles.
|
||||||
|
if i mod 5 = 1 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;
|
end if;
|
||||||
|
|
||||||
|
-- Go to next cycle.
|
||||||
|
wait until falling_edge(clk);
|
||||||
|
|
||||||
end loop;
|
end loop;
|
||||||
|
|
||||||
-- Re-seed generator.
|
-- Re-seed generator.
|
||||||
report "Re-seed generator";
|
report "Re-seed generator";
|
||||||
s_enable <= '1';
|
|
||||||
s_reseed <= '1';
|
s_reseed <= '1';
|
||||||
s_newseed <= x"3141592653589793fedcba9876543210";
|
s_newseed <= x"3141592653589793fedcba9876543210";
|
||||||
|
s_ready <= '0';
|
||||||
wait until falling_edge(clk);
|
wait until falling_edge(clk);
|
||||||
|
|
||||||
s_reseed <= '0';
|
s_reseed <= '0';
|
||||||
s_newseed <= (others => '0');
|
s_newseed <= (others => '0');
|
||||||
|
|
||||||
-- Produce numbers
|
-- Wait 1 clock cycle to re-seed generator.
|
||||||
for i in 0 to 150 loop
|
wait until falling_edge(clk);
|
||||||
|
s_ready <= '1';
|
||||||
|
|
||||||
if i mod 5 = 0 or i mod 7 = 0 then
|
-- Produce numbers
|
||||||
s_enable <= '0';
|
for i in 0 to 999 loop
|
||||||
wait until falling_edge(clk);
|
|
||||||
else
|
-- Check that output is valid.
|
||||||
s_enable <= '1';
|
assert s_valid = '1' report "Output not valid";
|
||||||
wait until falling_edge(clk);
|
|
||||||
report "Got 0x" & to_hex_string(s_output);
|
-- Write output to file.
|
||||||
|
write(lin, "0x" & to_hex_string(s_data));
|
||||||
|
writeline(outf2, 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;
|
end if;
|
||||||
|
|
||||||
|
-- Go to next cycle.
|
||||||
|
wait until falling_edge(clk);
|
||||||
|
|
||||||
end loop;
|
end loop;
|
||||||
|
|
||||||
-- End simulation.
|
-- End simulation.
|
||||||
|
|
Loading…
Reference in New Issue