Diferență între revizuiri ale paginii „CID Seminar 1”
Linia 178: | Linia 178: | ||
<syntaxhighlight lang="verilog"> | <syntaxhighlight lang="verilog"> | ||
circuitlogic dut3(.a(i1), .b (i3), .c(i2),. out (out)); | circuitlogic dut3(.a(i1), .b (i3), .c(i2),. out (out)); | ||
− | circuitlogic dut4(.a(i1), .b(i3), .out(out) | + | circuitlogic dut4(.a(i1), .b(i3), .out(out)); //nu am conectat semnal pe c |
</syntaxhighlight> | </syntaxhighlight> | ||
Versiunea de la data 18 februarie 2014 08:04
În acest seminar veţi învăţa să descrieţi unele circuite digitale simple în limbajul Verilog şi să folosiţi programul Xilinx ISim pentru a simula funcţionarea acestora.
Cuvinte cheie: formă de undă, proiect, modul, instanţiere, testbench
Sintaxa Verilog: module, assign, initial, $stop
În domeniul digital, toate sistemele, circuitele şi blocurile funcţionale sunt conectate între ele numai prin semnale digitale, adică dreptunghiulare (care pot lua doar două valori, 0 si 1).
Cum obţinem formele de undă de la ieşirea unui circuit?
Descriem circuitul într-o manieră inteligibilă (folosind un HDL – în cazul nostru, Verilog). Aplicăm semnale pe intrare şi apoi simulăm funcţionarea, folosind un simulator (aici, Xilinx ISim).
Exemplul 1
Descrieţi în Verilog un circuit de incrementare pentru numere binare pe 4 biţi şi testaţi funcţionarea acestui circuit, folosind modulul test_inc, cu ajutorul programului Model Sim.
Explicaţii suplimentare
Descrierea unui circuit include:
- descrierea interfetei (declararea porturilor)
- descrierea funcţiei (ce face circuitul? în esenţă, cum depind ieşirile de intrări)
Circuitul din acest exemplu are o intrare (in), pe 4 biţi şi o ieşire (out), pe 5 biţi. Bus-urile sunt semnale pe mai mulţi biţi care au o semnificaţie comună, este mai avantajos să îi definim împreună. Funcţia realizată de circuit este out = in + 1.
Regulă: Descrierile circuitelor în Verilog sunt alcătuite din module.
Intrările în Verilog se definesc cu cuvântul input, ieşirile sunt output. Orice modul începe cu cuvântul module şi se termină cu endmodule. Modulele nu se pot suprapune şi nu pot fi incluse unele în altele.
module circuitul_meu(lista_porturi); /* porturile sunt conexiunile externe ale circuitului*/
……//declaraţi mai întâi porturile
……//apoi daţi detaliile funcţionale
endmodule
Liniile de cod în Verilog se încheie cu ";" (există şi excepţii pe care le vom menţiona explicit, de exemplu după ultima linie – endmodule – de mai sus. În principiu, ";" determină o acţiune). Comentariile se introduc cu // sau cu /*....*/, vor apărea scrise în editorul programului cu verde şi sunt ignorate la compilare.
Un scurt tutorial pentru folosirea programului Xilinx ISim găsiţi aici.
Puteți descărca Xilinx ISE 14.7 de pe site-ul departamentului: ftp://zeus.arh.pub.ro/pub/kits/
Simularea funcţionării circuitelor
Pentru a verifica funcţionarea corectă a unui circuitul trebuie să îi aplicăm semnale pe intrare şi să verificăm dacă ieşirea este aşa cum ne-am aşteptat, altfel spus simulăm fucţionarea acestuia. Definim un circuit care este de fapt o platformă de testare (testbench).
Acesta circuit este un modul distinct, special pentru testare, numit de obicei modul de test. Modulul de test nu are conexiuni externe, dar face referinţă la modulul pe care l-am descris anterior.
module test_inc (); //nu are porturi externe, “()” poate lipsi
reg [3:0] a; // aici am definit o variabila pe 4 biti
wire [4:0] b; // aici am definit o conexiune, un “fir” pe 5 biti
//urmeaza generarea semnalelor care vor fi aplicate pe INTRARI
initial begin // intructiunile initial se executa la t = 0
a=0;
#10 a=5; /* #10 reprezinta o intarziere de 10 unitati timp, care se
aduna la intarzierea anterioara, in acest caz la t=0. Deci t
devine t = 10 */
#10 a=8; // aici suntem la t = 20
#15 a=15;
#5 a=4’b0001; // a este de fapt un semnal pe patru biti
#5 a=4’b0100;
#30 $stop; // va opri simularea, este bine sa nu lipseasca
end // dupa begin si end nu se pune “;”
inc dut(a, b); // atentie! modulul de incrementare trebuie denumit inc
endmodule
Exemplul 2
- Descrieţi în Verilog o poartă ŞI cu trei intrări.
- Testaţi funcţionarea acestei porţi.
Explicaţii suplimentare
Principalele funcţii logice (şi porţile logice corespunzătoare) sunt prezentate aici. Funcţia ŞI (AND) cu trei intrări ia valoarea 1 numai dacă toate intrările sunt 1, în rest ia valoarea 0.
Definirea porturilor unui circuit se poate face:
- în corpul modulului
- compactat, în lista porturilor
Varianta1 (Verilog '95)
module poarta_AND_3 (a, b, c, out);
input a, b, c; // putem pune mai multe pe aceeasi linie, separate cu ,
output out;
.....
endmodule
Varianta 2. (Verilog 2001)
module poarta_AND_3 (
input a, // scriem cu tab-uri ca sa fie vizibile
input b,
input c,
output out);
...
endmodule
Aici avem mai multe intrări pe 1 bit deci putem scrie şi
module poarta_AND_3 (
input a, b, c, // scriem cu tab-uri ca sa fie vizibile
output out);
...
endmodule
Vom verifica funcţionarea corectă cu modulul de test.
Completaţi formele de undă la intrare cu mai multe combinaţii logice. Simulaţi funcţionarea circuitului.
Exemplul 3
Folosiţi modulul anterior de test pentru a testa funcţionarea unui circuit care calculează funcţia logică out=ac+b.
Observaţie: Notaţiile simple folosite pentru funcţii logice în scrierea curentă nu sunt identice cu simbolurile operatorilor din Verilog.
Funcţie logică | Simbol | operator Verilog |
---|---|---|
ȘI | • (se poate omite) | & |
SAU | + | | |
XOR | ⊕ | ^ |
NOT | ' | ~ |
Explicaţii suplimentare
Atenție: În explicaţia de mai jos modulul respectiv este denumit circuitlogic şi are porturile a, b, c, out ca în figură. În modulul de test veţi experimenta simultan mai multe conexiuni posibile pentru semnalele de test, instanţiind de mai multe ori circuitul.
circuitlogic dut1(i1, i2, i3, out);
circuitlogic dut2(i1, i3, i2, out);
circuitlogic dut3(.a(i1), .b (i3), .c(i2),. out (out));
circuitlogic dut4(.a(i1), .b(i3), .out(out)); //nu am conectat semnal pe c
Instanţierea permite folosirea unui modul, după ce el a fost definit. Odată ce am definit un modul, numele lui este similar unei instrucţiuni a limbajului Verilog.
De exemplu, după ce am definit poarta ŞI cu 3 intrări putem folosi două porţi de acest tip, P1 şi P2, fiecare din ele fiind o poartă SI cu 3 intrări
poarta_AND_3 P1(i1, i2, i3, w1); // trebuie neaparat sa precizam numele
poarta_AND_3 P2(i4, i5, i6, w2);
Porturile se pot conecta ţinând cont de ordinea lor (ca mai sus), sau definind explicit semnalele conectate pe fiecare port:
circuitlogic dut3(.a(i1), .b (i3), .c(i2),. out (out));
circuitlogic dut4(.a(i1), .b(i3), .out(out)); //nu am conectat semnal pe c
Deşi le putem scrie în orice ordine, preferăm să le scriem în aceeaşi ordine! Este posibil să nu conectăm semnale pe toate intrările, dacă într-un context particular nu sunt necesare.
Modulul trebuie să fie definit în acelaşi proiect (nu neapărat în acelaşi fişier).
Exemplul 4
Descrieţi structural o poartă ŞI cu 3 intrări folosind 2 porţi ŞI cu 2 intrări, în următoarele variante:
- descrieţi poarta ŞI cu două intrări
- folosiţi primitiva and din Verilog
Explicaţii suplimentare
Descrierea unor scheme în Verilog (adică, a structurii unui circuit) se face instanţiind diferitele componente ale schemei şi conectând corespunzător semnalele din circuit pe porturile modulelor. Nu are nicio importanţă ordinea instrucţiunilor de instanţiere, deoarece ele rulează în paralel. Un modul care este apelat (prin instanţiere) trebuie să fie definit în acelaşi proiect.
Porţi logice în Verilog
În Verilog, porțile logice elementare sunt predefinite ca primitive, există deci cuvinte speciale de limbaj.
Pentru funcția ŞI:
and (out, in1, in2,..., ink); // intotdeauna prima e iesirea
and P1(out, in1, in2); // este bine sa dam si un nume fiecarei porti
Celelalte porţi logice sunt: nand, or, nor, xor, xnor. La toate aceste porţi, implicit prima este ieşirea şi se pot pune oricâte intrări.
Inversorul este definit cu not și poate avea mai multe ieșiri:
not P2 (out1, out2, in);
Exemplul 5
Desenaţi schema descrisă de următorul cod Verilog:
diferenta D(.in1(a), .in2 (b), .br (s), .out (dif));
complement C(.in(dif), .out(c2dif));
mux M(.in0(dif), .in1(cdif), .sel(s), .out(out));
... unde modulele au porturile declarate astfel:
module diferenta (
input [3:0] in1, in2,
output [3:0] out,
output br);
/* acest circuit face diferenta a doua numere in1 si in2, rezultatul este pe 4 biti si un bit de borrow, imprumut, br */
...
endmodule
module complement (
input [3:0] in,
output [3:0] out);
/* acest circuit calculeaza complementul fata de 2 pe 4 biti */
...
endmodule
module mux (
input [3:0] in0, in1,
input sel,
output [3:0] out);
/* acest circuit selecteaza la iesire unul dintre cele doua semnale de pe intrare, i0 sau i1, avand fiecare 4 biti, dupa cum bitul de selectie este 0, respectiv 1
iesirea circuitului este deci un semnal pe 4 biti*/
...
endmodule
Temă
- Descrieţi structural în Verilog circuitul din figură (veţi descrie efectiv schema cu porţi logice). Atenţie! trebuie definite toate interconexiunile ca wire.
- Descrieţi comportamental acelaşi circuit (folosind operatori logici şi instrucţiunea assign).
- Descrieţi în Verilog modulele componente ale circuitului din exemplul 5 (diferența, complement, mux) astfel încât să realizeze funcţiile precizate şi testaţi distinct fiecare modul în parte. Indicaţie: Modulul pentru multiplexor poate fi descris folosind instrucţiunea de atribuire condiţionată care este explicată în seminarul 2 (dar o puteţi găsi şi aici)
- Simulaţi funcţionarea întregului circuit din exemplul 5. Indicaţie: Trebuie să descrieti mai întâi modulul Top, care cuprinde cele trei instanţieri.
Reguli de bună practică
Organizarea fişierelor
- Salvaţi modulele pe care le scrieţi în fişiere distincte.
- Numele fişierului să fie identic cu numele modulului.
- Pentru simulare, folosiţi un folder distinct.
Scrierea codului
- Daţi nume sugestive modulelor, porturilor şi semnalelor.
- Introduceţi comentarii pentru documentarea codului.
- Folosiţi tab-uri şi linii goale pentru alinierea şi gruparea blocurilor de instrucţiuni.