0% found this document useful (0 votes)
17 views

Lab Report 06

The document describes a MIPS 32 processor implementation including a top level module, control unit module and ALU module. It contains code for these modules to perform operations like addition, subtraction, loading, storing and branching based on control signals from the control unit. Register transfers and data processing take place according to the MIPS instruction set.

Uploaded by

mussa
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
17 views

Lab Report 06

The document describes a MIPS 32 processor implementation including a top level module, control unit module and ALU module. It contains code for these modules to perform operations like addition, subtraction, loading, storing and branching based on control signals from the control unit. Register transfers and data processing take place according to the MIPS instruction set.

Uploaded by

mussa
Copyright
© © All Rights Reserved
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 19

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.

You might also like