简易CPU设计入门:取指令(三),ip_buf与rd_en的非阻塞赋值

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

下载本项目代码

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

在之前的章节里,我是讲解了,使用Quartus II 13.1的IP核生成的功能,来生成RAM IP核。讲完了这个以后,我们在这一节,接着来讲解取指令模块。

我还是将取指令模块的代码给整体地贴在下面。

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

上述代码块,位于【\cpu_me01\code\get_instruct.v】里面。

一.   ip_buf的非阻塞赋值

我们来看看关于ip_buf的非阻塞赋值代码块。

图1

由图1可以看到,ip_buf在复位时,它为0值。检测到输入信号中的【get_inst_en】为高电平以后,ip_buf非阻塞赋值为输入信号【ip】的值。此后,ip_buf保持此值不变。

在这里,取指令使能信号【get_inst_en】,它是来自于控制中心模块【ctrl_center】的。每次准备取指令时,【get_inst_en】才会变为1,且仅仅维持一个时钟周期的高电平。其余的时间里,它为0值。

这样一来,图1中的【ip_buf】,它是说,每检测到一次【get_inst_en】为高电平,就缓存一次【ip】的值,然后在【get_inst_en】为低电平期间,【ip_buf】保持不变。下一次检测到一次【get_inst_en】为高电平的时候,就缓存新的【ip】的值。逻辑不难。

二.   rd_en的非阻塞赋值

图2

从图2来看,读使能变量【rd_en】,它在系统复位时,为0值。当检测到控制中心传来的取指令使能信号【get_inst_en】变为高电平的时候,读使能信号【rd_en】变为1。其余时间,【rd_en】为0。

取指令使能我们讲了,它是由控制中心模块传来的,且仅仅维持一个时钟周期的高电平,其余时间为0值。而【rd_en】其实也是一样的。【rd_en】的逻辑,仅仅在检测到【get_inst_en】为1时,【rd_en】才为1,其余时候,【rd_en】为0。而【get_inst_en】仅仅维持一个时钟周期,所以,【rd_en】的高电平也是仅仅维持一个时钟周期。

注意,【ip_buf】与【rd_en】都是本地变量,如下图所示。

图3

图3中的第12行和第15行,可以表明,【ip_buf】与【rd_en】均为本地变量。

三.   延时信号【rd_en_d1】与【rd_en_d2】

在图3中,我们可以看到两个延时信号【rd_en_d1】与【rd_en_d2】。所谓的延时,是对【rd_en】信号进行延时。在这里,虽说我声明了两个延时信号,但是,实际用到的,只有【rd_en_d1】而已。之所以要多申请一个,是因为,我担心一个延时信号不够用。

生活中,好多事情我也是这样的。因为总担心东西会不够用,所以我倾向于多准备一些。对于擅长精打细算的人来讲,我这种做法,可能会显得有些不好理解。

我们还是来看一看代码。

图4

我先来说一说代码的执行效果。效果就是,【rd_en_d1】相比【rd_en】延后了1个时钟周期,【rd_en_d2】又比【rd_en_d1】延后了1个时钟周期。

接下来,我又会用文字说明的方法,来演示这种代码执行过程了。请大家先将图4给保存好,以随时对照着我的文字讲解。

我们知道,【rd_en】变为1,是由于非阻塞赋值。那么,它肯定是在某一个时钟上升沿到来后,在非阻塞赋值的第2阶段变为1的。

那么,我们先将初始条件设置为,时钟周期处于【rd_en】变为1的之前的一个时钟周期。

【初始条件】假定某一个时钟上升沿到来时,rd_en == 0,且本周期里面 rd_en 不会变为1。我们将这个时钟上升沿,定义为0号上升沿。此时,rd_en_d1与rd_en_d2的值均为0。

在0号时钟上升沿到来后的非阻塞赋值第1阶段,计算非阻塞赋值的右侧表达式的值。这个时候,表达式【rd_en_d1 <=  rd_en】与表达式【rd_en_d2 <= rd_en_d1】的右侧表达式分别为【rd_en】与【rd_en_d1】,它们都为0。

