Tutorial HDL @ Artix-7

Przykładowy projekt

Niniejszy tutorial pokazuje na wybranym przykładzie etapy postępowania, konieczne do wykonania projektu układu cyfrowego, opisanego za pomocą języka opisu sprzętu. Projekt zostanie praktycznie uruchomiony na platformie sprzętowej, wyposażonej w programowalny układ cyfrowy FPGA i konieczne zasoby wejścia / wyjścia. Tutorial prowadzi począwszy od edycji projektu, poprzez jego weryfikację, syntezę logiczną i implementację, a skończywszy na zaprogramowaniu układu FPGA.

Jako temat wyjściowy posłuży projekt dekodera kodu wyświetlacza siedmiosegmentowego. Konstrukcja pojedynczego znaku wyświetlacza oparta jest na siedmiu (a właściwie ośmiu, uwzględnaijąc kropkę dziesiętną  DP - Decimal Point) diodach elektroluminescencyjnych (LED), które emitują światło kiedy przepływa przez nie prąd:

Szeregowo włączony rezystor ogranicza prąd płynący przez diodę, aby zapewnić właściwe warunki jej pracy. Praktyczna realizacja powyższego obwodu może wyglądać np. tak:

Każdy segment wyświetlacza to odrębna dioda LED. Ułożone są one względem siebie tak, aby można było za ich pomocą wyświetlić przybliżone kształty znaków pisma (tu: cyfr arabskich). W praktyce zwykle elektrody jednego rodzaju (np. anody) są ze sobą połączone już w obudowie wyświetlacza, tworząc wtedy tzw. wyświetlacz ze wspólną anodą:

Wyświetlenie znaku polega tu więc na podaniu wysokiego poziomu napięcia na wspólną anodę, oraz niskiego poziomu napięcia na katody odpowiadające pożądanym do zaświecenia segmentom:

Z powodu zastosowania w obwodach anod kluczów tranzystorowych, które odwracają polaryzację, włączanie całego znaku odbywa się tutaj także niskim poziomem napięcia:

Aby świecąca kombinacja kilku segmentów ułożyła się w rozpoznawalny znak (tutaj: w cyfrę arabską), należy zakodowaną binarnie cyfrę dziesiętną (BCD - Binary Coded Decimal) przekodować na kod wyświetlacza:

Funkcję tę będzie pełnił zaprojektowany przez nas dekoder, który interpretuje informację na 4-bitowym wejściu (Digit) i zamienia ją na kombinację siedmiu bitów sterujących poszczególnymi segmentami (diodami LED) wyświetlacza (SegLED). Reguły transkodowania powinny być zgodne z poniższą tabelą, w której użyto tzw. "logiki prostej" (1 - segment świeci, 0 - segment nie świeci):

Ponieważ na docelowej dla niniejszego tutorialu platformie uruchomieniowej (płytka Digilent Nexys 4) zastosowano wyświetlacze ze wspólną anodą, skutkuje to odwróceniem poziomów napięciowych dla sterowania poszczególnych segmentów (tzw. "logika odwrotna"), a co za tym idzie - koniecznością zanegowania wartości logicznych na wyjściach dekodera (0 - segment świeci, 1 - segment nie świeci). Zostanie to zrealizowane w kodzie HDL za pomocą jednej operacji.

Ponadto na płytce umieszczono aż osiem wyświetlaczy siedmiosegmentowych, połączonych w jeden moduł sterowany multipleksowo. Jego szczególne właściwości będą jednak wykorzystywane dopiero w ostatnich zadaniach niniejszego tutorialu.

Rozpakowanie i otwarcie projektu

Używane tu oprogramowanie ActiveHDL jest rozbudowanym narzędziem, służącym do projektowania i weryfikacji układów cyfrowych. W ramach niniejszego tutoriala wykorzystywany będzie tylko edytor tekstowy HDL oraz symulator. Środowisko ActiveHDL posłuży także do wywoływania oprogramowania (do syntezy, implementacji, konfiguracji itp.) związanego z dalszą obróbką projektu dla wybranego typu układu programowalnego.

Aby poprawnie otworzyć wyjściową postać projektu należy wykonać kolejno następujące czynności:

Projektowanie układów cyfrowych za pomocą języków opisu sprzętu

Projekt systemu cyfrowego można wprowadzać przy pomocy edytora graficznego, umieszczając na schemacie elementy i łącząc je, dokonawszy wcześniej syntezy funkcji logicznych. O ile takie podejście jest akceptowalne dla bardzo prostych projektów, to jednak stopień złożoności projektów współczesnych (kilkaset tysięcy...kilka milionów odpowiedników bramek logicznych) nie pozwala już na stosowanie tak niewydajnych narzędzi. Z pomocą przychodzą tu projektantowi narzędzia do automatycznej syntezy (czyli generowania struktury) układów cyfrowych. Edycja projektu (tj. opis jego działania) odbywa się tu na wyższym poziomie abstrakcji za pomocą języków opracowanych specjalnie do opisu działania układów cyfrowych (np.: VHDL, Verilog, języki HLS itp.)

