Opis języka VHDL
Program w języku VHDL pisany jest w pliku tekstowym ASCII, który musi miec rozszerzenie .vhd, gdy kożysta się z programu MAX+PLUS II lub .vbe w programie ASIMUT. Po jego kompilacji otrzymujemy gotową siatkę połączeń pomiędzy komórkami, którą możemy wykorzystać do "przepalenia" układu. Plik .vhd moze też zostać użyty do zaprogramowania ukladów programowalnych firmy ALTERA za pomocą systemu MAX+PLUS II.
W poniższym opisie skupię się na zastosowaniu systemu MAX+PLUS II do realizacji projektu w jezyku VHDL. System ten pozwala na tworzenie hierarchicznych programów oraz wykorzystywać inne typy plików w projekcie, to znaczy:
Altera Design File (.adf)
EDIF Input File (.edf)
Graphic Design File (.gdf)
OrCAD Schematic File (.sch)
State Machine File (.smf)
Text Design File (.tdf)
VHDL Design File (.vhd)
Waveform Design File (.wdf)
Xilinx Netlist Format File (.xnf)
Do tworzenia progrmów w VHDL można użyc jakiegokolwiek edtytora ASCII, lecz edytor tekstowy MAX+PLUS II posiada wiele cech które są przydatne w czasie kompilacji i sprawdzania projektu.
W edytorze można automatycznie wykreować symbol, który reprezentuje inny plik VHDL oraz dołączyc go do pliku graficznego (.GDF). Plik .gdf przedstawia projekt jako "czarną skrzynkę" z zaznaczonymi tylko wejsciami i wyjsciami. W ten sposób można szybko tworzyć duże projekty hierarchiczne przez rysowanie połączeń pomiędzy plikami przedstawionymi w formie graficznej.
System ten umożliwia sprawdzenie składni VHDL lub przeprowadzenie pełnej kompilacji projektu. Wszystkie błędy zostaną zlokalizowane przez Message Processor i podświetlone w oknie edytora tekstu. Gdy kompilacja zakonczy sie sukcesem projekt mozna przesymulować oraz przeprowadzić jego analizę czsową. Kompilator potrafi też automatycznie wybrać najlepiej pasujący układ dla Twojego projektu.
Gramatyka VHDL.
Plik tekstowy w którym zwarty jest nasz projekt nazywany jest opisem behawioralnym. Składa sie on z dwóch modułów: ARCHITECTURE oraz ENTITY.
Modul ENTITY.
Zawiera on deklaracje wszystkich sygnalów wejsciowych i wyjsciowych. Sygnaly te mogą byc albo pojedynczymi bitami albo slowami o praktycznie dowolnej ilosci bitow:Na przyklad wejsciowe slowo 8-bitowe można zadeklarować pisząc:
word1 :IN BIT_VECTOR(7 DOWNTO 0);
lub
word2 :IN BIT_VECTOR(0 TO 7);
Gdy chcemy aby sygnał był wyjsciem to zamiast IN piszemy OUT.
Modul ENTITY może być wykonany według nastepujacego schematu:
ENTITY identyfikator IS
PORT (
deklaracje_sygnalow
);
END identyfikator;
Ponizej przedstawiona jest przykladowa deklaracja sygnalow:
res_alarm, set_alarm :IN BIT;
alarm :OUT BIT;
led_h, led_m, led_s :OUT BIT_VECTOR(6 DOWNTO 0);
W deklaracji bity numerowne sa od lewej do prawej, tzn. najmlodszy bit ma numer 0.
Moduł ARCHITECTURE.
Wtym module zawiera sie własciwy opis działania ukladu. Należy jednak zwrócić szczególną uwagę na fakt, że program w VHDL jest prawdziwy jednocześnie, gdyż w rzeczywistości jest to po prostu "przepalony" układ scalony. A zatem nie ma w nim sekwncyjnosci (np. petli), chociaż istnieje możliwość wykonania instrukcji warunkowych.
Na początku modulu umieszczane są deklaracje sygnalów wewnętrznych (SIGNALS) oraz definicje stałych (CONSTANTS). Sa one podobne do tych w module ENTITY lecz nie ma poprzedzających je słów IN lub OUT. Przykład:
ARCHITECTURE beh OF identyfikator IS
SIGNAL tym :BIT_VECTOR(8 DOWNTO 0);
SIGNAL alr :BIT
SIGNAL rej :REG_VECTOR(3 DOWNTO 0) REGISTER;
CONSTANT Fife:BIT_VECTOR := "11111";
Poniżej deklaracji sygnalów umieszczamy slowo BEGIN, które sygnalizuje początek logicznego opisu działania programu.
Gdy chcemy sprawdzić wartość pewnych sygnalów to możemy użyc istrukcji ASSERT. Instrukcja ta sprawdza wartosc sygnalów, i gdy są niepoprawne podaje odpowiedni komunikat. Przykład:
ASSERT( vdd = '1' and vss = '0')
REPORT "Wrong power supplies."
SEVERITY WARNING;
Instrukcja może mieć dwa poziomy ważności (SEVERITY):
error - wydrukuje komunikat błędu i przerwie symulacje
warning - powoduje tylko wydruk ostrzeżenia
W opisie behawioralnym najwżniejszą instrukcją jest intrukcja przypisania. Wykonuje się ją za pomocą operatora '< ='. Przypisywana moze byc wartosc, sygnal lub wyrazenie.Na przyklad:
syg1 < = sgn;
syg2 < = a OR b;
syg3 < = "1111";
syg4(3 DOWNTO 0) < = sgn(4 DOWNTO 1);
Praktycznie wszystkie działania na wartosciach sygnalów wykonuje się za pomocą operatorów logicznych:
OR --suma logiczna sygnalów z lewj i prawej strony operatora
AND --iloczyn logiczny sygnalów z lewj i prawej strony operatora
XOR --Exclusive OR
Na przykład:
ab < = a OR b;
abc < = ab(1) AND bc(3);
Pierwsza z powyższych instrukcji wykonuje sumę logiczną 'a' oraz 'b', a wynik umieszcza w 'ab'. Następna zaś wykonuje iloczyn logiczny drugiego bitu słowa 'ab' z czwartym bitem słowa 'bc', a wynik zostanie zapisany w najmłodszym bicie słowa 'abc'. W języku VHDL nie ma operatorów sumy i iloczynu arytmetycznego.
Gramatyka VHDL pozwala dokonywać przypisania warunkowe, to znaczy zależące od wartości sygnału sterującego:
WITH sel SELECT
out < = a WHEN '1' , b WHEN '0';
Sygnałem sterującym moze byc wielobitowe słowo. Możliwe jest też przypisanie warukowe o następującej składni:
out < = val_expr1 WHEN warunek ELSE val_expr2;
Zmienną 'val_expr' może być wartość lub wyrażenie.
Przykład:
syg(3 DOWNTO 0) < = "1111" WHEN a < b ELSE "0000";
out < = a AND b WHEN out ='1' ELSE a OR b;
Instrukcja BLOCK pozwala na realizację ukladów kontrolowanych zegarem. Zegar musi zostać wcześniej zadeklarowany w module ENTITY jako sygnał wejściowy. Sekwencja operacji w bloku rozpoczyna się słowem 'BEGIN', a kończy słowem 'END'. Każdy blok w programie jest wyróżniony indywidualną etykietą. Wewnątrz bloku można przypisywać wartści lub wyrażenia tylko do sygnlów, które zostały wcześniej zadeklarowane jako rejestry. Oto przykłady deklaracji:
ar :REG_BIT REGISTER;
br :REG_VECTOR(3 DOWNTO 0) REGISTER;
Przypisanie do rejestru jest nazywane wyrażeniem bloku (guarded expression).
Poniżej przedstawiony jest przyklad bloku, który wykonywany jest przy narastającym zboczu zegara.
ETYKIETA1: BLOCK(( clk='0' ) AND NOT clk'STABLE)
BEGIN
syg < = GUARDED tym(8 DOWNTO 6);
outreg < = GUARDED reg;
END BLOCK;
Wewnątrz bloku można również umieszczać opisane wyżej instrukcje warunkowe. Przypisania do sygnalów zadeklarowanych wczesnij jako REG_BIT albo REG_VECTOR mogą mieć miejsce tylko w bloku.
Komentarze w pliku VHDL umieszcza się po znaku '--'. Wszystko co po nim następuje nie jest interpretowane.
Przkładowy program w VHDL.
Przkładowy program w VHDL.
Poniżej przedstawiam projekt układu 4-bitowego licznika (modulo 16) z możliwoscią szeregowego wpisywania jego zawartości.
ENTITY lmod IS
PORT(
clk :IN BIT;
syg :IN BIT;
ster :IN BIT;
wyj :OUT BIT_VECTOR(3 DOWNTO 0);
);
END lmod;
ARCHITECTURE data_flow OF lmod IS
SIGNAL s,adder :REG_VECTOR(3 DOWNTO 0) REGISTER;
SIGNAL x :REG_VECTOR(2 DOWNTO 0) REGISTER;
SIGNAL tym,sum :BIT_VECTOR(3 DOWNTO 0);
SIGNAL cry :BIT_VECTOR(2 DOWNTO 0);
BEGIN
sum(0) < = tym(0) xor syg;
cry(0) < = tym(0) and syg;
sum(1) < = tym(1) xor cry(0);
cry(1) < = tym(1) and cry(0);
sum(2) < = tym(2) xor cry(1);
cry(2) < = tym(2) and cry(1);
sum(3) < = tym(3) xor cry(2);
tym < = adder;
w1:BLOCK(( clk='1' ) and not clk'stable)
BEGIN
s(3 DOWNTO 1) < = GUARDED x(2 DOWNTO 0);
s(0) < = GUARDED syg;
adder < = GUARDED sum;
END BLOCK;
w2:BLOCK(( clk='0' ) and not clk'stable)
BEGIN
x < = s(2 DOWNTO 0);
END BLOCK;
WITH ster SELECT
wyj < = s WHEN '0', adder WHEN '1'; --gdy ster=0 to szer. wpisywanie
--gdy ster=1 to licz mod 16
END;