--******************************************************************************
--* @short   16 bit VME status register (read only)
--*
--*          always contains data that is input at data port
--******************************************************************************
--* @author  SAKULIN Hannes  <hsakulin@dsy-srv2.cern.ch>
--* @version $Revision: 1.5 $
--* @date    $Date: 2005/01/20 14:41:42 $
--******************************************************************************
--/
library IEEE;
use IEEE.Std_logic_1164.all;
use IEEE.Numeric_Std.all;

entity VMEStatusReg is
  generic (
    my_vme_base_address : integer := 0); -- VME address of this instance

  port (
    -- data port
    data         : in std_logic_vector(15 downto 0);
    
    -- 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 VMEStatusReg;


-------------------------------------------------------------------------------
-- Implementation
-------------------------------------------------------------------------------

architecture behavioral of VMEStatusReg is

  signal vme_en_i   : std_logic;
  
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;

  -- generate VME enable out when addressed 
  reg_enout: process (vme_clk, reset) is
  begin  -- process reg
    if reset = '1' then                 -- asynchronous reset 
        vme_en_out <= '0';
    elsif vme_clk'event and vme_clk = '1' then  -- rising clock edge
      if (vme_wr = '0') then
        vme_en_out <= vme_en_i;
      end if;
    end if;
  end process reg_enout;

  -- always output status data
  vme_data_out <= data;

end behavioral;