用Verilog设计1个单周期CPU


一、原理

1.单周期CPU

单周期CPU可以看成由数据通路和和控制部件两大部分组成。数据通路是指在指令执行过程中,数据所经过的路径和路径上所涉及的功能部件。而控制部件则根据每条指令的不同功能,生成对不同数据通路的不同控制信号,正确地控制指令的执行流程。
因此,要设计处理器,首先需要确定处理器的指令集和指令编码,然后确定每条指令的数据通路,最后确定数据通路的控制信号。

2.单周期CPU指令模块

单周期(Single Cycle)CPU是指CPU从取出1条指令到执行完该指令只需1个时钟周期。一条指令的执行过程包括:取指令→分析指令→执行指令→保存结果(如果有的话)。对于单周期CPU来说,这些执行步骤均在一个时钟周期内完成。
在这里插入图片描述

3. MIPS指令格式

MIPS指令系统结构有MIPS-32和MIPS-64两种。本实验的MIPS指令选用MIPS-32。以下所说的MIPS指令均指MIPS-32。MIPS的指令格式为32位。下图给出了MIPS指令的3种格式。
在这里插入图片描述

4. 指令处理流程

在这里插入图片描述

5. 单周期CPU数据通路

CPU的电路包括数据路径(Data path)和控制部件(Control Unit)两大部分,下面给出了单周期CPU的总体设计图。
在这里插入图片描述
一个简单的基本上能够在单周期上完成所要求设计的指令功能的数据通路和必要的控制线路图。其中指令储存在指令储存器,数据储存在数据存储器。访问存储器时,先给出地址,然后由读/写信号控制。对于寄存器组,读操作时,先给出地址,输出端直接输出相应数据;而在写操作时,在 We使能信号为1时,在时钟边沿触发写入。

二、单周期CPU的设计

1.pcadd4

在这里插入图片描述
In为输入端口,输入当前指令地址;Out为下一条指令地址,为输出端口。
代码:

`timescale 1ns / 1ps
 
module PCadd4(PC_0,PCadd4);
 
    input [31:0] PC_0;//偏移量
 
    output [31:0] PCadd4;//新指令地址
 
    CLA_32 cla32_for_pcadd(PC_0,4,0, PCadd4, Cout);//在ALU模块
 
endmodule

2.指令存储器INSTMEM

在这里插入图片描述
依据当前pc,读取指令寄存器中相对应地址Addr[6:2]的指令。
address: 指令地址,输入信号
inst:指令编码,输出信号
代码:

`timescale 1ns / 1ps
 
