Verilog非阻塞赋值的仿真/综合问题

来源:互联网 发布:3dmax建模算法 编辑:程序博客网 时间:2024/05/16 18:10

指导方针和结论(概要):

1当为时序逻辑建模,使用“非阻塞赋值”。

2当为锁存器(latch)建模,使用“非阻塞赋值”。

3当用always块为组合逻辑建模,使用“阻塞赋值”

4当在同一个always块里面既为组合逻辑又为时序逻辑建模,使用“非阻塞赋值”。

5不要在同一个always块里面混合使用“阻塞赋值”和“非阻塞赋值”。

6不要在两个或两个以上always块里面对同一个变量进行赋值。

7使用$strobe以显示已被“非阻塞赋值”的值。

8不要使用#0延迟的赋值。

 

1、组合逻辑使用阻塞赋值(blocking assignment
       
Verilog可以有很多种方法为组合逻辑建模,但是当使用always块来为组合逻辑建模时,应该使用阻塞赋值(blocking assignment)。

module ao2 (y, a, b, c, d);
output y;
input a, b, c, d;
reg y, tmp1, tmp2;
always @(a or b or c or d) begin
tmp1 = a & b;
tmp2 = c & d;
y = tmp1 | tmp2;
end
endmodule
Example 21 - Efficient combinational logic coding style using blocking assignments

       
21与例19一样,不同之处只在于用阻塞赋值替代了非阻塞赋值。这保证了在一个登入路径贯穿alwaysy输出的正确(guarantee that the y-output assumes the correct value after only one pass through the always block?)。因此有下面的编码方针

3当用always块为组合逻辑建模,使用阻塞赋值

 

2时序-组合混合逻辑建模:使用非阻塞赋值
module nbex2 (q, a, b, clk, rst_n);
output q;
input clk, rst_n;
input a, b;
reg q;
always @(posedge clk or negedge rst_n)
if (!rst_n) q <= 1'b0;
else q <= a ^ b;
endmodule
Example 22 - Combinational and sequential logic in a single always block
       
与例22相同的逻辑也可以使用两个分立的always------一个是纯粹的时序逻辑(使用非阻塞赋值),另一个是纯粹的组合逻辑(使用阻塞赋值)------建模,例如下面的例23
module nbex1 (q, a, b, clk, rst_n);
output q;
input clk, rst_n;
input a, b;
reg q, y;
always @(a or b)
y = a ^ b;
always @(posedge clk or negedge rst_n)
if (!rst_n) q <= 1'b0;
else q <= y;
endmodule
Example 23 - Combinational and sequential logic separated into two always blocks
4当在同一个always块里面既为组合逻辑又为时序逻辑建模,使用非阻塞赋值

 

3、常见的非阻塞神话(外注:指与事实不符或严格说不正确的见解、想法)
3.1
非阻塞赋值和$display
  
神话:非阻塞赋值使用$display命令不起作用。
  
事实:非阻塞赋值在$display命令之后才被更新赋值。

module display_cmds;
reg a;
initial $monitor("\$monitor: a = %b", a);
initial begin
$strobe ("\$strobe : a = %b", a);
a = 0;
a <= 1;
$display ("\$display: a = %b", a);
#1 $finish;
end
endmodule
下面的仿真输出结果显示出$display命令在激活事件列the active event queue)里被执行的情形:在非阻塞赋值更新这个事件被执行之前。

$display: a = 0
$monitor: a = 1
$strobe : a = 1

3.2
零延迟
  
神话:“‘零延迟’#0使得该赋值事件在时间步结束时发生
  
事实:零延迟’#0使得赋值事件处于非激活事件列

module nb_schedule1;
reg a, b;
initial begin
a = 0;
b = 1;
a <= b;
b <= a;
$monitor ("%0dns: \$monitor: a=%b b=%b", $stime, a, b);
$display ("%0dns: \$display: a=%b b=%b", $stime, a, b);
$strobe ("%0dns: \$strobe : a=%b b=%b\n", $stime, a, b);
#0 $display ("%0dns: #0 : a=%b b=%b", $stime, a, b);
#1 $monitor ("%0dns: \$monitor: a=%b b=%b", $stime, a, b);
$display ("%0dns: \$display: a=%b b=%b", $stime, a, b);
$strobe ("%0dns: \$strobe : a=%b b=%b\n", $stime, a, b);
$display ("%0dns: #0 : a=%b b=%b", $stime, a, b);
#1 $finish;
end
endmodule
下面的仿真输出结果显示出$display命令在非激活事件列the inactive event queue)里被执行的情形:在非阻塞赋值更新这个事件被执行之前。

0ns: $display: a=0 b=1
0ns: #0 : a=0 b=1
0ns: $monitor: a=1 b=0
0ns: $strobe : a=1 b=0
1ns: $display: a=1 b=0
1ns: #0 : a=1 b=0
1ns: $monitor: a=1 b=0
1ns: $strobe : a=1 b=0
7使用$strobe以显示已被非阻塞赋值的值。

3.3
对同一变量多处进行非阻塞赋值
  
神话:“‘在同一个always块里对同一变量多处进行非阻塞赋值没有被明确定义。
  
事实:Verilog标准定义了以上操作。最后一个非阻塞赋值操作将赢得最后结果。

原创粉丝点击