Vai al contenuto

Verilog

Da Wikipedia, l'enciclopedia libera.
Verilog
linguaggio di programmazione
Data di origine1984
Ultima versioneIEEE 1800-2023
UtilizzoLinguaggio di descrizione dell'hardware
ParadigmiStrutturata
TipizzazioneStatica, debole
Estensioni comuni.v
Influenzato daSystemVerilog

Verilog è un linguaggio di descrizione dell'hardware (HDL) usato per descrivere sistemi elettronici digitali.

Il linguaggio (a volte chiamato Verilog HDL) supporta la progettazione, la verifica, e l'implementazione di circuiti digitali e più raramente di circuiti analogici o circuiti misti analogico-digitali a vari livelli di astrazione. Gli inventori del Verilog volevano un linguaggio con una sintassi simile al C così che fosse familiare agli utilizzatori e facilmente accettato.[senza fonte]

Uno dei metodi più immediati per fare pratica con Verilog è l'utilizzo di board che montano chip FPGA. Tramite i tool forniti dalle case produttrici delle board è possibile sintetizzare il codice e caricare il bitstream sul chip FPGA che implementerà il circuito progettato.

Il principale concorrente è VHDL più moderno ma allo stesso tempo meno immediato da utilizzare[senza fonte].

Caratteristiche

[modifica | modifica wikitesto]

Il linguaggio è case sensitive distingue cioè tra caratteri maiuscoli e caratteri minuscoli, ha un preprocessore come il C, e le maggiori parole chiave di controllo del flusso del programma, come "if" e "while", sono simili ai più noti linguaggio di programmazione. La formattazione delle procedure di stampa, gli operatori del linguaggio e la loro precedenza sono simili al C.

È sbagliato pensare al Verilog come a un linguaggio di programmazione. Infatti l'esecuzione del codice non è sequenziale ma è una descrizione del comportamento che deve assumere un modulo, cioè un componente che costituirà il sistema, per generare delle uscite in risposta a degli ingressi.

Può essere utile confrontare la sintassi con quella del linguaggio C per memorizzare i costrutti. Verilog usa Begin/End invece delle parentesi graffe per definire un blocco di codice. Le costanti in Verilog richiedono di essere specificate in termini di larghezza in numero di bit insieme al tipo di base utilizzata per la definizione. Verilog 95 e 2001 non ha strutture, puntatori, sottoprocedure ricorsive, mentre queste sono presenti nel SystemVerilog che ora include queste capacità. Infine il concetto di time —così importante per l'HDL— non esiste nel C.

Il linguaggio Verilog differisce dai linguaggi di programmazione convenzionali nell'esecuzione delle istruzioni dato che essendo un linguaggio che descrive hardware ogni modulo può essere eseguito parallelamente ad altri.

Un progetto Verilog consiste di una gerarchia di moduli. Ciascuno è definito da un insieme di ingressi e uscite e porte bidirezionali. Internamente contiene una lista di file e registri. Definizione di processi paralleli e sequenziali ne definiscono il comportamento definendo la relazione tra le porte i registri e i file. Le istruzioni sequenziali sono poste all'interno di un blocco begin/end in ordine sequenziale all'interno del blocco.

Tutte le istruzioni concorrenti e tutti i blocchi begin/end sono eseguiti in parallelo. Un modulo può contenere una o più istanze di un altro modulo per definire sotto comportamenti.

La controparte alla compilazione del codice sorgente dei comuni linguaggio di programmazione in Verilog è detta sintesi. Mentre nei linguaggio di programmazione il codice sorgente viene tradotto in codice macchina, sequenze di 1 e di 0 nella sintesi alle istruzioni e ai costrutti corrispondono componenti fisici. Le informazioni tratte dalla sintesi in successivi passo di sviluppo sono tradotte in maschere di layout per la stampa dei circuiti integrati oppure in specifico codice detto bitstream per la programmazione di FPGA.

Un sottoinsieme delle istruzioni del linguaggio è logicamente sintetizzabile. Se il modulo in un disegno contiene soltanto istruzioni sintetizzabili, ovvero non ha dichiarazioni di simulazione, del software può essere utilizzato per trasformare (sintetizzare) il progetto in una lista di componenti (gate o device) e di connessioni tra loro che descrivono i macro blocchi da implementare in hardware. La lista di connessioni (netlist) può essere per esempio in una forma che descrive un circuito integrato di tipo gate array, molto più raramente uno standard cells, (ovvero degli ASIC).

Più comunemente l'uscita è un bitstream utilizzata per un dispositivo programmable logic device (ad esempio, una FPGA).

Il Verilog fu inventato nel 1985 da Phil Moorby presso la Automated Integrated Design Systems (più tardi denominata Gateway Design Automation) come un linguaggio di programmazione dell'hardware. Nel 1990 l'azienda fu comprata da Cadence Design Systems, la quale rese di pubblico dominio il linguaggio, fino ad allora proprietario. Da qui derivò la possibilità di renderlo uno standard, cosa che avvenne con il nome di IEEE 1364, con revisioni nel 1995, 2001 e 2005. Cadence attualmente detiene la proprietà completa dei diritti dei simulatori logici della vecchia Gateway.

