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

entity square_test is
end square_test;

architecture rtl of square_test is

  component square is
    port
    (
      clk     : in std_logic;
      rst     : in std_logic;

    -- bus slave interface
      s_we      : in std_logic;
      s_addr    : in std_logic_vector(15 downto 0);
      s_din     : in std_logic_vector(15 downto 0);

    -- bus master interface (DMA!!)
      m_busy    : in std_logic;
      m_we      : out std_logic;
      m_addr    : out std_logic_vector(15 downto 0);
      m_dout    : out std_logic_vector(15 downto 0)
    );
  end component;

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

  signal s_we, m_busy, m_we: std_logic;
  signal s_addr, s_din, m_addr, m_dout: std_logic_vector(15 downto 0);

begin
  dut: square port map(clk => clk, rst => rst,
                       s_we => s_we, s_addr => s_addr, s_din => s_din,
                       m_busy => m_busy, m_we => m_we, m_addr => m_addr, m_dout => m_dout);

  -- tick tock
  process
  begin
    if finished = '0' then
      clk <= not clk;
      wait for 5 ns;
    else
      clk <= '0';
      wait;
    end if;
  end process;

  process
  begin
    rst <= '1';

    wait for 1 ns;
    assert(m_we='0') report "Fail rst" severity error;

    rst <= '0';
    m_busy <= '0';

    wait for 10 ns;

    s_we <= '1';
    s_addr <= x"0000"; -- period
    s_din <= x"0001"; -- 256 cycles (2560 ns)

    wait for 10 ns;

    s_we <= '1';
    s_addr <= x"0002"; -- high
    s_din <= x"0042";

    wait for 10 ns;

    s_we <= '1';
    s_addr <= x"0004"; -- low
    s_din <= x"0037";

    wait for 10 ns;

    s_we <= '1';
    s_addr <= x"0006"; -- DNA address
    s_din <= x"babe";

    wait for 10 ns;

    s_we <= '1';
    s_addr <= x"0008"; -- enable
    s_din <= x"0001";

    wait for 20 ns;

    assert(m_addr = x"babe") report "Fail to write to mem addr" severity error;
    assert(m_we = '1') report "Fail to write to mem we" severity error;
    assert(m_dout = x"0037") report "Fail to write to mem dout" severity error;

    wait for 20 ns;

    assert(m_we = '0') report "Fail to stop m_we" severity error;

    wait for 1300 ns;

    assert(m_dout = x"0042") report "Fail to write to mem dout" severity error;

    assert false report "Test done." severity note;

    finished <= '1';
    wait;

  end process;
end rtl;