====== 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