-- TestBench Template 

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.numeric_std.ALL;

ENTITY trigger_top_tb IS
  END trigger_top_tb;

ARCHITECTURE behavior OF trigger_top_tb IS 

  -- Component Declarationi
  component trigger_top
    port (
           pulse_i    : in   STD_LOGIC;
           pulse_o    : out  STD_LOGIC;

           utc_i      : in   STD_LOGIC_VECTOR(95 downto 0);

           wb_rst_i   : in   STD_LOGIC;
           wb_clk     : in   STD_LOGIC;
           wb_stb_i   : in   STD_LOGIC;
           wb_cyc_i   : in   STD_LOGIC;
           wb_ack_o   : out  STD_LOGIC;
           wb_err_o   : out  STD_LOGIC;
           wb_rty_o   : out  STD_LOGIC;
           wb_we_i    : in   STD_LOGIC;
           wb_sel_i   : in   STD_LOGIC_VECTOR (3  downto 0);
           wb_data_i  : in   STD_LOGIC_VECTOR (31 downto 0);
           wb_data_o  : out  STD_LOGIC_VECTOR (31 downto 0);
           wb_addr_i  : in   STD_LOGIC_VECTOR (2  downto 0)
         );
  end component;


  constant STATUS_addr  : STD_LOGIC_VECTOR (2 downto 0)  := "000";
  constant CTR0_addr    : STD_LOGIC_VECTOR (2 downto 0)  := "001";
  constant CTR1_addr    : STD_LOGIC_VECTOR (2 downto 0)  := "010";
  constant RAM0_addr    : STD_LOGIC_VECTOR (2 downto 0)  := "101";
  constant RAM1_addr    : STD_LOGIC_VECTOR (2 downto 0)  := "110";
  constant RAM2_addr    : STD_LOGIC_VECTOR (2 downto 0)  := "111";

  signal pulse_i   :  STD_LOGIC;
  signal pulse_o   :  STD_LOGIC;
  signal utc_i     :  STD_LOGIC_VECTOR(95 downto 0);

  signal wb_rst_i  :  STD_LOGIC;
  signal wb_clk    :  STD_LOGIC;
  signal wb_stb_i  :  STD_LOGIC;
  signal wb_cyc_i  :  STD_LOGIC;
  signal wb_ack_o  :  STD_LOGIC;
  signal wb_err_o  :  STD_LOGIC;
  signal wb_rty_o  :  STD_LOGIC;
  signal wb_we_i   :  STD_LOGIC;
  signal wb_sel_i  :  STD_LOGIC_VECTOR (3  downto 0);
  signal wb_data_i :  STD_LOGIC_VECTOR (31 downto 0);
  signal wb_data_o :  STD_LOGIC_VECTOR (31 downto 0);
  signal wb_addr_i :  STD_LOGIC_VECTOR (2  downto 0);

  constant wb_clk_period: time := 50 ns;

begin
  -- Component Instantiation
  uut: trigger_top 
  port map(
            pulse_i      =>    pulse_i,  
            pulse_o      =>    pulse_o, 
            utc_i        =>    utc_i, 
            wb_rst_i     =>    wb_rst_i,
            wb_clk       =>    wb_clk,
            wb_stb_i     =>    wb_stb_i, 
            wb_cyc_i     =>    wb_cyc_i,
            wb_ack_o     =>    wb_ack_o,
            wb_err_o     =>    wb_err_o,
            wb_rty_o     =>    wb_rty_o,
            wb_we_i      =>    wb_we_i,  
            wb_sel_i     =>    wb_sel_i ,
            wb_data_i    =>    wb_data_i,
            wb_data_o    =>    wb_data_o,
            wb_addr_i    =>    wb_addr_i
          );

  wb_clk_process :process
  begin
    wb_clk <= '1';
    wait for wb_clk_period/2;
    wb_clk <= '0';
    wait for wb_clk_period/2;
  end process;


  tb_proc: process

    procedure initial_cond is
    begin
      wait for wb_clk_period*2;
      pulse_i  <= '0';
      utc_i    <= (others => '0');
      wb_rst_i <= '1';
      wait for wb_clk_period*2;
      wb_rst_i <= '0';
      wait for wb_clk_period*10;
    end; 


    procedure write_reg (reg_addr: STD_LOGIC_VECTOR(2 downto 0); data: STD_LOGIC_VECTOR(31 downto 0)) is
    begin
      wait until rising_edge(wb_clk);
      wb_addr_i   <= reg_addr;
      wb_data_i   <= data;
      wb_we_i     <= '1';
      wb_stb_i    <= '1';
      wb_cyc_i    <= '1';
      wb_sel_i    <= X"0";
      wait until rising_edge(wb_clk);
      wait until rising_edge(wb_clk);
      assert wb_ack_o = '1' report "Wishbone write to register not acked";
      wb_we_i     <= '0';
      wb_stb_i    <= '0';
      wb_cyc_i    <= '0';
      wb_sel_i    <= X"0";
    end;

    procedure read_reg (reg_addr: STD_LOGIC_VECTOR(2 downto 0) ) is
    begin
      wait until rising_edge(wb_clk);
      wb_addr_i   <= reg_addr;
      wb_we_i     <= '0';
      wb_stb_i    <= '1';
      wb_cyc_i    <= '1';
      wb_sel_i    <= X"0";
      wait until rising_edge(wb_clk);
      wait until rising_edge(wb_clk);
      assert wb_ack_o = '1' report "Wishbone read to register not acked";
      wb_we_i     <= '0';
      wb_stb_i    <= '0';
      wb_cyc_i    <= '0';
      wb_sel_i    <= X"0";
    end;

  begin

    initial_cond;

-------------------------------------------------------------------------------
--  Configuration process
---------------------------------------
--  1.- CTR0: disable EN, EN_TT
--  2.- CTR0: set CGM, CPL
--  3.- CTR1: set MinPL, MaxPL
--  4.- RAM0: set CLR_TT
--  6.- CTR0: enable EN, EN_TT, disable CLR_TT 
---------------------------------------
--  Recommended masks to use for the steps
--  CTR0_step1     X"xxxxxxYY"     where Y is "yyy0"
--  CTR0_step2     X"xxxxxxxx"      
--  CTR1_step3     X"xxxxxxxx"
--  RAM0_step4     X"xxxxxxxZ"     where Z is "zz1z"
--  CTR0_step5     X"xxxxxxWY"     where Y is "yyy1"
----                               where W is "ww01"
-------------------------------------------------------------------------------
    
    pulse_i <= '1';

    write_reg(CTR0_addr, X"01FFFF22");
    wait for 2*wb_clk_period;
    read_reg(CTR0_addr);
    wait for 6*wb_clk_period;

    write_reg(CTR1_addr, X"3FFF00FF");
    wait for 2*wb_clk_period;
    read_reg(CTR1_addr);
    wait for 6*wb_clk_period;

    write_reg(CTR0_addr, X"01FFFF11");
    wait for 2*wb_clk_period;
    read_reg(CTR0_addr);
    wait for 4096*wb_clk_period;


  end process;

end;
