MIPS指令 31条多周期CPU(Verilog)
注意
这是本人大二《计算机组成与系统结构》实验的期末课设,毕业答辩时拿了95分。以下代码为全部代码,可直接使用,并带有CPU仿真代码,额外带有冒泡排序的汇编代码及其对应的机器代码作为该CPU的测试指令。
实验目的
(1)认识和掌握多周期数据通路原理及其设计方法;
(2)掌握多周期CPU的实现方法,代码实现方法;
(3)初步掌握了MARS的使用,将MIPS汇编程序编译为二进制机器码;
(4)掌握多周期CPU的测试方法。
实验内容
1、实验原理:
多周期CPU指的是将整个CPU的执行过程分成几个阶段,每个阶段用一个时钟去完成,然后开始
下一条指令的执行,而每种指令执行时所用的时钟数不尽相同,这就是所谓的多周期CPU。CPU
在处理指令时,一般需要经过以下几个阶段:
(1) 取指令(IF):根据程序计数器pc中的指令地址,从存储器中取出一条指令,同时,pc根据指令字长度自动递增产生下一条指令所需要的指令地址,但遇到“地址转移”指令时,则控制器把“转移地址”送入pc,当然得到的“地址”需要做些变换才送入pc。
(2)指令译码(ID):对取指令操作中得到的指令进行分析并译码,确定这条指令需要完成的操
作,从而产生相应的操作控制信号,用于驱动执行状态中的各种操作。
(3)指令执行(EXE):根据指令译码得到的操作控制信号,具体地执行指令动作,然后转移到
结果写回状态。
(4) 存储器访问(MEM):所有需要访问存储器的操作都将在这个步骤中执行,该步骤给出存储器的数据地址,把数据写入到存储器中数据地址所指定的存储单元或者从存储器中得到数据地址单元中的数据。
(5) 结果写回(WB):指令执行的结果或者访问存储器中得到的数据写回相应的目的寄存器中。
2、实验步骤:
(1)先将寄存器模块、PC模块、ALU模块、IR模块、指令存储器模块、扩展器模块、数据存储器模块、Br模块及各个多路选择器模块搭建好。
(2)编写控制模块,输出所有的控制信号。
(3)编写顶层模块,构建数据通路。
(4)测试指令,验证CPU的正确性:
31条指令为:
代码
## 顶层模块
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2021/05/30 18:34:50
// Design Name:
// Module Name: main
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module main(
input clk,
output [2:0]state,
output [31:0] alu_a,
output [31:0] alu_b,
output [3:0]aluctr,
output [31:0]da,
output [31:0]db,
output [31:0]OP,
output rd,
output pcwr,
output pcwrcond,
output [1:0]pcsource,
output irwr,
output [31:0]i_pc,
output [31:0]o_pc,
output [31:0] aluout
);
wire [31:0] din,dout,outdata1,dw,py,pc0,outdata,outbr,insout;
wire [4:0]rw;
wire [1:0]alusela,aluselb,regdst,memtoreg;
wire extop,brwr,regwr,memwr,overflow,Z,zero;
parameter [31:0]si=4;
parameter [4:0]ssy=5'b11111;
assign outdata1=outdata<<2;
assign pc0={o_pc[31:28],OP[25:0],2'b0};
assign py={27'b0,OP[10:6]};
CU CU1(clk,OP[31:26],OP[5:0],zero,alusela,aluselb,extop,pcsource,brwr,regwr,regdst,memtoreg,irwr,memwr,rd,pcwr,aluctr,pcwrcond,state,Z);
PC PC1(clk,i_pc,pcwr,pcwrcond,Z,o_pc);
RAM RAM1(aluout,db,memwr,dout);
ROM ROM1(rd,o_pc,insout);
Br Br1(aluout,clk,brwr,outbr);
IR IR1(clk,insout,irwr,OP);
Extend Extend1(OP[15:0],extop,outdata);
mux35 mux351(OP[20:16],OP[15:11],ssy,regdst,rw);
mux3_2 mux3_21(aluout,dout,o_pc,memtoreg,dw);
RegFile RegFile1(OP[25:21],OP[20:16],rw,dw,regwr,overflow,da,db);
mux3_1 mux3_11(o_pc,da,py,alusela,alu_a);
mux4 mux41(db,si,outdata,outdata1,aluselb,alu_b);
alu alu1(alu_a,alu_b,aluctr,aluout,zero,overflow);
mux4_1 mux4_11(pc0,aluout,outbr,da,pcsource,i_pc);
endmodule
## 控制模块
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2021/05/30 17:52:14
// Design Name:
// Module Name: CU
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module CU(
input clk,
input [5:0] op,
input [5:0] func,
input zero,
//output [2:0] ALUop,
//output reg RTypes,
output reg [1:0]ALUSelA,
output reg [1:0]ALUSelB,
output reg ExtOp,
output reg [1:0]PCSource,
output reg BrWr,
output reg RegWr,
output reg [1:0]RegDst,
output reg [1:0]MemtoReg,
output reg IRWr,
output reg MemWr,
output reg IorD,
output reg PCWr,
output reg [3:0] ALUCtr,
output reg PCWrCond,
output reg[2:0]state,
output reg Z
);
//reg PCWr=0;
parameter [2:0] s00=3'b000,
sif=3'b001,//?
sid=3'b010,
sexe=3'b011,
smem=3'b100,
swb=3'b101;
//reg [2:0] state=3'b0;
reg [2:0] next_state;
wire i_add,i_addu,i_sub,i_subu,i_lw,i_sw,i_beq,i_j,i_ori,i_addi,
i_and,i_or,i_xor,i_nor,i_slt,i_sltu,i_sll,i_srl,i_sra,i_sllv,
i_srlv,i_srav,i_jr,i_addiu,i_andi,i_xori,i_lui,i_bne,i_slti,i_sltiu,i_jal;
wire [3:0]addu,subu,add,sub,OR,AND,XOR,NOR,slt,sltu,sll,srl,sra,lui;
assign addu=4'b0000;
assign subu=4'b0100;
assign add=4'b0001;
assign sub=4'b0101;
assign AND=4'b0011;
assign OR=4'b0010;
assign XOR=4'b0110;
assign NOR=4'b0111;//或非
assign slt=4'b1001;
assign sltu=4'b1010;
assign sll=4'b1011;
assign srl=4'b1100;
assign sra=4'b1101;
assign lui=4'b1110;
assign i_add=(op[5:0]==6'b000000&&func[5:0]==6'b100000)?1:0;
assign i_addu=(op[5:0]==6'b000000&&func[5:0]==6'b100001)?1:0;
assign i_sub=(op[5:0]==6'b000000&&func[5:0]==6'b100010)?1:0;
assign i_subu=(op[5:0]==6'b000000&&func[5:0]==6'b100011)?1:0;
assign i_and=(op[5:0]==6'b000000&&func[5:0]==6'b100100)?1:0;
assign i_or= (op[5:0]==6'b000000&&func[5:0]==6'b100101)?1:0;
assign i_xor=(op[5:0]==6'b000000&&func[5:0]==6'b100110)?1:0;
assign i_nor=(op[5:0]==6'b000000&&func[5:0]==6'b100111)?1:0;
assign i_slt=(op[5:0]==6'b000000&&func[5:0]==6'b101010)?1:0;
assign i_sltu=(op[5:0]==6'b000000&&func[5:0]==6'b101011)?1:0;
assign i_sll=(op[5:0]==6'b000000&&func[5:0]==6'b000000)?1:0;
assign i_srl=(op[5:0]==6'b000000&&func[5:0]==6'b000010)?1:0;
assign i_sra=(op[5:0]==6'b000000&&func[5:0]==6'b000011)?1:0;
assign i_sllv=(op[5:0]==6'b000000&&func[5:0]==6'b000100)?1:0;
assign i_srlv=(op[5:0]==6'b000000&&func[5:0]==6'b000110)?1:0;
assign i_srav=(op[5:0]==6'b000000&&func[5:0]==6'b000111)?1:0;
assign i_jr=(op[5:0]==6'b000000&&func[5:0]==6'b001000)?1:0;
//17
assign i_addi=(op[5:0]==6'b001000)?1:0;
assign i_addiu=(op[5:0]==6'b001001)?1:0;
assign i_andi=(op[5:0]==6'b001100)?1:0;
assign i_ori=(op[5:0]==6'b001101)?1:0;
assign i_xori=(op[5:0]==6'b001110)?1:0;
assign i_lui=(op[5:0]==6'b001111)?1:0;
assign i_lw=(op[5:0]==6'b100011)?1:0;
assign i_sw=(op[5:0]==6'b101011)?1:0;
assign i_beq=(op[5:0]==6'b000100)?1:0;
assign i_bne=(op[5:0]==6'b000101)?1:0;
assign i_slti=(op[5:0]==6'b001010)?1:0;
assign i_sltiu=(op[5:0]==6'b001011)?1:0;
//12
assign i_j=(op[5:0]==6'b000010)?1:0;
assign i_jal=(op[5:0]==6'b000011)?1:0;
//2
initial
begin
state=s00;
PCWr=0;
IRWr=0;
MemWr=0;
RegWr=0;
PCWrCond=0;
BrWr=0;
IorD=0;
PCSource=2'b00;
Z=zero;
//ALUCtr=0;
end
always@(zero or state)
begin
case(state)
s00:begin0
PCWr=1;
PCSource=2'b01;
next_state=sif;
end
sif:begin ///1
PCWr=1;
BrWr=0;
PCSource=2'b01;
IRWr=1;
IorD=1;//?
MemWr=0;
ALUSelA=2'b00;
ALUSelB=2'b01;
ALUCtr=addu;
RegWr=0;
next_state=sid;
end
sid:begin 2
PCWr=0;
BrWr=1;
IRWr=0;
PCWrCond=0;
Z=zero;
MemWr=0;
ALUSelA=2'b00;
ALUSelB=2'b11;
ALUCtr=addu;
IorD=0;
ExtOp=1;
RegWr&