System verilog 在仲裁器的always_ff块中混合非阻塞和阻塞分配

System verilog 在仲裁器的always_ff块中混合非阻塞和阻塞分配,system-verilog,fsm,synthesis,round-robin,System Verilog,Fsm,Synthesis,Round Robin,我无法理解斯图尔特·萨瑟兰(及其同事)的书中的例子10-3 见第232行: 下面是代码片段。我的问题随后会提出 bit [0:NumRx-1] RoundRobin; always_ff @(posedge clk, posedge reset) begin: FSM bit breakVar; if (reset) begin: reset_logic Rxready <= '1; Txvalid <= '0; Txs

我无法理解斯图尔特·萨瑟兰(及其同事)的书中的例子10-3

见第232行:

下面是代码片段。我的问题随后会提出

  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
位[0:NumRx-1]循环;
始终_ff@(posedge时钟、posedge重置)开始:FSM
位突变;
如果(复位)开始:复位逻辑

Rxready决不能将阻塞和非阻塞赋值混合到同一个变量
breakVar
是一个临时变量,它将被合成为组合逻辑,因为它总是先写入,然后读取。没有要保存的状态
RoundRobin
是一个局部变量,用作中间变量和状态变量。但是,由于它只能从
始终\u ff
块中访问,因此不存在竞争条件的危险


临时变量只是表示一个等式的符号方式。下面是一个不同但更简单的示例:

always_ff @(posedge clock)
   begin
   full = (counter == 10);
   brimming = (counter > 7);
   hold <= brimming && !full;
   if (full) 
      counter <= counter + 1;
   else 
      counter < = 0;
end
始终\u ff@(posedge时钟)
开始
满=(计数器==10);
满溢=(计数器>7);
hold完全同意答案

您应该始终在always\u comb块中拆分逻辑元素,并在always\u ff块中拆分顺序元素

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

  • 您的代码将不干净,其他人无法理解

  • 同样,以上述风格写作,你只是在压缩文章的行数 代码,即使逻辑保持不变。这是毫无意义的 如果编写紧凑的代码会妨碍代码的可读性,则编写紧凑的代码

现在,就阻塞语句和非阻塞语句的使用而言,我认为辩论现在结束了。现在,在always\u comb块中使用阻塞语句和在always\u ff块中使用非阻塞语句更多地是一种规则而不是指导原则

然而,Clifford E Cummings在这篇精彩的论文中解释了你所有问题的答案

如果您对verilog/system verilog设计不熟悉,我建议您阅读他们的所有论文,它们非常有用,为RTL设计工程师奠定了良好的基础

另外,这里可能讲得太多了,但如果您正在寻找如何在组合块和顺序块中分离代码,您可以查看由


信号名称很难一下子理解,但如果仔细观察,代码在逻辑上非常简洁,不会因模拟和合成工具的突发奇想而留下任何东西。

我不确定这是否正确-
RoundRobin
在本例中是一个寄存器,应该真的使用非阻塞分配。我有一半是正确的-
RoundRobin
存储状态,但在写入循环后也会读取,因此需要阻塞分配。。。我的评论有点误导,但你发现了故意的错误;)2 always块方法更干净,尽管它需要更多的输入。一个
always\u comb
用于所有阻塞分配,包括下一个\u状态值,一个
always\u ff
用于非阻塞分配状态到下一个\u状态。这样可以在波形中看到D引脚,这对调试非常有用。我发现它使ECOs更容易操作和记录。根据,2-always方法提供了更好的面积和时间,但我认为它确实依赖于工具/版本。@dave_59,你能详细说明一下临时变量是如何合成的吗?更新的答案。你引用的论文是关于Verilog而不是SystemVerilog的。@ShashankVM SystemVerilog是Verilog的超集,同样的概念也适用。
always_ff @(posedge clock)
   begin
   hold <= (counter > 7) && !(counter == 10);
   if (counter == 10) 
      counter <= counter + 1;
   else 
      counter < = 0;
end