WebElektronika

Előjelnélküli tömbszorzó VHDL nyelven

person access_time 2018.09.25.
Megnézzük most ebben a cikkben az előjelnélküli tömbszorzó megvalósítását VHDL nyelven. Használhatnánk viselkedési leírást is a realizálás során, de akadnak olyan helyzetek (pl.: szilíciumfelületen történő megvalósítás), amikor struktúrálisan kell a szorzót leírnunk VHDL nyelven.


Nézzük meg először az előjelnélküli szorzás elméletének alapjait. Szeretnénk összeszorozni az "A" és a "B" operandust, amelyek vektorok ( a3 a2 a1 a0 * b3 b2 b1 b0 ). Az első ábra első sorában látjuk az alapműveletet. A második sornál az "A" és a "B" vektorok helyére behelyettesítettük a vektorok helyére a bináris számábrázolásukat, és végül a megvalósítandó egyenletet kapjuk (4. sor).

kep
1. ábra   A megvalósítandó egyenlet
 

Nézzük meg a realizálandó egyenletet úgy, hogy a két összeszorzandó szám például 4 bites  (a3 a2 a1 a0 * b3 b2 b1 b0). 
Ha elvégezzük a szorzást bitenként, akkor a 2. ábrán látható eredményt kapjuk.

kep
2. ábra   Két 4 bites szám összeszorzása
 

Fontos megjegyezni, hogy a két bit között a "szorzás" valójában logikai ÉS művelet. Tehát például az "A0B1" valójában (A0 and B1). Ennek a logikai műveletnek az eredménye logikai 1 vagy 0 lehet. Látható a 2. ábrán, hogy az "a0b0" megegyezik a P0 kimenettel, de a P1 -értékének a meghatározásához össze kell adnunk az a1b0-t az a0b1-gyel. Hogyan adjuk össze tehát ezeket a mintermeket úgy, hogy az (esetleges) átvitelképzést is figyelembe vegyük?
Erre az összeadásra alkalmas a teljes összeadó, amelyet már korábban is felhasználtunk.

"Helyezzük" be a tömbbe a teljes összeadókat (3. ábra).

kep
3. ábra   Előjelnélküli 4x4 tömbszorzó
 

Ahhoz, hogy a VHDL kódot könnyebben megírjuk/megértsük, a 3. ábrát kibővítettük úgy, hogy a belső jeleket elneveztük. Az "SC" az átvitelképzésre, az "SP" a teljes összeadó "S" kimenetére utal.

kep
4. ábra   A kiegészített 4x4-es szorzó
 

Nézzünk meg egy belső jelet, például az SC21-et. Látjuk az első sor első oszlopában lévő teljes összeadó jobb oldalán lévő bemeneten az a2b1 helyezkedik el. Ennek a két összeszorzandó vektornak az indexeit kapta meg az adott teljes összeadó "carry" kimenete.

Hozzunk létre egy projektet egy VHDL szimulátorban (pl.: VHDL Simili), majd másoljuk be a következő kódot, amely a teljes összeadó struktúrális megvalósítása. Az egész projektben "std_logic" típust alkalmaztunk a "bit" típus helyett. Részben azért, mert a nagy FPGA gyártók (pl.: Xilinx) ezt javasolják, illetve az esetleges hibákat is könnyebb megkeresni akkor, ha a kimenet ismeretlen, mint ha logikai 0 lenne.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
 
entity fa1 is
     port(A,B, Cin : in std_logic;
     S, Cout : out std_logic);
end fa1;
 
architecture STR of fa1 is
begin
 
     S <= A xor B xor CIN;
     COUT <= (A and B) or (A and CIN) or (B and CIN);
 
end STR;

 

Ezután másoljuk be egy újabb file-ba a következő kódot, amely az előjelnélküli 4x4-es szorzó struktúrális megvalósítása. Látjuk komponensként a teljes összeadót (fa1) is.
Tekintettel arra, hogy az architecture blokk párhuzamos utasításvégrehajtással "rendelkezik", ezért a különböző értékadások egyidőben kerülnek végrehajtásra.

library IEEE;
use ieee.std_logic_1164.all;
 
entity szorzo4x4 is
     port(A, B : in std_logic_vector(3 downto 0);
     P : out std_logic_vector(7 downto 0));
end szorzo4x4;
 
architecture STR of szorzo4x4 is
     component fa1 is
          port(A,B, Cin : in std_logic;
               S, Cout : out std_logic);
     end component;
