数字IC笔试知识点总结——锁存器、触发器、寄存器

 

目录

 锁存器、触发器、寄存器

锁存器特点、解决办法


锁存器、触发器、寄存器

锁存器:电平触发的存储单元,数据存储的动作(状态转换)取决于输入时钟(或者使能)信号的电平值,仅当锁存器处于使能状态时,输出才会随着数据输入发生变化。

分为普通锁存器门控锁存器普通锁存器无控制信号输出状态始终直接由输入决定。在实际的数字系统中,为了协调各部分的工作,往往需要有一个特定的控制信号去控制锁存器状态转换的时间,在控制信号无效时,输出保持不变,不随输入变换;当控制信号有效时,输出由输入决定,跟随输入变化。

①正是因为门控锁存器在控制信号有效的期间内,都可以接收输入信号,所以,激励信号的任何变化,都将直接引起锁存器输出状态的改变。这时输入信号若发生多次变化,输出状态也可能发生多次变化,这一现象称为锁存器的空翻
②其次,当门控锁存器的控制信号有效时,锁存器就变成了一个组合电路,时序逻辑电路的模型就等效为两个各组合电路互为反馈的反馈系统,因此,系统有可能会因为瞬态特性不稳定而产生振荡现象。


触发器(flip-flop):边沿敏感的存储单元,数据存储的动作(状态转换)由某一信号 的上升或者下降沿进行同步的(限制存储单元状态转换在一个很短的时间内)。

