说明
翻译自:FPGA Prototyping By Verilog Examples: Xilinx Spartan-3 Version的第7章第一节
内容
阻塞赋值VS非阻塞赋值
有两种赋值语句被用在always块内:阻塞赋值与非阻塞赋值。关于阻塞与非阻塞复制有3条简单的准则:
- 将电路分为两部分:寄存器电路和组合电路
- 在寄存器电路中使用非阻塞赋值
- 在组合电路中使用阻塞赋值
1 概览
阻塞赋值 基本语法如下:
当该条语句被执行时,右手边的表达式将被赋给左手边的变量,期间不允许其他语句的干扰。因此,就阻塞了其他语句,直到该条语句执行完毕为止。阻塞赋值的行为与C语言中的变量赋值类似。
非阻塞赋值 基本语法如下:
非阻塞赋值的行为非常令人难以琢磨。当always块被激活(在time step的开始),右手边的表达式被赋初值。当运行到always块的结尾(即time step的结尾),运算所得的值被赋给左手边的变量。
以x变量执行非阻塞赋值为例。因为Verilog模型的实际流程比较复杂,我们将非阻塞赋值的行为翻译成一下几个步骤:
- 在alway块的开始,x值传递给x_entry;
- 右手边的变量x的值被x_entry取代;
- 左手边变量x的值被x_exit取代;
- 在always块的结束,x_exit的值传递给x。
在下面的代码片段内,上述四个步骤被呈现在代码的注释中。
| 3 |
y <= x & ... // y = x_entry & ... |
| 4 |
x <= ... // x_exit = ... |
范例 为了了解阻塞赋值和非阻塞赋值的区别,我们用三输入的的电路来做讨论。
代码1 使用阻塞赋值的电路
阻塞赋值的欣慰类似于C语言中的顺序赋值。y最终得到的值为a & b & c。注意,此代码仅用于示范,使用顺序语义学来描述电路是比较差劲的行为。
下面给出的代码,其中的阻塞赋值被替换为非阻塞赋值。代码注释详细说明了y的赋值动作。
代码2 使用非阻塞赋值的电路
| 01 |
module and_nonblocking |
| 12 |
y <= y & b; // y_exit = y_entry & b |
| 13 |
y <= y & c; // y_exit = y_entry & c |
注意always块内的前2条语句将不会产生任何效果。上述always块等价与: