VLSI Design - Introduzione a Verilog

Verilog è un HARDWARE DESCRIPTION LANGUAGE (HDL). È un linguaggio usato per descrivere un sistema digitale come uno switch di rete o un microprocessore, una memoria o un flip-flop. Significa che utilizzando un HDL possiamo descrivere qualsiasi hardware digitale a qualsiasi livello. I progetti, descritti in HDL, sono indipendenti dalla tecnologia, molto facili per la progettazione e il debug e sono normalmente più utili degli schemi, in particolare per i circuiti di grandi dimensioni.

Verilog supporta un design a molti livelli di astrazione. I tre principali sono:

  • Livello comportamentale
  • Livello di trasferimento del registro
  • Livello del cancello

Livello comportamentale

Questo livello descrive un sistema mediante algoritmi concorrenti (comportamentali). Ogni algoritmo è sequenziale, il che significa che consiste in un insieme di istruzioni che vengono eseguite una per una. Funzioni, compiti e blocchi sono gli elementi principali. Non c'è riguardo alla realizzazione strutturale del progetto.

Livello di trasferimento del registro

I progetti che utilizzano il livello di trasferimento registro specificano le caratteristiche di un circuito utilizzando le operazioni e il trasferimento di dati tra i registri. La definizione moderna di un codice RTL è "Qualsiasi codice sintetizzabile è chiamato codice RTL".

Livello Gate

All'interno del livello logico, le caratteristiche di un sistema sono descritte da collegamenti logici e dalle loro proprietà temporali. Tutti i segnali sono segnali discreti. Possono avere solo valori logici definiti ("0", "1", "X", "Z"). Le operazioni utilizzabili sono primitive logiche predefinite (porte di base). La modellazione a livello di gate potrebbe non essere un'idea corretta per la progettazione logica. Il codice a livello di gate viene generato utilizzando strumenti come strumenti di sintesi e la sua netlist viene utilizzata per la simulazione a livello di gate e per il backend.

Token lessicali

I file di testo di origine della lingua Verilog sono un flusso di token lessicali. Un token è composto da uno o più caratteri e ogni singolo carattere si trova esattamente in un token.

I token lessicali di base utilizzati da Verilog HDL sono simili a quelli del linguaggio di programmazione C. Verilog fa distinzione tra maiuscole e minuscole. Tutte le parole chiave sono in minuscolo.

Spazio bianco

Gli spazi bianchi possono contenere caratteri per spazi, tabulazioni, nuove righe e feed modulo. Questi personaggi vengono ignorati tranne quando servono per separare i gettoni.

I caratteri dello spazio vuoto sono Spazio vuoto, Tabulazioni, Ritorni a capo, Nuova riga e Avanzamenti modulo.

Commenti

Esistono due forme per rappresentare i commenti

  • 1) I commenti su una sola riga iniziano con il token // e finiscono con il ritorno a capo.

Es .: // questa è una sintassi a riga singola

  • 2) I commenti su più righe iniziano con il token / * e finiscono con il token * /

Es .: / * questa è la sintassi multilinea * /

Numeri

È possibile specificare un numero in formato binario, ottale, decimale o esadecimale. I numeri negativi sono rappresentati nei numeri di complimento di 2. Verilog consente numeri interi, numeri reali e numeri con segno e senza segno.

La sintassi è data da - <size> <radix> <value>

La dimensione o il numero non dimensionato possono essere definiti in <Dimensione> e <radice> definisce se è binario, ottale, esadecimale o decimale.

Identificatori

L'identificatore è il nome utilizzato per definire l'oggetto, come una funzione, un modulo o un registro. Gli identificatori devono iniziare con caratteri alfabetici o caratteri di sottolineatura. Ex. A_Z, a_z, _

Gli identificatori sono una combinazione di caratteri alfabetici, numerici, di sottolineatura e $. Possono essere lunghi fino a 1024 caratteri.

Operatori

Gli operatori sono caratteri speciali utilizzati per inserire condizioni o per utilizzare le variabili. Ci sono uno, due e talvolta tre caratteri usati per eseguire operazioni sulle variabili.

Ex. >, +, ~, &! =.

Parole chiave Verilog

