SystemVerilog, standardizzato come IEEE 1800, è un linguaggio di descrizione e verifica dell'hardware utilizzato per modellare, progettare, simulare, testare e implementare sistemi elettronici. SystemVerilog è basato su Verilog ed è comunemente usato nell'industria dei semiconduttori e della progettazione elettronica come evoluzione di Verilog. Dal 2008 Verilog e SystemVerilog fanno parte dello stesso standard IEEE.

Storia SystemVerilog nasce nel 2002, con la donazione del linguaggio Superlog ad Accellera da parte della startup Co-Design Automation.Rich, D. “The evolution of SystemVerilog” IEEE Design and Test of Computers, July/August 2003 La maggior parte delle funzionalità di verifica si basa sul linguaggio OpenVera donato invece da Synopsys. Nel 2005, SystemVerilog è stato adottato come standard IEEE 1800-2005. Nel 2009, lo standard è stato unito allo standard di base Verilog (IEEE 1364-2005), creando lo standard IEEE 1800-2009. La versione attuale è lo standard IEEE 1800-2017.

Il set di funzionalità di SystemVerilog può essere suddiviso in due parti distinte:

SystemVerilog per la progettazione a livello di trasferimento tra registri (RTL): è un'estensione di Verilog-2005 e tutte le funzionalità di quel linguaggio sono disponibili in SystemVerilog. Pertanto, Verilog può essere considerato un sottoinsieme di SystemVerilog. SystemVerilog per la verifica: utilizza estesamente tecniche di programmazione orientate agli oggetti ed è più strettamente correlato a Java piuttosto che a Verilog. Questi costrutti generalmente non sono sintetizzabili.

Il resto di questo articolo discute le caratteristiche di SystemVerilog non presenti in Verilog-2005.

Caratteristiche a supporto della progettazione Durata delle variabili Esistono due tipi di durata delle variabili specificate in SystemVerilog: static e automatic. Le variabili automatiche vengono create nel momento in cui l'esecuzione del programma rientra nello scope della variabile. Le variabili statiche vengono create all'inizio dell'esecuzione del programma e mantengono lo stesso valore durante l'intero ciclo di vita del programma, a meno che non venga assegnato un nuovo valore durante l'esecuzione.

Qualsiasi variabile dichiarata all'interno di un task o di una funzione senza specificare il tipo verrà considerata automatica. Per specificare che una variabile è statica si utilizza la parola chiave static nella dichiarazione del tipo, ad esempio static int x;. La parola chiave automatic viene utilizzata allo stesso modo.

Nuovi tipi di dati I tipi di variabili avanzati aggiungono nuove funzionalità al tipo "reg" di Verilog:logic [31:0] my_var;Verilog-1995 e Verilog-2001 limitano le variabili reg a statement comportamentali come nel caso del codice RTL. SystemVerilog estende il tipo reg in modo che possa essere guidato da un singolo driver come un gate o un modulo. SystemVerilog chiama questo tipo "logic" per ricordare questa capacità ulteriore e che non si tratta di un registro hardware. I nomi "logic" e "reg" sono intercambiabili. Un segnale con più di un driver (come un buffer a tre stati per input/output generico) deve essere dichiarato usando un tipo net come "wire" in modo che SystemVerilog possa risolverne il valore finale.

I Packed array multidimensionali unificano ed estendono la nozione di "registri" e "memorie" di Verilog:logic [1:0][2:0] my_pack;Il Verilog classico consente di dichiarare solo una dimensione a sinistra del nome della variabile. SystemVerilog consente qualsiasi numero di tali dimensioni "impacchettate". Una variabile di tipo array packed mappa 1:1 su una quantità aritmetica intera. Nell'esempio precedente, ogni elemento di my_pack può essere utilizzato nelle espressioni come numero intero a sei bit. Le dimensioni a destra del nome (32 in questo caso) sono indicate come dimensioni "unpacked". Come in Verilog-2001, è consentito qualsiasi numero di dimensioni unpacked.

