如果语句在Verilog中导致锁存推断?

时间:2013-11-17 21:28:50

标签: verilog fpga

我正在编写一个用于合成算法的Verilog代码,我对哪些情况可能导致锁定被推断有点困惑。下面是代码的一个这样的部分,虽然它在仿真中工作正常,我担心它可能会导致硬件问题。

always@(b1 or b2)

.....
// b1_map,b2_map,m1_map & m2_map are derived from combinational functions using b1 & b2
.....

if(b1_map<=20 && m2_map<=20 && b1_map>=0 && m2_map>=0)



begin
accumulator1[b1_map][m2_map]= accumulator1[b1_map][m2_map] + 1;
end

if(b2_map<=20 && m2_map<=20 && b2_map>=0 && m2_map>=0)

begin
accumulator2[b2_map][m2_map]= accumulator2[b2_map][m2_map] + 1;
end

//accumulator1  & accumulator2 are 2d registers mapped like 2d arrays

因此,在这种情况下,我希望仅在数据处于指定限制时才映射数据。是否会推断出锁存器,因为没有定义“其他”方案?我没有添加else语句,因为如果数据不在限制范围内,我就不想对该数据做任何事情。

3 个答案:

答案 0 :(得分:3)

如果你正确地写了你的if语句,你会没事的。当有通过if语句的路径不更新一个或多个输出时,会生成锁存器。像下面这样的代码将生成一个锁存器:

always @* begin
    if (a) begin
        b <= c & d;
        e <= f;
    end else begin
        b <= c | d;
    end
end

请注意,仅在a为真时才分配e?这需要一个锁存器才能正确实现。

生成锁存器的另一个可能性是当灵敏度列表不包含代码中使用的信号时。

always @(a) begin
    if (a) begin
        b <= c & d;
    end else begin
        b <= c | d;
    end
end

此代码将在c和d或b上生成锁存器,因为它只允许在更改时更新b。

答案 1 :(得分:2)

你误解了你的问题(你不应该接受答案) - 这个问题与闩锁根本没有关系。你的代码没有 感觉(用于合成)。 Quartus知道这一点,它基本上告诉你 重写你的代码。

你有一个组合块,当a时,会立即增加一个数字 信号变化。两个问题:(1)这肯定不是你想要的 硬件,和(2)当b1时,数字必须保持不变,而不是增量 而且b2没有改变。第二个是Quartus报告的一个 - 你的 电路需要某种存储器,它会报告为“锁存器”。不是 足够聪明地报告第一个问题,这是真正的问题。

尝试使用真实硬件将电路绘制为原理图。什么是&#39;任何 改变b1或b2&#39;实际上意味着你打算如何保持价值? 当b1和b2没有改变时,累加器?电路不可能, 但这超出了SO问题。

使电路同步,在时钟边沿触发,只需一个时钟 敏感度列表中的(并且可能是重置),并准确地保留内部 相同。你的if陈述没有错,因为你实际上是这样 如果没有任何有趣的事情发生,希望累加器保持不变 在b1 / b2。

答案 2 :(得分:1)

推断锁存器可能来自不完整的灵敏度列表或不完整的分配。

组合块的灵敏度列表通常应使用always @*编写。这可以避免在更新代码时编码错误。组合块(不包括边缘灵敏度的块)一旦合成将以always @*的方式执行。具体而言,命名信号会增加更多工作,并可能导致RTL达到门级(合成后)错误。

暗示必须保持该值的不完整分配将推断锁存器。锁存器本身并不坏,但需要仔细考虑。以这种方式推断出一个可以消除思想的完整性和对它的控制。这可能导致复杂的时序问题。由于锁存器对电平敏感而不是边缘敏感。理想情况下,您希望锁存器在时钟周期的第一个开启时打开,以便在从中读取数据时将其关闭。推断锁存器删除此控件。

如果使用else的语句完成if语句响板的默认值设置一个合理的值(0)可以帮助避免这些意外的锁存。