--------------------------------------------------------------------------------
-- Title   : Top - LINAC monitoring function
-- Project : TimEX3
--------------------------------------------------------------------------------
-- Description : Top sheet of the LINAC monotoring block
--    The SPM and the LPM pulses are monitored for simultaneous trigger and delay
--    between two triggers
--------------------------------------------------------------------------------
-- File     : linacMON_top.vhdl
-- Revision : x.x.x
-- Created  : July 09, 2013
-- Updated  : November 20, 2014
--------------------------------------------------------------------------------
-- Author       : Jean-Paul Ricaud
-- Organization : Synchrotron Soleil
-- Web          : http://www.synchrotron-soleil.fr
-- Email        : jean-paul.ricaud@synchrotron-soleil.fr
--------------------------------------------------------------------------------
-- Copyright (C) 2012 - 2014 Synchrotron Soleil
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU Lesser General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU Lesser General Public License for more details.
--
-- You should have received a copy of the Lesser GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>
--------------------------------------------------------------------------------
--
--------------------------------------------------------------------------------
-- Modifications :
--
--------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

--------------------------------------------------------------------------------
--------------------------------- ENTITY ---------------------------------------
--------------------------------------------------------------------------------
entity linacMON_top is
  port (
    p_linacMON_inTTL             : in  std_logic_vector (1 downto 0); -- TTL inputs
    p_linacMON_inInhibit         : in  std_logic; -- TTL input for outputs inhibition
    p_linacMON_outTTL            : out std_logic_vector (4 downto 0); -- TTL outputs
    p_linacMON_outPECL           : out std_logic_vector (4 downto 0); -- LVPECL outputs
    p_linacMON_clk1kHz           : in  std_logic;
    p_linacMON_clk500mHz         : in  std_logic;
    p_linacMON_clk60MHz          : in  std_logic;
    p_linacMON_missingSPMDelay   : in  std_logic_vector (31 downto 0);
    p_linacMON_missingLPMDelay   : in  std_logic_vector (31 downto 0);
    p_linacMON_csw               : in  std_logic_vector (2 downto 0);
    p_linacMON_reset             : in  std_logic;
    p_linacMON_SPMMon            : out std_logic_vector (31 downto 0); -- SPM monitor
    p_linacMON_LPMMon            : out std_logic_vector (31 downto 0); -- LPM monitor
    p_linacMON_simultaneousTrigg : out std_logic_vector (31 downto 0); -- number of simultaneous
                                                                       --  SPM / LPM triggers
    p_linacMON_delayError        : out std_logic_vector (1 downto 0);
    p_linacMON_led               : out std_logic_vector (1 downto 0)
  );
end entity linacMON_top;

--------------------------------------------------------------------------------
------------------------------- ARCHITECTURE -----------------------------------
--------------------------------------------------------------------------------
architecture rtl_linacMON_top of linacMON_top is

  ------------------------------------------------------------------------------
  -- constant
  ------------------------------------------------------------------------------

  ------------------------------------------------------------------------------
  -- signal
  ------------------------------------------------------------------------------
  signal s_simTrigg_error  : std_logic; -- simultaneaous SPM / LPM error
  signal s_SPM_LPM_outputs : std_logic_vector (1 downto 0);

  ------------------------------------------------------------------------------
  --------------------------------- Main ---------------------------------------
  ------------------------------------------------------------------------------
  begin

    -- SPM and LPM monitoring block
    -- The time betwwen 2 pulses is stored in stored in MONITOR registers (in ms)
    pulseMonitor : entity work.linacMON_monitoring (rtl_linacMON_monitoring)
      port map (
        p_inTTL      => p_linacMON_inTTL(1 downto 0), -- TTL inputs
        p_clk1kHz    => p_linacMON_clk1kHz,
        p_reset      => p_linacMON_reset,
        p_SPMmonitor => p_linacMON_SPMMon,  -- register with the time value between two SPM
        p_LPMmonitor => p_linacMON_LPMMon   -- register with the time value between two LPM
      );

    -- Monitor and count any simultaneous SPM and LPM trigg
    simultaneousTrig : entity work.linacMON_simTrigg (rtl_linacMON_simTrigg)
      port map (
        p_clk1kHz     => p_linacMON_clk1kHz,
        p_clk60MHz    => p_linacMON_clk60MHz,
        p_inTTL       => p_linacMON_inTTL(1 downto 0),  -- TTL inputs
        p_simTriggReg => p_linacMON_simultaneousTrigg,
        p_csw         => p_linacMON_csw(2),
        p_reset       => p_linacMON_reset,
        p_error       => s_simTrigg_error
      );

    -- Inhibit the output if the inhibition input is at low level
    inhibition : entity work.linacMON_inhibition (rtl_linacMON_inhibition)
      port map (
        p_reset       => p_linacMON_reset,
        p_clk60MHz    => p_linacMON_clk60MHz,
        p_inputs      => p_linacMON_inTTL(1 downto 0),  -- TTL inputs
        p_inhibition  => p_linacMON_inInhibit,
        p_outputs     => s_SPM_LPM_outputs(1 downto 0)
      );

    -- LEDs management for the monitoring function block
    -- The green LED is blinked for 5s after a reset or after a input pulse is
    -- détected. It remains ON in other cases.
    -- The red LED is off after a reset. It gos ON if a simultaneous SPM and
    -- LPM is detected.
    leds : entity work.linacMON_leds (rtl_linacMON_leds)
      port map (
        p_inTTL           => s_SPM_LPM_outputs(1 downto 0),  -- TTL input
        p_clk1kHz         => p_linacMON_clk1kHz,
        p_clk500mHz       => p_linacMON_clk500mHz,
        p_clk60MHz        => p_linacMON_clk60MHz,
        p_missingSPMDelay => p_linacMON_missingSPMDelay,
        p_missingLPMDelay => p_linacMON_missingLPMDelay,
        p_csw             => p_linacMON_csw(1 downto 0),
        p_reset           => p_linacMON_reset,
        p_simTriggError   => s_simTrigg_error,
        p_delayError      => p_linacMON_delayError,
        p_led             => p_linacMON_led
      );

  ------------------------------------------------------------------------------
  ------------------------------------------------------------------------------
  p_linacMON_outTTL  (0) <= '0'; -- not used ; is configured as input
  p_linacMON_outTTL  (1) <= '0'; -- not used ; is configured as input
  p_linacMON_outTTL  (2) <= s_SPM_LPM_outputs(0); -- SPM
  p_linacMON_outTTL  (3) <= s_SPM_LPM_outputs(1); -- LPM
  p_linacMON_outTTL  (4) <= '0'; -- not used ; is configured as input
  p_linacMON_outPECL (4 downto 0) <= "00000";

end architecture rtl_linacMON_top;
