--******************************************************************************
--* @short   Input FPGA: synchronizes 4 muons
--*
--*   @param dummyb can be used as BCreset for testing
--*
--******************************************************************************
--* @author  SAKULIN Hannes  <hsakulin@dsy-srv3.cern.ch>
--* @date    $Date: 2005/12/06 16:11:56 $
--* @version $Revision: 1.29 $
--******************************************************************************
--/
library IEEE;
use IEEE.Std_logic_1164.all;
use WORK.GMTTypes.all;
use WORK.ReadOutBufTypes.all;
use WORK.VMEMux.all;
use WORK.IFVMEAddrMap.all;

-- need synplify virtex2 library for STARTUP_VIRTEX2
library virtex2;
use virtex2.components.all;

-- pragma translate_off
library UNISIM;
use UNISIM.VCOMPONENTS.all;
-- pragma translate_on
use IEEE.NUMERIC_STD.all;


entity InputFPGA is
  generic (
    input_fpga_idx : integer := 0);     -- DT, CSC, bRPC, fRPC
  port (
    -- CHIP INPUTS
    iMuons     : in TFourInMuons_flat;

    -- out to Logic FPGA and to MIPISO AU
    oMuonsLF   : out TFourSyncedMu_flat;
    oMuonsAU   : out TFourSyncedMu_flat;
    
    -- forCOU (DT and CSC chip, only)
    oPhi   : out TPhi_vec(0 to 3);   
    oEta   : out TEtaCOU_vec(0 to 3);

    -- VME port
    vme_addr   : in    std_logic_vector(19 downto 1);
    vme_data   : inout std_logic_vector(15 downto 0);
    vme_en     : in    std_logic;
    vme_wr     : in    std_logic;
    vme_ndtack : out   std_logic;       -- low active 
    vme_nirq   : out   std_logic;       -- low active 

    -- Readout Data Port
    ro_data    : out std_logic_vector(23 downto 0);
    ro_rdfifo  : in std_logic;
    ro_fetch   : in std_logic;
    l1a        : in std_logic;          -- Level-1 accept
    bcreset    : in std_logic;          -- Bunch Counter reset
    l1reset    : in std_logic;          -- Level-1 reset
    
    -- Clock and control
    clk_input  : in  std_logic;
    clk_test   : out std_logic;         -- clock1x from DCM
    clk_out    : out std_logic;         -- clock output for feedback (use optional)
                                        -- same as clk_test
    clk_fb     : in  std_logic;         -- clock feedback input (use optional)
    dcm_locked : out std_logic;         -- DCM is locked => goes to VME chip
    reset_dcm  : in  std_logic;         -- resets DCM
    inactive   : in  std_logic;         -- from front panel button  (to GTS)

    
    status     : out std_logic_vector(1 downto 0);
    test_lemo  : out std_logic;
    test       : out std_logic_vector(3 downto 0);
    reset_input: in  std_logic;         -- hard reset from trigger control
                                        --
                                        -- register input
                                        -- same function as level-1 reset
                                        -- or hard reset from trigger control
                                        --
                                        -- generated by VME chip
                                        -- resets only state machines, FFs,
                                        -- counters, error flags
                                        -- but not memories and registers

    --NB: reset is connected asynchronously to FF's
    --    and to the GSR input of STARTUP_VIRTEX2
    --    Synthesis will use the GSR network instead
    --    of the asynchronous reset lines

  dummyb : in std_logic);
end;


architecture behavioral of InputFPGA is
  attribute syn_useioff               : boolean;
  attribute syn_useioff of behavioral : architecture is true;

  type TIntArr is array (integer range <>) of integer;
  
  constant chip_id_h : TIntArr(0 to 3) := (
	16#0001#,
	16#0001#,
	16#0001#,
	16#0001#
	);

  constant chip_id_l : TIntArr(0 to 3) := (
	16#9133#, -- DT
	16#9132#, -- CSC
	16#9134#, -- BRPC
	16#9131#  -- FRPC
	);


  constant date_string : string := "$Date: 2005/12/06 16:11:56 $";
  

