多周期CPU设计(verilog)

一、设计思路

1.主要参照:

计算机组成与系统结构(第2版)(袁春风)中央处理器及所学知识

2.多周期处理器

把每条指令的执行分成多个大致相等的阶段,每个阶段在一个时钟周期内完成;各阶段内最多完成一次访存或一次寄存器读写或一次ALU操作;各阶段的执行结果在下一次时钟到来时保存到相应存储单元或稳定的保持在组合电路中;时钟周期的宽度以最复杂阶段所用时间为准,通常取一次存储器读写的时间。

3.指令周期:

  • 取指令(IF):根据程序计数器PC中的指令地址,从存储器中取出一条指令。同时,PC根据指令子长度自动递增产生下一条指令所需要的指令地址,但遇到地址转移指令时,则控制器把转移地址送入PC,得到的地址做些变换送入PC。
  • 指令译码(ID):对取指令操作中得到的指令进行分析和译码,确定这条指令需要完成的操作,从而产生相应的操作控制信号,用于驱动执行状态中的各种操作。
  • 指令执行(EXE):跟据指令译码得到的操作控制信号,具体的执行指令动作,然后转移到结果写回状态。
  • 存储器访问(MEM):所有需要访问存储器的操作都将在这个步骤中执行,该步骤给出存储器的数据地址,把数据写入到存储器中数据地址所指定的存储单元或者从存储器中得到数据地址单元中的数据。
  • 结果写回(WB):指令执行的结果或者访问存储器中得到的数据写回相应的目的寄存器中。

在这里插入图片描述

4.MIPS指令:

MIPS指令可以分为三种类型,每种类型的指令需要不同的时钟周期数。

  • 寄存器型(R型)指令

    oprsrtrdshamtfunct
    6位5位5位5位5位6位
  • 立即数型(I型)指令

    oprsrtimmediate
    6位5位5位16位
  • 跳转型(J型)指令

    opaddr
    6位26位

    op:操作码

    rs:第1个源操作数寄存器

    rt:第2个源操作数寄存器,或目的操作数寄存器

    rd:目的操作数寄存器

    shamt:位移量,移位指令用于指定移多少位

    func:功能码,在R类型指令中用来指定指令的功能

    immediate:16位立即数

    addr:地址

二、主要模块设计

1.总体模块构成

在这里插入图片描述

2. MultiCycleCPU.v

MultiCycleCPU作为顶层模块,只有一个CLK(时钟信号)作为输入,时钟周期在仿真模块中设置。

MultiCycleCPU通过调用每个模块,并控制信号在相应模块间的传递来实现多周期CPU的功能。

在这里插入图片描述

3. PCctr.v

PCctr计算下一条指令的地址,并对pc在刚开始进行置0初始化。

对于pc的改变有三种形式,beq指令,jump指令,其他。

要实现pc地址的正确计算,需要在取一条指令后,进行+4指向下一条指令,但是对于jump指令并不需要进行+4的操作。所以增加PCWre信号,当不为jump指令时设置位1。当PCWre为1时进行pc+4,对于jump指令则不进行这个操作。对于beq指令,则在译码产生Branch信号后在已经+4的pc基础上在加上扩展后的立即数即可。

PCctr模块设计如下,左侧是输入信号,右侧是输出信号。

端口名称说明
pc_in输入pc值
PCWrepc写使能
imm取自指令后26位,对于beq则在此基础上截取后16位
Zero控制信号,用于beq指令
Branch控制信号,用于beq指令
Jump控制信号,用于jump指令
pc_out输出pc值

在这里插入图片描述

3. ControlUnit.v

ControlUnit模块主要根据当前指令的op和func生成对应的控制信号,同时根据当前状态和操作码确定下一状态。

控制信号的生成

在这里插入图片描述

参照书上的11条MIPS指令,加上addu指令,共兼容12条MIPS指令。

funcopALUctr
addu000000100001000
  • ALUctr(ALU控制信号)编码方案:

