Verilog基础:在testbench中使用阻塞赋值和非阻塞赋值的区别

news/2024/7/27 11:30:30/文章来源:https://blog.csdn.net/weixin_45791458/article/details/137046594

相关阅读

Verilog基础icon-default.png?t=N7T8https://blog.csdn.net/weixin_45791458/category_12263729.html?spm=1001.2014.3001.5482


        本文详细阐述了在一个testbench中,应该如何使用阻塞赋值与非阻塞赋值。首先说结论,建议在testbench中,对时钟信号(包括分频时钟)使用阻塞赋值,对其他同步信号使用非阻塞赋值。

        下面是一个简单的D触发器模块,本文将针对它的testbench进行讨论。

module Dff(input clk, rst_n, data_in, output reg data_out);always@(posedge clk, negedge rst_n)beginif(!rst_n)data_out <= 1'b0;elsedata_out <= data_in;end
endmodule

        在Verilog仿真时,仿真波形与真实波形是有一定差距的,这体现在同步信号的改变与时钟沿一直是对齐的,而真实情况下,数据信号在时钟沿后需要延迟一段时间才会发生改变。

        体现在上面的模块中就是数据信号data_in的改变是与时钟信号clk同步的,data_out的改变也是与时钟信号clk同步的。

        图1展示了一个简单的仿真波形,其中信号data_in和信号data_out的改变都与时钟沿同步,需要注意的是在时钟沿处,信号data_out得到的是信号data_in在时钟沿处的原值,而不是改变后的值。

图1  仿真波形

        也就是说,一个更加真实的波形可能如图2所示。

图2 真实波形

        下面给出图1所示波形的testbench。

module Dff_t;reg rst_n = 1;reg clk = 0;reg data_in = 0;wire data_out;Dff dff(.clk(clk), .rst_n(rst_n), .data_in(data_in), .data_out(data_out));//时钟产生always begin#10 clk = ~clk;end//异步复位信号initial begin#3 rst_n = 0;#3 rst_n = 1;end//同步数据输入initial begin#10 data_in <= 1;#20 data_in <= 0;#20 data_in <= 1;#20 data_in <= 0;endendmodule

        其中时钟信号和异步复位信号使用了阻塞赋值,而数据信号使用了非阻塞赋值。如果不是这样,就无法保证产生如图1所示的仿真波形,下面将分别讨论。

1、如时钟信号使用非阻塞赋值,数据信号也使用非阻塞赋值

module Dff_t;reg rst_n = 1;reg clk = 0;reg data_in = 0;wire data_out;Dff dff(.clk(clk), .rst_n(rst_n), .data_in(data_in), .data_out(data_out));//时钟产生always begin#10 clk <= ~clk;end//异步复位信号initial begin#3 rst_n = 0;#3 rst_n = 1;end//同步数据输入initial begin#10 data_in <= 1;#20 data_in <= 0;#20 data_in <= 1;#20 data_in <= 0;endendmodule

图3 错误的波形(一种可能)

        此时进行仿真,可能会出现图3所示的错误波形,信号data_out得到的是信号data_in在时钟沿处改变后的值。

       拿第一个时钟上升沿即10ns时举例,此时时钟信号clk被非阻塞赋值,同时data_in被非阻塞赋值。首先说明非阻塞赋值的过程,非阻塞赋值是分两步进行的,第一步是将赋值号<=右表达式求值,在当前仿真时间的所有赋值和非阻塞赋值右表达式求值(活跃事件)完成后,再进行第二步,即非阻塞赋值的赋值(非阻塞赋值的赋值顺序由求值顺序决定),即非阻塞赋值分为两步:求值与赋值,后文仅使用“赋值”一词代表非阻塞赋值中的赋值这个步骤,注意其与阻塞赋值的区别。

        由于initial结构和always结构是并行的,因此无法确定哪一个非阻塞赋值的右表达式求值是先进行的,但可以确定的是,信号clk的赋值和信号data_in的赋值以某种先后顺序被调度到之后(非阻塞赋值更新区)执行。当进行第二步时,clk的赋值和data_in的赋值都从非阻塞赋值更新区激活到活跃事件区执行,此时有多种执行方式:

        1、如果clk的赋值先执行(即之前clk非阻塞赋值右表达式先求值),则其又触发了@(posedge clk),接着是执行data_out非阻塞赋值右表达式求值,还是执行data_in的赋值,是不确定的,它们都是活跃事件。如果先执行data_out非阻塞赋值右表达式求值,则data_out得到的是data_in的旧值即0;如果先执行data_in的赋值,则则data_out得到的是data_in的新值即1(图3可能就是这种情况)。

        2、如果data_in的赋值先执行(即之前data_in非阻塞赋值右表达式先求值),则最后data_out得到的一定是data_in的新值即1(图3可能就是这种情况)。

