单周期CPU设计(Verilog)

2017/06/08: 当时单周期cpu写的比较仓促,没有深入的进行调试,我准备在放假的时候重构一下代码, 然后把博文改进一下,现在实在没有时间,很抱歉~ 不过多周期我有调试过的,所以有需要的可以移步到我的多周期cpu设计


一、 实验目的

(1) 掌握单周期CPU数据通路图的构成、原理及其设计方法;
(2) 掌握单周期CPU的实现方法,代码实现方法;
(3) 认识和掌握指令与CPU的关系;
(4) 掌握测试单周期CPU的方法。

二、 实验内容

设计一个单周期CPU,该CPU至少能实现以下指令功能操作。需设计的指令与格式如下:
这里写图片描述
这里写图片描述
特别说明:
immediate是从PC+4地址开始和转移到的指令之间指令条数。immediate符号扩展之后左移2位再相加。为什么要左移2位?由于跳转到的指令地址肯定是4的倍数(每条指令占4个字节),最低两位是“00”,因此将immediate放进指令码中的时候,是右移了2位的,也就是以上说的“指令之间指令条数”。
这里写图片描述

补充:

1、PC、寄存器组和存储器写状态使用时钟触发。
2、指令存储器和数据存储器存储单元宽度一律使用8位,即一个字节的存储单位。不能使用32位作为存储器存储单元宽度。
3、控制器部分要学会用控制信号真值表方法分析问题并写出逻辑表达式;或者用case语句方法逐个产生各指令控制信号。
4、必须写一段测试用的汇编程序,而且必须包含所要求的所有指令,beq指令必须检查两种情况:“等”和“不等”。

三、实验原理

单周期CPU指的是一条指令的执行在一个时钟周期内完成,然后开始下一条指令的执行,即一条指令用一个时钟周期完成。电平从低到高变化的瞬间称为时钟上升沿,两个相邻时钟上升沿之间的时间间隔称为一个时钟周期。时钟周期一般也称振荡周期(如果晶振的输出没有经过分频就直接作为CPU的工作时钟,则时钟周期就等于振荡周期。若振荡周期经二分频后形成时钟脉冲信号作为CPU的工作时钟,这样,时钟周期就是振荡周期的两倍。)

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

这里写图片描述

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

这里写图片描述

相关部件及引脚说明:
Instruction Memory:指令存储器,
Iaddr,指令存储器地址输入端口
IDataIn,指令存储器数据输入端口(指令代码输入端口)
IDataOut,指令存储器数据输出端口(指令代码输出端口)
RW,指令存储器读写控制信号,为1写,为0读
Data Memory:数据存储器,
Daddr,数据存储器地址输入端口
DataIn,数据存储器数据输入端口
DataOut,数据存储器数据输出端口
RD,数据存储器读控制信号,为1读
WR,数据存储器写控制信号,为1写
Register File:寄存器组
Read Reg1,rs寄存器地址输入端口
Read Reg2,rt寄存器地址输入端口
Write Reg,将数据写入的寄存器端口,其地址来源rt或rd字段
Write Data,写入寄存器的数据输入端口
Read Data1,rs寄存器数据输出端口
Read Data2,rt寄存器数据输出端口
WE,写使能信号,为1时,在时钟上升沿写入
ALU: 算术逻辑单元
result,ALU运算结果
zero,运算结果标志,结果为0输出1,否则输出0

这里写图片描述

需要说明的是以上数据通路图是根据要实现的指令功能的要求画出来的,同时,还必须确定ALU的运算功能(当然,以上指令没有完全用到提供的ALU所有功能,但至少必须能实现以上指令功能操作)。从数据通路图上可以看出控制单元部分需要产生各种控制信号,当然,也有些信号必须要传送给控制单元。从指令功能要求和数据通路图的关系得出以上表1,这样,从表1可以看出各控制信号与相应指令之间的相互关系,根据这种关系就可以得出控制信号与指令之间的关系表(留给学生完成),再根据关系表可以写出各控制信号的逻辑表达式,这样控制单元部分就可实现了。

指令执行的结果总是在时钟下降沿开始保存到寄存器和存储器中,PC的改变是在时钟上升沿进行的,这样稳定性较好。另外,值得注意的问题,设计时,用模块化的思想方法设计,关于ALU设计、存储器设计、寄存器组设计等等,也是必须认真考虑的问题。

四、实验设备

PC机一台,BASYS 3 板一块,Xilinx Vivado 开发软件一套。

五. 实验分析与设计

下面是我设计单周期CPU的详细过程:
1.设计Control Unit
由数据通路图可知,
**输入信号为:**opCode、zero
输出信号为: PCWre, ALUSrcA, ALUSrcB,DBDataSrc,RegWre,InsMemRW, RD,WR, ExtSel,RegDst,PCSrc,ALUOp
设计control unit,必须列出控制信号与指令的关系表
这里写图片描述
然后根据该表assign对应的值。

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2017/04/23 20:43:40
// Design Name: 
// Module Name: controlUnit
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module controlUnit(
    // 根据数据通路图定义输入和输出
    input [5:0] opCode,
    input zero,
    output PCWre,
    output ALUSrcA,
    output ALUSrcB,
    output DBDataSrc,
    output RegWre,
    output InsMemRW,
    output RD,
    output WR,
    output ExtSel,
    output RegDst,
    output PCSrc,
    output [2:0] ALUOp
    );
    // 根据opcode定义控制信号为1或0
    assign PCWre = (opCode == 6'b111111) ? 0 : 1;
    assign ALUSrcA = (opCode == 6'b011000) ? 1 : 0;
    assign ALUSrcB = (opCode == 6'b000001 || opCode == 6'b010000 || opCode == 6'b100110 || opCode == 6'b100111) ? 1 : 0;
    assign DBDataSrc = (opCode == 6'b100111) ? 1 : 0;
    assign RegWre = (opCode == 6'b100110 || opCode == 6'b110000 || opCode == 6'b111111) ? 0 : 1;
    assign InsMemRW = 0;
    assign RD = (opCode == 6'b100111) ? 0 : 1;
    assign WR = (opCode == 6'b100110) ? 0 : 1;
    assign ExtSel = (opCode == 6'b010000) ? 0 : 1;
    assign RegDst = (opCode == 6'b000001 || opCode == 6'b010000 || opCode == 6'b100111) ? 0 : 1;
    assign PCSrc = (opCode == 6'b110000 && zero == 1) ? 1 : 0;
    assign ALUOp[2] = (opCode == 6'b010000 || opCode == 6'b010001 || opCode == 6'b010000) ? 1 : 0;
    assign ALUOp[1] = 0;
    assign ALUOp[0] = (opCode == 6'b000010 || opCode == 6'b010001 || opCode == 6'b110000) ? 1 : 0;
endmodule

2.设计ALU
由数据通路图可知,
输入信号为: ReadData1, ReadData2,inExt,insa,ALUSrcA,ALUSrcB,ALUOp
输出信号为: zero, result
然后根据表2 ALU运算功能表对result与zero赋值

`time
  • 70
    点赞
  • 511
    收藏
    觉得还不错? 一键收藏
  • 18
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值