首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >仲裁器的always_ff块中的非阻塞和阻塞分配混合

仲裁器的always_ff块中的非阻塞和阻塞分配混合
EN

Stack Overflow用户
提问于 2014-06-13 07:09:06
回答 2查看 3.1K关注 0票数 1

我无法理解斯图尔特萨瑟兰(和公司)的SystemVerilog设计书中的例子10-3。

见第232行:

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

下面是代码片段。我的问题会跟进。

代码语言:javascript
运行
复制
  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是否被合成到状态寄存器中?

大多数准则都规定永远不要混淆阻塞和非阻塞分配。有更好的方法来代表这样的东西吗?在SystemVerilog设计中,考虑到它在always_ff块中,混合两种类型的赋值可以吗?

EN

回答 2

Stack Overflow用户

发布于 2014-06-13 14:32:47

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

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

代码语言:javascript
运行
复制
always_ff @(posedge clock)
   begin
   full = (counter == 10);
   brimming = (counter > 7);
   hold <= brimming && !full;
   if (full) 
      counter <= counter + 1;
   else 
      counter < = 0;
end

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

代码语言:javascript
运行
复制
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. 在同一个始终块中写入变量之前先读取变量。请注意,即使首先出现非阻塞赋值语句,读取也会先发生,因为写入被安排在稍后发生。
  2. 由于有条件或循环语句,有时不需要写入变量就可以读取变量。
  3. 变量在always_ff块中写入并在该块外部读取。
票数 6
EN

Stack Overflow用户

发布于 2020-10-17 06:13:09

完全同意@jonathan的回答。

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

  • 如果您编写的代码非常紧密地拼接在一起(在同一个块中包括组合元素和顺序元素),即使它是正确的,并且符合system规范,那么一些旧版本的模拟器或正在开发的较新的模拟器可能会错误地推断它。
  • 您的代码将不干净,也不会被他人理解。
  • 此外,通过上面的写作风格,您只是压缩了代码行,即使逻辑保持不变。如果紧凑的代码妨碍了代码的可读性,那么编写它就没有意义了。

现在,就阻塞和非阻塞语句的使用而言,我认为辩论现在结束了。现在,在always_comb块中使用阻塞语句而在always_ff块中使用非阻塞语句更多地是一条规则,而不是一条准则。

然而,对您所有问题的回答Clifford E Cummings 非阻塞分配在Verilog合成,编码样式,杀死!的这篇精彩论文中作了解释。

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

此外,这里可能说得太多了,但是如果您正在研究如何在组合框和顺序块中隔离代码,您可以查看蓝语生成的代码。

信号名称很难一蹴而就就能理解,但是如果你仔细看一看,代码在逻辑上是非常整洁的,不会留下任何关于模拟和合成工具的怪念头。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24199587

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档