You are on page 1of 17

Laboratory Exercise #4

ALU Module in Verilog

1. Abstract
This lab was to demonstrate the ALU module and ALU control unit using Verilog. The ALU
module had two 32-bit busses and a 32-bit bus with a zero signal to tell that result is a zero. The
ALU control unit had a 4-bit operation signal with a 6-bit function signal. The ALU control unit
passes the function signal if the 4-bit op signal is all high, and the op signal goes directly to the
ALU if not all high. Both modules were successfully simulated, tested, and synthesized in this
lab.

2. Introduction
The fourth lab was to design and test the ALU module and the ALU Control module of a single-
cycle processor. The Arithmetic Logic Unit or ALU is a combinational logic module that
performs mathematical and logic expressions to two inputs based on the control signal. The ALU
design in this lab will have two buses both 32-bits and an output bus that is also 32-bits long.
When the output is a zero, a Zero signal will be set to high. No exception handling will be
designed in this lab but in later labs. The other module associated with the ALU is the ALU
Control unit. The ALU Control unit decodes the instruction to help determine what operations
the ALU needs to perform.

3. Procedures
The first step was to design the ALU module. The ALU module contains two 32-bit input busses,
a 32-bit output bus, and a zero-signal output. A 4-bit control line will be determining the ALU
operations. The ALU module is shown in Figure 1.

Figure 1. Register File

1
To make the ALU file, a switch case statement was made based on the control signal’s input.
Another alternative can be to use if-else statements; however, because there are many operations,
a switch case was more readable than if-else statements. For the ALU control, Table 1 is the
control signal operations of the ALU module.
Operation ALU Control
AND 0000
OR 0001
ADD 0010
SLL 0011
SRL 0100
SUB 0110
SLT 0111
ADDU 1000
SUBU 1001
XOR 1010
SLTU 1011
NOR 1100
SRA 1101
LUI 1110
Table 1: ALU Operations and Control Signals

For all additions and subtractions, the operations would perform basic two-input operations since
there is no exception handling. For the less than (SLT) operation, the operation will compare 2
two’s complement numbers. Both sign bits must be negated before they can be compared. For
shifting operations, Bus B shifts Bus A. The shift right arithmetic must shift a signed variable to
properly perform. The load upper immediate is performed by shifting Bus B 16 bits and loading
it to Bus W. The ALU file is shown in Figure 2.
`timescale 1ns / 1ps
//ALU.v

// Define associated operations with signals


`define AND 4'b0000
`define OR 4'b0001
`define ADD 4'b0010
`define SLL 4'b0011
`define SRL 4'b0100
`define SUB 4'b0110
`define SLT 4'b0111
`define ADDU 4'b1000
`define SUBU 4'b1001
`define XOR 4'b1010
`define SLTU 4'b1011
`define NOR 4'b1100

2
`define SRA 4'b1101
`define LUI 4'b1110
module ALU(BusW, Zero, BusA, BusB, ALUCtrl
);
input wire [31:0] BusA, BusB; //32-bit input busses
output reg [31:0] BusW; //32-bit output bus
input wire [3:0] ALUCtrl ; //4-bit control signal
output wire Zero ; //zero signal

wire less; //bit for less than operations


wire [63:0] Bus64; //64 bit bus
assign Zero = (BusW == 'd0) ? 1'b1 : 1'b0; //if output is high,
zero is high
assign less = ({1'b0,BusA} < {1'b0,BusB} ? 1'b1 : 1'b0); //less
than operation
assign Bus64 = {BusA, BusB};
always@(*)begin
//use switch case statements to create ALU operations
case (ALUCtrl)
`AND: BusW <= BusA & BusB;
`OR: BusW <= BusA | BusB;
`ADD: BusW <= BusA + BusB;
`ADDU: BusW <= BusA + BusB;
`SLL: BusW <= BusA << BusB; //By testbench, shift BusA bas
ed on BusB
`SRL: BusW <= BusA >> BusB;
`SUB: BusW <= BusA - BusB;
`SUBU: BusW <= BusA - BusB;
`XOR: BusW <= BusA ^ BusB;
`NOR: BusW <= ~(BusA | BusB);
`SLT: BusW <= {-BusA[31], BusA[30:0]} < {-
BusB[31], BusB[30:0]};
`SLTU: BusW <= less;
`SRA: BusW <= $signed(BusA) >>> BusB;
//switch BusA to a signed varialbe then shift

