Ta strona używa ciasteczek (plików cookies), dzięki którym może działać lepiej. Dowiedz się więcejRozumiem i akceptuję

Kurs FPGA – #8 – automat skończony w VHDL

Programowanie 30.12.2017 Adam, Damian

Dzięki automatom skończonym możliwe jest łatwe zrealizowanie nawet pozornie trudnych i zawiłych urządzeń elektronicznych.

Tym razem sprawdzimy w praktyce jak przejść od grafu reprezentującego działanie układu do kodu w VHDL. Dzięki temu przejdziemy cały proces tworzenia automatu skończonego.

Nawigacja serii artykułów:
« poprzednia częśćnastępna część »

Kup zestaw elementów i zacznij naukę w praktyce! Przejdź do strony dystrybutora »

Czym jest automat skończony?

Automaty skończone stanowią punkt wyjścia dla modelowania układów cyfrowych oraz szeroko pojętych systemów informatycznych. Zasada działania mechanizmów tego typu przydaje się nie tylko podczas pisania programów w VHDL. Podobne algorytmy są spotykane również w programach, zarówno tych na komputery PC, jak i na mikrokontrolery, czyli np. Arduino.

Automat stanów oraz maszyna stanów
to nazewnictwo używane zamiennie.

Na początek wprowadzimy pojęcia odnoszące się do typów układów cyfrowych:

  • Układy Kombinacyjne – to układy, w których zmiany wejść dają bezpośrednią i prawie natychmiastową reakcje na wyjściach systemu. Przykładem układu kombinacyjnego jest układ złożony jedynie z bramek logicznych lub multiplekser.
  • Układy Sekwencyjne – to układy posiadające stany wewnętrzne (pamięć), więc wyjścia zależą od wejść oraz od stanów wewnętrznych. Przykładem może być układ licznika oraz rejestr przesuwny.

W przypadku układów sekwencyjnych wyróżnia się dwa rodzaje:

  • Układy synchroniczne – każdy element pamięciowy (przerzutnik) jest sterowany wspólnym sygnałem zegarowym. Dzięki temu wszystkie przerzutniki są przełączane równocześnie i cały układ przechodzi równocześnie z jednego stanu do drugiego.
  • Układy asynchroniczne – zależnie od konstrukcji, jedne przerzutniki mogą być sterowane poprzez wyjścia innych przerzutników. Układy te są najbardziej skomplikowane i mogą na początku sprawiać pewne problemy.

W tym artykule skupimy się na układach synchronicznych!

Aby zrozumieć automaty skończone musimy poznać pojęcie stanu. Stan jest to określona stabilna konfiguracja wewnętrzna systemu, która może być zmieniona pod wpływem zmiany wartości wejść systemu.

Ogólnie rzecz biorąc każdy system mikroprocesorowy bądź układ cyfrowy działa w oparciu o maszynę skończoną i składa się z następujących bloków:

  • Blok wejść – za jego pomocą system otrzymuje informacje z zewnątrz. Prostym przykładem będzie informacja o wciśnięciu przycisku.
  • Blok pamiętający stany wewnętrzne układu – systemy komputerowe przechowują te informacje w pamięci (np. typu Flash), w układach PLD rolę tę pełnią przerzutniki, które znajdują się w blokach logicznych.
  • Blok wyjść – mogą to być diody świecące, sygnał VIDEO o określonych parametrach lub zupełnie inne sygnały, które mają być efektem działania układu.

Typy automatów skończonych

Wyróżnia się dwa najpopularniejsze typy automatów skończonych. Pierwszym z nich jest automat Mealy’ego. W tym układzie stany wyjść w danym momencie zależą od wejść układu oraz od jego aktualnych stanów wewnętrznych.

Drugim popularnym układem jest automat Moore’a. W jego przypadku wyjścia układu w danej chwili zależą wyłącznie od wewnętrznych stanów układu:

Funkcje automatów skończonych można opisać:

  • tabelarycznie w postaci tabel prawdy,
  • w formie grafu, który odwzorowuje działanie układu w sposób graficzny. Forma ta pozwala na łatwiejsze przedstawienie i zrozumienie działania układu.