在0号时钟上升沿到来后的非阻塞赋值第2阶段,将右侧表达式的值赋予左侧的变量。这样一来,在这个阶段里,rd_en_d1与rd_en_d2的值均被赋值为0,与0号时钟上升沿到来时的值是一样的。

【1号时钟上升沿到来】此时rd_en为0,且假定本上升沿到来后的非阻塞赋值第2阶段里,rd_en被非阻塞赋值为1。此时,rd_en_d1与rd_en_d2的值依然为0。

在1号上升沿到来后的非阻塞赋值第1阶段,计算非阻塞赋值的右侧表达式的值。此时,右侧表达式【rd_en】与【rd_en_d1】的值均为0。

在1号时钟上升沿到来后的非阻塞赋值第2阶段,将右侧表达式的值赋予左侧的变量。这样一来,在这个阶段里,rd_en_d1与rd_en_d2的值均被赋值为0,与1号时钟上升沿到来时的值是一样的。

【2号时钟上升沿到来】此时rd_en为1,且本上升沿到来后的非阻塞赋值第2阶段里,rd_en被非阻塞赋值为0。此时,rd_en_d1 == 0,rd_en_d2 == 0。

在2号上升沿到来后的非阻塞赋值第1阶段,计算非阻塞赋值的右侧表达式的值。此时,右侧表达式【rd_en】的值为1,右测表达式【rd_en_d1】的值为0。

在2号上升沿到来后的非阻塞赋值第2阶段,将右侧表达式的值赋予左侧的变量。这样一来,rd_en_d1被赋值为1,rd_en_d2被赋值为0。也就是,rd_en_d1变为1,而rd_en_d2不变。

【3号时钟上升沿到来】此时,rd_en == 0,rd_en_d1 == 1, rd_en_d2 == 0。

在3号上升沿到来后的非阻塞赋值第1阶段,计算非阻塞赋值的右侧表达式的值。此时,右侧表达式【rd_en】的值为0,【rd_en_d1】的值为1。

在3号上升沿到来后的非阻塞赋值第2阶段,将右侧表达式的值赋予左侧的变量。这样一来,rd_en_d1被赋值为0,rd_en_d2被赋值为1。

【4号时钟上升沿到来】此时,rd_en == 0,rd_en_d1 == 0, rd_en_d2 == 1。

在4号上升沿到来后的非阻塞赋值第1阶段,计算非阻塞赋值的右侧表达式的值。此时,右侧表达式

【rd_en】的值为0,【rd_en_d1】的值为0。

在4号上升沿到来后的非阻塞赋值第2阶段,将右侧表达式的值赋予左侧的变量。这样一来,rd_en_d1被赋值为0,rd_en_d2被赋值为0。

我们将上面的几个文字说明的信息摘录一下,我们将【rd_en】,【rd_en_d1】与【rd_en_d2】变为1的时机给摘录下来。

在1号时钟上升沿到来后,在非阻塞赋值的第2阶段,rd_en被非阻塞赋值为1。

在2号时钟上升沿到来后,在非阻塞赋值的第2阶段,rd_en_d1被非阻塞赋值为1。

在3号时钟上升沿到来后,在非阻塞赋值的第2阶段,rd_en_d2被非阻塞赋值为1。

所以呢,rd_en,rd_en_d1,rd_en_d2,它们分别是右边的信号比左边的信号延后一个时钟周期变为1。

四.   延时例题

本文第三节主要是为了向大家讲述延时逻辑。那个具体的文字表述不是重点,重点时,再次出现延时逻辑,你得是能够明白。

下面,我给大家来一个例题。

图5

如果第3节的知识,大家看懂了,那么,图5中的代码,其实是不难的。

图5中的代码,依然是一个延时逻辑。

signal,signal_d1,signal_d2,signal_d3,signal_d4,signal_d5,signal_d6,这几个信号,分别是右边的信号比左边的信号延后一个时钟周期。

延时逻辑,大家明白了没?

结束语

在本节,我又水了一节。

延时逻辑,也算是一个有趣的硬件代码逻辑。希望大家能学会。

本节里面,我没有采用表格的方法来解读代码逻辑,而是采用了文字说明的方法。其实两种方法只是不同的方法而已。你可以选择一种方法,来研究你所关注的问题。

