You are on page 1of 70

LAB MANUAL

Computer Architecture

SUBMMITTED BY
2019-EE-602
SUBMITTED TO
Engr. Osama Bin Naeem

UNIVERSITY OF ENGINEERING AND TECHNOLOGY, LAHORE (NAROWAL CAMPUS)


Table of Content
Sr No. Lab Page No.
1 How to download and install Xilinx 2-5
2 Implementation of Logical Gates 6-9
3 Full Adder/Subtractor and Half Adder/Subtractor 10-18
4 4-bit Adder and Subtractor 19-22
5 Multiplexer (MUX) 23-26
6 Barrel Shifter 27-30
7 Register File 31-36
8 ALU 35-41
9 R-Type 32 Bit Instruction 42-45
10 Complex Engineering Problem 46-69

Page 1 of 69
Lab 01
How to download and install Xilinx
Step 01:
Download the Xilinx ISE Design Suite v14.7 from the below link:
https://getintopc.com/softwares/design/xilinx-ise-design-suite-v14-7-free-download/

Step 02:
Extract the file which you have downloaded and then enter 123 in password to extract it.

Page 2 of 69
Step 03:
Turn off your antivirus before installation…!

Step 04:
Double click on Setup and accept all the options and click next.

Page 3 of 69
Step 05:
Wait until the installation is complete.

Step 06:
Copy the license file from the crack folder and replace it with
C:\Xilinx\14.7\ISE_DS\EDK\data\core_licenses

Page 4 of 69
Step 07:
All done! Now open the Xilinx ISE icon on the desktop and start working.

Page 5 of 69
Lab 02
Implementation of Logical Gates
Logical Gates:
A logic gate is a device that acts as a building block for digital circuits.
Different types of Gates are:
• AND Gate
• OR Gate
• Not Gate
• NAND Gate
• NOR Gate
• XOR Gate
• XNOR Gate

Page 6 of 69
Logical gates implementation in Xilinx:
To make this project follow the below instructions:
• Click on the New Project Option, name it and save it.
• Add a new file “Verilog Module” and declare inputs and outputs.
• Write the code of all logical gates and save it.
• Then in bottom left menu run “Check Syntax” in Synthesize – XST.
• Then click on View RTL Schematic to view the schematic diagram of the gates.
• Add another new file “Verilog Text Fixture”, name it and save it.
• Now edit the input values and save it.
• Click on the “Simulation” tab then run “Behavioral Check Syntax”.
• All done now click on “Simulate Behavioral Model” to run.

Verilog Module Code:


module Gates(
input a,b,
output o1,o2,o3,o4,o5,o6,o7
);
assign o1= a&b;
assign o2= a|b;
assign o3= ~b;
assign o4= ~(a&b);
assign o5= (a|b);
assign o6= a^b;
assign o7= ~(a^b);
endmodule

Verilog Test Bench Code:


module GatesTB;

// Inputs

Page 7 of 69
reg a;
reg b;

// Outputs
wire o1;
wire o2;
wire o3;
wire o4;
wire o5;
wire o6;
wire o7;

// Instantiate the Unit Under Test (UUT)


Gates uut (
.a(a),
.b(b),
.o1(o1),
.o2(o2),
.o3(o3),
.o4(o4),
.o5(o5),
.o6(o6),
.o7(o7)
);

initial begin
// Initialize Inputs
a = 0; b = 0;
#100 a = 0; b = 1;
#100 a = 1; b = 0;
#100 a = 1; b = 1;

// Wait 100 ns for global reset to finish


#100;

// Add stimulus here

end

endmodule

Page 8 of 69
Simulation:

Page 9 of 69
Lab 03
Full Adder/Subtractor and Half Adder/Subtractor
Adder/Subtractor:
Full Adder/Subtractor and Half Adder/Subtractor.
• A logic circuit used for adding two 1-bit numbers or simply two bits is called as a
Half Adder circuit.
• A Full Adder is a combinational logic circuit which performs addition on three bits
and produces two outputs: a Sum and a Carry.
• A Half Subtractor is a multiple output Combinational Logic Circuit that does the
subtraction of two 1-bit binary numbers
• A Full Subtractor is a combinational logic circuit which performs a subtraction
between the two 1-bit binary numbers and it also considers the borrow of the previous
bit i.e., whether 1 has been borrowed by the previous minuend bit.

Half Adder:

Page 10 of 69
Full Adder:

Half Subtractor:

Full Subtractor:

Full and Half Adder/Subtractor implementation:


To make this project follow the below instructions:
• Click on the New Project Option, name it and save it.
• Add a new file “Verilog Module” and declare inputs and outputs.
• Write the code of all logical gates and save it.
• Then in bottom left menu run “Check Syntax” in Synthesize – XST.
• Then click on View RTL Schematic to view the schematic diagram of the gates.

Page 11 of 69
• Add another new file “Verilog Text Fixture”, name it and save it.
• Now edit the input values and save it.
• Click on the “Simulation” tab then run “Behavioral Check Syntax”.
• All done now click on “Simulate Behavioral Model” to run.

Verilog Module Code:


module HalfAdder(

input a,b,

output cout,s

);

assign s= a^b;

assign cout= a&b;

endmodule

module FullAdder(

input a,b,cin,

output s,cout

);

assign s= (a^b)^cin;

assign cout= (a&b)|cin&(a^b);

endmodule

module HalfSubtactor(

input a,b,

output bout,d

);

assign d=a^b;

assign bout= ~a&b;

endmodule

module FullSubtractor(

input a,b,bin,

output d,bout

);

assign d= (a^b)^bin;

assign bout= bin&~(a^b)|(~a&b);

endmodule

Page 12 of 69
Verilog Test Bench Code:
module HalfAdderTB;

// Inputs

reg a;

reg b;

// Outputs

wire cout;

wire s;

// Instantiate the Unit Under Test (UUT)

HalfAdder uut (

.a(a),

.b(b),

.cout(cout),

.s(s)

);

initial begin

// Initialize Inputs

a = 0; b = 0;

Page 13 of 69
#100 a = 0; b = 1;

#100 a = 1; b = 0;

#100 a = 1; b = 1;

// Wait 100 ns for global reset to finish

#100;

// Add stimulus here

end

endmodule

module FullAdderTB;

// Inputs

reg a;

reg b;

reg cin;

// Outputs

wire s;

wire cout;

// Instantiate the Unit Under Test (UUT)

FullAdder uut (

.a(a),

.b(b),

.cin(cin),

.s(s),

.cout(cout)

);

initial begin

// Initialize Inputs

a = 0; b = 0; cin = 0;

#100 a = 1; b = 0; cin = 0;

#100 a = 0; b = 1; cin = 0;

#100 a = 1; b = 1; cin = 0;

#100 a = 0; b = 0; cin = 1;

#100 a = 1; b = 0; cin = 1;

#100 a = 0; b = 1; cin = 1;

#100 a = 1; b = 1; cin = 1;