2、如时钟信号使用阻塞赋值,数据信号也使用阻塞赋值

module Dff_t;reg rst_n = 1;reg clk = 0;reg data_in = 0;wire data_out;Dff dff(.clk(clk), .rst_n(rst_n), .data_in(data_in), .data_out(data_out));//时钟产生always begin#10 clk = ~clk;end//异步复位信号initial begin#3 rst_n = 0;#3 rst_n = 1;end//同步数据输入initial begin#10 data_in = 1;#20 data_in = 0;#20 data_in = 1;#20 data_in = 0;endendmodule

图4 错误的波形(一种可能)

        此时进行仿真,可能会出现图4所示的错误波形,信号data_out得到的是信号data_in在时钟沿处改变后的值。

        拿第一个时钟上升沿即10ns时举例,此时时钟信号clk被阻塞赋值,同时data_in被阻塞赋值。由于initial结构和always结构是并行的,因此无法确定哪一个阻塞赋值是先进行的,此时有多种执行方式。

        1、如果clk的阻塞赋值先进行,则其又触发了@(posedge clk),接着是执行data_out非阻塞赋值右表达式求值,还是执行data_in的阻塞赋值,是不确定的,它们都是活跃事件。如果先执data_out非阻塞赋值右表达式求值,则data_out得到的是data_in的旧值即0;如果先执行data_in的阻塞赋值,则则data_out得到的是data_in的新值即1(图4可能就是这种情况)。

        2、如果data_in的阻塞赋值先进行则最后data_out得到的一定是data_in的新值即1(图4可能就是这种情况)。

3、如时钟信号使用非阻塞赋值,数据信号使用阻塞赋值

module Dff_t;reg rst_n = 1;reg clk = 0;reg data_in = 0;wire data_out;Dff dff(.clk(clk), .rst_n(rst_n), .data_in(data_in), .data_out(data_out));//时钟产生always begin#10 clk <= ~clk;end//异步复位信号initial begin#3 rst_n = 0;#3 rst_n = 1;end//同步数据输入initial begin#10 data_in = 1;#20 data_in = 0;#20 data_in = 1;#20 data_in = 0;endendmodule

图5 错误的波形 

        此时进行仿真,一定会出现图5所示的错误波形,信号data_out得到的是信号data_in在时钟沿处改变后的值。 

        拿第一个时钟上升沿即10ns时举例,此时时钟信号clk被非阻塞赋值,同时data_in被阻塞赋值。由于initial结构和always结构是并行的,因此无法确定是非阻塞赋值的右表达式求值先进行还是阻塞赋值先进行,但是阻塞赋值一定是在非阻塞赋值的赋值前进行的(根据非阻塞赋值的定义),所以不管有多少种执行方式,此时只有一种结果。

        1、data_out得到的一定是data_in的新值即1(图5就是这种情况)。

 4、时钟信号使用阻塞赋值,数据信号使用非阻塞赋值

module Dff_t;reg rst_n = 1;reg clk = 0;reg data_in = 0;wire data_out;Dff dff(.clk(clk), .rst_n(rst_n), .data_in(data_in), .data_out(data_out));//时钟产生always begin#10 clk = ~clk;end//异步复位信号initial begin#3 rst_n = 0;#3 rst_n = 1;end//同步数据输入initial begin#10 data_in <= 1;#20 data_in <= 0;#20 data_in <= 1;#20 data_in <= 0;endendmodule

         最后分析正确的testbench,拿第一个时钟上升沿即10ns时举例,此时时钟信号clk被阻塞赋值,同时data_in被非阻塞赋值。由于initial结构和always结构是并行的,因此无法确定是非阻塞赋值的右表达式求值先进行还是阻塞赋值先进行。

        1、如果clk的阻塞赋值先进行,则其又触发了@(posedge clk),接着是执行data_out非阻塞赋值右表达式求值,还是执行data_in非阻塞赋值右表达式求值,是不确定的,它们都是活跃事件。但是可以肯定的是,data_out得到的一定是data_in的旧值,因为非阻塞赋值的赋值一定在所有非阻塞赋值的求值后进行(根据非阻塞赋值的定义)。

        2、如果data_in非阻塞赋值右表达式求值先进行,则在之后clk阻塞赋值进行后,其又触发了@(posedge clk),接着执行data_out非阻塞赋值右表达式求值,但求值时是使用data_in的旧值,因为非阻塞赋值的赋值一定在所有非阻塞赋值的求值后进行(根据非阻塞赋值的定义)。

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

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

