verilog / systemverilog - 跨两个always块阻塞语句的行为是什么?

时间:2014-06-09 15:20:49

标签: verilog blocking nonblocking system-verilog

我想知道下面代码的行为。总共有两个块,一个是组合来计算next_state信号,另一个是顺序,它将执行一些逻辑并确定是否关闭系统。它通过将shutdown_now信号设置为高,然后调用state <= next_state来完成此操作。

我的问题是,如果条件成立,shutdown_now信号在state <= next_state行之前以阻塞方式设置(在时钟周期n期间),则时钟周期n + 1期间的状态是SHUTDOWNRUNNING?换句话说,自shutdown_now = 1'b1信号以来,两个状态机上的state行阻止是否通过next_state确定依赖于它?

 enum {IDLE, RUNNING, SHUTDOWN} state, next_state;
 logic shutdown_now;

 // State machine (combinational)
 always_comb begin
    case (state)
       IDLE: next_state <= RUNNING;
       RUNNING: next_state <= shutdown_now ? SHUTDOWN : RUNNING;
       SHUTDOWN: next_state <= SHUTDOWN;
       default: next_state <= SHUTDOWN;
    endcase
 end

 // Sequential Behavior
 always_ff @ (posedge clk) begin
    // Some code here
    if (/*some condition*/) begin
       shutdown_now = 1'b0;
    end else begin
       shutdown_now = 1'b1;
    end
    state <= next_state;
 end

3 个答案:

答案 0 :(得分:1)

首先,您没有关注属性编码。 always_comb应仅使用阻止(=)分配,永不阻止(<=)。 always_ff是相反的,只有非阻塞(<=)分配,永不阻止(=)。

使用代码,stateRUNNING。这是因为next_state的分配是非阻塞的,因此next_state直到调度程序的后期才会更新。

假设,如果next_stateshutdown_now都是阻止分配,那么模拟器将具有竞争条件。在评估next_state之前或之后,可以评估和更新state。这就是为什么在同一个总块中混合阻塞和非阻塞不是一个好主意。

如果编码正确,即next_state = ...shutdown_now <= ...,则状态也会转到RUNNING。这是因为shutdown_now更新在所有计划的评估完成后发生。因此next_state在评估1'b1之后才会看到state

答案 1 :(得分:0)

迈尔斯,你真的只有一台状态机,这是你的always_comb块中的代码。 always_ff只创建一个寄存器来保存你的状态。

现在编写代码的方式,您将按以下顺序执行关闭:

  • 周期n:你的always_ff块中的逻辑将确定是否应该发生关闭,并且会在下一个时钟周期内调度shutdown_now信号以进行断言。
  • cycle n + 1:shutdown_now置位,状态机(当前处于RUNNING状态)将next_state设置为SHUTDOWN。
  • cycle n + 2:现在你的状态机将处于SHUTDOWN状态。

不确定是否需要在always_ff块中使用关闭逻辑。如果将该代码移动到always_comb块,则可以使其余代码保持不变,并且状态机将在周期n + 1中移至SHUTDOWN状态。

答案 2 :(得分:0)

以下是我希望代码执行的方式:

您有两个寄存器:“shutdown_now”寄存器和“状态”寄存器。

在clk的posedge上,这两个寄存器的状态都是原子更新的。即:当对shutdown_now进行阻塞分配时,当state_next更新时,当前进程不会中断。相反,为了always_ff过程的目的,state_next是在posedge clk模拟“tick”开始时保存的任何值。

所以:

  1. 在第一个posedge时钟滴答:shutdown_now将从0切换到1.

  2. 一旦“posedge clk”进程完成,“always_comb”块将注意到它有工作要做,并将更新state_next(即来自2个寄存器的新状态的组合解码)。

  3. 在第二个posedge时钟滴答:状态被更新的state_next锁存。

  4. 因此,关闭系统需要2个周期,而不是1个。