简易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;elseip_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;elserd_en <= 1'b0;always @(posedge sys_clk or negedge sys_rst_n)if (sys_rst_n == 1'b0)beginrd_en_d1 <= 1'b0;rd_en_d2 <= 1'b0;endelsebeginrd_en_d1 <= rd_en;rd_en_d2 <= rd_en_d1;endalways @(posedge sys_clk or negedge sys_rst_n)if (sys_rst_n == 1'b0)begindecode_en <= 1'b0;instruct_code <= 16'h0;endelse if (rd_en_d1 == 1'b1)begindecode_en <= 1'b1;instruct_code <= instruct_code_wire;endelsebegindecode_en <= 1'b0;instruct_code <= instruct_code;endram_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,这几个信号,分别是右边的信号比左边的信号延后一个时钟周期。

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

结束语

在本节,我又水了一节。

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

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

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

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

本节结束。

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

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

相关文章

jetlinks物联网平台学习4:http协议设备接入

http协议设备接入 1、创建产品2、配置设备接入方式3、配置网络组件4、上传消息协议5、填写网关信息6、配置http认证信息7、配置物模型8、创建设备9、使用apiPost模拟设备接入9.1、设备上线9.2、设备上报属性9.3、设备事件上报 1、创建产品 创建产品 2、配置设备接入方式 点击…

物联网行业中模组的AT指令详解以及使用

01 概述 AT 命令&#xff08;AT Commands&#xff09;最早是由发明拨号调制解调器&#xff08;MODEM&#xff09;的贺氏公司&#xff08;Hayes&#xff09;为了控制 MODEM 而发明的控制协议。后来随着网络带宽的升级&#xff0c;速度很低的拨号 MODEM 基本退出一般使用市场&am…

[深度学习]卷积神经网络CNN

1 图像基础知识 import numpy as np import matplotlib.pyplot as plt # 图像数据 #imgnp.zeros((200,200,3)) imgnp.full((200,200,3),255) # 可视化 plt.imshow(img) plt.show() # 图像读取 imgplt.imread(img.jpg) plt.imshow(img) plt.show() 2 CNN概述 卷积层convrelu池…

技术速递|加入 .NET 智能组件生态系统

作者&#xff1a;Daniel Roth - 首席产品经理 排版&#xff1a;Alan Wang .NET 智能组件是一组示例嵌入式 UI 组件&#xff0c;使得在应用中轻松添加 AI 启用的功能变得更加简单&#xff0c;例如从剪贴板数据自动填写表单、智能文本补全以及语义搜索等场景。.NET 智能组件演示了…

用友U8 CRM 多个接口存在SQL注入漏洞

本文所涉及的任何技术、信息或工具&#xff0c;仅供学习和参考之用&#xff0c;请勿将文章内的相关技术用于非法目的&#xff0c;如有相关非法行为与文章作者无关。请遵守《中华人民共和国网络安全法》。 中华人民共和国网络安全法 第二十七条 规定 任何个人和组织不得从事非…

uniapp 知识点

自定义导航 在page.json navigationstyle":"custom"navigateTo传参 页面传参只能onLoad(option)里面拿 px和upx的关系 在750设计图中&#xff0c;1px1upx 路由 navigateBack返回上一页 重定向 其实就是把当前页面干掉了 公共组件和页面共同点 computed,watc…

Unity中的功能解释(数学位置相关和事件)

向量计算 Vector3.Slerp&#xff08;起点坐标&#xff0c;终点坐标&#xff0c;t&#xff09;&#xff0c;可是从起点坐标以一个圆形轨迹到终点坐标&#xff0c;有那么多条轨迹&#xff0c;那怎么办 Vector3.Slerp 进行的是沿球面插值&#xff0c;因此并不是沿着严格的“圆形…

【笔记】自动驾驶预测与决策规划_Part4_时空联合规划

文章目录 0. 前言1. 时空联合规划的基本概念1.1 时空分离方法1.2 时空联合方法 2.基于搜索的时空联合规划 &#xff08;Hybrid A* &#xff09;2.1 基于Hybrid A* 的时空联合规划建模2.2 构建三维时空联合地图2.3 基于Hybrid A*的时空节点扩展2.4 Hybrid A* &#xff1a;时空节…

- 串口通信

