类MIPS单周期微处理器设计(单周期CPU)

类MIPS单周期微处理器设计(单周期CPU)

一、实验目的

  • 熟悉Verilog语言的编写;
  • 掌握单周期CPU的功能实现逻辑并理解过程;
  • 熟练掌握ise和vivado等软件并进行开发并实现逻辑功能。

二、实验任务与要求

基本要求:利用Verilog HDL语言,基于Xilinx FPGA nexys4实验平台,设计一个能够执行以下MIPS指令集的单周期类MIPS处理器,要求完成所有支持指令的功能仿真,验证指令执行的正确性;

  • 支持基本的算术逻辑运算如add,sub,and,or,slt, a n d i \textcolor{red}{andi} andi指令;

  • 支持基本的内存操作如lw,sw指令;

  • 支持基本的程序控制如beq,j指令。

二、实验内容和步骤

1、设计思路

1.1 整体设计

单周期cpu

​ 根据单周期mipsCPU的结构分析知,可以将子模块分为数据存储器dram、指令存储器irom、寄存器文件RegFile、主控制译码MainCtr、ALU控制信号译码ALUCtr以及算术逻辑单元ALU,分别实现各个模块的功能;

​ 再将控制信号等在mips的顶层模块中使用assign语句进行赋值,同时在顶层模块中进行其余子模块的实例化,使之与控制信号以及32位Instr等进行关联,对于不同的指令都有对应于各自的控制信号;

1.2 子模块的设计
  • 指令存储器irom

​ 使用vivado的IPcore实现指令存储器irom的逻辑功能。在时钟上升沿到来时,读入PC信号的高五位,作为地址,输出相应的32位Instr指令,此处我们在vivado中导入text.coe到irom_IP中,其本质为16进制的32位机器码,机器码对照表如下:
指令和机器码对照表
ps:此处的起始地址应该为0x00000000,j指令也应该相应地跳回0x00000000.

  • 数据存储器dram

​ 使用vivado的IPcore实现数据存储器dram的逻辑功能。在时钟下降沿到来时,根据写数据的使能信号MenWr决定是否在输入的地址addr处写入输入的数据DataIn,除此之外还会输出存储在输入的地址addr处的数据到DataOut;

  • 寄存器文件RegFile

​ 使用Verilog语言编写实现寄存器文件RegFile的逻辑功能。在时钟下降沿到来时,倘若写使能信号RegWr为高电平且复位信号reset为低电平,则将输入的数据DataIn写到地址为输入写地址WrAddr处的寄存器regs[WrAddr];倘若复位信号reset为高电平,则我们将regs的值设定为初始默认值regs[i]=i(按照要求也可将其写为学号的ASCII码)。模块中同时使用assign语句决定RsData和RtData的值是0或者地址为RsAddr或RtAddr的寄存器的值。

  • 主控制译码MainCtr

​ 使用Verilog语言编写实现主控制译码MainCtr的逻辑功能。输入Instr的高六位,输出控制信号和ALUOp,根据每个指令调用的模块得到各个控制信号的状态,再将ALUOp输入到ALU控制信号译码ALUCtr中去。

在这里插入图片描述

  • ALU控制信号译码ALUCtr

​ 使用Verilog语言编写实现ALU控制信号译码ALUCtr的逻辑功能。输入ALUOp和Instr的低六位Funct,输出各个指令相应的ALUCtr信号,并且输入到算术逻辑单元ALU中去,其中andi和and的ALUOp和Funct虽然不同,但ALUCtr是一致的。在这里插入图片描述

  • 算术逻辑单元ALU

​ 使用Verilog语言编写算术逻辑单元ALU。输入符号数字In1和符号数In2,由输入的ALUCtr信号觉得要做的运算,事实上我们采用的编码让sw和lw在算术逻辑单元ALU中所做的运算为add,andi所做的为and,beq所做的为sub。并且Zero信号默认为0,只有在执行sub运算时有机会为1,当其为1时,BranchZ = B & Zero才有机会为1,让PC跳转到BranchPC = ImmL2 + SquencePC,即左移两位的立即数与PC加4后的和。

1.3 顶层模块的设计