`LUI: BusW <= BusB << 16; // Shift BusB 16 bits to perform
load upper immediate
default:BusW <= BusA + BusB; //for default, add busses
endcase
end
endmodule
Figure 2: ALU.v File

3
The testbench code was provided to confirm if the register file was designed correctly. The
testbench file is in the Appendix. To simulate the register file, the device used for the simulation
and synthesis was the Virtex 7 Evaluation Board.
After the simulation (See Results), the next step was to design the ALU Control Unit. The ALU
op signal is 4 bits while the function code is 6 bits. If the ALU op signal = 4’b1111, the function
code is passed through the ALU. If the ALU op signal is not 4’b1111, the ALU op signal is
directly sent to the ALU. The operations and their bits are the same as Table 1. But the function
code is shown in Table 2.
Function Code Function Signal
SLL Function 000000
SRL Function 000010
SRA Function 000011
ADD Function 100000
ADDU Function 100001
SUB Function 100010
SUBU Function 100011
AND Function 100100
OR Function 100101
XOR Function 100110
NOR Function 100111
SLT Function 101010
SLTU Function 101011
MULA Function 111000
Table 2: Functions and Their Signals

`timescale 1ns / 1ps

// ALUControl.v

//Define operations to signal bits


`define AND 4'b0000
`define OR 4'b0001
`define ADD 4'b0010
`define SLL 4'b0011
`define SRL 4'b0100
`define MULA 4'b0101
`define SUB 4'b0110
`define SLT 4'b0111
`define ADDU 4'b1000
`define SUBU 4'b1001
`define XOR 4'b1010
`define SLTU 4'b1011
`define NOR 4'b1100

4
`define SRA 4'b1101
`define LUI 4'b1110

//Define function to function bits


`define SLLFunc 6'b000000
`define SRLFunc 6'b000010
`define SRAFunc 6'b000011
`define ADDFunc 6'b100000
`define ADDUFunc 6'b100001
`define SUBFunc 6'b100010
`define SUBUFunc 6'b100011
`define ANDFunc 6'b100100
`define ORFunc 6'b100101
`define XORFunc 6'b100110
`define NORFunc 6'b100111
`define SLTFunc 6'b101010
`define SLTUFunc 6'b101011
`define MULAFunc 6'b111000
module ALUControl(ALUCtrl, ALUop, FuncCode);
output reg [3:0] ALUCtrl; //4-bit ALU Control bus
input [3:0] ALUop; //4-bit ALU operation bus
input [5:0] FuncCode; //6-bit ALU function bus

//asynchronous
always@(*)
begin
if (ALUop == 4'b1111) // Send function code to ALU if hi
gh
begin
case(FuncCode)
`SLLFunc: ALUCtrl <= `SLL;
`SRLFunc: ALUCtrl <= `SRL;
`SRAFunc: ALUCtrl <= `SRA;
`ADDFunc: ALUCtrl <= `ADD;
`ADDUFunc: ALUCtrl <= `ADDU;
`SUBFunc: ALUCtrl <= `SUB;
`SUBUFunc: ALUCtrl <= `SUBU;
`ANDFunc: ALUCtrl <= `AND;
`ORFunc: ALUCtrl <= `OR;
`XORFunc: ALUCtrl <= `XOR;
`NORFunc: ALUCtrl <= `NOR;
`SLTFunc: ALUCtrl <= `SLT;
`SLTUFunc: ALUCtrl <= `SLTU;

5
`MULAFunc: ALUCtrl <= `MULA;
default: ALUCtrl <= `ADD;
endcase
end else // ALU op != 4'b1111, send ALU op to ALU Ctrl
begin
ALUCtrl <= ALUop;
end
end

endmodule
Figure 3: ALU Control File

The register file was simulated and synthesize using the same board, and the testbench is
attached to the Appendix.

4. Results
The testbench for the ALU file contained 28 tests to pass. However, the test cases do not perform
test on shifts. More will be done in later labs.

Figure 4: Simulation of the ALU

Figure 5: Snippet of the Output

6
Figure 6: ALU Synthesized Module

Figure 7: Output Log of Synthesis (ALU)

Looking at Figure 4 and 5, the passed variable shows that the design passed all 22 test cases
meaning that the ALU performed correctly. This provided testbench, however, does not test the
shift operations which will be later modified in the future labs. This lab assumed that the shift
operations worked correctly. In Figure 6, the synthesized module of the ALU is shown using the
Virtex 7 board. The synthesized module should the ALU with all components. In Figure 7, the
snippet showed that there are no latches in the synthesized device. In Figure 8, the module was
zoomed to show Bus A and Bus B input. All inputs contained a buffer in the synthesized device.

