Zaprojektujemy układ, który będzie wyświetlał liczbę na wyświetlaczu 7-segmentowym, a naciskając przyciski będziemy mogli tę liczbę zwiększać, zmniejszać lub wyzerować. Dowiemy się jak wyeliminować drgania przycisków, jak wykryć zbocze sygnału, jak zrobić licznik liczący w górę lub w dół i jak sterować wyświetlaczem. Nauczymy się także tworzyć bardziej elastyczny kod stosując parametry.
Utworzony teraz kod będzie potrzebny w kolejnej części kursu dotyczącej analizatora. Gotowy projekt jest dostępny w materiałach dodatkowych do artykułu: http://bit.ly/3Fp9bES.
Schemat
Analizę zacznijmy od zapoznania się ze schematem, wygenerowanym automatycznie przez Netlist Analyzer. Sygnały ButtonUp i ButtonDown mają rezystor pull-down wbudowany w strukturę FPGA, choć nie zostało to pokazane na schemacie. Należy je podłączyć do przycisków, zwierających do zasilania o napięciu 3,3 V. Sygnał Reset ma rezystor pull-up podciągający do zasilania. Sygnał ten należy połączyć z przyciskiem zwierającym do masy. Stan wysoki sygnału Reset to prawidłowa praca układu, a stan niski powoduje zerowanie wszystkich komponentów.
Prześledźmy działanie wszystkich modułów. Sygnały ButtonUp i ButtonDown wchodzą do instancji DebounceUp i DebounceDown. Są to dwie identyczne instancje modułu typu Debouncer. Ich zadaniem jest eliminacja efektu drgań styków, które znajdują się w przyciskach. Po wciśnięciu lub zwolnieniu przycisku występuje zjawisko tzw. drżenia styków, co powoduje, że przez pewien krótki czas następują wielokrotne, chaotyczne zmiany pomiędzy stanem niskim i wysokim. Byłoby to odczytane przez układ jako wielokrotne wciśnięcie przycisku i skutkowałoby nieprawidłowym działaniem licznika. Obecność modułów Debouncer eliminuje ten problem i zapewnia odpowiednio filtrowany sygnał.
Kolejnym krokiem są instancje UpDetector i DownDetector modułu typu EdgeDetector. Zadaniem tych modułów jest wykrycie momentu, kiedy przyciski Up i Down zostaną naciśnięte, czyli kiedy stan wejścia Signal zmieni się z 0 na 1. Wtedy, na wyjściach RisingEdge generowany jest stan wysoki, trwający pojedynczy takt sygnału zegarowego. Moduły te mają także możliwość wykrywania zbocza opadającego, tzn. zmiany wejścia Signal z 1 na 0. Spowoduje to wygenerowanie stanu wysokiego na jeden cykl zegarowy na wyjściu FallingEdge. Funkcja ta nie jest używana, a wyjście to pozostało niepodłączone do niczego. Zrobiłem to celowo, aby pokazać, jak wykryć zbocze opadające i jednocześnie zademonstrować, jak syntezator usuwa nieużywany kod. Przekonamy się, że jeżeli ręcznie usuniemy nieużywane fragmenty odpowiedzialne za wykrywanie zbocza opadającego, to uzyskany bitstream będzie używał dokładnie tyle samo zasobów, co przed usunięciem.
Kolejnym modułem jest licznik Counter0. Liczy on w górę lub w dół pod warunkiem, że na wejściu CountUp lub CountDown jest stan wysoki. Jeżeli na obu wejściach jest stan niski, wtedy licznik nie zmienia swojej wartości, obojętnie co dzieje się na wejściu zegarowym. Licznik jest 4-bitowy.
Ostatnim modułem jest instancja Dekoder0 modułu Decoder7seg. Przetwarza on liczbę binarną, dostępną na 4-bitowym wyjściu z licznika, na sygnały sterujące diodami LED w wyświetlaczu 7-segmentowym.