过程赋值以always”, “initial,” “task,” 和“function.”等程序块的形式出现。
过程赋值分为以下几类:
- 阻塞赋值
- 非阻塞赋值
阻塞赋值
阻塞赋值语句按顺序执行。在当前赋值操作完成之前,后面语句停止执行。
因此,让我们用一个例子来理解阻塞赋值。
module blocking_assignment;
//variables declaration
int a,b;
initial begin
$display("-----------------------------------------------------------------");
//initializing a and b
a = 10;
b = 15;
//displaying initial value of a and b
$display("\tBefore Assignment :: Value of a is %0d",a);
$display("\tBefore Assignment :: Value of b is %0d",b);
a = b;
b = 20;
$display("\tAfter Assignment :: Value of a is %0d",a);
$display("\tAfter Assignment :: Value of b is %0d",b);
$display("-----------------------------------------------------------------");
end
endmodule
下图显示了上述阻塞赋值代码的输出。
非阻塞赋值
当多个变量赋值可以在同一时间step内进行时,可以使用非阻塞赋值语句,而不考虑顺序或相互依赖。
非阻塞语法是:
变量名称 <= [延迟或事件控制] 表达式。
非阻塞赋值运算符是<=。非阻塞赋值运算符与关系运算符小于等于相同。
非阻塞赋值可以分为两个步骤:
1.在timing step开始时,评估非阻塞语句的RHS。
2.在timing step后,评估非阻塞语句的LHS。
考虑以下示例。我们将将阻塞与非阻塞进行比较:
module nblock;
logic a, b, c, d, e, f, temp;
initial begin
a = 0; b = 1;
//Blocking assignment
a = b;
c = a;
$display($stime,,, "Blocking a=%b b=%b c=%b", a, b, c);
end
initial begin
d = 0; e = 1;
//Non-Blocking assignment
d <= e;
f <= d;
$monitor($stime,,, "Non-blocking d=%b e=%b f=%b", d, e, f);
end
initial begin
#10;
d = 0; e = 1;
//Following is the same as non-blocking.
temp = e;
f = d;
d = temp;
$display($stime,,, "Using temp d=%b e=%b f=%b", d, e, f);
end
endmodule
上述代码将比较阻塞和非阻塞赋值,其输出如图所示。
让我解释一下这个代码。
有三个“initial”语句块。第一个是阻塞赋值:
a = b;
c= a;
使用此赋值,“b”被分配给“a”,新值“a”被分配给“c”。因此,仿真log中会出现以下内容:
a=1 b=1 c=1
另一方面,非阻塞赋值的运作方式如下:
D <= e;
F <= d;
由于它们是非阻塞的,所以两个赋值同时运行。第一个赋值并不妨碍第二个赋值的完成。
“e”的当前值分配给“d”,“d”的当前值(在分配d = e之前)分配给“f”。
d=1 e=1 f=0