--    TimeBase1.vhd
--    release 1.0  06/08/2006
--    TimeBase1 uses an input clock of 64 MHz to generate a divided TIMEBASEOUT 
--    pulse of period depending from the input 32 bit divider value. The high 
--    time of the pulse on TIMEBASEOUT will be 15.625 nsec or one clock period. 
--    The period of the subsequent pulses will be 15.625 * (1+DIVIDERVALUE) nsec.
--
--		For more info see: http://www.acmesystems.it/?id=120
--      Author: Roberto Asquini
--		Copyright (C) 2006 Acme Systems srl (http://www.acmesystems.it)
--		
--		This is free software; you can redistribute it and/or modify
--		it under the terms of the GNU General Public License as published by
--		the Free Software Foundation; either version 2 of the License, or
--		(at your option) any later version.
--		
--		This example 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 General Public License for more details.
--		
--		To have a copy of the GNU General Public License write to the Free Software
--		Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
library proasic3;

entity TimeBase1 is
  port(
    CLOCK : in std_logic;          -- input clock 64 MHz. 
    TIMEBASEOUT : out std_logic;   -- out timebase signal.  
    RESETN : in std_logic;         -- master reset signal (active low)
    DIVIDERVALUE : in std_logic_vector(31 downto 0); -- 32 bit divider value
    RUNCOUNTER : out std_logic_vector(31 downto 0) -- 32 bit testing output of the running counter
  );     
end TimeBase1;

architecture Behavioral of TimeBase1 is 

  signal RunningCounter : std_logic_vector(31 downto 0);   -- this is the 32 bit free running counter attached at the CLOCK

  signal resetCounter : std_logic; -- signal that resets the running counter at the right time

begin 
  
  -- this is the RunningCounterProcess:
  --   the Counter resets itself when either RESETN = '0' or the internal signal resetCounter goes '1';
  --   otherwise at every CLOCK rising front it is incremented.
  RunningCounterProcess : process (RESETN, resetCounter, CLOCK) 
  begin
    if ( RESETN = '0' or resetCounter = '1') then 
      RunningCounter <= x"00000000";
    elsif ( CLOCK'event and CLOCK = '1') then
      RunningCounter <= RunningCounter + 1;
    end if;
  end process;

  -- this is the resetCounterProcess:
  --   Initialized to zero during RESETN = '0', the signal resetCounter goes high 
  --   (on the falling edge of the CLOCK) when the RunningCounter value equals 
  --   the value of the 32 bit DIVIDERVALUE input port signal.
  --   So the RunningCounter is reset.
  --
  --   Making the comparison on the negative front of the CLOCK external signal 
  --   is useful to avoid logic races on the increment of the runningCounter that is
  --   operated on the rising edges of the CLOCK. 
  --   RunningCounter will be reset to all zeroes when either RESETN = '0' or the 
  --   internal signal resetCounter goes to '1';
  --   otherwise at every CLOCK rising front it will be incremented.
  resetCounterprocess : process (RESETN, CLOCK)
  begin
    if ( RESETN = '0' ) then 
      resetCounter <= '0';
    elsif ( CLOCK'event and CLOCK = '0') then
      if (RunningCounter = DIVIDERVALUE) then
        resetCounter <= '1';
      else 
        resetCounter <= '0';
      end if;
    end if;
  end process;

  -- the signal resetCounter is routed outside on the TIMEBASEOUT port signal so to generate a small 
  -- pulse high at every reset of the RunningCounter.
  -- This realizes a pulse high (long one CLOCK period) at every DIVIDERVALUE external CLOCK pulses.  
  TIMEBASEOUT <= resetCounter;

  -- the 32 bit runningCounter signal value is routed outside to be available as timebase actual value for external applications.
  RUNCOUNTER <= runningCounter;

end Behavioral; 