在Verilog / SystemVerilog中推断锁存器

时间:2015-01-24 22:40:17

标签: memory verilog system-verilog quartus

程序块中的语句按顺序执行,那么为什么block1,block2或block3中没有任何一个推断出锁存器?

module testing(
    input  logic a, b, c,
    output logic x, y, z, v
    );

    logic tmp_ref, tmp1, tmp2, tmp3;

    //reference
    always_comb begin: ref_block
        tmp_ref = a & b;
        x = tmp_ref ^ c;
    end

    always_comb begin: block1
        y = tmp1 ^ c;
        tmp1 = a & b;
    end

    always @(*) begin: block2
        tmp2 <= a & b;
        z = tmp2 ^ c;
    end

    always @(c) begin: block3
        tmp3 = a & b;
        v = tmp3 ^ c;
    end
endmodule: testing

在block1中,y是在tmp1的新值可用之前使用阻塞分配计算的。

在块2中,tmp2使用非阻塞分配计算,该分配应推迟总块完成时的分配。同时,z是使用阻塞分配计算的,并且tmp2的新值尚不可用。

在块3中,有一个不完整的敏感列表,但仍然没有锁存。

以下是Quartus II 14.1的综合结果: enter image description here

只有在我添加此块时才会推断出锁存器:

//infers a latch
always @(*) begin: block4
    if (c == 1'b1) begin
        tmp4 = a & b;
        w = tmp4 ^ c;
    end
end

有人可以解释为什么不完整的敏感度列表或在更新值之前使用变量不会推断出组合块中的锁存器吗?

1 个答案:

答案 0 :(得分:2)

组合块中使用的赋值类型不会影响合成。使用非阻塞(<=)可能会导致RTL(预合成)到门(合成后)模拟器不匹配。

灵敏度列表也是如此,综合将给出自动生成或完整列表的行为。

在时钟进程(@(posedge clk))中使用非阻塞(<=)来获取触发器的模拟行为。也可以使用阻塞(=)在计时过程中使用组合代码,但混合样式被认为是一种糟糕的编码实践。组合部分代码只是移动到一个单独的组合块(always @*)。

锁存器是一个基本的存储器元件,如果电路不需要存储器,则不会推断它。

例如:

always @* begin: 
    v = (a & b) ^ c;
end

v完全由输入定义,不涉及内存。与之相比:

always @* begin
  if (c == 1'b1) begin
    w = (a & b) ^ c;
  end
end

c为0时,w必须保持其值,因此推断出锁存器。

值得注意的是,虽然锁存器并不坏,但必须注意打开和关闭的时间,以确保它们捕获正确的数据。因此,推断锁存器通常被视为坏的并且来自不良编码。

SystemVerilog具有以下语义,用于语义暗示设计意图:

always_latch begin
  if (c == 1'b1) begin
    w = (a & b) ^ c;
  end
end