简易CPU设计入门:本系统所写入的指令

项目代码下载

请大家首先准备好本项目所用的源代码。如果已经下载了,那就不用重复下载了。如果还没有下载,那么,请大家点击下方链接,来了解下载本项目的CPU源代码的方法。

下载本项目代码

准备好了项目源代码以后,我们接着去讲解。

本节前言

在上一节,我提到,本节要来跟大家讲解,本系统里面,所执行的几条代码。

我的这个小系统,所写入的指令并不多,一共就6条有效指令。是什么指令呢?我们还是请看正式的内容讲解。

一.    打开内存初始化文件

首先呢,还是请大家打开Quartus II 13.1 软件。接下来,请大家跟我一起来操作。

第一步,依次点击选择【File】,【Open】菜单命令,打开【Open File】对话框,如下图所示。

图1
图2

我是将指令,写入了指令内存里面。具体地,是写入了本系统的一个RAM当中,这个RAM的名字是【ram_disk_256x16】,关于这个虚拟RAM,我们之前讲过它的生成方法的。忘记了的,可以参阅下方链接所示的文章。

调用IP核生成指令内存

然后呢,我这里所说的,将指令写入指令内存,不是说,将所要写的指令,直接写入虚拟RAM【ram_disk_256x16】里面,不是这个意思。而是说,将这个指令,写入一个内存初始化文件当中。

内存初始化文件,英文名字,应该叫做 Memory Initialization File。这个英文名词,它的首字母,是MIF,所以呢,内存初始化文件,它的后缀名,就是【.mif】。

所以呢,接下来,我们需要在系统中,寻找一个以【.mif】为后缀的内存初始化文件,这个文件里面保存了我们所写入的指令。我们接着往下操作。

第二步,修改文件过滤器中的文件类型。

首先呢,请大家在打开文件对话框中找到【文件类型】字样,它的右边,是一个组合框。如下图所示。

图3

本节的图2也有和图3类似的界面。只不过,在图2中,文件类型是【Memory Files】,而图3中的文件类型为【Design Files】。接下来,请大家点击图3中的【文件类型】右边的组合框中的下拉三角符号。

点击了下拉三角号以后,出现了一堆的文件类型列表,我们需要从文件类型列表中选择【Memory Files】选项,过程如下图所示。

图4
图5

请大家确保,自己选择后的结果里面,文件类型如图5中的红色框线所示。这一步好了以后,我们往下进行。

第三步,浏览到内存初始化文件,打开它。

关于这一步,首先呢,请大家在【Open File】对话框中,找到【cpu_me01】项目的总文件夹,然后呢,浏览到【\cpu_me01\ip_core\ram_disk_256x16】的位置,里面有一个名为【ram_disk.mif】的内存初始化文件,过程如下图所示。

图6
图7

点击选择图7的红色框线所示的文件,然后点击右下方的【打开】按钮,结果如下图所示。

图8
图9

经过这么几步的操作,我们已经是打开了内存初始化文件,接下来,我来讲解一下图9所示的,内存初始化文件的显示格式。

二.    内存初始化文件的显示格式——行列标签

在图9中,是一个显示的表格。在大家自己的软件界面的右边,还有一个垂直滚动条。当然了,在图8和图9的截图中,这个滚动条部分,我是没有截取的。在大家自己的软件中,是可以看到这个滚动条的。

这个表格,它有行和列。

请大家来看一看表格的标题行,如下图所示。

图10

图10所示的红色框线的部分,就是标题行了。

在这个标题行中,首列是【Addr】字样,再往右是【+0】,【+1】,【+2】等等的字样,一直排到【+7】,最右边是【ASCII】字样。

在这个,这个【+xxx】中的x,我们可以将其看作是一个偏移地址。【+3】的话,偏移地址为3。【+6】的话,偏移地址为6。

我们再来看标题列,如下图所示。

图11

在图11中,红色框线所示的列,就是标题栏。我的红色框线,仅仅是画出了标题列中的一部分。因为,我们所生成的虚拟RAM的尺寸是【256 x 16】的,也就是,有256个存储单元,每一个单元是16比特的。这样一来,列数太多了,所以,屏幕上显示不完,大家需要借助于软件界面的垂直滚动条,将界面往下拉,才可以看到最下面的一列的。

