Sunteți pe pagina 1din 6

STRUCTURI COMBINAŢIONALE MSI

IMPLEMENTATE ÎN VERILOG

1. Scopul lucrării
Descrierea structurală şi comportamentală a principalelor structuri
combinaţionale de uz general în limbajul Verilog şi înţelegerea funcţionării lor prin
testare cu ajutorul simulatorului Veriwell.

2. Aparate necesare
- calculator compatibil Pentium
- sistem de operare Windows 95 sau superior
- programul VeriWell 2.0, produs de Wellspring Solutions, versiunea
freeware, disponibilă pe Internet

3. Consideraţii teoretice
Circuitele combinaţionale MSI (Medium Scale Integration) de uz general sunt
multiplexorul (MUX), decodificatorul (DCD) şi demultiplexorul (DMUX). Memoria
ROM (Read Only Memory) este tot o structură combinaţională. De obicei, este de
mari dimensiuni şi atunci este considerată o structură LSI (Large Scale Integration),
dar poate fi considerată şi o structură MSI atunci când este de mici dimensiuni.
Multiplexorul este un circuit care permite transmiterea datelor de la una
din cele 2 n căi de intrare la o singură cale de ieşire. Selecţia unei anumite intrări
de date se face prin aplicarea unui cod binar pe n linii de intrare, linii care se
numesc intrări de selecţie. Reprezentarea unui multiplexor pentru n = 4 este dată
în figura 3.1. Descrierea comportamentală a circuitului poate fi următoarea:
module mux16_1(out, in, sel);

input[3:0] sel; // intrarile de selectie


input[15:0] in; // intrarile de date

output out; // iesirea, care este una dintre intrarile selectate

assign out = in[sel]; // selectia se face prin atribuire

endmodule

in[0] in[1] in[15]


.........
0 1 15
sel[3] 23
sel[2] 22
MUX 16:1
sel[1] 21
sel[0] 20 w

out = in[sel]

Fig. 3.1 Multiplexor cu 4 intrări de selecţie şi 16 intrări de date

1
a b
if (cnt == 0)
0 1
cnt out = a;
S MUX
else
W
out = b;
out

Fig. 3.2 Multiplexor cu o intrare de selecţie şi 2 intrări de date şi modelul lui Verilog

Se pot face şi alte descrieri comportamentale folosind, de exemplu,


instrucţiunile if sau case. În figura 3.2 s-a exemplificat modelul unui multiplexor cu
n = 1 care foloseşte instrucţiunea if. Un exemplu de folosire a instrucţiunii case tot
pentru n = 4 este dat mai jos, dar se vede că modelul este mult prea complicat:
module mux16_1(out, in, sel);

input[3:0] sel;
input[15:0] in;

output out;
reg out; // se fac atribuiri lui out

always @(sel) case (sel) // de cate ori se modifica intrarea de selectie, se


// recalculeaza out
4’b0000: out = in[0];
4’b0001: out = in[1];
4’b0010: out = in[2];
4’b0011: out = in[3];
4’b0100: out = in[4];
4’b0101: out = in[5];
4’b0110: out = in[6];
4’b0111: out = in[7];
4’b1000: out = in[8];
4’b1001: out = in[9];
4’b1010: out = in[10];
4’b1011: out = in[11];
4’b1100: out = in[12];
4’b1101: out = in[13];
4’b1110: out = in[14];
4’b1111: out = in[15];
endcase

endmodule

Pentru testarea circuitului, este imposibil să generăm toate combinaţiile


posibile pe cele 20 intrări combinaţionale. Acceptăm un vector de date de intrare
cunoscut, de exemplu 1110010110000011, şi verificăm cum se face comutarea căilor
de intrare prin modificarea vectorului de selecţie. Registrul sel devine de fapt un
numărător, care este incrementat la fiecare 10 unităţi de timp:
module test_mux;

reg[3:0] sel;
reg[15:0] in;
wire out;

initial #330 $stop; // simularea se opreste la t = 330

initial begin sel = 4'b0; // se initializeaza registrul sel


in = 16'b1110010110000011;
forever #10 sel = sel + 1;
end

2
mux16_1 dut(out, in, sel);

initial begin $vw_dumpvars;


$monitor("Time=%0d out=%b", $time, dut.out);
end
endmodule

Demultiplexorul este un circuit care realizează funcţia inversă celei de


