【问题标题】:Mixing nonblocking and blocking assignments in an always_ff block of an arbiter在仲裁器的 always_ff 块中混合非阻塞和阻塞分配
【发布时间】:2014-06-13 07:09:06
【问题描述】:

我无法理解斯图尔特·萨瑟兰(及其同事)在SystemVerilog For Design 书中的示例 10-3。

见第 232 行:

https://code.google.com/p/vak-opensource/source/browse/trunk/hardware/systemverilog/utopia-example/squat.sv?r=185

这里是sn-p的代码。我的问题将随之而来。

  bit [0:NumRx-1] RoundRobin;

  always_ff @(posedge clk, posedge reset) begin: FSM
    bit breakVar;
    if (reset) begin: reset_logic
      Rxready <= '1;
      Txvalid <= '0;
      Txsel_out <= '0;
      SquatState <= wait_rx_valid;
      forward <= 0;
      RoundRobin = 1;
    end: reset_logic
    else begin: FSM_sequencer
      unique case (SquatState)

        wait_rx_valid: begin: rx_valid_state
          Rxready <= '1;
          breakVar = 1;
          for (int j=0; j<NumRx; j+=1) begin: loop1
            for (int i=0; i<NumRx; i+=1) begin: loop2
              if (Rxvalid[i] && RoundRobin[i] && breakVar)
                begin: match
                  ATMcell <= RxATMcell[i];
                  Rxready[i] <= 0;
                  SquatState <= wait_rx_not_valid;
                  breakVar = 0;
                end: match
            end: loop2
            if (breakVar)
              RoundRobin={RoundRobin[1:$bits(RoundRobin)-1],
                          RoundRobin[0]};
          end: loop1
        end: rx_valid_state

具体来说,我的问题是关于 breakVarRoundRobin 的阻塞分配。我在某处读到变量是在本地评估的,但我无法用门来描述逻辑是如何合成的。 RoundRobin 会合成到状态寄存器吗?

大多数指南都规定永远不要混合阻塞和非阻塞分配。有没有更好的方法来表示这样的事情?鉴于它位于always_ff 块中,现在可以在 SystemVerilog 设计中混合两种类型的分配吗?

【问题讨论】:

    标签: system-verilog fsm synthesis round-robin


    【解决方案1】:

    您不应该将阻塞和非阻塞分配混合到 same 变量。 breakVar 是一个临时变量,将被合成为组合逻辑,因为它总是先写入,然后再读取。没有要保存的状态RoundRobin 是一个局部变量,用作中间变量和状态变量。但是因为它只能从always_ff 块内访问,所以没有竞争条件的危险。


    临时变量只是表示方程式的一种象征性方式。这是一个不同但更简单的例子:

    always_ff @(posedge clock)
       begin
       full = (counter == 10);
       brimming = (counter > 7);
       hold <= brimming && !full;
       if (full) 
          counter <= counter + 1;
       else 
          counter < = 0;
    end
    

    这相当于写以下内容(但可能更难理解)

    always_ff @(posedge clock)
       begin
       hold <= (counter > 7) && !(counter == 10);
       if (counter == 10) 
          counter <= counter + 1;
       else 
          counter < = 0;
    end
    

    在上面的两个例子中,counter 总是被综合为一个寄存器,因为它是先读后写的。我们使用阻塞赋值还是非阻塞赋值无关紧要,因为我们在写完counter 之后从未读过它。在这个 always_ff 块中没有使用阻塞分配的竞争条件,但如果有另一个 always_ff 块试图读取它,则可能存在竞争条件。由于fullbrimming 是在读取之前写入的,因此不必注册。

    总而言之,如果其中任何一个条件为真,则变量将被合成为寄存器

    1. 一个变量被读取之前被写入同一个always块。请注意,即使首先出现非阻塞赋值语句,读取也会先发生,因为写入会安排在稍后发生。
    2. 由于条件语句或循环语句,有时会读取而不写入变量
    3. 变量写入always_ff 块并在块外读取。

    【讨论】:

    • 我不确定这是否正确 - RoundRobin 在这种情况下是一个寄存器,应该真的使用非阻塞赋值。
    • 我说对了一半 - RoundRobin 存储状态,但在循环写入后也会被读取,因此需要阻塞分配......我的评论有点误导,但你发现了故意的错误;)
    • 2 always block 方法更简洁,尽管它需要更多的输入。一个 always_comb 用于所有阻塞分配,包括 next_state 值,以及一个 always_ff 用于将状态分配给它们的 next_state 的非阻塞。这允许查看对调试有用的波形中的 D 引脚。我发现它使 ECO 更容易执行和记录。根据Cliff's SNUG2003 paper on FSM,2-always 方法提供了更好的区域和时间,但我认为它确实取决于工具/版本。
    • @dave_59,您能否详细说明一下临时变量是如何合成的?
    • 更新答案。
    【解决方案2】:

    完全同意@jonathan的回答。

    您应该始终在 always_comb 块中拆分逻辑元素,在 always_ff 块中拆分顺序元素。

    • 如果您编写的代码如此紧密地缝合在一起(两者结合 和同一块中的顺序元素),即使它是正确的并且 符合系统verilog规范,一些旧版本的模拟器 或正在开发的新模拟器可能会以错误的方式推断它。

    • 你的代码不会被其他人理解和理解。

    • 另外,通过上面的风格,你只是在压缩线条 代码,即使逻辑保持不变。没有意义 如果妨碍代码的可读性,请编写紧凑的代码。

    现在就阻塞和非阻塞语句的使用而言,我认为辩论现在已经结束。现在,在 always_comb 块中使用阻塞语句,在 always_ff 块中使用非阻塞语句,这更像是一种规则。

    Clifford E Cummings 在这篇出色的论文中解释了所有问题的答案 Nonblocking Assignments in Verilog Synthesis, Coding Styles That Kill!

    如果您是 Verilog/系统 Verilog 设计的新手,我建议您阅读他们的所有论文,它们非常有用,为 RTL 设计工程师奠定了良好的基础。

    这里也可能说得太多了,但是如果您正在寻找如何在组合和顺序块中分离您的代码,您可以查看bluespec生成的代码

    信号名称很难一口气理解,但如果仔细观察,代码逻辑上非常简洁,不会留下任何模拟和综合工具的奇思妙想。

    【讨论】:

    • 你引用的论文是关于 Verilog 而不是 SystemVerilog。
    • @ShashankVM SystemVerilog 是 Verilog 的超集,适用相同的概念。
    • compliant with system verilog spec, some older versions of simulator or newer simulators being developed may infer it in wrong way 那么这是一个错误并命令供应商尽快修复它,他们必须遵循规范或者他们称之为其他东西。这也是一个足以使购买此类模拟器无效的法律错误。 (完成了,我们赢了)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-06
    相关资源
    最近更新 更多