VHDL (VHSIC Hardware Description Language) è un Hardware Description Language (HDL) ed è utilizzato per simulare e sintetizzare i circuiti logici. È un derivato del linguaggio Ada. La specifica del linguaggio VHDL è mantenuta da IEEE tramite lo standard IEEE 107.
VHDL consente di modellare circuiti logici tramite una descrizione algoritmica, tramite una descrizione basata su formule logiche, oppure tramite una descrizione delle singole porte e interconnessioni.
L’estensione del file VHDL è .vhd. Il linguaggio è case-insensitive e fortemente tipizzato. Similmente al C, ogni “statement” è terminato con un punto e virgola. I commenti sono solo a riga singola e sono introdotti da --.
Un progetto VHDL può contenere:
Dichiarazione di entità
Descrizione dell’architettura di entità
Dichiarazione di package
Descrizione del contenuto di un package
Configurazioni
Entità
Note
L’entità è il concetto base di VHDL e rappresenta, in maniera astratte, un’interfaccia con una visione “ai morsetti”, quindi non fornisce alcuna descrizione del suo comportamento.
entity componente is port (a, b, c : in std_logic; d, e : out std_logic); end; ```
In VHDL, i tipi di dato si trovano in vari package, i principali sono
standard
std_logic_1164
numeric_std
float_std
Libreria standard
La libreria standard contiene tipi di dati scalari, come bit, boolean, integer, real, time o character, oppure dati vettoriali, come bit_vector o string.
Esistono anche le enumerazioni, che contengono un insieme finito di possibili valori:
type color is (black, red, green, blue);
Inoltre esistono array:
type each_month is array(1 to 12) integer;
E record:
type studente isrecord nome : string (1 to 6); cognome : string (1 to 6); matricola : integer; end record;
Libreria std_logic_1164
Questa libreria contiene due due tipi principali. Il primo, std_logic assume diversi valori che rappresentano uno stato logico:
'U': Uninitialized
'X': Unknown
'1'
'0'
'Z': Alta impedenza
'W': Weak unknown
'L': Weak '0'
'H': Weak '1'
'-': Indifferenza
E std_logic_vector, che è una versione array di std_logic.
È inoltre possibile dichiarare dei generics, che consentono di creare entità parametriche, e entity statement, che contengono dichiarazioni comuni a tutte le architetture.
Architetture
Note
Ad ogni entità viene associata una o più architetture. Ogni architettura rappresenta una diversa implementazione di un’entità, e la configurazione deciderà quale specifica implementazione verrà utilizzata per la simulazione o sintesi.
architecture ARCHITECTURE_NAME of ENTITY_NAME is-- header dichiarativobegin-- bodyend architecture;
Costanti
Le costanti, come nei linguaggi di programmazione, aiutano a tenere il codice in ordine:
constant NOME: type := expression;
Segnali
I segnali sono l’astrazione dei “collegamenti fisici tra i componenti”:
signal NOME: type := expression;
Per istanziare un componente si usa la sintassi:
instance_name: component_name port map(port mappings)
Alcuni costrutti importanti
Operatore di concatenamento
L’operatore di concatenamento & concatena in un segnale più grande.
signal low_bytes: std_logic_vector(0 to 15);signal high_bytes: std_logic_vector(0 to 15);signal overall: std_logic_vector(0 to 31);overall <= high_bytes & low_bytes;
Operatore when/else
L’operatore when else ci permette di valutare condizioni.
output <= "001" when input = "100" else "010" when input = "010" else "100" when input = "001" else "000";
Quando facciamo condizioni con un solo assegnamento possiamo usare with:
with input selectoutput <= "001" when "100", "010" when "010", "100" when "001", "000" when others ```
Istruzione for
L’istruzione for generate consente la creazione di componenti multipli:
test_generator: for i in 0 to 10 generate test_comp : test port map (inp(i), inp(i + 1)); end generate;
Process
Note
Un process in VHDL è una procedura eseguita sequenzialmente, eseguita quando un valore nella sensitivity list cambia.
nome: process (in1, in2, ...) --- dichiarazioni di signal begin --- statement valutato quando cambia la sensitivity list end process;
Si noti che non si possono usare segnali come se fosse variabili in maniera sequenziale.
Dentro un process, si possono usare direttive come wait for, wait until o after, tuttavia queste non sono sintetizzabili.
Inoltre, all’interno di un process si possono usare i classici statement if/else/elsif:
nome: process [(sensitivity_list)]begin if condition_1 then statement_1 elsif condition_2 then statement_2 else statement_n end if;end process;
Esempio
Un Flip Flop SR è implementabile come:
latch_sr: process(s,r)begin if (s='1' and r='0') then q_internal <= '1'; elsif (s='0' and r='1') then q_internal <= '0'; elsif (s='1' and r='1') then q_internal <= 'X'; end if; end process; ```