在这个标题列中,最上方,也是【Addr】字样,而再往下,是8的整数倍的各个整数了。从上往下,依次是【0】,【8】,【16】等等。这里的【0】,【8】,【16】等等的行标签,我们可以将它们看作是一个基地址。

然后呢,在图9所示的整个显示表格里面,我们可以点击选中一个单元格,如下图所示。

图12

在这个图12里面,我点击的这个单元格,它是被蓝色高亮显示了。然后呢,我还用红色框线,标注了它所在的行和列。它的列标签,为【+3】。行标签,为【48】。那么,这个单元的地址,就是行标签所示的基地址48,加上列标签所示的偏移地址【+3】,为51。所以,我点击的这个单元格,它的内存地址,为51。

任何一个你所点击的单元格,都可以表示为【以8的整数倍数的整数所表示的基地址】再加上一个【大于等于0且小于等于7】的偏移地址的形式。然后呢,这个单元格,它的内存地址,就是基地址加偏移地址。

比如说,地址23,为基地址【16】 + 偏移地址【7】。地址99,为基地址【96】+ 偏移地址【3】。所以呢,地址23的行标签为【16】,列标签,为【+7】。地址99的行标签,为【96】,列标签,为【+3】。

三.    本系统所写入的指令

行列标签我讲完了,接下来,我来讲一讲本系统所写入的指令码,或者说是机器码。

我只往系统里写入了6条指令。这四条指令,依次位于0,1,2,3,四个内存地址之中。也就是,它们都位于行标签【0】所在的行,而列标签,分别为【+0】,【+1】,【+2】,【+3】,【+4】,【+5】。我们来看一看这6条指令。

图13

如图13所示,它们分别是2007,3001,2010,1001,2030,3801。

这几条指令,不是十进制数,而是十六进制的整数。这是因为,你打开一个内存初始化文件,它默认显示的数,就是十六进制的。可以将其修改为十进制等等的其他格式的数,但是,在这里,我们先保持着十六进制的默认显示数制。至于如何修改显示数制,我们后面再讲。

接下来,我们来讲一讲,这几条指令的含义。

想要讲解这几条指令的格式,我们就得是结合着本系统的指令码的格式,还有本系统的指令编码表。

本系统指令表

然后呢,之前,我在讲解译码模块的时候,谈到了本系统的指令码的格式。

在本系统里面,每一条指令,固定地,为16 bit。其中,高5位,也就是 位15到位11,为操作码。位10到位8,固定地,为保留字000,。低8位,也就是位7到位0,是操作数。

有了这样的信息,我们来逐个地分析本系统的6条指令码的内容。

第1条指令,2007(十六进制)

第一个,0x2007,它的低8位的值是7,高8位的值是0x20,我们将0x20展开为2进制,为0B 0010 0000。在这8个二进制位里面,低3位,对应着完整的一个指令码中的位10到位8,固定地,为000。这8个二进制位的高5位,对应着一个完整的指令码的位15到位11,为操作码。在这里呢,0x20的高5位的二进制码为0B 00100,这个0B 00100,它就和指令编码表中的格式4的一行对应上了。

格式4,它的功能是,将操作数n视为一个立即数,将其存入累加器da的低8位,并将其扩充为一个16 bit的整数。

这样一来,第一条指令 0x2007,它的含义是,将立即数7送入累加器da中。

第2条指令,3001(十六进制)

第2个,0x3001,它的低8位为1,高8位为0x30,转换为2进制码,为 0B 0011 0000,这8个二进制位,高5位为 0B 00110,低3位为000。这8位的低3位对应着完整的一条指令的位10到位8,是保留位,固定地,为 0B 000。而这8位中的高5位,为0B 00110,它对应着格式6。

格式6的功能,将累加器da中的内容,送入DRAM的地址r的位置。r的值,就是操作数所指定的值。

在这里,0x3001,它的意思是,将累加器da里面的数,送入DRAM地址1的位置。为啥地址为1?因为在0x3001中,低8位为1,而低8位是操作数,所以,结合着格式6的功能,我们说,0x3001,是将累加器da的内容送入DRAM地址1,而不是送入地址3。

第3条指令,2010(十六进制)