Le parole che hanno un significato speciale in Verilog sono chiamate parole chiave Verilog. Ad esempio, assign, case, while, wire, reg, and, or, nand e module. Non dovrebbero essere usati come identificatori. Le parole chiave di Verilog includono anche direttive del compilatore e attività e funzioni di sistema.

Modellazione a livello di gate

Verilog dispone di primitive integrate come porte logiche, porte di trasmissione e interruttori. Questi sono usati raramente per il lavoro di progettazione, ma sono usati nel mondo della post sintesi per la modellazione di cellule ASIC / FPGA.

La modellazione a livello di gate presenta due proprietà:

Drive strength- La forza delle porte di uscita è definita dalla forza motrice. L'output è più forte se c'è una connessione diretta alla sorgente. La forza diminuisce se la connessione avviene tramite un transistor conduttore e almeno quando è collegata tramite un resistivo pull-up / down. La forza del drive di solito non è specificata, nel qual caso i valori predefiniti sono strong1 e strong0.

Delays- Se i ritardi non sono specificati, le porte non hanno ritardi di propagazione; se vengono specificati due ritardi, il primo rappresenta il ritardo di salita e il secondo il ritardo di caduta; se viene specificato un solo ritardo, entrambi, salita e discesa, sono uguali. I ritardi possono essere ignorati in sintesi.

Primitive di Porta

Le porte logiche di base che utilizzano un'uscita e molti ingressi sono utilizzate in Verilog. GATE utilizza una delle parole chiave - and, nand, or, nor, xor, xnor per l'utilizzo in Verilog per N numero di input e 1 output.

Example:  
   Module gate() 
   Wire ot0; 
   Wire ot1; 
   Wire ot2; 
   
   Reg in0,in1,in2,in3; 
   Not U1(ot0,in0); 
   Xor U2(ot1,in1,in2,in3); 
   And U3(ot2, in2,in3,in0)

Primitive del cancello di trasmissione

Le primitive del gate di trasmissione includono sia buffer che inverter. Hanno un ingresso singolo e una o più uscite. Nella sintassi di istanziazione gate mostrata di seguito, GATE sta per la parola chiave buf o NOT gate.

Esempio: Not, buf, bufif0, bufif1, notif0, notif1

Non - n outout inverter

Buf - n buffer di output

Bufifo - buffer tristate, abilitazione bassa attiva

Bufif1 - buffer tristate, abilitazione alta attiva

Notifo - Inverter tristate, abilitazione bassa attiva

Notif1 - inverter tristate, abilitazione alta attiva

Example:  
   Module gate() 
   Wire out0; 
   Wire out1; 
   
   Reg in0,in1;
   Not U1(out0,in0); 
   Buf U2(out0,in0);

Tipi di dati

Valore impostato

Verilog consiste principalmente di quattro valori di base. Tutti i tipi di dati Verilog utilizzati in Verilog memorizzano questi valori:

0 (zero logico o condizione falsa)

1 (uno logico o condizione vera)

x (valore logico sconosciuto)

z (stato di alta impedenza)

l'uso di x e z è molto limitato per la sintesi.

Filo

Un filo viene utilizzato per rappresentare un filo fisico in un circuito e viene utilizzato per il collegamento di porte o moduli. Il valore di un filo può essere solo letto e non assegnato in una funzione o blocco. Un filo non può memorizzare il valore ma è sempre guidato da un'istruzione di assegnazione continua o collegando il filo all'uscita di un cancello / modulo. Altri tipi specifici di fili sono:

Wand (wired-AND) - qui il valore di Wand dipende dall'AND logico di tutti i driver di dispositivo ad esso collegati.

Wor (wired-OR) - qui il valore di un Wor dipende dall'OR logico di tutti i driver di dispositivo ad esso collegati.

Tri (three-state) - qui tutti i driver collegati a un tri devono essere z, tranne uno solo (che determina il valore di tri).

Example: 
   Wire [msb:lsb] wire_variable_list; 
   Wirec // simple wire 
   Wand d; 
   
   Assign d = a; // value of d is the logical AND of 
   Assign d = b; // a and b 
   Wire [9:0] A; // a cable (vector) of 10 wires. 
   
   Wand [msb:lsb] wand_variable_list; 
   Wor [msb:lsb] wor_variable_list; 
   Tri [msb:lsb] tri_variable_list;

Registrati

