CSCI 320 Computer Architecture
Lab 6 Design of a Ripple Carry Adder
October 2, 2007

PURPOSE

1. To explore structural modeling in Verilog HDL.

2. To explore a ripple carry adder.

PROBLEM

In previous labs, you implemented the architecture of the Ultra computers, ultra simple machines with only a few instructions. What you wrote was a behavioral model in Verilog HDL. This means you specified the what but not how the Verilog HDL code is to be realized (synthesized, in the jargon) in digital circuits. For example, you wrote

		#clock AC <= AC + MD;
as part of the control sequence of the Add instruction. This specifies that the contents of the AC register is to be added to the contents of the MD register but not how the add is to be accomplished. In this lab, we will specify the add to be performed by a ripple carry adder. This is called structural modeling in Verilog HDL.

Background on a Ripple Carry Adder

1. The Half Adder

The purpose of this section is to design a circuit that will add two one-place binary numbers and keep track of the carry. This circuit is called a Half Adder.

                0       1       0       1
+ 0 + 0 + 1 + 1
___ ___ ___ ___
0 1 1 10
If we ignore the carry for a moment and think of 0 and 1 as the Boolean symbols, we are led to find a circuit which will give the following operation for S, the sum bit.
       A      B       A B     
1 1 0
1 0 1
0 1 1
0 0 0

The symbol is used to described the Exclusive Or operation. We represent an Exclusive Or gate as an Or gate with inside it.

The carry operation (C) is given in the following truth table.

       A      B         C         
1 1 1
1 0 0
0 1 0
0 0 0

The carry C is A   B. We draw the logic circuit for both S and C.

The above circuit for a Half Adder will be represented by the following box with inputs and outputs having arrows to show the flow of the data.

2. The Full Adder

The Half Adder had two inputs and two outputs, i.e., the two numbers to be added, and the C and S outputs. The Full Adder has three inputs and two outputs. The inputs are the two numbers to be added and the carry from a previous addition. The outputs are the Sum and the Carry.

                1       0       1       1       0       1       0       0
1 1 0 1 0 0 1 0
+ 1 + 1 + 1 + 0 + 1 + 0 + 0 + 0
___ ___ ___ ___ ___ ___ ___ ___
11 10 10 10 1 1 1 0
Which gives us the following truth table.
   A      B         C          Carry    Sum       
1 1 1 1 1
1 1 0 1 0
1 0 1 1 0
1 0 0 0 1
0 1 1 1 0
0 1 0 0 1
0 0 1 0 1
0 0 0 0 0

The sum of products method gives both the Carry and Sum operations.

Having these we could design the circuit. But, we first check to see if there are any logically equivalent statements that would lead to a better equivalent circuit.

With a little algebraic manipulation, one can see that

Using these results we can construct our Full Adder using two Half Adders and an Or gate. To distinguish the C of the Half Adders from the C input of the Full Adder, we have labeled the latter Carryin.

To add two binary numbers of several bits, one need only join Full Adders together, one for each bit in the number.

Since the carry ripples from right to left, this adder is called a ripple-carry adder.

Note: in the above diagram, the indices go from right to left while in most of our labs we have had indices go from left to right.

Exercise 1:

Using the above discussion, design a Verilog HDL module for a half adder.

Since we want to realize the adder as a logical circuit, we want to use the primitive or built-in modules of Verilog HDL. Therefore, we will use the primitive modules of and, or and xor. For example,

		and and1(out, in1, in2);
is an "and" gate labeled "and1" with inputs in1 and in2. As in all the built-in primitive gates, the output is the first parameter and you may have two or more inputs. For example, you may have a four input and.

Test your module to be confident it works.

The semantics of the module construct in Verilog is very different from subroutines, procedures and functions in other languages. A module is never called! A module is instantiated at the start of the program and stays around for the life of the program. A Verilog module instantiation is used to model a hardware circuit where we assume no one unsolders or changes the wiring. Each time a module is instantiated, we give its instantiation a name. For example, and1 is the name of the instantiation of the and gate in the above code.

For later parts of this Lab, it is important that you use the built-in primitive modules, e.g., and, and not the & operator.

Exercise 2:

Using two instantiations of your half adder module, design a full adder module. See above discussion for the design. Note that only wires connect modules in Verilog HDL. Verilog will allow you to specify a register as input to a combinational logic circuit but it never allows a register as an output. reg variables can be assigned only inside of Verilog processes, i.e., the initial and always constructs.

Test your module to be confident it works.

Note: the modules for halfadder, fulladder and tester may be in separate files. Then you would compile and simulate the files together similar to the following:

           veriwell halfadd.v fulladd.v main.v

Exercise 3:

Using your full adder module, design a Verilog HDL module for a 16-bit ripple carry adder.

Test your 16-bit adder by connecting the inputs to two 16-bit registers and observing the 16-bit Sum wires and Carry wire.

Hand in the code for the modules and runs which show the 16-bit adder working.

Exercise 4:

In this exercise, you incorporate gate delays into your 16-bit adder. Do this by changing all the lines in Exercise 3 that use the Verilog primitive modules and, or and xor, to include a #gatedelay as shown:

		and #gatedelay and1(out, in1, in2);
Set gatedelay to 1 by a parameter statement. With a little experimenting, you will see that it takes a variable amount of simulation time for the output wires of the 16-bit adder to become stable.

What is the worst case? That is, what is the maximum time for the 16-bit adder to settle down? Devise a test case which demonstrates this worst case. State on the output the maximum time, i.e., the maximum gate delays, and discuss why.

Hand in the code for the modules, test run for your worst case and your discusssion.

Exercise 5:

Incorporate your 16-bit adder of Exercise 4 (with gate delays of 1) into your Ultra3 computer of Lab 3. To simplify the Lab, do it only for the "+" operation in the add instruction.

Now what should you set as your clock period? It is NOT 1!

Incorporating your combinational circuit for the 16-bit adder into the control sequence of the Ultra3 (statements inside the always construct) can be confusing. Remember to instantiate your 16-bit adder, say Add16, outside of the always construct. The instantiation, e.g., Add16a represents a digital circuit which exist for the life of the program. It has wires for output, i.e., Sum and Carry, as shown below. You sample these wires when you want to use them in a register transfer.

        wire [0:15] Sum;
wire Carry;
Add16 Add16a(AC, MD, Sum, Carry);
always begin
// #clock AC <= AC + MD; <---The old line
#clock AC <= Sum; end
Hand in listing of the modules and a run of the test program of Lab 3 to show that it works with the new 16-bit adder.

Page maintained by Dan Hyde, hyde at bucknell dot edu Late update October 1, 2007
Back to CSCI 320 Home Page.