library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.ssd_controller_pkg.all;
use work.nes_controller_pkg.all;
use work.ball_game_pkg.all;

entity ssd_controller_tb is
end entity;

architecture bench of ssd_controller_tb is

	-- ssd controller signals
	signal clk   : std_logic := '-';
	signal res_n : std_logic := '-';

	signal game_state    : ball_game_state_t := IDLE;
	signal controller    : nes_buttons_t := (others => '0');
	signal player_points : std_logic_vector(15 downto 0) := (others => '0');

	signal hex0 : std_logic_vector(6 downto 0);
	signal hex1 : std_logic_vector(6 downto 0);
	signal hex2 : std_logic_vector(6 downto 0);
	signal hex3 : std_logic_vector(6 downto 0);
	signal hex4 : std_logic_vector(6 downto 0);
	signal hex5 : std_logic_vector(6 downto 0);
	signal hex6 : std_logic_vector(6 downto 0);
	signal hex7 : std_logic_vector(6 downto 0);

	-- tb signals
	signal stop_clock : boolean := false;

	constant CLK_PERIOD     : time := 20 ns;
	constant BLINK_INTERVAL : integer := 6;
	constant BLINK_COUNT    : integer := 3;
	-- 1234 + (11907086 mod 500) = 1234 + 86 = 1320
	constant PP : integer := 1320;

begin

	ssd_controller_inst : ssd_controller
	generic map (
		BLINK_INTERVAL => 6,
		BLINK_COUNT => 3,
		ANIM_CYCLES => 4
	)
	port map (
		clk => clk,
		res_n => res_n,

		game_state => game_state,
		controller => controller,
		player_points => player_points,

		hex0 => hex0,
		hex1 => hex1,
		hex2 => hex2,
		hex3 => hex3,
		hex4 => hex4,
		hex5 => hex5,
		hex6 => hex6,
		hex7 => hex7
	);

	generate_ssd : process
	begin
		res_n <= '0';
		wait for 250 ns;
		wait until rising_edge(clk);
		res_n <= '1';
		wait until rising_edge(clk);

		for i in 0 to (1e4 - PP) loop
			player_points <= std_logic_vector(to_unsigned(i + PP, player_points'LENGTH));
			-- this would be a 1 sec event normally, but the simulation would
			-- take way too long
			wait for 500 ns;
			wait until rising_edge(clk);
		end loop;

		wait until rising_edge(clk);
		stop_clock <= true;
	end process;

	generate_select_press : process
	begin
		wait for 2 us;
		game_state <= RUNNING;
		controller.btn_select <= '1';
		wait;
	end process;

	-- taken from top_tb
	generate_clk : process
	begin
		while not stop_clock loop
			clk <= '0', '1' after CLK_PERIOD / 2;
			wait for CLK_PERIOD;
		end loop;
		wait;
	end process;

end architecture;
