Salta al contenuto
Note per Studenti Introduzione al VHDL - entity, architecture, tipi e livelli di descrizione

Introduzione al VHDL - entity, architecture, tipi e livelli di descrizione

In questa pagina 7

I circuiti con miliardi di transistor non si disegnano a mano: si descrivono con un linguaggio di descrizione dell'hardware (HDL, Hardware Description Language) e si usano strumenti CAD per simularli e sintetizzarli. I due HDL più diffusi, entrambi standard IEEE, sono VHDL e Verilog. VHDL (Very high speed integrated circuits Hardware Description Language) nasce nel 1987 da un progetto del Dipartimento della difesa statunitense ed è stato riveduto più volte.

Non è un linguaggio di programmazione

In Python o in C le istruzioni sono tradotte in una sequenza eseguita una dopo l'altra da un processore. Un HDL viene invece tradotto in un circuito digitale: le dichiarazioni sono concorrenti, cioè attive tutte nello stesso istante, come le porte di un circuito lavorano in parallelo. Un'istruzione VHDL definisce un blocco di hardware, non un passo di esecuzione; cambiare l'ordine delle istruzioni concorrenti non cambia il circuito.

Usi del VHDL:

  • documentare un progetto;
  • simulare il comportamento: si applicano segnali in ingresso e si osservano le uscite nel tempo (nel corso si usa un simulatore online);
  • sintetizzare: passare da una descrizione comportamentale a un insieme di porte e flip-flop (netlist). Solo un sottoinsieme del linguaggio è sintetizzabile; una descrizione pensata solo per la simulazione (come un testbench) può usare tutto il linguaggio. Nel corso non si studia la sintesi.