Na ten moment nie będziemy zagłębiać się w teorię. Osoby zainteresowane szczegółami odsyłamy np. do Wikipedii: automat Mealy’ego, automat Moore’a.

Automaty stanów w praktyce

Opis ten może być dla niektórych początkujących zawiły. Więc przed przejściem do przykładu związanego z VHDL wrócimy na chwilę do kursu Arduino (poziom II). W jednym z jego odcinków opisywana była centralka alarmowa. Której działanie opierało się na 4 stanach:

  1. Czuwanie – alarm czeka na uzbrojenie.
  2. Monitorowanie – system pilnuje naszego pomieszczenia.
  3. Rozbrajanie – alarm czeka na wprowadzenie poprawnego pinu.
  4. Sygnalizacja alarmu – alarm wydaje dźwięki i sygnały świetlne.

Oczywiście funkcje te mogą następować po sobie tylko w odpowiedniej kolejności. Nie zdarzy się sytuacja, że będziemy rozbrajać alarm, gdy jest w czasie czuwania itd. Najlepiej widoczne jest to na poniższym schemacie (nie jest to graf stanów, traktujmy to jako prostą, graficzną reprezentację powyższych opisów):

Taka centralka alarmowa, to świetny przykład na urządzenie, które może pracować jako automat skończony. Realizacja tego projektu w „C” została opisana w 5. części kursu Arduino. Wróćmy jednak do VHDLa i zróbmy coś w praktyce!

Jak tworzyć automaty skończone?

Krok 1. Należy zdefiniować liczbę wejść, wyjść i stanów wewnętrznych układu.

Krok 2. Należy narysować graf, który będzie prezentował działanie automatu. Najłatwiej zacząć od narysowania stanów układu, a później dodać strzałki oznaczające przejścia między stanami.

Maszyna stanów w FPGA – przykład praktyczny

Oczywiście najlepiej zrozumieć omawiane zagadnienie w praktyce. Przykładowy projekt będzie korzystał z 4 diod świecących (D8, D7, D6, D5) oraz dwóch przełączników typu DIP-switch, które oznaczone są na zestawie jako nr 7 oraz 8.

Za pomocą wspomnianych dwóch przełączników będziemy mogli sterować przejściami układu między czterema stanami naszej maszyny stanów (będą one oczywiście wejściami). Informacje o aktualnym stanie odczytamy z diod świecących.

Działanie aplikacji opisuje poniższy graf – diagram maszyny stanów:

Diagram maszyny stanów.

Wewnątrz „bąbelków” zostały umieszczone nazwy stanów (S0…S3) oraz wartości wyjść, gdy układ znajduje się w danym stanie (LED0…3). Przy strzałkach zaznaczono warunki tranzycji (przejść pomiędzy stanami). Zaznaczono również stan domyślny jako „init” – to właśnie w tym stanie układ znajdzie się automatycznie po włączeniu zasilania.

Jak czytać taki diagram?

Po włączeniu zasilania układ znajdzie się w stanie S0. Zaświeci się pierwsza z brzegu dioda. Układ przejdzie do stanu S1 tylko jeśli przełącznik DIP8 znajdzie się w stanie ON. Przy innych kombinacjach układ będzie ciągle pozostawał w S0.

Gdy powyższy warunek zostanie spełniony i znajdziemy się w stanie S1 to włączy się dioda, która będzie druga w kolejności. Układ pozostanie w tym stanie do momentu, w którym przełącznik DIP7 zostanie ustawiony w pozycję ON. Co ważne nie ma możliwości, aby układ cofnął się ze stanu S1 do S0! Pozostałe stany należy analizować analogicznie.

Zestaw do kursu FPGA

Gwarancja pomocy na forum dla osób, które kupią poniższy zestaw!

Zestaw uruchomieniowy Elbert v2 - Spartan 3A z wszystkimi niezbędnymi peryferiami do wykonania ćwiczeń z kursu FPGA!


Kup w Botland.com.pl »

Maszyna stanów w VHDL

Pora zrealizować układ w praktyce. W tym celu tworzymy nowy projekt. Standardowo zaczynamy od dodania bibliotek:

