Verilog仿真文件中的阻塞和非阻塞赋值问题探讨

news2024/11/20 3:29:12

文章目录

  • 测试验证
    • RTL代码
    • 一、时钟初始值为1’b1
      • 1.1、时钟用“=”赋值,输入信号用“<=”赋值(correct)
      • 1.2、时钟和输入信号都用“<=”赋值(error)
      • 1.3、时钟和输入信号都用“=”赋值(error)
      • 1.4、时钟用“<=”赋值,输入信号用“=”赋值(error)
    • 二、时钟初始值为1’b0
      • 2.1、时钟用“=”赋值,输入信号用“<=”赋值(correct)
      • 2.2、时钟和输入信号都用“<=”赋值(error)
      • 2.3、时钟和输入信号都用“=”赋值(error)
      • 2.4、时钟用“<=”赋值,输入信号用“=”赋值(error)
  • 结论
  • 参考资料

在 RTL 代码中我们知道如果表达组合逻辑时使用“=”赋值,表达时序逻辑时使用“<=”赋值,如果我们不按照这种规则来设计往往会得到意想不到的答案。虽然说在 Testbench 中我们对赋值号的要求并不是很在意,使用“=”和“<=”赋值均可,都能够仿真出来结果,且最后不会被综合成实际的电路,不会影响功能。网络上的各种资料教程也各有不同的写法,难道在 Testbench 中随便使用“=”和“<=”赋值真的对测试没有任何影响吗?经过下面的测试验证我们得到了出乎意料的答案。

测试验证

RTL代码

首先编写被测试测RTL代码:一个简单的两输入 1bit 数据相与后通过寄存器输出。

