--------------------------------------------------------------------------------
-- Title   : Top - LINAC synchronized interlock function
-- Project : TimEX3
--------------------------------------------------------------------------------
-- Description : Top sheet of the LINAC synchro interlock block
--    After a delay from the pre-charge event, the interlock signal is freezed
--    in its current state to avoid to truncate the injection trigger pulse.
--    The interlock is again monitored after the injection window.
--
--      pre-charge              injection               extraction
--         ___                     ___                     ___
--    ____|   |___________________|   |___________________|   |_________________
--        :
--    ==========================XXXXXXXXXXXX====================================
--        :<------------------->:<-------->:<-----------------------------------
--        : t start             : t freeze : wait next pre-charge
--        : interlock monitored : freezede : interlock monitored
--
--
--                                LPM
--                                ___
--    ___________________________|   |__________________________________________
--    -------------------------->:
--         0.131841163386 s      :
--                               :                    SPM
--                               :                    ___
--    _______________________________________________|   |______________________
--                               :<----------------->:
--                               :     82.295 µs     :
--                               :                   :
--    =========================XXXXXXXXXXXXXXXXXXXXXXXXXXXX=====================
--    ------------------------>:<------------------------>:
--              t start        :         t freeze         :
--         0.131821633861 s    :         120 µs           :
--
--     Local LPM delay = 5459333 steps = 0.0310016 s ; event = 2
--     Local SPM delay = 5473825 steps = 0.0310839 s ; event = 2
--     Local PRE delay = 0 steps ; event = 1
--     CENTRAL inj delay = 193019 steps = 0.10084 s
--     CENTRAL pre delay = 0 steps
--
--     p_linacSYNCLOCK_inTTL(0) = pre-charge event
--     p_linacSYNCLOCK_inTTL(1) = interlock signal
--------------------------------------------------------------------------------
-- File     : linacSYNCLOCK_top.vhdl
-- Revision : x.x.x
-- Created  : November 28, 2014
-- Updated  : December 15, 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 linacSYNCLOCK_top is
  port (
    p_linacSYNCLOCK_inTTL    : in  std_logic_vector (1 downto 0); -- TTL inputs
    p_linacSYNCLOCK_outTTL   : out std_logic_vector (4 downto 0); -- TTL outputs
    p_linacSYNCLOCK_outPECL  : out std_logic_vector (4 downto 0); -- LVPECL outputs
    p_linacSYNCLOCK_clk60MHz : in  std_logic;
    p_linacSYNCLOCK_reset    : in  std_logic;
    p_linacSYNCLOCK_state    : out std_logic; -- interlock state ; 1 = interlock ON
    p_linacSYNCLOCK_led      : out std_logic_vector (1 downto 0)
  );
end entity linacSYNCLOCK_top;

--------------------------------------------------------------------------------
------------------------------- ARCHITECTURE -----------------------------------
--------------------------------------------------------------------------------
architecture rtl_linacSYNCLOCK_top of linacSYNCLOCK_top is

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

  ------------------------------------------------------------------------------
  -- signal
  ------------------------------------------------------------------------------
  signal s_holdPrecharge : std_logic_vector (2 downto 0);
  signal s_holdInterlock : std_logic_vector (2 downto 0);
  signal s_linacSYNCLOCK_synchro_interlock : std_logic;

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

  -- Synchronization of the external async signals with the 60MHz clock
  process (p_linacSYNCLOCK_clk60MHz, p_linacSYNCLOCK_reset)
  begin
    if (p_linacSYNCLOCK_reset = '1') then
      s_holdPrecharge <= (OTHERS => '0');
      s_holdInterlock <= (OTHERS => '0');
    elsif (rising_edge(p_linacSYNCLOCK_clk60MHz)) then
      s_holdPrecharge(0) <= p_linacSYNCLOCK_inTTL(1);  -- pre-charge signal
      s_holdPrecharge(1) <= s_holdPrecharge(0);
      s_holdPrecharge(2) <= s_holdPrecharge(1);
      s_holdInterlock(0) <= p_linacSYNCLOCK_inTTL(0);  -- interlock signal
      s_holdInterlock(1) <= s_holdInterlock(0);
      s_holdInterlock(2) <= s_holdInterlock(1);
    end if;
  end process;

    -- Synchronize the interlock signal to the injection / extraction cycles
    synchroInterlock : entity work.linacSYNCLOCK_synchroInterlock (rtl_linacSYNCLOCK_synchroInterlock)
      port map (
        p_reset            => p_linacSYNCLOCK_reset,
        p_clk60MHz         => p_linacSYNCLOCK_clk60MHz,
        p_precharge        => s_holdPrecharge(2),               -- pre-charge event
        p_interlock        => s_holdInterlock(2),               -- interlock signal
        p_synchroInterlock => s_linacSYNCLOCK_synchro_interlock -- synchronized interlock signal
                                                                -- 0 = inhibited
      );

  -- Push the state of the interlock in the register
  process (p_linacSYNCLOCK_clk60MHz, p_linacSYNCLOCK_reset)
  begin
    if (p_linacSYNCLOCK_reset = '1') then
      p_linacSYNCLOCK_state <= '0';
    elsif (falling_edge(p_linacSYNCLOCK_clk60MHz)) then
      p_linacSYNCLOCK_state <= not s_linacSYNCLOCK_synchro_interlock;
    end if;
  end process;

  ------------------------------------------------------------------------------
  ------------------------------------------------------------------------------
  p_linacSYNCLOCK_outTTL  (0) <= '0'; -- not used ; is configured as input
  p_linacSYNCLOCK_outTTL  (1) <= '0'; -- not used ; is configured as input
  p_linacSYNCLOCK_outTTL  (2) <= s_linacSYNCLOCK_synchro_interlock; -- synchronized interlock signal
  p_linacSYNCLOCK_outTTL  (3) <= p_linacSYNCLOCK_inTTL(1); -- pre charge event
  p_linacSYNCLOCK_outTTL  (4) <= '1'; -- forced to 1 for test purpose
  p_linacSYNCLOCK_outPECL (4 downto 0) <= "00000";

  p_linacSYNCLOCK_led(0) <= not s_linacSYNCLOCK_synchro_interlock; -- red LED is on if interlocked
  p_linacSYNCLOCK_led(1) <= '1';   -- green LED ON

end architecture rtl_linacSYNCLOCK_top;