addiulwswaddu的ALU控制信号取值一样,都是进行加法运算并不判溢出,记为addu操作。

sububeq判0操作的ALU控制信号可看成一样,都做减法运算并不判溢出,记为subu操作。

ALU操作类型funcALUctr
addu100001000
add100000001
or010
subu100011100
sub100010101
sltu101011110
slt101010111

对于R-type型指令,除了ALUctr信号以外,其余控制信号的取值都相等

R—型指令的ALUctr信号的取值由其func字段决定

由上面func与ALUctr的对应关系,可得:

ALUctr[2]=!func[2] & func[1]

ALUctr[1]=func[3] & func[2] & func[1]

ALUctr[0]=!func[3] & !func[2] & !func[1] & !func[0] + !func[2] + func[1] + !func[0]

I—型指令,J—型指令的ALUctr控制信号的取值由op字段决定,可得编码方案:

ALUctr[2]=beq= !op[5] & !op[4] & !op[3] & op[2] & !op[1] & !op[0]

ALUctr[1]=ori= !op[5] & !op[4] & op[3] & op[2] & !op[1] & op[0]

ALUctr[0]=R-type= !op[5] & !op[4] & !op[3] & !op[2] & !op[1] & !op[0]

对于其他控制信号,采用编码方案有些复杂,采用判断的形式来生成它们的信号。

状态转换

有限状态机控制器思想:

用一个有限状态机描述指令执行过程,由当前状态和操作码确定下一状态,每来一个时钟发生一次状态改变,不同状态输出不同的控制信号值,然后送到数据通路来控制指令的执行。

在设计时采用与书上的有限状态机控制器思想有些不同的思路,不采用不同状态输出不同控制信号。控制信号在ID(指令译码)阶段同时生成,增加输出信号IF_clk、ID_clk、ALU_clk、MEM_clk、WB_clk区分指令的不同阶段,根据不同的状态来修改这些信号的值。通过这些信号来触发指令的不同执行阶段。

在多周期CPU中,不同的指令分别占用不同的周期数。查阅资料,不同的指令参照如下的状态转移图:

在这里插入图片描述

最后,ControlUnit模块设计如下(具体实现代码太多,只选取端口声明部分):

module ControlUnit(
clk,Opcode,func,
Branch,Jump,RegDst,ALUSrc,ALUctr,MemorReg,RegWr,MemWr,ExtOp,PCWre,
IF_clk,ID_clk,ALU_clk,MEM_clk,WB_clk,
state_out
    );
    input clk;
    input [5:0] Opcode;
    input [5:0] func;
    output reg Branch;
    output reg Jump;
    output reg RegDst;
    output reg ALUSrc;
    output reg [2:0] ALUctr;
    output reg MemorReg;
    output reg RegWr;
    output reg MemWr;
    output reg ExtOp;
    output reg PCWre;
    output reg [2:0] state_out;
    
    output reg IF_clk;
    output reg ID_clk;
    output reg ALU_clk;
    output reg MEM_clk;
    output reg WB_clk;
输入、输出端口声明:
端口名称说明
clk时钟周期
Opcode操作码
func功能码,在R类型指令中用来指定指令的功能
Branchbeq
Jumpjump
RegDst选择写回结果的寄存器编号
ALUSrcALU输入来源
ALUctrALU操作码
MemorReg数据来自存储器还是ALU结果
RegWrRegisterFile写使能
MemWr存储器写使能
ExtOp扩展方式
PCWre修改pc值
state_out状态输出
IF_clk取指信号
ID_clk指令译码信号
ALU_clk指令执行信号
MEM_clk存储器访问信号
WB_clk结果写回信号

3. 其他模块

ALU32.v总体与第一次课程设计相同,根据此次多周期CPU进行适当修改。

其他模块的实现也比较简单,前面总体模块构成已大概介绍。比较难实现的是考虑各种信号在不同模块间的传递,以及将模块组合后可以协调工作顺利实现多周期CPU的功能。

四、模块间主要信号传递

这里只标识了主要信号的传递,别的信号大致采用同名表示同一信号传递。

