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!
comparator.dig to
slt-unit.dig.alu-test.txt and place it into the Lab 3.1
folder.lab3.1 folder and do not proceed to
Exercise 5 until you have passed the tests for Exercises 1–4.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.
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.
We begin by building the Boolean Unit, which performs bitwise logical operations.
Ensure all components are 32 bits.
Data Bits.Number of Selector Bits.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.
“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.
You will use the Barrel Shifter component:
Components → Arithmetic → Barrel shifter
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].
Each barrel shifter performs only one operation, so your design will include three shifters:
Change these by modifying the Direction and Mode settings.
Compute:
OutSignOverflowUse:
A - B = A + (~B + 1)
Use the Adder component.
Make sure the bit width is 32.
You may not use the Subtract
component.
Instead compute:
A - B = A + (~B + 1)
You will therefore:
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 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 |
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.
Out value. Ignore Sign and
Overflow for now.Out value for both addition and subtraction. Ignore
Sign and Overflow for now.Sign.Overflow.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.
slt-unit.digWe 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:
SignOverflow| Overflow | Sign | A < B |
|---|---|---|
| 0 | 0 | 0 |
| 0 | 1 | 1 |
| 1 | 0 | 1 |
| 1 | 1 | 0 |
Derive the Boolean equation and implement the circuit.
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:
Boolean UnitShifter UnitAdd/Sub UnitSLT UnitUse 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 |
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.
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!
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.
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.