--
-- Star Fast-Link Testbench 
--
-- Matt Warren July 2015
--
--


library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
library readout130;
use readout130.pkg_star_flink.all;

entity star_flink_tester is
  port(
    symbol_align_o  : out std_logic_vector (2 downto 0);
    dec_output_en_o : out std_logic;

    -- signals 
    bcr_o     : out std_logic;
    ls_o      : out std_logic;
    lp_l0id_o : out std_logic_vector (7 downto 0);
    lp_req_o  : out std_logic;
    lp_done_i : in  std_logic;
    pr_l0id_o : out std_logic_vector (7 downto 0);
    pr_req_o  : out std_logic;
    pr_done_i : in  std_logic;
    -- infra
    clk160_o  : out std_logic;
    clk40_o   : out std_logic;
    rst_o     : out std_logic
    );

-- Declarations

end star_flink_tester;

---------------------------------------------------------------------------
architecture sim of star_flink_tester is

  constant POST_CLK_DELAY : time := 50 ps;

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

  signal pr_go : std_logic;
  signal lp_go : std_logic;

begin

  rst_o <= rst;

  clk     <= not(clk) after 12500 ps;
  clk40_o <= clk;

  clk160   <= not(clk160) after 3125 ps;
  clk160_o <= clk160;


  -- PR and LP signalling non-sequencial block
  -------------------------------------------------------------------
  -- This is done in a silly non-clocked way to make allow
  -- back-to back signals to be entered easily

  prc_sendprlp : process (lp_done_i, lp_go, pr_done_i, pr_go)
    variable pr_req : std_logic := '0';
    variable lp_req : std_logic := '0';

  begin

    if (pr_req = '0') and (lp_req = '0') then

      if (pr_go = '1') then
        pr_req := '1';
      elsif (lp_go = '1') then
        lp_req := '1';
      end if;

    else
      if (pr_done_i = '1') then
        pr_req := '0';
      end if;

      if (lp_done_i = '1') then
        lp_req := '0';
      end if;
    end if;
    pr_req_o <= pr_req;
    lp_req_o <= lp_req;

  end process;



  --======================================================================
  simulation : process
    --------------------------------------------------
    -- Procedures 
    --------------------------------------------------
    procedure WaitClk is
    begin
      wait until rising_edge(clk);
      wait for POST_CLK_DELAY;
    end procedure;
    ------------------------------------------------------
    procedure WaitClks (nclks : in integer := 1) is
    begin
      for waitclkloops in 1 to nclks loop
        wait until rising_edge(clk);
        wait for POST_CLK_DELAY;
      end loop;
    end procedure;
    ----------------------------------------------------

    ------------------------------------------------------
    procedure SendBCR is
    begin
      bcr_o <= '1';
      WaitClk;
      bcr_o <= '0';
    end procedure;
    ----------------------------------------------------
    procedure SendLS is
    begin
      ls_o <= '1';
      WaitClk;
      ls_o <= '0';
    end procedure;
    ----------------------------------------------------
    procedure SendBCRLS is
    begin
      bcr_o <= '1';
      ls_o  <= '1';
      WaitClk;
      bcr_o <= '0';
      ls_o  <= '0';
    end procedure;
    ----------------------------------------------------
    procedure SendPR(l0id : in integer := 16#a1#) is
    begin
      pr_l0id_o <= conv_std_logic_vector(l0id, 8);
      pr_go     <= '1';
      WaitClk;
      pr_go     <= '0';
    end procedure;
    ----------------------------------------------------
    procedure SendLP(l0id : in integer := 16#b3#) is
    begin
      lp_l0id_o <= conv_std_logic_vector(l0id, 8);
      lp_go     <= '1';
      WaitClk;
      lp_go     <= '0';
    end procedure;
    -----------------------------------------------------

    --============================================================================
  begin

    -- Init
    symbol_align_o  <= "000";
    dec_output_en_o <= '0';
    bcr_o           <= '0';
    ls_o            <= '0';
    lp_l0id_o       <= x"00";
    lp_go           <= '0';
    pr_l0id_o       <= x"00";
    pr_go           <= '0';

    rst <= '1';
    WaitClks(10);
    rst <= '0';

    WaitClks(10);
    --------------------------------------

    -- Test all the align settings
    --for n in 0 to 7 loop
    --  symbol_align_o <= conv_std_logic_vector(n, 3);
    --  WaitClks(20);
    --end loop;

    -- This one works!
    symbol_align_o  <= "010";
    WaitClks(10);
    dec_output_en_o <= '1';
    WaitClks(10);


    SendBCR;
    WaitClks(5);

    SendLS;
    WaitClks(5);

    SendBCRLS;
    WaitClks(5);

    SendPR(16#d1#);                     -- becomes symbols D3,D2,D1
    WaitClks(3);
    SendLP(16#53#);                     -- becomes symbols D1,D2,D3
    WaitClks(3);
    SendPR(16#e5#);                     -- becomes symbols D3,D4,D5
    WaitClks(3);
    SendLP(16#53#);                     -- becomes symbols D1,D2,D3
    WaitClks(3);
    SendLP(16#53#);                     -- becomes symbols D1,D2,D3
    SendBCR;
    SendLS;
    SendLS;
    SendLS;
    SendPR(16#d1#);                     -- becomes symbols D3,D2,D1
    SendLS;
    SendLS;



    wait;
  end process;

end architecture sim;