component SRL16
-- synthesis translate_off
    generic (
      INIT: bit_vector:= X"0001");
-- synthesis translate_on
    port (Q : out STD_ULOGIC;
          A0 : in STD_ULOGIC;
          A1 : in STD_ULOGIC;
          A2 : in STD_ULOGIC;
          A3 : in STD_ULOGIC;
          CLK : in STD_ULOGIC;
          D : in STD_ULOGIC);
  end component;

  -- purpose: calculate xor of all bits in d
  function parity (
    constant d : std_logic_vector)
    return std_logic is
    variable result  : std_logic;
  begin  -- function parity
    result := '0';
    for i in d'RANGE loop
      result := result xor d(i);
    end loop;  -- i
    return result;
  end function parity;

  -- clock and control signals
  signal clk         : std_logic;
  signal clk2x       : std_logic;
  signal clk4x       : std_logic;

  signal CLKIN_IBUFG_i : std_logic;

  -- sync config register
  type TSyncConfig_vec is array (integer range <>) of std_logic_vector(15 downto 0);
  signal sSyncConfig : TSyncConfig_vec(0 to 3);
  
  -- registered/synced/delayed inputs

  signal sMuons_reg     : TInMuons_vec(0 to 3);
  signal sMuons_d1      : TInMuons_vec(0 to 3);
  signal sMuons_d2      : TInMuons_vec(0 to 3);
  signal sMuons_d3      : TInMuons_vec(0 to 3);
  signal sMuons_d4      : TInMuons_vec(0 to 3);
  signal sMuons_synced  : TInMuons_vec(0 to 3);

  signal sMuons_fromSLR  : TInMuons_vec(0 to 3);
  signal sMuons_delayed  : TInMuons_vec(0 to 3);
  signal sMuons_selected : TInMuons_vec(0 to 3);

  signal compare_error_bits : TFourInMuons_flat;
  
  signal sMuons_out      : TSyncedMu_vector(0 to 3);
  signal sMuonsLF       : TSyncedMu_vector(0 to 3);
  signal sMuonsAU       : TSyncedMu_vector(0 to 3);  

   -- forCOU (DT and CSC chip, only)
  signal sPhi_with_empty : TPhi_vec(0 to 3);

  signal sync_err   : std_logic_vector(0 to 3);
  signal bx_err     : std_logic_vector(0 to 3);
  signal parity_err : std_logic_vector(0 to 3);
  signal clear_muon : std_logic_vector(0 to 3);

  signal empty_from_pt  : std_logic_vector(0 to 3);
  signal empty_from_phi : std_logic_vector(0 to 3);
  signal empty          : std_logic_vector(0 to 3);
  
  -- VME
  signal vme_addr_i : std_logic_vector (vme_addr'range);
  signal vme_data_i : std_logic_vector (vme_data'range);
  signal vme_en_i   : std_logic;
  signal vme_wr_i   : std_logic;

  -- VME data and enable from various units
  signal vme_data_out_i : TVMEData_vec (0 to 15);
  signal vme_en_out_i   : TVMEEnable_vec (0 to 15);

  -- VME data muxed, enbale ored
  signal vme_data_out_muxed : std_logic_vector (15 downto 0);
  signal vme_en_out_muxed   : std_logic;

  -- readout data 
  signal ro_rdfifo_reg  : std_logic;
  signal ro_fetch_reg   : std_logic;
  signal l1a_reg        : std_logic;          -- Level-1 accept
  signal bcreset_reg    : std_logic;          -- Bunch Counter reset
  signal bcreset_or_dummy    : std_logic;          -- Bunch Counter reset
  signal l1reset_reg    : std_logic;          -- Level-1 reset
  signal dummy_reg   : std_logic;
  signal dummy_reg_d : std_logic;
  signal dummy_pulse : std_logic;
 
  signal ro_data_i       : std_logic_vector(23 downto 0);
  signal readout_data    : TReadoutData_vec(0 to 3);
  signal sSimulatedData : TReadoutData_vec(0 to 3);
  signal mon_data        : TReadoutMonData_vec(0 to 9);
  signal sSimuMode       : std_logic;

  signal sDummyIsBCReset  : std_logic;
  
  signal sBCReset_pre     : std_logic;
  signal sBCReset_main    : std_logic;

  signal sBXCount     : std_logic_vector(11 downto 0);  -- the bx count
  
  signal clk_fb_reg   : std_logic;
  
  signal sDummy       : std_logic_vector(15 downto 0);
  signal dcm_locked_i : std_logic;
  signal reset_input_reg : std_logic;
  signal reset        : std_logic;

  signal svme_ndtack : std_logic;
  signal LFbit100 : std_logic; -- spare bit100 can be assigned as needed
  signal ooMuonsLF : TFourSyncedMu_flat;  -- internal output mu to LF chip (100:0)

begin

  -----------------------------------------------------------------------------
  -- Synchronization circuit at 160 MHz
  -----------------------------------------------------------------------------
--   sync_inputs : process (clk4x) is
--   begin
--     if (clk4x'event and clk4x = '1') then
--       sMuons_reg <= InMuons_vec_from_flat(iMuons);
--       sMuons_d1 <= sMuons_reg;
--       sMuons_d2 <= sMuons_d1;
--       sMuons_d3 <= sMuons_d2;
--       sMuons_d4 <= sMuons_d3;
--     end if;
--   end process sync_inputs;

  sync_inputs : process (clk2x) is
  begin
    if (clk2x'event and clk2x = '1') then
      sMuons_reg <= InMuons_vec_from_flat(iMuons);
      sMuons_d2 <= sMuons_d1;
      sMuons_d4 <= sMuons_d3;
    end if;
    if (clk2x'event and clk2x = '0') then
      sMuons_d1 <= sMuons_reg;
      sMuons_d3 <= sMuons_d2;
    end if;
  end process sync_inputs;

  -----------------------------------------------------------------------------
  --  Configuration Registers
  -----------------------------------------------------------------------------
  --
  -- 0   0   0   0       0      0      0     0      |  0   0   0   0   |  0   0   0   0 
  --             clr     clr    clr   use    use      delay (0 to 15)    sync 
  --             on      on     on    SLR    delay    in SRL            late        early
  --             parity  bxerr  syerr
  --             error
  
  config_reg: for i in 0 to 3 generate
  begin  -- generate config_reg
    reg: entity work.VMEReg
      generic map (
        init_val            => "0000000000011000",
        my_vme_base_address => IF_SyncConfigReg_addr(i))
      port map (
        data         => sSyncConfig(i),        
        reset        => reset,
        
        vme_addr     => vme_addr_i,
        vme_data     => vme_data_i,
        vme_en       => vme_en_i,
        vme_wr       => vme_wr_i,
        vme_data_out => vme_data_out_i(i),
        vme_en_out   => vme_en_out_i(i),
        vme_clk      => clk);
  end generate config_reg;

  -----------------------------------------------------------------------------
  -- Sunchronization Mux 
  -----------------------------------------------------------------------------
  sync_mux: for i in 0 to 3 generate
  begin  -- generate sync_mux
    register_synced: process (clk) is
    begin  -- process register_synced
      if clk'event and clk = '1' then  -- rising clock edge
        case sSyncConfig(i)(3 downto 0) is
          when "1000" => sMuons_synced(i) <= sMuons_d3(i);
          when "0100" => sMuons_synced(i) <= sMuons_d2(i); 
          when "0010" => sMuons_synced(i) <= sMuons_d1(i); 
          when "0001" => sMuons_synced(i) <= sMuons_reg(i);
          when others => sMuons_synced(i) <= sMuons_reg(i);
        end case;
      end if;
    end process register_synced;
  end generate sync_mux;

  -----------------------------------------------------------------------------
  -- Delay Line and Mux
  -----------------------------------------------------------------------------
  delay_line: for i in 0 to 3 generate
  begin  -- generate delay  
    per_bit: for j in sMuons_synced(i)'range generate
      delay_block: SRL16
        port map (
          Q   => sMuons_fromSLR(i)(j),
          A0  => sSyncConfig(i)(4),
          A1  => sSyncConfig(i)(5),
          A2  => sSyncConfig(i)(6),
          A3  => sSyncConfig(i)(7),
          CLK => clk,
          D   => sMuons_synced(i)(j));          
    end generate per_bit;  -- j

    reg_delay: process (clk) is
    begin  
      if clk'event and clk = '1' then  -- rising clock edge
        if sSimuMode = '1' then
          sMuons_delayed(i) <= sSimulatedData(i);
        else
          if (sSyncConfig(i)(9) = '1') then
            sMuons_delayed(i) <= sMuons_fromSLR(i);
          else
            sMuons_delayed(i) <= sMuons_synced(i);
          end if;
        end if;
      end if;
    end process reg_delay;    
    
    sMuons_selected(i) <= sMuons_delayed(i) when (sSyncConfig(i)(8) = '1' or sSimuMode = '1')
                          else sMuons_synced(i);
  end generate delay_line;


  -----------------------------------------------------------------------------
  -- clear muon (pt-code) on bxerr or syerr, do empty checks
  -----------------------------------------------------------------------------

  n: for i in 0 to 3 generate
    begin  -- generate n
      -- generate error bits
      -- sync, bx and parity errors are counted
      -- the muon can optionally be cleared on sync, bx or quality errors
      
      sync_err(i)   <= sMuons_selected(i)(28);
      bx_err(i)     <= '1' when sMuons_selected(i)(27 downto 25) /=  sBXCount(2 downto 0) else '0';
      parity_err(i) <= parity(sMuons_selected(i)(30 downto 0)) ;
                 
      clear_muon(i) <= '1' when  ( sync_err(i) = '1'   and sSyncConfig(i)(10) = '1') or  -- syerr
                                 ( bx_err(i) = '1'     and sSyncConfig(i)(11) = '1') or  -- bxerr
                                 ( parity_err(i) = '1' and sSyncConfig(i)(12) = '1') -- parity err
                       else '0';


      -- select empty muons
      -- muon is empty if either code indicates empty
      empty_from_pt(i) <= '1' when SyncedMu_from_flat( sMuons_selected(i)(24 downto 0)).pt = "11111" else '0';
      empty_from_phi(i) <= '1' when SyncedMu_from_flat( sMuons_selected(i)(24 downto 0)).phi = "11111111" else '0';

      empty(i) <= empty_from_pt(i) or empty_from_phi(i) or clear_muon(i);


      -- assign output muon (invert qual and pt, code empty in pt and phi)
      sMuons_out(i).ch_valid <= SyncedMu_from_flat( sMuons_selected(i)(24 downto 0)).ch_valid;
      sMuons_out(i).charge   <= SyncedMu_from_flat( sMuons_selected(i)(24 downto 0)).charge;
      sMuons_out(i).finehalo <= SyncedMu_from_flat( sMuons_selected(i)(24 downto 0)).finehalo;
      sMuons_out(i).eta      <= SyncedMu_from_flat( sMuons_selected(i)(24 downto 0)).eta;
      sMuons_out(i).qual     <= not (SyncedMu_from_flat( sMuons_selected(i)(24 downto 0)).qual);
      sMuons_out(i).pt       <= not (SyncedMu_from_flat( sMuons_selected(i)(24 downto 0)).pt) when empty(i) = '0'
                                else "00000";
      sMuons_out(i).phi      <= SyncedMu_from_flat( sMuons_selected(i)(24 downto 0)).phi when empty(i) = '0'
                                else "11111111";
      
    end generate n;

  -----------------------------------------------------------------------------
  -- code empty in phi ( for overlap cancel-out )
  -----------------------------------------------------------------------------
  n1: for i in 0 to 3 generate
    begin  -- generate n
      sPhi_with_empty(i) <= SyncedMu_from_flat( sMuons_selected(i)(24 downto 0)).phi  when empty(i) = '0'
                            else "11111111";    
    end generate n1;

  
  -----------------------------------------------------------------------------
  -- Register Outputs
  -----------------------------------------------------------------------------

  register_muons: process (clk) is
  begin  -- process register_muons
    if clk'event and clk = '0' then  -- falling clock edge
      for i in 0 to 3 loop
        sMuonsLF(i) <= sMuons_out(i);
        sMuonsAU(i) <= sMuons_out(i);
        oPhi(i) <= sPhi_with_empty(i);
        oEta(i) <= SyncedMu_from_flat( sMuons_selected(i)(24 downto 0)).eta;
      end loop;  -- i
      -- Version 23nov2005 A.T.
      -- bit42  to compensate bad output driver on fRPC (=3) chip
      LFbit100 <= sMuons_out(1).eta(1); 
    end if;
  end process register_muons;

  oMuonsAU <= SyncedMu_vec_to_flat (sMuonsAU);
  
  -- Version 23nov2005 A.T.
   -- without assigned bit100: 
   -- oMuonsLF <= SyncedMu_vec_to_flat (sMuonsLF);

   -- with assigned bit100 for bad fRPC (idx=3) chip
   
  ass_outmuons: process( sMuonsLF, LFbit100) is
  begin
        ooMuonsLF <= SyncedMu_vec_to_flat (sMuonsLF);
  	if (input_fpga_idx = 3) then	
          oMuonsLF(99 downto 0) <= ooMuonsLF(99 downto 0);
          oMuonsLF(100)         <= LFbit100;
     	else
  	  oMuonsLF <= SyncedMu_vec_to_flat (sMuonsLF);
   	end if;
  end process ass_outmuons;


  -----------------------------------------------------------------------------
  --* monitor errors
  -----------------------------------------------------------------------------
  error_monitor: entity work.ErrorMonitor4x4bit
    generic map (
      status_register_address    => IF_ErrorMonitorStatusReg_raddr,
      counter_register_addresses => IF_ErrorMonitorCounter_raddr)
    port map (
      bit0         => sync_err,
      bit1         => bx_err,
      bit2         => parity_err,
      bit3         => clear_muon,
      
      bc_reset     => bcreset_or_dummy,
      
      vme_addr     => vme_addr_i,
      vme_en       => vme_en_i,
      vme_wr       => vme_wr_i,
      
      vme_data_out => vme_data_out_i(9),
      vme_en_out   => vme_en_out_i(9),
      
      clk          => clk,
      reset        => reset);
  

  -----------------------------------------------------------------------------
  --* Monitor phase changes
  -----------------------------------------------------------------------------
  -- the counters count when a bit changed its value between the sample and
  -- 6.25ns earlier
  --
  --
  phase_monitor: entity work.PhaseMonitor
    generic map (
      status_register_address    => IF_PhaseMonitorStatusReg_raddr,
      counter_register_addresses => IF_PhaseMonitorCounter_raddr)
    port map (
      sample0      => sMuons_reg,
      sample1      => sMuons_d1,
      sample2      => sMuons_d2,
      sample3      => sMuons_d3,
      sample4      => sMuons_d4,

      bc_reset     => bcreset_or_dummy,
      
      vme_addr     => vme_addr_i,
      vme_en       => vme_en_i,
      vme_wr       => vme_wr_i,
      vme_data_out => vme_data_out_i(10),
      vme_en_out   => vme_en_out_i(10),
      
      clk          => clk,
      reset        => reset);

  -----------------------------------------------------------------------------
  --* Compare simulated data with undelayed input data (sMuons_synced)
  -----------------------------------------------------------------------------
  
  compare_error_bits <= InMuons_vec_to_flat(sMuons_synced) xor InMuons_vec_to_flat(sMuons_delayed);

  comparator_vec: entity work.ErrorCounterVec
    generic map (
      reset_address        => IF_CompareCounterReset_waddr,
      counter_base_address => IF_CompareCounterVec_raddr)
    port map (
      error_bits   => compare_error_bits,
      vme_addr     => vme_addr_i,
      vme_data     => vme_data_i,
      vme_en       => vme_en_i,
      vme_wr       => vme_wr_i,
      vme_data_out => vme_data_out_i(11),
      vme_en_out   => vme_en_out_i(11),
      clk          => clk,
      reset        => reset);

  -----------------------------------------------------------------------------
  --* register other inputs
  -----------------------------------------------------------------------------
  
  register_inputs : process (clk, reset) is
  begin
    if reset = '1' then
      ro_rdfifo_reg <= '0';
      ro_fetch_reg  <= '0';
      dummy_reg   <= '0';
      dummy_reg_d <= '0';
    elsif (clk'event and clk = '1') then
      ro_rdfifo_reg <= ro_rdfifo;
      ro_fetch_reg  <= ro_fetch;

      clk_fb_reg    <= clk_fb;
      dummy_reg <= dummyb;
      dummy_reg_d <= dummy_reg;
      reset_input_reg <= reset_input;
    end if;
  end process register_inputs;

  dummy_pulse <= dummy_reg and (not dummy_reg_d);
  
  -----------------------------------------------------------------------------
  -- register and decode TCS Signals
  -----------------------------------------------------------------------------

  tcs_decoder: entity work.TCSCommandDecoder
    port map (
      iL1A     => l1a,
      iBCReset => bcreset,
      iL1Reset => l1reset,

      oL1A     => l1a_reg,
      oBCReset => bcreset_reg,
      oL1Reset => l1reset_reg,
      oECReset => open,                 -- no event counter 
      
      clk      => clk,
      reset    => reset);

  -----------------------------------------------------------------------------
  -- generate BCreset (dummy_pulse for testing, otherwise external bcreset)
  -----------------------------------------------------------------------------
  bcreset_or_dummy <= dummy_pulse when sDummyIsBCReset = '1' else
                      bcreset_reg;
  
  -----------------------------------------------------------------------------
  -- BX counter
  -----------------------------------------------------------------------------

  bxcounter : entity work.BXCounter
    generic map (
      reg_addr         => IF_ReadoutSyncReg_addr,
      bcreset_delay_reg_default => "0000000000000000")
    port map (
      iBCReset         => bcreset_or_dummy,

      oPreBCReset      => sBCReset_pre,
      oBCReset         => sBCReset_main,
      oBXCounter       => sBXCount,

      vme_addr     => vme_addr_i,
      vme_data     => vme_data_i,
      vme_en       => vme_en_i,
      vme_wr       => vme_wr_i,
      vme_data_out => vme_data_out_i(4),
      vme_en_out   => vme_en_out_i(4),

      clk   => clk,
      reset => reset);
  
  -----------------------------------------------------------------------------
  -- Readout logic
  -----------------------------------------------------------------------------

  -- 4x 32bit readout data and
  -- 4x 10bit monitoring data
  
  -- assign readout data
  readout_muons : for i in 0 to 3 generate
  begin  -- generate i
    readout_data(i)(29 downto 0)  <= sMuons_selected(i)(29 downto 0);
    readout_data(i)(31 downto 30) <= std_logic_vector(to_unsigned(input_fpga_idx, 2));
  end generate readout_muons;

  mon: for i in mon_data'range generate
  begin  -- generate mon_data
    mon_data(i) <= (others => '0');
  end generate mon;
  
  readout_logic: entity work.ReadOutLogic
    generic map (
      nwords => 4,
      lat_delay_reg_addr => IF_LATDelayReg_addr)
    port map (
      data           => readout_data,
      mondata        => mon_data,
      
      iBXCount       => sBXCount,
      iBCReset       => bcreset_or_dummy,
      iL1A           => l1a_reg,
      iL1Reset       => l1reset_reg,
      
      vme_addr       => vme_addr_i,
      vme_data       => vme_data_i,
      vme_en         => vme_en_i,
      vme_wr         => vme_wr_i,
      
      vme_data_out   => vme_data_out_i(5),
      vme_en_out     => vme_en_out_i(5),
      
      ro_data        => ro_data_i,
      ro_rdfifo      => ro_rdfifo_reg,
      ro_fetch       => ro_fetch_reg,
      
      clk            => clk,
      reset          => reset);

  -----------------------------------------------------------------------------
  -- Simulation / Spy Logic
  -----------------------------------------------------------------------------

  simuspy_logic: entity work.SimuSpyLogic
    generic map (
      depth1k                     => 0,
      nwords                      => 4,
      simuspyconfig_reg_addr      => IF_SimuSpyConfig_addr,
      spydepth_reg_addr           => IF_SpyDepth_addr,
      spyarmpulse_reg_addr        => IF_SpyArmPulse_waddr,
      spydone_reg_addr            => IF_SpyDone_raddr,
      simuspyram_vme_base_address => IF_SimuSpyRAM_base)
    port map (
      iData        => readout_data,
      
      iPreBCRes    => sBCReset_pre,
      iBCRes       => sBCReset_main,
      oData        => sSimulatedData,
      oSimuMode    => sSimuMode,
      oDummyIsBCReset => sDummyIsBCReset,
      
      vme_addr     => vme_addr_i,
      vme_data     => vme_data_i,
      vme_en       => vme_en_i,
      vme_wr       => vme_wr_i,
      vme_data_out => vme_data_out_i(6),
      vme_en_out   => vme_en_out_i(6),
      
      clk          => clk,
      reset        => reset);
  
  -----------------------------------------------------------------------------
  -- Chip ID and Revision
  -----------------------------------------------------------------------------

  ChipID: entity work.ChipIDRegisters
    generic map (
      idregisters_vme_base_address => IF_chip_id0_raddr,

      chipID_h  => chip_id_h(input_fpga_idx),  chipID_l  => chip_id_l(input_fpga_idx),
      chipRev_h => 16#beee#,                   chipRev_l => 16#beee#,
      date_string => date_string)

    port map (
      vme_addr     => vme_addr_i,
      vme_en       => vme_en_i,
      vme_wr       => vme_wr_i,
      vme_data_out => vme_data_out_i(7),
      vme_en_out   => vme_en_out_i(7),
      vme_clk      => clk,
      reset        => reset);

  -----------------------------------------------------------------------------
  -- Dummy signals
  -----------------------------------------------------------------------------
  register_dummy: process (clk) is
  begin  -- process register_dummy
    if (clk'event and clk = '1') then
      sDummy(0) <=  clk_fb_reg or
                    sMuons_reg(0)(31) or
                    sMuons_reg(1)(31) or
                    sMuons_reg(2)(31) or
                    sMuons_reg(3)(31) or
                    sSimulatedData(0)(31) or
                    sSimulatedData(1)(31) or
                    sSimulatedData(2)(31) or
                    sSimulatedData(3)(31);
    end if;
  end process register_dummy;
  
  sDummy(15 downto 1) <= (others => '0');
  -----------------------------------------------------------------------------
  --* Dummy register
  -----------------------------------------------------------------------------
  dummy_register: entity work.VMEStatusReg
    generic map (
      my_vme_base_address => IF_dummy_raddr)
    port map (
      data         => sDummy,
      vme_addr     => vme_addr_i,
      vme_en       => vme_en_i,
      vme_wr       => vme_wr_i,
      vme_data_out => vme_data_out_i(8),
      vme_en_out   => vme_en_out_i(8),
      vme_clk      => clk,
      reset        => reset);



  --FIXME
  dummyvme : for i in 12 to 15 generate
  begin  -- generate dummyvme
    vme_data_out_i(i) <= (others => '0');
    vme_en_out_i(i)   <= '0';
  end generate dummyvme;


  -------------------------------------------------------------------------------
  -- multiplex VME outputs
  -------------------------------------------------------------------------------
  mux_vme(vme_data_out_i, vme_en_out_i, vme_data_out_muxed, vme_en_out_muxed);

  -----------------------------------------------------------------------------
  -- VME Logic
  -----------------------------------------------------------------------------
  vme_logic: entity work.InChipVMELogic
    port map (
      vme_addr     => vme_addr,
      vme_data     => vme_data,
      vme_en       => vme_en,
      vme_wr       => vme_wr,
      vme_ndtack   => svme_ndtack,
      vme_nirq     => vme_nirq,
      
      vme_addr_i   => vme_addr_i,
      vme_data_i   => vme_data_i,
      vme_en_i     => vme_en_i,
      vme_wr_i     => vme_wr_i,
      
      vme_data_out => vme_data_out_muxed,
      vme_en_out   => vme_en_out_muxed,
      
      clk          => clk,
      reset        => reset);

  vme_ndtack <= svme_ndtack;

  register_test : process (clk) is
  begin
    if (clk'event and clk = '1') then
      test_lemo <= sMuons_reg(0)(0);
      test(0) <=  compare_error_bits(0);
      test(1) <=  sMuons_reg(0)(2);
--      test(2) <=  sMuons_reg(0)(2);
--      test(3) <=  sMuons_reg(0)(3);
--       test(0) <= vme_en_i;  
--       test(1) <= vme_wr_i;  
--       test(2) <= vme_en_out_muxed;
--       test(3) <= svme_ndtack;
    end if;
  end process register_test;

  test(2) <= clk2x;
  test(3) <= clk;
  clk_test <= clk4x;
  
  -------------------------------------------------------------------------------
  -- Digital Clock Management
  -------------------------------------------------------------------------------

  theDCM: entity work.dcm4x
    port map (
      RST_IN          => reset_dcm,
      CLKIN_IN        => clk_input,
      LOCKED_OUT      => dcm_locked_i,
      CLK2X_OUT       => clk2x,
      CLKFX_OUT       => clk4x,
      CLK0_OUT        => clk,
      CLKIN_IBUFG_OUT => CLKIN_IBUFG_i); -- not used

  dcm_locked <= dcm_locked_i;
  
  -- output clock on two pins
  clk_out  <= clk;

  -- Connect Reset and Tristate lines
  --FIXME: move to other place if this design should also work for Spartan
  --FIXME: is it ok to use the DCM clock output as user startup clock?

-- this does not work with Cadence NCSIM and the Synplify vrtex2 library
-- the Virtex2 library has a component and an entity and architecture for
-- the startup_virtex2 ?!
  
--   startup: STARTUP_VIRTEX2
--     port map (
--       CLK => clk,
--       GSR => reset,
--       GTS => inactive);

  -- do them separately, instead
  
  -- no external reset that goes to GSR in ROP chip
  startup_CLK: STARTUP_VIRTEX2_CLK
    port map ( CLK => clk);

  startup_GTS: STARTUP_VIRTEX2_GTS
    port map ( GTS => inactive);

--   startup_GSR: STARTUP_VIRTEX2_GSR
--     port map ( GSR => reset);

  -- Xilinx recommends not to use the GSR netwok but the normal routing
  -- resources, instead. [Syntehsis and Verification design guide]. They
  -- are faster and can be analyzed by the trce tool.
  
  -- new solution: use general routing resources
  -- this is also fine for synthesis.
  reset <= reset_input or (not dcm_locked_i);
  
  status <= "00";
--  test_lemo <= '0';
--  test <= "1111";


  -------------------------------------------------------------------------------
  --* register outputs
  -------------------------------------------------------------------------------
  register_outputs : process (clk) is
  begin
    if (clk'event and clk = '1') then
      ro_data <= ro_data_i;
    end if;
  end process register_outputs;

end architecture behavioral;