

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_signed.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_misc.all;



library std;
use std.textio.all;
use ieee.std_logic_textio.all;

library work;
use work.common_interface.all;
use work.hail_simulation.all;

entity tb_tms_top is
end tb_tms_top;


architecture behave of tb_tms_top is

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

  signal links_in : links_in_type;
  signal links_out : links_out_type;

  signal system_in,system_out : std_logic_vector(system_width-1 downto 0);

  signal host_in : host_in_type := host_in_zeros;
  signal host_out : host_out_type;

  signal ten_mhz_clk : std_logic := '0';
  signal tbus_bplane,tbus_header,tbus_master : std_logic_vector(10 downto 1) := (others => '0');

  signal adc_in_0_0 : std_logic_vector(13 downto 0) := (others => '0');
  signal adc_in_0_1 : std_logic_vector(13 downto 0) := (others => '0');
  signal adc_in_0_2 : std_logic_vector(13 downto 0) := (others => '0');
  signal adc_in_1_0 : std_logic_vector(13 downto 0) := (others => '0');
  signal adc_in_1_1 : std_logic_vector(13 downto 0) := (others => '0');
  signal adc_in_1_2 : std_logic_vector(13 downto 0) := (others => '0');
  signal adc_in_2_0 : std_logic_vector(13 downto 0) := (others => '0');
  signal adc_in_2_1 : std_logic_vector(13 downto 0) := (others => '0');
  signal adc_in_2_2 : std_logic_vector(13 downto 0) := (others => '0');
  
  

  component user_top_level
    port (
    -- Host Abstract Interface Connection
    clk        : in  std_logic;
    rst        : in  std_logic;
    system_in  : in  std_logic_vector(system_width-1 downto 0);
    system_out : out std_logic_vector(system_width-1 downto 0);
    -- Timing Inputs
    tbus_bplane	:inout std_logic_vector(10 downto 1);
    tbus_header	:inout std_logic_vector(10 downto 1);  
    tbus_master	:in std_logic_vector(10 downto 1);
    ten_mhz_clk       : in std_logic;
    -- ADC Inputs
    adc_in_0_0 : in std_logic_vector(13 downto 0);
    adc_in_0_1 : in std_logic_vector(13 downto 0);
    adc_in_0_2 : in std_logic_vector(13 downto 0);
    adc_in_1_0 : in std_logic_vector(13 downto 0);
    adc_in_1_1 : in std_logic_vector(13 downto 0);
    adc_in_1_2 : in std_logic_vector(13 downto 0);
    adc_in_2_0 : in std_logic_vector(13 downto 0);
    adc_in_2_1 : in std_logic_vector(13 downto 0);
    adc_in_2_2 : in std_logic_vector(13 downto 0);
    adc_enb    : out std_logic_vector(2 downto 0);
    syn_rst    : out std_logic
    );
  end component;

  
  