除MultiCycleCPU外,主要模块大致都是左侧是输入信号,右侧是输出信号。

在这里插入图片描述

五、功能仿真

1. 仿真文件

每1ps个时间单位时钟信号反转一次,即时钟周期为2ps

module MultiCycleCPU_test(

    );
    
//    module MultiCycleCPU(
//                CLK,
//                Opcode,ALU_in1,ALU_in2,ALU_result,STATE_out,PC_out,
//                IF_clk,ID_clk,ALU_clk,MEM_clk,WB_clk
//                    );
    reg CLK;
    wire IF_clk,ID_clk,ALU_clk,MEM_clk,WB_clk;
    wire [5:0] Opcode;
    
    wire [31:0] ALU_in1;
    wire [31:0] ALU_in2;
    wire [31:0] ALU_result;
    wire [31:0] PC_out;
    
    MultiCycleCPU cpu32(
            .CLK(CLK),
            .Opcode(Opcode),
            .ALU_in1(ALU_in1),
            .ALU_in2(ALU_in2),
            .ALU_result(ALU_result),
            .PC_out(PC_out),
            .IF_clk(IF_clk),
            .ID_clk(ID_clk),
            .ALU_clk(ALU_clk),
            .MEM_clk(MEM_clk),
            .WB_clk(WB_clk)
            );
            
    initial
        begin
            CLK=0;
        end
    always #0.001 CLK=~CLK;
endmodule

2. 存储的指令

 memory[0]=32'b000000_00111_00010_00010_00000_100000;//add reg[2]=reg[7]+reg[2]
 memory[1]=32'b000000_00010_00111_00100_00000_100011;//subu reg[4]=reg[2]-reg[7]
 memory[2]=32'b000000_00000_00001_00010_00000_101011;//sltu reg[0]<reg[1]?reg[2]=1:reg[2]=0
 memory[3]=32'b001101_00011_00100_0010011111000001;//ori reg[4]=reg[3]|zeroext(0010011111000001)
 memory[4]=32'b101011_00101_00110_0000000000000111;//sw reg[6]=6 MEM[reg[5]+SignExt(imm16)<=reg[6]
 memory[5]=32'b100011_00101_00111_0000000000000111;//lw reg[7]<=MEM[reg[5]+SignExt(imm16)
 memory[6]=32'b000000_00111_00010_00011_00000_100000;//add reg[7]=6,,reg[2]=1,reg[3]=reg[7]+reg[2]
 memory[7]=32'b000100_00001_00010_0000000000000001;//beq reg[1]==reg[2] ? pc<=pc+4+SignExt(0000000000000001)*4 : pc<=pc+4
      //memory[8]beq跳转到memory[9]
 memory[9]=32'b000010_00000_00000_00000_00000_111111;//jump pc<=0000_00000_00000_00000_00000_111111_00

3. 测试

对照CLK、IF_clk、ID_clk、ALU_clk、MEM_clk、WB_clk所划分的周期可以很容易验证指令的执行情况。

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

六、模块代码

1. MultiCycleCPU

module MultiCycleCPU(
CLK,
Opcode,ALU_in1,ALU_in2,ALU_result,PC_out,
IF_clk,ID_clk,ALU_clk,MEM_clk,WB_clk
    );
    input CLK;
    output [5:0] Opcode;
    output [31:0] ALU_in1;
    output [31:0] ALU_in2;
    output [31:0] ALU_result;
    output [31:0] PC_out;//计算出的下一个pc值
    
    output IF_clk,ID_clk,ALU_clk,MEM_clk,WB_clk;
    //ControlUnit输出信号
    wire PCWre,Branch,Jump,RegDst,ALUSrc,MemorReg,MemWr,ExtOp;
    wire RegWr;
    wire [2:0] ALUctr;
    
    wire [2:0] STATE_out;
    
    //ALU输出信号
    wire Carryout,Zero,Overflow;
    
    wire [31:0] PC_in;
    
    //从指令中取出的相关数据
    wire [25:0] Imm26;
    wire [5:0] FUNC;
    wire [4:0] RS;
    wire [4:0] RT;
    wire [4:0] RD;
    
    wire [31:0] DataMem_out;
    
    //RegisterFile相关
    wire [31:0] data_to_registerfile;
    //wire [31:0] ALU_data1;
    wire [31:0] ALU_temp_data1;
    
    wire [31:0] ALU_temp_data2;
    //wire [31:0] ALU_data2;
