Salta al contenuto
Note per Studenti VHDL - struttura, tipi di dato e processi

VHDL - struttura, tipi di dato e processi

In questa pagina 6

Il VHDL (VHSIC hardware description language) è un linguaggio per descrivere circuiti digitali, che si simulano e si sintetizzano su FPGA o ASIC (Simulazione, testbench, vincoli di temporizzazione e flusso su FPGAUn progetto VHDL si verifica per simulazione con un testbench: una entity senza porte che istanzia il circuito sotto test (UUT), genera il clock (process con wait for e inversione), applica gli stimoli e controlla le uscite con assert/report/severity (note, warning, error, failure) o leggendo vettori da file (textio). Il flusso su FPGA è: descrizione VHDL, simulazione funzionale, sintesi (rete di LUT e flip-flop), implementazione (piazzamento e instradamento), analisi di temporizzazione, generazione del bitstream e programmazione della scheda. I vincoli (file XDC) assegnano i pin e definiscono il clock (periodo); l'analisi di temporizzazione verifica per ogni cammino registro-registro lo slack di setup, T − (t_c-q + t_logica + t_routing + t_su), e di hold; con slack negativo la frequenza è troppo alta: f_max = 1/(T − WNS).Simulazione, testbench, vincoli di temporizzazione e flusso su FPGA →). Rispetto al disegno dello schema (design capture), semplice e immediato ma difficile da gestire per sistemi complessi, la descrizione hardware richiede di imparare un linguaggio e dà un'idea delle risorse usate solo dopo la sintesi, ma offre più livelli di astrazione e permette di gestire facilmente progetti gerarchici. Un listato VHDL non rappresenta la sequenza di istruzioni che una FPGA deve eseguire: descrive un hardware, che può essere convertito in uno schema circuitale con un processo di sintesi (Dispositivi logici programmabili - PROM, PLA, PAL e CPLDUn componente logico programmabile (PLD) è un circuito integrato a catalogo la cui funzione logica viene fissata da una programmazione che altera la struttura del circuito (non va confusa con la programmazione software di un microprocessore). I meccanismi sono fusibili, antifusibili (una volta), EPROM/EEPROM/Flash (reversibili e non volatili) e celle SRAM (reversibili ma volatili). Le architetture semplici (SPLD) sono due piani AND-OR: PROM (AND fisso, cioè un decoder di tutti i mintermini, OR programmabile), PLA (entrambi programmabili, dimensione indipendente dal numero di ingressi, più lenta) e PAL (AND programmabile, OR fisso, più veloce). I CPLD sono matrici di blocchi SPLD con interconnessioni programmabili, le FPGA hanno molti blocchi logici piccoli (LUT + registro) in una griglia di interconnessioni complessa, configurata da SRAM.Dispositivi logici programmabili - PROM, PLA, PAL e CPLD →).

Entity e architecture

Ogni modulo ha due parti:

  • la entity descrive l'interfaccia (scatola nera): nome, porte (port) con nome, direzione e tipo; eventualmente parametri (generic);
  • l'architecture descrive l'implementazione interna. Una entity può avere più architetture.
vhdl
entity FULL_ADDER is
  port (A, B, CI : in  bit;
        CO, S    : out bit);
end FULL_ADDER;

architecture RTL of FULL_ADDER is
  signal P, G : bit;           -- parte dichiarativa
begin                          -- parte assertiva
  P  <= A xor B;
  G  <= A and B;
  S  <= P xor CI;
  CO <= (P and CI) or G;
end RTL;

Le direzioni delle porte sono in (sola lettura), out (sola scrittura: un'uscita non può essere letta dentro l'architecture, si usa un segnale interno), inout (bidirezionale, per i bus tri-state: Blocchi logici di un microprocessore - ALU, bus e logica tri-stateUn microprocessore semplice è formato da un'unità di controllo (decodifica le istruzioni e abilita gli altri blocchi), una ALU (operazioni aritmetiche e logiche), la memoria e i registri, collegati da bus (linee condivise unidirezionali o bidirezionali). La ALU combina un sommatore con un'unità logica e un multiplexer di selezione dell'operazione: la sottrazione è A + B̄ + 1 (XOR su B e riporto in ingresso a 1), le flag (zero, riporto, segno, overflow) descrivono il risultato. Un bus è una linea pilotata da più sorgenti: per evitare conflitti ogni uscita collegata è tri-state (il segnale enable la mette in alta impedenza) oppure open-drain (solo PDN: ciascuna può imporre 0, serve un pull-up per l'1).Blocchi logici di un microprocessore - ALU, bus e logica tri-state →). I generic parametrizzano il modulo (per esempio la larghezza NN di un sommatore). VHDL non distingue maiuscole e minuscole, i commenti iniziano con --.

