简易CPU设计入门:取指令(一),端口列表与变量声明

news2024/11/16 1:44:34

取指令这一块呢,个人觉得,不太好讲。但是呢,不好讲,我也得讲啊。那就尽量地讲吧。如果讲得不好的话,那么,欢迎大家提出好的意见,帮助我改进讲课的质量。

首先呢,还是请大家去下载本专栏所需要用到的项目源代码。

点击下方链接,以学习下载项目源代码的方法。

下载本项目代码

然后呢,我们来看本节的内容。

我们本节和接下来的一些课节,应该都是去讲取指令的。取指令的部分,位于【\cpu_me01\code】路径里面的【get_instruct.v】代码文件中。

本节呢,我先把这一代码文件中的所有的代码,都给贴在下面的代码块中。大家先整体浏览一下就行。里面的内容呢,我会一点一点地去讲解的。

module get_instruct
(
	input wire sys_clk,
	input wire sys_rst_n,
	input wire get_inst_en,
	input wire [15:0] ip,
	
	output reg decode_en,
	output reg [15:0] instruct_code
);

reg [15:0] ip_buf;
wire [15:0] instruct_code_wire;

reg rd_en;
reg rd_en_d1;
reg rd_en_d2;

always @(posedge sys_clk or negedge sys_rst_n)
	if (sys_rst_n == 1'b0)
		ip_buf <= 16'h0;
	else if (get_inst_en == 1'b1)
		ip_buf <= ip;
	else
		ip_buf <= ip_buf;

always @(posedge sys_clk or negedge sys_rst_n)
	if (sys_rst_n == 1'b0)
		rd_en <= 1'b0;
	else if (get_inst_en == 1'b1)
		rd_en <= 1'b1;
	else
		rd_en <= 1'b0;

always @(posedge sys_clk or negedge sys_rst_n)
	if (sys_rst_n == 1'b0)
	begin
		rd_en_d1 <= 1'b0;
		rd_en_d2 <= 1'b0;
	end
	else
	begin
		rd_en_d1 <= rd_en;
		rd_en_d2 <= rd_en_d1;
	end

always @(posedge sys_clk or negedge sys_rst_n)
	if (sys_rst_n == 1'b0)
	begin
		decode_en <= 1'b0;
		instruct_code <= 16'h0;
	end
	else if (rd_en_d1 == 1'b1)
	begin
		decode_en <= 1'b1;
		instruct_code <= instruct_code_wire;
	end
	else
	begin
		decode_en <= 1'b0;
		instruct_code <= instruct_code;
	end

ram_disk_256x16	ram_disk_inst (
	.aclr ( ~sys_rst_n ),
	.address ( ip_buf ),
	.clock ( sys_clk ),
	.data ( 16'hz ),
	.rden ( rd_en ),
	.wren ( 1'b0 ),
	.q ( instruct_code_wire )
	);

endmodule

代码文件中的代码内容,我已经贴出来了。接下来呢,我就一点一点地来讲解了。

首先呢,我们来看看这个端口列表,以及变量的声明部分。

图1

代码的第1行写了模块的名字,其实就是和文件名一样的东西。只不过,文件名有那个扩展名【.v】,而这个模块名呢,没有扩展名的部分。在我们的这个项目中,所有的代码文件,都是只含有一个模块,且代码文件名与模块名相同。

我自己这么写,是学习的别人的做法。我也建议大家这么做。因为,这算是一种通用的写法,大家都这么做,约定俗成 。你要是也按照这个约定俗成的规范来写的话,会方便团队合作吧。

代码的3到6行,是输入端口,都是wire型的。当然了,输入端口,肯定不能是reg型。输出端口可以是reg类型的,输入端口的话,wire型比较常见。

在声明端口类型的时候,如果端口是wire类型的,那么,wire这个关键字,其实是可以省略的。也就是说,端口声明部分,你可以像下面的示例这样子来书写。

图2,端口声明示例,省略wire关键字的写法

请大家着重去看图2中的红色框线所示的部分,没有写wire这个关键字。这样子来写,它和加上wire关键字的写法,意思是一样的。

(一)对wire类型的复习

这个怎么说呢?在Verilog HDL里面,端口的类型,最常见的是两种,一种是reg型的,一种是wire型的。这两种类型最常见。在这两种最常见的类型里面呢,Verilog将端口的默认的类型,指定为wire型。所以呢,无论是输入端口,还是输出端口,还是输入输出端口,如果你既不写reg关键字,也不写wire关键字,默认地,它就相当于写上了wire关键字。

然后呢,对于输入端口和输入输出端口来讲,不可以用reg类型,而可以使用wire型。

在这里呢,我是领着大家复习了一下Verilog的基础语法。为啥领着大家复习呢?这是因为,Verilog这个硬件编程语言,其实是一个比较杂乱的东西。C语言的语法,比较简洁,也容易记住。但是Verilog不是。Verilog的语法,庞杂,乱的很。建议大家呢,还是多注意复习和整理Verilog的语法细节,时常温习。

(二)系统时钟与系统复位信号

我们来看第3行和第4行。这个呢,它就是系统时钟与系统复位信号。其中呢,系统复位信号,有一个【n】的部分,就是【sys_rst_n】中的末尾的【n】。这个n,就代表着说,它是低电平有效。也就是说,这个系统复位信号,它是在低电平的时候,才会进行复位。

关于系统时钟与系统复位信号,基本上呢,它都会是从顶层模块,就开始传下来。然后呢,在FPGA里面,大家 知道,FPGA开发板上,会有时钟引脚与复位引脚。所以呢,顶层模块的系统时钟与系统复位信号,来自于FPGA开发板上的时钟引脚和复位引脚,而其余的代码文件中的时钟与复位信号,则多是直接或者间接地,来自于顶层模块中的系统时钟与系统复位信号。

本代码文件中的时钟与复位信号,都是来自于顶层模块。

我们看一看顶层模块中的时钟与复位信号,是如何连接到本代码文件的。如下图所示。

图3,顶层模块的端口声明
图4,顶层模块与本文件模块的连接

图3与图4,都是位于顶层模块。顶层模块,位于【\cpu_me01\code】路径下的【cpu_top.v】文件中。图3的3行与4行,声明了时钟与 复位信号。然后呢,图4里面,第45行与第46行,通过命名端口连接的方式,将顶层模块的时钟与复位信号,连接到了本模块的时钟与复位信号。且信号名都是一样的。

(三)取指令使能与指令指针信号

我们还是回到图1。我这里说回到图1,对你来讲,可能有些不方便。建议你呢,可以把这个图1的图片给下载下来,随时对照着来看。这样子呢,能方便一些。回到图1,图1的第5行和第6行,则分别是取指令使能信号【get_inst_en】与指令指针信号【ip】。

这俩信号,也是通过顶层模块,来连接过来的。但是呢,它们其实并非来自顶层模块,它们的源头,其实是来自控制中心【ctrl_center】模块。

图4的47行与48行,显示了顶层模块有名为【get_inst_en】与【instruct_pointer】的变量,连接到了本模块的取指令使能信号【get_inst_en】与指令指针信号【ip】。我们再来看看顶层模块的如下的代码截图。

图5,位于顶层模块

图5里面的11行和12行,分别是声明了wire型变量【get_inst_en】与【instruct_pointer】。这俩变量,其中的一个用途,是连接本模块的两个输入信号。我们再来看看这俩信号在顶层模块中,连接控制中心【ctrl_center】模块的情况。如下图所示。

图6,位于顶层模块

从图6中的红色框线的部分,可以看到顶层模块的wire型变量【get_inst_en】和【instruct_pointer】与控制中心模块【ctrl_center】的连接情况。

控制中心中的取指令使能信号,是如何产生的,以及如何连接到顶层模块的,这个呢,我们之前有讲过。忘记了的,请前往下面的链接去复习回顾。

初始化完成后,准备取指令

在上面的链接里面,我讲了第一个取指令使能信号的产生情况。然而,我并未讲第一个指令指针是如何产生的。

想要取指令,需要取指令使能信号,以告诉取指令模块,要去取指令了。同时呢,也需要一个指令指针,也就是,得告诉取指令模块,要取的指令,位于哪个内存地址中。

我们还是前往控制中心模块,看一看指令指针的产生情况。

控制中心模块【ctrl_center】,位于【\cpu_me01\code\Ctrl_Center】路径下的【ctrl_center.v】里面。我们来看看下图的代码。

图7,位于控制中心模块
图8,位于控制中心模块

从图7与图8来看,控制中心中的27行与28行,声明了指令指针【ip】与取指令使能信号。在390行到409行之间,是更新【ip】的逻辑代码。

在这里呢,对于更新【ip】的逻辑,我们暂时只需要看390行到392行,和408行,409行。390行到392行,是说,在系统复位信号的作用下,【ip】清零。408行和409行是说,在【else】的条件里面,ip保持原值不变。

在这里呢,我们暂时并不涉及图8中的两个【else if】的情况。那俩情况呢,它都是CPU运行起来以后,执行某些指令的时候,所产生的情形。现在呢,CPU 还没有运行指令呢,所以不涉及这两个【else if】的情况。

在这种情况下,ip呢,在系统复位信号的作用下,已经归零。然后呢,就是归于【else】的条件,【ip】保持0值不变。

这样一来呢,【ip】这个信号,它本来是控制中心的第27行声明的一个输出端口。然后呢,经由390到392行,与408,409行代码的作用,保持0值。并且呢,它在第一个取指令使能产生后,它是把这个0值,传递到了顶层模块里面。

图6中的39行,显示了,控制中心的【ip】信号,传递给了顶层模块的【instruct_pointer】变量。然后呢,顶层模块的【instruct_pointer】变量,又在图4中的48行,传递给了本模块的【ip】变量。

这样一来呢,本模块的4个输入变量,我们就清楚了它们的来源,含义。我们也知道,取指令模块第一次运行,也就是第一次取指令的时候,指令指针【ip】的值,为0。

(四)剩余的端口与变量

我们还是去看一看图1。下面,我给出图1的副本。

图1——副本

接下来呢,我们来看一看第8行和第9行,它们是译码使能与取出来的指令码。

我们取出了指令以后,就把它放在第9行的变量中,从本模块传出去,传给译码模块。同时呢,也要将译码使能信号【decode_en】给传递出去。译码使能信号与第9行变量,应该是同时有效的。这个时序,必须要予以保证。

我们再来看一看第12行到第17行。

第12行,ip_buf变量,它是对输入信号【ip】的缓存。

第13行,【instruct_code_wire】,它用来连接取出的指令码,并将取出的指令码传递给第9行的输出信号。这个信号的设置,我觉得是很重要的。

第15行,是读使能信号。第16行,是将读使能信号延后一个时钟周期所产生的信号。第17行,是将读使能信号延后两个时钟周期所产生的信号。

结束语

关于取指令这一块,我估计,我需要花费好几节的时间,来讲解这一块。个人觉得,这一块,可能会不好讲。当前,我对于如何讲解这一部分的知识,思路还比较乱。

希望能够学好吧。我们都努力。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

面试官:Spring是如何解决循依赖问题?

Spring 的循环依赖一直都是 Spring 中一个很重要的话题&#xff0c;一方面是 Spring 为了解决循环依赖做了很多工作&#xff0c;另一个方面是因为它是面试 Spring 的常客&#xff0c;因为他要求你看过 Spring 的源码&#xff0c;如果没有看过 Spring 源码你基本上是回答不了这个…

pytorch的动态计算图机制

pytorch的动态计算图机制 一&#xff0c;动态计算图简介 Pytorch的计算图由节点和边组成&#xff0c;节点表示张量或者Function&#xff0c;边表示张量和Function之间的依赖关系。 Pytorch中的计算图是动态图。这里的动态主要有两重含义。 第一层含义是&#xff1a;计算图的…

“吉林一号”宽幅02B系列卫星

离轴四反光学成像系统 1.光学系统参数&#xff1a; 焦距&#xff1a;77.5mm&#xff1b; F/#&#xff1a;7.4&#xff1b; 视场&#xff1a;≥56゜&#xff1b; 光谱范围&#xff1a;400nm&#xff5e;1000nm。 2.说明&#xff1a; 光学系统采用离轴全反射式结构&#xff0c;整…

解密的军事卫星图像在各种民用地理空间研究中都有应用

一、美军光学侦察卫星计划概述 国家侦察局 &#xff08;NRO&#xff09; 负责开发和操作太空侦察系统&#xff0c;并为美国国家安全开展情报相关活动。NRO 开发了几代机密锁眼 &#xff08;KH&#xff09; 军事光学侦察卫星&#xff0c;这些卫星一直是美国国防部 &#xff08;D…

人工智能不是人工“制”能

文/孟永辉 如果你去过今年在上海举办的世界人工智能大会&#xff0c;就会知道当下的人工智能行业在中国是多么火爆。 的确&#xff0c;作为第四次工业革命的重要组成部分&#xff0c;人工智能愈发引起越来越多的重视。 不仅仅是在中国&#xff0c;当今世界的很多工业强国都在将…

python爬虫案例——异步加载网站数据抓取,post请求(6)

文章目录 前言1、任务目标2、抓取流程2.1 分析网页2.2 编写代码2.3 思路分析前言 本篇案例主要讲解异步加载网站如何分析网页接口,以及如何观察post请求URL的参数,网站数据并不难抓取,主要是将要抓取的数据接口分析清楚,才能根据需求编写想要的代码。 1、任务目标 目标网…

Win10 安装Node.js 以及 Vue项目的创建

一、Node.js和Vue介绍 1. Node.js Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。它允许你在服务器端运行 JavaScript&#xff0c;使得你能够使用 JavaScript 来编写后端代码。以下是 Node.js 的一些关键特点&#xff1a; 事件驱动和非阻塞 I/O&#xff1a;Node…

list(一)

list是可以在常数范围内在任意位置进行插入和删除的序列式容器&#xff0c;并且该容器可以前后双向迭代。list的底层是双向链表结构&#xff0c;双向链表中每个元素存储在互不相关的独立节点中&#xff0c;在节点中通过指针指向 其前一个元素和后一个元素。 支持 -- 但是不支持…

Linux:终端(terminal)与终端管理器(agetty)

终端的设备文件 打开/dev目录可以发现其中有许多字符设备文件&#xff0c;例如对于我的RedHat操作系统&#xff0c;拥有tty0到tty59&#xff0c;它们是操作系统提供的终端设备。对于tty1-tty12使用ctrlaltF*可以进行快捷切换&#xff0c;下面的命令可以进行通用切换。 sudo ch…

校园热捧的“人气新贵”,D 咖智能饮品机器人

在 2024 年的校园中&#xff0c;一股全新的潮流正在悄然兴起。D 咖智能饮品机器人以其独特的魅力&#xff0c;成功入驻多个校园&#xff0c;迅速成为学生们热烈追捧的对象&#xff0c;在长江大学、荆州职业技术学院、中医高专等多个大学校园&#xff0c;都能发现他们靓丽的身姿…

calibre-web报错:File type isn‘t allowed to be uploaded to this server

calibre-web报错&#xff1a;File type isnt allowed to be uploaded to this server 最新版的calibre-web在Upload时候会报错&#xff1a; File type isnt allowed to be uploaded to this server 解决方案&#xff1a; Admin - Basic Configuration - Security Settings 把…

投资学 01 定义,投资

02. 03. 3.1 直接投资&#xff1a;使用方和提供方是一个人

VUE3学习---【一】【从零开始的VUE学习】

目录​​​​​​​ 什么是Vue 渐进式框架 创建一个Vue应用 什么是Vue应用 使用Vue应用 根组件 挂载应用 模板语法 文本插值 原始HTML Attribute绑定 简写 同名简写 布尔型Attribute 动态绑定多个值 使用JavaScript表达式 仅支持表达式 指令 Directives 指令…

COLORmap

在这段MATLAB代码中&#xff0c;surf(peaks)、map的定义以及colormap(map)的调用共同完成了以下任务&#xff1a; 1. **绘制曲面图**&#xff1a; - surf(peaks)&#xff1a;这个函数调用了MATLAB内置的peaks函数来生成数据&#xff0c;并使用surf函数将这些数据绘制成一个…

双向链表:实现、操作与分析【算法 17】

双向链表&#xff1a;实现、操作与分析 引言 双向链表&#xff08;Doubly Linked List&#xff09;是链表数据结构的一种重要形式&#xff0c;它允许节点从两个方向进行遍历。与单向链表相比&#xff0c;双向链表中的每个节点不仅包含指向下一个节点的指针&#xff08;或引用&…

蓝桥杯嵌入式的学习总结

一. 前言 嵌入式竞赛实训平台(CT117E-M4) 是北京国信长天科技有限公司设计&#xff0c;生产的一款 “ 蓝桥杯全国软件与信息技术专业人才大赛-嵌入式设计与开发科目 “ 专用竞赛平台&#xff0c;平台以STM32G431RBT6为主控芯片&#xff0c;预留扩展板接口&#xff0c;可为用户提…

数据结构篇--顺序查找【详解】

概念章 查找就是在数据集合中寻找某种条件的数据元素的过程。 查找表是指用于查找同一类型的数据元素集合。 找到了满足条件的数据元素&#xff0c;就是查找成功&#xff0c;否则就是称为查找失败。 关键字是指数据元素的某个数据项的值&#xff0c;可用于标识或者记录&…

【Java】线程暂停比拼:wait() 和 sleep()的较量

欢迎浏览高耳机的博客 希望我们彼此都有更好的收获 感谢三连支持&#xff01; 在Java多线程编程中&#xff0c;合理地控制线程的执行是至关重要的。wait()和sleep()是两个常用的方法&#xff0c;它们都可以用来暂停线程的执行&#xff0c;但它们之间存在着显著的差异。本文将详…

【AI学习笔记】初学机器学习西瓜书概要记录(二)常用的机器学习方法篇

初学机器学习西瓜书的概要记录&#xff08;一&#xff09;机器学习基础知识篇(已完结) 初学机器学习西瓜书的概要记录&#xff08;二&#xff09;常用的机器学习方法篇(持续更新) 初学机器学习西瓜书的概要记录&#xff08;三&#xff09;进阶知识篇(待更) 文字公式撰写不易&am…

Django 基础之启动命令和基础配置

Django启动 django启动一般可以通过ide或者命令启动 ide启动&#xff1a; 启动命令&#xff1a; python manage.py runserver该命令后续可以增加参数&#xff0c;如&#xff1a; python manage.py runserver 8081 python manage.py runserver 127.0.0.1:8082 注意&#xff1…