--******************************************************************************
--* @short      Sort Rank Assignment Unit (for one muon)
--******************************************************************************
--* @author  SAKULIN Hannes  <hsakulin@dsy-srv3.cern.ch>
--* @date    $Date: 2005/01/31 15:17:30 $
--* @version $Revision: 1.4 $
--******************************************************************************
--/
library IEEE;
use IEEE.Std_logic_1164.all;
use WORK.GMTTypes.all;
use WORK.LFTypes.all;
use work.LFVMEAddrMap.all;
use work.LFTiming.all;
use work.VMEMux.all;

entity LFRankAssUnit is
  
  generic (
    rank_ass_unit_idx : integer := 0;   -- 0: DT BRPC CSC FRPC
    idxmuon           : integer := 0;   -- muon index
    rank_ass_unit_lat_start : integer := 0); 

  port (
    iMuon       : in TSyncedMu;
    
    oSortRank   : out TSortRank;
    oVLQ        : out std_logic_vector(1 downto 0);        -- Very Low Quality
    oDisableHot : out std_logic;        -- Disable a Hot Region (goes to Matcher)

    -- 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 LFRankAssUnit;

architecture behavioral of LFRankAssUnit is

  signal rank_etaq   : std_logic_vector(1 downto 0);
  signal rank_ptq    : std_logic_vector(6 downto 0);
  signal rank_etaphi : std_logic_vector(1 downto 0);

  signal sVLQ        : std_logic_vector(1 downto 0);        -- Very Low Quality

  signal vme_data_out_i   : TVMEData_vec(0 to 3);
  signal vme_en_out_i     : TVMEEnable_vec(0 to 3);

begin  -- architecture behavioral

  EtaQLUT: entity work.lfsortranketaqlut
    generic map (
      instance_idx        => rank_ass_unit_idx,
      my_vme_base_address => LF_SortRankEtaQLUT_base(rank_ass_unit_idx mod 2) + idxmuon * LF_SortRankEtaQLUT_size,
      edge                => calc_lf_edge(rank_ass_unit_lat_start + LF_RLAT_SRU_LUT1))
    port map (
      eta          => iMuon.eta,
      q            => iMuon.qual,
      
      vlq          => sVLQ,
      rank_etaq    => rank_etaq,
      
      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_i(0),
      vme_en_out   => vme_en_out_i(0),
      vme_clk      => clk);
  
  -- Pt-q    LUT
  PtQLUT: entity work.lfsortrankptqlut
    generic map (
      instance_idx        => rank_ass_unit_idx,
      my_vme_base_address => LF_SortRankPtQLUT_base(rank_ass_unit_idx mod 2) + idxmuon * LF_SortRankPtQLUT_size,
      edge                => calc_lf_edge(rank_ass_unit_lat_start + LF_RLAT_SRU_LUT1))
    port map (
      q            => iMuon.qual,
      pt           => iMuon.pt,
      
      rank_ptq     => rank_ptq,
      
      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_i(1),
      vme_en_out   => vme_en_out_i(1),
      vme_clk      => clk);

  -- eta-phi LUT 
  EtaPhiLUT: entity work.lfsortranketaphilut
    generic map (
      instance_idx        => rank_ass_unit_idx,
      my_vme_base_address => LF_SortRankEtaPhiLUT_base(rank_ass_unit_idx mod 2) + idxmuon * LF_SortRankEtaPhiLUT_size,
      edge                => calc_lf_edge(rank_ass_unit_lat_start + LF_RLAT_SRU_LUT1))
    port map (
      eta          => iMuon.eta,
      phi          => iMuon.phi,
      
      rank_etaphi  => rank_etaphi,
      
      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_i(2),
      vme_en_out   => vme_en_out_i(2),
      vme_clk      => clk);

  oDisableHot <= '1' when rank_etaphi = "11" else '0';

  -- Combine LUT (on next half clock edge)
  RankCombineLUT: entity work.lfsortrankcombinelut
    generic map (
      instance_idx        => rank_ass_unit_idx,
      my_vme_base_address => LF_SortRankCombineLUT_base(rank_ass_unit_idx mod 2) + idxmuon * LF_SortRankCombineLUT_size,
      edge                => calc_lf_edge(rank_ass_unit_lat_start + LF_RLAT_SRU_LUT2))
    port map (
      rank_etaq    => rank_etaq,
      rank_ptq     => rank_ptq,
      rank_etaphi  => rank_etaphi,
      
      sort_rank    => oSortRank,
      
      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_i(3),
      vme_en_out   => vme_en_out_i(3),
      vme_clk      => clk);

  reg_vlq: process (clk) is
  begin
    if clk'event and clk = calc_lf_edge(rank_ass_unit_lat_start + LF_RLAT_SRU_LUT2) then
      oVLQ <= sVLQ;      
    end if;
  end process reg_vlq;
   

  
  -- multiplex vme_data_output
  mux_vme(vme_data_out_i, vme_en_out_i, vme_data_out, vme_en_out);
  
end architecture behavioral;