分配和锁存器不完整

Min*_*wat 1 verilog modelsim

当不完全分配一个值时,我得到一个闩锁。但是为什么在下面的示例中会出现闩锁?我认为不需要F输出锁存器,因为它定义为的所有值SEL

Verilog代码:

always @ (ENB or D or A or B pr SEL)
    if (ENB)
    begin 
        Q=D;
        if (SEL)
            F=A;
        else
            F=B;
    end
Run Code Online (Sandbox Code Playgroud)

推断逻辑:

https://imgur.com/kLW4QGe

Sil*_*602 5

尽管在的所有值中都定义了SEL,但并非在的所有值中都定义了ENB。如果为ENB = 0,则您的代码会同时声明Q和,并F应保留上一个周期的值。这也是您链接的图像中所推断出的内容:仅更新QF如果为ENB = 1

如果您不想Q成为闩锁F,则可以执行以下操作:

always @ (ENB or D or A or B or SEL)
begin
    if (ENB)
        Q=D;

    if (SEL)
        F=A;
    else
        F=B;
end
Run Code Online (Sandbox Code Playgroud)

编辑:其他信息

正如评论中指出的那样,我仅展示了如何实现组合逻辑和锁存器,而无需过多修改代码。但是,有些事情可以做得更好。因此,非TL; DR版本:

  1. 尽管可以将组合逻辑和锁存器放在一个程序块中,但最好将它们分成两个块。您正在设计两种不同的硬件,因此最好在Verilog中将它们分开。
  2. 对锁存器建模时,请使用非阻塞分配而不是阻塞分配。Clifford E. Cummings撰写了一篇出色的论文,介绍了阻塞式分配和非阻塞式分配之间的区别,以及了解区别的重要性。我还将在这里使用本文作为源:Verilog综合中的非阻塞分配,令人难以置信的编码风格

    首先,重要的是要了解Verilog中的竞争条件是什么(Cummings):

    如果按照IEEE Verilog标准的要求,更改了语句执行的顺序时,计划在同一模拟时间步执行的两个或多个语句将给出不同的结果,则会发生Verilog竞争条件。

    简而言之:always块可以以任意顺序执行,这可能会导致竞争状况,从而导致意外行为。

    要了解如何防止这种情况,重要的是要了解阻塞分配和非阻塞分配之间的区别。使用阻塞赋值(=)时,在不中断任何其他Verilog语句(即,)的情况下,对右侧(在代码AB,和D)的求值和对左侧(在代码中和)的赋值就可以完成。 ,“立即发生”)。但是,当使用无阻塞分配()时,左侧只会在时间步长结束时进行更新。QF<=

    可以想象,后一种分配类型有助于防止出现竞争状况,因为您可以确定分配的左侧何时更新。

    在对此问题进行分析之后,卡明斯得出以下结论:

    准则1:对顺序逻辑建模时,请使用非阻塞分配。

    准则2:在对闩锁进行建模时,请使用非阻塞分配。

    准则3:在使用Always块对组合逻辑进行建模时,请使用块分配。

    我要从上述论文中强调的最后一点是“为什么”。除了可以确定推断出正确的硬件这一事实之外,在将预合成模拟与实际硬件的行为相关联时,它也有帮助:

    但为什么?通常,答案与仿真有关。忽略上述指导原则[关于使用阻塞或非阻塞分配在本文的第2页上],仍可以推断出正确的合成逻辑,但是合成前的仿真可能与合成电路的行为不匹配。

  3. 如果您要严格遵守Verilog2001,那么最后一点是不可能的,但是如果您可以自由选择Verilog版本,请尝试将其always_comb用于组合逻辑和always_latch闩锁。这两个关键字都会自动推断出敏感度列表,并且工具可以更轻松地找出您是否实际编写了要设计的逻辑。

    SystemVerilog LRM报价:

    always_latch构造与该构造相同,always_comb除了软件工具应执行额外的检查并在always_latch构造中的行为不代表锁存逻辑时发出警告,而在always_comb构造中,工具应检查并警告行为是否不代表组合逻辑。

有了这些技巧,您的逻辑将如下所示:

always_latch
begin
    if (ENB)
       Q <= D;
end

always_comb
begin
    if (SEL)
        F = A;
    else
        F = B;
end
Run Code Online (Sandbox Code Playgroud)