--******************************************************************************
--* @short   16 bit VME read-only register
--*
--*          Always contains data that is loaded at initilaization (reset) time
--*          generates vme_en_out, only if read
--******************************************************************************
--* @author  SAKULIN Hannes  <hsakulin@dsy-srv2.cern.ch>
--* @version $Revision: 1.3 $
--* @date    $Date: 2005/12/06 16:11:56 $
--******************************************************************************
--/
library IEEE;
use IEEE.Std_logic_1164.all;
use IEEE.Numeric_Std.all;

entity VMEReadOnlyReg is
  generic (
    init_val            : std_logic_vector(15 downto 0);  -- type of LUT
    my_vme_base_address : integer := 0); -- VME address of this instance

  port (
    -- VME port
    vme_addr     : in    std_logic_vector;  -- leave unconstrained 
    vme_en       : in    std_logic;
    vme_wr       : in    std_logic;
    vme_data_out : out   std_logic_vector;                                    
    vme_en_out   : out   std_logic;        
    vme_clk      : in    std_logic;
    reset        : in    std_logic);
end VMEReadOnlyReg;


-------------------------------------------------------------------------------
-- Implementation
--  Updated 2dec2005 by A.T.
-------------------------------------------------------------------------------

architecture behavioral of VMEReadOnlyReg is

  signal vme_en_i   : std_logic;
  signal Q : std_logic_vector(15 downto 0);
  
begin  -- behavioral
  --------------------------------------------------------------------------------
  -- VME port
  --------------------------------------------------------------------------------
  assert vme_addr'high >= 5 report "error: VME addr width has to be greater than 5" severity error;

  -- purpose: decode VME address and generate internal enable signal
  --          ( asynchronous )
  vme_addr_decode : process (vme_addr, vme_en) is
    variable my_addr_vec : std_logic_vector(vme_addr'high downto 0);
    variable selected    : boolean;
  begin  -- process vme_addr_decode
    my_addr_vec := std_logic_vector( TO_UNSIGNED ( my_vme_base_address, vme_addr'high+1 ) );
    selected    := my_addr_vec(vme_addr'high downto 1) = vme_addr(vme_addr'high downto 1);
    vme_en_i <= '0' ;
    if selected then
      vme_en_i <= vme_en;
    end if;
  end process vme_addr_decode;

  -- purpose: register data during write
  --          generate VME enable out when addressed (both read and write)
  reg: process (vme_clk, reset) is
  begin  -- process reg
    if reset = '1' then                 -- asynchronous reset 
        Q <= init_val;
        vme_en_out <= '0';
    elsif vme_clk'event and vme_clk = '1' then  -- rising clock edge
      Q <= init_val;                            -- *****Added by A.T 2dec2005******
      if vme_en_i = '1' and vme_wr = '0' then
        vme_en_out <= '1';
      else
        vme_en_out <= '0';
      end if;
    end if;
  end process reg;
  
  vme_data_out <= Q;

end behavioral;