--******************************************************************************
--* @short      Muon Merger Unit. merges the one DTCSC/RPC pair
--******************************************************************************
--* @author  SAKULIN Hannes  <hsakulin@dsy-srv3.cern.ch>
--* @date    $Date: 2005/01/31 15:17:29 $
--* @version $Revision: 1.4 $
--******************************************************************************
--/
library IEEE;
use IEEE.Std_logic_1164.all;
use IEEE.Numeric_Std.all;
use WORK.GMTTypes.all;
use WORK.LFTiming.all;
use WORK.LFVMEAddrMap.all;

entity LFMuonMergerUnit is
  generic (
    idx_merger : integer := 0;          -- 0: brl, 1: fwd
    idx_mu     : integer;               -- muon index 0 => 4
    muon_merger_lat_start : integer); 
  port (
    -- INPUTS
    iRPCGMTMuon        : in TGMTMu;     --MIP/ISO are ignored, here
    iDTCSCGMTMuon      : in TGMTMu;     --MIP/ISO are ignored, here
    iFineHaloDTCSC     : in std_logic;
    
    iRPCisMIP,
    iDTCSCisMIP,
    iRPCisISO,
    iDTCSCisISO        : in std_logic;  --MIP/ISO come 1/2 bx later

    iDTCSCisMatched    : in std_logic;

    -- if the special-bit is not set then
    -- the select bit decides whether to take to DT or RPC
    iSelectBit_phi     : in std_logic;  -- 1 for DT/CSC
    iSelectBit_eta     : in std_logic;
    iSelectBit_pt      : in std_logic;
    iSelectBit_charge  : in std_logic;
    iSelectBit_MIP     : in std_logic;
    iSelectBit_ISO     : in std_logic;

    -- if a special bit is set for a parameter, then
    -- a special merging method is used
    iSpecialBit_eta    : in std_logic;
    iSpecialBit_pt     : in std_logic;
    iSpecialBit_charge : in std_logic;
    iSpecialBit_MIP    : in std_logic;
    iSpecialBit_ISO    : in std_logic;

    -- INPUTS (configuration)
    iSpecialMIPMergeUseAND      : in std_logic;
    iSpecialISOMergeUseAND      : in std_logic;
    iHaloOverwritesMatched      : in std_logic;

    -- OUTPUTS
    oMergedGMTMuon     : out TGMTMu;

    -- 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 and control
    clk            : in    std_logic;
    sinit          : in    std_logic
  );  
  
end entity LFMuonMergerUnit;

architecture behavioral of LFMuonMergerUnit is

  signal smartcharge : std_logic_vector(1 downto 0);
  signal smarteta    : std_logic_vector(5 downto 0);

  signal mixpt : std_logic_vector(4 downto 0);

  signal specialmip : std_logic;
  signal specialiso : std_logic;

  signal forceDTCSC : std_logic;
begin  -- architecture behavioral

  forceDTCSC <= (not iDTCSCisMatched ) when idx_merger = 0 else  --brl
                (not iDTCSCisMatched ) or (iFineHaloDTCSC and iHaloOverwritesMatched);  -- fwd

  -----------------------------------------------------------------------------
  -- Merge Phi
  -----------------------------------------------------------------------------

  oMergedGMTMuon.phi <= iDTCSCGMTMuon.phi when forceDTCSC = '1' else
                        iDTCSCGMTMuon.phi when iSelectBit_phi = '1' else
                        iRPCGMTMuon.phi;

  -----------------------------------------------------------------------------
  -- Merge Eta
  -----------------------------------------------------------------------------
  -- only useful in brl case, otherwise default to CSC
  smarteta <= iDTCSCGMTMuon.eta when idx_merger = 1 else  -- fwd
              iDTCSCGMTMuon.eta when iFineHaloDTCSC = '1' else
              iRPCGMTMuon.eta;

  oMergedGMTMuon.eta <= iDTCSCGMTMuon.eta when forceDTCSC = '1' else
                        smarteta when iSpecialBit_eta = '1' else
                        iDTCSCGMTMuon.eta when iSelectBit_eta = '1' else
                        iRPCGMTMuon.eta;

  -----------------------------------------------------------------------------
  -- Merge Charge
  -----------------------------------------------------------------------------
  smartcharge <= iDTCSCGMTMuon.sysign when iDTCSCGMTMuon.sysign(1) = '0' else 
                 iRPCGMTMuon.sysign when iRPCGMTMuon.sysign(1)='0' else
                 iDTCSCGMTMuon.sysign;  -- DT/CSC in default when both invalid

  oMergedGMTMuon.sysign <= iDTCSCGMTMuon.sysign when forceDTCSC = '1' else
                           smartcharge when iSpecialBit_charge = '1' else
                           iDTCSCGMTMuon.sysign when iSelectBit_charge = '1' else
                           iRPCGMTMuon.sysign;

  -----------------------------------------------------------------------------
  -- Merge pt
  -----------------------------------------------------------------------------
  -- pt mix LUT 
  ptmix: entity work.lfptmixlut
    generic map (
      instance_idx        => idx_merger,        
      my_vme_base_address => LF_PtMixLUT_base(0) + idx_mu * LF_PtMixLUT_size,
      edge                => calc_lf_edge(muon_merger_lat_start + LF_RLAT_MM_PTMIX))
    port map (
      pt_dtcsc     => iDTCSCGMTMuon.pt,
      pt_rpc       => iRPCGMTMuon.pt,
      
      pt_mixed     => mixpt,
      
      clk          => clk,
      sinit        => sinit,
      
      vme_addr     => vme_addr,
      vme_data     => vme_data,
      vme_en       => vme_en,
      vme_wr       => vme_wr,
      vme_data_out => vme_data_out,
      vme_en_out   => vme_en_out,
      vme_clk      => clk);
  
  oMergedGMTMuon.pt <= iDTCSCGMTMuon.pt when forceDTCSC = '1' else
                       mixpt when iSpecialBit_pt = '1' else
                       iDTCSCGMTMuon.pt when iSelectBit_pt = '1' else
                       iRPCGMTMuon.pt;

  -----------------------------------------------------------------------------
  -- Merge MIP
  -----------------------------------------------------------------------------
  specialmip <=  ( iDTCSCisMIP AND iRPCisMIP ) when iSpecialMIPMergeUseAND = '1' else
                 ( iDTCSCisMIP OR  iRPCisMIP );

  oMergedGMTMuon.mip <= iDTCSCisMIP when forceDTCSC = '1' else
                        specialmip when iSpecialBit_MIP = '1' else
                        iDTCSCisMIP when iSelectBit_MIP = '1' else
                        iRPCisMIP;
  
  -----------------------------------------------------------------------------
  -- Merge ISO
  -----------------------------------------------------------------------------
  specialiso <= ( iDTCSCisISO AND  iRPCisISO ) when iSpecialISOMergeUseAND = '1' else
                ( iDTCSCisISO OR  iRPCisISO );

  oMergedGMTMuon.isol <= iDTCSCisISO when forceDTCSC = '1' else
                         specialiso when iSpecialBit_ISO = '1' else
                         iDTCSCisISO when iSelectBit_ISO = '1' else
                         iRPCisISO;
  

  -----------------------------------------------------------------------------
  -- define quality
  -----------------------------------------------------------------------------
  oMergedGMTMuon.qual <= iDTCSCGMTMuon.qual when forceDTCSC = '1' else
                         std_logic_vector(TO_UNSIGNED(QCODE_MATCHED,3));
  
end architecture behavioral;