Diferență între revizuiri ale paginii „CID aplicatii 2 : Instantiere si porti logice”
(Nu s-a afișat o versiune intermediară efectuată de același utilizator) | |||
Linia 86: | Linia 86: | ||
Observatie: proiectarea si verificarea sunt 2 domenii diferite, firmele avand departamente separate pentru acestea. | Observatie: proiectarea si verificarea sunt 2 domenii diferite, firmele avand departamente separate pentru acestea. | ||
− | Proiectarea/Design se ocupa cu scrierea in Verilog a modului de top si toate modulele ce se afla in acesta, avand ca scop final realizarea fizica pe placa a unui circuit. | + | Proiectarea/Design se ocupa cu scrierea in Verilog/SystemVerilog a modului de top si toate modulele ce se afla in acesta, avand ca scop final realizarea fizica pe placa a unui circuit. |
Verificarea se ocupa de scrierea in SystemVerilog (limbaj format din Verilog cu concepte de POO) a modului de testbench si generarea de stimuli si scenarii care sa testeze functionarea design-ului. | Verificarea se ocupa de scrierea in SystemVerilog (limbaj format din Verilog cu concepte de POO) a modului de testbench si generarea de stimuli si scenarii care sa testeze functionarea design-ului. | ||
Linia 240: | Linia 240: | ||
Cand se doreste implementarea unui circuit pe FPGA, acesta urmeaza urmatoarele etape: | Cand se doreste implementarea unui circuit pe FPGA, acesta urmeaza urmatoarele etape: | ||
− | :'''Elaborarea''' este procesul prin care codul | + | :'''Elaborarea''' este procesul prin care codul SystemVerilog este transformat intr-un circuit la nivel de porti si registre (netlist) si este independent de modelul de FPGA folosit. |
:'''Sinteza''' este procesul în care se realizează transformarea circuitului descris într-un netlist dependent de tehnologie. Se vor folosi la acest pas primitivele disponibile pe FPGA. | :'''Sinteza''' este procesul în care se realizează transformarea circuitului descris într-un netlist dependent de tehnologie. Se vor folosi la acest pas primitivele disponibile pe FPGA. | ||
Linia 283: | Linia 283: | ||
In urmatorul exemplu se implementeaza o poarta NAND din o poarta AND si o poarta NOT. | In urmatorul exemplu se implementeaza o poarta NAND din o poarta AND si o poarta NOT. | ||
− | Codul de mai jos exemplifica ideea de instantiere si contine comentarii legate de sintaxa | + | Codul de mai jos exemplifica ideea de instantiere si contine comentarii legate de sintaxa SystemVerilog necesara. |
In mod uzual fisierele sunt denumite dupa modulul ce se afla in ele, in fiecare fisier fiind un singur modul. | In mod uzual fisierele sunt denumite dupa modulul ce se afla in ele, in fiecare fisier fiind un singur modul. | ||
Linia 291: | Linia 291: | ||
[[Fișier:schema_exemplu_rezolvat.png | 600px]] | [[Fișier:schema_exemplu_rezolvat.png | 600px]] | ||
− | '''Descrierea portii NOT (fisierul not_gate. | + | '''Descrierea portii NOT (fisierul not_gate.sv):''' |
<syntaxhighlight lang="Verilog"> | <syntaxhighlight lang="Verilog"> | ||
// comentarii cu "//" sau cu /* .... */ ; | // comentarii cu "//" sau cu /* .... */ ; | ||
Linia 300: | Linia 300: | ||
module not_gate // cuvant cheie "module" apoi numele modulului (asemanator clase din c++) | module not_gate // cuvant cheie "module" apoi numele modulului (asemanator clase din c++) | ||
( // intre paranteze se pune interfata (firele care intra sau ies din modul) | ( // intre paranteze se pune interfata (firele care intra sau ies din modul) | ||
− | input | + | input logic in0, // in0 este o intrare => input |
− | output | + | output logic out0 // out0 este o intrare => output |
); // aici ";" sa nu il uitati | ); // aici ";" sa nu il uitati | ||
Linia 311: | Linia 311: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | '''Descrierea portii AND (fisierul and_gate. | + | '''Descrierea portii AND (fisierul and_gate.sv):''' |
<syntaxhighlight lang="Verilog"> | <syntaxhighlight lang="Verilog"> | ||
module and_gate | module and_gate | ||
( | ( | ||
− | input in0, // aici sunt 2 intrari | + | input logic in0, // aici sunt 2 intrari |
− | input in1, | + | input logic in1, |
− | output out0 | + | output logic out0 |
); // nu conteaza ordinea in care sunt puse intrarile si iesirile. | ); // nu conteaza ordinea in care sunt puse intrarile si iesirile. | ||
// uzual si pentru usurinta se ordoneaza si grupeaza dupa functionalitate | // uzual si pentru usurinta se ordoneaza si grupeaza dupa functionalitate | ||
Linia 327: | Linia 327: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | '''Descrierea modulului top (fisierul top. | + | '''Descrierea modulului top (fisierul top.sv):''' |
<syntaxhighlight lang="Verilog"> | <syntaxhighlight lang="Verilog"> | ||
module top | module top | ||
( | ( | ||
− | input a, | + | input logic a, |
− | input b, | + | input logic b, |
− | output c | + | output logic c |
); | ); | ||
− | + | logic w0; //declarat un fir intern de legatura | |
and_gate and_gate_0 // instantiere: nume_modul nume_instanta (asemanator int x din c/c++) | and_gate and_gate_0 // instantiere: nume_modul nume_instanta (asemanator int x din c/c++) | ||
Linia 364: | Linia 364: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
− | Echivalent se pot folosi si "primitive" | + | Echivalent se pot folosi si "primitive" SystemVerilog pentru scrierea top-ului. |
Primitivele sunt porti logice care exista deja in limbaj, folosite atunci cand se doreste o descriere structurala a circuitului. | Primitivele sunt porti logice care exista deja in limbaj, folosite atunci cand se doreste o descriere structurala a circuitului. | ||
Linia 373: | Linia 373: | ||
− | '''Descrierea alternativa a modulului top (fisierul top_v2. | + | '''Descrierea alternativa a modulului top (fisierul top_v2.sv):''' |
<syntaxhighlight lang="Verilog"> | <syntaxhighlight lang="Verilog"> | ||
module top_v2 | module top_v2 | ||
( | ( | ||
− | input a, | + | input logic a, |
− | input b, | + | input logic b, |
− | output c | + | output logic c |
); | ); | ||
Linia 393: | Linia 393: | ||
− | '''Descrierea alternativa a modulului top (fisierul top_v3. | + | '''Descrierea alternativa a modulului top (fisierul top_v3.sv):''' |
<syntaxhighlight lang="Verilog"> | <syntaxhighlight lang="Verilog"> | ||
module top_v3 | module top_v3 | ||
( | ( | ||
− | input a, | + | input logic a, |
− | input b, | + | input logic b, |
− | output c | + | output logic c |
); | ); | ||
Linia 410: | Linia 410: | ||
− | '''Descrierea testbench-ului (fisierul top_tb. | + | '''Descrierea testbench-ului (fisierul top_tb.sv):''' |
<syntaxhighlight lang="Verilog"> | <syntaxhighlight lang="Verilog"> | ||
`timescale 1ns / 1ps | `timescale 1ns / 1ps | ||
Linia 416: | Linia 416: | ||
module top_tb(); // din/in tb nu intra si iese nimic. niciodata. | module top_tb(); // din/in tb nu intra si iese nimic. niciodata. | ||
− | + | logic a_tb; | |
− | + | logic b_tb; | |
− | + | logic c_tb; | |
top dut // instantierea modulului de tip "top" sub numele "dut" | top dut // instantierea modulului de tip "top" sub numele "dut" | ||
Linia 428: | Linia 428: | ||
initial | initial | ||
− | begin // in loc de { ... } din c/c++, in | + | begin // in loc de { ... } din c/c++, in SystemVerilog se pune begin ... end |
#10; // dupa 10 unitati de timp | #10; // dupa 10 unitati de timp | ||
a_tb = 0; // a_tb ia valoarea 0 | a_tb = 0; // a_tb ia valoarea 0 | ||
Linia 486: | Linia 486: | ||
Dupa programarea cu succes a placii, puteti testa functionalitatea circuitului prin modficarea valorilor switch-urilor si observarea starii LED-ului. | Dupa programarea cu succes a placii, puteti testa functionalitatea circuitului prin modficarea valorilor switch-urilor si observarea starii LED-ului. | ||
− | |||
− | |||
==Exercitii== | ==Exercitii== | ||
Linia 558: | Linia 556: | ||
[[Fișier:schema_and4_4b_din_and4_1b_v2.png | 600px]] | [[Fișier:schema_and4_4b_din_and4_1b_v2.png | 600px]] | ||
− | Fisierul and4_4b. | + | Fisierul and4_4b.sv: |
<syntaxhighlight lang="Verilog"> | <syntaxhighlight lang="Verilog"> | ||
module and4_4b | module and4_4b | ||
( | ( | ||
− | input | + | input logic [3:0] in0, // in0 are 4b, de la bit 3 la bit 0 inclusiv |
− | input | + | input logic [3:0] in1, // se noteaza msb:lsb (most significant bit: least significant bit) (echivalent cu conceptul de cifra sutelor, cifra unitatilor, pt binar) |
− | input | + | input logic [3:0] in2, |
− | input | + | input logic [3:0] in3, |
− | output | + | output logic [3:0] out0 |
); | ); | ||
Linia 579: | Linia 577: | ||
<syntaxhighlight lang="Verilog"> | <syntaxhighlight lang="Verilog"> | ||
module schema1 (a, b, c, d, f); | module schema1 (a, b, c, d, f); | ||
− | input a, b, c, d; | + | input logic a, b, c, d; |
− | output f, g; | + | output logic f, g; |
− | + | logic w1; | |
− | + | logic w2; | |
and P1 ( w1, a, c ); | and P1 ( w1, a, c ); | ||
Linia 599: | Linia 597: | ||
<syntaxhighlight lang="Verilog"> | <syntaxhighlight lang="Verilog"> | ||
module schema2 (a, b, c, d, f); | module schema2 (a, b, c, d, f); | ||
− | input a, b, c, d; | + | input logic a, b, c, d; |
− | output f; | + | output logic f; |
− | + | logic w1, w2; | |
nand P1 ( w1, a, b ), P2 (w2, c, d); | nand P1 ( w1, a, b ), P2 (w2, c, d); |
Versiunea curentă din 22 octombrie 2024 13:53
Teorie: incapsulare si instantiere
Unitatile constructive de baza din care se formeaza circuitele digitale se numesc porti logice. Acestea implementeaza functii logice si prin conectarea mai multor astfel de circuite simple complexitatea unui circuit poate creste pana la nivelul procesoarelor actuale. Pentru a putea controla cresterea complexitatii in proiectarea unui circuit de dimensiuni mari se folosesc 2 concepte cheie:
1) incapsularea functiei dorite intr-un modul
2) instantierea unor module mai mici si asamblarea acestora pentru a forma un modul mai mare.
Incapsularea se refera la a grupa elementele ce alcatuiesc o anumita functionalitate intre-un modul. Aceste elemente pot la randul lor sa fie alte module. Instantierea (asemanator cu POO) se refera la a apela un modul deja scris pentru a fi folosit efectiv in circuitul curent. Pentru a face o analogie cu programarea, cand se declara o variabila (sau un obiect), tipul variabilei este echivalent cu modulul si numele ei este numele instantei.
Pentru a intelege aceste concepte se da circuitul de mai jos:
Observatii:
1) Notatie aici: Numele modulului este scris in interior.
2) Notatie aici: Numele instantei este scris deasupra.
3) Idee fundamentala: prin instantierea si incapsularea unor circuite simple, mici, apar circuite mai complexe.
4) Idei esentiale (daca vreuna e neclara consultati cadrul didactic):
- a) "modul_2" este instantiat o singura data in tot proiecul, iar instanta se cheama "x"
- b) "modul_2" are o intrare numita "in0" si o iesire numita "out0"
- c) "modul_2" este instantiat in cadrul "modul_6"
- d) Modulul cel mai mare, ce cuprinde toata functionalitatea dorita a sistemului (aici "modul_6") se numeste uzual top.
- e) Instanta top-ului care apare atunci cand se doreste testarea sa in simulare intr-un testbench (tb) se numeste uzual DUT (design under test)
- f) "modul_0" apare instantiat de 3 ori. Circuitul final, cuprinde 3 subcircuite de tip "modul_0".
- g) La nivel de top, instanta sa se cheama "b".
- h) La nivel de "modul_5", cele 2 instante se cheama "a" si "c".
- i) "a" si "c" sunt 2 circuite fizice diferite chiar daca ambele sunt de tipul "modul_0". Fiind instante ale aceluiasi modul, deci identice in alcatuire, luate separat ele fac acelasi lucru. Luate in contextul lui "modul_5", "a" genereaza datele de pe firul "w0" si "c" genereaza datele pentru iesire.
- j) circuitul "b" de tip "modul_1" (instantiat in "modul_5") este complet diferit de circuitul "b" de tip "modul_0" (instantiat in top). Este permis ca ele sa aiba acelasi nume (cele 2 instante) deoarece se afla in locatii diferite.
- k) Identic, mai multe module au o intrare numita "in_0". La sinteza circuitului nu se face confuzie intre acestea deoarece fiecare e vazut la nivelul altei instante.
- l) Identic, firele de legatura "w0", "w1".
- m) La nivelul "top", firul de legatura "w2" leaga iesirea "out_0" a instantei "b" la intrarea "in2" a instantei "y".
- n) La nivelul "top", firul de legatura "w1" leaga iesirea "out_0" a instantei "x" la intrarea "in1" a instantei "y".
- o) La nivelul "modul_5", firul de legatura "w1" leaga iesirea instantei "b" la intrarea instantei "c".
- Pentru claritatea desenului, respectivele intrari si iesiri nu au fost denumite. In cod este obligatoriu ca ele sa fie definite si denumite.
- p) La nivelul "top", "in0","in1","in2","in3","in4" si "out0" formeaza interfata modulului (semnalele care intra sau ies din modul).
- q) La nivelul "top", "w0", "w1", "w2" sunt fire interne de legatura.
- r) La nivelul "top", firul "in3" este conectat ca intrare pentru 3 submodule.
Teorie: testarea circuitelor
Pentru a se testa functionarea corecta a circuitului final, acesta este instantiat intr-un modul numit "test_bench" sau "tb". Acest modul este folosit strict in simulare. Testarea unui circuit are loc conform schemei urmatoare:
Generarea datelor de intrare se va face asemanator cu laboratorul 1.
Voi veti avea rolul modelului ideal si al comparatorului datelor de iesire, uitandu-va la datele de intrare veti calcula iesirea corecta si apoi veti compara aceasta valoare cu raspunsul circuitului ce se testeaza.
In cazul unui sistem automat, se genereaza mesaje de eroare sau mesaje ca functionarea este in regula.
Observatie: proiectarea si verificarea sunt 2 domenii diferite, firmele avand departamente separate pentru acestea.
Proiectarea/Design se ocupa cu scrierea in Verilog/SystemVerilog a modului de top si toate modulele ce se afla in acesta, avand ca scop final realizarea fizica pe placa a unui circuit.
Verificarea se ocupa de scrierea in SystemVerilog (limbaj format din Verilog cu concepte de POO) a modului de testbench si generarea de stimuli si scenarii care sa testeze functionarea design-ului.
Teorie: porti logice
Portile logice folosite uzual, impreuna cu tabelele lor de adevar si reprezentarea grafica sunt date mai jos.
Se folosesc porti logice cu 1 sau 2 intrari, cele cu mai mult de 2 intrari fiind construite din acestea.
Despre FPGA
FPGA-ul (Field-Programmable Gate Array) este un circuit programabil, capabil sa implementeze circuite definit de utilizator. El este format dintr-o matrice de blocuri programabile, interconectate intre ele printr-o serie de conexiuni la randul lor programabile.
Cand se doreste implementarea unui circuit pe FPGA, acesta urmeaza urmatoarele etape:
- Elaborarea este procesul prin care codul SystemVerilog este transformat intr-un circuit la nivel de porti si registre (netlist) si este independent de modelul de FPGA folosit.
- Sinteza este procesul în care se realizează transformarea circuitului descris într-un netlist dependent de tehnologie. Se vor folosi la acest pas primitivele disponibile pe FPGA.
- Implementarea este procesul în care se preia netlist-ul ce conține primitivele FPGA și modul lor de interconectare realizat la pasul de sinteză și se realizează maparea lor efectivă în FPGA (place and route).
- Generarea Bitstream-ului este procesul prin care informatiile din implementare sunt asamblate intr-un singur fisier.
- Programarea este procesul prin care fisierul generat anterior este trimis efectiv catre placa cu FPGA (prin USB) unde determina modificarea valorilor si conexiunilor interne din aceasta.
O introducere mai detaliata poate fi gasita aici : FPGA - Introducere.
Observatii:
- Pentru a putea controla circuitul propus si a putea vedea rezultatele, intrarile si iesirile (input si output din module) in/din acesta trebuie conectate la pini fizici ai FPGA-ului care sunt conectati la butoane/switch-uri/leduri.
- Conexiunile dintre butoane/switch-uri si pinii FPGA sunt fixe. La fel si cele intre pinii FPGA si LED-uri. (in functie de PCB)
- Conexiunile dintre porturile modulului Module si pinii FPGA sunt configurabile. (in functie de noi, prin fisierul XDC)
- Legarea porturilor modulului Module la pinii fizici ai FPGA se realizeaza prin configurarea conexiunilor din FPGA conform contrangerilor de I/O pe care le vom mentiona in proiect, inainte de sinteza.
Exemple
Exemplul 1: Analiza circuitelor cu porti
Fie urmatorul circuit alcatuit din porti logice:
Se doreste exprimarea circuitului de mai sus ca formula de tip: iesire = f(intrari).
Pentru asta, abordarea consta in a porni de la iesire si a merge pas cu pas catre intrari, asa cum este exemplificat mai jos. Se vor folosi simbolurile "~" pentru NOT, "&" pentru AND, "|" pentru OR.
- pas1: out0 = ?
- pas2: out0 = w1 | w2
- pas3: out0 = w1 | ( ? )
- pas4: out0 = w1 | ( sel & in1 )
- pas5: out0 = ( ? ) | ( sel & in1 )
- pas6: out0 = ( in0 & w0 ) | ( sel & in1 )
- pas7: out0 = ( in0 & ( ? ) ) | ( sel & in1 )
- pas8: out0 = ( in0 & (~sel) ) | ( sel & in1 )
Exemplul 2: NAND2 din AND2 si NOT
In urmatorul exemplu se implementeaza o poarta NAND din o poarta AND si o poarta NOT.
Codul de mai jos exemplifica ideea de instantiere si contine comentarii legate de sintaxa SystemVerilog necesara.
In mod uzual fisierele sunt denumite dupa modulul ce se afla in ele, in fiecare fisier fiind un singur modul.
Schema circuitul care se doreste a fi creat este:
Descrierea portii NOT (fisierul not_gate.sv):
// comentarii cu "//" sau cu /* .... */ ;
/*
ca in c/c++
*/
module not_gate // cuvant cheie "module" apoi numele modulului (asemanator clase din c++)
( // intre paranteze se pune interfata (firele care intra sau ies din modul)
input logic in0, // in0 este o intrare => input
output logic out0 // out0 este o intrare => output
); // aici ";" sa nu il uitati
assign out0 = ~in0; // cuvant cheie assign;
// semnalele de tip wire (cum e out0) iau valoare prin assign
// ~ e semnul pentru negatie pe biti (ca in c/c++)
endmodule // cuvant cheie "endmodule". orice module se inchide cu endmodule.
Descrierea portii AND (fisierul and_gate.sv):
module and_gate
(
input logic in0, // aici sunt 2 intrari
input logic in1,
output logic out0
); // nu conteaza ordinea in care sunt puse intrarile si iesirile.
// uzual si pentru usurinta se ordoneaza si grupeaza dupa functionalitate
// in cazul de mai sus, am pus intai intrarile, apoi iesirile.
assign out0 = in0 & in1; // operatia propriu zisa
endmodule
Descrierea modulului top (fisierul top.sv):
module top
(
input logic a,
input logic b,
output logic c
);
logic w0; //declarat un fir intern de legatura
and_gate and_gate_0 // instantiere: nume_modul nume_instanta (asemanator int x din c/c++)
(
.in0(a), // la intrarea "in0" a instantei "and_gate_0" se conecteaza firul "a" din top
.in1(b), // grija ca "in0", "in1", "out0" sa existe in declararea modulului "and_gate"
.out0(w0) // grija ca "a", "b", "w0" sa existe la nivelul modulului in care se face instantierea
);
not_gate not_gate_0
(
.in0(w0), // "w0" care iese din "and_gate_0" intra in "not_gate_0"
.out0(c) // "c" care iese din "not_gate_0" iese din modulul "top" (e iesire in interfata de sus)
); // se poate scrie si ".in0(w0),.out0(c)" dar se prefera fiecare fir pe randul sau (lizibilitate si loc de comentarii pt design-uri complexe)
// Observatie: la varianta de mai sus de instantiere, nu conteaza ordinea firelor.
/*
not_gate not_gate_0
( // se poate instantia si in forma prescurtata ca aici
w0, // in acest caz se pun conexiunile in ordinea in care sunt declarate intrarile si iesirile din modul
c // NU se recomanda stilul asta de instantiere
); // apar greseli frecvent la ordinea firelor, la numarul lor,
*/ // mai ales daca modulul e complex si are multe intrari si intrari
endmodule
Echivalent se pot folosi si "primitive" SystemVerilog pentru scrierea top-ului.
Primitivele sunt porti logice care exista deja in limbaj, folosite atunci cand se doreste o descriere structurala a circuitului.
In instantiere acestora, iesirea se pune prima, urmata de intrari.
Observatie: daca se doreste scrierea acestor porti de catre voi (ca mai sus), numele modulului nu trebuie sa fie un cuvant cheie ocupat de primitive.
Descrierea alternativa a modulului top (fisierul top_v2.sv):
module top_v2
(
input logic a,
input logic b,
output logic c
);
wire w0;
and and_gate_0(w0,a,b); // primitiva pentru poarta and
not not_gate_0(c,w0); // primitiva pentru poarta not
endmodule
Fiind un modul simplu, intreaga functionalitate putea fi scrisa la nivel de "top" si simplificat ca mai jos.
Descrierea alternativa a modulului top (fisierul top_v3.sv):
module top_v3
(
input logic a,
input logic b,
output logic c
);
assign c = ~ (a & b); // a si b, negate
endmodule
Testarea circuitul se face printr-un testbench, acesta fiind:
Descrierea testbench-ului (fisierul top_tb.sv):
`timescale 1ns / 1ps
module top_tb(); // din/in tb nu intra si iese nimic. niciodata.
logic a_tb;
logic b_tb;
logic c_tb;
top dut // instantierea modulului de tip "top" sub numele "dut"
(
.a(a_tb),
.b(b_tb),
.c(c_tb)
);
initial
begin // in loc de { ... } din c/c++, in SystemVerilog se pune begin ... end
#10; // dupa 10 unitati de timp
a_tb = 0; // a_tb ia valoarea 0
b_tb = 0;
#10; // dupa inca 10 unitati de timp, deci in total la 20
a_tb = 1;
b_tb = 0;
#10;
a_tb = 0;
b_tb = 1;
#10;
a_tb = 1;
b_tb = 1;
#10;
a_tb = 0;
b_tb = 0;
#20 $stop(); // oprirea simularii
end //end pentru initial
endmodule
Formele de unda rezultate din simulare se pot vedea mai jos:
In chenarul verde se pot observa instantele din simulare.
Daca se doreste adaugarea de semnale noi pentru a fi vazute, se selecteaza modulul instantiat in care acestea se afla (chenar verde).
Apoi, din chenarul rosu se aleg semnalele si se adauga prin click dreapta->add to wave window.
Pentru o mai usoara vizualizare, semnalele se pot grupa asa cum se vede in chenarul mov prin click dreapta->new group.
Se observa o functionare corecta circuitului, acesta fiind o poarta NAND. El scoate "0" cand ambele semnale de intrare sunt "1" si scoate "1" in rest.
Implementarea circuitului pe FPGA
Dupa ce circuitul a fost testat in simulare, se doreste punerea sa fizica pe placa FPGA. Pentru aceasta, se tine cont de urmatoarele.
- Pentru a controla intrarile a si b ale circuitului 'top, va trebui sa le conectam prin intermediul conexiunilor configurabile ale FPGA-ului la pini ce sunt mai departe conectati fizic la dispozitive ce pot controla valorile semnalelor (switch-uri, butoane).
- Pentru a observa valoarea iesirii, vom conecta semnalul de iesire cla un dispozitiv de observare, cum ar fi un LED, care va fi aprins daca c este 1 si stins daca c este 0.
Pentru a realiza conectarea porturilor modulului top la pinii fizici ai FPGA ce sunt conectati mai departe la componentele de pe placa, va trebui sa specificam in utilitarul de sinteza maparea porturilor la acestia. Maparea se realizeaza prin mentionarea codurilor pinilor la care dorim conexiunea si poata numele de constrangeri de I/O. Aceste coduri sunt mentionate in documentatia placii de dezvoltare cu FPGA (in cazul nostru, PYNQ Z2) si pot fi regasite si in pagina PYNQ-Z2 - Pinout.
Conform schemei, la acest exemplu avem nevoie de codurile pinilor conectati mai departe la Switch0, Switch1 si LED0.
Observatie: Daca intrarile si iesirile ar fi semnale pe mai multi biti, fiecare bit al intrarilor va fi conectat la cate un switch/buton si fiecare bit al iesirii va fi conectat la un LED. Acest lucru este necesar deoarece switch-urile/butoanele pot avea doar doua stari (0 si 1) si astfel pot controla un singur bit. La fel, un LED poate avea doar doua stari (0 - stins si 1 - aprins) si poate afisa starea unui singur bit.
Dupa ce ati extras codurile necesare, urmati pasii descrisi in tutorialul Vivado.
Dupa programarea cu succes a placii, puteti testa functionalitatea circuitului prin modficarea valorilor switch-urilor si observarea starii LED-ului.
Exercitii
Pentru urmatoarele exercitii se doreste atat testarea designurilor prin simulare cat si punerea acestora pe placa. Legat de placa, intrarile vor fi conectate la butoane, iar iesirile la leduri. Se va consulta tabelul cu pini disponibili (Pynq-Z2 - Pinout).
Exista moduri mai rapide de a scrie functionalitatea dorita (vezi exemplu), dar tema principala a acestui laborator este instantierea, asa ca sunteti rugati sa respectati desenele si sa instantiati fiecare poarta individual.
Exercitiul 1: AND4 din AND2
Acest exercitiu arata cum se construieste o poarta AND cu 4 intrari din porti AND mai simple, cu 2 intrari. Iesirea acesteia va fi "1" doar daca toate intrarile sunt "1".
Pentru testarea circuitului, generati in testbench urmatoarele forme de unda (liniile punctate reprezinta 5ns):
Exercitiul 2: OR4 din OR2
Asemanator cu exercitiul anterior, se poate construi si o poarta or cu 4 intrari din porti or cu 2 intrari. Iesirea acesteia va fi "1" doar daca oricare din intrari (cel putin una) este "1".
Pentru testarea circuitului se folosesc formele de unda de la exercitiul 1.
Exercitiul 3: AND4 din AND2 aranjat pe lung (nu arbore)
In multe cazuri, aceeasi functionalitate poate fi atinsa prin circuite care arata diferit. O alta varianta de a face o poarta AND cu 4 intrari este prezentata mai jos.
Comparati cele 2 variante.
Pentru testarea circuitului se folosesc formele de unda de la exercitiul 1.
Exercitiul 4: AND4 din NAND2
Orice poarta logica de baza poate fi construita doar din porti NAND sau doar din porti NOR.
Desenati si implementati circuitul pentru o poarta AND4 din porti NAND cu 2 intrari.
Tip: Incercati intai sa generati o poarta AND2 din NAND2.
Pentru testarea circuitului se folosesc formele de unda de la exercitiul 1.
Exercitiul 5: AND4 pe 4b din AND4 pe 1b
Se pot face operatii logice si pe mai multi biti deodata prin punerea in paralel a mai multor porti cu o singura iesire. Exemplu : pentru intrarile 0011 si 1110 iesirea va fi 0010
Pentru exersarea instantierii si intelegerea circuitului din spatele operatilor multibit implementati acest circuit prin instantierea a 4 porti AND2 pe 1 bit intr-o poarta AND2 pe 4 biti.
Pentru testarea circuitului, generati in testbench urmatoarele forme de unda (liniile punctate reprezinta 5ns):
Exista si un mod mai rapid si simplu de a scrie aceasta functionalitate, grupand intrarile si iesirile in "bus"-uri, ca in codul de mai jos. Acest mod de a grupa firele este desenat mai jos.
Fisierul and4_4b.sv:
module and4_4b
(
input logic [3:0] in0, // in0 are 4b, de la bit 3 la bit 0 inclusiv
input logic [3:0] in1, // se noteaza msb:lsb (most significant bit: least significant bit) (echivalent cu conceptul de cifra sutelor, cifra unitatilor, pt binar)
input logic [3:0] in2,
input logic [3:0] in3,
output logic [3:0] out0
);
assign out0 = in0 & in1 & in2 & in3;
endmodule
Exercitiul 6: Desenati schemele logice pentru urmatoarele circuite:
a) Schema 1
module schema1 (a, b, c, d, f);
input logic a, b, c, d;
output logic f, g;
logic w1;
logic w2;
and P1 ( w1, a, c );
or P2 ( f, w1, w2, d);
not P3 (w2, b);
and P4 (g, w1, b, d);
endmodule
Observatie: In versiunea veche de verilog (si s-a pastrat si in cea curenta), se pot specifica directiile porturilor si in exteriorul parantezelor, ca mai sus. Aceasta scriere NU este recomandata.
b) Schema 2
module schema2 (a, b, c, d, f);
input logic a, b, c, d;
output logic f;
logic w1, w2;
nand P1 ( w1, a, b ), P2 (w2, c, d);
and P3 ( f, w1, w2);
endmodule
Observatie: asemanator cu C/C++, se pot face declaratii in aceeasi linie a mai multor "variabile", aici fire sau instante, cum se poate vedea la w1 si w2 (ambele fiind fire) sau la P1 si P2 (ambele fiind porti nand). Aceasta scriere NU este recomandata.