Osnovni stavki

Osnovni stavki jezika VHDL opisujejo pretok in preoblikovanje podatkov katerih nosilci so signali vezja. Osnovne stavke imenujemo sočasni (angl. concurrent) stavki. Vsak sočasen stavek predstavlja del vezja z definiranim izhodnim signalom. Sočasni stavki se med simulacijo izvajajo hkrati (paralelno), vrstni red v katerem so zapisani, pa ni pomemben. Med sočasne stavke spadajo:

  1. prireditveni stavek z aritmetičnimi in logičnimi operatorji,
  2. pogojni in izbirni prireditveni stavki

2.2 Operatorji

Prireditveni stavek zapišemo tako, da nekemu signalu z operatorjem <= priredimo vrednost drugega signala, konstantno vrednost ali izraz. Podatkovni tip na levi strani se mora ujemati s podatkovnim tipom na desni strani. Pri vektorskih signalih se mora ujemati tudi smer in število bitov. Primer:

  signal x, y: std_logic;
  signal a: std_logic_vector (31 downto 0);
  signal b,c: std_logic_vector (7 downto 0);

PravilnoNapačno
x <= '0';
y <= x;
a <= "00001111000011110000111100001111";
a <= (others =>'0');
b <= "01010101";
c <= b;
x <= "0"; -- x ni vektorski signal
y <= a;   -- y ni 32 bitni vektor
a <= 0;   -- a ni celo število
a <= '0'; -- a ni enobitni signal
b <= "0"; -- število bitov se ne ujema
c <= a;   -- število bitov se ne ujema

Aritmetični izrazi

V knjižnicah so definirane osnovne aritmetične operacije +, - in * nad vektorji, ki predstavljajo predznačena ali nepredznačena števila. Najlažje delamo operacije z uporabo numerične knjižnice (IEEE.numeric_std) in signali podatkovnega tipa signed ali unsigned:

  signal a, b: unsigned (7 downto 0);
  signal sum, dif: unsigned (7 downto 0);
  signal mul: unsigned (15 downto 0);

  sum <= a + b;
  dif <= a - b;
  mul <= a * b;

Velikost vektorja vsote ali razlike je enaka velikosti operandov, če sta različna pa je enaka tistemu, ki ima večje število bitov. Če želimo dobiti prenos pri seštevanju, moramo vektorjema prej dodati najvišji bit. Za predznačene in nepredznačene vektorje je na voljo funkcija resize, ki ji podamo vektor in število bitov:

  signal a, b: unsigned (7 downto 0);
  signal sum: unsigned (8 downto 0);

  sum <= resize(a, 9) + resize(b,9);

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);

2.3 Pogojni in izbirni stavki

Vezje, ki smo ga opisali z uporabo logičnih izrazov je dvovhodni izbiralnik (multiplekser). Funkcija izbiralnika je, da prenese na izhod vrednost enega izmed signalnih vhodov. Opis kombinacijskega vezja v obliki logične funkcije je lahko zelo nepregleden, zato uporabljamo za opis vezij v jeziku VHDL visokonivojske stavke.

 Izbiralnik

Dvovhodni izbiralnik opišemo s pogojnim prireditvenim stavkom. Signal izhod dobi vrednost signala vhod0 kadar je signal izbira na logični ničli, sicer dobi izhod vrednost signala vhod1.

izhod <= vhod0 when izbira='0' else
         vhod1;

Pogojni prireditveni stavek

signal <= izraz1 when pogoj1 else izraz2;

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

Sinteza kombinacijskih vezij

Program za sintezo vezij naredi kombinacijsko logiko iz visokonivojskega zapisa kadar uporabljamo pogojni prireditveni stavek. Kombinacijsko vezje dobimo, če je izhod definiran v vseh primerih, to pomeni, da je prisoten končni else v pogojnem stavku. Če tega ni, mora program ohranjati zadnjo vrednosti izhoda, kar pa pomeni sekvenčno vezje (zapah).

Kombinacijsko vezje dobimo tudi s pogojnim stavkom, vendar le pod pogojem, da je izhodni signal definiran v vseh primerih (obvezno mora biti prisoten else). Pogojni stavek lahko uporabljamo samo znotraj procesnega okolja, pogojni prireditveni stavek pa le izven procesa.

Primer: Izbiralnik s tremi vhodi

Pogojni prireditveni stavek

