COMP311: Lab 3.1

Getting started!

Lab 3.1 is intended as a continuation of Lab 3. In this lab, you will upgrade the Lab 3 ALU, which used separate control fields, into a RISC-V-style datapath ALU. You should begin from your completed Lab 3.

There is no additional starter circuit for this lab. Instead, you will copy your completed Lab 3 files into a new folder and modify them to match the Lab 3.1 specification.

You will need to copy your completed Lab 3.1 files into Lab 5 folder later!

To begin:


ALU

In this lab you will design the 32-bit ALU used by our RISC-V datapath.

The ALU you build here will be reused later when we construct a full processor. Because of this, the control interface and supported operations are chosen to match the subset of RISC-V instructions we will implement later in the course.

You will start by designing several sub-units, then combine them into a full ALU.


ALU Operations

Your ALU will support the following operations:

ALUOp Operation
0b0000 AND
0b0001 OR
0b0010 ADD
0b0011 XOR
0b0100 SLL
0b0101 SRL
0b0110 SUB
0b0111 SLT
0b1000 SRA

Later in the course, your control unit will generate ALUOp values from RISC-V instructions.

If you have already completed Lab 3, you may reuse your completed sub-units from that lab and proceed directly to Exercise 5 after updating your files for Lab 3.1 following instructions in To begin above.


Exercise 1: Boolean Unit

We begin by building the Boolean Unit, which performs bitwise logical operations.

Ensure all components are 32 bits.

Components

Think carefully:

A local tester for the Boolean Unit is provided. It works the same way as in Lab 3. DO NOT change the names of the inputs or outputs.

Common Error

“There are one bits needed, but 32 bits found.”

This means at least one component does not have the correct bit width. Verify that all components are 32 bits.


Exercise 2: Shifter Unit

Barrel Shifter Component

You will use the Barrel Shifter component:

Components → Arithmetic → Barrel shifter

Inputs

in
Value being shifted. This corresponds to the B input of our ALU.

shift
Shift amount. This corresponds to the lower 5 bits of A.

The Digital barrel shifter requires:

shift width = ceil(log2(input width + 1))

For a 32-bit input this means 5 bits.

You will therefore need to use a splitter to extract A[4:0].

Shift Types

Each barrel shifter performs only one operation, so your design will include three shifters:

Change these by modifying the Direction and Mode settings.

Tips


Exercise 3: Add/Sub Unit

Compute:

Use:

A - B = A + (~B + 1)

Addition

Use the Adder component.

Make sure the bit width is 32.

Subtraction

You may not use the Subtract component.

Instead compute:

A - B = A + (~B + 1)

You will therefore:

  1. Invert B
  2. Add 1
  3. Add the result to A

Sign

Sign is a one bit output that indicates the sign of our result. If Sign is 1, the result is negative. If Sign is 0, the result is positive.

Sign of Out Value of Sign
positive 0
negative 1

Overflow

Overflow is a one-bit output that will indicate if the operation overflowed. If Overflow is 1, overflow occurred. If Overflow is 0, overflow did not occur.

How do we know if overflow occurred? Recall the following information from COMP 211:

Operation Overflow occurs when
Adding two positive numbers The result is negative
Adding two negative numbers The result is positive
Adding two numbers of opposite signs Overflow will never occur

Adding two positive values should yield a positive result, so if the result is negative, this indicates that overflow has occurred. Adding two negative values should yield a negative result, so if the result is positive, this indicates that overflow has occurred. When adding numbers with opposite signs, overflow is not possible, as the sum always remains within the representable range of values for the given number of bits.

Ok, so we know how to detect overflow for additions. What about subtractions? Well, the circuit we built only performs addition (to perform subtraction, we negate B and add it to A), so we only need to know how to detect overflow when performing addition.

To implement the circuit that will detect overflow, start by filling out the table below. Then generate your equation and build your circuit!

Sign of A Sign of B Sign of Result Overflow?
0 0 0
0 0 1
0 1 0
0 1 1
1 0 0
1 0 1
1 1 0
1 1 1

Testing

A local add-sub unit tester is provided. It works the same as the testers for the previous components.

We recommend that you test incrementally. Implement the features in the order provided below. Test each feature before moving onto the next one. Following this process will save you a lot of headaches!

This video provides guidance on testing your add-sub unit incrementally.

  1. Implement addition. Verify that your circuit produces the correct Out value. Ignore Sign and Overflow for now.
  2. Implement subtraction. Verify that your circuit produces Out value for both addition and subtraction. Ignore Sign and Overflow for now.
  3. Implement and test Sign.
  4. Implement and test Overflow.

Exercise 4: SLT Unit

We now implement the Set-on-Less-Than (SLT) operation.

This corresponds to the RISC-V instruction:

slt rd, rs1, rs2

If A < B, output 1, otherwise 0.

Deliverable: slt-unit.dig

Method

We determine A < B by computing:

A - B

If the result is negative, then A < B.

However, overflow can invert the sign, so we must account for this.

Use the outputs from the Add/Sub unit:

Overflow Sign A < B
0 0 0
0 1 1
1 0 1
1 1 0

Derive the Boolean equation and implement the circuit.


Exercise 5: Full ALU

If you start from your previous alu.dig from Lab 3, Digital may show a custom component error. This happens because the old ALU used comparator.dig, but we have renamed it to slt-unit.dig. To fix this, replace it with the slt-unit custom component.

Your ALU had separate control inputs for sub, Bool, and Op. In this task, you will modify the interface of the ALU so that it takes in a 4-bit ALUOp control signal that encodes the sub, Bool, and Op control signals.

Your final ALU should have the following interface:

A[31:0]  ────────────────▶   ┌──────────────────────┐
                              │                      │
B[31:0]  ────────────────▶   │                      │───▶  Result[31:0]
                              │         ALU          │
ALUOp[3:0] ───────────▶      │                      │───▶  FlagZ
                              └──────────────────────┘

Add your custom components:

Components → Custom

Add:

Use tunnels to keep wiring manageable.

Your ALU must support the following operations:

ALUOp Operation
0b0000 AND
0b0001 OR
0b0010 ADD
0b0011 XOR
0b0100 SLL
0b0101 SRL
0b0110 SUB
0b0111 SLT
0b1000 SRA

Hint (One way to tackle this down)

If you are modifying your old Lab 3 alu.dig, try keeping the original sub-units and final result mux structure (Mux now has add-sub output, SLT32, Shift output and boolean-unit output as its four selections). Use Comparators to check whether ALUOp[3:0] matches each operation code, then use those outputs to build the older internal control signals (Sub, Bool, and Selecting for final mux). For example, SUB and SLT should both cause the Add/Sub Unit to subtract, so they can share the same internal Sub control.


New Test Cases

Replace the test cases in your local ALU test with the test cases in alu-test.txt: Right click on Green Test block in alu.dig → Copy and paste everything in txt file over the original test cases from lab 3 → This will be the tests for lab 3.1!


SLT Output

The SLT unit produces a 1-bit result, but the ALU output must be 32 bits.

Zero-extend the value:

1 → 0x00000001
0 → 0x00000000

Use a splitter/merger to perform this extension.


Zero Flag

FlagZ indicates whether the ALU result is zero.

FlagZ = 1  if Result == 0
FlagZ = 0  otherwise

Use the Comparator component:

Components → Arithmetic → Comparator

This component may NOT be used for SLT.