Gradivo na naslednjih straneh predstavlja najbolj osnovne koncepte jezika VHDL. Sintaksa jezika je opisana na primerih tipičnih digitalnih vezij, od preprostih vezij (izbiralniki, primerjalniki, flip-flopi) do kompleksnejših vezij kot so sekvenčni avtomati in osnov strukturnega načrtovanja. Primeri vezij so povzeti iz učbenika za laboratorijske vaje pri predmetih Integrirana vezja, Digitalni elektronski sistemi in izbirnem modulu B: IV / NDES.

Ob nekaterih primerih so ikone, ki ob kliku ponudijo okno z dodatno razlago sintakse, posebnosti simulacije in pravil kodiranja v jeziku VHDL za sintezo vezja :

Več informacij in razlage najdete v učbeniku:

2.1 Vmesnik, arhitektura in signali

Model digitalnega vezja ali sistema v jeziku VHDL je sestavljen iz dveh glavnih delov:

  1. v vmesniku (entity) so opisani zunanji signali
  2. v zgradbi (architecture) pa je opisano delovanje vezja.

Zgradba modela vezja

entity ime_vezja is    -- vmesnik
    port (...);     -- deklaracija zunanjih signalov
end ime_vezja;

architecture opis_vezja of ime_vezja is
  signal ime: tip_signala;    -- notranji signali
  ...
begin
  stavki ...
end opis_vezja;

Stavki v jeziku VHDL

Jeziki za visokonivojski opis digitalnih vezij so zelo podobni programskim jezikom, vendar je med njimi nekaj bistvenih razlik. Razliko najbolje opazimo, če primerjamo izvajanje računalniškega programa z izvajanjem simulacije vezja:

  • V programskem jeziku pomenijo posamezni stavki ukaze, ki jih računalnik izvršuje po določenem vrstnem redu.
  • V jeziku VHDL predstavljajo posamezni stavki dele digitalnega vezja, ki jih moramo pri simulaciji obravnavati hkrati. Takšne stavke imenujemo sočasni stavki in njihov vrstni red pri opisu vezja ni pomemben.
  c <= a + b;
  e <= c + d;

Vrstni red prireditvenih stavkov v nekem programskem jeziku je v splošnem pomemben. Če bi zamenjali vrstni red zgornjih stavkov, bi bil rezultat izvajanja programa povsem drugačen. V jeziku VHDL pa ni tako - zgornja stavka predstavljata dva seštevalnika, ki sta med seboj povezana s signalom c. Vrstni red zapisa stavkov je pri opisu vezja povsem nepomemben.

  c <= a + b;
  c <= c + 1;

Pri tem zapisu smo naredili v jeziku VHDL kar dve napaki. Prvič smo vezali dva seštevalnika na isti izhod (c) in s tem naredili kratek stik. Druga napaka pa je uporaba istega signala na levi in na desni strani prireditvenega stavka, kar pomeni povratno vezavo v kombinacijskem vezju. Povratno zanko lahko (uspešno) naredimo samo, če se prireditveni stavek izvrši ob fronti urinega signala, kakor bomo videli pri opisu sekvenčnih vezij.

Jezik VHDL nam omogoča različne načine opisa digitalnih vezij: z visokonivojskimi stavki (npr. if stavek) opisujemo obnašanje vezja (angl. behavioral description) ali pa povezujemo v naprej pripravljene strukture, podobno kot pri risanju sheme vezja (angl. structural description). VHDL je bil prvotno namenjen za modeliranje in simulacijo digitalnih vezij, zato vsebuje tudi ukaze in strukture, ki jih ne moremo sintetizirati. Primer takšnih struktur so časovne zakasnitve, ki omogočajo zelo natančno simulacijo, ne moremo pa sintetizirati vezja s poljubnimi časovnimi zakasnitvami. Primer ukazov, ki niso smiselni pri sintezi vezij, pa so ukazi za delo z datotekami, izpis na zaslon itd.

Kako deluje VHDL simulator?

