library ieee;
use ieee.std_logic_1164.all;		 
use ieee.std_logic_unsigned.all;

entity counters is
	 port(
		 clock 							: in 	std_logic;
		 reset 							: in 	std_logic;
		 enable							: in 	std_logic;	 
		 load							: in	std_logic;
		 period							: in	std_logic_vector(15 downto 0);
		 flashes						: in	std_logic_vector(15 downto 0);
		 end_of_flashlet 				: out 	std_logic;	 
		 count							: out	std_logic_vector(15 downto 0)
	);
end counters;

architecture synthesis of counters is		
signal period_reload		: std_logic_vector(15 downto 0);
signal flash_period			: std_logic_vector(15 downto 0);   
signal number_of_flashes	: std_logic_vector(15 downto 0); 
signal flash_end			: std_logic;
signal flashlet_end			: std_logic;
begin								 
	
	flash_end_ff : process(clock)
	begin		
		if rising_edge(clock) then
			if reset = '1' then
				flash_end <= '0';
			elsif enable = '1' then
				if flash_period = X"0001" then
					flash_end <= '1';
				else
					flash_end <= '0';
				end if;
			end if;
		end if;
	end process flash_end_ff;  
	
	flashlet_end_ff : process(clock)
	begin		
		if rising_edge(clock) then
			if reset = '1' then
				flashlet_end <= '0';
			elsif enable = '1' then 
				if number_of_flashes = X"0000" and flash_period = X"0001" then
					flashlet_end <= '1';
				else
					flashlet_end <= '0';   
				end if;
			end if;
		end if;
	end process flashlet_end_ff; 	
	
	period_reload_counter : process (clock)
	begin
		if rising_edge(clock) then
			if reset = '1' then
				period_reload <= (others => '0');
			elsif load = '1' then
				period_reload <= period;
			end if;
		end if;
	end process period_reload_counter;
	
	flash_counter : process(clock)
	begin		
		if rising_edge(clock) then
			if reset = '1' then
				flash_period <= (others => '0');   
			elsif load = '1' then
				flash_period <= period;
			elsif enable = '1' then
				if flash_end = '1' then
					flash_period <= period_reload;
				else 
					flash_period <= flash_period - 1;
				end if;
			end if;
		end if;
	end process flash_counter;	
	
	flashlet_counter : process(clock)
	begin		
		if rising_edge(clock) then
			if reset = '1' then
				number_of_flashes	<= (others => '0');	 
			elsif load = '1' then
				number_of_flashes <= flashes;
			elsif enable = '1' then
				if flash_end = '1' then
					number_of_flashes	<= number_of_flashes - 1;
				end if;
			end if;
		end if;
	end process flashlet_counter;			  
	
	end_of_flashlet	<= flashlet_end;   
	count			<= flash_period;
	
end synthesis;