​ 顶层模块的输入信号仅有时钟信号clk和复位信号reset,声明一系列中间信号,使用assign语句和子模块实例化实现指令功能的完成以及控制信号的传递,数据的读写运算等。除此之外,使用always语句实现PC信号的选择和PC的复位。

2、设计源代码及注释

​ 由于不同的指令需求,对于ALUCtr和MainCtr的编码不同,笔者在此处给出部分源码:

2.1 顶层模块mips
`timescale 1ns / 1ps

module mips (
    input clk, 
    input reset 
);

    wire [31:0] TempPC, JumpPC, MuxPC, SquencePC, BranchPC, Imm32, ImmL2, regWriteData, RsData, RtData, ALUin2, ALUres, memReadData, Instr;
    wire [4:0] regWriteAddr;
    wire [27:0] PsudeoPC;
    wire [1:0] ALUop;
    wire [3:0] ALUctr;
    wire BranchZ, regDst, ALUsrc, M2R, regWriteEn, zero, memWriteEn, B, J;
    reg [31:0] PC;

    assign PsudeoPC = {Instr[25:0], 2'b00};
    assign JumpPC = {SquencePC[31:28], PsudeoPC};
    assign TempPC = J ? JumpPC : MuxPC;
    assign MuxPC = BranchZ ? BranchPC : SquencePC;
    assign BranchPC = ImmL2 + SquencePC;
    assign ImmL2 = {Imm32[29:0], 2'b00};
    assign Imm32 = {Instr[15] ? 16'hffff : 16'h0000, Instr[15:0]};
    assign BranchZ = B & zero;
    assign regWriteAddr = regDst ? Instr[15:11] : Instr[20:16];
    assign ALUin2 = ALUsrc ? Imm32 : RtData;
    assign regWriteData = M2R ? memReadData : ALUres;
    assign SquencePC = PC + 4;
       
    always @(negedge clk) begin
        if(reset)
            PC <= 32'h0;
        else 
            PC <= TempPC;
    end

    ALU U0(RsData,ALUin2,ALUctr,ALUres,zero);
    //dram U1(memWriteEn,ALUres[6:2],memReadData,RtData);
    //irom U2(PC[6:2],Instr);
    dram_IP U1(~clk,memWriteEn,ALUres[6:2],RtData,memReadData);
    irom_IP U2(clk,PC[6:2],Instr);

    RegFile U3(~clk,reset,regWriteEn,Instr[25:21],Instr[20:16],regWriteAddr,regWriteData,RsData,RtData);
    MainCtr U4(Instr[31:26],regDst,ALUsrc,M2R,regWriteEn,memWriteEn,B,J,ALUop);
    ALUCtr U5(ALUop,Instr[5:0],ALUctr);
    
endmodule
2.2 算术逻辑单元ALU
`timescale 1ns / 1ps

module ALU (
    input signed [31:0] In1,
    input signed [31:0] In2,  
    input [3:0] ALUCtr,
    output reg [31:0] Res,
    output reg Zero
);

always @(In1 or In2 or ALUCtr) begin
    case (ALUCtr)
        4'b0110://sub
        begin
        Res = In1 - In2; 
        Zero = (Res == 0) ? 1 : 0;
        // only sub needs Zero be 1
        end

        4'b0010://add
        begin
        Res = In1 + In2; 
        Zero = 0;
        end

        4'b0000://and
        begin
        Res = In1 & In2; 
        Zero = 0;
        end

        4'b0001://or
        begin
        Res = In1 | In2; 
        Zero = 0;
        end

        4'b0111://slt
        begin
        Res = (In1 < In2) ? 1 : 0; 
        Zero = 0;
        end

        default: 
        begin
        Res = 0;
        Zero = 0;
        end
    endcase
end  
endmodule

2.3 寄存器文件RegFile
`timescale 1ns / 1ps

module RegFile (
    input         clk,
    input         reset,
    input         RegWr,//regWriteEn
    input  [4:0]  RsAddr,
    input  [4:0]  RtAddr,
    input  [4:0]  WrAddr,//regWriteAddr
    input  [31:0] DataIn,//regWriteData
    output [31:0] RsData,
    output [31:0] RtData
);
// 32 regs, for each one is 32
reg [31:0] regs[0:31];

assign RsData = (RsAddr == 5'b0) ? 32'b0 : regs[RsAddr]; 
assign RtData = (RtAddr == 5'b0) ? 32'b0 : regs[RtAddr]; 

integer i;
always @(posedge clk) begin
    if(!reset & RegWr) begin
        regs[WrAddr] = DataIn;
    end

    else if(reset) begin
        for (i = 0; i < 32; i = i + 1) begin
            regs[i] = i;
        end
    end
end
endmodule
2.4 主控制译码MainCtr
`timescale 1ns / 1ps

module MainCtr (
    input [5:0] OpCode,// Instr[31:26]
    output RegDst,
    output ALUSrc,
    output Mem2Reg,
    output RegWr,
    output MemWr,
    output B,
    output J, 
    output [1:0] ALUOp
);
    reg [8:0] outputtemp;

    assign RegDst = outputtemp[8];
    assign ALUSrc = outputtemp[7];  
    assign Mem2Reg = outputtemp[6];  
    assign RegWr = outputtemp[5];  
    assign MemWr = outputtemp[4];  
    assign B = outputtemp[3];  
    assign J = outputtemp[2];  
    assign ALUOp = outputtemp[1:0];

    always @(OpCode) begin
        case (OpCode)
            6'b000010: outputtemp = 9'bxxx0001xx;// j
            6'b000000: outputtemp = 9'b100100010;// R
            6'b100011: outputtemp = 9'b011100000;// lw
            6'b101011: outputtemp = 9'bx1x010000;// sw
            6'b000100: outputtemp = 9'bx0x001001;// beq
            6'b001100: outputtemp = 9'b010100011;// andi
            default:   outputtemp = 9'b000000000;// default
        endcase
    end
endmodule
2.5 ALU控制信号译码ALUCtr
`timescale 1ns / 1ps

module ALUCtr (
    input [1:0] ALUOp,
    input [5:0] Funct,
    output reg [3:0] ALUCtr
);
    always @(ALUOp or Funct) begin
        casex ({ALUOp, Funct})
            8'b00xxxxxx: ALUCtr[3:0] = 4'b0010;// lw, sw
            8'b01xxxxxx: ALUCtr[3:0] = 4'b0110;// beq
            8'b10xx0000: ALUCtr[3:0] = 4'b0010;// add
            8'b10xx0010: ALUCtr[3:0] = 4'b0110;// sub
            8'b10xx0100: ALUCtr[3:0] = 4'b0000;// and 
            8'b10xx0101: ALUCtr[3:0] = 4'b0001;// or
            8'b10xx1010: ALUCtr[3:0] = 4'b0111;// slt
            8'b11xxxxxx: ALUCtr[3:0] = 4'b0000;// andi->and
            default:     ALUCtr[3:0] = 4'b0000;// initial
        endcase
    end
endmodule

3、 部分模块仿真及波形

3.1 算术逻辑单元ALU的仿真
  • 仿真sim文件
`timescale 1ns / 1ps

module ALU_sim(
    output [31:0] Res,
    output Zero
    );
    reg [31:0] In1,In2;
    reg [3:0] ALUCtr;
    
    ALU S1(In1,In2,ALUCtr,Res, Zero);

    initial begin
    In1 = 32'hffff0000;
    In2 = 32'h00ffff00;
    ALUCtr=4'h2;
    #10
    ALUCtr=4'h6;
    #10
    ALUCtr=4'h0;
    #10
    ALUCtr=4'h1;
    #10
    ALUCtr=4'h7;
    end 
endmodule
  • 仿真波形在这里插入图片描述
3.2 寄存器文件RegFile的仿真
  • 仿真sim文件
