一、实验目的: 

通过设计并实现支持10 条指令的CPU,进一步理解和掌握CPU 设计的基本原理和过程。 

二、实验内容: 

设计和实现一个支持如下十条指令的单周期CPU。 

Ø非访存指令
u清除累加器指令CLA
u累加器取反指令COM
u算术右移一位指令SHR:将累加器ACC 中的数右移一位,结果放回ACC 

u循环左移一位指令CSL:对累加器中的数据进行操作
u停机指令STP 

Ø访存指令 

u 加法指令ADD 

u 存数指令STA 

u 取数指令LDA 

Ø转移类指令 

u 无条件转移指令JMP imm:signExt(imm) -> PC 

u 有条件转移(负则转)指令BAN X: ACC 最高位为1 则(PC)+ X -> PC,否则PC 不变 

三、实验原理

1、约定机器字长、指令字长和存储字长均为16位。

2、约定指令格式如下图所示,高4位为指令的操作码字段,低12位为指令的地址码或者立即寻址的操作数。

android crc 累加取反_数据

3、指令和相应的操作码对照表

android crc 累加取反_Verilog_02

CPU 原理图 

android crc 累加取反_数据_03

四、实验步骤

4.1 CPU 各模块Verilog 实现  

1) PC 模块

输入 

时钟信号clk、重置信号 rst 、停机信号stop、无条件转移信号wr、条件转移信号judge、 pc修改量jmp(12位)

 

输出 

 

指令地址addr(12 位) 

功能 

每个时钟上升沿 addr 的值自动加 1,并输出

如果wr为1,修改addr为 jmp - 1

如果judge为1,修改addr为 addr + jmp

如果rst为1,修改addr为0

 

Verilog 关键代码:

android crc 累加取反_Verilog_04

2) 指令存储器模块 

该模块中已经初始化了10条指令,并且刚好串在一起,可以作为一组逻辑统一的整体。

输入 

12位指令地址 addr 

输出 

16 位指令 ins 

功能 

存放待执行的指令(初始化),并根据地址输出指令 

Verilog 关键代码:

android crc 累加取反_android crc 累加取反_05

3) 累加器

输入 

时钟信号clk、读写控制线 wr、输入数据 indata

输出 

输出数据outdata

功能 

ACC数据从outdata输出,如果wr有效,在clk下降沿将会把indata写入ACC中。

Verilog 关键代码:

android crc 累加取反_android crc 累加取反_06

4) ALU 

表4.4 ALU 模块功能描述 

输入 

操作数 in1 和in2、操作选择信号alu_op 

输出 

 

ALU 运算结果 Z 

 

功能 

根据操作选择信号计算in1 和in2 的运算结果 Z 

Verilog 关键代码:

android crc 累加取反_android crc 累加取反_07

5) 控制单元 

表4.5 控制单元模块功能描述 

输入 

指令(操作码) 

输出 

停机信号stop、PC读写控制线 pcwr、ACC读写控制线 accwr 、数据存储器读写控制线 datamemorywr、ALU 的操作选择信号 op 

功能 

根据当前指令功能对stop、pcwr、accwr、datamemorywr和op 赋值 

Verilog 关键代码:

android crc 累加取反_Verilog_08

6) 数据存储器模块 

该模块中初始化了2条数据,一个用于测试各种运算功能,另一个用于测试条件转移。

输入 

时钟信号clk、读写控制线wr、12位指令地址 addr、输入数据 indata 

输出 

16 位输出数据 outdata 

功能 

存放数据,可以读出,或在clk下降沿写入。 

Verilog 关键代码:

android crc 累加取反_Verilog_09

4.2 CPU 顶层文件封装实现 

在这个文件中,声明了pc,insmemory,datamemory,acc,cu,alu等模块。

并且声明了几个wire类型的变量用于连接各个部件。

Verilog 关键代码:

android crc 累加取反_下降沿_10

4.3 CPU 模拟仿真 

1、TestBench关键代码 

CPU的测试文件如下,主要功能就是产生了时钟信号,并且使用rst信号初始化pc。

clk信号每1ns反转一次,一个时钟周期2ns。

20ns后结束测试,刚好测试完10条指令。

android crc 累加取反_android crc 累加取反_11

