博文目录

  • 写在前面
  • 正文
    • 什么是D锁存器?
    • 锁存器是如何生成的?
    • 如何避免生成锁存器?
  • 参考资料
  • 交个朋友

写在前面

  • 个人微信公众号: FPGA LAB
  • 个人博客首页
  • 注:学习交流使用!

本文我们将讨论两个问题:

  • 什么是锁存器?
  • 如何避免生成锁存器?

正文

在FPGA设计中永远不要使用锁存器!但好像没人在FPGA设计中故意设计锁存器,那为什么要讨论锁存器呢?
话虽如此,虽然你没有有意设计锁存器,但你能保证你的代码中没有锁存器了吗?
综合工具(将Verilog或VHDL代码转换为低级FPGA组件的工具)生成的常用锁存器是 门控D型锁存器。但是,还有其他类型的锁存器:SR锁存器,D锁存器,JK锁存器和Earle锁存器。这些类型的锁存器不在本文讨论范围内,如需了解,可以自行查询资料。

什么是D锁存器?

门控D锁存器有两个输入和一个输出。框图如下所示。输入D是您的数据输入。输入E是你的输入输入。仅当Enable为1时,输出Q才会获得D上的值。当Enable为0时,无论输入D在做什么,输出都不会改变,即保持。它保持其先前的值,因此为什么将其称为锁存器! 当使能为低电平时,输出被锁存。


现在,之所以建议不要使用锁存器,因为它们非常危险。 这有两个主要原因:

  • 通常,锁存器是FPGA工程师无意间生成的。 编写的HDL代码很可能不是设计人员真正想要的。
  • FPGA工具很难正确创建它们。 通常,它们会增加大量的布线延迟,并可能导致您的设计无法满足时序要求。(耗费资源)

让我们继续讨论锁存器,并讨论锁存器是如何生成的?并如何避免生成锁存器呢?

锁存器是如何生成的?

想要避免,就要了解锁存器生成的原理。只有了解它,才能对付它,也就是避免它!

在Verilog的组合always块,或者VHDL的组合process以及conditional assignment中,未给所有可能的输入分配输出,就是产生锁存器!这将创建综合工具所谓的不完全分配。
看如下VHDL代码:


library ieee;
use ieee.std_logic_1164.all;entity bad_latch isport (i_data   : in  std_logic;i_enable : in  std_logic;o_latch  : out std_logic);
end bad_latch;architecture rtl of bad_latch is
beginprocess (i_data, i_enable)beginif i_enable = '1' theno_latch <= i_data;end if;end process;end architecture rtl;

或Verilog代码:

module bad_latch(input i_data,input i_enable,output reg o_latch
);always@(*) beginif(i_enable) begino_latch = i_data;end
endendmodule

您在上面的代码中看到问题了吗?当i_enable为0时会发生什么?这是未定义的!这些工具假定,当i_enable为0时,o_latch上的值不应更改。由于这是组合逻辑(不使用时钟),因此可以推断出一个锁存器。

如下图为其RTL图:

让我们再看一个创建锁存器的VHDL示例。

library ieee;
use ieee.std_logic_1164.all;entity bad_latch_2 isport (i_select : in  std_logic_vector(1 downto 0);o_latch  : out std_logic_vector(3 downto 0));
end bad_latch_2;architecture rtl of bad_latch_2 is
begin-- Incomplete Assignment:o_latch <= "0101" when i_select = "00" else"0111" when i_select = "01" else"1111" when i_select = "10";-- Fixed!-- o_latch <= "0101" when i_select = "00" else--            "0111" when i_select = "01" else --            "1111" when i_select = "10" else --            (others => '0');end architecture rtl;

或Verilog表达为:

module bad_latch2(input [1:0] i_select,output reg [3:0] o_latch
);always@(*) begincase(i_select)2'b00: begino_latch = 4'b0101;end2'b01: begino_latch = 4'b0111;end2'b10: begino_latch = 4'b1111;endendcase
endendmodule

我们忘记指定i_select的所有可能的输入组合。当i_select =“ 11”时,o_latch会发生什么?这会导致分配不完整,因此会产生锁存器。
如下图:

锁存器几乎肯定不是数字设计师打算用此代码创建的。要修复上面的代码,数字设计师可以指定当i_select =“ 11”时发生的情况,或者可以在不附加任何条件的情况下使用else子句。我推荐后者,因为它更灵活。如果i_select的宽度从两位变为三位,您的代码仍不会创建锁存器。让我们看一下Verilog中的另一个示例:

module no_latch2(input [1:0] i_select,output reg [3:0] o_latch
);always@(*) begincase(i_select)2'b00: begino_latch = 4'b0101;end2'b01: begino_latch = 4'b0111;end2'b10: begino_latch = 4'b1111;enddefault: begino_latch = 4'b0000;endendcase
endendmodule

此时就不会生成锁存器!
如下图:

如何避免生成锁存器?

经过上面的讨论,我们知道了组合逻辑中如果未给所有可能的输入分配输出,就是产生锁存器!
需要注意的是一定是组合逻辑才会产生锁存器,时序逻辑永远不会!
既然我们知道了产生锁存器的原因,我们自然知道如何规范代码,为所有可能的输入分配输出,适当地在case中使用default以及在if中使用else并分配输出值,就可以避免这种情况。


参考资料

  • 参考资料1
  • 参考资料2
  • 参考资料3

