在Verilog中混合分配阻塞和非阻塞分配(或不分配!)

皮特·鲍曼

我在Verilog中实现了一个简单的序列化程序,但我不了解何时阻止分配会导致问题的细微差别。我特别难以理解此答案的一部分“但是,永远不要将阻塞分配用于同步通信,因为这是不确定的。”

我正在构建一个将其作为输入的块:

  • 有点钟
  • 5位并行数据输入(要序列化的值)
  • “数据有效”信号指示存在有效的5位数据

作为输出,我有:

  • 串行数据输出
  • 一个“完成”信号,指示是时候输入一个新的5位值
  • 每当总线上有有效的串行数据流出时,“发送”信号就为高

每当有效数据变高时,该块便从位时钟的下一个上升沿开始一次输出5位值,一次一次。当最后一位丢失时,该块发出“完成”信号,因此可以使用新的5位值。

省略一些复位逻辑,执行此操作的代码如下所示:

always @ (posedge clk) begin
    if(shiftIndex == 0) begin
        if(dataValid == 1) transmitting = 1; //Blocking assign
        else transmitting = 0; //Blocking assign
    end

   //Need the blocking assign up above to get this part to run
   //for the 1st bit
   if(transmitting == 1) begin
       shiftIndex <= shiftIndex + 1;
       dataOut <= data5b[shiftIndex];

       if(shiftIndex == 4) begin
           complete <= 1;
           shiftIndex <= 0;
       end
       else begin
           complete <= 0;
       end
   end
end

现在,我可以使用所有非阻塞分配来编写该块,但是我觉得这会损害可读性。看起来像这样:

always @ (posedge clk) begin
    if(shiftIndex == 0) begin
        if(dataValid == 1) begin
            transmitting <= 1; //Non-blocking now
            shiftIndex <= shiftIndex + 1;  //Duplicated code
            dataOut <= data5b[shiftIndex]; //Duplicated code
            complete <= 0;                 //Duplicated code
        end
        else transmitting <= 0;
    end

   //Now, this only runs for the 2nd, 3rd, 4th, and 5th bit.
   else if(transmitting == 1) begin
       shiftIndex <= shiftIndex + 1;
       dataOut <= data5b[shiftIndex];

       if(shiftIndex == 4) begin
           complete <= 1;
           shiftIndex <= 0;
       end
       else begin
           complete <= 0;
       end
   end
end

两者似乎都可以实现我在仿真中想要的功能,而我更喜欢第一个,因为它对我来说更容易阅读,但是由于我不明白为什么使用阻塞分配进行同步通信是不确定的,所以我担心自己编码了定时炸弹

问题:当我尝试对此进行综合时,我在第一代码中做错了什么吗?尽管很难读(尽管对我而言),第二代码还是可取的吗?我应该做一些第三件事吗?

摩根

使用阻塞(=)分配时,该值可用于下一行代码。这意味着它是组合的而不是由触发器驱动。

在仿真中,它看起来像是由触发器驱动的,因为该块仅在时钟正沿进行评估,实际上并不是这样,否则可能会破坏接口。

我说的是永远不要混合样式,因为这在代码审查和重构中可能是一个问题。重构,如果模块需要输出新信号,并且可以看到该信号已经存在,则只需将其更改为输出即可。乍一看,它好像是一个触发器,因为它处于always @(posedge clk阻塞状态。

因此,我建议不要混用样式,而要拉出组合的部分并将其放在自己的块中。这仍然符合您的要求吗?如果没有,那你就会有问题。

我看不到如何控制数据有效,但是它可以改变输出传输,可能是传输也可能由于组合解码而不是由触发器干净驱动而产生毛刺。接收接口可能是异步的,故障可能导致锁定等。

always @* begin
  if(shiftIndex == 0) begin
    if(dataValid == 1) transmitting = 1; //Blocking assign
    else transmitting = 0; //Blocking assign
  end
end

always @ (posedge clk) begin
  if(transmitting == 1) begin
    shiftIndex <= shiftIndex + 1;
    dataOut    <= data5b[shiftIndex];

   if(shiftIndex == 4) begin
       complete   <= 1;
       shiftIndex <= 0;
   end
   else begin
       complete   <= 0;
   end
  end
end

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章