In: Electrical Engineering
Implement 4-bit binary adder/subtractor using gate level. ( verilog code and test bench)
Adder/Subtractor
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.
Sum/Difference
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
.
Carry/Borrow
When adding, the carry output of the basic adder circuit is used directly. For subtraction, the borrow is the negation of the carry.
Overflow
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.
Example
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.
Verilog
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:
Kindly upvote if its helpful to you