Arithmetic Circuits
Read this article which gives another overview of multipliers.
Introduction
In this project, we will design arithmetic circuits using an FPGA. We will build a 4bit magnitude comparator, a ripplecarry adder, and a multiplier circuit. You can challenge yourself by integrating all of those circuits together with some multiplexers to build an arithmetic logic unit (ALU).
Before you begin, you should:
 Have the Xilinx^{®} ISE WebPACK™ installed.
 Have your FPGA board set up.
 Be able to describe digital circuits using logic operators.
 Be able to write test bench and simulate circuit using ISim.
After you're done, you should:
 Understand how magnitude comparators, ripplecarry adders, and multipliers work.
 Be able to describe magnitude comparators, ripplecarry adders, and multipliers structurally.
Inventory:
Qty  Description 

1  Digilent Nexys™4, Nexys™3, Nexys™2, or Basys™2 FPGA Board 
1  Xilinx ISE Design Suite: WebPACK (14.6 Recommended) 
1  Digilent Adept 
Comparator
A magnitude comparator is a device that receives two Nbit inputs and asserts one of three possible outputs depending on whether one input is greater than, less than, or equal to the other (simpler comparators, called equality comparators, provide a single output that is asserted whenever the two inputs are equal). The truth table of a bitsliced magnitude comparator and the block diagram of a magnitude comparator are shown in Figs. 1 and 2 below.
Figure 1. Truth table for a bitsliced magnitude comparator.
Figure 2. Block diagram of an 8bit magnitude comparator using a bitsliced magnitude comparator.
Step 1: Design a 4bit Comparator
 Create a Verilog module for a bitsliced magnitude comparator according to the truth table presented in Fig. 1 above.
