--******************************************************************************
--* @short   Logic FPGA (the whole chip)
--******************************************************************************
--* @author  SAKULIN Hannes  <hsakulin@dsy-srv3.cern.ch>, Updated: A.Taurok
--* @version $Revision: 1.18 $
--* @date    $Date: 2005/12/06 16:11:56 $
--******************************************************************************
-- Revision 1.18: feedabe1 24nov2005 LFF to get bad bit 42  via bit 100 from INF
-- Revision 1.19: feed0001 30nov2005 LFB to send bad bit 56 via bit 104 to Sorter
--/
library IEEE;
use IEEE.Std_logic_1164.all;
use WORK.LFTypes.all;
use WORK.GMTTypes.all;
use WORK.LFTiming.all;
use work.VMEMux.all;
use work.LFVMEAddrMap.all;

-- pragma translate_off
library UNISIM;
use UNISIM.VCOMPONENTS.all;
-- pragma translate_on
--use STD.TEXTIO.all;
use IEEE.NUMERIC_STD.all;
--use work.ieee_to_string.all;

entity LogicFPGA is
  generic (logic_fpga_idx  : integer :=0);  -- 0 for barrel / 1 for fwd
  port (
        -- CHIP INPUTS
        iRPCmuons   : in  TFourSyncedMu_flat;
        iDTCSCmuons : in  TFourSyncedMu_flat;

        -- eta and phi of DT/CSC from other stream for cancel-out
        iPhiCOU     : in TPhi_vec(0 to 3);
        iEtaCOU     : in TEtaCOU_vec(0 to 3);
        
        -- MIP & ISO bits 
        iRPCisMIP,
        iDTCSCisMIP,
        iRPCisISO,
        iDTCSCisISO : in std_logic_vector (0 to 3);
        
        -- cancel-out links
        iOtherDTCSCisMatched : in std_logic_vector (0 to 3);
        iCancelDTCSC         : in std_logic_vector (0 to 3);

        -- CHIP OUTPUTS
        oOutMuons         : out TFourGMTMu_flat;
        oSortRanks        : out TSortRank_vector(0 to 3);
        oIdxBits          : out TIndexBits_vector(0 to 3);  -- indices of
                                                            -- regional muons
        oIsRPCMu          : out std_logic_vector (0 to 3);  -- is the GMT mu an
                                                            -- RPC mu?

        oDTCSCisMatched   : out std_logic_vector (0 to 3);
        oCancelOtherDTCSC : out std_logic_vector (0 to 3);

        -- test outputs - for behavioral simu only
-- synthesis translate_off
        oPairMatrix    : out TPairMatrix;
        oPairMatrix1   : out TPairMatrix;
        oPairMatrix2   : out TPairMatrix;
        oCancelBits1   : out std_logic_vector(0 to 7);
        oCancelBits2   : out std_logic_vector(0 to 7);
        oMQMatrix      : out TMQMatrix;
-- synthesis translate_on
       
        oDummy         : in std_logic;  -- changed to input
        -- VME port
        vme_addr       : in    std_logic_vector;
        vme_data       : inout std_logic_vector;
        vme_en         : in    std_logic;
        vme_wr         : in    std_logic;
        vme_ndtack     : out   std_logic;  -- low active 
        vme_nirq       : out   std_logic;  -- low active 

        -- Clock and control
        clk_input      : in    std_logic;
        clk_test       : out   std_logic;   -- clock1x from DCM
        clk_out        : out   std_logic;   -- clock output for feedback (use optional)
                                            -- same as clk_test
        clk_fb         : in    std_logic;   -- clock feedback input (use optional)
        
        dcm_locked     : out   std_logic;   -- DCM is locked => goes to VME chip

        reset_dcm            : in    std_logic;   -- crate reset (crate reset button and after
                                            -- power-up)  => resets DCM
        inactive       : in    std_logic;   -- from front panel button (to GTS)
    
        
        status         : out std_logic_vector(1 downto 0);
        test           : out std_logic_vector(3 downto 0);
        spare          : in    std_logic;
        reset_input    : in    std_logic);  -- hard reset from trigger control
                                            --
                                            -- register input
                                            -- same function as level-1 reset
                                            -- or hard reset from trigger control
                                            --
                                            -- generated by VME chip
                                            -- resets only state machines, FFs,
                                            -- counters, error flags
                                            -- but not memories and registers
end;


architecture behavioral of LogicFPGA is
  attribute syn_useioff : boolean;
  attribute syn_useioff of behavioral : architecture is true;

  type TIntArr is array (integer range <>) of integer;
  
  constant chip_id_h : TIntArr(0 to 1) := (
	16#0001#,
	16#0001#
	);

  constant chip_id_l : TIntArr(0 to 1) := (
	16#9142#, -- barrel
	16#9141#  -- forward
	);