表格的话,其实我还是比较推荐大家去使用它。图表,应该算是现代社会里,我们经常需要去观察和分析的材料吧。

会计里面有资产负债表,炒股的人也需要去看股票价格的走势图。信息时代,图表思维,大概也是我们需要去训练的一种思维了。

本节结束。

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

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

相关文章

【重学 MySQL】五十一、更新和删除数据

【重学 MySQL】五十一、更新和删除数据 更新数据删除数据注意事项 在MySQL中&#xff0c;更新和删除数据是数据库管理的基本操作。 更新数据 为了更新&#xff08;修改&#xff09;表中的数据&#xff0c;可使用UPDATE语句。UPDATE语句的基本语法如下&#xff1a; UPDATE ta…

【ADC】噪声(1)噪声分类

概述 本文学习于TI 高精度实验室课程&#xff0c;总结 ADC 的噪声分类&#xff0c;并简要介绍量化噪声和热噪声。 文章目录 概述一、ADC 中的噪声类型二、量化噪声三、热噪声四、量化噪声与热噪声对比 一、ADC 中的噪声类型 ADC 固有噪声由两部分组成&#xff1a;第一部分是量…

【重学 MySQL】四十六、创建表的方式

【重学 MySQL】四十六、创建表的方式 使用CREATE TABLE语句创建表使用CREATE TABLE LIKE语句创建表使用CREATE TABLE AS SELECT语句创建表使用CREATE TABLE SELECT语句创建表并从另一个表中选取数据&#xff08;与CREATE TABLE AS SELECT类似&#xff09;使用CREATE TEMPORARY …

【JVM】垃圾释放方式:标记-清除、复制算法、标记-整理、分代回收

文章目录 1. 标记-清除2. 复制算法4. 标记-整理4. 分代回收 把标记为垃圾的对象的内存空间进行释放。主要有三种释放方式 1. 标记-清除 把标记为垃圾的对象&#xff0c;直接释放掉&#xff08;最朴素的做法&#xff09; 此时就是把标记为垃圾的对象所对应的内存空间直接释放。…

本地化测试对游戏漏洞修复的影响

本地化测试在游戏开发的质量保证过程中起着至关重要的作用&#xff0c;尤其是在修复bug方面。当游戏为全球市场做准备时&#xff0c;它们通常会被翻译和改编成各种语言和文化背景。这种本地化带来了新的挑战&#xff0c;例如潜在的语言错误、文化误解&#xff0c;甚至是不同地区…

k8s中,ingress的实现原理,及其架构。

图片来源&#xff1a;自己画的 图片来源&#xff1a;k8s官网 首先&#xff0c;什么是ingress? 是服务还是控制器&#xff1f; 都不精确 ingress是一个api资源 service和deployment也是api资源。 这几个相互协作&#xff0c;组建成一个对外提供服务的架构。 ingress提供的…

MDM监管锁系统上锁流程

上锁与解锁 上锁设备 完整的上锁流程可参考: https://b23.tv/UvM35sU 上锁需要已经注册了一个普通用户 并使用管理员分配了台数 且有可用的MDM证书和ABM证书(公有和私有的都可以 只要有可用的就可以) 一部用来上锁的手机 链接wifi wifi必须要是2.4g频段 不要使用5gwifi 上锁…

HTTPS协议详解:从原理到流程,全面解析安全传输的奥秘

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storm…

(done) 声音信号处理基础知识(11) (Complex Numbers for Audio Signal Processing)

参考&#xff1a;https://www.youtube.com/watch?vDgF4m0AWCgA&t1047s 似乎是因为信号处理需要使用复数&#xff0c;作者花了一节课介绍复数 据油管主所说&#xff0c;声学信号处理中引入复数的原因是&#xff1a;快速完成部分计算 这里的例子是&#xff0c;当我们做傅里…

行为型模式-命令-迭代-观察者-策略

命令模式 是什么 将一个请求封装成为一个对象, 从而可以使用不同的请求对客户进行参数化,对请求排队或记录请求日志,以及可以撤销的操作 实例 请求封装成为对象 //用来声明执行操作的接口 public abstract class Command { protected Receiver receiver; public Comma…