第3条指令,0x2010,它的低8位为0x10,高8位为0x20。我们将高8位转换为二进制,为0B 0010 0000,也就是,高8位里面的高5位,为0B 00100,它对应着完整的一个指令码的位15到位11,为操作码。这个0B 00100,对应着格式4。高8位中的低3位,对应着保留位,固定为0B 000。

格式4的功能,我们在第一条指令中讲过了,它是将操作数送入累加器da的低8位,并扩充为16 bit。

这样一来,0x2010,它的含义是,将立即数0x10,也就是十进制的16,送入累加器da的低8位,并扩充为16进制数。

所谓的,【将一个8位的操作数送入一个累加器的低8位,并扩充为16 bit】。它的意思是,将累加器的高位固定为0值,而将8位操作数送到累加器的低8位。

第4条指令,1001(十六进制)

第4条指令,为0x1001,它的低8位是1,高8位位为0x10。

我们将高8位转换为二进制数,为0B 0001 0000。在这8位中,低3位是保留位。高5位,对应着一条完整的指令码中的操作码部分,为0B 00010,它对应着格式2。

格式2的含义,将dram的r单元的数与累加器da相加,结果放在da中。在这里,这个DRAM的R单元,这个R,由操作数来指定。

这样的话,0x1001,它的意思是,将内存地址1中的数,和累加器中的数相加,结果存放在累加器da中。

在这里呢,我们来试着执行一下以上的指令。

第一条指令 0x2007,它的含义是,将立即数7送入累加器da中。第一条指令执行完以后,累加器da中存放的数,为整数7。

第二条指令0x3001,它的意思是,将累加器da里面的数,送入DRAM地址1的位置。第二条指令执行完了以后,累加器da中的数,也就是整数7,就被送到了内存地址1里面。此时,内存地址1中的数,就是整数7了。

第三条指令0x2010,它的含义是,将立即数0x10,也就是十进制的16,送入累加器da的低8位,并扩充为16进制数。第三条指令执行完了以后,累加器da中的内容,变为了整数0x10,或者说是十进制的16。

第四条指令,也就是本条指令0x1001,它的意思是,将内存地址1中的数,和累加器中的数相加,结果存放在累加器da中。在第四条指令开始执行之前,累加器中的数为十进制的16。内存地址1中的,为7,将16和7相加,结果为23,也就是十六进制的0x17。所以呢,本条指令执行完了以后,累加器da中的数,就变为0x17了。而内存地址1中,依旧是整数7。

第5条指令,2030(十六进制)

第5条指令,0x2030,它的低8位是0x30,也就是十进制的48。它的高8位为0x20。高8位为0x20的情况,我们在第3条指令和第1条指令中都已经分析过了,它是格式4。

格式4的功能,将操作数n视为一个立即数,将其存入累加器da的低8位,并将其扩充为一个16 bit的整数。

所以呢,0x2030,这条指令的含义,是将立即数0x30送入累加器的低8位,并扩充为一个16比特的整数。

本条指令执行以前,我们面临的环境,是第4条指令的执行结果。第4条指令的结果是,累加器da中的内容为0x17,内存地址1中的内容为7。

本条指令执行了以后,累加器的内容变为0x30,内存地址1中的内容,依旧是整数7。

第6条指令,3801(十六进制)

第6条指令,它的低8位为1,也就是,操作数为1。本条指令的高8位为0x38。

我们将高8位转换为二进制,为0B 0011 1000。在这8位里面,低3位是保留位,高5位对应着完整的一条指令中的位15到位11,为操作码,为0B 00111,它对应着格式7。

格式7的功能,dram的r单元与累加器da相减,结果放在累加器da。注意哈,在这里,其实是累加器中的数减去DRAM中的数,而不是内存中的数减去累加器中的数。这个,是我没有说明白。

本条指令执行以前,我们的执行环境为第5条指令的结果。

第5条指令的结果为,累加器的内容为0x30,内存地址1中的内容是整数7。

本条指令执行时,累加器中的内容0x30减去内存地址1中的整数7,也就是十进制的48减去7,结果为41。41的十六进制形式为0x29。

结束语

本节,算是讲完了。

有一段时间,我是没有去写作本专栏了。在搁置本专栏的期间里,我主要是在忙着学习MFC去了。