Page 14 of 69
// Wait 100 ns for global reset to finish

#100;

// Add stimulus here

end

endmodule

module HalfSubtractorTB;

// Inputs

reg a;

reg b;

// Outputs

wire bout;

wire d;

// Instantiate the Unit Under Test (UUT)

HalfSubtactor uut (

.a(a),

.b(b),

.bout(bout),

.d(d)

);

initial begin

// Initialize Inputs

a = 0; b = 0;

#100 a = 0; b = 1;

#100 a = 1; b = 0;

#100 a = 1; b = 1;

// Wait 100 ns for global reset to finish

#100;

// Add stimulus here

end

endmodule

module FullSubtractorTB;

// Inputs

reg a;

reg b;

Page 15 of 69
reg bin;

// Outputs

wire d;

wire bout;

// Instantiate the Unit Under Test (UUT)

FullSubtractor uut (

.a(a),

.b(b),

.bin(bin),

.d(d),

.bout(bout)

);

initial begin

// Initialize Inputs

a = 0; b = 0; bin = 0;

#100 a = 0; b = 0; bin = 1;

#100 a = 0; b = 1; bin = 0;

#100 a = 0; b = 1; bin = 1;

#100 a = 1; b = 0; bin = 0;

#100 a = 1; b = 0; bin = 1;

#100 a = 1; b = 1; bin = 0;

#100 a = 1; b = 1; bin = 1;

// Wait 100 ns for global reset to finish

#100;

// Add stimulus here

end

endmodule

Page 16 of 69
Simulation:

Page 17 of 69
Full Subtractor

Full Adder

Half Adder

Half Subtractor

Page 18 of 69
Lab 04
4-bit Adder and Subtractor
4-bit Adder/Subtractor:
Implementation using one circuit (full adder):
• A parallel adder is an arithmetic combinational logic circuit that is used to add more
than one bit of data simultaneously.
• A full adder adds two 1-bits and a carry to give an output. However, to add more than
one bit of data in length, a parallel adder is used.
• A parallel adder adds corresponding bits simultaneously using full adders.
• Simultaneously, it keeps generating a carry and pushing it towards the next most
significant bit to be added.
• An n-bit parallel adder uses n full adders connected in cascade with each full adder
adding the two corresponding bits of both the numbers.

4-bit Adder/Subtractor implementation:


To make this project follow the below instructions:
• Click on the New Project Option, name it and save it.
• Add a new file “Verilog Module” and declare inputs and outputs.
• Write the code of 4-bit adder/subtractor and save it.
• Then in bottom left menu run “Check Syntax” in Synthesize – XST.
• Then click on View RTL Schematic to view the schematic diagram of the gates.
• Add another new file “Verilog Text Fixture”, name it and save it.
• Now edit the input values and save it.
• Click on the “Simulation” tab then run “Behavioral Check Syntax”.
• All done now click on “Simulate Behavioral Model” to run.

Page 19 of 69
Verilog Module Code:
module ParallelAdderSubtractor(

output [0:3]R,

output O,

output V,

input [0:3]A,

input [0:3]B,

input M

);

wire O0;

wire O1;

wire O2;

wire O3;

wire B0;

wire B1;

wire B2;

wire B3;

xor(B0, B[0], M);

xor(B1, B[1], M);

xor(B2, B[2], M);

xor(B3, B[3], M);

xor(O, O3, M);

xor(V, O3, O2);

full_adder fa0(R[0], O0, A[0], B0, M);

full_adder fa1(R[1], O1, A[1], B1, O0);

full_adder fa2(R[2], O2, A[2], B2, O1);

full_adder fa3(R[3], O3, A[3], B3, O2);

endmodule

Verilog Test Bench Code:


module ParallelAdderSubtractorTB;

// Inputs

reg [0:3] A;

reg [0:3] B;

Page 20 of 69
reg M;

// Outputs

wire [0:3] R;

wire O;

wire V;

// Instantiate the Unit Under Test (UUT)

ParallelAdderSubtractor uut (

.R(R),

.O(O),

.V(V),

.A(A),

.B(B),

.M(M)

);

initial begin

// Initialize Inputs

A = 4'b1010; B = 4'b1001; M = 0;

#100 A = 4'b1010; B = 4'b1001; M = 1;

// Wait 100 ns for global reset to finish

#100;

// Add stimulus here

end

endmodule

Page 21 of 69
Simulation:

Page 22 of 69
Lab 05
Multiplexer (MUX)
MUX:
Multiplexing is the generic term used to describe the operation of sending one or more analogue
or digital signals over a common transmission line at different times or speeds and as such, the
device we use to do just that is called the multiplexer.
• The multiplexer, shortened to “MUX” or “MPX”, is a combinational logic circuit
designed to switch one of several input lines through to a single common output line
by the application of a control signal.
• Multiplexers operate like very fast acting multiple position rotary switches connecting
or controlling multiple input lines called “channels” one at a time to the output.
• Multiplexers, or MUX’s, can be either digital circuits made from high speed logic
gates used to switch digital or binary data or they can be analogue types using
transistors, MOSFET’s or relays to switch one of the voltage or current inputs
through to a single output.

4 to 1 MUX implementation:
To make this project follow the below instructions:
• Click on the New Project Option, name it and save it.
• Add a new file “Verilog Module” and declare inputs and outputs.
• Write the code of 4 to 1 MUX and save it.
• Then in bottom left menu run “Check Syntax” in Synthesize – XST.
• Then click on View RTL Schematic to view the schematic diagram of the gates.
• Add another new file “Verilog Text Fixture”, name it and save it.
• Now edit the input values and save it.
• Click on the “Simulation” tab then run “Behavioral Check Syntax”.
• All done now click on “Simulate Behavioral Model” to run.

Page 23 of 69
Verilog Module Code:
module MUX4_1(

input a,b,c,d,s0,s1,

output y

);

assign y= (~s0&~s1&a)|(~s0&s1&b)|(s0&~s1&c)|(s0&s1&d);

endmodule

Verilog Test Bench Code:


module MUX4_1TB;

// Inputs

reg a;

reg b;

reg c;

reg d;

reg s0;

reg s1;

// Outputs

wire y;

// Instantiate the Unit Under Test (UUT)

MUX4_1 uut (

.a(a),

.b(b),

.c(c),

.d(d),

.s0(s0),

.s1(s1),

.y(y)

);

initial begin

// Initialize Inputs

a = 0; b = 0; c = 0; d = 0; s0 = 0; s1 = 0;

#100 a = 0; b = 0; c = 0; d = 1; s0 = 0; s1 = 1;

#100 a = 0; b = 0; c = 1; d = 0; s0 = 1; s1 = 0;

Page 24 of 69
#100 a = 0; b = 0; c = 1; d = 1; s0 = 1; s1 = 1;

#100 a = 0; b = 1; c = 0; d = 0; s0 = 0; s1 = 0;

