当前位置: 首页 > article >正文

简易CPU设计入门:本系统中的通用寄存器(一)

项目代码下载

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

下载本项目代码

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

本节前言

从本节开始,我们要逐渐地来接触代码执行中的逻辑了。代码执行逻辑,属于是控制中心的代码,或者是属于控制中心中的一个子系统。

控制中心系统,算是本系统的一个核心系统。它的代码量,在本系统中,是最大的。很长的一段时间里,我都在犯愁着,如何来讲解控制中心的逻辑。其实到现在,我也还在犯愁这件事。不过,也算是经历了很长时间的磨蹭,到了这会儿,也不得不去讲解着了。

从本节开始,我们要去学习的,是本系统中的通用寄存器的逻辑。

通用寄存器的读写,DRAM的读写,我认为,它应该算是一个CPU必须要实现的指令。我们在使用CPu进行运算的时候,必须要有存放数据的地方。而寄存器与内存,是存放数据的基本的场所。

在这里,我们先来学习寄存器读写的知识。

一.    寄存器元素模块:register_element

在我这里,实现寄存器的一个基本的模块,位于【......cpu_me01\code\Ctrl_Center\】下面的【register_element.v】代码文件中。

我们来看一看模块的声明部分。

d9ecf2a4fbf64405a6194e26b64940e9.png

图1

大家看到了吧?模块的名字,叫做【register_element】,它和代码文件的名字是一致的。从第3行到第9行,一共7行代码,是寄存器元素模块的信号声明的部分。

第三行和第四行,是系统时钟和复位信号。这俩信号,和我们之前所讲解的系统时钟与系统复位信号,是一样的。时钟信号,我们都是将其定为,频率为50MHz。而系统复位信号,则是说,低电平有效复位。高电平的时候,不进行复位操作。

第9行呢,是输出信号,data_reg。这个信号,它同时也是保存了某一个寄存器里面所存储的值。当我们向某一个通用寄存器写入一个值的时候,其实就是将值,写入某一个寄存器元素的【data_reg】变量里面。而读寄存器的操作,其实就是将某一个通用寄存器的【data_reg】变量里面的值,给读取出来。

二.    总线建模:使用 inout 数据类型

在这里呢,其实,比较有趣的,还是四个带有【inout】字样的信号。带有【inout】字样的信号,是用来干嘛的呢?

我本人的话,没咋阅读过别人的处理器设计代码。在使用【inout】类型的变量的时候,我也是凭借着自己的感觉,来使用的。

按照我的理解呢,【inout】类型的变量,它适合用作总线结构。

我们来设想一下,假定说,甲模块,它有一个输入变量,假定它的声明为【input wire _in_sig】。很显然的,这是一个1位的输入信号。然后呢,有三个模块,它们都需要输出一个信号,并且呢,这三个信号,都需要连接到甲模块的【_in_sig】信号上。

在这个时候,如果将三个模块的输出变量的类型,直接声明为【output】类型,并且呢,让这三个模块的输出变量直接驱动甲模块的【_in_sig】信号,那么,这就会出现,三个模块同时驱动甲模块的【_in_sig】的现象,会产生竞争。

在这个时候呢,我们就需要设定一个机制,让三个信号,并不同时驱动甲模块的【_in_sig】输入信号,但是呢,又都跟甲模块的【_in_sig】信号有联系。在这种情况下,我们就可以声明一个总线。

在这个总线上,三个输出信号的模块,假定,它们分别为1号,2号和3号模块。这三个模块,在任一时刻,最多可以有一个模块将值写入这个总线上面。然后呢,出现在总线上的值,可以驱动甲模块的【_in_sig】信号。

三个模块,1号,2号和3号模块,它们可以选择断开或连接到总线上。但是呢,任一时刻,最多仅可以有一个信号连接到总线上。如果1号模块连接到总线,2号与3号均断开与总线的连接,在这种情况下,1号模块的输出值,会出现在总线上,并且呢,1号模块的这个输出值,会驱动甲模块的【_in_sig】信号。

同理地,也可以是说,1号和3模块断开与总线的连接,2号连接到总线上。这个时候,2号模块的输出值出现在总线上,并且它会驱动甲模块的【_in_sig】信号。

同理地,也可以是说,1号和2号模块断开与总线的连接,3号模块连接到总线上。在这个时候,3号模块的输出值出现在总线上,并且驱动甲模块的【_in_sig】信号。

最后呢,也可以是说,1号,2号和3号模块均断开与总线的连接,此时总线处于高阻态。在这个时候,甲模块的【_in_sig】信号线上,没有接收到有效的驱动信号。

像这样地,如果我们需要多个驱动源,来驱动同一个模块信号,此时,为了避免多个驱动源的竞争,我们就可以使用总线结构。对总线的建模,在Verilog中,我们使用【inout】类型的变量。

