zoukankan      html  css  js  c++  java
  • 【verilog】单周期MIPS CPU设计

    一、    实验要求

    设计一个单周期MIPS CPU,依据给定过的指令集,设计核心的控制信号。依据给定的数据通路和控制单元信号进行设计。

    二、    实验内容

    1.数据通路设计:mips指令格式只有三种:

    1)R类型  从寄存器堆中取出两个操作数,计算结果写回寄存器堆

    2)I类型  用一个16位的立即数作为一个源操作数

    3)J类型  用一个26位的立即数作为跳转的目标地址

    根据以上三种类型可以设计相应的数据通路。基本原理如下

    下面是实现之后的效果

    2.相应模块设计

    首先明确应该有哪些主要功能模块

    逻辑电路:控制单元,选择器,ALU,符号位扩展单元,branch加法器等

    时序电路:PC寄存器,指令/数据存储器,寄存器文件

    对应的主要代码如下:

    (1)top模块对各部分的例化:

    下面是具体的主要模块的实现

    (2)控制单元

    module controlunit(
    
     input [5:0] opcode,
    
     input [5:0] funct,          //本实验只考虑add所以暂时用不到这个字段
    
     
    
     output reg mem_write,
    
     output reg mem_toreg,
    
     output reg branch,
    
     output reg alu_src,
    
     output reg reg_dst,
    
     output reg reg_write,
    
     output reg [2:0] alu_op,
    
     output reg jump
    
     
    
     );
    
     
    
     always@(*)
    
           case(opcode)
    
                  6'b000000:                        //add
    
                         begin
    
                                reg_dst=1;
    
                                alu_src=0;
    
                                mem_toreg=0;
    
                                reg_write=1;
    
                                mem_write=0;
    
                                branch=0;
    
                                alu_op=3'b001;
    
                                jump=0;
    
                         end
    
                  6'b001000:                          //addi
    
                         begin
    
                                reg_dst=0;
    
                                alu_src=1;
    
                                mem_toreg=0;
    
                                reg_write=1;
    
                                mem_write=0;
    
                                branch=0;
    
                                alu_op=3'b001;
    
                                jump=0;
    
                         end
    
                  6'b100011:                        //lw
    
                         begin
    
                                reg_dst=0;
    
                                alu_src=1;
    
                                mem_toreg=1;
    
                                reg_write=1;
    
                                mem_write=0;
    
                                branch=0;
    
                                alu_op=3'b001;
    
                                jump=0;
    
                         end
    
                  6'b101011:                            //sw
    
                         begin
    
                                reg_dst=0;
    
                                alu_src=1;
    
                                mem_toreg=0;
    
                                reg_write=0;
    
                                mem_write=1;
    
                                branch=0;
    
                                alu_op=2'b001;
    
                                jump=0;
    
                         end
    
                  6'b000010:                            //jump
    
                         begin
    
                                reg_dst=1;
    
                                alu_src=0;
    
                                mem_toreg=0;
    
                                reg_write=0;
    
                                mem_write=0;
    
                                branch=1;
    
                                alu_op=2'b001;
    
                                jump=1;
    
                         end
    
                 
    
                  6'b000111:    //bgtz
    
                         begin
    
                                reg_dst=1;
    
                                alu_src=0;
    
                                mem_toreg=0;
    
                                reg_write=0;
    
                                mem_write=0;
    
                                branch=1;
    
                                alu_op=2'b001;
    
                                jump=0;
    
                         end
    
                        
    
                        
    
                  default:
    
                         begin
    
                                reg_dst=1;
    
                                alu_src=0;
    
                                mem_toreg=0;
    
                                reg_write=1;
    
                                mem_write=0;
    
                                branch=0;
    
                                alu_op=2'b10;
    
                         end
    
           endcase
    
    endmodule

    (3)符号位扩展单元

    module signextension(num_in,num_out);
    
     input wire[15:0] num_in;
    
     output reg[31:0] num_out;
    
     initial begin
    
       num_out = 0;
    
     end
    
     always @(num_in) begin
    
          num_out<= {{16{num_in[15]}},num_in[15:0]};
    
      end
    
     
    
    endmodule

    (4)branch加法器模块

           这里不进行左移操作,与至指令寄存器的设置相关,本实验中指令集寄存器每次读取32位数据,所以不需要像8位那样进行左移。

    (5)pc自增模块

    (6)选择器

    这里是32位的,还有5位的型号,原理一致较为简单,此不赘述

    (7)列一下关于两个ram的接口

                        

    (8)ALU,regfile参见前面几次实验,这里不作分析

    三、    实验验证

    1.编写coe文件

    根据实验的要求以及个人设计的情况,测试代码如下:

    (主要是因为pc寄存器指向的地址是32位而不是8位,所以做了修改,无关算法)

    MEMORY_INITIALIZATION_RADIX=16;
    
    MEMORY_INITIALIZATION_VECTOR=
    
    20080000,
    
    200d0014,
    
    8dad0000,
    
    200b0015,
    
    8d6b0000,
    
    200c0015,
    
    8d8c0001,
    
    ad0b0000,
    
    ad0c0001,
    
    21a9fffe,
    
    8d0b0000,
    
    8d0c0001,
    
    016c5020,
    
    ad0a0002,
    
    21080001,
    
    2129ffff,
    
    1d20fff9,
    
    08000011;

    测试数据:

    MEMORY_INITIALIZATION_RADIX=10;
    
    MEMORY_INITIALIZATION_VECTOR=
    
    0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,20,3,3;

    2.仿真测试

    这里主要是对pc的跳转进行分析,发现跳转无误,我们进入到ram里观察执行的情况,下面是dataram:

    正好存储了斐波那契数列的前二十个数,符合要求。

    四、    分析和总结

    本实验实现了一个单周期mipscpu,实现了addi、add、lw、sw、bgtz、j六条指令。

    实验的关键在于弄清楚cpu以及每条指令的数据通路,还有相应的控制信号的具体赋值。

    在具体实现的时候,最为重要的的是确保指令的跳转正确,在此基础上对各个指令的执行debug就轻而易举。

    需要注意的是,在实例化的时候各个对应的接口较为繁杂,应当注意不要出错,命名简单易懂。

  • 相关阅读:
    Java类对象转json字符串,servlet或js的json字符串转json对象或数组
    大三下每周总结--第一周
    阅读架构漫谈九篇博客有感-1500字
    大三上寒假15天--第15天
    大三上寒假15天--第14天
    大三上寒假15天--第13天
    jenkins+appium android app自动化测试
    windows jenkins 卸载
    jenkins运行Python
    pytest+jenkins安装+allure导出报告
  • 原文地址:https://www.cnblogs.com/JK-Z/p/12262050.html
Copyright © 2011-2022 走看看