synthesizeable_vhdl-model-library:carry-lookahead-adder-subtractor

Carry-Lookahead-Adder-Subtractor with arithmetic overflow

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

Carry-Lookahead-Adder-Subtractor block diagram

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
cla_adder_sub.vhd
-- ############################################################################
-- # 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;
tb_cla_adder_sub.vhd
-- ############################################################################
-- # 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;
trace_cla_adder_sub.vhd
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