概述
数字电路基础知识——锁存器与触发器在Verilog中使用问题
一、 锁存器(latch)和触发器 (Flip-Flop,FF) 的区别
-
锁存器与触发器
一般数字电路中说D触发器指的是边沿D触发器,钟控D触发器其实就是D锁存器,边沿D触发器才是真正的D触发器,钟控D触发器在使能情况下输出随输入变化,边沿触发器只有在边沿跳变的情况下输出才变化。这里一般用的最多的触发器的结构是以用CMOS传输门构成的D触发器:
常见的锁存器包括三个端口:数据输入口、数据输出口、使能端。当使能端为高电平时,输入口的数据直接送到输出口,此时输入输出口可以看成是直接连通的;当使能端为低电平时,输出口的数据保持之前的数据不变,无论输入口的数据怎么变化,输出都保持不变,就是把原来的状态锁存下来了(所以才叫锁存器)。锁存器与触发器的区别在于:锁存器是电平触发,而触发器是边沿触发。锁存器在不锁存数据时,输出随输入变化;但一旦数据锁存时,输入对输出不产生任何影响。锁存器与其所有的输入信号相关,当输入信号变化时锁存器就变化,没有时钟端;触发器受时钟控制,只有在时钟触发时才采样当前的输入,产生输出。
锁存器由电平触发,非同步控制。在使能信号有效时锁存器相当于通路,在使能信号无效时锁存器保持输出状态。触发器由时钟沿触发,同步控制。
锁存器对输入电平敏感,受布线延迟影响较大,很难保证输出没有毛刺产生;触发器则不易产生毛刺。
两个锁存器可以构成一个触发器,归根到底还是dff是边沿触发的,而latch是电平触发的。
-
总结下锁存器的主要缺点:
(1)对毛刺敏感,不能异步复位,因此在上电后处于不确定的状态。
(2)锁存器会使静态时序分析变得非常复杂,不具备可重用性。 (首先, 锁存器没有时钟参与信号传递,无法做 STA;其次,综合工具会将 latch 优化掉,造成前后仿真结果不一致)
(3)在 PLD 芯片中,基本的单元是由查找表和触发器组成的,若生成锁存器反而需要更多的资源。根据锁存器的特点可以看出,在电路设计中,要对锁存器特别谨慎,如果设计经过综合后产生出和设计意图不一致的锁存器,则将导致设计错误,包括仿真和综合。因此,在设计中需要避免产生意想不到的锁存器。
二、 在使用verilog 语言时描述触发器应注意的问题
由于always块可以表示时序逻辑或者组合逻辑,也可以用always块既表示电平敏感的透明锁存器又同时表示组合逻辑。但不推荐使用这种描述方法,因为这容易产生错误和多余的电平敏感的透明锁存器。这在电路中是尽量避免发生的。
因此在使用Verilog中极易产生锁存器的情况有如下几种:
- always@(敏感列表)
如果要为电平敏感的锁存器建模,使用连续赋值语句是最简单的方法(assign)。
module combination(a,b,c);
input a,b,c;
reg e,d;
always @(a or b or c) begin //d信号没有在敏感信号列表中,综合时会产生一个透明的锁存器 会锁存d
e =d & a & b;
end
endmodule
解决办法:
上面的代码片段,极容易出现透明的电平敏感锁存器,可以使用always(*)或者assign语句赋值。
module combination(a,b,c);
input a,b,c;
reg e,d;
always @(*) begin
e =d & a & b;
end
// assign e = d & a & b;
endmodule
- if 语句的使用中缺少 else 语句(前提是不是始终边沿触发,即时序逻辑还是组合逻辑)
1)时序逻辑:
2)组合逻辑:
当使用Vivado综合工具综合时,会出现两种不一样的电路。
组合逻辑(电平触发)会出现锁存器。在enable为低电平时,输出q1要保持不变,而组合逻辑没有存储元件,只能生成锁存器来保持数据
而时序逻辑(边沿触发)则生成触发器,而触发器是有使能端(enable)的,使能端无效时就可以保存数据,无需锁存器。
因此在时序逻辑中,不完整的 if…else… 结构并不会生成锁存器,而组合逻辑中不完整的 if…else… 结构就会生成锁存器。为了避免我们设计的组合逻辑中出现不想要的锁存器,在使用 if…else… 结构时一定要写完整。
对于上面生成锁存器的组合逻辑电路可以
修改如下:
module dff(q,enable,data);
input data,enable;
output q;
reg q;
always@(enable or data) begin
if (enable)
q <= data;
else
q<= 0;
end
endmodule
其RTL电路:(2MUX)
- case缺少default语句
1)组合逻辑中case 缺少default或者没有完全写完。
图中case分支中只写了(sel=0)的情况,而(sel=1)的情况未给出,且没有写default,于是当(se=1)时,q保持原来的值不变,这样就产生了锁存器。
2)时序逻辑中,即使case语句不完整,在综合时,会生成一个触发器,并不会生成锁存器。
4. 即使if-else 语句完整并且是组合逻辑电路一定不会生成锁存器吗?
答案是否定的
例如:锁存器的Verilog描述:
module dff(q,sel,data);
input data;
input sel;
output q;
reg q;
always@(*) begin // 锁存器的定义描述
if(sel)
q = data;
else
q = q;
end
endmodule
综合出的RTL电路:
仍然会得到一个锁存器
if/else文件是完整,但是依然产生了锁存器,因为我们这个电路所描述的功能就是一个锁存器。其实语句不完整和else data_out=data_out;是一样的。这里,所希望的就是保持数值,但这种情况可以通过增加一个寄存器来保持,也不应该生成一个锁存器。
三、使用Verilog避免生成锁存器应注意的事项
- 锁存器只存在于组合电路中,在时序电路上是不存在的。
- 当然上述的组合逻辑生成锁存器如果没有完整写出else或者case语句,可以通过赋初值的方式也能避免产生锁存器。
对于上面的左一的代码块,会综合出锁存器,当我们对输出赋值一个初值时,便会生成一个二选一的选择器。 - 总结一下避免生成锁存器的一些方法:
1)组合逻辑尽量使用assign语句描述组合逻辑电路。
2)时序逻辑电路不用担心生成锁存器,但也要尽量规避一些if-else 或者case不完整的情况,养成好的coding style.
3)如果采用case或者if结构描述组合逻辑时,应确保全部写全,不能遗漏。或者在组合逻辑块中先给输出变量赋初值。
最后
以上就是轻松小蘑菇为你收集整理的数字电路基础知识——锁存器与触发器在Verilog中使用问题的全部内容,希望文章能够帮你解决数字电路基础知识——锁存器与触发器在Verilog中使用问题所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复