Simulacija vezja v jeziku VHDL mora upoštevati sočasno izvajanje stavkov, ki predstavljajo gradnike vezja. Simulator deluje tako, da najprej izračuna vrednosti vseh prireditvenih stavkov, potem pa hkrati spremeni vse signale. Vsakokrat ko pride do spremembe vrednosti na vsaj enem signalu, se simulacijski cikel ponovi.

Primer: imamo dva prireditvena stavka


a1 <= a;
a2 <= a1;
Signali T0 T0+D T0+2D
a 1 1 1
a1 0 1 1
a2 0 0 1

Signal a je v trenutku T0 spremenil vrednost iz 0 na 1. Simulator v prvem ciklu izračuna novi vrednosti signalov a1 in a2 ter izvede prireditev ob koncu cikla (T0+D). Signal a2 se v tem trenutku še ni spremenil, ker je za njegovo spremembo potrebna nova vrednost signala a1, ta pa se je dodelila šele ob koncu cikla. Simulator nato izvrši še en cikel in izračuna končno vrednost signalov a1 in a2. Hitro se lahko prepričamo, da bi bil rezultat simulacije popolnoma enak, če bi zamenjali vrstni red obeh stavkov.

Simulator mora za vsak signal voditi tekočo vrednost in izračunano vrednost, ki bo dodeljena signalu ob koncu cikla. Če imamo v opisu vezja zakasnitve, mora simulator voditi tudi informacijo o času ob katerem se bo neka prireditev izvršila. Za vsak signal imamo tako lahko cel seznam vrednosti in časovnih trenutkov, ob katerih morajo biti vrednosti dodeljene.

Primer:
senzor <= '0', '1' after 320 ns, '0' after 540 ns, '1' after 1010 ns, '0' after 1230 ns;

Simulator naredi ob izvršitvi stavka seznam vrednosti in časovnih trenutkov ob katerem bodo vrednosti dodeljene signalu senzor. Pri napredovanju simulacije se potem v ustreznih časovnih trenutkih spreminja vrednost signala. Takšen zapis uporabljamo v testnih okoljih (Test Bench), kjer določamo časovno spreminjanje vhodov vezja, ki ga testiramo.

Osnovni elementi opisa vezja so signali. V vmesniku določimo ime vezja in naredimo deklaracijo zunanjih signalov (stavek port). Znotraj arhitekturnega dela deklariramo notranje signale in zapišemo stavke, ki določajo kaj se dogaja s signali vezja. Zunanjim signalom moramo določiti smer in podatkovni tip:

Opis zunanjih signalov

port ( ime: smer  tip_signala;
         ime1, ime2: smer  tip_signala;
         ...
        );

smer:   in  vhodni signal
           out izhodni signal
           buffer  izhodni in notranji signal
           inout dvosmerni signal

tip_signala:  bit, bit_vector, std_logic ...

  • Vhodni signali se uporabljajo za branje vrednosti (na desni prireditvenih stavkov ali v pogojih), ne moremo pa jim določati vrednosti,
  • izhodnim signalom določamo vrednosti v prireditvenih stavkih, ne moremo pa jih brati,
  • signali tipa buffer so izhodi, ki jim določamo vrednost in jih lahko tudi beremo (so na obeh straneh prireditvenih stavkov),
  • dvosmerne signale potrebujemo za opis posebnih zunanjih vodil, ki so obenem vhodi in izhodi.

Podatkovni tip

Osnovna podatkovna tipa, ki predstavljata signale (povezave) v vezju sta bit in std_logic. Signali tipa bit lahko zavzamejo le vrednost logične ničle ali enice. Za simulacijo je bolj primeren podatkovni tip std_logic, ker vsebuje tudi nedefinirano stanje 'U', kratek stik 'X', stanje visoke impedance 'Z' itd. Ta podatkovni tip ni vnaprej definiran, zato moramo pri njegovi uporabi v opis vezja vključiti knjižnico IEEE.std_logic_1164. Knjižnica vsebuje definicijo podatkovnega tipa std_logic in vseh logičnih operacij (z vsemi možnimi vrednostmi).

