verilog/systemverilog——在两个始终块之间阻塞语句的行为是什么?

verilog/systemverilog——在两个始终块之间阻塞语句的行为是什么?,verilog,blocking,nonblocking,system-verilog,Verilog,Blocking,Nonblocking,System Verilog,我想知道下面代码的行为。始终有两个块,一个是组合块,用于计算下一个\u状态信号,另一个是顺序块,用于执行某些逻辑并确定是否关闭系统。它通过将shutdown\u立即设置为信号高,然后首先调用state来实现这一点,您没有遵循属性编码。always\u comb应该只使用阻塞(=)赋值,而不是非阻塞(Miles),你实际上只有一个状态机,那就是always\u comb块中的代码。always\u ff只创建一个寄存器来保存你的状态 按照现在编写代码的方式,您将按以下顺序执行关机: 循环n:al

我想知道下面代码的行为。始终有两个块,一个是组合块,用于计算
下一个\u状态
信号,另一个是顺序块,用于执行某些逻辑并确定是否关闭系统。它通过将
shutdown\u立即设置为
信号高,然后首先调用
state来实现这一点,您没有遵循属性编码。
always\u comb
应该只使用阻塞(
=
)赋值,而不是非阻塞(
Miles),你实际上只有一个状态机,那就是always\u comb块中的代码。always\u ff只创建一个寄存器来保存你的状态

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

  • 循环n:always\u ff块中的逻辑将确定是否应该发生关机,并将安排关机\u now信号在下一个时钟滴答声中断言
  • 循环n+1:shutdown\u现在断言,状态机(当前正在运行)将下一个\u状态设置为shutdown
  • 循环n+2:现在您的状态机将处于关闭状态

不确定是否需要将关闭逻辑放在always\u ff块中。如果将该代码移动到always\u comb块,则可以保持代码的其余部分不变,并且您的状态机将在循环n+1中移动到关闭状态。

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

您有两个寄存器:“立即关机”寄存器和“状态”寄存器

在clk的posedge上,这两个寄存器的状态都会自动更新。也就是说:当对shutdown\u进行阻塞分配时,当前进程不会中断,而状态\u下一次更新。相反,为了始终\u ff进程的目的,状态\u下一次是它在posedge clk simula开始时保持的任何值“滴答声”

因此:

  • 在第一个posedge时钟滴答声中:关闭\u现在将从0切换到1

  • 一旦“posedge clk”过程完成,“always_comb”块将注意到它还有工作要做,并将更新状态_next(即,从2个寄存器的新状态进行组合解码)

  • 在第二个posedge时钟滴答声中:状态与更新的状态_next锁存


  • 因此,关闭您的系统需要2个周期,而不是1个周期。

    正如Greg提到的,您确实需要修复阻塞/非阻塞分配。谢谢Ciano,非常感谢。我确实需要在周期n+1期间处于关闭状态。我想我应该能够将关闭逻辑移动到always_comb块中以确保此行为。另外,请参阅我的co我在格雷格的帖子上提到了关于阻塞/非阻塞分配的内容。嗨,格雷格,谢谢你的回复。我看到了你描述的比赛情况,我会谨慎对待。我同意你的观点,总是梳块应该总是阻塞。但是,当你总是说所有的分配时,也许我误解了你s_ff block应该始终是非阻塞的?我经常在顺序块中同时使用阻塞语句和非阻塞语句来创建触发器之间的组合链。你介意澄清一下吗?@Miles,而我认识一些人,他们在顺序块中混合使用阻塞语句和非阻塞语句。我不这样做。正如Greg所说,一般建议不要在一个过程中混合使用不同的赋值类型。我倾向于自己编写组合逻辑和顺序逻辑(通常非常小)进程。对我来说,这似乎使代码更易于阅读,合成工具也更易于处理。@Ciano这是有意义的。感谢您的输入,从风格上讲,您是正确的。但是,在always_comb块中使用非阻塞赋值,或者在always_ff块中使用阻塞赋值,实际上并没有什么错。ThLRM定义了所有现代工具实现的一致行为。@JonathanMayer,阻塞与非阻塞仍然很重要,因为每个区域内的事件可以以不确定的顺序执行。每个区域的执行顺序是确定的。第4.6节确定性、第4.7节不确定性和第4.8节竞争条件。LRM允许阻塞nd NBA在所有形式的
    中始终
    ,但如果您希望RTL、门和电路匹配,请遵循阻塞/非阻塞指南。
    
     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