`timescale 1ns/1ps

module RegFile_sim (
    output [31:0] RsData,
    output [31:0] RtData
);
    reg clk;
    reg reset;
    reg regWriteEn;
    reg [4:0] RsAddr;
    reg [4:0] RtAddr;
    reg [4:0] regWriteAddr;
    reg [31:0] regWriteData;

    parameter PERIOD = 10;

    always begin
        clk = 1'b0;
        #(PERIOD/2) clk = 1'b1;
        #(PERIOD/2) ;  
    end

    initial begin
    reset = 1;
    RsAddr = 5'h0;
    RtAddr = 5'h0;
    #15

    reset = 0;
    #30

    regWriteEn = 1;
    regWriteAddr = 5'h03;
    regWriteData = 32'h5aa5;
    #20

    RsAddr = 5'h03;
    RtAddr = 5'h03;
    end

    RegFile S2(clk,reset,regWriteEn,RsAddr,RtAddr,regWriteAddr,regWriteData,RsData,RtData);
 
endmodule
  • 仿真波形
    在这里插入图片描述
3.3 顶层模块mips的仿真
  • 仿真sim文件
module mips_sim (

);
    reg clk;
    reg reset;
    mips U0(clk, reset);

    parameter PERIOD = 10;

    always begin
        clk = 1'b0;
        # (PERIOD/2) clk = ~clk;
        # (PERIOD/2)    
    end

    initial begin
    reset = 1;
    #20 

    reset = 0;
    end
endmodule
  • 仿真波形
    在这里插入图片描述
  • 10
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 华中科技大学的MIPS单周期微处理器是一种基于MIPS指令集架构的微处理器设计MIPS指令集架构是一种精简指令集(RISC)架构,其特点是指令集简单、指令执行速度快,非常适合用于高性能计算和嵌入式系统。 该微处理器设计采用单周期的执行方式,即每个指令在一个时钟周期内完成执行。这种方式简化了处理器的控制逻辑,并且使得指令执行的时间更为统一,有利于提高处理器的吞吐量。 该微处理器设计的指令集包括了MIPS指令集的主要功能模块,如算术逻辑单元ALU)、寄存器文件(Register File)、数据存储器(Data Memory)、指令存储器(Instruction Memory)等。ALU负责执行算术和逻辑运算,Register File用于存储中间计算结果和控制信号,Data Memory用于存储数据,Instruction Memory用于存储指令。 在指令的执行过程中,该微处理器采用了经典的五段流水线结构,包括取指令(Fetch)、译码(Decode)、执行(Execute)、访存(Memory Access)和写回(Write Back)五个阶段。这种流水线结构能够将多个指令并行执行,提高处理器的指令吞吐量。 除了基本的指令功能外,该微处理器还支持异常处理和中断处理等高级功能。异常处理可以在系统出现错误或异常情况时采取相应的措施,中断处理可以在外部事件发生时暂停当前指令的执行,并跳转到中断处理程序。 综上所述,华中科技大学设计MIPS单周期微处理器结构简单、执行效率高,非常适合用于高性能计算和嵌入式系统等领域的应用。 ### 回答2: 华中科技大学MIPS单周期微处理器是一种基于MIPS结构的微处理器设计,在华中科技大学的计算机体系结构课程中进行教学和研究。该微处理器采用单周期的指令执行流程,每个指令的执行过程包括取指、译码、执行、访存和写回等阶段。 该微处理器的指令集采用了精简指令集计算机(RISC)的设计思想,指令长度固定为32位,共有32个通用寄存器。指令的种包括算术逻辑指令、访存指令、分支指令和跳转指令等。 在该微处理器的结构中,指令以流水线的方式传递,每个阶段分别由不同的硬件模块负责。取指阶段通过指令地址发送请求给指令存储器,将指令读取到指令寄存器中。译码阶段将指令进行解析,确定操作码、操作数等信息,并从寄存器堆中读取寄存器的值。执行阶段进行指令的运算操作,根据操作码执行不同的运算指令。访存阶段根据指令的访存需求进行数据存储或读取操作。最后的写回阶段将计算结果写入寄存器堆中。 该微处理器设计注重时间性能和资源利用率的优化,通过流水线的方式实现了多个指令的并行执行,提高了执行效率。另外,通过使用高速缓存、提前读取指令等优化技术,进一步优化了处理器的性能。 华中科技大学的这个MIPS单周期微处理器设计项目不仅帮助学生深入了解计算机体系结构的原理和设计方法,还为学生提供了丰富的硬件设计和优化实践的机会,培养了学生的问题解决能力和创新精神。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值