-------------------------------------------------------------------------------
-- Title   : Top-up gating
-- Project : TimEX3
-------------------------------------------------------------------------------
-- Description : Gating of top-up
--                                     ___
--     Machine pre top-up signal   ___|   |___________________________________
--                                    :              ______________
--     p_gateWindow signal         _________________|              |___________
--                                    :             :              :
--                                    <-------------><------------->
--                                      t hold off       t width
-------------------------------------------------------------------------------
-- File     : topup_gating.vhdl
-- Revision : x.x.x
-- Created  : December 05, 2012
-- Updated  : February 03, 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 :
--
-------------------------------------------------------------------------------

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

library work;
use work.registers_init.all;

-------------------------------------------------------------------------------
--------------------------------- ENTITY --------------------------------------
-------------------------------------------------------------------------------
entity topup_gating is
  port (
    p_clk1kHz     : in  std_logic;
    p_clk60MHz    : in  std_logic;
    p_inTTL       : in  std_logic_vector (1  downto 0);
    p_gateWindow  : out std_logic; -- top-up gate (hold on time);
    p_gateHoldOff : in  std_logic_vector (31 downto 0);
    p_gateWidth   : in  std_logic_vector (31 downto 0);
    p_csw         : in  std_logic_vector (1  downto 0);
    p_reset       : in  std_logic
  );
end entity topup_gating ;

-------------------------------------------------------------------------------
------------------------------- ARCHITECTURE ----------------------------------
-------------------------------------------------------------------------------
architecture rtl_topup_gating of topup_gating is
  -----------------------------------------------------------------------------
  -- constant
  -----------------------------------------------------------------------------

  -----------------------------------------------------------------------------
  -- signal
  -----------------------------------------------------------------------------
  signal s_holdOffStart    : std_logic;
  signal s_cntHoldOff      : unsigned (31 downto 0);
  signal s_cntHoldOffMax   : unsigned (31 downto 0);
  signal s_cntGateWidth    : unsigned (31 downto 0);
  signal s_cntGateWidthMax : unsigned (31 downto 0);
  signal s_gateStart       : std_logic;
  signal s_gateEnd         : std_logic; -- top-up gate (hold on time);
  signal s_rstCNT          : std_logic;
  signal s_rstCNT0         : std_logic;
  signal s_rstCNT1         : std_logic;

  -----------------------------------------------------------------------------
  -- Components
  -----------------------------------------------------------------------------

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

   -- Start a gating cycle on a pre top-up trigger on p_inTTL(0)
  process (p_reset, s_gateEnd, p_inTTL(0))
  begin
    if ((p_reset = '1') or (s_gateEnd ='1')) then
      s_holdOffStart <= '0';
    elsif (rising_edge(p_inTTL(0))) then
      s_holdOffStart <= '1'; -- pre top-up
    else
      s_holdOffStart <= s_holdOffStart;
    end if;
  end process;

  -- Hold off time
  process (p_reset, s_rstCNT, s_holdOffStart, p_clk1kHz)
  begin
    if ((p_reset = '1') or (s_rstCNT = '1') or (s_holdOffStart = '0')) then
      s_cntHoldOff <= X"00000001";
      s_gateStart  <= '0';
    elsif (rising_edge(p_clk1kHz)) then
      if (s_cntHoldOff >= s_cntHoldOffMax) then
        -- Start the gating windows
        s_cntHoldOff <= s_cntHoldOff;
        s_gateStart  <= '1';
      else
        --  Counting the hold off time
        s_cntHoldOff <= s_cntHoldOff + 1;
        s_gateStart  <= '0';
      end if;
    end if;
  end process;

  -- Gating window time
  process (p_reset, s_rstCNT, s_gateStart, p_clk1kHz)
  begin
    if ((p_reset = '1') or (s_rstCNT = '1') or (s_gateStart = '0')) then
      s_cntGateWidth <= X"00000001";
      s_gateEnd      <= '0';
    elsif (rising_edge(p_clk1kHz)) then
      --  Counting the hold off time
      if (s_cntGateWidth >= s_cntGateWidthMax) then
        -- Start the gating windows
        s_cntGateWidth <= s_cntGateWidth;
        s_gateEnd      <= '1';
      else
        s_cntGateWidth <= s_cntGateWidth + 1;
        s_gateEnd      <= '0';
      end if;
    end if;
  end process;

  -- Latch from the register the hold off time
  process (p_reset, p_clk60MHz)
  begin
    if (p_reset = '1') then
      s_cntHoldOffMax <= unsigned (c_wRegister_init(4));
      s_rstCNT0       <= '0';
    elsif (rising_edge(p_clk60MHz)) then
      if (p_csw(0) = '1') then
        s_cntHoldOffMax <= unsigned (p_gateHoldOff);
        s_rstCNT0       <= '1';
      else
        s_cntHoldOffMax <= s_cntHoldOffMax;
        s_rstCNT0       <= '0';
      end if;
    end if;
  end process;

  -- Latch from the register the gating width
  process (p_reset, p_clk60MHz)
  begin
    if (p_reset = '1') then
      s_cntGateWidthMax <= unsigned (c_wRegister_init(5));
      s_rstCNT1         <= '0';
    elsif (rising_edge(p_clk60MHz)) then
      if (p_csw(1) = '1') then
        s_cntGateWidthMax <= unsigned (p_gateWidth);
        s_rstCNT1         <= '1';
      else
        s_cntGateWidthMax <= s_cntGateWidthMax;
        s_rstCNT1         <= '0';
      end if;
    end if;
  end process;

  -----------------------------------------------------------------------------
  -----------------------------------------------------------------------------
  s_rstCNT     <= s_rstCNT0 or s_rstCNT1;
  p_gateWindow <= s_gateStart; -- top-up gate (hold on time);

end architecture rtl_topup_gating;
