阻塞赋值和非阻塞赋值

来源:互联网 发布:ubuntu联网 编辑:程序博客网 时间:2024/06/06 01:02

阻塞赋值
阻塞赋值操作符用等号(即 = )表示。为什么称这种赋值为阻塞赋值呢?这是因为在赋值时先计算等号右手方向(RHS)部分的值,这时赋值语句不允许任何别的Verilog 语句的干扰,直到现行的赋值完成时刻,即把RHS 赋值给 LHS 的时刻,它才允许别的赋值语句的执行。一般可综合的阻塞赋值操作在RHS 不能设定有延迟,(即使是零延迟也不允许)。从理论上讲,它与后面的赋值语句只有概念上的先后,而无实质上的延迟。 若在RHS 加上延迟,则在延迟期间会阻止赋值语句的执行, 延迟后才执行赋值,这种赋值语句是不可综合的,在需要综合的模块设计中不可使用这种风格的代码。阻塞赋值的执行可以认为是只有一个步骤的操作:计算RHS 并更新LHS。

非阻塞赋值
非阻塞赋值操作符用小于等于号 (即 <= )表示。为什么称这种赋值为非阻塞赋值?这是因为在赋值操作时刻开始时计算非阻塞赋值符的RHS 表达式,赋值操作时刻结束时更新LHS。在计算非阻塞赋值的RHS表达式和更新LHS 期间,其他的Verilog 语句,包括其他的Verilog 非阻塞赋值语句都能同时计算RHS表达式和更新LHS。非阻塞赋值允许其他的Verilog 语句同时进行操作。非阻塞赋值的操作可以看作为两个步骤的过程:
1) 在赋值时刻开始时,计算非阻塞赋值RHS 表达式。
2) 在赋值时刻结束时,更新非阻塞赋值LHS 表达式。

用非阻塞赋值的反馈振荡器
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 是确定的。从用户的角度看这两个非阻塞赋值正好是并行执行的。

在编写时牢记这八个要点可以为绝大多数的Verilog 用户解决在综合后仿真中出现的90-100% 的冒险竞争问题。
1) 时序电路建模时,用非阻塞赋值。
2) 锁存器电路建模时,用非阻塞赋值。
3) 用always 块建立组合逻辑模型时,用阻塞赋值。
4) 在同一个always 块中建立时序和组合逻辑电路时,用非阻塞赋值。
5) 在同一个always 块中不要既用非阻塞赋值又用阻塞赋值。
6) 不要在一个以上的always 块中为同一个变量赋值。
7) 用$strobe 系统任务来显示用非阻塞赋值的变量值
8) 在赋值时不要使用 #0 延迟

非阻塞赋值只能用在always和initial等描述进程的语句中,非阻塞赋值时,进程中赋值语句先计算右值,算完后不立即赋给左值,而是同时计算下一条赋值语句的右值,等到所有该进程的右值计算结束后,在一起赋给左值。

阻塞赋值则是先计算一个右值,同时赋给左值,然后计算下一个赋值语句的右值,在赋给左值,以此类推。

注:本文摘自【夏宇闻Verilog经典教程】

0 0
原创粉丝点击