W otworzonym pliku projektu dekodera wyświetlacza w języku VHDL odnaleźć można dwie podstawowe jednostki projektowe: entity i architecture. Pierwsza z nich opisuje tylko interfejs projektowanego modułu, a więc wszystkie wejścia i wyjścia, ich szerokość, typ i ew. inne parametry. Druga z jednostek projektowych opisuje natomiast tylko sposób działania projektowanego modułu, odnosząc się do pierwszej.

W jednostce entity przykładowego projektu zadeklarowane są więc następujące sygnały:

W jednostce architecture przykładowego projektu, po deklaracji pomocniczej, wewnętrznej, 7-bitowej magistrali Segment, opisano zachowanie się poszczególnych sygnałów wyjściowych:

Należy tu zauważyć, że zasadnicza, najbardziej czasochłonna do zaprojektowania część architektury, czyli zbiór siedmiu funkcji logicznych, sterujących poszczególnymi segmentami w zależności od wartości cyfry podanej na wejście, w ogóle nie został przez projektanta zsyntezowany (jego struktura jest nieznana na etapie specyfikacji projektu) - tę część pracy wykona bowiem automatyczne narzędzie do syntezy, odciążając tym projektanta od żmudnej syntezy układu "na piechotę". Projektant ograniczył się tu jedynie do wyspecyfikowania zamierzonego efektu działania (podania de facto tablicy prawdy dla funkcji logicznych, nie wnikając w szczegóły ich implementacji).

Kompilacja i symulacja projektu

Przy aktywnym oknie pliku projektu seg7.vhd (kursor w jego obrębie) dokonujemy jego kompilacji poprzez naciśnięcie na klawiaturze przycisku funkcyjnego F11. Kompilacja nie powoduje jeszcze wygenerowania struktury układu, realizującej opisane działanie, ale jedynie buduje w pamięci komputera model symulacyjny, pozwalający zweryfikować poprawność kodu wprowadzonego przez projektanta. Po poprawnej kompilacji w oknie konsoli programu (zwykle w dolnej części ekranu) powinien się pojawić raport:

# Compile success 0 Errors 0 Warnings  Analysis time :  31.0 [ms]

Teraz można już przejść do weryfikacji projektu. W tym celu należy:

Każdorazowe naciśnięcie przycisku F5 powoduje wykonanie symulacji dla kolejnego 100ns (umownie) odcinka czasu. Ponieważ czas ten jest równy okresowi wymuszanych zmian na wejściu dekodera, tak więc po każdym naciśnięciu F5 otrzymuje się kolejną liczbę dla dekodera i kolejną kombinację włączonych i wyłączonych segmentów wyświetlacza LED, wygenerowanych na tej podstawie przez dekoder. Należy zweryfikować poprawność pracy dekodera dla wszystkich 16 kombinacji.

Ostateczny wynik symulacji powinien wyglądać jak poniżej. Na koniec należy zatrzymać tryb symulacji, wybierając z menu Simulation opcję End Simulation.

Synteza i implementacja projektu

 Dalsza obróbka projektu będzie wykonywana przez zewnętrzne oprogramowanie (do syntezy, implementacji, programowania itp.), dostarczone przez producenta wybranego typu układu programowalnego (tu: Xilinx). Programy te są jednak zintegrowane ze środowiskiem ActiveHDL, a współpraca z nimi będzie się odbywać za pośrednictwem graficznej konsoli Design Flow (fiszka Design Flow w głównym oknie programu).

Pierwszym krokiem jest wykonanie syntezy opracowanego i zweryfikowanego projektu. Podczas tego procesu przygotowany w języku HDL opis działania układu jest za pomocą złożonych algorytmów zamieniany na model struktury układu, który będzie realizował zaprojektowaną funkcjonalność. Utworzony w wyniku syntezy model co prawda nadal istnieje tylko w zasobach komputera, na którym jest opracowywany, ale jest on już modelem strukturalnym, zawierającym elementy logiczne (bramki, przerzutniki i inne funktory) oraz opisującym połączenia między nimi.

Aby uruchomić syntezę należy na konsoli Design Flow nacisnąć przycisk synthesis. Otworzone zostanie okno logu, w którym pojawiały się będą bieżące raporty z przebiegu procesu syntezy logicznej. Po krótkim czasie synteza powinna zakończyć się sukcesem (poniżej). Okno logu należy wtedy zamknąć przyciskiem Close na dole.

