-----------------------------------------------
-- Progetto	   : MUX a 4 ingressi
-- Nome file   : mux4.vhdl
-- Descrizione : multiplexer a 4 ingressi da 1bit con 2bit di selezione
-- Autore      : Guido Matrella
-- Revisione   : 1.0
-- Note        : per una descrizione fortemente strutturale
--               avremmo dovuto definire la porta AND3, OR4, e NOT
--               ma poich� le nostre attivit� di progettazione 
--				 sono orientate alla sintesi automatica
--               � preferibile utilizzare gli operatori and, or, e not 
--				 messi a disposizione dal VHDL
--               N.B. nell'uso degli operatori si faccia attenzione alle parentesi!
-----------------------------------------------

-- dichiarazione delle librerie
library IEEE;
use IEEE.std_logic_1164.all;

-- definizione dell'entit� MUX4: 4 ingressi da 1bit, 2bit di selezione, 1bit uscita
entity mux4 is 
  port(
       din_0: in STD_LOGIC; -- bit di ingresso 0
	   din_1: in STD_LOGIC; -- bit di ingresso 1
	   din_2: in STD_LOGIC; -- bit di ingresso 2
	   din_3: in STD_LOGIC; -- bit di ingresso 3
       sel: in STD_LOGIC_VECTOR (1 downto 0); -- 2 bit di selezione
       mux_out: out STD_LOGIC -- bit di uscita del mux
  );
end mux4;

-- descriviamo l'architettura 
architecture behavior of mux4 is 
  signal w,x,y,z : STD_LOGIC;
  begin
--> INSERIRE QUI LA DESCRIZIONE
	mux_out <= w or x or y or z;
	w <= din_0 and not sel(0) and not sel(1);
	x <= din_1 and sel(0)	  and not sel(1);
	y <= din_2 and not sel(0) and sel(1);
	z <= din_3 and sel(0)     and sel(1);
	 
  end behavior;
  
  
-------------------------------------------- 
-----------------TEST BENCH-----------------
--------------------------------------------

-- dichiarazione delle librerie
library IEEE;
use IEEE.std_logic_1164.all;

-- definizione dell'entit� di test (si noti che non ci sono porte)
entity mux4_tb is
end mux4_tb;

-- descriviamo l'architettura
architecture test of mux4_tb is
component mux4 is -- definizione dell'entit� MUX4: 4 ingressi, 2 selezioni, 1 uscita
  port(
       din_0: in STD_LOGIC; -- bit di ingresso 0
	   din_1: in STD_LOGIC; -- bit di ingresso 1
	   din_2: in STD_LOGIC; -- bit di ingresso 2
	   din_3: in STD_LOGIC; -- bit di ingresso 3
       sel: in STD_LOGIC_VECTOR (1 downto 0); -- 2 bit di selezione
       mux_out: out STD_LOGIC -- bit di uscita del mux
  );
end component;


-- per semplicit� chiamo i segnali esattamente come le porte 
signal din_0, din_1, din_2, din_3: STD_LOGIC;
signal sel: STD_LOGIC_VECTOR (1 downto 0);
signal mux_out: STD_LOGIC;
-- si notino questi due nuovi segnali
-- definisco l'uscita ideale e un segnale di errore
signal ideal_out: STD_LOGIC;
signal ERRORE: STD_LOGIC := '0'; 

begin
-- esempio di instanziazione dei componenti
-- LABEL: NOME_COMP port map (porta=>segnale, ...);
UUT: mux4 port map (
					din_0   => din_0,
					din_1   => din_1,
					din_2   => din_2,
					din_3   => din_3,
					sel     => sel,
					mux_out => mux_out
					);
					
	process
	begin
		din_0<='1';din_1<='0';din_2<='0';din_3<='0';
		sel<="00";
		ideal_out <='1';
		wait for 10 ns;
		sel<="01";
		ideal_out <='0';
		wait for 10 ns;
		sel<="10";
		ideal_out <='0';
		wait for 10 ns;
		sel<="11";
		ideal_out <='0';
		wait for 10 ns;
		
		din_0<='1';din_1<='1';din_2<='0';din_3<='0';
		sel<="00";
		ideal_out <='1';
		wait for 10 ns;
		sel<="01";
		ideal_out <='1';
		wait for 10 ns;
		sel<="10";
		ideal_out <='0';
		wait for 10 ns;
		sel<="11";
		ideal_out <='0';
		wait for 10 ns;
		
		din_0<='1';din_1<='0';din_2<='1';din_3<='0';
		sel<="00";
		ideal_out <='1';
		wait for 10 ns;
		sel<="01";
		ideal_out <='0';
		wait for 10 ns;
		sel<="10";
		ideal_out <='1';
		wait for 10 ns;
		sel<="11";
		ideal_out <='0';
		wait for 10 ns;
		
		din_0<='1';din_1<='0';din_2<='0';din_3<='1';
		sel<="00";
		ideal_out <='1';
		wait for 10 ns;
		sel<="01";
		ideal_out <='0';
		wait for 10 ns;
		sel<="10";
		ideal_out <='0';
		wait for 10 ns;
		sel<="11";
		ideal_out <='1';
		wait for 10 ns;
    
		wait;  
	end process;
	
	-- Confrontiamo il nostro progetto con un Benchmark ideale
	ERRORE <= '0' when (ideal_out = mux_out) else '1' after 1 ns;  
	assert (ERRORE='0')
	report "attenzione! controlla la somma con GTKWAVE"
	severity WARNING;
end test;

  
 