Table of Contents
In this lab you will implement a two’s complement binary adder and an overflow detector in a hierarchical design and demonstrate the ability to perform binary addition and subtraction and overflow detection.
The average time to complete this lab is 4.6 hours.
Learning Outcomes
- Demonstrate understanding of two’s complement addition, subtraction, and overflow detection
- Develop a hierarchical design with three levels of hierarchy
- Validate the circuit with a testbench
Preliminary
In this preliminary exercise, you will work through some binary arithmetic examples. Answer the following questions to demonstrate your understanding of two’s complement representation, sign extension, negation, addition, subtraction, and overflow detection. You may want to refer to Chapter 3 of the textbook specifically as you complete this preliminary work.
Determine the decimal value for the following eight-bit two’s complement binary numbers: (See Section 3.3)
10000100
00011001
Extend each of the following numbers to nine bits using sign-extension. Include leading zeros in the binary result: (See Section 3.3.1)
10000100
00011001
Negate each of the following eight-bit two’s complement numbers. Include leading zeros in the binary result: (See Section 3.3.2)
10000100
00011001
Overflow can be detected by inspecting the sign bit of the operands and the result. The sign bit is the MSB. If the sign bit of the two operands are different, then overflow cannot occur. If the sign bit of the result is opposite the two operands, two’s complement overflow has occurred.
Perform addition with the following eight-bit two’s complement numbers. Include leading zeros in the binary result. Indicate if overflow occurs with a ‘#’ sign at the beginning of the 8-bit result: (See Sections 3.3.3 and 3.5.1)
1) 10000100
+ 01100100
2) 01111111
+ 01100111
3) 11100110
+ 10110111
4) 10000100
+ 10011001
Subtraction can be performed with an adder circuit if the second operand is inverted before the operation and the carry-in is set to one. This method is equivalent to negation of the second operand followed by addition. In the following cases, you should negate the second number and then use two’s complement addition to calculate the result.
Perform subtraction with the following eight-bit two’s complement numbers. Include leading zeros in the binary result. Indicate if overflow occurs with a ‘#’ sign at the beginning of the 8-bit result: (See Sections 3.3.2, 3.3.3, and 3.5.1)
1) 10000100
- 01100100
2) 01111111
- 10011001
3) 01111111
- 01100111
Exercises
In this exercise, you will create an 8-bit two’s complement full adder for implementing arithmetic. You will do this with two SystemVerilog files:
- A single-bit full adder module (
full_add) - A multi-bit adder that combines eight single-bit adders (
add_8)
This is a classical hierarchical design: you will create a simple 1-bit full adder module, and you will then create a new module and instance 8 of your 1-bit adders inside it to build up your circuit.
Exercise #1: 1-bit Full Adder
Create an empty SystemVerilog file named full_add/full_add.sv and add the following ports to this module as described in the table below:
| Module Name: full_add | |||
|---|---|---|---|
| Port Name | Direction | Width | Function |
| a | Input | 1 | ‘a’ operand input |
| b | Input | 1 | ‘b’ operand input |
| cin | Input | 1 | Carry in |
| s | Output | 1 | Sum output |
| co | Output | 1 | Carry out output |
Once you have created the empty module with the ports outlined above, create the single-bit full adder cell as shown in Figure 9.2 of the text. Like the diagram, your circuit should include a 3-input XOR gate, three 2-input AND gates, and a 3-input OR gate. Note that you must use structural SystemVerilog to create this full adder cell. Although there are easier ways to create adder circuits using dataflow SystemVerilog, you are required to use structural SystemVerilog for this lab.
Make sure you follow the class’s SystemVerilog Coding Standards. In particular, pay attention to the following standards: S14
Include the file full_add/full_add.sv in your repository.
Once you have created your circuit, simulate the full adder by testing all possible input conditions.
Create a Tcl file named full_add/sim.tcl to provide the stimulus for this simulation.
The Tcl code below simulates two of the eight conditions.
# Simulate a=0, b=0, cin=0 for 10 ns
add_force a 0
add_force b 0
add_force cin 0
run 10 ns
# Simulate a=1, b=1, cin=1 for 10 ns
add_force a 1
add_force b 1
add_force cin 1
run 10 ns
You will need to create a full_add/Makefile similar to the ones provided in previous lab, so that you can access the rules in the common.mk file.
As a reminder, run make sim, to simulate your design using your sim.tcl file.
Include the file full_add/sim.tcl in your repository.
Exercise #2: 8-bit Adder
As mentioned above, this lab will involve hierarchy. This is covered in-depth in Chapter 11, but will be briefly explained here.
A circuit with hierarchy is a circuit that contains modules within modules.
In many complex digital logic circuits there are many levels of hierarchy.
In this circuit you will have three levels of hierarchy - your full_add, your add_8, and a top-level module.
For this step you will create the add_8 module which will instance eight full_add modules.
Program 11.1.1 in your textbook gives an example of instancing modules.
Begin the creation of an 8-bit ripple-carry adder by making a new SystemVerilog file named add_8.sv and add the following ports as shown in the table below:
| Module Name: add_8 | |||
|---|---|---|---|
| Port Name | Direction | Width | Function |
| a | Input | 8 | ‘a’ operand input |
| b | Input | 8 | ‘b’ operand input |
| cin | Input | 1 | Carry in |
| s | Output | 8 | Sum output |
| co | Output | 1 | Carry out of last stage |
After creating the empty module, create the needed local wires (you will need some, figure out where). For example, the carry signals that go between the various adder stages is one place where you will need them. You could declare each such carry signal individually with names like c3, c4, … Or, you could declare a multi-bit wire and use indexing with square brackets to get at the various bits. It is your choice.
Insert 8 instances of your full_add module into your add_8 module (as described in Section 9.1 of the textbook and as shown in the figure below).
You should use the .port(wire) way of mapping ports on instances to your wires (see Program 11.1.2 in the textbook).
Note that the co (1 bit) output of your add_8 is the carry-out of the last full_add instance.

