Lab 3: RISC-V ALU

Due: November 6 at 11:59 p.m.

In this lab, you will build a 32-bit arithmetic logic unit (ALU) in Digital. Your ALU will perform arithmetic, bitwise logic, shifts, and signed comparisons for our RISC-V processor. You will reuse it in Lab 4, when you build a CPU.

Build and test the Boolean, shifter, add/sub, and SLT sub-units in Exercises 1–4. In Exercise 5, connect them to a single ALUOp control input to complete the ALU.

Getting started

You can accept the assignment on classroom50 here.

Once the assignment is released, accept it and clone your repository. Open the starter circuits directly in Digital. They contain named input/output pins and a green Test block; you will build the logic and wiring.

Keep these supplied circuit files together in your Lab 3 folder:

You may move the supplied pins, but do not change their names or widths. Save each sub-unit before inserting it into another circuit using Components → Custom. All data inputs and results are 32 bits unless otherwise specified; control signals and flags have their own widths.

ALU interface and operations

The final circuit, alu.dig, has inputs A (32 bits), B (32 bits), and ALUOp (4 bits), and outputs Result (32 bits) and FlagZ (1 bit).

ALUOp Operation Result
0000 AND Bitwise A AND B
0001 OR Bitwise A OR B
0010 ADD A + B
0011 XOR Bitwise A XOR B
0100 SLL A shifted left by B[4:0], filling with zeros
0101 SRL A shifted right by B[4:0], filling with zeros
0110 SUB A − B
0111 SLT 1 if signed A < signed B; otherwise 0
1000 SRA A shifted right by B[4:0], copying A’s sign bit

Operation codes are binary. Keep only the low 32 bits of arithmetic results. Signed values use two’s complement. For shifts, A is the value being shifted and B supplies the shift amount; only the lowest five bits of B are used.

These ALUOp codes are our course’s internal control signals, not RISC-V instruction opcodes. In Lab 4, your CPU control unit will generate them. The remaining ALUOp codes are not tested.

Exercise 1: Boolean unit

Deliverable: boolean-unit.dig

Implement bitwise AND, OR, and XOR using logic gates and a mux.

Pin Direction Width Meaning
A, B Input 32 Operands
Bool Input 2 00: AND; 01: OR; 10: XOR
Out Output 32 Selected Boolean result

The 11 selector value is not tested. Set gates and mux data paths to 32 Data Bits. The mux selector is 2 bits, not 32 bits.

Building the unit

Connect A and B to each of the three logic gates, then use a mux to choose which gate’s result reaches Out. Right-click a component to change its Data Bits. For the mux, set Number of Selector Bits to match Bool.

Think about which mux input is selected by each Bool value. Connect the unused input to a 32-bit constant 0 so it is not left floating.

Testing

Test each operation before moving on. Use operands with a mixture of zeros and ones so that AND, OR, and XOR produce different results.

If Digital reports “There are one bits needed, but 32 bits found,” check the widths at that connection. Data paths are 32 bits; selectors and flags use the smaller widths in the interface tables. Constants must also match the width of the wires they drive.

Exercise 2: Shifter unit

Deliverable: bidirectional-shifter.dig

Pin Direction Width Meaning
A, B Input 32 Value and shift amount, respectively
ShiftOp Input 2 00: SLL; 01: SRL; 10: SRA
Out Output 32 Selected shift result

Use three Barrel shifter components, available under Components → Arithmetic, and a mux. Set each shifter’s data width to 32 bits. Configure one for logical left shift, one for logical right shift, and one for arithmetic right shift. Do not use rotation. The 11 selector value is not tested.

Digital barrel shifter with in, shift, and out pins

Connect A to the shifters’ data inputs. Use a splitter to extract B[4:0] for the shift amount. Configure the shift amount as unsigned. If your Digital version expects a wider shift input, zero-extend these five bits to the required width; do not include higher bits of B.

Right-click each shifter to set its Direction and Mode, and give it a label identifying its operation. In the settings shown below, change Data Bits to 32 and leave shift input has sign unchecked. That setting concerns the shift amount; arithmetic right shift still copies the sign bit of A.

Barrel shifter settings dialog; set Data Bits to 32

Connect the three results to a mux controlled by ShiftOp. Connect the unused mux input to a 32-bit constant 0.

Testing

Test shift amounts 0, 1, and 31. Also test a value with its most significant bit set: SRL and SRA should produce different results when shifting it right.

Exercise 3: Add/sub unit

Deliverable: add-sub-unit.dig

Add/sub unit with A, B, and Sub inputs and Out, Overflow, and Sign outputs

Pin Direction Width Meaning
A, B Input 32 Operands
Sub Input 1 0: addition; 1: subtraction
Out Output 32 Arithmetic result
Sign Output 1 Most significant bit of Out
Overflow Output 1 Signed overflow indicator

