FPGA基础知识极简教程(5)什么是锁存器以及如何在FPGA开发中避免生成锁存器?
博文目录
- 写在前面
- 正文
- 什么是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开发中避免生成锁存器?相关推荐
- FPGA基础知识极简教程(10)二进制到BCD转换算法
文章目录 写在前面 正文 快速认识 实现方式一 实现方式二 写在最后 写在前面 FPGA基础知识极简教程(9)讲到了七段数码管的显示Verilog设计,我们都知道,要在数码管上显示的数字,使用BCD编 ...
- FPGA基础知识极简教程(7)详解亚稳态与跨时钟域传输
博文目录 写在前面 正文 FPGA或ASIC中的传播延迟 建立和保持时间是什么? 建立和保持时间与传播延迟和时钟频率有何关系? 如果违反建立和保持时间会发生什么? FPGA中的亚稳定是什么? 亚稳态何 ...
- FPGA基础知识极简教程(4)从FIFO设计讲起之异步FIFO篇
博文目录 写在前面 正文 同步FIFO回顾 $clog2()系统函数使用 综合属性控制资源使用 异步FIFO设计 FIFO用途回顾 异步FIFO原理回顾 异步FIFO设计 异步FIFO仿真 参考资料 ...
- FPGA基础知识极简教程(1)从布尔代数到触发器
博文目录 写在前面 正文 初学者数字设计 什么是FPGA? 什么是ASIC? 数字设计师如何使用布尔代数? 使用查找表(LUT)在FPGA内部执行布尔代数 触发器如何在FPGA中工作? 参考资料 交个 ...
- FPGA基础知识极简教程(9)七段数码管显示的Verilog简单设计
博文目录 写在前面 正文 七段数码管原理 七段数码管译码表 单个七段数码管显示verilog设计 多个数码管动态扫描显示 参考资料 交个朋友 写在前面 作为FPGA的基础知识教程怎么能少得了这个简单的 ...
- FPGA基础知识极简教程(6)UART通信与移位寄存器的应用
博文目录 写在前面 正文 关于UART的介绍 UART通信过程 UART.RS232以及TTL之间的关系 UART的使用场合 有关UART的总结 调试UART的技巧 UART的Verilog实现 波特 ...
- FPGA基础知识极简教程(3)从FIFO设计讲起之同步FIFO篇
博文目录 写在前面 正文 FPGA/ASIC中的FIFO 同步FIFO的设计 参考资料 交个朋友 写在前面 个人博客首页 注:学习交流使用! 正文 FPGA/ASIC中的FIFO FIFO缓冲区如何用 ...
- FPGA基础知识极简教程(8)详解三态缓冲器
博文目录 写在前面 正文 全双工与半双工 FPGA和ASIC中的三态缓冲器 如何在VHDL和Verilog中推断出三态缓冲区 参考资料 交个朋友 写在前面 下面用举例子的方式引出三态门,内容过长,大家 ...
- FPGA基础知识极简教程(2)抛却软件思维去设计硬件电路
博文目录 写在前面 正文 可综合以及不可综合的代码 每个软件程序员需要了解的有关硬件设计的内容 参考资料 交个朋友 写在前面 相关博文 个人博客首页 注:学习交流使用! 学过一门或多门软件语言的数字设 ...
最新文章
- VC下提前注入进程的一些方法1——远线程不带参数
- redis安装过程中遇到的问题
- Android App开发——添加APP启动界面
- 内存中的调用别的软件程序加密解密函数_公司加密软件哪个最好用?
- 零位扩展和符号位扩展
- 一道抛物线自编题的思考
- 嵌入式论文3000字_SCI英文论文一般多少字
- java restful_Java EE中的RESTful计时器
- Asp.Net Session 丢失的奇怪问题,求救!
- Spring事务配置的五种方式和spring里面事务的传播属性和事务隔离级别、不可重复读与幻读的区别
- springboot+事务,多张表的操作事务回滚
- linux安装php和nginx,Linux下安装配置Nginx以及安装PHP
- 客观真实的数据为何揭不开真相?
- python运用ico图标,处理Django中的favicon.ico图标实例方法
- 手机做web服务器 无限流量,无限流量卡和手机随身无线wifi,你选择哪一个?
- python键盘上下左右控制_【322】python控制键盘鼠标:pynput
- 自动白平衡也即:color constancy (色彩恒常)研究总结
- 大数据hive篇_group seting解决业务问题
- 端口号被占用的解决方法
- mybatis-day02-CRUD、动态代理开发、核心xml详解、输入输出参数
热门文章
- 怎样使用dhcp自动分配IP地址
- userinits.exe, wupcltr.exe的分析及解决办法
- ibm笔记本电脑电池_福建省厦门市集美区电池定制供应多少钱
- Java根据模板创建excel文件
- html 表格过滤功能,简单的带排序和过滤功能的jQuery表格插件
- android 返回字符串,android – 如何从异步回调使用Retrofit返回String或JSONObject?
- matlab选择激发波长,【求助】怎么确定一个物质的激发波长和发射波长?
- 高压放电与防静电塑料包装
- 智能车竞赛中的车模足底按摩
- 朋友圈里的一张组合逻辑图