Include the file add_8/add_8.sv in your repository.
Next you will simulate the behavior of your 8-bit adder.
Remember, you will need to create a Makefile and a sim.tcl file in order to use the make sim command.
Within your Makefile you will need to list both the full_add.sv and the add_8.sv files as SystemVerilog source files (since add_8 uses full_add).
You can do this like so:
SV_FILES = add_8.sv ../full_add/full_add.sv
In your simulation, provide at least one input condition for each of the following cases to test your adder. You could use the examples for addition in the Preliminary section above. Note that this 8-bit adder does not implement overflow detection. You will have to examine the simulation output to determine if there is overflow.
- Add a positive binary number to a negative binary number.
- Add two positive binary numbers without overflow.
- Add two positive binary numbers with overflow.
- Add two negative binary numbers without overflow.
- Add two negative binary numbers with overflow.
Rather than assigning each bit of an input with a single Tcl command, you can assign all 8 bits of an input with a single add_force command as shown in the following example:
add_force a 11000101
Include the file add_8/sim.tcl in your repository.
Exercise #3: Top-Level Design
For this exercise you will create a top-level design named arithmetic_top/arithmetic_top.sv that instances your 8-bit adder and connects your adder to a button, the switches and LEDs.
Both operands to the adder will be interpreted as two’s complement numbers.
Begin your design by creating a top-level module with the following name and ports.
| Module Name: arithmetic_top | |||
|---|---|---|---|
| Port Name | Direction | Width | Function |
| sw | Input | 16 | Switches (sw[15:8] = ‘b’, sw[7:0] = ‘a’ operand) |
| btnc | Input | 1 | Center button (subtract when pressed) |
| led | Output | 9 | LEDs (led[8] = overflow, led[7:0] = sum) |
NOTE: the name of the module and the ports are crucial – use what is in the table above.
The reason for using the exact names is that the testbench you will use below to prove your circuit works relies on the top-level module being called arithmetic_top and on the ports having the specified names.
A block diagram of the overall design is shown below.
It has an input signal called sub (refer to Figure 9.4).
The top-level circuit will perform addition when sub is 0 and subtraction when sub is 1.
The center button (btnc) serves as the sub signal. When btnc = 1'b0, addition is performed, and when btnc = 1'b1, subtraction is performed.
The sub signal must be connected to the carry-in input of the add_8 adder.