(钟控D触 发器其实就是 D 锁存器,边沿 D 触发器才是真正的 D 触发器

触发器分为两种,是主从触发器和边沿触发器。

主从触发器  在时钟有效期内(主触发器)接收数据,在时钟边沿输出状态转换。

边沿触发器  在时钟边沿期间,触发器才接收数 据并使输出状态转换。 (常见)


寄存器(register):用来暂时存放参与运算的数据和运算结果。在实际的数字系统中, 通常把能够用来存储一组二进制代码的同步时序逻辑电路称为寄存器。

区别与联系:

由于触发器内有记忆功能,因此利用触发器可以方便地构成寄存器。由于一个触发器能够存储一位二进制码,所以把 n 个触发器的时钟端口连接起来就能构成一个存 储 n 位二进制码的寄存器。

寄存数据的角度来讲,寄存器和锁存器的功能是相同的;

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

一般的设计规则是:在绝大多数设计中避免产生锁存器。隐蔽性强,破坏时序。


锁存器特点、解决办法


锁存器具备下列特点
(1)对毛刺敏感(使能信号有效时,输出状态可能随输入多次变化,产生空翻,对下一级电路很危险),不能异步复位,因此在上电后处于不确定的状态。
(2)锁存器会使静态时序分析变得非常复杂,不具备可重用性。                                                                                                                                                                                                         (首先, 锁存器没有时 钟参与信号传递,无法做 STA;其次,综合工具会将 latch 优化掉,造成前后仿真结果不一致)
(3)在FPGA中基本的单元是由查找表和触发器组成的,若生成锁存器反而需要更多的资源。根据锁存器的特点可以看出,在电路设计中,要对锁存器特别谨慎,如果设计 经过综合后产生出和设计意图不一致的锁存器,则将导致设计错误,包括仿真和综合。因此, 在设计中需要避免产生意想不到的锁存器。 如果组合逻辑的语句完全不使用 always  语句块,就可以保证综合器不会综合出锁存器。
(4)但如果锁存器和触发器两者都由与非门搭建的话,锁存器耗用的逻辑资源要比D触发器少(D触发器需要12个MOS管,锁存器只需6个MOS管),锁存器的集成度更高。所以在的ASIC设计中会用到锁存器。但锁存器对毛刺敏感,无异步复位端,不能让芯片在上电时处在确定的状态;另外,锁存器会使静态时序分析变得很复杂,不利于设计的可重用,所以,在ASIC设计中,除了CPU这高速电路,或者RAM这种对面积很敏感的电路,一般不提倡用锁存器。 

常见的锁存器包括三个端口:数据输入口、数据输出口、使能端。当使能端为高电平时,输入口的数据直接送到输出口,此时输入输出口可以看成是直接连通的;当使能端为低电平时,输出口的数据保持之前的数据不变,无论输入口的数据怎么变化,输出都保持不变,就是把原来的状态锁存下来了(所以才叫锁存器)。


锁存器的出现以及解决办法:
在基于   always   的组合逻辑描述语句中容易综合出锁存器的地方:

1. if……else……结构中缺少else

先看一个实际的例子:

if else锁存器

综合一下这两个电路,看看产生的RTL图是怎样的:

左边的电路:

时序逻辑

右边的电路:

组合逻辑

由RTL视图可以直观的看出,左边的电路没有生成锁存器,而右边的电路生成了一个我们不想要的锁存器(q1$latch)。左边的电路是时序逻辑,生成触发器,而触发器是有使能端(en)的,使能端无效时就可以保存数据,无需锁存器。右边的电路是组合逻辑,在en为低电平时,输出q1要保持不变,而组合逻辑没有存储元件,只能生成锁存器来保持数据。所以在时序逻辑中,不完整的 if…else… 结构并不会生成锁存器,而组合逻辑中不完整的 if…else… 结构就会生成锁存器。为了避免我们设计的组合逻辑中出现不想要的锁存器,在使用 if…else… 结构时一定要写完整。把刚才例子中右边的电路写完整,并查看其RTL视图如下:

完整的组合逻辑

写完整后,就没有生成锁存器,而是生成了一个二选一的选择器,这正是我们想要设计的。

2. case结构中的分支没有包含所有情况且没有default语句

case结构中一般要加上default语句,以保证出现意外情况也可以作出相应的反应。如果没有加default并且case分支不完整,当出现case分支中没有列出的情况时,电路状态保持原来的状态不变,于是就会生成锁存器来保存状态,如下图的电路所示:

case锁存

图中case分支中只写了(se=0)的情况,而(se=1)的情况未给出,且没有写default,于是当(se=1)时,q1保持原来的值不变,这样就产生了锁存器(q1$latch)。

如果将case分支补全,或者加上default语句,则如下图所示:

case无锁存

补全case分支后,就不会生成锁存器了。

同样,只有在组合逻辑中的case结构才有可能产生锁存器,而在时序逻辑电路中,即使case结构中的分支不完整,也不会产生锁存器,如下图所示:

case时序逻辑

实际上,在时序逻辑中,由于触发器具有锁存数据的功能,所以不会生成锁存器,锁存器只会在组合逻辑电路中产生

因此,在设计组合逻辑电路时,要注意将 if…else… 结构中的else写完整,case结构中一定要加上default语句,这样可以减少综合出锁存器的可能性。

其他例子,

3.形成锁存器,如果给q赋初值,不会形成锁存器
module a0(
input  clk     ,
input  [3:0] data,
input   [1:0] enable  ,
output reg q
);
always @(*)begin
       if(enable==0) q = data[3];
       else if(enable==1) q = data[2];
//       else if(enable==2) q = data[1];
//       else if(enable==3) q = data[0];
end
endmodule
(4)其他的情况(摘自他人博客,我均用DC综合过,结果正确)

case1(有锁存器):

module mux_latch
(
    input   [3:0] data,
    input   [1:0] valid,
    input   flag,
    output reg valid_data
);

always @ (*)
    begin
        if(valid==2'd0) valid_data = data[3];
        if(valid==2'd1) valid_data = data[2];
        if(valid==2'd2) valid_data = data[1];
        if(valid==2'd3) valid_data = data[0];
    end

endmodule

//---------------------------------------------------------

case 2解决办法1:加else与if配对

always @ (*)
    begin
        if(valid==2'd0) valid_data = data[3];else
        if(valid==2'd1) valid_data = data[2];else
        if(valid==2'd2) valid_data = data[1];else
        if(valid==2'd3) valid_data = data[0];else
                     valid_data = 1'b0;
    end

//-----------------------------------------------------------

case3解决办法2:赋初始值

always @ (*)
    begin

   valid_data = 1'b0
        if(valid==2'd0) valid_data = data[3];
        if(valid==2'd1) valid_data = data[2];
        if(valid==2'd2) valid_data = data[1];
        if(valid==2'd3) valid_data = data[0];
    end

//----------------------------------------------------------

case 4(有锁存器)

always @ (*)
begin
    case(valid)
        2'b00 : begin if(flag) valid_data = data[0];end
        2'b01 : begin if(flag) valid_data = data[1];end
        2'b10 : begin if(flag) valid_data = data[2];end
        2'b11 : begin if(flag) valid_data = data[3];end
    endcase

//-------------------------------------------------------------

case 5(有锁存器)

always @ (*)
begin
    case(valid)
        2'b00 : begin if(flag) valid_data = data[0];end
        2'b01 : begin if(flag) valid_data = data[1];end
        2'b10 : begin if(flag) valid_data = data[2];end
        2'b11 : begin if(flag) valid_data = data[3];end
        default:valid_data=1'b0;
    endcase
end

//--------------------------------------------------------------

case 6解决办法---赋初始值

always @ (*)
begin
   valid_data=1'b0;
    case(valid)
        2'b00 : begin if(flag) valid_data = data[0];end
        2'b01 : begin if(flag) valid_data = data[1];end
        2'b10 : begin if(flag) valid_data = data[2];end
        2'b11 : begin if(flag) valid_data = data[3];end
    endcase
end

//----------------------------------------------------------------

case7解决办法-- 加else

always @ (*)
begin
    case(valid)
        2'b00 : begin if(flag) valid_data = data[0];else valid_data = 1'b0;end
        2'b01 : begin if(flag) valid_data = data[1];else valid_data = 1'b0;end
        2'b10 : begin if(flag) valid_data = data[2];else valid_data = 1'b0;end
        2'b11 : begin if(flag) valid_data = data[3];else valid_data = 1'b0;end
    endcase
end

  • 1
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值