• Nem Talált Eredményt

Egyidejű (konkurens) hozzárendelési utasítások

2. Programozható logikai kapuáramkörök,

2.3. VHDL – konkurens és szekvenciális hozzárendelési utasítások

2.3.1. Egyidejű (konkurens) hozzárendelési utasítások

Éppen ebben, a konkurens, azaz ténylegesen párhuzamosított utasítás végrehajtásban rejlik az újrakonfigurálható FPGA áramkörök és a HDL nyelvek nagy előnye. Szemben a hagyomá-nyos nyelvi leírásokkal, amelyek a sorrendi, azaz egymás utáni lépések sorozatában hajtják végre az utasításokat (pl. ha egy egymagos számítógép architektúrán egy-szálú programfutta-tást tekintünk), addig az FPGA-kon ténylegesen egyidejűleg, azaz nagyfokú párhuzamosítás-sal, és utasítás feldolgozással történhet a műveletek végrehajtása. Mindezt ráadásul órajel-ciklus pontossággal követhetjük nyomon szimuláció során. Ez az ún. „masszívan párhuzamo-sított” feldolgozás, amely az FPGA-k architekturális felépítésének köszönhető: itt gondoljunk arra, hogy nagyszámú programozható logikai, és dedikált makrocellás erőforrások reguláris 2D-tömbjeiből épülnek fel. Az egyidejű, konkurens utasításoknak a VHDL szintézis szem-pontjából vizsgálva több lehetséges típusa van:

• Ténylegesen egyidejű hozzárendelési utasítás (feltétel és kiválasztás nélküli)

Egyidejű feltételes hozzárendelés (when-else szerkezet)

• Egyidejű kiválasztó hozzárendelés (with-select szerkezet)

Egyidejű jelhozzárendelés

Ha nem adunk meg feltételeket és kiválasztó jeleket, akkor alapvetően egy entitás architektúrális részében lévő hozzárendelő (<= ) utasításokat konkurens, azaz ténylegesen egyidejű jel hozzárendelési utasításoknak nevezzük: a hozzárendelés jobb oldalán lévő kifeje-zés értékét a bal oldalon álló objektum (pl. signal) fogja felvenni. A konkurens jelhozzárendelési utasításokat az architektúra Begin…End közötti részén, de a szekvenciális utasítás blokkokon (pl. process() lásd később) kívüli hatókörön kell deklarálni.

A jelhozzárendelési utasításokra láthatunk egy rövid példát:

library IEEE;

use IEEE.std_logic_1164.all

entity pelda is --portlista ...

end pelda;

architecture behav of pelda is

signal nibble : std_logic_vector(0 to 3);

signal concatenation : std_logic_vector (7 downto 0);

signal switch_sig : std_logic;

signal sw : std_logic_vector(7 downto 0);

signal low_sig : std_logic;

begin

--ezek az egyidejű jelhozzárendelési utasítások ténylegesen egyidőben, -- párhuzamosan hajtódnak végre.

nibble <= "1000";

concatenation <= '1' & sw(1) & sw(0) & "10101";

switch_sig <= sw(7);

low_sig <= '0';

-- . . . end behav;

Ha ugyanazon jelhez többszörös, egyidejű hozzárendelési utasítással adunk értéket, akkor mindenegyes konkurens utasítás kiértékelődik, és mint párhuzamos ágak a kimeneti jelhez egyszerre fognak kapcsolódni (tie). Azonban a kimeneti értékek ily módon történő huzalozott összekötése a legtöbb technológiai leírás szerint nem megengedett művelet, illetve explicit módon kell kezelni (a kimeneti jelnek több forrása, ún. drivere lehet), különben a szintézis során hibát kapunk. Ilyen esetekben alkalmazhatók az ún. rezolúciós, feloldó függvények, amelyekről részletesen a [BME], [KERESZTES], [ASHENDEN] referenciákban olvashatunk.

A konkurens utasításoknak további két fő csoportját különböztetjük meg: feltételes-, illet-ve kiválasztáson alapuló jelhozzárendelési utasításokat. A működésüket tekintve a hagyomá-nyos szekvenciális ’if-else’ és ’case’ szerkezetekhez hasonlítanak, azzal a lényeges eltéréssel, hogy ezek a konkurens utasítások (végrehajtási ágakat) a szintézis során a programozható összeköttetés hálózat (routing network) segítségével párhuzamosítva képeződnek le az FPGA áramkörre.

