V H D L H. Honkanen Very high speed integrated circuits Hardware Description Language Allaolevassa kuvassa on esitetty FGPA tai ASIC piirin suunnittelun vuokaavio. Kuva: FPGA piirin suunnittelu Tästä kokonaisuudesta suunnittelukielen ( VHDL ) osuus on piirisuunnittelu ( Design entry ). Simuloinnit ja synteesi ovat kääntäjäohjelmiston tehtäviä. VHDL kielellä kuvataan digitaalitaalipiirin toiminta. Kuvaus voidaan tehdä joko rakennekuvauksena ( structual description ) tai käyttäytymiskuvauksena ( behavioral description ). VHDL kielessä ei kuvata pinninumeroita ( kuten esim AbelHDL:ssa ), vaan pinnikytkennät määritellään kääntäjässä
VHDL kielen ominaisuuksia: Standardisoitu kieli, IEEE 1076-1987, IEEE 1076-1993, IEEE 1076-2002 Laajasti tuettu, ( lähes ) kaikista kääntäjistä löytyy VHDL tuki Laaja, VHDL:llä voidaan kuvata kaikki digitaalipiirit, PLD piireistä prosessoreihin Koodi tekstipohjainen, eli koodia voi kirjoittaa millä hyvänsä tekstieditorilla ( esim. nodepad ) Kuvaus voidaan tehdä: o Rakennekuvauksena ( structual description ) Esitetään logiikan toiminta komponentein ja/tai alemman tason sunnitteluyksiköin Vastaa kuvausta piirikaavio- tai lohkokaaviotasolla o Käyttäytymiskuvauksena ( behavioral description ) Esitetään piirin toiminta Vastaa kuvausta totuustaulun tai tilakaavion avulla EI priorisointia, laskentajärjestys määriteltävä sulkulausekkein! Samassa ohjelmassa ( END ) olevat operaatiot toteutuvat RINNAKKAISESTI!!! Kellotus kuvattava ehtolauseella Ei erottele pieniä ja suuria kirjaimia ( paitsi CHARACTER ) VHDL kielessä on runsaasti varattuja sanoja, tässä ohjeessa VHDL kielen sanat ovat kirjoitettu ISOLLA ja väriltään sinisiä tai punaisia OPERAATTORIT ( keskeisimmät ) : Loogiset operaattorit, Logical operators o AND, OR, NOT, NAND, NOR, XOR, XNOR o Vain NOT operaatio on korkeammalla prioriteetillä, muut prioriteetit määriteltävä sulkulausekkein! Aritmeettiset operaattorit, Arithmetic operators o + = Summa o = Erotus o * = Kertolasku o / = Jakolasku o ** = Potenssiinkorotus o MOD = Jakojäännösvarmistus o REM = Jakojäännös o ABS = Itseisarvo Vertailuoperaattorit, Relations operators o =, /=, <, >, <=, >= Ketjutusoperaattori, Concatenaus operator o &
TYYPIT ( Keskeisimmät ) BIT, Bitti o 0, 1 BIT_VECTOR, Bittijono o Esim: 000, 010101, 01101001 o Bittivektorin käsittely: Esimerkkinä 8- bittinen bittivektori: BIT_VECTOR (1 TO 8) -- Bittijono, LSB ensin BIT_VECTOR (8 DOWNTO 1) -- Bittijono, MSB ensin Ylemmällä rivillä olevassa bittijonossa ensimmäinen bitti on bitti numero yksi ja alemmalla rivillä olevassa bittijonossa bitti numero 1 on viimeinen. Bittijonon yksittäiseen bittiin voidaan viitata antamalla bittijonon nimi lisättynä osoitettavan bitin numero suluissa, esimerkki: Valimuuttuja <= bittijono(5); -- Valimuuttuja:n -- arvoksi asetetaan bittijono:n bitti numero 5 STD_LOGIC, Standardilogiikka o 0 ; 1 ; L ; H = loogiset tilat o X ; W = Ei tunnettu ( 0/1 ; L/H ) o Z = HiZ, korkeaimpedanssinen tila o - = Don t care o U = Uninitialized, Ei alustettu STD_LOGIC_VECTOR, bittijono o Samat tilavaihtoehdot, kuin STD_LOGIC:lla o Käsittely kuten bittivektorilla ( BIT_VECTOR ) BOOLEAN, Totuusarvo o FALSE ; TRUE CHARACTER, Merkki o Esim: a ; A ; 5 STRING, Merkkijono o Esim: abc123 ; tama on merkkijono INTEGER, Kokonaisluku o Esim: 0 ; 1 ; 123 ; -123 ; 65532 REAL, Reaaliluku o Esim: 0 ; 1.234 ; -2.456 ; 1.23e10 ; -4.53e-8 TIME, Aika [ Testbench ] o Esim: 45ns ; 500ps o Tuetut aikayksiköt: fs.. hr! o Aikamäärittelyt ovat vain testipenkkiä varten, eivät syntetisoidu kääntäjässä!!! o Käytetään testipenkin koodissa yleensä yhdessä WAIT FOR käskyjen kanssa
Koodin rakenne: o Tekstipohjainen ( ASCII ) Ensin esitetään käytettävät kirjastot: o Yleisesti tuetut kirjastot: LIBRARY IEEE; o Tämä kirjasto mahdollistaa matemaattiset operaatiot myös bittijonojen kesken ( ei tuettu kaikissa kääntäjissä ): USE IEEE.STD_LOGIC_UNSIGNED.ALL Sitten esitellään suunnitteluyksikkö, ENTITY Esitetään suunnitteluyksikön signaalit ja muuttujat tyyppeineen o PORT = Piiriin kytkettävät signaalit o SIGNAL = Sisäiset signaalit ( Näitä ei kytketä piirin nastoihin ) o VARIABLE = Muuttuja ( sisäinen ) o CONSTANT = Vakio ( sisäinen ) Sitten arkkitehtuuri, ARCHITECTURE o Sijoitusoperaattori: <= o Huom! OUT tyypin muuttujia EI VOI käyttää tulomuuttujina!! Huomioi sulkeet ja puolipisteet.. Useampia ehdon toteuttavia vaihtoehtoja voidaan antaa pystyviivalla: Kommentit erotetaan: -- Esimerkki VHDL kielisestä kuvauksesta, 2 tuloinen AND portti: - Esimerkissä VHDL kielen sanat suurella, kaikkiin koodeihin tuleva sinisellä ja käskyt punaisella LIBRARY IEEE; -- Alkuun aina kirjastomäärittelyt ENTITY kaksituloinen_ja IS -- Suunnitteluyksikön nimi PORT ( -- Piirin pinneihin kytkettäviä a, b: IN BIT; -- Esitellään tulobitit f: OUT BIT); -- Esitellään lähtöbitit END kaksituloinen_ja; ARCHITECTURE toiminto OF kaksituloinen_ja IS f <= a AND b; -- AND funktio, a&b=f END toiminto;
HERKKYYSLISTA Herkkyyslistalla voidaan määrittää ne muuttujat, joiden muuttuessa toiminto toteutetaan ARCHITECTURE OF IS PROCESS (... ) IS -- Sulkeiden sisään määräävät muuttujat koodi -- Tässä normaali ohjelmakoodi END PROCESS END EHTOLAUSEET VHDL kielessä on kaksi ehtolauserakennetta, IF ja CASE lauseet IF LAUSE IF lauseessa on kolme peruskäskyä: IF ( Jos ) o IF käsky voi esiintyä vain kerran ehtolausetta kohden ELSIF ( Ellei ja Jos ) ELSE ( Ellei ) Lopuksi END IF; CASE LAUSE CASE lauseessa annetaan jokainen vaihtoehto erikseen Käskyinä: CASE ; WHEN ja END CASE Ehdollinen sijoitus, WHEN Esimerkkinä nelituloisen MUX:n toiminta esitettynä IF ja CASE lausein LIBRARY IEEE; -- Alkuun aina kirjastomäärittelyt ENTITY nelituloinen_vali IS -- Suunnitteluyksikön nimi PORT ( -- Piirin pinneihin kytkettäviä val: IN BIT_VECTOR (1 DOWNTO 0); -- Kaksi ohjausbittiä D1, D1, D2, D3: IN BIT; -- Esitellään tulobitit Q: OUT BIT); -- Esitellään lähtöbitit END nelituloinen_vali; ARCHITECTURE Iffilause OF nelituloinen_vali IS PROCESS ( D0, D1, D2, D3, val ) IS IF val = "00" THEN -- Jos val 00 Q <= D0; -- niin Q saa D0 arvon
ELSIF val = "01" THEN -- Jos val 01 Q <= D1; -- niin Q saa D1 arvon ELSIF val = "10" THEN -- Jos val 10 Q <= D2; -- niin Q saa D2 arvon ELSE -- Ellei mikään em. toteudu, niin Q <= D3; -- niin Q saa D3 arvon END IF; -- Lopetetaan IF -lause END Iffilause; ARCHITECTURE Caselause OF 4tuloinen_valitsin IS PROCESS ( D0, D1, D2, D3, val ) IS CASE val IS -- Ohjaava muuttuja on val WHEN 00 => -- Kun val on 00, niin Q <= D0; -- niin Q saa D0 arvon WHEN 01 => -- Kun val on 01, niin Q <= D1; -- niin Q saa D1 arvon WHEN 10 => -- Kun val on 10, niin Q <= D2; -- niin Q saa D2 arvon WHEN 11 => -- Kun val on 11, niin Q <= D3; -- niin Q saa D3 arvon END CASE; -- Lopetetaan IF lause END Caselause; Saman valitsimen voi toteuttaa myös ehdollisen sijoituksen avulla Esittelyosio [ ENTITY END ] sama kuin aiemmissakin ARCHITECTURE Iffilause OF 4tuloinen_valitsin IS PROCESS ( D0, D1, D2, D3, val ) IS Q <= D0 WHEN val = 00 ELSE -- Jos val= 00,niin Q=D0, ellei D1 WHEN val = 01 ELSE -- Jos val= 01,niin Q=D1, ellei D2 WHEN val = 10 ELSE -- Jos val= 10,niin Q=D2, ellei D3 ; -- Muutoin D3 END Iffilause;
DYNAAMINEN TULO ( KELLON OHJAAMA TULO ) Kello-ohjatulle tulolle ei ole VHDL:ssa mitään erikoiskäskyä, vaan se toteutetaan ehtolauseen avulla, esimerkki nousevalla reunalla aktiivisesta kellosignaalista: IF kello EVENT AND kello = 1 THEN -- Jos kello:n reuna muuttunut ja kello 1,niin Huom! Kellon IF lauseeseen EI SAA liittää mitään kellotukseen liittymättömiä ehtoja! [ Käytännössä vain kellon enablointi voidaan liittää kellotuksen IF -lauseeseen ] Esimerkkejä herkkyyslistan ja kellotuksen käytöstä: Nousevalla reunalla aktiivinen D kiikku: LIBRARY IEEE; ENTITY D_kiikku IS -- Suunnitteluyksikön nimi PORT ( -- Piirin pinneihin kytkettäviä Kello, D: IN BIT; -- Esitellään tulobitit Q: OUT BIT); -- Esitellään lähtöbitit END D_kiikku; ARCHITECTURE behavior OF D_kiikku IS PROCESS ( Kello ) IS -- Tehdään, kun kello muuttuu IF kello EVENT AND kello = 1 THEN -- Jos kello:n reuna -- muuttunut ja kello 1,niin Q <= D ; -- Sijoitetaan Q:n arvoksi D:n arvo END IF; END behavior; -- Päätetään arkkitehtuuri Asykronisella nollauksella ( 0-aktiivinen ) varustettu T-kiikku: Koska OUT tyyppistä muuttujaa EI VOI käyttää tulomuuttujana, täytyy Q:lle luoda apumuuttuja funktiokäsittelyn mahdollistamiseksi LIBRARY IEEE; -- Alkuun aina kirjastomäärittelyt ENTITY T_kiikku IS -- Suunnitteluyksikön nimi PORT ( -- Piirin pinneihin kytkettäviä Kello, T, Nollaus: IN BIT; -- Tulobitit Q: OUT BIT); -- Lähtöbitit END T_kiikku;
ARCHITECTURE behavior OF T_kiikku IS SIGNAL apumuuttuja:bit; -- määritellään apumuuttuja -- Koodi alkaa PROCESS ( Kello, Nollaus ) IS -- Tehdään, kun kello -- tai nollaus muuttuu -- Alikoodi alkaa IF Nollaus = 0 THEN -- Jos nollaus on aktiivinen apumuuttuja <= 0 ; -- apumuuuttuja saa arvon 0 ELSIF kello EVENT AND kello = 0 THEN -- Ellei ja jos kellolla on laskeva reuna, niin IF T = 1 THEN -- Jos T on 1, niin apumuuttuja <= NOT apumuuttuja; -- Invertoidaan apumuut END IF; END IF; Q <= apumuuttuja; -- Nyt Q:n arvoksi sijoitetaan -- apumuuttujan arvo END behavior; -- Päätetään arkkitehtuuri JK kiikku: LIBRARY IEEE; ENTITY JK_kiikku IS -- Suunnitteluyksikön nimi PORT ( -- Piirin pinneihin kytkettäviä JK: IN BIT_VECTOR ( 1 DOWNTO 0 ); -- JK tulo bittiryhmänä Kello, Nollaus: IN BIT; -- Tulobitit Q: OUT BIT); -- Lähtöbitit END JK_kiikku; ARCHITECTURE behavior OF JK_kiikku IS SIGNAL apumuuttuja:bit; -- määritellään apumuuttuja -- Koodi alkaa PROCESS ( Kello, Nollaus ) IS -- Tehdään, kun kello -- tai nollaus muuttuu -- Alikoodi alkaa IF Nollaus = 0 THEN -- Jos nollaus on aktiivinen apumuuttuja <= 0 ; -- apumuuuttuja saa arvon 0 ELSIF kello EVENT AND kello = 1 THEN -- Jos kellolla on nouseva reuna, niin CASE JK IS -- Case käsky bittiryhmän JK mukaan WHEN 00 => NULL ; -- Jos JK 00, niin mitään ei tehdä WHEN 01 => apumuuttuja <= 0 ; -- Jos JK 01, niin -- apumuuttuja saa arvon 0 WHEN 10 => apumuuttuja <= 1 ; -- Jos JK 10, niin
-- apumuuttuja saa arvon 1 WHEN 11 => apumuuttuja <= NOT apumuuttuja; -- Jos JK 11, niin invertoidaan apumuuttuja END CASE; -- Lopetetaan Case -lause END IF; Q <= apumuuttuja; -- Nyt Q:n arvoksi sijoitetaan -- apumuuttujan arvo END behavior; -- Päätetään arkkitehtuuri LASKURI esimerkki laskurista ENTITY laskuri IS PORT( kello, nollaus: IN BIT; -- tulot lahto: OUT INTEGER RANGE 0 TO 15); -- lähtö 0.. 15 END laskuri; ARCHITECTURE behavior OF laskuri IS SIGNAL apu: INTEGER RANGE 0 TO 15; -- apumuuttuja PROCESS ( kello, nollaus ) IS -- jos kello tai nollaus -- muuttuu, niin IF nollaus = '0' THEN -- jos nollaus aktiivinen apu <= 0; -- niin nollataan ELSIF kello'event AND kello='1' THEN -- jos kello apu <= apu+1; -- lisätään laskurin arvoa END IF; lahto <= apu; -- sijoitetaan apumuuttujan arvo lähtöön END behavior; MUUNNOKSET ERI TYYPPIEN KESKEN BITIN OSOITTAMINEN BITTIRYHMÄSTÄ Bitti tai bittejä bittiryhmästä ( BIT_VECTOR tai STD_LOGIC_VECTOR ) voidaan osoittaa asettamalla ko. bitin tai bittiryhmän bitin tai bittien järjestysnumero sulkeisiin. Esimerkkejä: -- Annetaan Q:n arvoksi bittijono nimisen bittijonon toiseksi vähiten merkitsevä bitti: Q <= bittijono( 1 ); -- Huom! Bitti 0 on LSB -- Annetaan JK kiikun tuloksi bittijono nimisen bittijonotavun kaksi keskimmäistä bittiä: JK <= bittijono( 4 DOWNTO 3 ); VHDL kielessä tyyppimuunnos voidaan toteuttaa CONV käskyllä, onnistuu tiedostotyypistä STD_LOGIC_VECTOR. Muuttunut tyyppi on esiteltävä
Esimerkkinä kahden kahdeksanbittisen luvun summain: Bittivektorina: LIBRARY IEEE; -- Alkuun aina kirjastomäärittelyt USE IEEE.STD_LOGIC_UNSIGNED.ALL; -- mahdollistaa matemaattiset -- operaatiot bittijonojen välillä ENTITY summain IS -- Suunnitteluyksikön nimi PORT ( -- Piirin pinneihin kytkettäviä Tulo1, Tulo2 : IN STD_LOGIC_VECTOR ( 7 DOWNTO 0 );-- Tulot, MSB ensin Kello : STD_LOGIC ; Summa : OUT STD_LOGIC_VECTOR ( 7 DOWNTO 0 )); -- Lähtötavu, MSB ensin END summain; ARCHITECTURE summmain OF summain IS -- Esittelyt PROCESS ( Kello ) -- Jos kello muuttuu IF kello'event AND kello = '1' THEN -- jos kellolla nouseva reuna summa <= Tulo1 + Tulo2 ; -- Summaus END IF; -- Päätetään IF -lause -- Päätetään herkkyyyslistan lause END summmain; Kokonaislukuna: LIBRARY IEEE; -- Alkuun aina kirjastomäärittelyt ENTITY summain IS -- Suunnitteluyksikön nimi PORT ( -- Piirin pinneihin kytkettäviä Tulo1, Tulo2 : IN INTEGER RANGE 0 to 255 ; -- Tulot Kello : STD_LOGIC ; Summa : OUT INTEGER RANGE 0 to 511 ); -- Lähtö END summain; ARCHITECTURE summmain OF summain IS -- Esittelyt PROCESS ( Kello ) -- Jos kello muuttuu IF kello'event AND kello = '1' THEN -- jos kellolla nouseva reuna summa <= Tulo1 + Tulo2 ; -- Summaus kokonaisluvuilla END IF; -- Päätetään IF -lause -- Päätetään herkkyyyslistan lause END summmain;
Kertolasku: LIBRARY IEEE; -- Alkuun aina kirjastomäärittelyt USE IEEE.STD_LOGIC_UNSIGNED.ALL; -- mahdollistaa matemaattiset -- operaatiot bittijonojen välillä ENTITY kertoja IS -- Suunnitteluyksikön nimi PORT ( -- Piirin pinneihin kytkettäviä Luku1, Luku2 : IN STD_LOGIC_VECTOR ( 3 DOWNTO 0 );-- Tulot, MSB ensin Kello : STD_LOGIC ; Tulo : OUT STD_LOGIC_VECTOR ( 7 DOWNTO 0 )); -- Lähtötavu, MSB ensin END kertoja; ARCHITECTURE kertoja OF kertoja IS -- Esittelyt PROCESS ( Kello ) -- Jos kello muuttuu IF kello'event AND kello = '1' THEN -- jos kellolla nouseva reuna Tulo <= Luku1 * Luku2 ; -- Tulo END IF; -- Päätetään IF -lause -- Päätetään herkkyyyslistan lause END kertoja;
KOMPONENTTI ja KOMPONENTIN KÄYTTÖ Mutkikkaampien komponenttien, kuten kiikkujen ja siirtorekistereiden kuvaaminen useamman kerran samassa prosessissa ei ole tarpeen, vaan kuvaus voidaan määrittää komponentiksi, jolloin sitä voidaan käyttää kuten komponenttia, määritellään tuloihin tulevat ja lähdöistä lähtevät komponentit. Komponentiksi voidaan määrittää myös toiminnallisia lohkoja, jolloin kuvaus siirtyykin lohkokaaviotasolle Rakenne: -- Esitellään kytkennän tulot ja lähdöt ENTITY vimpain IS -- Suunnitteluyksikön nimi PORT ( -- Piirin pinneihin kytkettäviä?,?: IN BIT; -- Esitellään tulobitit?,?: OUT BIT); -- Esitellään lähtöbitit END vimpain; ARCHITECTURE struktuuri OF vimpain IS -- Esitellään käytettävät komponentit COMPONENT komponentin_nimi PORT (?,? : IN BIT;? : OUT BIT); END COMPONENT; -- Muutkin komponentit samaan tyyliin -- Seuraavaksi esitellään sisäiset signaalit SIGNAL?,? : BIT; -- Sitten itse asiaan, eli määritellään kytkennät u1: komponentin_nimi PORT MAP(? =>?,? =>? ); jne -- Esitetään kytkennät signaalinimien avulla -- Kaikkien komponenttien kytkennät samalla tavalla END struktuuri;
Esimerkkinä seuraavanlainen tilakone:
-- Ensiksi esitetään käytettävät kirjastot LIBRARY IEEE; -- Sitten esitellään komponentit ENTITY kaksituloinen_tai IS -- Suunnitteluyksikön nimi PORT ( -- Piirin pinneihin kytkettäviä a, b: IN BIT; -- Esitellään tulobitit f: OUT BIT); -- Esitellään lähtöbitit END kaksituloinen_tai; ARCHITECTURE toiminto OF kaksituloinen_tai IS f <= a OR b; -- AND funktio, a+b=f END toiminto; ENTITY Invertteri IS -- Suunnitteluyksikön nimi PORT ( -- Piirin pinneihin kytkettäviä a: IN BIT; -- Esitellään tulobitit f: OUT BIT); -- Esitellään lähtöbitit END Invertteri; ARCHITECTURE toiminto OF Invertteri IS f <= NOT a; END toiminto; ENTITY JK_kiikku IS -- Suunnitteluyksikön nimi PORT ( -- Piirin pinneihin kytkettäviä JK: IN BIT_VECTOR ( 1 DOWNTO 0 ); -- JK tulo bittiryhmänä Kello: IN BIT; -- Tulobitit Q: OUT BIT); -- Lähtöbitit END JK_kiikku; ARCHITECTURE behavior OF JK_kiikku IS SIGNAL apumuuttuja:bit; -- määritellään apumuuttuja -- Koodi alkaa PROCESS ( Kello ) IS -- Tehdään, kun kello muuttuu -- Alikoodi alkaa IF kello EVENT AND kello = 1 THEN -- Jos kellolla on nouseva reuna, niin CASE JK IS -- Case käsky bittiryhmän JK mukaan WHEN 00 => NULL ; -- Jos JK 00, niin mitään ei tehdä WHEN 01 => apumuuttuja <= 0 ; -- Jos JK 01, niin -- apumuuttuja saa arvon 0 WHEN 10 => apumuuttuja <= 1 ; -- Jos JK 10, niin -- apumuuttuja saa arvon 1 WHEN 11 => apumuuttuja <= NOT apumuuttuja; -- Jos JK 11, niin invertoidaan apumuuttuja END CASE; -- Lopetetaan Case -lause END IF; Q <= apumuuttuja; -- Nyt Q:n arvoksi sijoitetaan -- apumuuttujan arvo END behavior; -- Päätetään arkkitehtuuri
-- Tilakoneen kytkentä esitetään ENTITY Tilakone IS -- Suunnitteluyksikön nimi PORT ( -- Piirin pinneihin kytkettäviä Y, clk : IN BIT; -- Esitellään tulobitit M, N: OUT BIT); -- Esitellään lähtöbitit END Tilakone; -- sitten kytkennät ARCHITECTURE struktuuri OF tilakone IS -- Esitellään käytettävät komponentit COMPONENT Kaksituloinen_tai PORT (a, b : IN BIT; f : OUT BIT); END COMPONENT; COMPONENT Invertteri PORT (a : IN BIT; f : OUT BIT); END COMPONENT; COMPONENT JK_kiikku PORT (JK : IN BIT_VECTOR; kello: IN BIT; Q : OUT BIT); END COMPONENT; -- Seuraavaksi esitellään sisäiset signaalit SIGNAL apu1, apu2, apu3 : BIT; -- Sitten itse asiaan, eli määritellään kytkennät u1: Invertteri PORT MAP( a => Y, f => apu1 ); u2: kaksituloinen_tai PORT MAP ( a => apu1, b => apu3, f => apu2 ); u3: JK_kiikku PORT MAP ( JK(1) => apu2, JK(0) => apu2, Q => M, kello => clk ); u4: JK_kiikku PORT MAP ( JK(1) => Y, JK(0) => Y, Q => apu3, kello => clk ); N <= apu3; END struktuuri;