--******************************************************************************
--* @short   16 bit VME Write Pulse register generates 25 ns pulses
--*          when written to
--******************************************************************************
--* @author  SAKULIN Hannes  <hsakulin@dsy-srv2.cern.ch>
--* @version $Revision: 1.2 $
--* @date    $Date: 2005/01/20 11:01:47 $
--******************************************************************************
--/
library IEEE;
use IEEE.Std_logic_1164.all;
use IEEE.Numeric_Std.all;

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

  port (
    -- data port
    data_pulse  : out std_logic_vector(15 downto 0);
    
    -- VME port
    vme_addr     : in    std_logic_vector;  -- leave unconstrained 
    vme_data     : 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 VMEWritePulseReg;


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

architecture behavioral of VMEWritePulseReg is

  signal vme_en_i   : std_logic;
  signal vme_en_i_d : std_logic;
  signal Q : std_logic_vector(15 downto 0);
  
begin  -- behavioral
  --------------------------------------------------------------------------------
  -- VME port
  --------------------------------------------------------------------------------
  assert vme_data'high <= 15 report "error: max VME data width is 16 bits" severity error;
  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 a pulse when written to
  --* generate enable out only when written to
  reg: process (vme_clk, reset) is
  begin  -- process reg
    if reset = '1' then                 -- asynchronous reset 
        data_pulse <= (others => '0');
        vme_en_i_d <= '0';
    elsif vme_clk'event and vme_clk = '1' then  -- rising clock edge
      vme_en_i_d <= vme_en_i;
      if vme_en_i = '1' and vme_wr = '1' and vme_en_i_d = '0' then
        data_pulse <= vme_data;
        vme_en_out <= '1';
      else
        data_pulse <= ( others=> '0');
        vme_en_out <= '0';
      end if;
    end if;
  end process reg;

  vme_data_out <= (others => '0');

end behavioral;