module INSTMEM(
 
      input  [31:0] address,
 
      output [31:0] inst
 
    );
 
    wire [31:0] ram [0:18];
 
 
 
 assign ram[5'h00] = 32'b001000_00001_00001_0000000000000000;
 
//不写的码,仅占位用(andi R1 , R1 , 0x0000)
 
assign ram[5'h01] = 32'b001000_00001_00001_0001001000110100;
 
//addi R1 , R1 , 0x1234   
 
assign ram[5'h02] = 32'b001000_00010_00010_0001000100010001;
 
//addi R2 , R2 , 0x1111
 
 assign ram[5'h03] = 32'b000000_00001_00010_00011_00000_100000;
 
//add R3 , R1 , R2 0x2345
 
assign ram[5'h04] = 32'b000000_00001_00010_00100_00000_100010;
 
//sub R4 , R1 , R2 0x0123
 
assign ram[5'h05] = 32'b000000_00001_00010_00011_00000_100100;
 
//and R3 , R1 , R2  0x1010
 
assign ram[5'h06] = 32'b000000_00001_00010_00100_00000_100101;
 
//or R4 , R1 , R2 0x1335
 
assign ram[5'h07] = 32'b001100_00001_00101_0010001000100010;
 
//andi R5 , R1 , 0x2222
 
assign ram[5'h08] = 32'b001101_00001_00101_0011001100110011;
 
//ori R5 , R1 , 0x3333
 
assign ram[5'h09] = 32'b000010_00000000000000000000001100;
 
//j   跳转到beq行  0800000C
 
assign ram[5'h0a] = 32'b000000_00000_00010_00011_00100_000010;
 
//不用
 
assign ram[5'h0b] = 32'b000000_00000_00010_00011_00100_000011;
 
//不用
 
assign ram[5'h0c] = 32'b000100_00001_00011_0000000000000011;
 
//beq R1 , R2 , 3 不跳 10230003
 
assign ram[5'h0d] = 32'b000101_00001_00011_0000000000000010;
 
//bne R1 , R2 , 2 跳至sw行  14230002
 
assign ram[5'h0e] = 32'b001101_00001_00011_0000000011101111;
 
//不用
 
assign ram[5'h0f] = 32'b001110_00001_00011_0000000011101111;
 
//不用
 
assign ram[5'h10] = 32'b101011_00100_00101_0000000000000001;
 
//sw R5 , 1(R4)  AC850001 r5=r4=0x1335
 
assign ram[5'h11] = 32'b100011_00100_00110_0000000000000001;
 
// lw R6 , 1(R4)  8C860001
 
assign ram[5'h12] = 32'b000010_00000000000000000000000001;
 
//j 跳回开头  08000001
 
assign inst = ram[address[6:2]];
 
endmodule

3.控制单元CONUNIT

在这里插入图片描述
控制器是作为CPU控制信号产生的器件,通过解析op得到该指令的各种控制信号,使其他器件有效或无效。
Func:输入信号
Op :输入信号
Z:零标志信号,对Pcsrc有影响,输入信号
Aluc :控制ALU的计算种类,输出信号
Aluqb:控制ALU的Y端口的输入值,输出信号
Pcsrc :控制目标指令地址,输出信号
Regrt:控制输入寄存器的Wr端口,输出信号
Reg2reg:控制REHFILE更新值的来源
Se:控制扩展模块,输出信号
Wmem:控制数据存储器的写使能信号,输出信号
Wreg:控制寄存器端的写使能信号,输出信号
代码:

`timescale 1ns / 1ps
 
module CONUNIT(Op,Func,Z,Regrt,Se,Wreg,Aluqb,Aluc,Wmem,Pcsrc,Reg2reg);
 
    input [5:0] Op,Func;
 
    input Z;
 
    //输入指令的op和func字段(对应[31:26][5:0])
 
    //输入的z是alu的运算结果 全为零则z为零
 
    output Regrt,Se,Wreg,Aluqb,Wmem,Reg2reg;
 
    output [1:0] Aluc,Pcsrc;
 
    //regrt决定是读取立即数还是寄存器1/0
 
    //se决定是符号扩展还是0扩展 1/0
 
    //wreg寄存器的写信号
 
    //aluqb选择alu读取的扩展后的 还是qb寄存器输出的0/1
 
    //wmem 数据储存器的写信号1有效
 
    //reg2regd 输入寄存器D的是运算R还是dmem的dout
 
    //aluc 00+ 01- 10& 11|
 
    //pcsrs 0 0pc+4 2分支语句 3j指令
 
    wire R_type=~|Op;
 
   
 
    wire I_add=R_type&Func[5]&~Func[4]&~Func[3]&~Func[2]&~Func[1]&~Func[0];
 
    wire I_sub=R_type&Func[5]&~Func[4]&~Func[3]&~Func[2]&Func[1]&~Func[0];
 
    wire I_and=R_type&Func[5]&~Func[4]&~Func[3]&Func[2]&~Func[1]&~Func[0];
 
    wire I_or=R_type&Func[5]&~Func[4]&~Func[3]&Func[2]&~Func[1]&Func[0];
 
    wire I_addi=~Op[5]&~Op[4]&Op[3]&~Op[2]&~Op[1]&~Op[0];
 
    wire I_andi=~Op[5]&~Op[4]&Op[3]&Op[2]&~Op[1]&~Op[0];
 
    wire I_ori=~Op[5]&~Op[4]&Op[3]&Op[2]&~Op[1]&Op[0];
 
    wire I_lw=Op[5]&~Op[4]&~Op[3]&~Op[2]&Op[1]&Op[0];
 
    wire I_sw=Op[5]&~Op[4]&Op[3]&~Op[2]&Op[1]&Op[0];
 
    wire I_beq=~Op[5]&~Op[4]&~Op[3]&Op[2]&~Op[1]&~Op[0];
 
    wire I_bne=~Op[5]&~Op[4]&~Op[3]&Op[2]&~Op[1]&Op[0];
 
    wire I_J=~Op[5]&~Op[4]&~Op[3]&~Op[2]&Op[1]&~Op[0];
 
   
 
    assign Regrt=I_addi|I_andi|I_ori|I_lw|I_sw|I_beq|I_bne|I_J;
 
    assign Se=I_addi|I_lw|I_sw|I_beq|I_bne;
 
    assign Wreg=I_add|I_sub|I_and|I_or|I_addi|I_andi|I_ori|I_lw;
 
    assign Aluqb=I_add|I_sub|I_and|I_or|I_beq|I_bne|I_J;
 
    assign Aluc[1]=I_and|I_or|I_andi|I_ori;
 
    assign Aluc[0]=I_sub|I_or|I_ori|I_beq|I_bne;
 
    assign Wmem=I_sw;
 
    assign Pcsrc[1]=I_beq&Z|I_bne&~Z|I_J
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值