--------------------------------------------------------------------------------
-- Title   : Top - duplication function
-- Project : TimEX3
--------------------------------------------------------------------------------
-- Description : Top sheet of the duplication block
--    inTTL(0) is duplicated to outTTL[4 donwto 1] and outPECL[4 downto 1]
--    outTTL(0) is not used as the board IO connector is hard configured as
--    input
--------------------------------------------------------------------------------
-- File     : dup_top.vhdl
-- Revision : x.x.x
-- Created  : October 26, 2012
-- Updated  : June 17, 2013
--------------------------------------------------------------------------------
-- Author       : Jean-Paul Ricaud
-- Organization : Synchrotron Soleil
-- Web          : http://www.synchrotron-soleil.fr
-- Email        : jean-paul.ricaud@synchrotron-soleil.fr
--------------------------------------------------------------------------------
-- Copyright (C) 2012 - 2013 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 :
--   Version 1.2.1 ; June 14 2013 ; Jean-Paul Ricaud
--     * Added deay on duplicated outputs to compensate the outputs offsets
--
--------------------------------------------------------------------------------

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

--------------------------------------------------------------------------------
--------------------------------- ENTITY ---------------------------------------
--------------------------------------------------------------------------------
entity dup_top is
  port (
    p_dup_inTTL             : in  std_logic;                     -- input TTL
    p_dup_outTTL            : out std_logic_vector (4 downto 0); -- TTL outputs
    p_dup_outPECL           : out std_logic_vector (4 downto 0); -- LVPECL outputs
    p_dup_clk1kHz           : in  std_logic;
    p_dup_clk500mHz         : in  std_logic;
    p_dup_clk60MHz          : in  std_logic;
    p_dup_missingPulseDelay : in  std_logic_vector (31 downto 0);
    p_dup_csw               : in  std_logic;
    p_dup_reset             : in  std_logic;
    p_dup_pulseMon          : out std_logic_vector (31 downto 0); -- pulses monitor
    p_dup_led               : out std_logic_vector (1 downto 0)
  );
end entity dup_top;

--------------------------------------------------------------------------------
------------------------------- ARCHITECTURE -----------------------------------
--------------------------------------------------------------------------------
architecture rtl_dup_top of dup_top is

  ------------------------------------------------------------------------------
  -- constant
  ------------------------------------------------------------------------------
  constant c_lenght_delayedOut4 : integer := 8;
  constant c_lenght_delayedOut3 : integer := 6;
  constant c_lenght_delayedOut2 : integer := 4;
  constant c_lenght_delayedOut1 : integer := 2;

  ------------------------------------------------------------------------------
  -- signal
  ------------------------------------------------------------------------------
  signal s_impulse     : std_logic; -- detection of impulse
  signal s_dup_outTTL  : std_logic_vector (4 downto 0);
  signal s_delayedOut4 : std_logic_vector (c_lenght_delayedOut4 downto 0);
  signal s_delayedOut3 : std_logic_vector (c_lenght_delayedOut3 downto 0);
  signal s_delayedOut2 : std_logic_vector (c_lenght_delayedOut2 downto 0);
  signal s_delayedOut1 : std_logic_vector (c_lenght_delayedOut1 downto 0);

  attribute keep : string;
  attribute keep of s_delayedOUT1 : signal is "True";
  attribute keep of s_delayedOUT2 : signal is "True";
  attribute keep of s_delayedOUT3 : signal is "True";
  attribute keep of s_delayedOUT4 : signal is "True";

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

    -- Signal duplication block (either TTL or LVPECL)
--    duplication : entity work.dup_duplication (rtl_dup_duplicationPECL)
    duplication : entity work.dup_duplication (rtl_dup_duplicationTTL)
      port map (
        p_inTTL   => p_dup_inTTL,  -- TTL in
        p_outTTL  => s_dup_outTTL, -- TTL out
        p_outPECL => p_dup_outPECL -- LVPECL out
      );

    -- Signal monitoring block
    -- The time betwwen 2 input pulses in stored in MONITOR register (in ms)
    pulseMonitor : entity work.dup_monitoring (rtl_dup_monitoring)
      port map (
        p_inTTL   => p_dup_inTTL,    -- TTL input
        p_clk1kHz => p_dup_clk1kHz,
        p_reset   => p_dup_reset,
        p_monitor => p_dup_pulseMon  -- register with the time value between two pulses
      );

    -- LEDs management for the duplication 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 no input signal is detected
    -- after delay defined in the missingPulseDelay register.
    leds : entity work.dup_leds (rtl_dup_leds)
      port map (
        p_inTTL             => p_dup_inTTL,  -- TTL input
        p_clk1kHz           => p_dup_clk1kHz,
        p_clk500mHz         => p_dup_clk500mHz,
        p_clk60MHz          => p_dup_clk60MHz,
        p_missingPulseDelay => p_dup_missingPulseDelay,
        p_csw               => p_dup_csw,
        p_reset             => p_dup_reset,
        p_led               => p_dup_led
      );

  ------------------------------------------------------------------------------
  ------------------------------------------------------------------------------

  s_delayedOut4(0) <= not s_dup_outTTL(4);
  genDelay4 : for i in 1 to (c_lenght_delayedOut4) generate
  begin
    s_delayedOut4(i) <=  not s_delayedOut4(i - 1);
  end generate genDelay4;
  p_dup_outTTL(4) <= not s_delayedOut4(c_lenght_delayedOut4);

  s_delayedOut3(0) <= not s_dup_outTTL(3);
  genDelay3 : for i in 1 to (c_lenght_delayedOut3) generate
  begin
    s_delayedOut3(i) <=  not s_delayedOut3(i - 1);
  end generate genDelay3;
  p_dup_outTTL(3) <= not s_delayedOut3(c_lenght_delayedOut3);

  s_delayedOut2(0) <= not s_dup_outTTL(2);
  genDelay2 : for i in 1 to (c_lenght_delayedOut2) generate
  begin
    s_delayedOut2(i) <=  not s_delayedOut2(i - 1);
  end generate genDelay2;
  p_dup_outTTL(2) <= not s_delayedOut2(c_lenght_delayedOut2);

  s_delayedOut1(0) <= not s_dup_outTTL(1);
  genDelay1 : for i in 1 to (c_lenght_delayedOut1) generate
  begin
    s_delayedOut1(i) <=  not s_delayedOut1(i - 1);
  end generate genDelay1;
  p_dup_outTTL(1) <= not s_delayedOut1(c_lenght_delayedOut1);
--  p_dup_outTTL(1) <= s_dup_outTTL(1);

end architecture rtl_dup_top;
