基于vivado的32位MIPS单周期CPU设计(无异常中断)

32位单周期CPU

11条指令的功能

每条指令的第一步都是取指令并PC加4,故除了第一行均省略了

在这里插入图片描述

指令集

基本形式

31-2625-2120-1615-1110-65-0
op(6bits)rs(5bits)rt(5bits)rd(5bits)shamt(bits)funct(6bits)
oprsrtimmediate(16bits)
optarget address(26bits)

11条指令:

指令对应的码
add000000_rs_rt_rd_shamt_100000
sub000000_rs_rt_rd_shamt_100010
subu000000_rs_rt_rd_shamt_100011
slt000000_rs_rt_rd_shamt_101010
sltu000000_rs_rt_rd_shamt_101011
ori000001_rt_rs_imm
addiu001000_rt_rs_imm
lw100011_rt_rs_imm
sw101011_rt_rs_imm
beq000100_rs_rt_imm
j000010_addr

CPU内部的控制信号

变量名含义
MemToReg表明是否从Memory中读取数据并写入Reg,1表示是
MemWrite是否写内存,1表示是
Branch分支跳转,将PC更新为计算得出的地址,与ALU输出的Zero配合使用
AluSrcALU第二个操作数的来源,1为立即数,0为寄存器(rt)
RegDst目的寄存器的选取,1选取rt,0为rd
RegWrite是否写寄存器,1表示是
jump表明是直接跳转,使用特定的PC更新方式
PCsrcPCsrc=branch&zero,为1时进行分支跳转
指令OpCodeRegWriteRegDstALUSrcBranchMemWriteMemtoRegALUOp
R-TYPE00000011000010
lw10001110100100
sw1010110X101X00
beq0001000X010X01
addiu00100010100X00
ori00000110100X00
j0000100X000000

注意到lw和sw都需要用到ALU的addu,则可直接根据ALUOp将ALUcth设定为addu

同理,beq拥有唯一的ALUop码01,则可将ALUOp的01对应到sub(相等则Zero置1)

各部件代码

数据通路如图所示:
在这里插入图片描述

0.Registers

module Registers(
    input clk,
    input RegWr, //写使能
    input [4:0]Reg1,
    input [4:0]Reg2,//读取的两个数据rs,rt,5bits    
    input [4:0]RegWrite,//被写的寄存器,rd
    input [31:0]DataWrite,//写用的数据
    output [31:0]Data1,
    output [31:0]Data2 //读出的两个数据
    );
    logic [31:0]RegFile[31:0]; //1024KB,每位32bits
    assign RegFile[0] = 32'b0;//0号寄存器恒为0
    always @ (posedge clk)
        if(RegWr==1&&RegWrite!=0)
            begin
                RegFile[RegWrite]<=DataWrite;
            end 
        //rd判断,如果rd不为0,则说明需要写入
    assign Data1=  RegFile[Reg1];
    assign Data2 = RegFile[Reg2];
    //输出两个寄存器中的值
endmodule

1.DataMemory

module DataMemory(
    input logic clk,
    input logic MemWr,
    input logic [31:0] DataIn,
    input logic [31:0] address,
    output logic [31:0] DataOut
    );
    logic [31:0] RAM[63:0];//32*64的内存
    
    assign DataOut=RAM[address[31:2]];//4bits对齐,读取数据
    
    always_ff@(posedge clk)
        if(MemWr) RAM[address[31:2]]<= DataIn;//内存写使能为1,则进行写
endmodule

2.imem(指令集)

module imem(
    input logic[5:0] address,//0—31
    output logic[31:0] out
    );//用于读取一条指令
    logic [31:0] RAM[63:0];
    
    initial 
     begin
        $readmemh("data.dat",RAM);
     end
     
    assign out=RAM[address];
endmodule

3.MainDec(主译码器)

