Week: 2
Points: 20
Time: ~5 hours
Deliverable: verilog/alu/ directory + diary/week-02.md
What you ship
verilog/alu/full_adder.v— full adderverilog/alu/adder32.v— 32-bit ripple-carry adderverilog/alu/alu.v— 32-bit ALU (ADD/SUB/AND/OR/XOR/SLT)lab2_testbench_output.txt— all tests passdiary/week-02.md
Lab 2.1: Full adder
Extend the half adder from Lab 1.4 to a full adder. The full adder accepts carry_in and produces sum and carry_out:
module full_adder(
input a, b, carry_in,
output sum, carry_out
);
wire sum1, carry1, carry2;
half_adder ha1(.a(a), .b(b), .sum(sum1), .carry(carry1));
half_adder ha2(.a(sum1), .b(carry_in), .sum(sum), .carry(carry2));
or_gate or1(.a(carry1), .b(carry2), .out(carry_out));
endmodule
Test all 8 input combinations. Verify 1+1+1 = 1 with carry_out = 1.
Lab 2.2: 32-bit ripple-carry adder
Wire 32 full_adder instances. Bit 0 has carry_in = 0 (or a sub control signal for subtraction):
module adder32(
input [31:0] a, b,
input sub, // 1 = subtract (inverts b, carry_in=1)
output [31:0] result,
output carry_out
);
wire [31:0] b_in = sub ? ~b : b;
wire [32:0] carry;
assign carry[0] = sub; // two's complement: flip + add 1
// wire 32 full_adder instances using generate or explicit instantiation
...
endmodule
Verify with the testbench: 20 test cases including at least:
0 + 0 = 01 + 1 = 20xFFFFFFFF + 1 = 0withcarry_out = 1(overflow)10 - 3 = 7withsub = 10 - 1 = 0xFFFFFFFF(unsigned underflow)
Lab 2.3: ALU
Write alu.v with ADD, SUB, AND, OR, XOR, SLT operations selected by op[2:0]:
| op | Operation |
|---|---|
| 3'b000 | ADD |
| 3'b001 | SUB |
| 3'b010 | AND |
| 3'b011 | OR |
| 3'b100 | XOR |
| 3'b101 | SLT (set less than: signed comparison) |
Also output zero = (result == 0) which the CPU uses for BEQ/BNE.
Run lab2_alu_tb.v: at least 10 test cases per operation (60 cases total). All must pass.
Lab 2.4: IEEE-754 hand encoding
This is a hand exercise, not a Verilog lab. Encode these three values in IEEE-754 single precision (32-bit):
| Value | Sign | Biased exponent | Mantissa (fraction) | Hex |
|---|---|---|---|---|
1.5 |
||||
-0.75 |
||||
0.1 |
Verify with Python:
import struct
for v in [1.5, -0.75, 0.1]:
print(f"{v}: {struct.pack('>f', v).hex()}")
Note: 0.1 does not have an exact binary representation. Record the rounding in your diary.
Toolchain Diary
Record in diary/week-02.md:
- Gate depth of your
adder32.v: count the longest propagation path from any primary input to any output - Whether you used
generateor explicit instantiation for the 32 full adders and why - IEEE-754 encoding results for all three values
Grading
| Component | Points |
|---|---|
full_adder.v and adder32.v pass 20 testbench cases |
6 |
alu.v passes 60-case testbench |
10 |
| IEEE-754 hand encoding correct for all 3 values | 2 |
| Toolchain Diary entry (gate depth + design choice noted) | 2 |