Related
Index
Obbiettivi HDL
2 principali obbiettivi:
- Simulazione: si forniscono gli input e controllando gli output si osserva se il modulo si comporta correttamente
- Sintesi: La descrizione del modulo viene tradotta in un circuito
oss
HDL = hardware description language
Definizione Modulo
Esistono due “stili” per descrivere un modulo:
- Comportamentale: descrive cosa fa un modulo (utilizzando espressioni booleane e controlli condizionali)
- Strutturale: descrive com il circuito interno di un modulo, suddividendolo in moduli più piccoli.
oss
Noi descriveremo i moduli in modo comportamentale
Sintassi Modulo
module name(input logic datatype variables...
...
output logic datatype variables...
...
);
logic datatype variables ...;
assign y = operazione;
endmodule
module
inizializza il moduloname
è il nome che diamo al modulo- dopo
input logic
scriviamo gli input- Data type 2 opzioni:
- Variabile booleana (default, non scrivere niente)
- Bus di bit (scrivere [start:end] dove start ed end indicano la grandezza del bus )
- gli input scritti sulla stessa “linea” sono dello stesso datatype
- se abbiamo più input di tipo diverso scriverli su
input logic
diversi
- Data type 2 opzioni:
- dopo
output logic
scriviamo gli output- Stessa cosa degli input
assign
è usato per assegnare a una variabile un valore o un risultato di un operazione
Variabili logiche
Esistono 3 modi diversi per definire delle variabili:
- Input Logic : Variabili in ingresso (input del modulo)
- Output Logic : variabili in uscita (output del modulo)
- Logic: variabili interne
Esistono 2 tipi di variabili logiche:
- Variabili booleane: variabile che può assumere vero (1) o falso (0)
- Bus: più variabili booleane racchiuse in una sola variabile
Come definire variabili:
logic a, b; // a e b sono variabilie booleane
logic [0:3] c, d; // c e d sono bus a 4 canali
oss
Sostituendo
logic
conlogic input
ologic output
si definiscono rispettivamente gli input e gli output logici
Bus multipli
Un bus è una serie di variabili booleane contenuta in una sola variabile
Definizione base:
[0:3] a
→ bus a 4 bit (dal meno significativoa[0]
al più significativoa[3]
)[4:1] a
→ bus a 4 bit (dal più significativoa[4]
al meno significativoa[1]
)
oss: [0:2] a
⇒ a[0], a[1], a[2]
Bus concatenati
module esempio (logic input a, b,
logic output [0:1] y);
logic c;
assign c = a & b;
assign y = {c, b}; // y[0] = c, y[1] = b
endmodule
b = {a[0], a[1]}
→ bus a 2 bit (b[0] = a[0]
eb[1] = a[1]
)c = {3{a[0]}}
→ bus a 3 bit (copia dia[0]
x 3 volte)d = {3'b110}
→ bus a 3 bit (d[0] = 1
,d[1] = 1
,d[2] = 0
)
oss: leggi Numeri in verilog per capire meglio caso 4
Notazione particolare (tipo slicing python):
- È possibile selezionare alcuni canali di un bus con questa sintassi
module esempio(logic input [0:5] d //bus 6bit dal meno al più significativo
logic output [0:2] x, y, x;). // bus 3 bit
assign x = d[0:2]; // x = {d[0], d[1], d[2]}
assign y = d[2:0]; // x = {d[2], d[1], d[0]}
assign z = d[1:3]; // x = {d[1], d[2], d[3]}
Esempi generali bus:
Esempio 1
module and4_1(input logic [0:3] a, output logic y); assign y = &a; assign y = a[0] & a[1] & a[2] & a[3]; // fanno stessa cosa endmodule
Esempio 2
module and4_1(input logic a0, a1, a2, a3, output logic y); assign y = a0 & a1 & a2 & a3; endmodule
Oss:
Esempio 1 ed Esempio 2 fanno stessa cosa
Numeri in verilog
Operatori
Operatori Logici
module all_logic(input logic a, b,
output logic NOT, AND, OR, XOR, NAND, NOR);
assign NOT = ~a; // NOT
assign AND = a & b; // AND
assign OR = a | b; // OR
assign XOR = a ^ b; // XOR
assign NAND = ~(a & b); // NAND
assign NOR = ~(a | b); // NOR
endmodule
Operatori Bitwise: Questi sono operatori logici Bitwise, ovvero operatori che lavorano su singolo bit o su bus multipli
Esempi:
Esempio 1:
module not_bus(input logic [0:3] a, output logic [0:3] y); assign y = ~a; assign y = {~a[0], ~a[1], ~a[2], ~a[3]}; // fanno stessa cosa endmodule
Esempio 2:
module and_bus(input logic [0:3] a, output logic y); assign y = &a; assign y = a[0] & a[1] & a[2] & a[3]; // fanno stessa cosa endmodule
Esempio 3:
module and4_1(input logic a0, a1, a2, a3, output logic y); assign y = a0 & a1 & a2 & a3; endmodule
Oss:
Esempio 2 e 3 fanno la stessa cosa
Operatori assegnazione continua
- Assign o operatore di assegnazione continua, assegna a una variabile un valore.
- Viene utilizzato per la realizzazioni di reti combinatorie
Assegnare a una variabile true o false:
assign y = 1'b1;
⇒ assegno a y un bit di binario di valore 1assign y = 1'b0;
⇒ assegno a y un bit di binario di valore 0
Assegnare a una variabile attraverso un operazione altre variabili:
assign y = a | b;
Assegnazione tra bus:
assign
{x, y, z} = ~{a, b, c};
⇒ Significato: x = ~a, y = ~b, x = ~c
assign {x, y, z} = ~{a, b, c};
assign x = ~a;
assign y = ~b;
assign z = ~c;
// fanno stessa cosa
Oss:
Ogni volta che cambia a o b il valore di y viene ricalcolato
Assign con ritardo
Sintassi:
'timescale ritardo/precisione
module name(input ..., output ... );
logic ... ;
assign #1 ... ;
assign #2 ... ;
...
assign #n ... ;
endmodule
- Ritardo indica l’unita di tempo del ritardi
- esempio: 1ns (1 nano second), 10ms (10 millisecondi) ecc.
- Precisione indica il possibile errore
- infatti per simulare circuiti reali serve prendere in considerazione anche possibili errori
assign #n
indica dopo quante unita di mistura eseguire l’assegnazione- esempio:
ritardo = 1ns
e alloraassign #1
verra effettuato dopo1ns
eassign #2
dopo2ns
- esempio:
Esempio:
'timescale 1ns/1ps
module esempio(input a, b, c, output x, y);
logic ab, ac, bc;
assign #1 x = a | b | c; //ritardo 1ns + 1ps
assign #2 ab = a & b; //ritardo 2ns + 1ps
assign #2 ac = a & c; //ritardo 2ns + 1ps
assign #2 bc = b & c; //ritardo 2ns + 1ps
assign #4 y = ab | ac | bc; //ritardo 4ns + 1ps
endmodule
Operatore condizionale
- Selezione in base a una condizione la prima o la seconda espressione
Sintassi:
assign y = c? s1 : s2; // y = s1
// c = condizione
// s1 = espressione 1
// s2 = espressione 2
Esempio:
logic c;
assign c = a & b; //c = 1
assign y = c? s1 : s2; // y = s1
assign a = 1'b0; // a = 0
assign c = a & b; //c = 0
assign y = c? s1 : s2; // y = s2
Operatore always
- Istruzione viene eseguita quando è rispettata una condizione
- Viene utilizzate
Sintassi:
always@(sensitivity list)
istruzione
- always@ va sostituito con:
- sensitivity va sostituita con:
posedge
(sensibile al fronte di salita)negedge
(sensibile al fronte di discesa)
- list va sostituito con segale di ingresso, solitamente di usa:
clk
(clock)en
(enable)
always_ff@(sensitivity list)
always_latch@(sensitivity list)
always_comb@(sensitivity list)
always@(posedge clk) //sensibile al fornte di salita
Bloccante e non bloccante: Esistono due tipi di always:
- Non bloccante ⇐ (sequenziale, usato con always_ff e always_latch)
- Bloccante = (combinatoria, usato con always_comb)
Operatore case
Modellazione Strutturale
- Utilizzo di uno p più moduli in un latro modulo
Dope aver definito un modulo con la sentassi
module modulo1(input..., output ...);
...
endmodule
È possibile riutilizzare il modulo in un altro modulo assegnatogli un nome univoco
module modulo2 (input..., output ...);
module modulo1( input_oputput );
//in input_oputput iserire variabili che rispettino la definizione di modulo1
endmodule
Esempio:
mux4:1
costruito utilizzandomux2:1
- Definire
mux2:1
- Definire
mux4:1
module mux2_1(input logic d0, d1, s, output logic y); assign y = s ? d1 : d0; endmodule
module mux4_1(input logic d0, d1, d2, d3, s0, s1, // d bit dati, s bit selezione output logic y); logic basso, alto; //uscite dei mux (mux_alto, mux_basso) mux2_1 muxalto(d0, d1, s0, basso); mux2_1 muxbasso(d2, d3, s0, alto); mux2_1 muxuscita(alto, basso, s1, y); endmodule
Esempio con bus:
mux4:1
costruito utilizzandomux2:1
module mux2(input logic [0:1] d, // bus bit dati input logic s, // bit selezione output logic y); // bit output assign y = s ? d[1] : d[0]; endmodule
module mux4(input logic [0:3] d, input logic [0:1] s, output logic y); logic basso, alto; mux2 muxbalto(d[0:1], s[0], alto); mux2 muxbasso(d[2:3], s[0], basso); mux2 muxuscita({basso, alto}, s[1], y); endmodule
Esercizi:
module ffd(input logic D, clk, output logic Q, not_Q):
always_ff@(posedge clk);
begin
Q <= D;
not_Q <= ~D;
end
endmodule
module circuito(input logic A, clk, logic output [0:1] y);
logic ponte;
ffd ffd_sx(A, clk, y[0], ponte);
ffd ffd_dx(ponte, clk, y[1]);
endmodule
Shift register 8 bit con load e reset asincrono
module mux2-1 (input logic x0, x1, s, output logic y);
assign y = s ? x1 : x0
endmodule
module ffd (logic input d, clk, reset, logic output y);
always@ff(posedege clk or posedge reset)
if(reset) y <= 1b'0
if else y <= d
else q <= {y[6:0], si}
endmodule
module registro (logic input [7:0] x, logic input load, reset, si,
logic output rso);
logic m7, m6, m5, m4, m3, m2, m1, m0; //output mux
logic o7, o6, o5, o4, o3, o2, o1, o0; //output fliplop
mux7(si,x[7],load, m7)
ff7(m7,clk, reset, o7)
mux6(o7,x[6],load, m6)
ff6(m7,clk, reset, o6)
mux5(o7,x[5],load, m5)
ff5(m7,clk, reset, o5)
mux4(rsi,x[4],load, m4)
ff4(m7,clk, reset, o4)
mux3(rsi,x[3],load, m3)
ff3(m3,clk, reset, o3)
mux2(rsi,x[2],load, m2)
ff2(m2,clk, reset, o2)
mux1(rsi,x[1],load, m1)
ff1(m1,clk, reset, o1)
mux0(rsi,x[0],load, m0)
ff0(m0,clk, reset, o0)
endmodule