DEPARTMENT OF COMPUTER & SOFTWARE
ENGINEERING
COLLEGE OF E&ME, NUST, RAWALPINDI
Subject Name
Computer System Architecture
Lab Report
02
SUBMITTED TO:
Dr. Muhammad Yasin
LE Malyka Awais
SUBMITTED BY:
Student Name
1. Muhammad Mussa Kazim #404047
2. Bazil bin Amir #432243
3. Hashir Ashraf #408557
4. Sohaib Afzal #411928
DE- 44 Dept C&SE- Syn B
Task:
MIPS 32 Processor:
Code:
1. Top Level:
`timescale 1ns / 1ps
module toplevel(
output[31:0] Result,
output[31:0] storedWord,
output reg[7:0]sevenseg,
output reg[3:0] anodes,
output reg [20:0]counter,
input clk, // switch
//input inclk, // In bult clk
input tempJump,
input temppcSrc,
input [31:0] branchAddress,
input [31:0] jumpAddress,
input[31:0] writeData,
input sw
);
initial
begin
counter = 21'd0;
end
wire[31:0] pcOut;
wire[31:0] instruction;
wire[5:0] opcode;
wire[5:0] funct;
wire[31:0] extendedtemp;
wire zeroFlag;
wire pcSrc;
instructionFetch uut1(pcOut,instruction,opcode,funct,clk,branchAddress,jumpAddress,tempJump,pcSrc,extendedtemp,zeroFlag);
wire RegDst;
wire RegWrite;
wire ALUSrc;
wire [2:0] ALUOp;
wire MemWrite;
wire MemRead;
wire MemToReg;
wire ExtOp;
wire Branch;
wire Jump;
controlUnit uut2(RegDst,RegWrite,ALUSrc,ALUOp,MemWrite,MemRead,MemToReg,ExtOp,Branch,Jump,pcSrc,opcode,funct,clk);
// assign tempJump = Jump;
//assign temppcSrc = pcSrc;
wire[31:0] rsData;
wire[31:0] rtData;
wire[31:0] rdData;
wire[31:0] extendedImmediate;
//wire[5:0] funct;
wire[4:0] shamt;
//wire[5:0] opcode;
wire [4:0]writeDataAddress;
wire[4:0] rs;
wire[4:0] rt;
instructionDecoder
uut3(rsData,rtData,rdData,extendedImmediate,shamt,writeDataAddress,rs,rt,clk,instruction,writeData,RegWrite,RegDst,ExtOp);
wire[31:0] ALUResult;
ALUmodule uut4(zeroFlag,ALUResult,rsData,rtData,extendedImmediate,ALUOp,ALUSrc);
DataMemory uut5(Result,storedWord,rtData,rs,rs,ALUResult,MemWrite,MemToReg,clk);
wire[31:0] rsData2;
wire[31:0] rtData2;
wire[31:0] rdData2;
wire[31:0] extendedImmediate2;
//output[5:0] funct,
wire[4:0] shamt2;
//output[5:0] opcode,
wire[4:0]writeDataAddress2;
wire[4:0] rs2;
wire[4:0] rt2;
instructionDecoder
uut6(rsData2,rtData2,rdData2,extendedImmediate2,shamt2,writeDataAddress2,rs2,rt2,clk,instruction,Result,RegWrite,RegDst,ExtOp);
assign extendedtemp = extendedImmediate;
reg [15:0] res;
always@(*)
begin
if(sw==1'b0)
begin
res = Result[15:0];
end
else
begin
res = Result[31:16];
end
end
always@(posedge clk)
begin
if(counter == 21'd4000000)
begin
anodes <= 4'b1110;
end
else if(counter == 21'd8000000)
begin
anodes <= 4'b1101;
end
else if(counter == 21'd12000000 )
begin
anodes <= 4'b1011;
end
else if(counter == 21'd16000000)
begin
anodes <= 4'b0111;
counter <= 21'd0;
end
counter <=counter+21'd1;
end
initial
begin
sevenseg = ~8'b00111111;
end
always @(posedge clk)
begin
case(anodes)
4'b0111:
case(res[15:12])
4'b0000: sevenseg = ~8'b00111111;
4'b0001: sevenseg = ~8'b00000110;
4'b0010: sevenseg = ~8'b01011011;
4'b0011: sevenseg = ~8'b01001111;
4'b0100: sevenseg = ~8'b01100110;
4'b0101: sevenseg = ~8'b01101101;
4'b0110: sevenseg = ~8'b01111101;
4'b0111: sevenseg = ~8'b00000111;
4'b1000: sevenseg = ~8'b01111111;
4'b1001: sevenseg = ~8'b01101111;
4'b1010: sevenseg = ~8'b01110111;
4'b1011: sevenseg = ~8'b11111111;
4'b1100: sevenseg = ~8'b00111001;
4'b1101: sevenseg = ~8'b00111111;
4'b1110: sevenseg = ~8'b01111001;
4'b1111: sevenseg = ~8'b01110001;
default: sevenseg = 8'b00000000;
endcase
4'b1011:
case(res[11:8])
4'b0000: sevenseg = ~8'b00111111;
4'b0001: sevenseg = ~8'b00000110;
4'b0010: sevenseg = ~8'b01011011;
4'b0011: sevenseg = ~8'b01001111;
4'b0100: sevenseg = ~8'b01100110;
4'b0101: sevenseg = ~8'b01101101;
4'b0110: sevenseg = ~8'b01111101;
4'b0111: sevenseg = ~8'b00000111;
4'b1000: sevenseg = ~8'b01111111;
4'b1001: sevenseg = ~8'b01101111;
4'b1010: sevenseg = ~8'b01110111;
4'b1011: sevenseg = ~8'b11111111;
4'b1100: sevenseg = ~8'b00111001;
4'b1101: sevenseg = ~8'b00111111;
4'b1110: sevenseg = ~8'b01111001;
4'b1111: sevenseg = ~8'b01110001;
default: sevenseg = 8'b00000000;
endcase
4'b1101:
case(res[7:4])
4'b0000: sevenseg = ~8'b00111111;
4'b0001: sevenseg = ~8'b00000110;
4'b0010: sevenseg = ~8'b01011011;
4'b0011: sevenseg = ~8'b01001111;
4'b0100: sevenseg = ~8'b01100110;
4'b0101: sevenseg = ~8'b01101101;
4'b0110: sevenseg = ~8'b01111101;
4'b0111: sevenseg = ~8'b00000111;
4'b1000: sevenseg = ~8'b01111111;
4'b1001: sevenseg = ~8'b01101111;
4'b1010: sevenseg = ~8'b01110111;
4'b1011: sevenseg = ~8'b11111111;
4'b1100: sevenseg = ~8'b00111001;
4'b1101: sevenseg = ~8'b00111111;
4'b1110: sevenseg = ~8'b01111001;
4'b1111: sevenseg = ~8'b01110001;
default: sevenseg = 8'b00000000;
endcase
4'b1110:
case(res[3:0])
4'b0000: sevenseg = ~8'b00111111;
4'b0001: sevenseg = ~8'b00000110;
4'b0010: sevenseg = ~8'b01011011;
4'b0011: sevenseg = ~8'b01001111;
4'b0100: sevenseg = ~8'b01100110;
4'b0101: sevenseg = ~8'b01101101;
4'b0110: sevenseg = ~8'b01111101;
4'b0111: sevenseg = ~8'b00000111;
4'b1000: sevenseg = ~8'b01111111;
4'b1001: sevenseg = ~8'b01101111;
4'b1010: sevenseg = ~8'b01110111;
4'b1011: sevenseg = ~8'b11111111;
4'b1100: sevenseg = ~8'b00111001;
4'b1101: sevenseg = ~8'b00111111;
4'b1110: sevenseg = ~8'b01111001;
4'b1111: sevenseg = ~8'b01110001;
default: sevenseg = 8'b00000000;
endcase
default: sevenseg = ~8'b00111111;
endcase
end
endmodule
2. Control Unit:
// Define the timescale
`timescale 1ns / 1ps
// Define the Control Unit module
module controlUnit(
output RegDst, // Output: Selects destination register
output RegWrite, // Output: Enables register write
output ALUSrc, // Output: Selects ALU input source
output [2:0] ALUOp, // Output: ALU operation code
output MemWrite, // Output: Enables memory write
output MemRead, // Output: Enables memory read
output MemToReg, // Output: Selects memory to register data
output ExtOp, // Output: Selects sign extension operation
output Branch, // Output: Enables branch operation
output Jump, // Output: Enables jump operation
output pcSrc, // Output: Selects the next PC source
input [5:0] opcode, // Input: Opcode
input [5:0] funct, // Input: Function code
input clk // Input: Clock
);
// Define internal registers for control signals
reg tempRegDst;
reg tempRegWrite;
reg tempALUSrc;
reg [2:0] tempALUOp;
reg tempMemWrite;
reg tempMemRead;
reg tempMemToReg;
reg tempExtOp;
reg tempBranch;
reg tempJump;
reg temppcSrc;
// Combinational logic to generate control signals
always @(*) begin
if (opcode == 6'b000000) begin // R TYPE
tempRegDst <= 1'b1;
tempRegWrite <= 1'b1;
tempALUSrc <= 1'b0;
tempMemWrite <= 1'b0;
tempMemRead <= 1'b0;
tempMemToReg <= 1'b0;
tempExtOp <= 1'b0;
tempJump <= 1'b0;
tempBranch <= 1'b0;
temppcSrc <= 1'b0;
if (funct == 6'b100000) // ADD
tempALUOp <= 3'b010;
else if (funct == 6'b100010) // SUBTRACT
tempALUOp <= 3'b110;
end
else if (opcode == 6'b000010) begin // STORE WORD
tempRegDst <= 1'b0;
tempRegWrite <= 1'b0;
tempALUSrc <= 1'b1;
tempALUOp <= 3'b010;
tempMemWrite <= 1'b1;
tempMemRead <= 1'b0;
tempMemToReg <= 1'b0;
tempExtOp <= 1'b0;
tempJump <= 1'b0;
tempBranch <= 1'b0;
temppcSrc <= 1'b0;
end
else if (opcode == 6'b010011) begin // LOAD WORD
tempRegDst <= 1'b0;
tempRegWrite <= 1'b1;
tempALUSrc <= 1'b1;
tempALUOp <= 3'b010;
tempMemWrite <= 1'b0;
tempMemRead <= 1'b1;
tempMemToReg <= 1'b1;
tempExtOp <= 1'b0;
tempJump <= 1'b0;
tempBranch <= 1'b0;
temppcSrc <= 1'b0;
end
else if (opcode == 6'b000100) begin // BEQ
tempRegDst <= 1'b0;
tempRegWrite <= 1'b0;
tempALUSrc <= 1'b0;
tempALUOp <= 3'b110;
tempMemWrite <= 1'b0;
tempMemRead <= 1'b0;
tempMemToReg <= 1'b0;
tempExtOp <= 1'b1;
tempJump <= 1'b0;
tempBranch <= 1'b1;
temppcSrc <= 1'b1;
end
else if (opcode == 6'b011111) begin // JUMP
tempRegDst <= 1'b0;
tempRegWrite <= 1'b0;
tempALUSrc <= 1'b0;
tempALUOp <= 3'b000;
tempMemWrite <= 1'b0;
tempMemRead <= 1'b0;
tempMemToReg <= 1'b0;
tempExtOp <= 1'b0;
tempJump <= 1'b1;
tempBranch <= 1'b0;
temppcSrc <= 1'b0;
end
end
// Assign control signals to outputs
assign RegDst = tempRegDst;
assign RegWrite = tempRegWrite;
assign ALUSrc = tempALUSrc;
assign ALUOp = tempALUOp;
assign MemWrite = tempMemWrite;
assign MemRead = tempMemRead;
assign MemToReg = tempMemToReg;
assign ExtOp = tempExtOp;
assign Jump = tempJump;
assign Branch = tempBranch;
assign pcSrc = temppcSrc;
endmodule
3. ALU Module:
// Define the timescale
`timescale 1ns / 1ps
// Define the ALU module
module ALUmodule(
output zeroFlag, // Output: Indicates if the result is zero
output [31:0] ALUResult, // Output: ALU result
input [31:0] rs, // Input: Operand rs
input [31:0] rt, // Input: Operand rt
input [31:0] extendedImmediate, // Input: Extended immediate value
input [2:0] ALUOp, // Input: ALU operation code
input ALUSrc // Input: Selects ALU input source
);
// Internal registers and wires
reg [31:0] tempALUResult; // Temporary ALU result
reg tempzeroFlag; // Temporary zero flag
reg [31:0] srcA; // Source A
reg [31:0] srcB; // Source B
// Combinational logic to compute ALU result and zero flag
always @(*) begin
// Assign source A from rs
srcA = rs;
// Select source B based on ALUSrc
if (ALUSrc == 1'b0) begin
srcB = rt;
end
else begin
srcB = extendedImmediate;
end
// Perform ALU operation based on ALUOp
if (ALUOp == 3'b010) begin // ADD
tempALUResult = srcA + srcB;
end
else if (ALUOp == 3'b110) begin // SUBTRACT
tempALUResult = srcA - srcB;
end
// Set zero flag if result is zero
if (tempALUResult == 32'd0) begin
tempzeroFlag = 1'b1;
end
else begin
tempzeroFlag = 1'b0;
end
end
// Assign outputs
assign ALUResult = tempALUResult;
assign zeroFlag = tempzeroFlag;
endmodule
4. Data Memory:
`timescale 1ns / 1ps
module DataMemory(
output[31:0] Result,
output[31:0] storedWord,
input[31:0] rtData,
input[4:0] writeDataAddress, //rs
input[4:0] readDataAddress, //rs
input [31:0] ALUResult,
input MemWrite,
input MemToReg,
input clk
);
parameter DATA_FILE = "dataMemory.txt";
parameter INIT_START_ADDR = 0;
parameter INIT_END_ADDR = 10;
//reg[31:0] dataMemory [31:0];
/* initial
begin
dataMemory[0] = 32'd0;
dataMemory[1] = 32'd1;
dataMemory[2] = 32'd2;
dataMemory[3] = 32'd3;
dataMemory[4] = 32'd4;
dataMemory[5] = 32'd5;
dataMemory[6] = 32'd6;
dataMemory[7] = 32'd7;
dataMemory[8] = 32'd8;
dataMemory[9] = 32'd9;
dataMemory[10] = 32'd10;
dataMemory[11] = 32'd11;
dataMemory[12] = 32'd12;
dataMemory[13] = 32'd13;
dataMemory[14] = 32'd14;
dataMemory[15] = 32'd15;
dataMemory[16] = 32'd16;
dataMemory[17] = 32'd17;
dataMemory[18] = 32'd18;
dataMemory[19] = 32'd19;
dataMemory[20] = 32'd20;
dataMemory[21] = 32'd21;
dataMemory[22] = 32'd22;
dataMemory[23] = 32'd23;
dataMemory[24] = 32'd24;
dataMemory[25] = 32'd25;
dataMemory[26] = 32'd26;
dataMemory[27] = 32'd27;
dataMemory[28] = 32'd28;
dataMemory[29] = 32'd29;
dataMemory[30] = 32'd30;
dataMemory[31] = 32'd31;
end */
(* RAM_STYLE="BLOCK" *)
reg [31:0] dataMemory [31:0];
// The forllowing code is only necessary if you wish to initialize the RAM
// contents via an external file (use $readmemb for binary data)
initial
$readmemh(DATA_FILE, dataMemory, INIT_START_ADDR, INIT_END_ADDR);
reg[31:0] tempResult;
reg[31:0] tempstoredWord;
always@(*)
begin
if(MemWrite==1)
begin
dataMemory[writeDataAddress] = rtData; //dataMemory[rs] = rtData (sw)
tempstoredWord = dataMemory[writeDataAddress];
end
if(MemToReg==1)
begin
tempResult = dataMemory[readDataAddress]; // rt = dataMemory[rs] (lw)
end
else
begin
tempResult = ALUResult;
end
end
assign storedWord = tempstoredWord;
assign Result = tempResult;
endmodule
5. Instruction Decoder:
`timescale 1ns / 1ps
module instructionDecoder(
output[31:0] rsData,
output[31:0] rtData,
output[31:0] rdData,
output[31:0] extendedImmediate,
//output[5:0] funct,
output[4:0] shamt,
//output[5:0] opcode,
output [4:0]writeDataAddress,
output[4:0] rs,
output[4:0] rt,
input clk,
input[31:0] instruction,
input[31:0] writeData,
input RegWrite, //� Write Enable signal for the Register File
input RegDst, //� Selects the write address for the Register File
input ExtOp //� selects between Sign and Zero extension of the immediate field
);
parameter DATA_FILE = "registerFile.txt";
parameter INIT_START_ADDR = 0;
parameter INIT_END_ADDR = 10;
// reg [31:0] registerFile[31:0];
(* RAM_STYLE="BLOCK" *)
reg [31:0] registerFile [31:0];
// The forllowing code is only necessary if you wish to initialize the RAM
// contents via an external file (use $readmemb for binary data)
initial
$readmemh(DATA_FILE, registerFile, INIT_START_ADDR, INIT_END_ADDR);
/* initial
begin
registerFile[0] = 32'd5;
registerFile[1] = 32'd10;
registerFile[2] = 32'd20;
registerFile[3] = 32'd30;
registerFile[4] = 32'd40;
registerFile[5] = 32'd50;
registerFile[6] = 32'd60;
registerFile[7] = 32'd70;
registerFile[8] = 32'd80;
registerFile[9] = 32'd90;
registerFile[10] = 32'd100;
registerFile[11] = 32'd110;
registerFile[12] = 32'd120;
registerFile[13] = 32'd130;
registerFile[14] = 32'd140;
registerFile[15] = 32'd150;
registerFile[16] = 32'd160;
registerFile[17] = 32'd170;
registerFile[18] = 32'd180;
registerFile[19] = 32'd190;
registerFile[20] = 32'd200;
registerFile[21] = 32'd210;
registerFile[22] = 32'd220;
registerFile[23] = 32'd230;
registerFile[24] = 32'd240;
registerFile[25] = 32'd250;
registerFile[26] = 32'd260;
registerFile[27] = 32'd270;
registerFile[28] = 32'd280;
registerFile[29] = 32'd290;
registerFile[30] = 32'd300;
registerFile[31] = 32'd310;
end */
reg[4:0] temprs;
reg[4:0] temprt;
reg[4:0] rd;
reg[15:0] immediate;
reg[25:0] jumpConst;
reg [4:0]writeAddress; //ADDRESS TO WRITE TO (RT OR RD AFTER MUX)
assign shamt = instruction[10:6];
always@(*)
begin
temprs = instruction[25:21];
temprt = instruction[20:16];
rd = instruction[15:11];
immediate = instruction[15:0];
jumpConst = instruction[25:0];
end
assign rs = temprs;
assign rt= temprt;
reg[31:0] tempextendedImmediate;
always@(posedge clk)
begin
if(ExtOp==1)
begin
tempextendedImmediate[14:0] = immediate[14:0];
if(immediate[15] == 1'b0)
begin
tempextendedImmediate[30:15] = 16'd0;
end
else
begin
tempextendedImmediate[30:15] = 16'b1111111111111111;
end
tempextendedImmediate[31] = immediate[15];
end
end
reg[31:0] temprsData;
reg[31:0] temprtData;
always@(*)
begin
temprsData <= registerFile[rs];
temprtData <= registerFile[rt];
if(RegDst == 0)
begin
writeAddress <= rt;
end
else
begin
writeAddress <= rd;
end
if(RegWrite==1)
begin
registerFile[writeAddress] <= writeData;
end
end
assign writeDataAddress = writeAddress;
assign extendedImmediate = tempextendedImmediate;
assign rsData = temprsData;
assign rtData = temprtData;
assign rdData = registerFile[rd];
endmodule
6. Instruction Fetch:
`timescale 1ns / 1ps
module instructionFetch(
output [31:0] pcOut,
output [31:0] instruction,
output [5:0] opcode,
output [5:0] funct,
input clk,
input [31:0] branchAddress,
input [31:0] jumpAddress,
input jump,
input pcSrc,
input [31:0] constant,
input zeroflag
);
initial
begin
pc=31'd0;
end
parameter DATA_FILE = "instructionMem.txt";
parameter INIT_START_ADDR = 0;
parameter INIT_END_ADDR = 10;
reg [31:0] pc;
reg [31:0] instrOut;
reg [31:0] tempconstant;
reg [31:0] tempbranchAddress;
// RAM for instruction memory
reg [31:0] instructionMemory [31:0];
// Initialize instruction memory
initial begin
$readmemb(DATA_FILE, instructionMemory, INIT_START_ADDR, INIT_END_ADDR);
// pc = 0;
end
always @(posedge clk) begin
instrOut = instructionMemory[pc];
if (pcSrc != 1) begin
pc = pc + 1; // Increment PC if pcSrc is 0
end else if (zeroflag == 1) begin
tempconstant = constant; // Store constant value
tempbranchAddress = tempconstant << 2; // Calculate branch address
pc = tempbranchAddress; // Set PC to branch address
end else begin
if (jump == 1) begin
pc = jumpAddress; // Set PC to jump address if jump signal is 1
end else begin
pc = pc; // Do nothing to PC if jump signal is 0
end
end
end
// Outputs
assign branchAddress = tempbranchAddress;
assign instruction = instrOut;
assign pcOut = pc - 1;
assign opcode = instruction[31:26];
assign funct = instruction[5:0];
endmodule
7. TestBench:
module topleveltb;
// Inputs
reg clk;
reg [31:0] branchAddress;
reg [31:0] jumpAddress;
reg jump;
reg pcSrc;
// Instantiate the Unit Under Test (UUT)
toplevel uut (
.clk(clk),
.branchAddress(branchAddress),
.jumpAddress(jumpAddress),
.jump(jump),
.pcSrc(pcSrc)
);
initial
begin
clk=0;
forever #100 clk=~clk;
end
initial begin
// Initialize Inputs
branchAddress = 0;
jumpAddress = 0;
jump = 0;
pcSrc = 0;
// Wait 100 ns for global reset to finish
#100;
// Add stimulus here
end
endmodule
FPGA Picture:
We are storing the 32 bit result of our Processor in the variable
‘Result[31:0]’ which is being displayed on the FPGA using the ucf file
constraints.
We are using the first two 7 segment displays for displaying 16 bits
alternatively.
The 16 Least significant bits are displayed using the ‘T10’ switch being
off (i.e. T10 = 1’b0) and the 16 most significant bits are being displayed
on the 7-segment display using the same switch ‘T10’ being on (i.e. T10 =
1’b1).
The second switch T9 is used for the clock.
Conclusion:
In conclusion, this lab provided valuable hands-on experience in
implementing a MIPS processor on an FPGA, enhancing understanding of
various modules of the processor such as ALU, Data Memory, and other
modules.