RACCOLTA ESERCIZI Modellazione Verilog

Transcript

RACCOLTA ESERCIZI Modellazione Verilog
RACCOLTA ESERCIZI
Modellazione Verilog
Eserciziio 1
Scrivere una
u
descriizione verilog del cirrcuito disegnato in fiigura, dove
e i blocchi hanno la
a
funzionalità descritta
a di seguito
o.
REG: Reg
gistro a 16
6 bit con re
eset (rst) asincrono
a
attivo bassso e con u
un uscita ZERO
Z
che
e
indica se il contenutto del regisstro è pari a zero (ZE
ERO=1 se ili contenutto è zero)
MUX: mulltiplexer co
on due ingrressi a 16 bit, 1 bit dii selezione
e ed un’usccita a 16 biit
c due ing
gressi (ope
erandi A e B) da 16 b
bit, 3 bit dii selezione
e
ALU: unittà aritmeticco/logica con
(Sel[2:0]) un’uscita Y determin
nata dalla tabella
t
seg
guente:
sel[2
[2]
0
0
0
1
1
1
sel[1
1]
0
0
1
0
0
1
sel[[0]
0
1
0
0
1
1
Op
perazioni ALU
A
Operazion
ne
Y<= A
Y<=A+1
Y<=A+B
B
Y<=A and
dB
Y<= A norr B
Y A xnorr B
Y<=
Fun
nzione
Trasfe
ferimento
Increm
menta A
So
omma
AND bit a bit
NOR
R bit a bit
XNOR
R bit a bit
Si scriva un modulo
o per ogni blocco ba
ase (ALU, MUX e REG)
R
ed un
n modulo di più alto
o
livello (myy_MODULE) con l’isttanziazione
e dei tre bllocchi base
e. Si consiglia di imp
plementare
e
la ALU con
c
un un
nico case per quell che rigu
uarda la generazion
g
ne dell’usc
cita Y. Sii
implemen
ntino i 3 mo
oduli base in stile alg
goritmico (tranne
(
eve
entualmen
nte il MUX, per cui sii
lascia sce
elta libera) e, ovviame
ente, quello a più alto
o livello in stile struttu
urale.
ED – Esercizi sulla modellazio
m
one Verilog
g
Massim
mo Barbaro
o
Soluzione
module REG(din, clk, rst, dout, zero);
input clk, rst;
input [15:0] din;
output zero;
output [15:0] dout;
wire clk, rst, zero;
wire [15:0] din;
reg [15:0] dout;
always @(posedge clk or negedge rst)
if(~rst)
dout=16’b0;
else
dout=din;
assign zero=(dout==0)?1:0;
endmodule
module MUX(a, b, sel, out);
input sel;
input [15:0] a,b;
output [15:0] out;
wire sel;
wire [15:0] a,b,out;
assign out=sel?b:a;
endmodule
module ALU(a, b, sel, y);
input [2 :0] sel ;
input [15 :0] a,b ;
output [15:0] y;
wire [2:0] sel;
wire [15:0] a,b;
reg [15:0] y;
always @(a or b or sel)
case(sel)
3’b000: y=a;
3’b001: y=a+1;
3’b010: y=a+b;
3’b100: y=a&b;
3’b101: y=~(a|b);
3’b111: y=a~^b;
default : y=16’bx ;
endcase
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
module my_MODULE (A, B, RST, CLK, SEL, ZERO, Z);
input CLK, RST;
input [3:0] SEL;
input [15:0] A, B;
output ZERO;
output [15:0] Z;
wire CLK, RST, ZERO;
wire [3:0] SEL;
wire [15:0] A, B, Z,outMUX,outALU;
REG i_reg(outALU,CLK,RST,Z,ZERO);
MUX i_mux(B,Z,SEL[3],outMUX);
ALU i_alu(A,outMUX,SEL[2 :0],outALU);
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
Esercizio 2
Scrivere un modello verilog di un registro a 16 bit con i seguenti segnali di ingresso:
din: ingresso parallelo a 16 bit
clk: ingresso di clock attivo sul fronte negativo
rst: ingresso di reset, asincrono, attivo basso
e l’uscita:
dout: uscita a 16 bit
Scrivere inoltre il testbench per testare il funzionamento del modulo, verificando, in
particolar modo, le operazioni di reset e di scrittura. Il testbench dovrà verificare il corretto
funzionamento del reset (che funzioni in modo asincrono) e che la scrittura avvenga solo
in assenza di reset.
Soluzione
module reg16(din, clk, rst, dout);
input clk, rst;
input [15:0] din;
output [15:0] dout;
reg [15:0] dout;
always @(negedge clk or negedge rst)
if(~rst)
dout=16’b0;
else
dout=din;
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
module tb_reg16;
reg clk, rst;
reg [15:0] din;
wire [15:0] dout;
// Istanziazione modulo da testare (UUT)
reg16 UUT(din, clk, rst, dout);
// Generazione clock (periodo 10)
always
#5 clk= ~clk;
initial
begin
clk=1;
// Reset inattivo
rst=1;
din=16’hFFFF;
#5;
// Dopo 5 il clock va basso ed il dato è memorizzato
#3 rst=0;
// Il reset è andato basso ed il registro è resettato
#1 din=16’h00FF;
#16;
// Il clock va bassa ma il dato non viene memorizzato perché il reset è basso
#1 rst=1;
#20 $finish;
end
initial
$monitor($time,,“Din=”,din,,”Clk=”,clk,,”Rst=”,rst,,”Dout=”,dout);
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
Esercizio 3
Dato il modulo verilog descritto nel riquadro successivo:
a) Dire se implementa logica combinatoria o sequnziale e spiegare il perché
b) Data la sequenza di ingressi indicata nel riquadro soluzione (b) tracciare la forma
d’onda d’uscita (si ricordi che inizialmente il valore dei reg è sempre pari a x)
module my_module (A, B, C, Z);
input A, B, C;
output Z;
wire A, B, C;
reg Z;
always @(A or B)
Z=(A|B)&C;
endmodule
a) Tipo di logica
SEQUENZIALE
Perché:
La sensitivity list non è completa. Al variare dell’ingresso C l’always non viene attivato
quindi l’uscita non viene aggiornata. Si vede infatti dalla risposta alla seconda domanda
che l’uscita NON corrisponde alla funzione Z=(A or B) and C ma a qualcosa di diverso.
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
b) Forma d’onda in uscita
A
B
C
Z
t
Z non è uguale a (A or B) and C
Le variazioni di C sono ignorate
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
Esercizio 4
Dato il modulo verilog descritto nel riquadro successivo:
a) Dire se implementa logica combinatoria o sequenziale e spiegare il perché
b) Data la sequenza di ingressi indicata nel riquadro soluzione (b) tracciare la forma
d’onda d’uscita (si ricordi che inizialmente il valore dei reg è sempre pari a x)
module my_module (A, B, C, Z);
input A, B, C;
output Z;
wire A, B, C;
reg Z;
always @(A or B or C)
if(B)
Z=A&C;
endmodule
a) Tipo di logica
Sequenziale
Perché
Non viene sempre assegnato un valore a Z in quanto manca il ramo else del if. In realtà il
modulo rappresenta un latch il cui segnale di ENABLE è il segnale B. Con B alto il latch
memorizza il valore della and fra A e C.
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
b) Forma d’onda in uscita
A
B
C
Z
t
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
Esercizio 5
a) Si scriva il modulo verilog che implementa una ALU con 2 operandi (A, B) ed un
ingresso di selezione a 3 bit (SEL). Le operazioni implementate sono:
sel[2]
0
0
0
1
1
1
sel[1]
0
0
1
0
0
1
sel[0]
0
1
0
0
1
1
Operazioni ALU
Operazione
Y<= A+1
Y<=B+1
Y<=A+B
Y<=A or B
Y<= A xnor B
Y<= A and B
Funzione
Incrementa A
Incrementa B
Somma
OR bit a bit
XNOR bit a bit
AND bit a bit
b) Scrivere un testbench per verificare il corretto funzionamento della ALU al variare
dell’ingresso SEL
a) Implementazione verilog
module ALU(a, b, sel, y);
input [2 :0] sel ;
input [7 :0] a,b ;
output [7:0] y;
wire [2:0] sel;
wire [7:0] a,b;
reg [7:0] y;
always @(a or b or sel)
case(sel)
3’b000: y=a+1;
3’b001: y=b+1;
3’b010: y=a+b;
3’b100: y=a|b;
3’b101: y=~(a^b);
3’b111: y=a&b;
default : y=8’bx ;
endcase
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
b) Testbench
module tb_ALU;
wire [7:0] Y;
reg [7:0] A,B;
reg [2:0] SEL;
// Istanziazione DUT
ALU dut(A,B,SEL,Y);
// Utilizzo un solo initial per verificare tutte le combinazioni di SEL, dovrei verificare
// anche tutti i valori di A e B ma la cosa non è richiesta dal testo dell’esercizio
// quindi inizializzerò A e B con due valori scelti a caso.
// Potrei ovviamente anche utilizzare altri metodi, come un always che genera tutte
// le combinazioni di SEL tramite un ciclo FOR.
initial
begin
A=4;
B=5;
SEL=3’b000;
#5 SEL=3’b001;
#5 SEL=3’b010;
#5 SEL=3’b011;
#5 SEL=3’b100;
#5 SEL=3’b101;
#5 SEL=3’b110;
#5 SEL=3’b111;
#5 $finish;
end
// Monitor dei risultati
initial
$monitor( “SEL=%b A=%b B=%b => Y=%b\n“,SEL,A,B,Y);
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
Esercizio 6
Realizzare un modulo verilog che implementi un registro contatore. Il registro ha i seguenti
ingressi:
Ingressi
Nome
Numero di bit
Funzione
8
Ingresso parallelo
din
1
Segnale di reset, asincrono, attivo basso
clear
1
Segnale di clock
clk
1
Segnale di selezione dell’operazione di conteggio
count
1
Segnale di selezione dell’operazione di caricamento parallelo
load
e le seguenti uscite:
Uscite
Nome
Numero di bit
Funzione
8
Uscita parallela (contenuto del registro contatore)
dout
1
Uscita (combinatoria) pari a 1 quando il contatore è abilitato
co
a contare ed il suo contenuto è pari a 8’hFF (tutti 1)
Il reset (clear) è attivo basso ed asincrono. In assenza di reset, ad ogni colpo di clock, se
load=1 il registro memorizza il dato parallelo in ingresso (din), altrimenti se count=1 il
contatore è abilitato a contare ed il suo contenuto viene incrementato di 1. L’uscita co è
un’uscita combinatoria pari a 1 solo quando il contatore è abilitato a contare ed il registro
contiene tutti 1.
Soluzione
module counter(din, clk, clear, load, count, dout, co);
input clk, clear, load, count;
input [7:0] din;
output co;
output [7:0] dout;
wire clk, load, count, clear, co;
wire [7:0] din;
reg [7:0] dout;
// Parte combinatoria
assign co=(~load)&(count)&(dout==8’b11111111);
// Parte sequenziale (registro)
always @(posedge clk or negedge clear)
if(~clear)
dout=0;
else
if(load)
dout=din;
else
if(count)
dout=dout+1’b1;
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
Esercizio 7
Implementare la descrizione verilog di un modulo digitale costituito da due sottocircuiti:
una ALU ed un registro.
La ALU ha un’uscita a 8 bit (Y) ed in ingresso due operandi a 8 bit (A e B) ed un ingresso
di selezione (SEL) a 3 bit che definisce le seguenti operazioni:
sel[2]
0
0
0
1
1
1
sel[1]
0
0
1
0
1
1
sel[0]
0
1
0
0
0
1
Operazioni ALU
Operazione
Y<= A+1
Y<=A+B
Y<=A-B
Y<=A or B
Y<= A xnor B
Y<= A nand B
Funzione
Incrementa A
Somma
Differenza
OR bit a bit
XNOR bit a bit
NAND bit a bit
Il registro ha un ingresso D a 8 bit, l’ingresso di clock (CLK), un ingresso di reset (RST)
sincrono attivo alto ed un uscita Q a 8 bit.
Il modulo digitale da implementare è mostrato in Figura, se ne richiede una descrizione
gerarchica, quindi vanno realizzati due moduli distinti per la ALU e per il registro e poi
istanziati in un modulo ad più alto livello di gerarchia (denominato MY_MOD).
opA
MY_MOD
ALU
opB
opSel
clk
rst
CLK
REG
RST
out
Si richiede inoltre di scrivere un testbench che effettui la seguente sequenza di operazioni:
Reset del registro e predisposizione degli operandi della ALU rispettivamente con
A=8’hA0 e B=8’h22
Somma di A e B e memorizzazione
Differenza di A e B e memorizzazione
Or bit a bit di A e B e memorizzazione
Ogni operazione è svolta in corrispondenza di un colpo di clock.
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
Moduli
module ALU(A, B, SEL, Y);
input [2 :0] SEL ;
input [7 :0] A,B ;
output [7:0] Y;
wire [2:0] SEL;
wire [7:0] A,B;
reg [7:0] Y;
always @(A or B or SEL)
case(SEL)
3’b000: Y=A+1;
3’b001: Y=A+B;
3’b010: Y=A-B;
3’b100: Y=A|B;
3’b101: Y=~(A^B);
3’b111: Y=~(A&B);
default : Y=8’bx ;
endcase
endmodule
module REG(D, CLK, RST, Q);
input CLK, RST;
input [7 :0] D;
output [7:0] Q;
wire [7:0] D;
wire CLK, RST;
reg [7:0] Q;
always @(posedge CLK)
if(RST)
Q=8’b0;
else
Q=D ;
endmodule
module MY_MOD(opA, opB, sel, clk, rst, out);
input clk, rst;
input [7:0] opA, opB;
input [2:0] sel;
output [7:0] out;
wire clk, rst;
wire [2:0] sel;
wire [7:0] opA, opB, int_Y, out;
// Istanziazione ALU
ALU i_alu(opA, opB, sel, int_Y);
// Istanziazione registro
REG i_reg(int_Y, clk, rst, out);
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
Testbench
Testbench
module tb_my_mod;
reg clk, rst;
reg [2:0] sel;
reg [7:0] opA, opB;
wire [7:0] out;
// Istanziazione modulo
MY_MOD dut(opA, opB, sel, clk, rst, out);
// Generazione clock
always
begin
clk=0; #5 clk=1; #5 clk=0;
end
// Sequenza operazioni
initial
begin
rst=1;
// Al primo colpo di clock ($time=5) il registro è resettato (rst=1)
#7 rst=0; sel=3’b001; opA=8’hA0; opB=8’h22; // Eseguito a $time=7
// Al secondo colpo di clock ($time=15) viene effettuata la somma
#10 sel=3’b010; // Questo assegnamento è eseguito a $time=17
// Al terzo clock ($time=25) viene effettuata la differenza
#10 sel=3’b100; // Questo assegnamento è eseguito a $time=27
// Al quarto clock ($time=35) OR bit a bit
#10 $stop;
end
// Monitor risultati
initial
$monitor(“$time,,opA,,opB,,sel,,clk,,rst,,out);
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
Esercizio 8
Scrivere il modulo verilog che implementa un priority encoder. Il priority encoder è un
codificatore (blocco combinatorio) che prende in ingresso N bit e mette in uscita M=log2N
bit che rappresentano la codifica binaria di quale fra i bit di ingresso è attivo (basso).
Se più di un bit in ingresso è basso utilizzare una priorità crescente (i bit meno significativi
hanno priorità maggiore dei bit più significativi, quindi se ad esempio il bit 2 ed il bit 5 sono
entrambi bassi l’uscita è la codifica binaria di 2). Utilizzare come dimensioni N=8.
Si scriva un opportuno testbench che testi tutte le possibili combinazioni di ingresso.
Soluzione
module pri_enc8(IN, OUT);
input [7:0] IN;
output [2:0] OUT;
wire [7:0] IN;
reg [2:0] OUT;
always @(IN)
casex(IN)
8’bxxxxxxx0: OUT=0;
8’bxxxxxx01: OUT=1;
8’bxxxxx011: OUT=2;
8’bxxxx0111: OUT=3;
8’bxxx01111: OUT=4;
8’bxx011111: OUT=5;
8’bx0111111: OUT=6;
8’b01111111: OUT=7;
default:
OUT=8’bx;
endcase
endmodule
module tb_pri_enc8;
reg [7:0] in;
wire [2:0] out;
integer i;
pri_enc8 UUT(in, out);
initial
begin
for(i=0; i<256;i=i+1)
#5 in=i;
#5 $stop;
end
initial
$monitor($time,,in,,out);
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
Esercizio
o9
Scrivere un
u modulo verilog (M
MY_DP) che
e implementi lo schematico nellla Figura seguente.
s
Il modulo,, nel suo complesso
c
, ha gli ing
gressi: opA
A[15:0], op
pB[15:0], o
opC[7:0], s[[4:0], rst e
clk e le uscite
u
Y[15
5:0] e resC
COMP. Sccrivere un testbench che eseg
gue, in seq
quenza, le
e
seguenti operazioni
o
: 1) reset del registro 2) somm
ma di opA=
=2 e opB=5
5 e memo
orizzazione
e
3) xor bit a bit del co
ontenuto del registro e di opB=2
20 e memo
orizzazione
e
MUX: Multiplexer co
on 2 ingresssi a 16 bit, 1 ingres
sso di selezzione a sin
ngolo bit (in Figura è
indicato quale
q
dei due
d ingresssi deve passare a se
econda del valore de
el bit di sellezione), 1
uscita ad 16 bit
ALU: Uniità logico/a
aritmetica con due operandi
o
A e B (16
6 bit) e 3 bit di sele
ezione che
e
determina
ano le operrazioni com
me segue (l’operando
(
o A è quello di sinistrra in Figura
a):
S
Sel[2:0]
Ope
erazione
000
Tras
sferimento di A in usccita
001
A+B
B
011
A-B
100
xor bit
b a bit
101
and bit a bit
110
nor bit a bit
COMP: Un
U modulo COMBINA
ATORIO che
c
con du
ue ingresssi A e B (1
16 bit) e le
e uscite Y
(16bit) e resCOMP
r
(1bit). Y è sempre uguale
u
al maggiore
m
frra A e B m
mentre resC
COMP è 1
se A è strrettamente maggiore di B (A è l’ingresso di
d sinistra in
i Figura)
REG: Reg
gistro a scorrimento a 16 bit co
on un ingre
esso di resset (rst) sin
ncrono attiv
vo alto, un
n
clock (clk) attivo sull fronte negativo ed un ingress
so di shift (sh). Finch
hé sh è altto, ad ognii
colpo di clock,
c
il contenuto de
el registro scorre di una
u posizione verso sinistra, altrimenti
a
ill
contenuto
o del registtro viene ag
ggiornato col
c dato in ingresso.
ED – Esercizi sulla modellazio
m
one Verilog
g
Massim
mo Barbaro
o
Modulo MUX
module MUX(A,B,sel,Y);
input sel;
input [15:0] A,B;
output [15:0] Y;
wire sel;
wire [15:0] A,B;
reg [15:0] Y;
always @(A or B or sel)
if(sel)
Y=A;
else
Y=B;
endmodule
Modulo ALU
module ALU(A,B,sel,Y);
input [2:0] sel;
input [15:0] A,B;
output [15:0] Y;
wire [2:0] sel;
wire [15:0] A,B;
reg [15:0] Y;
always @(A or B or sel)
case (sel)
3’b000: Y=A;
3’b001: Y=A+B;
3’b011: Y=A-B;
3’b100: Y=A^B;
3’b101: Y=A&B;
3’b110: Y=|(A|B);
default: Y=16’bX;
endcase
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
Modulo COMP
module COMP(A,B,Y,resCOMP);
input [15:0] A,B;
output resCOMP;
output [15:0] Y;
wire [15:0] A,B;
reg resCOMP;
reg [15:0] Y;
always @(A or B)
begin
Y=B;
resCOMP=0;
if(A>B)
begin
Y=A;
resCOMP=1;
end
end
endmodule
Modulo REG
module REG(clk,rst,sh,Din,Dout);
input clk,rst,sh;
input [15:0] Din;
output [15:0] Dout;
wire clk,rst,sh;
wire [15:0] Din;
reg [15:0] Dout;
always @(negedge clk)
if(rst)
Dout=16’b0;
else
if(sh)
Dout=Dout<<1;
else
Dout=Din;
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
Modulo MY_DP (top)
module MY_DP(clk, rst, s, opA, opB, opC, Y, resCOMP);
input clk, rst;
input [4:0] s;
input [15:0] opA,opB,opC;
output resCOMP;
output [15:0] Y;
wire clk, rst, resCOMP;
wire [4:0] s;
wire [15:0] opA,opB,opC,Y,outMUX,outALU,ooutCOMP;
MUX i_mux(opA,Y,s[3],outMUX);
ALU i_alu(outMUX, outCOMP, s[2:0], outALU);
COMP i_comp(opB,opC,outCOMP,resCOMP);
REG i_reg(clk,rst,s[4],outALU,Y);
endmodule
Testbench
module tb_MY_DP;
reg clk, rst;
reg [4:0] s;
reg [15:0] A,B,C;
wire resCOMP;
wire [15:0] Y;
// Istanziazione modulo
MY_DP UUT(clk,rst,s,A,B,C,Y,resCOMP);
// Generazione clock
always
begin clk=0; #5 clk=1;
#5 clk=0;
end
// Stimoli
initial
begin
$monitor($time,,clk,,rst,,s,,A,,B,,C,,Y,,resCOMP);
rst=1;
#12 A=2; B=5; C=0; s=5’b01001;
#10 B=20; s=5’b00100;
#10 $stop;
end
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
Esercizio 10
Dato il modulo verilog seguente:
module MY_MOD(A,B,C,Z);
input A,B,C;
output Z;
wire A,B,C,Z;
reg Z_int;
always @(A or B)
case ({A,B})
2’b00: Z_int = 0;
2’b01: Z_int = 1;
2’b10: Z_int = 1;
endcase
assign Z = Z_int & C;
endmodule
a) Dire se implementa logica combinatoria o sequenziale e spiegare perché
b) Completare il grafico della pagina successiva disegnando la forma d’onda Z
c) Scrivere un testbench per verificare il funzionamento del modulo con gli ingressi definiti
nel grafico della pagina successiva
a) Tipo di logica
La logica è evidentemente sequenziale perché l’always, sebbene abbia, correttamente, la
sensitivity list completa (vi compaiono A e B che sono gli unici ingressi che influenzano
l’always) contiene un case incompleta che non contempla tutte le combinazioni (manca
A=1, B=1). Perciò, quando A=1, B=1 l’uscita Z_int non viene aggiornata e quindi non viene
aggiornata neanche Z. Dunque in presenza di A=1, B=1 la porta (se C=1) mantiene il
valore di uscita assunto con la combinazione precedente quindi dipende dalla sequenza
degli ingressi.
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
b) Uscita
A
B
C
A seconda del simulatore l’uscita fra 0 e 1 potrebbe anche
essere pari a 0 (anzi che X) a seconda che gli assegnamenti fatti
nel testbench all’istante 0 siano presi come variazioni oppure no
Disegnare qua l’uscita Z
Z
0
1
2
3
4
5
6
7
8
Time (nsec)
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
c) Testbench
module tb;
reg A,B,C;
wire Z;
// Istanziazione Unit Under Test
MY_MOD UUT(A,B,C,Z);
initial
begin
// Monitor dei risultati
$monitor($time,, A,B,C,,Z);
A=0;
B=0;
C=1;
#1 B=1;
#1 A=1;
#1 B=0;
#1 A=0;
#1 A=1; B=1;
#1 B=0; C=0;
#1 A=0;
#2 $stop;
end
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
Esercizio
o 11
Si scriva la descrizzione verillog, in stille algoritm
mico/RTL, di una rette COMBIINATORIA
A
chiamata display7 con
c gli ingre
essi e le usscite mostrate in Figu
ura.
Quando la rete è abilitata dal segna
ale EN, pilota un display
d
a sette segmenti perr
visualizza
are quale, fra le 10 linee di ing
gresso (A[9
9:0]), risultta alta. Se
e più di un
na linea in
n
ingresso risultasse
r
alta, sul display verrrà visualizz
zato il num
mero corrisspondente a quella a
massima priorità do
ove la priorità è defin
nita dalla sequenza
s
0246813579 (quindi la linea 0
ha massim
ma priorità, poi viene
e la linea 2, poi la 4, la 6, la 8, la
a 1, la 3 e così via). Quando
Q
la
a
rete è dissabilitata (EN=0), op
ppure quan
ndo nessu
una delle linee in ing
gresso è alta,
a
viene
e
visualizza
ato sul disp
play un tratttino (-).
La codifica del display a sette segmenti è data in fiigura:
egmento de
el display è acceso se
s il segnale che lo p
pilota è bas
sso (0). E’’
Si ricorda che un se
mentazione gerarchicca che se
epari il mo
odulo per l’identifica
azione dell
richiesta un’implem
segnale in
n ingresso attivo (pri_
_enc10) da
al modulo che
c pilota il display (driver7seg
g).
ED – Esercizi sulla modellazio
m
one Verilog
g
Massim
mo Barbaro
o
Modulo verilog
// Priority-encoder
module pri_enc10(A,Z,idle);
input [9:0] A;
output idle;
output [3:0] Z;
reg idle;
reg [3:0] Z;
always @(A)
begin
idle=0;
casex (A)
10'bxxxxxxxxx1: Z=4'b0000;
10'bxxxxxxx1x0: Z=4'b0010;
10'bxxxxx1x0x0: Z=4'b0100;
10'bxxx1x0x0x0: Z=4'b0110;
10'bx1x0x0x0x0: Z=4'b1000;
10'bx0x0x0x010: Z=4'b0001;
10'bx0x0x01000: Z=4'b0011;
10'bx0x0100000: Z=4'b0101;
10'bx010000000: Z=4'b0111;
10'b1000000000: Z=4'b1001;
default: begin
Z=4'bxxxx;
idle=1;
end
endcase
end
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
// Driver display a 7 segmenti
module driver7seg(EN,A,a,b,c,d,e,f,g);
input EN;
input [3:0] A;
output a,b,c,d,e,f,g;
wire EN;
wire [3:0] A;
reg a,b,c,d,e,f,g;
// La visualizzazione delle cifre si basa sullo schema seguente
//
// aaaaa
a=1 (segmento spento)
// f b
a=0 (segmento acceso)
// f b
// f b
// ggggg
// e c
// e c
// e c
// ddddd
//
// Quindi la codifica in uscita dei segnali a,b,c,d,e,f,g è:
//
// A=0 A=1 A=2 A=3 A=4 A=5 A=6 A=7 A=8 A=9
//
//
00 11 00 00 11 00 00 00 00 00
// 0 0 1 0 1 0 1 0 0 0 0 1 0 1 1 0 0 0 0 0
// 0 0 1 0 1 0 1 0 0 0 0 1 0 1 1 0 0 0 0 0
//
11 11 00 00 00 00 00 11 00 00
// 0 0 1 0 0 1 1 0 1 0 1 0 0 0 1 0 0 0 1 0
// 0 0 1 0 0 1 1 0 1 0 1 0 0 0 1 0 0 0 1 0
//
00 11 00 00 11 00 00 11 00 00
//
always @(EN or A)
if(EN)
case (A)
0: {a,b,c,d,e,f,g}=7'b0000001;
1: {a,b,c,d,e,f,g}=7'b1001111;
2: {a,b,c,d,e,f,g}=7'b0010010;
3: {a,b,c,d,e,f,g}=7'b0000110;
4: {a,b,c,d,e,f,g}=7'b1001100;
5: {a,b,c,d,e,f,g}=7'b0100100;
6: {a,b,c,d,e,f,g}=7'b0100000;
7: {a,b,c,d,e,f,g}=7'b0001111;
8: {a,b,c,d,e,f,g}=7'b0000000;
9: {a,b,c,d,e,f,g}=7'b0000100;
default: {a,b,c,d,e,f,g}=7'bxxxxxxx;
endcase
else
{a,b,c,d,e,f,g}=7'b1111110;
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
// Modulo DISPLAY, VERSIONE GERARCHICA
module DISPLAY_hierarchy(EN,A,a,b,c,d,e,f,g);
input EN;
input [9:0] A;
output a,b,c,d,e,f,g;
wire EN,ENdriver,a,b,c,d,e,f,g,idlePRI;
wire [3:0] outPRI;
wire [9:0] A;
// Ho scelto di visualizzare l'uscita nel
// caso in cui nessun ingresso è valido con
// un trattino, come nel caso in cui EN=0.
// In questo modo, il driver del display deve
// essere NON abilitato (ENdriver=0) quando il modulo NON è selezionato (EN=0)
// OPPURE l'encoder è inattivo (idlePRI=1)
assign ENdriver = ~ ( ~EN | idlePRI );
// Istanziazione priority-encoder
pri_enc10 i_enc(A,outPRI,idlePRI);
// Istanziazione driver 7 segmenti
driver7seg i_driver(ENdriver,outPRI,a,b,c,d,e,f,g);
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
Esercizio 12
Dato il modulo verilog seguente:
module MY_MOD(A,B,C,Z);
input A,B,C;
output Z;
wire A,B,C,Z;
reg Z_int;
always @(A or B)
case ({A,B})
2’b00: Z_int = 0;
2’b01: Z_int = 1;
2’b10: Z_int = 1;
endcase
assign Z = Z_int | C;
endmodule
a) Dire se implementa logica combinatoria o sequenziale e spiegare perché
b) Completare il grafico della pagina successiva disegnando la forma d’onda Z
c) Scrivere un testbench per verificare il funzionamento del modulo con gli ingressi definiti
nel grafico della pagina successiva
a) Tipo di logica
Logica sequenziale, infatti il case non è completo dunque esiste una combinazione di
ingresso per cui non è definito un nuovo valore di Z_int che memorizza quindi il valore
precedentemente assunto.
Se Z_int ha comportamento sequenziale lo ha di conseguenza anche Z che è ottenuta
combinatoriamente da Z_int stesso.
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
b) Uscita
A
B
C
A seconda del simulatore l’uscita fra 0 e 1 potrebbe anche
essere pari a 1 (anzi che X) a seconda che gli assegnamenti fatti
nel testbench all’istante 0 siano presi come variazioni oppure no
Disegnare qua l’uscita Z
Z
0
1
2
3
4
5
6
7
8
Time (nsec)
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
c) Testbench
module tb;
reg A,B,C;
wire Z;
// Istanziazione Unit Under Test
MY_MOD UUT(A,B,C,Z);
initial
begin
// Monitor dei risultati
$monitor($time,, A,B,C,,Z);
A=0; B=0; C=1;
#1 A=0; B=0; C=1;
#1 A=0; B=1; C=1;
#1 A=1; B=1; C=1;
#1 A=1; B=0; C=1;
#1 A=0; B=0; C=1;
#1 A=1; B=1; C=1;
#1 A=1; B=0; C=0;
#1 A=0; B=0; C=0;
#1 $stop;
end
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
Esercizio 13
a) Dare una descrizione verilog di un modulo MY_MOD in grado di prendere in ingresso
un dato (D) a 8 bit e memorizzarlo sul fronte positivo del clock (clk) dopo averne fatto uno
shift verso destra o verso sinistra a seconda del valore del segnale di ingresso dir_shift (se
dir_shift è 1 lo shift è verso destra, se dir_shift è 0 verso sinistra). Un quarto ingresso
pos_shift stabilisce di quante posizioni dovrà essere effettuato lo shift (il numero massimo
di posizioni di shift è ovviamente pari al numero di bit del registro). Lo shift è di tipo
aritmetico quindi vengono inseriti degli zeri per riempire le posizioni rimaste vuote nel caso
che lo shift sia fatto a sinistra, se invece lo shift viene fatto verso destra bisogna
mantenere il segno del dato in ingresso (rappresentato in complemento a 2). Infine, il
modulo dovrà prevedere un ingresso di reset asincrono attivo basso in grado di azzerare il
dato memorizzato. E’ preferibile una descrizione gerarchica, che separi la parte
combinatoria di shift da quella sequenziale di memorizzazione in due moduli separati.
b) Scrivere un testbench per verificare le seguenti operazioni (un’operazione per
colpo di clock):
1) Scrittura nel registro del dato D=16
2) Scrittura nel registro di D=-24 shiftato a sinistra di 2 posizioni
3) Scrittura nel registro di D=1 shiftato a destra di 1 posizione
4) Reset del registro
5) Scrittura nel registro di D=3 shiftato a destra di 3 posizioni
a) Modulo
// Modulo top
module MY_MOD(clk, rst, dir_shift, pos_shift, D, Q);
input clk, rst, dir_shift;
input [2:0] pos_shift;
input [7:0] D;
output [7:0] Q;
wire [7:0] outshift;
// Istanziazione shifter
shifter I_SH(dir_shift, pos_shift, D, outshift);
// Istanziazione registro
reg8 I_REG(clk, rst, outshift, Q);
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
// Modulo shifter
module shifter(dir_shift, pos_shift, D, out);
input dir_shift;
input [2:0] pos_shift;
input [7:0] D;
output [7:0] out;
reg [7:0] out;
always @(dir_shift or pos_shift or D)
if(dir_shift)
case(pos_shift)
0: out = D;
1: out = {1{D[7]},D[7:1]};
2: out = {2{D[7]},D[7:2]};
3: out = {3{D[7]},D[7:3]};
4: out = {4{D[7]},D[7:4]};
5: out = {5{D[7]},D[7:5]};
6: out = {6{D[7]},D[7:6]};
7: out = {7{D[7]},D[7]};
endcase // Non c’è bisogno del default perché ho elencato tutti i casi possibili
else
case(pos_shift)
0: out = D;
1: out = {D[6:0],1’b0};
2: out = {D[5:0],2’b0};
3: out = {D[4:0],3’b0};
4: out = {D[3:0],4’b0};
5: out = {D[2:0],5’b0};
6: out = {D[1:0],6’b0};
7: out = {D[0],7’b0};
endcase // Non c’è bisogno del default perché ho elencato tutti i casi possibili
endmodule
module reg8(clk, rst, D, Q);
input clk, rst;
input [7:0] D;
output [7:0] Q;
reg [7:0] Q;
// Registro, reset asincrono attivo alto
always @(posedge clk or posedge rst)
if(rst)
Q=8’b0;
else
Q=D;
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
b) Testbench
module tb_MY_MOD;
reg clk, rst, dir_shift;
reg [2:0] pos_shift;
reg [7:0] D;
wire [7:0] Q;
// Istanziazione Unit Under Test
MY_MOD UUT(clk,rst, dir_shift, pos_shift, D, Q);
// Generazione clock
always // clk deve essere inizializzato a 0!!!!!!
#5 clk=~clk;
// Generazione stimoli e visualizzazione risultati
initial
begin
// Monitor dei risultati
$monitor($time,, clk,,rst,,dir_shift,,pos_shift,,D,,,,Q);
clk=0; rst=0; dir_shift=0; pos_shift=0; D=16;
// Aspetto il clock (arriva a 5) e memorizzo D (pos_shift=0)
#6 dir_shift=0; pos_shift=2; D=-24;
#5 dir_shift=1; pos_shift=1; D=1;
#4 rst=1;
#2 rst=0; dir_shift=1; pos_shift=3; D=3;
#5 $stop;
end
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
Esercizio 14
a) Scrivere il modulo verilog che implementa uno shifter (COMBINATORIO). Lo shifter ha
un ingresso D a 16 bit, un ingresso dir_shift a 1 bit, un ingresso pos_shift a 2 bit. L’uscita Y
è a 16 bit e rappresenta l’ingresso D spostato di un numero di posizioni pari a quello
indicato da pos_shift verso destra (se dir_shift è 1) oppure verso sinistra se (dir_shift è 0).
Lo shift è di tipo logico quindi vengono inseriti degli zeri per riempire le posizioni rimaste
vuote.
b) Scrivere il modulo verilog che implementa un registro a 16 bit con reset asincrono attivo
basso e sensibile ai fronti negativi del clock
c) Scrivere un modulo verilog (MY_DP) che implementi un blocco logico costituito dallo
shifter e dal registro dei punti a) e b). Gli ingressi dello shifter sono ingressi del modulo,
mentre l’uscita dello shifter va in ingresso al registro.
d) Scrivere un testbench per verificare le seguenti operazioni (un’operazione per colpo di
clock):
1) Scrittura nel registro del dato D=16
2) Scrittura nel registro di D=24 shiftato a sinistra di 2 posizioni
3) Scrittura nel registro di D=1 shiftato a destra di 1 posizione
4) Reset del registro
5) Scrittura nel registro di D=3 shiftato a destra di 3 posizioni
b) Modulo REG
module REG(clk, rst, Din, Dout);
input clk, rst;
input [15:0] Din;
output [15:0] Dout;
reg [15:0] Dout;
// Registro con reset ASINCRONO (dunque nella sensistivity-list) attivo BASSO
// sensisibile ai fronti NEGATIVI del clock
always @(negedge clk or negedge rst)
if(~rst)
Dout = 16’b0;
else
Dout = Din;
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
a) Modulo SHIFTER
module SHIFTER(D, dir_shift, pos_shift, Y);
input dir_shift;
input [1:0] pos_shift;
input [15:0] D;
output [15:0] Y;
reg [15:0] Y;
// Blocco procedurale per implementare lo shift
always @(D or dir_shift or pos_shift)
if(dir_shift)
case(pos_shift)
0: Y = D;
1: Y = D>>1;
2: Y = D>>2;
3: Y = D>>3;
endcase
// Oppure, al posto del case, Y = D>>pos_shift;
else
case(pos_shift)
0: Y = D;
1: Y = D<<1;
2: Y = D<<2;
3: Y = D<<3;
endcase
// Oppure, al posto del case, Y = D<<pos_shift;
endmodule
c) Modulo MY_DP
module MY_DP(clk, rst, Din, dir_shift, pos_shift, Dout);
input clk, rst, dir_shift;
input [1:0] pos_shift;
input [15:0] Din;
output [5:0] Dout;
wire [15:0] Y;
// Istanziazione moduli
SHIFTER I_SHIFT(Din, dir_shift, pos_shift, Y);
REG I_REG(clk, rst, Y, Dout);
endmodule
d) Testbench
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
module tb_MY_DP;
reg clk, rst, dir_shift;
reg [1:0] pos_shift;
reg [15:0] Din;
wire [15.0] Dout;
// -- Istanziazione UUT -MY_DP UUT(clk, rst, Din, dir_shift, pos_shift, Dout);
// -- Generazione stimuli –
// Clock (bisogna INIZIALIZZARLO!!!)
always
#5 clk = ~ clk;
// Altri stimoli
initial
begin
// Valori iniziali
clk=1;
// Il registro NON deve essere resettato
rst=1;
// Per scrivere 16 nel registro metto 16 in ingresso e faccio uno shift di 0 posizioni
Din = 16; dir_shift=0; pos_shift=0;
// Aspetto il colpo di clock poi mi preparo per la prossima operazione
#7 D=24; pos_shift=2;
// Aspetto un altro colpo poi mi preparo alla prossima operazione
#10 D=1; dir_shift=1; pos_shift=1;
// Aspetto un altro colpo poi mi resetto
#10 rst=0;
// Aspetto il colpo di clock poi mi preparo per la prossima operazione
#10 D=3; pos_shift=3;
// Aspetto un altro colpo poi interrompo
#10 $stop;
end
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
Esercizio
o 15
Modellare in verilog il modulo
m
MIPS
S_DP rappre
esentato in Figura
F
che ha
h i seguentti segnali di ingresso ed
d
uscita:
Nome
Direzione
N
Numero di bit
Clk
Input
1
RegWrite
Input
1
Instr
Input
32
ALUsrc
Input
6
OV
Output
1
Zero
Output
1
DataOut
Output
32
I blocchi che
e compongo
ono il modulo
o hanno le se
eguenti funzio
onalità.
MUX: Mutlip
plexer 2x1 co
on due ingressi a 32 bit ed
e un bit di selezione.
ALU: Unità logico/aritme
etica con due
e operandi (A
A e B) a 32 bit
b in ingresso ed un’uscitta a 32 bit (A
ALU_result)
il cui valore è definito da
alle operazioni definite da
alla tabella se
eguente:
ALUsel
Functio
on
Spiegazio
one
000
AND bit a bit fra gli operandi
o
AeB
AND
001
OR bit a bit fra gli operandi A e B
OR
010
Somma
a dei due op
perandi (A+B)
Add
110
Differenz
za fra i due operandi
o
(A-B
B)
Subtracct
Se A<B
111
A
l’uscita è composta da
d tutti 0 tran
nne il bit men
no significativ
vo che è a
Set on le
ess
1, se invece A>=B
A
tutti i bit
b dell’uscita
a sono 0
than
Le uscite OV e zero son
no alte, rispettivamente, quando
q
l’ope
erazione della
a ALU ha da
ato overflow e quando il
risultato dell’operazione
e è pari a 0.
Sign_exten
nd: prende in
n ingresso un
n segnale di 16 bit e lo es
stende in usccita su 32 bitt mantenendone il segno
o
(il numero è espresso in compleme
ento a 2, mantenere il segno
s
signiffica semplice
emente replicare il bit dii
segno, a sin
nistra)
ALU_contrrol: genera gli opportuni segnali
s
di selezione per l’ALU in base
e ad un segn
nale di ingres
sso a 6 bit
(Instr[31:26]) ed alla tab
bella seguentte:
Ins
str[31:26]
Funzio
one della AL
LU desideratta
6’’b00xxxx
Add
6’’b01xxxx
Subtracct
6’b100000
Add
6’b100010
Subtracct
6’b100100
AND
6’b100101
OR
6’b101010
Set on lesss than
Register: banco
b
di 32 registri attivo
o sul fronte positivo del clock. Le usscite DataOu
ut1 e DataO
Out2, ad ognii
colpo di clo
ock, risultano
o uguali al co
ontenuto dell registro ind
dirizzato rispe
ettivamente dagli ingress
si DataIn1 e
DataIn2. Ino
oltre se Write
eEnable è altto, al colpo di
d clock viene
e memorizza
ato sul registrro indirizzato
o da Addresss
il segnale in
n ingresso su
u WriteData.
ED – Esercizi sulla modellazio
m
one Verilog
g
Massim
mo Barbaro
o
Modulo MIPS_DP
// Multiplexer 2x1
module MUX(sel, A, B, Y) ;
input sel ;
input [31 :0] A, B ;
output [31 :0] Y ;
// Continuous assignment per implementare logica combinatoria
assign Y = (sel) ? A : B;
endmodule
// ALU
module ALU(sel, A, B, OV, zero, Y) ;
input [2:0] sel ;
input [31 :0] A, B ;
output OV, zero;
output [31 :0] Y ;
reg [31 :0] Y ;
// Logica combinatoria : stile algoritmico
// Utilizzo istruzioni procedurali dentro un blocco always.
// Tutti gli ingressi nella sensitivity-list e l’uscita sempre assegnata
always @(A or B or sel)
case(sel)
3’b000: Y = A & B;
3’b001: Y = A | B;
3’b010: Y = A + B;
3’b110: Y = A - B;
3’b111: Y = (A < B) ? 32’b1 : 32’b0;
default: Y = 32’bx;
endcase
// L’uscita zero è un semplice continuous assignment
assign zero = (Y==0) ? 1 : 0 ;
// Descrizione algoritmica dell'uscita OV
always @(A[31] or B[31] or sel or Y[31])
case({sel,A[31],B[31],Y[31]})
6'b010001: OV=1;
6'b010110: OV=1;
6'b110011: OV=1;
6'b110100: OV=1;
default: OV=0;
endcase
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
module REGFILE(clk, WriteEnable, DataIn1, DataIn2, Address, WriteData, DataOut1,
DataOut2);
input clk, WriteEnable;
input [4:0] DataIn1, DataIn2, Address;
input [31:0] WriteData;
output [31:0] DataOut1, DataOut2;
// Banco di registri implementato con un array di reg
reg [31:0] RegFile [0:31], DataOut1, DataOut2;
// Scrittura e lettura sono sincrone, sul colpo di clock
always @(posedge clk)
begin
DataOut1 = RegFile[DataIn1]; // Metto in uscita il registro indirizzato da DataIn1
DataOut2 = RegFile[DataIn2]; // Metto in uscita il registro indirizzato da DataIn2
// Memorizzo WriteData sul registro indirizzato da Address
if(WriteEnable)
RegFile[Address] = WriteData;
end
endmodule
module SignExtend(DataIn, DataOut);
input [15:0] DataIn;
output [31:0] DataOut;
// Basta un continuous assignment con l’operatore replica e l’operatore concatenazione
assign DataOut = {{16{DataIn[15]}},DataIn};
endmodule
module ALUcontrol(OpCode, ALUsel);
input [5:0] OpCode;
output [2:0] ALUsel;
reg [2:0] ALUsel;
// Descrizione algoritmica di un circuito combinatorio:
// richiede un always nella cui sensitivity-list compaiano
// tutti gli ingressi del blocco combinatorio ed in cui
// per ogni combinazione di ingresso venga assegnato un valore
// all'uscita
always @(OpCode)
casex (OpCode)
6’b00xxxx: ALUsel = 3'b010;
6'b01xxxx: ALUsel = 3'b110;
6'b100000: ALUsel = 3'b010;
6'b100010: ALUsel = 3'b110;
6'b100100: ALUsel = 3'b000;
6'b100101: ALUsel = 3'b001;
6'b101010: ALUsel = 3'b111;
default: ALUsel = 3'bxxx;
endcase
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
moduleMIPS_DP(clk, RegWrite, ALUsrc, Instr, OV, zero, DataOut);
input clk, RegWrite, ALUsrc;
input [31:0] Instr;
output OV, zero;
output DataOut;
wire [2:0] ALUsel;
wire [31:0] RegDataOut1, RegDataOut2, outMUX, outSignExtend
// Instaziazione moduli
// Register file
REGFILE i_REGFILE(clk, RegWrite, Instr[25:21], Instr[20:16], Instr[15:11], DataOut,
RegDataOut1, RegDataOut2);
// MUX
MUX i_MUX(ALUsrc, outSignExtend, RegDataOut2, outMUX);
// ALU
ALU i_ALU(ALUsel, RegDataOut1, outMUX, OV, zero, DataOut);
// SignExtend
SignExtend i_SIGEXT(Instr[15:0], outSignExtend);
// ALU control
ALUcontrol i_ALUcontrol(Instr[31:26], ALUsel);
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
Esercizio
o 16
Modellare in verilog ili modulo BOOTH_MO
B
OD_DP (data
apath del moltiplicatore
m
e di Booth modificato))
rappresenta
ato in Figura che ha i seg
guenti segnali di ingresso
o ed uscita:
Direzione
N
Numero di bit
Nome
clk
Input
1
rst
Input
1
load
Input
1
en
Input
1
multiplican
nd
Input
16
multiplier
Input
16
product
Output
32
I blocchi che
e compongo
ono il modulo
o hanno le se
eguenti funzio
onalità.
MUX_EXT: Mutliplexer 2x1 con un ingresso
i
a 16
6 bit (IN1, un
no a 17 (IN0, un bit di sellezione (sel) ed un’uscita
a
a 17 bit. Qu
uando il bit dii selezione è pari a 1passsa l’ingresso
o IN1 che vie
ene esteso a 17 bit aggiu
ungendo uno
o
0 a destra (in
( posizione
e meno signifficativa) men
ntre quando ili bit di selezzione è 0 passsa l’ingresso
o IN0 (che è
già a 17 bit e non deve essere estesso).
Mult_AND: Registro a 16
1 bit con ing
gresso di clock (clk) attivo
o sul fronte positivo,
p
rese
et asincrono attivo basso
(rst) ed ingrresso di abilittazione (en) attivo alto (il registro memorizza solo
o se abilitato)).
Mult_ER: Registro
R
a 17
7 bit con ingrresso di clocck (clk) attivo
o sul fronte positivo,
p
rese
et asincrono attivo basso
o
(rst) ed ingrresso di abilittazione (en) attivo alto (il registro memorizza solo
o se abilitato)).
Shifter: Blo
occo combin
natorio che esegue lo shift
s
del seg
gnale di ingresso (a 17
7 bit) verso destra di 2
posizioni.
BOOTH_SH
H_ADD: un blocco com
mbinatorio che
c
compie delle opporrtune operazzioni di shifft&add suglii
operandi A e B in base ad
a un segna
ale di selezion
ne (code) se
econdo la seg
guente tabella:
code
Operazio
one
00
00 o 111
Trassferimento in uscita di A
010 o 001
A+B
110 o 101
A-B
011
A+2B ((*)
100
A-2B (**)
(*) La moltiiplicazione per 2 si fa con
n uno shift ve
erso sinistra
ACC: Regisstro a 32 bit con
c ingresso
o di clock (clkk) attivo sul fronte
f
positivvo, reset asin
ncrono attivo
o basso (rst),,
ingresso di abilitazione (en) attivo alto
a (il registtro memorizz
za solo se abilitato) ed ingresso di azzeramento
a
o
n è 1) ed il segnale di azzeramento
a
o è alto il re
egistro deve azzerarsi (ill
(clear). Se il registro è abilitato (en
nza del resett, è sincrono)).
segnale clear, a differen
ED – Esercizi sulla modellazio
m
one Verilog
g
Massim
mo Barbaro
o
Modulo BOOTH_MOD_DP (SCRIVERE IN STAMPATELLO ED AGGIUNGERE GLI
OPPORTUNI COMMENTI AL CODICE)
// Compito di ESD1
// Datapath del moltiplicatore di Booth modificato
// Author: M. Barbaro
// 02/03/2005
module BOOTH_MOD_DP(clk, rst, en, load, multiplicand, multiplier, product);
input clk, rst, en, load;
input [15:0] multiplicand, multiplier;
output [15:0] product;
reg [15:0] mult_and, booth_sh_add;
reg [16:0] mer;
reg [31:0] product;
wire [16:0] mer_in, out_shift;
// -- Registri –
// Moltiplicando
always @(posedge clk or negedge rst)
if(~rst)
mult_and = 16’b0; // Reset
else
if(load)
mult_and = multiplicand; // Memorizzazione
// Moltiplicatore
always @(posedge clk or negedge rst)
if(~rst)
mer= 17’b0; // Reset
else
if(en)
mer= mer_in; // Memorizzazione
// Accumulatore
always @(posedge clk or negedge rst)
if(~rst)
product = 32’b0; // Reset
else
if(en)
if(clr)
product = 32’b0; // Clear
else
product = booth_sh_add; // Memorizzazione
// -- Logica –
// Multiplexer
assign mer_in = (load) ? {multiplier,1’b0} : out_shift ;
// Shifter
assign out_shift = mer >> 2;
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
// Booth_sh_add
always @ ( mult_and or product or mer[2:0] )
case (mer[2:0] )
3’b000, 3’b111: booth_sh_add = product;
3’b010, 3’b001: booth_sh_add = product + mult_and;
3’b110, 3’b101: booth_sh_add = product - mult_and;
3’b011: booth_sh_add = product + {mult_and,0};
3’b100: booth_sh_add = product - {mult_and,0};
// Non c’è bisogno di default perché tutti i casi sono contemplati
endcase
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
Esercizio 17
a) Modellare in verilog il register file (REGFILE) di un processore MIPS. Tale modulo costituisce l’insieme di
registri interni del processore ed ha i seguenti segnali di ingresso ed uscita:
Nome
Direzione
Numero di bit
clk
Input
1
we
Input
1
raddrA
Input
5
raddrB
Input
5
waddr
Input
5
dataIn
Input
32
dataOutA
Output
32
dataOutB
Output
32
Il modulo è costituito da un banco di 31 registri effettivi ed un registro fittizio (il registro 0) che non può
essere scritto e che quando viene letto fornisce in uscita una parola nulla (32 bit pari a 0). Il registro 0,
quindi, non è realizzato veramente come elemento di memoria ma implementato solo tramite la logica di
lettura.
La scrittura è SINCRONA quindi avviene sul colpo di clock: se il segnale write enable (we) è alto viene
memorizzato sul registro indirizzato da waddr (quindi il registro di posizione waddr) il dato in ingresso su
dataIn. La lettura, viceversa, non è sincronizzata sul clock ma sulle porte di uscita dataOutA e dataOutB
viene messo il dato contenuto nel registro indirizzato da, rispettivamente, raddrA e raddrB in qualsiasi
momento cambi uno qualsiasi dei segnali in ingresso
b) Scrivere un testbench per la verifica del funzionamento del modulo al punto a) eseguendo, in
successione, la scrittura su ciascun registro di un dato (il numero del registro stesso, ad esempio) e poi
leggendo in successione i dati memorizzati prima tramite la porta dataOutA e poi tramite la dataOutB.
a) Modulo REGFILE (SCRIVERE GLI OPPORTUNI COMMENTI PER LA
COMPRENSIONE DEL CODICE)
module REGFILE(clk,we,raddrA,raddrB,waddr,dataIn,dataOutA,dataOutB);
input clk,we;
input [4:0] raddrA, raddrB, waddr;
input [31:0] dataIn;
output [31:0] dataOutA, dataOutB;
reg [31:0] mem[1:31];
// Memorizzazione
always @(posedge clk) // Scrittura sincrona
if(we && (waddr!=5’b0)) // Verifica se il registro è abilitato alla scrittura e non sto scrivendo il registro 0
mem[waddr] = dataIn; // Scrive dataIn alla locazione puntata da waddr
// Lettura porta A
always @(raddrA or mem)
if(raddrA)
dataOutA=mem[raddrA]; // Se l’indirizzo non è 0 mette in uscita il contenuto del registro opportuno
else
dataOutA=32’b0; // Altrimenti mette in uscita una parola nulla
// Lettura porta B
always @(raddrB or mem)
if(raddrB)
dataOutB=mem[raddrB]; // Se l’indirizzo non è 0 mette in uscita il contenuto del registro opportuno
else
dataOutB=32’b0; // Altrimenti mette in uscita una parola nulla
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
b) Testbench (SCRIVERE GLI OPPORTUNI COMMENTI PER LA COMPRENSIONE
DEL CODICE)
module tb_REGFILE;
reg [4:0] raddrA, raddrB, waddr;
reg [31:0] dataIn;
reg clk, we;
wire [31:0] dataOutA, dataOutB;
integer K;
// Istanziazione modulo da testare
REGFILE DUT(clk,we,raddrA,raddrB,waddr,dataIn,dataOutA,dataOutB);
// Generazione clock
always
#5 clk=~clk; // Bisogna però inizializzare clk in un initial !!!!
// Il clock ha periodo 10
// Generazione stimoli
initial
begin
clk=0; // Inizializzo il clock a 0
waddr=0; raddrA=0; raddrB=0;
#3; // Mi disallineo dal fronte del clock in modo da presentare gli ingressi
// sempre 2 unità di tempo prima del fronte stesso
we=1; // Abilito alla scrittura
// Scrivo in ogni registro del register file un numero che corrisponde all’indirizzo
// di quel registro
for(K=0;K<32;K=K+1)
begin
waddr=K;
dataIn=K;
#10; // Aspetto il colpo di clock e procedo
end
we=0; // Disabilito la scrittura
// Leggo sulla porta A
for(K=0;K<32;K=K+1)
begin
raddrA=K;
#10; // Aspetto il colpo di clock e procedo
end
// Leggo sulla porta B
for(K=0;K<32;K=K+1)
begin
raddrB=K;
#10; // Aspetto il colpo di clok e procedo
end
end
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
Esercizio
o 18
a) Modellarre in verilog il modulo Sw
witch_1x4 ra
appresentato
o in Figura. Tale
T
modulo ha i seguen
nti segnali dii
ingresso ed
d uscita:
Nome
Clk
flit_IN
out_flit_N
out_flit_S
out_flit_W
W
out_flit_E
Direzione
Input
Input
Output
Output
Output
Output
N
Numero di bit
1
32
32
32
32
32
Il modulo rappresenta uno switch per applicazzioni di netw
work-on-chip,, ossia il ma
attone costitutivo di una
a
topologia di interconnessione fra blocchi
b
di ela
aborazione. La rete è costituita dall’interconnes
ssione di più
ù
switch. In pratica
p
il blo
occo da mod
dellare riceve
e in ingress
so un dato a 32 bit sull’unica porta di ingresso
o
(flit_IN) ed instrada talle dato su una
u
della 4 porte d’usc
cita (out_flit_
_N(orth), S(o
outh), W(estt), E(ast)) a
seconda de
el contenuto del
d dato stessso.
Il dato in ingresso (flit_IIN) ha infattii la struttura di Figura 2:: è costituito da 32 bit, i 24 bit meno
o significativii
contengono
o l’informazio
one vera e propria
p
da in
nstradare (da
ata) e ciascu
uno dei 4 gru
uppi di 2 bitt (dst0, dst1,,
dst2 e dst3)) rappresenta
a il percorso su cui deve essere instra
adato il dato.
Ad ogni collpo di clock, il modulo prende
p
il dato
o in ingresso
o, verifica su
u quale porta
a deve esse
ere messo in
n
uscita in ba
ase al codice
e presente nel campo dsst0 (out_flit_N
N è codificatta con 0, outt_flit_S con 1,
1 out_flit_W
W
con 2 e out_flit_E con 3)
3 e lo pone in uscita spo
ostando i campi destinazzione verso ssinistra (ossia trasferisce
e
il campo dsst1 in dst0, dsst2 in dst1, dts3
d
in dst2 e riempie dst3 di zeri). In
n questo mod
do inizialmen
nte i 4 campii
dst vengono riempiti co
on il percorsso che dovrà
à prendere il dato e po
oi, ad ogni ccolpo di cloc
ck, il dato sii
sposterà di switch in sw
witch, opportu
unamente.
Si faccia un’implementtazione a singolo modulo, ma si se
epari opporttunamente la
a parte com
mbinatoria (ill
riconoscime
ento della po
orta di uscita e lo shift) da
alla parte seq
quenziale (la
a memorizzazzione, sul clo
ock, del dato
o
in ingresso opportunamente shiftato
o sulla porta di
d uscita des
siderata).
scita devono
o quindi ess
sere presen
nti 4 registri
ri, uno per ogni
o
porta d
di uscita (tu
utte le porte
e
N.B.: In us
sono registrate)l
b) Scrivere un testbencch che imple
ementi una re
ete 3 livelli di
d switch (al primo livello
o c’è un unic
co switch, all
secondo livello i 4 switcch pilotati da quello del primo
p
livello, al terzo i 16
6 switch pilota
ati da quelli del secondo
o
livello) face
endo in mod
do che un dato a scelta
a presentato in ingresso
o al primo sswitch segua
a il percorso
o
NORD-OVE
EST-OVEST in tre colpi di
d clock successivi.
Figura 1
Figura 2
ED – Esercizi sulla modellazio
m
one Verilog
g
Massim
mo Barbaro
o
a) Moduli Switch_1x4 (SCRIVERE GLI OPPORTUNI COMMENTI PER LA
COMPRENSIONE DEL CODICE)
// Una versione del modulo che sfrutta un multiplexing degli ingressi dei registri per
// scrivere solo su quello selezionato: sul registro selezionato si mette in ingresso
// il dato con i campi destinazione opportunamente shiftati mentre sugli altri si mette in
// in ingresso la loro stessa uscita, sovrascrivendo quindi il registro col suo stesso
// contenuto
module Switch_1x4(clk,flit_IN,out_flit_N,out_flit_S,out_flit_W,out_flit_W);
input clk;
input [31:0] flit_IN;
output [31:0] out_flit_N, out_flit_S, out_flit_W, out_flit_E;
reg [31:0] out_flit_N, out_flit_S, out_flit_W, out_flit_E, in_N, in_S, in_W, in_E;
// Parte combinatoria
always @(flit_IN or out_flit_N or out_flit_S or out_flit_W or out_flit_E)
begin
// Di default l’ingresso dei registri (in_N, in_S, in_W, in_E)
// è posto uguale all’uscita in modo da riscrivere solo il registro interessato
in_N=out_flit_N;
in_S=out_flit_S;
in_W=out_flit_W;
in_E=out_flit_E;
// Case per la scelta del registro su cui instradare il dato
case(flit_IN[31:30])
2’b00: in_N={flit_IN[29:24],2’b00,flit_IN[23:0])};
2’b01: in_S={flit_IN[29:24],2’b00,flit_IN[23:0])};
2’b10: in_W={flit_IN[29:24],2’b00,flit_IN[23:0])};
2’b11: in_E={flit_IN[29:24],2’b00,flit_IN[23:0])};
endcase
end
// Parte sequenziale : 4 registri
always @(posedge clk)
begin
out_flit_N=in_N;
out_flit_S=in_S;
out_flit_W=in_W;
out_flit_E=in_E;
end
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
// Una versione alternative del modulo, che utilizza registri con enable
module Switch_1x4_v2(clk,flit_IN,out_flit_N,out_flit_S,out_flit_W,out_flit_W);
input clk;
input [31:0] flit_IN;
output [31:0] out_flit_N, out_flit_S, out_flit_W, out_flit_E;
reg en_reg_N, en_reg_S, en_reg_W, en_reg_E;
reg [31:0] out_flit_N, out_flit_S, out_flit_W, out_flit_E, in_reg;
// Parte combinatoria
always @(flit_IN)
begin
// Di default nessuno dei registri è abilitato
// e l’ingresso di tutti i registri è posto uguale al flit in ingresso con
// l’opportuno shift dei campi destinazione
en_reg_N=1’b0;
en_reg_S=1’b0;
en_reg_W=1’b0;
en_reg_E=1’b0;
in_reg={flit_IN[29:24],2’b00,flit_IN[23:0])};
// Case per la scelta del registro da abilitare
case(flit_IN[31:30])
2’b00: en_reg_N=1’b1;
2’b01: en_ reg_S=1’b1;
2’b10: en_ reg_W=1’b1;
2’b11: en_ reg_E=1’b1;
// Uno solo dei registri è abilitato alla scrittura
endcase
// Da notare che i segnali di enable sono combinatori perché sono sempre comunque
// assegnati e tutti gli inglessi (flit_IN) sono nella sensitività-list
end
// Parte sequenziale : 4 registri
always @(posedge clk)
begin
// Scriverò solo sul registro abilitato
if(en_reg_N)
out_flit_N=in_N;
if(en_reg_S)
out_flit_S=in_S;
if(en_reg_W)
out_flit_W=in_W;
if(en_reg_E)
out_flit_E=in_E;
end
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
b) Testbench
// Modulo contenente tutte le istanze di switch da testare (la topologia)
module topology(clk, flit_IN, f3_1_N, f3_1_S, f3_1_W, f3_1_E, f3_2_N, f3_2_S, f3_2_W,
f3_2_E, f3_3_N, f3_3_S, f3_3_W, f3_3_E, f3_4_N, f3_4_S, f3_4_W, f3_4_E, f3_5_N,
f3_5_S, f3_5_W, f3_5_E, f3_6_N, f3_6_S, f3_6_W, f3_6_E, f3_7_N, f3_7_S, f3_7_W,
f3_7_E, f3_8_N, f3_8_S, f3_8_W, f3_8_E, f3_9_N, f3_9_S, f3_9_W, f3_9_E, f3_10_N,
f3_10_S, f3_10_W, f3_10_E, f3_11_N, f3_11_S, f3_11_W, f3_11_E, f3_12_N, f3_12_S,
f3_12_W, f3_12_E, f3_13_N, f3_13_S, f3_13_W, f3_13_E, f3_14_N, f3_14_S, f3_14_W,
f3_14_E, f3_15_N, f3_15_S, f3_15_W, f3_15_E, f3_16_N, f3_16_S, f3_16_W, f3_16_E);
input clk;
input [31:0] flit_IN;
output [31:0] f3_1_N, f3_1_S, f3_1_W, f3_1_E, f3_2_N, f3_2_S, f3_2_W, f3_2_E, f3_3_N,
f3_3_S, f3_3_W, f3_3_E, f3_4_N, f3_4_S, f3_4_W, f3_4_E, f3_5_N, f3_5_S, f3_5_W,
f3_5_E, f3_6_N, f3_6_S, f3_6_W, f3_6_E, f3_7_N, f3_7_S, f3_7_W, f3_7_E, f3_8_N,
f3_8_S, f3_8_W, f3_8_E, f3_9_N, f3_9_S, f3_9_W, f3_9_E, f3_10_N, f3_10_S, f3_10_W,
f3_10_E, f3_11_N, f3_11_S, f3_11_W, f3_11_E, f3_12_N, f3_12_S, f3_12_W, f3_12_E,
f3_13_N, f3_13_S, f3_13_W, f3_13_E, f3_14_N, f3_14_S, f3_14_W, f3_14_E, f3_15_N,
f3_15_S, f3_15_W, f3_15_E, f3_16_N, f3_16_S, f3_16_W, f3_16_E;
wire [31:0] f1_1_N, f1_1_S, f1_1_W, f1_1_E, f2_1_N, f1_1_S, f2_1_W, f2_1_E, f2_2_N,
f1_2_S, f2_2_W, f2_2_E, f2_3_N, f1_3_S, f2_3_W, f2_3_E, f2_4_N, f1_4_S, f2_4_W,
f2_4_E;
// Istanziazione primo livello
Switch_1x4 SW1_1(clk, flit_IN, f1_1_N, f1_1_S, f1_1_W, f1_1_E);
// Istanziazione secondo livello
Switch_1x4 SW2_1(clk, f1_1_N, f2_1_N, f1_1_S, f2_1_W, f2_1_E),
SW2_2(clk, f1_1_S, f2_2_N, f1_2_S, f2_2_W, f2_2_E),
SW2_3(clk, f1_1_W, f2_3_N, f1_3_S, f2_3_W, f2_3_E),
SW2_4(clk, f1_1_E, f2_4_N, f1_4_S, f2_4_W, f2_4_E);
// Istanziazione terzo livello
Switch_1x4 SW3_1(clk, f2_1_N, f3_1_N, f3_1_S, f3_1_W, f3_1_E),
SW3_2(clk, f2_1_S, f3_2_N, f3_2_S, f3_2_W, f3_2_E),
SW3_3(clk, f2_1_W, f3_3_N, f3_3_S, f3_3_W, f3_3_E),
SW3_4(clk, f2_1_E, f3_4_N, f3_4_S, f3_4_W, f3_4_E)
SW3_5(clk, f2_2_N, f3_5_N, f3_5_S, f3_5_W, f3_5_E),
SW3_6(clk, f2_2_S, f3_6_N, f3_6_S, f3_6_W, f3_6_E),
SW3_7(clk, f2_2_W, f3_7_N, f3_7_S, f3_7_W, f3_7_E),
SW3_8(clk, f2_2_E, f3_8_N, f3_8_S, f3_8_W, f3_8_E).
SW3_9(clk, f2_3_N, f3_9_N, f3_9_S, f3_9_W, f3_9_E),
SW3_10(clk, f2_3_S, f3_10_N, f3_10_S, f3_10_W, f3_10_E),
SW3_11(clk, f2_3_W, f3_11_N, f3_11_S, f3_11_W, f3_11_E),
SW3_12(clk, f2_3_E, f3_12_N, f3_12_S, f3_12_W, f3_12_E),
SW3_13(clk, f2_4_N, f3_13_N, f3_13_S, f3_13_W, f3_13_E),
SW3_14(clk, f2_4_S, f3_14_N, f3_14_S, f3_14_W, f3_14_E),
SW3_15(clk, f2_4_W, f3_15_N, f3_15_S, f3_15_W, f3_15_E),
SW3_16(clk, f2_4_E, f3_16_N, f3_16_S, f3_16_W, f3_16_E);
Endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
// Testbench vero e proprio
module tb_topology;
reg clk;
reg [31:0] flit_IN;
wire [31:0] f3_1_N, f3_1_S, f3_1_W, f3_1_E, f3_2_N, f3_2_S, f3_2_W, f3_2_E, f3_3_N,
f3_3_S, f3_3_W, f3_3_E, f3_4_N, f3_4_S, f3_4_W, f3_4_E, f3_5_N, f3_5_S, f3_5_W,
f3_5_E, f3_6_N, f3_6_S, f3_6_W, f3_6_E, f3_7_N, f3_7_S, f3_7_W, f3_7_E, f3_8_N,
f3_8_S, f3_8_W, f3_8_E, f3_9_N, f3_9_S, f3_9_W, f3_9_E, f3_10_N, f3_10_S, f3_10_W,
f3_10_E, f3_11_N, f3_11_S, f3_11_W, f3_11_E, f3_12_N, f3_12_S, f3_12_W, f3_12_E,
f3_13_N, f3_13_S, f3_13_W, f3_13_E, f3_14_N, f3_14_S, f3_14_W, f3_14_E, f3_15_N,
f3_15_S, f3_15_W, f3_15_E, f3_16_N, f3_16_S, f3_16_W, f3_16_E;
// Istanziazione blocco
topology DUT(clk,flit_IN, f3_1_N, f3_1_S, f3_1_W, f3_1_E, f3_2_N, f3_2_S, f3_2_W,
f3_2_E, f3_3_N, f3_3_S, f3_3_W, f3_3_E, f3_4_N, f3_4_S, f3_4_W, f3_4_E, f3_5_N,
f3_5_S, f3_5_W, f3_5_E, f3_6_N, f3_6_S, f3_6_W, f3_6_E, f3_7_N, f3_7_S, f3_7_W,
f3_7_E, f3_8_N, f3_8_S, f3_8_W, f3_8_E, f3_9_N, f3_9_S, f3_9_W, f3_9_E, f3_10_N,
f3_10_S, f3_10_W, f3_10_E, f3_11_N, f3_11_S, f3_11_W, f3_11_E, f3_12_N, f3_12_S,
f3_12_W, f3_12_E, f3_13_N, f3_13_S, f3_13_W, f3_13_E, f3_14_N, f3_14_S, f3_14_W,
f3_14_E, f3_15_N, f3_15_S, f3_15_W, f3_15_E, f3_16_N, f3_16_S, f3_16_W, f3_16_E);
// Generazione clock
always
#5 clk=~clk; // Bisogna però inizializzare clk in un initial !!!!
// Il clock ha periodo 10
// Generazione stimoli
initial
begin
clk=0;
// Inizializzo il dato in ingresso con il percorso necessario per muoversi N-W-W
// la quarta destinazione la scelgo a caso tanto non c’è il corrispondente livello nella
// topologia
#2 flit_IN={2’b00,2’10,2’b10,2’b11,{3{8’b01100011}});
#30 $stop; // Aspetto 3 colpi di clock
end
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
Esercizio
o 19
a) Modellarre in verilog il modulo selBlock
s
rappresentato in Figura. Ta
ale modulo ha i seguen
nti segnali dii
ingresso ed
d uscita:
Direzione
N
Numero di bit
Nome
clk
Input
1
enShift
Input
1
dirShift
Input
1
serial_In
Input
1
enReg
Input
1
rst
Input
1
wordLine
Output
64
Il modulo è costituito da
d 2 sottom
moduli (shiftR
REG e word
dREG) cha hanno
h
il fun
nzionamento descritto dii
seguito.
shiftREG: si
s tratta di un
n registro a scorrimento (shift registe
er) a 64 bit. Quando è a
abilitato (enS
Shift alto), ad
d
ogni colpo di
d clock (clk)), fa scorrere
e tutti i bit me
emorizzati ve
erso sinistra (dirShift alto
o) oppure destra (dirShiftt
basso) di una posizione
e. Se lo scorrrimento è ve
erso sinistra nella posizio
one meno siignificativa viene
v
inserito
o
l’ingresso serial_In, altrimenti, se lo scorrimento è verso des
stra, si inserissce in posiziione più sign
nificativa uno
o
zero.
wordREG: si tratta di un
u registro a 64 bit, con ingresso di abilitazione
a
(
(enReg)
attivvo alto e reset asincrono
o
(rst) attivo alto.
a
Si realizzi in
nfine un mod
dulo testbencch per testare
e il funzionam
mento del mo
odulo top. Il ttestbench de
eve:
a) Ressettare il worrdREG
b) Farre scorrere ve
erso sinistra il contenuto dello shiftRE
EG inserendo 3 bit pari a 1 consecutiivi
c) Trasferire il contenuto di shiiftREG in wo
ordREG
d) Farre scorrere ve
erso destra di
d 2 posizioni lo shiftREG
G
e) Trasferire il contenuto di shiiftREG in wo
ordREG
STA UN’IMPL
LEMENTAZIIONE GERAR
RCHICA, CO
OSTITUITA DA
D 3 MODUL
LI: 1 PER IL REGISTRO
O
E’ RICHIES
A SCORRIIMENTO, UN
NO PER IL
L REGISTRO
O NORMAL
LE ED UNO
O PER IL M
MODULO TO
OP CHE LII
CONTIENE
E.
ED – Esercizi sulla modellazio
m
one Verilog
g
Massim
mo Barbaro
o
a) Moduli selBlock, shiftREG e wordREG (SCRIVERE GLI OPPORTUNI COMMENTI PER
LA COMPRENSIONE DEL CODICE)
module shiftREG(clk,en,dir,sin,outshift);
input clk,en,dir,sin;
output [63:0] outshift;
reg [63:0] outshift;
always @(posedge clk)
if(en)
if(dir)
outshift={outshift[62:0],sin};
else
outshift=outhisft>>1;
// Sul fronte del clock
// se il registro è abilitato
// e se lo scorrimento è a sinistra
// scorro verso sinistra ed inserisco sin a destra
// altrimenti
// scorro a destra ed inserisco 0 a sinistra
endmodule
module wordREG(clk, rst, en, dataIn, dataOut);
input clk, rst, en;
input [63:0] dataIn;
output [63:0] dataOut;
reg [63:0] dataOut;
always @(posedge clk or posedge rst) // Reset asincrono nella sensitivity list
if(rst)
// Se il reset è attivo
outData=64’b0;
// azzero il contenuto del registro
else
// altrimenti
if(en)
// se il registro è abilitato
outData=dataIn;
// memorizzo il dato in ingresso
endmodule
module selBlock(clk, rst, enShift, dirShift, enReg, serial_In, wordLine);
input clk, rst, enShift, dirShift, enReg, serial_In;
output [63:0] wordLine;
reg [63:0] wordLine;
wire [63:0] out_shifter;
// Istanziazione shift register
shiftREG i_shifter(clk,enShift,dirShift,serial_In,out_shifter);
// Istanziazione registro
wordREG i_reg(clk,rst,enReg,out_shifter,wordLine);
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
b) Testbench (SCRIVERE GLI OPPORTUNI COMMENTI PER LA COMPRENSIONE
DEL CODICE)
module tb_selBlock;
reg clk,rst,enShift,dirShift,enReg,serial_In;
wire [63:0] wordLine;
// Istanziazione componente
selBlock DUT(clk, rst, enShift, dirShift, enReg, serial_In, wordLine);
// Generazione clock
always
#5 clk=~clk; // Bisogna però inizializzare clk in un initial !!!!
// Il clock ha periodo 10
// Generazione stimoli
initial
begin
clk=0; rst=0; enShift=0; dirShift=0; enReg=0; serial_In=0;
#3 rst=1; // Reset
#5 rst=0; // Reset terminato
// Sono passate 8 unità di tempo, da ora in poi modificherò i segnali in ingresso
// con step temporali di 10 unità di tempo in modo da presentare i segnali in ingresso
// sempre PRIMA del colpo di clock per rispettare i tempi di setup
enShift=1; // Abilito lo shift register
serial_In=1; // Metto in ingresso degli 1
dirShift=1; // Lo shift è verso sinistra
// Aspetto 3 colpi di clock (30 unità di tempo) per inserire i 3 uno richiesti
#30 enShift=0; enReg=1; // Disabilito lo shift ed abilito il registro alla scrittura
// Aspetto un colpo di clock (10 unità di tempo) e poi faccio gli altri due shift
#10 enReg=0; enShift=1; dirShift=0;
// Disabilito il registro, abilito lo shift a destra ed aspetto due colpi di clock (20 unità)
#20 enShift=0; enReg=1; // Disabilito lo shift ed abilito il registro alla scrittura
#10 $stop;
end
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
Esercizio 20
Si modelli, in verilog, il modulo RAM_interface del sistema mostrato in Figura 1:
Figura 1
Il sistema si compone di un processore, due memorie RAM ed un modulo di interfaccia (COMBINATORIO)
che si incarica di convertire opportunamente i segnali di controllo del processore per adattarli al
meccanismo di comunicazione delle memorie.
In particolare, il processore si aspetta di comunicare con una memoria organizzata in 1024 locazioni da un byte,
indirizzate tramite il bus indirizzi (AddrBus). Il bus dati bidirezionale (DataBus), però, è un bus a 32 bit. Per un
accesso in lettura (RnW alto), il processore si aspetta di trovare sul bus dati, rispettivamente 4 byte (word) alla volta,
2 byte (half-word) oppure singoli byte, a seconda del valore del segnali di controllo Opcode, secondo lo schema
indicato in Figura 2a (la notazione @[AddrBus] indica il dato contenuto alla locazione indirizzata da AddrBus). Per un
accesso in scrittura (RnW basso), invece, non c’è differenza fra signed/unsigned e debbono comunque essere scritti
in memoria, tutti i 4 byte (accesso word), i due byte meno significativi (accesso tipo half-word, signed o unsigned)
oppure solo il byte meno significativo (accesso tipo byte, signed o unsigned) presenti sul bus dati.
Figura 2a
Figura 2b
Le due memorie sono però organizzate in 256 locazioni (ciascuna) da 16 bit, dunque i byte indirizzati dal
processore devono essere mappati sulle memorie secondo lo schema di Figura 2b.
Il meccanismo di accesso alle memorie è simile a quello del processore, quindi per accedere in lettura RnWRAM1(2)
è alto, mentre è basso per accedere in scrittura. Un segnale di controllo di 2 bit (OpcodeRAM1(2)) decide se
l’accesso avviene su un’intera parola da 16 bit (OpcodeRAM1(2)=00) oppure sul byte meno significativo
(OpcodeRAM1(2)=01) o più significativo (OpcodeRAM1(2)=10). Nel caso delle memorie non c’è differenza fra
accesso byte signed ed unsigned, quindi il byte viene messo nella metà opportuna (più o meno significativa) del bus
dati (DataBusRAM1(2)) ed il resto del bus viene riempito da zeri. Ovviamente il bus indirizzi delle memorie è
AddrBusRAM1(2).
Tutti i bus dati (memorie e processore) sono bidirezionali e gestiscono la bidirezionalità con il tri-state.
Il modulo deve essere COMBINATORIO.
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
Modulo RAM_interface (INSERIRE TUTTI I COMMENTI PER LA COMPRENSIONE DEL
CODICE)
module RAM_interface(RnW, Opcode, AddrBus, DataBus, RnWRAM1, OpcodeRAM1,
AddrBusRAM1,
DataBusRAM1,
RnWRAM2,
OpcodeRAM2,
AddrBusRAM2,
dataBusRAM2);
// ** INTERFACCIA **
// Segnali di ingresso
input RnW;
input [2:0] Opcode;
input [9:0] AddrBus;
// Segnali di ingresso/uscita (i bus bidirezionali)
inout [31:0] DataBus;
inout[15:0] DataBusRAM1, DataBusRAM2;
// Segnali di uscita
ouput RnWRAM1, RnWRAM2;
output [1:0] OpCodeRAM1, OpCodeRAM2;
output [7:0] AddrBusRAM1, AddrBUSRAM2;
// ** REG **
reg RnWRAM1, RnWRAM2;
reg [1:0] OpcodeRAM1, OpcodeRAM2;
// Questi 3 reg interni sono usati per la gestione del tri-state
reg [15:0] DataBusRAM1_int, DataBusRAM2_int;
reg [31:0] DataBus_int;
// ** Gestione del tri-state **
// Se siamo in operazione di lettura (RnW alto) assegna il valore opportuno al DataBus
// diretto verso il processore e lascia in alta impedenza i DataBusRAM1(2) in quanto
// si suppone che siano le RAM stesse a dovere pilotare tali bus.
// Altrimenti, se l’operazione è di scrittura (RnW basso) lascia in alta impedenza il
// DataBus che proviene dal processore (per consentirgli di fissare il valore del bus)
// ed impone il valore opportuno sui DataBusRAM1(2) diretti verso le RAM.
assign DataBus = (RnW) ? DataBus_int : 32’bz;
assign DataBusRAM1 = (RnW) ? 32’bz : DataBusRAM1_int;
assign DataBusRAM2 = (RnW) ? 32’bz : DataBusRAM2_int;
// I bit di indirizzo per le RAM sono gli 8 più significativi perché i byte 0,1,2,3 (multipli)
// si trovano tutti allo stesso indirizzo ma in diverse porzioni della word oppure in
// una diversa ram
assign AddrBusRAM1=AddrBus[9:2];
assign AddrBusRAM2=AddrBus[9:2];
// Blocco always per la gestione dell’interfaccia, si occupa di generare:
// 1) I segnali di controllo per le memorie (RnWRAM1(2) e OpcodeRAM1(2)
// 2) I valori da propagare in uscita sui bus delle memorie in caso
// di scrittura (DataBusRAM1_int e DataBusRAM2_int)
// 3) Il valore da propagare verso il bus del processore in caso di lettura (DataBus_int)
// Bisogna assicurarsi che tutti gli ingressi siano nella sensitivity-list e che
// queste 7 uscite siano sempre assegnate
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
always @(RnW or Opcode or AddrBus or DataBus or DataBusRAM1 or DataBusRAM2)
if(RnW)
// Accesso in lettura
begin
// Sono in lettura, assegno un valore qualsiasi a DataBusRAM1(2)_int tanto
// non verranno utilizzati (ma devo assegnare comunque un valore perché si tratti
// di logica combinatoria
DataBusRAM1_int=16’b0; DataBusRAM2_int=16’b0;
// Per la stessa ragione assegna un valore qualsiasi a OpcodeRAM1(2)
OpcodeRAM1=2’b0; OpcodeRAM2=2’b0;
// Metto le RAM in lettura
RnWRAM1=1; RnWRAM2=1;
// In base a Opcode decido come leggere
case(Opcode)
// Accesso per WORD
3’b000:
DataBus_int = {DataBusRAM1, DataBusRAM2};
// Accesso UNSIGNED per HALF-WORD
3’b001:
// Se l’indirizzo è divisibile per 4 si trova sulla RAM1 altrimenti sulla RAM2
// Si da per scontato che l’indirizzo sia correttamente allineato sulle half-word
// quindi sia un multiplo di 2 e perciò AddrBus[0]=0
if (AddrBus[1])
DataBus_int = {16’b0, DataBusRAM2};
else
DataBus_int = {16’b0, DataBusRAM1};
// Accesso SIGNED per HALF-WORD
3’b010:
if (AddrBus[1])
DataBus_int = {{16{DataBusRAM2[15]}}, DataBusRAM2};
else
DataBus_int = {{16{ DataBusRAM1[15]}}, DataBusRAM1};
// Accesso UNSIGNED per BYTE
3’b101:
// A seconda dei due bit meno significativi dell’indirizzo decido come
// comporre il dato da mettere sul bus del processore
case (AddrBus[1:0])
2’b00: DataBus_int = {24’b0, DataBusRAM1[15:8]};
2’b01: DataBus_int = {24’b0, DataBusRAM1[7:0]};
2’b10: DataBus_int = {24’b0, DataBusRAM2[15:8]};
2’b11: DataBus_int = {24’b0, DataBusRAM2[7:0]};
endcase
// Accesso SIGNED per BYTE
3’b110:
case (AddrBus[1:0])
2’b00: DataBus_int = {{24{DataBusRAM1[15]}}, DataBusRAM1[15:8]};
2’b01: DataBus_int = {{24{DataBusRAM1[7]}}, DataBusRAM1[7:0]};
2’b10: DataBus_int = {{24{DataBusRAM2[15]}}, DataBusRAM2[15:8]};
2’b11: DataBus_int = {{24{DataBusRAM2[7]}}, DataBusRAM2[7:0]};
endcase
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
// Il default è necessario per il comportamento combinatorio
default: DataBus_int = 32’bx;
endcase
end
else
// Accesso in scrittura
begin
// Assegno un valore qualsiasi a DataBus_int che non verrà usato (sono in scrittura)
// ma deve comunque essere assegnato per il comportamento combinatorio
DataBus_int = 32’b0;
// Tutti gli altri segnali li assegno in base a Opcode
casex(Opcode)
// Accesso per WORD
3’b000: begin
{DataBusRAM1_int, DataBusRAM2_int} = DataBus;
RnWRAM1=0; RnWRAM2=0; // RAM in scrittura
OpcodeRAM1=2’b00; OpcodeRAM2=2’b00; // Scrivo tutti i 16 bit
end
// Accesso per HALF-WORD
3’b0xx:
// Se l’indirizzo è divisibile per 4 si trova sulla RAM1 altrimenti sulla RAM2
// Si da per scontato che l’indirizzo sia correttamente allineato sulle half-word
// quindi sia un multiplo di 2 e perciò AddrBus[0]=0
if (AddrBus[1])
begin
DataBusRAM2_int = DataBus[15:0];
// L’altro bus viene assegnato comunque ma ad un valore qualsiasi
// tanto non conta
DataBusRAM1_int = 16’b0;
RnWRAM1=1; RnWRAM2=0; // RAM1 in lettura e RAM2 in scrittura
// La RAM2 va scritta interamente, per la RAM1 non fa differenza
OpcodeRAM1=2’b00; OpcodeRAM2=2’b00;
end
else
begin
DataBusRAM1_int = DataBus[15:0];
// L’altro bus viene assegnato comunque ma ad un valore qualsiasi
// tanto non conta
DataBusRAM2_int = 16’b0;
RnWRAM1=0; RnWRAM2=1; // RAM1 in scrittura e RAM2 in lettura
// La RAM1 va scritta interamente, per la RAM2 non fa differenza
OpcodeRAM1=2’b00; OpcodeRAM2=2’b00;
end
// Accesso per BYTE
3’b1xx:
// A seconda dei due bit meno significativi dell’indirizzo decido cosa
// mettere sui bus delle RAM e quali abilitare
case (AddrBus[1:0])
2’b00: begin
// Sto scrivendo nel byte più significativo di RAM1
DataBusRAM1_int = {DataBus[7:0],8’b0};
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro
// L’altro bus viene assegnato comunque (combinatorio)
// tanto non conta
DataBusRAM2_int = 16’b0;
RnWRAM1=0; RnWRAM2=1; // RAM1: scrivi, RAM2: leggi
// RAM1: scrivi byte più significativo, RAM2: don’t care
OpcodeRAM1=2’b10; OpcodeRAM2=2’b00;
end
2’b01: begin
// Sto scrivendo nel byte meno significativo di RAM1
DataBusRAM1_int = {8’b0,DataBus[7:0]};
// L’altro bus viene assegnato comunque (combinatorio)
// tanto non conta
DataBusRAM2_int = 16’b0;
RnWRAM1=0; RnWRAM2=1; // RAM1: scrivi, RAM2: leggi
// RAM1: scrivi byte meno significativo, RAM2: don’t care
OpcodeRAM1=2’b01; OpcodeRAM2=2’b00;
end
2’b10: begin
// Sto scrivendo nel byte più significativo di RAM2
DataBusRAM2_int = {DataBus[7:0],8’b0};
// L’altro bus viene assegnato comunque (combinatorio)
// tanto non conta
DataBusRAM1_int = 16’b0;
RnWRAM1=1; RnWRAM2=0; // RAM1: leggi, RAM2: scrivi
// RAM1: don’t care, RAM2: scrivi byte più significativo
OpcodeRAM1=2’b00; OpcodeRAM2=2’b10;
end
2’b11: begin
// Sto scrivendo nel byte meno significativo di RAM2
DataBusRAM2_int = {8’b0,DataBus[7:0]};
// L’altro bus viene assegnato comunque (combinatorio)
// tanto non conta
DataBusRAM1_int = 16’b0;
RnWRAM1=1; RnWRAM2=0; // RAM1: leggi, RAM2: scrivi
// RAM1: don’t care, RAM2: scrivi byte più significativo
OpcodeRAM1=2’b00; OpcodeRAM2=2’b01;
end
endcase
default: begin
// Tutti i segnali sono don’t care
DataBusRAM1_int = 16’bx; DataBusRAM2_int=16’bx;
RnWRAM1=1’bx; RnWRAM2=1’bx;
OpcodeRAM1=2’bx; OpcodeRAM2=2’bx;
end
endcase
end
endmodule
ED – Esercizi sulla modellazione Verilog
Massimo Barbaro