相关文章

基于Hive大数据分析springboot为后端以及vue为前端的的民宿系

标题基于Hive大数据分析springboot为后端以及vue为前端的的民宿系 本文介绍了如何利用Hive进行大数据分析,并结合Spring Boot和Vue构建了一个民宿管理系统。该民民宿管理系统包含用户和管理员登陆注册的功能,发布下架酒店信息,模糊搜索,酒店详情信息展示,收藏以及对收藏的…

【数据结构】新篇章 -- 顺序表

&#x1f308; 个人主页&#xff1a;白子寰 &#x1f525; 分类专栏&#xff1a;python从入门到精通&#xff0c;魔法指针&#xff0c;进阶C&#xff0c;C语言&#xff0c;C语言题集&#xff0c;C语言实现游戏&#x1f448; 希望得到您的订阅和支持~ &#x1f4a1; 坚持创作博文…

wireshark数据流分析-学习日记day1

参考内容&#xff1a; 网址hxxp://194.55.224[.]9/liuz/5/fre.php描述Loki Bot C2 网址早在 2023-08-15 就被注意到了2023-07-27 记录的 IcedID C2 域&#xff1a; vrondafarih[.]com - HTTP trafficmagiketchinn[.]com - HTTPS trafficmagizanqomo[.]com - HTTPS traffic 网…

关系(二)利用python绘制热图

关系&#xff08;二&#xff09;利用python绘制热图 热图 &#xff08;Heatmap&#xff09;简介 热图适用于显示多个变量之间的差异&#xff0c;通过颜色判断彼此之间是否存在相关性。 快速绘制 基于seaborn import seaborn as sns import pandas as pd import numpy as np i…

关于磁盘算法

性能瓶颈&#xff1a;IO–>IO调度–>IO调度算法–>1楼到顶楼&#xff0c;再从零楼下来&#xff0c;效率高–>IO调度目标–>IO算法–>电梯算法–linux6和Linux7算法不一样–>linux6 单队列 Linux7 多队列 inux6: 试用于不同的环境和介质。 noop 适合闪存&…

机器学习第32周周报TAD

文章目录 week32 TAD摘要Abstract一、时序噪声检测二、文献阅读1. 题目2. abstract3. 问题与模型阐述3.1 TAD评估中的陷阱3.1.1 问题描述3.1.2 具有高 F1PA 的随机异常分数3.1.3 具有较高 F1 的未经训练的模型 3.2 对 TAD 进行严格评估3.2.1 TAD 的新基线3.2.2 新的评估方案 PA…

HarmonyOS 应用开发之featureAbility接口切换particleAbility接口切换

