kategória | ||||||||||
|
||||||||||
|
||
Digitális rendszerek tervezése a VHDL nyelv segítségével
1. Bevezetés
1.1. Hardver-leíró nyelvek
A hardver rendszerek klasszikus tervezése általában a következő részekből áll: a tervezési specifikációk leírása természetes nyelvben, a terv megvalósítása rajzokkal és a terv szimulálása. A jelenlegi hardver rendszerek bonyolultsága miatt szükség van új tervezési módszerekre. A tervezők számára előnyös a rendszer specifikációinak leírása egy hardver-leíró nyelv segítségével. Ennek a megközelítésnek a főbb előnyei a következők:
A leírás szimulálásával lehetővé válik a tervezett rendszer működésének ellenőrzése a rendszer megvalósítása előtt;
A leírás felhasználható egy szintézis program bemeneteként;
A leírás a tervezett rendszer dokumentálását teszi lehetővé, ami technológiailag független;
A hardver-leíró nyelvek magas szintű absztrakt specifikációt tesznek lehetővé;
A típusok szigorú ellenőrzésével kiszűrhető a hibák nagy része.
1.2. A VHDL hardver-leíró nyelv
A VHDL (VHSIC Hardware Description Language) az ADA programozási nyelvre alapszik. A VHDL nyelv kifejlesztését az Egyesült Államok Védelmi Minisztériuma kezdeményezte, azzal a céllal, hogy egy szabványos nyelvet hozzon létre a VHSIC (Very High Speed Integrated Circuit) projekt részére. A nyelv első verzióját 1985-ben publikálta a Védelmi Minisztérium egy katonai szabványként (MIL-STD-454L), majd több módosítás után az IEEE szervezet szabványosította (IEEE 1076-1987 szabvány - VHDL'87). A nyelv egy újabb verzióját 1993-ban szabványosították (IEEE 1076-1993 szabvány - VHDL'93).
A VHDL nyelv főbb jellemzői a következők:
Különböző leírási stílusokat tesz lehetővé: funkcionális leírások, adat-folyam típusú leírások és strukturális leírások.
Különböző tervezési módszereket és modellezési technikákat tesz lehetővé: algoritmikus leírások, egyenletek, automaták.
Különböző hardver technológiák használhatók, új primitív logikai típusok és technológiai attribútumok segítségével.
Konkurrens utasítások használhatók, amelyek egyidejű események modell 858e43i ezését teszik lehetővé.
Új adattípusok definiálhatók.
1.3. A tervezési folyamat
A digitális rendszerek tervezési folyamata a VHDL nyelv segítségével (1. ábra) a következő lépésekb l áll:
A rendszer modellezése egy VHDL leírással.
A modell kiegészítése teszt vektorokkal.
A modell szimulálása egy VHDL szimulátor segítségével.
A VHDL leírás szintézise egy szintézis program segítségével, amely technológiailag független.
Egy ASIC (Application Specific Integrated Circuit) vagy FPGA (Field-Progra-mmable Gate Array) fejlesztői rendszer felhasználása, egy bizonyos technológia szerint.
A generált hardver rendszer VHDL modelljének a szimulálása.
A két szimulációs eredmény összehasonlítása, amely alapján megállapítható, hogy a generált rendszer működése megegyezik-e az eredeti modell működésével.
1. ábra. A tervezési folyamat
2. VHDL tervezési egységek
A tervezési egységek egy leírás alapelemei. Egy bizonyos tervezési egység egyetlen állományban kell szerepeljen, tehát nem lehet felosztani több állomány között. Egy állomány tartalmazhat viszont bármilyen számú tervezési egységet. A VHDL nyelv tervezési egységei feloszthatók elsődleges és ezeknek megfelelő másodlagos tervezési egységekre. A tervezési egységek a következők:
Entitás (elsődleges) és architektúra
(másodlagos);
- Csomag deklaráció (elsődleges)
és csomag törzs (másodlagos);
- Konfiguráció (elsődleges).
2.1. Entitás
Az entitás egy elsődleges tervezési egység, amely egy teljes digitális rendszert, egy alrendszert vagy komponenst ábrázol. Egy entitás deklaráció a hardver rendszer interfészét határozza meg: a be- és kimeneteket (portokat), az adatok irányát (in, out), az adatok típusát és a paramétereket (generikusokat).
2. ábra. Az 1 bites összeadó grafikus szimbóluma.
A 2. ábrán szimbolizált 1 bites összeadónak megfelelő entitás a következő:
entity add_1 is
port (a, b, cin: in bit;
s, cout: out bit)
end entity add_1;
2.2. Architektúra
Az architektúra leírja a megfelelő entitás tartalmát vagy funkcióját. Minden architektúra tartalmazhat egy deklarációs részt és konkurrens utasításokat. A deklarációs részben jelek, típusok, konstansok, komponensek és alprogramok definiálhatók. A konkurrens utasítások lehetnek jel-értékadó utasítások, komponensek, folyamatok, alprogram hívások vagy blokkok. Az architektúra szerkezete a 3. ábrán látható.
3. ábra. Egy architektúra általános szerkezete
Az előbbi add_1 entitásnak megfelelő architektúra például a következő lehet:
architecture szintezis of add_1 is
signal s1, c1, c2: bit;
begin
s1 <= a xor b;
c1 <= s1 and cin;
c2 <= a and b;
s <= s1 xor cin;
cout <= c1 or c2;
end szintezis;
2.3. Csomag deklaráció és csomag törzs
Egy csomag deklaráció tartalmazhat konstans deklarációkat, típus deklarációkat, komponens deklarációkat és alprogram deklarációkat. Egy csomagban deklarált információk felhasználhatók utólag több entitásban és architektúrában. A csomag törzs a deklarált alprogramok törzsét tartalmazza.
A következő csomag deklaráció egy típus, altípus, jel, komponens és funkció deklarációját tartalmazza.
package pelda is
type byte is range 0 to 255;
subtype nibble is byte range 0 to 15;
constant end_k: byte := 255;
signal op1: byte;
component adder is
port (a, b: in byte;
c: out byte;
over: out boolean);
end component;
function f_mul (a, b: nibble) return byte;
end pelda;
3. Leírási stílusok
Egy architektúra leírásában a VHDL nyelv több stílus felhasználását teszi lehetővé: funkcionális leírás, adatfolyam-típusú leírás (dataflow) és strukturális leírás. A különböző stílusokat egy 4 bites egyenlőségi komparátorral mutatjuk be, amelynek bemenetei a[3:0] és b[3:0] vektorok, a kimenet pedig eq, amely logikai '1' lesz, ha a két bemenet egyenlő.
3.1. Funkcionális leírások
A funkcionális leírások algoritmikus leírások, ezért a magas szintű programozási nyelvekre hasonlítanak. Egy bizonyos entitás struktúrájának a meghatározása helyett, a funkcionális leírások szekvenciális utasításokból és folyamatokból állnak, amelyeknek a végrehajtása az entitás működését modellezi. A funkcionális leírások előnye, hogy a tervező nem kell figyeljen az entitás megvalósítására kapuk szintjén, hanem az entitás működésének a modellezésére koncentrálhat.
A következő példa az említett egyenlőségi komparátor funkcionális leírását tartalmazza.
entity komp_4 is
port (a, b: in bit_vector (3 downto 0);
eq: out bit);
end komp_4;
architecture funkcionalis of komp_4 is
begin
komp: process (a, b)
begin
if a = b then
eq <= '1';
else
eq <= '0';
end if;
end process komp;
end funkcionalis;
3.2. Adatfolyam-típusú leírások
Az egyenlőségi komparátor egy lehetséges adatfolyamat-típusú leírása a következő:
entity komp_4 is
port (a, b: in bit_vector (3 downto 0);
eq: out bit);
end komp_4;
architecture adat_f of komp_4 is
begin
eq <= '1' when (a = b) else '0';
end adat_f;
Az adatfolyam-típusú leírások konkurrens utasításokat tartalmaznak folyamatok és szekvenciális utasítások helyett. Az előbbi példában az eq jel értékadó utasítása egy konkurrens utasítás.
A következő példa az egyenlőségi komparátor egy más architektúráját mutatja be, amely logikai egyenleteket tartalmaz.
architecture adat_f of komp_4 is
begin
eq <= not (a(0) xor b(0))
and not (a(1) xor b(1))
and not (a(2) xor b(2))
and not (a(3) xor b(3));
end adat_f;
3.3. Strukturális leírások
A strukturális leírások kapcsolási listákat tartalmaznak, amelyekben a komponensek jelekkel vannak összekötve. Ezek a leírások hierarchikusak; a különböző komponensek csomagokban definiálhatók, amelyeket könyvtárakban lehet tárolni. A strukturális leírások főleg a bonyolult tervek esetén előnyösek, amelyek több részre oszthatók. Minden rész tervezése függetlenül valósítható meg.
A következő strukturális leírásban szereplő xnor2 és and4 komponenseket a kapuk nevű csomagban kell definiálni, és ezt a csomagot a munka nevű könyvtárban kell tárolni.
entity komp_4 is
port (a, b: in bit_vector (3 downto 0);
eq: out bit);
end komp_4;
use munka.kapuk.all;
architecture strukturalis of komp_4 is
signal x: bit_vector (3 downto 0);
begin
u0: xnor2 port map (a(0), b(0), x(0));
u1: xnor2 port map (a(1), b(1), x(1));
u2: xnor2 port map (a(2), b(2), x(2));
u3: xnor2 port map (a(3), b(3), x(3));
u4: and4 port map (x(0), x(1), x(2), x(3), eq);
end strukturalis;
4. VHDL szimulátorok
A VHDL szimulátorok események által vezérelt szimulálást végeznek. Egy esemény egy bizonyos jel állapotának módosítását jelenti. Az események által vezérelt szimulálás alapfogalmai a következők: a szimulációs idő, az események feldolgozása és a delta késés.
A szimulálás alatt a szimulátor nyilvántartja a szimulációs időt, amely azt az időpontot jelenti, amikor kezdetét veszi a szimulálás, és nem a szimuláláshoz szükséges időt. A szimulációs időt általában egy időegységnek a sokszorosában mérjük, amelyet felbontási határnak nevezünk. A felbontási határ általában 1 ps.
Egy esemény feldolgozásánál a szimulátor újraértékel minden utasítást, amelynek bemenete az a jel, amely az eseményt okozta (tehát, azokat az utasításokat, amelyek "érzékenyek" az illető jelre). Az utasítások újraértékelése más jelek módosítását és más események létrehozását eredményezi.
A következő példa egy egyszerű folyamatot tartalmaz, amely egyetlen jel-értékadó utasításból áll.
p1: process (a, b, c)
begin
x <= a and b and c;
end process p1;
Az a b vagy c jel állapotának módosítása esetén, az x jel újraértékelődik és a szimulátor egy új értéket számít ki az x jelnek. A szimulátor a jelenlegi szimulációs időpontra egy esemény végrehajtását tervezi meg, amely az x jel módosításából áll. Potenciális problémák keletkezhetnek abban az esetben, ha az x jelet ugyanabban az időpontban kell aktualizálni, mint azok a jelek egyike, amelyből az x jel lesz generálva. Az ilyen problémák kiküszöbölésére a VHDL bevezeti a delta késést (d). A delta késés egy végtelenül kis késés, amely egy delta ciklus végrehajtását eredményezi a jelek értékének aktualizálása végett. Tehát, az előbbi értékadó utasítás szemantikája a következő: a jobboldali kifejezés értéke a jelenlegi szimulációs időben, Tc, egy delta késéssel a jelenlegi szimulációs idő után adödik át az x jelnek, tehát a Tx+d időpontban.
A Tx+d szimulációs időben feldolgozásra kerül minden esemény, amely erre az időpontra volt megtervezve, és új események jönnek létre. Az új események egy része a jelenlegi szimulációs időpontra lesz tervezve, ami azt jelenti, hogy a Tx+2d szimulációs időpontban kerül végrehajtásra. Egy újabb delta késés után a szimulátor újból feldolgozza az eseményeket, ami által új események jönnek létre, és így tovább, amíg nem terveznek más eseményeket a jelenlegi szimulációs időre. Ekkor a szimulátor megállapítja a következő szimulációs időt, és ennek megfelelően növeli a szimulációs időt.
5. Típusok
5.1. A típusok osztályozása
A 4. ábra a VHDL nyelv típusainak osztályozását mutatja be.
A skaláris típusok egyszerű típusok, tehát nem tevődnek össze más elemekből. A skaláris típusok a következők: felsorolt típusok, egész típusok, lebegőpontos típusok és fizikai típusok. Az összetett típusok a tablókat és rekordokat tartalmazzák. A hozzáférési típusok hasonlóak a programozási nyelvekből ismeretes mutatókkal (pointerek), és lehetővé teszik a tár dinamikus lefoglalását egy objektum részére és utólag a tár felszabadítását. A hozzáférési típusokat nem lehet szintézisre használni, csak szimulálásra. Egy fájl típus lehetővé teszi egy fájl típusú objektum deklarálását, amely egy bizonyos típusú értéke sorozatát tartalmazza. A fájl típusok csak szimulálásra használhatók.
4. ábra. A VHDL nyelv típusainak osztályozása
5.2. Standard típusok
Bizonyos típusok definiáltak a VHDL nyelv által. Ezek a típusok egy standard nevű csomagban találhatók. Az 1. táblázat bemutatja a standard csomagban definiált adattípusokat és a kategóriát amelyhez tartoznak.
Típus |
Kategória |
Felhasználás szintézisre |
bit |
Felsorolt típus |
|
boolean |
Felsorolt típus |
|
character |
Felsorolt típus |
|
integer |
Egész típus |
|
natural |
Az integer altípusa |
|
positive |
Az integer altípusa |
|
real |
Lebegőpontos típus |
|
time |
Fizikai típus |
|
delay_length |
A time altípusa |
|
string |
Character típusú vektor |
|
bit_vector |
Bit típusú vektor |
|
1. táblázat. A standard csomagban definiált típusok
Az előbbi típusokon kívül, léteznek más standard típusok, amelyek más csomagokban vannak definiálva. Ezek közül a legfontosabb csomag a std_logic_1164, amely az IEEE 1164-es számú szabvány része. Az ebben a csomagban definiált típusokat a 2. táblázat tartalmazza.
Típus |
Kategória |
Felhasználás szintézisre |
std_ulogic |
Felsorolt típus |
|
std_logic |
A std_ulogic altípusa |
|
std_ulogic_vector |
std_ulogic típusú vektor |
|
std_logic_vector |
std_logic típusú vektor |
|
2. táblázat. A std_logic_1164 csomagban definiált típusok
Egyszerű típusok
5.3.1. Felsorolt típusok
Egy felsorolt típus egy bizonyos objektum lehetséges értékeit sorolja fel egy lista formájában. A lista minden eleme egy szimbolikus név vagy egy karakter lehet. Például, a következő típus négy lehetséges logikai értéket sorol fel:
type log4 is ('X', '0', '1', 'Z');
Az IEEE 1076 számú szabvány által definiált legfontosabb felsorolt típusok, amelyek felhasználhatók szintézisre is, a következők: bit boolean és character. Az IEEE 1164 számú szabvány definiálja a std_ulogic típust és ennek több altípusát, amelyek ugyancsak felhasználhatók szintézisre.
A bit típus két értéket definiál, amelyeket a és karakterekkel jelölünk. A definíció a következő:
type bit is ('0', '1');
A boolean típus a következőképpen definiált:
type boolean is (FALSE, TRUE)
Az összehasonlítási műveletek eredményei boolean típusúak. Szintézisnél a FALSE érték logikai 0-át jelent, míg a TRUE érték logikai 1-et.
A character típus ASCII karaktereket definiál. A nyelv VHDL'87 verziójában a character típus a 7-bites ASCII karakterszettet definiálja, míg a VHDL'93 verzióban az ISO 8859-1 (Latin-1) karakterszettet. A kontroll karakterek, amelyeknek kódja és 1Fh között van, szimbolikusan vannak jelölve, például: BEL 07h BS 08h HT 09h CR 0Dh
5.3.2. Egész típusok
A legfontosabb egész típus az integer, amely a standard csomagban definiált:
type integer is range -2147483648 to +2147483647;
Az integer típus két altípusa a natural és a positive
subtype natural is integer range 0 to integer'high;
subtype positive is integer range 1 to integer'high;
Az integer'high érték az integer típus legnagyobb értékét jelenti. Egy natural vagy positive típusú jel alaptípusa az integer, de a lehetséges értékek a természetes számokra, illetve a pozitív számokra korlátozódnak.
Az integer típuson és ennek altípusain kívül a felhasználó tetszőlegesen definiálhat más típusokat. Az így definiált típusok főleg a szintézisre használt jelek és változók lehetséges értékeinek korlátozására hasznosak.
5.3.3. Fizikai típusok
A fizikai típusok nemcsak az objektumok értékeit jelölik meg, hanem az értékek mértékegységeit is. Egy fizikai típus deklarációjában két típusú mértékegységet lehet megadni: egy elsődleges mértékegységet és több másodlagos mértékegységet; az utóbbiak az elsődleges mértékegység függvényében vannak kifejezve.
A VHDL nyelv egyedüli előre definiált fizikai típusa a time, amelynek elsődleges mértékegysége a femtoszekundum (fs). A time típus definíciója a következő:
type time is range -2147483647 to +2147483647
units
fs;
ps = 1000 fs;
ns = 1000 ps;
us = 1000 ns;
ms = 1000 us;
sec = 1000 ms;
min = 60 sec;
hr = 60 min;
end units;
5.4. Összetett típusok
5.4.1. Tablók
Egy tabló típusú objektum több elem gyűjteményéből áll, amelyben minden elem alaptípusa ugyanaz. A különböző elemek egy vagy több index alapján érhetők el, ahol az indexek száma a tabló dimenziójától függ.
A VHDL nyelvben két előre definiált tabló van, és mindkettő egy dimenziójú (vektor). A bit_vector tabló bit típusú, a string tabló pedig character típusú. E két tabló definíciója a következő:
type bit_vector is array (natural range <>) of bit;
type string is array (positive range <>) of character;
A bit_vector vagy string típusú jelek deklarációjánál a lehetséges értékek tartományát korlátozni kell, mint például a következő deklarációkban:
signal data: bit_vector (31 downto 0);
signal mes: string (1 to 40);
A data és a mes vektorok elemei data(31) data(0), valamint mes(1 mes(40
Az IEEE 1164 számú szabvány két tablót definiál a std_logic_1164 csomagban, a std_ulogic típus, illetve a std_logic altípus alapján. A szabvány ugyanakkor operátorokat és konverzió funkciókat definiál a tablók számára. A két tabló definíciója a következő:
type std_ulogic_vector is array (natural range <>) of std_ulogic;
type std_logic_vector is array (natural range <>) of std_logic;
Az IEEE 1076.3 számú szabvány két új csomagot definiál, a numeric_bit és a numeric_std csomagokat. Mindkét csomag tablók formájában definiál két típust, az unsigned és a signed típusokat. A két csomagot nem lehet egyszerre használni, mivel a két típust különböző módon definiálja. A numeric_bit csomagban a definíciók a következők:
type unsigned is array (natural range <>) of bit;
type signed is array (natural range <>) of bit;
A numeric_std csomagban a két típus definíciója a következő:
type unsigned is array (natural range <>) of std_logic;
type signed is array (natural range <>) of std_logic;
Az unsigned típus egy előjel nélküli bináris egész számot jelent, míg a signed típus egy előjeles bináris egész számot, kettes komplement ábrázolásban.
5.4.2. Rekordok
Egy rekord típusú objektum több elem gyűjteményéből áll, amelyben az elemek alaptípusa különböző lehet. Egy bizonyos elemhez a rekord neve és az elem neve által lehet hozzáférni. A következő példában egy két elemes rekord és egy ilyen rekord típusú jel van definiálva.
type complex is record
re: integer;
im: integer;
end record;
signal a: complex;
Az a jel reális részének értékadása a következőképpen történhet:
a.re <= 0;
Egy rekord típusú jel minden elemének az értékadása egy aggregátum felhasználásával lehetséges, például:
a <= (re => 0, im => 0);
vagy:
a <= (0, 0);
6. Attribútumok
Egy attribútum információkat szolgáltat egy bizonyos típusról vagy egy bizonyos típusú objektum értékeiről. A VHDL nyelv előre definiált attribútumai típusokra, tablókra és jelekre vonatkoznak. A típusokra vonatkozó attribútumok egy része felhasználható a tablók attribútumaiként is. A nyelv ezen attribútumain kívül léteznek a szimulátor által vagy a szintézis rendszer által definiált attribútumok. Ugyanakkor a felhasználó is definiálhat attribútumokat.
6.1. Típusokra vonatkozó attribútumok
A VHDL nyelv a következő attribútumokat definiálja a felsorolt és egész típusok részére (ezeknek egy része használható a fizikai típusok részére is):
típus'left
típus'right
típus'low
típus'high
típus'pred (x)
típus'succ (x)
típus'leftof (x)
típus'rightof (x)
típus'pos (x)
típus'val (x)
A 'left és 'right attribútumok egy típus baloldali, illetve jobboldali értékének meghatározására használhatók. Egy típus legkisebb és legnagyobb értéke meghatározható a 'low, illetve 'high attribútummal. A 'pred és 'succ attribútumokkal meghatározható az x érték elődje, illetve utódja (tehát, az x értékhez viszonyított közvetlenül kisebb, illetve közvetlenül nagyobb érték a típuson belül). A 'leftof és a 'rightof attribútumok alkalmazásával az x argumentum baloldali értéke, illetve jobboldali értéke kapható meg. A 'pos attribútum az x argumentumot, amely egy felsorolt típus értéke, egy egész számra konvertálja, amely az illető érték pozíciójával egyenlő a típuson belül. A 'val attribútum az x argumentumot, amely egy érték pozíciója egy felsorolótípuson belül, az ennek a pozíciónak megfelelő értékre konvertálja.
6.2. Tablókra vonatkozó attribútumok
A tablókra vonatkozó attribútumok információkat szolgáltatnak egy tabló dimenziójáról, tartományáról vagy indexeléséről. A legfontosabb attribútumok, amelyek tablókra vonatkoznak, a következők:
tabló'left
tabló'right
tabló'low
tabló'high
tabló'range
tabló'reverse_range
tabló'length
A 'left attribútum egy tabló indexének a baloldali határértékét téríti vissza, míg a 'right attribútum egy tabló indexének a jobboldali határértékét téríti vissza. Abban az esetben, ha a tabló többdimenziójú, használhatók a 'left (n), illetve 'right (n) formák, ahol n az index számát jelenti. A 'low és 'high attribútumok egy tabló indexének a legkisebb értékét, illetve a legnagyobb értékét térítik vissza. Egy többdimenziójú tabló esetén, a 'low (n), illetve 'high (n) formák a tabló n-edik indexének a legkisebb értékét, illetve a legnagyobb értékét térítik vissza. A 'range attribútum egy tabló indexének tartományát téríti vissza, míg a 'reverse_range attribútum egy tabló indexének fordított tartományát téríti vissza. Hasonlóképpen a többi attribútummal, használhatók a 'range (n), illetve a 'reverse_range (n) formák is. A 'length attribútum egy tabló elemeinek számát téríti vissza.
6.3. Jelekre vonatkozó attribútumok
A jelekre vonatkozó attribútumok információkat szolgáltatnak a jelek módosításáról. A legfontosabb attribútumok, amelyek jelekre vonatkoznak, a következők:
jel'event
jel'last_value
jel'last_event
jel'delayed (t)
jel'stable (t)
Az 'event attribútum a TRUE értéket téríti vissza, ha az illető jel módosult a jelenlegi delta ciklus alatt; ellentétes esetben, az attribútum a FALSE értéket teríti vissza. Az 'event attribútum nagyon hasznos egy órajel éleinek detektálására. Például, a clk órajel felmenő élének detektálására a következő utasítás használható:
if (clk'event and clk = '1') then ... end if;
A 'last_value attribútum egy jel előző értékét téríti vissza, tehát az utolsó esemény előtti értéket. A 'last_event attribútum az illető jel utolsó eseményétől eltelt időt téríti vissza. Ez az attribútum a szimulálásnál hasznos, mivel lehetővé teszi a különböző időzítések tesztelését. A 'delayed attribútum egy új jelet hoz létre, amely az eredeti jel t időegységgel megkésett változata. A 'stable attribútum egy boolean típusú jelet hoz létre, amely TRUE értékű, ha a megadott t idő alatt az illető jel nem módosult.
7. Konkurrens utasítások
7.1. Folyamatok
A folyamatok konkurrens utasítások, tehát párhuzamosan futnak más konkurrens utasításokkal. Minden folyamat viszont szekvenciális utasításokat tartalmaz, amelyek a megadott sorrendben futnak. Egy folyamat deklarációja egy szekvenciális részt határol el azon az architektúrán belül, amelyben a deklaráció megjelenik.
Egy folyamat általános szerkezetét az 5. ábra szemlélteti.
5. ábra. Egy folyamat általános szerkezete
A folyamat deklarációs része a process és begin kulcsszavak között van elhelyezve. Ebben a részben típusok, konstansok, változók, komponensek és alprogramok deklarálhatók. Az itt deklarált objektumok csak a folyamaton belül használhatók. Egy folyamat keretében nem deklarálhatók jelek.
Egy folyamat csak szekvenciális utasításokat tartalmazhat. A következő példában a p1 folyamat két értékadó utasítást tartalmaz.
p1: process (a, b, c)
begin
x <= a and b and c;
y <= a xor b;
end process p1;
Az előbbi folyamat tartalmaz egy úgynevezett érzékenységi listát, amely az a b és c jelekből áll. Amikor a listában szereplő jel bármelyike módosul, a folyamat utasításai végrehajtódnak, hasonló módon egy program utasításaihoz. Egy programozási nyelvtől eltérően, az end process kulcsszavak nem jelentik a folyamat végrehajtásának végét. Egy folyamat végtelen ciklusban fut; az utolsó utasítás után a folyamat végrehajtása felfüggesztődik, amíg az érzékenységi listában szereplő jelek valamelyike módosul.
Ha az érzékenységi lista hiányzik, a folyamat nem áll le. Ebben az esetben, a folyamat egy wait utasítást kell tartalmazzon, amely a folyamat végrehajtását felfüggeszti egy esemény megjelenéséig vagy egy feltétel teljesítéséig. A következő folyamat egy wait utasítást tartalmaz egy érzékenységi lista helyett.
p1: process
begin
x <= a and b and c;
y <= a xor b;
wait on a, b, c;
end process p1;
A szintézis szempontjából kombinacionális és szekvenciális folyamatokat lehet megkülönböztetni. Az egyedüli különbség közöttük, hogy a szekvenciális folyamatoknál a kimenő jelek bistabilokba vagy regiszterekbe íródnak.
A következő példa egy kombinacionális folyamatot tartalmaz, amely egy AND kapunak felel meg.
p2: process
begin
wait on a, b;
z <= a and b;
end process p2;
Azért, hogy egy folyamat egy kombinacionális áramkört modellezzen, a folyamat érzékenységi listájának tartalmaznia kell minden bemenő jelet.
Az előbbi folyamatnak a következőképpen módosított változata szekvenciális folyamatként értelmezhető:
p3: process
begin
wait until clk = '1';
z <= a and b;
end process p3;
A p3 folyamat szintézise a 6. ábrában látható áramkört eredményezi.
6. ábra Egy szekvenciális folyamat szintézisének eredménye
7.2. Feltételes jel-értékadó utasítás
A feltételes jel-értékadó utasítás egy when else konstrukció. Ez az utasítás az if szekvenciális utasításnak felel meg. A feltételes jel-értékadó utasítást a következő példával szemléltetjük:
z <= a when s0 = '1' else
b when s1 = '1' else
c;
A feltételek a leírt sorrendben kerülnek kiértékelésre. Az első teljesített feltételnek megfelelő kifejezés értéke lesz az, amely kiválasztódik a jel-értékadásra. Hardver szempontból az utasítás több sorba kötött multiplexernek felel meg, ahol az első feltétel a kimenethez legközelebb levő multiplexert vezérli. Az előbbi utasításnak megfelelő áramkör a 7. ábrában látható.
7. ábra. Egy feltételes jel-értékadó utasításnak megfelelő áramkör
7.3. Szelektív jel-értékadó utasítás
Egy szelektív jel-értékadó utasítást egy with select when konstrukcióval lehet megvalósítani. Ebben az esetben is, az utasítás lehetővé teszi egy kifejezés kiválasztását több kifejezés közül. A különbség a feltételes jel-értékadó utasítással szemben az, hogy a szelektív jel-értékadó utasítás egyetlen feltételt használ. Ez az utasítás a case szekvenciális utasításnak felel meg.
A következő példa egy xor kaput ír le egy with select when konstrukció segítségével.
-- xor kapu (x <- a xor b)
architecture a_xor2 of xor2 is
signal t: std_logic_vector (1 downto 0);
begin
temp := a & b;
with temp select
x <= '0' when "00",
'1' when "01",
'1' when "01",
'0' when "11";
'0' when others;
end a_xor2;
8. Szekvenciális utasítások
If utasítás
Az if utasítás egy utasítás sorozatot választ ki végrehajtás céljából több utasítás sorozatból, a sorozatnak megfelelő feltétel alapján. Minden feltétel egy boolean típusú kifejezés kell legyen. Az if utasítást a következő példával szemléltetjük:
process (a, b, c, s0, s1)
begin
if s0 = '1' then
z <= a;
elsif s1 = '1' then
z <= b;
else
z <= c;
end if;
end process;
Először az if kulcsszó utáni feltételt értékelik ki és, ha a feltétel igaz, lefut a megfelelő utasítás. Ellenkező esetben, ha jelen van az elsif kulcsszó, kiértékelődik az ennek megfelelő feltétel és, ha a feltétel igaz, lebonyolódik a megfelelő utasítás. Ha a feltétel nem igaz és más elsif kulcsszó is jelen van, folytatódik az ezeknek megfelelő feltételek kiértékelése. Ha egyik feltétel sem igaz, az else kulcsszónak megfelelő utasítás kerül végrehajtásra, ha ez a kulcsszó jelen van.
Az if utasítás hardver megfelelője, hasonlóan a feltételes jel-értékadó utasítás esetében, egy multiplexer. Az előbbi példában leírt if utasítás a feltételes jel-értékadó utasításnál illusztrált when else konstrukciónak felel meg, így a hardver megfelelője is ugyanaz (7. ábra).
Case utasítás
Hasonlóan az if utasításhoz, a case utasítás is kiválaszt végrehajtás céljából egy utasítás sorozatot egy kifejezés értékének függvényében. Az if utasítástól eltérően azonban, a kiválasztás nem egy boolean típusú kifejezés szerint történik, hanem egy felsorolt vagy egész típusú jel, változó vagy kifejezés szerint. A case utasítás akkor előnyös, amikor nagyszámú alternatívából lehet választani.
A következő példa a már használt xor kaput írja le egy case utasítás segítségével.
-- xor kapu (a xor b -> x)
process (a, b)
variable t: std_logic_vector (1 downto 0);
begin
temp := a & b;
case temp is
when "00" => x <= '0';
when "01" => x <= '1';
when "10" => x <= '1';
when "11" => x <= '0';
when others => x <= '0';
end case;
end process;
Egy case utasítás hardver megfelelője ugyancsak egy multiplexer. Az if utasítástól eltérően, a case utasítás esetében lehetséges a feltételek optimalizálása, aminek eredményeképpen a létrehozott áramkörök egyszerűbbek.
8.3. Loop utasítások
A loop utasítások egy utasítássorozat ismételt végrehajtását teszik lehetővé, például egy tabló minden elemének a feldolgozását. A VHDL nyelvben három típusú loop utasítás létezik: az egyszerű loop utasítás, a while loop utasítás és a for loop utasítás.
Az egyszerű loop utasítás az adott utasítássorozat ismétlését eredményezi egy végtelen ciklusban. Ebben az esetben az egyedüli lehetőség az utasítássorozat befejezésére egy exit utasítás használata.
A while loop utasítás addig ismétli a megadott utasítássorozatot, amíg egy bizonyos feltétel igaz. Amikor a feltétel nem teljesül, az end loop kulcsszavak után levő utasítás végrehajtására kerül sor. A while loop utasítás egy példája a következő:
while szint = '1' loop
n : = n + 1;
wait until clk = '0';
end loop;
A for loop utasítás egy megadott utasítássorozatot addig ismétel, amíg egy számláló a megfelelő tartományban van. Egy iteráció elvégzése után a számláló az illető tartomány következő értékét veszi fel. A következő for loop utasítás az 1 és 10 közötti egész értékek négyzetét számítja ki és ezeket a negyzet tablóban helyezi el.
for i in 1 to 10 loop
negyzet (i) <= i * i;
end loop;
Next utasítás
A next utasítás egy loop utasítás törzsén belül helyezhető el. A next utasítás elérésénél a jelenlegi iteráció végrehajtása befejeződik. A végrehajtás a loop utasítás törzsének elején folytatódik feltétel nélkül, ha a when kulcsszó nincs jelen, vagy a when kulcsszóval megadott feltétel teljesítése után.
A next utasítás egy if utasítás helyett használható egy utasítássorozat feltételes végrehajtására. A következő példa egy for loop utasítást mutat be, amely egy vektor '1'-es bitjeinek számlálását végzi el egy next utasítás felhasználásával.
for i in v'range loop
next when v(i) = '0';
n := n + 1;
end loop;
Exit utasítás
Az exit utasítás egy loop utasítás végrehajtásának teljes leállítását eredményezi. Általában a végrehajtás leállítása egy feltételtől függ, amit a when kulcsszóval lehet megadni.
A következő példa egy for loop utasítást mutat be, amely egy vektor elején található '0'-ás bitek számlálását végzi el egy exit utasítás felhasználásával.
for i in v'reverse_range loop
exit when v(i) = '1';
n := n + 1;
end loop;
Az előbbi leírás szintézise után a 8. ábrában látható áramkör jön létre. Az exit utasítást az OR kapukkal választjuk meg, amelyek a multiplexerek azon bemeneteit választják ki, amelyek nem tartalmazzák az inkrementáló áramkört, abban az esetben, ha az exit utasítás feltétele teljesül.
8. ábra. Egy exit utasítást tartalmazó for loop utasításnak megfelelő áramkör
Irodalomjegyzék
Mazor S, Langstraat, P: A Guide for VHDL, Kluwer Academic Publishers, 1993.
Perry, D. L.: VHDL, McGraw-Hill, 1991.
Rushton, A.: VHDL for Logic Synthesis, McGraw-Hill Europe, 1995.
Skahill, K.: VHDL for Programmable Logic, Addison-Wesley Publishing Co., 1996.
ActiveHDL dokumentáció, Aldec Inc.
FPGA Express dokumentáció, Synopsys Inc.
Baruch, Z. F.: Structura sistemelor de calcul cu aplicaţii, Todesco, Cluj, 2001.
Találat: 2545