Read this article which gives another overview of multipliers.
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).
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 
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.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

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 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

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 
1
2
3
4
5
6
7
8
9
10
11
12
13
14

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 
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.
1
2
3
4
5
6
7
8
9
10
11
12
13

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 
1
2
3
4
5
6
7
8
9
10
11
12

module HA( input A, input B, output S, output Cout ); assign S = A ^ B; assign Cout = A & B; endmodule 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44

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 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

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 
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.
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.
Now that you've completed this project, try these modifications:
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.