概述
计组课程的其中一个大实验–实现一个单周期CPU。所谓单周期,是指一条指令在一个时钟周期内执行完,这是单周期CPU的核心思想。接下来我将详细介绍整个实验的内容与实现,代码可以直接看https://github.com/leungyukshing/-CPU-。
CPU的工作阶段
CPU在处理每一条指令的时候,一般会经过以下几个步骤(有的指令不是所有的都需要执行,这也是单周期与多周期的区别):
- 取指(IF):根据程序计数器PC中的指令地址,从指令存储器中取出一条指令,同时,PC根据指令字长度自动递增产生下一条指令所需要的指令地址(一般是+4),但遇到“地址转移”指令时,则控制器把“转移地址”送入PC,当然得到的“地址”需要做些变换才送入PC。
- 译码(ID):对取指令操作中得到的指令进行分析并译码,确定这条指令需要完成的操作,从而产生相应的操作码,用于驱动执行状态中的各种操作。
- 执行(EXE):根据指令译码得到的操作控制信号,使用ALU具体地执行指令动作,然后转移到结果写回状态。
- 访存(MEM):所有需要访问存储器的操作都将在这个步骤中执行,该步骤给出存储器的数据地址,把数据写入到存储器中数据地址所指定的存储单元或者从存储器中得到数据地址单元中的数据。
- 写回(WB):指令执行的结果或者访问存储器中得到的数据写回相应的目的寄存器中。
数据通路
一条指令的执行需要不同部件的配合,如何使用这些部件就需要控制单元发出控制信号。指令以及数据在CPU各部件中的移动是使用数据通路图来描述的,老师提供的数据通路图如下:
接下来我们在实现的过程中,需要紧密地联系以上这幅数据通路图,因此最好先熟悉这幅图,包括每个模块的接口,每个数据的位数等。
每条指令由不同模块功能相互组合而成,模块主要有程序计数器(PC),指令寄存器(rom),寄存器组(register),控制单元(control unit),ALU运算器(ALU),数据存储器(ram),符号或者零拓展模块(extend)以及加法器,移位器和几个二选一数据选择器。
代码实现
在vivado中使用verilog语言逐个.v
文件实现,以下是主要模块的代码。
1.控制单元(ControlUnit.v)
这里需要根据每条指令所用到的模块,通过建立对应的真值表,对每个控制信号进行赋值,以确定使用哪些模块。
确定控制信号真值表,也是整个CPU逻辑最重要的部分。
1 | module ControlUnit( |
2.程序计数器(PC.v)
为了分离出PC和PC+4,这里特意分成两个模块。PC模块是设置PC为PCnext。在时钟上升沿到来或清零信号到来的时候,设置新的PC。
1 | module PC( |
3.PC选择器(Mux.v)
根据指令形式,确定下一个PC是PC+4还是跳转。这里牵涉到了数据选择的功能,因此我选择把他分离出来。
1 | module Mux( |
4.指令寄存器(InsMEM.v)
指令寄存器是由寄存器组成的,存储所有我们将要执行的指令。这里采用的是8位大端的存储模式。
这里先给出我们需要测试的指令序列。
1 | module InsMEM( |
5.寄存器组(RegisterFile.v)
寄存器组是用32个32位的寄存器组成的存储模块,用于存储运算中的一些变量,模拟的是CPU中的寄存器。现实中,当CPU断电后,这一部分的内容将会被清空。
1 | module RegisterFile( |
6.算术逻辑运算单元(ALU.v)
ALU是CPU中的核心部分,用于指令执行中的算术和逻辑运算,返回运算的结果可能是控制跳转的信号,也可能是计算结果,需要写回寄存器或者写入到存储器。
1 | module ALU( |
7.数据存储器(DataMEM.v)
数据存储器使用8位字长的存储器,同样采用大端模式。现实中,这一部分模拟的是现实中的二级存储器–外存。当CPU断电时,这一部分的信息是不会丢失的。
1 | module DataMEM( |
8.符号位拓展单元(Extend.v)
CPU在处理数据的过程中,会遇到一些位数不一样的数据,比如在指令中提取的立即数,需要拓展成32位数据才可以给ALU运算。
1 | module Extend( |
9.顶层模块(s_cpu.v)
上面实现了CPU中的8大模块,接下来就需要有一个顶层模块来连接各模块,运行整个CPU。
根据数据通路图,连接各模块的接口,wire变量就相当于连线,这个是比较好理解的。
1 | module s_cpu( |
仿真测试
以上我们实现了CPU的主要功能,接下来可以编写仿真测试文件对上面实现的内容进行仿真测试,以验证CPU的正确性。
仿真测试文件是sim文件,这里我命名为test.v
。
1 | module test; |
这里只给出简单的而一些结果,具体的测试结果在这里就不详细叙述了,大家可以自己跑一下来看。
小结
以上就是单周期CPU的实现过程以及一些简单的分析。烧板的部分将在下一篇博客介绍,希望大家多多支持,谢谢!