A VHDL típusszerkezete az Ada-éhoz hasonlóan épül fel. Az egyes elemi típusok és új típusok deklarációja ugyanúgy történik, mint Ada-ban. Mivel az Ada erős típusosságának megőrzése fontos volt a készítők számára, ezért a szigorú hierarchikus szervezést is megtartották. Ez alatt értem például az altípusok létrehozásának lehetőségét, az operátorok esetleges túlterhelését a package-ek segítségével. Mindezekhez ugyanazon nyelvi eszközök állnak rendelkezésünkre, mint Ada-ban.
Az elemi típusok az STD könyvtárban előre megírt STANDARD csomagban találhatók. Az alábbi táblázatban felsorolom a VHDL beépített típusait, amik közül csak néhány lesz, ami nem Ada típus.
TÍPUS | JELLEMZŐK |
BOOLEAN | (FALSE, TRUE) |
BIT | ('0','1') |
BIT_VECTOR | BIT típusú elemek tömbje |
CHARACTER | az összes ASCII-karakter értékét felveheti |
STRING | CHARACTER típusú elemek tömbje |
SEVERITY_LEVEL | (NOTE, WARNING, ERROR, FAILURE) |
INTEGER | implementációtól függő tartományon értelmezett egészek |
NATURAL | INTEGER altípus a [0,INTEGER’HIGH] tartományban |
POSITIVE | INTEGER altípus a [1,INTEGER’HIGH] tartományban |
REAL | implementációtól függő tartományon és pontossággal értelmezett valósok |
TIME | a tartomány implementáció-függő, a lehetséges nagyságrendjei a femtoszekundumtól az óráig terjednek |
FILE_OPEN_KIND, FILE_OPEN_STATUS |
fájl megnyitására vonatkozó típusok |
Továbbá használhatjuk a jól ismert access kulcsszót mutatók létrehozására az Ada-ban megszokott szigorú ellenőrzések mellett.
A VHDL fejlesztőkörnyezetek részeként hozzáférünk egy IEEE elnevezésű könyvtárhoz, aminek csomagjai további típusokat definiálnak a fejlesztő számára. E könyvtár szerkezetét az IEEE 1164 kódú szabvány írja le, amit azért hoztak létre, hogy a különböző áramkörökben előforduló logikai értékeket egységesen lehessen kezelni a kód megírásakor. Az IEEE.std_logic_1164 csomag alapvető típusa az std_ulogic, ami kilenc lehetséges értéket vehet fel a következő sorrendben:
LITERÁL | ÉRTÉK |
'U' | meghatározatlan, olyan érték, amit az eszköz működtetésének elején nem láttunk el kezdőértékkel |
'X' | ismeretlen logikai érték, a valóságban nem létezik, csupán arra használhatjuk, hogy szimuláció során egy-egy figyelmen kívül hagyott tervezési hibát felfedezzünk a megjelenésével; vagy az előállított áramkörben külső körülmények hatására bekövetkező alternatív eseteket tudjuk kezelni (a valóságban ez azt jelenti, hogy ’0’ vagy ’1’ értéket is felvehet) |
'0' | logikai hamis érték |
'1' | logikai igaz érték |
'Z' | magas impedanciát jelző érték, amikor a logikai értéket sem ’0’-ként, sem pedig ’1’-ként nem lehet meghatározni |
'W' | magas impedanciájú megfelelője az ’X’ értéknek |
'L' | magas impedanciájú megfelelője az ’0’ értéknek |
'H' | magas impedanciájú megfelelője az ’1’ értéknek |
'-' | lényegtelen, azt jelenti, hogy nem vesszük figyelembe az adott helyen megjelenő logikai értéket |
Az std_ulogic ’u’ betűje az unresolved (vagyis feloldatlan) szó rövidítése, ami azt jelenti, hogy szükséges megírnunk egy ezeket az értékeket értelmező függvényt (például háromértékű logikához, ahol ’0’, ’1’ és ’Z’ értékeket használhatunk).
Az imént tárgyalt típusból származik az std_logic nevű, szintén a csomagban leírt típus is, ami már megvalósítja az ipari szabványoknak megfelelő értelmezést is. Más altípusokat is találhatunk még itt, amik a kilencelemű értékhalmaz néhány gyakran alkalmazott részhalmazát definiálják. Továbbá az előbbiekből képzett összetett típusokat is tartalmaz az std_logic_1164, amik az std_ulogic_vector és az std_logic_vector.
Az STD_LOGIC_VECTOR típusú objektumoknak legtöbbször valamilyen a fentebb felsorolt lehetséges karaktereket tartalmazó megfelelő hosszúságú sztringgel adunk értéket. Ez azonban nem mindig kényelmes, és nagyobb méretű tömbök esetén jelentősen csökkentheti az átláthatóságot. Ezért már a legelső szabvány is támogatta a következő literálokat, amik viszont csak számok reprezentálására voltak használhatók:
signal Value : unsigned(7 downto 0); Value <= "00000000"; Value <= B"0000_0000"; -- bináris ábrázolás (ugyanaz, mint előbb, -- de használható az olvasást segítő '_' elválasztó jel) Value <= X"00"; -- hexadecimális ábrázolás (jóval tömörebb) Value <= O"0000"; -- oktális ábrázolás (néha kényelmes lehet)
Az IEEE 1076-2008 szabvány még inkább megkönnyíti a bitvektorok értékadásait. Azt is fontos megjegyezni, hogy az alábbi literálok az STD_LOGIC_VECTOR típusú elemeknél használhatók.
variable Reg : std_logic_vector(5 downto 0); Reg := 6x"0f"; -- a megadott érték 6 bit szélességen ábrázolva, -- '0'-kkal kitöltve a nem használt helyiértékeket Reg := 6x"XF"; -- hasonló az előzőhöz, csak itt: "XX1111" Reg := 6SX"F"; -- előjeles kiterjesztés (sign extension), tehát: "111111" Reg := 6Ux"f"; -- előjel nélküli formára való kiegésítés: "001111" Reg := 6sb"11"; -- a harmadikhoz hasonló, csak bináris számként -- értelmezi az értéket: "111111" Reg := 6uO"7"; -- a negyedikhez hasonló, csak oktális számként -- értelmezi az értéket: "000111"
Mivel lényegében semmi különbség nincs az összetett típusok konstrukcióját illetően a VHDL és az Ada között, ezért csak azt emelném ki, hogy a VHDL tömbjei indextartományának beállítására használhatjuk a (imin to imax) helyett az (imax downto imin) kifejezést is, ahol az újdonság a downto kulcsszó.
A csökkenő indexelés a hardveres gondolkodás sajátja, mivel általában binárisan ábrázolt számokkal dolgozunk, valamint az ezeket kezelő regiszterekkel és huzalokkal. Az átláthatóság miatt ezért a hagyományos csökkenő helyi értékes ábrázolás sokkal előnyösebb.
Az IEEE 1076-2008 szabvány már azt is megengedi, hogy a következő módokon egy-egy tömb vagy rekord elemei előre nem meghatározott méretűek legyenek:
type myArrayT is array (natural range <>) of std_logic_vector; type myRecordT is record a : std_logic_vector; b : std_logic_vector; end record;
Ilyen típussal ellátott objektumok olyan értékeket tartalmaznak, amik valamely fizikai mennyiséget reprezentálnak. Az értékkészletük mindig az egész számok halmaza, amit kiegészíthetünk a különböző mértékegységekre vonatkozó szorzókkal.
Nézzünk egy jellemző példát:
type aramerosseg is range 0 to 1 E9 units nA; uA = 1000 nA; mA = 1000 uA; Amp = 1000 mA; end units;
Ugyanilyen fizikai típus a beépített TIME is.