-- LEGGERE CON ATTENZIONE tutta la sezione introdutiva (specilamente i CONSIGLI)

-- ANAGRAFICA DELLO STUDENTE 
-- * Cognome: ...
-- * Nome: ...
-- * Matricola: ...

-- DESCRIZIONE DELLA PROVA:
-- il candiato progetti, disegni su foglio e descriva in VHDL un FILTRO
-- anche il disegno cartaceo deve essere consegnato
-- FILTRO funziona in questo modo:
-- il circuito campiona un segnale di ingresso ricevuto in RX
-- per filtrare possibili imperfezioni del segnale il circuito decide il valore dell'uscita GOAL
-- decidendo a maggioranza sugli ultimi tre campioni ricevuti
-- esempi:
-- RX(k)=1; RX(k-1)=1; RX(k-2)=0  allora GOAL = 1
-- RX(k)=0; RX(k-1)=1; RX(k-2)=0  allora GOAL = 0

-- OSSERVAZIONI
-- si realizzi Filtro come si crede purchè in modo RTL
-- a tal fine si possono utilizzare come COMPONENT le entity presenti in testa al progetto
-- ATTENZIONE: se si intendesse utilizzare una MSF (Macchina a Stati Finiti) si tenga presente che
-- NON è necessario assegnare una codifica esplicita agli stati
-- il TestBench è già predisposto per la simulazione
-- per editare il file si consiglia di utilizzare l'editor NOTEPAD++ (copiatene un collegamento sul desktop)

-- ISTRUZIONI:
-- si noti che per verificare e simulare il circuito si deve fare in modo che il programma GHDL sia nel PATH, per cui:
-- 1. aprire una finestra di comando: START-> Esegui -> CMD ed indirizzarla nella direcotry di lavoro
-- 2. digitare: set path=%path%;C:\Programmi\GHDL\bin;C:\Programmi\GHDL\gtk\bin;
-- il punto 2 va eseguito solo la prima volta e vale finché non si chiude la finestra di comando
-- 3. digitare: GHDL -a [nomefile.vhdl]
-- 4. digitare: GHDL -e [nome entity]
-- il punto 4 deve essere ripetuto per tutte le entity presenti nel file [nomefile.vhdl]
-- 5. digitare GHDL -r [nome entity_tb] --vcd=out.vcd
-- 6. se dopo il punto 5 non compare nulla nella riga di comando allora la simulazione è OK 
-- se invece compare un messaggio di Warning è necessario controllare con gtkwave 
-- dove il vostro segnale differisce quello del processo di riferimento, ovvero 'Processo_di_Test'
-- 7. digitare: gtkwave out.vcd 

-- CONSIGLI IMPORTANTI:
-- 1. la realizzazione mediante instanziazione dei COMPONENT già previsti è consigliata
-- 2. per avere un'idea dell'andamento che devono avere i segnali e per provare la procedura 
-- di compilazione e visualizzazione, prima di cominciare a scrivere alcunché, si esegua 
-- tutta la procedura e vi visualizza il risultato utilizzando il TestBench già predisposto
-- 3. chi  lo preferisce può utilizzare il file MAKE.BAT già predisposto
-- 4. FACENDO PRIMA IL DISEGNO DEL CIRCUITO LA PROVA RISULTA MOLTO SEMPLIFICATA
----------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------

-- descrizione del FFD da usare come componente
-- questa parte non deve essere modificata
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

	entity FFD is
  	port(CLK, D, reset : in STD_LOGIC;
		 Q : out STD_LOGIC);
	end FFD;
	
	architecture behaviour of FFD is
	begin
		process(CLK, reset)
		begin
			if reset='1' then Q<='0';  
			elsif (clk'event and clk='1') then Q<=D;											
			else null;
			end if;
		end process;
	end behaviour;


----------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------

-- descrizione dell'entità oggetto di progetto: Filtro
-- si modifichi solo la sezione 'architecture'
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

entity Filtro is
	port (	CLK, reset, RX : in std_logic;
			goal : out std_logic);
end entity Filtro;

architecture RTL of Filtro is
-- dichiarazione dei SIGNAL - esempio: 
-- signal a,b,c : std_logic;
signal x0, x1, x2 : std_logic;

--dichiarazione dei COMPONENT
	component FFD is
  	port(CLK, D, reset : in STD_LOGIC;
		 Q : out STD_LOGIC);
	end component;

-- si modifichi questa sezione; 
-- ATTENZIONE a dichiarare opportunamente i signal che si intende utilizzare
begin
	-- instanziazione di un FFD - esempio:
	-- inst1: FFD port map (CLK=>?, D=>?, reset=>?, Q=>?);

  ffd0: FFD port map (CLK=>CLK, D=>RX, reset=>reset, Q=>x0);
  ffd1: FFD port map (CLK=>CLK, D=>x0, reset=>reset, Q=>x1);
  ffd2: FFD port map (CLK=>CLK, D=>x1, reset=>reset, Q=>x2);

  -- Evaluator
  goal <= (x0 and x1) or (x2 and ((x0 and not x1) or (not x0 and x1)));
	
	
end architecture RTL;

----------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------

-- descriozione del Test_bench
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

entity Filtro_tb is
end Filtro_tb;

architecture behaviour of Filtro_tb is
component Filtro is
	port (	CLK, reset, RX : in std_logic;
			goal : out std_logic	
			);
end component;

-- Clock period definitions
constant clk_period : time := 1 us; 
   
signal CLK,RX: STD_LOGIC := '0';
signal reset: STD_LOGIC := '1';
signal goal: STD_LOGIC ;

signal I : integer := 0;
signal TEST_GOAL, errore: STD_LOGIC := '0';

begin
		clk_process: process --processo di generazione del CLK
		begin
			clk <= '0';
			wait for clk_period/2;
			clk <= '1';
			wait for clk_period/2;
			I<=I+1;
		
			if I=15 then wait; -- durata della simulazione: 20 colpi di CLK
			else null;
			end if;
		
		end process;
	
	-- instanziazione della Unit Under Test
	UUT: Filtro port map (CLK => CLK, reset => reset, RX=>RX, goal=>goal);

	stimoli: process
    begin		
		reset<='1'; 
		wait for clk_period*3;
		reset<='0'; RX<='0';
		wait for clk_period*1;
		RX<='1';
		wait for clk_period*1;
		RX<='0';
		wait for clk_period*1;
		RX<='0';
		wait for clk_period*1;
		RX<='0';
		wait for clk_period*1;
		RX<='1';
		wait for clk_period*1;
		RX<='1';
		wait for clk_period*1;
		RX<='1';
		wait for clk_period*1;
		RX<='0';
		wait for clk_period*1;
		RX<='1';
		wait for clk_period*1;
						
		wait;
		
    end process;
	
	
	Processo_di_Test: process
	begin
		test_goal<='0'; 
		wait for clk_period/2;
		test_goal<='0'; 
		wait for clk_period*9;
		test_goal<='1';
		wait for clk_period;
		wait;
	end process;
	
   
   
   ERRORE <= '0' when (goal=test_goal) else '1' after 1 ns;  
   assert (ERRORE='0')
   report "attenzione! controlla con GTKWAVE"
   severity WARNING;
   
end behaviour;
	
	
	
	