//    module PCctr(
//           clk,PCWre,Branch, Jump, Zero, imm,pc_in,pc_out);
//imm取自指令后26位
    PCctr pcctr(
                .PCWre(PCWre),
                .Branch(Branch),
                .Jump(Jump),
                .Zero(Zero),
                .imm(Imm26),
                .pc_in(PC_in),
                .pc_out(PC_out)
                );
      
      
//      module PC_in_out(
//                        clk,pc_in,
//                        pc_out  ); 
//把当前pc值PC_out,送入PC_in,以便PCctr下一次计算
        PC_in_out pc_in_out(
                    .clk(CLK),
                    .pc_in(PC_out),
                    .pc_out(PC_in)
                    );            
    
//    module InstructionMem(
//        pc,IF_clk,
//        ins_Opcode,ins_func,ins_rs,ins_rt,ins_rd,ins_imm );
//imm取自指令后26位
    InstructionMem IM(
                        .pc(PC_out),
                        .IF_clk(IF_clk),
                        .ins_Opcode(Opcode),
                        .ins_func(FUNC),
                        .ins_rs(RS),
                        .ins_rt(RT),
                        .ins_rd(RD),
                        .ins_imm(Imm26)
                        );
       
//       module ControlUnit(
//                    clk,Opcode,func,
//                    Branch,Jump,RegDst,ALUSrc,ALUctr,MemorReg,RegWr,MemWr,ExtOp,PCWre,
//                    IF_clk,ID_clk,ALU_clk,MEM_clk,WB_clk,
//                    state_out
//                        );
        ControlUnit controlunit(
                    .clk(CLK),
                    .Opcode(Opcode),
                    .func(FUNC),
                    .Branch(Branch),
                    .Jump(Jump),
                    .RegDst(RegDst),
                    .ALUSrc(ALUSrc),
                    .ALUctr(ALUctr),
                    .MemorReg(MemorReg),
                    .RegWr(RegWr),
                    .MemWr(MemWr),
                    .ExtOp(ExtOp),
                    .PCWre(PCWre),
                    .IF_clk(IF_clk),
                    .ID_clk(ID_clk),
                    .ALU_clk(ALU_clk),
                    .MEM_clk(MEM_clk),
                    .WB_clk(WB_clk),
                    .state_out(STATE_out)
                    );
                    
              
//      module RegisterFile(
//                WB_clk,RegWr,Overflow,RegDst,Ra,Rb,Rc,busW,
//                busA,busB ); 
        RegisterFile registerfile(
                    .WB_clk(WB_clk),
                    .RegWr(RegWr),
                    .Overflow(Overflow),
                    .RegDst(RegDst),
                    .Ra(RS),
                    .Rb(RT),
                    .Rc(RD),
                    .busW(data_to_registerfile),
                    .busA(ALU_in1),
                    .busB(ALU_temp_data1)
                    );  
           
           
//           module Extender(
//                    ExtOp,ex_imm,
//                    ex_out
//                        ); 
            Extender extender(
                        .ExtOp(ExtOp),
                        .ex_imm(Imm26),
                        .ex_out(ALU_temp_data2)
                        );
                                
//         module ALUSrc_select(
//                        ALUSrc,busB,imm36,
//                        src_out );           
           ALUSrc_select alusrc_select(
                    .ALUSrc(ALUSrc),
                    .busB(ALU_temp_data1),
                    .imm36(ALU_temp_data2),
                    .src_out(ALU_in2)
           );
           