module MainDec(
    input logic[5:0]op,//传入指令op码,解码出各个控制关系
    output logic MemToReg,MemWrite,//MemToReg为1则从Memory中读取数据,并写入Reg;MemWrite表示写内存
    output logic Branch,AluSrc,//  Branch表明是分支跳转,将PC更新为计算得出的地址;ALU第二个操作数的来源,为1则为立即数
    output logic RegDst,RegWrite,//目的寄存器的选取,为1选取rt,为0选取rd;写寄存器使能
    output logic jump,//表明是直接跳转,使用特定的PC更新方式
    output logic [1:0] ALUop//ALUop码,具体的运算方式需要结合func来确定
    );
    
    logic [8:0] controls;
    
    assign {RegWrite,RegDst,AluSrc,Branch,MemWrite,MemToReg,jump,ALUop} = controls;
    
    always_comb
        case(op)
            6'b000000:controls<=9'b110000010;//RTYPE
            6'b100011:controls<=9'b101001000;//LW
            6'b101011:controls<=9'b001010000;//SW
            6'b000100:controls<=9'b000100001;//BEQ
            6'b001000:controls<=9'b101000000;//ADDI
            6'b000010:controls<=9'b000000100;//J
            6'b000001:controls<=9'b101000011;//ORI
            default:  controls<=9'bxxxxxxxxx;//illegal op
        endcase
endmodule

4.ALUdec(ALU译码器)

module ALUdec(
    input logic [5:0] funct,
    input logic [1:0] ALUop,
    output logic [2:0] ALUcontrol
    );
    always_comb
        case(ALUop)
        2'b00:ALUcontrol<=3'b010;//addu (for lw/sw/addi)
        2'b01:ALUcontrol<=3'b110;//subu (for beq)
        2'b11:ALUcontrol<=3'b001;//or (for ori)
        default:case(funct) //R-type
            6'b100000:ALUcontrol<=3'b010;//addu
            6'b100111:ALUcontrol<=3'b101;//add
            6'b100010:ALUcontrol<=3'b110;//subu
            6'b100011:ALUcontrol<=3'b100;//sub
            6'b100100:ALUcontrol<=3'b000;//and
            6'b100101:ALUcontrol<=3'b001;//or
            6'b101010:ALUcontrol<=3'b111;//slt
            6'b101011:ALUcontrol<=3'b011;//sltu
            default:  ALUcontrol<=3'bxxx;//?
            endcase
         endcase
endmodule

5.Controller

module Controller(
    input logic[5:0]op,
    input logic[5:0]funct,
    input logic zero,
    output logic MemToReg,MemWrite,
    output logic PCsrc,ALUsrc,
    output logic RegDst,RegWrite,
    output logic jump,
    output logic [2:0] ALUctr
    );
//用于将输入的指令转换为控制信号
    logic[1:0]ALUop;
    logic     branch;
    
    MainDec MD(op,MemToReg,MemWrite,branch,ALUsrc,RegDst,RegWrite,jump,ALUop);
    ALUdec AD(funct,ALUop,ALUctr);
    
    assign PCsrc= branch & zero;

6.DataPath(数据通路)

module DataPath(
    input logic clk,reset,
    input logic MemToReg,PCsrc,
    input logic ALUsrc,RegDst,
    input logic RegWrite,jump,
    input logic[2:0] ALUcontrol,
    output logic Zero,
    output logic OF,
    output logic SF,
    output logic [31:0] PC,
    input logic [31:0] Instr,
    output logic [31:0] ALUout,WriteData,
    input logic [31:0] ReadData
    );
    logic [4:0] WriteReg;
    logic[31:0] PCnext,PCnextBr,PCplus4,PCbranch;
    logic[31:0] signimm,signimmsh;
    logic[31:0] srcA,srcB;
    logic[31:0] result;
    
    //计算下一个PC地址
    flopr#(32)  PCreg(clk,reset,PCnext,PC);
    Adder       PCadd1(PC,32'b100,PCplus4);
    sl2         immsh(signimm,signimmsh);
    Adder       PCadd2(PCplus4,signimmsh,PCbranch);
    MUX2#(32)   PCbrmux(PCplus4,PCbranch,PCsrc,PCnextBr);//branch分支跳转
    MUX2#(32)   PCmux(PCnextBr,{PCplus4[31:28],Instr[25:0],2'b00},jump,PCnext);//j跳跃
    
    //寄存器文件逻辑
    Registers   rf(clk,RegWrite,Instr[25:21],Instr[20:16],WriteReg,result,srcA,WriteData);
    MUX2 #(5)   wrmux(Instr[20:16],Instr[15:11],RegDst,WriteReg);
    MUX2 #(32)  resmux(ALUout,ReadData,MemToReg,result);
    SignExt     se(Instr[15:0],signimm);
    
    //ALU逻辑
    MUX2#(32)   srcBmux(WriteData,signimm,ALUsrc,srcB);
    ALU         alu(srcA,srcB,ALUcontrol,ALUout,Zero,OF,SF);
    

7.ALU

module ALU(
    input [31:0] Data1,
    input [31:0] Data2,
    input [2:0] ALUctr,//7个操作
    output logic [31:0] result,
    output logic ZF,
    output logic OF,
    output logic SF
    );
    assign ZF =(result==0)?1:0;
    assign SF =result[31];
    always@(ALUctr or Data1 or Data2) //有效时运行
        begin
        case(ALUctr)
            //add和sub的OF依然会计算,但是否使用取决于指令(是否判断溢出)
            3'b010: begin result=Data1+Data2;OF = 0; end //addu 
            3'b101: begin result=Data1+Data2;OF = (Data1[31]==Data2[31])&&(Data1[31]!=result[31]); end //add
            3'b001: begin OF=0;result = Data1|Data2; end // or
            3'b000: begin OF=0;result = Data1&Data2; end // and 
            3'b110: begin result=Data1-Data2;OF=0;end //subu 
            3'b100: begin result=Data1-Data2;OF=(Data1[31]!=Data2[31])&&(Data2[31]==result[31]); end //sub
            3'b011: begin OF=0;result= Data1<Data2 ; end //sltu
            3'b111: begin OF=0;result=((Data1[31]==Data2[31])&&Data1<Data2)|(Data1[31]==1&&Data2[31]==0); end //slt
        endcase
        end
    
endmodule

8.flopr

//可复位触发器
module flopr #(parameter WIDTH=8)(
    input logic clk,reset,
    input logic [WIDTH-1:0] d,
    output logic [WIDTH-1:0] q
    );
   always_ff@(posedge clk,posedge reset)
        if(reset) q<=0;
        else    q<=d;
   endmodule

