Verilog 触发器和锁存器推断困境

Verilog 触发器和锁存器推断困境,verilog,hardware,digital-logic,flip-flop,digital-design,Verilog,Hardware,Digital Logic,Flip Flop,Digital Design,有人能给我解释一下为什么会推断出是闩锁而不是触发器吗 always_ff @ (posedge clk, negedge rst) begin if (!rst) a <= '0; end 始终\u ff@(posedge时钟、negedge rst) 开始 如果(!rst) 合成器将推断锁存器,因为此代码的行为类似于锁存器。它的行为不像人字拖。就这么简单 想想这个代码的行为:最初a的值将是'x。当rst被断言为低时,a将变为'0a将永远保持在'0。因此,a的状态不仅取决于

有人能给我解释一下为什么会推断出是闩锁而不是触发器吗

always_ff @ (posedge clk, negedge rst) 
begin
  if (!rst)
    a <= '0;
end
始终\u ff@(posedge时钟、negedge rst)
开始
如果(!rst)

合成器将推断锁存器,因为此代码的行为类似于锁存器。它的行为不像人字拖。就这么简单


想想这个代码的行为:最初
a
的值将是
'x
。当
rst
被断言为低时,
a
将变为
'0
<代码>a将永远保持在
'0
。因此,
a
的状态不仅取决于输入的当前状态,还取决于过去的状态。因此,我们有顺序逻辑,而不是组合逻辑。触发器改变时钟边缘的状态<代码>a
没有。“始终”块对信号边缘敏感这一事实与此无关。这仅仅意味着内部的代码是在信号边缘执行的,
clk
的正边缘。但当这种情况发生时,什么也不会发生,因此此代码的行为类似于闩锁。

合成器将推断闩锁,因为此代码的行为类似于闩锁。它的行为不像人字拖。就这么简单


想想这个代码的行为:最初
a
的值将是
'x
。当
rst
被断言为低时,
a
将变为
'0
<代码>a将永远保持在
'0
。因此,
a
的状态不仅取决于输入的当前状态,还取决于过去的状态。因此,我们有顺序逻辑,而不是组合逻辑。触发器改变时钟边缘的状态<代码>a没有。“始终”块对信号边缘敏感这一事实与此无关。这仅仅意味着内部的代码是在信号边缘执行的,
clk
的正边缘。但当这种情况发生时,什么也不会发生,所以这段代码的行为就像一个锁存器。

因为您尚未指定在时钟的边缘发生了什么。这就好像
a
根本不依赖于
clk
或其posedge。您的描述是当
rst=0
时,
a
被设置为
0
。此外,它(隐式地)表示,
a
在所有其他情况下保持其先前的值。这可以通过闩锁实现

请注意,仅仅因为您有@posedge of
clk
,并不意味着该块中的每个变量都将合成为一个触发器。当在clk的posedge处激活块时,您还需要为
a
进行非阻塞分配。看

如果您坚持使用触发器来实现相同的功能,您可以尝试以下方法:

always_ff @ (posedge clk or negedge rst) 
begin
  if (!rst)
    a <= '0;
  else 
    a <= a;  //Here, we are specifying what happens @posedge of clk
end
始终\u ff@(posedge clk或negedge rst)
开始
如果(!rst)

a因为您没有指定在时钟的边缘发生什么。这就好像
a
根本不依赖于
clk
或其posedge。您的描述是当
rst=0
时,
a
被设置为
0
。此外,它(隐式地)表示,
a
在所有其他情况下保持其先前的值。这可以通过闩锁实现

请注意,仅仅因为您有@posedge of
clk
,并不意味着该块中的每个变量都将合成为一个触发器。当在clk的posedge处激活块时,您还需要为
a
进行非阻塞分配。看

如果您坚持使用触发器来实现相同的功能,您可以尝试以下方法:

always_ff @ (posedge clk or negedge rst) 
begin
  if (!rst)
    a <= '0;
  else 
    a <= a;  //Here, we are specifying what happens @posedge of clk
end
始终\u ff@(posedge clk或negedge rst)
开始
如果(!rst)

a好的,但在我看来,它也可以表现得像一个人字拖。在负复位时,清除触发器,否则在clk的正边缘保持先前的值。这将相当于:[link]()而且,硬件不能有状态x。它可以是0、1或Z,因此在这两种情况下(锁存或触发器),它都会在通电时设置为任意值(0或1)。在我看来,代码可以两者兼而有之,但合成工具会选择占用较少资源的代码。@evilpascal选择占用较少资源的电路对合成器来说是非常重要的。好吧,但在我看来,它也可以像触发器一样工作。在负复位时,清除触发器,否则在clk的正边缘保持先前的值。这将相当于:[link]()而且,硬件不能有状态x。它可以是0、1或Z,因此在这两种情况下(锁存或触发器),它都会在通电时设置为任意值(0或1)。在我看来,这两种代码都可以,但合成工具会选择占用较少资源的代码。@evilpascal选择占用较少资源的电路对合成器来说是非常重要的。但我文章中的第一段代码应该像触发器一样,具有异步重置功能,而不是锁存器,因为它应该只在重置的下降沿采样,而不是在重置被取消断言的所有时间采样。请看我在编辑的问题中的分析。触发器能做什么,锁存器不能做什么,是在时钟边缘采样信号。重置会将输出值强制为常量值。这可以通过闩锁实现,合成工具首选闩锁,因为它的面积较低。示例中的
y
信号的作用类似于触发器,因为现在
nrst
的作用类似于时钟信号,并在其边缘对输入值进行采样。这不能由单个闩锁完成。请注意,尽管您指定了@negedge rst,但由于输出被指定给一个常量,因此它不需要对rst敏感。一个对rst电平敏感的模块就足够了。当一个常量位于赋值的右侧时,锁存器和触发器的行为是等效的。这不是问题。你提到了
y
信号,这就是事情变得奇怪的地方,因为
y
z
都被合成为锁存器,我认为这不可能是真的。因为右侧si上有一个变量(信号)