Več signalov združujemo v vodila, za katere uporabljamo v jeziku VHDL vektorske podatkovne tipe: bit_vector in std_logic_vector. Velikost vektorjev določimo pri deklaraciji kjer navedemo indeksa spodnje in zgornje meje. Najnižji bit ima običajno indeks 0 in se nahaja na desni strani, zato npr. 8-bitni vektor deklariramo kot: (7 downto 0).

Vrednost vektorja je dvojiško število, ki ga lahko interpretiramo kot celo število s predznakom ali brez predznaka. Za nedvoumno interpretacijo vrednosti uporabimo vektorski tip signed ali unsigned iz numerične knjižnice IEEE.numeric_std. Tam so definirane tudi vse osnovne aritmetične operacije s celoštevilskimi vektorji. Podatkovni tip integer predstavlja 32 bitna cela števila in se uporablja pri računskih operacijah, v primerjalnih izrazih in za indeksiranje vektorjev.

Vektorji

Deklaracija:  a: std_logic_vector (7 downto 0)
Prirejanje vrednosti:  a <= "01011001"
Posamezni element vektorja:  a(7) = '0'
Podvektor:  a(3 downto 0) = "1001"

Jezik VHDL zahteva, da zapišemo pretvorbo podatkovnih tipov v vseh izrazih, kjer se pojavljajo signali različnih tipov. Izjema so izrazi z nekaterimi računskimi operatorji (seštevanje, odštevanje, množenje) in primerjalnimi operatorji, kjer je pretvorba definirana v knjižnicah. Prireditveni izrazi pa vedno zahtevajo eksplicitno pretvorbo:

signal a,b,c: std_logic_vector(7 downto 0);
signal vsota: unsigned(7 downto 0);
...
-- a in b pred seštevanjem pretvorimo v unsigned
vsota <= unsigned(a) + unsigned(b);
c <= std_logic_vector(vsota);

 Model vezja

Naredimo model vezja, ki generira učinek leteče luči. Na vhodu vezja je ura (clk) in dva kontronlna signala (ena in neg), izhod pa je 4-biten vektor (luc).

Kadar izdelujemo novo izvorno datoteko (New Source) določimo vrsto datoteke: VHDL Module. Programska oprema bo avtomatsko odprla čarovnik (wizzard), ki nam pomaga pri prvih korakih sestavljanja modela vezja. Določiti moramo ime datoteke z opisom vezja, ime vezja in arhitekture ter imena in vrsto zunanjih signalov. Program bo avtomatsko sestavil datoteko z vmesnikom in praznim arhitekturnim stavkom. V naslednjih korakih moramo le še dopolniti arhitekturni del z deklaracijami notranjih signalov in stavki, ki opisujejo delovanje vezja.

Celoten opis vezja:

library IEEE;
use IEEE.std_logic_1164.all; -- definicija std_logic_vector
use IEEE.numeric_std.all;    -- def. unsigned in seštevanja

entity LetLuc is
  Port ( clk : in STD_LOGIC;
         ena : in STD_LOGIC;
         neg : in STD_LOGIC;
         luc : out STD_LOGIC_VECTOR (3 downto 0));
end LetLuc;
zunanji signali

architecture Opis of LetLuc is
  signal st: unsigned (1 downto 0):="00";
  signal komb: std_logic_vector (3 downto 0);
begin
notranji signali

Kontr: process(clk)
begin
  if rising_edge(clk) and ena='1' then
    st <= st + 1;
  end if;
end process;
sekvenčni proces

Log: process(st)
begin
  if st="00" then
    komb <= "1000";
  elsif st="01" then
    komb <= "0100";
  elsif st="10" then
    komb <= "0010";
  else
    komb <= "0001";
  end if;
end process;
kombinacijski proces

luc <= komb when neg='0' else not komb;

end Opis;
prireditveni stavek

Osnovni stavki