物联网智能项目全面解析

目录 引言 一、物联网概述 1.1 什么是物联网 1.2 物联网的历史与发展 二、物联网智能项目分类 三、关键组件与技术 3.1 传感器和执行器 3.2 连接技术 3.3 数据处理与分析 3.4 用户界面 四、物联网智能项目案例分析 4.1 智能家居 4.2 智慧城市 4.3 工业物联网 4.4…

react-问卷星项目(3)

项目实战 React Hooks 缓存&#xff0c;性能优化&#xff0c;提升时间效率&#xff0c;但是不要为了技术而优化&#xff0c;应该是为了业务而进行优化 内置Hooks保证基础功能&#xff0c;灵活配合实现业务功能&#xff0c;抽离公共部分&#xff0c;自定义Hooks或者第三方&am…

【Kubernetes】常见面试题汇总(五十四)

目录 120.创建 init C 容器后&#xff0c;其状态不正常&#xff1f; 特别说明&#xff1a; 题目 1-68 属于【Kubernetes】的常规概念题&#xff0c;即 “ 汇总&#xff08;一&#xff09;~&#xff08;二十二&#xff09;” 。 题目 69-113 属于【Kubernetes】的生产…

Swagger配置且添加小锁(asp.net)(笔记)

此博客是基于 asp.net core web api(.net core3.1)框架进行操作的。 一、安装Swagger包 在 NuGet程序包管理中安装下面的两个包&#xff1a; swagger包&#xff1a;Swashbuckle.AspNetCore swagger包过滤器&#xff1a;Swashbuckle.AspNetCore.Filters 二、swagger注册 在…

开源 AI 智能名片 O2O 商城小程序与抖音:品牌传播的新机遇与挑战

摘要&#xff1a;本文探讨了开源 AI 智能名片 O2O 商城小程序在品牌传播中的作用&#xff0c;以及与抖音平台相结合所带来的机遇与挑战。分析了抖音如何利用算法适配品牌调性为门店找到目标消费者&#xff0c;放大品牌势能&#xff0c;同时阐述了新品牌在抖音上进行品牌传播的优…

C++平台跳跃游戏

目录 开头程序Game.cpp源文件Player.h头文件Player.cpp源文件 程序的流程图程序游玩的效果下一篇博客要说的东西 开头 大家好&#xff0c;我叫这是我58。 程序 Game.cpp源文件 #include <iostream> #include "Player.h" using namespace std; void printma…

[数据集][目标检测]电力场景防震锤缺陷检测数据集VOC+YOLO格式705张1类别

重要说明&#xff1a;防震锤缺陷图片太难找&#xff0c;数据集里面存在大量单一场景图片&#xff0c;请仔细查看图片预览谨慎下载&#xff0c;此外数据集均为小目标检测&#xff0c;如果训练map偏低属于正常现象 数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径…

19.第二阶段x86游戏实战2-寻找寻路call

免责声明&#xff1a;内容仅供学习参考&#xff0c;请合法利用知识&#xff0c;禁止进行违法犯罪活动&#xff01; 本次游戏没法给 内容参考于&#xff1a;微尘网络安全 本人写的内容纯属胡编乱造&#xff0c;全都是合成造假&#xff0c;仅仅只是为了娱乐&#xff0c;请不要…

C++容器之list基本使用

目录 前言 一、list的介绍&#xff1f; 二、使用 1.list的构造 2.list iterator的使用 3.list capacity &#x1f947; empty &#x1f947;size 4.list element access &#x1f947; front &#x1f947; back 5.list modifiers &#x1f947; push_front &#x1f947; po…

VMware ESXi 8.0U3b macOS Unlocker OEM BIOS 2.7 Dell HPE 定制版 9 月更新发布

VMware ESXi 8.0U3b macOS Unlocker & OEM BIOS 2.7 Dell HPE 定制版 9 月更新发布 VMware ESXi 8.0U3b macOS Unlocker & OEM BIOS 2.7 标准版和厂商定制版 ESXi 8.0U3 标准版&#xff0c;Dell (戴尔)、HPE (慧与)、Lenovo (联想)、IEIT SYSTEMS (浪潮信息)、Cisco …