Un reg (registro) è un oggetto dati, che contiene il valore da un'assegnazione procedurale a quella successiva e viene utilizzato solo in diverse funzioni e blocchi procedurali. Un registro è un semplice Verilog, registro di tipo variabile e non può implicare un registro fisico. Nei registri multi-bit, i dati vengono memorizzati sotto forma di numeri senza segno e l'estensione del segno non viene utilizzata.

Esempio -

reg c; // singola variabile di registro a 1 bit

reg [5: 0] gemma; // un vettore a 6 bit;

reg [6: 0] d, e; // due variabili a 7 bit

Ingresso, uscita, Inout

Queste parole chiave vengono utilizzate per dichiarare le porte di input, output e bidirezionali di un'attività o di un modulo. Qui le porte di input e inout, che sono di tipo wire e la porta di output è configurata per essere di tipo wire, reg, wand, wor o tri. Sempre, l'impostazione predefinita è il tipo di filo.

Example

Module sample(a, c, b, d);  
Input c;   // An input where wire is used. 

Output a, b;  // Two outputs where wire is used. 
Output [2:0] d;  /* A three-bit output. One must declare type in a separate statement. */ 
reg [1:0] a;  // The above ‘a’ port is for declaration in reg.

Numero intero

I numeri interi vengono utilizzati nelle variabili di uso generale. Sono usati principalmente in loop-indicies, costanti e parametri. Sono del tipo di dati di tipo "reg". Memorizzano i dati come numeri firmati mentre i tipi reg dichiarati esplicitamente li memorizzano come dati non firmati. Se il numero intero non è definito al momento della compilazione, la dimensione predefinita sarà 32 bit.

Se un numero intero contiene una costante, il sintetizzatore li regola alla larghezza minima necessaria al momento della compilazione.

Example

Integer c;   // single 32-bit integer 
Assign a = 63;  // 63 defaults to a 7-bit variable.

Supply0, Supply1

Supply0 definisce i fili legati alla logica 0 (massa) e supply1 definisce i fili legati alla logica 1 (alimentazione).

Example

supply0 logic_0_wires; 
supply0 gnd1;  // equivalent to a wire assigned as 0 

supply1 logic_1_wires; 
supply1 c, s;

Tempo

Il tempo è una quantità a 64 bit che può essere utilizzata insieme all'attività di sistema $ time per mantenere il tempo di simulazione. Il tempo non è supportato per la sintesi e quindi viene utilizzato solo per scopi di simulazione.

Example

time time_variable_list; 
time c; 
c = $time;   //c = current simulation time

Parametro

Un parametro definisce una costante che può essere impostata quando si utilizza un modulo, che consente la personalizzazione del modulo durante il processo di istanziazione.

Example 
Parameter add = 3’b010, sub = 2’b11; 
Parameter n = 3; 
Parameter [2:0] param2 = 3’b110; 