Librerie. Per i tipi logici si dichiarano prima della entity:

vhdl
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;   -- std_logic, std_logic_vector
use IEEE.NUMERIC_STD.ALL;      -- unsigned, signed e aritmetica

(le librerie std_logic_arith e std_logic_unsigned, usate in alcuni esempi, non sono standard: oggi si preferisce numeric_std).

Parte dichiarativa e parte assertiva

L'architecture è divisa da begin in due parti:

  • parte dichiarativa (prima di begin): si dichiarano segnali (signal), costanti, tipi, componenti. Un segnale si definisce qui (non dentro un processo);
  • parte assertiva (tra begin ed end): istruzioni concorrenti (assegnazioni di segnale, istanze di componenti, processi, generate).

Tutte le istruzioni dell'architecture sono concorrenti, cioè rappresentano blocchi hardware che lavorano in parallelo: l'ordine in cui sono scritte (anche dei processi) non modifica il comportamento del circuito (in un linguaggio di programmazione l'ordine conta, qui no). Un'assegnazione concorrente è un caso di processo con tutti gli ingressi nella lista di sensibilità.

Processi

Un process contiene un blocco di istruzioni sequenziali (eseguite in ordine) che viene attivato ogni volta che cambia un segnale della lista di sensibilità:

vhdl
process (A, B, C)             -- lista di sensibilità
begin
  if C = '1' then
    Z <= '0';
  else
    Z <= A nand B;
  end if;
end process;

All'interno si usano if ... elsif ... else, case ... when, cicli for/while, null. Il processo, a differenza dell'architettura, può avere istruzioni a priorità (if/elsif) o senza priorità (case). Esistono anche le assegnazioni concorrenti equivalenti:

vhdl
Z <= C nor (A and B);                         -- semplice
Z <= '0' when C = '1' else A nand B;          -- condizionata (con priorità)
with SEL select Y <= X0 when "00", X1 when "01", X2 when "10", X3 when others;  -- selezionata

Le tre scritture di ZZ sopra (if in un processo, nor concorrente, when-else) descrivono la stessa porta AOI.

Segnali e variabili. Il segnale (<=) rappresenta un filo o un registro: l'assegnazione ha effetto alla fine dell'esecuzione del processo (dopo un ritardo infinitesimo, delta cycle), quindi dentro il processo un segnale conserva il valore precedente finché il processo non termina. La variabile (:=) esiste solo dentro il processo e viene aggiornata subito. Esempio (slide): due architetture

vhdl
process (a) begin x <= a; y <= x; end process;         -- x segnale: y riceve il VECCHIO x
process (a)  variable x : bit := '0';
begin x := a; y <= x; end process;                      -- x variabile: y riceve a

La prima sintetizza due registri/ritardi in cascata, la seconda un filo diretto y=ay=a. Un segnale può essere usato (letto o scritto) dentro un processo ma va dichiarato nella parte dichiarativa dell'architecture.

Simulazione a eventi. Il simulatore mantiene una coda di eventi (timewheel): quando un segnale cambia valore (evento) vengono eseguiti i processi sensibili a quel segnale, che pianificano nuove transazioni. Se il valore assegnato non cambia, non c'è evento e i processi collegati non si riattivano. Si può aggiungere un ritardo (after 2 ns) solo per simulazione: non è sintetizzabile.

Tipi di dato

tipo valori note
bit '0', '1'
boolean false, true risultato dei confronti
integer −231+1…231−1-2^{31}+1\ldots2^{31}-1 natural (≥0\ge0), positive (≥1\ge1)
std_logic 'U','X','0','1','Z','W','L','H','-' 9 valori: non inizializzato, sconosciuto, zero forte, uno forte, alta impedenza, ...
std_logic_vector(N-1 downto 0) array di std_logic bus; non ha operazioni aritmetiche
unsigned, signed array di std_logic numeri con aritmetica (numeric_std)
tipi enumerati type STATE is (idle, counting); stati di una FSM
fisici time (ps, ns, ...) solo simulazione

std_logic è preferito a bit perché modella anche 'Z' (uscite tri-state) e 'X' (conflitto). Costanti letterali: '1'; stringhe di bit "1010" o B"1010", X"A" (esadecimale), O"12" (ottale).

Array e slice. Con signal a : std_logic_vector(3 downto 0); a(3) è il bit più significativo; a(3 downto 2) una fetta; a <= (others => '1') assegna tutti i bit a 11; b & a è la concatenazione. Attributi: x'LENGTH, x'LEFT, x'RIGHT, x'RANGE. Gli operatori sono not and nand or nor xor xnor, = /= < <= > >=, + - * / (su unsigned/signed), sll srl sra rol ror, &.

Esempi

Allarme di auto (VHDL descrittivo): WARNING <= (not DOOR and IGNITION) or (not SBELT and IGNITION);. ALU a 2 bit (esempio di laboratorio) con case Sel is when "00" => Res <= A + B; when "01" => Res <= A + (not B) + 1; when "10" => Res <= A and B; when others => Res <= A or B; end case; (Blocchi logici di un microprocessore - ALU, bus e logica tri-stateUn microprocessore semplice è formato da un'unità di controllo (decodifica le istruzioni e abilita gli altri blocchi), una ALU (operazioni aritmetiche e logiche), la memoria e i registri, collegati da bus (linee condivise unidirezionali o bidirezionali). La ALU combina un sommatore con un'unità logica e un multiplexer di selezione dell'operazione: la sottrazione è A + B̄ + 1 (XOR su B e riporto in ingresso a 1), le flag (zero, riporto, segno, overflow) descrivono il risultato. Un bus è una linea pilotata da più sorgenti: per evitare conflitti ogni uscita collegata è tri-state (il segnale enable la mette in alta impedenza) oppure open-drain (solo PDN: ciascuna può imporre 0, serve un pull-up per l'1).Blocchi logici di un microprocessore - ALU, bus e logica tri-state →).

