library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_textio.all;

library std;
use std.textio.all;

entity tb is
end entity;

architecture bench of tb is
	constant CLK_PERIOD : time := 10 ns;
    
	signal stop : boolean := false;
    
	signal clk : std_logic;
	signal clk_en : std_logic := '0';
	signal reset : std_logic := '0';

	signal n : std_logic_vector(0 downto 0) := "0";
	signal start : std_logic := '0';
	signal done : std_logic;
    
	signal dataa : std_logic_vector(31 downto 0);
	signal datab : std_logic_vector(31 downto 0);
	signal result : std_logic_vector(31 downto 0);

	type test_vector_t is array (0 to 4) of std_logic_vector(31 downto 0);

	constant test_vector : test_vector_t := (
		x"00010000", -- one
		x"11110000", -- -one
		x"fff842ab", -- x
		x"ffe2859a", -- y
		x"001e3999"  -- z
	);

    begin
	ci_div_inst : entity work.ci_div
	port map (
	    clk       => clk,
	    clk_en    => clk_en,
	    reset     => reset,
	    dataa     => dataa,
	    datab     => datab,
	    result    => result,
	    start     => start,
	    done      => done,
            n         => n
	);
    
	stimulus : process
	begin
		reset <= '1';
		dataa <= x"00000000";
		datab <= x"00000000";
		wait for 50 ns;
		wait until rising_edge(clk);
		reset <= '0';
                -- enqueue div of 1/1
		clk_en <= '1';
                wait until rising_edge(clk);
                for i in 0 to test_vector'length - 1 loop
                        for j in 0 to test_vector'length - 1 loop
                                n <= "0";
                                dataa <= test_vector(i);
                                datab <= test_vector(j);
                                start <= '1';
                                wait until rising_edge(clk);
                                n <= "0";
                                dataa <= not(test_vector(i));
                                datab <= not(test_vector(j));
                                start <= '1';
                                wait until rising_edge(clk);
                                start <= '0';
                                wait until done <= '1';
                                wait until rising_edge(clk);
                                n <= "1";
                                start <= '1';
                                wait until rising_edge(clk);
                                start <= '0';
                                wait until done <= '1';
                                wait until rising_edge(clk);
                                n <= "1";
                                start <= '1';
                                wait until rising_edge(clk);
                                start <= '0';
                                wait until done <= '1';
                                wait until rising_edge(clk);
                        end loop;
                end loop;
		wait until rising_edge(clk);
		start <= '0';
                wait for 512*CLK_PERIOD;
                clk_en <= '0';
		stop <= true;
		wait;
	end process;
    
	generate_clk : process
	begin
		while not stop loop
			clk <= '1', '0' after CLK_PERIOD / 2;
			wait for CLK_PERIOD;
		end loop;
		wait;
	end process;
    
    end architecture;
    
