单周期CPU设计【Verilog】

第一章 单周期CPU的设计原理

1.1 单周期CPU概述

1.2 CPU工作原理

第二章 单周期CPU的设计内容

2.1 指令系统的设计

2.1.1 概述

2.1.2 运算类指令的设计

2.1.3 传送类指令的设计

2.1.4 存储类指令的设计

2.1.5 控制类指令的设计

2.2 整体框架的设计

2.3 数据通路的设计

2.4 控制信号的设计

第三章 单周期CPU的具体实现

3.1 底层模块的实现

3.1.1 程序计数器PC

3.1.2 指令存储器InstructionMemory

3.1.3 寄存器组RegisterFile

3.1.4 算术逻辑单元ALU

3.1.5 数据存储器DataMemory

3.1.6 控制单元ControlUnit

3.2 顶层模块的实现

第四章 单周期CPU的仿真验证

4.1 测试程序

4.2 波形仿真


第一章 单周期CPU的设计原理

为实现单周期CPU,本文首先研究了单周期CPU的相关理论和工作原理。本章首先简要介绍单周期CPU的基本概念,然后对CPU的工作原理进行简要分析,以便为单周期CPU的设计和开发提供理论基础。

1.1 单周期CPU概述

中央处理器,即CPU,作为计算机系统的运算和控制核心,是信息处理、程序运行的最终执行单元。在CPU内部,电平从低到高变化的瞬间称为时钟上升沿,两个相邻时钟上升沿之间的时间间隔称为一个时钟周期。单周期CPU指的是一条指令的执行在一个时钟周期内完成,然后开始下一条指令的执行,即一条指令用一个时钟周期完成。

1.2 CPU工作原理

CPU在处理指令时,一般需要经过以下几个步骤:

(1) 取指令(IF):根据程序计数器PC中的指令地址,从存储器中取出一条指令,同时,PC根据指令字长度自动递增产生下一条指令所需要的指令地址,但遇到“地址转移”指令时,则控制器把“转移地址”送入PC,当然得到的“地址”需要做些变换才送入PC。

(2) 指令译码(ID):对取指令操作中得到的指令进行分析并译码,确定这条指令需要完成的操作,从而产生相应的操作控制信号,用于驱动执行状态中的各种操作。

(3) 指令执行(EXE):根据指令译码得到的操作控制信号,具体地执行指令动作,然后转移到结果写回状态。

(4) 存储器访问(MEM):所有需要访问存储器的操作都将在这个步骤中执行,该步骤给出存储器的数据地址,把数据写入到存储器中数据地址所指定的存储单元或者从存储器中得到数据地址单元中的数据。

(5) 结果写回(WB):指令执行的结果或者访问存储器中得到的数据写回相应的目的寄存器中。

CPU的指令处理过程如下:

 

单周期CPU,是在一个时钟周期内完成这五个阶段的处理。

第二章 单周期CPU的设计内容

2.1 指令系统的设计

2.1.1 概述

本文所设计的单周期CPU的指令系统采用类似MIPS的设计风格,包括以下四类指令:

(1) 运算类指令;

(2) 传送类指令;

(3) 存储类指令;

(4) 控制类指令;

其中,所有指令的操作码部分用4位二进制表示,寄存器编号用3位二进制表示。在下述的具体设计表示中,以助记符表示的是汇编指令;以代码表示的则是二进制机器指令。

2.1.2 运算类指令的设计

运算类指令共有8条,具体的指令功能与指令格式如下:

(1) add rd,rs,rt

0000

rs(3位)

rt(3位)

rd(3位)

reserved(未用)

功能:将寄存器rs和rt中的值相加并将结果写回寄存器rd。reserved为预留部分,即未用,一般填“0”。

(2) addi rt,rs,immediate

0001

rs(3位)

rt(3位)

immediate(6位)

功能:将立即数immediate进行符号扩展后再和寄存器rs中的值相加并将结果写回寄存器rt。

(3) sub rd,rs,rt

0010

rs(3位)

rt(3位)

rd(3位)