signal A0B0, A1B0, A2B0, A3B0 : std_logic;
signal A0B1, A1B1, A2B1, A3B1 : std_logic;
signal A0B2, A1B2, A2B2, A3B2 : std_logic;
signal A0B3, A1B3, A2B3, A3B3 : std_logic;
signal SC01, SC02, SC03, SC11, SC12, SC13 : std_logic;
signal SC21, SC22, SC23, SC1, SC2 : std_logic;
signal SP11, SP21, SP12, SP22, SP13, SP23 : std_logic;
begin
 
     A0B0 <= A(0) and B(0);
     A0B1 <= A(0) and B(1);
     A0B2 <= A(0) and B(2);
     A0B3 <= A(0) and B(3);
 
     A1B0 <= A(1) and B(0);
     A1B1 <= A(1) and B(1);
     A1B2 <= A(1) and B(2);
     A1B3 <= A(1) and B(3);
 
     A2B0 <= A(2) and B(0);
     A2B1 <= A(2) and B(1);
     A2B2 <= A(2) and B(2);
     A2B3 <= A(2) and B(3);
 
     A3B0 <= A(3) and B(0);
     A3B1 <= A(3) and B(1);
     A3B2 <= A(3) and B(2);
     A3B3 <= A(3) and B(3);
 
     P(0) <= A0B0;
     n01: fa1 port map(A1B0, A0B1, '0', P(1), SC01);
     n11: fa1 port map(A2B0, A1B1, '0', SP11, SC11);
     n21: fa1 port map(A3B0, A2B1, '0', SP21, SC21);
 
     n02: fa1 port map(SP11, A0B2, SC01, P(2), SC02);
     n12: fa1 port map(SP21, A1B2, SC11, SP12, SC12);
     n22: fa1 port map(A3B1, A2B2, SC21, SP22, SC22);
 
     n03: fa1 port map(SP12, A0B3, SC02, P(3), SC03);
     n13: fa1 port map(SP22, A1B3, SC12, SP13, SC13);
     n23: fa1 port map(A3B2, A2B3, SC22, SP23, SC23);
 
     nP0: fa1 port map(SP13, '0', SC03, P(4), SC1);
     nP1: fa1 port map(SP23, SC1, SC13, P(5), SC2);
     nP2: fa1 port map(A3B3, SC2, SC23, P(6), P(7));
 
end STR;

 

Szimuláljuk le a 4x4-es tömbszorzó működését, készítsük el ennek az aritmetikai modulnak a tesztkörnyezetét. Másoljuk be egy újabb file-ba a következő kódot, amely már tartalmazza a tesztvektorokat is.

library IEEE;
use ieee.std_logic_1164.all;
 
entity szorzo4x4sim is
     port(P : out std_logic_vector(7 downto 0));
end szorzo4x4sim;
 
architecture SIM of szorzo4x4sim is
signal SA, SB : std_logic_vector(3 downto 0);
begin
 
     nev: entity aritmetika.szorzo4x4 port map(SA, SB, P);
 
     process
     begin
          SA <= "0000";
          SB <= "0001";
          wait for 10 ns;
          SA <= "0001";
          wait for 10 ns;
          SA <= "1111";
          wait for 10 ns;
          SA <= "0101";
          SB <= "1010";
          wait for 10 ns;
          SA <= "1111";
          SB <= "1111";
          wait for 10 ns;
     end process;
 
end SIM;

 

Futtassuk ezt a VHDL kódot a szimulátorban, és az 5. ábrán lévő eredményt kapjuk.

kep
5. ábra   A 4x4-es tömbszorzó futási eredménye
 

Nézzük most meg ennek a 4x4-es szorzónak a késleltetését. Ahhoz, hogy megkapjuk két összeszorzandó szám eredményét, figyelembe kell vennünk a különböző átvitelek útjait. A legnagyobb átvitelképzés útját látjuk a 6. ábrán. 

kep
6. ábra   A 4x4-es tömbszorzó az átvtelképzés útvonalával
 

Ahhoz, hogy megkapjuk a 4x4-es szorzó késleltetését, módosítani kell a teljes összeadó VHDL kódját, be kell tennünk az "after" segítségével a logikai kapuk becsült késleltetési értékét. Változtassuk meg tehát a teljes összeadó VHDL kódjának a felépítését, hiszen a logikai kapuknak fizikai késleltetése van. Ezt a késleltetést becsüljük meg, legyen például 0.5 ns (ez technológiafüggő, és egyébként nagyon sok).

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
 
entity fa1d is
     port(A,B, Cin : in std_logic;
          S, Cout : out std_logic);
end fa1d;
 
architecture STR of fa1d is
signal AB, AC, BC : std_logic;
begin
 
     S <= (A xor B xor CIN) after 0.5 ns;
 
     AB <= (A and B) after 0.5 ns;
     AC <= (A and Cin) after 0.5 ns;
     BC <= (B and Cin) after 0.5 ns;
 
     COUT <= (AB or AC or BC) after 0.5 ns;
 
end STR;

 

Futtassuk le újra a szimulációt (ehhez módosítani kell a szorzo4x4.vhd file-t is), és a 6. ábrán lévő szimulációs eredményt kapjuk.

kep
6. ábra   Szimulációs eredmény
 

Látható a szimulációs eredményből, hogy különböző bemeneti értékek különböző késleltetéseket okoznak. Ha nem grafikusan szeretnénk megkapni ennek a szimulációnak az eredményét, akkor javasoljuk a trace-t.