Verilog基础:时序调度中的竞争(四)(描述时序逻辑时使用非阻塞赋值)
相关阅读
Verilog基础
https://blog.csdn.net/weixin_45791458/category_12263729.html?spm=1001.2014.3001.5482
作为一个硬件描述语言,Verilog HDL常常需要使用语句描述并行执行的电路,但其实在仿真器的底层,这些并行执行的语句是有先后顺序的,然而Verilog标准并没有将这些事件调度的顺序定死,而是给予了仿真器厂商一定的自由去实现自己的产品,这就导致了设计者如果不遵循一定的编程习惯,会导致意想不到的仿真结果,下面是一些相关的规则。
4、描述时序逻辑时使用非阻塞赋值
首先以一个三级触发器为例说明描述时序逻辑时使用非阻塞赋值,其电路如图1所示。

图1 一个触发器组
例1
如果使用例1所示的阻塞赋值,顺序执行的阻塞赋值会导致d在时钟上升沿被直接传递到q3,最后的仿真结果(图2)和综合结果(图3)都只有一级触发器。
# 例1
module example1 (q3, d, clk); output [7:0] q3; input [7:0] d; input clk; reg [7:0] q3, q2, q1; always @(posedge clk) begin q1 = d; q2 = q1; q3 = q2; end
endmodule

图2 例1的仿真结果

图3 例1的综合结果
例2
例2将例1中的三个阻塞赋值重排序了,以描述一个三级触发器的行为,q3首先得到q2的值,随后q2再得到q1的值,最后才更新q1,最后的仿真结果(图4)和综合结果(图5)都是三级触发器。
# 例2
module example2 (q3, d, clk); output [7:0] q3; input [7:0] d;input clk;reg [7:0] q3, q2, q1;always @(posedge clk) beginq3 = q2;q2 = q1; q1 = d; end
endmodule

图4 例2的仿真结果

图5 例2的综合结果
虽然看起来很完美,但例2其实是有问题的,如果在该模块后某个触发器采样了q3(或与q3有关的组合逻辑),则此时q3可能使用未更新的值(正确),也可能使用已更新的值(错误),下面的例3说明了这种情况。
例3
例3在三级触发器后又加了一个触发器,在时钟上升沿时,q3的值会更新同时q4的值也会,谁先执行是一个取决于仿真器的未定义行为。如果q4先更新,则q4得到的是q3旧值(正确);如果q3先更新,则q4得到的是q3新值(错误),如图6的仿真结果所示。即使图7所示的综合结果是正确的,但这会造成前仿和后仿的不一致。
# 例3
module example3 (q4, d, clk); output [7:0] q4; input [7:0] d;input clk;reg [7:0] q4, q3, q2, q1;always @(posedge clk) beginq3 = q2;q2 = q1; q1 = d; endalways @(posedge clk) beginq4 = q3; // q4 <= q3; 这两种赋值都会导致竞争end
endmodule

图6 例3的仿真结果(一种可能,错误)

图7 例3的综合结果
例4
如果理解了上面的例3,那么将例3拆成三个always块的例4毫无疑问是一种会导致前仿和后仿不一致的写法,因为不同always块的执行顺序是不确定的。图8展示的仿真结果表示,该仿真器选择从下到上执行这三个always块,因此得到了和例1一样的结果。从图9所示的综合结果来看是正确的。
# 例4
module example4 (q3, d, clk); output [7:0] q3; input [7:0] d;input clk;reg [7:0] q3, q2, q1;always @(posedge clk) beginq3 = q2;endalways @(posedge clk) beginq2 = q1;endalways @(posedge clk) beginq1 = d;end
endmodule

图8 例4的仿真结果(一种可能,错误)

图9 例4的综合结果
例5
例5在例4的基础上,将always块的顺序调换了,图10展示的仿真结果表示,该仿真器选择从下到上执行这三个always块,因此得到了和例2一样的结果。从图11所示的综合结果来看是正确的。
# 例5
module example5 (q3, d, clk); output [7:0] q3; input [7:0] d;input clk;reg [7:0] q3, q2, q1;always @(posedge clk) beginq1 = d;endalways @(posedge clk) beginq2 = q1;endalways @(posedge clk) beginq3 = q2;end
endmodule

图10 例5的仿真结果(一种可能,正确)

图11 例5的综合结果
上面四种使用阻塞赋值的方法中,只有一种能保证仿真结果正确,即使三种的综合结果是正确的。
例6
例6以非阻塞赋值重写了例1,由于非阻塞赋值分两步执行,首先是<=右侧表达式值的计算,在当前仿真时间的最后才将右侧表达式值赋值给左值。因此q2得到的是q1的旧值,而q3得到的也是q2的旧值,如仿真结果图12所示,这时的综合结果如图13所示,也是正确的。
# 例6
module example6 (q3, d, clk); output [7:0] q3; input [7:0] d; input clk; reg [7:0] q3, q2, q1; always @(posedge clk) begin q1 <= d; q2 <= q1; q3 <= q2; end
endmodule

