【问题标题】:Verilog strange simulation results post synthesisVerilog奇怪的模拟结果后期合成
【发布时间】:2017-06-30 12:58:33
【问题描述】:

我遇到了一个奇怪的问题。该代码用于一个简单的 ALU。此处仅粘贴感兴趣的代码:

   always @(posedge clk or posedge rst)
   begin
        if (rst == 1) begin
           mul_valid_shr = 3'b000; 
        end else begin
            if (op_mul_i == 1) begin
                mul_valid_shr = 3'b111;
            end else begin
                mul_valid_shr <= mul_valid_shr << 1;
            end
        end
   end

在always块之外:

assign mul_valid = mul_valid_shr[2];

使用我的测试台进行 POST SYNTHESIS FUNCTIONAL SIMULATION 的结果如下:

reset 已经很低了,为什么第一次 sim 不行,第二次和第三次都正常?如果我在 100ns 标记之前触发op_mul_i,即使rst 很低,即使mul_result 第一次停止工作。

欢迎任何猜测。

更新:此处为完整代码:https://www.edaplayground.com/x/28Hx

【问题讨论】:

  • 我怀疑这不是您的问题的原因,但切勿在时钟始终块中混合阻塞和非阻塞分配到同一个变量。通常,您希望对任何暗示触发器的变量使用非阻塞赋值。我很惊讶你的合成器允许你这样做。因此,mul_valid_shr (mul_valid_shr = 3'b...) 的两个阻塞分配应该是非阻塞的 (mul_valid_shr &lt;= 3'b...)。
  • 我已经尝试过这个并且对所有事情都使用了非阻塞。它仍然具有完全相同的结果。
  • 我认为这不会有帮助。但是不要把它们混在一起。
  • 是的,刚刚改了。
  • 它在pre-synthesis 模拟中有效吗?我还认为您在示例中遗漏了一些重要的 rtl 部分。

标签: verilog hdl synthesis vivado


【解决方案1】:

Xilinx 仿真器在任何综合后仿真的前 100ns 中模拟 FPGA 全局复位,因此您基本上必须将逻辑保持在复位和时钟状态至少 100ns 才能获得合理的结果。这在第 13 页的 UG900 中有所提及。

【讨论】:

    【解决方案2】:

    Verilog 具有不确定性和种族条件的概念。下面是从各种版本的 Verilog 和 SystemVerilog 中解释概念的作用:

    • IEEE Std 1364-1995 § 5.4.2 非确定性
    • IEEE Std 1364-2001 § 5.4.2 非确定性
    • IEEE Std 1800-2012 § 4.8 非确定性

    不确定性的一个来源是活动事件可以从队列中取出并以任何顺序进行处理。不确定性的另一个来源是行为块中没有时间控制结构的语句不必作为一个事件执行。时间控制语句是 # 表达式和 @ 表达式结构(参见 9.7 [9.4 for IEEE1800])。在评估行为语句的任何时候,模拟器都可以暂停执行并将部分完成的事件作为未决活动事件放置在事件队列上。这样做的效果是允许进程执行的交错。请注意,交错执行的顺序是不确定的,不受用户控制。

    • IEEE Std 1364-1995 § 5.5 竞赛条件
    • IEEE Std 1364-2001 § 5.5 竞赛条件
    • IEEE Std 1800-2012 § 4.8 比赛条件

    因为表达式求值和网络更新事件的执行可能混合在一起,所以可能出现竞争条件:

    assign p = q;
    initial begin
      q = 1;
      #1 q = 0;
      $display(p);
    end

    模拟器在显示 1 或 0 时是正确的。将 0 分配给 q 会启用 p 的更新事件。模拟器可以继续执行 $display 任务,也可以执行 p 的更新,然后执行 $display 任务。

    简而言之,这意味着即使clkop_mul_i 在同一时间步中更改,也可以在更新op_mul_i 之前或之后评估在clk 上触发的always 块。这种非确定性和竞争条件行为是故意的;允许该语言以一种方式模仿 FPGA 和芯片上的关键路径可能发生的相同行为。

    无论解决方案和最佳实践是在时钟和输入激励之间有一个偏移量(时间或调度程序区域)。您可以在第一个 # 延迟的 ± 1 处使用时间偏移;就像我在评论中建议的那样。或者将输入激励分配给非阻塞分配 (&lt;=);它将始终在时钟之后更新,并且任何依赖于时钟的东西。 (这就是为什么应为翻牌分配非阻塞的原因)。您选择哪条路线由您或您的团队负责人决定。

    【讨论】:

    • 感谢您的详细回答。不幸的是,它并没有解决完整的问题。正如我在 cmets 中所写,重置的问题仍然存在。如果我给出足够长的主动复位(~100ns),所有功能都在那里,但对于较小的复位,100ns 内发生的任何事情都会被忽略。该设计以 250 Mhz 运行,建立/保持时间小于十分之一纳秒。你对此有什么想法吗?
    【解决方案3】:

    op_mul_i 是如何生成的? 与clk同步吗?我问是因为在模拟的第二部分中,当 op_mul_i 为逻辑 1 时,我看到 mul_valid 被驱动为逻辑 1。如果它是同步的,我希望 mul_valid 在 200ns 边沿旁边的时钟边沿为逻辑 1。 由于这是后期合成,我怀疑亚稳态会导致这个问题。 在 100ns 时,op_mul_i 在故障窗口内发生变化,并且时钟边沿不会将 op_mul_i 检测为逻辑 1,因此您什么也看不到。

    将 op_mul_i 同步到 clk,并使用同步信号驱动 mul_valid_shr。 此外,不要在顺序块中使用阻塞语句。

    希望对您有所帮助。 VK

    【讨论】:

    • 感谢您的回答,op_mul_i 是在 n*period 时间与时钟同步生成的。 mul_valid 应该在 op_mul_i 变高后的第三个周期变高。我已经停止混合阻塞和非阻塞语句。
    【解决方案4】:

    您使用 op_mul_i 作为异步信号创建了一个异步触发器。它在您的初始块中进行了修改,并且此修改与 clk 不同步。所以,这对我来说就像一场比赛。忽略一些步骤,硬件是正确的。

    因此,由于模拟工件,您的模拟结果可能是正确的。我猜想正确的 rtl 方法是通过为该信号提供另一个触发器来使信号与时钟同步。

    除此之外,您可以尝试在初始块中为该信号模拟非阻塞分配或#0 延迟。

    【讨论】:

    • 感谢您的回答。你是什​​么意思“与 op_mul_i 的异步翻牌”? op_mul_i 是一个输入信号,仅在 n*周期(即 20、40、60 等)触发。这不是使这个同步,即随时钟变化吗?在最初的 tb 块中,我现在使用“#0”,但它对结果没有影响。
    猜你喜欢
    • 1970-01-01
    • 2014-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-18
    • 1970-01-01
    • 2011-05-25
    相关资源
    最近更新 更多