多周期CPU实验

一、实验内容和要求

  设计一个多周期CPU,该CPU至少能实现以下指令功能操作。需设计的指令与格式如下:


==>算术运算指令
(1)add rd, rs, rt

000000rs(5位)rt(5位)rd(5位)reserved

  功能:rd<-rs + rt
(2)sub rd, rs, rt

000001rs(5位)rt(5位)rd(5位)reserved

  功能:rd<-rs - rt
(3)addi rt, rs, immediate

000010rs(5位)rt(5位)immediate(16位)

  功能:rt<-rs + (sign-extend)immediate

==>算术运算指令
(4)or rd, rs, rt

010000rs(5位)rt(5位)rd(5位)reserved

  功能:rd<-rs | rt
(5)and rd, rs, rt

010001rs(5位)rt(5位)rd(5位)reserved

  功能:rd<-rs & rt
(6)ori rt, rs, immediate

010010rs(5位)rt(5位)immediate(16位)

  功能:rt<-rs | (zero-extend)immediate

==>移位指令
(7)sll rd, rs,sa

011000rs(5位)未用rd(5位)sareserved

  功能:rd<-rs<<(zero-extend)sa,左移sa位 ,(zero-extend)sa

==>传送指令
(8)move rd, rs

100000rs(5位)00000rd(5位)reserved

  功能:rd<-rs + $0

==>比较指令
(9) slt rd, rs, rt

100111rs(5位)rt(5位)rd(5位)reserved

  功能:如果(rs < rt),则rd=1; 否则 rd=0

==>存储器读写指令
(10)sw rt, immediate(rs)

110000rs(5位)rt(5位)immediate(16位)

  功能:memory[rs+ (sign-extend)immediate]<-rt
(11)lw rt, immediate(rs)

110001rs(5位)rt(5位)immediate(16位)

  功能:rt <- memory[rs + (sign-extend)immediate]

==>分支指令
(12)beq rs,rt, immediate (说明:immediate是从pc+4开始和转移到的指令之间间隔条数)

110100rs(5位)rt(5位)immediate(16位)

  功能:if(rs=rt) pc <-pc + 4 + (sign-extend)immediate <<2

==>跳转指令
(13)j addr

111000addr[27..2]

  功能:pc <{pc[31..28],addr[27..2],0,0},转移
(14)jr rs

111001rs(5位)未用未用reserved

  功能:pc <- rs,转移

==>调用子程序指令
(15)jal addr

111010addr[27..2]

功能:调用子程序,pc <- {pc[31..28],addr[27..2],0,0}; 31<pc+4jr 31。

==>停机指令
(16)halt (停机指令)

11111100000000000000000000000000(26位)

  功能:pc <{pc[31..28],addr[27..2],0,0},转移


二、实验原理

  多周期CPU指的是将整个CPU的执行过程分成几个阶段,每个阶段用一个时钟去完成,然后开始下一条指令的执行,而每种指令执行时所用的时钟数不尽相同,这就是所谓的多周期CPU。CPU在处理指令时,一般需要经过以下几个阶段:
(1) 取指令(IF):根据程序计数器pc中的指令地址,从存储器中取出一条指令,同时,pc根据指令字长度自动递增产生下一条指令所需要的指令地址,但遇到“地址转移”指令时,则控制器把“转移地址”送入pc,当然得到的“地址”需要做些变换才送入pc。
(2) 指令译码(ID):对取指令操作中得到的指令进行分析并译码,确定这条指令需要完成的操作,从而产生相应的操作控制信号,用于驱动执行状态中的各种操作。
(3) 指令执行(EXE):根据指令译码得到的操作控制信号,具体地执行指令动作,然后转移到结果写回状态。
(4) 存储器访问(MEM):所有需要访问存储器的操作都将在这个步骤中执行,该步骤给出存储器的数据地址,把数据写入到存储器中数据地址所指定的存储单元或者从存储器中得到数据地址单元中的数据。
(5) 结果写回(WB):指令执行的结果或者访问存储器中得到的数据写回相应的目的寄存器中。
  实验中就按照这五个阶段进行设计,这样一条指令的执行最长需要五个(小)时钟周期才能完成,但具体情况怎样?要根据该条指令的情况而定,有些指令不需要五个时钟周期的,这就是多周期的CPU。
  
