Trivium: Add VHDL test bench.
This commit is contained in:
parent
5fbe51dff5
commit
eca4097d59
|
@ -0,0 +1,358 @@
|
|||
--
|
||||
-- Test bench for PRNG Trivium.
|
||||
--
|
||||
|
||||
use std.textio.all;
|
||||
|
||||
library ieee;
|
||||
use ieee.std_logic_1164.all;
|
||||
use ieee.numeric_std.all;
|
||||
|
||||
entity tb_trivium is
|
||||
end entity;
|
||||
|
||||
architecture arch of tb_trivium is
|
||||
|
||||
type output_vector is record
|
||||
pos: natural;
|
||||
data: std_logic_vector(511 downto 0);
|
||||
end record;
|
||||
|
||||
type output_vectors is array (natural range <>) of output_vector;
|
||||
|
||||
type test_vector is record
|
||||
key: std_logic_vector(79 downto 0);
|
||||
iv: std_logic_vector(79 downto 0);
|
||||
data: output_vectors(0 to 3);
|
||||
-- data: array (0 to 3) of output_vector;
|
||||
end record;
|
||||
|
||||
type test_vectors is array (natural range <>) of test_vector;
|
||||
|
||||
constant testvec: test_vectors(0 to 1) := (
|
||||
0 => ( key => x"0053A6F94C9FF24598EB",
|
||||
iv => x"0D74DB42A91077DE45AC",
|
||||
data => ( ( pos => 0, data =>
|
||||
x"F4CD954A717F26A7D6930830C4E7CF08" &
|
||||
x"19F80E03F25F342C64ADC66ABA7F8A8E" &
|
||||
x"6EAA49F23632AE3CD41A7BD290A0132F" &
|
||||
x"81C6D4043B6E397D7388F3A03B5FE358" ),
|
||||
( pos => 65472, data =>
|
||||
x"C04C24A6938C8AF8A491D5E481271E0E" &
|
||||
x"601338F01067A86A795CA493AA4FF265" &
|
||||
x"619B8D448B706B7C88EE8395FC79E5B5" &
|
||||
x"1AB40245BBF7773AE67DF86FCFB71F30" ),
|
||||
( pos => 65536, data =>
|
||||
x"011A0D7EC32FA102C66C164CFCB189AE" &
|
||||
x"D9F6982E8C7370A6A37414781192CEB1" &
|
||||
x"55C534C1C8C9E53FDEADF2D3D0577DAD" &
|
||||
x"3A8EB2F6E5265F1E831C86844670BC69" ),
|
||||
( pos => 131008, data =>
|
||||
x"48107374A9CE3AAF78221AE77789247C" &
|
||||
x"F6896A249ED75DCE0CF2D30EB9D889A0" &
|
||||
x"C61C9F480E5C07381DED9FAB2AD54333" &
|
||||
x"E82C89BA92E6E47FD828F1A66A8656E0" ))),
|
||||
1 => ( key => x"80000000000000000000",
|
||||
iv => x"00000000000000000000",
|
||||
data => ( ( pos => 0, data =>
|
||||
x"38EB86FF730D7A9CAF8DF13A4420540D" &
|
||||
x"BB7B651464C87501552041C249F29A64" &
|
||||
x"D2FBF515610921EBE06C8F92CECF7F80" &
|
||||
x"98FF20CCCC6A62B97BE8EF7454FC80F9" ),
|
||||
( pos => 192, data =>
|
||||
x"EAF2625D411F61E41F6BAEEDDD5FE202" &
|
||||
x"600BD472F6C9CD1E9134A745D900EF6C" &
|
||||
x"023E4486538F09930CFD37157C0EB57C" &
|
||||
x"3EF6C954C42E707D52B743AD83CFF297" ),
|
||||
( pos => 256, data =>
|
||||
x"9A203CF7B2F3F09C43D188AA13A5A202" &
|
||||
x"1EE998C42F777E9B67C3FA221A0AA1B0" &
|
||||
x"41AA9E86BC2F5C52AFF11F7D9EE480CB" &
|
||||
x"1187B20EB46D582743A52D7CD080A24A" ),
|
||||
( pos => 448, data =>
|
||||
x"EBF14772061C210843C18CEA2D2A275A" &
|
||||
x"E02FCB18E5D7942455FF77524E8A4CA5" &
|
||||
x"1E369A847D1AEEFB9002FCD02342983C" &
|
||||
x"EAFA9D487CC2032B10192CD416310FA4" )))
|
||||
);
|
||||
|
||||
signal clk: std_logic;
|
||||
signal clock_active: boolean := false;
|
||||
|
||||
signal x1_rst: std_logic;
|
||||
signal x1_reseed: std_logic;
|
||||
signal x1_newkey: std_logic_vector(79 downto 0);
|
||||
signal x1_newiv: std_logic_vector(79 downto 0);
|
||||
signal x1_out_ready: std_logic;
|
||||
signal x1_out_valid: std_logic;
|
||||
signal x1_out_data: std_logic_vector(0 downto 0);
|
||||
|
||||
signal x8_rst: std_logic;
|
||||
signal x8_reseed: std_logic;
|
||||
signal x8_newkey: std_logic_vector(79 downto 0);
|
||||
signal x8_newiv: std_logic_vector(79 downto 0);
|
||||
signal x8_out_ready: std_logic;
|
||||
signal x8_out_valid: std_logic;
|
||||
signal x8_out_data: std_logic_vector(7 downto 0);
|
||||
|
||||
signal x64_rst: std_logic;
|
||||
signal x64_reseed: std_logic;
|
||||
signal x64_newkey: std_logic_vector(79 downto 0);
|
||||
signal x64_newiv: std_logic_vector(79 downto 0);
|
||||
signal x64_out_ready: std_logic;
|
||||
signal x64_out_valid: std_logic;
|
||||
signal x64_out_data: std_logic_vector(63 downto 0);
|
||||
|
||||
-- Convert bit vector to hexadecimal string.
|
||||
function to_hex_string(s: std_logic_vector)
|
||||
return string
|
||||
is
|
||||
constant alphabet: string(1 to 16) := "0123456789abcdef";
|
||||
variable y: string(1 to s'length/4);
|
||||
begin
|
||||
for i in y'range loop
|
||||
y(i) := alphabet(to_integer(unsigned(s(s'high+4-4*i downto s'high+1-4*i))) + 1);
|
||||
end loop;
|
||||
return y;
|
||||
end function;
|
||||
|
||||
-- Reverse order of 8-bit groups within long bit vector.
|
||||
function flipbits(x: std_logic_vector) return std_logic_vector is
|
||||
variable y: std_logic_vector(x'length-1 downto 0);
|
||||
begin
|
||||
for p in 0 to x'length / 8 - 1 loop
|
||||
y(p*8+7 downto p*8) := x(x'high-p*8 downto x'high-p*8-7);
|
||||
end loop;
|
||||
return y;
|
||||
end function;
|
||||
|
||||
-- Force interpretation of string literal.
|
||||
function force_str(s: string) return string is
|
||||
begin
|
||||
return s;
|
||||
end function;
|
||||
|
||||
-- Test one of the instances of the RNG.
|
||||
procedure test_inst(signal s_rst: out std_logic;
|
||||
signal s_reseed: out std_logic;
|
||||
signal s_newkey: out std_logic_vector(79 downto 0);
|
||||
signal s_newiv: out std_logic_vector(79 downto 0);
|
||||
signal s_ready: out std_logic;
|
||||
signal s_valid: in std_logic;
|
||||
signal s_data: in std_logic_vector)
|
||||
is
|
||||
constant nbit: natural := s_data'length;
|
||||
constant init_duration: natural := 4 * 288 / nbit;
|
||||
variable lin: line;
|
||||
variable p: natural := 0;
|
||||
variable bitpos: natural;
|
||||
variable vk: natural;
|
||||
variable w: std_logic_vector(511 downto 0);
|
||||
variable wp: natural;
|
||||
begin
|
||||
-- Initialize inputs.
|
||||
s_reseed <= '0';
|
||||
s_newkey <= (others => '0');
|
||||
s_newiv <= (others => '0');
|
||||
s_ready <= '0';
|
||||
|
||||
-- End reset.
|
||||
wait until falling_edge(clk);
|
||||
s_rst <= '0';
|
||||
|
||||
-- Loop over test vectors.
|
||||
for k in testvec'range loop
|
||||
|
||||
write(lin, force_str("key = "));
|
||||
write(lin, to_hex_string(testvec(k).key));
|
||||
writeline(output, lin);
|
||||
write(lin, force_str("iv = "));
|
||||
write(lin, to_hex_string(testvec(k).iv));
|
||||
writeline(output, lin);
|
||||
|
||||
-- Reseed generator, except for first test vector.
|
||||
-- First test vector runs on initial seed.
|
||||
if k /= 0 then
|
||||
s_reseed <= '1';
|
||||
s_newkey <= flipbits(testvec(k).key);
|
||||
s_newiv <= flipbits(testvec(k).iv);
|
||||
wait until falling_edge(clk);
|
||||
s_reseed <= '0';
|
||||
s_newkey <= (others => '0');
|
||||
s_newiv <= (others => '0');
|
||||
end if;
|
||||
|
||||
-- Give generator time to complete initialization.
|
||||
for i in 0 to init_duration loop
|
||||
assert s_valid = '0'
|
||||
report "Generator indicates VALID too early";
|
||||
if (p mod 3 = 0) or (p mod 5 = 0) or (p mod 17 = 0) then
|
||||
s_ready <= '0';
|
||||
else
|
||||
s_ready <= '1';
|
||||
end if;
|
||||
wait until falling_edge(clk);
|
||||
p := p + 1;
|
||||
end loop;
|
||||
|
||||
-- Start generating random bits.
|
||||
bitpos := 0;
|
||||
|
||||
-- Start looping over output vectors.
|
||||
vk := testvec(k).data'low;
|
||||
|
||||
while vk <= testvec(k).data'high loop
|
||||
|
||||
-- Generate a block of bits.
|
||||
assert s_valid = '1' report "Output not VALID";
|
||||
|
||||
if (p mod 3 = 0) or (p mod 5 = 0) or (p mod 17 = 0) then
|
||||
-- Skipping this clock cycle.
|
||||
s_ready <= '0';
|
||||
else
|
||||
-- Consuming data this clock cycle.
|
||||
s_ready <= '1';
|
||||
|
||||
if bitpos >= testvec(k).data(vk).pos * 8 then
|
||||
-- Store bits in block.
|
||||
wp := bitpos - testvec(k).data(vk).pos * 8;
|
||||
assert wp = 0 or wp >= nbit
|
||||
report "Invalid test vector offset";
|
||||
assert wp + nbit <= w'length
|
||||
report "Invalid test vector offset";
|
||||
w(wp+nbit-1 downto wp) := s_data;
|
||||
end if;
|
||||
|
||||
bitpos := bitpos + nbit;
|
||||
end if;
|
||||
|
||||
wait until falling_edge(clk);
|
||||
p := p + 1;
|
||||
|
||||
if bitpos = testvec(k).data(vk).pos * 8 + w'length then
|
||||
-- Reached end of current output vector.
|
||||
|
||||
-- Dump output data to screen.
|
||||
write(lin, force_str("out["));
|
||||
write(lin, testvec(k).data(vk).pos, right, 6);
|
||||
write(lin, force_str("] = "));
|
||||
write(lin, to_hex_string(flipbits( w(127 downto 0))));
|
||||
writeline(output, lin);
|
||||
for tk in 1 to w'length / 128 - 1 loop
|
||||
write(lin, force_str(" "));
|
||||
write(lin, to_hex_string(flipbits(
|
||||
w(128*tk+127 downto 128*tk))));
|
||||
writeline(output, lin);
|
||||
end loop;
|
||||
|
||||
-- Check against expected output vector.
|
||||
assert w = flipbits(testvec(k).data(vk).data)
|
||||
report "Unexpected output from RNG";
|
||||
|
||||
-- Go to next output vector.
|
||||
vk := vk + 1;
|
||||
end if;
|
||||
|
||||
end loop;
|
||||
|
||||
-- Go to next test vector.
|
||||
writeline(output, lin);
|
||||
end loop;
|
||||
|
||||
-- Put instance back in reset.
|
||||
s_rst <= '1';
|
||||
|
||||
end procedure;
|
||||
|
||||
begin
|
||||
|
||||
-- Instantiate PRNG with 1-bit output.
|
||||
inst_x1: entity work.rng_trivium
|
||||
generic map (
|
||||
num_bits => 1,
|
||||
init_key => x"eb9845f29f4cf9a65300",
|
||||
init_iv => x"ac45de7710a942db740d" )
|
||||
port map (
|
||||
clk => clk,
|
||||
rst => x1_rst,
|
||||
reseed => x1_reseed,
|
||||
newkey => x1_newkey,
|
||||
newiv => x1_newiv,
|
||||
out_ready => x1_out_ready,
|
||||
out_valid => x1_out_valid,
|
||||
out_data => x1_out_data );
|
||||
|
||||
-- Instantiate PRNG with 8-bit output.
|
||||
inst_x8: entity work.rng_trivium
|
||||
generic map (
|
||||
num_bits => 8,
|
||||
init_key => x"0053A6F94C9FF24598EB",
|
||||
init_iv => x"0D74DB42A91077DE45AC" )
|
||||
port map (
|
||||
clk => clk,
|
||||
rst => x8_rst,
|
||||
reseed => x8_reseed,
|
||||
newkey => x8_newkey,
|
||||
newiv => x8_newiv,
|
||||
out_ready => x8_out_ready,
|
||||
out_valid => x8_out_valid,
|
||||
out_data => x8_out_data );
|
||||
|
||||
-- Instantiate PRNG with 64-bit output.
|
||||
inst_x64: entity work.rng_trivium
|
||||
generic map (
|
||||
num_bits => 64,
|
||||
init_key => x"eb9845f29f4cf9a65300",
|
||||
init_iv => x"ac45de7710a942db740d" )
|
||||
port map (
|
||||
clk => clk,
|
||||
rst => x64_rst,
|
||||
reseed => x64_reseed,
|
||||
newkey => x64_newkey,
|
||||
newiv => x64_newiv,
|
||||
out_ready => x64_out_ready,
|
||||
out_valid => x64_out_valid,
|
||||
out_data => x64_out_data );
|
||||
|
||||
-- Generate clock.
|
||||
clk <= (not clk) after 10 ns when clock_active else '0';
|
||||
|
||||
-- Main simulation process.
|
||||
process is
|
||||
begin
|
||||
|
||||
report "Start test bench";
|
||||
|
||||
-- Reset all instances.
|
||||
x1_rst <= '1';
|
||||
x8_rst <= '1';
|
||||
x64_rst <= '1';
|
||||
|
||||
-- Start clock.
|
||||
clock_active <= true;
|
||||
wait for 30 ns;
|
||||
|
||||
-- Test 1-bit instance.
|
||||
report "Test 1-bit generator";
|
||||
test_inst(x1_rst, x1_reseed, x1_newkey, x1_newiv,
|
||||
x1_out_ready, x1_out_valid, x1_out_data);
|
||||
|
||||
-- Test 8-bit instance.
|
||||
report "Test 8-bit generator";
|
||||
test_inst(x8_rst, x8_reseed, x8_newkey, x8_newiv,
|
||||
x8_out_ready, x8_out_valid, x8_out_data);
|
||||
|
||||
-- Test 64-bit instance.
|
||||
report "Test 64-bit generator";
|
||||
test_inst(x64_rst, x64_reseed, x64_newkey, x64_newiv,
|
||||
x64_out_ready, x64_out_valid, x64_out_data);
|
||||
|
||||
-- End simulation.
|
||||
report "End testbench";
|
||||
|
||||
clock_active <= false;
|
||||
wait;
|
||||
|
||||
end process;
|
||||
|
||||
end architecture;
|
Loading…
Reference in New Issue