» Historia «
Język VHDL jest jednym z nowszych języków opisu i projektowania układów cyfrowych. Już w lipcu 1983 roku zespół złożony z przedstawicieli firm Intermetrics, IBM oraz Texas Instruments rozpoczął pierwszy etap pracy nad nowym językiem opisu i projektowania układów VLSI. Po roku pracy zaimplementowano dany język, dzięki czemu w grudniu 1985 otrzymano pierwszą wersję narzędzia napisanego w języku Ada dla komputerów klasy VA 11/780 i IBM 370.
Projekt VHDL był częścią programu Departamentu Obrony USA o nazwie VHSIC, którego zadaniem było opracowanie metod projektowania oraz wykorzystanie najbardziej złożonych i bardzo szybkich układów scalonych. W roku 1987 VHDL stał się obowiązującym standardem w dziedzinie języków opisu i projektowania układów VLSI. Ulepszona wersja języka pojawiła się dopiero w 1993 roku i obecnie jest stosowana przez większość projektantów układów cyfrowych na świecie (niestety jednak, w Polsce język VHDL nie jest jeszcze zbyt popularny).
» Podstawy języka «
Język VHDL spełnia podobną funkcję w dziedzinie projektowania sprzętu, jak język C++ w dziedzinie programowania. Ma on następujące właściwości:
· wspiera hierarchiczność projektowanego sprzętu,
· umożliwia opis projektu i jego sprawdzenie w całym procesie jego powstania,
· umożliwia tworzenie nowych wersji projektowych realizowanych w nowych technologiach na postawie rozwiązań projektowych przechowywanych w bibliotece projektów - jest zatem niezależny od konkretnej technologii, metody projektowania, narzędzi wspomagających projektowanie,
· umożliwia reprezentację dynamiki układu cyfrowego oraz współbieżnych operacji w sprzęcie - można stworzyć równoważne modele funkcjonalne,
· ułatwia dokumentowanie projektu, a najlepsze rozwiązania można gromadzić w bibliotekach projektów,
· ułatwia wymianę informacji między projektantami oraz całymi zespołami projektowymi,
W języku VHDL można reprezentować układy cyfrowe na poziomach: od bramkowego do systemowego. Oznacza to, że najmniejszym elementem naszego projektu jest bramka logiczna. Nie mamy więc dostępu do poziomu analogowego (topografii bramki logicznej), chociaż w kolejnych wersjach języka VHDL prawdopodobnie się to zmieni.
» Zasady gramatyki «
Dla opisu składni używanej w języku VHDL używa się podstawowej notacji BNF o następujących cechach:
1. elementy syntaktyczne języka są przedstawione w postaci słów połączonych znakiem podkreślenia,
część_deklaracyjna_jednostki
2. każda "produkcja" gramatyki języka VHDL składa się z:
· części lewej reprezentującej wybrany element syntaktyczny języka,
· symbolu "::=",
· części prawej przedstawiającej sposób rozkładu elementu syntaktycznego na części składowe,
· znaku ";"
jednostka_podstawowa ::= identyfikator ;
3. znak "|" występujący między dwoma elementami gramatyki oznacza, że możemy wybrać albo jeden, albo drugi element syntaktyczny,
literał_wyliczeniowy ::= identyfikator | literał znakowy ;
4. nawias klamrowy "{...}" oznacza, że elementy syntaktyczne występujące wewnątrz nawiasu mogą tworzyć listę tych elementów,
lista_czułości ::= nazwa_sygnału { , nazwa_sygnału } ;
5. słowa wytłuszczone oznaczają słowa kluczowe języka VHDL,
definicja_typu_rzeczywistego ::= range zakres_prosty ;
6. nawias kwadratowy "[...]" oznacza, że elementy gramatyczne języka będące wewnątrz nawiasu mogą nie występować w produkcji,
instrukcja_założenia ::= [ etykieta: ] założenie ;
7. komentarze umieszczamy po dwóch myślnikach "--''.
-- funkcja zwracająca wartość A ;
» Budowa projektu «
Każda jednostka projektowa (ang. desing entity) w języku VHDL składa się z:
· sprzęgu jednostki projektowej,
· ciała architektonicznego jednostki projektowej.
Zależność między nimi jest ściśle określona. Do jednego sprzęgu może być przypisanych kilka ciał architektonicznych. A z kolei jedno ciało architektoniczne może być powiązane tylko i wyłącznie z jednym sprzęgiem. Dzięki takiemu rozwiązaniu jeden projekt, np.: dekodera, może działać w różny sposób w zależności od użytego ciała architektonicznego jednostki projektowej.
Najprostszy projekt układu cyfrowego musi zawierać jeden sprzęg i jedno ciało jednostki projektowej. Jednak w bardziej skomplikowanych projektach znaleźć można kilka jednostek projektowych tj. więcej niż jeden sprzęg i ponad dwa ciała architektoniczne. Projekty takie mogą także dodatkowo zawierać:
· pakiety,
· deklaracje konfiguracji.
Dzięki nim można znacznie przyśpieszyć proces projektowania wykorzystując w swoim projekcie poszczególne części innych projektów gromadzonych w bibliotekach.
» Sprzęg «
Sprzęg jednostki projektowej nazywany jest interfejsem (ang. interface) lub deklaracją jednostki projektowej. Składnia sprzęgu jest następująca:
deklaracja_jednostki_projektowej ::=entity identyfikator is[generic ( lista_parametrów); ][port ( lista_portow); ]część_deklaracyjna_jednostki[begininstrukcje_współbieżne ]end [entity] [nazwa_jednostki_projektowej] ;
Jak widać z syntaktycznej postaci interfejsu, udostępnia on porty wejściowe i wyjściowe oraz parametry formalne innym jednostkom.
Sprzęg jednostki projektowej składa się zatem z:
· identyfikatora jednostki projektowej - reprezentującego jednostkę w środowisku projektowym,
· nagłówka jednostki projektowej - zawierającego listę parametrów i listę portów,
· części deklaracyjnej jednostki projektowej - zawierającej typy i obiekty używane w danej jednostce projektowej,
· pasywnych instrukcji współbieżnych - działań opisujących zachowanie się (funkcjonowanie) jednostki projektowej, ale nie zmieniających wartości sygnałów.
Oprócz identyfikatora wszystkie pozostałe części interfejsu mogą wystąpić opcjonalnie. Zatem najprostszy sprzęg jednostki projektowej może wyglądać następująco:
entity Dekoder is end;
Lista portów
Porty to inaczej sygnały zewnętrzne, które połączone są z wyprowadzeniami naszego projektu. Innymi słowy, jeżeli naszą jednostkę projektową potraktujemy jako "czarną skrzynkę", to wszelkie jej wyprowadzenia nazywamy portami. Charakter takiego portu (tzn. kierunek przepływu danych) określamy przy deklaracji portu.
Przykład:
entity Dekoder isport (wejscie : in bit_vectorwyjscie : out bit_vector );end entity Dekoder;
Rys. Sprzęg jednostki projektowej 'Dekoder'
Deklaracja portów jest jednoznaczna z deklaracją sygnałów. Sygnały te różnią się jednak od zwykłych sygnałów "rodzajem" umieszczanym przed wskaźnikiem typu sygnału.
rodzaj ::= in | out | inout | buffer | linkage ;
Wyróżniamy pięć typów portów:
1. wejściowe - charakteryzujące się:
· słowem kluczowym "in";
· jednokierunkowym przepływem informacji do jednostki projektowej;
· gą być tylko i wyłącznie odczytywane;
· nie można odczytywać ich atrybutów takich jak: stable, quiet, delayed, transaction;
wejscie1 : in bit_vector (0 to 3) ;
2. wyjściowe - charakteryzujące się:
· słowem kluczowym "out";
· jednokierunkowym przepływem informacji z jednostki projektowej;
· wartości ich są wyliczane wewnątrz danej jednostki;
· mogą być tylko uaktualniane;
· nie można odczytywać ich atrybutów takich jak: stable, quiet, delayed, transaction, event, active, last_event, last_active, last_value;
wyjscie1 : out bit ;
3. wejściowo-wyjściowe z wieloma źródłami - charakteryzujące się:
· słowem kluczowym "inout";
· dwukierunkowym przepływem informacji z i do jednostki projektowej (możliwy jest np. odczyt sygnału a potem jego aktualizacja);
· mogą być uaktualniane przez więcej niż jedno źródło;
sgnA : inout bit_vector ;
4. wejściowo-wyjściowe z jednym źródłami - charakteryzujące się:
· słowem kluczowym "buffer";
· dwukierunkowym przepływem informacji z i do jednostki projektowej;
· mogą być uaktualniane tylko przez jedno źródło;
· można odczytywać ich wszystkie atrybuty;
sgnB : buffer bit_vector (5 downto 1) ;
5. wejściowo-wyjściowe o nie określonym kierunku przepływu informacji - charakteryzujące się:
· słowem kluczowym "linkage";
· stosuje się je do komunikacji z jednostkami projektowymi definiowanymi w innym środowisku niż język VHDL;
Lista parametrów
Parametry to rodzaj zmiennych globalnych, które zasadniczo wpływają na działanie jednostki projektowej. Różnią się od innych zmiennych tym, że deklaruje się je po słowie kluczowym "generic", a także tym że parametry mogą być mapowane (tzn. przyporządkowane) przez inne jednostki projektowe przy pomocy konfiguracji. Innymi słowy, są pewnego rodzaju zmiennymi wejściowymi.
Parametry w jednostkach projektowych stosujemy głównie po to, aby tworzone przez nas jednostki projektowe były bardziej wszechstronne, a także aby przyśpieszyć proces projektowania. Chodzi o to, aby jeden projekt z parametrem zastąpił co najmniej dwa inne projekty bez parametru, ale o bardzo zbliżonym działaniu. Przykładem mogą być wszelkiego rodzaju dekodery, których sposób dekodowania jest taki sam (np. z kodu BCD na postać umożliwiającą sygnalizację na diodach LED), jednak są one w stanie zdekodować tylko i wyłącznie sygnał wejściowy o określonej długości słowa. Zastosowanie parametru umożliwia stworzenie jednego, uniwersalnego dekodera, który nie jest uzależniony od długości sygnału wejściowego. Projekt taki z odpowiednio zmapowanymi parametrami staje się konkretnym dekoderem, który może być samodzielnym projektem lub też stanowić element jakiegoś projektu.
» Ciało architektoniczne «
Ciało architektoniczne jednostki projektowej zawiera własności funkcjonalne (behawioralne) i strukturalne układu cyfrowego. Składnia ciała architektonicznego jednostki projektowej wygląda następująco:
ciało_architektoniczne ::= architecture identyfikator of nazwa_jednostki_projektowej isczęść deklaracyjna_ciałabegininstrukcje współbieżneend [ architecture ] [ nazwa_ciała ] ;
Ciało architektoniczne jednostki projektowej składa się zatem z:
· identyfikatora - reprezentującego ciało jednostki w środowisku projektowym,
· nazwy jednostki projektowej - wiążącej dane ciało z określonym interfejsem (sprzęgiem jednostki projektowej),
· części deklaracyjnej ciała jednostki projektowej - zawierającej m.in typy, obiekty, podprogramy używane w danym ciele jednostki projektowej,
· instrukcji współbieżnych - działań opisujących funkcjonalne i/lub strukturalne własności ciała jednostki projektowej.
Oprócz identyfikatora i nazwy jednostki projektowej wszystkie pozostałe części interfejsu mogą wystąpić opcjonalnie.
Ciało architektoniczne może wyglądać różnie. W zależności od jego struktury ciała architektoniczne dzielimy na:
· ciało strukturalne - zawierające strukturę danej jednostki projektowej (czyli skonkretyzowane i połączone ze sobą składniki)
· ciało behawioralne (funkcjonalne) - zawierający opis działania danej jednostki projektowej,
· ciało mieszane - zawierające zarówno strukturę jak i opis działania danej jednostki projektowej.
Różnice między tymi typami ciał można zademonstrować na prostym przykładzie sumatora:
Rys.2. Graficzny opis przykładowego sumatora
Dany sumator można przedstawić w języku VHDL w postaci ciała:
a. strukturalnego
architecture Budowa_Sumatora1 of Sumator is signal S1, S2 : bit; begin Bramka_Not1 : entity Work.Gate_Not port map (wej1, S1); Bramka_Not2 : entity Work.Gate_Not port map (wej2, S2); Bramka_And1 : entity Work.Gate_And port map (S1, S2, wyj); end Budowa_Sumatora1;
Ciało architektoniczne zawiera skonkretyzowane składniki, które wcześniej zostały zadeklarowane i umieszczone w bibliotece "Work". Zastosowanie tego typu ciała pozwala na wykorzystanie wcześniej stworzonych projektów i tym samym przyśpieszenie procesu projektowania. Jego wadą natomiast jest to, że aby dowiedzieć się czegokolwiek o działaniu poszczególnych składników należy odwołać się do konkretnej jednostki projektowej.
b. funkcjonalnego
architecture Budowa_Sumatora2 of Sumator issignal S1, S2 : bit;beginprocess (wej1, wej2)S1 <= not wej1 after 2 ns;S2 <= not wej2 after 2 ns;wyj <= S1 and S2 after 2 ns;end process;end Budowa_Sumatora2;
Ciało architektoniczne zawiera dokładny opis działania (zachowania się) układu, dzięki czemu możemy go wnikliwie analizować. Nie jest on jednak bardzo czytelny przy projektowaniu skomplikowanych i rozbudowanych układów.
c. mieszanego
architecture Budowa_Sumatora3 of Sumator issignal S1, S2 : bit;beginprocess (wej1, wej2)S1 <= not wej1 after 2 ns;S2 <= not wej2 after 2 ns;end process;Bramka_And1 : entity Work.Gate_And port map (S1, S2, wyj);end Budowa_Sumatora3;
Ciało mieszane zawiera częściowy opis działania układu, a także konkretyzację składnika "Bramka_And1". W bardziej skomplikowanych układach jest to dużą zaletą, gdyż jest to w pewnym sensie kompromis między czytelnością funkcjonowania układu i szybkością projektowania. Niezbędne okazują się tu także komentarze, które poprawiają w znacznym stopniu przejrzystość programu.
» Pakiety «
W języku VHDL część deklaracji wspólnych dla różnych projektów może być przechowywana w pakietach, które są umieszczane tak, jak i całe projekty, w bibliotekach. Dzięki nim możliwe jest znaczne przyśpieszenie procesu projektowania. Zawartość raz określonego pakietu i umieszczonego w konkretnej bibliotece można wykorzystać w dowolnej części własnego projektu. Warunkiem użycia danego pakietu jest odpowiednia deklaracja w postaci zakresu dostępu do pakietu i biblioteki.
Każdy pakiet składa się z dwóch części:
· części deklaracyjnej - zawierająca tylko nagłówki deklaracji (mogą tu się znaleźć m.in. deklaracje podprogramów, typy, podtypy, obiekty i aliasy, składniki i atrybuty);
deklaracja_pakietu ::=package identyfikator isczęść_deklaracyjna_pakietuend [ package ] [ nazwa_pakietu ] ;
·...
Automation_Engineering