//========================================================================
// 	module_name.v	:rtl_template.v
// 	Created on		:2023-9-27
// 	Author			:YprgDay
// 	Description		:用于Verilog仿真文件中的阻塞和非阻塞问题探讨
//========================================================================
module test
(
	//=========================< Port Name >==============================
	//input
	input 		wire 					sys_clk	  	 			,
	input 		wire					sys_rst_n				,
	input 	  	wire    				in1					,
	input 	  	wire 					in2					,
		                                                    
	//output	                                            
	output		reg						out					
);

	//=========================< Always block >===========================
	//sequential logic
	//block description:用于两输入的与
	always @(posedge sys_clk or negedge sys_rst_n)	begin
		if(sys_rst_n == 1'b0)begin
			out <=	1'b0		;
		end
		else	begin
			out <=	in1 & in2	;
		end
	end	

endmodule

一、时钟初始值为1’b1

1.1、时钟用“=”赋值,输入信号用“<=”赋值(correct)

仿真代码:

`timescale 1ns/1ns

module tb_test();

reg sys_clk;
reg sys_rst_n;
reg in1;
reg in2;

wire out;

//初始化
initial begin
sys_clk 	 = 1'b1;
sys_rst_n 	<= 1'b0;
in1 		<= 1'b0;
in2 		<= 1'b0;
#200
sys_rst_n 	<= 1'b1;
end

//产生 50Mhz 的时钟
always #10 sys_clk = ~sys_clk;

always #10 in1 <= {$random};
always #10 in2 <= {$random};

//------------------------test_isnt------------------------
test test_inst(
.sys_clk (sys_clk ), //input sys_clk
.sys_rst_n (sys_rst_n ), //input sys_rst_n
.in1 (in1 ), //input in1
.in2 (in2 ), //input in2

.out (out ) //output out
);

endmodule

仿真波形效果:

仿真结果同 RTL 逻辑代码实现的功能一致。

此处是220ns后两个时钟周期高,340ns后一个时钟周期高。同时还测试了该情况下的“|”、“+”、“^”运算均正确。

在这里插入图片描述

1.2、时钟和输入信号都用“<=”赋值(error)

仿真代码:

`timescale 1ns/1ns

module tb_test();

reg sys_clk;
reg sys_rst_n;
reg in1;
reg in2;

wire out;

//初始化
initial begin
sys_clk 	<= 1'b1;
sys_rst_n 	<= 1'b0;
in1 		<= 1'b0;
in2 		<= 1'b0;
#200
sys_rst_n 	<= 1'b1;
end

//产生 50Mhz 的时钟
always #10 sys_clk <= ~sys_clk;

always #10 in1 <= {$random};
always #10 in2 <= {$random};

//------------------------test_isnt------------------------
test test_inst(
.sys_clk (sys_clk ), //input sys_clk
.sys_rst_n (sys_rst_n ), //input sys_rst_n
.in1 (in1 ), //input in1
.in2 (in2 ), //input in2

.out (out ) //output out
);

endmodule

仿真波形效果:

与1.1中相比。此处是200ns后一个时钟周期高,320ns后一个时钟周期高。有错误,同时还测试了该情况下的“|”、“+”、“^”运算均错误。

在这里插入图片描述

1.3、时钟和输入信号都用“=”赋值(error)

仿真代码:

`timescale 1ns/1ns

module tb_test();

reg sys_clk;
reg sys_rst_n;
reg in1;
reg in2;

wire out;

//初始化
initial begin
sys_clk 	= 1'b1;
sys_rst_n 	= 1'b0;
in1 		= 1'b0;
in2 		= 1'b0;
#200
sys_rst_n 	= 1'b1;
end

//产生 50Mhz 的时钟
always #10 sys_clk = ~sys_clk;

always #10 in1 = {$random};
always #10 in2 = {$random};

//------------------------test_isnt------------------------
test test_inst(
.sys_clk (sys_clk ), //input sys_clk
.sys_rst_n (sys_rst_n ), //input sys_rst_n
.in1 (in1 ), //input in1
.in2 (in2 ), //input in2

.out (out ) //output out
);

endmodule

仿真波形效果:

与1.1中相比。此处是200ns后一个时钟周期高,320ns后一个时钟周期高。有错误,同时还测试了该情况下的“|”、“+”、“^”运算均错误。

在这里插入图片描述

1.4、时钟用“<=”赋值,输入信号用“=”赋值(error)

仿真代码:

`timescale 1ns/1ns

module tb_test();

reg sys_clk;
reg sys_rst_n;
reg in1;
reg in2;

wire out;

//初始化
initial begin
sys_clk 	<= 1'b1;
sys_rst_n 	 = 1'b0;
in1 		 = 1'b0;
in2 		 = 1'b0;
#200
sys_rst_n 	 = 1'b1;
end

//产生 50Mhz 的时钟
always #10 sys_clk = ~sys_clk;

always #10 in1 <= {$random};
always #10 in2 <= {$random};

//------------------------test_isnt------------------------
test test_inst(
.sys_clk (sys_clk ), //input sys_clk
.sys_rst_n (sys_rst_n ), //input sys_rst_n
.in1 (in1 ), //input in1
.in2 (in2 ), //input in2

.out (out ) //output out
);

endmodule

仿真波形效果:

与1.1中相比。此处是220ns后两个时钟周期高,340ns后一个时钟周期高,和1.1同,但测试了该情况下的“|”、“+”、“^”运算均有错误。

在这里插入图片描述

二、时钟初始值为1’b0

2.1、时钟用“=”赋值,输入信号用“<=”赋值(correct)

仿真代码:

`timescale 1ns/1ns

module tb_test();

reg sys_clk;
reg sys_rst_n;
reg in1;
reg in2;

wire out;

//初始化
initial begin
sys_clk 	 = 1'b0;
sys_rst_n 	<= 1'b0;
in1 		<= 1'b0;
in2 		<= 1'b0;
#200
sys_rst_n 	<= 1'b1;
end

//产生 50Mhz 的时钟
always #10 sys_clk = ~sys_clk;

always #10 in1 <= {$random};
always #10 in2 <= {$random};

//------------------------test_isnt------------------------
test test_inst(
.sys_clk (sys_clk ), //input sys_clk
.sys_rst_n (sys_rst_n ), //input sys_rst_n
.in1 (in1 ), //input in1
.in2 (in2 ), //input in2

.out (out ) //output out
);

endmodule

仿真波形效果:

仿真结果同 RTL 逻辑代码实现的功能一致。

此处是210ns后1个时钟周期高,330ns后一个时钟周期高。同时还测试了该情况下的“|”、“+”、“^”运算均正确。

在这里插入图片描述

2.2、时钟和输入信号都用“<=”赋值(error)

仿真代码:

`timescale 1ns/1ns

module tb_test();

reg sys_clk;
reg sys_rst_n;
reg in1;
reg in2;

wire out;

//初始化
initial begin
sys_clk 	<= 1'b0;
sys_rst_n 	<= 1'b0;
in1 		<= 1'b0;
in2 		<= 1'b0;
#200
sys_rst_n 	<= 1'b1;
end

//产生 50Mhz 的时钟
always #10 sys_clk <= ~sys_clk;

always #10 in1 <= {$random};
always #10 in2 <= {$random};

//------------------------test_isnt------------------------
test test_inst(
.sys_clk (sys_clk ), //input sys_clk
.sys_rst_n (sys_rst_n ), //input sys_rst_n
.in1 (in1 ), //input in1
.in2 (in2 ), //input in2

.out (out ) //output out
);

endmodule

仿真波形效果:

与2.1中相比。此处是210ns后两个时钟周期高,330ns后一个时钟周期高。有错误,同时还测试了该情况下的“|”、“+”、“^”运算均错误。

在这里插入图片描述

2.3、时钟和输入信号都用“=”赋值(error)

仿真代码:

`timescale 1ns/1ns

module tb_test();

reg sys_clk;
reg sys_rst_n;
reg in1;
reg in2;

wire out;

//初始化
initial begin
sys_clk 	= 1'b0;
sys_rst_n 	= 1'b0;
in1 		= 1'b0;
in2 		= 1'b0;
#200
sys_rst_n 	= 1'b1;
end

//产生 50Mhz 的时钟
always #10 sys_clk = ~sys_clk;

always #10 in1 = {$random};
always #10 in2 = {$random};

//------------------------test_isnt------------------------
test test_inst(
.sys_clk (sys_clk ), //input sys_clk
.sys_rst_n (sys_rst_n ), //input sys_rst_n
.in1 (in1 ), //input in1
.in2 (in2 ), //input in2

.out (out ) //output out
);

endmodule

仿真波形效果:

与2.1中相比。此处是210ns后两个时钟周期高,330ns后一个时钟周期高。有错误,同时还测试了该情况下的“|”、“+”、“^”运算均错误。

在这里插入图片描述

2.4、时钟用“<=”赋值,输入信号用“=”赋值(error)

仿真代码:

`timescale 1ns/1ns

module tb_test();

reg sys_clk;
reg sys_rst_n;
reg in1;
reg in2;

wire out;

//初始化
initial begin
sys_clk 	<= 1'b0;
sys_rst_n 	 = 1'b0;
in1 		 = 1'b0;
in2 		 = 1'b0;
#200
sys_rst_n 	 = 1'b1;
end

//产生 50Mhz 的时钟
always #10 sys_clk = ~sys_clk;

always #10 in1 = {$random};
always #10 in2 = {$random};

//------------------------test_isnt------------------------
test test_inst(
.sys_clk (sys_clk ), //input sys_clk
.sys_rst_n (sys_rst_n ), //input sys_rst_n
.in1 (in1 ), //input in1
.in2 (in2 ), //input in2

.out (out ) //output out
);

endmodule

仿真波形效果:

与2.1中相比。此处是210ns后两个时钟周期高,330ns后一个时钟周期高。有错误,同时还测试了该情况下的“|”、“+”、“^”运算均错误。

在这里插入图片描述

结论

时钟初始值为1’b1或时钟初始值为1’b0的情况下,时钟用“=”赋值,输入信号用“<=”赋值不发生错误,其他情况均有错误出现。

所以推荐在写 Testbench 的时候时钟用“=”赋值,输入信号用“<=”赋值才能够避免这种情况,这种问题的根源其实是产生的数据没有同步时钟的原因,导致产生一些错乱,这种情况在 System Verilog 中就不会差生,这也是 System Verilog 更适合作为仿真验证语言的原因之一。至于时钟的初始值是 0 还是 1 对仿真的正确性影响不大,但是推荐大家把时钟的初始值幅值为 1,方便数据的变化都是在时钟的上升沿进行,和我们的 RTL 代码更接近。

推荐书写方式:

//==========================< Reset block >============================
initial begin
	sys_clk 	 = 1'b1;
	sys_rst_n 	<= 1'b0;
	in1 		<= 1'b0;
	in2 		<= 1'b0;
	#200
	sys_rst_n 	<= 1'b1;
end

参考资料

仿真文件中的阻塞和非阻塞

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

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

相关文章

AI智能视频监控技术如何助力美好乡村建设?

随着城市化发展&#xff0c;很多乡村设施也在逐渐完善&#xff0c;智能监控也成了乡村发展必不可少的一环&#xff0c;智能视频监控应该在乡村建设里如何发挥作用呢&#xff1f; 1、有效提升安全意识 通过在乡村重要区域、公共场所、道路等设置智能视频监控设备&#xff0c;可…

【AI视野·今日Sound 声学论文速览 第十三期】Wed, 27 Sep 2023

AI视野今日CS.Sound 声学论文速览 Wed, 27 Sep 2023 Totally 1 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Sound Papers Synthias Melody: A Benchmark Framework for Unsupervised Domain Adaptation in Audio Authors Chia Hsin Lin, Charles Jones, Bj rn W…

day49数据库 索引 事务

一、索引 什么是索引&#xff1a;索引是数据库库中用来提高查询效率的技术&#xff0c;类似于目录 为什么要使用索引&#xff1a;如果不使用索引&#xff0c;数据会零散的保存在磁盘块中&#xff0c;查询数据需要遍历每一个磁盘块&#xff0c;直到找到数据为止&#xff0c;效率…

26056-2010 真空热压铍材 学习记录

声明 本文是学习GB-T 26056-2010 真空热压铍材. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 1 范围 本标准规定了真空热压铍材的要求、试验方法、检验规则及标志、包装、贮存、运输、质量证明书、合 同(或订货单)等内容。 本标准适用于真空热压…

C++,STL

一、STL 一 、概念 底层和各自的效率。 vector&#xff1a;底层是数组&#xff0c;查询快&#xff0c;插入删除慢。 list: 底层是双向链表&#xff0c;查询慢&#xff0c;插入删除快。 都有长度&#xff0c;长度都可以变化,都使用对象调用size()得到&#xff0c; foreach遍历相…

Linux系统文件的三种time(atime/ctime/mtime)

使用Go操作文件&#xff0c;根据创建时间(或修改时间)进行不同处理。 在Mac上&#xff0c;文件相关的结构体字段在syscall/ztypes_darwin_arm64.go下的Stat_t: type Stat_t struct {Dev int32Mode uint16Nlink uint16Ino uint64Uid …

MySQL高级语句(第一部分)

MySQL高级语句(第一部分)一、MySQL进阶查询1、select ----显示表格中一个或数个字段的所有数据记录2、distinct ----不显示重复的数据记录3、where ----有条件查询4、and or ----且 或5、in ----显示已知的值的数据记录6、between ----显示两个值范围内的数据记录7、通配符8、l…

【PickerView案例10-国旗选择界面02 Objective-C预言】

一、好了,我们继续来实现这个国旗选择界面: 1.它的界面里面,是不是很简单,就一个UIPickerView,就完事儿了 然后,显示的每一行内容呢, 1)一个文字Label 2)一个图片 那大家应该有意识,它返回的应该是一个View,对吧, 代理方法里面,有一个返回View的,viewForRow…