2、ModelSim仿真及分析 

指令1 LDA 取数指令

这条指令在指令存储器的地址000000000000处。传送给ALU的命令是0110。

将数据地址为000000000000处的数据0000000000000010存储进ACC中。

CU会向ACC发出写信号,在时钟的下降沿写入数据。

android crc 累加取反_数据_12

指令2 COM 取反指令

这条指令在指令存储器的地址000000000001处。传送给ALU的命令是0001。

将ACC中的数据0000000000000010取反后得到1111111111111101。

CU会向ACC发出写信号,在时钟的下降沿写入数据。

android crc 累加取反_Verilog_13

指令3 SHR 算数右移指令

这条指令在指令存储器的地址000000000010处。传送给ALU的命令是0010。

将ACC中的数据1111111111111101算数右移后得到1111111111111110。

CU会向ACC发出写信号,在时钟的下降沿写入数据。

android crc 累加取反_数据_14

指令4 CSL 循环左移指令

这条指令在指令存储器的地址000000000011处。传送给ALU的命令是0011。

将ACC中的数据1111111111111110循环左移后得到1111111111111101。

CU会向ACC发出写信号,在时钟的下降沿写入数据。

android crc 累加取反_android crc 累加取反_15

指令5 CLA 清除指令

这条指令在指令存储器的地址000000000100处。传送给ALU的命令是0000。

将ACC中的数据1111111111111101清零后得到0000000000000000。

CU会向ACC发出写信号,在时钟的下降沿写入数据。

android crc 累加取反_下降沿_16

指令6 ADD 加法指令

这条指令在指令存储器的地址000000000101处。传送给ALU的命令是0100。

将ACC中的数据0000000000000000和数据存储器的地址为000000000001处的数据相加得到1000000000000000再保存到ACC中。

CU会向ACC发出写信号,在时钟的下降沿写入数据。

android crc 累加取反_数据_17

指令7 STA 存数指令

这条指令在指令存储器的地址000000000110处。传送给ALU的命令是0101。

ACC中的数据存储到数据存储器地址为000000000010的单元。

可以从图中看到000000000010单元的值由不确定变为1000000000000000。

CU会向数据存储器发出写信号,在时钟的下降沿写入数据。

android crc 累加取反_android crc 累加取反_18

指令8 JMP 无条件转移指令

这条指令在指令存储器的地址000000000111处。传送给ALU的命令是1111。

这条指令使用地址码采用立即寻址方式向PC传送跳转的目标地址。

这里我们跳转到指令存储器地址为000000001001的单元(该单元保存了条件转移指令)。

可以看到下降沿的时候PC的值被修改为000000001000而不是000000001001,因为下一个时钟周期上升沿PC自动加1会进行修正。

CU会向PC发出写信号,在时钟的下降沿写入数据。

android crc 累加取反_数据_19

指令9 BAN 条件转移指令

这条指令在指令存储器的地址000000001001处。传送给ALU的命令是0111。

这里我这条指令设置为会判断ACC最高位是否位1,如果为1,会把PC增加2。

注意这里不需要进行PC的修正,直接在下降沿将PC加2修改000000001011。

因为在相对寻址中,位移量是以条件转移指令的下一条指令的地址为基准的做偏移的。

而指令字长刚好是一个存储字,所以最终会跳转到地址为000000001100的指令存储器单元。该单元内的指令为停机指令。

ALU会根据判断的结果向PC发出写信号judge,如果为1,在时钟的下降沿修改PC。

android crc 累加取反_android crc 累加取反_20

指令10 STP 停机指令

这条指令在指令存储器的地址000000001100处。传送给ALU的命令是1111。

这条指令会将PC内的标志位state设置为0。

如果state为0的话,PC在每个时钟上升沿将不会自动加1。

在图中可以看到下一个时钟上升沿到来的时候,地址保持000000001100无变化。

CU会向PC发出停机信号STOP,使PC不再自动增加。

android crc 累加取反_android crc 累加取反_21

五、总结

Verilog语法简洁优雅大方,给人以美的享受。

 

譬如CU中的这一段关键代码,既滴水不漏地实现了功能,还十分简洁。

android crc 累加取反_Verilog_22