1、阻塞赋值和非阻塞赋值对应着两种不同的电路结构
(1)阻塞赋值对应的电路结构往往与触发沿没有关系,只与输入电平的变化有关系。
(2)非阻塞赋值对应的电路结构往往与触发沿有关系,只有在触发沿时才有可能发生赋值的变化。
2、正确使用赋值操作避免在Verlog仿真时出现竞争和冒险的现象
在编写代码时首先要遵循下面这两个要点:
(1)在描述组合逻辑的always块中用阻塞赋值,则综合成组合逻辑的电路结构。
(2)在描述时序逻辑的always块中用非阻塞赋值,则综合成时序逻辑的电路结构。
为什么要遵循这两个要点呢?这是因为要使综合前仿真和综合后仿真一致的缘故。如果不按照上面这两个要点来编写Verilog代码,也有可能综合出正确的逻辑,但前后仿真的结果就会不一致。
IEEE Verilog标准定义了有些语句有确定的执行时间,有些语句没有确定的执行时间。若有两条或两条以上语句准备在同一时刻执行,但由于语句的排列顺序不同(而这种排列顺序的不同是IEEE Verilog标准所允许的),却产生的不同的输出结果,这就造成了Verilog模块竞争和冒险现象的原因。为了避免产生竞争,理解阻塞和非阻塞赋值在执行时间上的差别是至关重要的。
3、阻塞赋值和非阻塞赋值详细介绍
3.1、阻塞赋值
阻塞赋值操作符用等号(即 = )表示。为什么称这种赋值为阻塞赋值呢?这是因为在赋值时先计算等号右手方向(RHS)部分的值,只是赋值语句不允许任何别的Verilog语句的干扰,直到现行的赋值完成时刻,即把RHS赋值给LHS的时刻,它才允许别的赋值语句的执行。一般可综合的阻塞赋值操作在RHS不能设定有延迟的(即使是零延迟也不允许)。从理论上讲,它与后面的阻塞赋值只有概念上的先后,而无实质上的延迟。若在RHS上加延迟,则在延迟期间会阻止赋值语句的执行,延迟后才能执行赋值,这种赋值语句是不可综合的,在需要综合的模块设计中不可使用这种风格的代码。
阻塞赋值的执行可以认为是只有一个步骤的操作,即计算RHS并更新LHS,此时不能允许有来自任何其他Verilog语句的干扰。所谓阻塞的概念是指同一个always块中,其后面的赋值语句从概念上(即使不设定延迟)是在前一句赋值语句结束后再开始赋值的。
如果在一个过程块中阻塞赋值的RHS变量正好是另一个过程块中阻塞赋值的LHS变量,这两个过程块又用同一个时钟触发,这时阻塞赋值操作会出现问题,即如果阻塞赋值的顺序安排不好,就会出现竞争。若这两个阻塞赋值操作用同一个时钟沿触发,则执行的顺序是无法确定的。
举例如下:
module fboscl (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块是并行执行的,若复位信号已从1到0,且例中上面的always块的有效时钟沿比下面的always块的时钟沿早几个皮秒(由时钟偏差造成)到达,则y1和y2都会取1;而若下面的那个always块的有效时钟沿早几个皮秒到达,则y1和y2都会取0。这清楚的说明这个Verilog模块是不稳定的,必定会产生竞争和冒险的情况。
3.2、非阻塞赋值
非阻塞赋值操作符用小于等于号(即 <= )表示。为什么称这种赋值为非阻塞赋值?这是因为在赋值操作时刻开始时计算非阻塞赋值符的RHS表达式,赋值操作结束时刻才更新LHS。在计算非阻塞赋值的RHS表达式和更新LHS期间,其他的Verilog语句,包括其他的Verilog非阻塞赋值语句都能同时计算RHS表达式和更新LHS。非阻塞赋值允许其他的Verilog语句同时进行操作。非阻塞赋值的操作过程可以看作两个步骤:
(1)在赋值开始时刻,计算非阻塞赋值RHS表达式;
(2)在赋值结束时刻,更新非阻塞赋值LHS表达式。
非阻塞赋值操作只能用于对寄存器类型变量进行赋值,因此只能用于在“initial”块和“always”块等过程块中,而非阻塞赋值不允许用于连续赋值。
举例如下:
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; //预置值
else y1 <= y2;
always@(posedge clk or posedge rst)
if(rst) y2 <= 1; //预置值
else y2 <= y1;
endmodule
同样,按照 IEEE Verilog的标准,上例中两个always块是并行执行的,与先后顺序无关。复位信号回到0后,无论哪一个always块的有效沿先到,两个always块中的非阻塞赋值都在赋值开始时刻计算RHS表达式,而在结束时刻才更新LHS表达式。所以,复位信号从1回到0后,无论哪个always块的有效时钟沿早到几个皮秒,y1为1,而y2为0是确定的,因为实质上y1被赋的y2值是由rst正跳变沿决定的,而y2被赋的y1也是由rst正跳变沿决定的(若以后rst继续保持为0,时钟信号不断重复,则每次被赋值的y1和y2都是由上一个周期的时钟有效沿确定的),从用户的角度看这两个非阻塞赋值好像是并行执行的。
4、Verilog模块编程要点
在编写Verilog代码时必须牢记这8个要点,才能在综合布局布线后的仿真中避免出现j竞争冒险现象。
(1)时序电路电路建模时,用非阻塞赋值。
(2)锁存器电路建模时,用非阻塞赋值。
(3)用always块建立组合逻辑模型时,用阻塞赋值。
(4)在同一个always块中建立时序和组合逻辑电路时,用非阻塞赋值。
(5)在同一个always块中不要既用非阻塞赋值又用阻塞赋值。
(6)不要在一个以上的always块中为同一个变量赋值。
(7)用$strobe系统任务来显示用非阻塞赋值的变量值。
(8)在赋值时不要使用#0延迟。
5、什么是竞争与冒险
竞争:在组合电路中,信号经由不同的路径到达某一会合点的时间不一致的现象。
冒险:由于竞争而引起电路输出发生瞬间错误,表现为输出端出现了理论上没有的窄脉冲。
~OVER~