Następnie pora na blok enitity. Oprócz wspomnianych wcześniej przełączników DIP i LEDów będziemy korzystać z sygnału zegarowego Clk. Będzie on potrzebny w bloku process, wewnątrz którego będzie opisana funkcjonalność maszyny stanów.

W bloku architecture w obszarze deklarowania sygnałów lokalnych (czyli przed instrukcją begin) definiujemy nowy rodzaj sygnału. Typ ten może przyjąć wartości podane w nawiasie. Konstrukcja ta jest podobna do deklaracji zmiennej typu enum znanej z języka C. Mówiąc prościej, dzięki temu będziemy mogli tworzyć „zmienne”, które będą przyjmowały tylko zdefiniowane przez nas wcześniej wartości (tutaj będą to nazwy kolejnych stanów):

Niżej tworzymy sygnał wcześniej utworzonego typu. Sygnał ten nosi nazwę Stan. Będzie on przechowywał informacje na temat tego jaki stan panuje w naszym układzie. Przy okazji, od razu w tym miejscu została mu przypisana domyślna wartość S0 (nasz punkt startowy „Init”).

Wewnątrz konstrukcji architecture (poniżej jej słowa kluczowego begin) opisujemy działanie układu. Gotowy kod prezentuje się następująco (został dokładnie omówiony poniżej):

Jak widać (po komentarzach) blok process jest wykonywany przy każdej zmianie stanu sygnału zegarowego. Ponadto instrukcja warunkowa wyznacza, że wnętrze bloku process będzie wykonywane dla każdego narastającego zbocza sygnału zegarowego.

Dalej znajduje się blok case-when. Instrukcja ta sprawdza wartość sygnału znajdującego się za case i wykonuje blok instrukcji znajdujący się za odpowiednim when. Przykładowo, gdy wartość sygnału Stan wyniesie S3, to zostanie wykonany blok when S3.

Oczywiście jest to instrukcja analogiczna do instrukcji switch-case
znanej z innych języków programowania.

Zawartość bloku case opisuje właśnie zachowanie naszego układu (zgodnie z wcześniejszym diagramem). Przykładowo w sytuacji, gdy układ jest w stanie S0 i DIP8 będzie w pozycji ON (co jest opisane wyrażeniem:  (not DPSwitch(0)) = '1')), to w chwili spełnienia tego warunku układ przejdzie w stan S1. W przeciwnym wypadku urządzenie pozostanie w stanie S0. Pozostałe stany są analogicznym odwzorowaniem diagramu.

Warto w tym miejscu jeszcze wspomnieć o tym, że dobrą praktyką jest stosowanie dodatkowego przypadku w bloku case. Mowa o bloku when others, bardzo często programy do syntezy (np. Xilinx ISE) mogą zgłaszać ostrzeżenia lub nawet błędy, gdy tego bloku zabraknie. Ma to na celu uniknięcie stworzenia „zatrzasków” (ang. latches) w układzie.

Temat zjawiska powstawania zatrzasków wykracza poza ramy tego kursu. Zagadnienie to jest związane ze sztuką projektowania układów cyfrowych i ma za zadanie takie konstruowanie układów, by wykluczyć niepożądane stany nieustalone.

Na końcu naszego kodu znajdują się instrukcje, które przypisują wyjścia układy na diody:

Zgodnie z diagramem stanów zależnie od wartości sygnału Stan dana dioda jest włączana albo nie. Można tutaj zobaczyć nową konstrukcje WHEN-ELSE, która należy do zbioru instrukcji współbieżnych (wykonywanej w sposób natychmiastowy i ciągły). Jej działanie odpowiada pojedynczej instrukcji warunkowej. Gdy warunek umieszczony po WHEN jest spełniony to zostaje wykonane przypisanie wartości umieszczonej przed WHEN. W innych przypadkach następuje przypisanie wartości umieszczonej po ELSE.

Przykładowo, gdy sygnał Stan osiągnie wartość S0 to do LED(0) będzie przypisane logiczne 1. W innych przypadkach dioda będzie miała przypisaną wartość logiczną 0.


Poniżej, dla pewności, znajduje się cały program dla tego projektu:

Dodanie pliku UCF

Podobnie jak w poprzednich projektach można napisać własny plik lub skorzystać z gotowego:

Działanie układu w praktyce

Pora sprawdzić układ w praktyce. Przesuwamy przełącznik w pozycję OFF i uruchamiamy układ. Po jego włączeniu powinna świecić się jedna skrajna dioda. Czyli wszystko się zgadza z pierwszymi założeniami. Teraz można sprawdzić, czy cały układ działa poprawnie.

Pomocny będzie graf:

Diagram maszyny stanów.

Analizujemy kolejne elementy:

  1. Przełączamy DIP7 na ON i wracamy na OFF (można kilka razy) – nic się nie dzieje. Przełączamy DIP8 na ON i układ przechodzi z S0 do S1.
  2. Przełączamy DIP8 na OFF i wracamy na ON – nic się nie dzieje. Przełączamy DIP7 na ON i układ przechodzi z S1 do S2.
  3. Przełączamy DIP7 na OFF i wracamy na ON – nic się nie dzieje. Przełączamy DIP8 na OFF i układ przechodzi z S2 do S3.
  4. Przełączamy DIP8 na OFF i wracamy na ON – nic się nie dzieje. Przełączamy DIP7 na OFF i układ przechodzi z S3 do S0.
  5. Procedura rozpoczyna się od początku.

Wszystko zgadza się idealnie z grafem!

Układ działa, ale ma pewne niedoskonałości, które widać gdy się pobawimy przyciskami trochę „losowo”. Czasami nasz automat przeskakuje jeden stan lub się cofa! Czy to prawda? Zachęcam do zastanowienia się czym powodowane są dziwne zachowania i czy faktycznie jest to błąd, czy może wynika to z naszego prostego diagramu?

Podsumowanie

Celem artykułu było delikatne wprowadzenie automatów skończonych. Specjalnie nie poruszaliśmy tutaj praktycznie żadnej teorii, tylko szybko przeszliśmy do prostego przykładu, aby pokazać, że to nic strasznego. W praktyce rozwiązanie to przydaje się podczas pisania wielu programów (nie tylko na FPGA). Szczególnie, gdy działanie układu składa się z kilku wyraźnie odrębnych stanów, które muszą następować po sobie w odpowiedniej kolejności.

W kolejnej części kursu podstaw VHDL stworzymy układ, który również będzie miał tylko 4 stany, jednak pojawi się w nim znacznie więcej zawiłości. Konieczne będzie również poradzenie sobie z problemem drgań styków w przyciskach. W tym celu przygotujemy osobny moduł podrzędny.

Kup zestaw elementów i zacznij naukę w praktyce! Przejdź do strony dystrybutora »

Autor kursu: Adam Bemski
Redakcja: Damian Szymański
Ilustracje, testy: Piotr Adamczyk

O autorze: Adam Bemski

Autorem kursu jest Adam Bemski, specjalista od systemow wbudowanych. Pracuje w obszarze automatycznego testowania urządzeń z funkcjonalnością IoT. Adam dodatkowo prowadzi zajęcia z techniki mikroprocesorowej na wyższej uczelni DHBW Stuttgart. Więcej szczegółów o Adamie na blogu adambemski.com.

Powiadomienia o nowych, darmowych artykułach!

Komentarze

Elvis

13:17, 30.12.2017

#1

Przepraszam, że się czepiam ale od pierwszego zdania mam drobną uwagę - mówimy o skończonych stanach, czy skończonym automacie? Tytuł "automat stanów skończonych" sugeruje skończone stany, co jest nieco dziwne. O skończonych automatach słyszałem, o skończonych zbiorach stanów też, ale automat stanów skończonych wydaje mi się dziwnym pojęciem. Czym jest stan nieskończony?

Treker
Administrator

16:11, 30.12.2017

#2

Faktycznie może nazewnictwo nie jest zbyt dobrze tutaj dobrane. Nazwa taka pojawia się w niektórych publikacjach, ale nie jest najpopularniejsza. Wrócę z tym zaraz do pierwotnej wersji i będzie o "automatach skończonych" ;)

Zobacz powyższe komentarze na forum

FORBOT Damian Szymański © 2006 - 2018 Zakaz kopiowania treści oraz grafik bez zgody autora. vPRsLH.