--
-- host_interface.vhd
--
-- Host Accessible Regsiters and Memories
--
-- Version 1.0 5/1/06 A.McCormick (Alpha Data)


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


library work;
use work.common_interface.all;

entity host_interface is
  generic (
    index : integer := 0);
  port (
    -- Host Abstract Interface
    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);
    -- Connection to Timing, PLL and Data Logger

    control     : out std_Logic_vector(31 downto 0);
    status      : in  std_Logic_vector(31 downto 0);                                      
    test_timing : out std_logic_vector(31 downto 0);
    test_timing_wstb : out std_logic;
    cycle             : in std_logic_vector(31 downto 0);
    cycle_init_val    : out  std_logic_vector(31 downto 0);
    cycle_val_set     : out  std_logic;
    ctime             : in std_logic_vector(31 downto 0);
    time_tbladdr      : in std_logic_vector(31 downto 0);
    pll_frequency     : out  std_logic_vector(31 downto 0);
    pll_freqdelay     : out  std_logic_vector(31 downto 0);
    pll_phasedelay    : out  std_logic_vector(31 downto 0);
    pll_gain          : out  std_logic_vector(31 downto 0);
    dds_freq_min      : out  std_logic_vector(31 downto 0);
    dds_freq_max      : out  std_logic_vector(31 downto 0);
    diag_control      : out  std_logic_vector(31 downto 0);
    diag_control_set  : out  std_logic;
    diag_delay        : out  std_logic_vector(31 downto 0);
    diag_delay_set    : out  std_logic;
    diag_trigger      : out  std_logic_vector(31 downto 0);
    diag_status       : in   std_logic_vector(31 downto 0);
    sdram_addr        : in std_logic_vector(24 downto 0);
    sdram_data        : in std_logic_vector(63 downto 0);
    sdram_write       : in std_logic;
    fifo_irq          : out std_Logic;
    timing_addr       : in std_logic_vector(11 downto 0);
    timing_data       : in std_logic_vector(63 downto 0);
    timing_write      : in std_logic;
    info_addr         : in std_logic_vector(5 downto 0);
    info_data         : in std_logic_vector(63 downto 0);
    info_write        : in std_logic;
    phase_table_addr  : in std_logic_vector(12 downto 0);
    phase_table_data  : out  std_logic_vector(7 downto 0);
    switch_table_addr : in std_logic_vector(3 downto 0);
    switch_table_data : out  std_logic_vector(31 downto 0);
    diagnostics_data  : in std_logic_vector(63 downto 0);
    diagnostics_addr  : in std_logic_vector(11 downto 0);
    diagnostics_write : in std_logic;
    bunchmean0_data   : in std_logic_vector(63 downto 0);
    bunchmean0_addr   : in std_logic_vector(11 downto 0);
    bunchmean0_write   : in std_logic;
    bunchmean1_data   : in std_logic_vector(63 downto 0);
    bunchmean1_addr   : in std_logic_vector(11 downto 0);
    bunchmean1_write   : in std_logic
    );


  
end host_interface;

architecture rtl of host_interface is

  constant ncomponents : integer := 25;
  type     sys_bus_type is array (0 to ncomponents) of std_logic_vector(system_width-1 downto 0);
  signal s : sys_bus_type;

  constant reg_bank_size : integer := 16;
  constant control_reg_addr : integer := 0;
  constant cycle_reg_addr : integer := 1;
  constant ctime_reg_addr : integer := 2;
  constant time_tbladdr_reg_addr : integer := 3;
  constant pll_frequency_reg_addr : integer := 4;
  constant pll_freqdelay_reg_addr : integer := 5;
  constant pll_phasedelay_reg_addr : integer := 6;
  constant pll_gain_reg_addr : integer := 7;
  constant dds_freq_min_reg_addr : integer := 8;
  constant dds_freq_max_reg_addr : integer := 9;
  constant diag_ctrl_reg_addr : integer := 10;
  constant diag_trig_reg_addr : integer := 11;
  constant diag_delay_reg_addr : integer := 12;
  constant timing_test_reg_addr : integer := 13;

  component sync_fifo
    generic (
      width : natural := 32);
    port (
      clk     : in  std_logic;
      rst     : in  std_logic;
      wadv    : in  std_logic;
      wdata   : in  std_logic_vector(width-1 downto 0);
      wnfull  : out std_logic;
      wfull   : out std_logic;
      hfull   : out std_logic;
      radv    : in  std_logic;
      rdw_out : out std_logic_vector(width-1 downto 0);
      rempty  : out std_logic;
      rnempty : out std_logic);
  end component;

  signal fifo_data_in,fifo_data_out : std_logic_vector(64+25-1 downto 0);
  signal fifo_empty,read_fifo : std_logic;
  signal sdram_req,sdram_gnt,sdram_busy : std_logic;
  signal sdram_addr1 : std_logic_vector(24 downto 0);
  signal sdram_data1 : std_logic_vector(63 downto 0);
  
  