图12 例6的仿真结果

图13 例6的综合结果
例7
例7以非阻塞赋值重写了例2,但仿真结果和综合结果依旧如图12和图13所示,因为此时所有值的更新都是在最后进行的,不会影响<=右侧表达式的计算结果。
# 例7
module example7 (q3, d, clk); output [7:0] q3; input [7:0] d; input clk; reg [7:0] q3, q2, q1; always @(posedge clk) beginq3 <= q2;q2 <= q1;q1 <= d; end
endmodule
例8
例8以非阻塞赋值重写了例4,虽然不同always块的执行顺序是不确定的,但这只表示<=右侧表达式值的计算顺序是不确定的,右侧表达式值赋值给左值的顺序是不确定的,这不会对结果有任何影响,所有右侧表达式值赋值给左值还是发生在右侧表达式值的计算前。仿真结果和综合结果依旧如图12和图13所示。
# 例8
module example8 (q3, d, clk); output [7:0] q3; input [7:0] d;input clk;reg [7:0] q3, q2, q1;always @(posedge clk) beginq3 <= q2;endalways @(posedge clk) beginq2 <= q1;endalways @(posedge clk) beginq1 <= d;end
endmodule
例9
例9以非阻塞赋值重写了例5,与例8同理,仿真结果和综合结果依旧如图12和图13所示。
# 例9
module example9 (q3, d, clk); output [7:0] q3; input [7:0] d;input clk;reg [7:0] q3, q2, q1;always @(posedge clk) beginq1 <= d;endalways @(posedge clk) beginq2 <= q1;endalways @(posedge clk) beginq3 <= q2;end
endmodule
上面四种使用非阻塞赋值的方法中,全部能保证仿真结果和综合结果正确。上面的九个例子说明了在描述时序逻辑时,最好使用非阻塞赋值。
例10
例10展示了一个使用阻塞赋值实现的线性反馈移位寄存器(LFSR),关于这种结构的详细介绍,可见数字IC前端学习笔记:LFSR(线性反馈移位寄存器)。
module example10 (q3, clk, pre_n); output q3; input clk, pre_n; reg q3, q2, q1; always @(posedge clk or negedge pre_n) if (!pre_n) {q3,q2,q1} = 3'b111; else {q3,q2,q1} = {q2,(q1^q3),q3};
endmodule
例10将所有的赋值写在了一行,保证了赋值的正确,但这种风格是不建议的,会让debug变得更加复杂。可以发现,例10无法使用例2中将阻塞赋值重排序的方法实现,因为其是有互相依赖,即q3依赖q2而q2依赖于q3。而且,例10仍然有例3所示的前仿和后仿不一致的问题。
例11
例11以非阻塞赋值重写了例10,解决了例10存在的前仿和后仿不一致的问题。
module example11 (q3, clk, pre_n); output q3; input clk, pre_n; reg q3, q2, q1; always @(posedge clk or negedge pre_n) if (!pre_n) {q3,q2,q1} <= 3'b111; else {q3,q2,q1} <= {q2,(q1^q3),q3};
endmodule
例12
例12将例11拆成了一个always块中的三个非阻塞赋值,仿真结果和综合结果和例11一致。
module example12 (q3, clk, pre_n); output q3; input clk, pre_n; reg q3, q2, q1; always @(posedge clk or negedge pre_n) if (!pre_n) beginq1 <= 1'b1; q2 <= 1'b1;q3 <= 1'b1;endelse beginq1 <= q3; q2 <= q1^q3;q3 <= q2;end
endmodule
例13
例13将例12中的三个非阻塞赋值重排序了,仿真结果和综合结果和例11一致。
module example13 (q3, clk, pre_n); output q3; input clk, pre_n; reg q3, q2, q1; always @(posedge clk or negedge pre_n) if (!pre_n) beginq3 <= 1'b1; q2 <= 1'b1;q1 <= 1'b1;endelse beginq3 <= q2;q2 <= q1^q3;q1 <= q3; end
endmodule
例14
例14将例11拆成了三always块,仿真结果和综合结果和例11一致。
module example14 (q3, clk, pre_n); output q3; input clk, pre_n; reg q3, q2, q1; always @(posedge clk or negedge pre_n) if (!pre_n) beginq3 <= 1'b1;endelse beginq3 <= q2;end always @(posedge clk or negedge pre_n) if (!pre_n) beginq2 <= 1'b1;endelse beginq2 <= q1^q3;end always @(posedge clk or negedge pre_n) if (!pre_n) beginq1 <= 1'b1;endelse beginq1 <= q3; end
endmodule
例15
例15在例14的基础上,将always块的顺序调换了,仿真结果和综合结果和例11一致。
module example15 (q3, clk, pre_n); output q3; input clk, pre_n; reg q3, q2, q1; always @(posedge clk or negedge pre_n) if (!pre_n) beginq1 <= 1'b1;endelse beginq1 <= q3; end always @(posedge clk or negedge pre_n) if (!pre_n) beginq2 <= 1'b1;endelse beginq2 <= q1^q3;end always @(posedge clk or negedge pre_n) if (!pre_n) beginq3 <= 1'b1;endelse beginq3 <= q2;end
endmodule
本文是基于《CUMMINGS, Clifford E., et al. Nonblocking assignments in verilog synthesis, coding styles that kill!. SNUG (Synopsys Users Group) 2000 User Papers, 2000. 》的进一步阐述,感谢Clifford E. Cummings对此做出贡献。
原文链接:http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdf
相关文章:
Verilog基础:时序调度中的竞争(四)(描述时序逻辑时使用非阻塞赋值)
相关阅读 Verilog基础https://blog.csdn.net/weixin_45791458/category_12263729.html?spm1001.2014.3001.5482 作为一个硬件描述语言,Verilog HDL常常需要使用语句描述并行执行的电路,但其实在仿真器的底层,这些并行执行的语句是有先后顺序…...
嵌入式边缘计算软硬件开发“1+X”考证建设方案
一、引言 随着物联网、大数据、人工智能等技术的飞速发展,嵌入式边缘计算作为连接物理世界与数字世界的桥梁,其重要性日益凸显。为了适应行业对高技能人才的需求,推动嵌入式边缘计算技术的普及与应用,特制定本“1X”考证建设方案…...
ES8的Java API client 8.0 简单示例操作 Elasticsearch
1.加入依赖 <dependency><groupId>co.elastic.clients</groupId><artifactId>elasticsearch-java</artifactId><version>8.12.2</version></dependency>2.配置类 Slf4j Configuration public class ElasticSearchConfig {Valu…...
多线程CompletableFuture
最近发现同事整理了一个不错的关于CompletableFuture的文档,在这里记录一下,方便以后工作备用 CompletableFuture future CompletableFuture.supplyAsync(() -> {return "开新线程异步执行"; })result future.get(); // 线程阻塞等待结果…...
AR传送门+特定区域显示内容+放大镜 效果着色器使用
AR传送门特定区域显示内容放大镜 效果 关键词:Portal Mask 1、教程链接: AR 传送门教程 Unity - Portal Mask Implementation - Part 4_哔哩哔哩_bilibili 应用案例效果: 2、案例下载地址:使用unity 2021.3.33f1 obi 工具…...
设置Hadoop守护进程的JVM参数
一般情况下我们不去动守护进程的JVM,这里的守护进程说的是NameNode、DataNode等Hadoop服务自己本身的进程。但是有一些特殊情况下需要限制,比如工作中虽然集群中资源队列会有10%左右的预留空余,不过这是整个集群队列的限制,对于Da…...
可视化大屏
可视化大屏 是一种利用计算机图形学技术,将复杂的数据和信息转换为直观的可视化图形,以呈现数据信息的工具。它不仅在电影中常见,而且已经实实在在地被应用在商业、金融、制造等各个行业的业务场景中,成为大数据分析和展示的重要工…...
pytest框架
pytest测试框架 单元测试框架定义:针对软件开发最小的单元(函数,方法)进行正确性位置测试 单元测试框架:java(junit,testing)python(unittest,pytest&#…...
基于大数据的亚健康人群数据分析及可视化系统
作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏:Java精选实战项目…...
黄金短线交易策略:波动中的高效盈利之法
今日,亚市盘初,现货黄金就高位震荡。在昨日金价再度冲高,一度刷新历史高点至2685.49美元,收报2672.25美元。其中主要原因是美国公布了最新的核心PCE(个人消费支出)物价指数和初请失业金人数等经济数据&…...
西陆家政系统V1.0.1
微信小程序开发的西陆家政服务管理系统小程序 V1.0.1bug修复优化 1.修复首页轮播不能自动轮播问题;2.修复订单详情价格显示问题;3.修复在开放城市模式下,其他城市可以下单问题;4.修复个人二维码跳转小程序路径异常问题;5.修复小程序编辑我的地址选择定位后不刷新问题…...
时间安全精细化管理平台/iapp/mobile/facereg/facereg.html接口存在未授权访问漏洞
漏洞描述 登录--时间&安全精细化管理平台/iapp/mobile/facereg/facereg.html接口存在未授权访问漏洞,黑客可以未授权等级员工信息对平台造成影响 FOFA: body"登录--时间&安全精细化管理平台" 漏洞复现 IP/iapp/mobile/facereg…...
自动化测试实例:Web登录功能性测试(无验证码)
🍅 点击文末小卡片 ,免费获取软件测试全套资料,资料在手,涨薪更快 一、什么是自动化测试 把人为驱动的测试行为转化为机器执行的一种过程称为自动化测试。(来自百度百科)本质上来说,自动化测试对比起手工测试除了需要…...
【算法篇】二叉树类(3)(笔记)
目录 一、Leetcode 题目 1. 二叉树的最近公共祖先 2. 二叉搜索树的最近公共祖先 (1)递归法 (2)迭代法 3. 二叉搜索树中的插入操作 (1)递归法 (2)迭代法 4. 删除二叉搜索树中…...
基于php的律所管理系统
作者:计算机学姐 开发技术:SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等,“文末源码”。 专栏推荐:前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码 精品专栏:Java精选实战项目…...
MySQL 之索引详解
想象一下,你正在图书馆寻找一本关于 MySQL 索引的书。图书馆里有成千上万本书,但没有目录。你只能一排一排、一本一本地找,直到找到你想要的书。这将会花费大量的时间!数据库索引就像图书馆的目录一样,可以帮助数据库系…...
C#测试调用FreeSpire.PDFViewer浏览PDF文件
Free Spire.PDFViewer是商业版Spire.PDFViewer的社区版本,支持以控件形式打开并查看PDf文件,但由于是免费版本,存在使用限制,打开的PDF文档只显示前10页内容。如果日常操作的pdf文件都不超过10页,可以考虑使用Free Spi…...
又一挣钱副业:AI生成影视解说,半个月涨粉变现3.5W+!
这两年大家都在感叹生活不易,然而我想说的是,机会还是有的,但问题不在于有没有,而在于你是否能够认准机会,然后抓住它。 接触过很多咨询项目的人,发现很多人依旧停留在传统思维中,认为副业就是…...
R语言 基础 笔记 3
起因, 目的: 思考一个问题: AI 这么强,AI 什么都知道,为什么还要学习这些基础的东西, 为什么还要写这些笔记? 我觉得,大体过一遍,还是有好处的。 有个大致印象,下次查的时候,也方便一些。 几个函数 cbind() 按照列,拼接数据, 会改变某些列的数据类型。data() 查看…...
【MySQL】常见的SQL优化方式(一)
目录 1、插入数据 (1)批量插入 (2)手动提交事务 (3)主键顺序插入 2、主键优化 (1)页分裂 (2)页合并 3、order by 优化 (1)排…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
java_网络服务相关_gateway_nacos_feign区别联系
1. spring-cloud-starter-gateway 作用:作为微服务架构的网关,统一入口,处理所有外部请求。 核心能力: 路由转发(基于路径、服务名等)过滤器(鉴权、限流、日志、Header 处理)支持负…...
基于Flask实现的医疗保险欺诈识别监测模型
基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施,由雇主和个人按一定比例缴纳保险费,建立社会医疗保险基金,支付雇员医疗费用的一种医疗保险制度, 它是促进社会文明和进步的…...
Java多线程实现之Callable接口深度解析
Java多线程实现之Callable接口深度解析 一、Callable接口概述1.1 接口定义1.2 与Runnable接口的对比1.3 Future接口与FutureTask类 二、Callable接口的基本使用方法2.1 传统方式实现Callable接口2.2 使用Lambda表达式简化Callable实现2.3 使用FutureTask类执行Callable任务 三、…...
高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...
Cinnamon修改面板小工具图标
Cinnamon开始菜单-CSDN博客 设置模块都是做好的,比GNOME简单得多! 在 applet.js 里增加 const Settings imports.ui.settings;this.settings new Settings.AppletSettings(this, HTYMenusonichy, instance_id); this.settings.bind(menu-icon, menu…...
python如何将word的doc另存为docx
将 DOCX 文件另存为 DOCX 格式(Python 实现) 在 Python 中,你可以使用 python-docx 库来操作 Word 文档。不过需要注意的是,.doc 是旧的 Word 格式,而 .docx 是新的基于 XML 的格式。python-docx 只能处理 .docx 格式…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)
本期内容并不是很难,相信大家会学的很愉快,当然对于有后端基础的朋友来说,本期内容更加容易了解,当然没有基础的也别担心,本期内容会详细解释有关内容 本期用到的软件:yakit(因为经过之前好多期…...
面向无人机海岸带生态系统监测的语义分割基准数据集
描述:海岸带生态系统的监测是维护生态平衡和可持续发展的重要任务。语义分割技术在遥感影像中的应用为海岸带生态系统的精准监测提供了有效手段。然而,目前该领域仍面临一个挑战,即缺乏公开的专门面向海岸带生态系统的语义分割基准数据集。受…...
