Download - Project single cyclemips processor_verilog
Designing a Single Cycle MIPS microprocessor inVerilog
Harsha Yelisala
Spring 2009
Technology Profile
The following technologies are used in this project,
I MIPS Processor Architecture.
I Verilog HDL.
I VHDL HDL.
I ModelSim 6.2 SE
I Timing Analysis
I SPIM
Aim
The Objectives of this project are
I 1. To design a Single Cycle MIPS Microprocessor in Verilogand simulate the design in Modelsim.
I 2. To get hands-on experience in Verilog coding.
I 3. To get working expertise in using the Modelsim PEStudent Edition 6.6a.
I 4. To understand the various stages of a processor design.
I 5. To analyze a processor from timing perspective.
Abstract
Designing a processor is one of the most challenging tasks in chipdesigning industry. Being part of processor making is the ultimategoal of many hardware engineers. Hence a thorough understandingof working of a processor is of high importance. This project dealswith designing a single cycle microprocessor in Verilog. The designis then simulated in Modelsim.
Work Flow
I 1. Studying the data path of a processor from ComputerOrganization and Design, The Hardware Software Interface3rd Edition 2004.
I 2. Creating Verilog modules for each functional unit of thedatapath.
I 3. Testing the created modules with customized test benches.
I 4. Combining the designed modules to a single top module.
I 5. Verifying and testing the final module in Modelsim.
Datapath
The datapath of a processor has the following functional units.
I 1. ProgramCounter
I 2. Register File
I 3. Arithmetic Logic Unit
I 4. Instruction Memory
I 5. Data Memory
I 6. Adders
I 7. Multiplexors
I 8. Shifters
I 9. SignExtender and
I 10. Control Unit
Datapath
Control Information
ALU Control Lines Function
0000 AND0001 OR0010 ADD0110 SUB0111 SLT1100 NOR
Alu Control Implementation-1 of 2
Opcode AluOp Operation Funct Field Desired ALU Action ALU Control output
LW 00 load word XXXXXX add 0010SW 00 store word XXXXXX add 0010
BEQ 01 branch equal XXXXXX sub 0110R-type 10 add 100000 add 0010R-type 10 sub 100010 sub 0110R-type 10 and 100100 and 0000R-type 10 or 100101 or 0001R-type 10 slt 101010 set lessthan 0111
Alu Control Implementation-2 of 2
AluOp 1 AluOp 0 F5 F4 F3 F2 F1 F0 Operation
0 0 X X X X X X 0010
X 1 X X X X X X 0110
1 X X X 0 0 0 0 0010
1 X X X 0 0 1 0 0110
1 X X X 0 1 0 0 0000
1 X X X 0 1 0 1 0001
1 X X X 1 0 1 0 0111
Control Block Implementation
Control R-Format LW SW BEQ
RegDst 1 0 X X
ALUSrc 0 1 1 0
MemtoReg 0 1 X X
RegWrite 1 1 0 0
MemRead 0 1 0 0
MemWrite 0 0 1 0
Branch 0 0 0 1
AluOp1 1 0 0 0
AluOp 0 0 0 0 1
ProgramCounter
module PC(clock,reset,pcin,pcout);
input clock;
input reset;
input [31:0] pcin;
output [31:0] pcout;
reg clk;
reg [31:0] pcout;
initial
begin
clk=clock;
end
always
#5 clk = ~clk;
always @(posegde(clk))
pcout<=pcin;
endmodule
RegisterFile
module REGISTERS(ReadRegister1,ReadRegister2, WriteRegister, WriteData_reg,RegWrite,ReadData1,ReadData2);
input [4:0] ReadRegister1, ReadRegister2, WriteRegister;
input [31:0] WriteData_reg;
input RegWrite;
output [31:0] ReadData1, ReadData2;
reg [31:0] ReadData1, ReadData2;
reg [31:0] REG[0:31];
integer i;
initial
begin
for(i=0;i<32;i=i+1)
REG[i]=0;
end
always @(ReadRegister1,ReadRegister2,RegWrite,WriteRegister,WriteData_reg)
if(RegWrite==1’b1)
REG[WriteRegister]=WriteData_reg;
else
begin
ReadData1 <= REG[ReadRegister1];
ReadData2 <= REG[ReadRegister2];
end
endmodule
ArithmeticLogicUnit
module ALU(Read_data_1, Read_data_2, ALUControl, ALUresult, isZero);
input [31:0] Read_data_1, Read_data_2;
input [3:0] ALUControl;
output [31:0]ALUresult, isZero;
reg [31:0] ALUresult, isZero;
reg [3:0] addcode, subcode, andcode, orcode, sltcode;
initial begin
addcode[3:0] <= 4’b0010;
subcode[3:0] <= 4’b0110;
andcode[3:0] <= 4’b0000;
orcode[3:0] <= 4’b0001;
sltcode[3:0] <= 4’b0111;
end
always @(Read_data_1, Read_data_2, ALUControl)
if (ALUControl == addcode) //add
ALUresult = Read_data_1 + Read_data_2;
else if(ALUControl == subcode) //sub
ALUresult = Read_data_1 - Read_data_2;
else if(ALUControl == andcode) //and
ALUresult = Read_data_1 & Read_data_2;
else if(ALUControl == orcode) //or
ALUresult = Read_data_1 | Read_data_2;
else if(ALUControl == sltcode) //slt
if(Read_data_1 < Read_data_2)
ALUresult = 32’b00000000000000000000000000000001;
else
ALUresult = 32’b00000000000000000000000000000000;
always @(Read_data_1, Read_data_2, ALUControl,ALUresult)
if(ALUresult == 32’b0)
isZero = 32’b00000000000000000000000000000001;
else
isZero = 32’b00000000000000000000000000000000;
endmodule
InstructionMemory
module INSTRUCTIONMEMORY(ReadAddress,Instruction);
input [31:0] ReadAddress;
output [31:0] Instruction;
reg [31:0] Instruction;
reg [31:0] IMEM[0:64];
integer i;
initial begin
for(i=0;i<64;i=i+1)
IMEM[i]=1’b0;
end
always @(ReadAddress)
Instruction=IMEM[ReadAddress];
endmodule
DataMemory
module DATAMEMORY(Address,MemWrite,MemRead,WriteData,ReadData);
input [31:0] Address;
input MemWrite;
input MemRead;
input [31:0] WriteData;
output [31:0] ReadData;
reg [31:0] ReadData;
reg [31:0] RAM[0:63];
integer i,j;
initial
begin
for(i=0;i<64;i=i+1)
for(j=0;j<32;j=j+1)
RAM[i][j]<=0;
end
always @(Address,MemWrite,MemRead,WriteData)
if(MemWrite==1’b1)
RAM[Address]=WriteData;
else if(MemRead==1’b1)
ReadData=RAM[Address];
endmodule
ControlUnitmodule CONTROL(opcode,RegDst,Branch,MemRead,MemtoReg,ALUOp,MemWrite,ALUSrc,RegWrite);
input [6:0] opcode;
output RegDst, Branch, MemRead, MemtoReg, MemWrite, ALUSrc, RegWrite;
output [1:0] ALUOp;
reg RegDst, Branch, MemRead, MemtoReg, MemWrite, ALUSrc, RegWrite;
reg [1:0] ALUOp;
always @(opcode)
begin
if(opcode==6’b000000) //r controls
begin
RegDst<=1’b1;
ALUSrc<=1’b0;
MemtoReg<=1’b0;
RegWrite<=1’b1;
MemRead<=1’b0;
MemWrite<=1’b0;
Branch<=1’b0;
ALUOp<=2’b10;
end
if(opcode==6’b100011) //lw controls
begin
RegDst<=1’b0;
ALUSrc<=1’b1;
MemtoReg<=1’b1;
RegWrite<=1’b1;
MemRead<=1’b1;
MemWrite<=1’b0;
Branch<=1’b0;
ALUOp<=2’b00;
end
if(opcode==6’b101011) //sw controls
begin
RegDst<=1’bx;
ALUSrc<=1’b1;
MemtoReg<=1’bx;
RegWrite<=1’b0;
MemRead<=1’b0;
MemWrite<=1’b1;
Branch<=1’b0;
ALUOp<=2’b00;
end
if(opcode==6’b101011) //beq controls
begin
RegDst<=1’bx;
ALUSrc<=1’b0;
MemtoReg<=1’bx;
RegWrite<=1’b0;
MemRead<=1’b0;
MemWrite<=1’b0;
Branch<=1’b1;
ALUOp<=2’b01;
end
end
endmodule
Adders and Multiplexors
module ADD(data1, data2, sum);
input [31:0] data1;
input [31:0] data2;
output [31:0]sum;
reg [31:0]sum;
always @(data1, data2)
sum = data1 + data2;
endmodule
module MUX(mux_in_1,mux_in_2,sel,mux_out);
input [31:0] mux_in_1;
input [31:0] mux_in_2;
input sel;
output [31:0] mux_out;
reg [31:0] mux_out;
always @(mux_in_1,mux_in_2,sel)
if(sel==1’b0)
mux_out=mux_in_1;
else
mux_out=mux_in_2;
endmodule
Shifter and Signextender
module SHIFTLEFT(shift_in,shift_out);
input [31:0] shift_in;
output [31:0] shift_out;
reg [31:0] shift_out;
reg [29:0] temp;
always @(shift_in)
shift_out= shift_in<<2;
endmodule
module SIGNEXTEND(sign_in, sign_out);
input [15:0] sign_in;
output [31:0] sign_out;
reg [31:0] sign_out;
reg [31:0] tmp;
integer i;
initial
begin
sign_out <=32’b0;
end
always @(sign_in)
if(sign_in[15] == 0)
sign_out = {32’b000000000000000000,sign_in};
else
sign_out = {32’b111111111111111111,sign_in};
endmodule
SingleCycleMIPSProcessormodule SINGLECYCLEMIPSPROCESSOR(globalclock,globalreset);
input globalclock;
input globalreset;
wire [31:0] _pcout;
wire [31:0] _Instruction;
wire [31:0] _ReadData1;
wire [31:0] _ReadData2;
wire _RegDst,_Branch,_MemRead,_MemtoReg,_MemWrite,_ALUSrc,_RegWrite;
wire [1:0] _ALUOp;
wire [31:0] _sign_out;
wire [31:0] _shift_out;
wire [31:0] _sum_pcplus4;
wire [31:0] _sum_branchadder;
wire _sel_regfiledest;
wire [31:0] _mux_out_alusrc;
wire _sel_alusrc;
wire [31:0] _mux_out_branchornot;
wire _sel_branchornot;
wire [31:0] #20 _mux_out_regfiledata;
wire [4:0] _mux_out_regfiledest_5b;
wire [3:0] _ALUControl;
wire [31:0] _ReadData;
wire [31:0] _ALUresult;
wire _isZero;
//After Portmapping
PC mypc(.clock(globalclock),.reset(globalreset),.pcin(_mux_out_branchornot),.pcout(_pcout));
INSTRUCTIONMEMORY myinstructionmemory(.ReadAddress(_pcout),.Instruction(_Instruction));
REGISTERS myregisters(.ReadRegister1(_Instruction[25:21]),.ReadRegister2(_Instruction[20:16]),.WriteRegister(_mux_out_regfiledest_5b),.WriteData_reg(_mux_out_regfiledata),.RegWrite(_RegWrite),.ReadData1(_ReadData1),.ReadData2(_ReadData2));
CONTROL mycontrol(.opcode(_Instruction[31:26]),.RegDst(_RegDst),.Branch(_Branch),.MemRead(_MemRead),.MemtoReg(_MemtoReg),.ALUOp(_ALUOp),.MemWrite(_MemWrite),.ALUSrc(_ALUSrc),.RegWrite(_RegWrite));
SIGNEXTEND mysignextend( .sign_in(_Instruction[15:0]), .sign_out(_sign_out) );
SHIFTLEFT myshiftleft( .shift_in(_sign_out), .shift_out(_shift_out) );
ADDPLUS4 myadd_pc_plus4(.data1(_pcout), .sum(_sum_pcplus4));
ADD myadd_branchadder(.data1(_sum_pcplus4), .data2(_shift_out), .sum(_sum_branchadder));
MUX5B mymux_regfiledest( .mux_in_1(_Instruction[20:16]), .mux_in_2(_Instruction[15:11]), .sel(_RegDst), .mux_out(_mux_out_regfiledest_5b) );
MUX mymux_alusrc( .mux_in_1(_ReadData2), .mux_in_2(_sign_out), .sel(_ALUSrc), .mux_out(_mux_out_alusrc) );
AND a(_sel_branchornot,Branch,isZero);
MUX mymux_branchornot( .mux_in_1(_sum_pcplus4), .mux_in_2(_sum_branchadder), .sel(_sel_branchornot), .mux_out(_mux_out_branchornot) );
MUX mymux_regfiledata( .mux_in_1(_ReadData), .mux_in_2(_ALUresult), .sel(_MemtoReg), .mux_out(_mux_out_regfiledata) );
ALUCONTROL myalucontrol( .ALUop(_ALUOp), .Funct(_Instruction[5:0]), .ALUControl(_ALUControl) );
DATAMEMORY mydatamemory(.Address(_ALUresult),.MemWrite(_MemWrite),.MemRead(_MemRead),.WriteData(_ReadData2),.ReadData(_ReadData));
ALU myalu( .Read_data_1(_ReadData1), .Read_data_2(_mux_out_alusrc), .ALUControl(_ALUControl), .ALUresult(_ALUresult),.isZero(_isZero) );
endmodule
Pros-Cons
Pros
I Simple to design
I CPI is always 1.
Cons
I It is inefficient.
I Every clockcycle must have the same length as the longestpossible path(Load instruction) in the design making the otherinstructions which work in lesser cycle time are forced to workfor extra time.
I Though the CPI is 1, the overall system performance of thedesign is not good.
Conclusion
In this academic project,
I A single cycle MIPS microprocessor is designed.
I Understood the design flow for the datapath design in aProcessor design.
I Experience gained in Verilog coding and debugging.
I Experience gained in usage of ModelSim 6.2 SE.
I Understood the necessity of Pipelining and other advancedtechniques for processor design.