锁存器的产生
论述1
(转)时序电路,生成触发器,触发器是有使能端的,使能端无效时数据不变,这是触发器的特性。
组合逻辑,由于数据要保持不变,只能通过锁存器来保存。
第一个代码,由于是时序逻辑,生成的触发器在enable无效时就可以保存数据。跟锁存器无关。
第二个代码就是在enable为低时,数据不变,因此要生成锁存器。
论述2
(转)所谓生成latch其实是针对使用always语句描述一个组合逻辑而言。
因为如果描述时序逻辑总是使用时钟或者时钟+复位作为敏感列表条件,所生成的电路总是组合逻辑+DFF;
如果是描述组合逻辑,敏感列表中必然没有时钟复位,而是组合逻辑的输入信号。在FPGA设计,避免使用latch,不利于时序分析和仿真。
楼上有提到latch比DFF省资源, 这个在FPGA设计中其实还好, 因为在FPGA中DFF就是一个专用的硬件资源,并且数量也比较多。
使用always描述组合逻辑时,好的习惯是使用always @(*)作为敏感列表, 并且需要检查每个分支都有明确的赋值,从而避免生成latch。
论述3
从阻塞和非阻塞的角度总结一下always块。
1.要生成DFF,是时序逻辑所以用<=,要用时钟所以用always@(posedge clk),。
2.要生成latch,是时序逻辑所以用<=,本质是个不完整的if分支,不用时钟所以用always@(*)。
3.要生成组合逻辑,是组合逻辑,都用=,自然不用时钟所以用always@(*)。
关于alway块,有两点是要小心的:
(一)写组合逻辑时,由于分支不完整带来的latch。
(二)写时序逻辑时错用=导致逻辑错误。
论述4
生成latch的代码
module top_module (
input d,
input ena,
output q);
assign q=(ena)?d:q;
endmodule
module top_module (
input d,
input ena,
output reg q);
always @(*)begin
q <= (ena) ? d : q;
end
endmodule
不推荐
module top_module (
input d,
input ena,
output reg q);
always @(*)begin
q = (ena) ? d : q;
end
endmodule
//上述3种描述⽅式⽣成最终电路是相同的。
or
always@(*) begin
if(E) begin
Q = D
end
end
防止综合不必要的锁存器
锁存器并不是一种所谓的“不好的东西”,据说在 ASIC 设计中会使用锁存器减少硅片面积,提高流水线处理中的性能(这段来自书本)。糟糕的是综合器推断出了不必要的,和原本设计目的相冲突的锁存器。
方法一:使用同步设计
方法二:保持良好的编码风格,使用完整的 if 语句覆盖所有的 case
always @(latch ena) begin
if(latch_ena)
latch_out = latch data;
else
latch_out = 1'b0;
end
综合器将代码综合为了一个选择器
总结
时序电路无论如何不会产生锁存器,组合电路只要条件不完备就会产生锁存器。
FPGA ug974
FDCE
FDPE
FDRE
FDSE
LDCE
LDPE
总结
关于FPGA中锁存器的生成 有FPGA电路图