关于锁存器和触发器的一点记录

一,锁存器与寄存器的区别:

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

首先应该明确锁存器和触发器也是由与非门之类的东西构成。尤其是锁存器,虽说数字电路定义含有锁存器或触发器的电路叫时序电路,但锁存器有很多组合电路的特性。

组合电路就是一个真值表,一个函数,一组输入对应一组输出,当前什么输入就根据函数得到什么输出,实时跟踪变化,这样也就容易有冒险、竞争之类的问题产生毛刺。

二.锁存器的危害:

对毛刺敏感,不能异步复位,所以上电以后处于不确定的状态;

Latch会使静态时序分析变得非常复杂;

在PLD芯片中,基本的单元是由查找表和触发器组成的,若生成锁存器反而需要更多的资源。

三.产生的原因

上面说了那没多只是觉得网上的没把锁存器说明白。下面的才是重点。

1,case

2,if——-else if

3,always@(敏感信号表)

四. 解决

1.case——————加default:

关于defalut的情况:
一是可以 default:data=1‘bx;这个x表示未知,在综合时可以避免产生锁存器。在仿真时是红线表示。

二是 default:data=0;这样产生一个默认的情况。

2.if———————–一定要有else语句。

3.always———如是说道:在赋值表达式右边参与赋值的信号都必须在always@(敏感电平列表)中列出。

如果在赋值表达式右端引用了敏感电平列表中没有列出的信号,那么在综合时,将会为该没有列出的信号隐含地产生一个透明锁存器。
4.赋初值。

分为如下几种情况:
1.产生latch,warning

always@(a or en)
   begin
//      b = 1'b0;
      casex(en)
         3'bxx1: b = a[0];
         3'bx1x: b = a[1];
         3'b1xx: b = a[2];
//         default:  b = 1'b0;
      endcase
   end

RTL图如下:


这里写图片描述

2.由于阻塞语句,使用default或者再case前直接赋值;
不产生latch ,综合是没有warning

always@(a or en)
   begin
//      b = 1'b0;
      casex(en)
         3'bxx1: b = a[0];
         3'bx1x: b = a[1];
         3'b1xx: b = a[2];
         default:  b = 1'b0;
      endcase
   end
always@(a or en)
   begin
      b = 1'b0;
      casex(en)
         3'bxx1: b = a[0];
         3'bx1x: b = a[1];
         3'b1xx: b = a[2];
//         default:  b = 1'b0;
      endcase
   end

RTL如下:
这里写图片描述

五.关于时序逻辑if_else不完整
时序电路,生成触发器,触发器是有使能端的,使能端无效时数据不变,这是触发器的特性。

always@(posedge I_clk)
   begin
      if(en)
         c <= a;
//      else
//         c <= c;
   end
endmodu


这里写图片描述

常见的错误及纠正:

always@(a or en)
   begin
      if(en)
         c = a;
   end
endmodule

产生latch:
这里写图片描述

改为:

always@(a or en)
   begin
      if(en)
         c = a;
      else
         c = 0;
   end
endmodule

这里写图片描述
变为了选择器。

猜你喜欢

转载自blog.csdn.net/alangaixiaoxiao/article/details/82432204