时序仿真中阻塞赋值和非阻塞赋值的区别

1 实验设置

1.1 功能模块编写

设置8位的变量c,通过非阻塞赋值的方式,将同样为8位的变量a和变量b之间按位与的结果赋值给c,代码如下:

module test_a4_and_b4(
	clk,
	a,
	b,
	c,
);

	input 	wire 		clk;
	input	wire [7:0]	a;
	input	wire [7:0]	b;

	output 	reg  [7:0]	c = 0;

	//非阻塞赋值
	always @ (posedge clk) begin
		c <= a & b;
	end

endmodule

1.2 激励代码编写

设置a和b的激励为随机8位0~255的数据,时钟用阻塞赋值,激励源a和b的产生分别用阻塞赋值和非阻塞赋值,数据变化时刻和上升沿同步。

`timescale 1ns/1ns
`define clk_period 20

module test_a4_and_b4_tb;

 	reg			clk;
	reg	 [7:0]	a;
	reg  [7:0]	b;

	wire [7:0]	c;

	test_a4_and_b4 test_a4_and_b4_inst(
		.clk 	(clk),
		.a 		(a),
		.b 		(b),
		.c 		(c)
	);

	always #(`clk_period/2) clk = ~clk;

	always #(`clk_period/2) a = {$random}%256;
	always #(`clk_period/2) b = {$random}%256;

	initial begin
		clk = 0;
		a = 0;
		b = 0;
	end

endmodule

2 实验分析

2.1 阻塞赋值分析

激励源a和b的产生用阻塞赋值:

	always #(`clk_period/2) a = {$random}%256;
	always #(`clk_period/2) b = {$random}%256;

仿真波形如下:

image-20240510213726797

可以看到,当处于第2个时钟上升沿时,c为a和b变化后的值按位与的值。

2.2 非阻塞赋值分析

激励源a和b的产生用非阻塞赋值:

	always #(`clk_period/2) a <= {$random}%256;
	always #(`clk_period/2) b <= {$random}%256;

仿真波形如下:

image-20240510214459798

可以看到,当处于第2个时钟上升沿时,c为a和b变化前的值按位与的值。

3 实验结论

若时钟和激励源同时变化:

(1)如果激励源使用阻塞赋值,仿真工具会认为时钟和激励源同时变化,则上升治会采集到激励源变化之后的值。

(2)如果激励源使用非阻塞赋值,仿真工具会认为激励源晚于时钟变化,则上升治会采集到激励源变化之前的值。

非阻塞赋值发生赋值的时刻晚于阻塞赋值0ns

仿真时,激励源的赋值需使用非阻塞赋值。

posted @ 2024-05-10 22:00  Yamada_Ryo  阅读(31)  评论(0编辑  收藏  举报