Day 63: Building block: the parameterized ALU
Building block: the parameterized ALU
Time to build the reusable pieces ChipX is made of. First, the ALU from Stage 1: a combinational module taking two operands and an op-select, producing a result (and a zero flag). Make it parameterized in width so the same code serves a 32-bit datapath now and any width later, and verify it with a self-checking testbench that mirrors each operation independently.
module alu #(parameter W = 32) (
input [W-1:0] a, b,
input [3:0] op,
output reg [W-1:0] y,
output zero
);
localparam ADD=0, SUB=1, AND=2, OR=3, XOR=4, SLL=5, SRL=6, SRA=7, SLT=8, SLTU=9;
assign zero = (y == '0);
always @(*) begin
case (op)
ADD: y = a + b;
SUB: y = a - b;
AND: y = a & b;
OR: y = a | b;
XOR: y = a ^ b;
SLL: y = a << b[4:0];
SRL: y = a >> b[4:0];
SRA: y = $signed(a) >>> b[4:0];
SLT: y = ($signed(a) < $signed(b)) ? 1 : 0;
SLTU: y = (a < b) ? 1 : 0;
default: y = '0;
endcase
end
endmoduleSigned vs unsigned matters
SRA (arithmetic shift) and SLT (signed compare) need $signed() — a classic bug is forgetting it and getting logical shifts or unsigned comparisons. This is two's complement (Stage 0/1) meeting Verilog: the ISA distinguishes signed and unsigned operations, and your RTL must too.
Ship for Day 63
Why must the SRA (shift-right-arithmetic) and SLT (set-less-than) operations use $signed() in Verilog?