9.Adder

module Adder(
    input [31:0] a,b,
    output [31:0] y
    );
    assign y = a+b;
endmodule

10.sl2

module sl2(
    input logic[31:0] a,
    output logic[31:0] y
    );
    assign y={a[29:0],2'b00};
endmodule

11.MUX2

module MUX2 #(parameter WIDTH=32)(
        input logic[WIDTH-1:0]d0,
        input logic[WIDTH-1:0]d1,
        input logic s,//判断
        output logic [WIDTH-1:0]y
    );
    assign y=s?d1:d0;//1则选择d1,0则选择d0
endmodule

12.SignExt

module SignExt(
    input logic [15:0] a,
    output logic [31:0] b
    );
    assign b = {{16{a[15]}},a};
endmodule

13.相关顶层文件

module Mips(
    input logic clk,reset,
    output logic [31:0] PC,
    input logic [31:0] Instr,
    output logic MemWrite,
    output logic [31:0] ALUout,WriteData,
    input logic [31:0] ReadData
    );
    logic MemToReg,ALUsrc,RegDst,RegWrite,jump,PCsrc,Zero,OF,SF;
    logic [2:0] ALUcontrol;
    
    Controller c(Instr[31:26],Instr[5:0],Zero,MemToReg,MemWrite,PCsrc,ALUsrc,RegDst,RegWrite,jump,ALUcontrol);
    DataPath dp(clk,reset,MemToReg,PCsrc,ALUsrc,RegDst,RegWrite,jump,ALUcontrol,Zero,OF,SF,PC,Instr,ALUout,WriteData,ReadData);
endmodule

module CPU_top(
    input clk,reset,
    output [31:0] WriteData,DataAdr,//ALUout
    output MemWrite
    );
    logic [31:0]PC,Instr,ReadData;
    
    Mips mips (clk,reset,PC,Instr,MemWrite,DataAdr,WriteData,ReadData);
    imem imem (PC[7:2],Instr);
    DataMemory dm(clk,MemWrite,WriteData,DataAdr,ReadData);
endmodule

data.dat

#AssemblyAddressMachine
main:addi $2,$0,502002005
addi $3,$0,1242003000c
addi $7, $3,-982067fff7
or $4, $7, $2c00e22025
and $5, $3, $41000642824
add $5, $5, $41400a42820
beq $5, $7,end1810a7000a
slt $4, $3,$41c0064202a
beq $4, $0,around2010800001
addi $5, $0,02420050000
around:slt $5,$7, $22800e2202a
add $7, $4, $52c00853820
sub $7, $7, $23000e23822
sw $7,68($3)34ac670044
lw $2, $80( $0)388c020050
j end3c08000011
addi $2, $0,14020020001
end:sw $2,84($0)44ac020054
  • 13
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值