这个是非阻塞赋值,b的值为0,
仿真结果也是0module TOP(
input clk,
input rst,
output reg b
);
reg a,c;
always@(posedge clk or negedge rst)
begin
if(~rst)
begin
a <=0;
end
else
begin
a <=a+1;
b <=a-c;
end
end
always@(posedge clk or negedge rst)
begin
if(~rst)
begin
c <= 0;
end
else
c <= a;
end
endmodule
这个是阻塞赋值的话,阻塞赋值是有先后顺序的,先计算a= a+1;计算完了再计算b= a-c;所以按照理论上来分析应该b= 1但是实际
仿真结果为0;
module TOP(
input clk,
input rst,
output reg b
);
reg a,c;
always@(posedge clk or negedge rst)
begin
if(~rst)
begin
a =0;
end
else
begin
a =a+1;
b =a-c;
end
end
always@(posedge clk or negedge rst)
begin
if(~rst)
begin
c = 0;
end
else
c = a;
end
endmodule
但是实际仿真结果是b依旧等于0
所以按照下边的理论来分析的话,就与仿真结果矛盾了,这是怎么回事呢??
阻塞与非阻塞赋值的语言结构是Verilog语言中最难理解的概念之一。
有这样的两个要点:
(1)在描述组合逻辑的always块中用阻塞赋值,则综合成组合逻辑的
威廉希尔官方网站
结构;
(2)在描述时序逻辑的always块中用非阻塞赋值,则综合成时序逻辑的威廉希尔官方网站
结构。
这样做的原因是:
这是因为要使综合前仿真和综合后仿真一致的缘故。
为了更好地理解上述要点,我们需要对Verilog语言中的阻塞赋值和非阻塞赋值的功能和执行时间上的差别有深入的理解。我们定义下面的两个关键字:
RHS——方程式右手方向的表达式或变量可分别缩写成 RHS表达式或RHS变量;
LHS ——方程式左手方向的表达式或变量可分别缩写成LHS 表达式或LHS变量。
IEEE Verilog标准定义了有些语句有确定的执行时间,有些语句没有确定的执行时间。若有两条或两条以上的语句准备在同一时间执行,但由于语句的排列顺序不同,却产生了不同的输出结果。这就是造成Verilog模块冒险和竞争的原因。为了避免产生竞争,理解阻塞和非阻塞赋值在执行时间上的差别是至关重要的。
1、阻塞赋值
阻塞赋值用等号(=)表示。为什么称这种赋值为阻塞赋值呢?因为在赋值时先计算RHS部分的值,这是
赋值语句不允许任何别的Verilog语言的干扰,直到现行的赋值完成时刻,即把RHS赋值给LHS的时刻,它才允许别的
赋值语句的执行。
一般可综合的赋值操作在RHS不能设定延时(即使是0延时也不允许)。从理论上讲,它与后面的
赋值语句只有概念上的先后,而无实质的延迟。若在RHS上加延迟,则在
延迟时间会阻止赋值语句的执行,延迟后才进行赋值,这种赋值语句是不可综合的,在需要综合的模块设计中不可使用这种风格的代码。
所谓阻塞的概念是指在同一个always块中,其后面的赋值语句从概念上是在前一句赋值语句结束之后再开始赋值的。
2、非阻塞赋值
非阻塞赋值用小于等于号(<=)表示。为什么称这种赋值为非阻塞赋值呢?因为在赋值开始时计算RHS表达式,赋值操作时刻结束时更新LHS。在计算非阻塞赋值的RHS表达式和更新LHS期间,其他的Verilog语句,包括其他的非阻塞赋值语句都可能计算RHS表达式和更新LHS。非阻塞赋值允许其他的Verilog语句同时进行操作。非阻塞赋值可以看作两个步骤的过程:
(1)在赋值开始时,计算非阻塞赋值RHS表达式;
(2)在赋值结束时,更新非阻塞赋值LHS表达式。
非阻塞赋值操作只能用于对寄存器类型变量进行赋值,因此只能用在“ini
tial”块和“always”块等过程块中,而非阻塞赋值不允许用于连续赋值。