#100 a = 0; b = 1; c = 0; d = 1; s0 = 0; s1 = 1;

#100 a = 0; b = 1; c = 1; d = 0; s0 = 1; s1 = 0;

#100 a = 0; b = 1; c = 1; d = 1; s0 = 1; s1 = 1;

#100 a = 1; b = 0; c = 0; d = 0; s0 = 0; s1 = 0;

#100 a = 1; b = 0; c = 0; d = 1; s0 = 0; s1 = 1;

#100 a = 1; b = 0; c = 1; d = 0; s0 = 1; s1 = 0;

#100 a = 1; b = 0; c = 1; d = 1; s0 = 1; s1 = 1;

#100 a = 1; b = 1; c = 0; d = 0; s0 = 0; s1 = 0;

#100 a = 1; b = 1; c = 0; d = 1; s0 = 0; s1 = 1;

#100 a = 1; b = 1; c = 1; d = 0; s0 = 1; s1 = 0;

#100 a = 1; b = 1; c = 1; d = 1; s0 = 1; s1 = 1;

// Wait 100 ns for global reset to finish

#100;

// Add stimulus here

end

endmodule

Page 25 of 69
Simulation:

Page 26 of 69
Lab 06
Barrel Shifter
Barrel Shifter:
A barrel shifter is a specialized digital electronic circuit with the purpose of shifting an entire
data word by a specified number of bits by only using combinational logic, with no sequential
logic used.
• Barrel shifters are specialized electronic circuits used to shift the bits of binary data
and often employed by embedded digital signal processors and other general-purpose
processors in order to manipulate data.
• Data shifting is required for various low-level data applications such as floating-point
arithmetic operations, bit indexing and variable-length coding.
• A barrel shifter is able to complete the shift in a single clock cycle, giving it a great
advantage over a simple shifter which can shift n bits in n clock cycles.
• It is used in conjunction with a processor’s arithmetic logic unit (ALU) or otherwise
embedded in the ALU itself.

Barrel Shifter implementation:


To make this project follow the below instructions:
• Click on the New Project Option, name it and save it.
• Add a new file “Verilog Module” and declare inputs and outputs.
• Write the code of Barrel Shifter and save it.
• Then in bottom left menu run “Check Syntax” in Synthesize – XST.
• Then click on View RTL Schematic to view the schematic diagram of the gates.
• Add another new file “Verilog Text Fixture”, name it and save it.
• Now edit the input values and save it.
• Click on the “Simulation” tab then run “Behavioral Check Syntax”.
• All done now click on “Simulate Behavioral Model” to run.

Page 27 of 69
Verilog Module Code:
module BarelShifter(

input [7:0] in,

input [2:0] ctrl,

output [7:0] out,

wire [7:0] x,y

);

//4bit shift right

