Digital System Design
Assignment No. : 02
Submitted to: Dr. Qurat ul Ain
Submitted by: Huzaifa Ahmad
CMS ID: 424981
Date: 17/05/2025
Problem 1:
Design, implement, and simulate a 32-bit Arithmetic Logic Unit (ALU) in Verilog HDL that
performs both arithmetic and logical operations based on a 4-bit control signal (ALU_Sel).
Operations (controlled by ALU_Sel):
0000: AND
0001: OR
0010: ADD
0110: SUBTRACT
0111: SET LESS THAN (SLT)
1100: NOR
Inputs:
A: 32-bit input
B: 32-bit input
ALU_Sel: 4-bit control input
Outputs:
Result: 32-bit output
Zero: 1-bit output (set to 1 if Result is all zeros)
Requirement: Simulate using a Verilog simulator.
Code:
module alu #(
parameter WIDTH = 32 // Parameterized width, default 32 bits
) (
input [WIDTH-1:0] A, // 32-bit input A
input [WIDTH-1:0] B, // 32-bit input B
input [3:0] ALU_Sel, // 4-bit operation select
output [WIDTH-1:0] Result, // 32-bit result
output Zero, // Zero flag
output CarryOut, // Carry-out flag
output Overflow // Overflow flag
);
reg [WIDTH-1:0] Result_reg;
reg CarryOut_reg, Overflow_reg;
wire [WIDTH-1:0] Sum;
wire CarryIn;
// Compute sum for ADD and SUBTRACT
assign CarryIn = (ALU_Sel == 4'b0110) ? 1'b1 : 1'b0; // 1 for SUBTRACT
assign Sum = A + (CarryIn ? ~B : B) + CarryIn;
// ALU operation logic
always @(*) begin
case (ALU_Sel)
4'b0000: begin // AND
Result_reg = A & B;
CarryOut_reg = 1'b0; Overflow_reg = 1'b0;
end
4'b0001: begin // OR
Result_reg = A | B;
CarryOut_reg = 1'b0;
Overflow_reg = 1'b0;
end
4'b0010: begin // ADD
Result_reg = Sum;
CarryOut_reg = (A[WIDTH-1] & B[WIDTH-1]) |
(A[WIDTH-1] & ~Sum[WIDTH-1]) |
(B[WIDTH-1] & ~Sum[WIDTH-1]);
Overflow_reg = (A[WIDTH-1] == B[WIDTH-1]) &&
(A[WIDTH-1] != Sum[WIDTH-1]);
end
4'b0110: begin // SUBTRACT
Result_reg = Sum;
CarryOut_reg = (~A[WIDTH-1] & B[WIDTH-1]) |
(~A[WIDTH-1] & Sum[WIDTH-1]) |
(B[WIDTH-1] & Sum[WIDTH-1]);
Overflow_reg = (A[WIDTH-1] != B[WIDTH-1]) &&
(A[WIDTH-1] != Sum[WIDTH-1]);
end
4'b0111: begin // SLT (Set Less Than)
Result_reg = (A[WIDTH-1] == B[WIDTH-1]) ?
(A < B ? 1 : 0) :
(A[WIDTH-1] ? 1 : 0);
CarryOut_reg = 1'b0;
Overflow_reg = 1'b0;
end
4'b1100: begin // NOR
Result_reg = ~(A | B);
CarryOut_reg = 1'b0;
Overflow_reg = 1'b0;
end
default: begin
Result_reg = {WIDTH{1'b0}};
CarryOut_reg = 1'b0;
Overflow_reg = 1'b0;
end
endcase
end
// Assign outputs
assign Result = Result_reg;
assign Zero = (Result_reg == {WIDTH{1'b0}}) ? 1'b1 : 1'b0;
assign CarryOut = CarryOut_reg;
assign Overflow = Overflow_reg;
Wave Form Output:
Problem 2:
Write a Verilog testbench module that:
Applies at least 3 different test cases for each ALU operation.
Displays inputs, selected operation, and output using $display or $monitor.
Verifies correct functionality by comparing expected vs. actual results
Test Bench:
module alu_tb;
// Parameters
parameter WIDTH = 32;
// Signals
reg [WIDTH-1:0] A, B;
reg [3:0] ALU_Sel;
wire [WIDTH-1:0] Result;
wire Zero, CarryOut, Overflow;
// Expected results
reg [WIDTH-1:0] Expected_Result;
reg Expected_Zero, Expected_CarryOut, Expected_Overflow;
// Instantiate ALU
alu #(WIDTH) uut (
.A(A),
.B(B),
.ALU_Sel(ALU_Sel),
.Result(Result),
.Zero(Zero),
.CarryOut(CarryOut),
.Overflow(Overflow)
);
// Operation names for display
reg [31*8:0] op_name;
// Test procedure
initial begin
$monitor("Time=%0t A=%h B=%h ALU_Sel=%b (%s) Result=%h Zero=%b
CarryOut=%b Overflow=%b Expected_Result=%h Pass=%b",
$time, A, B, ALU_Sel, op_name, Result, Zero, CarryOut,
Overflow, Expected_Result,
(Result == Expected_Result && Zero == Expected_Zero &&
CarryOut == Expected_CarryOut && Overflow ==
Expected_Overflow));
// Test cases
// AND (0000)
ALU_Sel = 4'b0000; op_name = "AND";
A = 32'hFFFF0000; B = 32'h0000FFFF; Expected_Result =
32'h00000000; Expected_Zero = 1; Expected_CarryOut = 0;
Expected_Overflow = 0; #10;
A = 32'hAAAAAAAA; B = 32'h55555555; Expected_Result =
32'h00000000; Expected_Zero = 1; Expected_CarryOut = 0;
Expected_Overflow = 0; #10;
A = 32'hFFFFFFFF; B = 32'hFFFFFFFF; Expected_Result =
32'hFFFFFFFF; Expected_Zero = 0; Expected_CarryOut = 0;
Expected_Overflow = 0; #10;
// OR (0001)
ALU_Sel = 4'b0001; op_name = "OR";
A = 32'hFFFF0000; B = 32'h0000FFFF; Expected_Result =
32'hFFFFFFFF; Expected_Zero = 0; Expected_CarryOut = 0;
Expected_Overflow = 0; #10;
A = 32'hAAAAAAAA; B = 32'h55555555; Expected_Result =
32'hFFFFFFFF; Expected_Zero = 0; Expected_CarryOut = 0;
Expected_Overflow = 0; #10;
A = 32'h00000000; B = 32'h00000000; Expected_Result =
32'h00000000; Expected_Zero = 1; Expected_CarryOut = 0;
Expected_Overflow = 0; #10;
// ADD (0010)
ALU_Sel = 4'b0010; op_name = "ADD";
A = 32'h00000001; B = 32'h00000001; Expected_Result =
32'h00000002; Expected_Zero = 0; Expected_CarryOut = 0;
Expected_Overflow = 0; #10;
A = 32'h7FFFFFFF; B = 32'h00000001; Expected_Result =
32'h80000000; Expected_Zero = 0; Expected_CarryOut = 0;
Expected_Overflow = 1; #10;
A = 32'hFFFFFFFF; B = 32'h00000001; Expected_Result =
32'h00000000; Expected_Zero = 1; Expected_CarryOut = 1;
Expected_Overflow = 0; #10;
// SUBTRACT (0110)
ALU_Sel = 4'b0110; op_name = "SUBTRACT";
A = 32'h00000002; B = 32'h00000001; Expected_Result =
32'h00000001; Expected_Zero = 0; Expected_CarryOut = 0;
Expected_Overflow = 0; #10;
A = 32'h80000000; B = 32'h00000001; Expected_Result =
32'h7FFFFFFF; Expected_Zero = 0; Expected_CarryOut = 0;
Expected_Overflow = 1; #10;
A = 32'h00000000; B = 32'h00000001; Expected_Result =
32'hFFFFFFFF; Expected_Zero = 0; Expected_CarryOut = 1;
Expected_Overflow = 0; #10;
// SLT (0111)
ALU_Sel = 4'b0111; op_name = "SLT";
A = 32'h00000001; B = 32'h00000002; Expected_Result =
32'h00000001; Expected_Zero = 0; Expected_CarryOut = 0;
Expected_Overflow = 0; #10;
A = 32'hFFFFFFFF; B = 32'h00000000; Expected_Result =
32'h00000001; Expected_Zero = 0; Expected_CarryOut = 0;
Expected_Overflow = 0; #10;
A = 32'h00000002; B = 32'h00000001; Expected_Result =
32'h00000000; Expected_Zero = 1; Expected_CarryOut = 0;
Expected_Overflow = 0; #10;
// NOR (1100)
ALU_Sel = 4'b1100; op_name = "NOR";
A = 32'hFFFF0000; B = 32'h0000FFFF; Expected_Result =
32'h00000000; Expected_Zero = 1; Expected_CarryOut = 0;
Expected_Overflow = 0; #10;
A = 32'hAAAAAAAA; B = 32'h55555555; Expected_Result =
32'h00000000; Expected_Zero = 1; Expected_CarryOut = 0;
Expected_Overflow = 0; #10;
A = 32'h00000000; B = 32'h00000000; Expected_Result =
32'hFFFFFFFF; Expected_Zero = 0; Expected_CarryOut = 0;
Expected_Overflow = 0; #10;
// Invalid ALU_Sel
ALU_Sel = 4'b1111; op_name = "INVALID";
A = 32'hAAAAAAAA; B = 32'h55555555; Expected_Result =
32'h00000000; Expected_Zero = 1; Expected_CarryOut = 0;
Expected_Overflow = 0; #10;
$finish;
end endmodule
Console Output:
Problem 3:
Choose any two of the following enhancements for the ALU:
1. Add Shift Left Logical (SLL) and Shift Right Logical (SRL) operations.
2. Add a carry-out flag and overflow flag.
3. Make the ALU parameterized for N-bit width.
4. Integrate the ALU into a simple datapath (e.g., for a MIPS-like processor).
Code:
Enhancement 1: Carry-out and Overflow Flags (Implementation)
Enhancement 2: Parameterized N-bit Width (Ref. to Waveform)
module alu #(
parameter WIDTH = 32
) (
input [WIDTH-1:0] A, B,
input [3:0] ALU_Sel,
output [WIDTH-1:0] Result,
output Zero,
output CarryOut,
output Overflow
);
reg [WIDTH-1:0] Result_reg;
reg CarryOut_reg, Overflow_reg;
wire [WIDTH-1:0] Sum;
wire CarryIn;
assign CarryIn = (ALU_Sel == 4'b0110) ? 1'b1 : 1'b0; // 1 for SUBTRACT
assign Sum = A + (CarryIn ? ~B : B) + CarryIn;
always @(*) begin
case (ALU_Sel)
4'b0010: begin // ADD
Result_reg = Sum;
CarryOut_reg = (A[WIDTH-1] & B[WIDTH-1]) |
(A[WIDTH-1] & ~Sum[WIDTH-1]) |
(B[WIDTH-1] & ~Sum[WIDTH-1]);
Overflow_reg = (A[WIDTH-1] == B[WIDTH-1]) &&
(A[WIDTH-1] != Sum[WIDTH-1]);
end
4'b0110: begin // SUBTRACT
Result_reg = Sum;
CarryOut_reg = (~A[WIDTH-1] & B[WIDTH-1]) |
(~A[WIDTH-1] & Sum[WIDTH-1]) |
(B[WIDTH-1] & Sum[WIDTH-1]);
Overflow_reg = (A[WIDTH-1] != B[WIDTH-1]) &&
(A[WIDTH-1] != Sum[WIDTH-1]);
end
default: begin // For AND, OR, SLT, NOR, etc.
CarryOut_reg = 1'b0;
Overflow_reg = 1'b0;
// ... (other operations as in full code)
end
endcase
end
assign Result = Result_reg;
assign Zero = (Result_reg == {WIDTH{1'b0}}) ? 1'b1 : 1'b0;
assign CarryOut = CarryOut_reg;
assign Overflow = Overflow_reg;
endmodule
Wave Form Snippet:
Console Output:
ADD (Time 60–90 ns):
SUBTRACT (Time 90–120 ns):
AND (0 ns, showing 32-bit operation):
Conclusion:
This project successfully achieved the design, implementation, and simulation of a 32-bit
Arithmetic Logic Unit (ALU) using Verilog HDL, fulfilling all the assignment requirements.
The ALU accurately performed six core operations based on a 4-bit control signal, with correct
output generation for the Result and Zero flags. A comprehensive testbench validated the ALU's
functionality across multiple test cases, with all results matching the expected outputs.
Additionally, enhancements such as parameterization for scalability and the inclusion of
CarryOut and Overflow flags demonstrated a deeper understanding of digital system design. The
simulation results, including waveforms and console outputs, confirmed the ALU’s reliable and
accurate performance. Overall, this project reflects a strong grasp of Verilog HDL and
fundamental digital design principles.