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

use work.sercon_types.all;

entity top_test is
  port(
    rstin: in std_logic;
    clkin: in std_logic;  
    -- usb interface:
    sx2_ifclk: out std_logic;
    sx2_int: in std_logic;
    sx2_ready: in std_logic;
    sx2_reset: out std_logic;
    sx2_sloe: out std_logic;
    sx2_slrd: out std_logic;
    sx2_slwr: out std_logic;
    sx2_pkt_end: out std_logic;
    sx2_fifo_address:out std_logic_vector(2 downto 0);
    sx2_flag_a: in std_logic;
    sx2_flag_b: in std_logic;
    sx2_flag_c: in std_logic;
    sx2_wakeup: out std_logic;
    sx2_n_cs  : out std_logic;
    sx2_fifo_data: inout std_logic_vector(15 downto 0);
    usb_nc: in std_logic;

    -- user signals:
    led0: out std_logic;
    led1: out std_logic;
    --
    test_output: out std_logic;
    test_output2: out std_logic
    
    );

end entity top_test;

architecture v0 of top_test is

  component sx2_ui 
    port(
      rstin: in std_logic;
      clkin: in std_logic;
      --
      sysclk: out std_logic;
      logic_reset: out std_logic;
      
      -- usb interface:
      sx2_ifclk: out std_logic;
      sx2_int: in std_logic;
      sx2_ready: in std_logic;
      sx2_reset: out std_logic;
      sx2_sloe: out std_logic;
      sx2_slrd: out std_logic;
      sx2_slwr: out std_logic;
      sx2_pkt_end: out std_logic;
      sx2_fifo_address:out std_logic_vector(2 downto 0);
      sx2_flag_a: in std_logic;
      sx2_flag_b: in std_logic;
      sx2_flag_c: in std_logic;
      sx2_wakeup: out std_logic;
      sx2_n_cs  : out std_logic;
      sx2_fifo_data: inout std_logic_vector(15 downto 0);
      usb_nc: in std_logic;
      --
      flush_sx2_buffers: in std_logic:='0';
      -- user configuration interface:
      config_control: out sercon_ctrl;
      config_src: out sercon_bus;
      config_dest: in sercon_bus;
      -- data pipe for block transfers into the design (from the pc):
      wren: out std_logic;
      full: in std_logic;
      data_from_pc: out std_logic_vector(15 downto 0);
      -- data pipe for block transfers out of the design (to the pc):
      rden: out std_logic;
      empty: in std_logic;
      data_to_pc: in std_logic_vector(15 downto 0)
      );
  end component sx2_ui;
  
  signal int_logic_reset:std_logic;

  constant int_reg_block_size:natural:=9;
  signal int_reg_block:long_word_array(int_reg_block_size-1 downto 0);

  signal int_config_ctrl:sercon_ctrl;
  signal int_config_bus_0:sercon_bus;
  signal int_config_bus_1:sercon_bus;
  signal int_config_bus_2:sercon_bus;
  signal int_config_bus_dest:sercon_bus;
  
  component sercon_block
    generic(
      -- note: ensure n_regs >=2
      n_regs:natural;
      bit_width:natural
      );
    port(
      ctrl: in sercon_ctrl;
      --
      sbus_in: in sercon_bus;
      sbus_out: out sercon_bus;
      --
      -- parallel data output/input.
      pdout: out long_word_array(n_regs-1 downto 0)
      );
  end component sercon_block;

  component sercon_stat 
    generic(
      bit_width:natural:=32
      );
    port(
      ctrl: in sercon_ctrl;
      --
      sbus_in: in sercon_bus;
      sbus_out: out sercon_bus;

      -- parallel data input.
      pdin: in std_logic_vector(bit_width-1 downto 0)
      );
  end component sercon_stat;

  component sercon_trig
    generic(
      bit_width:natural:=32
      );
    port(
      ctrl: in sercon_ctrl;
      --
      sbus_in: in sercon_bus;
      sbus_out: out sercon_bus;

      -- parallel data output/input.
      pdout: out std_logic_vector(bit_width-1 downto 0);
      pdin: in std_logic_vector(bit_width-1 downto 0)
      );
  end component sercon_trig;

  signal int_trigger_vector:std_logic_vector(31 downto 0);

  
  component loopback_fifo 
    port (
        din: in std_logic_vector(15 downto 0);
        rd_clk: in std_logic;
        rd_en: in std_logic;
        rst: in std_logic;
        wr_clk: in std_logic;
        wr_en: in std_logic;
        dout: out std_logic_vector(15 downto 0);
        empty: out std_logic;
        full: out std_logic);
  end component loopback_fifo;

  signal int_sysclk: std_logic;

  signal int_loopback_full:std_logic;
  signal int_loopback_empty: std_logic;
  signal int_loopback_wren: std_logic;
  signal int_loopback_rden: std_logic;
  signal int_data_to_pc: std_logic_vector(15 downto 0);
  signal int_data_from_pc: std_logic_vector(15 downto 0);

  signal int_test_output: std_logic;
  