multiplexare, permiţând transmiterea datelor de pe o singură cale de intrare pe una
din cele 2 n căi de ieşire. Selecţia liniilor de ieşire se face prin aplicarea unui cod
binar pe n linii de intrare, care devin acum intrări de selecţie. Descrierea
circuitului şi simularea funcţionării lui se poate face ca şi în cazul
multiplexorului.
Decodificatorul este un circuit care transformă un cod de intrare în alt cod
de ieşire. Decodificatorul binar-zecimal identifică un cod binar de intrare prin
activarea unei singure linii de ieşire. Dacă circuitul are n variabile binare de
intrare, atunci numărul liniilor de ieşire este 2 n . Figura 3.3 exemplifică acest
circuit pentru cazul n = 2.
Un alt exemplu este decodificatorul BCD-7segmente, care transformă
codurile binare ale celor 10 cifre zecimale de la 0 la 9 într-un cod pe 7 biţi.
Aceste 7 ieşiri pot comanda segmentele unui element de afişare care ne permite să
vizualizăm comod cifra afişată (figura 3.4). Tabelul de adevăr al circuitului este
prezentat în figura 3.5. Descrierea circuitului se poate face cu ajutorul
instrucţiunii case, iar modulul pentru testarea circuitului poate fi următorul:
module test_trans;

reg[3:0] counter;
wire[6:0] segments;

initial #22 $stop;

initial begin counter = 0;


forever #1 counter = counter + 1;
end

seven_seg dut(segments, counter);

initial $monitor("time=%0d input=%b output=%b",


$time, counter, dut.segments);

endmodule

1 A B 0 1 2 3
A 2
DCD
0 0 0 0 1 1 1
B 2
0 1 2 3 0 1 1 0 1 1
1 0 1 1 0 1
P0 P1 P2 P3 1 1 1 1 1 0

Fig. 3.3 Decodificatorul binar-zecimal şi tabelul lui de adevăr pentru n=2

a
f g b

e c
d

Fig. 3.4 Afişajul cu 7 segmente şi notaţiile folosite

3
counter segments
BCD - 7 segmente 0000 1111110
3 a segments[6] 0001 0110000
counter[3] 2 0010 1101101
b segments[5]
0011 1111001
counter[2] 2
2 c segments[4] 0100 0110011
d segments[3] 0101 1011011
1
counter[1] 2 e segments[2] 0110 1011111
f segments[1] 0111 1110000
0
counter[0] 2 g segments[0] 1000 1111111
1001 1111011

Fig. 3.5 Decodificatorul BCD-7segmente şi tabelul lui de adevăr

Se poate observa că pentru combinaţiile care nu au fost precizate explicit în


instrucţiunea case (intrările 10, 11, ..., 15) se ia ultima valoare din instrucţiunea case.
Deci pentru orice combinaţie BCD interzisă, se va afişa tot “ 9 “. Acest lucru se poate
evita printr-o linie suplimentară în tabelul de adevăr.
Memoria ROM este tot un convertor de cod format dintr-un decodificator şi
un codificator. Spre deosebire de decodificator, ea este o structură programabilă, deci
conţinutul ei poate fi modificat de utilizator prin programarea memoriei, iar apoi
numai citit pentru o aplicaţie oarecare. Şi decodificatorul BCD-7segmente din
exemplul anterior poate fi implementat cu o memorie ROM. Soluţia este funcţională,
dar este de obicei mai scumpă şi mai lentă.
Informaţia din memoria ROM este organizată matricial, având un număr de
cuvinte care au o lungime stabilită ca număr de biţi pe cuvânt. Fiecare cuvânt poate fi
selectat printr-un cod binar aplicat pe intrările de adresă ale memoriei. De exemplu,
circuitul din figura 3.6 este o memorie ROM cu organizarea de 8 cuvinte a câte 4 biţi
fiecare. Dacă mem.dat este un fişier care conţine cei 32 biţi de date, amplasaţi pe 8
linii şi 4 coloane, atunci citirea datelor din memorie se poate face cu următorul modul:
module testmemory;
reg [3:0] memory [7:0];
integer index;

initial begin
$readmemb("mem.dat", memory);

for(index = 0; index < 8; index = index + 1)


$display("memory[%d] = %b", index[4:0], memory[index]);
end
endmodule

Toate circuitele s-au prezentat funcţional, fără alte intrări de validare a datelor
la ieşire (ENABLE, OUTPUT ENABLE), pentru simplitatea descrierilor.

ROM A2 A1 A0 O0 O1 O2 O3
O0 0 0 0 1 1 1 0
A2 0 0 1 1 1 0 1
O1 0 1 0 1 0 1 1
A1 0 1 1 0 1 1 1
O2 1 0 0 0 0 0 1
A0 1 0 1 0 0 1 0
O3 1 1 0 0 1 0 0
1 1 1 1 0 0 0

