概述
就知道在Verilog HDL中 阻塞赋值"="和 非阻塞赋值"<="有着很大的不同。
对于我这样的初学者而言,首先要掌握可综合风格的Verilog模块编程的7个原则,并且牢记,才能在综合布局布线的仿真中避免出现竞争冒险现象。
(1) 时序电路建模时,用非阻塞赋值。
(2) 锁存器电路建模时,用非阻塞赋值。
(3) 用always块建立组合逻辑模型时,用阻塞赋值。
(4) 在同一个always块中建立时序和组合逻辑电路时,用非阻塞赋值。
(5) 在同一个always块中不要既用非阻塞赋值又用阻塞赋值。
(6) 不要在一个以上的always块中为同一个变量赋值。
(7) 在赋值时不要使用 #0延时。
这样做的目的是为了使综合前仿真和综合后仿真一致。在很多时候,用"="或者是"<="实际上对应的是不同的硬件电路,这点一定要十分清楚。
阻塞赋值(=):
我们先做下面定义:RHS—赋值等号右边的表达式,LHS—赋值等号左边的表达式。在串行语句块中,阻塞赋值语句按照它们在块中的排列顺序依次执行,即前一条语句没有完成赋值之前,后面的语句不可能被执行,换言之,后面的语句被阻塞了。阻塞赋值的执行可以认为只有一个步骤的操作,即计算RHS并更新LHS,此时不允许有来自任何其他Verilog语句的干扰。所谓阻塞的概念是指在同一个always块中,其后面的赋值语句从概念上是在前一条赋值语句结束后开始赋值的。有句话我一直没读懂:从理论上讲,它与后面的赋值语句只有概念上的先后,而无实质上的延时。
例如:
begin
B = A;
C = B + 1;
end
首先第一条语句执行,将A的值赋给B,接着执行第二条语句,将B+1(即A加1),并赋给C。也就是说C = A + 1。
非阻塞赋值(<=):
非阻塞语句的执行过程是:首先计算语句块内部所有右边表达式(RHS)的值,然后完成对左边寄存器变量的赋值操作,例如,下面两条非阻塞赋值语句的执行过程是:先计算右边表达式的值并暂存在一个暂存器中,A的值被保存在一个寄存器中,而B+1的值被保存在另一个寄存器中,在begin和end之间所有语句的右边表达式都被计算并存储完后,对左边的寄存器变量的赋值才会进行。这样C得到的是B的原始值而不是A加一。
begin
B <= A;
C <= B +1;
end
如果我们想让两个最基本的D触发器串联,我们用阻塞和非阻塞赋值看看结果有什么不同
阻塞和非阻塞的不同造成了电路上巨大的不同,因此他们的差别应该牢记。
我们在从仿真(Simulation)的角度去看一下,在输出结果上有造成什么样的不同,我们有同样的的testbench。
仿真波形如下:
可以看到,在阻塞赋值的情况下当时钟上升沿来的时候读取输入iD的值,并且输出oQA和oQB的值应该是一样的,从波形中我们可以看出输出oQA和oQB的波形是完全一样的。
在非阻塞赋值的情况下,它是先计算 iD 和 oQA的值,开始 iD的值为1, oQA的值是不定的,所以oQA被赋为1, 而oQB还是被赋为不定值,两者的波形不一致。
阻塞和非阻塞的学习随着以后的深入还得深刻理解,在用时要遵循规则,避免麻烦。
----------------------------------------------------------------------------------------------------------
总结一下,
在verilog中,阻塞赋值是按照时间逻辑进行的,即,逐步进行,每一个语句,等到上一个语句赋值结束后再进行赋值。
而在同一个always模块中,所有的非阻塞赋值都是同时赋值的,无所谓时间先后。及,并行结构。也正因如此,非阻塞赋值能根据输入逐步赋值。
这里还找到一个很好的例子:
[例1]. 用阻塞赋值的反馈振荡器
module fbosc1 (y1, y2, clk, rst);
output y1, y2;
input clk, rst;
reg y1, y2;
always @(posedge clk or posedge rst)
if (rst) y1 = 0; // reset
else y1 = y2;
always @(posedge clk or posedge rst)
if (rst) y2 = 1; // preset
else y2 = y1;
endmodule
按照IEEE Verilog 的标准,上例中两个always块是并行执行的,与前后次序无关。如果前一个always块的复位信号先到0时刻,则y1 和y2都会取1,而如果后一个always块的复位信号先到0时刻,则y1 和y2都会取0。这清楚地说明这个Verilog模块是不稳定的会产生冒险和竞争的情况。这样一个模块的波形图是这样的:
[例2]. 用非阻塞赋值的反馈振荡器
module fbosc2 (y1, y2, clk, rst);
output y1, y2;
input clk, rst;
reg y1, y2;
always @(posedge clk or posedge rst)
if (rst) y1 <= 0; // reset
else y1 <= y2;
always @(posedge clk or posedge rst)
if (rst) y2 <= 1; // preset
else y2 <= y1;
endmodule
同样,按照IEEE Verilog 的标准,上例中两个always块是并行执行的,与前后次序无关。无论哪一个always块的复位信号先到, 两个always块中的非阻塞赋值都在赋值开始时刻计算RHS表达式,,而在结束时刻才更新LHS表达式。所以这两个always块在复位信号到来后,在always块结束时 y1为0而y2为1是确定的。从用户的角度看这两个非阻塞赋值正好是并行执行的。这样的一个模块的波形图就是:
最后
以上就是细心小猫咪为你收集整理的阻塞(=)和非阻塞赋值(<=)的不同的全部内容,希望文章能够帮你解决阻塞(=)和非阻塞赋值(<=)的不同所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复