由于我所学习的MFC教材的页数比较多,并且,学习它所需要的思考力度比较大,所以,我没有脱开身来写作本专栏。当前,我已经在CSDN里面开设了MFC专栏。

MFC,就是微软基础类库,英文名称为 Microsoft Foundation Class Library。它是用微软的类库来编写图形界面程序的一种,面向对象的编程。难度比较高,学习它,耗费了我相当的精力,比较累吧。

大家若是有兴趣,也欢迎前往我的MFC专栏,去学习关于MFC的知识。

当前,预计,我应该会在一段时间以后,才来开始连续地讲解着MFC的知识。在连续地讲解着MFC的知识之前,我是打算着,先将本专栏的内容给讲完吧。本专栏讲完了以后,我打算再去讲解着MFC的知识。

本节里面,我是讲解了本系统中写入的6条指令码。这6条指令,是可以在仿真软件MultiSim中观察执行情况的。

本节,我就先不去领着大家一起观察仿真结果了,因为写文章写得有些累了。到了这里,如果你之前认真地学习了本专栏的内容,并且,你自己知道如何在Quartus II中切换顶层设计模块,也知道如何切换Simulation的Test Bench模块,那么,你可以自己去观测本节所讲的内容执行情况。

本节所述的6条指令的执行情况,我会在下一节中,来领着大家一起在仿真软件MultiSim中观测仿真执行情况。

祝大家学习愉快

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/936621.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

rabbitMq举例

