FPGA设计中锁存器产生、避免与消除
FPGA设计中锁存器产生、避免与消除
- 一、锁存器的产生
- 1.1 组合逻辑中使用保持状态
- 1.2 组合逻辑中的if-else语句或case语句未列出所有可能性
- 1.3 小结
- 二、锁存器的避免
- 三、锁存器的消除
- 3.1 情况一
一、锁存器的产生
锁存器的产生主要有以下两种情况:(1)组合逻辑中使用保持状态;(2)组合逻辑中的if-else语句或case语句未列出所有可能性;
1.1 组合逻辑中使用保持状态
assign data_out = valid ? data_in : data_out; //变量保持当前值
always @(*) beginif(valid)data_out = data_in;elsedata_out = data_out; //变量保持当前值
end
1.2 组合逻辑中的if-else语句或case语句未列出所有可能性
对于组合逻辑中,如果使用if-else语句,未补全else语句,则默认在其他条件下,数据均保持为原来的状态,那么也会产生锁存器。
//if-else语句缺少else
always @(*) beginif(valid)data_out = data_in;
end
而如果在组合逻辑中使用case语句,未列出case中条件所有的可能性,则相当于对于未列出的那些情况,数据均保持为原来的状态,也会产生锁存器。
//case语句未列出所有可能性
always @(*) begincase(sel)2'b00: data_out = 2'b00;2'b01: data_out = data_in;endcase
end
1.3 小结
那么,总而言之,言而总之。对于锁存器,其产生的原因可以总结为一点:想要通过组合逻辑保持数据不变。对于组合逻辑的实现,我们可以认为它是用很多门电路搭建而成的,那么,门电路与寄存器不同,其不具有保持当前状态的功能。也就是说,构成当前组合逻辑的电路中任何一个信号发生改变,都会导致输出结果发生改变。如果要通过组合逻辑实现保持数据的不变,那就只能产生锁存器了(可以参考《数字电子技术基础》第五版的SR触发器)。
二、锁存器的避免
我们知道了锁存器的产生原因,就可以对症下药,在编写Verilog代码时注意编码风格,即可避免锁存器的产生。
(1)在组合逻辑中使用if-else语句时补全else语句
always @(*) beginif(sel)data_out = data_in;elsedata_out = 2'b00;
end
(2)在组合逻辑中使用case语句时,设置默认状态default,并默认状态下的数据进行赋值
always @(*) begincase(sel)xxx: data_out <= 2'b01;xxx: data_out <= data_in;default: data_out = 2'b00;endcase
end
(3)在组合逻辑中,不可一个变量赋值给变量自身
//错误示例
always @(*) beginif(sel)data_out = data_in;elsedata_out = data_out; //变量赋值给变量自身
end//正确示例
always @(*) beginif(sel)data_out = data_in;elsedata_out = 2'b00; //需要赋值一个准确的数值或者其他变量
end
三、锁存器的消除
在FPGA设计过程中,有可能出现一些情况,必须使用组合逻辑,保证其实时性,且需要保持数据不变,保证其他运算的正确性。那么又该如何处理?
3.1 情况一
假如我们要实现如下面时序图所示功能,输出data_out在有效信号valid的上升沿处锁存输入data_in的值,那么要如何实现?
最开始考虑的是采用时序逻辑进行实现,代码如下。
always @(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)data_out <= 'd0;else if(valid)data_out <= data_in;elsedata_out <= data_out;
end
那么,采用时序逻辑实现,会导致延迟一怕,无法在有效信号valid的上升沿锁存数据,如下图所示。
于是考虑使用组合逻辑进行实现,代码如下。
assign data_out = valid ? data_in : data_out;
但是组合逻辑要实现保持状态,必然会产生锁存器。综合后会再Messages界面会警告出现锁存器,同时在Schematic中也可以看到出现了锁存器,如下图所示。而在我们的设计中,我们是不希望出现锁存器的,因为其不利于时序分析。
那么,也可以采用组合逻辑+时序逻辑的方式实现,通过多使用一部分寄存器资源,来实现在valid上升沿处进行数据采样,且不产生锁存器,代码如下。重新综合后,可见锁存器消失,同时可以对齐进行仿真,时序符合前面的要求。
reg [3:0] r_data_in;always @(posedge sys_clk or negedge sys_rst_n)if(!sys_rst_n)r_data_in <= 'd0;elser_data_in <= data_in;assign data_out = valid ? data_in ? r_data_in;
相关文章:

