--******************************************************************************
--* @short      Phi projection unit. Projects phi from muon system to vertex
--******************************************************************************
--* @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 IEEE.Numeric_Std.all;
use WORK.GMTTypes.all;
use WORK.LFTypes.all;
use work.LFVMEAddrMap.all;
use work.LFTiming.all;
use work.VMEMux.all;
--use STD.TEXTIO.all;

entity LFPhiProUnit is
  
  generic (
    phipro_unit_idx       : integer := 0;   -- 0: DT 1:bRPC 2:CSC 3:FRPC
    idx_mu                : integer := 0;              -- muon index 0 to 3
    phipro_unit_lat_start : integer := 0);  -- start latency

  port (
    -- INPUTS
    iPhi           : in std_logic_vector(7 downto 0);
    iEta           : in std_logic_vector(5 downto 0);
    iPt            : in std_logic_vector(4 downto 0);
    iCharge        : in std_logic;

    oPhi           : out std_logic_vector(7 downto 0);
    -- 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 LFPhiProUnit;

architecture behavioral of LFPhiProUnit is

  signal sEta4 : std_logic_vector(3 downto 0);
  signal sDPhi : std_logic_vector(8 downto 0);

  signal sCharge : std_logic_vector(0 downto 0);

  signal newphi  : signed(8 downto 0);
  signal newphi1 : signed(8 downto 0);
  signal newphi2 : signed(8 downto 0);

  signal newphi_out : signed(8 downto 0);

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

begin  -- architecture behavioral

  -- convert eta to 4 bits, first
  phiproetaconv: entity work.lfphiproetaconvlut
    generic map (
      instance_idx        => phipro_unit_idx,
      my_vme_base_address => LF_PhiProEtaConvLUT_base(phipro_unit_idx mod 2) + LF_PhiProEtaConvLUT_size * idx_mu)
    port map (
      eta_in       => iEta,
      eta_out      => sEta4,
      
      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);

  sCharge(0) <= iCharge;
  -- project (look up delta-phi)
  phipro: entity work.lfphiprolut
    generic map (
      instance_idx        => phipro_unit_idx,
      my_vme_base_address => LF_PhiProLUT_base(phipro_unit_idx mod 2) + LF_PhiProLUT_size * idx_mu,
      edge                => calc_lf_edge(phipro_unit_lat_start + LF_RLAT_PHIPRO_LUT) )
    port map (
      eta          => sEta4,
      pt           => iPt,
      charge       => sCharge,
      dphi         => sDPhi,
      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);

  -- calculate delta phi mod 144
  newphi  <= SIGNED(resize( UNSIGNED(iPhi), 9)) +SIGNED(sDPhi);
  newphi1 <= SIGNED(resize( UNSIGNED(iPhi), 9)) +SIGNED(sDPhi) - TO_SIGNED(144,9);
  newphi2 <= SIGNED(resize( UNSIGNED(iPhi), 9)) +SIGNED(sDPhi) + TO_SIGNED(144,9);

  newphi_out <= newphi1 when (newphi>TO_SIGNED(143,9)) else
               newphi2 when (newphi<TO_SIGNED(0,9)) else
               newphi;

  oPhi <= std_logic_vector( resize (UNSIGNED(newphi_out), 8) );
  
--  assert not (newphi_out(8) = '1' and iPt /= "00000") report "error in phipro unit: newphi is negative ! - check the code and/or LUT contents" severity failure;
  
  -- multiplex vme_data_output
  mux_vme(vme_data_out_i, vme_en_out_i, vme_data_out, vme_en_out);
end architecture behavioral;