AHDL (ang. Altera Hardware Description Language) jest językiem opisu sprzętu (HDL) przeznaczonym do programowania układów FPGA i CPLD firmy Altera.
Zastosowanie
Jest to bardzo prosty język o niskim stopniu abstrakcji przeznaczony głównie do projektowania małych układów. Jest także nauczany na wielu uczelniach wyższych jako wstęp do współcześnie wykorzystywanych w przemyśle języków opisu sprzętu takich jak: VHDL i Verilog.
Charakterystyka języka
Język AHDL umożliwia podział projektu na jednostki (subdesign), przy czym jedna z tych jednostek pełni rolę nadrzędną (wykorzystuje pozostałe jednostki). Wejścia i wyjścia z jednostki nadrzędnej są wyprowadzane na nogi układu programowalnego. Każda jednostka może zawierać w sobie bramki logiczne, przerzutniki oraz inne mniejsze jednostki. Do tworzenia bloków kombinacyjnych zwykle wykorzystuje się instrukcje if, else, elsif, case, oraz funkcje logiczne and, or, not, ale można również stosować tablice funkcji. Tworzenie przerzutnika wymaga ręcznego zdefiniowania elementu (zwykle DFF lub DFFE) w bloku zmiennych jednostki oraz podłączenia sygnałów zegara oraz resetu. AHDL ułatwia tworzenie automatów dzięki konstrukcji machine of bits with states oraz tabelom przejść i wyjść.
Przykład
Poniżej znajduje się kod prostego licznika rewersyjnego z synchronicznym, równoległym ładowaniem oraz asynchronicznym zerowaniem. Jeśli wejścia clear i load są nieaktywne (wynoszą 1) oraz enable jest aktywne (wynosi 1), to licznik zwiększa lub zmniejsza swą wartość o 1 w zależności od stanu wejścia updown.
title "counter"; -- definicja stałych constant COUNT_UP=0; constant COUNT_DOWN=1; -- definicja nazwy oraz opis wejść i wyjść licznika subdesign counter ( -- aktualna wartość licznika q[15..0]:output; -- wartość do załadowania do licznika data[15..0]:input; -- sygnał ładowania (aktywny stanem niskim) load:input; -- reset asynchroniczny (aktywny stanem niskim) clear:input; -- sygnał zezwolenia na zliczanie (aktywny stanem wysokim) enable:input; -- czy zliczać w górę (stan niski) lub dół (stan wysoki) updown:input; -- zegar synchronizujący operacje (aktywny narastającym zboczem) clock:input; ) variable -- 16 przerzutników reprezentujących bieżący stan licznika q[15..0]:DFF; begin -- podłączenie zegara i resetu q[].clk=clock; q[].clrn=clear; -- operacja ładowania ma wyższy priorytet niż operacja zliczania -- dlatego sprawdzamy bit load przed innymi if load==0 then -- załaduj wartość licznika wartością z wejścia data q[]=data[]; elsif enable==1 then -- sprawdzamy, w którą stronę należy zliczać if updown==COUNT_UP then -- zwiększ wartość licznika o 1 q[]=q[]+1; else -- zmniejsz wartość licznika o 1 q[]=q[]-1; end if; else -- podtrzymaj wartość licznika (pozostawia go bez zmian) -- brak przypisania w tym miejscu skutkowałby wyzerowaniem licznika q[]=q[]; end if; end;