//           module ALU32(
//                    ALU_clk,ALUctr,in0,in1,
//                    carryout,overflow,zero,out );
           ALU32 alu32(
                       .ALU_clk(ALU_clk),
                       .ALUctr(ALUctr),
                       .in0(ALU_in1),
                       .in1(ALU_in2),
                       .carryout(Carryout),
                       .overflow(Overflow),
                       .zero(Zero),
                       .out(ALU_result)
                       );
                       
                       
//           module DataMem(
//                    MEM_clk,WrEn,Adr,DataIn,
//                    DataOut
//                        );
             DataMem datamem(
                      .MEM_clk(MEM_clk),
                      .WrEn(MemWr),
                      .Adr(ALU_result),
                      .DataIn(ALU_temp_data1),
                      .DataOut(DataMem_out)
                      );
                      
//             module Data_select(
//                    MemorReg,ALU_out,DataMem_out,
//                    Data_out
//                        );
               Data_select data_select(
                        .MemorReg(MemorReg),
                        .ALU_out(ALU_result),
                        .DataMem_out(DataMem_out),
                        .Data_out(data_to_registerfile)
                        );
                      
                       
endmodule

2. PCctr

module PCctr(
PCWre,Branch, Jump, Zero, imm,pc_in,pc_out
    );
    //input clk;
    input PCWre;
    input Branch;
    input Jump;
    input Zero;
    input [25:0] imm;//imm取自指令的后26位
    input [31:0] pc_in;
    output reg [31:0] pc_out;
    initial
    begin
        pc_out=0;
    end
    //clk上升沿触发
    always @(Jump or Branch or Zero or PCWre)
    if(Jump)
        pc_out={pc_in[31:28],imm[25:0],1'b0,1'b0};
    else if(Branch&&Zero)
        pc_out=pc_in+{{14{imm[15]}},imm[15:0],1'b0,1'b0};
    else if(!Jump&&PCWre)
        pc_out=pc_in+4;
        
endmodule

3. PC_in_out

module PC_in_out(
clk,pc_in,
pc_out
    );
    input clk;
    input [31:0] pc_in;
    output reg [31:0] pc_out;
    
    always@(posedge clk)
    begin
        pc_out<=pc_in;
    end
endmodule

4. InstructionMem

module InstructionMem(
pc,IF_clk,
ins_Opcode,ins_func,ins_rs,ins_rt,ins_rd,ins_imm
    );
    input [31:0] pc;
    input IF_clk;
    output reg [5:0] ins_Opcode;
    output reg [5:0] ins_func;
    output reg [4:0] ins_rs;
    output reg [4:0] ins_rt;
    output reg [4:0] ins_rd;
    output reg [25:0] ins_imm;
    reg [31:0] memory[64:0];
    
    initial
    begin
      memory[0]=32'b000000_00111_00010_00010_00000_100000;//add reg[2]=reg[7]+reg[2]
      memory[1]=32'b000000_00010_00111_00100_00000_100011;//subu reg[4]=reg[2]-reg[7]
      memory[2]=32'b000000_00000_00001_00010_00000_101011;//sltu reg[0]<reg[1]?reg[2]=1:reg[2]=0
      memory[3]=32'b001101_00011_00100_0010011111000001;//ori reg[4]=reg[3]|zeroext(0010011111000001)
      memory[4]=32'b101011_00101_00110_0000000000000111;//sw reg[6]=6 MEM[reg[5]+SignExt(imm16)<=reg[6]
      memory[5]=32'b100011_00101_00111_0000000000000111;//lw reg[7]<=MEM[reg[5]+SignExt(imm16)
      memory[6]=32'b000000_00111_00010_00011_00000_100000;//add reg[7]=6,,reg[2]=1,reg[3]=reg[7]+reg[2]
      memory[7]=32'b000100_00001_00010_0000000000000001;//beq reg[1]==reg[2] ? pc<=pc+4+SignExt(0000000000000001)*4 : pc<=pc+4
      //memory[8]beq跳转到memory[9]
      memory[9]=32'b000010_00000_00000_00000_00000_111111;//jump pc<=0000_00000_00000_00000_00000_111111_00
    end
    
    always @(posedge IF_clk)
    begin
       ins_Opcode=memory[pc[31:2]][31:26];
       ins_func=memory[pc[31:2]][5:0];
       ins_rs=memory[pc[31:2]][25:21];
       ins_rt=memory[pc[31:2]][20:16];
       ins_rd=memory[pc[31:2]][15:11];
       ins_imm=memory[pc[31:2]][25:0];
    end
        