1234567891011121314151617
module
cmp_bitslice(
input
A,
input
B,
input
LT_I,
input
EQ_I,
input
GT_I,
output
LT_O,
output
EQ_O,
output
GT_O
);
assign
GT_O = ( A & ~B )  GT_I;
assign
EQ_O = EQ_I & (( A & B )  (~A & ~B));
assign
LT_O = ( B & ~A )  LT_I;
endmodule
 Connect the bitsliced magnitude comparator according to the block diagram shown in Fig. 2 above.
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
module
cmp(
input
[3:0] A,
input
[3:0] B,
output
LT_O,
output
EQ_O,
output
GT_O
);
wire
[3:0] GT_int;
wire
[3:0] EQ_int;
wire
[3:0] LT_int;
cmp_bitslice slice_0 (
.A(A[0]),
.B(B[0]),
.LT_I(1'b0),
.EQ_I(1'b1),
.GT_I(1'b0),
.LT_O(LT_int[0]),
.EQ_O(EQ_int[0]),
.GT_O(GT_int[0])
);
cmp_bitslice slice_1 (
.A(A[1]),
.B(B[1]),
.LT_I(LT_int[0]),
.EQ_I(EQ_int[0]),
.GT_I(GT_int[0]),
.LT_O(LT_int[1]),
.EQ_O(EQ_int[1]),
.GT_O(GT_int[1])
);
cmp_bitslice slice_2 (
.A(A[2]),
.B(B[2]),
.LT_I(LT_int[1]),
.EQ_I(EQ_int[1]),
.GT_I(GT_int[1]),
.LT_O(LT_int[2]),
.EQ_O(EQ_int[2]),
.GT_O(GT_int[2])
);
cmp_bitslice slice_3 (
.A(A[3]),
.B(B[3]),
.LT_I(LT_int[2]),
.EQ_I(EQ_int[2]),
.GT_I(GT_int[2]),
.LT_O(LT_int[3]),
.EQ_O(EQ_int[3]),
.GT_O(GT_int[3])
);
assign
LT_O = LT_int[3];
assign
EQ_O = EQ_int[3];
assign
GT_O = GT_int[3];
endmodule
 Create a test bench on your own to test the comparator. Please make sure that all possible cases are covered.
 To implement a comparator, it is more convenient to use behavioral descriptions in Verilog. The following codes can implement the same circuit as the structural implementation above:
1234567891011121314
module
cmp(
input
[3:0] A,
input
[3:0] B,
output
LT_O,
output
EQ_O,
output
GT_O
);
assign
LT_O = (A < B) ? 1'b1 : 1'b0;
assign
EQ_O = (A == B) ? 1'b1 : 1'b0;
assign
GT_O = (A > B) ? 1'b1 : 1'b0;
endmodule
 Apply the same test bench on the second comparator and check the result.
Adders
Adder circuits add two Nbit operands to produce an Nbit result and a carry out signal (the carry out is a '1' only when the addition result requires more than Nbits). The logic graph in Fig. 3 below shows the eight different cases that may be encountered when adding two binary numbers. The highlighted bit pairs and the associated carries show that a bitslice adder circuit must process three inputs (the two addend bits and a carryin from the previous stage) and produce two outputs (the sum bit and a carry out bit). The circuit block that implements the bitsliced adder is called a "full adder" (FA).
Figure 3. Truth table for a bitslice adder (full adder).
Note the carryin of the RCA LSB is connected directly to ground, because (by definition) the carryin to the LSB of any adder must be logic '0'. It is possible to capitalize on this observation, and create a smaller bitslice circuit for use in the LSB position that does not have a carryin input. Called a half adder (HA), this reducedfunction adder circuit is often used in the LSB position. The ripple carry adder block diagram is displayed in Fig. 4 below.
Figure 4. Ripplecarry adder block diagram.
Step 2: Design a 4bit Binary Adder
 Create a Verilog module for a full adder.
12345678910111213
module
FA(
input
A,
input
B,
input
Cin,
output
S,
output
Cout
);
assign
S = A ^ B ^ Cin;
assign
Cout = (A & B)  ((A ^ B) & Cin);
endmodule
 Create another Verilog module for a half adder.
123456789101112
module
HA(
input
A,
input
B,
output
S,
output
Cout
);
assign
S = A ^ B;
assign
Cout = A & B;
endmodule
 Create a Verilog module called "adder" to wrap three FAs with one HA to form a 4bit adder:
1234567891011121314151617181920212223242526272829303132333435363738394041424344
module
adder(
input
[3:0] A,
input
[3:0] B,
output
[3:0] S,
output
Cout
);
wire
[3:0] Carry;
HA add_0 (
.A(A[0]),
.B(B[0]),
.S(S[0]),
.Cout(Carry[0])
);
FA add_1 (
.A(A[1]),
.B(B[1]),
.Cin(Carry[0]),
.S(S[1]),
.Cout(Carry[1])
);
FA add_2 (
.A(A[2]),
.B(B[2]),
.Cin(Carry[1]),
.S(S[2]),
.Cout(Carry[2])
);
FA add_3 (
.A(A[3]),
.B(B[3]),
.Cin(Carry[2]),
.S(S[3]),
.Cout(Carry[3])
);
assign
Cout = Carry[3];
endmodule
 Create a test bench that covers all of the possible inputs to the adder and verify whether the result is correct. After the verification, you can tie SW30 to A and SW74 to B as two operands in UCF file, and tie LED40 to result of adder, you can test out your adder on your FPGA board.
 Here, we provide you with another way of implementing adder in Verilog behaviorally. In the codes below, we use operator "+" to indicate an adder. It is very important to remember that when you put down a "+" in Verilog HDL, the tools will instantiate
an adder for you, instead of just a operation as you might be familiar with in software programming language.
123456789101112131415
module
adder(
input
[3:0] A,
input
[3:0] B,
output
[3:0] S,
output
Cout
);
wire
[4:0] Result;
assign
Result = A + B;
assign
S = Result[3:0];
assign
Cout = Result[4];
endmodule
Multipliers
Hardware multipliers, based directly on adder architectures, have become indispensable in modern computers. Multiplier circuits are modeled after the "shift and add" algorithm, as shown below. In this algorithm, one partial product is created for each bit in the multiplier—the first partial product is created by the LSB of the multiplier, the second partial product is created by the second bit in the multiplier, and so forth. The partial product bits need to be fed to an array of full adders (and half adders where appropriate), with the adders shifted to the left as indicated by the multiplication example. The final partial products are added with a CLA circuit. Note that some fulladder circuits bring signal values into the carryin inputs (instead of carry's from the neighboring stage). This is a valid use of the fulladder circuit; the full adder simply adds any three bits applied to its inputs. The circuit for a partial product and the block diagram of the multiplier is shown in Fig. 5 below.
Figure 5. Hardware multiplier.
Step 3: Design a 4bit Multiplier
Up to this point, you are expected to be able to describe circuits structurally. Based on the block diagram shown above in Fig. 5, you can use assignment statements to implement the circuit for partial products, and use the FA, HA, and the adder you implemented in previous steps to add those partial products together. Before deploying your circuit on your board, write a test bench to verify that your circuit is correct. Use SW30 as A and SW74 as B (A and B are multiplicants), and show the result of multiplication on 8bit LEDs.
Unlike the adder and subtractor, multipliers do not have an operator support in Verilog, mostly due to the fact that there are various ways to implement a multiplier which trade off power, hardware resource, and speed. So implementing a multiplier structurally is the only solution.
Test Your Knowledge!
Now that you've completed this project, try these modifications:
 Implement a 4bit borrow ripple subtractor using bitsliced design methodology and describe it structurally in Verilog.
 Modify the adder you implemented in step 2 into an add_subtract circuit. Add an input "subtract". When "subtract" is '1' the output of add_subtract equals A−B. When "subtract" is "1", the output of add_subtract equals A+B. Inputs and outputs of the add_subtract circuit are represented in 2's complement. Instead of cout, an output "ERR" is needed as overflow/underflow indicator, i.e., ERR is "1" when overflow/underflow occurs.
 Can you combine add_subtract with other logics to implement an ALU according to the following opcode table? (Inputs and Output of the ALU are 4bit binary numbers in 2's complement).

OpCode Description Output F 000 Addition A+B 001 Increment A+1 010 Subtract A−B 011 Bit wise XOR A⊕B 100 Bit wise OR AB 101 Bitwise AND A&B
Source: Digilent Inc., https://learn.digilentinc.com/Documents/261
This work is licensed under a Creative Commons AttributionNonCommercial 4.0 License.