FPGA设计中锁存器产生、避免与消除
FPGA设计中锁存器产生、避免与消除 一、锁存器的产生1.1 组合逻辑中使用保持状态1.2 组合逻辑中的if-else语句或case语句未列出所有可能性1.3 小结 二、锁存器的避免三、锁存器的消除3.1 情况一 一、锁存器的产生 锁存器的产生主要有以下两种情况:(1&…...

一份标准的软件测试方案模板
第一章 概述 软件的错误是不可避免的,所以必须经过严格的测试。通过对本软件的测试,尽可能的发现软件中的错误,借以减少系统内部各模块的逻辑,功能上的缺陷和错误,保证每个单元能正确地实现其预期的功能。检测和排…...

【C++】-对于自定义类型的输入输出运算符重载
💖作者:小树苗渴望变成参天大树 ❤️🩹作者宣言:认真写好每一篇博客 💨作者gitee:gitee 💞作者专栏:C语言,数据结构初阶,Linux,C 文章目录 前言一、案例引入二、<<的重载三、>>的…...
(详解)js中什么是宏任务、微任务?宏任务、微任务有哪些?又是怎么执行的?
目录 参考资料 必看强烈建议十分钟看完视频 ,即可学会 必看参考详解宏任务微任务 笔记 宏任务与微任务 定时器的任务编排 promise的微任务处理逻辑 DOM渲染任务 任务队列共享内存 进度条的实现 任务拆分成多个任务 promise复杂任务分割 img算同步还是异步…...
Okta 即代码:云原生时代的身份管理
我们为什么应该将 Okta 配置作为代码进行管理? 对于需要跨多个应用程序和环境管理对其数字资源的访问的组织来说,Okta 可能是最受欢迎的选择,因为它提供了一系列使其在身份验证和授权方面很受欢迎的功能,例如: 单点登…...

数据结构(六)—— 二叉树(7)构建二叉树
文章目录 如何使用递归构建二叉树1、创建一颗全新树(题1-5)2、在原有的树上新增东西(题6) 1 106 从 后序 与 中序 遍历序列构造二叉树2 105 从 前序 与 中序 遍历序列构造二叉树3 108 将有序数组转换为二叉搜索树(输入…...

安装适用于Linux的Windows11子系统(WSL2)
1. 主板BIOS开启虚拟化 开启虚拟化需要在BIOS中进行设置,进入主板BIOS→找到虚拟化设置→开启。 2. 检验是否开启虚拟化 打开Windows命令行,并运行 systeminfo固件中已启用虚拟化为是,代表主板BIOS已经开启虚拟化。 3. 启用Windows功能…...

使用Spring的五大类注解读取和存储Bean
目录 1.存储Bean对象的注解 1.1 五大类注解 1.2 方法注解 1.3添加注解的依赖 2.注解的使用 2.1 controller注解 2. 2Service注解 2.3.Resopsitory注解 2.4Component注解 2.5Configuration注解 2.6 注解之间的关系 3.方法注解 3.1 方法注解要配合类注解来使用。 3.2…...
Vue3通透教程【十一】初探TypeScript
文章目录 🌟 写在前面🌟 TypeScript是什么?🌟TypeScript 增加了什么?🌟TypeScript 初体验🌟 写在最后🌟 写在前面 专栏介绍: 凉哥作为 Vue 的忠实 粉丝输出过大量的 Vue 文章,应粉丝要求开始更新 Vue3 的相关技术文章,Vue 框架目前的地位大家应该都晓得,所谓…...

Linux环境安装iperf3(网络性能测试工具)
[rootlocalhost ]# yum search iperf 已加载插件:fastestmirror Loading mirror speeds from cached hostfile* base: mirrors.tuna.tsinghua.edu.cn* extras: mirrors.huaweicloud.com* updates: mirrors.tuna.tsinghua.edu.cnN/S matched: iperf iperf3-devel.i6…...
回顾第一章
回顾 Shell脚本中的$虚函数虚函数和纯虚函数 git merge/rebasegit merge特点git rebase特点 Linux内核调试——coredump获取core dump 深度测试和模板测试2D游戏的制作思路C11特性 Shell脚本中的$ $0: 脚本自身的名称; $1: 传入脚本的第一个参数; $2…...

Jupyter Notebook入门教程
Jupyter Notebook(又称Python Notebook)是一个交互式的笔记本,支持运行超过40种编程语言。本文中我们将介绍Jupyter Notebook的主要特点,了解为什么它能成为人们创造优美的可交互式文档和教育资源的一个强大工具。 首先ÿ…...

独立按键识别
项目文件 文件 关于项目的内容知识点可以见专栏单片机原理及应用 的第四章 IO口编写 参考图电路编写程序,要求实现如下功能: 开始时LED均为熄灭状态,随后根据按键动作点亮相应LED(在按键释放后能继续保持该亮灯状态,直至新的按键压下时为止…...
【论文阅读】AlphaFold2阅读笔记
摘要 给一串氨基酸的序列,去预测他的结构是什么样的 蛋白质的折叠问题 alphaFold精度不够 这里可以达到原子精度的预测 CASP14 精度 这个是什么问题是不是解决了问题 模型的结果并不重要 导论 摘要故事的详细版本 在写论文的时候,可以这样写&a…...

机器学习基础知识之数据归一化
文章目录 归一化的原因1、最大最小归一化2、Z-score标准化3、不同方法的应用 归一化的原因 在进行机器学习训练时,通常一个数据集中包含多个不同的特征,例如在土壤重金属数据集中,每一个样本代表一个采样点,其包含的特征有经度、…...
QCC51XX---pydbg_cmd集合
目录 common pydbg_cmd headset pydbg_cmd earbud pydbg_cmd common pydbg_cmd log apps1.log_level() apps1.fw.gbl.debug_log_level__global 查看log等级apps1.fw.gbl.debug_log_level__global.value = 5 设置log等级 apps1.log()...
camx 马达的MSM_ACTUATOR_WRITE_DAC 操作
camx 马达的MSM_ACTUATOR_WRITE_DAC操作 为什么要分析 MSM_ACTUATOR_WRITE_DACmm-camera MSM_ACTUATOR_WRITE_DACcamx MSM_ACTUATOR_WRITE_DAC总结 为什么要分析 MSM_ACTUATOR_WRITE_DAC 目前的camx源码 省略了hw_mask 的处理。 一般来说 hw_mask 是0 ,但是对于非0…...

【无人机】无人机平台的非移动 GPS 干扰器进行位置估计的多种传感器融合算法的性能分析(Matlab代码实现)
💥 💥 💞 💞 欢迎来到本博客 ❤️ ❤️ 💥 💥 🏆 博主优势: 🌞 🌞 🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 …...

一篇文章搞定《RecyclerView缓存复用机制》
------《RecyclerView缓存复用机制》 前言零、为什么要缓存一、RecyclerView如何构建我们的列表视图二、缓存过程三、缓存结构1、mChangedScrap/mAttachedScrap2、mCachedViews3、mViewCacheExtension4、mRecyclerPool 四、总结 前言 本篇文章,暂时不加入预加载进行…...
Elasticsearch概述
1.Elasticsearch干啥的? Elasticsearch 是一个开源的分布式搜索和分析引擎,用于实时搜索、分析和存储大规模数据。它可以帮助用户在海量数据中快速进行全文搜索、聚合分析、地理空间分析等操作,并支持水平扩展以应对高并发访问需求。 Elasti…...

铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...
DockerHub与私有镜像仓库在容器化中的应用与管理
哈喽,大家好,我是左手python! Docker Hub的应用与管理 Docker Hub的基本概念与使用方法 Docker Hub是Docker官方提供的一个公共镜像仓库,用户可以在其中找到各种操作系统、软件和应用的镜像。开发者可以通过Docker Hub轻松获取所…...
STM32+rt-thread判断是否联网
一、根据NETDEV_FLAG_INTERNET_UP位判断 static bool is_conncected(void) {struct netdev *dev RT_NULL;dev netdev_get_first_by_flags(NETDEV_FLAG_INTERNET_UP);if (dev RT_NULL){printf("wait netdev internet up...");return false;}else{printf("loc…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...

QT: `long long` 类型转换为 `QString` 2025.6.5
在 Qt 中,将 long long 类型转换为 QString 可以通过以下两种常用方法实现: 方法 1:使用 QString::number() 直接调用 QString 的静态方法 number(),将数值转换为字符串: long long value 1234567890123456789LL; …...
[Java恶补day16] 238.除自身以外数组的乘积
给你一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O(n) 时间复杂度…...

中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...

让回归模型不再被异常值“带跑偏“,MSE和Cauchy损失函数在噪声数据环境下的实战对比
在机器学习的回归分析中,损失函数的选择对模型性能具有决定性影响。均方误差(MSE)作为经典的损失函数,在处理干净数据时表现优异,但在面对包含异常值的噪声数据时,其对大误差的二次惩罚机制往往导致模型参数…...

springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...