====== Array-Divider-Multiplier ======
===== Parametereinstellung =====
Eine kurze Funktions- und Schnittstellenbeschreibung:
* Das Modell des Dividierers/Multiplizierers ist ein in der Bitbreite parametrisierbares (@BITBR) Modul zur Multiplikation oder Division zweier Operanden im 2'er-Komplement (vorzeichenbehaftet).
* Die Algorithmen sind asynchron implementiert.
* mode = 1 -> op_1/op_2 = erg_1: Quotient ; erg_2: Rest
* mode = 0 -> op_1*op_2 = erg_1: höherwert. Produkt ; erg_2: niederwert. Produkt
{{:synthesizeable_vhdl-model-library:lib_array_divider_multiplier.svg?nolink&300|Array-Divider-Multiplier block diagram}}
===== Schnittstellen =====
* mode : Moduswahl, in dem sich das Modul befindet:
* mode = 1 -> Division
* mode = 0 -> Multiplikation
* op_1 : Eingangsport fuer 1. Operanden
* bei der Division: Dividend
* bei der Multiplikation: Multiplikant
* op_2 : Eingangsport fuer 2. Operanden
* bei der Division: Diviso
* bei der Multiplikation: Multiplikant
* erg_1 : Ausgangsport für 1. Teil des Ergebnisses
* bei der Division: Quotient
* bei der Muliplikation: höherwertiger Teil des Produktes
* erg_2 : Ausgangsport fuer 2. Teil des Ergebnisses
* bei der Division: Rest
* bei der Muliplikation: niederwertiger Teil des Produktes
===== Model =====
-- ############################################################################
-- # Project : VHDL-Modellbibliothek #
-- # #
-- # Filename : array_divider_multiplier.vhd #
-- # #
-- # Schaltung : Modul zur Multiplikation/Division zweier Binaer- #
-- # zahlen in 2'er Komplementdarstellung #
-- # #
-- # Modell : array_divider_multiplier #
-- # #
-- # Designer : Wolfgang Sehr; ueberarbeitet von Stefan Schmechtig #
-- # Abteilung : Lehrstul fuer rechnergestuetzten Schaltungsentwurf #
-- # Datum : 23.01.1995 #
-- ############################################################################
-- ############################################################################
-- # IEEE PACKAGES #
-- ############################################################################
Library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
-- ############################################################################
ENTITY array_divider_multiplier IS
GENERIC(X :INTEGER := @BITBR); -- X := Operandenbreite
-- symmetrisches Array X * X
PORT(mode : IN STD_LOGIC;
op_1 : IN UNSIGNED ((X-1) DOWNTO 0);
op_2 : IN UNSIGNED ((X-1) DOWNTO 0);
erg_1 : OUT UNSIGNED ((X-1) DOWNTO 0);
erg_2 : OUT UNSIGNED ((X-1) DOWNTO 0));
-- mode : Moduswahl, in dem sich das Modul befindet:
-- o mode = 1 -> Division
-- o mode = 0 -> Multiplikation
--
-- op_1 : Eingangsport fuer 1. Operanden
-- o bei der Division: Dividend
-- o bei der Multiplikation: Multiplikant
--
-- op_2 : Eingangsport fuer 2. Operanden
-- o bei der Division: Divisor
-- o bei der Multiplikation Multiplikator
--
--
-- erg_1 : Ausgangsport fuer 1. Teil des Ergebnisses
-- o bei der Division: Quotient
-- o bei der Muliplikation: hoeherwertiger Teil
-- des Produktes
--
-- erg_2 : Ausgangsport fuer 2. Teil des Ergebnisses
-- o bei der Division: Rest
-- o bei der Muliplikation: niederwertiger Teil
-- des Produktes
--
-- -> Darstellung im 2'er Komplement
END array_divider_multiplier;
ARCHITECTURE verhalten OF array_divider_multiplier IS
SIGNAL op_1_sgn : SIGNED((X-1) DOWNTO 0);
SIGNAL op_2_sgn : SIGNED((X-1) DOWNTO 0);
BEGIN
op_1_sgn <= CONV_SIGNED(op_1, op_1_sgn'LENGTH);
op_2_sgn <= CONV_SIGNED(op_2, op_2_sgn'LENGTH);
PROCESS(op_1_sgn, op_2_sgn, mode)
CONSTANT eins : STD_LOGIC := '1';
VARIABLE ztld : SIGNED ((2*X-2) DOWNTO 0);
VARIABLE tlr : SIGNED ((X-1) DOWNTO 0);
VARIABLE k_ztld : UNSIGNED ((ztld'LENGTH-1) DOWNTO 0);
VARIABLE k_tlr : UNSIGNED ((tlr'LENGTH-1) DOWNTO 0);
VARIABLE vz : UNSIGNED ( 1 DOWNTO 0);
VARIABLE a : UNSIGNED ((ztld'LENGTH-1) DOWNTO 0);
VARIABLE a_ein : UNSIGNED ((ztld'LENGTH-1) DOWNTO 0);
VARIABLE b : UNSIGNED ((tlr'LENGTH-1) DOWNTO 0);
VARIABLE k_b : UNSIGNED ((tlr'LENGTH-1) DOWNTO 0);
VARIABLE q : UNSIGNED ((tlr'LENGTH-1) DOWNTO 0);
VARIABLE k_q : UNSIGNED ((tlr'LENGTH-1) DOWNTO 0);
VARIABLE r : UNSIGNED ((tlr'LENGTH-1) DOWNTO 0);
VARIABLE k_r : UNSIGNED ((tlr'LENGTH-1) DOWNTO 0);
VARIABLE sum : UNSIGNED ( tlr'LENGTH DOWNTO 0);
VARIABLE n_divisable : UNSIGNED ((tlr'LENGTH-1) DOWNTO 0);
VARIABLE n_div_detect : STD_LOGIC;
VARIABLE b_add : UNSIGNED ((tlr'LENGTH) DOWNTO 0);
VARIABLE zwischenerg_2 : UNSIGNED ((X*X-1) DOWNTO 0);
VARIABLE p : UNSIGNED (2*X-1 DOWNTO 0);
VARIABLE k_p : UNSIGNED ((ztld'LENGTH) DOWNTO 0);
VARIABLE a_add : UNSIGNED (X DOWNTO 0);
VARIABLE mknt : UNSIGNED ((X-1) DOWNTO 0);
VARIABLE mktr : UNSIGNED ((X-1) DOWNTO 0);
-- ztld : enthaelt den Dividenden, aufbereitet
-- : fuer den Divisionsalgorithmus
--
-- tlr : enthaelt den Divisor, aufbereitet
-- : fuer den Divisionsalgorithmus
--
-- k_ztld : komplementierter Dividend aufbereitet fuer den
-- : Divisionsalgorithmus
--
-- k_tlr : komplementierter Divisor
--
-- vz : 0 -> positives Vorzeichen
-- : 1 -> negatives Vorzeichen
-- : vz(1) Vorzeichen des Dividenden
-- : vz(0) Vorzeichen des Divisors
--
-- a : Variable fuer den aktuellen Dividenden
-- : waehrend der Ausfuehrumg des
-- : Divisionsalgorithmus
--
-- a_ein : Variable fuer den Dividenden, der anfangs in
-- : Divisionsalgorithmus uebernommen wird
--
-- b : Variable fuer den Divisor (immer positiv)
--
-- k_b : komplmentierter Divisor (immer negativ)
--
-- q : Variable fuer den Quotienten
--
-- k_q : komplementierter Quotient
--
-- r : ganzzahliger Rest der Division
--
-- k_r : komplementierter ganzzahliger Rest der
-- Division
--
-- sum : Ergebnis der Addition/Subtraktion in de
-- einzelnen Stufen
--
-- n_divisable : ist in der Stufe i Null, ab der der Dividend
-- nicht mehr weiter durch den Divisor teilbar
-- ist
--
-- n_div_detect : ist 1, wenn der Dividend vor der letzten Zeile
-- nicht mehr durch den Divisor teilbar ist
--
-- b_add : Zwischenspeichervariable fuer Addition
--
-- zwischenerg_2 : Stellt den aktuellen Zwischenerg_2 dar, der
-- : sich aus dem Ergebnis der Addition/Subtraktion
-- : und den noch nicht behandelten Stellen des
-- : Dividenden zusammensetzt.
--
-- p : erhaelt den Wert des Produktes im Falle
-- : einer Multiplikation
--
-- k_p : 2'er Komplement des Produktes
--
-- a_add : ein Summand fuer den Addierer
--
-- mknt : Multiplikant
--
-- mktr : Multiplikator
--
BEGIN
-- ####################################################################
-- Eingangssignale bzw. komplementierte Eingangssignale werden den
-- internen Variablen des PROCESS zugewiesen
-- ####################################################################
ztld := CONV_SIGNED(op_1_sgn, ztld'LENGTH);
tlr := CONV_SIGNED(op_2_sgn, tlr'LENGTH);
FOR i IN 0 TO (ztld'LENGTH-1) LOOP
k_ztld(i) := NOT(ztld(i));
END LOOP;
k_ztld := k_ztld + eins;
FOR i IN 0 TO (tlr'LENGTH-1) LOOP
k_tlr(i) := NOT(tlr(i));
END LOOP;
k_tlr := k_tlr + eins;
IF (op_1_sgn(op_1_sgn'LENGTH-1) = '1') THEN
vz(1) := '1';
ELSE
vz(1) := '0';
END IF;
IF (op_2_sgn(op_2_sgn'LENGTH-1) = '1') THEN
vz(0) := '1';
ELSE
vz(0) := '0';
END IF;
CASE vz IS
WHEN "00" => a := CONV_UNSIGNED(ztld,a'LENGTH);
a_ein := CONV_UNSIGNED(ztld,a'LENGTH);
b := CONV_UNSIGNED(tlr, b'LENGTH);
mknt := CONV_UNSIGNED(op_1_sgn, mknt'LENGTH);
mktr := CONV_UNSIGNED(op_2_sgn, mktr'LENGTH);
WHEN "01" => a := CONV_UNSIGNED(ztld, a'LENGTH);
a_ein := CONV_UNSIGNED(ztld, a'LENGTH);
b := CONV_UNSIGNED(k_tlr, b'LENGTH);
mknt := CONV_UNSIGNED(op_1_sgn, mknt'LENGTH);
mktr := CONV_UNSIGNED(k_tlr, mktr'LENGTH);
WHEN "10" => a := CONV_UNSIGNED(k_ztld,a'LENGTH);
a_ein := CONV_UNSIGNED(k_ztld,a'LENGTH);
b := CONV_UNSIGNED(tlr, b'LENGTH);
mknt := CONV_UNSIGNED(k_ztld((X-1) DOWNTO 0),
mknt'LENGTH);
mktr := CONV_UNSIGNED(op_2_sgn, mktr'LENGTH);
WHEN "11" => a := CONV_UNSIGNED(k_ztld,a'LENGTH);
a_ein := CONV_UNSIGNED(k_ztld,a'LENGTH);
b := CONV_UNSIGNED(k_tlr, b'LENGTH);
mknt := CONV_UNSIGNED(k_ztld((X-1) DOWNTO 0),
mknt'LENGTH);
mktr := CONV_UNSIGNED(k_tlr, mktr'LENGTH);
WHEN OTHERS => a := CONV_UNSIGNED(0, a'LENGTH);
a_ein := CONV_UNSIGNED(0, a'LENGTH);
b := CONV_UNSIGNED(0, b'LENGTH);
mknt := CONV_UNSIGNED(0, mknt'LENGTH);
mktr := CONV_UNSIGNED(0, mktr'LENGTH);
END CASE;
-- ####################################################################
-- ####################################################################
-- Divisionsalgorithmus/Multiplikationsalgorithmus
-- ####################################################################
IF (mode = '1') THEN
sum(tlr'LENGTH) := '1';
ELSE
sum := CONV_UNSIGNED(0, X+1);
p := CONV_UNSIGNED(0, p'LENGTH);
END IF;
zwischenerg_2 := CONV_UNSIGNED(0, zwischenerg_2'LENGTH);
FOR n IN 0 TO (tlr'LENGTH-1) LOOP
k_b(n) := NOT(b(n));
END LOOP;
k_b := k_b + eins;
FOR i IN 0 TO (tlr'LENGTH-1) LOOP
--------------------------------------------------------------------
-- Addition oder Subtraktion des Divisors in Abhaengigkeit des
-- Uebertrags der zuvor erfolgten Rechenoperation
--------------------------------------------------------------------
b_add := CONV_UNSIGNED(0, b_add'LENGTH); -- Vermeidung von Latches
IF (mode = '1') THEN -- Division
IF sum(tlr'LENGTH) = '1' THEN
b_add := CONV_UNSIGNED(k_b, tlr'LENGTH+1);
ELSIF sum(tlr'LENGTH) ='0' THEN
b_add := CONV_UNSIGNED(b, tlr'LENGTH+1);
END IF;
a_add := CONV_UNSIGNED(a(ztld'LENGTH-1-i DOWNTO
ztld'LENGTH-tlr'LENGTH-i), tlr'LENGTH+1);
ELSE -- Multiplikation
b_add := CONV_UNSIGNED(0, b_add'LENGTH);
FOR k IN 0 TO (X-1) LOOP
b_add(k) := mknt(k) AND mktr(i);
END LOOP;
a_add := CONV_UNSIGNED(sum(X DOWNTO 1),
a_add'LENGTH);
END IF;
sum := a_add + b_add;
-------------------------------------------------------------------
-------------------------------------------------------------------
-- sichern des Zwischenergebnisses mit angehaengtem Dividendenerg_2
-------------------------------------------------------------------
FOR k IN 0 TO (X-1-1-i) LOOP
zwischenerg_2(i*X+k) := a_ein(k);
END LOOP;
FOR l IN 0 TO i LOOP
zwischenerg_2(i*X+(X-1-i+l)) := sum(l);
END LOOP;
-------------------------------------------------------------------
-------------------------------------------------------------------
-- Umlagern der Zwischenergebnisse und Ablagern der endgueltigen
-- Ergebnisse
-------------------------------------------------------------------
-- fuer Divisionsalgorithmus
FOR m IN 1 TO (tlr'LENGTH-1) LOOP
a(ztld'LENGTH-m-1-i) := sum(tlr'LENGTH-m-1);
END LOOP;
q(tlr'LENGTH-1-i) := sum(tlr'LENGTH);
-- Uebertrag bei der Addition stellt
-- Quotientenstelle dar
-- fuer Multiplikationsalgorithmus
p(i) := sum(0);
-------------------------------------------------------------------
END LOOP;
FOR i IN X TO (2*X-1) LOOP
p(i) := sum(i-X+1);
END LOOP;
-- ####################################################################
-- Restkorrektur
-- ####################################################################
r := CONV_UNSIGNED('0', tlr'LENGTH);
n_div_detect := '0';
-- --------------------------------------------------------------------
-- Ueberpruefung der Teilbarkeit
-- --------------------------------------------------------------------
FOR i IN 0 TO (tlr'LENGTH-1) LOOP
IF (i < tlr'LENGTH-1) THEN
IF (q(tlr'LENGTH-1-i) = '1') THEN
n_divisable(i) := '0';
FOR l IN i+1 TO (tlr'LENGTH-1) LOOP
n_divisable(i) := n_divisable(i) OR (q(tlr'LENGTH-1-l));
END LOOP;
ELSE
n_divisable(i) := '1';
END IF;
END IF;
END LOOP;
-- --------------------------------------------------------------------
-- Zuweisung des entsprechenden Restes
-- --------------------------------------------------------------------
IF (q = CONV_UNSIGNED(0, tlr'LENGTH)) THEN
r := CONV_UNSIGNED(a_ein((tlr'LENGTH-1) DOWNTO 0), tlr'LENGTH);
ELSE
FOR i IN 1 TO (tlr'LENGTH-1) LOOP
IF (i < tlr'LENGTH-1) THEN
IF (n_divisable(i) = '0') THEN
r := CONV_UNSIGNED(zwischenerg_2(i*X+X-1 DOWNTO i*X),
tlr'LENGTH);
n_div_detect := '1';
END IF;
ELSE
IF (n_div_detect = '0') THEN
r := CONV_UNSIGNED(zwischenerg_2(i*X+X-1 DOWNTO i*X),
tlr'LENGTH);
END IF;
END IF;
END LOOP;
END IF;
-- ####################################################################
-- ####################################################################
-- interne Variablen werden Ausgangssignalen zugewiesen
-- ####################################################################
FOR i IN 0 TO (q'LENGTH-1) LOOP
k_q(i) := NOT(q(i));
END LOOP;
k_q := k_q + CONV_UNSIGNED(1, q'LENGTH);
FOR i IN 0 TO (r'LENGTH-1) LOOP
k_r(i) := NOT(r(i));
END LOOP;
k_r := k_r + eins;
FOR i IN 0 TO (p'LENGTH-1) LOOP
k_p(i) := NOT(p(i));
END LOOP;
k_p := k_p + eins;
IF (mode = '1') THEN
CASE vz IS
WHEN "00" => erg_1 <= q;
erg_2 <= r;
WHEN "01" => erg_1 <= k_q;
erg_2 <= r;
WHEN "10" => erg_1 <= k_q;
erg_2 <= k_r;
WHEN "11" => erg_1 <= q;
erg_2 <= k_r;
WHEN OTHERS => erg_1 <= CONV_UNSIGNED(0, erg_1'LENGTH);
erg_2 <= CONV_UNSIGNED(0, erg_2'LENGTH);
END CASE;
ELSE
CASE vz IS
WHEN "00" => erg_2 <= CONV_UNSIGNED(p(erg_1'LENGTH-1
DOWNTO 0), erg_1'LENGTH);
erg_1 <= CONV_UNSIGNED(p(2*X-1 DOWNTO X),
erg_2'LENGTH);
WHEN "01" => erg_2 <= CONV_UNSIGNED(k_p(erg_1'LENGTH-1
DOWNTO 0), erg_1'LENGTH);
erg_1 <= CONV_UNSIGNED(k_p(2*X-1 DOWNTO X),
erg_2'LENGTH);
WHEN "10" => erg_2 <= CONV_UNSIGNED(k_p(erg_1'LENGTH-1
DOWNTO 0), erg_1'LENGTH);
erg_1 <= CONV_UNSIGNED(k_p(2*X-1 DOWNTO X),
erg_2'LENGTH);
WHEN "11" => erg_2 <= CONV_UNSIGNED(p(erg_1'LENGTH-1
DOWNTO 0), erg_1'LENGTH);
erg_1 <= CONV_UNSIGNED(p(2*X-1 DOWNTO X),
erg_2'LENGTH);
WHEN OTHERS => erg_2 <= CONV_UNSIGNED(0, erg_1'LENGTH);
erg_1 <= CONV_UNSIGNED(0, erg_2'LENGTH);
END CASE;
END IF;
-- ####################################################################
END PROCESS;
END verhalten;
CONFIGURATION CFG_array_divider_multiplier OF array_divider_multiplier IS
FOR verhalten
END FOR;
END CFG_array_divider_multiplier;
===== Testbench =====
-- ############################################################################
-- # Project : VHDL-Modellbibliothek #
-- # #
-- # Filename : tb_array_divider_multiplier.vhd #
-- # #
-- # Schaltung : Testbench fuer Divisions/Multiplikations-Modul #
-- # #
-- # tb_array_divider_multiplier #
-- # #
-- # Designer : Wolfgang Sehr; ueberarbeitet von Stefan Schmechtig #
-- # Abteilung : Lehrstul fuer rechnergestuetzten Schaltungsentwurf #
-- # Datum : 23.01.1995 #
-- ############################################################################
-- ############################################################################
-- # IEEE PACKAGES #
-- ############################################################################
Library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
USE IEEE.math_real.all; -- wird fuer die Erzeugung von Zufallszahlen
-- benoetigt
-- ############################################################################
ENTITY TB_array_divider_multiplier IS
GENERIC(X :INTEGER := @BITBR); -- symmetrisches Array X * X
END TB_array_divider_multiplier;
ARCHITECTURE verhalten OF TB_array_divider_multiplier IS
SIGNAL tb_mode : STD_LOGIC;
SIGNAL tb_op_1 : UNSIGNED ((X-1) DOWNTO 0);
SIGNAL tb_op_2 : UNSIGNED ((X-1) DOWNTO 0);
SIGNAL tb_erg_1 : UNSIGNED ((X-1) DOWNTO 0);
SIGNAL tb_erg_2 : UNSIGNED ((X-1) DOWNTO 0);
SIGNAL fehler_num : STD_LOGIC;
SIGNAL fehler_bereich : STD_LOGIC;
SIGNAL fehler_insg : STD_LOGIC;
-- tb_mode : Modus, der von der Testbench stimuliert wird
--
-- tb_op_1 : Dividend, der von der Testbench stimuliert wird
--
-- tb_op_2 : Divisor, der von der Testbench stimuliert wird
--
-- tb_erg_1 : Quotient, den die Testbench vom UUT empfaengt
--
-- tb_erg_2 : Rest den die Testbench vom UUT empfaengt
--
-- fehler_num : ist nur '1', wenn Division durch Null auftritt
--
-- fehler_bereich : ist nur '1', wenn ein von der Testbench
-- : ausgegebener Stimuli den Darstellungsbereich
-- : der Zahl in der gewawehlten Bitbreite uebersteigt
--
-- fehler_insg : ist '1', wenn ein Fehler auftritt der auf
-- : UUT zurueckzufuehren ist
COMPONENT array_divider_multiplier
PORT(mode : IN STD_LOGIC;
op_1 : IN UNSIGNED ((X-1) DOWNTO 0);
op_2 : IN UNSIGNED ((X-1) DOWNTO 0);
erg_1 : OUT UNSIGNED ((X-1) DOWNTO 0);
erg_2 : OUT UNSIGNED ((X-1) DOWNTO 0)
);
END COMPONENT;
BEGIN
UUT: array_divider_multiplier -- einzige Schaltung
PORT MAP(tb_mode,
tb_op_1,
tb_op_2,
tb_erg_1,
tb_erg_2);
mode: PROCESS
BEGIN
tb_mode <= '0';
WAIT FOR 500 ns;
LOOP
tb_mode <= NOT(tb_mode);
WAIT FOR 500 ns;
END LOOP;
END PROCESS;
stim: PROCESS
VARIABLE op_1_int : INTEGER;
VARIABLE op_2_int : INTEGER;
VARIABLE tb_op_1_var : SIGNED((X-1) DOWNTO 0);
VARIABLE tb_op_2_var : SIGNED((X-1) DOWNTO 0);
-- op_1_int : 1. Operand als Integerzahl dargestellt
-- op_2_int : 2. Operand als Integerzahl dargestellt
-- tb_op_1_var : 1. Operand im SIGNED-Format dargestellt
-- tb_op_2_var : 2. Operand im SIGNED-Format dargestellt
BEGIN
op_1_int := RAND;
op_2_int := RAND;
tb_op_1_var := CONV_SIGNED(op_1_int, tb_op_1'LENGTH);
tb_op_2_var := CONV_SIGNED(op_2_int, tb_op_2'LENGTH);
tb_op_1 <= CONV_UNSIGNED(tb_op_1_var,
tb_op_2_var'LENGTH);
tb_op_2 <= CONV_UNSIGNED(tb_op_2_var,
tb_op_1_var'LENGTH);
WAIT FOR 0.1 ns;
tb_op_1_var := CONV_SIGNED(tb_op_1, tb_op_1_var'LENGTH);
tb_op_2_var := CONV_SIGNED(tb_op_2, tb_op_2_var'LENGTH);
op_1_int := CONV_INTEGER(tb_op_1_var);
op_2_int := CONV_INTEGER(tb_op_2_var);
WAIT FOR 100 ns;
LOOP
-- ------------------------------------------------------------
-- Bestimmmung des 1. Operanden
-- ------------------------------------------------------------
op_1_int := RAND;
tb_op_1_var := CONV_SIGNED(op_1_int, tb_op_1_var'LENGTH);
tb_op_1 <= CONV_UNSIGNED(tb_op_1_var, tb_op_1'LENGTH);
WAIT FOR 0.1 ns;
tb_op_1_var := CONV_SIGNED(tb_op_1, tb_op_1_var'LENGTH);
op_1_int := CONV_INTEGER(tb_op_1_var);
WAIT FOR 75 ns;
-- ------------------------------------------------------------
-- ------------------------------------------------------------
-- Bestimmung des 2. Operanden
-- ------------------------------------------------------------
op_2_int := RAND;
tb_op_2_var := CONV_SIGNED(op_2_int, tb_op_2_var'LENGTH);
tb_op_2 <= CONV_UNSIGNED(tb_op_2_var, tb_op_2'LENGTH);
WAIT FOR 0.1 ns;
tb_op_2_var := CONV_SIGNED(tb_op_2, tb_op_2_var'LENGTH);
op_2_int := CONV_INTEGER(tb_op_2_var);
WAIT FOR 100 ns;
-- ------------------------------------------------------------
END LOOP;
END PROCESS;
contr: Process(tb_erg_1, tb_erg_2, tb_mode)
VARIABLE quot_sgn : SIGNED(tb_erg_1'LENGTH-1 DOWNTO 0);
VARIABLE rest_sgn : SIGNED(tb_erg_2'LENGTH-1 DOWNTO 0);
VARIABLE quot_int : INTEGER;
VARIABLE rest_int : INTEGER;
VARIABLE quot_chk : INTEGER;
VARIABLE rest_chk : INTEGER;
VARIABLE op_1_chk : INTEGER;
VARIABLE op_2_chk : INTEGER;
VARIABLE op_1_sgn_var : SIGNED((X-1) DOWNTO 0);
VARIABLE op_2_sgn_var : SIGNED((X-1) DOWNTO 0);
VARIABLE unzul_bitkomb : UNSIGNED((X-1) DOWNTO 0);
VARIABLE produkt_sgn : SIGNED(2*X-1 DOWNTO 0);
VARIABLE produkt_chk : INTEGER;
VARIABLE produkt_int : INTEGER;
-- quot_sgn : Quotient vom UUT empfangen im SIGNED-Format
-- :
-- rest_sgn : Rest vom UUT empfangen im SIGNED-Format
-- :
-- quot_int : Quotient vom UUT empfangen im Integer-Format
-- :
-- rest_sgn : Rest vom UUT empfangen im Integer-Format
-- :
-- quot_chk : Quotient innerhalb der Testbench berechnet
-- : im Integer-Format
-- :
-- rest_chk : Rest innerhalb der Testbench berechnet
-- : im Integer-Format
-- :
-- op_1_chk : Dividend wie er als Stimuli vorliegt,
-- : aber im Integer-Format
-- :
-- op_2_chk : Divisor wie er als Stimuli vorliegt,
-- : aber im Integer-Format
-- :
-- op_1_sgn_var : Dividend wie er als Stimuli vorliegt,
-- : aber im SIGNED-Format
-- :
-- op_2_sgn_var : Divisor wie er als Stimuli vorliegt,
-- : aber im SIGNED-Format
-- :
-- unzul_bitkomb : In dieser Variable wird die entsprechende
-- : unzulaessige Bitkombination abgelegt die
-- : eine Bereichsueberschreitung im jeweiligen
-- : Zahlenformat darstellt.
-- : (naemlich: 100.....000)
-- :
-- produkt_sgn : Produkt vom UUT empfangen im SIGNED-Format
-- :
-- produkt_chk : Produkt vom UUT empfangen im Integer-Format
-- :
-- :
-- produkt_int : Produkt, wie es innerhalb der Testbench
-- : berechnet wurde
BEGIN
produkt_sgn := CONV_SIGNED(0, produkt_sgn'LENGTH);
-- -----------------------------------------------------------------
-- Abfragen der am UUT anliegenden Signale
-- -----------------------------------------------------------------
op_1_sgn_var := CONV_SIGNED(tb_op_1, op_1_sgn_var'LENGTH);
op_2_sgn_var := CONV_SIGNED(tb_op_2, op_2_sgn_var'LENGTH);
op_1_chk := CONV_INTEGER(op_1_sgn_var);
op_2_chk := CONV_INTEGER(op_2_sgn_var);
FOR i IN 0 TO (tb_erg_2'LENGTH-1) LOOP
rest_sgn(i) := tb_erg_2(i);
produkt_sgn(i) := tb_erg_2(i);
END LOOP;
rest_int := CONV_INTEGER(rest_sgn);
FOR i IN 0 TO (tb_erg_1'LENGTH-1) LOOP
quot_sgn(i) := tb_erg_1(i);
produkt_sgn(i+X) := tb_erg_1(i);
END LOOP;
quot_int := CONV_INTEGER(quot_sgn);
produkt_chk := CONV_INTEGER(produkt_sgn);
-- -----------------------------------------------------------------
-- -----------------------------------------------------------------
-- Berechnung der Ausgangssignale, die am UUT anliegen muessen,
-- lediglich aufgrund der Eingangssignale
-- "Vergleichsmodell"
-- -----------------------------------------------------------------
IF (tb_mode = '1') THEN
IF ( op_2_chk /= 0) THEN
quot_chk := op_1_chk / op_2_chk;
rest_chk := op_1_chk - (op_2_chk*quot_chk);
END IF;
ELSIF (tb_mode = '0') THEN
produkt_int := op_1_chk * op_2_chk;
END IF;
-- -----------------------------------------------------------------
-- -----------------------------------------------------------------
-- Ueberpruefung, ob die Zahlenwerte, die im UUT berechnet wurden,
-- mit denen, die hier in der Testbench berechnet wurden ueberein-
-- stimmen bzw., ob andere Fehler auftreten
-- -----------------------------------------------------------------
unzul_bitkomb := CONV_UNSIGNED(0, tb_op_1'LENGTH);
unzul_bitkomb(tb_op_1'LENGTH-1) := '1';
IF (tb_mode = '1') THEN
IF (tb_op_1 = unzul_bitkomb) THEN
fehler_num <= '0';
fehler_bereich <= '1';
fehler_insg <= '0';
ELSIF (op_2_chk = 0) THEN
fehler_num <= '1';
fehler_bereich <= '0';
fehler_insg <= '0';
ELSE
IF (quot_chk /= quot_int) OR (rest_chk /= rest_int) THEN
fehler_num <= '0';
fehler_bereich <= '0';
fehler_insg <= '1';
ELSE
fehler_num <= '0';
fehler_bereich <= '0';
fehler_insg <= '0';
END IF;
END IF;
ELSIF (tb_mode = '0') THEN
IF (tb_op_1 = unzul_bitkomb) THEN
fehler_num <= '0';
fehler_bereich <= '1';
fehler_insg <= '0';
ELSE
IF (produkt_chk /= produkt_int) THEN
fehler_num <= '0';
fehler_bereich <= '0';
fehler_insg <= '1';
ELSE
fehler_num <= '0';
fehler_bereich <= '0';
fehler_insg <= '0';
END IF;
END IF;
END IF;
-- -----------------------------------------------------------------
END PROCESS;
END verhalten;
CONFIGURATION CFG_TB_array_divider_multiplier OF TB_array_divider_multiplier IS
FOR verhalten
FOR UUT: array_divider_multiplier
USE CONFIGURATION WORK.CFG_array_divider_multiplier;
END FOR;
END FOR;
END CFG_TB_array_divider_multiplier;
===== Synopsys VSS Trace =====
tr tb_mode
tr tb_op_1
tr tb_op_2
tr tb_erg_1
tr tb_erg_2
tr fehler_num
tr fehler_bereich
tr fehler_insg
cd stim
tr op_1_int
tr op_2_int
cd contr
tr quot_int
tr rest_int
tr produkt_int