📜  Verilog阻止和非阻止

📅  最后修改于: 2021-01-11 14:47:41             🧑  作者: Mango

Verilog阻止和非阻止

Verilog支持Always块内具有不同行为的阻塞和非阻塞分配语句。

阻塞分配类似于大多数流行编程语言中的软件分配语句。非阻塞分配是描述许多硬件系统(尤其是用于综合)的更自然的分配声明。

阻塞分配只能在少数情况下使用,例如对组合逻辑建模,定义函数或实现测试平台算法。要求所有符合IEEE P1364.1的综合工具都必须以显式样式代码支持阻塞和非阻塞分配,但要限制每个变量和每个块只能使用一种或另一种分配。

阻止分配

块分配语句是使用(=)运算符分配的,并在过程块中一个接一个地执行。但是,这不会阻止在并行块中运行的语句的执行。

module Block;
  reg [7:0] a, b, c, d, e;

  initial begin
    a = 8'hDA;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
    b = 8'hF1;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
    c = 8'h30;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
  end

  initial begin
    d = 8'hAA;
    $display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
    e = 8'h55;
    $display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
  end
endmodule

有两个初始块可以并行执行。语句在每个块中顺序执行,并且两个块均在时间0ns处完成。

更具体地说,首先分配变量,然后分配display语句,然后分配所有其他语句。

这在输出中可见,其中在第一条显示语句中变量bc为8'hxx。这是因为在调用第一个$ display时尚未执行变量bc的赋值。

ncsim> run
[0] a=0xda b=0xx c=0xx
[0] a=0xda b=0xf1 c=0xx
[0] a=0xda b=0xf1 c=0x30
[0] d=0xaa e=0xx
[0] d=0xaa e=0x55
ncsim: *W,RNQUIE: Simulation is complete.

在下面的示例中,我们将在同一组语句中添加一些延迟,以查看其反应和行为方式。

module Block;
  reg [7:0] a, b, c, d, e;
  initial begin
    a = 8'hDA;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
    #10 b = 8'hF1;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
    c = 8'h30;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
  end
  initial begin
    #5 d = 8'hAA;
    $display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
     #5 e = 8'h55;
    $display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
  end
endmodule

执行后,将提供以下数据。

ncsim> run
[0] a=0xda b=0xx c=0xx
[5] d=0xaa e=0xx
[10] a=0xda b=0xf1 c=0xx
[10] a=0xda b=0xf1 c=0x30
[10] d=0xaa e=0x55
ncsim: *W,RNQUIE: Simulation is complete.

非阻塞分配

非阻塞分配语句允许在不阻塞以下语句执行的情况下进行调度,并由(<=)符号指定。

相同的符号在表达式中用作关系运算符符,在非阻塞分配中用作赋值运算符。

采取与上述相同的示例,将所有(=)符号替换为非阻塞赋值运算符(<=),我们将获得输出的差异。

module Block;
  reg [7:0] a, b, c, d, e;
  initial begin
    a <= 8'hDA;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
    b <= 8'hF1;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
    c <= 8'h30;
    $display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
  end
initial begin
    d <= 8'hAA;
    $display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
     e <= 8'h55;
    $display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
  end
endmodule

现在,所有$ display语句都打印'h'x 。此行为的原因是非阻塞分配语句的执行。

捕获特定时间步长的每个非阻塞语句的RHS,并将其移至下一个语句。

仅在时间步结束时才将捕获的RHS值分配给LHS变量。

ncsim> run
[0] a=0xx b=0xx c=0xx
[0] a=0xx b=0xx c=0xx
[0] a=0xx b=0xx c=0xx
[0] d=0xx e=0xx
[0] d=0xx e=0xx
ncsim: *W,RNQUIE: Simulation is complete.