1. Vmesnik, arhitektura in signali

Osnovni elementi opisa vezja so signali. V vmesniku (entity) 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.

Zgradba modela vezja

library IEEE;    -- knjižnice in paketi
use IEEE.std_logic_1164.all;

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;

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 ...

Signale, ki predstavljajo enostavne povezave, deklariramo s podatkovnim tipom bit ali std_logic. Signali tipa bit lahko zavzamejo le vrednost logične ničle ali enice, ki jih v jeziku VHDL pišemo med enojnimi narekovaji: '0' in '1'.

Za simulacijo je bolj primeren podatkovni tip std_logic, ker omogoča prikaz več različnih stanj, v karetem se signalna povezava nahaja:

Ta podatkovni tip ni vnaprej definiran, zato moramo pri njegovi uporabi v opis vezja vključiti knjižnico IEEE in paket IEEE.std_logic_1164. Paket vsebuje definicijo podatkovnega tipa std_logic in vseh logičnih operacij (z vsemi možnimi vrednostmi).

1.1 Večbitni signali

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. Npr. 8-bitni vektor deklariramo kot: (7 downto 0), tako da ima najnižji bit indeks 0. Vrednosti vektorskih signalov pišemo med dvojnimi narekovaji:

Vektorji

   signal a: std_logic_vector (7 downto 0);

Prireditev vektorju:  a <= "01011001";
Prireditev elementu:  a(7) = '0';
Primer podvektorja:  a(3 downto 0)
Sestavljanje vektorja:  a <= b & c;
Vrednosti večbitnih signalov si največkrat prestavljamo kot cela števila v dvojiškem zapisu. Cela števila deklariramo v jeziku VHDL s signali podatkovnega tipa integer, ki predstavlja vrednosti v 32 bitnem zapisu. Takšen zapis je lahko precej potraten pri sintezi vezja, zato pri deklaraciji celih števil omejimo območje vrednosti ali pa raje uporabimo vektorske signale.

Jezik VHDL omogoča deklaracijo lastnih podatkovnih tipov. Najpogosteje deklariramo naštevni podatkovni tip, pri katerem določimo simbolična imena za vrednosti signalov. V visokonivojskem opisu (npr. opisu avtomatov) operiramo s simboličnimi imeni, ki se šele pri sintezi vezja pretvorijo v konkretne večbitne vrednosti.

Naštevni tip podatkov

Deklaracija:
type ime_tipa is (ime1, ime2, ime3...);
signal ime_signala: ime_tipa;

Prireditveni stavek:

ime_signala <= ime1;

2. Sočasni prireditveni stavki

V arhitekturnem delu s stavki jezika VHDL opišemo kaj se dogaja s signali. Stavki predstavljajo gradnike v vezju, ki jih mora simulator izvajati hkrati, zato jih imenujemo sočasni stavki. Najbolj osnovni so prireditveni stavki, s katerimi signalu priredimo vrednost ali izraz.

Logični izrazi

Logični izraz zapišemo v jeziku VHDL z logičnimi operatorji: and, or, not, nand, nor, xor, xnor. Z uporabo logičnih izrazov opišemo vezja na nivoju logičnih vrat.

izhod <= (vhod0 and (not izbira)) or (vhod1 and izbira);

Aritmetični izrazi

Z vektorskimi signali lahko pišemo aritmetične izraze v katerih nastopajo operatorji seštevanja, odštevanja in množenja. Ti operatorji so definirani v knjižnici za delo z nepreznačenimi vrednostmi: IEEE.std_logic_unsigned ali s predznačenimi vrednostmi: IEEE.std_logic_signed.

sum <= a + b;

2.1 Pogojni prireditveni stavek

S pogojnim prireditvenim stavkom izbiramo več konstantami ali izrazi, ki se priredijo ob določenem pogoju. Pogoje zapišemo z relacijskimi (primerjalnimi) operatorji. Operatorja enako in ni enako sta definirana za vse tipe podatkov, ostali pa za skalarne in vektorske tipe.

Pogojni prireditveni stavek

signal <= izraz1 when pogoj1 else izraz2;

signal <= izraz1 when pogoj1 else
          izraz2 when pogoj2 else
          izraz3;

Relacijski operatorji

=/=>>=<<=
enakoni enakovečjevečje ali enakomanjšemanjše ali enako

2.2 Izbirni stavek

Izbirni stavek nam omogoča, da izhodnemu signalu priredimo različne vrednosti ali izraze v odvisnosti od kombinacije na izbirnem signalu. Izbirni stavek najpogosteje uporabljamo za opis kombinacijskih dekodirnikov.

Izbirni stavek

with izbirni_signal select
  signal <= izraz1 when kombinacija1,
            izraz2 when kombinacija2,
            ...
            izrazn when others;

3. Sekvenčni stavki

S sekvenčnimi stavki opišemo vezje na nivoju obnašanja, kar pomeni da opisujemo delovanje vezja in ne neposredno zgradbo vezja. Sekvenčne stavke pišemo v jeziku VHDL znotraj določenega okolja (npr. procesa ali procedure...). Opis procesa se začne z oznako, sledi ji rezervirana beseda process in v oklepaju seznam vhodnih signalov. Simulator izvede stavke v procesnem okolju vsakokrat, ko se spremeni vrednost kateregakoli signala iz seznama signalov, na katere je občutljiv.

Procesni stavek

OZNAKA: process (seznam)
begin
    sekvenčni stavki;
end process;

seznam: vhodni signali, na katere je proces občutljiv

Kadar opisujemo kombinacijsko logiko moramo v seznam signalov napisati vse signale, ki se pojavljajo na desni strani prireditev ali v pogojih. Ob spremembi kateregakoli izmed teh signalov se mora izvesti nova simulacija procesa

Pri opisu sekvenčnih vezij pa zapišemo v seznam le uro in morebitne asinhrone vhode (npr. asinhroni reset)

3.1 Pogojni stavek

Znotraj procesa lahko opisujemo obnašanje kombinacijskih vezij s pogojnimi (if) stavki in prireditvenimi stavki. V pogojnem stavku za besedo then zapišemo stavke, ki se izvršijo, ko je pogoj izpolnjen, za else pa stavke, ki se izvršijo ob neizpolnjenem pogoju. Pogojni stavek zaključimo z end if.

Pogojni stavek

if pogoj then
  sekvenčni stavki;
else
  sekvenčni stavki;
end if;
  if pogoj1 then
    sekvenčni stavki;
  elsif pogoj2 then
    sekvenčni stavki;
    ...
  else
    sekvenčni stavki;
  end if;

Kadar imamo več zaporednih (povezanih) pogojev, jih zapišemo z if...elsif...else obliko pogojnega stavka. V takšnam stavku imajo pogoji, ki so zapisani prej, prednost pred tistimi, ki so zapisani kasneje.

Stavek else lahko tudi izpustimo, vendar moramo v primeru opisa kombinacijskih vezij poskrbeti, da bodo izhodi definirani pri vseh kombinacijah na vhodih. V praksi to naredimo tako, da signalu priredimo privzeto vrednost pred if stavkom.

3.2 Sekvenčni izbirni stavek

Sekvečni izbirni stavek uporabljamo znotraj procesa za izbiro stavkov, ki se izvršijo glede na vrednost izbirnega signala. Izbirni signal navedemo za rezervirano besedo case, vrednosti pa naštevamo v vrsticah when. Če signal ne zavzame nobene izmed naštetih vrednosti, se izvedejo stavki, ki so zapisani za vrstico when others.

Stavek case

case signal is
  when vrednost1 =>
     stavki;
  when vrednost2 =>
     stavki;
  when vrednost3 =>
     stavki;
  when others =>
     stavki;
end case;

3.3 Sinhrona sekvenčna vezja

Sinhrona sekvenčna vezja spreminjajo izhode le ob fronti ure. Takšna vezja opišemo s pogojnim stavkom v katerem detektiramo naraščajočo (rising) ali padajočo (falling) fronto ure. Vsi ostali stavki v procesu morajo biti zapisani znotraj tega pogoja. Takšen proces imnujemo sinhroni sekvečni proces:

Sinhroni proces I

oznaka: process (clk)
begin
  if rising_edge(clk) then
    sekvenčni stavki;
  end if;
end process;

Sinhroni proces II

oznaka: process (clk, reset)
begin
  if reset='1' then
    priredi začetno vrednost;
  elsif rising_edge(clk) then
    sekvenčni stavki;
  end if;
end process;

4. Komponente

Kompleksnejša vezja načrtujemo s povezovanjem posameznih gradnikov, ki predstavljajo ločene VHDL opise vezij. Posamezni gradniki se v jeziku VHDL imenujejo komponente. Pri strukturnem načrtovanju vezij se osredotočimo na povezovanje komponent, ne pa na njihovo obnašanje, ki je opisano v ločenih VHDL datotekah.

Komponente

Deklaracija:
  component ime_komponente
    port (ime: smer tip_signala... );
  end component;

Povezovanje komponet:
  oznaka: ime_komponente port map (
    ime1 => IME1,
    ime2 => IME2 ... );

ime1, ime2: signali v komponenti
IME1, IME2: signali v vezju

Deklaracijo komponente naredimo na vrhu arhitekturnega stavka (pred begin), povezavo komponente pa določimo znotraj arhitekture. Vsaki komponenti pri povezovanju določimo unikatno oznako.



LNIV