Diferență între revizuiri ale paginii „CID Aplicatii 4”
Sduda (discuție | contribuții) |
|||
(Nu s-au afișat 6 versiuni intermediare efectuate de un alt utilizator) | |||
Linia 1: | Linia 1: | ||
== Memoria ROM–Introducere == | == Memoria ROM–Introducere == | ||
− | Memoria ROM(Read-Only Memory)este | + | Memoria ROM(Read-Only Memory) este un circuit combinational folosit pentru stocarea unor date ce pot fi accesate cu ajutorul unei intrari de adrese. Asa cum se intelege si din nume, memoria ROM, in general, nu poate fi modificata. |
− | Pentru | + | Pentru a intelege termenul de memorie, putem face urmatorul exercitiu de imaginatie: sa ne gandim la un dulap cu mai multe sertare. Continutul memoriei este reprezentat de continutul sertarelor, iar adresele sunt reprezentate de etichetele lipite pe aceste sertare, pentru a le identifica. Daca avem nevoie de continutul unui sertar, va trebui sa stim eticheta aferenta acestuia. |
− | Am | + | Am intalnit memoria ROM in aplicatiile anterioare, atunci cand am vorbit despre structura unui FPGA. Am vazut atunci ca functiile logice erau implementate pe FPGA prin intermediul unor LUT-uri (memorii ROM), care stocau iesirile corespunzatoare unor combinatii de intrari. Asadar, in cazul acela, adresele erau reprezentate de combinatii ale intrarilor, iar continutul memoriei era reprezentat de iesirile aferente acestor combinatii. |
− | O memorie ROM are urmatorii | + | O memorie ROM are urmatorii parametri: numarul de biti ai adresei, care este legat de numarul de locatii de memorie (cu n biti de adresa putem forma 2<sup>𝑛</sup> combinatii diferite, deci putem accesa maxim 2<sup>𝑛</sup> locatii de memorie) si dimensiunea locatiei de memorie, care ne spune cat de multa informatie poate stoca o locatie de memorie. |
Linia 17: | Linia 17: | ||
− | Aici, | + | Aici, adresa are dimensiunea de 4 biti, asadar putem accesa cu aceasta 16 locatii diferite de memorie. Dimensiunea fiecarei locatii este de 8 biti, asadar fiecare locatie de memorie poate stoca numere de 8 biti. Spunem ca memoria ROM este o memorie 4x8. Capacitatea acestei memorii este de 16 x 8 biti = 128 biti. |
== Exemplul 1 == | == Exemplul 1 == | ||
− | '''Scop''': Descrierea | + | '''Scop''': Descrierea comportamentala a unui decodor, testarea acestuia prin simulare si sinteza pe FPGA. |
− | Decodorul este circuitul care, pentru o anumita valoare a intrarii, va genera | + | Decodorul este circuitul care, pentru o anumita valoare a intrarii, va genera la iesire un sir binar care contine 1 pe pozitia cu indicele egal cu valorea intrarii si 0 in rest. De exemplu, decodorul de mai jos pe 2 biti, va avea urmatoarea corespondenta intrare-iesire: |
{| class="wikitable" | {| class="wikitable" | ||
Linia 41: | Linia 41: | ||
− | Vom implementa acest circuit ca | + | Vom implementa acest circuit ca memorie ROM. |
Linia 93: | Linia 93: | ||
</syntaxhighlight> | </syntaxhighlight> | ||
+ | |||
+ | '''Observatii:''' | ||
+ | * Circuitul Decoder va avea o intrare pe 2 biti, care va reprezenta adresa memoriei ROM si o iesire pe 4 biti, reprezentand continuturile memoriei ROM corespunzatoare fiecarei combinatii de la intrare. | ||
+ | * Chiar daca in interiorul instructiunii ''case'' se acopera toate cazurile posibile (toate combinatiile de 2 biti), este bine sa punem si un ''default'' pentru a evita inserarea in locul circuitului combinational dorit (aici, memoria ROM) a unui latch. | ||
+ | |||
+ | '''Implementarea pe FPGA:''' | ||
+ | * Implementarea pe FPGA are ca tinta doar modulul in sine (Decoder), modulul de test (Decoder_TB) fiind nesintetizabil. | ||
+ | * Semnalele de intrare vor fi legate la dispozitive care comanda stari, iar iesirile la dispozitive care observa stari. Asadar, vom alege aici comutatoare pentru intrari (cate un comutator pentru fiecare bi tal fiecarei intrari –2 in total) si 4 LED-uri pentru iesiri. | ||
+ | |||
+ | {| class="wikitable" | ||
+ | |- align="center" | ||
+ | ||'''Semnal''' || '''Dispozitiv''' || '''PIN''' | ||
+ | |- align="center" | ||
+ | | in[0] || SW0 || AB12 | ||
+ | |- align="center" | ||
+ | | in[1] || SW1 || AC12 | ||
+ | |- align="center" | ||
+ | | out[0] || LEDR0 || V16 | ||
+ | |- align="center" | ||
+ | | out[1] || LEDR1 || W16 | ||
+ | |- align="center" | ||
+ | | out[2] || LEDR2 || V17 | ||
+ | |- align="center" | ||
+ | | out[3] || LEDR3 || V18 | ||
+ | |||
+ | |} | ||
+ | |||
+ | |||
+ | [[Fișier:Fpga connections.PNG | 600px]] | ||
+ | |||
+ | |||
+ | ==Exemplul 2 == | ||
+ | |||
+ | '''Scop:''' Implementarea unui circuit de afisare a sumei dintre doua numere pe 2 biti, folosind afisajul cu 7 segmente | ||
+ | |||
+ | [[Fișier:Add and display.PNG | 500px]] | ||
+ | |||
+ | |||
+ | ''' Implementarea Verilog amodululuiAdder2b''' | ||
+ | |||
+ | <syntaxhighlight lang="Verilog"> | ||
+ | module Adder2b( | ||
+ | input [1:0] in0, | ||
+ | input [1:0] in1, | ||
+ | output reg [2:0] sum | ||
+ | ); | ||
+ | |||
+ | always@(*) begin | ||
+ | sum = in0 + in1; | ||
+ | end | ||
+ | |||
+ | endmodule | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | '''Observatii:''' | ||
+ | * Suma a doua numere pe n biti este un numar pe n+1 biti, cel de-al n+1 -ulea fiind bitul de carry. De aceea, aici suma a doua numere pe 2 biti va fi un numar pe 3 biti. | ||
+ | * Aici consideram un sumator simplu, pentru care carry este inglobat in suma (nu este explicit un port separat). | ||
+ | |||
+ | '''Implementarea Verilog a modululuiAfisaj7Seg''' | ||
+ | |||
+ | Inainte de a prezenta codul Verilog, trebuie sa intelegem cum functioneaza afisajul cu 7 segmente. Acest dispozitiv de afisare este format, asa cum sugereaza si numele, din 7 segmente ce pot fi controlate separat. Putem aprinde sau stinge fiecare segment controland tensiunea aplicata pe acesta. Pentru acest afisaj, comanda este negativa: aplicand 0 logic pe un segment acesta se va aprinde, iar aplicand 1 logic, acesta se va stinge. | ||
+ | Structura unui afisaj cu 7 segmente este prezentata in imaginea de mai jos: | ||
+ | |||
+ | [[Fișier:7LED display.PNG | 200px]] | ||
+ | |||
+ | Pentru a reprezenta, de exemplu, cele 16 numere hexa, segmentele trebuie aprinse conform Anexei 1. | ||
+ | |||
+ | In cazul circuitului nostru, vom vrea sa afisam numerele de la 0 la 6, deoarece suma maxima ce poate fi obtinuta este 6. Pentru aceasta, implementam o memorie ROM care va contine codurile de aprins-stins pentru fiecare segment, fiind accesate pe baza numarului pe care dorim sa il afisam. Asadar, intrarea memoriei ROM (adresa) va fi pe 3 biti (3 biti sunt de ajuns pentru a reprezenta numerele de la 0 la 6), iar iesirea va fi pe 7 biti, cate un bit de stare pentru fiecare segment. Vom considera, asadar, ca bitul 0 al iesirii se va lega la segmentul 0, bitul 1 la segmentul 1 si tot asa. | ||
+ | |||
+ | De exemplu, daca la intrare vom avea 0, memoria ROM va trebui sa dea la iesire sirul 1000000, stingand segmentul 6 si aprinzandu-le pe toate celelalte. Extinzand pentru toate numerele de la 0 la 7, obtinem: | ||
+ | |||
+ | {| class="wikitable" | ||
+ | |- align="center" | ||
+ | ||'''Numar''' || '''Sir de afisare''' | ||
+ | |- align="center" | ||
+ | | 0 || 7'b100_0000 | ||
+ | |- align="center" | ||
+ | | 1 || 7'b111_1001 | ||
+ | |- align="center" | ||
+ | | 2 || 7'b010_0100 | ||
+ | |- align="center" | ||
+ | | 3 || 7'b011_0000 | ||
+ | |- align="center" | ||
+ | | 4 || 7'b001_1001 | ||
+ | |- align="center" | ||
+ | | 5 || 7'b001_0010 | ||
+ | |- align="center" | ||
+ | | 6 || 7'b000_0010 | ||
+ | |} | ||
+ | |||
+ | |||
+ | '''Implementarea Verilog a modululuiDisplay7Seg''' | ||
+ | |||
+ | |||
+ | <syntaxhighlight lang="Verilog"> | ||
+ | module Display7Seg( | ||
+ | input [2:0] in, | ||
+ | output reg [6:0] out | ||
+ | ); | ||
+ | |||
+ | always@(in) begin | ||
+ | case(in) | ||
+ | 3'd0: out = 7'b1000000; | ||
+ | 3'd1: out = 7'b1111001; | ||
+ | 3'd2: out = 7'b0100100; | ||
+ | 3'd3: out = 7'b0110000; | ||
+ | 3'd4: out = 7'b0011001; | ||
+ | 3'd5: out = 7'b0010010; | ||
+ | 3'd6: out = 7'b0000010; | ||
+ | default: out = 7'b0000110; | ||
+ | endcase | ||
+ | end | ||
+ | |||
+ | endmodule | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | '''Implementarea Verilog a circuitului AddAndDisplay''' | ||
+ | |||
+ | <syntaxhighlight lang="Verilog"> | ||
+ | module AddAndDisplay( | ||
+ | input [1:0] in0, | ||
+ | input [1:0] in1, | ||
+ | output [6:0] displayCode | ||
+ | ); | ||
+ | |||
+ | wire [2:0] sum; | ||
+ | |||
+ | Adder2b ADD ( | ||
+ | .in0(in0), | ||
+ | .in1(in1), | ||
+ | .sum(sum) | ||
+ | ); | ||
+ | |||
+ | Display7Seg DISPLAY( | ||
+ | .in(sum), | ||
+ | .out(displayCode) | ||
+ | ); | ||
+ | |||
+ | endmodule | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | '''Implementarea Verilog a modulului de test''' | ||
+ | |||
+ | <syntaxhighlight lang="Verilog"> | ||
+ | module AddAndDisplay_TB(); | ||
+ | |||
+ | reg [1:0] in0_t, in1_t; | ||
+ | wire [6:0] displayCode_t; | ||
+ | |||
+ | integer idx, jdx; | ||
+ | |||
+ | initial begin | ||
+ | for(idx=0; idx<4; idx = idx + 1) begin | ||
+ | for(jdx=0; jdx<4; jdx = jdx + 1) begin | ||
+ | in0_t = idx; | ||
+ | in1_t = jdx; | ||
+ | #1; | ||
+ | end | ||
+ | end | ||
+ | #2 $stop(); | ||
+ | end | ||
+ | |||
+ | AddAndDisplay DUT( | ||
+ | .in0(in0_t), | ||
+ | .in1(in1_t), | ||
+ | .displayCode(displayCode_t) | ||
+ | ); | ||
+ | |||
+ | endmodule | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ''' Implementarea pe FPGA:''' | ||
+ | |||
+ | Implementarea pe FPGA are ca tinta doar modulul in sine (AddAndDisplay), modulul de test (AddAndDisplay_TB) fiind nesintetizabil. | ||
+ | |||
+ | Conform indicatiilor din Introducere, semnalele de intrare vor fi legate la dispozitive care comanda stari, iar iesirile la dispozitive care observa stari. Asadar, vom alege aici comutatoare pentru intrari (cate un comutator pentru fiecare bit al fiecarei intrari –4 in total) si afisajul cu 7 segmente Digit 0 pentru iesire. | ||
+ | |||
+ | {| class="wikitable" | ||
+ | |- align="center" | ||
+ | ||'''Semnal''' || '''Dispozitiv''' || '''PIN''' | ||
+ | |- align="center" | ||
+ | | in[0] || SW0 || AB12 | ||
+ | |- align="center" | ||
+ | | in[1] || SW1 || AC12 | ||
+ | |- align="center" | ||
+ | | in[2] || SW2 || AF9 | ||
+ | |- align="center" | ||
+ | | in[3] || SW3 || AF10 | ||
+ | |||
+ | |- align="center" | ||
+ | | out[0] || HEX0[0] || AE26 | ||
+ | |- align="center" | ||
+ | | out[1] || HEX0[1] || AE27 | ||
+ | |- align="center" | ||
+ | | out[2] || HEX0[2] || AE28 | ||
+ | |- align="center" | ||
+ | | out[3] || HEX0[3] || AG27 | ||
+ | |- align="center" | ||
+ | | out[4] || HEX0[4] || AF28 | ||
+ | |- align="center" | ||
+ | | out[5] || HEX0[5] || AG28 | ||
+ | |- align="center" | ||
+ | | out[6] || HEX0[6] || AH28 | ||
+ | |} | ||
+ | |||
+ | [[Fișier:Add and display fpga conn.PNG | 700px]] | ||
+ | |||
+ | ==Anexa1== | ||
+ | |||
+ | [[Fișier:Anexa1.PNG | 800px]] | ||
<syntaxhighlight lang="Verilog"> | <syntaxhighlight lang="Verilog"> | ||
</syntaxhighlight> | </syntaxhighlight> |
Versiunea curentă din 22 martie 2021 16:14
Memoria ROM–Introducere
Memoria ROM(Read-Only Memory) este un circuit combinational folosit pentru stocarea unor date ce pot fi accesate cu ajutorul unei intrari de adrese. Asa cum se intelege si din nume, memoria ROM, in general, nu poate fi modificata.
Pentru a intelege termenul de memorie, putem face urmatorul exercitiu de imaginatie: sa ne gandim la un dulap cu mai multe sertare. Continutul memoriei este reprezentat de continutul sertarelor, iar adresele sunt reprezentate de etichetele lipite pe aceste sertare, pentru a le identifica. Daca avem nevoie de continutul unui sertar, va trebui sa stim eticheta aferenta acestuia.
Am intalnit memoria ROM in aplicatiile anterioare, atunci cand am vorbit despre structura unui FPGA. Am vazut atunci ca functiile logice erau implementate pe FPGA prin intermediul unor LUT-uri (memorii ROM), care stocau iesirile corespunzatoare unor combinatii de intrari. Asadar, in cazul acela, adresele erau reprezentate de combinatii ale intrarilor, iar continutul memoriei era reprezentat de iesirile aferente acestor combinatii.
O memorie ROM are urmatorii parametri: numarul de biti ai adresei, care este legat de numarul de locatii de memorie (cu n biti de adresa putem forma 2𝑛 combinatii diferite, deci putem accesa maxim 2𝑛 locatii de memorie) si dimensiunea locatiei de memorie, care ne spune cat de multa informatie poate stoca o locatie de memorie.
Sa urmarim exemplul din figura urmatoare:
Aici, adresa are dimensiunea de 4 biti, asadar putem accesa cu aceasta 16 locatii diferite de memorie. Dimensiunea fiecarei locatii este de 8 biti, asadar fiecare locatie de memorie poate stoca numere de 8 biti. Spunem ca memoria ROM este o memorie 4x8. Capacitatea acestei memorii este de 16 x 8 biti = 128 biti.
Exemplul 1
Scop: Descrierea comportamentala a unui decodor, testarea acestuia prin simulare si sinteza pe FPGA.
Decodorul este circuitul care, pentru o anumita valoare a intrarii, va genera la iesire un sir binar care contine 1 pe pozitia cu indicele egal cu valorea intrarii si 0 in rest. De exemplu, decodorul de mai jos pe 2 biti, va avea urmatoarea corespondenta intrare-iesire:
in | out |
2'b00 | 4'b0001 |
2'b01 | 4'b0010 |
2'b10 | 4'b0100 |
2'b11 | 4'b1000 |
Vom implementa acest circuit ca memorie ROM.
Implementarea Verilog a circuitului
module Decoder(
input [1:0] in,
output reg [3:0] out
);
always@(in) begin
case(in)
2'b00: out = 4'b0001;
2'b01: out = 4'b0010;
2'b10: out = 4'b0100;
2'b11: out = 4'b1000;
default: out = 4'b0000;
endcase
end
endmodule
Implementarea Verilog a modulului de test
`timescale 1ns/1ps
module Decoder_TB();
reg [1:0] in_t;
wire [3:0] out_t;
integer idx;
initial begin
for(idx=0; idx<4; idx = idx + 1) begin
in_t = idx;
#1;
end
#2 $stop();
end
Decoder DUT(
.in(in_t),
.out(out_t)
);
endmodule
Observatii:
- Circuitul Decoder va avea o intrare pe 2 biti, care va reprezenta adresa memoriei ROM si o iesire pe 4 biti, reprezentand continuturile memoriei ROM corespunzatoare fiecarei combinatii de la intrare.
- Chiar daca in interiorul instructiunii case se acopera toate cazurile posibile (toate combinatiile de 2 biti), este bine sa punem si un default pentru a evita inserarea in locul circuitului combinational dorit (aici, memoria ROM) a unui latch.
Implementarea pe FPGA:
- Implementarea pe FPGA are ca tinta doar modulul in sine (Decoder), modulul de test (Decoder_TB) fiind nesintetizabil.
- Semnalele de intrare vor fi legate la dispozitive care comanda stari, iar iesirile la dispozitive care observa stari. Asadar, vom alege aici comutatoare pentru intrari (cate un comutator pentru fiecare bi tal fiecarei intrari –2 in total) si 4 LED-uri pentru iesiri.
Semnal | Dispozitiv | PIN |
in[0] | SW0 | AB12 |
in[1] | SW1 | AC12 |
out[0] | LEDR0 | V16 |
out[1] | LEDR1 | W16 |
out[2] | LEDR2 | V17 |
out[3] | LEDR3 | V18 |
Exemplul 2
Scop: Implementarea unui circuit de afisare a sumei dintre doua numere pe 2 biti, folosind afisajul cu 7 segmente
Implementarea Verilog amodululuiAdder2b
module Adder2b(
input [1:0] in0,
input [1:0] in1,
output reg [2:0] sum
);
always@(*) begin
sum = in0 + in1;
end
endmodule
Observatii:
- Suma a doua numere pe n biti este un numar pe n+1 biti, cel de-al n+1 -ulea fiind bitul de carry. De aceea, aici suma a doua numere pe 2 biti va fi un numar pe 3 biti.
- Aici consideram un sumator simplu, pentru care carry este inglobat in suma (nu este explicit un port separat).
Implementarea Verilog a modululuiAfisaj7Seg
Inainte de a prezenta codul Verilog, trebuie sa intelegem cum functioneaza afisajul cu 7 segmente. Acest dispozitiv de afisare este format, asa cum sugereaza si numele, din 7 segmente ce pot fi controlate separat. Putem aprinde sau stinge fiecare segment controland tensiunea aplicata pe acesta. Pentru acest afisaj, comanda este negativa: aplicand 0 logic pe un segment acesta se va aprinde, iar aplicand 1 logic, acesta se va stinge. Structura unui afisaj cu 7 segmente este prezentata in imaginea de mai jos:
Pentru a reprezenta, de exemplu, cele 16 numere hexa, segmentele trebuie aprinse conform Anexei 1.
In cazul circuitului nostru, vom vrea sa afisam numerele de la 0 la 6, deoarece suma maxima ce poate fi obtinuta este 6. Pentru aceasta, implementam o memorie ROM care va contine codurile de aprins-stins pentru fiecare segment, fiind accesate pe baza numarului pe care dorim sa il afisam. Asadar, intrarea memoriei ROM (adresa) va fi pe 3 biti (3 biti sunt de ajuns pentru a reprezenta numerele de la 0 la 6), iar iesirea va fi pe 7 biti, cate un bit de stare pentru fiecare segment. Vom considera, asadar, ca bitul 0 al iesirii se va lega la segmentul 0, bitul 1 la segmentul 1 si tot asa.
De exemplu, daca la intrare vom avea 0, memoria ROM va trebui sa dea la iesire sirul 1000000, stingand segmentul 6 si aprinzandu-le pe toate celelalte. Extinzand pentru toate numerele de la 0 la 7, obtinem:
Numar | Sir de afisare |
0 | 7'b100_0000 |
1 | 7'b111_1001 |
2 | 7'b010_0100 |
3 | 7'b011_0000 |
4 | 7'b001_1001 |
5 | 7'b001_0010 |
6 | 7'b000_0010 |
Implementarea Verilog a modululuiDisplay7Seg
module Display7Seg(
input [2:0] in,
output reg [6:0] out
);
always@(in) begin
case(in)
3'd0: out = 7'b1000000;
3'd1: out = 7'b1111001;
3'd2: out = 7'b0100100;
3'd3: out = 7'b0110000;
3'd4: out = 7'b0011001;
3'd5: out = 7'b0010010;
3'd6: out = 7'b0000010;
default: out = 7'b0000110;
endcase
end
endmodule
Implementarea Verilog a circuitului AddAndDisplay
module AddAndDisplay(
input [1:0] in0,
input [1:0] in1,
output [6:0] displayCode
);
wire [2:0] sum;
Adder2b ADD (
.in0(in0),
.in1(in1),
.sum(sum)
);
Display7Seg DISPLAY(
.in(sum),
.out(displayCode)
);
endmodule
Implementarea Verilog a modulului de test
module AddAndDisplay_TB();
reg [1:0] in0_t, in1_t;
wire [6:0] displayCode_t;
integer idx, jdx;
initial begin
for(idx=0; idx<4; idx = idx + 1) begin
for(jdx=0; jdx<4; jdx = jdx + 1) begin
in0_t = idx;
in1_t = jdx;
#1;
end
end
#2 $stop();
end
AddAndDisplay DUT(
.in0(in0_t),
.in1(in1_t),
.displayCode(displayCode_t)
);
endmodule
Implementarea pe FPGA:
Implementarea pe FPGA are ca tinta doar modulul in sine (AddAndDisplay), modulul de test (AddAndDisplay_TB) fiind nesintetizabil.
Conform indicatiilor din Introducere, semnalele de intrare vor fi legate la dispozitive care comanda stari, iar iesirile la dispozitive care observa stari. Asadar, vom alege aici comutatoare pentru intrari (cate un comutator pentru fiecare bit al fiecarei intrari –4 in total) si afisajul cu 7 segmente Digit 0 pentru iesire.
Semnal | Dispozitiv | PIN |
in[0] | SW0 | AB12 |
in[1] | SW1 | AC12 |
in[2] | SW2 | AF9 |
in[3] | SW3 | AF10 |
out[0] | HEX0[0] | AE26 |
out[1] | HEX0[1] | AE27 |
out[2] | HEX0[2] | AE28 |
out[3] | HEX0[3] | AG27 |
out[4] | HEX0[4] | AF28 |
out[5] | HEX0[5] | AG28 |
out[6] | HEX0[6] | AH28 |