7
BusB

BusA

Figure 8: ALU Synthesized Module Input

For the ALU Control Unit, the testbench contained 24 test cases to pass. The simulation result is
shown in Figure 6.

Figure 9: Simulation of ALU Control

8
Figure 10: Snippet of the Output

Figure 11: ALU Control Synthesized Module

Figure 12: Output Log of Synthesis (ALU Control)

Looking at Figure 9 and 10, the passed variable shows that the design passed all 24 test cases
meaning that the ALU performed correctly. In Figure 9, the function code also contained x’s
which are don’t care values. Based on the specification, the function input does not matter if the

9
ALU op code signal is not 4’b1111. In figure 11, the synthesized module of the ALU Control
unit is shown using the Virtex 7 board. Looking at the input, the function and operation inputs
are buffered before being sent to the control unit. The control unit then outputs through the
buffers and then is sent to the ALU. The output is 4-bits wide which is expected. In Figure 12,
the synthesis report showed that there were no latch warnings in the module; therefore, the
synthesized device consisted of combinational logic.

5. Conclusion
This lab was a review on the ALU module and the ALU Control unit in Verilog. The ALU
module inputted two 32-bit busses and outputted a 32-bit bus and a zero signal. The ALU control
unit inputs the ALU operation bits and the function bits. If the ALU op is 4’b1111, the function
code is passed into the ALU. If the ALU op is not 4’b1111, the ALU op is sent directly to the
ALU for operations. Both modules were simulated, tested, and synthesized successfully for this
lab.

10
6. Appendix
`timescale 1ns / 1ps

`define STRLEN 32
module ALUTest_v;