mux2X1 ins_17 (.in0(in[7]),.in1(1'b0),.sel(ctrl[2]),.out(x[7]));

mux2X1 ins_16 (.in0(in[6]),.in1(1'b0),.sel(ctrl[2]),.out(x[6]));

mux2X1 ins_15 (.in0(in[5]),.in1(1'b0),.sel(ctrl[2]),.out(x[5]));

mux2X1 ins_14 (.in0(in[4]),.in1(1'b0),.sel(ctrl[2]),.out(x[4]));

mux2X1 ins_13 (.in0(in[3]),.in1(in[7]),.sel(ctrl[2]),.out(x[3]));

mux2X1 ins_12 (.in0(in[2]),.in1(in[6]),.sel(ctrl[2]),.out(x[2]));

mux2X1 ins_11 (.in0(in[1]),.in1(in[5]),.sel(ctrl[2]),.out(x[1]));

mux2X1 ins_10 (.in0(in[0]),.in1(in[4]),.sel(ctrl[2]),.out(x[0]));

//2 bit shift right

mux2X1 ins_27 (.in0(x[7]),.in1(1'b0),.sel(ctrl[1]),.out(y[7]));

mux2X1 ins_26 (.in0(x[6]),.in1(1'b0),.sel(ctrl[1]),.out(y[6]));

mux2X1 ins_25 (.in0(x[5]),.in1(x[7]),.sel(ctrl[1]),.out(y[5]));

mux2X1 ins_24 (.in0(x[4]),.in1(x[6]),.sel(ctrl[1]),.out(y[4]));

mux2X1 ins_23 (.in0(x[3]),.in1(x[5]),.sel(ctrl[1]),.out(y[3]));

mux2X1 ins_22 (.in0(x[2]),.in1(x[4]),.sel(ctrl[1]),.out(y[2]));

mux2X1 ins_21 (.in0(x[1]),.in1(x[3]),.sel(ctrl[1]),.out(y[1]));

mux2X1 ins_20 (.in0(x[0]),.in1(x[2]),.sel(ctrl[1]),.out(y[0]));

//1 bit shift right

mux2X1 ins_07 (.in0(y[7]),.in1(1'b0),.sel(ctrl[0]),.out(out[7]));

mux2X1 ins_06 (.in0(y[6]),.in1(y[7]),.sel(ctrl[0]),.out(out[6]));

mux2X1 ins_05 (.in0(y[5]),.in1(y[6]),.sel(ctrl[0]),.out(out[5]));

mux2X1 ins_04 (.in0(y[4]),.in1(y[5]),.sel(ctrl[0]),.out(out[4]));

mux2X1 ins_03 (.in0(y[3]),.in1(y[4]),.sel(ctrl[0]),.out(out[3]));

mux2X1 ins_02 (.in0(y[2]),.in1(y[3]),.sel(ctrl[0]),.out(out[2]));

mux2X1 ins_01 (.in0(y[1]),.in1(y[2]),.sel(ctrl[0]),.out(out[1]));

Page 28 of 69
mux2X1 ins_00 (.in0(y[0]),.in1(y[1]),.sel(ctrl[0]),.out(out[0]));

endmodule

Verilog Test Bench Code:


module BarrelShifterTB;

// Inputs

reg [7:0] in;

reg [2:0] ctrl;

// Outputs

wire [7:0] out;

// Instantiate the Unit Under Test (UUT)

BarelShifter uut (

.in(in),

.ctrl(ctrl),

.out(out)

);

initial begin

// Initialize Inputs

in= 8'd0; ctrl=3'd0; //no shift

#100 in=8'd128; ctrl= 3'd4; //shift 4 bit

#100 in=8'd128; ctrl= 3'd2; //shift 2 bit

#100 in=8'd128; ctrl= 3'd1; //shift by 1 bit

#100 in=8'd255; ctrl= 3'd7; //shift by 7bit

// Wait 100 ns for global reset to finish

#100;

// Add stimulus here

end

endmodule

Page 29 of 69
Simulation:

Page 30 of 69
Lab 07
Register File
Register File:
A register file is a means of memory storage within a computer's central processing unit (CPU).
• The computer's register files contain bits of data and mapping locations.
• These locations specify certain addresses that are input components of a register file.
Other inputs include data, a read and write function and execute function.
• When a user installs a program on a computer, that software application writes a
register file on the CPU.
• Most software programs will contain more than one file.
• Those files contain execution instructions that the CPU follows when the user
launches and uses the application.

Register File implementation:


To make this project follow the below instructions:
• Click on the New Project Option, name it and save it.
• Add a new file “Verilog Module” and declare inputs and outputs.
• Write the code of Register File and save it.
• Then in bottom left menu run “Check Syntax” in Synthesize – XST.
• Then click on View RTL Schematic to view the schematic diagram of the gates.
• Add another new file “Verilog Text Fixture”, name it and save it.
• Now edit the input values and save it.
• Click on the “Simulation” tab then run “Behavioral Check Syntax”.
• All done now click on “Simulate Behavioral Model” to run.

Page 31 of 69
Verilog Module Code:
module RegFile(Ip1,sel_i1,Op1,sel_o1,Op2,sel_o2,RD,WR,rst,EN,clk);

input [31:0] Ip1;

input [3:0] sel_i1,sel_o1,sel_o2;

input RD,WR;

input EN,clk,rst;

output [31:0] Op1,Op2;

reg [31:0] Op1,Op2;

reg [31:0] regFile [0:15];

integer i;

wire sen;

assign sen = clk || rst;

always @ (posedge sen)

begin

if (EN == 1)

begin

if (rst == 1) //If at reset

begin

for (i = 0; i < 16; i = i + 1) begin

regFile [i] = 32'h0;

end

Op1 = 32'hx;

end

else if (rst == 0) //If not at reset

begin

case ({RD,WR})

2'b00: begin

end

2'b01: begin //If Write only

regFile [sel_i1] = Ip1;

end

2'b10: begin //If Read only

Op1 = regFile [sel_o1];

Page 32 of 69
Op2 = regFile [sel_o2];

end

2'b11: begin //If both active

Op1 = regFile [sel_o1];

Op2 = regFile [sel_o2];

regFile [sel_i1] = Ip1;

end

default: begin //If undefined

end

endcase

end

else;

end

else;

end

endmodule

Verilog Test Bench Code:


module RegFileTB;

// Inputs

reg [31:0] Ip1;

reg [3:0] sel_i1;

reg [3:0] sel_o1;

reg [3:0] sel_o2;

reg RD;

reg WR;

reg rst;

reg EN;

reg clk;

// Outputs

wire [31:0] Op1;

wire [31:0] Op2;

// Instantiate the Unit Under Test (UUT)

RegFile uut (

Page 33 of 69
.Ip1(Ip1),

.sel_i1(sel_i1),

.Op1(Op1),

.sel_o1(sel_o1),

.Op2(Op2),

.sel_o2(sel_o2),

.RD(RD),

.WR(WR),

.rst(rst),

.EN(EN),

.clk(clk)

);

initial begin

// Initialize Inputs

Ip1 = 32'b0;

sel_i1 = 4'b0;

sel_o1 = 4'b0;

sel_o2 = 4'b0;

RD = 1'b0;

WR = 1'b0;

rst = 1'b1;

EN = 1'b0;

clk = 1'b0;

// Wait 100 ns for global reset to finish

#100;

// Add stimulus here

rst = 1'b0;

EN = 1'b1;

#20;

WR = 1'b1;

RD = 1'b0;

Ip1 = 32'habcd_efab;

sel_i1 = 4'h0;

#20;

Page 34 of 69
Ip1 = 32'h0123_4567;

sel_i1 = 4'h1;

#20;

WR = 1'b0;

RD = 1'b1;

sel_o1 = 4'h0;

sel_o2 = 4'h1;

end

always begin

#10;

clk = ~clk;

end

endmodule

Simulation:

Page 35 of 69
Page 36 of 69
Lab 08
Arithmetic-Logical Unit
ALU:
In the computer system, ALU is a main component of the central processing unit, which stands
for arithmetic logic unit and performs arithmetic and logic operations.
• It is also known as an integer unit (IU) that is an integrated circuit within a CPU or
GPU, which is the last component to perform calculations in the processor.
• It has the ability to perform all processes related to arithmetic and logic operations
such as addition, subtraction, and shifting operations, including Boolean comparisons
(XOR, OR, AND, and NOT operations).
• Also, binary numbers can accomplish mathematical and bitwise operations. The
arithmetic logic unit is split into AU (arithmetic unit) and LU (logic unit).
• The operands and code used by the ALU tell it which operations have to perform
according to input data.
• When the ALU completes the processing of input, the information is sent to the
computer's memory.

ALU implementation:
To make this project follow the below instructions:
• Click on the New Project Option, name it and save it.
• Add a new file “Verilog Module” and declare inputs and outputs.
• Write the code of ALU and save it.
• Then in bottom left menu run “Check Syntax” in Synthesize – XST.
• Then click on View RTL Schematic to view the schematic diagram of the gates.
• Add another new file “Verilog Text Fixture”, name it and save it.
• Now edit the input values and save it.
• Click on the “Simulation” tab then run “Behavioral Check Syntax”.
• All done now click on “Simulate Behavioral Model” to run.

Page 37 of 69
Verilog Module Code:
module alu(

input [7:0] A,B, // ALU 8-bit Inputs

input [3:0] ALU_Sel,// ALU Selection

output [7:0] ALU_Out, // ALU 8-bit Output

output CarryOut // Carry Out Flag

);

reg [7:0] ALU_Result;

wire [8:0] tmp;

assign ALU_Out = ALU_Result; // ALU out

assign tmp = {1'b0,A} + {1'b0,B};

assign CarryOut = tmp[8]; // Carryout flag

always @(*)

begin

case(ALU_Sel)

4'b0000: // Addition

ALU_Result = A + B ;

4'b0001: // Subtraction

ALU_Result = A - B ;

4'b0010: // Multiplication

ALU_Result = A * B;

4'b0011: // Division

ALU_Result = A/B;

4'b0100: // Logical shift left

ALU_Result = A<<1;

4'b0101: // Logical shift right

ALU_Result = A>>1;

4'b0110: // Rotate left

ALU_Result = {A[6:0],A[7]};

4'b0111: // Rotate right

ALU_Result = {A[0],A[7:1]};

4'b1000: // Logical and

ALU_Result = A & B;

Page 38 of 69
4'b1001: // Logical or

ALU_Result = A | B;

4'b1010: // Logical xor

ALU_Result = A ^ B;

4'b1011: // Logical nor

ALU_Result = ~(A | B);

4'b1100: // Logical nand

ALU_Result = ~(A & B);

4'b1101: // Logical xnor

ALU_Result = ~(A ^ B);

4'b1110: // Greater comparison

ALU_Result = (A>B)?8'd1:8'd0 ;

4'b1111: // Equal comparison

ALU_Result = (A==B)?8'd1:8'd0 ;

default: ALU_Result = A + B ;

endcase

end

endmodule

Verilog Test Bench Code:


module aluTB;

// Inputs

reg [7:0] A;

reg [7:0] B;

reg [3:0] ALU_Sel;

// Outputs

wire [7:0] ALU_Out;

wire CarryOut;

// Instantiate the Unit Under Test (UUT)

integer i;

alu uut (

.A(A),

.B(B),

.ALU_Sel(ALU_Sel),

Page 39 of 69
.ALU_Out(ALU_Out),

.CarryOut(CarryOut)

);

initial begin

// Initialize Inputs

A = 8'h0A;

B = 4'h02;

ALU_Sel = 4'h0;

for (i=0;i<=15;i=i+1)

begin

ALU_Sel = ALU_Sel + 8'h01;

#10;

end;

A = 8'hF6;

B = 8'h0A;

end

endmodule

Simulation:

Page 40 of 69
Page 41 of 69
Lab 09
R-Type 32 Bit Instruction
R-Type instruction:
In computer architecture, R-Type (Register Type) instruction is a type of machine
instruction that operates on registers. These instructions are used in many computer architectures,
including the MIPS architecture used in the example code we have been discussing. An R-Type
instruction typically consists of an opcode (operation code) and three register operands: one for
the source register rs1, one for the source register rs2, and one for the destination register rd. The
specific operation performed by the instruction is determined by the opcode. R-Type instructions
are typically used for operations such as arithmetic and logical operations that involve the values
stored in registers. Because these instructions operate directly on registers, they can execute very
quickly and efficiently, making them ideal for performance-critical code.

Working of R-Type instruction:


In the code given bellow. R-Type function takes three 5-bit register address inputs (rs1,
rs2, and rd) and two 3-bit function code inputs (funct3 and funct7). The R-Type function then
performs an operation specified by the function code inputs using the values stored in the
specified registers, and stores the result in the register specified by rd.
The exact operation performed by the R-Type function depends on the values of the
function code inputs. The funct3 input specifies a general category of operation, such as addition
or subtraction, while the funct7 input provides additional details about the operation, such as
whether it is a multiplication or a division.
The R-Type function supports the following operations:
• Addition (funct3 = 3'b000)
• Subtraction (funct3 = 3'b010)
• Bitwise AND (funct3 = 3'b111, funct7 = 7'b0000000)
• Bitwise OR (funct3 = 3'b110, funct7 = 7'b0000000)
• Bitwise XOR (funct3 = 3'b100, funct7 = 7'b0000000)
• Shift left logical (funct3 = 3'b001)
• Shift right logical (funct3 = 3'b101)
• Shift right arithmetic (funct3 = 3'b101, funct7 = 7'b0100000)
• Multiplication (funct3 = 3'b000, funct7 = 7'b0000001)
When the funct3 field is 3'b101 and the funct7 field is 7'b0100000, the R-Type instruction
specifies a shift right arithmetic operation. This operation shifts the value in register rs1 to the
right by the number of bits specified in the least significant 5 bits of the value in register rs2,
while preserving the sign bit. The result is stored in the register specified by rd. The R-Type
function is a common type of instruction format used in computer instruction sets to perform
arithmetic and logical operations on registers.

Page 42 of 69
Verilog Module Code:
module instruction (

input [31:0] instruction,

output reg [31:0] result

);

reg [31:0] opcode;

reg [4:0] rd;

reg [4:0] rs1;

reg [4:0] rs2;

reg [2:0] funct3;

reg [6:0] funct7;

always @ (instruction) begin

opcode = instruction[6:0];

rd = instruction[11:7];

funct3 = instruction[14:12];

rs1 = instruction[19:15];

rs2 = instruction[24:20];

funct7 = instruction[31:25];

case (funct3)

3'b000: result = rs1 & rs2; // AND

3'b001: result = rs1 | rs2; // OR

3'b010: result = rs1 ^ rs2; // XOR

3'b100: result = rs1 < rs2; // SLT

3'b101: result = rs1 < rs2; // SLTU

default: result = 0;

endcase

end

endmodule

Page 43 of 69
Simulation:

Output Waveform:
• Both inputs are Zero:

Page 44 of 69
• Both inputs are Zero and funct3 is 001:

• Inputs are 10101 and 01011 respectively and funct3 is 001(OR operation):

• Inputs are 10101 and 01011 respectively and funct3 is 000(AND operation):

Page 45 of 69
Complex Engineering Problem
Design and Implementation of 32-bit RISC-V processor with three stage pipeline
CLOs and PLOs for Complex Engineering Problem
Please state CLOs and PLOs addressed in the complex engineering problem along with
domain and level. These are the CLOs from the theory/lab course which are already defined.

CLOs Description Domains & PLOs,


Levels
Levels

CLO1 Theory Demonstrate the skills to Cognitive, PLO1


design data path of singlecycle,
2. Understand
multi-cycle, and pipeline
microprocessor
architecture using a variety
of techniques

CLO2 Lab Formulate the control portion Psychomotor, PLO3


of a processor, and its data path
4. Articulate
consisting of the general-purpose
register file, ALU, the memory
interface, internal registers
between stages, and
multiplexers.

CLO3 Lab Design and emulate a Psychomotor, PLO3


pipelined CPU by given
specifications using Verilog

5.
Naturalization

Problem Statement
In this open-ended design lab, students as a group will investigate and design a 32-bit RISCV
processor with three stage pipeline.
• Implement a processor that supports a subset of the RISC-V ISA. The designed processor
does not support all RISC-V ISA instruction, so it cannot execute most programs. However,
the processor has most parts that a real processor has: A fetch unit, decode logic, functional

Page 46 of 69
units, a register file, I/O support, access to memory, interrupt handling, hazard elimination
protocols, and CSR Support.
• Students will be implementing the data path while designing a pipelined RISC-V processor
which will work with five stages mainly, It must contain a file or block RAM of FPGA that
will be used as Random Access Memory. Memory will be 8-bits wide but the processor
accesses 32-bits (4B) for operation. It will have 32 Registers working as General Purpose
Register. While one special purpose register (Program Counter) will be used to hold the
address of the instruction. Each Register must be 32 bit wide and clock edge triggered.
• Students are required to explore different methodologies to investigate the problem and
select/develop an optimal methodology for design of the system.
Complex Engineering Problem Attributes

WP1: Depth of WP1: Depth of Knowledge Requires knowledge of Digital


Systems and Computer Architecture (WK4), design of Data path
knowledge
and Controller for pipelined architecture (WK5), use of Modern
Tools to program and test the code on FPGA (WK6) and
engagement in research literature (WK8)
WP2: Range of
conflicting WP3: Depth of analysis Numerous approaches can be
adopted. Choice of the selected algorithm requires in detail
requirements analysis
WP5: Extent of applicable codes Requires going beyond
WP3: Depth of the use of standardized features of Standard Verilog modules.
analysis
Rubrics

Methodically investigates different design WP1,


WP4: Familiarity approaches and techniques to design data path of
of WP3
pipelined microprocessor architecture. (CLO1)
issues
Selects an optimal methodology to design the WP3,
control portion of a processor, and its data path
WP5
consisting of the generalpurpose register file, ALU,
WP5: Extent of the memory. interface, internal registers between
applicable codes stages, and multiplexers with proper justification
WP6: Extent of (CLO2)

stakeholders Designs a comprehensive test bench system to WP1,


test and verify the designed processor requirements
WP5
subject to the given constraints (CLO3)

Page 47 of 69
WP7: Identifies limitations and implications of the WP1
Interdependence proposed solution (CLO3)

EA1: Range of • EA1: Range of resources The design involves


resources internet resources, information related to software
usage and technology (modern end tools
EA2: Level of
including Cadence).
interaction
• EA3: Innovation Addressing sustainability and
EA3: Innovation optimization of the design based on engineering
principles and knowledge.

EA4: Rubrics
Consequences for
Methodically investigates different design EA1,
society and approaches and techniques to design data path of
environment EA5: EA3
pipelined microprocessor architecture. (CLO1)
Familiarity
Selects an optimal methodology to design the EA1,
control portion of a processor, and its data path
EA3
consisting of the generalpurpose register file, ALU,
the memory interface, internal registers between
stages, and multiplexers with proper justification
(CLO2)

Designs a comprehensive test bench system to test EA1,


and verify the designed processor requirements
EA3
subject to the given constraints (CLO3)

Identifies limitations and implications of the EA3


proposed solution (CLO3)

Page 48 of 69
Complex Engineering Problem Rubrics

Good (8-10) Average (4-7) Bad (0-3)

Latex Used
Latex not used
References
properly added in References properly
IEEE added in IEEE Format
Report If any section is
Template has not been
Format
(2 Marks) followed and formatting missing.
Template has is not properly done but
been followed with all sections have been
all required covered
sections.

Hardware Viva 100% answer


60-90% answer rate 0-50% answer rate
(10 Marks) rate.

Software Viva
(10 Marks) 60-90% 0-50%
100% Understanding Understanding
Understanding.

Optocouplers
used Take care of Optocouplers not
Hardware Setup voltage and current used Won’t care of
and ratings voltage and current Wrong Hardware
Wiring Perfectly rating Perfectly Circuit.
(8 Marks) hardware hardware connection
connection Clean Poor wiring
wiring

Perfectly/Minor Not
Hardware Working with not
issues in working Working/Working with
Working (10 able to fulfill few
with all constraints not able to fulfill many
Marks) constraints
fulfilled constraints

Page 49 of 69
Solution of Complex Engineering Problem
Introduction:
RISC stands for Reduced Instruction Set computer. RISC processors are widely used
processor nowadays. There are many advantages of RISC over CISC (complex instruction set
computer) architecture. Those are high performance, fixed length instruction, single cycle
execution, smaller size, and short development time. RISC design resulted in computers that
execute instructions faster than other computers built of the same technology.Complexity is at
software level rather than hardware level. One of the main advantages is pipelining which is
absent in CISC processor. Pipelining improves overall performance of RISC architecture.
MIPS stand for microprocessor without interlocked pipeline stages. It is an open source soft
processor & one of the first successful RISC architecture. MIPS are widely used in embedded
systems. MIPS processor design is based on the RISC design principle that concentrates on
load/store architecture. MIPS has already been pronoun of MIPS instruction set and MIPS
instruction set architecture. In this we use 3 stage RISC single cycle 32 bit pipelined processor
which is inspired by MIPS having large set of registers. [1]

Instruction Format:
Proposed architecture supports Two Types of instructions. These are R-type instructions and J-
type instructions. It considers two source registers, one destination register, shift value and
opcodes for instructions. [2]
Type 01: General instruction format

Figure 1 shows R-Type Instructions Format.


5 bits: for shifting or rotating operation (2^5=32 bits).
6 bits: opcode (2^6=64) to support instructions up to 64.
7 bits: To access registers up to 127th. (R0-R127)
Example:
1. ADD r0, r1, r2;
r0=r1+r2
2. AND r5, r6, r7;

Page 50 of 69
r5=r6 & r7
Type: 2 Jump instruction format

Figure 2 shows Jump type Instruction Format


Example: JMP LABEL
Suppose LABEL is located at 125th instruction then PC will immediately jumps to 125th
instruction.

List of Instruction and Opcode for Registers:


Table 1 shows list of instructions included in purposed architecture with respective opcodes.

Page 51 of 69
Table 2 shows how register is accessed with their opcode. Registers can be accessed like R0 as
0000000, R1 as 0000001, R2 as 0000010, R3 as 0000011, R4 as 0000100, R5 as 0000101, R6 as
0000110, R7 as 0000111, R8 as 0001000, and so on.

Architecture of 32 bit RISC-V Processor:


The 32 Bit Asynchronous RISC-V processor Comprises of Arithmetic unit(ALU), Booth’s
Multiplier, Control Unit, Register Bank, Memory and Data path. The Architecture divided into
five stages. The pipeline stages are Instruction fetch(IF), Instruction decode(ID), Instruction
Execution(IE), Memory Access(MA), Write back(WB). The Design consists of three types of
memories are Data memory, Instruction memory and register memory. In Instruction fetch stage,
the 32 bit Instruction is being loaded into Instruction register by using address in the program
counter(PC). After the fetch cycle the PC will increment by four addresses because of each
register stores only 8 bit as it requires 4 registers to store 32 bit instruction. In Instruction Decode
stage, the 32 bit Instruction is divided. Depends Upon the 6 bit opcode it decodes from
instruction. The Opcode is sent to the decoder then appropriate control signals are generated. In
Execution stage, the ALU unit performs the operations as per the decoded information. In
Memory access (MA) the load and store instructions access the memory I.e read and write
operations on memory. [3]

Page 52 of 69
Processor Control Unit Design:

ALU Control Unit Design:

Page 53 of 69
Verilog code for the RISC processor:
Verilog code for Instruction Memory:
module Instruction_Memory(

input[15:0] pc,

output[15:0] instruction

);

reg [col - 1:0] memory [row_i - 1:0];

wire [3 : 0] rom_addr = pc[4 : 1];

initial

begin

$readmemb("./test/test.prog", memory,0,14);

end

assign instruction = memory[rom_addr];

endmodule

Verilog code for register file:


module GPRs(

input clk,

// write port

input reg_write_en,

input [2:0] reg_write_dest,

input [15:0] reg_write_data,

//read port 1

input [2:0] reg_read_addr_1,

output [15:0] reg_read_data_1,

//read port 2

input [2:0] reg_read_addr_2,

output [15:0] reg_read_data_2

);

reg [15:0] reg_array [7:0];

integer i;

// write port

//reg [2:0] i;

initial begin

Page 54 of 69
for(i=0;i<8;i=i+1)

reg_array[i] <= 16'd0;

end

always @ (posedge clk ) begin

if(reg_write_en) begin

reg_array[reg_write_dest] <= reg_write_data;

end

end

assign reg_read_data_1 = reg_array[reg_read_addr_1];

assign reg_read_data_2 = reg_array[reg_read_addr_2];

endmodule

Verilog code for Data Memory:


module Data_Memory(

input clk,

// address input, shared by read and write port

input [15:0] mem_access_addr,

// write port

input [15:0] mem_write_data,

input mem_write_en,

input mem_read,

// read port

output [15:0] mem_read_data

);

reg [`col - 1:0] memory [`row_d - 1:0];

integer f;

wire [2:0] ram_addr=mem_access_addr[2:0];

initial

begin

$readmemb("./test/test.data", memory);

f = $fopen(`filename);

$fmonitor(f, "time = %d\n", $time,

"\tmemory[0] = %b\n", memory[0],

"\tmemory[1] = %b\n", memory[1],

"\tmemory[2] = %b\n", memory[2],

Page 55 of 69
"\tmemory[3] = %b\n", memory[3],

"\tmemory[4] = %b\n", memory[4],

"\tmemory[5] = %b\n", memory[5],

"\tmemory[6] = %b\n", memory[6],

"\tmemory[7] = %b\n", memory[7]);

`simulation_time;

$fclose(f);

end

always @(posedge clk) begin

if (mem_write_en)

memory[ram_addr] <= mem_write_data;

end

assign mem_read_data = (mem_read==1'b1) ? memory[ram_addr]: 16'd0;

endmodule

Verilog code for ALU unit:


module ALU(

input [15:0] a, //src1

input [15:0] b, //src2

input [2:0] alu_control, //function sel

output reg [15:0] result, //result

output zero

);

always @(*)

begin

case(alu_control)

3'b000: result = a + b; // add

3'b001: result = a - b; // sub

3'b010: result = ~a;

3'b011: result = a<<b;

3'b100: result = a>>b;

3'b101: result = a & b; // and

3'b110: result = a | b; // or

3'b111: begin if (a<b) result = 16'd1;

else result = 16'd0;

Page 56 of 69
end

default:result = a + b; // add

endcase

end

assign zero = (result==16'd0) ? 1'b1: 1'b0;

endmodule

Verilog code for ALU Control Unit of the RISC processor:


module alu_control( ALU_Cnt, ALUOp, Opcode);

output reg[2:0] ALU_Cnt;

input [1:0] ALUOp;

input [3:0] Opcode;

wire [5:0] ALUControlIn;

assign ALUControlIn = {ALUOp,Opcode};

always @(ALUControlIn)

casex (ALUControlIn)

6'b10xxxx: ALU_Cnt=3'b000;

6'b01xxxx: ALU_Cnt=3'b001;

6'b000010: ALU_Cnt=3'b000;

6'b000011: ALU_Cnt=3'b001;

6'b000100: ALU_Cnt=3'b010;

6'b000101: ALU_Cnt=3'b011;

6'b000110: ALU_Cnt=3'b100;

6'b000111: ALU_Cnt=3'b101;

6'b001000: ALU_Cnt=3'b110;

6'b001001: ALU_Cnt=3'b111;

default: ALU_Cnt=3'b000;

endcase

endmodule

Verilog code for Datapath of the RISC processor:


module Datapath_Unit(

input clk,

input jump,beq,mem_read,mem_write,alu_src,reg_dst,mem_to_reg,reg_write,bne,

input[1:0] alu_op,

Page 57 of 69
output[3:0] opcode

);

reg [15:0] pc_current;

wire [15:0] pc_next,pc2;

wire [15:0] instr;

wire [2:0] reg_write_dest;

wire [15:0] reg_write_data;

wire [2:0] reg_read_addr_1;

wire [15:0] reg_read_data_1;

wire [2:0] reg_read_addr_2;

wire [15:0] reg_read_data_2;

wire [15:0] ext_im,read_data2;

wire [2:0] ALU_Control;

wire [15:0] ALU_out;

wire zero_flag;

wire [15:0] PC_j, PC_beq, PC_2beq,PC_2bne,PC_bne;

wire beq_control;

wire [12:0] jump_shift;

wire [15:0] mem_read_data;

// PC

initial begin

pc_current <= 16'd0;

end

always @(posedge clk)

begin

pc_current <= pc_next;

end

assign pc2 = pc_current + 16'd2;

// instruction memory

Instruction_Memory im(.pc(pc_current),.instruction(instr));

// jump shift left 2

assign jump_shift = {instr[11:0],1'b0};

// multiplexer regdest

assign reg_write_dest = (reg_dst==1'b1) ? instr[5:3] :instr[8:6];

Page 58 of 69
// register file

assign reg_read_addr_1 = instr[11:9];

assign reg_read_addr_2 = instr[8:6];

// GENERAL PURPOSE REGISTERs

GPRs reg_file

.clk(clk),

.reg_write_en(reg_write),

.reg_write_dest(reg_write_dest),

.reg_write_data(reg_write_data),

.reg_read_addr_1(reg_read_addr_1),

.reg_read_data_1(reg_read_data_1),

.reg_read_addr_2(reg_read_addr_2),

.reg_read_data_2(reg_read_data_2)

);

// immediate extend

assign ext_im = {{10{instr[5]}},instr[5:0]};

// ALU control unit

alu_control ALU_Control_unit(.ALUOp(alu_op),.Opcode(instr[15:12]),.ALU_Cnt(ALU_Control));

// multiplexer alu_src

assign read_data2 = (alu_src==1'b1) ? ext_im : reg_read_data_2;

// ALU

ALU alu_unit(.a(reg_read_data_1),.b(read_data2),.alu_control(ALU_Control),.result(ALU_out),.zero(zero_flag));

// PC beq add

assign PC_beq = pc2 + {ext_im[14:0],1'b0};

assign PC_bne = pc2 + {ext_im[14:0],1'b0};

// beq control

assign beq_control = beq & zero_flag;

assign bne_control = bne & (~zero_flag);

// PC_beq

assign PC_2beq = (beq_control==1'b1) ? PC_beq : pc2;

// PC_bne

assign PC_2bne = (bne_control==1'b1) ? PC_bne : PC_2beq;

// PC_j

Page 59 of 69
assign PC_j = {pc2[15:13],jump_shift};

// PC_next

assign pc_next = (jump == 1'b1) ? PC_j : PC_2bne;

/// Data memory

Data_Memory dm

.clk(clk),

.mem_access_addr(ALU_out),

.mem_write_data(reg_read_data_2),

.mem_write_en(mem_write),

.mem_read(mem_read),

.mem_read_data(mem_read_data)

);

// write back

assign reg_write_data = (mem_to_reg == 1'b1)? mem_read_data: ALU_out;

// output to control unit

assign opcode = instr[15:12];

endmodule

Verilog code for the Control Unit of the RISC processor:


module Control_Unit(

input[3:0] opcode,

output reg[1:0] alu_op,

output reg jump,beq,bne,mem_read,mem_write,alu_src,reg_dst,mem_to_reg,reg_write

);

always @(*)

begin

case(opcode)

4'b0000: // LW

begin

reg_dst = 1'b0;

alu_src = 1'b1;

mem_to_reg = 1'b1;

reg_write = 1'b1;

mem_read = 1'b1;

Page 60 of 69
mem_write = 1'b0;

beq = 1'b0;

bne = 1'b0;

alu_op = 2'b10;

jump = 1'b0;

end

4'b0001: // SW

begin

reg_dst = 1'b0;

alu_src = 1'b1;

mem_to_reg = 1'b0;

reg_write = 1'b0;

mem_read = 1'b0;

mem_write = 1'b1;

beq = 1'b0;

bne = 1'b0;

alu_op = 2'b10;

jump = 1'b0;

end

4'b0010: // data_processing

begin

reg_dst = 1'b1;

alu_src = 1'b0;

mem_to_reg = 1'b0;

reg_write = 1'b1;

mem_read = 1'b0;

mem_write = 1'b0;

beq = 1'b0;

bne = 1'b0;

alu_op = 2'b00;

jump = 1'b0;

end

4'b0011: // data_processing

begin

Page 61 of 69
reg_dst = 1'b1;

alu_src = 1'b0;

mem_to_reg = 1'b0;

reg_write = 1'b1;

mem_read = 1'b0;

mem_write = 1'b0;

beq = 1'b0;

bne = 1'b0;

alu_op = 2'b00;

jump = 1'b0;

end

4'b0100: // data_processing

begin

reg_dst = 1'b1;

alu_src = 1'b0;

mem_to_reg = 1'b0;

reg_write = 1'b1;

mem_read = 1'b0;

mem_write = 1'b0;

beq = 1'b0;

bne = 1'b0;

alu_op = 2'b00;

jump = 1'b0;

end

4'b0101: // data_processing

begin

reg_dst = 1'b1;

alu_src = 1'b0;

mem_to_reg = 1'b0;

reg_write = 1'b1;

mem_read = 1'b0;

mem_write = 1'b0;

beq = 1'b0;

bne = 1'b0;

Page 62 of 69
alu_op = 2'b00;

jump = 1'b0;

end

4'b0110: // data_processing

begin

reg_dst = 1'b1;

alu_src = 1'b0;

mem_to_reg = 1'b0;

reg_write = 1'b1;

mem_read = 1'b0;

mem_write = 1'b0;

beq = 1'b0;

bne = 1'b0;

alu_op = 2'b00;

jump = 1'b0;

end

4'b0111: // data_processing

begin

reg_dst = 1'b1;

alu_src = 1'b0;

mem_to_reg = 1'b0;

reg_write = 1'b1;

mem_read = 1'b0;

mem_write = 1'b0;

beq = 1'b0;

bne = 1'b0;

alu_op = 2'b00;

jump = 1'b0;

end

4'b1000: // data_processing

begin

reg_dst = 1'b1;

alu_src = 1'b0;

mem_to_reg = 1'b0;

Page 63 of 69
reg_write = 1'b1;

mem_read = 1'b0;

mem_write = 1'b0;

beq = 1'b0;

bne = 1'b0;

alu_op = 2'b00;

jump = 1'b0;

end

4'b1001: // data_processing

begin

reg_dst = 1'b1;

alu_src = 1'b0;

mem_to_reg = 1'b0;

reg_write = 1'b1;

mem_read = 1'b0;

mem_write = 1'b0;

beq = 1'b0;

bne = 1'b0;

alu_op = 2'b00;

jump = 1'b0;

end

4'b1011: // BEQ

begin

reg_dst = 1'b0;

alu_src = 1'b0;

mem_to_reg = 1'b0;

reg_write = 1'b0;

mem_read = 1'b0;

mem_write = 1'b0;

beq = 1'b1;

bne = 1'b0;

alu_op = 2'b01;

jump = 1'b0;

end

Page 64 of 69
4'b1100: // BNE

begin

reg_dst = 1'b0;

alu_src = 1'b0;

mem_to_reg = 1'b0;

reg_write = 1'b0;

mem_read = 1'b0;

mem_write = 1'b0;

beq = 1'b0;

bne = 1'b1;

alu_op = 2'b01;

jump = 1'b0;

end

4'b1101: // J

begin

reg_dst = 1'b0;

alu_src = 1'b0;

mem_to_reg = 1'b0;

reg_write = 1'b0;

mem_read = 1'b0;

mem_write = 1'b0;

beq = 1'b0;

bne = 1'b0;

alu_op = 2'b00;

jump = 1'b1;

end

default: begin

reg_dst = 1'b1;

alu_src = 1'b0;

mem_to_reg = 1'b0;

reg_write = 1'b1;

mem_read = 1'b0;

mem_write = 1'b0;

beq = 1'b0;

Page 65 of 69
bne = 1'b0;

alu_op = 2'b00;

jump = 1'b0;

end

endcase

end

endmodule

Verilog code for the 32-bit RISC processor:


module Risc_32_bit(

input clk

);

wire jump,bne,beq,mem_read,mem_write,alu_src,reg_dst,mem_to_reg,reg_write;

wire[1:0] alu_op;

wire [3:0] opcode;

// Datapath

Datapath_Unit DU

.clk(clk),

.jump(jump),

.beq(beq),

.mem_read(mem_read),

.mem_write(mem_write),

.alu_src(alu_src),

.reg_dst(reg_dst),

.mem_to_reg(mem_to_reg),

.reg_write(reg_write),

.bne(bne),

.alu_op(alu_op),

.opcode(opcode)

);

// control unit

Control_Unit control

.opcode(opcode),

Page 66 of 69
.reg_dst(reg_dst),

.mem_to_reg(mem_to_reg),

.alu_op(alu_op),

.jump(jump),

.bne(bne),

.beq(beq),

.mem_read(mem_read),

.mem_write(mem_write),

.alu_src(alu_src),

.reg_write(reg_write)

);

endmodule

Verilog Testbench code for the 32-bit RISC Processor:


module test_Risc_16_bit;

// Inputs

reg clk;

// Instantiate the Unit Under Test (UUT)

Risc_16_bit uut (

.clk(clk)

);

initial

begin

clk <=0;

`simulation_time;

$finish;

end

always

begin

#5 clk = ~clk;

end

endmodule

Page 67 of 69
Simulation:
RTL Schematics:

Schematic Diagram:

Page 68 of 69
End Result:

References

[1] J. P. S. a. M. H. Lipasti, "Modern Processor Design," undamentals of Superscalar , p. 5.7, 2005.

[2] J. L. H. David A. Patterson, "Computer," vol. 3, 2005.

[3] M. V. L. P. Ajith Kumar, "Design of a Pipelined in MIPS," vol. 5, no. 2016, p. 126.

Page 69 of 69

You might also like