Introduzione al VHDL Alcuni concetti introduttivi
Riferimenti The VHDL Cookbook, Peter J. Ashenden, Reperibile nel sito: http://vlsilab.polito.it/documents.html The VHDL Made Easy, David Pellerin, Douglas Taylor, Prentice Hall, 1997 Reperibile in Biblioteca Centrale
VHDL VHSIC HARDWARE DESCRIPTION LANGUAGE VHSIC Very High Speed Integer Circuits
Caratteristica Principale Serve a descrivere circuiti harware Caratteristica fondamentale: Concorrenza Cosi come blocchi (circuiti) fisici possono operare in parallelo anche in VHDL pezzi di codice sono simulati come se lavorassero contemporanemente
VHDL Event-Driven I compilatori/simulatori VHDL sono Event- Driven Ogni volta che cambia un valore di un segnale interno del codice vengono attivati tutti i blocchi (in cui opera tale segnale) in modo concorrente
Struttura di un file VHDL library ieee; use ieee.std_logic_1164.all; Definizione Librerie entity nome_circuito is port ( ingr : in tipo_ingresso; usci : out tipo_uscita; IN_OUT1 : inout tipo_inout); end nome_circuito ; ENTITY architecture tipo_arch of nome_circuito is constant : tipo_costante; signal : tipo_signal; -- COMMENTO ARCHITECTURE begin... end tipo_arch;
LIBRERIE Utilizziamo SEMPRE la libreria IEEE con il package std_logic_1164 (con use) Esempio: library ieee; use ieee.std_logic_1164.all; Altre librerie all uopo Esempio: library VIRTEX; use VIRTEX.all;
Libreria IEEE Con il package std_logic_1164 permette di utilizzare il tipo: std_logic Questo tipo descrive tutti i possibili valori che un segnale digitale puo assumere (esempio: 1, 0, Z ) Tipo std_logic Definisce segnali da 1 bit Tipo std_logic_vector(nbit-1 downto 0) Defisce un bus di segnali da nbit bit
ENTITY Serve a definire INTERFACCIA di un circuito Descrive le porte di: - in (solo ingresso) - out (solo uscita) - inout (ingresso/uscita) Useremo sempre porte di tipo STD_LOGIC (o STD_LOGIC_VECTOR)
ARCHITECTURE Descrive la FUNZIONALITA del circuito Due tipi di architecture: - behavioral descrizione comportamentale del circuito (cosa fa) - strucural descrizione tramite blocchi base (component) e di come sono connessi tra loro (come è fatto circuito)
Constant Sono dei valori sempre costanti Utilizzeremo anche per loro i tipi std_logic Esempio: constant uno : std_logic_vector(7 downto 0) :=(0 => 1, others => 0 ); constant due : std_logic_vector(3 downto 0) := 0010 constant flag : std_logic := 0 ; Ovvero: alla costante uno (bus di 8 bit) assegno al bit di peso 0 il valore 1 ed agli altri 0 Alla costante due assegno la stinga 0010 A flag assegno il valore 0
Signal Rappresentano i fili di connessione Se il loro valore logico non varia, mantengono il valore precedente Esempio: signal bus1 : std_logic_vector (31 downto 0); signal singolo : std_logic;
library ieee; use ieee.std_logic_1164.all; Esempio entity comparatore is port ( in1 : in std_logic_vector(3 downto 0); usci : out std_logic); end comparatore ; architecture behavioral of comparatore is constant zeri : std_logic_vector(3 downto 0):= (others => 0 ); signal temp : std_logic_vector(3 ; -- circuito comparatore tra ingresso e zero begin temp <= in1; comp: process (temp) -- vedremo dopo cosa è un process begin if (temp = zeri) then usci <= 1 ; else usci <= 0 ; end process comp; end behavioral;
Istantazione di blocchi già descritti In architecture di tipo structural si istanziano sotto-circuiti già descritti Per richiamare tali circuiti si utilizza il comando: component
Component Richiede la definizione del tipo di componente prima del begin dell architecture Dentro al begin si da un nome al componente e si definiscono le interconnessioni con blocchi vicini nel cosiddetto port map
library ieee; use ieee.std_logic_1164.all; Esempio entity circuito1 is port (entra : in std_logic_vector(3 downto 0); esci : out std_logic); end comparatore ; architecture structural of comparatore is component comparatore port ( in1 : in std_logic_vector(3 downto 0); usci : out std_logic); end component; signal temp : std_logic; begin compa:comparatore port map ( in1 => entra, usci => temp ); esci <= temp1 end structural;
La Concorrenza La caratteristica principale del VHDL è permettere la descrizioni concorrenti Questo si può fare istanziando dei component Si può anche fare, però, usando dei process
Process Il compilatore/simulatore VHDL sa che ad ogni evento che si verifica deve far partire in modo concorrente i vari blocchi di codice Tali blocchi sono quelli racchiusi dentro ad un process Un process è attivato se e solo se il segnale che è variato è racchiuso nella sua sensivity list
Esempio Process Si da un esempio di un process nome_process: process (sensivity list) begin... end process nome_process;
Tipi di Process Esistono 2 tipi fondamentali di process Process Combinatorio Serve a descrivere circuiti PURAMENTE combinatori (no clock) Process Sequenziali Serve a descrivere circuiti SEQUENZIALI (ovvero dove è presente un segnale di clock)
Tipi di process Sequenziali nella SENSIVITY LIST compaiono SOLO CLOCK e RESET ASINCRONO Combinatori nella SENSIVITY LIST compiono TUTTI i SEGNALI da ELABORARE
Esempio Process Sequenziale --purpose: registro numero 1 --type : sequential --inputs : clk, reset, in_data -- outputs: scambio1 reg_1: process (clk, reset) begin process reg_1 if reset = '0' then -- asynchronous reset (active low) temp1 <= (others => '0'); elsif clk'event and clk = '1' then --rising clock edge temp1 <= appoggio; end if; scambio1 <= temp1; end process reg_1;
Commento Nella Sensivity List ho solo clock e reset asincrono e non altri segnali Questo processo diventa attivo se e solo se o il clock o il reset subiscono variazioni Riconosco il fronte attivo (che è quello di salita) del clock tramite: clk'event and clk = '1'
Esempio Process Combinatorio MUX_TOBALLY: process (sel_r,from_pci) begin -- process MUX_TOBALLY if sel_r='0' then To_Bally <= from_pci; else To_Bally <= (others => '0'); end if; end process MUX_TOBALLY;
Commento La Sensivity List contiene 2 segnali che sono gli ingressi del process Sono questi 2 che, quando viene rivelata una loro variazione che scatenano l elaborazione del processo
Costrutti - if E utilizzato dentro un process if Condizione1 then elsif Condizione2 then else end if; Possono non Essere necessari
Esempio if if word_in(29) = '0' then currstate <= waitm after 0.1 ns; elsif word_in(29) = '1' then currstate <= waititer after 0.1 ns; else currstate <= selez after 0.1 ns; end if;
Costrutto case - when E` utilizzato nei process Serve a fare scelte multiple Codice più compatto rispetto a soluzione con if-elsif-else multipli Molto utile nel descrivere multiplexer o macchine a stati
Costrutto Case - When case signal1 then when valore1 => when valore2 => when other => end case;
Esempio case - when case word_in(29 downto 28) is when "01" => currstate <= waitllr after 0.1 ns; when "11" => currstate <= start after 0.1 ns; when "10" => currstate <= waitn after 0.1 ns; when others => currstate <= selez after 0.1 ns; end case;
Costrutti - for E utilizzato dentro un process La variabile di conteggio viene istanziata direttamente nel ciclo for for variabile in val_iniziale to/downto val_finale loop... end loop;
Esempio for for i in 0 to (log2maxadd) loop delay_line(i) <= (others => '0') after 0.5 ns; prior_r(i) <= (others => '0') after 0.5 ns; ff_del(i) <= '0' after 0.5 ns; end loop; -- i
Costrutto for generate Serve ad istanziare in modo automatico un numero n=(val_fin-val_iniz) di component Usato fuori da un process Sintassi: label: for variabile in val_iniz to/downto val_fin... end generate label;
Esempio for - generate layer_4: for j in 1 to (max_add/(2**ii)) generate som_4: add_reg generic map ( busw => busw) port map ( clk => clk_i, rst => rst_i, a => parz3((((max_add/8)*busw)-1-(((j+j-1)-1)*busw)) downto (((max_add/8)*busw) - ((j+j-1)*busw))), b => parz3((((max_add/8)*busw)-1- (busw*(j+j-1))) downto (((max_add/8)*busw) - (busw*((j+j-1)+1)))), sum => parz4(((((max_add/(2**ii)))*busw)-1-((j-1)*busw)) downto ((((max_add/(2**ii)))*busw)-(j*busw)))); end generate layer_4;