reg [n-1:0] jam; /* A 3-bit register with length of n or above. */ 
always @(z) 
y = {{(add - sub){z}};  

if (z)
begin 
   state = param2[1];
else
   state = param2[2]; 
end

Operatori

Operatori aritmetici

Questi operatori eseguono operazioni aritmetiche. I + e − sono usati come operatori unari (x) o binari (z − y).

Gli operatori inclusi nelle operazioni aritmetiche sono:

+ (addizione), - (sottrazione), * (moltiplicazione), / (divisione),% (modulo)

Example -

parameter v = 5;
reg[3:0] b, d, h, i, count; 
h = b + d; 
i = d - v; 
cnt = (cnt +1)%16; //Can count 0 thru 15.

Operatori relazionali

Questi operatori confrontano due operandi e restituiscono il risultato in un singolo bit, 1 o 0.

Le variabili Wire e reg sono positive. Quindi (−3'd001) = = 3'd111 e (−3b001)> 3b110.

Gli Operatori inclusi nell'operazione relazionale sono:

  • == (uguale a)
  • ! = (non uguale a)
  • > (maggiore di)
  • > = (maggiore o uguale a)
  • <(minore di)
  • <= (minore o uguale a)

Example

if (z = = y) c = 1; 
   else c = 0; // Compare in 2’s compliment; d>b 
reg [3:0] d,b; 

if (d[3]= = b[3]) d[2:0] > b[2:0]; 
   else b[3]; 
Equivalent Statement 
e = (z == y);

Operatori bit per bit

Operatori bit per bit che eseguono un confronto bit per bit tra due operandi.

Gli operatori inclusi nell'operazione Bit Wise sono:

  • & (AND bit per bit)
  • | (bitwiseOR)
  • ~ (bit a bit NON)
  • ^ (XOR bit per bit)
  • ~ ^ o ^ ~ (XNOR bit per bit)

Example

module and2 (d, b, c); 
input [1:0] d, b; 
output [1:0] c; 
assign c = d & b; 
end module

Operatori logici

Gli operatori logici sono operatori bit-wise e vengono utilizzati solo per operandi a bit singolo. Restituiscono un singolo valore di bit, 0 o 1. Possono lavorare su numeri interi o gruppi di bit, espressioni e trattare tutti i valori diversi da zero come 1. Gli operatori logici sono generalmente utilizzati nelle istruzioni condizionali poiché lavorano con le espressioni.

Gli operatori inclusi nel funzionamento logico sono:

  • ! (NOT logico)
  • && (AND logico)
  • || (OR logico)

Example

wire[7:0] a, b, c; // a, b and c are multibit variables. 
reg x; 

if ((a == b) && (c)) x = 1; //x = 1 if a equals b, and c is nonzero. 
   else x = !a; // x =0 if a is anything but zero.

Operatori di riduzione

Gli operatori di riduzione sono la forma unaria degli operatori bit per bit e operano su tutti i bit di un vettore operando. Restituiscono anche un valore a bit singolo.

Gli operatori inclusi nell'operazione di riduzione sono:

  • & (riduzione AND)
  • | (riduzione OR)
  • ~ & (riduzione NAND)
  • ~ | (riduzione NOR)
  • ^ (riduzione XOR)
  • ~ ^ o ^ ~ (riduzione XNOR)

Example

Module chk_zero (x, z); 

Input [2:0] x; 
Output z; 
Assign z = & x; // Reduction AND 
End module

Operatori di turno

Operatori di scorrimento, che spostano il primo operando del numero di bit specificato dal secondo operando nella sintassi. Le posizioni libere sono riempite con zeri per entrambe le direzioni, spostamenti a sinistra ea destra (non è prevista l'estensione del segno).

Gli operatori inclusi nell'operazione di turno sono:

  • << (sposta a sinistra)
  • >> (sposta a destra)

Example

Assign z = c << 3; /* z = c shifted left 3 bits;

I posti vacanti sono riempiti con 0 * /

Operatore di concatenazione

L'operatore di concatenazione combina due o più operandi per formare un vettore più grande.

L'operatore incluso nell'operazione di concatenazione è - {} (concatenazione)

Example

wire [1:0] a, h; wire [2:0] x; wire [3;0] y, Z; 
assign x = {1’b0, a}; // x[2] = 0, x[1] = a[1], x[0] = a[0] 
assign b = {a, h}; /* b[3] = a[1], b[2] = a[0], b[1] = h[1], 
b[0] = h[0] */ 
assign {cout, b} = x + Z; // Concatenation of a result

Operatore di replica

L'operatore di replica sta effettuando più copie di un elemento.

L'operatore utilizzato nell'operazione di replica è: {n {item}} (replica n volte di un elemento)

Example

Wire [1:0] a, f; wire [4:0] x; 
Assign x = {2{1’f0}, a}; // Equivalent to x = {0,0,a } 
Assign y = {2{a}, 3{f}}; //Equivalent to y = {a,a,f,f} 
For synthesis, Synopsis did not like a zero replication.

For example:- 
Parameter l = 5, k = 5; 
Assign x = {(l-k){a}}

Operatore condizionale

L'operatore condizionale sintetizza in un multiplexer. È lo stesso tipo utilizzato in C / C ++ e valuta una delle due espressioni in base alla condizione.

L'operatore utilizzato nell'operazione condizionale è:

(Condizione) ? (Risultato se la condizione è vera) -

(risultato se la condizione è falsa)

Example

Assign x = (g) ? a : b; 
Assign x = (inc = = 2) ? x+1 : x-1; 
/* if (inc), x = x+1, else x = x-1 */

Operandi

Letterali

I letterali sono operandi a valori costanti utilizzati nelle espressioni Verilog. I due letterali Verilog comunemente usati sono:

  • String - Un operando letterale stringa è una matrice unidimensionale di caratteri, racchiusi tra virgolette doppie ("").

  • Numeric - Un operando di numero costante è specificato in numero binario, ottale, decimale o esadecimale.

Example

n - numero intero che rappresenta il numero di bit

F - uno dei quattro possibili formati di base -

b per binario, o per ottale, d per decimale, h per esadecimale.

“time is”  // string literal 
267        // 32-bit decimal number 
2’b01      // 2-bit binary 
20’hB36F   // 20-bit hexadecimal number 
‘062       // 32-bit octal number

Fili, reg. E parametri

Fili, registri e parametri sono i tipi di dati utilizzati come operandi nelle espressioni Verilog.

Selezione bit "x [2]" e selezione parte "x [4: 2]"

Le selezioni di bit e le selezioni di parte vengono utilizzate per selezionare rispettivamente un bit e più bit da un filo, un registro o un vettore di parametro con l'uso delle parentesi quadre "[]". Le selezioni di bit e di parte vengono utilizzate anche come operandi nelle espressioni nello stesso modo in cui vengono utilizzati i loro oggetti dati principali.

Example

reg [7:0] x, y; 
reg [3:0] z; 
reg a; 
a = x[7] & y[7];      // bit-selects 
z = x[7:4] + y[3:0];  // part-selects

Chiamate di funzione

Nelle chiamate di funzione, il valore di ritorno di una funzione viene utilizzato direttamente in un'espressione senza la necessità di assegnarlo prima a un registro oa un cavo. Posiziona semplicemente la chiamata di funzione come uno dei tipi di operandi. È necessario per assicurarti di conoscere la larghezza di bit del valore di ritorno della chiamata di funzione.

Example  
Assign x = y & z & chk_yz(z, y); // chk_yz is a function 

. . ./* Definition of the function */ 
Function chk_yz; // function definition 
Input z,y; 
chk_yz = y^z; 
End function

Moduli

Dichiarazione del modulo

In Verilog, un modulo è l'entità di progettazione principale. Indica il nome e l'elenco delle porte (argomenti). Le prossime righe che specificano il tipo di input / output (input, output o inout) e la larghezza di ciascuna porta. La larghezza della porta predefinita è solo 1 bit. Le variabili di porta devono essere dichiarate tramite filo, bacchetta magica ,. . ., reg. La variabile di porta predefinita è wire. Normalmente, gli ingressi sono cablati perché i loro dati sono bloccati all'esterno del modulo. Le uscite sono di tipo reg se i loro segnali sono memorizzati all'interno.

Example

module sub_add(add, in1, in2, out); 
input add; // defaults to wire 
input [7:0] in1, in2; wire in1, in2; 

output [7:0] out; reg out; 
... statements ... 
End module

Assegnazione continua

L'assegnazione continua in un modulo viene utilizzata per assegnare un valore a un filo, che è l'assegnazione normale utilizzata al di fuori dei blocchi sempre o iniziali. Questa assegnazione viene eseguita con un'istruzione di assegnazione esplicita o per assegnare un valore a un filo durante la sua dichiarazione. L'assegnazione continua viene eseguita continuamente al momento della simulazione. L'ordine delle istruzioni assign non lo influenza. Se si modifica un qualsiasi segnale di ingresso sul lato destro, cambierà un segnale di uscita sul lato sinistro.

Example

Wire [1:0] x = 2’y01;   // assigned on declaration 
Assign y = c | d;       // using assign statement 
Assign d = a & b; 
/* the order of the assign statements does not matter. */

Istanze del modulo

Le dichiarazioni dei moduli sono modelli per la creazione di oggetti reali. I moduli vengono istanziati all'interno di altri moduli e ogni istanziazione crea un singolo oggetto da quel modello. L'eccezione è il modulo di primo livello che è la propria istanza. Le porte del modulo devono essere abbinate a quelle definite nel modello. È specificato -

  • By name, utilizzando un punto ".template port name (nome del filo connesso alla porta)". O

  • By position, posizionando le porte nella stessa posizione negli elenchi delle porte sia del modello che dell'istanza.

Example

MODULE DEFINITION 
Module and4 (x, y, z); 
Input [3:0] x, y; 
Output [3:0] z; 
Assign z = x | y; 
End module