--******************************************************************************
--* @short   Phase monitor: monitors at what phase the input changes for all 4 muons
--*          
--*
--*          The Input are 5 samples of an input bit of each muon sampled at 6.25 ns intervals.
--*          The monitor counts the signal changes of each of the first four samples
--*          with respect to the following (earlier in time) sample over the
--*          period of an orbit.
--*
--*          If any signal change occurs at a certain position, a bit in the
--*          Phase Monitor Status Register is set. These bits are cleared upon
--*          VME-read of the status register.
--*
--*          Signal changes are also counter over the period of a orbit.
--*          At every bunch counter reset, the counter states are shifted to registers
--*          for readout and the counters are cleared.
--*
--******************************************************************************
--* @author  SAKULIN Hannes  <hsakulin@dsy-srv2.cern.ch>
--* @version $Revision: 1.1 $
--* @date    $Date: 2005/01/10 16:30:16 $x
--******************************************************************************
--/
library IEEE;
use IEEE.Std_logic_1164.all;
use IEEE.Numeric_Std.all;
use work.VMEMux.all;
use work.GMTTypes.all;
use work.IFVMEAddrMap.all;

entity PhaseMonitor is
  generic (
    status_register_address : integer := 0;
    counter_register_addresses : TBaseArray(0 to 3)); 

  port (
    -- data port
    sample0 : in TInMuons_vec(0 to 3);
    sample1 : in TInMuons_vec(0 to 3);
    sample2 : in TInMuons_vec(0 to 3);
    sample3 : in TInMuons_vec(0 to 3);
    sample4 : in TInMuons_vec(0 to 3);
    
    bc_reset     : in    std_logic;

    -- VME port
    vme_addr     : in    std_logic_vector;  -- leave unconstrained 
    vme_en       : in    std_logic;
    vme_wr       : in    std_logic;
    vme_data_out : out   std_logic_vector;                                    
    vme_en_out   : out   std_logic;

    
    clk          : in    std_logic;
    reset        : in    std_logic);

end PhaseMonitor;


-------------------------------------------------------------------------------
-- Implementation
-------------------------------------------------------------------------------

architecture behavioral of PhaseMonitor is

  signal value_change_at_phase0 : std_logic_vector(0 to 3);
  signal value_change_at_phase1 : std_logic_vector(0 to 3);
  signal value_change_at_phase2 : std_logic_vector(0 to 3);
  signal value_change_at_phase3 : std_logic_vector(0 to 3);
  
  
begin  -- behavioral

  -----------------------------------------------------------------------------
  --* generate the phase change bits
  -----------------------------------------------------------------------------
  gen_value_change: process (clk, reset) is
  begin  -- process gen_value_change
    if reset = '1' then
      value_change_at_phase0 <= ( others => '0' );
      value_change_at_phase1 <= ( others => '0' );
      value_change_at_phase2 <= ( others => '0' );
      value_change_at_phase3 <= ( others => '0' );      
    elsif clk'event and clk = '1' then  -- rising clock edge
      for imu in 0 to 3 loop
        value_change_at_phase0(imu) <= (sample0(imu)(0) xor sample1(imu)(0));
        value_change_at_phase1(imu) <= (sample1(imu)(0) xor sample2(imu)(0));
        value_change_at_phase2(imu) <= (sample2(imu)(0) xor sample3(imu)(0));
        value_change_at_phase3(imu) <= (sample3(imu)(0) xor sample4(imu)(0));        
      end loop;  -- imu
    end if;
  end process gen_value_change;

  -----------------------------------------------------------------------------
  --* monitor the phase change bits with an error monitor
  -----------------------------------------------------------------------------
  error_monitor: entity work.ErrorMonitor4x4bit
    generic map (
      status_register_address    => status_register_address,
      counter_register_addresses => counter_register_addresses)
    port map (
      bit0         => value_change_at_phase0,
      bit1         => value_change_at_phase1,
      bit2         => value_change_at_phase2,
      bit3         => value_change_at_phase3,
      
      bc_reset     => bc_reset,
      
      vme_addr     => vme_addr,
      vme_en       => vme_en,
      vme_wr       => vme_wr,
      
      vme_data_out => vme_data_out,
      vme_en_out   => vme_en_out,
      
      clk          => clk,
      reset        => reset);
  
  
end behavioral;