Fig. 3.6 Memorie ROM şi tabelul ei de adevăr

4
4. Modul de lucru
4.1. Se lansează în execuţie VeriWell 2.0, se deschide proiectul mux1.prj şi
se vizualizează fişierele componente mux1.v şi test_mux1.v. Faceţi simularea
circuitului şi verificaţi că nu aveţi erori. Vizualizaţi formele de undă, folosind
fereastra wavefile.vwf. Modificaţi fişierele proiectului, dar salvaţi-le cu alte nume
într-un subdirector nou, creat de dumneavoastră, şi reluaţi simulările pentru cazurile n
= 3 şi n = 2. Încercaţi modelul prezentat în figura 3.2 pentru n = 1. Formulaţi o
descriere structurală pentru acest ultim caz şi refaceţi simulările.

4.2. Se deschide proiectul bcd_7seg.prj şi se vizualizează fişierele


componente bcd_7seg.v şi test_bcd_7seg.v. Faceţi simularea circuitului şi
verificaţi că nu aveţi erori. Vizualizaţi formele de undă, folosind fereastra
wavefile.vwf. Comentaţi rezultatele obţinute.

4.3. Descrierea comportamentală a unui decodificator binar-zecimal cu 4


intrări de selecţie şi cu ieşirea activă pe 1 logic este dată în următorul modul:
module dec4_16(out, sel);

input[3:0] sel;
output[15:0] out;

assign out = 16'b1 << sel;

endmodule

Descrierea structurală a aceluiaşi circuit este dată în următorul modul:


module dec4_16(out, sel);

input[3:0] sel;
output[15:0] out;

wire w0, w1, w2, w3, nw0, nw1, nw2, nw3;

not not_3(nw3, sel[3]),


not_2(nw2, sel[2]),
not_1(nw1, sel[1]),
not_0(nw0, sel[0]),
buf_3(w3, nw3),
buf_2(w2, nw2),
buf_1(w1, nw1),
buf_0(w0, nw0);

and and_15(out[15], w3, w2, w1, w0),


and_14(out[14], w3, w2, w1, nw0),
and_13(out[13], w3, w2, nw1, w0),
and_12(out[12], w3, w2, nw1, nw0),
and_11(out[11], w3, nw2, w1, w0),
and_10(out[10], w3, nw2, w1, nw0),
and_09(out[09], w3, nw2, nw1, w0),
and_08(out[08], w3, nw2, nw1, nw0),
and_07(out[07], nw3, w2, w1, w0),
and_06(out[06], nw3, w2, w1, nw0),
and_05(out[05], nw3, w2, nw1, w0),
and_04(out[04], nw3, w2, nw1, nw0),
and_03(out[03], nw3, nw2, w1, w0),
and_02(out[02], nw3, nw2, w1, nw0),
and_01(out[01], nw3, nw2, nw1, w0),
and_00(out[00], nw3, nw2, nw1, nw0);

endmodule

5
Verificaţi cele două modele prin simulare în mediul VeriWell. Comparaţi cele
două modele din punct de vedere al complexităţii lor. Folosind modelul structural
desenaţi schema logică cu porţi a decodificatorului prezentat.

4.4. Descrieţi comportamental un demultiplexor cu 3 intrări de selecţie.


Semnalul aplicat la intrare este un semnal de ceas cu perioada de 20 unităţi de timp. El
trebuie să fie vizualizat la diferite ieşiri ale demultiplexorului, în funcţie de codul de
selecţie aplicat pe intrări. Verificaţi prin simulare funcţionarea circuitului. Generarea
semnalului periodic se poate face cu următoarea secvenţă:
initial begin
clock = 1’b0;
forever #10 clock = ~clock;
end

4.5. Analizaţi următorul modul Verilog. Explicaţi ce face programul şi rulaţi-l


în mediul VeriWell pentru a verifica funcţionarea lui:
module fileDemo;

integer handle, channels, index, rand;


reg [7:0] memory [15:0];

initial begin
handle = $fopen("mem.dat");
channels = handle | 1;
$display("Generating contents of file mem.dat");
$fdisplay(channels, "@2");

for(index = 0; index < 14; index = index + 1) begin


rand = $random;
$fdisplay(channels, "%b", rand[12:5]);
end

$fclose(handle);

$readmemb("mem.dat", memory);

display("\nContents of memory array");


or(index = 0; index < 16; index = index + 1)
$displayb(memory[index]);
end

endmodule

S-ar putea să vă placă și