featureAbility接口切换 FA模型接口Stage模型接口对应d.ts文件Stage模型对应接口getWant(callback: AsyncCallback<Want>): void; getWant(): Promise<Want>;ohos.app.ability.UIAbility.d.tslaunchWant: Want;startAbility(parameter: StartAbilityParameter, c…

【C++】lambda 表达式 / 包装器 / bind 绑定

目录 一. lambda 表达式1. lambda 表达式的语法1. lambda 表达式的使用2. lambda 表达式的捕捉列表 二. 包装器三. bind 绑定 一. lambda 表达式 Lambda 表达式是 C11 标准引入的一种新特性, 它提供了一种方便的方式来定义匿名函数. lambda 表达式实际上是一个匿名的仿函数; …

Maven是什么? Maven的概念+作用

1.Maven的概念 Maven中文意思为“专家“、”内行“的意思&#xff0c;它是一个项目管理工具&#xff0c;可以对Java项目进行构建、依赖管理&#xff0c;通俗点 就是通过pom.xml文件的配置获取jar包不用手动的去添加jar包。 2.Maven的作用 对于大的工程&#xff0c;需要引用各…

Linux:基本指令篇

文章目录 前言1.ls 指令2.pwd命令3.cd 指令4.touch指令5.mkdir指令&#xff08;重要&#xff09;6.rmdir指令 && rm 指令&#xff08;重要&#xff09;7.man指令&#xff08;重要&#xff09;8.cp指令&#xff08;重要&#xff09;9.mv指令&#xff08;重要&#xff09…

系列学习前端之第 8 章:一文掌握 Vue2(核心基础篇)

1、 Vue简介 1.1 简介 Vue 是动态构建用户界面的渐进式 JavaScript 框架&#xff0c;Vue 只关注视图层&#xff0c; 采用自底向上增量开发的设计。采用组件化模式&#xff0c;提高代码复用率、且让代码更好维护。借鉴 Angular 的模板和数据绑定技术声明式编码&#xff0c;让编…

isaacgym 渲染黑屏

问题描述&#xff1a; isaacgym安装完IsaacGym_Preview_4_Package.tar.gz之后&#xff0c;运行python joint_monkey.py没有任何内容现实&#xff0c;但是终端还是正常输出信息。 环境是ubuntu22服务器&#xff0c;python3.8&#xff0c;nvidia Driver Version: 515.65.01 CUDA…

Day57:WEB攻防-SSRF服务端请求Gopher伪协议无回显利用黑白盒挖掘业务功能点

目录 SSRF-原理&挖掘&利用&修复 SSRF无回显解决办法 SSRF漏洞挖掘 SSRF协议利用 http:// &#xff08;常用&#xff09; file:/// &#xff08;常用&#xff09; dict:// &#xff08;常用&#xff09; sftp:// ldap:// tftp:// gopher:// &#xff08;…

搜索与图论——Kruskal算法求最小生成树

kruskal算法相比prim算法思路简单&#xff0c;不用处理边界问题&#xff0c;不用堆优化&#xff0c;所以一般稀疏图都用Kruskal。 Kruskal算法时间复杂度O(mlogm) 每条边存结构体里&#xff0c;排序需要在结构体里重载小于号 判断a&#xff0c;b点是否连通以及将点假如集合中…

65W智能快充—同为科技桌面PDU插座推荐

近10年&#xff0c;移动设备的智能化、功能化已经完全且紧密的融入到我们的基础生活与工作当中。 在常态化的电子设备的应用中&#xff0c;设备的电力续航以及后续的供电充电就尤为重要。 就目前而言&#xff0c;所有消费电子产品中的输入以及充电的接口&#xff0c;usb-c可以…

竞赛 python图像检索系统设计与实现

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; python图像检索系统设计与实现 &#x1f947;学长这里给一个题目综合评分(每项满分5分) 难度系数&#xff1a;3分工作量&#xff1a;3分创新点&#xff1a;4分 该项目较为新颖&#xff0c…

华为开源自研AI框架昇思MindSpore应用案例:梯度累加

目录 一、环境准备1.进入ModelArts官网2.使用CodeLab体验Notebook实例 二、案例实现 梯度累加的训练算法&#xff0c;目的是为了解决由于内存不足&#xff0c;导致Batch size过大神经网络无法训练&#xff0c;或者网络模型过大无法加载的OOM&#xff08;Out Of Memory&#xff…

C++之类和对象的中篇

&#x1d649;&#x1d65e;&#x1d658;&#x1d65a;!!&#x1f44f;&#x1f3fb;‧✧̣̥̇‧✦&#x1f44f;&#x1f3fb;‧✧̣̥̇‧✦ &#x1f44f;&#x1f3fb;‧✧̣̥̇:Solitary_walk ⸝⋆ ━━━┓ - 个性标签 - &#xff1a;来于“云”的“羽球人”。…

分布式任务调度框架XXL-JOB

1、概述 XXL-JOB是一个分布式任务调度平台&#xff0c;其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品线&#xff0c;开箱即用。 官方文档&#xff1a;https://www.xuxueli.com/xxl-job/#%E4%BA%8C%E3%80%81%E5%BF%AB%E9%80%9F%E…

BGP实训

BGP基础配置实训 实验拓扑 注&#xff1a;如无特别说明&#xff0c;描述中的 R1 或 SW1 对应拓扑中设备名称末尾数字为 1 的设备&#xff0c;R2 或 SW2 对应拓扑中设备名称末尾数字为2的设备&#xff0c;以此类推&#xff1b;另外&#xff0c;同一网段中&#xff0c;IP 地址的主…