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:

  1. 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
  2. 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])$
  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)
  4. 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

  1. Clone the assignment repository: git clone <url> <custom_name>
  2. Start Vivado
  3. 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]);
    
endmodule

Implementation 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)
  • Carry-in control: The + subtract term 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;
    
endmodule

Design 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
endmodule

Verification Steps:

  1. Run the simulation and observe the waveforms for each test case
  2. Verify that result[3:0] matches your pre-lab predictions
  3. Confirm that overflow flag is asserted only for tests 6, 7, and 15
  4. Check that carry_out reflects the carry from the MSB position
  5. 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:

  1. 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
  2. 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
  3. 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)
  4. 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 simulation and 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 hardware and 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 done

If 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 moreandgates using alternative testbench