Un programma che visualizza "hello world":

module main;
  initial 
    begin
      $display("Hello world!");
      $finish;
    end
endmodule

Il codice sopra è utile solo per la simulazione. Non è possibile sintetizzare con queste istruzioni un circuito che abbia questo comportamento.

Un esempio di 2 flip-flop.

module toplevel(clock, reset);
 input clock;
 input reset;

 reg ff1;
 reg ff2;

 always @ (posedge reset or posedge clock)
 if (reset)
   begin
     ff1 <= 0;
     ff2 <= 1;
   end
 else
   begin
     ff1 <= ff2;
     ff2 <= ff1;
   end
endmodule

L'operatore <= costituisce un altro aspetto del fatto che Verilog è un linguaggio per la descrizione dell'hardware e non un normale linguaggio procedurale. Tale operatore è conosciuto come "assegnazione non bloccante". Quando la simulazione viene eseguita, tutti quei segnali impostati mediante "<=" vengono modificati solo dopo che tutte le istruzioni che avvengono nello stesso momento sono state eseguite. Questo rende più semplice descrivere comportamenti che avvengono simultaneamente.

Nell'esempio sopra, ff1 è assegnato a ff2 e ff2 a ff1. Queste istruzioni sono eseguite durante lo stesso evento temporale. Visto che le assegnazioni sono codificate mediante <=, queste accadono alla fine dell'evento e sino ad allora tutte le letture dei valori di ff1 e ff2 restituiranno il valore all'inizio dell'evento. Questo significa che l'ordine delle assegnazione non è significativo e produrrà gli stessi risultati. ff1 e ff2 si scambieranno i valori a ogni ciclo.

L'altra scelta per l'assegnazione è l'operatore =, conosciuto come "assegnazione bloccante". Quando viene utilizzato, le cose accadono nella sequenza con cui appaiono, come in un linguaggio procedurale.

Nell'esempio sopra, se le assegnazioni avessero fatto uso di = invece di <=, l'ordine con cui compaiono avrebbe influenzato il comportamento: il reset avrebbe impostato ff2 a 1 e ff1 a 0. Al ciclo successivo, ff1 sarebbe stato impostato al valore di ff2, che è 1 dopo il reset. L'istruzione successiva verrebbe stata quindi eseguita, e avrebbe impostato ff2 a ff1, che adesso è pari a 1. Invece di scambiare i valori a ogni ciclo, ff1 e ff2 sarebbero stati impostati a 1 e rimasti così.

Un esempio di contatore:

module Div20x (rst, clk, cet, cep, count,tc);
// TITLE 'Divide-by-20 Counter with enables'
// enable CEP is a clock enable only
// enable CET is a clock enable and
// enables the TC output
// contatore in Verilog

parameter size = 5;
parameter length = 20;

input rst; // questi ingressi/uscite rappresentano
input clk; // connessioni al modulo
input cet;
input cep;

output [size-1:0] count;
output tc;

reg [size-1:0] count; // segnali assegnati
                      // all'interno di un blocco "always"
                      // (o "initial")
                      // devono essere di tipo "reg"
                      
wire tc; // gli altri segnali sono di tipo "wire"

// l'istruzione "always" di seguito indica una
// esecuzione in parallelo che
// avviene ogni volta che i segnali
// "rst" o "clk" effettuano una transizione da basso ad alto

always @ (posedge clk or posedge rst)
  if (rst) // questo causa il reset del contatore
    count <= 5'b0;
  else
  if (cet && cep) // entrambi "true"
    begin
      if (count == length-1)
        count <= 5'b0;
      else
        count <= count + 5'b1; // 5'b1 &egrave 5 bit
    end                        // di dimensione e pari
                               // al valore 1

// a "tc" viene assegnato continuamente
// il valore dell'espressione
assign tc = (cet && (count == length-1));

endmodule

Un esempio di ritardo:

...
reg a, b, c, d;
wire e;
...
always @(b or e)
 begin
   a = b & e;
   b = a | b;
   #5 c = b;
   d = #6 c ^ e;
 end

L'utilizzo della parola-chiave always sopra illustra l'altro metodo di utilizzo, cioè viene eseguita ogni volta che un'entità specificata nella lista cambia nell'esempio b o e. Quando questo avviene, ad a e b sono immediatamente assegnati dei nuovi valori. Dopo 5 unità di tempo, a c è assegnato il valore di b, mentre il risultato di c ^ e viene messo da parte in un'area nascosta. Quindi, dopo altre 6 unità di tempo, questo valore "nascosto" è assegnato a d.

Segnali che partono dall'interno di un processo (un blocco di tipo initial o always devono essere di tipo reg. Segnali che partono dal di fuori di un processo devono essere di tipo wire. La parola-chiave reg non comporta necessariamente un registro hardware.

Collegamenti esterni

[modifica | modifica wikitesto]

Informazioni su Verilog

[modifica | modifica wikitesto]
Controllo di autoritàLCCN (ENsh90004761 · GND (DE4268385-3 · J9U (ENHE987007536924105171