[英]Inferring latches in Verilog/SystemVerilog
过程块中的语句按顺序执行,那么为什么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
在块1中,使用新的tmp1值之前的阻塞分配来计算y。
在block2中,tmp2是使用非阻塞分配计算的,该分配应在始终阻塞完成时推迟分配。 同时,使用阻塞分配计算z且tmp2的新值尚不可用。
在块3中,灵敏度列表不完整,仍然没有锁存器。
这是Quartus II 14.1的综合结果:
仅当我添加此块时,才会推断出闩锁:
//infers a latch
always @(*) begin: block4
if (c == 1'b1) begin
tmp4 = a & b;
w = tmp4 ^ c;
end
end
有人可以解释为什么在更新值之前不完整的灵敏度列表或使用变量不会推断组合块中的锁存器吗?
组合块中使用的分配类型不会影响综合。 使用非阻塞( <=
)可能会导致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
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.