-- It's gonna be pretty goddamn hard to automatically verify that the outputs
-- are right. Instead, we'll just throw some reads and writes at it and take a 
-- look at the wave forms to make sure the right things are happening.

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

entity ray_tracer_avalon_module_tester is
end ray_tracer_avalon_module_tester;

architecture test of ray_tracer_avalon_module_tester is
	signal clock : std_logic := '0';
	signal reset : std_logic := '1';

	signal read       : std_logic := '0';
	signal write      : std_logic := '0';
	signal chipselect : std_logic := '0';
	signal address    : unsigned(6 downto 0)  := (others => '0');
	signal readdata   : unsigned(15 downto 0) := (others => '0');
	signal writedata  : unsigned(15 downto 0) := (others => '0');

	signal vga_clock : std_logic  := '0';
	signal vga_h_sync : std_logic := '0';
	signal vga_v_sync : std_logic := '0';
	signal vga_blank : std_logic  := '0';
	signal vga_sync : std_logic   := '0';
	signal vga_r : unsigned(9 downto 0) := (others => '0');
	signal vga_g : unsigned(9 downto 0) := (others => '0');
	signal vga_b : unsigned(9 downto 0) := (others => '0');
begin
	ray_tracer_avalon_module_inst : entity work.ray_tracer_avalon_module port map (
		clock => clock,
		reset => reset,

		read => read,
		write => write,
		chipselect => chipselect, 
		address => address,
		readdata => readdata,
		writedata => writedata,

		vga_clock => vga_clock,
		vga_h_sync => vga_h_sync,
		vga_v_sync => vga_v_sync,
		vga_blank => vga_blank,
		vga_sync => vga_sync,
		vga_r => vga_r,
		vga_g => vga_g,
		vga_b => vga_b,
		
		debug_address => (others => '0')
	);

	process
	begin
		loop
			clock <= '0';
			wait for 10 ns;
			clock <= '1';
			wait for 10 ns;
			reset <= '0';
		end loop;
	end process;
	
	process
	begin
		wait for 20 ns;

		read <= '0';
		chipselect <= '1';
		
		-- Camera
		address <= "0000000"; writedata <= "0000000011100111"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0000001"; writedata <= "0000000010101011"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0000010"; writedata <= "0000000000001010"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		
		-- Rectangles
		address <= "0000011"; writedata <= "0000000000000000"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0000100"; writedata <= "0000000000000000"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0000101"; writedata <= "0000000000000000"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0000110"; writedata <= "0000000011111110"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0000111"; writedata <= "0000000011111110"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0001000"; writedata <= "0000000000000000"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0001001"; writedata <= "0000000000111100"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0001010"; writedata <= "0000000011111110"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0001011"; writedata <= "0000000000000000"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0001100"; writedata <= "0000000000000000"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0001101"; writedata <= "0000000011111110"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0001110"; writedata <= "0000000011111110"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0001111"; writedata <= "0000000011111110"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0010000"; writedata <= "0000000000000011"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0010001"; writedata <= "0000000011110001"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0010010"; writedata <= "0000000010100001"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0010011"; writedata <= "0000000000000001"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0010100"; writedata <= "0000000011111011"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0010101"; writedata <= "0000000010110101"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0010110"; writedata <= "0000000000000001"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0010111"; writedata <= "0000000000001100"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0011000"; writedata <= "0000000011110001"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0011001"; writedata <= "0000000010100001"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0011010"; writedata <= "0000000000001011"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0011011"; writedata <= "0000000011111011"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0011100"; writedata <= "0000000010110101"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0011101"; writedata <= "0000000000001011"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0011110"; writedata <= "0000000000001100"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0011111"; writedata <= "0000000011110001"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0100000"; writedata <= "0000000010100001"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0100001"; writedata <= "0000000000010101"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0100010"; writedata <= "0000000011111011"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0100011"; writedata <= "0000000010110101"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0100100"; writedata <= "0000000000010101"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0100101"; writedata <= "0000000000001100"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0100110"; writedata <= "0000000011001000"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0100111"; writedata <= "0000000000110010"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0101000"; writedata <= "0000000011111110"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0101001"; writedata <= "0000000011001000"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0101010"; writedata <= "0000000011001000"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0101011"; writedata <= "0000000011111011"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		address <= "0101100"; writedata <= "0000000000110011"; write <= '1'; wait for 20 ns; write <= '0'; wait for 20 ns;
		
		wait for 20 ms;
		
		report "No problem mon! End of simulation." severity failure;
	end process;
end test;
