1

想知道 always 块中事件控制语句的行为:

always @(posedge clk) begin: TEST
    ...
    @(wait_for_signal_from_subsystem);
    ... 
    @(wait_for_another_signal_from_subsystem);
    ...
end

在事件信号到来之前,进程会“卡住”,还是会在每次 clk 边缘到来时重新启动?

这也是可合成的(Quartus II 说是,但还没有模拟......)?这是一个好的做法还是有其他更好的方法来解决这个问题?

4

2 回答 2

1

是的,正如您所说,它“卡住”了。一次只能激活一个块的“循环”,如果它没有完成循环,它将不会重新进入。

由于块内的等待操作,您在那里尝试做的事情可能无法合成。

我不知道您设计的确切细节,但我会用一个小型有限状态机来解决这个问题。我假设来自子系统的信号不比时钟快,所以它看起来像:

always @* begin
  if(state_f == `WAIT_FOR_FIRST) 
       state_nxt = got_first_signal ? `WAIT_FOR_SECOND : `WAIT_FOR_FIRST;
  else if(state_f == `WAIT_FOR_SECOND)
       state_nxt = got_second_signal ? `DONE_STATE : `WAIT_FOR_SECOND;
  else if(state_f == `DONE_STATE) 
       state_nxt = `WAIT_FOR_FIRST;
  else
       state_nxt = 2'bxx;
end

always @(posedge clk) begin
    state_f <= state_nxt;
end
于 2013-03-26T03:26:11.420 回答
1

假设您正在设计硬件而不是非综合测试台代码,这不是一个好的做法,并且可能无论如何都不会做您想做的事情。

从语言的角度来看,这将编译和模拟。它将阻止等待总是块内的事件,而不是在时钟的每个位置重新启动。我找不到这方面的规范参考,但这是我在模拟中观察到的。我很好奇如果你甚至让它没有错误地合成它会合成什么。


如果来自另一个子系统的信号已经在同一个时钟域(同步到clk),那么您可以在每个时钟沿检查它的状态,并使用它做一些事情。

always @(posedge clk) begin: TEST
  if (the_other_signal == 1'b1) begin
    ...
  end
end

其他一些需要考虑的事情:

  • 也许您只关心信号何时断言/取消断言。在这种情况下,您需要进行边缘检测。
  • 如果信号与 异步clk,那么您有一个时钟域交叉,您需要在查看输入信号之前对其进行同步。
于 2013-03-26T03:26:59.720 回答