izhod <= x when a=1 else
    y when a=2 else
    z;

Pogojni stavek

 P: process(a,x,y,z)
  begin
    if a=1 then
      izhod <= x;
    elsif a=2 then
      izhod <= y;
    else
      izhod <= z;
    end if;
 end process;

Celoten opis dvovhodnega izbiralnika v jeziku VHDL izgleda takole:

library IEEE;
use IEEE.std_logic_1164.all;

entity mux is
  port ( vhod0: in std_logic;
         vhod1: in std_logic;
         izbira: in std_logic;
         izhod: out std_logic );
end mux;

architecture opis of mux is
begin
  izhod <= vhod0 when izbira='0' else vhod1;
end opis;

 Primerjalnik

Primerjalnik je vezje, ki primerja dve binarni vrednosti na vhodu in ugotovi ali je prva vrednost večja, manjša ali enaka drugi vrednosti. Za primerjavo uporabljamo relacijske operatorje:

Relacijski operatorji

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

Kako deluje primerjava vektorjev?

Rezultat primerjave vektorjev je odvisen od tega kako jih obravnavamo - kot nepredznačena ali kot predznačena dvojiška števila. Jezik VHDL obravnava vektorje kot nepredznačena dvojiška števila, vendar se to spremeni, če vključimo knjižnico IEEE.std_logic_signed. V tem primeru bo VHDL obravnaval vsa števila v vezju kot predznačena števila in rezultat primerjave vektorjev je lahko popolnoma drugačen!

Primer:
Zapišimo pogojni stavek, s katerim ugotavljamo ali je štiribitno število večje od deset.

  if x > "1010" then
       ...

Vrednost "1010" predstavlja desetiško število 10, če jo obravnavamo kot nepredznačeno dvojiško število. Pogoj bo izpolnjen za števila 11 (1011), 12 (1100), 13 (1101), 14 (1110) in 15 (1111).

Če je v opis vezja vključena knjižnica IEEE.std_logic_signed pa nam "1010" predstavlja število -6. Pogoj bo v tem primeru izpolnjen za števila: -5 (1011), -4 (1100), -3 (1101), -2 (1110), -1 (1111), 0 (0000), 1 (0001), 2 (0010), 3 (0011), 4 (0100), 5 (0101), 6 (0110) in 7 (0111).

Operatorja enako in ni enako sta definirana za vse tipe podatkov, ostali pa za skalarne in vektorske tipe. Vhodna signala x in y naj bosta 8 bitna vektorja. Pri deklaraciji vektorskega signala moramo navesti tudi velikost vektorja (npr. (7 downto 0) za osembitni vektor). Vrednost posameznega izhoda določimo s pogojnim prireditvenim stavkom:

library IEEE;
use IEEE.std_logic_1164.all;

entity prim8 is
  port ( x, y: in std_logic_vector (7 downto 0);
         vecje, manjse, enako: out std_logic );
end prim8;

architecture opis of prim8 is
begin
  vecje <= '1' when x > y else '0';
  manjse <= '1' when x < y else '0';
  enako <= '1' when x = y else '0';
end opis;

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;

 Dekodirnik

Opisali bomo dekodirnik za 7-segmentni prikazovalnik. Dekodirnik ima na vhodu štiribitni vektor, ki predstavlja BCD vrednosti med 0 in 9. Vhodne vrednosti pretvori v kombinacije, ki prižigajo ustrezne segmente na prikazovalniku. Prikazovalnik krmilimo z osembitnim signalom, pri katerem je najvišji bit vezan na decimalno piko, ostali biti pa prižigajo segmente števila. Za prižiganje pike imamo v vezju dodaten enobiten vhodni signal.

entity bin2led is
  port ( vhod: in bit_vector(3 downto 0);
         pika: in bit;
         prikaz: out bit_vector(7 downto 0));
end bin2led;

architecture opis of bin2led is
begin
 with vhod select
  prikaz(6 downto 0) <= "0000110" when "0001",
                       "1011011" when "0010",
                       "1001111" when "0011",
                       "1100110" when "0100",
                       "1101101" when "0101",
                       "1111101" when "0110",
                       "0000111" when "0111",
                       "1111111" when "1000",
                       "1101111" when "1001",
                       "0111111" when others;
 prikaz(7) <= pika;
end opis;

VHDL uvod Proces