Lab5: Signed & Unsigned
Time Estimate2-4 Hours Grade Impact2.5% DueSep 30 @ 3pm Required for Pass
Objective
Implement a simple combinational circuit.
Additional Materials & Formats
Check Box for the most up-to-date versions of this lecture’s materials.
Warning
Before starting any lab, always read the entire lab description. You are working with expensive, fragile hardware. Look particularly closely at these boxes, which warn you of potential problems.
Before the Lab
Repository
Accept the invitation to this lab assignment’s Github repository on Canvas.
Equipment
Please bring the following equipment to this lab:
- Digilent Basys 3 FPGA board
- Compatible (power-and-data) USB cable
- Note taking mechanism (laptop, notebook, etc.)
Pre-Lab Work
This lab has pre-lab work, specified below. Pre-lab work is due within the first 30 minutes of the lab session designated for this lab (that is, 3:00pm on September 23).
Pre-Lab
Reviewing 2’s Complement Representation
In this lab, you will design and implement a 4-bit adder/subtractor that performs arithmetic on 2’s complement numbers. This module will form the foundation for arithmetic operations on signed integers.
2’s Complement Basics:
- Range for 4-bit 2’s complement: -8 to 7
- When the most significant bit (MSB) is 1, the number is negative
- Negative values are calculated as: $-2^3 + \text{lower bits}$
- For example:
1000= -8,1001= -7,1111= -1,0111= 7
4-Bit Adder/Subtractor Design
Before the lab, analyze and design a 4-bit 2’s complement adder/subtractor with the following requirements:
Module Interface:
Inputs: A[3:0] - First operand (4-bit 2's complement)
B[3:0] - Second operand (4-bit 2's complement)
subtract - Control signal (0 = add, 1 = subtract)
Outputs: result[3:0] - Sum or difference (4-bit 2's complement)
overflow - Overflow flag (1 if result exceeds ±8)
carry_out - Carry-out from MSB (useful for monitoring)Pre-Lab Tasks:
-
Derive the subtraction logic: Show how subtraction is implemented using 2’s complement arithmetic:
- To compute $A - B$: calculate $A + (-B)$ where $-B = \overline{B} + 1$ (invert and add one)
- Explain how a control signal can select between addition and subtraction using XOR gates
- Show the complete 4-bit adder structure with all carry chains
-
Overflow Detection: Derive a Boolean expression for overflow detection:
- Overflow occurs when adding two numbers with the same sign produces a result with a different sign
- Express this using the sign bits (MSBs) of $A$, $B$, and the result
- Hint: $\text{overflow} = (A[3] \cdot B[3] \cdot \overline{\text{result}[3]}) + (\overline{A[3]} \cdot \overline{B[3]} \cdot \text{result}[3])$
-
Carry Propagation: Explain how a ripple carry adder works and why carry bits propagate from the LSB to the MSB
- Draw a diagram showing the internal carry chain through all four full adders
- Explain when $c_{\text{in}} = 0$ (addition) vs. $c_{\text{in}} = 1$ (subtraction via 2’s complement)
-
Test Cases: Prepare a comprehensive set of test cases covering:
- Basic addition (positive + positive)
- Basic subtraction (positive - positive)
- Mixed signs (positive + negative, negative - positive)
- Negative operands (negative + negative, negative - negative)
- Overflow cases (e.g., $7 + 1 = -8$, $-8 - 1 = 7$)
- Edge cases (e.g., $0 + 0$, $0 - (-8)$, adding complements)
Deliverable Checkpoint
Submit your pre-lab work with:
- Complete derivation of the 4-bit adder/subtractor logic
- Boolean expressions for overflow detection
- A circuit diagram or detailed pseudocode showing the structure of your adder/subtractor module
- Truth table or comprehensive list of test cases (at least 15 examples) with predicted results
Vivado Tips
There are no deliverables for this section, only useful tips.
After launching a simulation, the window changes slightly and you will notice the following toolbar:
The most commonly used button on the toolbar is the play button with a (T) subscript. It runs the simulation for the additional time period set in this toolbar (in the case of the screenshot, 10 microseconds).
If your testbench does not contain a $finish statement, DO NOT click the plain play button, as it will attempt to simulate your design until the heat death of the universe.
Another useful button is the relaunch simulation button, denote by the circular arrow. This is faster than closing the simulation and reopening it. If you make changes to your testbench or verilog modules, you can press this button to relaunch the simulation and see the new results. However, if you changed which testbench you are running, you must close the simulation and relaunch it.
The following screenshot shows potential simulation errors you might encounter:
If the inputs/outputs are not green or are marked by X (for unknown) or Z (for high-impedance), there is an error! Blue high-impedance signals (marked with Z) show that a net has not been connected to an input or output. Basically, this is the equivalent of an unplugged appliance: the cable exists but is not currently being used. Red unknown signals (marked with X) can mean that (a) the inputs have not propagated all the way to the outputs of the circuit yet, or (b) the outputs are never assigned a value in the design.
By default, only the top signals declared in your testbench will show up on the waveform window. Sometimes, it’s useful to dig deeper into sub-modules and sub-signals to find out what may be causing an error. To do this, click on the scope window and then on the drop down for the testbench. There you will find all the modules that are being tested, click on one of the submodules then the objects window will show all the signals in that module. From here you can right click and add them to the waveform window. You must relaunch the simulation to see the changes take effect.
One last tip: sometimes it may be hard to verify that all the connections between modules are correct just by looking at the Verilog code. Thankfully, Vivado provides a graphical representation of the design. This can be found by clicking the RTL ANALYSIS drop down then the Open Elaborated design drop down. Here you will find a Schematic option, click on it and it should open up a diagram like the following screenshot. This makes it much easier to follow connections down into sub modules. You can expand the module to see whats underneath by clicking the + symbol next to each module. As an added bonus, when you open the RTL schematic it also performs a check on your constraints file. If you have errors in your constraints file, running RTL analysis is much faster to report back problems than waiting for synthesis and implementation to run just to report back an error
Lab Setup
- Clone the assignment repository:
git clone <url> <custom_name> - Start Vivado
- Create a new project called
AddSubtract
Implementation Strategy
4-Bit Adder/Subtractor Module
Create a new module called AddSubtract4Bit that performs 2’s complement addition and subtraction:
module AddSubtract4Bit(
input [3:0] A,
input [3:0] B,
input subtract, // 0 = add, 1 = subtract
output [3:0] result,
output overflow,
output carry_out
);
wire [3:0] B_adjusted;
wire [4:0] sum; // 5 bits to capture carry_out
// Implement 2's complement subtraction:
// If subtract=1, compute -B by inverting and adding 1
// XOR with subtract signal: if subtract=1, invert B; otherwise pass through
assign B_adjusted = B ^ {4{subtract}};
// Perform addition with conditional carry-in
// carry_in = 1 when subtracting (to implement +1 in 2's complement)
assign sum = A + B_adjusted + subtract;
assign result = sum[3:0];
assign carry_out = sum[4];
// Overflow detection: occurs when same-sign operands produce opposite-sign result
// Adjusted B represents the actual second operand in the operation
wire B_sign = B_adjusted[3];
assign overflow = (A[3] == B_sign) & (result[3] != A[3]);
endmoduleImplementation Details:
-
XOR with subtract signal:
B ^ {4{subtract}}conditionally inverts all bits of B- When
subtract = 0: $B \text{ XOR } 0 = B$ (pass through) - When
subtract = 1: $B \text{ XOR } 1 = \overline{B}$ (invert)
- When
-
Carry-in control: The
+ subtractterm adds 1 to the sum only when subtracting- This completes the 2’s complement operation: $-B = \overline{B} + 1$
-
5-bit sum: Captures the carry-out from the MSB position, useful for debugging and monitoring
-
Overflow detection: Compares the signs of the two operands (after adjustment) with the result sign
- No overflow if operands have different signs (adding a positive and negative always fits)
- Overflow if both operands have the same sign but result has a different sign
Top-Level Module
Create a top-level module that connects the adder/subtractor to your FPGA board’s inputs and outputs:
module AddSubtractTop(
input [7:0] sw,
input [4:0] btn,
output [3:0] an,
output [6:0] seg,
output [15:0] led
);
wire [3:0] A = sw[7:4];
wire [3:0] B = sw[3:0];
wire subtract = btn[0]; // Button 0 controls add/subtract
wire [3:0] result;
wire overflow, carry_out;
AddSubtract4Bit ALU(
.A(A),
.B(B),
.subtract(subtract),
.result(result),
.overflow(overflow),
.carry_out(carry_out)
);
// Display result on LEDs for easy verification
// Use upper byte for result, lower byte for flags
assign led[3:0] = result;
assign led[4] = overflow;
assign led[5] = carry_out;
assign led[15:6] = 10'b0;
// Optional: Display result on seven-segment
// For now, just turn off displays
assign an = 4'b1111;
assign seg = 7'b1111111;
endmoduleDesign Choices:
- Input mapping: Upper four switches (sw[7:4]) → operand A; lower four switches (sw[3:0]) → operand B
- Control: Button 0 selects between addition (0) and subtraction (1)
- Output: LEDs display the result and status flags for easy verification
- Future expansion: Seven-segment display can be added later to show formatted results
Simulation Test Bench
Create a comprehensive testbench that verifies all aspects of the adder/subtractor:
module AddSubtract4BitTest;
reg [3:0] A, B;
reg subtract;
wire [3:0] result;
wire overflow, carry_out;
AddSubtract4Bit DUT(
.A(A),
.B(B),
.subtract(subtract),
.result(result),
.overflow(overflow),
.carry_out(carry_out)
);
initial begin
// Test 1: Basic addition (3 + 5 = 8, overflow)
A = 4'b0011; B = 4'b0101; subtract = 0; #10;
// Test 2: Basic subtraction (5 - 3 = 2)
A = 4'b0101; B = 4'b0011; subtract = 1; #10;
// Test 3: Subtraction resulting in negative (3 - 5 = -2)
A = 4'b0011; B = 4'b0101; subtract = 1; #10;
// Test 4: Addition with negative operand (5 + (-3) = 2)
A = 4'b0101; B = 4'b1101; subtract = 0; #10;
// Test 5: Negative + negative (-2 + -3 = -5, no overflow)
A = 4'b1110; B = 4'b1101; subtract = 0; #10;
// Test 6: Overflow case (7 + 1 = -8)
A = 4'b0111; B = 4'b0001; subtract = 0; #10;
// Test 7: Overflow case (-8 - 1 = 7)
A = 4'b1000; B = 4'b0001; subtract = 1; #10;
// Test 8: Zero operand (0 + 5 = 5)
A = 4'b0000; B = 4'b0101; subtract = 0; #10;
// Test 9: Subtract from zero (0 - 5 = -5)
A = 4'b0000; B = 4'b0101; subtract = 1; #10;
// Test 10: Adding inverses (5 + (-5) = 0)
A = 4'b0101; B = 4'b1011; subtract = 0; #10;
// Test 11: Double negative (-5 - (-3) = -2)
A = 4'b1011; B = 4'b1101; subtract = 1; #10;
// Test 12: Minimum value addition (-8 + 0 = -8)
A = 4'b1000; B = 4'b0000; subtract = 0; #10;
// Test 13: Maximum value addition (7 + 0 = 7)
A = 4'b0111; B = 4'b0000; subtract = 0; #10;
// Test 14: Subtract to minimum (-7 - 1 = -8)
A = 4'b1001; B = 4'b0001; subtract = 1; #10;
// Test 15: Subtract to maximum (6 - (-2) = 8, overflow)
A = 4'b0110; B = 4'b1110; subtract = 1; #10;
$stop;
end
endmoduleVerification Steps:
- Run the simulation and observe the waveforms for each test case
- Verify that
result[3:0]matches your pre-lab predictions - Confirm that
overflowflag is asserted only for tests 6, 7, and 15 - Check that
carry_outreflects the carry from the MSB position - Use the waveform viewer to trace through the carry propagation in a few cases
Hardware Testing
Program your board with the top-level module and verify functionality:
-
Basic Tests: Set switches and observe results on the LEDs
- Flip sw[0] on and off to switch between add and subtract modes
- Observe the result and flag bits changing on the LEDs
-
Overflow Verification: Test cases that cause overflow
- Set A = 7 (0111), B = 1 (0001), subtract = 0 → result = -8 (1000), overflow = 1
- Set A = -8 (1000), B = 1 (0001), subtract = 1 → result = 7 (0111), overflow = 1
-
Sign Handling: Verify correct handling of negative operands
- Set A = 5 (0101), B = -3 (1101), subtract = 0 → result = 2 (0010)
- Set A = -2 (1110), B = -3 (1101), subtract = 0 → result = -5 (1011)
-
Boundary Conditions: Test edge cases
- Set A = 0, B = 0 → result = 0
- Set A = -8 (1000), B = 0 → result = -8
- Set A = 7 (0111), B = 0 → result = 7
Deliverable Checkpoint: Simulation
Submit your simulation results showing:
- Waveforms for all 15+ test cases
- Verification that results match pre-lab predictions
- Confirmation of overflow flags at the correct times
Tag your commit
simulationand push tags.
Deliverable Checkpoint: Hardware
Demonstrate your successful program to the instructor in-person or by recording a video showing:
- At least 10 different test cases with switches and button input
- Clear observation of result and flag bits on the LEDs
- Multiple overflow cases to verify the overflow detection logic
- Switching between add and subtract modes with the same operands
Tag your commit
hardwareand push tags.
Deliverables
Indicate to your instructor that you’re ready to submit your work by leaving a comment on the Feedback PR and requesting a review from @mossbiscuits. Ensure that your submission is on the main branch. Create a tag named done to mark your submission:
git tag -a done -m "Lab2 submission"
git push origin doneIf you took photos, screenshots, or videos, remember to upload them to Box or OneDrive and link to them in the Feedback PR. Alternatively, you can submit these items directly on Canvas.
To receive 100 points, submissions must include evidence of the following:
- (10) Correct use of Github repository for this course
- (30) Correct simulation of the behavioral AND gates
- (30) Working implementations of the behavioral AND gate descriptions on the FPGA board
- (30) Correct simulation of
moreandgatesusing alternative testbench