--******************************************************************************
--* @short   Simulation Logic in the MipIsoAU Chip
--*             
--******************************************************************************
--* @author  SAKULIN Hannes  <hsakulin@dsy-srv5.cern.ch>
--* @date    $Date: 2005/02/01 19:05:00 $
--* @version $Revision: 1.3 $
--******************************************************************************
--/
library IEEE;
use IEEE.Std_logic_1164.all;
use IEEE.Numeric_std.all;
use work.VMEMux.all;
-- pragma translate_off
library UNISIM;
use UNISIM.VCOMPONENTS.all;
-- pragma translate_on

entity MIAUSimuLogic is
  
  generic (
    simuspyconfig_reg_addr      : integer;
    spydepth_reg_addr           : integer;
    spyarmpulse_reg_addr        : integer;
    spydone_reg_addr            : integer;
    simuspyram_vme_base_address : integer);

  port (
    iPreBCRes      : in std_logic;
    iBCRes         : in std_logic;

    oData          : out std_logic_vector (15 downto 0);

    oSimuMode      : out std_logic;
    oDummyIsBCReset: out std_logic;
    
    -- VME port 
    vme_addr       : in    std_logic_vector;
    vme_data       : in    std_logic_vector;
    vme_en         : in    std_logic;
    vme_wr         : in    std_logic;

    vme_data_out   : out   std_logic_vector(15 downto 0);
    vme_en_out     : out   std_logic;

    -- Clock, control
    clk            : in    std_logic;
    reset          : in    std_logic
    );  

end entity MIAUSimuLogic;


architecture behavioral of MIAUSimuLogic is

  component mi_simuram4k
    port (
      A: IN std_logic_VECTOR(11 downto 0);
      CLK: IN std_logic;
      D: IN std_logic_VECTOR(15 downto 0);
      WE: IN std_logic;
      DPRA: IN std_logic_VECTOR(11 downto 0);
      DPO: OUT std_logic_VECTOR(15 downto 0);
      SPO: OUT std_logic_VECTOR(15 downto 0));
  end component;

  -- Synplicity black box declaration
  attribute syn_black_box : boolean;
  attribute syn_black_box of mi_simuram4k: component is true;



signal rw_addr : std_logic_vector(11 downto 0);  -- 4k
  signal we_simuspy : std_logic;

  signal en_simuspy : std_logic;
  
  signal vme_data_out_i   : TVMEData_vec (0 to 1);
  signal vme_en_out_i     : TVMEEnable_vec (0 to 1);

  signal vme_en_i         : std_logic;
  signal vme_we_i         : std_logic;

begin  -- architecture behavioral

  -----------------------------------------------------------------------------
  --* SimuSpyControlLogic
  -----------------------------------------------------------------------------

  ctrl: entity work.SimuSpyControlLogic
    generic map (
      simuspyconfig_reg_addr => simuspyconfig_reg_addr,
      spydepth_reg_addr      => spydepth_reg_addr,
      spyarmpulse_reg_addr   => spyarmpulse_reg_addr,
      spydone_reg_addr       => spydone_reg_addr)
    port map (
      iPreBCRes       => iPreBCRes,
      iBCRes          => iBCRes,
      
      oSimuMode       => oSimuMode,
      oDummyIsBCReset => oDummyIsBCReset,
      
      oWE_simuspy     => we_simuspy,
      oRW_addr        => rw_addr,
      
      vme_addr        => vme_addr,
      vme_data        => vme_data,
      vme_en          => vme_en,
      vme_wr          => vme_wr,
      
      vme_data_out    => vme_data_out_i(1),
      vme_en_out      => vme_en_out_i(1),
      
      clk             => clk,
      reset           => reset);
  

  en_simuspy <= '1';
  

  -----------------------------------------------------------------------------
  -- instantiate the Simu Memory
  -----------------------------------------------------------------------------

  -----------------------
  -- vme control logic
  -----------------------
  vme_addr_decode : process (vme_addr, vme_en) is
                                                 variable my_addr_vec  : std_logic_vector(vme_addr'high downto 0);
                                               variable selected     : boolean;
                                               variable my_base_addr : integer;                                                 
  begin  -- process vme_addr_decode
    my_base_addr := simuspyram_vme_base_address;
    my_addr_vec := std_logic_vector( TO_UNSIGNED (my_base_addr, vme_addr'high+1 ) );
    selected    := my_addr_vec(vme_addr'high downto 13) = vme_addr(vme_addr'high downto 13);
    vme_en_i <= '0' ;
    if selected then
      vme_en_i <= vme_en;
    end if;
  end process vme_addr_decode;

  -- register output enable
  reg_enout: process (clk) is
  begin  
    if clk'event and clk = '1' then
      vme_en_out_i(0) <= vme_en_i ; --and ( not vme_wr );    
    end if;
  end process reg_enout;

  vme_we_i <= vme_en_i and vme_wr;
  
  simu_ram : mi_simuram4k
    port map (
      -- VME port
      A => vme_addr(12 downto 1),
      D => vme_data,
      SPO => vme_data_out_i(0),
      WE => vme_we_i,
      CLK => clk,

      -- GMT port (read-only)
      DPRA => rw_addr,
      DPO => oData);
  
  -- multiplex vme_data_output
  mux_vme(vme_data_out_i, vme_en_out_i, vme_data_out, vme_en_out);

end architecture behavioral;