--------------------------------------------------------------------------------
-- Title   : Top
-- Project : TimEX3
--------------------------------------------------------------------------------
-- Description : Top sheet
--------------------------------------------------------------------------------
-- File     : top.vhd
-- Revision : x.x.x
-- Created  : October 26, 2012
-- Updated  : December 01, 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 GNU Lesser General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>
--------------------------------------------------------------------------------
--
--------------------------------------------------------------------------------
-- Modifications :
--   Version 1.2.1 ; June 14, 2013 ; Jean-Paul Ricaud
--     * Added delay on duplicated outputs to compensate the outputs offsets
--   Version 1.4.0 ; July 09, 2013 ; Jean-Paul Ricaud
--     * Added LINAC monitoring function
--   Version 1.4.1 ; October 29, 2013 ; Jean-Paul Ricaud
--     * Added a bit in the status register for top-up gating window active
--     * Renamed some signals ; added comments
--     * Added a config read register (duplication, top-up, etc.)
--   Version 1.6.0 ; November 18, 2013 ; Jean-Paul Ricaud
--     * Multiplexed cPCI registers to overlap them depending on the
--       configuration (duplication, top-up, etc.)
--     * Duplication monitoring now reacts on rising edge of the signal instead
--       of level
--   Version 1.6.1 ; February 03, 2014 ; Jean-Paul Ricaud
--     * Added frequency divider block for slicing DG
--   Version 1.8.0 ; September 19, 2014 ; Jean-Paul Ricaud
--     * Added clock padding for CRISTAL beamline laser syncgrinization
--   Version 1.8.1 ; November 20, 2014 ; Jean-Paul Ricaud
--     * Added outputs inhibition capability to LINAC monitoring config
--   Version 1.9.0 ; November 28 2014 ; Jean-Paul Ricaud
--     * Changed the configuration switch of the clock padding from
--         0-0-0-1-0-1 to 0-0-0-1-1-0
--     * Added synchronized interlock of the LINAC's synchronization signals
--
--------------------------------------------------------------------------------

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

library unisim;
use unisim.vcomponents.all;

library work;
use work.type_lib.all;

--------------------------------------------------------------------------------
--------------------------------- ENTITY ---------------------------------------
--------------------------------------------------------------------------------
entity top is
  port (
    -- PLX bus
    pin_AD       : in    std_logic_vector (9 downto 2);  -- address bus
    pin_DATA     : inout std_logic_vector (31 downto 0); -- data bus
    pin_CSn      : in    std_logic_vector (1 downto 0);  -- chip select
    pin_BEn      : in    std_logic_vector (3 downto 0);  -- byte enable
    pin_BLASTn   : in    std_logic; -- burst last
    pin_LWRn     : in    std_logic; -- read/write ; = LW/R
    pin_RDn      : in    std_logic; -- read strobe
    pin_WRn      : in    std_logic; -- write strobe ; = WR
    pin_WAITOn   : in    std_logic; -- wait
    pin_ADSn     : in    std_logic; -- address strobe
    pin_ALE      : in    std_logic; -- address latch
    pin_CLK60MHz : in    std_logic; -- clock 60 MHz
    pin_READYn   : out   std_logic; -- ready
    pin_BTERMn   : out   std_logic; -- burst treminate
    pin_LINTI    : out   std_logic_vector (1 downto 0); -- interrupt
    pin_RESETn   : in    std_logic; -- reset input

    -- IO signals
    pin_inTTL    : in    std_logic_vector (4 downto 0); -- TTL inputs
    pin_outTTL   : out   std_logic_vector (4 downto 0); -- TTL outputs
    pin_outPECL  : out   std_logic_vector (4 downto 0); -- LVPECL outputs

    -- Other signals
    pin_RST_BRD  : out   std_logic; -- Board reset output
    pin_LED      : out   std_logic_vector (1 downto 0); -- LEDs ; 0 = red, 1 = green
    pin_EXTS     : out   std_logic_vector (7 downto 0); -- Test header
    pin_SW       : in    std_logic_vector (5 downto 0)  -- Configuration dip switch
  );
end entity top;