USART串口通信 目录 USART串口通信 回顾 USART串口通信 1、通信分类与作用 2、串口通信的相关参数&#xff08;重点&#xff09; 3、位协议层 -- RS232协议 4、STM32F103 中的串口外设 5、调试串口编程 -- &#xff08;1&#xff09;串口初始化&#xff1a;时钟、IO、…

数据结构:队列及其应用

队列&#xff08;Queue&#xff09;是一种特殊的线性表&#xff0c;它的主要特点是先进先出&#xff08;First In First Out&#xff0c;FIFO&#xff09;。队列只允许在一端&#xff08;队尾&#xff09;进行插入操作&#xff0c;而在另一端&#xff08;队头&#xff09;进行删…

某客户Oracle RAC无法启动故障快速解决

某日&#xff0c;9:50左右接到好友协助需求&#xff0c;某个客户Oracle RAC无法启动&#xff0c;并发过来一个报错截图&#xff0c;如下&#xff1a; 和客户维护人员对接后&#xff0c;远程登录服务端进行故障分析。 查看hosts信息&#xff0c;首先进行心跳测试&#xff0c;测…

数据库软题3-专门的集合运算

一、投影&#xff08;筛选列&#xff09; 题1 题2 二、选择(筛选行) 三、连接 3.自然连接 题1-自然连接的属性列数&#xff08;几元关系&#xff09;和元组数 解析&#xff1a; 题2-自然连接的属性列数&#xff08;几元关系&#xff09;和元组数 自然连接后的属性个数 A列…

GNSS定位中自适应调整电离层延迟参数过程噪声的方法

文章目录 前言一、非差非组合PPP模型二、电离层功率谱密度计算三、具体实现方法3.1 不平滑3.2 三阶多项式平滑 参考文献 前言 GNSS定位中不少技术手段如PPP和长基线RTK需要将电离层延迟作为参数估计&#xff0c;电离层延迟的变化通常被描述为随机游走过程&#xff0c;而功率谱密…

解决sortablejs+el-table表格内限制回撤和拖拽回撤失败问题

应用场景&#xff1a; table内同一类型可拖拽&#xff0c;不支持不同类型拖拽&#xff08;主演可拖拽交换位置&#xff0c;非主演和主演不可交换位置&#xff09;,类型不同拖拽效果需还原&#xff0c;试了好几次el-table数据更新了&#xff0c;但是表格样式和数据不能及时保持…

Linux-df命令使用方法

Linux-df&#xff08;disk filesystem&#xff09;命令 df 命令是 Unix 和 Linux 系统中用于报告文件系统磁盘空间使用情况的工具。 df [OPTION]... [FILE]...OPTION 常用选项&#xff08;博主一般df -h用的较多&#xff0c;可读性较好&#xff09; -h&#xff1a;以人类可读的…

如何只用 CSS 制作网格?

来源&#xff1a;how-to-make-a-grid-like-graph-paper-grid-with-just-css 在看 用于打印到纸张的 CSS 这篇文章时&#xff0c;对其中的网格比较好奇&#xff0c;作者提供了 stackoverflow 的链接&#xff0c;就看到了来源的这个问题和众多回复。本文从里面挑选了一些个人比较…

docker简介、安装、基础知识

基础知识 Docker简介&#xff1a; 1.Docker是一种用于构建、发布及运行应用程序的开源项目&#xff0c;他通过容器化技术简化了应用程序的部署和管理 2.Docker是一个开源的应用容器引擎&#xff0c;基于go语言开发&#xff0c;为应用打包、部署平台&#xff0c;而非单纯的虚…

【Redis技术进阶之路】「原理分析系列开篇」探索事件驱动枚型与数据特久化原理实现(数据持久化的实现RDB)

揭秘高效存储模型与数据结构底层实现 【专栏简介】【技术大纲】【专栏目标】【目标人群】1. Redis爱好者与社区成员2. 后端开发和系统架构师3. 计算机专业的本科生及研究生 Redis数据持久化的必要Redis数据持久化的实现RDB的持久化机制RDB文件的创建与载入SAVEBGSAVESAVE与BGSA…

基于SpringBoot+Vue的社区智慧消防管理系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏&#xff1a;Java精选实战项目…

Python数据分析和可视化详解

Python数据分析和可视化详解 Python 是当前最受欢迎的数据分析和可视化工具之一。凭借其简单的语法和强大的第三方库&#xff0c;Python 为数据科学家、分析师和工程师提供了广泛的工具&#xff0c;用于处理、分析和展示数据。本文将介绍如何使用 Python 进行数据分析与可视化…