task passTest;
input [32:0] actualOut, expectedOut;
input [`STRLEN*8:0] testType;
inout [7:0] passed;

if(actualOut == expectedOut) begin $display ("%s passed",


testType); passed = passed + 1; end
else $display ("%s failed: %x should be %x", testType, act
ualOut, expectedOut);
endtask

task allPassed;
input [7:0] passed;
input [7:0] numTests;

if(passed == numTests) $display ("All tests passed");


else $display("Some tests failed");
endtask

// Inputs
reg [31:0] BusA;
reg [31:0] BusB;
reg [3:0] ALUCtrl;
reg [7:0] passed;

// Outputs
wire [31:0] BusW;
wire Zero;

// Instantiate the Unit Under Test (UUT)


ALU uut (
.BusW(BusW),
.Zero(Zero),
.BusA(BusA),
.BusB(BusB),

11
.ALUCtrl(ALUCtrl)
);

initial begin
// Initialize Inputs
BusA = 0;
BusB = 0;
ALUCtrl = 0;
passed = 0;

// Add stimulus here

//ADD YOUR TEST VECTORS FROM THE PRELAB HERE

{BusA, BusB, ALUCtrl} = {32'hFFFF1234, 32'd6 , 4'd4}; #40;


passTest({Zero, BusW}, 33'h003FFFC48, "SRL 0xFFFF1234,6", passed)
;
{BusA, BusB, ALUCtrl} = {32'h00000000, 32'h00000000, 4'd8}
; #40; passTest({Zero, BusW}, 33'h100000000, "ADDU 0,0", passed);
{BusA, BusB, ALUCtrl} = {32'h00000000, 32'hFFFFFFFF, 4'd8}
; #40; passTest({Zero, BusW}, 33'h0FFFFFFFF, "ADDU 0,-1", passed);
{BusA, BusB, ALUCtrl} = {32'hFFFFFFFF, 32'h00000000, 4'd8}
; #40; passTest({Zero, BusW}, 33'h0FFFFFFFF, "ADDU -1,0", passed);
{BusA, BusB, ALUCtrl} = {32'h000000FF, 32'h00000001, 4'd8}
; #40; passTest({Zero, BusW}, 33'h000000100, "ADDU FF,1", passed);
{BusA, BusB, ALUCtrl} = {32'h00000000, 32'h00000000, 4'd8}
; #40; passTest({Zero, BusW}, 33'h100000000, "SUBU 0,0", passed);
{BusA, BusB, ALUCtrl} = {32'h00000001, 32'hFFFFFFFF, 4'd9}
; #40; passTest({Zero, BusW}, 33'h000000002, "SUBU 1,-1", passed);
{BusA, BusB, ALUCtrl} = {32'h00000001, 32'h00000001, 4'd9}
; #40; passTest({Zero, BusW}, 33'h100000000, "SUBU 1,1", passed);
{BusA, BusB, ALUCtrl} = {32'hF0F0F0F0, 32'h0000FFFF, 4'd10
}; #40; passTest({Zero, BusW}, 33'h0F0F00F0F, "XOR 0xF0F0F0F0,0x00
00FFFF", passed);
{BusA, BusB, ALUCtrl} = {32'h12345678, 32'h87654321, 4'd10
}; #40; passTest({Zero, BusW}, 33'h095511559, "XOR 0x12345678,0x87
654321", passed);
{BusA, BusB, ALUCtrl} = {32'h00000000, 32'h00000000, 4'd11
}; #40; passTest({Zero, BusW}, 33'h100000000, "SLTU 0,0", passed);
{BusA, BusB, ALUCtrl} = {32'h00000000, 32'h00000001, 4'd11
}; #40; passTest({Zero, BusW}, 33'h000000001, "SLTU 0,1", passed);

12
{BusA, BusB, ALUCtrl} = {32'h00000000, 32'hFFFFFFFF, 4'd11
}; #40; passTest({Zero, BusW}, 33'h000000001, "SLTU 0,-
1", passed);
{BusA, BusB, ALUCtrl} = {32'h00000001, 32'h00000000, 4'd11
}; #40; passTest({Zero, BusW}, 33'h100000000, "SLTU 1,0", passed);
{BusA, BusB, ALUCtrl} = {32'hFFFFFFFF, 32'h00000000, 4'd11
}; #40; passTest({Zero, BusW}, 33'h100000000, "SLTU -
1,0", passed);
{BusA, BusB, ALUCtrl} = {32'hF0F0F0F0, 32'h0000FFFF, 4'd12
}; #40; passTest({Zero, BusW}, 33'h00F0F0000, "NOR 0xF0F0F0F0,0x00
00FFFF", passed);
{BusA, BusB, ALUCtrl} = {32'h12345678, 32'h87654321, 4'd12
}; #40; passTest({Zero, BusW}, 33'h0688aa886, "NOR 0x12345678,0x87
654321", passed);
{BusA, BusB, ALUCtrl} = {32'h00000001, 32'd3, 4'd13}; #40;
passTest({Zero, BusW}, 33'h100000000, "SRA 0x00000001,3", passed)
;
{BusA, BusB, ALUCtrl} = {32'h00001234, 32'd6, 4'd13}; #40;
passTest({Zero, BusW}, 33'h000000048, "SRA 0x00001234,6", passed)
;
{BusA, BusB, ALUCtrl} = {32'hFFFF1234, 32'd6, 4'd13}; #40;
passTest({Zero, BusW}, 33'h0FFFFFC48, "SRA 0xFFFF1234,6", passed)
;
{BusA, BusB, ALUCtrl} = {32'h0, 32'h12345678, 4'd14}; #40;
passTest({Zero, BusW}, 33'h056780000, "LUI 0x12345678", passed);
{BusA, BusB, ALUCtrl} = {32'h0, 32'h00001234, 4'd14}; #40;
passTest({Zero, BusW}, 33'h012340000, "LUI 0x00001234", passed);

allPassed(passed, 22);
end

endmodule

`timescale 1ns / 1ps

`define AND 4'b0000


`define OR 4'b0001
`define ADD 4'b0010
`define SLL 4'b0011
`define SRL 4'b0100
`define MULA 4'b0101

13
`define SUB 4'b0110
`define SLT 4'b0111
`define ADDU 4'b1000
`define SUBU 4'b1001
`define XOR 4'b1010
`define SLTU 4'b1011
`define NOR 4'b1100
`define SRA 4'b1101
`define LUI 4'b1110

`define SLLFunc 6'b000000


`define SRLFunc 6'b000010
`define SRAFunc 6'b000011
`define ADDFunc 6'b100000
`define ADDUFunc 6'b100001
`define SUBFunc 6'b100010
`define SUBUFunc 6'b100011
`define ANDFunc 6'b100100
`define ORFunc 6'b100101
`define XORFunc 6'b100110
`define NORFunc 6'b100111
`define SLTFunc 6'b101010
`define SLTUFunc 6'b101011
`define MULAFunc 6'b111000

`define STRLEN 32
module ALUControlTest_v;

task passTest;
input [5:0] actualOut, expectedOut;
input [`STRLEN*8:0] testType;
inout [7:0] passed;

if(actualOut == expectedOut) begin $display ("%s passed",


testType); passed = passed + 1; end
else $display ("%s failed: %d should be %d", testType, act
ualOut, expectedOut);
endtask

task allPassed;
input [7:0] passed;
input [7:0] numTests;

14
if(passed == numTests) $display ("All tests passed");
else $display("Some tests failed");
endtask

// Inputs
reg [3:0] ALUop;
reg [5:0] FuncCode;
reg [7:0] passed;

// Outputs
wire [3:0] ALUCtrl;

// Instantiate the Unit Under Test (UUT)


ALUControl uut (
.ALUCtrl(ALUCtrl),
.ALUop(ALUop),
.FuncCode(FuncCode)
);

initial begin
// Initialize Inputs
passed = 0;

{ALUop, FuncCode} = {4'b1111, `SLLFunc};


#10
passTest(ALUCtrl, `SLL, "SLL Instruction", passed);

{ALUop, FuncCode} = {4'b1111, `SRLFunc};


#10
passTest(ALUCtrl, `SRL, "SRL Instruction", passed);

{ALUop, FuncCode} = {4'b1111, `SRAFunc};


#10
passTest(ALUCtrl, `SRA, "SRA Instruction", passed);

{ALUop, FuncCode} = {4'b1111, `ADDFunc};


#10
passTest(ALUCtrl, `ADD, "ADD Instruction", passed);

{ALUop, FuncCode} = {4'b1111, `ADDUFunc};


#10
passTest(ALUCtrl, `ADDU, "ADDU Instruction", passed);

15
{ALUop, FuncCode} = {4'b1111, `SUBFunc};
#10
passTest(ALUCtrl, `SUB, "SUB Instruction", passed);

{ALUop, FuncCode} = {4'b1111, `SUBUFunc};


#10
passTest(ALUCtrl, `SUBU, "SUBU Instruction", passed);

{ALUop, FuncCode} = {4'b1111, `ANDFunc};


#10
passTest(ALUCtrl, `AND, "AND Instruction", passed);

{ALUop, FuncCode} = {4'b1111, `ORFunc};


#10
passTest(ALUCtrl, `OR, "OR Instruction", passed);

{ALUop, FuncCode} = {4'b1111, `XORFunc};


#10
passTest(ALUCtrl, `XOR, "XOR Instruction", passed);

{ALUop, FuncCode} = {4'b1111, `NORFunc};


#10
passTest(ALUCtrl, `NOR, "NOR Instruction", passed);

{ALUop, FuncCode} = {4'b1111, `SLTFunc};


#10
passTest(ALUCtrl, `SLT, "SLT Instruction", passed);

{ALUop, FuncCode} = {4'b1111, `SLTUFunc};


#10
passTest(ALUCtrl, `SLTU, "SLTU Instruction", passed);

{ALUop, FuncCode} = {`AND, 6'bXXXXXX};


#10
passTest(ALUCtrl, `AND, "ANDI Instruction", passed);

{ALUop, FuncCode} = {`OR, 6'bXXXXXX};


#10
passTest(ALUCtrl, `OR, "ORI Instruction", passed);

{ALUop, FuncCode} = {`ADD, 6'bXXXXXX};


#10

16
passTest(ALUCtrl, `ADD, "ADDI Instruction", passed);

{ALUop, FuncCode} = {`SUB, 6'bXXXXXX};


#10
passTest(ALUCtrl, `SUB, "SUBI Instruction", passed);

{ALUop, FuncCode} = {`SLT, 6'bXXXXXX};


#10
passTest(ALUCtrl, `SLT, "SLTI Instruction", passed);

{ALUop, FuncCode} = {`ADDU, 6'bXXXXXX};


#10
passTest(ALUCtrl, `ADDU, "ADDIU Instruction", passed);

{ALUop, FuncCode} = {`SUBU, 6'bXXXXXX};


#10
passTest(ALUCtrl, `SUBU, "SUBIU Instruction", passed);

{ALUop, FuncCode} = {`XOR, 6'bXXXXXX};


#10
passTest(ALUCtrl, `XOR, "XORI Instruction", passed);

{ALUop, FuncCode} = {`SLTU, 6'bXXXXXX};


#10
passTest(ALUCtrl, `SLTU, "SLTU Instruction", passed);

{ALUop, FuncCode} = {`NOR, 6'bXXXXXX};


#10
passTest(ALUCtrl, `NOR, "NORI Instruction", passed);

{ALUop, FuncCode} = {`LUI, 6'bXXXXXX};


#10
passTest(ALUCtrl, `LUI, "LUI Instruction", passed);

allPassed(passed, 24);
end

endmodule

17

You might also like