锁存器的产生--习题

在这里插入图片描述
在这里插入图片描述
FPGA中避免锁存器的方法:
【1】在组合逻辑进程中,if语句一定要有else。并且所有的信号都要在if的所有分支中被赋值。

always @( * )

begin

if ( sig_a == 1‘b1 )

sig_b = sig_c;

end

这个是绝对会产生latch的。

这种情况要想避免锁存器的出现,应当为if语句增加else语句。

【2】下面也会产生latch。也就是说在组合逻辑进程中不能出现自己赋值给自己或者间接出现自己赋值给自己的情况。

always @( * )

begin

  if ( rst == 1‘b1 ) 

     counter = 32’h00000000;case语句的default一定不能少!

原因和if语句相同,这里不再多说了。

需要提醒的是,在时序逻辑进程中,default语句也一定要加上,这是一个很好的习惯。

else 

     counter = counter + 1;

 end

但如果是时序逻辑进程,则不存在该问题。

【3】case语句的default一定不能少!原因和if语句相同,这里不再多说了。需要提醒的是,在时序逻辑进程中,default语句也一定要加上,这是一个很好的习惯。

【4】组合逻辑进程敏感变量不能少也不能多

下面哪种写法会产生latch?为什么?
代码如下:
A.


always  @(*)begin
if(d)
a = b;
end

代码A:

是一个always语句块构成的组合逻辑,其中缺少else分支。

当d=1’b0时,综合工具会默认保持a的值,即生成锁存器
在这里插入图片描述

B

always  @(*)begin
if(d)
  a = b;
else
  a = a;
end

代码B虽然补全了else分支语句。但是,其代码依然有保持功能,即会生成锁存器;也就是说,组合逻辑是否会生成锁存器,其根本原因是该组合逻辑存在保持功能!
在这里插入图片描述

C

always @ (b or d)
  case(d)
    2’b00: a=b>>1;
    2’b11: c=b>>1;
    default:
      begin
        a=b;
        c=b;
      end
endcase

代码C在always语句块内使用了case语句,并且case语句中含有default分支。但是,我们可以发现:
【1】d=2’b00时,没有说明c的赋值;
【2】d=2’b01时,没有说明a的赋值;
在这里插入图片描述

D

always @(b or d)begin
  a=b;
  c=b;
  case(d)
    2’b00: a=b>>1;
    2’b11: c=b>>1;
  endcase
end

代码D和代码C的不同是,它在always语句块的开始,对a和c进行了默认赋值;

这就类似于软件里面的初始化,当然只是类似而已,不会生成锁存器;

在这里插入图片描述

E

always@(bor d)begin
  case(d) //synopsys full_case
    2’b00: a=b>>1;
    2’b11: c=b>>1;
  endcase
end

使用了//synopsys full_case 选项,该选项:

1、防止综合工具将case语句综合成不必要的优先级电路,增大硬件开销

2、和default语句类似,补全case语句没有列出的情况。

3、但是//synopsys full_case会造成工具之间的移植性问题,改代码依然综合出了锁存器
在这里插入图片描述

时序电路—之锁存器

verilog中if与case语句必须完整,即if要加上else,case后要加上default语句,以防止锁存器的发生,接下来就来说说其中原因。

一,**什么是锁存器?**锁存器与触发器的区别。http://www.eefocus.com/liuyuxue/blog/13-11/300280_d7008.html

锁存器与触发器最大的区别在于,锁存器是电平触发,而触发器是边沿触发。锁存器在不锁存数据时,输出随输入变化;但一旦数据锁存时,输入对输出不产生任何影响。

锁存器和触发器区别
http://wenku.baidu.com/link?url=co1YvI0Ktb7sItCPzqNXiy7SXyWigv7uAnWaL3EtOT_7T7XsYOXIcfCTlYvlqPgPhy3bBpbeiQAcM2hVAUbK9qiJxRI3F0JctHaLCsWrYiS(写的挺好的)

二,为什么语句的不完整会导致锁存器的产生?
在这里插入图片描述
解:

老阮 (2014-10-21 19:30:10)
1、时序电路,生成触发器,触发器是有使能端的,使能端无效时数据不变,这是触发器的特性。
2、组合逻辑,由于数据要保持不变,只能通过锁存器来保存。
楼主位的第二个代码就是在enable为低时,数据不变,因此要生成锁存器。 第一个代码,由于是时序逻辑,生成的触发器在enable无效时就可以保存数据。跟锁存器无关。

walkman416
个人理解: 所谓生成latch其实是针对使用always语句描述一个组合逻辑而言,因为如果描述时序逻辑总是使用时钟或者时钟+复位作为敏感列表条件,所生成的电路总是组合逻辑+DFF;如果是描述组合逻辑,敏感列表中必然没有时钟复位,而是组合逻辑的输入信号。在FPGA设计,避免使用latch,不利于时序分析和仿真。 楼上有提到latch比DFF省资源, 这个在FPGA设计中其实还好, 因为在FPGA中DFF就是一个专用的硬件资源,并且数量也比较多。

使用always描述组合逻辑时,好的习惯是使用always @(*)作为敏感列表, 并且需要检查每个分支都有明确的赋值,从而避免生成latch.

黎释注
我是这么理解的,在一份资料看的,
时序电路=组合逻辑电路+储存电路;
储存电路有两个:锁存器(latch)和触发器;
边沿触发产生触发器,
电平触发产生锁存器,
多个触发器组成寄存器,

当描述的是时序电路,寄存器变量对应的寄存器
描述的是完整的组合逻辑电路,对应为硬件连线
当描述的是不完整组合逻辑,则寄存器对应的是锁存

总结:
1,存储单元按照触发的方式分为电平触发和边沿触发,电平触发的为锁存器,边沿触发的触发器。 2,对于if,case的完整性,@老阮已经说的很清楚了,在FPGA建议使用触发器。
参考文献:
【1】https://blog.csdn.net/bleauchat/article/details/100068920
【2】版权声明:本文为CSDN博主「ALIFPGA」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/woshifennu1234/article/details/81805163
【3】https://www.cnblogs.com/rrttp/p/5945082.html

发布了67 篇原创文章 · 获赞 7 · 访问量 4948

猜你喜欢

转载自blog.csdn.net/qq_43042339/article/details/104112537