这里写图片描述

  MIPS32的指令的三种格式:
R类型:

这里写图片描述

I类型:

这里写图片描述

J类型:

这里写图片描述

其中,
op:为操作码;
rs:为第1个源操作数寄存器,寄存器地址(编号)是00000~11111,00~1F;
rt:为第2个源操作数寄存器,或目的操作数寄存器,寄存器地址(同上);
rd:为目的操作数寄存器,寄存器地址(同上);
sa:为位移量(shift amt),移位指令用于指定移多少位;
func:为功能码,在寄存器类型指令中(R类型)用来指定指令的功能;
immediate:为16位立即数,用作无符号的逻辑操作数、有符号的算术操作数、数据加载(Laod)/数据保存(Store)指令的数据地址字节偏移量和分支指令中相对程序计数器(PC)的有符号偏移量;
address:地址。

这里写图片描述

  状态的转移有的是无条件的,例如从IF状态转移到ID 和 EXE状态就是无条件的;有些是有条件的,例如ID 或 EXE状态之后不止一个状态,到底转向哪个状态由该指令功能,即指令操作决定。每个状态代一个时钟周期。

这里写图片描述

  图3是多周期CPU控制部件的电路结构,三个D触发器用于保存当前状态,是时序逻辑电路,RST用于初始化状态“000“,另外两个部分都是组合逻辑电路,一个用于产生下一个阶段的状态,另一个用于产生每个阶段的控制信号。从图上可看出,下个状态取决于指令操作码和当前状态;而每个阶段的控制信号取决于指令操作码、当前状态和反映运算结果的状态zero标志等。

这里写图片描述

  图4是一个简单的基本上能够在单周期上完成所要求设计的指令功能的数据通路和必要的控制线路图。其中指令和数据各存储在不同存储器中,即有指令存储器和数据存储器。访问存储器时,先给出地址,然后由读/写信号控制(1-写,0-读。当然,也可以由时钟信号控制,但必须在图上画出来)。对于寄存器组,读操作时,给出寄存器地址(编号),输出端就直接输出相应数据;而在写操作时,在 WE使能信号为1时,在时钟边沿触发写入。图中控制信号功能如表1所示,表2是ALU运算功能表。


  特别提示,图上增加IR指令寄存器,目的是使指令代码保持稳定,还有pc增加写使能控制信号pcWre,也是确保pc适时修改,原因都是和多周期工作的CPU有关。ADR、BDR、ALUout、ALUM2DR四个寄存器不需要写使能信号,其作用是切分数据通路,将大组合逻辑切分为若干个小组合逻辑,大延时变为多个分段小延时。


这里写图片描述
这里写图片描述
这里写图片描述

相关部件及引脚说明:
Instruction Memory:指令存储器,
  Iaddr,指令地址输入端口
  DataIn,存储器数据输入端口
  DataOut,存储器数据输出端口
  RW,指令存储器读写控制信号,为1写,为0读
Data Memory:数据存储器,
  Daddr,数据地址输入端口
  DataIn,存储器数据输入端口
  DataOut,存储器数据输出端口
  RW,数据存储器读写控制信号,为1写,为0读
Register File:(寄存器组)
  Read Reg1,rs寄存器地址输入端口
  Read Reg2,rt寄存器地址输入端口
  Write Reg,将数据写入的寄存器,其地址输入端口(rt、rd)
  Write Data,写入寄存器的数据输入端口
  Read Data1,rs寄存器数据输出端口
  Read Data2,rt寄存器数据输出端口
  WE,写使能信号,为1时,在时钟上升沿写入
IR: 指令寄存器,用于存放正在执行的指令代码
ALU:
  result,ALU运算结果
  zero,运算结果标志,结果为0输出1,否则输出0

这里写图片描述

三、实现代码

1、各个部分代码实现

  首先,根据各条指令和信号的关系,实现ControlUnit。这次的ControlUnit的设计和上次略有不同。由于一条指令分多个周期实现,各个信号因状态的不同而不同。所以,这次的实现要设计一个状态机:状态转换和信号量变换。根据不同信号的作用,可以列出下列真值表:

这里写图片描述
这里写图片描述
这里写图片描述
  
  依据此表格,设计ControlUnit模块如下。

`timescale 1ns / 1ps
`include "defines.v"

