====== Carry-Lookahead-Adder-Subtractor with arithmetic overflow ====== ===== Parameters ===== A short interface specification: * The model is parameterized over the bit width (@BITBR). * The model adds or subtracts depending on the input add_sub. * The model is not cascadable. * The inputs have to be in complement of 2. * add_sub = 1 -> s = a + b * add_sub = 0 -> s = a - b {{:synthesizeable_vhdl-model-library:lib_cla_adder_sub.svg?nolink&300|Carry-Lookahead-Adder-Subtractor block diagram}} ===== Ports ===== a, b : binary values in the 2-complement representation add_sub : mode: add_sub = '1' : addition add_sub = '0' : subtraction overflow : arithmetic overflow overflow = '1': overflow = '0': no overflow s : computed sum/difference ===== Model ===== -- ############################################################################ -- # Project : VHDL-Modellbibliothek # -- # # -- # Filename : cla_adder_sub.vhd # -- # # -- # Schaltung : Carry-Lookahead-Addierer/Subtrahierer # -- # # -- # Kurzbeschreibung: addiert oder subtrahiert in Abhaengigkeit des Steuer- # -- # signals add_sub die beiden eingegebenen Binaerzahlen: # -- # o add_sub = 1 -> s = a + b # -- # o add_sub = 0 -> s = a - b # -- # # -- # cla_adder_sub # -- # # -- # Designer : Wolfgang Sehr; ueberarbeitet von Stefan Schmechtig # -- # Abteilung : Lehrstul fuer rechnergestuetzten Schaltungsentwurf # -- # Datum : 03.02.1995 # -- ############################################################################ -- ############################################################################ -- # IEEE PACKAGES # -- ############################################################################ Library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; -- ############################################################################ ENTITY cla_adder_sub IS GENERIC (BR : INTEGER := @BITBR);-- Bitbreite der zu addierenden Werte PORT ( a, b : IN SIGNED ((BR-1) DOWNTO 0); add_sub : IN STD_LOGIC; s : OUT UNSIGNED ((BR-1) DOWNTO 0); overflow : OUT STD_LOGIC ); -- a, b : Eingabewerte fuer die beiden zu addierenden Binaerzahlen -- -- add_sub : Auswahl des Modus dieses Moduls: -- : o add_sub = '1': Addition -- : o add_sub = '0': Subtraktion -- -- overflow : Anzeige eines arithmetischen Ueberlaufs: -- : o overflow = '1': Ueberlauf -- : o overflow = '0': kein Ueberlauf -- -- s : vom Addierer berechnete Summe END cla_adder_sub; ARCHITECTURE dataflow OF cla_adder_sub IS SIGNAL carry : UNSIGNED (BR DOWNTO 0); SIGNAL b_int : UNSIGNED ((BR-1) DOWNTO 0); SIGNAL carry_in_int : STD_LOGIC; -- carry : Uebertragssignal fuer die einzelnen Stufen -- -- b_int : internes Signal fuer den negierten Operanden B -- -- carry_in_int : internes Signal fuer den Uebertrag in der 0. Stufe -- : (Wird zur Bildung des 2'er Komplementes verwendet.) BEGIN compl: PROCESS(b, add_sub) VARIABLE carry_in_int_var : STD_LOGIC; VARIABLE b_int_var : UNSIGNED ((BR-1) DOWNTO 0); -- -------------------------------------------------------------------- -- Bildung des 2'er Komplements der Eingangszahl b -- -------------------------------------------------------------------- BEGIN IF (add_sub = '1') THEN FOR i IN 0 TO (BR-1) LOOP b_int_var(i) := b(i); END LOOP; carry_in_int_var := '0'; ELSIF (add_sub = '0') THEN FOR i IN 0 TO (BR-1) LOOP b_int_var(i) := NOT(b(i)); END LOOP; carry_in_int_var := '1'; END IF; b_int <= b_int_var; carry_in_int <= carry_in_int_var; END PROCESS; cla: PROCESS(a,b_int ,carry_in_int, add_sub) -- -------------------------------------------------------------------- -- Dieser Process stellt quasi eine Carry-Look-Ahead Einheit dar und -- berechnet aus den eingegebenen Binaerzahlen a und b und dem ein- -- gegebenen Uebertrag (carry_in) parallel die Uebertraege (Variable c) -- fuer die einzelnen Stufen und weist diese dem Signal carry bzw. -- carry_out zu. -- -------------------------------------------------------------------- VARIABLE p : UNSIGNED ((BR-1) DOWNTO 0); -- "propagate" VARIABLE g : UNSIGNED ((BR-1) DOWNTO 0); -- "generate" VARIABLE c : UNSIGNED ( BR DOWNTO 0); -- Uebertraege der einzelnen Stufen BEGIN FOR i IN 0 TO (BR-1) LOOP g(i) := a(i) AND b_int(i); p(i) := a(i) OR b_int(i); END LOOP; c(0) := carry_in_int ; FOR i IN 0 TO (BR-1) LOOP c(i+1) := g(i) OR (p(i) AND c(i)); END LOOP; FOR i IN 0 TO BR LOOP carry(i) <= c(i); END LOOP; END PROCESS; sum: PROCESS(a,b_int,carry) -- -------------------------------------------------------------------- -- eigentliche Addition -- -------------------------------------------------------------------- BEGIN FOR i IN 0 TO (BR-1) LOOP s(i) <= a(i) XOR b_int(i) XOR carry(i); END LOOP; overflow <= carry(BR) XOR carry(BR-1); END PROCESS; END dataflow; CONFIGURATION CFG_cla_adder_sub OF cla_adder_sub IS FOR dataflow END FOR; END CFG_cla_adder_sub; ===== Testbench ===== -- ############################################################################ -- # Project : VHDL-Modellbibliothek # -- # # -- # Filename : tb_cla_adder_sub.vhd # -- # # -- # Schaltung : Carry-Lookahead Addierer/Subtrahierer # -- # # -- # # -- # Modell : tb_cla_adder_sub # -- # # -- # Designer : Wolfgang Sehr; ueberarbeitet von Stefan Schmechtig # -- # Abteilung : Lehrstul fuer rechnergestuetzten Schaltungsentwurf # -- # Datum : 14.12.1994 # -- ############################################################################ -- ############################################################################ -- # 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_cla_adder_sub IS GENERIC (X : INTEGER := @BITBR );-- Bitbreite der zu addierenden Werte END TB_cla_adder_sub; ARCHITECTURE behaviour OF TB_cla_adder_sub IS SIGNAL tb_a : SIGNED (X-1 DOWNTO 0); SIGNAL tb_b : SIGNED (X-1 DOWNTO 0); SIGNAL tb_add_sub : STD_LOGIC; SIGNAL tb_s : UNSIGNED (X-1 DOWNTO 0); SIGNAL tb_overflow : STD_LOGIC; SIGNAL fehler_bereich : STD_LOGIC; SIGNAL fehler_insg : STD_LOGIC; -- tb_a : Testbenchsignal fuer 1. Operand -- tb_b : Testbenchsignal fuer 2. Operand -- tb_add_sub : Testbenchsignal fuer Moduswahl -- tb_s : Testbenchsignal fuer Summe -- tb_overflow : Testbenchsignal fuer Ueberlauf -- fehler_bereich : Fehlersignal fuer unzulaessige Bitkombination -- fehler_insg : Fehlersignal fuer einen Fehler, der vom UUT -- : verursacht wurde COMPONENT cla_adder_sub PORT( a, b : IN SIGNED ((X-1) DOWNTO 0); add_sub : IN STD_LOGIC; s : OUT UNSIGNED ((X-1) DOWNTO 0); overflow : OUT STD_LOGIC ); END COMPONENT; BEGIN UUT: cla_adder_sub -- einzige Schaltung PORT MAP(tb_a, tb_b, tb_add_sub, tb_s, tb_overflow); mode: PROCESS -- bestimmt den Modus des Moduls BEGIN tb_add_sub <= '0'; WAIT FOR 20 ns; LOOP tb_add_sub <= NOT(tb_add_sub); WAIT FOR 20 ns; END LOOP; END PROCESS; stim: PROCESS -- generiert die Stimuli fuer die zu untersuchende Schaltung VARIABLE a_int : INTEGER; VARIABLE b_int : INTEGER; BEGIN a_int := RAND; b_int := RAND; tb_a <= CONV_SIGNED(a_int, tb_a'LENGTH); tb_b <= CONV_SIGNED(b_int, tb_b'LENGTH); WAIT FOR 0.1 ns; a_int := CONV_INTEGER(tb_a); b_int := CONV_INTEGER(tb_b); WAIT FOR 10 ns; LOOP ---------------------------------------------------------------- -- Bestimmung des 1. Operanden ---------------------------------------------------------------- a_int := RAND; tb_a <= CONV_SIGNED(a_int, tb_a'LENGTH); WAIT FOR 0.1 ns; a_int := CONV_INTEGER(tb_a); WAIT FOR 7.5 ns; ---------------------------------------------------------------- ---------------------------------------------------------------- -- Bestimmung des 2. Operanden ---------------------------------------------------------------- b_int := RAND; tb_b <= CONV_SIGNED(b_int, tb_b'LENGTH); WAIT FOR 0.1 ns; b_int := CONV_INTEGER(tb_b); WAIT FOR 12.3 ns; ---------------------------------------------------------------- END LOOP; END PROCESS; contr: PROCESS(tb_s, tb_overflow) -- vergleicht die Ergebnisse, welche vom UUT geliefert werden mit den -- Ergebnissen, die vom "Gut-Modell geliefert werden VARIABLE s_sgn : SIGNED((tb_s'LENGTH-1) DOWNTO 0); VARIABLE s_chk : INTEGER; VARIABLE s_int : INTEGER; VARIABLE a_sgn : SIGNED((tb_a'LENGTH-1) DOWNTO 0); VARIABLE b_sgn : SIGNED((tb_b'LENGTH-1) DOWNTO 0); VARIABLE a_chk : INTEGER; VARIABLE b_CHK : INTEGER; VARIABLE unzul_bitkomb : SIGNED((X-1) DOWNTO 0); VARIABLE overflow_var : STD_LOGIC; -- s_sgn : Summe vom UUT empfangen im SIGNED-Format -- s_chk : Summe innerhalb der Testbench berechnet -- s_int : Summe vom UUT empfangen im Integerformat -- a_sgn : Operand A, vom UUT empfangen -- b_sgn : Operand B, vom UUT empfangen -- a_chk : Operand A wie er an das UUT gesandt wird, aber im -- : Integer-Format -- b_chk : Operand B wie er an das UUT gesandt wird, aber im -- : Integer -- unzul_bitkomb : unzulaessige Bitkombination wie sie im 2'er Komplement -- : nicht erlaubt ist -- overflow_var : arithmetischer Ueberlauf, vom "Gut-Modell" berechnet BEGIN unzul_bitkomb := CONV_SIGNED(0, unzul_bitkomb'LENGTH); unzul_bitkomb(unzul_bitkomb'LENGTH-1) := '1'; a_sgn := CONV_SIGNED(tb_a, a_sgn'LENGTH); b_sgn := CONV_SIGNED(tb_b, b_sgn'LENGTH); a_chk := CONV_INTEGER(a_sgn); b_chk := CONV_INTEGER(b_sgn); s_sgn := CONV_SIGNED(tb_s, s_sgn'LENGTH); s_int := CONV_INTEGER(s_sgn); -- -------------------------------------------------------------------- -- "Gut-Modell" -- -------------------------------------------------------------------- -- Bestimmen des Ergebnisses IF (tb_add_sub = '1') THEN s_chk := a_chk + b_chk; ELSE s_chk := a_chk - b_chk; END IF; -- Bestimmen des arithmetischen Ueberlaufs IF (ABS(s_chk) > ((2**(X-1))-1)) THEN overflow_var := '1'; ELSE overflow_var := '0'; END IF; -- -------------------------------------------------------------------- -- -------------------------------------------------------------------- -- Vergleich zwischen UUT und Gut-Modell -- -------------------------------------------------------------------- IF ((tb_a = unzul_bitkomb) OR (tb_b = unzul_bitkomb)) THEN fehler_bereich <= '1'; fehler_insg <= '0'; ELSIF ((s_int /= s_chk) AND (overflow_var = tb_overflow)) OR (s_int = s_chk) THEN fehler_bereich <= '0'; fehler_insg <= '0'; ELSE fehler_bereich <= '0'; fehler_insg <= '1'; END IF; END PROCESS; END behaviour; CONFIGURATION CFG_TB_cla_adder_sub OF TB_cla_adder_sub IS FOR behaviour FOR UUT: cla_adder_sub USE CONFIGURATION WORK.CFG_cla_adder_sub; END FOR; END FOR; END CFG_TB_cla_adder_sub; ===== Synopsys VSS Trace ===== tr tb_a tr tb_b tr tb_add_sub tr tb_s tr tb_overflow tr fehler_bereich tr fehler_insg cd stim tr a_int tr b_int cd contr tr s_int