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