begin 

  u_sx2_ui:sx2_ui
    port map(
      rstin=>rstin,
      clkin=>clkin,
      --
      sysclk=>int_sysclk,
      logic_reset=>int_logic_reset, 
      
      -- usb interface=>,
      sx2_ifclk=>sx2_ifclk, 
      sx2_int=>sx2_int, 
      sx2_ready=>sx2_ready,
      sx2_reset=>sx2_reset,
      sx2_sloe=>sx2_sloe, 
      sx2_slrd=>sx2_slrd,
      sx2_slwr=>sx2_slwr,
      sx2_pkt_end=>sx2_pkt_end,
      sx2_fifo_address=>sx2_fifo_address,
      sx2_flag_a=>sx2_flag_a, 
      sx2_flag_b=>sx2_flag_b, 
      sx2_flag_c=>sx2_flag_c, 
      sx2_wakeup=>sx2_wakeup, 
      sx2_n_cs  =>sx2_n_cs, 
      sx2_fifo_data=>sx2_fifo_data, 
      usb_nc=>usb_nc, 
      --
      flush_sx2_buffers=>open, 
      -- user configuration interface=>,
      config_control=>int_config_ctrl, 
      config_src=>int_config_bus_0, 
      config_dest=>int_config_bus_dest, 
      -- data pipe for block transfers into the design (from the pc)=>,
      wren=>int_loopback_wren, 
      full=>int_loopback_full, 
      data_from_pc=>int_data_from_pc, 
      -- data pipe for block transfers out of the design (to the pc)=>,
      rden=>int_loopback_rden, 
      empty=>int_loopback_empty,
      data_to_pc=>int_data_to_pc 
      );

  -- some registers in a block:
  
  u_config_space:sercon_block
    generic map(
      -- note: ensure n_regs >=2
      n_regs=>9,
      bit_width=>sercon_bit_width
      )
    port map(
      ctrl=>int_config_ctrl,
      --
      sbus_in=>int_config_bus_0,
      sbus_out=>int_config_bus_1,
      --
      -- parallel data output.
      pdout=>int_reg_block
      );  

  led0<=not(int_reg_block(0)(0));
  led1<=not(int_trigger_vector(0));
  
  
  -- read-only status register
  u_status:sercon_stat
     generic map(
       bit_width=>sercon_bit_width
      )
    port map(
      ctrl=>int_config_ctrl,
      --
      sbus_in=>int_config_bus_1,
      sbus_out=>int_config_bus_2,

      -- parallel data input.
      pdin=>int_reg_block(0)
      );
  
  -- event trigger (& status) register:
  u_trigger:sercon_trig
    generic map(
      bit_width=>sercon_bit_width
      )
    port map(
      ctrl=>int_config_ctrl,
      --
      sbus_in=>int_config_bus_2,
      sbus_out=>int_config_bus_dest,

      -- parallel data output/input.
      pdout=>int_trigger_vector,
      pdin=>int_reg_block(1)
      );

  
  -- loop back buffer:
  u_loopback_buffer:loopback_fifo
    port map(
      rst=>int_logic_reset,
      rd_clk=>int_sysclk,
      wr_clk=>int_sysclk,

      full=>int_loopback_full,
      wr_en=>int_loopback_wren,
      din=>int_data_from_pc,

      rd_en=>int_loopback_rden,
      empty=>int_loopback_empty,
      dout=>int_data_to_pc
      );
  

  pr_test_pin:process(int_logic_reset, int_sysclk)
  begin 
    if(int_logic_reset='1')then
      int_test_output<='0';
    elsif(rising_edge(int_sysclk))then
      
      int_test_output<=not(int_test_output);

    end if;
  end process pr_test_pin;

  test_output<=int_test_output when int_reg_block(0)(1)='0' else '0';
  test_output2<=int_test_output when int_reg_block(0)(1)='1' else '0';
  
end architecture v0;
