--------------------------------------------------------------------------------
-- (c) by c't magazin 
--------------------------------------------------------------------------------
--
-- Design name : CT_Lab_FPGA
--
-- Filename : Timer.vhd
-- Version : 1.0
-- Date: 25.7.2008
--
-- Engineer : Klaus Philipp
--
--------------------------------------------------------------------------------
-- Timer
--
-- The timer generates a high and a low phase
-- high an low phases are controlled by 2 32 bit counters
-- These counters are clocked by 200 MHz
--
--------------------------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all; 
use IEEE.std_logic_unsigned.all;
--use IEEE.numeric_std.all;

library UNISIM;
use UNISIM.Vcomponents.ALL;

entity Timer is
   port ( CLK       : in    std_logic;
          CLK_TIMER : in    std_logic;		 
          D_H       : in    std_logic_vector (31 downto 0); 
          D_L       : in    std_logic_vector (31 downto 0); 
          PULSE_OUT : out   std_logic);
end Timer;

architecture BEHAVIORAL of Timer is

type state_type IS (count_high, count_low);
signal next_state: state_type := count_high;  -- initial state

signal timer_cnt_high: std_logic_vector(31 downto 0) := X"00000000";
signal timer_cnt_low : std_logic_vector(31 downto 0) := X"00000000";

begin

--------------------------------------------------------------------------------------------------
-- finite state maschine with two states: count_high and count low
			
	high_low: process (CLK_TIMER, D_L, D_H, timer_cnt_high, timer_cnt_low)
	begin
	  if rising_edge (CLK_TIMER)
	  then
		case next_state is
 			when count_high =>
			 if timer_cnt_high = X"00000000"
			 then
				next_state <= count_low;
				timer_cnt_low <= D_L;         -- load count value from register
				PULSE_OUT <= '0';                       -- set pulse output to low
			 else
				next_state <= count_high;
				timer_cnt_high <= timer_cnt_high - 1;   -- count down high time until zero
			 end if;
			 
			when count_low =>
			 if timer_cnt_low = X"00000000"
			 then
				next_state <= count_high;
				timer_cnt_high <= D_H;       -- load count value from register
				PULSE_OUT <= '1';                       -- set pulse output to high
			 else
				next_state <= count_low;
				timer_cnt_low <= timer_cnt_low - 1;     -- count down low time until zero
			 end if;
		end case;
	 end if;
	end process high_low;
	
end BEHAVIORAL;