--------------------------------------------------------------------------------
------------------------------- ARCHITECTURE -----------------------------------
--------------------------------------------------------------------------------
architecture rtl_top of top is
  ------------------------------------------------------------------------------
  -- constant
  ------------------------------------------------------------------------------

  ------------------------------------------------------------------------------
  -- signal
  ------------------------------------------------------------------------------
  -- Registers
  signal s_cmdReg     : std_logic_vector (31 downto 0); -- command register
  signal s_SW         : std_logic_vector (31 downto 0); -- configuration rgister (duplication, top-up ...)
  signal s_status     : std_logic_vector (29 downto 0); -- bit 31 & 30 are reserved for access error
  signal s_dupMissingPulseDelay     : std_logic_vector (31 downto 0); -- maximum delay before a missing
                                                                      -- synchro pulse is signaled
  signal s_dupPulseMon              : std_logic_vector (31 downto 0); -- time between 2 pulses
  signal s_beamLostHoldOff          : std_logic_vector (31 downto 0); -- maximum delay before a missing
                                                                      -- beam is signaled
  signal s_beamLostHoldOn           : std_logic_vector (31 downto 0); -- maximum delay before after a missing
                                                                      -- beam a re-injection is signaled
  signal s_topUpGateHoldOff         : std_logic_vector (31 downto 0); -- delay before a gating signal is
                                                                      -- triggered after the pre top-up
                                                                      -- signal is received
  signal s_topUpGateWidth           : std_logic_vector (31 downto 0); -- width of the gating windows
  signal s_linacMPMissingPulseDelay : std_logic_vector (31 downto 0); -- maximum delay before a missing
  signal s_linacMPPulseMon          : std_logic_vector (31 downto 0); -- time between 2 pulses
  signal s_linacMONSPMMon           : std_logic_vector (31 downto 0);
  signal s_linacMONMissingSPMDelay  : std_logic_vector (31 downto 0);
  signal s_linacMONLPMMon           : std_logic_vector (31 downto 0);
  signal s_linacMONMissingLPMDelay  : std_logic_vector (31 downto 0);
  signal s_linacMONsimTrigg         : std_logic_vector (31 downto 0);
  signal s_linacMONsimTriggRST      : std_logic_vector (31 downto 0);
  signal s_freqDivMissingPulseDelay : std_logic_vector (31 downto 0); -- maximum delay before a missing
                                                                      -- CLK_SR pulse is signaled
  signal s_freqDivPulseMon          : std_logic_vector (31 downto 0); -- time between 2 CLK_SR pulses

  signal s_wRegister      : register_array;
  signal s_wRegister_init : register_array;

  signal s_rRegister      : register_array;

  signal s_wRegister_foo0  : std_logic_vector (31 downto 0);
  signal s_wRegister_foo6  : std_logic_vector (31 downto 0);
  signal s_wRegister_foo8  : std_logic_vector (31 downto 0);
  signal s_wRegister_foo10 : std_logic_vector (31 downto 0);
  signal s_wRegister_foo12 : std_logic_vector (31 downto 0);
  signal s_wRegister_foo14 : std_logic_vector (31 downto 0);

  signal s_csw       : std_logic_vector (20 downto 0); -- chip select of internal write transfert
  signal s_csr       : std_logic_vector (20 downto 0); -- chip select of internal read transfert
  signal s_mux_csw   : std_logic_vector (15 downto 0);
  signal s_mux_csr   : std_logic_vector (15 downto 0);
  signal s_clk60MHz  : std_logic; -- 60 MHz clock
  signal s_clk1kHz   : std_logic; -- 1 kHz clock
  signal s_clk500mhz : std_logic; -- 0.5 Hz clock
  signal s_reset     : std_logic;

  -- Duplication signals
  signal s_dupOutTTL  : std_logic_vector (4 downto 0);
  signal s_dupOutPECL : std_logic_vector (4 downto 0);
  signal s_dupLED     : std_logic_vector (1 downto 0);

  -- Topup signals
  signal s_topUpOutTTL       : std_logic_vector (4 downto 0);
  signal s_topUpOutPECL      : std_logic_vector (4 downto 0);
  signal s_topUpLED          : std_logic_vector (1 downto 0);
  signal s_topUpTopUpGate    : std_logic_vector (1 downto 0);
  signal s_topUpBeamLostGate : std_logic_vector (1 downto 0);

  -- LINAC multipulse signals
  signal s_linacMPOutTTL  : std_logic_vector (4 downto 0);
  signal s_linacMPOutPECL : std_logic_vector (4 downto 0);
  signal s_linacMPLED     : std_logic_vector (1 downto 0);

  -- LINAC monitoring signals
  signal s_linacMONOutTTL     : std_logic_vector (4 downto 0);
  signal s_linacMONOutPECL    : std_logic_vector (4 downto 0);
  signal s_linacMONLED        : std_logic_vector (1 downto 0);
  signal s_linacMONdelayError : std_logic_vector (1 downto 0);

  -- Frequency divider signals
  signal s_freqDivOutTTL  : std_logic_vector (4 downto 0);
  signal s_freqDivOutPECL : std_logic_vector (4 downto 0);
  signal s_freqDivLED     : std_logic_vector (1 downto 0);

  -- LINAC synchronized interlock block
  signal s_linacSYNCLOCKOutTTL  : std_logic_vector (4 downto 0);
  signal s_linacSYNCLOCKOutPECL : std_logic_vector (4 downto 0);
  signal s_linacSYNCLOCKstate   : std_logic;
  signal s_linacSYNCLOCKLED     : std_logic_vector (1 downto 0);

  -- Clock padding signals
  signal s_clkPaddingOutTTL  : std_logic_vector (4 downto 0);
  signal s_clkPaddingOutPECL : std_logic_vector (4 downto 0);
  signal s_clkPaddingLED     : std_logic_vector (1 downto 0);

  -- Test signals
  signal s_testOutTTL  : std_logic_vector (4 downto 0);
  signal s_testOutPECL : std_logic_vector (4 downto 0);
  signal s_testLED     : std_logic_vector (1 downto 0);

  ------------------------------------------------------------------------------
  -- Attributes
  ------------------------------------------------------------------------------
  attribute PERIOD : string;
  attribute PERIOD of s_clk60MHz : signal is "16 ns";

  attribute BUFFER_TYPE : string;
  attribute BUFFER_TYPE of s_clk60MHz : signal is "BUFG";

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

  -- IBUFG: Global Clock Buffer (sourced by an external pin)
  --        Spartan-6
  -- Xilinx HDL Language Template, version 13.2
  IBUFG_inst : IBUFG
    generic map (
      IBUF_LOW_PWR => FALSE, -- Low power (TRUE) vs. performance (FALSE) setting for referenced I/O standards
      IOSTANDARD => "LVTTL")
    port map (
      O => s_clk60MHz,   -- Clock buffer output
      I => pin_CLK60MHz  -- Clock buffer input (connect directly to top-level port)
    );
  -- End of IBUFG_inst instantiation

  ------------------------------------------------------------------------------
  ------------------------------------------------------------------------------
  -- Reset block
  reset : entity work.reset (rtl_reset)
    port map (
      -- Internal bus
      p_ext_RESETn => pin_RESETn,   -- board reset in
      p_clk60MHz   => s_clk60MHz,   -- clock 60 MHz
      p_cmd_REG0   => s_cmdReg(0),  -- command register bit 0
      p_CSW        => s_csw(0),     -- chip select of internal write transfert
      -- Other signals
      p_fpga_RST   => s_reset,      -- reset out
      p_board_RST  => pin_RST_BRD   -- board reset out
    );

  -- Clock generator
  clk_gen : entity work.clk_sources (rtl_clk_sources)
    port map (
      p_clk60MHz  => s_clk60mHz,  -- clock 60 MHz
      p_reset     => s_reset,     -- reset in
      p_clk1kHz   => s_clk1kHz,   -- clock 1 KHz
      p_clk500mHz => s_clk500mhz  -- clock 0.5 Hz
    );

  -- cPCI interface
  cPCI_interface : entity work.cPCI_hermes (rtl_cPCI_hermes)
    port map (
      -- PLX bus
      p_AD          => pin_AD,        -- adress bus
      p_DATA        => pin_DATA,      -- data bus
      p_CSn         => pin_CSn,       -- chip select
      p_BEn         => pin_BEn,       -- byte enable
      p_BLASTn      => pin_BLASTn,    -- burst last
      p_LWRn        => pin_LWRn,      -- read/write
      p_RDn         => pin_RDn,       -- read strobe
      p_WRn         => pin_WRn,       -- write strobe
      p_WAITOn      => pin_WAITOn,    -- wait
      p_ADSn        => pin_ADSn,      -- address strobe
      p_ALE         => pin_ALE,       -- address latch
      p_CLK60MHz    => s_clk60MHz,    -- clock 60 MHz
      p_READYn      => pin_READYn,    -- ready
      p_BTERMn      => pin_BTERMn,    -- burst treminate
      p_LINTI       => pin_LINTI,     -- interrupt

      -- Write registers
      p_config_reg  => s_SW,          -- config register
      p_status_reg  => s_status,      -- status register ; bit 31 & 30 are reserved for access error
      p_cmdREG      => s_cmdReg,      -- command register
      p_wRegister   => s_wRegister,
      p_wRegister_init => s_wRegister_init, -- write registers init values

      -- Read registers
      p_rRegister => s_rRegister,

      -- Internal bus
      p_CSW         => s_mux_csw, -- chip select of internal write transfert
      p_CSR         => s_mux_csr, -- chip select of internal read transfert
      -- Other signals
      p_reset       => s_reset -- reset
    );

  -- cPCI register multiplexer
  -- 0  : 0x00 : board ID (R) => in Hermes module
  -- 1  : 0x04 : firmware version (R) => in Hermes module
  -- 2  : 0x08 : test register (R/W)  => in Hermes module
  -- 3  : 0x0C : config register (R)
  -- 4  : 0x10 : status register (R/W)
  -- 5  : 0x14 : command register (R/W)
  -- *** Duplication ***
  -- 6  : 0x18 : time between two synchronization pulses (R) [duplication mode]
  -- 7  : 0x1C : maximum delay before a missing synchro pulse is signaled (R/W) [duplication mode]
  -- *** Top-up ***
  -- 8  : 0x18 : beam lost hold off time (R/W) [top-up]
  -- 9  : 0x1C : beam lost hold on time (R/W) [top-up mode]
  -- 10 : 0x20 : gating hold off time (R/W) [top-up mode]
  -- 11 : 0x24 : gating window time (R/W) [top-up mode]
  -- *** LINAC multipulse ***
  -- 12 : 0x18 : time between two synchronization pulses (R) [LINAC multipulse mode]
  -- 13 : 0x1C : maximum delay before a missing synchro pulse is signaled (R/W) [LINAC multipulse mode]
  -- *** LINAC monitoring ***
  -- 14 : 0x18 : time between two SPM pulses (R) [LINAC monitiring mode]
  -- 15 : 0x1C : maximum delay before a missing SPM is signaled (R/W) [LINAC monitoting mode]
  -- 16 : 0x20 : time between two LPM pulses (R) [LINAC monitiring mode]
  -- 17 : 0x24 : maximum delay before a missing SPM is signaled (R/W) [LINAC monitoting mode]
  -- 18 : 0x28 : number of simultaneous SPM / LPM pulses (R) [LINAC monitoting mode]
  -- 19 : 0x30 : reset the simultaneous SPM / LPM counter (W) [LINAC monitoting mode]
  -- *** Frequency divider ***
  -- 20 : 0x18 : time between two CLK_SR pulses (R) [frequency divider mode]
  -- 21 : 0x1C : maximum delay before a missing CLK_SR pulse is signaled (R/W) [frequency divider mode]
  cPCI_registerMUX : entity work.cPCI_registerMUX (rtl_cPCI_registerMUX)
    port map (
      -----------------
      -- Write register
      -----------------
      -- Duplication
      p_mux_wRegister(0)  => s_wRegister_foo0, -- wRegister_foo0 ; not used read only register
                                               -- (time between 2 pulses)
      p_mux_wRegister(1)  => s_dupMissingPulseDelay, -- maximum delay before a missing synchro pulse is signaled
      -- Top-Up
      p_mux_wRegister(2)  => s_beamLostHoldOff,  -- beam lost hold off time
      p_mux_wRegister(3)  => s_beamLostHoldOn,   -- beam lost hold on window width
      p_mux_wRegister(4)  => s_topUpGateHoldOff, -- gating hold off time
      p_mux_wRegister(5)  => s_topUpGateWidth,   -- gating window time
      -- LINAC SPM multipulses
      p_mux_wRegister(6)  => s_wRegister_foo6,   -- wRegister 6  ; not used read only register
                                                 -- (time between 2 pulses)
      p_mux_wRegister(7)  => s_linacMPMissingPulseDelay, -- maximum delay before a missing synchro pulse is signaled
      -- LINAC monitoring
      p_mux_wRegister(8)  => s_wRegister_foo8,  -- wRegister 8 ; not used read only register
                                                -- (time between 2 SPM)
      p_mux_wRegister(9)  => s_linacMONMissingSPMDelay, -- maximum delay before a missing SPM is signaled
      p_mux_wRegister(10) => s_wRegister_foo10, -- wRegister 10 ; not used read only register
                                                -- (time between 2 LPM)
      p_mux_wRegister(11) => s_linacMONMissingLPMDelay, -- maximum delay before a missing LPM is signaled
      p_mux_wRegister(12) => s_wRegister_foo12, -- wRegister 12 ; not used read only register
                                                -- (number of simultaneous SPM / LPM trigg)
      p_mux_wRegister(13) => s_linacMONsimTriggRST, -- reset the s_linacMONsimTrigg register
      -- Frequency divider
      p_mux_wRegister(14) => s_wRegister_foo14, -- wRegister_foo14 ; not used read only register
                                                -- (time between 2 CLK_SR pulses)
      p_mux_wRegister(15) => s_freqDivMissingPulseDelay, -- maximum delay before a missing synchro
                                                         -- pulse is signaled

      -----------------
      -- Read registers
      -----------------
      -- Duplication
      p_mux_rRegister(0)  => s_dupPulseMon,              -- time between two synchronization pulses
      p_mux_rRegister(1)  => s_dupMissingPulseDelay,     -- read back s_dupMissingPulseDelay value
      -- Top-Up
      p_mux_rRegister(2)  => s_beamLostHoldOff,          -- read back s_beamLostHoldOff value
      p_mux_rRegister(3)  => s_beamLostHoldOn,           -- read back s_beamLostHoldOn value
      p_mux_rRegister(4)  => s_topUpGateHoldOff,         -- read back s_topUpGateHoldOff value
      p_mux_rRegister(5)  => s_topUpGateWidth,           -- read back s_topUpGateWidth value
      -- LINAC SPM multipulses
      p_mux_rRegister(6)  => s_linacMPPulseMon,          -- time between two synchronization pulses
      p_mux_rRegister(7)  => s_linacMPMissingPulseDelay, -- read back s_linacMPMissingPulseDelay value
      -- LINAC monitoring
      p_mux_rRegister(8)  => s_linacMONSPMMon,           -- time between two SPM pulses
      p_mux_rRegister(9)  => s_linacMONMissingSPMDelay,  -- read back s_linacMONMissingSPMDelay value
      p_mux_rRegister(10) => s_linacMONLPMMon,           -- time between two SPM pulses
      p_mux_rRegister(11) => s_linacMONMissingLPMDelay,  -- read back s_linacMONMissingLPMDelay value
      p_mux_rRegister(12) => s_linacMONsimTrigg,         -- number of simultaneous SPM / LPM trigg
      p_mux_rRegister(13) => s_linacMONsimTriggRST,      -- not used ; write only register
      -- Frequency divider
      p_mux_rRegister(14) => s_freqDivPulseMon,          -- time between two CLK_SR pulses
      p_mux_rRegister(15) => s_freqDivMissingPulseDelay, -- read back s_freqDivMissingPulseDelay value

      -- Write registers
      p_wRegister      => s_wRegister,
      p_wRegister_init => s_wRegister_init, -- write registers init

      -- Read registers
      p_rRegister => s_rRegister,

      p_mux_csw   => s_mux_csw, -- cPCI write chip select ; input
      p_mux_csr   => s_mux_csr, -- cPCI read chip select ; input
      p_csw       => s_csw,     -- chip select of internal write transfert ; output
      p_csr       => s_csr,     -- chip select of internal read transfert ; output

      -- Other signals
      p_mux_SWsel => pin_SW -- configuration switch (duplication, top-up, etc.)
    );

  -- Status register manager
  -- *** Duplication ***
  -- Status(0) set : time between 2 synchro pulses exceeded the maximum delay [duplication mode]
  -- *** Top-up ***
  -- Status(0) set : top-up gated (1 : top-up window active) [top-up gating mode]
  -- Status(1) set : beam lost gated (1 : beam lost window active) [top-up gating mode]
  -- Status(2) set : top-up gated 2s width (1 : top-up window active) [top-up gating mode]
  -- Status(3) set : beam lost gated 2s width (1 : beam lost window active) [top-up gating mode]
  -- *** LINAC multipulse ***
  -- Status(0) set : time between 2 SPM exceeded the maximum delay [LINAC multipulse mode]
  -- *** LINAC monitoring ***
  -- Status(0) set : time between 2 SPM exceeded the maximum delay [LINAC monitoring mode]
  -- Status(1) set : time between 2 LPM exceeded the maximum delay [LINAC monitoring mode]
  -- Status(2) set : simultaneous SPM / LPM [LINAC monitoring mode]
  -- *** Frequency divider ***
  -- Status(0) set : time between 2 CLK_SR pulses exceeded the maximum delay [frequency divider mode]
  -- *** LINAC synchronized interlock ***
  -- Status(0) set : interlock signal is ON [LINAC synchronized interlock mode]
  cPCI_status: entity work.cPCI_statusManager (rtl_cPCI_statusManager)
    port map (
      p_inStates(0)  => s_dupLED(0),             -- time between 2 synchro pulses exceeded the maximum delay
      p_inStates(1)  => s_topUpTopUpGate(0),     -- top-up gated (1 : window active)
      p_inStates(2)  => s_topUpBeamLostGate(0),  -- beam lost gated (1 : window active)
      p_inStates(3)  => s_topUpTopUpGate(1),     -- top-up gated (1 : window active) ; 2s width
      p_inStates(4)  => s_topUpBeamLostGate(1),  -- beam lost gated (1 : window active) ; 2s width
      p_inStates(5)  => s_linacMPLED(0),         -- time between 2 SPM synchro pulses exceeded the maximum delay
      p_inStates(6)  => s_linacMONdelayError(0), -- time between 2 SPM exceeded the maximum delay
      p_inStates(7)  => s_linacMONdelayError(1), -- time between 2 LPM exceeded the maximum delay
      p_inStates(8)  => s_linacMONLED(0),        -- simultaneous SPM / LPM
      p_inStates(9)  => s_freqDivLED(0),         -- time between 2 CLK_SR pulses exceeded the maximum delay
      p_inStates(10) => s_linacSYNCLOCKstate,    -- interlock state (1 : ON ; 0 : non interlock)
      p_status       => s_status,
      p_cfgSW        => pin_SW,                  -- configuration switch (duplication, top-up, etc.)
      -- Other signals
      p_clk60MHz     => s_clk60MHz, -- clock 60 MHz
      p_reset        => s_reset     -- reset
    );

  -- Signal duplication block
  dup : entity work.dup_top (rtl_dup_top)
    port map (
      p_dup_inTTL             => pin_inTTL(0),
      p_dup_outTTL            => s_dupOutTTL,
      p_dup_outPECL           => s_dupOutPECL,
      p_dup_clk1kHz           => s_clk1kHz,
      p_dup_clk500mHz         => s_clk500mhz,
      p_dup_clk60MHz          => s_clk60MHz,
      p_dup_missingPulseDelay => s_dupMissingPulseDelay, -- maximum delay before a missing synchro
                                                         -- pulse is signaled
      p_dup_csw               => s_csw(2),
      p_dup_reset             => s_reset,
      p_dup_pulseMon          => s_dupPulseMon, -- time between two synchronization pulses
      p_dup_LED               => s_dupLED
    );

  -- TopUp gating
  topUp : entity work.topup_top (rtl_topup_top)
    port map (
      p_topUp_inTTL(0)     => pin_inTTL(0),
      p_topUp_inTTL(1)     => pin_inTTL(1),
      p_topUp_outTTL       => s_topUpOutTTL,
      p_topUp_outPECL      => s_topUpOutPECL,
      p_topUp_clk1kHz      => s_clk1kHz,
      p_topUp_clk500mHz    => s_clk500mHz,
      p_topUp_clk60MHz     => s_clk60MHz,
      p_beamLost_holdOff   => s_beamLostHoldOff,
      p_beamLost_holdOn    => s_beamLostHoldOn,
      p_topUp_gateHoldOff  => s_topUpGateHoldOff,
      p_topUp_gateWidth    => s_topUpGateWidth,
      p_topUp_csw          => s_csw(6 downto 3),
      p_topUp_reset        => s_reset,
      p_topup_topUpGate    => s_topUpTopUpGate,    -- top-up gate (1 : top-up window active)
      p_topup_beamLostGate => s_topUpBeamLostGate, -- beam lost gate (1 : beam lost window active)
      p_topUp_LED          => s_topUpLED
    );

  -- LINAC multipulse block
  LinacMP : entity work.linacMP_top (rtl_linacMP_top)
    port map (
      p_linacMP_inTTL             => pin_inTTL(3 downto 0),
      p_linacMP_outTTL            => s_linacMPOutTTL,
      p_linacMP_outPECL           => s_linacMPOutPECL,
      p_linacMP_clk1kHz           => s_clk1kHz,
      p_linacMP_clk500mHz         => s_clk500mhz,
      p_linacMP_clk60MHz          => s_clk60MHz,
      p_linacMP_missingPulseDelay => s_linacMPMissingPulseDelay, -- maximum delay before a
                                                                 --  missing synchro pulse is signaled
      p_linacMP_csw               => s_csw(8),
      p_linacMP_reset             => s_reset,
      p_linacMP_pulseMon          => s_linacMPPulseMon, -- time between two synchronization pulses
      p_linacMP_LED               => s_linacMPLED
    );

  -- LINAC monotoring block
  LinacMON : entity work.linacMON_top (rtl_linacMON_top)
    port map (
      p_linacMON_inTTL             => pin_inTTL(1 downto 0),
      p_linacMON_inInhibit         => pin_inTTL(4),
      p_linacMON_outTTL            => s_linacMONOutTTL,
      p_linacMON_outPECL           => s_linacMONOutPECL,
      p_linacMON_clk1kHz           => s_clk1kHz,
      p_linacMON_clk500mHz         => s_clk500mhz,
      p_linacMON_clk60MHz          => s_clk60MHz,
      p_linacMON_missingSPMDelay   => s_linacMONMissingSPMDelay, -- maximum delay before a
                                                                 --  missing SPM is signaled
      p_linacMON_missingLPMDelay   => s_linacMONMissingLPMDelay, -- maximum delay before a
                                                                 --  missing LPM is signaled
      p_linacMON_csw(0)            => s_csw(10), -- maximum delay before a missing SPM is signaled
      p_linacMON_csw(1)            => s_csw(12), -- maximum delay before a missing LPM is signaled
      p_linacMON_csw(2)            => s_csw(14), -- reset the SPM / LPM simultaneous trigg counter
      p_linacMON_reset             => s_reset,
      p_linacMON_SPMMon            => s_linacMONSPMMon,     -- time between two SPM pulses
      p_linacMON_LPMMon            => s_linacMONLPMMon,     -- time between two LPM pulses
      p_linacMON_simultaneousTrigg => s_linacMONsimTrigg,   -- number of simultaneous SPM / LPM triggers
      p_linacMON_delayError        => s_linacMONdelayError, -- Status
      p_linacMON_LED               => s_linacMONLED
    );

  -- Frequency divider block for slicing DG
  freqDIV : entity work.freqDIV_top (rtl_freqDIV_top)
    port map (
      p_freqDIV_inTTL             => pin_inTTL(0),
      p_freqDIV_outTTL            => s_freqDivOutTTL,
      p_freqDIV_outPECL           => s_freqDivOutPECL,
      p_freqDIV_clk1kHz           => s_clk1kHz,
      p_freqDIV_clk500mHz         => s_clk500mhz,
      p_freqDIV_clk60MHz          => s_clk60MHz,
      p_freqDIV_missingPulseDelay => s_freqDivMissingPulseDelay, -- maximum delay before a missing synchro
                                                                 -- clk_SR is signaled
      p_freqDIV_csw               => s_csw(16),
      p_freqDIV_reset             => s_reset,
      p_freqDIV_pulseMon          => s_freqDivPulseMon, -- time between two synchronization pulses
      p_freqDIV_LED               => s_freqDivLED
    );

  -- LINAC synchronized interlock block
  linacSynchroLOCK : entity work.linacSYNCLOCK_top (rtl_linacSYNCLOCK_top)
    port map (
      p_linacSYNCLOCK_inTTL    => pin_inTTL(1 downto 0),
      p_linacSYNCLOCK_outTTL   => s_linacSYNCLOCKOutTTL,
      p_linacSYNCLOCK_outPECL  => s_linacSYNCLOCKOutPECL,
      p_linacSYNCLOCK_clk60MHz => s_clk60MHz,
      p_linacSYNCLOCK_reset    => s_reset,
      p_linacSYNCLOCK_state    => s_linacSYNCLOCKstate, -- Status
      p_linacSYNCLOCK_LED      => s_linacSYNCLOCKLED
    );

  -- Clock padding block
  clkPADDING : entity work.clkPADDING_top (rtl_clkPADDING_top)
    port map (
      p_clkPADDING_clk500mHz => s_clk500mhz,
      p_clkPADDING_clk_mon   => pin_inTTL(0),
      p_clkPADDING_clk_sr    => pin_inTTL(1),
      p_clkPADDING_reset     => s_reset,
      p_clkPADDING_outTTL    => s_clkPaddingOutTTL,
      p_clkPADDING_outPECL   => s_clkPaddingOutPECL,
      p_clkPADDING_LED       => s_clkPaddingLED
    );

  -- Test
  test : entity work.test_top (rtl_test_top)
    port map (
      p_test_outTTL    => s_testOutTTL,
      p_test_outPECL   => s_testOutPECL,
      p_test_CLK500mHz => s_clk500mHz,
      p_test_reset     => s_reset,
      p_test_LED       => s_testLED
    );

  -- Multiplexer
  outMux : entity work.outputMux (rtl_outputMux)
    port map (
      -- Duplication block mux inputs
      p_dup_outTTL      => s_dupOutTTL,
      p_dup_outPECL     => s_dupOutPECL,
      p_dup_LED         => s_dupLED,
      -- Top-up block mux inputs
      p_topUp_outTTL    => s_topUpOutTTL,
      p_topUp_outPECL   => s_topUpOutPECL,
      p_topUp_LED       => s_topUpLED,
      -- LINAC multipulses block mux inputs
      p_linacMP_outTTL  => s_linacMPOutTTL,
      p_linacMP_outPECL => s_linacMPOutPECL,
      p_linacMP_LED     => s_linacMPLED,
      -- LINAC monitoring block mux inputs
      p_linacMON_outTTL  => s_linacMONOutTTL,
      p_linacMON_outPECL => s_linacMONOutPECL,
      p_linacMON_LED     => s_linacMONLED,
      -- Test block mux inputs
      p_test_outTTL     => s_testOutTTL,
      p_test_outPECL    => s_testOutPECL,
      p_test_LED        => s_testLED,
      -- Frequency divider block mux inputs
      p_freqDIV_outTTL  => s_freqDivOutTTL,
      p_freqDIV_outPECL => s_freqDivOutPECL,
      p_freqDIV_LED     => s_freqDivLED,
      -- LINAC synchronized interlock block mux inputs
      p_linacSYNCLOCK_outTTL  => s_linacSYNCLOCKOutTTL,
      p_linacSYNCLOCK_outPECL => s_linacSYNCLOCKOutPECL,
      p_linacSYNCLOCK_LED     => s_linacSYNCLOCKLED,
      -- Clock padding block mux inputs
      p_clkPADDING_outTTL  => s_clkPaddingOutTTL,
      p_clkPADDING_outPECL => s_clkPaddingOutPECL,
      p_clkPADDING_LED     => s_clkPaddingLED,
      -- Mux block mux outputs
      p_mux_SWsel       => pin_SW,
      p_mux_outTTL      => pin_outTTL,
      p_mux_outPECL     => pin_outPECL,
      p_mux_outLED      => pin_LED
    );

  ------------------------------------------------------------------------------
  ------------------------------------------------------------------------------
  s_SW <= "00000000000000000000000000" & pin_SW;
  pin_EXTS(7 downto 0) <= "00000000";

end architecture rtl_top;
