4-bit adder-subtractor logic

hr0m picture hr0m · Dec 4, 2013 · Viewed 24.8k times · Source

I have almost successfully implemented n-bit adder-subtractor. It works fine, except for one thing.

Carry after an unsigned subtraction doesn't behave, how i expected.

Here is on page 11 the circuit which i have build. In my opinion i have build it the right way. It is a 4-bit adder/subtractor.

So to understand my troubles with the unsigned carry let's calculate 1111 - 1111 in unsigned. Well 15 - 15 is 0, so it should be 0000. What is the unsigned carry?

Input:

a <= "1111";
b <= "1111";
s <= '1';

The only thing s does, is building a 2's complement of b. Let's do it.

b = 1111
1'st complement
b = 0000
2's complement
b = 0001

Now we can perform an addition 1111 + 0001.

 1111
 0001
=====
10000

And right here is my (thought) problem. The carry (the 5'th bit) is 1. I have calculated 15-15 = 0 with an overflow carry, which i don't understand at all.

On the other hand, i can calculate 1110 - 1111 (14-15) which should be -1, which can't be represented with unsigned numbers. So here i would expect an overflow bit.

b = 1111
2's complement => 0001

 1110
 0001
=====
01111

So it tells me that 14-15 is 15 (which is not surprising) but the overflow flag is set to 0.

Did i misunderstood the subtraction overflow bit, or is a unsigned_cout xor sub missing?

My VHDL-Code:


--full adder

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity fad is
    port(
        a,b,cin : in std_logic;
        o, cout: out std_logic);
end fad;



architecture behavior of fad is
begin
    o <= a xor b xor cin;
    cout <= (a and b)or (cin and (a xor b));
end behavior;

--adder-subtractor

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity add_sub is
    generic(N : natural := 4);
    port(
        a, b : in std_logic_vector(N-1 downto 0);
        sub : in std_logic;
        o : out std_logic_vector(N-1 downto 0);
        scout, ucout : out std_logic);

end add_sub;

architecture behavior of add_sub is
    signal carries : std_logic_vector(N downto 0);
    signal bXorSub : std_logic_vector(N-1 downto 0);
    component fad is
        port( a, b, cin : in std_logic;
                o, cout : out std_logic
        );
    end component;
begin
    carries(0) <= sub;
    subtraction: for i in 0 to N-1 generate
        bXorSub(i) <= b(i) xor sub; 
    end generate subtraction;

    RCA: for i in 0 to N-1 generate
        fadN: fad port map( 
            a => a(i), 
            b => bXorSub(i), 
            cin => carries(i),
            o => o(i), 
            cout => carries(i+1));
    end generate RCA;
    ucout <= carries(N);
    scout <= carries(N) xor carries(N-1);
end behavior;

Answer

hr0m picture hr0m · Dec 5, 2013

Ok, i slept and now evrything is much clearer ;-)

After an unsigned subtraction the carry has to be '1' otherwise there is an overflow, an here is why.

The ripple carry adder consists of more (here 4) full adders. So we are never really subtracting. However in signed addition, we can calculate for exampe 4 + (-1).

With unsigned numers i can't represent a negative number. So in fact, i simply can't calculate 4 - 1. I dont have any subtractor and i can't represent a negatie number.

So how can i perform such an operation. Because it clearly works. 4 - 1 = 3 (0100 - 0001 = 0011).

The only way, to decrease an unsigned number with only an adder, is to overflow it. The fact, that we can't represent all positive numbers is the solution (with 4 bit is the unsigned maximum 15).

For example we calculate 15 - 15 with 4 bit unsigned numbers. 15 - 15 is 0. So what do we add on "1111" to get "0000"? Simply just a "0001", which ist the Two's complement of 15. We rember:

2's complement = invert the number and add 1
"1111" => "0000"
"0000" + "0001" = "0001".

And then we add this number on our 15.

 1111
 0001
=====
10000

And there, as you can see is the (right) overflow.

So the last carry-bit by an unsigned subtraction has to be set to '1' if the calculation was performed right. Otherwise, if it is '0', the subtracted number should be negative, wich an unsigned number can not represent.