begin 

  -- Generate 125MHz CLK 
  
  clk <= not clk after 4 ns;
  ten_mhz_clk <= not ten_mhz_clk after 50 ns;
  
  dut0: user_top_level
    port map (
      clk        => clk,
      rst        => rst,
      system_in  => system_in,
      system_out => system_out,
      tbus_bplane => tbus_bplane,
      tbus_header => tbus_header,
      tbus_master => tbus_master,
      ten_mhz_clk => ten_mhz_clk,
      adc_in_0_0 => adc_in_0_0,
      adc_in_0_1 => adc_in_0_1,
      adc_in_0_2 => adc_in_0_2,
      adc_in_1_0 => adc_in_1_0,
      adc_in_1_1 => adc_in_1_1,
      adc_in_1_2 => adc_in_1_2,
      adc_in_2_0 => adc_in_2_0,
      adc_in_2_1 => adc_in_2_1,
      adc_in_2_2 => adc_in_2_2);

  hail0: hail_simulator
    generic map (
      board              => adm_xrc4,
      number_of_memories => 4)
    port map (   
      clk          => clk,
      rst          => rst,
      system_out   => system_out,
      system_in    => system_in,
      links_in     => links_in,
      links_out    => links_out,
      host_in      => host_in,
      host_out     => host_out);

  -- N.B. Not used by PUPE design
  -- Connect Link 0 to 1 and 2 to 3
  links_i: for i in 0 to 1 generate
    link_connect_i: link_connect
      port map (
        linkA_in  => links_in(2*i),
        linkA_out => links_out(2*i),
        linkB_in  => links_in(2*i+1),
        linkB_out => links_out(2*i+1));
  end generate links_i;

  -- Host Simulation
  -- Sequential process
  process
    file switch_table_file : text is in "switch_table.txt";
    file phase_table_file : text is in "phase_table.txt";
    file sigma_file : text is in "beam1-437000-8-sigma.txt";
    file deltax_file : text is in "beam1-437000-8-deltax.txt";
    file deltay_file : text is in "beam1-437000-8-deltay.txt";    
    
    variable text_in : line;
    variable val : integer;
    variable addr : integer;
    variable bank : integer;
    variable data : std_logic_vector(63 downto 0);
    variable d : std_logic_vector(31 downto 0);
  begin  -- process
    rst <= '1';
    wait for 30 ns;
    rst <= '0';
    wait for 1000 ns;
    -- Set Timing Reg to enable internal 10MHz CLK
    d := CONV_STD_LOGIC_VECTOR(350,16) & "11111111" & "00000000";
    addr := 16+12;
    host_write_control_register(host_in => host_in, host_out => host_out, address => addr, data => d);
    -- Copy Switch Table from File to BRAM Bank #3
    addr := 0;
    bank := 3;
    while not endfile(switch_table_file) loop
      for i in 0 to 1 loop
        if not endfile(switch_table_file) then
          readline(switch_table_file,text_in);
          read(text_in,val);
        else
          val := 0;
        end if;
        data(i*32+31 downto i*32) := CONV_STD_LOGIC_VECTOR(val,32);
      end loop;  -- i      
      host_write_internal_memory(host_in => host_in, host_out => host_out, bank => bank, address => addr, data => data);
      addr := addr+1;
    end loop;

    -- Copy Phase Table from File to BRAM Bank #2
    addr := 0;
    bank := 2;
    while not endfile(phase_table_file) loop
      for i in 0 to 7 loop
        if not endfile(phase_table_file) then
          readline(phase_table_file,text_in);
          read(text_in,val);
        else
          val := 0;
        end if;
        data(i*8+7 downto i*8) := CONV_STD_LOGIC_VECTOR(val,8);
      end loop;  -- i      
      host_write_internal_memory(host_in => host_in, host_out => host_out, bank => bank, address => addr, data => data);
      addr := addr+1;
    end loop;

    -- Set Trigger
    d := CONV_STD_LOGIC_VECTOR(254,32);
    addr := 16+11;
    host_write_control_register(host_in => host_in, host_out => host_out, address => addr, data => d);
    -- Set Diagnostics
    d := CONV_STD_LOGIC_VECTOR(17,32);
    addr := 16+10;
    host_write_control_register(host_in => host_in, host_out => host_out, address => addr, data => d);
    
--    wait for 1 us;
--    -- Start Cycle
--    d := CONV_STD_LOGIC_VECTOR(2+32256,32);
--    addr := 16+12;
--    host_write_control_register(host_in => host_in, host_out => host_out, address => addr, data => d);
--    wait for 1 us;
--    -- Stop Cycle
--    d := CONV_STD_LOGIC_VECTOR(32256,32);
--    addr := 16+12;
--    host_write_control_register(host_in => host_in, host_out => host_out, address => addr, data => d);
    
--    -- Set up test SDRAM from File
--    addr := 0;
--    bank := 3;
--    while not endfile(sigma_file) loop
--      for i in 0 to 1 loop
--        if not endfile(sigma_file) then
--          readline(sigma_file,text_in);
--          read(text_in,val);
--        else
--          val := 0;
--        end if;
--        data(i*32+11 downto i*32) := CONV_STD_LOGIC_VECTOR(val,12);
--        if not endfile(deltax_file) then
--          readline(deltax_file,text_in);
--          read(text_in,val);
--        else
--          val := 0;
--        end if;
--        data(i*32+21 downto i*32+12) := CONV_STD_LOGIC_VECTOR(val,10);
--        if not endfile(deltay_file) then
--          readline(deltay_file,text_in);
--          read(text_in,val);
--        else
--          val := 0;
--        end if;
--        data(i*32+31 downto i*32+22) := CONV_STD_LOGIC_VECTOR(val,10);
--      end loop;  -- i      
--      host_write_external_memory(host_in => host_in, host_out => host_out, bank => bank, address => addr, data => data);
--      addr := addr+1;
--    end loop;

--    -- Grant access to SDRAM
--    for i in 0 to 3 loop
--      bank := i;
--      host_external_memory_set_grant(host_in => host_in, host_out => host_out,bank => bank);
--    end loop;  -- i

    
--    -- Set ADC regs to enable test SDRAM
--    d := CONV_STD_LOGIC_VECTOR(addr-1,32);
--    addr := 4;
--    host_write_control_register(host_in => host_in, host_out => host_out, address => addr, data => d);
--    d := EXT("111111111",32);
--    addr := 1;
--    host_write_control_register(host_in => host_in, host_out => host_out, address => addr, data => d);
--    d := (others => '0');
--    d(25) := '1';
--    addr := 3;
--    host_write_control_register(host_in => host_in, host_out => host_out, address => addr, data => d);
    
    -- Set frequnecy
    d := CONV_STD_LOGIC_VECTOR(2300457,32);
    addr := 16+4;
    host_write_control_register(host_in => host_in, host_out => host_out, address => addr, data => d);
    -- Set phase delay
    d := CONV_STD_LOGIC_VECTOR(-232,32);
    addr := 16+6;
    host_write_control_register(host_in => host_in, host_out => host_out, address => addr, data => d);
    -- Set gain
    d := CONV_STD_LOGIC_VECTOR(500,32);
    addr := 16+7;
    host_write_control_register(host_in => host_in, host_out => host_out, address => addr, data => d);
    -- Pulse INIT
    addr := 16;
    d := X"00000001";
    host_write_control_register(host_in => host_in, host_out => host_out, address => addr, data => d);
    d := X"00000000";
    host_write_control_register(host_in => host_in, host_out => host_out, address => addr, data => d);
    
    -- Timing
    -- Start pulse  
    wait for 20 us;
    -- Set Timing Reg
    d := CONV_STD_LOGIC_VECTOR(350,16) & "11111111" & "00000010";
    addr := 16+12;
    host_write_control_register(host_in => host_in, host_out => host_out, address => addr, data => d);
    wait for 200 ns;
    d := CONV_STD_LOGIC_VECTOR(350,16) & "11111111" & "00000000";
    addr := 16+12;
    host_write_control_register(host_in => host_in, host_out => host_out, address => addr, data => d);
    -- Calibration Start
    wait for 10 us;
    d := CONV_STD_LOGIC_VECTOR(350,16) & "11111111" & "00001000";
    addr := 16+12;
    host_write_control_register(host_in => host_in, host_out => host_out, address => addr, data => d);
    wait for 200 ns;
    d := CONV_STD_LOGIC_VECTOR(350,16) & "11111111" & "00000000";
    addr := 16+12;
    host_write_control_register(host_in => host_in, host_out => host_out, address => addr, data => d);
    -- Calibration Stop
    wait for 10 us;
    d := CONV_STD_LOGIC_VECTOR(350,16) & "11111111" & "00010000";
    addr := 16+12;
    host_write_control_register(host_in => host_in, host_out => host_out, address => addr, data => d);
    wait for 20 ns;
    d := CONV_STD_LOGIC_VECTOR(350,16) & "11111111" & "00000000";
    addr := 16+12;
    host_write_control_register(host_in => host_in, host_out => host_out, address => addr, data => d);
    -- Injection
    wait for 500 us;
    d := CONV_STD_LOGIC_VECTOR(350,16) & "11111111" & "00100000";
    addr := 16+12;
    host_write_control_register(host_in => host_in, host_out => host_out, address => addr, data => d);
    wait for 200 ns;
    d := CONV_STD_LOGIC_VECTOR(350,16) & "11111111" & "00000000";
    addr := 16+12;
    host_write_control_register(host_in => host_in, host_out => host_out, address => addr, data => d);
    -- HChange
    wait for 5000 us;
    d := CONV_STD_LOGIC_VECTOR(350,16) & "11111111" & "01000000";
    addr := 16+12;
    host_write_control_register(host_in => host_in, host_out => host_out, address => addr, data => d);
    wait for 200 ns;
    d := CONV_STD_LOGIC_VECTOR(350,16) & "11111111" & "00000000";
    addr := 16+12;
    host_write_control_register(host_in => host_in, host_out => host_out, address => addr, data => d);
    -- HChange
    wait for 5000 us;
    d := CONV_STD_LOGIC_VECTOR(350,16) & "11111111" & "01000000";
    addr := 16+12;
    host_write_control_register(host_in => host_in, host_out => host_out, address => addr, data => d);
    wait for 200 ns;
    d := CONV_STD_LOGIC_VECTOR(350,16) & "11111111" & "00000000";
    addr := 16+12;
    host_write_control_register(host_in => host_in, host_out => host_out, address => addr, data => d);
    -- Cycle end
    wait for 5000 us;
    d := CONV_STD_LOGIC_VECTOR(350,16) & "11111111" & "00000100";
    addr := 16+12;
    host_write_control_register(host_in => host_in, host_out => host_out, address => addr, data => d);
    wait for 200 ns;
    d := CONV_STD_LOGIC_VECTOR(350,16) & "11111111" & "00000000";
    addr := 16+12;
    host_write_control_register(host_in => host_in, host_out => host_out, address => addr, data => d);

    wait;
  end process;
  

 
  
  
end behave;