reserved(未用)

功能:用寄存器rs中的值减去rt中的值并将结果写回寄存器rd。reserved为预留部分,即未用,一般填“0”。

(4) or rd,rs,rt

0011

rs(3位)

rt(3位)

rd(3位)

reserved(未用)

功能:将寄存器rs和rt中的值进行按位或运算并将结果写回寄存器rd。reserved为预留部分,即未用,一般填“0”。

(5) ori rt,rs,immediate

0100

rs(3位)

rt(3位)

immediate(6位)

功能:将立即数immediate进行“0”扩展后再和寄存器rs中的值进行按位或运算并将结果写回寄存器rt。

(6) and rd,rs,rt

0101

rs(3位)

rt(3位)

rd(3位)

reserved(未用)

功能:将寄存器rs和rt中的值进行按位与运算并将结果写回寄存器rd。reserved为预留部分,即未用,一般填“0”。

(7) sll rd,rt,sa

0110

未用(3位)

rt(3位)

rd(3位)

sa(3位)

功能:先将sa表示的立即数进行“0”拓展,然后将寄存器rt中的值左移sa位并将结果写回寄存器rd。

(8) slt rd,rs,rt

0111

rs(3位)

rt(3位)

rd(3位)

reserved(未用)

功能:将寄存器rs和rt中的值作为带符号数进行比较,若rs中的值更小,则将寄存器rd中的值置1,否则置0。

2.1.3 传送类指令的设计

传送类指令共有2条,具体的指令功能与指令格式如下:

(1) mov rd,rt

1000

未用(3位)

rt(3位)

rd(3位)

reserved(未用)

功能:将寄存器rt中的值传送到寄存器rd。reserved为预留部分,即未用,一般填“0”。

(2) movi rt,immediate

1001

未用(3位)

rt(3位)

immediate(6位)

功能:将立即数immediate进行符号扩展后传送到寄存器rt。

2.1.4 存储类指令的设计

存储类指令共有2条,具体的指令功能与指令格式如下:

(1) sw  rt,immediate(rs)

1010

rs(3位)

rt(3位)

immediate(6位)

功能:将寄存器rt中的值存储到内存中,存储单元的地址为寄存器rs中的值加上经符号拓展的立即数immediate。

(2) lw  rt,immediate(rs)

1011

rs(3位)

rt(3位)

immediate(6位)

功能:将内存中的值加载到寄存器rt中,存储单元的地址为寄存器rs中的值加上经符号拓展的立即数immediate。

2.1.5 控制类指令的设计

控制类指令共有4条,具体的指令功能与指令格式如下:

(1) beq  rs,rt,immediate

1100

rs(3位)

rt(3位)

immediate(6位)

功能:比较寄存器rs和rt中的值,若相等则跳转到目标处执行,否则继续执行下一条指令。跳转的目标地址与当前指令的下一条指令的相对位移由立即数immediate给出。

(2) bgtz  rs,immediate

1101

rs(3位)

000

immediate(6位)

功能:判断寄存器rs中的值是否大于0,若大于0则跳转到目标处执行,否则继续执行下一条指令。跳转的目标地址与当前指令的下一条指令的相对位移由立即数immediate给出。

(3) j  addr

1110

addr(12位)

功能:执行无条件跳转,跳转的目的地址组成如下:高3位为PC中值的高3位,第1-12位由addr给出,最低位为0。

(4) halt

1111

000000000000(12位)

功能:停机指令,不改变PC的值,PC保持不变。

2.2 整体框架的设计

本文所设计的单周期CPU的整体框架主要包括七部分:程序计数器、指令寄存器、寄存器组、算术逻辑单元、数据存储器、控制单元和顶层模块。具体框架如下:

单周期CPU设计【Verilog】_第1张图片

2.3 数据通路的设计

本文所设计的单周期CPU的数据通路如下:

单周期CPU设计【Verilog】_第2张图片