endmodule

5. ControlUnit

module ControlUnit(
clk,Opcode,func,
Branch,Jump,RegDst,ALUSrc,ALUctr,MemorReg,RegWr,MemWr,ExtOp,PCWre,
IF_clk,ID_clk,ALU_clk,MEM_clk,WB_clk,
state_out
    );
    input clk;
    input [5:0] Opcode;
    input [5:0] func;
    output reg Branch;
    output reg Jump;
    output reg RegDst;
    output reg ALUSrc;
    output reg [2:0] ALUctr;
    output reg MemorReg;
    output reg RegWr;
    output reg MemWr;
    output reg ExtOp;
    output reg PCWre;
    output reg [2:0] state_out;
    
    output reg IF_clk;
    output reg ID_clk;
    output reg ALU_clk;
    output reg MEM_clk;
    output reg WB_clk;
    
    parameter [2:0] IF=3'b000,//IF state
                     ID=3'b001,//ID state
                     EXE1=3'b110,//add,sub,subu,slt,sltu,ori,addiu
                     EXE2=3'b101,//beq
                     EXE3=3'b010,//sw lw
                     MEM=3'b011,//MEM state
                     WB1=3'b111,//add,sub,subu,slt,sltu,ori,addiu
                     WB2=3'b100;//lw
    parameter [5:0] R_type=6'b000000,
                     ori=6'b001101,
                     addiu=6'b001001,
                     lw=6'b100011,
                     sw=6'b101011,
                     beq=6'b000100,
                     jump=6'b000010;
    //状态寄存器                 
    reg [2:0] state,next_state;
  
    initial
        begin
        Branch=0;
        Jump=0;
        RegDst=0;
        ALUSrc=0;
        ALUctr=0;
        MemorReg=0;
        RegWr=0;
        MemWr=0;
        ExtOp=0;
        PCWre=0;
        state=3'b000;
        state_out=state;
        end
        
        //上升沿触发
        always@(posedge clk)
        begin
            state<=next_state;
            state_out=state;
        end
        
        always@(state)
        begin
        case(state)
            //IF阶段无条件跳转到ID阶段
            IF:  next_state<=ID;
            //ID阶段
            ID:
                begin
                    if(Opcode == jump)
                        next_state<=IF;
                    else if(Opcode==beq)
                        next_state<=EXE2;
                    else if(Opcode==lw||Opcode==sw)
                        next_state<=EXE3;
                    else
                        next_state<=EXE1;
                end
            EXE1:next_state<=WB1;
            EXE2:next_state<=IF;
            EXE3:next_state<=MEM;
            MEM:
                begin
                    if(Opcode==lw)
                        next_state=WB2;
                    else
                        next_state=IF;
                end
           WB1:next_state<=IF;
           WB2:next_state<=IF;
           default:next_state=IF;
      endcase
      end
      
      
      always @(next_state)
      begin
            if(next_state==IF)
                IF_clk=1;
            else
                IF_clk=0;
            
            if(next_state==ID)
                ID_clk=1;
            else
                ID_clk=0;
            
            if(next_state==EXE1||next_state==EXE2||next_state==EXE3)
                ALU_clk=1;
            else
                ALU_clk=0;
                
            if(next_state==MEM)
                MEM_clk=1;
            else
                MEM_clk=0;
            
            if(next_state==WB1||next_state==WB2)
                WB_clk=1;
            else
                WB_clk=0;
                
      end
      
      always@(state)
      begin
        if(state==IF&&Opcode!=jump)
            PCWre<=1;
        else
            PCWre<=0;
        if(Opcode==R_type)
            begin
            Branch<=0;
            Jump<=0;
            RegDst<=1;
            ALUSrc<=0;
            MemorReg<=0;
            RegWr<=1;
            MemWr<=0;
            ALUctr[2]<=(~func[2])&func[1];
            ALUctr[1]<=func[3]&(~func[2])&func[1];
            ALUctr[0]<=((~func[3])&(~func[2])&(~func[1])&(~func[0])) | ((~func[2])&func[1]&(~func[0]));
            end
        else
            begin
            if(Opcode==beq)
                Branch<=1;
            else
                Branch<=0;
                
            if(Opcode==jump)
                Jump<=1;
            else
                Jump<=0;
                
            RegDst<=0;
            
            if(Opcode==ori||Opcode==addiu||Opcode==lw||Opcode==sw)
                ALUSrc<=1;
            else
                ALUSrc<=0;
                
            if(Opcode==lw)
                MemorReg<=1;
            else
                MemorReg<=0;
                
            if(Opcode==ori||Opcode==addiu||Opcode==lw)
                RegWr<=1;
             else
                RegWr<=0;
                
             if(Opcode==sw)
                MemWr<=1;
             else
                MemWr<=0;
                
             if(Opcode==addiu||Opcode==lw||Opcode==sw)
                ExtOp<=1;
             else
                ExtOp<=0;
                
             ALUctr[2]<=~Opcode[5]&~Opcode[4]&~Opcode[3]&Opcode[2]&~Opcode[1]&~Opcode[0];
             ALUctr[1]<=~Opcode[5]&~Opcode[4]&Opcode[3]&Opcode[2]&~Opcode[1]&Opcode[0];
             ALUctr[0]<=0;
             end
       end  
            
      
           
