锁存器是电平触发的控制器件,这与边沿触发的触发器是有着本质的区别的。锁存器是一种在异步时序电路系统中,对输入信号电平敏感的单元,用来存储信息。一个锁存器可以存储1bit的信息,通常,锁存器会多个一起出现,如4位锁存器,8位锁存器。锁存器在数据未锁存时,输出端的信号随输入信号变化,就像信号通过一个缓冲器,一旦锁存信号有效,则数据被锁存,输入信号不起作用。因此,锁存器也被称为透明锁存器,指的是不锁存时输出对于输入是透明的。与触发器的区别:两者都是基本存储单元,单锁存器是电平触发的存储器,触发器是边沿触发的存储器。本质是,两者的基本功能是。一样的,都可以存储数据。意思是说一个是组合逻辑的,一个是在时序电路中用的,时钟触发的
verilog对锁存器的描述(建模):
常见的锁存器包括三个端口:数据输入口、数据输出
always@(E or D)
begin
if(E)
Q = D ;
end
1. 什么情况下会生成锁存器?
在组合逻辑中,若是存在某个信号需要保持不变的时候,就会生成锁存器。
看几个Verilog描述:
描述方式1:
always@(*)
begin
if(sl)
begin
q = a ;
end
end
根据组合逻辑的描述,假设生成如下的选择器,即sl =1 时候,q = a,如下所示:
描述方式2:
这里需要注意一点,以上的verilog描述中其实隐含了 else 即若sl =0时,q保持不变即 q=q,也就是上述的verilog描述与下面的verilog描述是一样的:
always@(*)
begin
if(sl)
begin
q = a ;
end
else
begin
q = q ;
end
end
如何实现呢?最直接的想法似乎是如下的电路实现:
这是不可以的,组合逻辑中是不能有回路的,要求都是正向的。严格说来,Verilog描述组合逻辑“有反馈 ”时,这段代码可以被编译和实现 出组合路,但是编译器肯定给出警告 ,因为这段代码的结果没有实际意义 根本不知道结果是多少。
CAUSE: The TimeQuest Timing Analyzer found latches implemented using non-optimal resources (look-up tables (LUTs) with combinational feedback). The TimeQuest analyzer replaces the combinational loop with an equivalent latch. The TimeQuest analyzer treats this logic as asynchronous endpoint, and will not analyze the path through the node.
ACTION: You must implement these latches with registers using asynchronous load and
data signals, or remove them from your design. For more information, run the check_timing tcl command in the TimeQuest analyzer.原因:TimeQuest时序分析器发现使用非最佳资源(具有组合反馈的查找表(LUT))实现锁存器。 TimeQuest分析器用等效的锁存器替换组合循环。 TimeQuest分析器将此逻辑视为异步端点,并且不会分析通过该节点的路径。
操作:您必须使用异步加载数据信号的寄存器来实现这些锁存器,或者从设计中删除它们。 有关更多信息,请在TimeQuest分析器中运行check_timing tcl命令
以加法为例,那生成的加法电路会执行几次呢?还是一直在加?怎么控制呢?
描述方式3:
always@(*)
begin
a = a + 1;
end
我在尝试综合时,综合工具会将Latch优化掉,这将会造成前、后仿真结果不一致。
描述方式4:
always @ (A,B)
C = A & B;
只要A或B有变化就会触发对C的赋值。
描述方式5:
always@(*)
begin
case(d)
2'b00: a=b>>1; //这里没有对C描述,因此c保持不变,会生成锁存器
2'b11: c=b>>1;//a保持不变
default:
begin
a = b ;
c = b;
end
end
看到一篇博文中有一个问题,感觉挺值得注意的:
如下的设计中,采用了时序逻辑设计,却生成了锁存器
module Decode( input A, input B, input C, output reg[31:0] edata, output reg[31:0] eCapData, input bCap, output reg CapSt, input n_rst, input [31:0] rstVal, input clk); reg[1:0] state; always@(posedge clk or negedge n_rst) begin if(!n_rst) begin edata <= rstVal; state <= {A,C}; end else begin state <= {A,B}; edata <= {31'd0,A}; *****此处省略一万***** end ———————————————— 版权声明:本文为CSDN博主「江东风又起」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/ysgjiangsu/article/details/82718462
他分析后得出原因:表面上是按照触发器的方式在写代码,实则不然。在异步复位代码段,我的输出依然由外界输入决定,因此综合之后产生了锁存器。
将代码作如下修改,问题解决:module Decode( input A, input B, input C, output reg[31:0] edata, output reg[31:0] eCapData, input bCap, output reg CapSt, input n_rst, input [31:0] rstVal, input clk); reg[1:0] state; always@(posedge clk or negedge n_rst) begin if(!n_rst) begin edata <= 32'd0; state <= 2'd0; end else begin state <= {A,B}; edata <= {31'd0,A}; *****此处省略一万***** end ———————————————— 版权声明:本文为CSDN博主「江东风又起」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。 原文链接:https://blog.csdn.net/ysgjiangsu/article/details/82718462
2. 锁存器的危害?
首先声明,latch并非完全有害,不然FPGA中也不会既有latch和flip-flop,在支持DDR的IOB中,利用latch实现DDIO。那为什么明明锁存器比触发器节省面积却还要去避免使用latch而采用触发器呢?
对时序分析的影响:
我们尽可能的避免使用或者生成锁存器,主要还是因为锁存器的存在不利于时序的分析。下图中,做时序分析时候,若组合逻辑不生成latch,那么在分析该时序是否符合时候,就可以根据分析原理去分析寄存器输出延迟Tco,组合逻辑延迟Tcomb,触发器的建立时间Ts,要求延迟的综合不超过时钟周期,这都是可预知的。假如在下图两个触发器间的组合逻辑中生成了latch,那么该路径的时序就很难分析,因为latch是电平触发,而不是时钟的边沿去触发,latch很可能在时钟的有效沿之间被触发,这就导致无法确定latch的输出什么时候为低,什么时候为高(与时钟不同步了),这是锁存器的特性所导致的。而采用D触发器,分析的时候只需考虑触发器之间的路径即可。
还有种说法:
锁存器为电平触发,无效电平则锁存,有效电平输入即反应到输出,由于延时不同容易产生毛刺。组合逻辑中数据不需要锁存,需要避免产生锁存器。FPGA资源中木有锁存器,需要触发器加逻辑门构成,消耗逻辑资源较多,但有时为了需要满足一些规范协议,会用到锁存器,总之FPGA用的很少。 而ASIC设计中,由于锁存器构成较简单,传输速度快,用锁存器可以有效提高集成度,所以用的比较多!
总结:
-
对毛刺敏感,不能异步复位,所以上电以后处于不确定的状态;
-
Latch会使静态时序分析变得非常复杂;
-
在PLD芯片中,基本的单元是由查找表和触发器组成的,若生成锁存器反而需要更多的资源。
-
第三条也是最基本的原因。
3. 如何避免生成锁存器
组合逻辑生成锁存器的原因是逻辑中有信号需要保持不变,组合逻辑不能有环路(即反馈),因而通过生成锁存器达到保持不变的目的。
这样的话,可以从两个角度入手:(1)采用时序逻辑,即在组合逻辑中插入触发器,多用触发器来实现信号的寄存;(2)尽可能避免在组合逻辑中某个信号需要保持不变,或者说避免组合逻辑存在环路。
【注】:
经常看到说组合逻辑中,if-else语句不要省略else,而case语句中条件分支也不要缺省,否则容易产生锁存器。其本质上说的是不要出现保持不变的信号,因为缺省后就默认会保持不变。组合逻辑的if语句缺省else导致描述变为else时候信号保持不变,因而生成锁存器,但如果组合逻辑中if-else语句的else中还描述的还是信号保持不变,那就算有else依旧会生成锁存器。
贴一个其他博主的总结:链接
简述组合逻辑的注意事项:
(1)避免组合逻辑反馈环路(容易毛刺、振荡、时序违规等)。
解决:A. 牢记任何反馈回路必须包含寄存器 ; B.检查综合、实现报告的warning信息,发现反馈回路(combinaTIonal loops)后进行相应修改。
(2) 替换延迟链。
解决:用倍频、分频或者同步计数器完成。
(3)替换异步脉冲产生单元(毛刺生成器)。
解决:用同步时序设计脉冲电路。
(4)慎用锁存器。
解决方式:
A、使用完备的if…else语句;
B、检查设计中是否含有组合逻辑反馈环路;
C、对每个输入条件,设计输出操作,对case语句设置default 操作。特别是在状态机设计中,最好有一个default的状态转移,而且每个状态最好也有一个default的操作。
D、如果使用case语句时,特别是在设计状态机时,尽量附加综合约束属性,综合为完全条件case语句。
小技巧:仔细检查综合器的综合报告,目前大多数的综合器对所综合出的latch都会报“warning”,通过综合报告可以较为方便地找出无意中生成的latch。