module ControlUnit(
    input wire[5:0] opCode,
    input wire zero,
    input wire clk,
    input wire reset,
    output reg PCWre,
    output reg InsMemRW,
    output reg IRWre,
    output reg WrRegData,
    output reg RegWre,
    output reg ALUSrcB,
    output reg ALUM2Reg,
    output reg DataMemRW,
    output reg[1:0] ExtSel,
    output reg[1:0] RegOut,
    output reg[1:0] PCSrc,
    output reg[2:0] ALUOp,
    output reg[2:0] State
    );

    reg[2:0] Nowstate, Nextstate;

    initial begin
        PCWre = 0;
        InsMemRW = 0;
        IRWre = 0;
        WrRegData = 0;
        RegWre = 0;
        ALUSrcB = 0;
        ALUM2Reg = 0;
        DataMemRW = 0;
        ExtSel = 2'b11;
        RegOut = 2'b11;
        PCSrc = 2'b00;
        ALUOp = 3'b000;
        Nowstate = `IF;
        State = Nowstate;
    end

    always @(posedge clk) begin
        if(reset == 0)begin
                Nowstate = `IF;
        end
        else begin
                Nowstate = Nextstate;
        end

        State = Nowstate;
    end

    always@(Nowstate or opCode) begin
        case(Nowstate)

            `IF: Nextstate <= `ID;

            `ID: begin
                case(opCode)
                    `J: Nextstate = `IF;
                    `Jal: Nextstate = `IF;
                    `Jr: Nextstate = `IF;
                    `Halt: Nextstate = `IF;
                    `Beq: Nextstate = `EXE2;
                    `Sw: Nextstate = `EXE3;
                    `Lw: Nextstate = `EXE3;
                    default: Nextstate = `EXE1;
                endcase
            end

            `EXE1: Nextstate = `WB1;

            `EXE2: Nextstate = `IF;

            `EXE3: Nextstate = `MEM;

            `MEM: begin
                if(opCode == `Lw) Nextstate = `WB2;
                else Nextstate = `IF;
            end

            `WB1: Nextstate = `IF;

            `WB2: Nextstate = `IF;

            default: Nextstate = `IF;

        endcase
    end

    always@(Nowstate) begin
        PCWre = (Nowstate == `IF && opCode != `Halt)? 1 : 0; //PCWre = 1 PC值+4
        InsMemRW = 1; //写指令存储器
        IRWre = (Nowstate == `IF)? 1 : 0; //IRWre = 1 写指令寄存器

        RegWre = (Nowstate == `WB1 || Nowstate == `WB2 || (Nowstate == `ID && opCode == `Jal))? 1 : 0; // = 1 写寄存器(数据)
        WrRegData = (Nowstate == `WB1 || Nowstate == `WB2)? 1 : 0;  //=0 记录(PC+4)的值;否则记录计算所得的Result
        ALUSrcB = (opCode == `Addi || opCode == `Ori || opCode == `Sll ||
                    opCode == `Sw || opCode == `Lw)? 1 : 0; //第二个源操作数的来源:寄存器 0r 扩展的立即数
        DataMemRW = (Nowstate == `MEM && opCode == `Sw)? 1 : 0;
        ALUM2Reg = (Nowstate == `WB2)? 1 : 0; //=1 输出来寄存器Reg,即ALU的计算结果; =0 输出来自dataMemory

        case(opCode)
            `Ori: ExtSel = 2'b01;
            `Sll: ExtSel = 2'b00;
            default: ExtSel = 2'b10;
        endcase

        case(opCode)
            `Jal: RegOut = 2'b00;
            `Addi: RegOut = 2'b01;
            `Ori: RegOut = 2'b01;
            `Lw: RegOut = 2'b01;
            default: RegOut = 2'b10;
        endcase

        case(opCode)
            `J: PCSrc = 2'b11;
            `Jal: PCSrc = 2'b11;
            `Jr: PCSrc = 2'b10;
            `Beq: begin
                if(zero) PCSrc = 2'b01;
                else PCSrc = 2'b00;
            end
            default: PCSrc = 2'b00;
        endcase

        ALUOp[2] = (opCode == `Sll || opCode == `Or ||
                    opCode == `And || opCode == `Ori)? 1 : 0;
        ALUOp[1] = (opCode == `Srl || opCode == `Slt ||
                    opCode == `And)? 1 : 0;//有些指令没有 所以ALU单元并不完整
        ALUOp[0] = (opCode == `Sub || opCode == `Srl || opCode == `Beq ||
                    opCode == `Ori || opCode == `Or)? 1 : 0; //有些指令没有 所以ALU单元并不完整

        if(Nowstate == `IF) begin
            RegWre = 0;
            DataMemRW = 0;
        end
    end

endmodule

PC模块:

`timescale 1ns  /   1ps
//
// Module Name:    PC 
// Function:    store the next instruction address.
//
module PC(
    input wire clk, //时钟信号
    input wire Rst, //重置信号
    input wire PCWre, //PC是否更改
    input wire[1:0] PCSrc, //PC指令更新方式
    input wire[31:0] immediate,  //32位立即数
    input wire[31:0] addr,  //直接跳转至某地址 相关指令:j,jal
    input wire[31:0] Regaddr,   //存放在寄存器中的地址 相关指令:jr
    output reg[31:0] address    //下一条指令地址
    );

    always @(PCWre or negedge Rst)begin
            if(Rst == 0) begin
                address = 0;    //初始化
            end
            else if(PCWre) begin
                if(PCSrc == 2'b00)//正常跳转
                    address = address + 4;
                else if(PCSrc == 2'b01)//beq跳转
                    address = address + 4 + immediate*4;
                else if(PCSrc == 2'b10)//jr指令
                    address = Regaddr;
                else if(PCSrc == 2'b11)//j jal指令
                    address = addr;
            end
            else begin
                address <= address; //Halt指令执行以后,PC不变
            end
        end

endmodule

PCAddr模块(扩展地址,相关指令j, jr):

`timescale 1ns / 1ps
//////////////////////////////////////////////////////
//j 和 jal 指令会使用
module PCAddr(
    input wire[25:0] in_addr,
    input wire[31:0] PC0,
    output reg[31:0] PC1
    );
    wire[27:0] mid;
    assign mid = in_addr << 2;
    always @(in_addr) begin
        PC1 <= {PC0[31:28], mid[27:0]};//高4位保留,其余位替换
    end
endmodule

instructionMemory模块(指令存储器):

`timescale 1ns / 1ps
////////////////////////////////////////////////////////////////////////////
module instructionMemory(
    input wire[31:0] addr,
    input wire InsMemRW,
    input wire IRWre,
    input wire clk,
    output reg[31:0] ins
    );

    reg[31:0] ins_out;
    reg[7:0] mem[0:127];

    initial begin
     $readmemb("./instruction/my_store.txt",mem);//系统函数 遇到空格和换行符,自动分割
    end

    always @(addr or InsMemRW) begin
        if(InsMemRW) begin//每条PC相差4,一个word位宽,所以采用此方法存储
            ins_out[31:24] = mem[addr];
            ins_out[23:16] = mem[addr+1];
            ins_out[15:8] = mem[addr+2];
            ins_out[7:0] = mem[addr+3];
        end
    end

    always @(negedge clk) begin
        if(IRWre) ins <= ins_out;
    end

endmodule

IR模块(指令解析器,在ID阶段执行):

`timescale 1ns / 1ps

module IR(
    input wire clk,
    input wire IRWre,
    input wire[31:0] ins,
    output reg[5:0] opcode,
    output reg[4:0] rs,
    output reg[4:0] rt,
    output reg[4:0] rd,
    output reg[4:0] sa,
    output reg[25:0] addr,
    output reg[15:0] immediate
    );

    always @(posedge clk) begin
        if(IRWre == 1) begin
            opcode = ins[31:26];
            rs = ins[25:21];
            rt = ins[20:16];
            rd = ins[15:11];
            sa = ins[10:6];
            addr = ins[25:0];
            immediate = ins[15:0];
        end
    end

endmodule

RegFile模块:

`timescale 1ns / 1ps
//
// Module Name:    regFile 
//  Function:   create 32 registers and initial them, 
//                  then use to store and read some data.
//
module RegFile(
    input wire clk,
    input wire RegWre,
    input wire WrRegData,
    input wire[1:0] RegOut,
    input wire[4:0] rs,
    input wire[4:0] rt,
    input wire[4:0] rd,
    input wire[31:0] pc,
    input wire[31:0] data,
    output reg[31:0] Data1,
    output reg[31:0] Data2
    );

    reg[4:0] writeReg;
    reg[31:0] writeData;

    reg[31:0] register[0:31];
    integer i;
    initial begin   //寄存器初始化
        for(i = 0; i < 32; i = i + 1)
            register[i] = 0;
    end

    //写入数据

    always @(negedge clk) begin
        #1;
        case(RegOut)
            2'b00: writeReg = 5'b11111;
            2'b01: writeReg = rt;
            2'b10: writeReg = rd;
            default: writeReg = 5'b00000;
        endcase
        assign writeData = (WrRegData == 1)? data : pc;
        //读取数据
        assign Data1 = register[rs];    //读取寄存器中的值,源操作数1
        assign Data2 = register[rt];    //读取寄存器中的值,源操作数2
        if(RegWre == 1 && writeReg != 0) register[writeReg] = writeData;
    end

endmodule

无符号和有符号扩展模块(和第一次相比,学会了使用拼接符):

`timescale 1ns / 1ps
//
module signZeroExtend(
    input wire[15:0] indata,
    input wire[1:0] ExtSel,
    output reg[31:0] out
    );

    //使用拼接运算符,表达式更加简洁
    always @(indata or ExtSel) begin
        case(ExtSel)
            2'b00: out <= {{27{1'b0}}, indata[10:6]};// sll指令,扩充sa
            2'b01: out <= {{16{1'b0}}, indata[15:0]};//立即数扩展,零扩展 如ori
            2'b10: out <= {{16{indata[15]}}, indata[15:0]};//立即数扩展,符号位扩展 beq、addi、lw、sw
            default: out <= {{16{indata[15]}}, indata[15:0]}; //其他情况,默认符号位扩展
      endcase
    end

endmodule

ALU模块:

`timescale 1ns / 1ps
`include "defines.v"


`include "defines.v"
`timescale 1ns  /   1ps
//////////////////////////////////////////////////////////////////////////////////
// Module Name:    ALU 
// Function:    implement the logical operation
//////////////////////////////////////////////////////////////////////////////////
module ALU(
    input wire[31:0] ReadData1,     //源操作数1
    input wire[31:0] ReadData2, //源操作数2
    input wire[31:0] ExtData,       //扩展立即数
    input wire ALUSrcB,             //若为1,则为立即数
    input wire[2:0] ALUOp,          //操作符
    output reg zero,                //结果标志
    output reg[31:0] result         //结果
    );


    wire[31:0] inReadData2;
    assign inReadData2 = ALUSrcB? ExtData : ReadData2;

    always@(ReadData1 or ReadData2 or ALUOp or ExtData or inReadData2)
        begin
            case(ALUOp)

                `AaddB: begin
                    result = ReadData1 + inReadData2;
                    zero = (result == 0)? 1 : 0;
                end

                `AsubB: begin
                    result = ReadData1 - inReadData2;
                    zero = (result == 0)? 1 : 0;
                end

                `AcompareB: begin
                    result = (ReadData1 < inReadData2) ? 1 : 0;
                    zero = (result == 0)? 1 : 0;
                end

                `Arshift: begin
                    result = ReadData1 >> inReadData2;
                    zero = (result == 0)? 1 : 0;
                end

                `Alshift: begin
                    result = ReadData1 << inReadData2;
                    zero = (result == 0)? 1 : 0;
                end

                `AorB: begin
                    result = ReadData1 | inReadData2;
                    zero = (result == 0)? 1 : 0;
                end

                `AandB: begin
                    result = ReadData1 & inReadData2;
                    zero = (result == 0)? 1 : 0;
                end

                `AxorB: begin
                    result = ReadData1 ^ inReadData2;
                    zero = (result == 0)? 1 : 0;
                end

            endcase
        end
endmodule

DataMemory模块:

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Module Name:    DataMemory 
// Function:    store and read the data about result
//////////////////////////////////////////////////////////////////////////////////
module DataMemory(
     input wire[31:0] DAddr,    //数据地址
     input wire[31:0] DataIn,   //输入数据
     input wire DataMemRW,      //=1,写数据; =0,读数据
     output reg[31:0] DataOut   //输出数据
    );
    reg[7:0] memory[0:63];

    //初始化
    integer i;
    initial begin
        for(i = 0; i < 64; i = i + 1) memory[i] = 0;
    end

    always @(DAddr or DataIn or DataMemRW)begin
        if(DataMemRW)begin//写入数据 大端模式
            memory[DAddr] = DataIn[31:24];
            memory[DAddr+1] = DataIn[23:16];
            memory[DAddr+2] = DataIn[15:8];
            memory[DAddr+3] = DataIn[7:0];
        end
        else begin //读取数据
            DataOut[31:24] = memory[DAddr];
            DataOut[23:16] = memory[DAddr+1];
            DataOut[15:8] = memory[DAddr+2];
            DataOut[7:0] = memory[DAddr+3];
        end
    end

endmodule

二选一数据选择模块(除此之外,也可以分别实现其他几个数据选择模块,但是不如直接在模块内使用代码实现简单,所以选择只实现其中一个):

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////
module DataSelect2_1(
    input wire[31:0] data1,
    input wire[31:0] data2,
    input wire sign,
    output wire[31:0] result
    );

    assign result = (sign == 1)? data2 : data1;

endmodule

DataDelay模块(实现数据延迟传递):

`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////
module Datadelay(
    input wire[31:0] in,
    input wire clk,
    output reg[31:0] out
    );

    always @(negedge clk) begin
        out = in;
    end

endmodule

最后,实现顶层模块:

`timescale 1ns / 1ps
`include "ALU.v"
`include "ControlUnit.v"
`include "DataMemory.v"
`include "DataSelect2_1.v"
`include "Datadelay.v"
`include "PC.v"
`include "PCAddr.v"
`include "instructionMemory.v"
`include "signZeroExtend.v"
`include "RegFile.v"
//`include "DataDelay2.v"

module MultiCycleCPU(
    input wire clk,
    input wire Rst
    );

    wire[5:0] opCode;   //操作码
    wire[31:0] Data1;   //来自寄存器的源操作数1
    wire[31:0] Data2;   //来自寄存器的源操作数2
    wire[31:0] Rdata1;//来自ADR的输出
    wire[31:0] Rdata2;//来自BDR的输出
    wire[31:0] curPC;   //目前PC地址
    wire[31:0] j_addr;//接跳转至某地址 相关指令:j,jal
    wire[31:0] Regaddr;//存放在寄存器中的地址 相关指令:jr
    wire[25:0] Insaddr;//指令中存储的指令
    wire[31:0] Regins;//指令寄存器,一个,暂存指令
    wire[31:0] Result;  //ALU运算结果
    wire[31:0] Result1;//ALUout模块的输出

    wire[2:0] ALUOp;    //ALU运算操作码
    wire[31:0] ExtOut;  //扩展后的立即数
    wire[31:0] DMOut;   //读取的寄存器中的树 lw时使用
    wire[31:0] DelayReg1;//延迟前写入寄存器数据
    wire[31:0] DelayReg2;//延迟后写入寄存器数据
    wire[15:0] immediate;   //立即数,扩展前
    wire[4:0] rs, rt, rd, sa;   //三个类型的寄存器
    wire zero, PCWre, ALUSrcB, ALUM2Reg, RegWre, InsMemRW, DataMemRW, IRWre, WrRegData; //controlUnit单元信号   
    wire[1:0] ExtSel;
    wire[1:0] RegOut;
    wire[1:0] PCSrc;
    wire[2:0] State;
    /*
    module PC(
    input wire clk, //时钟信号
    input wire Rst, //重置信号
    input wire PCWre, //PC是否更改
    input wire[1:0] PCSrc, //PC指令更新方式
    input wire[31:0] immediate,  //32位立即数
    input wire[31:0] addr,  //直接跳转至某地址 相关指令:j,jal
    input wire[31:0] Regaddr,   //存放在寄存器中的地址 相关指令:jr
    output reg[31:0] address    //下一条指令地址
    );*/
    PC pc( clk, Rst, PCWre, PCSrc, ExtOut, j_addr, Data1, curPC);

    /*
    module instructionMemory(
    input wire[31:0] addr,
    input wire InsMemRW,
    input wire IRWre,
    input wire clk,
    output reg[31:0] ins
    );*/
    instructionMemory insMem(curPC, InsMemRW, IRWre, clk, Regins);

    /*module IR(
    input wire clk,
    input wire IRWre,
    input wire[31:0] ins,
    output reg[5:0] opcode,
    output reg[4:0] rs,
    output reg[4:0] rt,
    output reg[4:0] rd,
    output reg[4:0] sa,
    output reg[25:0] addr,
    output reg[15:0] immediate
    );*/
     IR ir( clk, IRWre, Regins, opCode, rs, rt, rd, sa, Insaddr, immediate);

    /*
    module PCAddr(
    input wire[25:0] in_addr,
    input wire[31:0] PC0,
    output reg[31:0] PC1
    );*/
    PCAddr pcaddr(Insaddr, curPC, j_addr);


    /*module regFile(
    input wire clk,
    input wire RegWre,
    input wire WrRegData,
    input wire[1:0] RegOut,
    input wire[4:0] rs,
    input wire[4:0] rt,
    input wire[4:0] rd,
    input wire[31:0] dataFromALU,
    input wire[31:0] dataFromDataMem,
    output wire[31:0] Data1,
    output wire[31:0] Data2
    );*/
    RegFile regfile(clk, RegWre, WrRegData, RegOut, rs, rt, rd, (curPC+4), DelayReg2, Data1, Data2);

    /*
    module Datadelay(
    input wire[31:0] in,
    input wire clk,
    output wire[31:0] out
    );*/
    Datadelay ADR(Data1, clk, Rdata1);
    Datadelay BDR(Data2, clk, Rdata2);

    /*
    module signZeroExtend(
    input wire[15:0] indata,
    input wire[1:0] ExtSel,
    output reg[31:0] out
    );*/
    signZeroExtend ext(immediate, ExtSel, ExtOut);

    /*
    module ALU(
    input wire[31:0] ReadData1,     //源操作数1
    input wire[31:0] ReadData2, //源操作数2
    input wire[31:0] ExtData,       //扩展立即数
    input wire ALUSrcB,             //若为1,则为立即数
    input wire[2:0] ALUOp,          //操作符
    output reg zero,                //结果标志
    output reg[31:0] result         //结果
    );*/
    ALU alu(Data1, Data2, ExtOut, ALUSrcB, ALUOp, zero, Result);

    Datadelay ALUout(Result, clk, Result1);

    /*module DataMemory(
     input wire[31:0] DAddr,    //数据地址
     input wire[31:0] DataIn,   //输入数据
     input wire DataMemRW,      //=1,写数据; =0,读数据
     output reg[31:0] DataOut   //输出数据
    );*/
    DataMemory datamemoey(Result1, Data2, DataMemRW, DMOut);

    DataSelect2_1 dataselect(Result, DMOut, ALUM2Reg, DelayReg1);

    Datadelay ALUM2DR(DelayReg1, clk, DelayReg2);

    ControlUnit control(opCode, zero, clk, Rst,PCWre, InsMemRW, IRWre, WrRegData, RegWre, ALUSrcB, ALUM2Reg, DataMemRW, ExtSel, RegOut, PCSrc, ALUOp, State);

endmodule

2、测试代码设计

根据实验提供的提示,设计测试代码如下:
这里写图片描述
这里写图片描述
这里写图片描述

指令以32位形式,存储在my_store.txt中,示例如下:
这里写图片描述

3、测试模块的实现

`timescale 1ns / 1ps
`include "MultiCycleCPU.v"
///////////////////////////////////////////////////////
module Test;
    reg Reset; //初始化地址
    reg clk;
    /*wire[5:0] opCode;
    wire[31:0] Out1;
    wire[31:0] Out2;
    wire[31:0] curPC;
    wire[31:0] Result;
    */
    MultiCycleCPU Multi(
        .clk(clk), 
        .Rst(Reset)/*,
        .opCode(opCode),
        .Out1(Out1),
        .Out2(Out2),
        .curPC(curPC),
        .Result(Result)
        */);

    initial begin
        //Initialize Inputs
        clk = 0;
        Reset = 0;

        #100;
        clk = ~clk;

      forever #100 begin // 产生时钟信号
                Reset = 1;
            clk = ~clk;
        end
    end

endmodule

四、实验结果(部分)

  只列出部分,以作参考。
  
这里写图片描述
这里写图片描述

  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kiloveyousmile

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值