-- See the file "LICENSE" for the full license governing this code. --
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;

LIBRARY work;
USE work.lt16soc_peripherals.ALL;

ENTITY scrolling_buffer_tb IS
END ENTITY;

ARCHITECTURE sim OF scrolling_buffer_tb IS

    constant CLK_PERIOD : time := 10 ns;

    signal rst : std_logic;
    signal clk : std_logic := '0';

    signal buffer_clear : std_logic := '0';
    signal buffer_write : std_logic := '0';
    signal buffer_data : std_logic_vector(4 downto 0) := (others => '0');
    signal next_char : std_logic := '0';
    signal hex_char : std_logic_vector(4 downto 0);

    component scrolling_buffer
        port(
            clk : in std_logic;
            rst : in std_logic;
            buffer_clear : in std_logic;
            buffer_write : in std_logic;
            buffer_data : in std_logic_vector(4 downto 0);
            next_char : in std_logic;
            hex_char : out std_logic_vector(4 downto 0)
        );
    end component;

BEGIN

	buf: scrolling_buffer
        port map(
			clk => clk,
            rst => rst,
            buffer_clear => buffer_clear,
            buffer_write => buffer_write,
            buffer_data => buffer_data,
            next_char => next_char,
            hex_char => hex_char
    );

    clk_gen: process
	begin
		clk	<= not clk;
		wait for CLK_PERIOD/2;
	end process clk_gen;

	stimuli: process
	begin
        rst <= '1';
        wait for CLK_PERIOD;

        rst <= '0';
        wait for CLK_PERIOD;

        buffer_data <= "00001";
        buffer_write <= '1';
        
        wait for CLK_PERIOD;
        buffer_data <= "01011";
        
        wait for CLK_PERIOD;
        buffer_write <= '0';
        
        wait for CLK_PERIOD;
        buffer_data <= "01001";
        buffer_write <= '1';
        
        wait for CLK_PERIOD;
        buffer_data <= "00000";
        buffer_write <= '0';
        
        wait for CLK_PERIOD;
        next_char <= '1';
        
        wait for CLK_PERIOD;
        assert hex_char = "00001" severity failure;
        
        wait for CLK_PERIOD;
        assert hex_char = "01011" severity failure;
        
        wait for CLK_PERIOD;
        assert hex_char = "01001" severity failure;
        
        wait for CLK_PERIOD;
        next_char <= '0';
        assert hex_char = "00001" severity failure; -- special case

        wait for CLK_PERIOD * 3;
        
        -- Write buffer full
        buffer_data <= "11111";
        buffer_write <= '1';
        
        wait for CLK_PERIOD * 16;
        buffer_data <= "00000";
        buffer_write <= '0';
        
        wait for CLK_PERIOD;
        next_char <= '1';

		wait for CLK_PERIOD * 8;
		buffer_clear <= '1';
		next_char <= '0';
		
		wait for CLK_PERIOD;
		buffer_clear <= '0';
        buffer_data <= '0' & x"D";
        buffer_write <= '1';

        wait for CLK_PERIOD;
		buffer_data <= '0' & x"E";
    
        wait for CLK_PERIOD;
		buffer_data <= '0' & x"A";

        wait for CLK_PERIOD;
		buffer_data <= '0' & x"D";

        wait for CLK_PERIOD;
		buffer_data <= '0' & x"B";

        wait for CLK_PERIOD;
		buffer_data <= '0' & x"E";

        wait for CLK_PERIOD;
		buffer_data <= '0' & x"E";

        wait for CLK_PERIOD;
		buffer_data <= '0' & x"F";

        wait for CLK_PERIOD;
        buffer_data <= (others => '0');
		buffer_write <= '0';
		
        wait for CLK_PERIOD;
        wait for CLK_PERIOD;
        next_char <= '1';
        
        wait for CLK_PERIOD;
        assert hex_char = '0' & x"D" severity failure;
        
        wait for CLK_PERIOD;
        assert hex_char = '0' & x"E" severity failure;
        
        wait for CLK_PERIOD;
        assert hex_char = '0' & x"A" severity failure;
        
        wait for CLK_PERIOD;
        assert hex_char = '0' & x"D" severity failure;

        wait for CLK_PERIOD;
        assert hex_char = '0' & x"B" severity failure;
        
        wait for CLK_PERIOD;
        assert hex_char = '0' & x"E" severity failure;
        
        wait for CLK_PERIOD;
        assert hex_char = '0' & x"E" severity failure;
        
        wait for CLK_PERIOD;
        assert hex_char = '0' & x"F" severity failure;

		wait for CLK_PERIOD * 8;

		assert false report "Simulation terminated!" severity failure;
	end process stimuli;

END ARCHITECTURE;
