时序仿真中阻塞赋值和非阻塞赋值的区别
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;
仿真波形如下:
可以看到,当处于第2个时钟上升沿时,c为a和b变化后的值按位与的值。
2.2 非阻塞赋值分析
激励源a和b的产生用非阻塞赋值:
always #(`clk_period/2) a <= {$random}%256;
always #(`clk_period/2) b <= {$random}%256;
仿真波形如下:
可以看到,当处于第2个时钟上升沿时,c为a和b变化前的值按位与的值。
3 实验结论
若时钟和激励源同时变化:
(1)如果激励源使用阻塞赋值,仿真工具会认为时钟和激励源同时变化,则上升治会采集到激励源变化之后的值。
(2)如果激励源使用非阻塞赋值,仿真工具会认为激励源晚于时钟变化,则上升治会采集到激励源变化之前的值。
非阻塞赋值发生赋值的时刻晚于阻塞赋值0ns。
仿真时,激励源的赋值需使用非阻塞赋值。