endmodule

6. RegisterFile

module RegisterFile(
WB_clk,RegWr,Overflow,RegDst,Ra,Rb,Rc,busW,
busA,busB
    );
    input WB_clk;
    input RegWr;
    input Overflow;
    input RegDst;
    //Ra(Rs),Rb(Rt),Rc(Rd)
    input [4:0] Ra;
    input [4:0] Rb;
    input [4:0] Rc;
    
    input [31:0] busW;
    output  reg [31:0] busA;
    output  reg [31:0] busB;
    reg [31:0] RegMem [31:0];//32个32位宽寄存器
    
    //初始化寄存器中的值
    integer i;
    initial 
    begin
//        RegMem[0]<=5;
//        RegMem[1]<=32'b11;
//        RegMem[2]<=32'b10;
        for(i=0;i<32;i=i+1)
            RegMem[i]<=i;
    end
    
    always @(Ra or Rb)
    begin
     busA=RegMem[Ra];
     busB=RegMem[Rb];
    end
    
    always@(posedge WB_clk or RegWr)
    begin
    //RegMem[2]<=2;
        if(RegWr&&!Overflow)
        begin
            if(RegDst)
//                RegMem[2]=2;
                RegMem[Rc]<=busW;
            else
               
                RegMem[Rb]<=busW;
                
        end
     end
    
endmodule

7. Extender