UWAGA! Nie zamykać okna dopóki trwa proces syntezy - wtedy przycisk ma funkcję przerwania procesu (Abort).

Drugim krokiem obróbki projektu jest wykonanie implementacji zsyntezowanego już projektu. Podczas tego procesu otrzymany po syntezie model struktury układu zostaje dopasowany do zasobów konkretnego, wybranego do zaprogramowania układu FPGA. W procesie tym dokonywane jest rozmieszczenie zawartej w modelu logiki stosownie do zasobów docelowego układu oraz rozplanowywane są połączenia między tymi zasobami (dlatego w literaturze proces ten nazywany jest także Place & Route). Na tym etapie poszczególnym sygnałom projektu zostają też przyporządkowane - zgodnie z życzeniami projektanta - konkretne wyprowadzenia docelowego układu programowalnego. Należy tu podkreślić, że efektem działania procesu implementacji jest nadal istniejący tylko w zasobach komputera model struktury układu (tym razem z uwzględnieniem realiów fizycznych), ale oprócz tego uzyskiwany jest tu już plik z danymi, służącymi bezpośrednio do zaprogramowania wybranego układu FPGA.

Aby uruchomić implementację należy na konsoli Design Flow nacisnąć przycisk implementation. Otworzone zostanie okno logu, w którym pojawiały się będą bieżące raporty z przebiegu procesu implementacji. Po krótkim czasie implementacja powinna zakończyć się sukcesem (poniżej, ostrzeżenia są dopuszczalne). Okno logu należy wtedy zamknąć przyciskiem Close na dole.

UWAGA! Nie zamykać okna dopóki trwa proces implementacji - wtedy przycisk ma funkcję przerwania procesu (Abort).

Programowanie i testowanie układu

 Układ będzie uruchamiany na platformie uruchomieniowej Digilent Nexys 4 DDR (Nexys A7).

Podłączyć płytkę Nexys 4 do komputera przy pomocy kabla micro USB. W tym celu wykorzystać złącze micro USB ulokowane na płytce w pobliżu włącznika zasilania (lewy górny róg). Następnie włączyć zasilanie płytki.

Aby zaprogramować układ, należy z pulpitu Windows uruchomić program do konfiguracji układu programowalnego Vivado Lab 2019.1 (względnie całe narzędzie Vivado 2019.1). Po uruchomieniu środowiska Vivado:

Po załadowaniu danych konfiguracyjnych do układu programowalnego powinien zostać wyświetlony komunikat o powodzeniu...

... a wyświetlacz na płytce powinien zaświecić.

Teraz należy przetestować działanie dekodera, wymuszając przy pomocy czterech połączonych z wejściami dekodera przełączników (zaznaczonych na rysunku) kolejno wszystkie możliwe kombinacje i obserwując zachowanie się wyświetlacza LED.

Zadania samodzielne

UWAGA!

Każde z poniższych zadań wymaga - oprócz modyfikacji kodu - jego kompilacji (dla zapisania pliku i ew. wykrycia błędów składniowych), a następnie syntezy i implementacji, na końcu zaś - ponownego zaprogramowania układu FPGA.

UWAGA!

Aby uniknąć konieczności ustawiania konfiguratora Hardware Manager dla każdego poniższego zadania, nie należy go zamykać po pierwszym jego wykorzystaniu, a jedynie ew. zminimalizować. Każdorazowo po stworzeniu w procesie implementacji nowego pliku konfiguracyjnego seg7.bit, konfigurator powinien tę zmianę wykryć, w wyniku czego kolejne programowanie układu FPGA będzie wykonane już nową zawartością.

Zadanie 1 (dla spróbowania własnych sił)

Zaprojektowany dotychczas dekoder cyfr BCD posiada pewną ułomność. Dla cyfr 6 i 9 kombinacje sterujące wyświetlaczem nie powodują włączenia niektórych segmentów (odpowiednio segmentu A i segmentu D). Należy dokonać odpowiednich zmian w kodzie VHDL, skompilować go, przeprowadzić symulację, syntezę, implementację, zaprogramować układ i przetestować, czy zmiany zostały skutecznie wprowadzone. W tym celu można posłużyć się zamieszczoną na początku tutorialu tabelką kodów.

Zadanie 2 (dla zaspokojenia rosnącego apetytu)

