tag 标签: 锁存器

相关帖子
相关博文
  • 热度 31
    2016-2-6 14:13
    3217 次阅读|
    0 个评论
    第二讲 case 语句及 task 任务块 实验任务: ( 1 )用 case 语句实现具有译码功能的模块(类似于 3-8 译码器); ( 2 )学会在 testbench 中使用 task 任务块语句,用它产生测试数据给待测模块; ( 3 )注意 case 语句的写法,思考:若 case 分支列举不全面,会出现什么不良后果? 实验内容及过程: 因本次实验简单,故直接贴出代码并予以简单的讲解,代码截图如下图所示: 注意事项: 在用 Verilog 语言设计数字电路的时候,出现多余无用的锁存器对电路危害大,应格外小心,消除锁存器的办法:① always 中的敏感信号列表要写全(要包含 case 条件、赋值符号右边的变量);②所有条件分支要写全(包括default );③ if—else 语句要写全,不要只写 if 不写 else ,没有 else 的时候也要写一条空的 else 语句。 以下两个图展示了 case 条件分支写全与不全时综合后的结果: 图 1 case 条件分支不全时综合的 RTL 视图 图 1 为漏写了 3'd7:begin         o_data = 8'b0111_1111;         o_dv = 1'b1; end 这条分支时综合后的结果,从图 1 可看出,在电路的输出端出现了 8 个 latch ,且它们都与 MUX7 的输出端相连。由此可见,是因为漏写了上面的那段语句。 在利用 Quartus II 综合 设计的实例时,也会出现一些相关的警告,如图 2 所示: 图 2 Quartus II 综合时产生的警告 正确的 RTL 视图应该如图 3 所示: 图 3 正确的 RTL 级视图(无 latch )   在 testbench 中使用 task 任务块依次产生 0~255 之间的数,并分别将这些数值赋值给 i_data 和 i_addr ,代码截图如下图所示: 关于写 task 任务块,有很多语法约束,这里一一列举出来: ( 1 ) task 没有端口列表,但可以有输入变量列表,并且变量须在 task 内部予以声明(如上图中的 size ); ( 2 )输入输出端口可在 task 内部尽心声明,支持 input 、 output 以及 inout 三种端口信号; ( 3 )可以用 integer 或 reg 声明 task 要用到的变量,但不能用 wire 声明; ( 4 ) task 任务块也属于块语句,但与 module—endmodule 的架构类似,可仿照 module—endmodule 的架构 task 任务块,但是, task 与 always 、 initial 属于同一层次,故 task 的内容要写在 always 块和 initial 块之外,但可在 always 块、 initial 块以及 task 任务块中调用 task 任务块(即:任务中可以再调用其他任务); ( 5 )调用任务时,需按照端口声明的顺序调用(跟模块实例化中的“按顺序”实例化的操作是类似的); ( 6 )任务不能实时输出,而是只能在整个任务结束时得到一个最终的结果,输出的值也是这个最终的结果的值,例如: task seq; output    q;   begin q = 0; #10   q = 1; end   endtask 上述代码仿真的结果是,调用此任务之后只会得到一个延迟 10 个时间单位的输出数据 1 ,前 10ns 输出数据的状态是未知的,如图 4 所示: 图 4 task 不能实时输出的仿真图 ( 6 )在仿真过程中如果出现多次调用同一个任务,且每次操作的值不同时,就可能出现由于地址空间相互覆盖而导致的结果错误。针对这一问题,通常使用自动任务解决此问题。 最后,贴出本例的仿真波形图,如图 5 所示: 图 5 译码器和 task 任务块的功能仿真图  
  • 热度 25
    2014-9-17 19:36
    2105 次阅读|
    0 个评论
    首先应该明确锁存器和触发器也是由与非门之类的东西构成。尤其是锁存器,虽说数字电路定义含有锁存器或触发器的电路叫时序电路,但锁存器有很多组合电路的特性。 组合电路就是一个真值表,一个函数,一组输入对应一组输出,当前什么输入就根据函数得到什么输出,实时跟踪变化,这样也就容易有冒险、竞争之类的问题产生毛刺。 锁存器:电平敏感 always @ (enable)   if (enable)  q = d; 那就是说,在enable有效的时间内,q完全跟踪d的值,比如在这个时间内d变化了,q跟着变化,当enable失效的时候,q存储d最后的值。 触发器:我们把输出只在时钟某个时刻变化的玩意儿叫触发器。边沿敏感 always @ (posedge enable)   if (enable) q = d; 这个便是一个d触发器。只在enable(一般大家都叫它clock)的上升沿q采样d,而且在每个时钟的上升沿都会采样。 在fpga中一般避免用latch,因为在FPGA中触发器资源丰富,不用白不用,latch由于是电平触发的,相对触发器来说容 易产生毛刺,电路不稳定. latch的优点是完成同一个功能所需要的门较触发器要少,所以在asic中用的较多   那最后再说寄存器,寄存器这个玩意儿是一个概念层次的东西,1个寄存器就是能存1bit数据的东西。既可以用触发器实现也可以用锁存器实现。以触发器为例,由于触发器每个时钟上升沿都会采样,所以触发器会有一个反馈逻辑,当load有效的时候才会采样d,否则保持不变。 always @ (posedge clk or negedge rst_n) if (!rst_n) q = 0; else if (load) q = d; 这便就是一个寄存器了。over,不对之处希望大家指正。
  • 热度 19
    2014-7-1 10:14
    2352 次阅读|
    1 个评论
    1.什么是触发器 能够存储1位二值信号的基本单元电路统称为 触发器 它有二个基本的特点: 第一,具有两个能自行保持的稳定状态,用来表示逻辑状态的0和1,或二进制数的0和1 第二,在触发信号的操作下,根据不同的输入信号可以置成1或0的状态 2.触发器的分类 触发器的分类可以按不同的类别进行归纳。如果按触发方式分类:可以分成电平触发,脉冲触发,边沿触发三种;如果按控制方式不同分类:SD触发器,JK触发器,T触发器,D触发器等几种类型;如果按存储数据的原理不同分类:可以分成静态触发器和动态触发器这二大类。本次总结只介绍静态触发器。 3.触发器的基础构成部分:SR锁存器 下面是使用或非门构成的锁存器的电路结构图和图形符号: 其中Rd是复位端或置0输入端,Sd是置位端或置1输入端。Q和Q'称为输出端,并且定义Q=1,Q'=0为锁存器的1 状态,Q=0,Q'=1为锁存器的0状态。下面是或非门构成的锁存器的特性表: 下图则是与非门构成的锁存器的特性表: 在这里需要注意的是: 1.对于或非门构成的SR锁存器来讲,输入信号中电平1是有效信号。对于与非门构成的SR锁存器来讲,输入信号0是有效信号。可以这样理解,对于或非门来讲,只要有一个输入电平为高电平1,则输出就肯定为低电平0;对于与非门来讲,只要有一个输入电平是低电平0,则输出肯定为高电平1。 2.对于或非门构成的SR锁存器,输入信号不要出现Sd=1,Rd=1的情况,而对于与非门构成的锁存器,输入信号 则不要出现 Sd=0,Rd=0的情况。这是因为当Sd,Rd的1状态或者0状态同时消失以后,Q的状态不能确定。   下面是与非门构成的SR锁存器的电路结构与图形符号 从与非门,或非门的图形符号可以得知:当图形中,Sd,Rd旁边有小圆圈时,表示是输入信号低电平有效,则Sd,Rd旁边没有小圆圈时,表示是输入信号高电平有效。   4.电平触发的触发器 为何要引入电平触发的触发器? 因为先前的SR锁存器中,当输入信号一到达,锁存器就会马上进行转化。这个过程是不能控制的,往往人们需要一个触发信号来控制锁存器的保存,只有当触发信号到达时,才可以进行电平的保存,当触发信号没有到达时,尽管输入信号已经到达,但是锁存器还是不能进行保存其输入的二进制值 。所以就产生了如下的电平触发SR触发器,其电路结构和图形符号如下: 下面的图是电平触发SR触发器的特性表: 从特性表中可以总结出:当CLK=0时,Q*保持不变,当CLK=1时,Sd=1,Rd=0时,Q*=1; Sd=0,Rd=1时,Q*=0; Sd=0,Rd=0时,Q*=Q保持不变; Sd=1,Rd=1不允许出现。   下面是电平触发D触发器的电路结构与图形符号 这是它的特性表: 从表中可以得出D触发器的特性方程为:Q*=D   电平触发方式的动作特点: a.只有当CLK变为有效电平,触发器才能接受输入信号,并按照输入信号将触发器的输出置成相应的状态 b.在CLK=1的全部时间内,S和R状态的变化都可能引起输出状态的改变。在CLK回到0以后,触发器保存的是CLK回到0以前瞬间的状态。   5.脉冲触发的触发器 为什么要引入脉冲触发的触发器? 为了提高触发器工作的可靠性,希望在每个CLK周期里面输出端的状态只能改变一次,为此目的,在电平触发的触发器的基础上又设计出了脉冲触发的触发器。 脉冲触发的触发器的典型电路结构和图形符号如下图所示: 它是由二个同样的电平脉冲触发SR触发器所组成,其中G1~G4组成的触发器称为从触发器,由G5~G8组成的触发器称为主触发器。因此也经常将这个电路称为:主从SR触发器 当CLK=1时,门G7和G8被打开,门G3和G4被封锁,主触发器根据S和R的状态翻转,而从触发器保持原来的状态不弯 当CLK=0时,门G7和G8被封锁,此后无论S,R的状态如何改变,主触发器将不会改变,而从触发器按照与主触发器相同的状态进行翻转。因此在一个CLK的变化周期里触发器输出端的状态只能改变一次。   特别需要注意的是:主从SR触发器输出端电平状态的改变发生的时刻。我们可以通过主从触发器的逻辑符号可以得知: 当CLK以低电平为有效信号时,在CLK输入端加有小圆圈,输出端状态的变化发生在CLK脉冲的上升沿 当CLK以高电平为有效信号 时,在CLK输入端没有小圆圈,输出端状态的状态发生在CLK脉冲的下降沿   主从JK触发器  
  • 热度 15
    2013-10-22 09:56
    1403 次阅读|
    0 个评论
         好吧!看一下锁存器这个概念吧!对于锁存器这个概念确实困扰我一段时间,知道自己的数电知识不是很好,而且对于FPGA还是“半路出家”,本来就不容易的FPGA对于我来说学起来更加费劲了,别人看一遍就能够懂的知识,我看好几篇才会懂。但是这样才会具有挑战性对吧?好了不说的有点多了,一般我遇到自己从来没有遇到的知识或者问题我都会习惯性的去百度,如果有官方网站的话我会去官网上去寻找我需要的答案,如果找不到的话,我才会去找课本或者问别人啊,我也不知道我这个解决问题的思路对不对。对于锁存器这个概念百度上是这样解释的锁存器是一种对脉冲电平敏感的存储单元电路,它们可以在特定输入脉冲电平作用下改变状态。锁存,就是把信号暂存以维持某种电平状态。锁存器的最主要作用是缓存,其次完成高速的控制其与慢速的外设的不同步问题,再其次是解决驱动的问题,最后是解决一个 I/O 口既能输出也能输入的问题。只有在有锁存信号时输入的状态被保存到输出,直到下一个锁存信号,通常只有0和1两个值。     在实际的verilog hdl的代码书写过程中,很容易产生不期望的锁存器,使自己设计的代码功能失效,我感觉锁存器是一种基本单元,完全是由你所写的代码决定,所以产生不期望锁存器是我们所书写的代码决定的。 说一下锁存器与寄存器之间的区别吧,曾经在一本书中看到有很多的篇幅讲锁存器(那是我见过对锁存器说的最详细的一本书,感谢作者)锁存器是电平触发的存储器,触发器是边沿触发的存储器。锁存器对毛刺敏感,上电之后处于不确定的状态;是静态时序分析变得很复杂;需要很多的资源,因为PLD芯片里面的基本单元是查找表很触发器。所以要避免产生不期望的锁存器。     锁存器产生的原因always组合逻辑描述语句中,可能产生锁存器有两种,一种是在if语句中,另一种是在case语句中。由于if语句中缺乏else分支或者case语句的不完整,但有时候也会产生我们需要的信号,而且这个时候虽然会出现警告信息。这里截取一本书上的例子: 通过verilog hdl 语言实现序列最大值的搜寻程序,并保持检测到的最大值。 module two_max (a,reset_n,abmax); input a; input reset_n; output abmax;   reg abmax_tmp; always @ (a or reset_n) begin if (reset_n)       abmax_tmp=8’h00; else    if (aabmax_tmp)       abmax_tmp=a; end assign abmax=abmax_tmp; endmodule      这是综合后产生的警告但是锁存器是设计所需要的,因此代码没有问题。    总结一下:锁存器是一种基本的电路单元,会影响到电路的时序性能,应该尽量避免使用,但是出现一些不期望的锁存器,那应该是设计人员设计代码所出现的问题
  • 热度 17
    2013-6-6 16:35
    1700 次阅读|
    0 个评论
    数字逻辑设计中的锁存器和触发器 1、锁存器和触发器的定义和比较 锁存器(latch)---对脉冲电平敏感,在时钟脉冲的电平作用下改变状态, 当 Gate输入为高电平时,输入D透明传输到输出Q;当Gate从高变低或者保持低电平时,输出Q被锁存保持不变。锁存器是电平触发的存储器。 应用场合:数据有效迟后于时钟信号有效。这意味着时钟信号先到,数据信号后到。在某些运算器电路中有时采用锁存器作为数据暂存器。 触发器(flip-flop)---对脉冲边沿敏感,其状态只在时钟脉冲的上升沿或下降沿的瞬间改变 。当时钟信号 C上升沿时刻(或者下降沿时刻),输入D被赋值到输出Q,其他情况保持锁存。触发器 是边沿触发的存储器。 应用场合:时钟有效迟后于数据有效。这意味着数据信号先建立,时钟信号后建立。在CP上升沿时刻打入到寄存器。 比较: 1)、latch和flip-flop都是时序逻辑,所以输出不但同当前的输入相关还同上一时间的输出相关; 2)、latch由电平触发,异步控制。在使能信号有效时latch相当于通路, 在使能信号无效时latch保持输出状态。触发器由时钟沿触发,同步控制。所以说,触发器是一个同步版锁存器; 3)、FPGA主要有触发器和查找表组成,没有标准的latch单元,一个latch需要更多资源才能实现; 4)、一般的设计规则是:在绝大多数设计中避免产生latch。latch最大的危害在于不能过滤毛刺。这对于下一级电路是极其危险的。所以,只要能用D触发器的地方,就不用latch; 5)、if语句 或者 case 语句 不全很容易产生latch。在RTL描述中,如果一个信号在一个条件的分支中被赋值,而不是在所有分支中被赋值,则该信号的前一个值就要被保留 。 同步情况下(敏感列表时时钟边沿)用触发器实现,保留到下一个时钟边沿为止,异步情况下(即敏感列表中是电平而非时钟的边沿)需要由锁存器来实现,保留到下一个已列出的分支情况的电平有效为止。 2、锁存器的有与无 推导出锁存器的一般规则是: 1)、 如果在 电平触发的 always语句所有可能的执行过程 (如 if/case 语句 ) 中 变量没有全部 被赋值,就 会产生 锁存器; 2)、 如果在边沿触发的 always语句所有的可执行过程中变量没有被全部复制,会产生触发器; 3)、 如果 在 always语句中 变量在if/case的所有分支中都被赋值则综合成组合逻辑;  always @ (Toggle)         case (Toggle)            //synthesis full_case                   2'b01: NextToggle = 2'b10;           2'b10: NextToggle = 2'b01;         e ndcase   always @ (Toggle)         case (Toggle)                               2'b01: NextToggle = 2'b10;           2'b10: NextToggle = 2'b01;        endcase 第一种写法用编译命令synthesis full_case把case语句补全,效果和default语句或将case列举出所有情况类似。 此时没有锁存器,只用两个2输入的LUT完成2输入2输出的逻辑功能 ,纯粹的组合逻辑 。 第二种写法没有将case的所有情况列举出,就产生了锁存器LD。 查看Xilinx的库手册,LD是透明锁存器,当G使能的时候,Q输出D的值;当G不使能的时候,Q保持上一状态的值。 以下改用的时钟的上调沿触发,生成了两个D触发器,当时钟上调沿来临时用输入端D更新输出端Q的数据。 always @ (posedge clk)         case (Toggle)                        2'b01: NextToggle = 2'b10;           2'b10: NextToggle = 2'b01;        endcase   这说明边沿触发的 always块中,即使if...else或者case没写全也不会出现锁存器。   参考链接: http://www.eefocus.com/jinxi/blog/07-08/3425_b8946.html http://blog.csdn.net/surgeddd/article/details/4683657  
相关资源