An adder/subtractor is an arithmetic combinational logic circuit which can add/subtract two N-bit binary numbers and output their N-bit binary sum/difference, a carry/borrow status bit, and if needed an overflow status bit. If we choose to represent signed numbers using 2's complement, then we can build an adder/subtractor from a basic adder circuit, e.g. a ripple carry adder.


In the case of addition, the adder/subtractor would behave exactly as the basic adder circuit. Subtraction, however, is different. Here the number to be subtracted is negated, i.e we make use of the algebraic rule A-B = A+(-B). The negation of a number B in 2's complement is not(B)+1. We can achieve this computation by giving the basic adder the numbers A and not(B) then setting the initial carry input to the basic adder to be 1.


When adding, the carry output of the basic adder circuit is used directly. For subtraction, the borrow is the negation of the carry.


The detection of an overflow is the same for both addition and subtraction: an overflow has occurred if and only if the basic adder's two most significant carry outputs are different.


As an example imagine we have four full adders. With these we can easily build a 4-bit ripple carry adder to calculate A+B — we just link up the four half adders, the carry out of one becomes the carry in of another, and set the first carry in to 0. Now, if we want to calculate A+(-B) then we can use the same half adders if we invert the bits of B and set the first carry in to 1. This would add A and the 2's complement of B giving us our subtraction.

To build our 4-bit adder/subtractor circuit using a 4-bit ripple carry adder we need, along with the two input numbers to add/subtract (A and B), an input telling us if we are to perform an addition or subtraction operation which we can call Op. Now, if we look at the definition of the XOR gate we see that B xor 0 = B and B xor 1 = not(B). We can use this in our negation of B if we set Op to 0 when adding and to 1 when subtracting. This in conjunction with setting the initial carry input of the ripple carry adder to Op gives us what we need. The following table shows how this works:

Op Operand 1 Operand 2 Initial carry Result
0 A B 0 A+B
1 A not(B) 1 A-B

The carry/borrow status bit output can also make use of the XOR gate. If C is the carry output of the ripple carry adder, then we can set the carry/borrow output of the adder/subtractor to be C xor Op. The overflow status bit output is handled easily, as it is C3 xor C4 when C3 and C4 are the respective carry outputs of the third and fourth half adder respectively.


The following Verilog code shows a 4-bit adder/subtractor that uses the ripple carry method. The code for the full adder is also shown for completeness.

module ripple_carry_adder_subtractor(S, C, V, A, B, Op);
   output [3:0] S;   // The 4-bit sum/difference.
   output 	C;   // The 1-bit carry/borrow status.
   output 	V;   // The 1-bit overflow status.
   input [3:0] 	A;   // The 4-bit augend/minuend.
   input [3:0] 	B;   // The 4-bit addend/subtrahend.
   input 	Op;  // The operation: 0 => Add, 1=>Subtract.
   wire 	C0; // The carry out bit of fa0, the carry in bit of fa1.
   wire 	C1; // The carry out bit of fa1, the carry in bit of fa2.
   wire 	C2; // The carry out bit of fa2, the carry in bit of fa3.
   wire 	C3; // The carry out bit of fa2, used to generate final carry/borrrow.
   wire 	B0; // The xor'd result of B[0] and Op
   wire 	B1; // The xor'd result of B[1] and Op
   wire 	B2; // The xor'd result of B[2] and Op
   wire 	B3; // The xor'd result of B[3] and Op

   // Looking at the truth table for xor we see that  
   // B xor 0 = B, and
   // B xor 1 = not(B).
   // So, if Op==1 means we are subtracting, then
   // adding A and B xor Op alog with setting the first
   // carry bit to Op, will give us a result of
   // A+B when Op==0, and A+not(B)+1 when Op==1.
   // Note that not(B)+1 is the 2's complement of B, so
   // this gives us subtraction.     
   xor(B0, B[0], Op);
   xor(B1, B[1], Op);
   xor(B2, B[2], Op);
   xor(B3, B[3], Op);
   xor(C, C3, Op);     // Carry = C3 for addition, Carry = not(C3) for subtraction.
   xor(V, C3, C2);     // If the two most significant carry output bits differ, then we have an overflow.
   full_adder fa0(S[0], C0, A[0], B0, Op);    // Least significant bit.
   full_adder fa1(S[1], C1, A[1], B1, C0);
   full_adder fa2(S[2], C2, A[2], B2, C1);
   full_adder fa3(S[3], C3, A[3], B3, C2);    // Most significant bit.
endmodule // ripple_carry_adder_subtractor

module full_adder(S, Cout, A, B, Cin);
   output S;
   output Cout;
   input  A;
   input  B;
   input  Cin;
   wire   w1;
   wire   w2;
   wire   w3;
   wire   w4;
   xor(w1, A, B);
   xor(S, Cin, w1);
   and(w2, A, B);   
   and(w3, A, Cin);
   and(w4, B, Cin);   
   or(Cout, w2, w3, w4);
endmodule // full_adder

When given test inputs, the 4-bit adder/subtractor generated the following waveform:


Mano, M. Morris, and Kime, Charles R. Logic and Computer Design Fundamentals. 2nd Edition. Prentice Hall, 2000.