新来个技术总监,把 RabbitMQ 讲的那叫一个透彻,佩服! 生产者 代码举例 public String sendMsg(final String exchangeName,final String routingKey,final String msg) {} /*** 发送消息* param exchangeName exchangeName* param routin…

对话小系统(智能图书助手)

对话小系统(智能图书助手) 文章说明核心代码效果展示源码下载 文章说明 现在GPT的功能十分强大,是否可以利用开源的接口来实现自己的智能小助手呢,我想到可以提供一些能力接口,然后对问询内容进行意图识别,…

数智读书笔记系列006 协同进化:人类与机器融合的未来

书名:协同进化:人类与机器融合的未来 作者:[美]爱德华阿什福德李 译者:李杨 出版时间:2022-06-01 ISBN:9787521741476 中信出版集团制作发行 爱德华・阿什福德・李(Edward Ashford Lee)是一位在计算机科学与工程领域颇具影响力的学者&am…

C# 探险之旅:第二十七节 - 类型class(属性) —— 给你的类穿上“属性”的外衣

嘿,探险家们!欢迎再次踏上我们的C#奇幻之旅。今天,我们要聊聊一个超级有趣的话题——类的“属性”。想象一下,如果我们要给类穿上一件酷炫的外衣,那属性就是这件外衣上的各种口袋和装饰,让类变得既实用又拉…

数据保护策略:如何保障重要信息的安全

一、什么是数据安全? 数据安全是保护数字信息免遭盗窃、未经授权的访问和恶意修改的过程。这是一个持续的过程,负责监督信息的收集、存储和传输。 机密性:保护数据免遭未授权方访问。 完整性:保护数据免遭未经授权的修改、损坏…

Mvc、Springmvc框架

一.Mvc: 1.概念: MVC它是一种设计理念。把程序按照指定的结构来划分: Model模型 、View视图 、Controller控制层; 结构图: 二.Springmvc: 1.概念: springmvc框架它是spring框架的一个分支。它是按照mvc架构思想设计…

【CSS in Depth 2 精译_078】12.6 调整字间距,提升可读性 + 12.7 本章小结

当前内容所在位置(可进入专栏查看其他译好的章节内容) 第四部分 视觉增强技术 ✔️【第 12 章 CSS 排版与间距】 ✔️ 12.1 间距设置 12.1.1 使用 em 还是 px12.1.2 对行高的深入思考12.1.3 行内元素的间距设置 12.2 Web 字体12.3 谷歌字体12.4 font-fac…

Python高性能web框架-FastApi教程:(2)路径操作装饰器方法

路径操作装饰器方法 1. fastapi支持的各种请求方式 app.get() app.post() app.put() app.patch() app.delete() app.options() app.head() app.trace()2. 定义不同请求方式的路由 # 定义GET请求的路由 app.get(/get) def get_test():return {method: get方法} app.get(/get)…

PostgreSQL 入门

下载与安装 部分国产数据库采用PostgreSQL作为基础进行研发,因此先尝试了解一下原始数据库情况。 PostgreSQL 简称 PG 官网:https://www.postgresql.org/ PostgreSQL “世界上最先进的开源关系型数据库” 这是官网上的口号。 PostgreSQL: The World…

Java-26 深入浅出 Spring - 实现简易Ioc-02 无IoC与AOP场景下实现业务

点一下关注吧!!!非常感谢!!持续更新!!! 大数据篇正在更新!https://blog.csdn.net/w776341482/category_12713819.html 目前已经更新到了: MyBatis&#xff…

工作流审批功能全解析:提升流程效率的关键要素

1. 引言 在当今数字化时代,企业与组织的运营效率在很大程度上依赖于高效、精准的工作流审批系统。随着业务日益复杂且多样化,审批流程变得愈加细致和灵活。一个完善的工作流审批系统不仅能确保任务在组织内部有序流转、协调各方资源,还能实现…

API接口示例:电商商品评论数据

当然,以下是一个简化的电商商品评论数据API接口的示例。请注意,这只是一个示例,实际的API接口可能会更加复杂,并且会包含更多的验证、错误处理和安全措施。 API接口示例:电商商品评论数据 基础信息 API名称&#xf…

HCIA-Access V2.5_2_2_2网络通信基础_IP编址与路由

网络层数据封装 首先IP地址封装在网络层,它用于标识一台网络设备,其中IP地址分为两个部分,网络地址和主机地址,通过我们采用点分十进制的形式进行表示。 IP地址分类 对IP地址而言,它细分为五类,A,B,C,D,E,…

Microsemi Libero使用技巧11——CoreUARTAPB RX管脚分配时不显示

调用串口IP核CoreUARTAPB,并例化到顶层设计,发现UART_RX管脚在进行管脚分配时没有显示出来,最后发现是CoreAPB3总线IP核配置不对导致,改为如下配置后正常。

SEGGER | 基于STM32F405 + Keil - RTT组件01 - 移植SEGGER RTT

导言 RTT(Real Time Transfer)是一种用于嵌入式中与用户进行交互的技术,它结合了SWO和半主机的优点,具有极高的性能。 使用RTT可以从MCU非常快速输出调试信息和数据,且不影响MCU实时性。这个功能可以用于很多支持J-Link的设备和MCU&#xff0…

SpringBoot集成JWT和Redis实现鉴权登录功能

目前市面上有许多鉴权框架,鉴权原理大同小异,本文简单介绍下利用JWT和Redis实现鉴权功能,算是抛砖引玉吧。 主要原理就是“令牌主动失效机制”,主要包括以下4个步骤: (1)利用拦截器LoginInterceptor实现所有接口登录拦…

29.在Vue 3中使用OpenLayers读取WKB数据并显示图形

在Web开发中,地理信息系统(GIS)应用越来越重要,尤其是在地图展示和空间数据分析的场景中。OpenLayers作为一个强大的开源JavaScript库,为开发者提供了丰富的地图展示和空间数据处理能力。在本篇文章中,我将…

【bWAPP】 HTML Injection (HTML注入)

我们都是在一条铺满荆棘的新路上摸索着前行,碰个鼻青眼肿几乎不可避免,而问题在于,我们能不能在这条路上跌倒之后,爬起来继续走下去。 HTML Injection - Reflected (GET) get方式的html代码注入 漏洞url:http://ran…

内网是如何访问到互联网的(华为源NAT)

私网地址如何能够访问到公网的? 在上一篇中,我们用任意一个内网的终端都能访问到百度的服务器,但是这是我们在互联网设备上面做了回程路由才实现的,在实际中,之前也说过运营商是不会写任何路由过来的,那对于…

tomcat的优化和动静分离

tomcat的优化 1.tomcat的配置优化 2.操作系统的内核优化 注意:设置保存后,需要重新ssh连接才会看到配置更改的变化 vim /etc/security/limits.conf # 65535 为Linux系统最大打开文件数 * soft nproc 65535 * hard nproc 65535 * soft nofile 65535 *…