Errori comuni

  • Pensare che l'ordine delle istruzioni nell'architecture conti: sono concorrenti.
  • Definire un signal dentro un processo (si dichiara nella parte dichiarativa).
  • Leggere dentro l'architecture una porta out.
  • Aspettarsi che un segnale assegnato dentro un processo cambi subito (cambia alla fine del processo; per un valore immediato serve una variabile).
  • Usare after o wait for e credere che si sintetizzino: sono solo per la simulazione.
  • Confondere std_logic_vector (nessuna aritmetica) con unsigned.

Versione ripasso

  • VHDL: descrive un hardware (non istruzioni eseguite da una FPGA); la sintesi lo traduce in schema; più livelli di astrazione, progetti gerarchici.
  • Entity: interfaccia (port: in, out, inout; generic); architecture: implementazione, con parte dichiarativa (segnali, costanti, componenti) prima di begin e parte assertiva (assegnazioni concorrenti, processi, generate) dopo.
  • Concorrenza: tutte le istruzioni dell'architecture sono parallele; l'ordine non conta.
  • Process: istruzioni sequenziali (if, case, cicli), attivato dalla lista di sensibilità. Assegnazioni concorrenti: semplice, when-else (priorità), with-select (senza priorità).
  • Segnale vs variabile: <= alla fine del processo (delta cycle), dichiarato nell'architecture; := immediata, solo nel processo. Esempio x<=a; y<=x (vecchio xx) contro x:=a; y<=x (y=ay=a). Simulazione a eventi.
  • Tipi: bit, boolean, integer, std_logic (99 valori, 'Z', 'X'), std_logic_vector, unsigned/signed (numeric_std), enumerati; array: (others=>'1'), &, attributi.
  • Errori: ordine importante; segnale definito nel processo; lettura di out; segnale immediato; after sintetizzato; std_logic_vector aritmetico.

Esercizi su questo argomento

Teoria collegata