I tipi di dati enumerati (enums) consentono di assegnare nomi significativi a quantità numeriche. Le variabili dichiarate di tipo enumerato non possono essere assegnate a variabili di un diverso tipo enumerato senza conversione di tipo. Questo non è vero per i parametri, la tecnica di implementazione preferita per le quantità enumerate in Verilog-2005:typedef enum logic [2:0] { RED, GREEN, BLUE, CYAN, MAGENTA, YELLOW } color_t;

color_t my_color = GREEN; initial $display("The color is %s", my_color.name());Come mostrato sopra, il progettista può specificare un tipo aritmetico sottostante (logic [2:0] in questo caso) che viene utilizzato per rappresentare il valore di enumerazione. Possono essere usati meta-valori X e Z, possibilmente per rappresentare stati illegali. La funzione name() restituisce una stringa ASCII per il valore enumerato corrente, utile per la convalida e il test.

Nuovi tipi interi: SystemVerilog definisce byte, shortint, int e longint come tipi interi con segno a due stati con rispettivamente 8, 16, 32 e 64 bit. Un tipo bit è un tipo a due stati a larghezza variabile che funziona in modo molto simile a logic. I tipi a due stati mancano dei metavalori X e Z del Verilog classico; l'uso di questi tipi può consentire una simulazione più veloce.

Le strutture e le unioni funzionano in modo molto simile al linguaggio di programmazione C. I miglioramenti di SystemVerilog includono l'attributo tagged e l'attributo packed. L'attributo tagged consente il monitoraggio in fase di esecuzione di quali membri di un'unione sono attualmente in uso. L'attributo packed fa sì che la struttura o l'unione venga mappata 1:1 su un packed array di bit. I contenuti dei tipi di dati struct occupano un blocco continuo di memoria senza interruzioni, simile ai campi di bit in C e C++:typedef struct packed { bit [10:0] expo; bit sign; bit [51:0] mant; } FP;

FP zero = 64'b0;Come mostrato in questo esempio, SystemVerilog supporta anche typedef, come in C e C++.

Blocchi procedurali SystemVerilog introduce tre nuovi blocchi procedurali destinati a modellare l'hardware: always_comb (per modellare la logica combinatoria), always_ff (per i flip-flop ) e always_latch (per i latch ). Mentre Verilog utilizza un unico blocco generico always per modellare diversi tipi di strutture hardware, ciascuno dei nuovi blocchi di SystemVerilog ha lo scopo di modellare un tipo specifico di hardware, imponendo restrizioni semantiche per garantire che l'hardware descritto dai blocchi corrisponda all'uso previsto del modello. Un compilatore HDL o un programma di verifica può eseguire passaggi aggiuntivi per garantire che si verifichi solo il tipo di comportamento previsto.

Un blocco always_comb modella circuiti logici combinatori. Il simulatore deduce che la sensitivity list sia costituito da tutte le variabili dalle istruzioni contenute:always_comb begin tmp = b * b - 4 * a * c; no_root = (tmp < 0); endUn blocco always_latch modella latch sensibili al livello. Ancora una volta, la sensitivity list è dedotta dal codice:always_latch if (en) q <= d;Un blocco always_ff modella la circuiti sincroni (in particolare circuiti logici sequenziali sensibili al fronte):always_ff @(posedge clk) count <= count + 1;Gli strumenti EDA (Electronic Design Automation) possono verificare l'intento del progetto controllando che il modello hardware non violi alcuna semantica di utilizzo dei blocchi. Ad esempio, i nuovi blocchi limitano l'assegnazione a una variabile consentendo solo una fonte, mentre Verilog blocca always l'assegnazione consentita da più fonti procedurali.

Interfacce Per progetti di piccole dimensioni, le porte Verilog descrivono in modo compatto la connettività di un modulo con l'ambiente circostante. Ma i blocchi principali all'interno di un'ampia gerarchia di progettazione in genere possiedono migliaia di porte. SystemVerilog introduce il concetto di interfacce sia per ridurre la ridondanza delle dichiarazioni dei nomi delle porte tra i moduli collegati, sia per raggruppare e astrarre i segnali correlati in un bundle dichiarato dall'utente. Un concetto aggiuntivo è quello di modport, che mostra la direzione delle connessioni logiche.

