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

这篇具有很好参考价值的文章主要介绍了Verilog仿真文件中的阻塞和非阻塞赋值问题探讨。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


在 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后一个时钟周期高。同时还测试了该情况下的“|”、“+”、“^”运算均正确。

Verilog仿真文件中的阻塞和非阻塞赋值问题探讨,Verilog语法,fpga开发,Verilog,阻塞与非阻塞,仿真注意事项

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后一个时钟周期高。有错误,同时还测试了该情况下的“|”、“+”、“^”运算均错误。

Verilog仿真文件中的阻塞和非阻塞赋值问题探讨,Verilog语法,fpga开发,Verilog,阻塞与非阻塞,仿真注意事项

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后一个时钟周期高。有错误,同时还测试了该情况下的“|”、“+”、“^”运算均错误。

Verilog仿真文件中的阻塞和非阻塞赋值问题探讨,Verilog语法,fpga开发,Verilog,阻塞与非阻塞,仿真注意事项

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同,但测试了该情况下的“|”、“+”、“^”运算均有错误。

Verilog仿真文件中的阻塞和非阻塞赋值问题探讨,Verilog语法,fpga开发,Verilog,阻塞与非阻塞,仿真注意事项

二、时钟初始值为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后一个时钟周期高。同时还测试了该情况下的“|”、“+”、“^”运算均正确。

Verilog仿真文件中的阻塞和非阻塞赋值问题探讨,Verilog语法,fpga开发,Verilog,阻塞与非阻塞,仿真注意事项

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后一个时钟周期高。有错误,同时还测试了该情况下的“|”、“+”、“^”运算均错误。

Verilog仿真文件中的阻塞和非阻塞赋值问题探讨,Verilog语法,fpga开发,Verilog,阻塞与非阻塞,仿真注意事项

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后一个时钟周期高。有错误,同时还测试了该情况下的“|”、“+”、“^”运算均错误。

Verilog仿真文件中的阻塞和非阻塞赋值问题探讨,Verilog语法,fpga开发,Verilog,阻塞与非阻塞,仿真注意事项

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后一个时钟周期高。有错误,同时还测试了该情况下的“|”、“+”、“^”运算均错误。

Verilog仿真文件中的阻塞和非阻塞赋值问题探讨,Verilog语法,fpga开发,Verilog,阻塞与非阻塞,仿真注意事项

结论

时钟初始值为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

参考资料

仿真文件中的阻塞和非阻塞文章来源地址https://www.toymoban.com/news/detail-729691.html

到了这里,关于Verilog仿真文件中的阻塞和非阻塞赋值问题探讨的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 什么是Java中的阻塞队列和非阻塞队列?

    首先,让我们从基础概念开始。在计算机科学中,数据结构可以分为两种:队列和管道。队列是一种先进先出(FIFO)的数据结构,你可以想象成排队买电影票的情况。你加入队伍的时候,你可以决定站在哪里,但是一旦决定站在哪里,你就不能改变位置。而一旦你到达队尾,

    2024年02月14日
    浏览(44)
  • Verilog中的force语句用来强制更改信号的值,特别适用于仿真和调试。本文将深入探讨force语句在FPGA开发中的应用和注意事项。

    Verilog中的force语句用来强制更改信号的值,特别适用于仿真和调试。本文将深入探讨force语句在FPGA开发中的应用和注意事项。 首先,我们需要了解force语句的语法。其基本格式为force [time] signal = value。其中,time是可选参数,表示在何时开始强制更改信号的值;signal是要更改的

    2024年02月12日
    浏览(95)
  • socket 的阻塞模式和非阻塞模式

    对 socket 在阻塞和非阻塞模式下的各个函数的行为差别深入的理解是掌握网络编程的基本要求之一,是重点也是难点。 阻塞和非阻塞模式下,我们常讨论的具有不同行为表现的 socket 函数一般有如下几个,见下表: connect accept send (Linux 平台上对 socket 进行操作时也包括 write 函

    2024年02月04日
    浏览(45)
  • Verilog force语句详解:FPGA中的信号强制赋值

    Verilog force语句详解:FPGA中的信号强制赋值 在FPGA开发中,时序分析和调试是非常重要的一部分。其中,对于一些信号的调试,我们需要准确地模拟不同的情况来检测其工作状态。这时,Verilog force语句就起到了重要的作用。 force语句可以使信号立即进行强制赋值操作,在仿真

    2024年02月06日
    浏览(39)
  • Verilog语法——6.测试文件使用for和random语句进行赋值

    参考资料 【明德扬_verilog零基础入门语法HDL仿真快速掌握-手把手教你写FPGA/ASIC代码设计流程中的应用】 题目要求: 涉及到for语句的赋值语句: 小贴士 verilog不支持c/c++中的自增语句i++,因此只能写成i=i+1 for语句应该用在initial begin(…) end中,此处只展示关键代码 6.2.1 random语句

    2024年01月17日
    浏览(42)
  • 关于FPGA(Vivado)后仿真相关问题的探讨

            FPGA后仿真时,相比于功能仿真增加了门延时和布线延时,相对于门级仿真增加了布线延时,因此后仿真相比于功能仿真具有不同的特点。         下面所示的代码在功能仿真时是正确的的,但在后仿真时,似乎是有问题的。功能很简单,当delay为高电平时,a与

    2024年02月08日
    浏览(49)
  • 5.1阻塞和非阻塞、同步和异步 5.2Unix、Linux上的五种IO模型

    典型的一次IO的两个阶段是什么?数据就绪和数据读写 数据就绪:根据IO操作的就绪状态 阻塞 非阻塞 数据读写:根据应用程序和内核的交互方式 同步 异步 陈硕:在处理IO的时候,阻塞和非阻塞都是同步IO,只有使用了特殊的API才是异步IO。 一个典型的网络接口调用,分为两

    2024年02月12日
    浏览(41)
  • 【FPGA零基础学习之旅#8】阻塞赋值与非阻塞赋值讲解

    🎉欢迎来到FPGA专栏~阻塞赋值与非阻塞赋值 ☆* o(≧▽≦)o *☆ 嗨 ~我是 小夏与酒 🍹 ✨ 博客主页: 小夏与酒的博客 🎈该系列 文章专栏: FPGA学习之旅 文章作者技术和水平有限,如果文中出现错误,希望大家能指正🙏 📜 欢迎大家关注! ❤️ 阻塞赋值 ,操作符为 “ = ”

    2024年02月10日
    浏览(44)
  • I.MX6ULL_Linux_驱动篇(39) 阻塞和非阻塞IO

    阻塞和非阻塞 IO 是 Linux 驱动开发里面很常见的两种设备访问模式,在编写驱动的时候一定要考虑到阻塞和非阻塞。本章我们就来学习一下阻塞和非阻塞 IO,以及如何在驱动程序中处理阻塞与非阻塞,如何在驱动程序使用等待队列和 poll 机制。 阻塞和非阻塞简介 这里的“IO”

    2024年02月12日
    浏览(41)
  • Verilog 基础仿真文件编写

    在学习Verilog的过程中,相信大家都陷入了一个怪圈,那就是对于写模块相当拿手,但是一到编写仿真激励的时候就开始“抓瞎”,不知从何写起,本人也是一样。发现问题就要积极解决问题,因此,总结一篇博客(今后会不断更新)来介绍常用的一些基础仿真语句,供自己总

    2024年02月03日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包