Verilog的阻塞分配

问题描述 投票:3回答:4

我有些新来的Verilog。我知道,在一个时钟进程,我们应该使用非阻塞的任务,并在非时钟过程中,我们使用阻塞赋值。

我曾经碰到这个代码来了,当我读别人的代码。

reg iowrb_int,iowrb_met;
reg iordb_int,iordb_met;
always@(*)
begin
  iowrb_int <= iowrb_met;
  iordb_int <= iordb_met;

  iowrb_met <= iowr_bar;
  iordb_met <= iord_bar;
end

我真的不知道上面的代码!我不认为这是做任何登记,是否正确?这一切意味着什么有一个始终@(*)语句非阻塞?

有没有在使用中总是阻止与非阻止任何区别@(*)语句?

verilog blocking nonblocking
4个回答
3
投票

主要的区别是:

  • 阻塞分配下一个任务,即它块的下一个语句的执行之前执行。
  • 非阻塞赋值并联即执行它们不阻挡该语句的以下它们的执行。

假设一个= 2和b = 3,那么非阻塞赋值:

a <= 4;
b <= a; 

导致= 4且b = 2 - 值的之前分配的

a = 4;
b = a;

将导致= 4和b = 4 - 阻塞分配完成后值的。

一种可变得到合成到寄存器(锁存器或触发器)对组合逻辑取决于总是块的灵敏度列表上。它不依赖于使用阻塞或非阻塞分配。

例如:

always @(*) begin
  if (enable)
     q = d;
end

这将导致d-锁,因为不是时启用== 0,因此需要记住的是最后分配指定分配给q为。

always @(*) begin
  if (enable)
    q = d;
  else
    q = f;
end

这将导致因为对使能等q不必记得任何事情的两种情况下被指定分配到q多路复用器(组合逻辑)。


1
投票

阻挡与非阻挡是使你的栅极电平(合成)您的RTL仿真匹配。使用不同的一个改变模拟的行为,据我所知不会影响合成,因此门级的行为。

<=有效无阻塞采取复制右侧的临时副本,使=在时间步长结束封锁任务。

a <= b;
b <= a;

相当于:

a_temp = b;
b_temp = a;
//
a = a_temp;
b = b_temp;

该示例使用组合逻辑,即它不包含任何状态,因此,所有输入必须通过所有输出来定义。

always@* begin
  iowrb_int <= iowrb_met;
  iordb_int <= iordb_met;
  iowrb_met <= iowr_bar;
  iordb_met <= iord_bar;
end

当右侧更新块应该重新触发。由于iowrb_met是双方我不知道这意味着interms电连接性。

<=意味着复制到一个临时位置,组合逻辑不具备这种能力,它总是不断被分配驱动。

我想在模拟您有效地有这样的:

always@* begin
  iowrb_int_temp = iowrb_met;
  iordb_int_temp = iordb_met;
  iowrb_met      = iowr_bar;
  iordb_met      = iord_bar;
  iowrb_int      = iowrb_int_temp;
  iordb_int      = iordb_int_temp;
end

在硬件你会:

always@* begin
  iowrb_int = iowrb_met;  //= iowr_bar;
  iordb_int = iordb_met;  //= iord_bar;
  iowrb_met = iowr_bar;
  iordb_met = iord_bar;
end

其中iowrb_int实际上是相同的iowrb_met

触发器使用always @(posedge clk隐含 组合逻辑是使用always @*隐含但当输出没有完全从输入锁存器定义可以暗示。


1
投票

仅通过改变代码来阻塞赋值可以综合成锁存器和/或创建取决于工具的处理逻辑等效性检查不匹配。

这是它的外观通过调度:

  • 随着阻塞: 的*_int信号被分配 的*_met信号被分配 移动到下一个时间步长。 *_int保持*_met的未更新的值
  • 无阻塞: 的*_int信号被分配 的*_met信号被分配 到*_met变化来检测导致环回调度器的有源区 重新分配*_int信号 重新分配*_int信号 移动到下一个时间步长。 *_int具有如*_met相同的值 浪费CPU时间再处理。这不是一个小项目很重要,但可以添加在整个大项目中使用明显的开销。

正确的逻辑等价的,CPU友好的方式将扭转分配顺序(分配qazxsw POI之前qazxsw POI):

*_met
  1. *_int信号被分配
  2. always@(*) begin iowrb_met = iowr_bar; iordb_met = iord_bar; iowrb_int = iowrb_met; iordb_int = iordb_met; end 信号被分配
  3. 移动到下一个时间步长。 *_int具有如*_met相同的值

或使用*_int作为所述分配值(即,如果一个== B和B == C,然后一个== b和a == c)中:

*_met
  1. *_baralways@(*) begin iowrb_int = iowr_bar; iordb_int = iord_bar; iowrb_met = iowr_bar; iordb_met = iord_bar; end 信号被分配
  2. 移动到下一个时间步长。 *_int具有如*_met相同的值

0
投票

正如其他人所说,转变为阻塞赋值这里实际上将无法正常工作。在组合always块使用阻塞赋值(这是我们推荐的)要求你把任务按正确的顺序。

在组合使用非阻塞赋值总是块可能看起来有吸引力的,因为你就可以在任何顺序分配,就像在VHDL。除了性能,一个好理由,以避免这种情况的是,它不与*_int工作。此代码不能正常工作:

*_met

原因是,always_comb不会成为敏感列表的一部分。它将按预期工作,如果你使用always_comb begin tmp <= in; out <= tmp; end tmp或阻塞赋值替换。

© www.soinside.com 2019 - 2024. All rights reserved.