Egyidejű feltételes jelhozzárendelés (when-else)

A feltételes jelhozzárendelés (when-else szerkezet) egyszerűsített VHDL szintaxisa a követ-kező:

jel_neve <= ertekado_kifejezes_1 when boolean_kifejezes_1 else ertekado_kifejezes_2 when boolean_kifejezes_2 else . . .

ertekado_kifejezes_n;

Minden egyes when-else feltételes ágban szereplő boolean kifejezés egymást követően ér-tékelődik ki (tekinthetnénk prioritásos megvalósításúnak is), mindaddig, amíg valamelyik feltétel igazzá nem válik. Ezekből a when-else szerkezetekből felépülő jelhozzárendeléseket (<=) akár egyidejűleg el tudjuk végezni.

Nézzünk erre egy konkrét példát is. A következő egyidejű feltételes jelhozzárendelés egy többszintű, útvonalválasztó (logikai) hálózatot fog szintetizálni, amelynek elvi megvalósítása a 2.6. ábrán látható:

rout <= a + b + c when m = n else a – b when m > n else c + 1;

Az útvonalválasztást 2-1 Multiplexerek sorozata végzi, amelynek működését a következő módon lehet definiálni: a multiplexerek lehetséges 2^n bemenete közül az n darab kiválasztó (selector) jel segítségével adjuk meg, hogy pontosan melyik bemenetet kössük (route) össze a kimenettel. Az egyidejű feltételes hozzárendelés elvi kapcsolási rajza pedig a 2.6. ábrán adott. Ha a kiértékelés sorrendjében az első boolean kifejezés (m=n) értéke igaz, akkor az eredményként a+b+c kerül a kimenetre, ha nem, akkor a következőt értékeljük ki, azaz a-b kerülhet a kimenetre. Ha az m > n (és korábban az m = n) értéke is hamis, akkor az utolsó

2.6. ábra: Az egyidejű feltételes hozzárendelési utasításnak megfelelő elvi áramköri modell

Megjegyzés: mivel a Boole kifejezések és értékadó utasítások konkurens módon értékelődnek ki, ahogy a kiválasztáshoz használt Boole kifejezések számát növeljük, úgy növekszik a multiplexer-szintek száma is. Így egy komplexebb when-else szerkezetből hosszabb multi-plexer lánc szintetizálódik, amely viszont megnövelheti a teljes áramkör jelterjedési időszük-ségletét.

Feladat 1

Nézzünk egy konkrét példát when-else egyidejű hozzárendelési utasításra. Tervezzünk egy prioritásos kódoló (priority encoder) áramkört, amelynek a 4-bites bemenete az igényeket, kéréseket definiáló bitmintázatot adja meg, legyen a neve req(3:0). A legnagyobb prioritás-sal az MSB bit, azaz a req(3) bír. A prioritásos kódoló pcode_out(2:0) kimenete pedig egy olyan bináris kód, amely mindig a beérkezett kérések közül a legnagyobb prioritású kérésnek felel meg. Az áramköri entitás neve legyen „priencoder_4_conc”, míg a hozzá tartozó architektúra neve legyen „Behavioral” (azaz viselkedési, hiszen az áramkörnek a viselkedé-sét a VHDL leírásban egyidejű feltételes utasítással adjuk meg).

Ennek a prioritásos kódolónak a működése adott a következő igazságtáblázattal:

bemenetek

prioritásos kódolt kimenet req(3) req(2) req(1) req(0) pcode_out(2:0)

1 - - - 100

0 1 - - 011

0 0 1 - 010

0 0 0 1 001

0 0 0 0 000

A fenti igazságtáblának megfelelő 4-bemenetű prioritásos kódoló áramkör VHDL leírása a következő:

-- Feladat. prioritásos kódoló áramkör when-else egyide -- feltételes hozzárendeléssel

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity priencoder_4_conc is

Port ( req : in STD_LOGIC_VECTOR (3 downto 0);

pcode_out : out STD_LOGIC_VECTOR (2 downto 0));

end priencoder_4_conc;

architecture Behavioral of priencoder_4_conc is

begin

pcode_out <= "100" when (req(3)='1') else "011" when (req(2)='1') else

"010" when (req(1)='1') else "001" when (req(0)='1') else "000";

end Behavioral;

A fenti kódban először az req(3) bemeneten keresztül érkezett kérést vizsgáljuk meg, amely ha ’1’-es volt a pcode_out(2:0) = "100" -ra állítódik be. Egyébként pedig, mindig az egyre alacsonyabb prioritású igényeket vizsgáljuk sorban egymás után (req(2), req(1),

végül req(0)).