其中Ins.MEM为指令存储器,Data.MEM为数据存储器。访问存储器时,先给出内存地址,然后由读或写信号控制操作。对于寄存器组Register File,先给出寄存器编号,读操作时,输出端就直接输出相应数据;而在写操作时,当写使能信号为1时,在时钟边沿触发将数据写入寄存器。

主要模块接口说明如下:

(1) Instruction Memory:指令存储器。

IAddr,指令存储器地址输入端口

IDataOut,指令存储器数据输出端口(指令代码输出端口)

InsMemRW,指令存储器读写控制信号,为0写,为1读

(2) Data Memory:数据存储器。

DAddr,数据存储器地址输入端口

DataIn,数据存储器数据输入端口

DataOut,数据存储器数据输出端口

RD,数据存储器读控制信号,为0读

WR,数据存储器写控制信号,为0写

(3) Register File:寄存器组。

Read Reg1,rs寄存器地址输入端口

Read Reg2,rt寄存器地址输入端口

Write Reg,将数据写入的寄存器端口,其地址来源为rt或rd字段

Write Data,写入寄存器的数据输入端口

Read Data1,rs寄存器数据输出端口

Read Data2,rt寄存器数据输出端口

WE,写使能信号,为1时,在时钟边沿触发写入

(4) ALU:算术逻辑单元。

A,操作数A输入端口

B,操作数B输入端口

result,ALU运算结果

zero,运算结果标志,结果为0,则zero=1;否则zero=0

sign,运算结果标志,结果最高位为0,则sign=0,正数;否则,sign=1,负数

2.4 控制信号的设计

本文所设计的单周期CPU的各控制信号如下:

单周期CPU设计【Verilog】_第3张图片

 各控制信号的功能如下:

控制信号名

状态“0”

状态“1”

Reset

初始化PC为0

PC接收新地址

PCWre

PC不更改,相关指令:halt

PC更改,相关指令:除指令halt外

ALUSrcA

来自寄存器堆data1输出,相关指令:add、addi、sub、or、ori、and、slt、mov、movi、beq、bgtz、sw、lw

来自经过“0”拓展的移位数sa,即 {{13{0}},sa},相关指令:sll

ALUSrcB

来自寄存器堆data2输出,相关指令:add、sub、or、and、sll、slt、mov、beq、bgtz

来自sign或zero扩展的立即数,相关指令:addi、ori、movi、sw、lw

DBDataSrc

来自ALU运算结果的输出,相关指令:add、addi、sub、or、ori、and、sll、slt、mov、movi

来自数据存储器(Data MEM)的输出,相关指令:lw

RegWre

寄存器组写不使能,相关指令:sw、beq、bgtz、j、halt

寄存器组写使能,相关指令:add、addi、sub、or、ori、and、sll、slt、mov、movi、lw

InsMemRW

写指令存储器

读指令存储器

RD

读数据存储器,相关指令:lw

无操作

WR

写数据存储器,相关指令:sw

无操作

RegDst

写寄存器组寄存器的地址,来自rt字段,相关指令:addi、ori、movi、lw

写寄存器组寄存器的地址,来自rd字段,相关指令:add、sub、or、and、sll、slt、mov

ExtSel

(zero-extend)immediate0扩展),相关指令:ori

(sign-extend)immediate符号扩展,相关指令:addi、movi、sw、lw、beq、bgtz

PCSrc[1..0]

00:pc<-pc+2,相关指令:add、addi、sub、or、ori、and、sll、slt、sw、lw、beq(zero=0)、bgtz(sign=1,或zero=1);

01:pc<-pc+2+(sign-extend)immediate,相关指令:beq(zero=1)、bgtz(sign=0,zero=0);

10:pc<-{(pc+2)[15..13],addr[12..1],0},相关指令:j;

11:未用

ALUOp[2..0]

ALU 8种运算功能选择(000-111),具体见ALU功能表

ALU运算功能表如下:

ALUOp[2..0]

功能

描述

000

Y = A+B

001

Y = A-B

010

Y = B<

B左移A位

011

Y = A∨B

100

Y = A∧B

101