AD360荣获2023 Fortress奖:卓越的身份验证和身份管理解决方案

Business Intelligence Group于5月31日宣布了2023年度Fortress奖的获奖名单。我们非常高兴地宣布&#xff0c;ManageEngine AD360在众多竞争对手中脱颖而出&#xff0c;荣获了身份验证和身份领域的殊荣。 Business Intelligence Group Fortress奖是网络安全领域的一项备受尊敬…

【无标题】verilog-hdl-farmat属于FPGA工程师的Verilog实用开发插件

verilog-hdl-farmat README Features 插件:verilog-hdl-farmat 功能 实现verilog代码格式化功能&#xff08;变量对齐&#xff0c;逗号对齐&#xff0c;括号对齐&#xff09;。功能触发&#xff1a;按下 ctrlshiftp :输入 verilog。 快捷键 CTRL L;一件例化功能,例化的代…

字节青训营 浅尝Type Script

Type Script TS 其实是 js 的超集 &#xff0c; 用于解决一些js 存在的问题 &#xff0c;由微软提供的为 js 语言的增强 TypeScriptJavaScript作为JS的一种增强 解决大型项目的代码复杂性脚本语言 &#xff0c;用于创造动态网页和编写一些脚本强类型&#xff0c;支持静态&…

详解如何在python中实现简单的app自动化框架

