VHDL coding tips and tricks: April 2015

Monday, April 27, 2015

VHDL code for Carry Save Adder

Carry save adder is very useful when you have to add more than two numbers at a time. Normally if you have three numbers, the method would be to add the first two numbers together and then add the result to the third one. This causes so much delay.

In this post I have implemented a 4 bit carry save adder which adds three numbers at a time. You might want to see page 1 and 2 of this paper to get a better understanding of how this exactly works.

fulladder.vhd

I have used the same full adder code in this post.

CSA.vhd

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity CSA is 
    Port ( x : in  unsigned (3 downto 0);
           y : in  unsigned (3 downto 0);
           z : in  unsigned (3 downto 0);
           cout : out std_logic;
           s : out unsigned (4 downto 0)
              );
end CSA;

architecture Behavioral of CSA is

component fulladder is
    port (: in std_logic;
            b : in std_logic;
           cin : in std_logic;
           sum : out std_logic;
           carry : out std_logic
         );
end component;

signal c1,s1,c2 : unsigned (3 downto 0) := (others => '0');

begin

fa_inst10 : fulladder port map(x(0),y(0),z(0),s1(0),c1(0));
fa_inst11 : fulladder port map(x(1),y(1),z(1),s1(1),c1(1));
fa_inst12 : fulladder port map(x(2),y(2),z(2),s1(2),c1(2));
fa_inst13 : fulladder port map(x(3),y(3),z(3),s1(3),c1(3)); 

fa_inst20 : fulladder port map(s1(1),c1(0),c2(0),s(1),c2(1));
fa_inst21 : fulladder port map(s1(2),c1(1),c2(1),s(2),c2(2));
fa_inst22 : fulladder port map(s1(3),c1(2),c2(2),s(3),c2(3));
fa_inst23 : fulladder port map('0',c1(3),c2(3),s(4),cout); 

s(0) <= s1(0);

end Behavioral;


tb_adder.vhd

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
use ieee.numeric_std.all;
 
ENTITY tb_adder IS
END tb_adder;
 
ARCHITECTURE behavior OF tb_adder IS 
 
    -- Component Declaration for the Unit Under Test (UUT)
    COMPONENT CSA is 
    Port ( x : in  unsigned (3 downto 0);
           y : in  unsigned (3 downto 0);
           z : in  unsigned (3 downto 0);
           cout : out std_logic;
           s : out unsigned (4 downto 0)
              );
        end COMPONENT;
    
   signal x,y,z : unsigned(3 downto 0) := (others => '0');
    signal s : unsigned(4 downto 0) := (others => '0');
   signal cout : std_logic := '0';
    signal error : integer := 0;
 
BEGIN
 
    -- Instantiate the Unit Under Test (UUT)
   uut: CSA PORT MAP (x,y,z,cout,s);

-- Stimulus process - all the input combinations are tested here.
--the number of errors are recorded in the signal named "error".
   stim_proc: process
   begin    
      for i in 0 to 15 loop
            for j in 0 to 15 loop
                for k in 0 to 15 loop
                    x <= to_unsigned(i,4);
                    y <= to_unsigned(j,4);
                    z <= to_unsigned(k,4);
                    wait for 10 ns;
                    if(to_integer(cout & S) /= (i+j+k)) then
                        error <= error + 1;
                    end if; 
                end loop;   
            end loop;   
        end loop;
        
      wait;
   end process;

END;



Simulation waveform:

The simulated waveform in Xilinx ISIM would look like this: