4-bit adder-subtractor logic

addition, logic, subtraction, vhdl

Solution

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.

Problem

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; ```

Original source