Feladat 2

A következő példa egy n→2^n bináris dekódoló áramkör egyidejű feltételes utasításokkal történő viselkedési leírását adja meg VHDL-ben. Tekintsünk egy 2→4-es dekóder áramkört, amely en_in magas-aktív engedélyező bemenettel is rendelkezik, illetve ún. „one-hot”, azaz 1-es súlyú bináris dekódolást használ: a decode_out kimeneten mindig az adott 2^n bitpozí-cióban ’1’-es állítódik be a bemeneti kombinációnak megfelelően. A 2→4-es bináris dekódo-ló áramkör (neve legyen decoder_2_4_conc) működését leíró igazságtáblázat a következő:

bemenetek

dekódolt kime-net en_in a_in(1) a_in(0) decode_out(3:0)

0 - - 0000

1 0 0 0001

1 0 1 0010

1 1 0 0100

1 1 1 1000

Az igazságtáblázat szerint a 2→4-es dekódoló áramkörnek következő viselkedési leírás adható meg, amelyben az egyidejű feltételes hozzárendelő utasítás(oka)t használunk:

-- Feladat. 2->4 dekódoló áramkör when-else egyide -- feltételes hozzárendeléssel

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity decoder_2_4_conc is port(

a_in: in std_logic_vector(1 downto 0);

en_in: in std_logic;

decode_out: out std_logic_vector(3 downto 0) );

end decoder_2_4_conc;

architecture behav of decoder_2_4_conc is begin

--one-hot, 1-es bináris súlyú dekódolt kimenetek decode_out <= "0000" when (en_in='0') else "0001" when (a_in="00") else

"0010" when (a_in="01") else "0100" when (a_in="10") else

"1000"; -- egyébként ha a_in="11"

end behav;

A fenti VHDL kódban először azt teszteljük, hogy en_in engedélyező jel értéke ’0’-e. Ha a feltétel hamis (azaz en_in = ’1’), akkor soron következő when-else feltételes utasítás ágak hajtódnak végre előállítva a megfelelő one-hot dekódolt kimeneti értéket.

Egyidejű kiválasztás alapú jelhozzárendelés (with – select)

A másik fontos konkurens jel hozzárendelési módszert kiválasztó hozzárendelési utasításnak vagy with-select szerkezetnek is nevezzük, melynek szintaxisa a következő:

with kifejezes select

jel_neve <= kifejezes_erteke_1 when valasztas_1, kifejezes_erteke_2 when valasztas_2,

kifejezes_erteke_3 when valasztas_3 | valasztas_4, . . .

kifejezes_erteke_n when others;

A fenti with-select szerkezettel a kifejezes jel értékétől függően rendelünk hozzá a jel_neve kifejezéshez valamilyen értéket. A valasztas_i jel a kifejezes jel egy valódi értéknek, vagy a valódi értékek egy halmazának kell állnia: több lehetőséget is felsorolhatunk

’|’ operátorral elválasztva. Az others foglalt szót a with-select utasítások végén akkor hasz-nálhatjuk, amikor minden más lehetőséget, amit nem soroltunk fel, adjuk meg.

Fontos megjegyzések: a with-select konkurens kiválasztó jelhozzárendelés esetén a valasztas_ilehetőségeknek egymásra nézve egyrészt:

• kölcsönösen kizárólagosnak kell lenniük (mutual exclusive, = mutex tulajdonság), azaz egyazon választási lehetőség sem szerepelhet egyszerre több különböző sorban

• másrészt minden lehetséges valasztas_ilehetőséget fel kell sorolni (all inclusive tulajdonság), nem maradhat ki lehetőség, mert akkor azokat le kell fedni (others).

Vizsgáljuk meg az előző, egyidejű feltételes hozzárendelésnél bemutatott példát, de most az egyidejű kiválasztó hozzárendelési utasításra, kisebb módosítással (a+b+c kiválasztását tekintve):

signal szelektor : std_logic_vector(1 downto 0);

with szelektor select

rout <= c + 1 when "00", a - b when "10",

a + b + c when others;

