彻底理解锁存器

,让你不再为锁存器头疼!

锁存器(latch):是电平触发的存储单元,数据存储的动作取决于输入时钟(或者使能)信号的电平值,尽当锁存器处于使能状态时,输出才会随着数据输入发生变化。
触发器(flipflop)是边沿敏感的存储单元,数据存储的动作由某一信号的上升或者下降沿进行同步的。(钟控D触发器其实就是D锁存器,边沿D触发器才是真正的D触发器)
寄存器(register):用来暂时存放参与运算的数据和运算结果。在实际的数字系统中,通常把能够用来存储一组二进制代码的同步时序逻辑电路称为寄存器.
区别与联系:由于触发器内有记忆功能,因此利用触发器可以方便地构成寄存器。由于一个触发器能够存储一位二进制码,所以把n个触发器的时钟端口连接起来就能构成一个存储n位二进制码的寄存器。
从寄存数据的角度来讲,寄存器和锁存器的功能是相同的;它们的区别在于寄存器是同步时钟控制,而锁存器是电位信号控制。
一般的设计规则是:在绝大多数设计中避免产生锁存器。它会让您设计的时序完蛋,并且它的隐蔽性很强,非老手不能查出。锁存器最大的危害在于不能过滤毛刺。这对于下一级电路是极其危险的。所以,只要能用D触发器的地方,就不用锁存器。

附件里是更详细的分析。

让锁存器不再让人头痛.pdf



基本概念:

触发器是指有时钟边沿触发的存储单元。锁存器指一个由信号而不是时钟控制的电平敏感的设备。

锁存器的工作原理:

锁存器不同于触发器,锁存器在不锁存数据时,输出端的信号随输入信号变化,就像信号通过一个缓存器一样;一旦锁存信号起锁存作用,则数据被锁住,输入信号不起作用。因此锁存器也称为透明锁存器,值得是不锁存是输出对输入是透明的。

锁存器出现的地点:

两个最明显的地方:1:if语句的使用中缺少else语句(前提是不是始终边沿触发);2:case语句中没有给出全部的情况。

1:if语句中缺少else的情况:

process(en,d)

begin

if(en = '1')then //注意这里是边沿触发

q <= d;

end if; //注意没有else语句

end process;

综合出来的RTL图如下:





从上图可以看出综合出来的是锁存器。

针对这种情路可以采用一些措施来防止生成锁存器:给输出变量幅初值;增加else语句;将锁存器改为带使能的触发器。如下:

(1):给输出变量赋初值:

process(en,d)

begin

q <= '0'; //注意这里和上面的不同,在这里赋了初值

if(en = '1')then

q <= d;

end if;

end process;

此时综合出来

的RTL级图如
下:





此时综合出来的就是选择器。

(2):增加else语句:

process(en,d)

begin

if(en = '1')then

q <= d;

else

q <= '0';

end if;

end process;

此时综合出来的RTL级图与赋初值的图一样。

(3):将锁存器改为带使能的触发器:

process(clk,en)

begin

if(clk'event and clk = '1')then

if(en = '1') then

q <= d;

end if;

end if;

end process;

综合出来的RTL级图如下:





可以看出此时综合出来的已经是触发器。



2:case语句中情况不完整的情况:

process(sel,d)

begin

case sel is

when "000" => q <= d(0);

when "001" => q <= d(1);

when "010" => q <= d(2);

when "011" => q <= d(3); //没有写出所有的情况

end case;

end process;

理论上上面的代码综合出来的图应该是带锁存器的,可奇怪的是我用synplify综合出来的却没有。是不是自动优化成选择器了?





相关文档
最新文档