Inside your top-level module, the carry-out of the add_8 adder is not used, but you do need to connect something to it.
So, declare a local signal for it and connect it to the carry-out of the adder.
Do not connect this local signal to anything else — the synthesis tool will recognize that it is unused and discard it without issues.
The input btnc controls the inversion of the b input to the adder. When performing subtraction (btnc = 1’b1), the bits of b must be inverted before being passed to the adder.
As can be seen from the block diagram, the top-level module will also contain logic to implement overflow detection.
The output from the overflow detector is connected to led[8].
Overflow can be detected by looking at the signals a[7], b[7], and s[7]. Overflow occurs in one of the following cases:
- Both inputs are positive (a[7] = 0, b[7] = 0) but the result is negative (s[7] = 1).
- Both inputs are negative (a[7] = 1, b[7] = 1) but the result is positive (s[7] = 0).
This overflow logic can be expressed in a Boolean equation:
overflow = (a[7]' b[7]' s[7]) + (a[7] b[7] s[7]')
You must use built-in gates (e.g., not, and, or) to implement this circuit as part of the top-level module.
Key Implementation Notes:
- The
btncsignal directly controls both the carry-in of the adder and the inversion of b. - The sum output (
s) of the adder is assigned toled[7:0]. - The overflow detection output is assigned to
led[8]. - The unused carry-out signal from the add_8 adder should be connected to a local signal, which will be discarded during synthesis.
Include the file arithmetic_top/arithmetic_top.sv in your repository.
Viewing Hierarchy in Vivado
After completing your top-level design, you can view the hierarchy of your design in Vivado. Follow the Viewing Hierarchy Tutorial to learn how to generate a pre-synthesis schematic of your design, where hierarchy is expanded. After viewing this tutorial, create a schematic of your top-level design and expand the hierarchy as follows:
- Press “+” on the
add_8cell so you can see the top-level and the contents of theadd_8on the same schematic - Press “+” on the first
full_addcell so you can see the top-level,add_8, and onefull_addon the same schematic - Zoom out enough so you can see all three levels of hierarchy on the same schematic (don’t worry about missing small text details)
Take a screenshot of this schematic and name it arithmetic_top/pre-synth-schematic.png and include it in your lab repository.
Include the file arithmetic_top/pre-synth-schematic.png in your repository.
Exercise #4: Simulating with a Testbench
When you have completed your top-level design and removed all syntax errors, simulate your design manually using Tcl scripts to convince yourself that your circuit is working properly (the Tcl scripts are not required for your submission).
Once you believe your circuit is working properly, test your design with the testbench file tb.sv that has been included in your starter code:
make sim_tb
What time does the simulation start? (i.e., Starting simulation at time X ns)?
What time is the simulation done (in ns)?
How many test cases are applied in the testbench?
Exercise #5: Synthesize, Implement and Download
-
Begin this exercise by creating an XDC constraints file,
arithmetic_top/basys3.xdc.Follow the instructions in the Vivado Constraints Tutorial to create this file. Your XDC file should include an entry for each of the ports in the top-level design. As suggested in the tutorial, copy the provided
resources/basys3.xdcfile, and modify it as needed.Include the file
arithmetic_top/basys3.xdcin your repository. -
Run synthesis (
make synth).Carefully review the synthesis log (
work/synth.log) to make sure there are no Warnings.How many total LUT resources are used by the design? (add up all the LUT* resources)
How many total IBUF resources are used by the design?
How many total OBUF resources are used by the design?
-
View the post-synthesis schematic file, take a screenshot of this schematic, and name it
arithmetic_top/post-synth-schematic.png.Include the file
arithmetic_top/post-synth-schematic.pngin your repository.You will notice that unlike the pre-synthesis schematic you created in an earlier exercise, this schematic is “flat” meaning that there is no longer any hierarchy. All levels of hierarchy have been flattened into a single netlist using FPGA primitives.
-
Run implementation, and review the implementation log (
work/implement.log) to check for warnings. You may see a warning about There are no user specified timing constraints…, and Timing had been disabled…. You can ignore these warnings for this lab.How many
Sliceresources are used by the design from the utilization report? (UseSlicenotSlice LUTs)How many
Bonded IOBresources are used from the design from the utilization report? -
Download your design to the board and make sure your design operates properly. The TAs will be building your design and checking it themselves so make sure it works before submitting your lab.
Final Pass-Off
Refer to the passoff tutorial for the passoff process.
- See
required_filesin the passoff script. - Makefile rules that must work correctly and be free from errors and warnings:
Makefile:cleanarithmetic_top/Makefile:sim_tb,synth,implement
Answer the final two questions in your laboratory report:
How many hours did you work on the lab?
Provide any suggestions for improving this lab in the future