Y=(A

比较A与B

不带符号

110

if (A

    Y = 1;

else if ( A[15] && !B[15)  Y = 1;

else Y = 0; 

比较A与B

带符号

111

Y = B

直送

在具体进行控制时,PC的改变是在时钟上升沿进行的,指令执行的结果总是在时钟下降沿保存到寄存器和存储器中,这样稳定性较好。

第三章 单周期CPU的具体实现

3.1 底层模块的实现

单周期CPU每个时钟周期可被划分为五个阶段,对应的有五个最关键的底层模块:IF阶段对应PC,ID阶段对应InstructionMemory和RegisterFile,EXE阶段对应ALU,MEM阶段对应DataMemory,WB阶段也对应RegisterFile。除此之外,还需要生成控制信号的控制单元(ControlUnit)等。下面具体介绍上述各主要模块的设计与实现。

3.1.1 程序计数器PC

PC为时序逻辑,在时钟上升沿到来时,若PCWre为1,则输出下一条待处理的指令地址,否则不输出新的指令地址。若Reset为0,则设置输出的指令地址为0。具体代码如下:

module PC(    
    input clk,    
    input [15:0] PCin,    
    input PCWre,    
    input Reset,    
    output reg [15:0] PCout    
);    
      
    initial begin    
        PCout <= 0;   
    end  
        
    always@(posedge clk) begin    
        if(Reset == 0) begin    
            PCout <= 0;    
        end    
        else if(PCWre == 0) begin    
            PCout <= PCout;    
        end    
        else begin    
            PCout <= PCin;    
        end    
    end  
        
endmodule    

3.1.2 指令存储器InstructionMemory

InstructionMemory为组合逻辑,内含128个字节的mem。mem中存放要执行的测试程序段的机器码,使用initial语句中的$readmemb伪指令从Instructions.txt文件中读取出来。当输入一个16位长的指令地址,输出对应地址中的16位机器指令。具体代码如下:

module InsMemory(    
    input InsMemRW,    
    input [15:0] address,    
    output reg [15:0] DataOut    
);    

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

    initial begin    
        DataOut = 16'b1111000000000000;  
        $readmemb("Instructions.txt", mem);      
    end   
      
    always@(*) begin   
        DataOut[15:8] <= mem[address];    
        DataOut[7:0] <= mem[address+1];  
    end   
       
endmodule    

3.1.3 寄存器组RegisterFile

RegisterFile中定义了一个含有8个寄存器的寄存器组,设计逻辑包括两部分:一方面,读寄存器组为组合逻辑,当输入一个3位长的寄存器编号时,输出对应寄存器中的数值。另一方面,写寄存器组是时序逻辑,在时钟下降沿到来时触发写入。具体代码如下:

module RegFile(    
    input CLK,    
    input RST,    
    input RegWre,    
    input [2:0] ReadReg1,    
    input [2:0] ReadReg2,    
    input [2:0] WriteReg,    
    input [15:0] WriteData,    
    output [15:0] ReadData1,    
    output [15:0] ReadData2    
);    
  
    reg [15:0] regFile[0:7];  
       
    integer i;    
      
    assign ReadData1 = regFile[ReadReg1];   
    assign ReadData2 = regFile[ReadReg2];  
        
    always @ (negedge CLK) begin    
        if (RST == 0) begin    
            for(i=1;i<8;i=i+1)    
                regFile[i] <= 0;    
        end    
        else if(RegWre == 1 && WriteReg != 0) begin    
            regFile[WriteReg] <= WriteData;    
        end    
    end    
            
endmodule    

3.1.4 算术逻辑单元ALU

ALU为组合逻辑,根据控制信号对两个操作数进行相应的运算,并输出结果。具体代码如下:

module ALU(    
    input [2:0] ALUopcode,    
    input [15:0] rega,    
    input [15:0] regb,    
    output reg [15:0] result,    
    output zero,    
    output sign    
);    
  
    assign zero = (result==0)?1:0;    
    assign sign = result[15];    
      
    always @( ALUopcode or rega or regb ) begin    
        case (ALUopcode)    
            3'b000 : result = rega + regb;    
            3'b001 : result = rega - regb;    
            3'b010 : result = regb << rega;    
            3'b011 : result = rega | regb;    
            3'b100 : result = rega & regb;    
            3'b101 : result = (rega < regb)?1:0;     
            3'b110 : begin    
                if (rega

3.1.5 数据存储器DataMemory

DataMemory中包含128个字节的ram,设计逻辑包括两部分:一方面,读存储器为组合逻辑,当输入一个16位长的数据地址时,输出对应地址中的16位数据。另一方面,写存储器是时序逻辑,在时钟下降沿到来时触发写入。具体代码如下:

module DataMemory(    
    input clk,    
    input [15:0] address,    
    input RD,    
    input WR,    
    input [15:0] DataIn,    
    output [15:0] DataOut    
);    
    
    reg [7:0] ram[0:127];  
        
    integer i;    
      
    initial begin;    
        for(i=0;i<128;i=i+1)    
            ram[i]<=0;    
    end    
       
    assign DataOut[7:0] = (RD == 0)? ram[address+1]:8'bz;    
    assign DataOut[15:8] = (RD == 0)? ram[address]:8'bz;    
   
    always@(negedge clk) begin    
        if(WR == 0) begin    
            if(address>=0 && address<128) begin    
                ram[address] <= DataIn[15:8];    
                ram[address+1] <= DataIn[7:0];     
            end    
        end    
    end  
        
endmodule    

3.1.6 控制单元ControlUnit

ControlUnit为组合逻辑,将机器码中的操作码(opcode)转换为各个控制信号,从而控制不同的指令在不同的数据通路中传输。具体代码如下:

module ControlUnit(    
    input [3:0] opcode,    
    input zero,    
    input sign,    
    output reg PCWre,    
    output reg ALUSrcA,    
    output reg ALUSrcB,    
    output reg DBDataSrc,    
    output reg RegWre,    
    output reg InsMemRW,    
    output reg RD,    
    output reg WR,    
    output reg RegDst,    
    output reg ExtSel,    
    output reg [1:0] PCSrc,    
    output reg [2:0] ALUOp    
);    
  
    initial begin    
        RD = 1;    
        WR = 1;    
        RegWre = 0;   
        PCWre = 0;   
        InsMemRW = 1;    
    end   
       
    always@ (opcode) begin    
        case(opcode)     
            4'b0000:begin // add    
                PCWre = 1;    
                ALUSrcA = 0;    
                ALUSrcB = 0;    
                DBDataSrc = 0;    
                RegWre = 1;    
                InsMemRW = 1;    
                RD = 1;    
                WR = 1;    
                RegDst = 1;    
                ALUOp = 3'b000;    
            end    
            4'b0001:begin //addi    
                PCWre = 1;    
                ALUSrcA = 0;    
                ALUSrcB = 1;    
                DBDataSrc = 0;    
                RegWre = 1;    
                InsMemRW = 1;    
                RD = 1;    
                WR = 1;    
                RegDst = 0;    
                ExtSel = 1;    
                ALUOp = 3'b000;    
            end    
            4'b0010:begin //sub    
                PCWre = 1;    
                ALUSrcA = 0;    
                ALUSrcB = 0;    
                DBDataSrc = 0;    
                RegWre = 1;    
                InsMemRW = 1;    
                RD = 1;    
                WR = 1;    
                RegDst = 1;    
                ALUOp = 3'b001;    
            end  
            4'b0011:begin // or    
                PCWre = 1;    
                ALUSrcA = 0;    
                ALUSrcB = 0;    
                DBDataSrc = 0;    
                RegWre = 1;    
                InsMemRW = 1;    
                RD = 1;    
                WR = 1;    
                RegDst = 1;    
                ALUOp = 3'b011;    
            end     
            4'b0100:begin // ori    
                PCWre = 1;    
                ALUSrcA = 0;    
                ALUSrcB = 1;    
                DBDataSrc = 0;    
                RegWre = 1;    
                InsMemRW = 1;    
                RD = 1;    
                WR = 1;    
                RegDst = 0;    
                ExtSel = 0;    
                ALUOp = 3'b011;    
            end    
            4'b0101:begin //and    
                PCWre = 1;    
                ALUSrcA = 0;    
                ALUSrcB = 0;    
                DBDataSrc = 0;    
                RegWre = 1;    
                InsMemRW = 1;    
                RD = 1;    
                WR = 1;    
                RegDst = 1;    
                ALUOp = 3'b100;    
            end    
            4'b0110:begin //sll    
                PCWre = 1;    
                ALUSrcA = 1;    
                ALUSrcB = 0;    
                DBDataSrc = 0;    
                RegWre = 1;    
                InsMemRW = 1;    
                RD = 1;    
                WR = 1;    
                RegDst = 1;    
                ALUOp = 3'b010;    
            end    
            4'b0111:begin //slt    
                PCWre = 1;    
                ALUSrcA = 0;    
                ALUSrcB = 0;    
                DBDataSrc = 0;    
                RegWre = 1;    
                InsMemRW = 1;    
                RD = 1;    
                WR = 1;    
                RegDst = 1;    
                ALUOp = 3'b110;    
            end  
            4'b1000:begin //mov    
                PCWre = 1;    
                ALUSrcA = 0;    
                ALUSrcB = 0;    
                DBDataSrc = 0;    
                RegWre = 1;    
                InsMemRW = 1;    
                RD = 1;    
                WR = 1;    
                RegDst = 1;    
                ExtSel = 1;    
                ALUOp = 3'b111;    
            end  
            4'b1001:begin //movi    
                PCWre = 1;    
                ALUSrcA = 0;    
                ALUSrcB = 1;    
                DBDataSrc = 0;    
                RegWre = 1;    
                InsMemRW = 1;    
                RD = 1;    
                WR = 1;    
                RegDst = 0;    
                ExtSel = 1;    
                ALUOp = 3'b111;    
            end      
            4'b1010:begin //sw    
                PCWre = 1;    
                ALUSrcA = 0;    
                ALUSrcB = 1;    
                RegWre = 0;    
                InsMemRW = 1;    
                RD = 1;    
                WR = 0;    
                ExtSel =1;    
                ALUOp = 3'b000;    
            end    
            4'b1011:begin //lw    
                PCWre = 1;    
                ALUSrcA = 0;    
                ALUSrcB = 1;    
                DBDataSrc = 1;    
                RegWre = 1;    
                InsMemRW = 1;    
                RD = 0;    
                WR = 1;    
                RegDst = 0;    
                ExtSel = 1;    
                ALUOp = 3'b000;    
            end   
            4'b1100:begin //beq    
                PCWre = 1;    
                ALUSrcA = 0;    
                ALUSrcB = 0;    
                RegWre = 0;    
                InsMemRW = 1;    
                RD = 1;    
                WR = 1;    
                ExtSel = 1;    
                ALUOp = 3'b001;    
            end    
            4'b1101:begin  //bgtz  
                PCWre = 1;    
                ALUSrcA = 0;    
                ALUSrcB = 0;    
                RegWre = 0;    
                InsMemRW = 1;    
                RD = 1;    
                WR = 1;    
                ExtSel = 1;    
                ALUOp = 3'b001;    
            end    
            4'b1110:begin //j    
                PCWre = 1;    
                RegWre = 0;    
                InsMemRW = 1;    
                RD = 1;    
                WR = 1;    
                ALUOp = 3'b010;    
            end    
            4'b1111:begin //halt    
                PCWre = 0;    
                RegWre = 0;    
                InsMemRW = 1;    
                RD = 1;    
                WR = 1;    
            end    
            default:begin    
                RD = 1;    
                WR = 1;    
                RegWre = 0;    
                InsMemRW = 0;    
            end    
        endcase    
    end   
       
    always@(opcode or zero or sign) begin    
        if(opcode == 4'b1110) // j    
            PCSrc = 2'b10;    
        else if(opcode == 4'b1100) begin  
            if(zero == 1)  
                PCSrc = 2'b01;  
            else  
                PCSrc = 2'b00;  
        end  
        else if(opcode == 4'b1101) begin  
            if(zero == 0 && sign == 0)    
                PCSrc = 2'b01;    
            else    
                PCSrc = 2'b00;  
        end    
        else begin    
            PCSrc = 2'b00;    
        end    
    end   
       
endmodule    

3.2 顶层模块的实现

在顶层模块中,通过实例化各个底层模块,并使用导线将它们按照数据通路图连接起来,构成单周期CPU的完整结构,具体原理图如下:

单周期CPU设计【Verilog】_第4张图片

第四章 单周期CPU的仿真验证

根据上述实现的单周期CPU,利用指令系统中所有的指令设计一个测试程序,对该CPU进行如下仿真验证。

4.1 测试程序

使用该指令系统中所有指令,设计出如下一段具有实际意义的测试程序。该程序计算数字1到5的和以及按位或的和,并将两者中较大者存储到内存中地址为14的存储单元中,最后读出该存储单元中的值。具体指令序列如下:

地址

汇编程序

机器指令代码(二进制)

0x0000

movi     $0,0

10010000 00000000

0x0002

mov      $1,$0

10000000 00001000

0x0004

and      $3,$1,$0

01010010 00011000

0x0006

addi      $2,$0,6

00010000 10000110

0x0008

ori      $3,$0,1

01000000 11000001

0x000A

add      $5,$0,$3

00000000 11101000

0x000C

or       $6,$1,$3

00110010 11110000

0x000E

mov      $0,$5

10000001 01000000

0x0010

mov      $1,$6

10000001 10001000

0x0012

addi      $4,$3,1

00010111 00000001

0x0014

mov      $3,$4

10000001 00011000

0x0016

beq      $3,$2,1

11000110 10000001

0x0018

j         5

11100000 00000101

0x001A

slt      $5,$0,$1

01110000 01101000

0x001C

movi     $4,4

10010001 00000100

0x001E

sub     $6,$2,$4

00100101 00110000

0x0020

sll       $7,$6,1

01100001 10111001

0x0022

bgtz      $5,2

11011010 00000010

0x0024

sw      $0,10($7)

10101110 00001010

0x0026

j         21

11100000 00010101

0x0028

sw      $1,10($7)

10101110 01001010

0x002A

lw       $6,10($7)

10111111 10001010

0x002C

halt

11110000 00000000

4.2 波形仿真

在仿真过程中,设置如下输入和输出,并显示如下寄存器中的内容:

输入

clk

CPU时钟信号,周期为10ns

reset

CPU复位信号,0为复位

输出

nowIns

当前指令

nextPC

下一条指令地址

nowPC

当前PC地址

ALUSrcA

ALU操作数A

ALUSrcB

ALU操作数

ALUResult

ALU运算结果

finalData

写回的结果

寄存器

RegFile[0]-RegFile[7]

寄存器组

DataMemory[10]-DataMemory[15]

数据存储器

仿真结果如下:

(1) movi $0,0至ori $3,$0,1

单周期CPU设计【Verilog】_第5张图片

(2) add $5,$0,$3至j 5 (第一轮循环)

单周期CPU设计【Verilog】_第6张图片

(3) add $5,$0,$3至j 5 (第二轮循环)

单周期CPU设计【Verilog】_第7张图片

(4) add $5,$0,$3至j 5 (第三轮循环)

单周期CPU设计【Verilog】_第8张图片

(5) add $5,$0,$3至j 5 (第四轮循环)

单周期CPU设计【Verilog】_第9张图片

(6) add $5,$0,$3至beq $3,$2,1 (第五轮循环)

单周期CPU设计【Verilog】_第10张图片

(7) slt $5,$0,$1至sll $7,$6,1

单周期CPU设计【Verilog】_第11张图片

(8) bgtz $5,2至halt

单周期CPU设计【Verilog】_第12张图片

 

你可能感兴趣的:(课程设计,CPU,单周期,Verilog)