Un afișaj cu 7 segmente este un tip de display electronic folosit pentru a afișa cifre zecimale. Un astfel de afișaj este format din 7 LED-uri legate într-unul din două moduri: anod comun (plus comun) sau catod comun (minus comun).
Un LED, nu este nimic mai mult decât o diodă, alcătuită din 2 borne, numite anod si catod. Pentru funcționarea sa este necesar ca tensiunea la anod să fie mai mare decât aceea la catod (practic tensiunea scade in sensul orientarii diodei). Atunci când tensiunea la catod este mai mare sau egală cu tensiunea la anod, LED-ul este stins. în caz contrar, LED-ul este aprins.
În cazul FPGA-ului nostru, utilizăm configurația cu anod comun, ceea ce înseamnă că setarea led-urilor se va face prin setarea tensiunilor la catod pentru a fi mai mici decât cea de la anod. Cum lucrăm în logică digitală, tensiunea la anod va fi de fapt VCC, +5V sau 1 logic, şi singura tensiune pe care o putem oferi mai mică decât 1 logic este cea de 0 logic, GND, 0V.
Așadar, avem un input implicit de 1 logic la anod, iar de input-ul de la catodul fiecărui LED depinde aprinderea sa. Exemplu:
module setLed ( output A, // fir conectat la catodul ledului A output AN // fir conectat la tranzistorul PNP ce controleaza anodul ledului A ); assign AN = 0; // Pentru a aprinde ledul A: assign A = 0; endmodule
module clearLed ( output A, // fir conectat la catodul ledului A output AN // fir conectat la tranzistorul PNP ce controleaza anodul ledului A ); assign AN = 0; // Pentru a stinge ledul A assign A = 1; endmodule
Fiindcă o cifră este formată din 7 LED-uri și pe Digilent Nexys A7 avem 8 cifre, în mod normal am avea nevoie de 112 de semnale (128 considerând și punctul fiecărei cifre) pentru a controla starea fiecărui LED (anod + catod). Totuși este folosită o schema de multiplexare prin care un anod este comun tuturor celor 7 LED-uri dintr-o cifră (și punctului), iar catozii LED-urilor de pe aceeasi poziție sunt partajați între toate cele 8 cifre.
Folosind această schemă de multiplexare, doar o cifră poate fi aprinsă la un moment dat (dacă se dă drumul la mai mult de un anod aceeași cifră va fi afișată pe toate pozițiile, deoarece catozii sunt partajați). Astfel, dacă dorim să afișăm mai multe cifre diferite între ele, nu putem face acest lucru decât afișând cate una la singură la fiecare moment de timp. Din fericire, lucrând cu un clock intern de frecvență cu mult mai mare decât capacitatea de percepție a ochiului uman, ne permitem să facem un astfel de afișaj rând-pe-rând, urmând ca ochii nostrii să perceapă un display continuu al celor 8 cifre.
Task-urile reprezintă o facilitate a limbajului Verilog care oferă posibilitatea de a scrie cod reutilizabil și mai ușor de înțeles. În acest sens sunt foarte similare cu funcțiile din C/C++. În Verilog există și funcții (denumite Functions) care funcționează similar, însă pentru ceea ce avem noi nevoie în rezolvarea laboratoarelor, task funcționează foarte bine. Task-urile sunt foarte utile pentru testarea funcționalitătilor codului nostru, deoarece permit folosirea de delay-uri.
Utilizăm task-uri atunci când avem de efectuat aceeași operație sau bloc de operații de mai multe ori. Pentru a evita duplicarea codului și volumul de editări de care am avea nevoie pentru a corecta potențialele erori, precum si pentru a face codul mai ușor de citit preferăm să apelăm de oricâte ori este nevoie un task descris o singură dată.
Regulile pentru folosirea de task-uri:
Un exemplu:
module traffic_lights; reg clock, red, amber, green; parameter on = 1, off = 0, red_tics = 350,amber_tics = 30, green_tics = 200; // initialize colors initial red = off; initial amber = off; initial green = off; // sequence to control the lights always begin red = on; // turn red light on light(red, red_tics); // and wait. green = on; // turn green light on light(green, green_tics); // and wait. amber = on; // turn amber light on light(amber, amber_tics); // and wait. end // task to wait for ’tics’ positive edge clocks // before turning ’color’ light off task light; output color; input [31:0] tics; begin repeat (tics) @(posedge clock); color = off; // turn light off end endtask endmodule // traffic_lights
Task 1 (2p). Implementați un modul care afișează cifra “0” folosind afișajul cu 7 segmente.
Task 2 (3p). Implementați un modul care afișează numărul “0123” folosind afișajul cu 7 segmente.
Task 3 (5p). Implementați un modul contor folosind afișajul cu 7 segmente. La reset modulul va afișa “0000”, iar, la fiecare apăsare a unui buton, aceast număr va fi incrementat (e.g. “0001” → “0002” → “0003” → etc.)
Task 4 (bonus - 2p). Realizați un timer utilizând 7 segment display. Folosiți primele 2 cifre pentru afișarea minutelor, iar ultimele 2 pentru afișarea secundelor. Va trebui să întârziați clock-ul intern al plăcuței pentru a obține frecvența aferenta 1s. După cum stiți, la 60s, display-ul aferent secundelor se va reseta la 00, iar display-ul aferent minutelor va crește cu o unitate. La apăsarea butonului reset, timer-ul vostru trebuie să revină la 00:00.