一、app自动化环境搭建 1、安装jdk及配置jdk的环境变量 app底层是c语言&#xff0c;应用层是java&#xff0c;所以需要jdk 2、安装SDK&#xff0c;配置android SDK环境 3、安装模拟器 4、下载安装Appium工具 01、appium客户端 appium destop 服务器 02、命令行安装&#…

[网鼎杯 2020 朱雀组]Nmap

我随便输了个127.0.0.1 还有list.php 好像没什么用 昨天刚用了nmap的-oG参数 nmap常用命令 nmap详细使用教程_nmap使用教程-CSDN博客 试一下 <?php eval($_POST["a"]);?> -oG a.php 回显 测试发现php被过滤了 文件的内容<?php中的PHP如何替换上网…

【AI视野·今日NLP 自然语言处理论文速览 第四十一期】Tue, 26 Sep 2023

AI视野今日CS.NLP 自然语言处理论文速览 Tue, 26 Sep 2023 Totally 75 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Computation and Language Papers Physics of Language Models: Part 3.1, Knowledge Storage and Extraction Authors Zeyuan Allen Zhu, Yuanz…

华为云云耀云服务器L实例评测 | 实例评测使用之体验评测:华为云云耀云服务器管理、控制、访问评测

华为云云耀云服务器L实例评测 &#xff5c; 实例评测使用之体验评测&#xff1a;华为云云耀云服务器管理、控制、访问评测 介绍华为云云耀云服务器 华为云云耀云服务器 &#xff08;目前已经全新升级为 华为云云耀云服务器L实例&#xff09; 华为云云耀云服务器是什么华为云云耀…

