单周期CPU仿真

之前的几周我们做了单周期CPU仿真的实验,虽然一开始做得一脸懵逼,但最后还是成功实现了一个简单的CPU。

单周期CPU原理

单周期CPU指的是一条指令的执行在一个时钟周期内完成,无论是哪种指令。处理指令有以下五个步骤:
1. 取指令:从PC取出下一条指令的地址并读取指令。
2. 指令译码:根据指令产生各种控制信号。
3. 指令执行:根据控制信号执行指令。
4. 存储器访问:读写存储器。
5. 写回:将运算结果或读存储器的数据写入寄存器。

单周期CPU设计

单周期CPU处理的是MIPS指令,共有三种类型,即R指令,I指令和J指令。不同的指令有不同的功能,执行的步骤也各不相同。一个时钟周期只有上升沿和下降沿,而单周期CPU必须在一个周期内完成最多五个步骤,因此需要组合逻辑电路和时序逻辑电路的结合。时序逻辑电路可以控制操作的先后顺序以及执行次数,我选择在上升沿取指令,在下降沿写寄存器和存储器。组合逻辑电路虽然无法确定多个操作的执行顺序,但执行多个操作几乎可以瞬间完成,我选择将译码、读寄存器、读存储器和运算操作用组合逻辑电路实现。

在一个时钟周期内,上升沿读取指令地址,瞬间读取对应指令,瞬间完成译码,瞬间产生控制信号,瞬间完成读寄存器,瞬间完成运算,瞬间完成读存储器,然后下降沿写寄存器和写存储器。

使用工具

vivado软件和verilog语言

单周期CPU实现

从理论上分析指令按步骤执行,但实际上由于组合逻辑电路的存在,各模块运行的顺序关系非常复杂,甚至会出现循环。从整体上看,整个单周期CPU的输入只有时钟信号和重置信号,测试程序的读入可以看作指令存储器的初始化,由此可以直接或间接确定电路中每一个信号。为了简化逻辑,我只关注信号的直接来源,对大部分信号用wire类型以契合组合逻辑的思路,对小部分信号用reg类型并赋予初值以避免组合逻辑形成循环。我先实现功能模块,再实现连接模块,然后实现控制单元,最后用顶层模块整合。因为每个信号只与直接来源相关,所以我可以对任意一个bug跟踪溯源,最后确定是逻辑问题还是整合问题。

注意事项

在实验中有很多细节需要注意:
1. 读写存储器统一采用大端模式,即数据的高字节保存在内存的低字节。统一采用小端模式也没有问题,不过大端模式方便读入测试程序。
2. always不能混用边沿敏感和电平敏感。边沿敏感即指定上升沿或下降沿触发,常用于时钟信号,也可用于异步信号;电平敏感即电平变化时触发,常用于变量。
3. 边沿敏感常用非阻塞赋值=,电平敏感常用阻塞赋值<=。非阻塞赋值无需等待赋值完成即可继续执行程序,阻塞赋值需要等待赋值完成才能继续执行程序。我的理解是,上升沿和下降沿时间短,非阻塞赋值可以节约时间;电平敏感对执行速度要求不高,阻塞赋值可以确定执行顺序。
4. 程序开始执行时,第一条指令已经完成读取,但还需要下降沿执行指令,因此我将时钟信号初始化为1;每次重置程序时,第一条指令已经完成读取,但还需要下降沿执行指令,因此在重置信号为0时,我将时钟信号设置为1。
5. 我们的实验还可以在Basys3开发板上仿真。用按钮模拟时钟需要消抖处理,可以设置tmp,每隔一小段间隔t才将tmp更新为当前按钮值,那么短时间内的重复按下也只会产生单步脉冲。

猜你喜欢

转载自blog.csdn.net/fast_g/article/details/80635871
今日推荐