Use a 32-bit Adder component. You may not use the Subtract component. Implement subtraction using:

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

Use Sub to control whether B is inverted and whether the initial carry-in is 1. Addition must still work when Sub=0.

Digital adder with operand and carry-in inputs and sum and carry-out outputs

The adder’s s output supplies Out. Its carry-in is one bit. If you use XOR gates to conditionally invert B, you will need a 32-bit mask controlled by Sub; sign-extending the one-bit control is one way to create that mask.

Sign and overflow

Sign is bit 31 of Out. A sign bit of 0 represents a nonnegative result, including zero. When signed overflow occurs, the stored result does not represent the correct mathematical answer.

Use the signs of the original A and B inputs and the stored result to detect signed overflow:

Operation Signed overflow occurs when
ADD A and B have the same sign, but the result has the opposite sign
SUB A and B have different signs, and the result’s sign differs from A’s

Derive the logic for Overflow, including the Sub control. A carry-out alone does not indicate signed overflow.

Use this truth table to work out the two cases before combining them with Sub:

A[31] B[31] Out[31] Overflow when Sub=0 Overflow when Sub=1
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

  1. Implement addition and check Out.
  2. Implement subtraction and check Out for both operations.
  3. Connect and test Sign.
  4. Implement and test Overflow.

Include these checks (values are hexadecimal):

A B Sub Out Sign Overflow
00000004 00000005 0 00000009 0 0
7FFFFFFF 00000001 0 80000000 1 1
00000003 00000001 1 00000002 0 0
80000000 00000001 1 7FFFFFFF 0 1
00000000 80000000 1 80000000 1 1

Exercise 4: SLT unit

Deliverable: slt-unit.dig

The SLT unit takes one-bit inputs named Sign and Overflow from the add/sub unit and produces a one-bit output named Out. For SLT, the add/sub unit must compute A − B.

A negative subtraction result usually means A < B, but overflow can reverse the stored sign. Derive and implement the Boolean equation from this table:

Overflow Sign Out: signed A < signed B
0 0 0
0 1 1
1 0 1
1 1 0

Do not use Digital’s Comparator component to implement SLT. Test all four input combinations, then test it together with the add/sub unit using both ordinary and overflowing subtractions.

Exercise 5: Full ALU

Deliverable: alu.dig

Combine your four sub-units using the final interface and operation table above. Use tunnels to keep the wiring readable.

Connect the sub-units

Insert your saved circuits using Components → Custom. Send A and B to the Boolean, shifter, and add/sub units. Connect the add/sub unit’s Sign and Overflow outputs to the SLT unit. The SLT unit uses this subtraction result; it does not need a second subtractor.

Decode and select

  1. Decode the 4-bit ALUOp into the internal controls needed by your sub-units. The Boolean and shift selectors are internal signals; they are not extra inputs to the final ALU.
  2. Make the add/sub unit subtract for both SUB and SLT.
  3. Select the correct sub-unit result for each operation. You may use muxes and equality comparisons against operation codes to build the selection logic.
  4. Zero-extend the SLT output to 32 bits: a true comparison produces 00000001, and a false comparison produces 00000000 (hexadecimal).
  5. Generate FlagZ from the selected final Result: it is 1 exactly when Result is zero, for every supported operation.

You may use a 32-bit Comparator to check whether Result equals zero. The restriction on Comparators applies to implementing SLT.

One way to organize the final selection is a four-input, 32-bit mux: Boolean result, shift result, arithmetic result, and zero-extended SLT result. Derive its selector and the sub-unit controls from ALUOp. The encodings for Bool and ShiftOp are given in their interface tables; do not assume the low bits of ALUOp already match them.

Check the whole path for one operation at a time: decode the operation, verify the sub-unit output, verify the selected Result, then check FlagZ.

Testing

Each starter circuit includes local tests in its green Test block. Run that circuit’s test cases in Digital after implementing it. The same tests are included as text files in the repository’s tests/ folder. Keep the supplied expected outputs unchanged; you may add your own cases. The unfinished starter circuits will not pass until you wire them.

Download the ALU check cases. This CSV lists inputs and expected outputs for manual testing; it is not a Digital test-block file. A, B, and Result are hexadecimal, ALUOp is binary, and FlagZ is a single bit.

Test your sub-units before testing the full ALU. The supplied cases cover every operation, signed comparisons, overflow edge cases, and shift amounts. Add your own cases as well; passing these examples alone does not establish that every input works.

Submission

Submit all five .dig files, together with any additional custom circuit files they depend on, to the course’s Lab 3 assignment on Gradescope. Follow the repository/submission directions posted with the classroom50 assignment when it is released.

Before submitting, open alu.dig from the folder you will submit and confirm that all custom components load. Keep a working copy for Lab 4.