Összevetve a korábbi áramkörrel az első szintű multiplexer ’1’-es állapotánál kaptunk a – b kimenetet, amelyet a második szintű multiplexer ’0’-s állapotán keresztül a rout kimenetre továbbítottunk (azaz szelektor ’10’). Hasonló módon az c+1 bemenetet előállítva, az első szinten lévő multiplexer ’1’-es állapotán, míg a második szintű multiplexer ’0’-s állapotán keresztül jut az rout kimenetre. Végül az a+b+celőállított bemeneti kifejezésnél azt others kulcsszót használjuk minden más eset ún. lefedésére.

Ennek az egyidejű kiválasztó jelhozzárendelésnek az áramköri modellje a következő 2.7.

ábrán látható.

Értékadó kifejezések

+

+

Mux4-1

- r

+1

a

b Mux

hálózat c

00 01 10 11

szelektor

2.7. ábra: Egyidejű kiválasztó jel hozzárendelési utasításnak megfelelő elvi áramköri modell

Feladat 3

Tekintsük az egyidejű feltételes hozzárendelésnél korábban megismert 4-bites prioritásos kódoló áramkört (Feladat 1). Ennek az áramkörnek, most az egyidejű kiválasztó jelhozzáren-delő utasításokból felépített VHDL viselkedési leírását adjuk meg. Az entitás neve legyen:

priencoder_4_with.

-- Feladat 3. prioritásos kódoló áramkör with-select egyidejű -- kiválasztó hozzárendeléssel

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity priencoder_4_with is

Port ( req : in STD_LOGIC_VECTOR (3 downto 0);

pcode_out : out STD_LOGIC_VECTOR (2 downto 0));

end priencoder_4_with;

architecture behav of priencoder_4_with is begin

with req select

--összes lehetséges kiválasztási esetet meg kell adni pcode_out <= "100" when "1000"|"1001"|"1010"|"1011"|

"1100"|"1101"|"1110"|"1111", "011" when "0100"|"0101"|"0110"|"0111", "010" when "0010"|"0011",

"001" when "0001",

"000" when others; -- req="0000" egyébként end behav;

A fenti kód a lehetséges kiválasztási esetekhez tartozó összes kombinációt megadja a req(3:0)jelet illetően. A ’|’ szimbólum szolgál arra, hogy az több lehetséges kombinációt egyetlen esethez tudjuk rendelni, továbbá az others kulcsszóval minden más esetet le tudunk

„fedni”.

Feladat 4

Hasonló módon, tekintsük az egyidejű feltételes hozzárendelésnél korábban megismert 2→4-es bináris dekódoló áramkört (lásd Feladat 2). Ennek az áramkörnek, most az egyidejű kivá-lasztó jelhozzárendelő utasításokból felépített viselkedési leírását adjuk meg VHDL nyelven.

Az entitás neve legyen: decoder_2_4_with.

-- Feladat 4. 2->4 dekódoló áramkör with-select egyidejű -- kiválasztó hozzárendeléssel

library IEEE;

use IEEE.STD_LOGIC_1164.ALL;

entity decoder_2_4_with is port(

a_in: in std_logic_vector(1 downto 0);

en_in: in std_logic;

decode_out: out std_logic_vector(3 downto 0) );

end decoder_2_4_with;

architecture behav of decoder_2_4_with is

signal sel: std_logic_vector(2 downto 0);

begin

sel <= en_in & a_in;

with s select

decode_out <= "0000" when "000"|"001"|"010"|"011", "0001" when "100",

"0010" when "101", "0100" when "110",

"1000" when others; -- sel="111" egyebkent

end behav;

A fenti VHDL kódban az en_in és a_in(1:0) jeleket egy 3-bites sel(2:0) néven defi-niált jellé fűzzük össze, éppen azért, hogy a korábbi igazságtáblázatnak megfelelő kiválasztó jelhozzárendeléseket is meg tudjuk adni. A fenti kód a lehetséges kiválasztási esetekhez tartozó összes kombinációt megadja a sel jelet illetően. A ’|’ szimbólum szolgál arra, hogy több lehetséges kombinációt egyetlen esethez tudjuk rendelni, továbbá az others kulcsszóval minden más esetet le tudunk „fedni”.

További feladatok: az előző VHDL nyelven leírt Feladatokhoz 1.)–4.) hozzon létre egy-egy tesztpadot. Ágyazza be a tesztpadba a megfelelő példányosított entitásokat, majd adjon rájuk gerjesztést, és vizsgálja a kimenetek változásait a Xilinx ISim szimulátor segítségével.

A szimulációval kapcsolatban bővebb leírást a későbbi 2.4. fejezetben találhat.