Test bench for Xoroshiro128plus:

* Update tb_xoroshiro128plus for new interface.
 * Add Makefile for testbenches with GHDL.
This commit is contained in:
Joris van Rantwijk 2016-10-21 13:54:42 +02:00
parent b498a1e543
commit 404c307f62
3 changed files with 116 additions and 30 deletions

View File

@ -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

27
sim/Makefile Normal file
View File

@ -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

View File

@ -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.