Flusso di sintesi (per capire dove si colloca il VHDL): descrizione HDL + vincoli (area, velocità, consumo) + librerie tecnologiche →\to forma intermedia RTL (Register Transfer Level: porte e registri generici) →\to ottimizzazione →\to mappatura tecnologica sui blocchi realmente disponibili →\to netlist, usata per produrre il layout di un circuito integrato o la configurazione di un FPGA (Logica programmabile - ROM, PLA, PAL e FPGAI dispositivi logici programmabili (PLD) hanno strutture logiche configurabili dal costruttore o dall'utente (configurazione $\ne$ programmazione software): ROM ($2^k$ parole da $n$ bit: decoder + OR programmabili), PLA (AND e OR programmabili, termini prodotto condivisi tra le uscite), PAL (AND programmabili, OR fisse, niente condivisione), FPGA (blocchi logici con LUT e flip-flop, interconnessioni e I/O programmabili, memoria di configurazione volatile o no). La programmazione può essere irreversibile (fuse/anti-fuse, mask) o riconfigurabile (SRAM, gate flottante).Logica programmabile - ROM, PLA, PAL e FPGA →). È un processo iterativo.

Caratteristiche generali

  • Fortemente tipizzato: dati di tipo diverso non si assegnano l'uno all'altro senza una funzione di conversione.
  • Case insensitive: Entity ed ENTITY sono la stessa cosa; spazi, tabulazioni e a capo sono ignorati; i commenti iniziano con --.
  • Ogni istruzione termina con ;.
  • Si tenga sempre presente l'hardware che si sta descrivendo.

Entity e architecture

Un blocco VHDL ha due parti obbligatorie.

Entity. È la "targa" del blocco: ne dà il nome e definisce l'interfaccia con l'esterno (quali porte, di che direzione e tipo). Non dice che cosa c'è dentro, come il simbolo di un circuito in uno schema. Un blocco deve avere una sola entity.

vhdl
entity nome_entity is
  port ( ingresso1, ingresso2 : in  std_logic;
         uscita               : out std_logic );   -- il ';' non va dopo l'ultima porta
end nome_entity;

Modo (direzione) delle porte: in (il valore può essere letto ma non assegnato dal blocco: il driver è fuori), out (il valore può essere assegnato ma non letto: il driver è dentro). Esistono anche inout e buffer, non usati nel corso. L'assegnazione si scrive X <= Y;: si legge "Y è assegnato a X", la freccia va da destra a sinistra; ogni volta che YY cambia, cambia anche XX. Lo statement X <= Y è il driver del segnale XX (la sorgente).

Architecture. È una descrizione particolare del contenuto di una entity: come si comporta e come opera internamente. Una entity può avere più architecture nello stesso progetto (per esempio una structural e una dataflow); un progetto non può avere più entity per lo stesso blocco.

vhdl
architecture nome_arch of nome_entity is
  -- dichiarazioni: component, signal, constant, type
begin
  -- corpo: istruzioni concorrenti
end nome_arch;

Librerie e package. Si dichiarano prima di ogni entity:

vhdl
library IEEE;
use IEEE.std_logic_1164.all;     -- tipi std_logic e std_logic_vector

Le librerie sono raccolte di package che contengono codice riusabile (tipi, componenti, costanti). .all significa "tutto ciò che il package definisce". Per le operazioni aritmetiche sui vettori ci sono package IEEE (numeric_std) e package Synopsys (std_logic_unsigned, std_logic_signed) che cambiano il modo in cui un std_logic_vector è trattato (con o senza segno).

Tipi di dato

tipo che cosa è esempio di valore
std_logic un bit "logico" a 9 valori '0', '1', 'X', 'Z', '-'
std_logic_vector vettore di std_logic "010", x"1F"
bit solo '0' e '1' '1'
boolean TRUE / FALSE true
integer intero a 32 bit 100

I valori di std_logic (da std_logic_1164): '0' e '1' logici; 'X' valore non noto o in conflitto; 'U' non inizializzato (si vede in simulazione); 'Z' alta impedenza (uscita scollegata); '-' don't care (il sintetizzatore può ottimizzare); 'L', 'H' e 'W' valori "deboli". Per noi contano 0, 1, X, -, Z, U. Un std_logic va tra apici singoli ('1'), un vettore tra virgolette doppie ("010").

Vettori. std_logic_vector(n-1 downto 0) ha il bit più significativo a sinistra, di indice n−1n-1; std_logic_vector(0 to n-1) ha l'indice 00 a sinistra (è il MSB). Un bit si estrae con x(2), una porzione con x(3 downto 1); il concatenamento si scrive &: "10" & "01" vale "1001". I letterali esadecimali si scrivono x"1F". Il tipo integer si usa per parametri (lunghezza dei vettori, indici dei cicli) e si scrive in decimale senza virgolette.

Signal e constant. Le porte comunicano con l'esterno e sono definite nella entity; i segnali interni (signal) si dichiarano nell'architecture, prima di begin, e servono a collegare nodi interni o blocchi tra loro: signal n1, n2 : std_logic;. Le costanti (constant N : integer := 8;) danno un nome a valori fissi, per leggibilità e per facilitare le modifiche.

I tre livelli di descrizione: il comparatore a 2 bit

Specifica: ingressi A=A1A0A=A_1A_0, B=B1B0B=B_1B_0 (il pedice 11 è il bit più significativo), uscita AgtB =1=1 se A>BA>B. Dalla mappa di Karnaugh (Mappe di Karnaugh - implicanti e copertura minimaLa mappa di Karnaugh è la tabella di verità disposta in una griglia con righe e colonne in codice Gray, così che celle adiacenti (anche tra bordi opposti) differiscano in una sola variabile. Si raggruppano gli 1 in rettangoli di $2^k$ celle: ogni gruppo elimina $k$ variabili e dà un prodotto. Implicante primo = gruppo massimo; essenziale = unico a coprire un mintermine; la copertura minima contiene tutti gli essenziali più il minimo di altri primi (può non essere unica). Efficace fino a 4 variabili.Mappe di Karnaugh - implicanti e copertura minima →) si ottiene la SOP minima A>B=A1B1‾+A0B1‾ B0‾+A1A0B0‾.A>B=A_1\overline{B_1}+A_0\overline{B_1}\,\overline{B_0}+A_1A_0\overline{B_0}. Stessa entity per tutti i livelli:

vhdl
library IEEE;
use IEEE.std_logic_1164.all;

entity comp2 is
  port ( A, B : in  std_logic_vector(1 downto 0);
         AgtB : out std_logic );
end comp2;

Dataflow

Descrive il flusso dei segnali con equazioni booleane espresse da assegnazioni concorrenti, senza dettagliare la struttura (nessun componente):

vhdl
architecture dataflow of comp2 is
begin
  AgtB <= (A(1) and not B(1)) or
          (A(0) and not B(1) and not B(0)) or
          (A(1) and A(0) and not B(0));
end dataflow;

Behavioral

Descrive solo il comportamento, lasciando al sintetizzatore la scelta del circuito. Per esempio con la tabella di verità (si elencano le sei combinazioni di A,BA,B con A>BA>B, scritte come A1A0B1B0A_1A_0B_1B_0):

vhdl
architecture behav of comp2 is
  signal AB : std_logic_vector(3 downto 0);
begin
  AB <= A & B;
  with AB select
    AgtB <= '1' when "0100" | "1000" | "1001" | "1100" | "1101" | "1110",
            '0' when others;
end behav;

Le costruzioni with ... select e when ... else sono spiegate in VHDL - istruzioni concorrenti, process e testbenchLe istruzioni concorrenti VHDL sono l'assegnazione di segnale, when-else (logica prioritaria, condizioni valutate in ordine) e with-select (logica parallela: tutti i casi coperti da una sola scelta, others obbligatorio). Un process è un'istruzione concorrente il cui corpo è sequenziale (if, case, loop); parte quando cambia un segnale della sensitivity list (per la logica combinatoria: tutti gli ingressi); i segnali si aggiornano alla sospensione e vince l'ultima assegnazione. Un if senza else (o un caso non coperto) crea memoria non voluta. Il testbench è codice di simulazione con entity vuota, DUT istanziato e un process di stimoli con wait.VHDL - istruzioni concorrenti, process e testbench →.

Structural

Descrive il circuito come componenti interconnessi, equivalente a uno schema a porte: livello di astrazione più basso. Servono le porte come blocchi VHDL; per esempio:

vhdl
-- inverter
library IEEE; use IEEE.std_logic_1164.all;
entity inv is port (x : in std_logic; y : out std_logic); end inv;
architecture impl of inv is begin y <= not x; end impl;

-- AND a 2 ingressi
library IEEE; use IEEE.std_logic_1164.all;
entity and2 is port (a, b : in std_logic; y : out std_logic); end and2;
architecture impl of and2 is begin y <= a and b; end impl;

-- AND a 3 ingressi
library IEEE; use IEEE.std_logic_1164.all;
entity and3 is port (a, b, c : in std_logic; y : out std_logic); end and3;
architecture impl of and3 is begin y <= a and b and c; end impl;

-- OR a 3 ingressi
library IEEE; use IEEE.std_logic_1164.all;
entity or3 is port (a, b, c : in std_logic; y : out std_logic); end or3;
architecture impl of or3 is begin y <= a or b or c; end impl;

architecture struct of comp2 is
  signal nb1, nb0, p1, p2, p3 : std_logic;    -- nodi interni
begin
  I1 : entity work.inv(impl)  port map (B(1), nb1);
  I0 : entity work.inv(impl)  port map (B(0), nb0);
  G1 : entity work.and2(impl) port map (A(1), nb1, p1);
  G2 : entity work.and3(impl) port map (A(0), nb1, nb0, p2);
  G3 : entity work.and3(impl) port map (A(1), A(0), nb0, p3);
  G4 : entity work.or3(impl)  port map (p1, p2, p3, AgtB);
end struct;

Nell'istanziazione si crea un'istanza di un blocco già definito collegando le sue porte ai segnali desiderati con la port map. La mappatura può essere posizionale (l'ordine è quello della entity, come sopra) o per nome (port map (a => A(1), b => nb1, y => p1)).

Tre modi di istanziare un componente

  1. Per componente: si dichiara component nella parte dichiarativa dell'architecture (prima di begin), ripetendo le porte della entity, poi si istanzia:
vhdl
component inv is port (x : in std_logic; y : out std_logic); end component;
...
INV1 : inv port map (input, output);
  1. Diretta: si istanzia scrivendo entity e architecture, entity work.inv(impl), senza dichiarare il componente (più compatta; è quella usata sopra).
  2. Con package: i componenti sono dichiarati in un package che poi si importa con use work.MyPackage.all;.

L'istanziazione è sempre contenuta nell'architecture, mai nella entity.

Livello di astrazione e risultato

stile descrive livello per quando
structural componenti interconnessi basso (schema) gerarchie, controllo diretto della struttura
dataflow equazioni booleane intermedio funzioni logiche compatte
behavioral comportamento alto circuiti complessi, macchine a stati

Una descrizione structural non porta automaticamente a una sintesi migliore di una behavioral (né viceversa): il sintetizzatore ottimizza. I tre stili si possono combinare nello stesso progetto. L'architecture più comune per i circuiti sequenziali è la behavioral (VHDL - macchine a stati finiti e testbench sequenzialeUna macchina a stati finiti (FSM) si descrive in VHDL, in stile behavioral, con un tipo enumerato per gli stati e tre process: (1) registro di stato con reset (asincrono) e aggiornamento state<=next_state sul fronte; (2) stato futuro come funzione combinatoria di stato e ingresso (case state, default next_state<=state); (3) uscita come funzione combinatoria di stato (Moore) o di stato e ingresso (Mealy). Il testbench ha il process del clock e il process degli ingressi (reset iniziale, sequenza di test che percorre tutti gli stati).VHDL - macchine a stati finiti e testbench sequenziale →).

Errori comuni

  • Credere che VHDL sia sequenziale: tutte le assegnazioni concorrenti sono attive insieme.
  • Mettere il ; dopo l'ultima porta nella lista port (...) (va dopo la parentesi chiusa).
  • Dichiarare signal dopo begin (vanno prima).
  • Assegnare un valore a una porta di modo in, o leggere una porta di modo out.
  • Dimenticare di ripetere library/use prima di ogni entity.
  • Mescolare apici e virgolette: '1' per un bit, "1" per un vettore di un bit.

Versione ripasso

Esercizi su questo argomento

Teoria collegata