当然了,仅有【inout】类型,是不足以避免冲突的。我们还需要有总线的协议。总线协议有很多种。I2C是一种,PCI-Express也是一种。

在我们的系统中,其实我这里没有建立什么总线协议,没有总线仲裁机制。我只是自己在代码中,控制着不同的驱动源对总线的使用。并且,在使用中,确保仅有一个驱动源的驱动信号出现在总线上。

目前,对我来讲,I2C总线,它还是一个庞然大物。PCI-Express,那就更是大得厉害了。

如果,你还没有专门地学习过总线知识,没有尝试过,自己去实现一个总线协议的话,那么,我这里的代码,算是能为你提供一个很简单的,使用总线的方法。当然了,非常地简单,简陋。

三.    三个内部信号总线

在图1中,第5行到第7行,它是声明了三个内部信号总线,都是16位的。它们是内部控制信号总线,内部数据信号总线,内部地址信号总线。

这里所说的内部信号总线,虽然它们也带有控制,地址,数据的字样。但是,它应该不属于我们在汇编语言与微机原理教程中所谈到的控制总线、地址总线和数据总线。

我这里用了应该,是因为,我自己也不了解通行的写CPU代码的写法。不知道我自己这里建立的几种内部信号总线,究竟是什么。反正呢,我自己就先这么用着了。

整个的这个项目,有一小部分东西,我是借鉴了流行的教材的写法。但是呢,大多数的东西,都是我自己想出来的。因为,流行的教材上面的代码,我看了一会儿功夫,就觉得看不懂了。所以呢,干脆就自己想,自己来设计一个。

关于第5行到第7行的三种内部信号总线的用法,在这本分节里面,我们先不讲,以后,我们再慢慢地来讲解它们。

四.    完成信号:work_ok_inner

接下来,我们来说第8行代码。它也是一个【inout】类型的信号,因而,它是使用了总线结构。

这个【work_ok_inner】信号,它是做什么用的呢?

在寄存器元素模块里面,当我们进行完了寄存器读写的工作以后,我们需要向控制中心发送一下完成信号,表示说,读写工作已经是完成了。这个完成信号信号,就用【work_ok_inner】信号来表示。

比如说,我们想要往寄存器里面写入一个值,当控制中心从寄存器读写模块里,或者,从我们的这个寄存器元素模块里面,收到了完成信号,那就表示,已经是将值写入目标寄存器里面了。然后呢,控制中心就可以去做其他的工作了。

如果呢,我们想要从寄存器里面读取它的数值,那么,当控制中心收到了完成信号的时候,控制中心就可以从某一个信号总线上接收寄存器元素传过来的值。那么,这个传递寄存器元素保存的数值的信号总线,其实正是内部数据信号总线,也就是我们在第7行声明的【data_sig_inner】信号。

而具体地,寄存器元素模块是如何将寄存器中的数据传递给内部数据信号总线【data_sig_inner】,进而传递给控制中心的,又是如何将完成信号【work_ok_inner】传递给控制中心的,这个,我们以后会慢慢地来讲解。此处,我们仅需要有一个大致的了解即可。

结束语

在本节,我们仅仅是讲了寄存器元素模块【register_element】中的信号声明部分。希望大家能够理解我在本节所讲的东西。

如何讲好控制中心的内容,对我来讲,这算是一个挑战。

我们都加油,争取搞好本项目代码的教学工作。

本节结束。

 


http://www.kler.cn/a/448924.html

相关文章:

  • SpringBoot 自动装配原理及源码解析
  • BERT模型入门(1)BERT的基本概念
  • 安装fast_bev环境
  • Android 代码模式的理解
  • CNN回归-卷积神经网络(Convolutional Neural Network)
  • 微服务——技术选型与框架
  • 刷题 两数之和
  • Aec-Library-Website 项目常见问题解决方案
  • laya游戏引擎中打包之后图片模糊
  • 【python高级】341-计算机网络基础 for Socket网络编程
  • VSCode:IDE显示设置 --自定义字体及主题颜色
  • 【JVM】如何有效调整JVM年轻代和老年代的大小
  • Java项目--仿RabbitMQ的消息队列--基于MQ的生产者消费者模型
  • elasticache备份
  • Debian 12.0 上为 Nginx 配置 SSL/TLS 证书
  • Vue:父页面调用子页面方法等待完成
  • Zabbix告警通知部署方案详解
  • ELM分类-单隐藏层前馈神经网络(Single Hidden Layer Feedforward Neural Network, SLFN)
  • 12寸半导体厂等保安全的设计思路
  • Transfomer的各层矩阵
  • Spring Boot开发编译后读取不到@spring.profiles.active@的问题
  • MySQL的分析查询语句
  • 网络刷卡器的功能和使用场景
  • 无人机森林草原播种施肥植物恢复技术详解
  • Wireshark(1)
  • 【Python使用】嘿马头条项目从到完整开发教程第9篇:缓存,1 缓存穿透【附代码文档】