Search code examples
vhdl

N-bits adder/subtractor using ripple of full adders- problem with carryout


I am trying to create N-bits adder/subtractor using a ripple of full adders. The input is N-bits A, N-bits B, and the result should be at length of 2N (it outputs ALU with 2 buses High and low of N-bits each, so I am trying to extend the signed bit).

The problem arises with carryout in subtraction. For example, when doing 3-2 (assume N=3 so that it's 011-010 and with two's compliment it's 011+110) I get 001 with carry 1. The problem is that this carry is garbage and can't be extended, but in other case it's necessary. For example, when trying do (-3)+(-3) (101+101, again N=3), then I get 010 with carry of 1. This time the carry really indicate the sign, so I would like to extend it.

Here is my code:

entity FullAdder is
      Port (
          A : in std_logic;
          B : in std_logic;
          Cin : in std_logic;
          sum : out std_logic;
          Cout : out std_logic
          );
end FullAdder;


architecture gate of FullAdder is
begin
     sum <= A xor B xor Cin ;
     Cout <= (A and B) OR (Cin and A) OR (Cin and B) ;
end gate;

here is the N-bit Adder

entity NbitsAdder is
    generic(N: integer := 8); 
    Port(
       A :     in std_logic_vector((N-1) downto 0);
       B :     in std_logic_vector((N-1) downto 0);
       Cin:    in std_logic;
       SUM :   out std_logic_vector((N-1) downto 0);
       Cout : out std_logic
    );
end NbitsAdder;


architecture  NbitsAdderGate of NbitsAdder is
...

    signal temp : std_logic_vector (N downto 0);
    begin
        temp (0) <= Cin; 
        arrrayOfFullAdders : for i in 0 to N-1 generate
            adder_i: FullAdder port map  ( A(i), B(i), temp(i), SUM(i), temp (i+1) );
        end generate;
        Cout <= temp(N); --which will be extend         
end NbitsAdderGate;

And this is the ADDER or SUBTRACTOR

entity NbitsAddOrSub is 
    generic(N: integer := 8);
        port(
            A :     in std_logic_vector ((N-1) downto 0);
            B :     in std_logic_vector ((N-1) downto 0);
            addOrSub :   in std_logic;
            sumLo :   out std_logic_vector ((N-1) downto 0);
            sumHi :   out std_logic_vector ((N-1) downto 0)
                    );              
end NbitsAddOrSub;

architecture NbitsAddOrSubGate of NbitsAddOrSub is 

    signal tempB: std_logic_vector ( (N-1) downto 0);
    signal CoutTemp:  std_logic;
    begin
    loop1 : for i in 0 to N-1 generate
        xor_i: xorGate port map ( B(i), addOrSub, tempB(i));
        end generate;
        theOperation : NbitsAdder generic map (N)
            port map (  A => A, B => tempB, Cin => addOrSub, sum => sumLo, Cout => CoutTemp);
        sumHi <= (N-1 downto 0 => CoutTemp); -- tring to extend the sign bit
end NbitsAddOrSubGate;

Solution

  • In signed addition the carry has no meaning. You get the sign bit from the MSB of the sum and not from the carry. In your second example there is an underflow because -3+-3 is smaller than 2^((N=3)-1), thus the result is incorrect. To sign-extend the result you should first check the overflow/underflow conditions for signed addition. If no overflow/underflow has occured, you look at the MSB of the sum and extend that bit