版权声明:本文为CSDN博主「单片机学习经验交流」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_20222919/article/details/107576195
在Verilog语言中经常要用到延时语句,延时语句添加的位置不同,输出的结果就会不同。今天就来分析比较一下延时语句在不同位置时,对赋值语句的影响。
一、阻塞式左延时赋值
文件代码:
`timescale 1ns/1ns
module delay(
a,
b,
sum
);
input [3:0] a;
input [3:0] b;
output reg [4:0] sum;
//阻塞式左延时赋值语句
always @(*) begin
#12 sum = a + b;
end
endmodule
测试代码
`timescale 1ns/1ns
module delay_tb;
reg [3:0] a;
reg [3:0] b;
wire [4:0] sum;
delay delay(
.a(a),
.b(b),
.sum(sum)
);
initial begin
a = 0; b = 0;
#5;
a = 1; b = 1;
#5;
a = 2; b = 2;
#5;
a = 3; b = 3;
#5;
a = 4; b = 4;
#5;
a = 5; b = 5;
#5;
a = 6; b = 6;
#5;
a = 7; b = 7;
#5;
a = 8; b = 8;
#5;
a = 9; b = 9;
#5;
a = 10; b = 10;
#5;
#30;
$stop;
end
endmodule
a、b的值5ns改变一次,通过阻塞式语句读取a、b的和,延时语句加在左侧。
仿真波形如下:
通过波形可以看到初始化之后,a、b的值每5ns变化一次,在第12ns时,sum输出a+b的和为4,说明在延时时间到了之后,才取a和b的值计算,然后更新给sum。执行完阻塞赋值语句后,程序退出always块,等待下一次数据变化。在第15ns时,a、b的值又发生了变化,延时等待12ns后,在第27ns取出a和b的值并计算,然后更新给sum。也就是说延时语句在阻塞赋值左侧时,在延时时候到了之后,系统更新右值同时赋值给左值。sum总是为a和b最新值的和。
二、阻塞式右延时赋值
代码修改如下:
`timescale 1ns/1ns
module delay(
a,
b,
sum
);
input [3:0] a;
input [3:0] b;
output reg [4:0] sum;
//阻塞式右延时赋值语句
always @(*) begin
sum = #12 a + b;
end
endmodule
测试代码保持不变,仿真波形如下:
通过仿真波形可以看出,在第12ns的时候,sum输出值为0,说明初始化之后,程序进入always块中计算a+b值,延时等待12ns之后,再将值更新给sum。虽然此时a和b的值都变为了2。但是计算的依然是12ns之前的值。计算完成之后推出always块,当第15ns时,a、b的值发生了变化,又进入always块中计算此时a+b的值,等待12ns之后,也就是在第27ns时将结果6赋值给sum。由此可以看出,当延时语句在阻塞赋值右边时,更新的是延时之前的值。在延时等待过程中数据发生变化时将会被忽略。
三、非阻塞式左延时赋值
修改代码如下:
`timescale 1ns/1ns
module delay(
a,
b,
sum
);
input [3:0] a;
input [3:0] b;
output reg [4:0] sum;
//非阻塞式左延时赋值语句
always @(*) begin
#12 sum <= a + b;
end
endmodule
测试代码不变,仿真波形如下:
通过波形可以看到,系统初始化之后a、b的值5ns变化一次,在第12ns时sum结果为4。说明计算的是a、b的最新值。在第15ns时,a、b的值发生了更新,延时12ns后,也就是第27ns,读取a、b当前最新值,计算累加和赋值给sum输出。由此可看到延时加在非阻塞赋值左侧时,在延时时间到了之后,读取a、b最新值并计算累加和。
四、非阻塞式右延时赋值
修改代码如下:
`timescale 1ns/1ns
module delay(
a,
b,
sum
);
input [3:0] a;
input [3:0] b;
output reg [4:0] sum;
//非阻塞式右延时赋值语句
always @(*) begin
sum <= #12 a + b;
end
endmodule
测试代码不变,仿真波形如下:
通过波形可以看出,初始化之后a、b的值每5ns更新一次,在第12ns时sum值为0,说明计算的是0ns时a、b的值。在第17ns时,sum值为2,说明计算的是第5ns时,a、b的值。后面的值以此类推,说明sum的值统一延迟的12ns。但是每次a、b的变化都被捕捉到了。说明延时加在非阻塞赋值的右侧时,输出结果会统一延迟。但是不会漏掉任何一次数据变化。
五、连续赋值
修改代码如下:
`timescale 1ns/1ns
module delay(
a,
b,
sum
);
input [3:0] a;
input [3:0] b;
output [4:0] sum;
assign #12 sum = a + b;
endmodule
测试不变,仿真波形如下:
由波形图可以看出,当a、b停止变化后12ns,sum才会输出最后一次a+b的值。
通过上面几种延时方法比较,可以看出,延时在不同语句中不同位置,输出结果也不相同。