Ad esempio:interface intf; logic a; logic b; modport in (input a, output b); modport out (input b, output a); endinterface

module top; intf i (); u_a m1 (.i1(i.in)); u_b m2 (.i2(i.out)); endmodule

module u_a (intf.in i1); endmodule

module u_b (intf.out i2); endmodule

Funzionalità di verifica Le seguenti funzionalità di verifica in genere non sono sintetizzabili, il che significa che non possono essere implementate in hardware sulla base del relativo codice HDL. Esse aiutano invece nella creazione di test bench estensibili e flessibili.

Nuovi tipi di dati Il tipo di dati string rappresenta una stringa di testo di lunghezza variabile. Ad esempio:string s1 = "Hello"; string s2 = "world"; string p = ".?!"; string s3 = {s1, ", ", s2, p}; // string concatenation $display("[%d] %s", s3.len(), s3); // simulation will print: " Hello, world!"Oltre agli array statici utilizzati nella progettazione, SystemVerilog offre array dinamici, array associativi e code:int cmdline_elements; // # elements for dynamic array int da[]; // dynamic array int ai[int]; // associative array, indexed by int int as[string]; // associative array, indexed by string int qa[$]; // queue, indexed as an array, or by built-in methods

initial begin cmdline_elements = 16; da = new[ cmdline_elements ]; // Allocate array with 16 elements endUn array dinamico funziona in modo molto simile a un array unpacked, ma offre il vantaggio di essere allocato dinamicamente in fase di esecuzione (come mostrato sopra). Mentre la dimensione di un packed array deve essere nota in fase di compilazione (da una costante o espressione di costanti), la dimensione dell'array dinamico può essere inizializzata da un'altra variabile, consentendo all'array di essere dimensionato e ridimensionato arbitrariamente secondo necessità.

Un array associativo può essere considerato come un albero di ricerca binario con un tipo della chiave e un tipo dei dati specificati dall'utente. La chiave implica un ordinamento. Gli elementi di un array associativo possono essere letti in ordine lessicografico.

Infine, una coda fornisce gran parte delle funzionalità del tipo deque della Standard Template Library C++: gli elementi possono essere aggiunti e rimossi da entrambe le estremità in modo efficiente. Queste primitive consentono la creazione di strutture di dati complesse, necessarie ad esempio per lo scoreboard di un progetto di grandi dimensioni.

Classi SystemVerilog fornisce un modello di programmazione orientato agli oggetti.

In SystemVerilog, le classi supportano un modello di ereditarietà singola, ma possono implementare funzionalità simili all'ereditarietà multipla attraverso l'uso delle cosiddette "classi di interfaccia" (identiche nel concetto alla funzionalità interface di Java). Le classi possono essere parametrizzate per tipo, fornendo la funzione di base dei template C++. Tuttavia, la specializzazione dei template e le funzioni template non sono supportati.

Le funzionalità di polimorfismo di SystemVerilog sono simili a quelle di C++: il programmatore può definire una funzione virtual per fare in modo che una classe derivata ottenga il controllo della funzione.

L'incapsulamento e l'occultamento dell'informazione (information hiding) vengono eseguiti utilizzando le parole chiave local e protected, che devono essere applicate a qualsiasi elemento che deve essere nascosto. Per impostazione predefinita, tutte le proprietà della classe sono pubbliche.

Le istanze delle classi vengono create dinamicamente con laparola chiave new. È possibile definire un costruttore denotandolo come function new. SystemVerilog implementa la garbage collection, quindi non c'è alcuna funzione del linguaggio per distruggere in modo esplicito le istanze create dall'operatore new.

Ad esempio:virtual class Memory; virtual function bit [31:0] read(bit [31:0] addr); endfunction