交个朋友

  • 个人微信公众号:FPGA LAB

  • 知乎:李锐博恩

  • FPGA/IC技术交流2020

FPGA基础知识极简教程(5)什么是锁存器以及如何在FPGA开发中避免生成锁存器?相关推荐

  1. FPGA基础知识极简教程(10)二进制到BCD转换算法

    文章目录 写在前面 正文 快速认识 实现方式一 实现方式二 写在最后 写在前面 FPGA基础知识极简教程(9)讲到了七段数码管的显示Verilog设计,我们都知道,要在数码管上显示的数字,使用BCD编 ...

  2. FPGA基础知识极简教程(7)详解亚稳态与跨时钟域传输

    博文目录 写在前面 正文 FPGA或ASIC中的传播延迟 建立和保持时间是什么? 建立和保持时间与传播延迟和时钟频率有何关系? 如果违反建立和保持时间会发生什么? FPGA中的亚稳定是什么? 亚稳态何 ...

  3. FPGA基础知识极简教程(4)从FIFO设计讲起之异步FIFO篇

    博文目录 写在前面 正文 同步FIFO回顾 $clog2()系统函数使用 综合属性控制资源使用 异步FIFO设计 FIFO用途回顾 异步FIFO原理回顾 异步FIFO设计 异步FIFO仿真 参考资料 ...

  4. FPGA基础知识极简教程(1)从布尔代数到触发器

    博文目录 写在前面 正文 初学者数字设计 什么是FPGA? 什么是ASIC? 数字设计师如何使用布尔代数? 使用查找表(LUT)在FPGA内部执行布尔代数 触发器如何在FPGA中工作? 参考资料 交个 ...

  5. FPGA基础知识极简教程(9)七段数码管显示的Verilog简单设计

    博文目录 写在前面 正文 七段数码管原理 七段数码管译码表 单个七段数码管显示verilog设计 多个数码管动态扫描显示 参考资料 交个朋友 写在前面 作为FPGA的基础知识教程怎么能少得了这个简单的 ...

  6. FPGA基础知识极简教程(6)UART通信与移位寄存器的应用

    博文目录 写在前面 正文 关于UART的介绍 UART通信过程 UART.RS232以及TTL之间的关系 UART的使用场合 有关UART的总结 调试UART的技巧 UART的Verilog实现 波特 ...

  7. FPGA基础知识极简教程(3)从FIFO设计讲起之同步FIFO篇

    博文目录 写在前面 正文 FPGA/ASIC中的FIFO 同步FIFO的设计 参考资料 交个朋友 写在前面 个人博客首页 注:学习交流使用! 正文 FPGA/ASIC中的FIFO FIFO缓冲区如何用 ...

  8. FPGA基础知识极简教程(8)详解三态缓冲器

    博文目录 写在前面 正文 全双工与半双工 FPGA和ASIC中的三态缓冲器 如何在VHDL和Verilog中推断出三态缓冲区 参考资料 交个朋友 写在前面 下面用举例子的方式引出三态门,内容过长,大家 ...

  9. FPGA基础知识极简教程(2)抛却软件思维去设计硬件电路

    博文目录 写在前面 正文 可综合以及不可综合的代码 每个软件程序员需要了解的有关硬件设计的内容 参考资料 交个朋友 写在前面 相关博文 个人博客首页 注:学习交流使用! 学过一门或多门软件语言的数字设 ...

最新文章

  1. VC下提前注入进程的一些方法1——远线程不带参数
  2. redis安装过程中遇到的问题
  3. Android App开发——添加APP启动界面
  4. 内存中的调用别的软件程序加密解密函数_公司加密软件哪个最好用?
  5. 零位扩展和符号位扩展
  6. 一道抛物线自编题的思考
  7. 嵌入式论文3000字_SCI英文论文一般多少字
  8. java restful_Java EE中的RESTful计时器
  9. Asp.Net Session 丢失的奇怪问题,求救!
  10. Spring事务配置的五种方式和spring里面事务的传播属性和事务隔离级别、不可重复读与幻读的区别
  11. springboot+事务,多张表的操作事务回滚
  12. linux安装php和nginx,Linux下安装配置Nginx以及安装PHP
  13. 客观真实的数据为何揭不开真相?
  14. python运用ico图标,处理Django中的favicon.ico图标实例方法
  15. 手机做web服务器 无限流量,无限流量卡和手机随身无线wifi,你选择哪一个?
  16. python键盘上下左右控制_【322】python控制键盘鼠标:pynput
  17. 自动白平衡也即:color constancy (色彩恒常)研究总结
  18. 大数据hive篇_group seting解决业务问题
  19. 端口号被占用的解决方法
  20. mybatis-day02-CRUD、动态代理开发、核心xml详解、输入输出参数

热门文章

  1. 怎样使用dhcp自动分配IP地址
  2. userinits.exe, wupcltr.exe的分析及解决办法
  3. ibm笔记本电脑电池_福建省厦门市集美区电池定制供应多少钱
  4. Java根据模板创建excel文件
  5. html 表格过滤功能,简单的带排序和过滤功能的jQuery表格插件
  6. android 返回字符串,android – 如何从异步回调使用Retrofit返回String或JSONObject?
  7. matlab选择激发波长,【求助】怎么确定一个物质的激发波长和发射波长?
  8. 高压放电与防静电塑料包装
  9. 智能车竞赛中的车模足底按摩
  10. 朋友圈里的一张组合逻辑图