-------------------------------------------------------------------------------
--
-- Title       : fibonacciero
-- Design      : fibonacciero
-- Author      : Ney Calazans
-- Company     : PUCRS - School of Technology
--
-------------------------------------------------------------------------------
--
-- File        : fibonacciero.vhd
-- Generated   : Sunday Sep 05 2021
--
-------------------------------------------------------------------------------
--
-- Description:	Hardware que computa os nro_elementos
-- 				primeiros elementos da Série de Fibonacci 
--				O processo de geração pode ser temporariamente
--				interrompido a qualquer instante, colocando o sinal
--              anda_para='0'.
--
-------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.STD_LOGIC_unsigned.all;

entity fibonacciero is
	 port(
		 clock : in STD_LOGIC;
		 reset : in STD_LOGIC;		
		 anda_para : in STD_LOGIC;	
		 nro_elementos : in STD_LOGIC_VECTOR(7 downto 0);
		 saida : out STD_LOGIC_VECTOR(7 downto 0)		 
	     );
end fibonacciero;

--}} End of automatically maintained section

architecture fibonacciero of fibonacciero is
signal soma, soma_old, saida_int, contador : STD_LOGIC_VECTOR(7 downto 0);
signal vai, zero : STD_LOGIC;
type states is (Start, C_P, Fim);
signal EA, PE : states;
begin
	
	saida <= saida_int; 
	soma <= saida_int + soma_old; 	
	
--------------------------------------------------	
-- Bloco de Dados
--------------------------------------------------	
-- Um somador de duas entradas e dois registradores,
-- formando um pipeline de armazenamento e cálculo de
-- 3 elementos consecutivos da série.
Bl_dados: process (clock, reset)
	begin			
		if reset='1' then
			soma_old <= (0=>'1', others=>'0');
			saida_int <= (others=>'0');
		elsif clock'event and clock='1' then 
			if vai='1' then
				soma_old <= soma;
				saida_int <= soma_old;
			end if;
		end if;
	end process;
	
--------------------------------------------------	
-- Bloco de Controle
--------------------------------------------------	
-- Máquina de estados com dois processos: um cria
-- o registrador de estados e um cria as funções de
-- transição de estados e de cálculo da saída
Reg_estado: process (clock, reset) 	
	begin	   
	   if reset='1' then
		   EA <= Start;
	   elsif clock'event and clock='1' then
		   EA <= PE;
	   end if;		   
	end process; 

Func_S_PE: process (EA, zero, anda_para)
	begin
		case EA is 
         when Start =>  vai <='0'; 
			 if zero='0' then
			 	PE <= C_P; 
			 else PE <= Fim; 
			 end if; 
         when C_P =>  
			 if zero='0' then
			 	PE <= C_P; 
			 else PE <= Fim; 
			 end if; 
			 if anda_para='1' and zero='0' then	
			 	vai<='1';
			 else vai<='0';
			 end if;	
		when Fim =>  	
			vai <='0';
			PE <= Fim;
		end case; 
	end process;

-- Contador auxiliar com detecção de zero combinacional.
-- Inicializado com nro_elementos-1 a cada reset, exceto 
-- se valor inicial -- for 0, em cujo caso inicializa-se
-- este com 0 mesmo.
cria_cont: process (clock, reset)
	begin			
		if reset='1' then
			if nro_elementos /=x"00" then
					contador <= nro_elementos-1;
			else 	contador <= x"00";
			end if;
		elsif clock'event and clock='1' then 
			if vai='1' then
				contador <= contador-1;
			end if;
		end if;
	end process;   
	
	zero <= '1' when contador=x"00" else '0'; 
		
end fibonacciero;