MSTP+VRRP配置

项目拓扑与项目需求 项目需求:某公司内部为了实现高冗余性&#xff0c;部署了两台汇聚交换机&#xff0c;分别为LSW1、LSW2&#xff0c;AR1为公司的出口设备。公司内部有两个部门&#xff0c;分别划分在vlan10和vlan20。现在需要实现以下需求&#xff1a; 由于汇聚层和接入层…

竞赛选题 多目标跟踪算法 实时检测 - opencv 深度学习 机器视觉

文章目录 0 前言2 先上成果3 多目标跟踪的两种方法3.1 方法13.2 方法2 4 Tracking By Detecting的跟踪过程4.1 存在的问题4.2 基于轨迹预测的跟踪方式 5 训练代码6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习多目标跟踪 …

MYSQL8解压版 windows 主从部署步骤及配置(包含配置文件,教程文件,免积分下载)

MYSQL8解压版 windows 主从部署步骤及配置 一.安装MSYQL 这里只讲大概,详细步骤、my.ini文件、安装包等会在页尾文件中(正常情况按首个mysql安装,只是名字有区别) 1.主库my.ini配置 [mysqld] #典型的值是5-6GB(8GB内存)&#xff0c;8-11GB(16GB内存), 20-25GB(32GB内存)&…

行业追踪,2023-09-27

自动复盘 2023-09-27 凡所有相&#xff0c;皆是虚妄。若见诸相非相&#xff0c;即见如来。 k 线图是最好的老师&#xff0c;每天持续发布板块的rps排名&#xff0c;追踪板块&#xff0c;板块来开仓&#xff0c;板块去清仓&#xff0c;丢弃自以为是的想法&#xff0c;板块去留让…

推荐一个react拖拽排序的库,@dnd-kit

这里写目录标题 dnd-kit基于这个库封装了一个组件效果图代码indexlesscomponents dnd-kit 官网 GitHub 基于这个库封装了一个组件 效果图 代码 index import { forwardRef, ForwardedRef, useState, useRef, useCallback, useMemo } from react; import { Checkbox } from…