实验五、单周期 CPU 设计与实现——十条指令 CPU

2024-01-29 19:40

本文主要是介绍实验五、单周期 CPU 设计与实现——十条指令 CPU,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

一、实验目的: 

通过设计并实现支持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位为指令的地址码或者立即寻址的操作数。

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

CPU 原理图 

四、实验步骤

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 关键代码:

2) 指令存储器模块 

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

输入 

12位指令地址 addr 

输出 

16 位指令 ins 

功能 

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

Verilog 关键代码:

3) 累加器

输入 

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

输出 

输出数据outdata

功能 

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

Verilog 关键代码:

4) ALU 

表4.4 ALU 模块功能描述 

输入 

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

输出 

 

ALU 运算结果 Z 

 

功能 

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

Verilog 关键代码:

5) 控制单元 

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

输入 

指令(操作码) 

输出 

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

功能 

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

Verilog 关键代码:

6) 数据存储器模块 

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

输入 

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

输出 

16 位输出数据 outdata 

功能 

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

Verilog 关键代码:

4.2 CPU 顶层文件封装实现 

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

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

Verilog 关键代码:

4.3 CPU 模拟仿真 

1、TestBench关键代码 

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

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

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

2、ModelSim仿真及分析 

指令1 LDA 取数指令

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

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

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

指令2 COM 取反指令

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

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

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

指令3 SHR 算数右移指令

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

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

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

指令4 CSL 循环左移指令

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

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

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

指令5 CLA 清除指令

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

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

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

指令6 ADD 加法指令

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

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

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

指令7 STA 存数指令

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

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

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

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

指令8 JMP 无条件转移指令

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

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

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

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

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

指令9 BAN 条件转移指令

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

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

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

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

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

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

指令10 STP 停机指令

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

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

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

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

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

五、总结

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

 

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

 

这篇关于实验五、单周期 CPU 设计与实现——十条指令 CPU的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/657974

相关文章

Oracle查询优化之高效实现仅查询前10条记录的方法与实践

《Oracle查询优化之高效实现仅查询前10条记录的方法与实践》:本文主要介绍Oracle查询优化之高效实现仅查询前10条记录的相关资料,包括使用ROWNUM、ROW_NUMBER()函数、FET... 目录1. 使用 ROWNUM 查询2. 使用 ROW_NUMBER() 函数3. 使用 FETCH FI

Python脚本实现自动删除C盘临时文件夹

《Python脚本实现自动删除C盘临时文件夹》在日常使用电脑的过程中,临时文件夹往往会积累大量的无用数据,占用宝贵的磁盘空间,下面我们就来看看Python如何通过脚本实现自动删除C盘临时文件夹吧... 目录一、准备工作二、python脚本编写三、脚本解析四、运行脚本五、案例演示六、注意事项七、总结在日常使用

Java实现Excel与HTML互转

《Java实现Excel与HTML互转》Excel是一种电子表格格式,而HTM则是一种用于创建网页的标记语言,虽然两者在用途上存在差异,但有时我们需要将数据从一种格式转换为另一种格式,下面我们就来看看... Excel是一种电子表格格式,广泛用于数据处理和分析,而HTM则是一种用于创建网页的标记语言。虽然两

Java中Springboot集成Kafka实现消息发送和接收功能

《Java中Springboot集成Kafka实现消息发送和接收功能》Kafka是一个高吞吐量的分布式发布-订阅消息系统,主要用于处理大规模数据流,它由生产者、消费者、主题、分区和代理等组件构成,Ka... 目录一、Kafka 简介二、Kafka 功能三、POM依赖四、配置文件五、生产者六、消费者一、Kaf

使用Python实现在Word中添加或删除超链接

《使用Python实现在Word中添加或删除超链接》在Word文档中,超链接是一种将文本或图像连接到其他文档、网页或同一文档中不同部分的功能,本文将为大家介绍一下Python如何实现在Word中添加或... 在Word文档中,超链接是一种将文本或图像连接到其他文档、网页或同一文档中不同部分的功能。通过添加超

windos server2022里的DFS配置的实现

《windosserver2022里的DFS配置的实现》DFS是WindowsServer操作系统提供的一种功能,用于在多台服务器上集中管理共享文件夹和文件的分布式存储解决方案,本文就来介绍一下wi... 目录什么是DFS?优势:应用场景:DFS配置步骤什么是DFS?DFS指的是分布式文件系统(Distr

NFS实现多服务器文件的共享的方法步骤

《NFS实现多服务器文件的共享的方法步骤》NFS允许网络中的计算机之间共享资源,客户端可以透明地读写远端NFS服务器上的文件,本文就来介绍一下NFS实现多服务器文件的共享的方法步骤,感兴趣的可以了解一... 目录一、简介二、部署1、准备1、服务端和客户端:安装nfs-utils2、服务端:创建共享目录3、服

C#使用yield关键字实现提升迭代性能与效率

《C#使用yield关键字实现提升迭代性能与效率》yield关键字在C#中简化了数据迭代的方式,实现了按需生成数据,自动维护迭代状态,本文主要来聊聊如何使用yield关键字实现提升迭代性能与效率,感兴... 目录前言传统迭代和yield迭代方式对比yield延迟加载按需获取数据yield break显式示迭

Python实现高效地读写大型文件

《Python实现高效地读写大型文件》Python如何读写的是大型文件,有没有什么方法来提高效率呢,这篇文章就来和大家聊聊如何在Python中高效地读写大型文件,需要的可以了解下... 目录一、逐行读取大型文件二、分块读取大型文件三、使用 mmap 模块进行内存映射文件操作(适用于大文件)四、使用 pand

python实现pdf转word和excel的示例代码

《python实现pdf转word和excel的示例代码》本文主要介绍了python实现pdf转word和excel的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价... 目录一、引言二、python编程1,PDF转Word2,PDF转Excel三、前端页面效果展示总结一