-------------------------------------------------------------------------------- -- -- VHDL Test Bench for module: binary_algorithm.vhd (ch4) -- -- Executes NUMBER_TESTS operations with random values. -- -------------------------------------------------------------------------------- LIBRARY ieee; USE ieee.std_logic_1164.ALL; USE IEEE.std_logic_arith.all; USE ieee.std_logic_unsigned.all; USE ieee.numeric_std.ALL; USE ieee.std_logic_textio.ALL; use ieee.math_real.all; -- for UNIFORM, TRUNC USE std.textio.ALL; use work.Fermat_divider_parameters.all; ENTITY test_fermat_divider IS END test_fermat_divider; ARCHITECTURE behavior OF test_fermat_divider IS -- Component Declaration for the Unit Under Test (UUT) COMPONENT fermat_divider is PORT ( x, y: in std_logic_vector(K-1 downto 0); clk, reset, start: in std_logic; z: out std_logic_vector(K-1 downto 0); done: out std_logic ); END COMPONENT; -- Internal signals SIGNAL x, y, z : std_logic_vector(K-1 downto 0) := (others=>'0'); SIGNAL clk, reset, start, done: std_logic; constant DELAY : time := 100 ns; constant PERIOD : time := 200 ns; constant DUTY_CYCLE : real := 0.5; constant OFFSET : time := 0 ns; constant NUMBER_TESTS: natural := 1000; BEGIN -- Instantiate the Unit Under Test (UUT) uut: fermat_divider PORT MAP(x => x, y => y, clk => clk, reset => reset, start => start, z => z, done => done); PROCESS -- clock process for clk BEGIN WAIT for OFFSET; CLOCK_LOOP : LOOP clk <= '0'; WAIT FOR (PERIOD *(1.0 - DUTY_CYCLE)); clk <= '1'; WAIT FOR (PERIOD * DUTY_CYCLE); END LOOP CLOCK_LOOP; END PROCESS; tb_proc : PROCESS --generate values VARIABLE TX_LOC : LINE; VARIABLE TX_STR : String(1 to 4096); VARIABLE seed1, seed2: positive; VARIABLE rand: real; VARIABLE i_x, i_y, i_p, i_z, i_yz_modp: integer; VARIABLE cycles, max_cycles, min_cycles, total_cycles: integer := 0; VARIABLE avg_cycles: real; VARIABLE initial_time, final_time: time; BEGIN min_cycles:= 2**20; i_p := conv_integer(P); start <= '0'; reset <= '1'; WAIT FOR PERIOD; reset <= '0'; WAIT FOR PERIOD; for I in 1 to NUMBER_TESTS loop UNIFORM(seed1, seed2, rand); i_x := INTEGER(TRUNC(rand * real(i_p))); x <= CONV_STD_LOGIC_VECTOR (i_x, k); UNIFORM(seed1, seed2, rand); i_y := INTEGER(TRUNC(rand * real(i_p))); if (i_y = 0) then i_y := i_p-1; end if; y <= CONV_STD_LOGIC_VECTOR (i_y, k); start <= '1'; initial_time := now; WAIT FOR PERIOD; start <= '0'; wait until done = '1'; final_time := now; cycles := (final_time - initial_time)/PERIOD; ASSERT (FALSE) REPORT "Number of Cycles: " & integer'image(cycles) SEVERITY WARNING; if cycles > max_cycles then max_cycles:= cycles; end if; if cycles < min_cycles then min_cycles:= cycles; end if; total_cycles := total_cycles+cycles; WAIT FOR 2*PERIOD; i_z := conv_integer(z); i_yz_modp := (i_y * i_z) mod i_p; IF ( i_x /= i_yz_modp ) THEN write(TX_LOC,string'("ERROR!!! (X=")); write(TX_LOC, x); write(TX_LOC,string'("/ Y=")); write(TX_LOC, y); write(TX_LOC,string'(") mod P=")); write(TX_LOC, p); write(TX_LOC,string'(" is Z=")); write(TX_LOC, z); write(TX_LOC,string'(" Y*Z mod P = ")); write(TX_LOC, (i_yz_modp)); write(TX_LOC, string'(" ( i_x =")); write(TX_LOC, i_x); write(TX_LOC, string'(", i_y =")); write(TX_LOC, i_y); write(TX_LOC, string'(", i_p =")); write(TX_LOC, i_p); write(TX_LOC, string'(", i_z =")); write(TX_LOC, i_z); write(TX_LOC, string'(" )")); TX_STR(TX_LOC.all'range) := TX_LOC.all; Deallocate(TX_LOC); ASSERT (FALSE) REPORT TX_STR SEVERITY ERROR; END IF; end loop; WAIT FOR DELAY; avg_cycles := real(total_cycles)/real(NUMBER_TESTS); ASSERT (FALSE) REPORT "Simulation successful!. MinCycles: " & integer'image(min_cycles) & " MaxCycles: " & integer'image(max_cycles) & " TotalCycles: " & integer'image(total_cycles) & " AvgCycles: " & real'image(avg_cycles) SEVERITY FAILURE; END PROCESS; END;