WebElektronika

Programozható szélességű multiplexer VHDL nyelven

person access_time 2017.09.28.
Megnézünk most három megvalósítási példát egy olyan multiplexerre, amelynek a bemeneti adatszélessége fordítás előtt változtatható. A megvalósítások során különböző csomagokat fogunk felhasználni, illetve készítünk egy saját függvényt is, amelynek segítségével az std_logic_vector típus közvetlenül konvertálható át integer típussá.


Egy olyan multiplexert készítünk most el, amelynek a bemeneti szélessége tetszőlegesen változtatható a fordítás előtt. Kényelmesen lesz módosítható a multiplexer 4/1-ről 8/1-re, 16/1-re, és így tovább. Ehhez természetesen szükséges a generic alkalmazása, amelyet az entitás blokkban kell megadnunk.
Tekintettel arra, hogy a bemeneti szélesség szabadon módosítható, tehát a multiplexer struktúrális megadása nem lehetséges, ezért a megvalósítás során a viselkedési leírást kell választani.

A viselkedési leíráshoz szükségünk lesz a hatványozásra, illetve valamilyen konverziós (std_logic_vector->integer) függvény alkalmazására is, hiszen a multiplexer select (SEL) bemenete std_logic_vector típus, de a másik bemenetnek (amelynek az adott bitjét kell a kimenetre tenni) az indexe egész.

A multiplexer első VHDL kódjánál látjuk a generic-et, amelynek segítségével paramétert hozunk létre. Ez a paraméter adja meg közvetlenül a multiplexer select (SEL) bemenetének a szélességét, illetve közvetve a multiplexer adatbemenetének a szélességét (ehhez ezt a paramétert hatványra kell emelni) is.

library IEEE;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity muxprog is
         generic(m : integer := 3);
          port(BE : in std_logic_vector(2**m-1 downto 0);
                    SEL : in std_logic_vector(m-1 downto 0);
                  Y : out std_logic);
end muxprog;

architecture BEH of muxprog is
begin
         Y <= BE(to_integer(unsigned(SEL)));
end BEH;

 

A multiplexer architektúrális leírásában a "BE" adatbemenet egyik elemét kell a kimenetre tennünk, de a "BE" bementi vektor indexét egészként (integer) kell megadnunk, viszont a "SEL" std_logic_vector típus. Ezért konverziót kell alkalmaznunk, amelyre több lehetőségünk is van.

A "ieee.numeric_std.all" csomag tartalmazza a "to_integer()" függvényt, amelynek a segítségével a paraméterlistában megadott "unsigned" típust át tudjuk konvertálni egésszé. Ehhez szükséges az, hogy a "SEL" (std_logic_vector) bemenetet konvertáljuk unsigned-dé.

A következő VHDL kód is ezt a multiplexert valósítja meg azzal a különbséggel, hogy itt egy másik csomagot alkalmazunk. Ebben a csomagban nem találjuk meg a "to_integer()" függvényt, helyette a "conv_integer()" alkalmazható.

library IEEE;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;

entity muxprog2 is
          generic(m : integer := 3);
          port(BE : in std_logic_vector(2**m-1 downto 0);
                    SEL : in std_logic_vector(m-1 downto 0);
                    Y : out std_logic);
end muxprog2;

architecture BEH of muxprog2 is
begin

          Y <= BE(conv_integer(unsigned(SEL)));

end BEH;

 

Végül nézzük meg azt a megoldást a programozható szélességű multiplexerre, amely nem használ plusz csomagot (az ieee.std_logic_1164.all kell az std_logic típus miatt!), tehát nekünk kell ezt az std_logic_vector->integer konverziót megírnunk.
Ehhez írnunk kell egy konverziós függvényt, amelyet elhelyezhetünk processben, architektúrális leírásban, illetve csomagban. A mostani megoldásban mi a második lehetsőég mellett döntöttünk, tehát az achitektúrális leírásnál definiáljuk ezt a konverziós függvényt (FromStdToInt()).

library IEEE;
use ieee.std_logic_1164.all;

entity muxprog3 is
          generic(m : integer := 3);
          port(BE : in std_logic_vector(2**m-1 downto 0);
                    SEL : in std_logic_vector(m-1 downto 0);
                    Y : out std_logic);
end muxprog3;

architecture BEH of muxprog3 is
function FromStdToInt(be : in std_logic_vector) return integer is
variable eredmeny : integer:= 0;
begin
          for i in (be'Length-1) downto 0 loop
                    if be(i) = '1' then
                              eredmeny :=eredmeny + 2**i;
                    else
                              null;
                    end if;
          end loop;
          return eredmeny;
end;
begin

          Y <= BE(FromStdToInt(SEL));

end BEH;

 

A saját konverziós függvényünknek egy bemenő paramétere van, azt az std_logic_vector-t kell megadnunk a függvény meghívásakor, amelyet szeretnénk átalakítani. A paraméter szélessége nem befolyásolja az alprogram működését.
A for ciklusnál a "Length" segítségével megkapjuk a bemenő paraméterünk szélességét, és innen kezdünk a for ciklus segítségével leszámolni 0-ig. A ciklus magjában az if-es feltételes szerkezettel azt vizsgáljuk, hogy a bemenő paraméter adott értéke 0 vagy 1. Ha 1, akkor az "eredmeny" változóhoz hozzáadjuk a 2**i hatványának az értékét.
Ha ezt a függvényt implementálni szeretnénk FPGA-ba, akkor a feltételes szerkezet else ágát is meg kell adnunk, hogy az esetleges memóriahatást elkerüljük.