Po wprowadzeniu powyższych zmian możliwe jest już odróżnienie cyfry 6 od litery b. Tak poprawiony układ należy teraz rozbudować do dekodera cyfr HEX (szesnastkowych). Ponownie należy dokonać odpowiednich zmian w kodzie VHDL, przeprowadzić symulację, syntezę, implementację, zaprogramować układ i przetestować, czy zmiany zostały skutecznie wprowadzone. Po prawidłowym wykonaniu tego zadania na jednej pozycji wyświetlacza - w zależności od kombinacji na wejściu - powinny się pokazywać cyfry szesnastkowe 0..9 i A..F (dla uniknięcia niejednoznaczności cyfry szesnastkowe b oraz d należy zaprojektować jako małe litery alfabetu, dla odróżnienia ich od cyfr dziesiętnych 8 i 0).

UWAGA! Linia kodu zawierająca klauzulę when others powinna pozostać jako ostatnia linia selektywnego przypisania współbieżnego, które opisuje cały dekoder. Dodatkowe linie kodu w tym zadaniu należy wprowadzać POWYŻEJ tej linii.

Zadanie 3 (dla zaawansowanych)

Po wprowadzeniu powyższych zmian można uruchomić drugą pozycję wyświetlacza. W tym celu potrzebna będzie kolejna 4-bitowa magistrala wejściowa, wprowadzająca cyfrę BCD oraz skalarny sygnał wejściowy, wybierający do wyświetlania w danym momencie jedną z dwu cyfr (czyli do tzw. multipleksowania). W tym celu należy dokonać następujących zmian w kodzie VHDL:

Następnie wprowadzone zmiany należy zweryfikować w sposób analogiczny jak w poprzednich punktach. z tym, że w odpowiednim momencie:

Przesymulować układ sprawdzając działanie selektora. Na koniec zatrzymać tryb symulacji, wybierając z menu Simulation opcję End Simulation.

Dla fizycznego wprowadzenia drugiej cyfry do układu wykorzystane zostaną kolejne cztery przełączniki, zaś do wyboru do wyświetlania w danym momencie jednej z dwu cyfr - przycisk BTNC (centralny). W tym celu należy zmodyfikować plik seg7.xdc, w którym znajduje się specyfikacja przypisania sygnałów występujących w projekcie do konkretnych wyprowadzeń układu FPGA, a co za tym idzie - do konkretnych zasobów sprzętowych płytki Nexys 4 (wyświetlacz, przełączniki, przyciski itp.) W tym celu w panelu Design Browser, na fiszce Files otworzyć plik seg7.xdc, a w nim:

Na koniec zapisać plik!

Następnie należy przeprowadzić syntezę i implementację oraz zaprogramować i przetestować układ. Po wstępnym sprawdzeniu prawidłowości działania przyciskać przez chwilę przycisk BTNC możliwie szybko raz po razie (ale z zachowaniem odpowiedniej delikatności !), obserwując narastające proporcjonalne do szybkości przełączeń złudzenie jednoczesnego widzenia obu znaków. Efekt ten jest spowodowany bezwładnością ludzkiego oka i jest podstawą działania wyświetlacza multipleksowanego.

Zadanie 4 (dla ekspertów)

Chcąc pozbyć się uciążliwej konieczności szybkiego przyciskania przycisku i niedoskonałości efektu multipleksowania (widzialne migotanie cyfr) należy zlecić to zadanie odpowiednio szybko działającemu automatowi. W tym celu wykorzystany zostanie dostępny na płytce Nexys 4 układ oscylatora o częstotliwości 100MHz.

Generowany przez niego sygnał zegarowy o okresie 10 ns jest jednak zdecydowanie zbyt szybki, aby układ wyświetlacza multipleksowanego mógł prawidłowo zadziałać (zobacz na innych wykładach: relacja między częstotliwością a wzmocnieniem tranzystora). Dlatego, aby spowolnić szybkość przełączeń przy wyświetlaniu obu znaków do pożądanego zakresu od ok. 0,25 do 4,0 ms, zostanie zbudowany licznik, zliczający okresy zegara i odpowiednio wolniej sterujący sygnałem Sel.

Aby osiągnąć zamierzony cel, należy dokonać następujących modyfikacji projektu:

Po tym zapisać oba pliki!

Dla tej zmiany w kodzie nie przewidziano weryfikacji, ponieważ konieczność symulacji tak wielu zdarzeń (zboczy zegara) znacznie wydłużyłaby czas opracowania i utrudniłaby obserwację rezultatów. Należy jedynie przeprowadzić kompilację pliku VHD dla sprawdzenia poprawności składniowej, a następnie wykonać syntezę i implementację projektu oraz zaprogramować i przetestować układ.

Zadanie 5 (dla maniaków)

Zaproponować i wprowadzić odpowiednie zmiany zarówno w kodzie projektu VHD, jak i w pliku XDC, tak aby w analogiczny do powyższego sposób uruchomić cztery cyfry wyświetlacza.

Projekt seg7.zip:     seg7v1_ahdl11v1_vivado2019v1.zip