begin  -- rtl

  s(0) <= system_in;
  
  -- Control/Status Register
  creg0 : control_register
    generic map (
      width => 32, addr => reg_bank_size*(index+1)+control_reg_addr)
    port map (
      clk          => clk, rst => rst, system_in => s(0), system_out => s(1),
      control_data => control, control_wstb => open);
  sreg0 : status_register
    generic map (
      width => 32, addr => reg_bank_size*(index+1)+control_reg_addr)
    port map (    
      clk         => clk, rst => rst, system_in => s(1), system_out => s(2),
      status_data => status);
  
  -- Cycle Number
  -- Write modifies cycle counter
  creg1 : control_register
    generic map (
      width => 32, addr => reg_bank_size*(index+1)+cycle_reg_addr)
    port map (
      clk          => clk, rst => rst, system_in => s(2), system_out => s(3),
      control_data => cycle_init_val, control_wstb => cycle_val_set);
  sreg1 : status_register
    generic map (
      width => 32, addr => reg_bank_size*(index+1)+cycle_reg_addr)
    port map (
      clk         => clk, rst => rst, system_in => s(3), system_out => s(4),
      status_data => cycle);
  
  -- CTIME Register
  sreg2 : status_register
    generic map (
      width => 32, addr => reg_bank_size*(index+1)+ctime_reg_addr)
    port map (
      clk         => clk, rst => rst, system_in => s(4), system_out => s(5),
      status_data => ctime);

  
  -- TIMETBL_ADDR Register
  sreg3 : status_register
    generic map (
      width => 32, addr => reg_bank_size*(index+1)+time_tbladdr_reg_addr)
    port map (
      clk         => clk, rst => rst, system_in => s(5), system_out => s(6),
      status_data => time_tbladdr);

  -- PLL Frequency
  creg4 : readable_control_register
    generic map (
      width => 32, addr => reg_bank_size*(index+1)+pll_frequency_reg_addr)
    port map (
      clk          => clk, rst => rst, system_in => s(6), system_out => s(7),
      control_data => pll_frequency, control_wstb => open);

  -- PLL Frequency Delay
  creg5 : readable_control_register
    generic map (
      width => 32, addr => reg_bank_size*(index+1)+pll_freqdelay_reg_addr)
    port map (
      clk          => clk, rst => rst, system_in => s(7), system_out => s(8),
      control_data => pll_freqdelay, control_wstb => open);

  -- PLL Phase Delay
  creg6 : readable_control_register
    generic map (
      width => 32, addr => reg_bank_size*(index+1)+pll_phasedelay_reg_addr)
    port map (
      clk          => clk, rst => rst, system_in => s(8), system_out => s(9),
      control_data => pll_phasedelay, control_wstb => open);

  -- PLL Gain
  creg7 : readable_control_register
    generic map (
      width => 32, addr => reg_bank_size*(index+1)+pll_gain_reg_addr)
    port map (
      clk          => clk, rst => rst, system_in => s(9), system_out => s(10),
      control_data => pll_gain, control_wstb => open);

  -- DDS FREQ MIN
  creg8 : readable_control_register
    generic map (
      width => 32, addr => reg_bank_size*(index+1)+dds_freq_min_reg_addr)
    port map (
      clk          => clk, rst => rst, system_in => s(10), system_out => s(11),
      control_data => dds_freq_min, control_wstb => open);

  -- DDS FREQ MAX
  creg9 : readable_control_register
    generic map (
      width => 32, addr => reg_bank_size*(index+1)+dds_freq_max_reg_addr)
    port map (
      clk          => clk, rst => rst, system_in => s(11), system_out => s(12),
      control_data => dds_freq_max, control_wstb => open);

  
  -- Cycle Number
  -- Write modifies cycle counter
  creg10 : control_register
    generic map (
      width => 32, addr => reg_bank_size*(index+1)+diag_ctrl_reg_addr)
    port map (
      clk          => clk, rst => rst, system_in => s(12), system_out => s(13),
      control_data => diag_control, control_wstb => diag_control_set);
  sreg10 : status_register
    generic map (
      width => 32, addr => reg_bank_size*(index+1)+diag_ctrl_reg_addr)
    port map (
      clk         => clk, rst => rst, system_in => s(13), system_out => s(14),
      status_data => diag_status);
  
  -- Diagnostics Trigger
  creg11 : readable_control_register
    generic map (
      width => 32, addr => reg_bank_size*(index+1)+diag_trig_reg_addr)
    port map (
      clk          => clk, rst => rst, system_in => s(14), system_out => s(15),
      control_data => diag_trigger, control_wstb => open);

  -- Timing Test
  creg12 : readable_control_register
    generic map (
      width => 32, addr => reg_bank_size*(index+1)+timing_test_reg_addr)
    port map (
      clk          => clk, rst => rst, system_in => s(15), system_out => s(16),
      control_data => test_timing, control_wstb => test_timing_wstb);

  -- Cycle Data Table
  -- SDRAM Interface
  dram0 : external_memory
    generic map (
      width   => 64,
      depth   => 25,
      bank_id => index)
    port map(
      clk        => clk,
      rst        => rst,
      system_in  => s(16),
      system_out => s(17),
      w          => read_fifo,
      a          => sdram_addr1,
      d          => sdram_data1,
      q          => open,
      qv         => open,
      r          => '0',
      full       => sdram_busy,
      req        => sdram_req,
      gnt        => sdram_gnt);


  fifo_data_in <= sdram_addr & sdram_data;
  sdram_addr1 <= fifo_data_out(24+64 downto 64);
  sdram_data1 <= fifo_data_out(63 downto 0);
  
  read_fifo <= (not fifo_empty) and (not sdram_busy);
  sdram_req <= '0'; --not fifo_empty;
  
  sdram_fifo0: sync_fifo
    generic map (
      width => 64+25)
    port map (
      clk        => clk,
      rst        => rst,
      wdata      => fifo_data_in,
      wadv       => sdram_write,
      hfull   => fifo_irq,
      wnfull  => open,
      wfull   => open,
      radv    => read_fifo,
      rdw_out => fifo_data_out,
      rempty  => fifo_empty);   
  
  -- Cycle Timing Table
  iram0: internal_memory
    generic map (
      width   => 64,
      depth   => 12,
      bank_id => 8*index+0)
    port map (
      clk        => clk,
      rst        => rst,
      system_in  => s(17),
      system_out => s(18),
      w          => timing_write,
      a          => timing_addr,
      d          => timing_data,
      q          => open);

  -- Cycle Info Table
  iram1: internal_memory
    generic map (
      width   => 64,
      depth   => 6,
      bank_id => 8*index+1)
    port map (
      clk        => clk,
      rst        => rst,
      system_in  => s(18),
      system_out => s(19),
      w          => info_write,
      a          => info_addr,
      d          => info_data,
      q          => open);
  
  -- Phase Table
  iram2: internal_memory
    generic map (
      width   => 8,
      depth   => 13,
      bank_id => 8*index+2)
    port map (
      clk        => clk,
      rst        => rst,
      system_in  => s(19),
      system_out => s(20),
      w          => '0',
      a          => phase_table_addr,
      d          => "00000000",
      q          => phase_table_data);

  -- Switch Table
  iram3: internal_memory
    generic map (
      width   => 32,
      depth   => 4,
      bank_id => 8*index+3)
    port map (
      clk        => clk,
      rst        => rst,
      system_in  => s(20),
      system_out => s(21),
      w          => '0',
      a          => switch_table_addr,
      d          => X"00000000",
      q          => switch_table_data);

  
  -- Diagnostics Table
  iram4: internal_memory
    generic map (
      width   => 64,
      depth   => 12,
      bank_id => 8*index+4)
    port map (
      clk        => clk,
      rst        => rst,
      system_in  => s(21),
      system_out => s(22),
      w          => diagnostics_write,
      a          => diagnostics_addr,
      d          => diagnostics_data,
      q          => open);

  -- Bunch Mean Table #0
  iram5: internal_memory
    generic map (
      width   => 64,
      depth   => 12,
      bank_id => 8*index+5)
    port map (
      clk        => clk,
      rst        => rst,
      system_in  => s(22),
      system_out => s(23),
      w          => bunchmean0_write,
      a          => bunchmean0_addr,
      d          => bunchmean0_data,
      q          => open);
  
  -- Bunch Mean Table #1
  iram6: internal_memory
    generic map (
      width   => 64,
      depth   => 12,
      bank_id => 8*index+6)
    port map (
      clk        => clk,
      rst        => rst,
      system_in  => s(23),
      system_out => s(24),
      w          => bunchmean1_write,
      a          => bunchmean1_addr,
      d          => bunchmean1_data,
      q          => open);


  -- Diagnostics Trigger
  creg13 : readable_control_register
    generic map (
      width => 32, addr => reg_bank_size*(index+1)+diag_delay_reg_addr)
    port map (
      clk          => clk, rst => rst, system_in => s(24), system_out => s(25),
      control_data => diag_delay, control_wstb => diag_delay_set);

  system_out <= s(ncomponents);

end rtl;