--  constant date_string : string := "$Date: 2005/12/06 16:11:56 $";  --rev 1.18
  constant date_string : string := "$Date: 2005/12/06 16:11:56 $";    --rev 1.19

  signal clk,reset          : std_logic;
  
  

  -- registered inputs
  signal iRPCmuons_reg      : TFourSyncedMu_flat; --  in flat format
  signal sRPCmuons_reg      : TSyncedMu_vector4;  --  in vector array format 
  signal sDTCSCmuons_reg    : TSyncedMu_vector4;
  signal sPhiCOU_reg        : TPhi_vec(0 to 3);
  signal sEtaCOU_reg        : TEtaCOU_vec(0 to 3);
  signal sEtaCOU4           : TEta4_vec(0 to 3);
  signal OtherDTCSCisMatched_reg : std_logic_vector (0 to 3);
  signal sCancelDTCSC_reg : std_logic_vector (0 to 3);
  signal reset_reg       : std_logic;

  -- delayed version
  signal sRPCmuons_reg_d    : TSyncedMu_vector4;
  signal sDTCSCmuons_reg_d  : TSyncedMu_vector4;

  
  signal phi1, phi2    : TPhi_vec (0 to 3);
  signal eta1, eta2    : TEta_vec (0 to 3);
  signal empty1          : std_logic_vector (0 to 3);
  signal empty2          : std_logic_vector (0 to 3);
  signal empty1_d1       : std_logic_vector (0 to 3);
  signal empty2_d1       : std_logic_vector (0 to 3);
  signal empty1_d2       : std_logic_vector (0 to 3);
  signal empty2_d2       : std_logic_vector (0 to 3);
  signal empty1_d3       : std_logic_vector (0 to 3);
  signal empty2_d3       : std_logic_vector (0 to 3);
  signal empty1_d4       : std_logic_vector (0 to 3);
  signal empty2_d4       : std_logic_vector (0 to 3);

  signal DTCSC_is_matched : std_logic_vector (0 to 3);
  signal DTCSC_is_matched_nr : std_logic_vector (0 to 3);
  signal RPC_is_matched   : std_logic_vector (0 to 3);
  signal RPC_is_matched_d : std_logic_vector (0 to 3);
  signal RPC_is_matched_d1: std_logic_vector (0 to 3);
  signal PairMatrix_i      : TPairMatrix;
  signal PairMatrix_i1      : TPairMatrix;
  signal PairMatrix_i2      : TPairMatrix;

  -- cancel-out signals
  signal cancel_DTCSC_COU1 : std_logic_vector (0 to 3);
  signal cancel_dummy_COU1 : std_logic_vector (0 to 3);
  signal cancel_RPC_COU2 : std_logic_vector (0 to 3);
  signal cancel_OtherDTCSC_COU2_nr : std_logic_vector (0 to 3);

  signal cancel_DTCSC_COU1_d : std_logic_vector (0 to 3);
  signal cancel_RPC_COU2_d : std_logic_vector (0 to 3);

  -- sort ranks
  signal sSortRanksDTCSC        : TSortRank_vector(0 to 3);
  signal sSortRanksRPC          : TSortRank_vector(0 to 3);
  signal sSortRanksMatchedDTCSC : TSortRank_vector(0 to 3);
  signal sSortRanksMatchedRPC   : TSortRank_vector(0 to 3);

  -- sort ranks delayed
  signal sSortRanksRPC_d   : TSortRank_vector(0 to 3);

  -- sort ranks merged
  signal sSortRanksMerged      : TSortRank_vector(0 to 3);

  signal sVLQbitsDTCSC         : TVLQbits_vector(0 to 3);
  signal sVLQbitsRPC           : TVLQbits_vector(0 to 3);
  signal sDisableDTCSC         : std_logic_vector(0 to 3);
  signal sDisableRPC           : std_logic_vector(0 to 3);
  signal sDisableOtherDTCSC    : std_logic_vector(0 to 3);

  signal sRPCGMTMuons          : TGMTMu_vector4;
  signal sDTCSCGMTMuons        : TGMTMu_vector4;
  signal sRPCGMTMuons_d        : TGMTMu_vector4;
  signal sRPCGMTMuons_d1       : TGMTMu_vector4;

  signal sFineHaloDTCSC        : std_logic_vector(0 to 3);

  -- from MM
  signal sMergedGMTMuons       : TGMTMu_vector4;
  signal sMergedGMTMuons_d     : TGMTMu_vector4;

  -- from Sorter
  signal sGMTMuons             : TGMTMu_vector4;
  signal sOutMuons             : TFourGMTMu_flat; --before outputs, to assign bad bit56 to bit104

  
  signal sRPCisMIP_reg,
         sDTCSCisMIP_reg,
         sRPCisISO_reg,
         sDTCSCisISO_reg       : std_logic_vector (0 to 3);

  signal sIdxBitsMerged : TIndexBits_vector(0 to 3);
  signal sIdxBitsMerged_d : TIndexBits_vector(0 to 3);

  -- FROM MergeMethodSelector TO MuonMerger
  -- select and special matrices
  signal sSelectMatrix_SRK    : TPairMatrix;
  signal sSelectMatrix_phi    : TPairMatrix;
  signal sSelectMatrix_eta    : TPairMatrix;
  signal sSelectMatrix_pt     : TPairMatrix;
  signal sSelectMatrix_charge : TPairMatrix;
  signal sSelectMatrix_MIP    : TPairMatrix;
  signal sSelectMatrix_ISO    : TPairMatrix;
  
  signal sSpecialBit_phi    : std_logic;
  signal sSpecialBit_eta    : std_logic;
  signal sSpecialBit_pt     : std_logic;
  signal sSpecialBit_charge : std_logic;
  signal sSpecialBit_MIP    : std_logic;
  signal sSpecialBit_ISO    : std_logic;
  
  signal sSpecialMIPMergeUseAND : std_logic;
  signal sSpecialISOMergeUseAND : std_logic;
  signal sHaloOverwritesMatched : std_logic;


  signal sDummy       : std_logic_vector(15 downto 0);

  signal vme_addr_i      : std_logic_vector (vme_addr'RANGE);
  signal vme_data_i      : std_logic_vector (vme_data'RANGE);
  signal vme_en_i        : std_logic;
  signal vme_wr_i        : std_logic;

  -- VME data and enable from various units
  signal vme_data_out_i   : TVMEData_vec (0 to 9);
  signal vme_en_out_i     : TVMEEnable_vec (0 to 9);

  -- VME data muxed
  signal vme_data_out_muxed : std_logic_vector (15 downto 0);
  signal vme_en_out_muxed   : std_logic;  -- not used

  signal clk_fb_reg : std_logic;

  -- convince synplify not to optimize away the output FFs
  attribute syn_keep : boolean;
  attribute syn_keep of DTCSC_is_matched:signal is true;
  attribute syn_keep of DTCSC_is_matched_nr:signal is true;
  -- convince synplify not to optimize away the input FFs
  attribute syn_keep of sRPCmuons_reg:signal is true;
  attribute syn_keep of sDTCSCmuons_reg:signal is true;
  
  attribute syn_keep of sRPCmuons_reg_d:signal is true;
  attribute syn_keep of sDTCSCmuons_reg_d:signal is true;
  -- even this attributes do not convince the tools to use FFs instead of shift
  -- regs


  -- signal sRPCMuons100_reg   : std_logic;  -- before 24Nov2005
  signal sDTCSCMuons100_reg : std_logic;
  signal spare_reg          : std_logic;
  signal dummy_reg          : std_logic;



begin
  
  -------------------------------------------------------------------------------
  -- register inputs
  -------------------------------------------------------------------------------

  -- muons
  --   24 Nov 2005: changed by A.Taurok for LFF
  --   Because of bad INF chip I register the fRPC input bits in 'flat' format.
  --   Then the registered fRPC muons are converted to vector format.
  
  register_inputs: process (clk) is
  begin 
    if (clk'event and clk = calc_lf_edge(0)) then
 --     sRPCmuons_reg <= SyncedMu_vec_from_flat( iRPCmuons ); -- before 24Nov2005 
      sDTCSCmuons_reg <= SyncedMu_vec_from_flat( iDTCSCmuons );
      sPhiCOU_reg <= iPhiCOU;
      sEtaCOU_reg <= iEtaCOU;
 --     sRPCMuons100_reg   <= iRPCmuons(100);                -- before 24Nov2005 
      sDTCSCMuons100_reg <= iDTCSCmuons(100);
      spare_reg          <= spare;
      dummy_reg          <= oDummy;
      clk_fb_reg <= clk_fb;
      
    -- 24 Nov 2005  A.T
      -- Bad INF chip sends eta(1) of fRPC muon1 via iRPCmuons(100) instead as RPCmuons(42)
      -- 
      for i in 0 to 99 loop
        if ((i=42) and (logic_fpga_idx =1)) then       -- replace bad bit42 only in LFF chip
	      iRPCmuons_reg(42) <= iRPCmuons(100);     -- LFF: take spare bit 100 as eata(1) of muon1
	    else
              iRPCmuons_reg(i)   <= iRPCmuons(i);      -- all other fRPC and all bRPC bits
        end if;
      end loop;
      if (logic_fpga_idx =1) then
	    iRPCmuons_reg(100)    <= iRPCmuons(42);      -- LFF: keep unused bad bit 42
	else
	    iRPCmuons_reg(100)    <= iRPCmuons(100);     -- LFB: keep unused spare bit 100
      end if; 
    end if;
  end process register_inputs;
  
  --   change registered fRPC bits from flat to vector format
  sRPCmuons_reg <= SyncedMu_vec_from_flat( iRPCmuons_reg );

  -- other DT/CSC is matched
  register_otherismatched: process (clk) is
  begin 
    if (clk'event and clk = calc_lf_edge(LF_LAT_IN_OTHERDTCSCISMATCHED)) then
      OtherDTCSCisMatched_reg <= iOtherDTCSCisMatched;
    end if;
  end process register_otherismatched;

  -- cancel DT/CSC 
  register_cancelDTCSC: process (clk) is
  begin 
    if (clk'event and clk = calc_lf_edge(LF_LAT_IN_CANCELDTCSC)) then
      sCancelDTCSC_reg <= iCancelDTCSC;
    end if;
  end process register_cancelDTCSC;
  
  -- MIP/ISO bits
  register_mipiso: process (clk) is
  begin
    if clk'event and clk = calc_lf_edge(LF_LAT_IN_MIPISO) then
      sDTCSCisMIP_reg <= iDTCSCisMIP;
      sDTCSCisISO_reg <= iDTCSCisISO;
      sRPCisMIP_reg <= iRPCisMIP;
      sRPCisISO_reg <= iRPCisISO;
    end if;
  end process register_mipiso;

  
-------------------------------------------------------------------------------
-- generate blocks
-------------------------------------------------------------------------------

  split: for i in 0 to 3 generate
  begin  -- generate split
    phi1(i) <= sDTCSCmuons_reg(i).phi;
    eta1(i) <= sDTCSCmuons_reg(i).eta;

    phi2(i) <= sRPCmuons_reg(i).phi;
    eta2(i) <= sRPCmuons_reg(i).eta;

    empty1(i) <= '1' when sDTCSCmuons_reg(i).pt = "00000" else '0';
    empty2(i) <= '1' when sRPCmuons_reg(i).pt = "00000" else '0';
  end generate split;

  -- delay input muons that will go to the conversion units
  delay_inputs: process (clk) is
  begin  -- process delay_inputs
    if clk'event and clk = calc_lf_edge( LF_LAT_CONV_START ) then
      sDTCSCmuons_reg_d <= sDTCSCmuons_reg;
      sRPCmuons_reg_d <= sRPCmuons_reg;
    end if;
  end process delay_inputs;

  -- convert input muons
  ConversionUnit: entity work.LFConversionUnit
    generic map (
      conversion_unit_idx       => logic_fpga_idx,
      conversion_unit_lat_start => LF_LAT_CONV_START)
    port map (
      iDTCSCMuons    => sDTCSCmuons_reg_d,
      iRPCMuons      => sRPCmuons_reg_d,
      
      iVLQbitsDTCSC  => sVLQbitsDTCSC,
      iVLQbitsRPC    => sVLQbitsRPC,
      
      oDTCSCGMTMuons => sDTCSCGMTMuons,
      oRPCGMTMuons   => sRPCGMTMuons,
      oFineHaloDTCSC => sFineHaloDTCSC,
      
      vme_addr       => vme_addr_i,
      vme_data       => vme_data_i,
      vme_en         => vme_en_i,
      vme_wr         => vme_wr_i,
      vme_data_out   => vme_data_out_i(4),
      vme_en_out     => vme_en_out_i(4),
      
      clk            => clk,
      sinit          => reset);
  
  -- main matching unit
  MatchingUnit: entity work.LFMatchingUnit
    generic map (
      match_unit_idx => logic_fpga_idx,
      match_unit_lat_start => 0)
    port map (
      phi1            => phi1,
      phi2            => phi2,
      eta1            => eta1,
      eta2            => eta2,
      
      empty1          => empty1,
      empty2          => empty2,
      disable1        => sDisableDTCSC,
      disable2        => sDisableRPC,
      
      oFirstIsMatched  => DTCSC_is_matched,
      oFirstIsMatched_nr  => DTCSC_is_matched_nr,
      oSecondIsMatched => RPC_is_matched,
      
      oPairMatrix      => PairMatrix_i,
--      oMQMatrix      => MQMatrix_i,
      
      vme_addr        => vme_addr_i,
      vme_data        => vme_data_i,
      vme_en          => vme_en_i,
      vme_wr          => vme_wr_i,
      vme_data_out    => vme_data_out_i(0),
      vme_en_out      => vme_en_out_i(0),
      clk             => clk,
      sinit           => reset);

  OvlDisableHot: entity work.LFOvlDisableHotUnit
    generic map (
      logic_fpga_idx => logic_fpga_idx)
    port map (
      iPhi         => sPhiCOU_reg,
      iEta         => sEtaCOU_reg,
      oDisableHot  => sDisableOtherDTCSC,
      oEta4_nr     => sEtaCOU4,
      
      vme_addr     => vme_addr_i,
      vme_data     => vme_data_i,
      vme_en       => vme_en_i,
      vme_wr       => vme_wr_i,
      vme_data_out => vme_data_out_i(7),
      vme_en_out   => vme_en_out_i(7),
      clk          => clk,
      sinit        => reset);


  DTCSC_COU: entity work.LFCancelOutUnit
    generic map (
      cou_idx => logic_fpga_idx,
      cou_lat_start => 0)
    port map (
      phi_mine         => phi1,
      eta_mine         => eta1,
      phi_other        => sPhiCOU_reg,
      eta_other        => sEtaCOU4,
      empty_mine       => empty1,
      disable_mine     => sDisableDTCSC,
      disable_other    => sDisableOtherDTCSC,
      mine_is_matched  => DTCSC_is_matched,
      other_is_matched => OtherDTCSCisMatched_reg,
      
      oPairMatrix      => PairMatrix_i1,
--      oMQMatrix        => MQMatrix_i1,
      
      oCancelMine      => cancel_DTCSC_COU1,
      oCancelOther_nr  => cancel_dummy_COU1,
      
      vme_addr         => vme_addr_i,
      vme_data         => vme_data_i,
      vme_en           => vme_en_i,
      vme_wr           => vme_wr_i,
      vme_data_out     => vme_data_out_i(1),
      vme_en_out       => vme_en_out_i(1),
      
      clk              => clk,
      sinit            => reset);


  RPC_DTCSC_COU: entity work.LFCancelOutUnit
    generic map (
      cou_idx => logic_fpga_idx+2,
      cou_lat_start => 0)
    port map (
      phi_mine         => phi2,
      eta_mine         => eta2,
      phi_other        => sPhiCOU_reg,
      eta_other        => sEtaCOU4,
      empty_mine       => empty2,
      disable_mine     => sDisableRPC,
      disable_other    => sDisableOtherDTCSC,
      mine_is_matched  => RPC_is_matched,
      other_is_matched => OtherDTCSCisMatched_reg,
      
      oPairMatrix      => PairMatrix_i2,
--      oMQMatrix        => MQMatrix_i2,
      
      oCancelMine      => cancel_RPC_COU2,
      oCancelOther_nr  => cancel_OtherDTCSC_COU2_nr,
      
      vme_addr         => vme_addr_i,
      vme_data         => vme_data_i,
      vme_en           => vme_en_i,
      vme_wr           => vme_wr_i,
      vme_data_out     => vme_data_out_i(2),
      vme_en_out       => vme_en_out_i(2),
      
      clk              => clk,
      sinit            => reset);

  sru: entity work.LFSortRankUnit
    generic map (
      sort_rank_unit_idx       => logic_fpga_idx,
      sort_rank_unit_lat_start => 0)
    port map (
      iDTCSCMuons           => sDTCSCmuons_reg,
      iRPCMuons             => sRPCmuons_reg,
      
      oSortRankDTCSC        => sSortRanksDTCSC,
      oSortRankRPC          => sSortRanksRPC,
      oVLQbitsDTCSC         => sVLQbitsDTCSC,
      oVLQbitsRPC           => sVLQbitsRPC,
      oDisableDTCSC         => sDisableDTCSC,
      oDisableRPC           => sDisableRPC,
      
      oSortRankMatchedDTCSC => sSortRanksMatchedDTCSC,
      oSortRankMatchedRPC   => sSortRanksMatchedRPC,
      
      vme_addr              => vme_addr_i,
      vme_data              => vme_data_i,
      vme_en                => vme_en_i,
      vme_wr                => vme_wr_i,
      
      vme_data_out          => vme_data_out_i(3),
      vme_en_out            => vme_en_out_i(3),
      
      clk                   => clk,
      sinit                 => reset);

  SRM: entity work.LFSortRankMerger
    generic map (
      sort_rank_merger_lat_start => LF_LAT_SRM_START)
    port map (
      iSortRanksDTCSC        => sSortRanksDTCSC,
      iSortRanksMatchedDTCSC => sSortRanksMatchedDTCSC,
      iSortRanksMatchedRPC   => sSortRanksMatchedRPC,
      iPairMatrix            => PairMatrix_i,
      iSelectMatrix_SRK      => sSelectMatrix_SRK,
      oSortRanksMerged       => sSortRanksMerged,
      
      clk                    => clk,
      sinit                  => reset);

  MMS: entity work.LFMergeMethodSelector
    generic map (
      mms_idx       => logic_fpga_idx,
      mms_lat_start => LF_LAT_MMS_START)
    port map (
      iDTCSCMuons            => sDTCSCMuons_reg,
      iRPCMuons              => sRPCMuons_reg,
      
      oSelectMatrix_SRK      => sSelectMatrix_SRK,
      oSelectMatrix_phi      => sSelectMatrix_phi,
      oSelectMatrix_eta      => sSelectMatrix_eta,
      oSelectMatrix_pt       => sSelectMatrix_pt,
      oSelectMatrix_charge   => sSelectMatrix_charge,
      oSelectMatrix_MIP      => sSelectMatrix_MIP,
      oSelectMatrix_ISO      => sSelectMatrix_ISO,

      oSpecialBit_eta        => sSpecialBit_eta,
      oSpecialBit_pt         => sSpecialBit_pt,
      oSpecialBit_charge     => sSpecialBit_charge,
      oSpecialBit_MIP        => sSpecialBit_MIP,
      oSpecialBit_ISO        => sSpecialBit_ISO,
      
      oSpecialMIPMergeUseAND => sSpecialMIPMergeUseAND,
      oSpecialISOMergeUseAND => sSpecialISOMergeUseAND,
      oHaloOverwritesMatched => sHaloOverwritesMatched,

      
      vme_addr               => vme_addr_i,
      vme_data               => vme_data_i,
      vme_en                 => vme_en_i,
      vme_wr                 => vme_wr_i,
      vme_data_out           => vme_data_out_i(6),
      vme_en_out             => vme_en_out_i(6),
      clk                    => clk,
      sinit                  => reset);
  

  -- Muon Merger
  MM: entity work.LFMuonMerger
    generic map (
      idx_merger            => logic_fpga_idx,
      muon_merger_lat_start => LF_LAT_MM_START)
    port map (
      iRPCGMTMuons          => sRPCGMTMuons,
      iDTCSCGMTMuons        => sDTCSCGMTMuons,
      
      iFineHaloDTCSC        => sFineHaloDTCSC,
      
      iRPCisMIP             => sRPCisMIP_reg,
      iDTCSCisMIP           => sDTCSCisMIP_reg,
      iRPCisISO             => sRPCisISO_reg,
      iDTCSCisISO           => sDTCSCisISO_reg,
      
      iPairMatrix           => PairMatrix_i,
      
      iSelectMatrix_phi     => sSelectMatrix_phi,
      iSelectMatrix_eta     => sSelectMatrix_eta,
      iSelectMatrix_pt      => sSelectMatrix_pt,
      iSelectMatrix_charge  => sSelectMatrix_charge,
      iSelectMatrix_MIP     => sSelectMatrix_MIP,
      iSelectMatrix_ISO     => sSelectMatrix_ISO,

      iSpecialBit_eta       => sSpecialBit_eta,
      iSpecialBit_pt        => sSpecialBit_pt,
      iSpecialBit_charge    => sSpecialBit_charge,
      iSpecialBit_MIP       => sSpecialBit_MIP,
      iSpecialBit_ISO       => sSpecialBit_ISO,
      
      iSpecialMIPMergeUseAND => sSpecialMIPMergeUseAND,                      
      iSpecialISOMergeUseAND => sSpecialISOMergeUseAND,
      iHaloOverwritesMatched => sHaloOverwritesMatched,

      oMergedGMTMuons       => sMergedGMTMuons,
      oIdxBits              => sIdxBitsMerged,
      
      vme_addr              => vme_addr_i,
      vme_data              => vme_data_i,
      vme_en                => vme_en_i,
      vme_wr                => vme_wr_i,
      vme_data_out          => vme_data_out_i(5),
      vme_en_out            => vme_en_out_i(5),
      
      clk                   => clk,
      sinit                 => reset);
  
  -- register RPC sort ranks
  reg_rank1: process (clk) is
  begin  
    if clk'event and clk = calc_lf_edge(LF_LAT_SRM_START + LF_RLAT_SRM_DONE) then  
      sSortRanksRPC_d <= sSortRanksRPC;
    end if;
  end process reg_rank1;

  delays: process(clk)
  begin
    if clk'event and clk = '0' then

      cancel_RPC_COU2_d   <= cancel_RPC_COU2;
      cancel_DTCSC_COU1_d <= cancel_DTCSC_COU1;

      RPC_is_matched_d <= RPC_is_matched;
      RPC_is_matched_d1 <= RPC_is_matched_d;
      
      sRPCGMTMuons_d <= sRPCGMTMuons;      
      sRPCGMTMuons_d1 <= sRPCGMTMuons_d;
      -- add MIP/ISO bits
      for i in 0 to 3 loop
        sRPCGMTMuons_d1(i).mip <= sRPCisMIP_reg(i);
        sRPCGMTMuons_d1(i).isol <= sRPCisISO_reg(i);
      end loop;  -- i
      
    end if;
  end process delays;

  -- register at falling edge
  delay_empty: process(clk)
  begin
    if clk'event and clk = '0' then
      empty1_d1 <= empty1;
      empty2_d1 <= empty2;
      empty1_d2 <= empty1_d1 or sDisableDTCSC;
      empty2_d2 <= empty2_d1 or sDisableRPC;
      empty1_d3 <= empty1_d2;
      empty2_d3 <= empty2_d2;
      empty1_d4 <= empty1_d3;
      empty2_d4 <= empty2_d3;
    end if;
  end process delay_empty;

  delay_sorter_input: process(clk)
  begin
    if clk'event and clk = '0' then
      sMergedGMTMuons_d <= sMergedGMTMuons;
      sIdxBitsMerged_d <= sIdxBitsMerged;
    end if;
  end process delay_sorter_input;

  

  sorter: entity work.LFSortStage1
    generic map (
      sorter_lat_start => LF_LAT_SORT_START)
    port map (
      iSortRanksOther => sSortRanksMerged,
      iSortRanksRPC   => sSortRanksRPC_d,
      
      iEmptyOther     => empty1_d4,
      iEmptyRPC       => empty2_d4,
      
      iCancelOther_A  => cancel_DTCSC_COU1_d,  -- from my COU1
      iCancelRPC_A    => cancel_RPC_COU2_d,    -- from my COU2
      
      iCancelOther_B  => sCancelDTCSC_reg,  -- from other chip
      iCancelRPC_B    => RPC_is_matched_d1,    -- because is matched

      iMuonsOther     => sMergedGMTMuons_d,
      iMuonsRPC       => sRPCGMTMuons_d1,

      iIdxBitsOther   => sIdxBitsMerged_d,
      
      oMuons          => sGMTMuons,
      oSortRanks      => oSortRanks,
      oIdxBits        => oIdxBits,
      oIsRPCMu        => oIsRPCMu,
      
      clk             => clk,
      sinit           => reset);
  
  -- Assign outputs to SorterChip
  -- Rev 1.19 30nov2005: In LFB chip send bad bit 56 also to bit 104
      ass_outmuons: process(sGMTMuons)
      begin
        sOutMuons <= GMTMu_vec_to_flat(sGMTMuons);   -- assign result of SortStage1 to intermediate signals
	
	for i in 0 to 103 loop	            -- connect all muon bits but not the spare bit
	   oOutMuons(i)   <= sOutMuons(i);
	end loop;
	
        if (logic_fpga_idx =0) then                
	   oOutMuons(104) <= sOutMuons(56); -- LFB chip: connect bad bit56 to spare bit
	else 
	   oOutMuons(104) <= '0';           -- LFF chip: assign '0' to spare bit
	end if; 
      end process ass_outmuons;
      
    -- Original Version for good bit 56 instead of process ass_outmuons.
    -- oOutMuons <= GMTMu_vec_to_flat(sGMTMuons);    

  -----------------------------------------------------------------------------
  -- Chip ID and Revision
  -- Rev 1.18 24nov05: chipRev=feed abe1
  -- Rev 1.19 30nov05: chipRev=feed 0001
  -----------------------------------------------------------------------------

  ChipID: entity work.ChipIDRegisters
    generic map (
      idregisters_vme_base_address => LF_chip_id0_raddr,

      chipID_h  => chip_id_h(logic_fpga_idx),  chipID_l  => chip_id_l(logic_fpga_idx),
      chipRev_h => 16#feed#,                   chipRev_l => 16#0001#,
      date_string => date_string)

    port map (
      vme_addr     => vme_addr_i,
      vme_en       => vme_en_i,
      vme_wr       => vme_wr_i,
      vme_data_out => vme_data_out_i(8),
      vme_en_out   => vme_en_out_i(8),
      vme_clk      => clk,
      reset        => reset);

  -----------------------------------------------------------------------------
  -- Dummy signals
  -----------------------------------------------------------------------------
  -- need to do this in order to persuade synplify/xilinx
  -- not to put the finehalo and charge into shift regs
  -- otherwise the delays are realised using a shift reg
  -- and no input ff is used
  register_dummy: process (clk, reset) is
  begin  -- process register_dummy
    if clk'event and clk = '1' then  -- rising clock edge
      sDummy(0) <=
        sRPCmuons_reg(0).finehalo or
        sRPCmuons_reg(1).finehalo or
        sRPCmuons_reg(2).finehalo or
        sRPCmuons_reg(3).finehalo or 
        sRPCmuons_reg(0).charge or
        sRPCmuons_reg(1).charge or
        sRPCmuons_reg(2).charge or
        sRPCmuons_reg(3).charge or
        sRPCmuons_reg(0).ch_valid or
        sRPCmuons_reg(1).ch_valid or
        sRPCmuons_reg(2).ch_valid or
        sRPCmuons_reg(3).ch_valid or
        sDTCSCmuons_reg(0).finehalo or
        sDTCSCmuons_reg(1).finehalo or
        sDTCSCmuons_reg(2).finehalo or
        sDTCSCmuons_reg(3).finehalo or 
        sDTCSCmuons_reg(0).charge or
        sDTCSCmuons_reg(1).charge or
        sDTCSCmuons_reg(2).charge or
        sDTCSCmuons_reg(3).charge or
        sDTCSCmuons_reg(0).ch_valid or
        sDTCSCmuons_reg(1).ch_valid or
        sDTCSCmuons_reg(2).ch_valid or
        sDTCSCmuons_reg(3).ch_valid or
--        sRPCMuons100_reg or sDTCSCMuons100_reg or spare_reg or dummy_reg or  -- before 24 Nov2005
        iRPCmuons_reg(100) or sDTCSCMuons100_reg or spare_reg or dummy_reg or
        clk_fb_reg;      
    end if;
  end process register_dummy;
  
  sDummy(15 downto 1) <= (others => '0');
  -----------------------------------------------------------------------------
  --* Dummy register
  -----------------------------------------------------------------------------
  dummy_register: entity work.VMEStatusReg
    generic map (
      my_vme_base_address => LF_dummy_raddr)
    port map (
      data         => sDummy,
      vme_addr     => vme_addr_i,
      vme_en       => vme_en_i,
      vme_wr       => vme_wr_i,
      vme_data_out => vme_data_out_i(9),
      vme_en_out   => vme_en_out_i(9),
      vme_clk      => clk,
      reset        => reset);

  -------------------------------------------------------------------------------
  -- multiplex VME outputs
  ------------------------------------------------------------------------------- 
  mux_vme(vme_data_out_i, vme_en_out_i, vme_data_out_muxed, vme_en_out_muxed);

  -------------------------------------------------------------------------------
  -- register outputs
  -------------------------------------------------------------------------------


  -- isMatched output
  register_ismatched: process (clk) is
  begin
    if (clk'event and clk = calc_lf_edge(LF_LAT_OUT_MYDTCSCISMATCHED) ) then
      oDTCSCisMatched <= DTCSC_is_matched_nr;
    end if;      
  end process register_ismatched;

-- synthesis translate_off
  -- pair matrix test output
  register_pm: process (clk) is
  begin
    if (clk'event and clk = calc_lf_edge(LF_LAT_OUT_PM_DEBUG) ) then
      oPairMatrix     <= PairMatrix_i;
    end if;      
  end process register_pm;
-- synthesis translate_on
  

  -- COU output
  register_cououtputs: process (clk) is
  begin 
    if (clk'event and clk = calc_lf_edge(LF_LAT_OUT_CANCELOTHERDTCSC) ) then
      oCancelOtherDTCSC <= cancel_OtherDTCSC_COU2_nr;
    end if;
  end process register_cououtputs;

-- synthesis translate_off

-- COU output
  register_coudebug: process (clk) is
--                                       variable LO : line;
  begin 
    if (clk'event and clk = calc_lf_edge(LF_LAT_OUT_COU_DEBUG) ) then
      oPairMatrix1    <= PairMatrix_i1;
      oPairMatrix2    <= PairMatrix_i2;

      oCancelBits1(0 to 3) <= cancel_DTCSC_COU1;
      oCancelBits1(4 to 7) <= cancel_dummy_COU1;
      oCancelBits2(0 to 3) <= cancel_RPC_COU2;
      oCancelBits2(4 to 7) <= cancel_OtherDTCSC_COU2_nr;
    end if;
  end process register_coudebug;

-- synthesis translate_on
  
  -----------------------------------------------------------------------------
  -- VME Logic
  -----------------------------------------------------------------------------

  vme_logic: entity work.InChipVMELogic
    port map (
      vme_addr     => vme_addr,
      vme_data     => vme_data,
      vme_en       => vme_en,
      vme_wr       => vme_wr,
      vme_ndtack   => vme_ndtack,
      vme_nirq     => vme_nirq,
      
      vme_addr_i   => vme_addr_i,
      vme_data_i   => vme_data_i,
      vme_en_i     => vme_en_i,
      vme_wr_i     => vme_wr_i,
      
      vme_data_out => vme_data_out_muxed,
      vme_en_out   => vme_en_out_muxed,
      
      clk          => clk,
      reset        => reset);
  
  
  -------------------------------------------------------------------------------
  -- Digital Clock Management & Chip Startup
  -------------------------------------------------------------------------------
  startup_dcm: entity work.StartupDCMVirtex2
    port map (
      iResetToGSR    => reset_input,
      iTristateToGTS => inactive,
      
      oResetNet      => reset,
      
      iClkFromPAD    => clk_input,
      oClkNet        => clk,
      iResetDCM      => reset_dcm,
      oDCMLocked     => dcm_locked);

  -- output clock on two pins
  clk_out <= clk;
  clk_test <= clk;


  status <= "00";

  
  
--  test <= "1111";

  -- muons are already registerd in sorter
  register_outputs: process (clk) is
  begin 
    if (clk'event and clk = '1' ) then
      test(0) <= vme_addr_i(9);
      test(1) <= vme_addr_i(10);
      test(2) <= vme_addr_i(11);
      test(3) <= vme_en_i;
    end if;
  end process register_outputs;
  
end architecture behavioral;