总是@(posedge clk)中的事件控制

时间:2013-03-26 02:24:52

标签: verilog fpga synthesis

想知道始终阻止事件控制语句的行为:

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

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

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

2 个答案:

答案 0 :(得分: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

答案 1 :(得分:1)

假设您正在设计硬件而不是非合成的测试平台代码,这不是一个好的做法,并且可能无法完成您想要的任何操作。

从语言的角度来看,这将进行编译和模拟。 阻止等待始终块内的事件,而不是在时钟的每个副本上重新启动。我无法为此找到规范参考,但这是我在模拟中观察到的。如果你让它合成没有错误,我很好奇这会合成什么。


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

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

还需要考虑其他一些事项:

  • 也许你只关心信号何时断言/取消断言。在这种情况下,您需要进行边缘检测。
  • 如果信号与clk异步,那么你有一个时钟域交叉,你需要在看到它之前同步输入信号。