module Extender(
ExtOp,ex_imm,
ex_out
    );
    input ExtOp;
    input [25:0] ex_imm;
    output  [31:0] ex_out;
    assign ex_out=ExtOp?{ {16{ex_imm[15]}} ,ex_imm[15:0]}:{ 16'b0,ex_imm[15:0]};
    //符号扩展
//    always @(ExtOp)
//    begin
//        if(ExtOp)
//            ex_out={ {16{ex_imm[15]}} ,ex_imm[15:0]};
//         else
//            ex_out={ 16'b0,ex_imm[15:0]};
//    end
endmodule

8. ALUSrc_select

module ALUSrc_select(
ALUSrc,busB,imm36,
src_out
    );
    input ALUSrc;
    input [31:0] busB;
    input [31:0] imm36;
    output [31:0] src_out;
    
    assign src_out=ALUSrc?imm36:busB;
endmodule

9. ALU32

module ALU32(
ALU_clk,ALUctr,in0,in1,
carryout,overflow,zero,out
    );
    input ALU_clk;
    input [31:0] in0,in1;
    input [2:0] ALUctr;//控制ALU进行何种操作
    output reg[31:0] out;
    output reg carryout,overflow,zero;
   
always@(posedge ALU_clk)
begin
    case(ALUctr)
        //addu
        3'b000:
            begin
            {carryout,out}=in0+in1;
            zero=(out==0)?1:0;
            overflow=0;
            end
            
        //add
        3'b001:
            begin
            out=in0+in1;
            overflow=((in0[31]==in1[31])&&(~out[31]==in0[31]))?1:0;
            zero=(out==0)?1:0;
            carryout=0;
            end
        //or
        3'b010:
            begin
            out=in0|in1;
            zero=(out==0)?1:0;
            carryout=0;
            overflow=0;
            end
        //subu
        3'b100:
            begin
            {carryout,out}=in0-in1;
            zero=(out==0)?1:0;
            overflow=0;
            end
        //sub
        3'b101:
            begin
            out=in0-in1;
            overflow=((in0[31]==0&&in1[31]==1&&out[31]==1)||(in0[31]==1&&in1[31]==0&&out[31]==0))?1:0;
            zero=(in0==in1)?1:0;
            carryout=0;
            end
        //sltu
        3'b110:
            begin
                out=(in0<in1)?1:0;
                carryout=out;
                zero=(out==0)?1:0;
                overflow=0;
            end
        //slt
        3'b111:
            begin                        
            if(in0[31]==1&&in1[31]==0)
                out=1;
            else if(in0[31]==0&&in1[31]==1)
                out=0;
            else 
                out=(in0<in1)?1:0;
           overflow=out; 
           zero=(out==0)?1:0;
           carryout=0;              
           end
        /*
        //and
        11'b00000100100:
            begin
            out=in0&in1;
            zero=(out==0)?1:0;
            carryout=0;
            overflow=0;
            end
       
        //xor
        11'b00000100110:
            begin
            out=in0^in1;
            zero=(out==0)?1:0;
            carryout=0;
            overflow=0;
            end
        //nor
        11'b00000100111:
            begin
            out=~(in0|in1);
            zero=(out==0)?1:0;
            carryout=0;
            overflow=0;
            end
        
        //shl
        11'b00000000100:
            begin
            {carryout,out}=in0<<in1;
            overflow=0;
            zero=(out==0)?1:0;
            end
        //shr
        11'b00000000110:
            begin
            out=in0>>in1;
            carryout=in0[in1-1];
            overflow=0;
            zero=(out==0)?1:0;
            end
        //sar
        11'b00000000111:
            begin
            out=($signed(in0))>>>in1;
            carryout=in0[in1-1];
            overflow=0;
            zero=(out==0)?1:0;
            end
        */
    endcase
end
endmodule

10. DataMem

module DataMem(
MEM_clk,WrEn,Adr,DataIn,
DataOut
    );
    input MEM_clk;
    input WrEn;
    input [31:0] Adr;
    input [31:0] DataIn;
    output reg [31:0] DataOut;
    //32个32位宽寄存器
    reg [31:0] memory[0:31];
    integer i;
    initial
    begin
        for(i=0;i<32;i=i+1)
            memory[i]<=0;
    end
    
    always@ (posedge MEM_clk)
    begin
        if(WrEn==0)
            DataOut=memory[Adr];
        else
            memory[Adr]=DataIn;
    end
    
endmodule

11. Data_select

module Data_select(
MemorReg,ALU_out,DataMem_out,
Data_out
    );
    input MemorReg;
    input [31:0] ALU_out;
    input [31:0] DataMem_out;
    output [31:0] Data_out;
    
    assign Data_out=MemorReg?DataMem_out:ALU_out;
endmodule
  • 27
    点赞
  • 261
    收藏
    觉得还不错? 一键收藏
  • 9
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值