【必看】时序逻辑仿真成组合逻辑?你知道原因吗?
对于初学者,一般会遇到这种情况,明明写的时序逻辑,结果仿真结果却是组合逻辑,然后看遍设计代码,始终找不到原因,交流群、知乎这种问题随处可见。但不要怀疑软件问题,modelsim这些专用软件基本不会遇见软件自身问题,原因其实很简单,因为多数人只关注设计文件不会关注TestBentch的合理性,导致找不到问题原因,后文分析原因并给出避免这种问题的方法。
在仿真时经常会使用“#”和“@(posedge clk)”来实现延迟,“#”后面跟数字,表示延迟数字对应最小的时间单位,而“@(posedge clk)”则用来检测clk信号上升沿,如果CYCLE表示始终周期对应的时间长度,那么“#(CYCLE)”表示延迟一个时钟周期长度的时间。在时钟上升沿输出数据后,使用“@(posedge clk)”,会延迟到下个时钟上升沿,同样也可以表示延迟一个时钟周期,那有没有区别?
分析以下代码,输出dout就是两个输入dataa与datab相加,由于是时序逻辑,dout会延迟dataa或datab变化后的一个时钟周期。
module add( input clk ,//系统时钟; input rst_n ,//系统复位,低电平有效; input [3 : 0] data_a ,//加数dataa; input [3 : 0] data_b ,//加数datab; output reg [4 : 0] dout );always@(posedge clk or negedge rst_n)begin if(rst_n==1'b0)begin//初始值为0; dout <= 4'd0; end else begin dout <= data_a + data_b; end endendmodule
Testbench如下所示:
`timescale 1 ns/1 ns
module test(); parameter CYCLE = 10 ;//系统时钟周期,单位ns,默认10ns; parameter RST_TIME = 5 ;//系统复位持续时间; parameter STOP_TIME = 100 ;//仿真运行时间,复位完成后运行100个系统时钟后停止; reg clk ;//系统时钟,默认100MHz; reg rst_n ;//系统复位,默认低电平有效; reg [3 : 0] data_a; reg [3 : 0] data_b;wire [4 : 0] dout ; add u_add ( .clk ( clk ), .rst_n ( rst_n ), .data_a ( data_a ), .data_b ( data_b ), .dout ( dout ) ); //生成周期为CYCLE数值的系统时钟; initial begin clk = 1; forever #(CYCLE/2) clk=~clk; end//生成复位信号; initial begin rst_n = 1; #2; rst_n = 0;//开始时复位10个时钟; #(RST_TIME*CYCLE); rst_n = 1; end //生成输入信号din; initial begin data_a = 0;data_b=0;//输入数据初始化为0; #(10*CYCLE);//延迟10个时钟周期; repeat(STOP_TIME)begin//循环STOP_TIME次;#(CYCLE); data_a = {$random} % 16; data_b = {$random} % 16; end $stop;//停止仿真; endendmodule
使用modelsim仿真如下图所示,奇怪的是为什么时序逻辑仿真成组合逻辑了?
分析:加法器代码肯定是没有问题的,modelsim软件也是经过fpga设计以及IC设计人员多年使用,是最常用的仿真工具,也不可能出现这样的低级bug。如果你把代码下载到开发板上,使用在线逻辑分析仪抓取数据,能够得到正确的运行结果,但是仿真就是错误的。这是为什么?那就只剩下写的testbench文件了,来看下testbench与输出相关的信号,首先时钟和复位信号是没有问题的,那就只剩下dataa与datab的产生模块了,如下所示:
//生成输入信号din;
initial begin data_a = 0;data_b=0;//输入数据初始化为0; #(10*CYCLE);//延迟10个时钟周期; repeat(STOP_TIME)begin//循环STOP_TIME次;#(CYCLE); data_a = {$random} % 16; data_b = {$random} % 16; end $stop;//停止仿真;
end
开始仿真时两个输入信号都被赋值为0,经10个时钟延迟之后进入forever循环内,每次循环之前都会把数据延迟一个时钟周期,然后在对两个输入信号赋一个0~15的随机值。逻辑上其实没有问题,但是注意一个问题,每次给dataa和datab赋值时间与时钟clk上升沿是对齐的,导致D触发器的输入信号在时钟上升沿时发生变化,由此导致D触发器数据采集错误,最终导致D触发器输出信号dout提前更新数据。这里实际上与保持时间违例有点类似,D触发器的下一个输入数据来得过快,影响了上一个数据的采集。
解决方法很简单,因为是数据刚好在时钟上升沿时发生更新导致D触发器数据采集错误,那么把两个输入数据全部延迟一点不就行了,修改如下,将两个输入数据的所有变化均延迟1ns,与时钟上升沿错开。
//生成输入信号din;
initial begin #1; data_a = 0;data_b=0;//输入数据初始化为0; #(10*CYCLE);//延迟10个时钟周期; repeat(STOP_TIME)begin//循环STOP_TIME次; #(CYCLE); data_a = {$random} % 16; data_b = {$random} % 16; end $stop;//停止仿真;
end
修改后仿真结果如下:
从上面仿真结果就可以看到,dataa与datab的变化都延迟时钟上升沿1ns之后,就没有在影响仿真结果了。这也是为什么很多代码在对信号赋值之前会延迟1ns的原因,就是为了数据变化与时钟上升沿错开,避免发生上面这种由于testbench书写问题所引发的离奇结果。
使用“#”会引发上面问题,那如果过使用“@(posedge clk)”这种写法还会出现那样的仿真结果?
先给答案,不会出现类似问题,因为“@(posedge clk)”表示已经检测到时钟上升沿了,那么在这之后更新的数据自然与时钟上升沿就是错开的了。
同样的案例,只是把dataa和datab赋值的部分改成如下代码。
//生成输入信号din;
initial begin data_a = 0;data_b=0;//输入数据初始化为0; #(10*CYCLE);//延迟10个时钟周期; repeat(STOP_TIME) @(posedge clk)begin//循环STOP_TIME次; data_a = {$random} % 16; data_b = {$random} % 16; end $stop;//停止仿真;
end
上面代码表达结果与下面代码一致。
//生成输入信号din;
initial begin data_a = 0;data_b=0;//输入数据初始化为0; #(10*CYCLE);//延迟10个时钟周期; repeat(STOP_TIME)begin//循环STOP_TIME次; @(posedge clk); data_a = {$random} % 16; data_b = {$random} % 16; end $stop;//停止仿真;
end
仿真结果如下,没有出现任何问题,数据变化近似与时钟上升沿对齐,但是输出数据dout没有受到影响,这就是“@(posedge clk)”的效果。
“#”和“@(posedge clk)”虽然都可以写成延时几个时钟周期的形式,但是他们是有区别的,区别在与“#”延迟与时钟其实没有关系,就有可能和时钟上升沿重合,这是使用是需要注意的,建议在仿真开始时就对数据延迟1ns然后在赋值,与时钟信号变化错位。而“@(posedge clk)”本质是检测时钟上升沿,在时钟上升沿之后才会去执行后面的语句,所以数据变化与时钟上升沿变化是错位的,不会出现“#”那种问题。
上述从效果看肯定是使用“@(posedge clk)”,作为延迟更好,使用“#(CYCLE)”延迟一个时钟更号理解,但是要注意可能遇到的问题,一般使用模板时,赋值语句开头会带有“#1;”,或者在每次赋值前用“@(posedge clk)”作为延迟,如下我常用赋值模板。
//生成输入信号din;
initial begin #1;din = 0;//输入数据初始化为0; #(10*CYCLE);//延迟10个时钟周期; end
相关文章:

【必看】时序逻辑仿真成组合逻辑?你知道原因吗?
对于初学者,一般会遇到这种情况,明明写的时序逻辑,结果仿真结果却是组合逻辑,然后看遍设计代码,始终找不到原因,交流群、知乎这种问题随处可见。但不要怀疑软件问题,modelsim这些专用软件基本不…...

PyTorch翻译官网教程-LANGUAGE MODELING WITH NN.TRANSFORMER AND TORCHTEXT
官网链接 Language Modeling with nn.Transformer and torchtext — PyTorch Tutorials 2.0.1cu117 documentation 使用 NN.TRANSFORMER 和 TORCHTEXT进行语言建模 这是一个关于训练模型使用nn.Transformer来预测序列中的下一个单词的教程。 PyTorch 1.2版本包含了一个基于论…...

SpringBoot复习:(43)如何以war包的形式运行SpringBoot程序
一、.pom.xml配置packging为war <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven…...

Dubbo高手之路2,6种扩展机制详解
目录 一、Dubbo扩展机制的概述二、Dubbo的自适应扩展机制1. 什么是自适应扩展机制2. 自适应扩展机制的使用示例 三、Dubbo的SPI扩展机制1. 什么是SPI扩展机制2. SPI扩展机制的使用示例3. Dubbo的SPI扩展机制中自定义扩展点的实现示例 四、Dubbo的自定义扩展点机制1. 什么是自定…...

C语言快速回顾(二)
前言 在Android音视频开发中,网上知识点过于零碎,自学起来难度非常大,不过音视频大牛Jhuster提出了《Android 音视频从入门到提高 - 任务列表》,结合我自己的工作学习经历,我准备写一个音视频系列blog。C/C是音视频必…...

ADB连接安卓手机提示unauthorized
近期使用airtest进行自动化测试时,因为需要连接手机和电脑端,所以在使用adb去连接本人的安卓手机vivo z5时,发现一直提示unauthorized。后来经过一系列方法尝试,最终得以解决。 问题描述: 用数据线将手机接入电脑端&…...
【软件工程】内聚
概念 是指一个模块内部个成分之间相互关联程度的度量。也就是说,凝聚是对模块内各处理动作组合强度的一种度量。很显然,一个模块的内聚越大越好。 偶然凝聚 一个模块内的各处理元素之间没有任何联系,只是偶然地被凑到一起。这种模块也称为…...

支持对接鸿蒙系统的无线模块及其常见应用介绍
近距离的无线通信得益于万物互联网的快速发展,基于集成部近距离无线连接,为固定和移动设备建立通信的蓝牙技术也已经广泛应用于汽车领域、工业生产及医疗领域。为协助物联网企业终端产品能快速接入鸿蒙生态系统,SKYLAB联手国产芯片厂家研发推…...

java项目打包运行报异常:Demo-1.0-SNAPSHOT.jar中没有主清单属性
检查后发现pom文件中有错误,需要添加build内容才能恢复正常。 添加下面文件后再次启动恢复正常。 <build><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactI…...
nginx+keepalived实现负载均衡和高可用
环境准备 IPVIP环境客户端192.168.134.174Master192.168.134.170192.168.134.100需要配置nginx负载均衡Backup192.168.134.172192.168.134.100需要配置nginx负载均衡web1服务器192.168.134.171 web2服务器 192.168.134.173 1、首先安装nginx服务器(此处采用yum安装…...
微信小程序实现图片多点裁剪
话不多说,直接上代码 1、页面布局 <view class"buttons" style"height: 50px;"><view class"upload btn" style"background-color: #d18118;"bindtap"uploadImage"> 上传图片 </view><vie…...
计算图片的均值和方差用图片的归一化取值
计算图片的均值和方差用图片的归一化取值 注意:使用这种方法的前提是进行了数据批量化操作,需要使用神经网络库,torch,DataLoader def getStat(data):print(len(data))loader torch.utils.data.DataLoader(data, batch_size1, …...

预测算法|改进粒子群算法优化极限学习机IDM-PSO-ELM
回归拟合: 分类 本文是作者的预测算法系列的第四篇,前面的文章中介绍了BP、SVM、RF及其优化,感兴趣的读者可以在作者往期文章中了解,这一篇将介绍——极限学习机 过去的几十年里基于梯度的学习方法被广泛用于训练神经网络&am…...

小黑子—JavaWeb:第六章 - Filter、Listener、AJAX与JSON
JavaWeb入门6.0 1. Filter1.1 Filter快速入门1.2 Filter执行流程1.3 Filter拦截路径配置1.4 Filter过滤器链1.5 案例登录验证 2. Listener2.1 ServletContextListener使用 3. AJAX3.1 AJAX 快速入门3.2 案例 验证用户名是否存在3.3 Axios 异步框架3.3.1 Axios 快速入门3.3.2 Ax…...

STM32 LL库开发
一、STM32开发方式 标准库开发:Standard Peripheral Libraries,STDHAL库开发:Hardware Abstraction Layer,硬件抽象层LL库开发:Low-layer,底层库 二、HAL库与LL库开发对比 ST在推行HAL库的时候,…...

标记垃圾,有三种色彩:四千长文带你深入了解三色标记算法
🔭 嗨,您好 👋 我是 vnjohn,在互联网企业担任 Java 开发,CSDN 优质创作者 📖 推荐专栏:Spring、MySQL、Nacos、Java,后续其他专栏会持续优化更新迭代 🌲文章所在专栏&…...
277/300 React+react-router-dom+Vite 二级页面刷新时,白屏问题解决
(一)方案 BrowserRouter 换为 HashRouter (二)代码 import routes from ./routes import {ReactElement, Suspense} from react import {createHashRouter, Navigate} from react-router-dom // 生成路由数据 const generateR…...
如何做线上监控
1、背景 软件的质量是需要全生命周期进行关注的,在生产环境下QA的活动就是测试右移,测试右移最关键的手段就是线上监控,也是至关重要的一个环节,可以通过技术的手段,提前感知到线上问题和风险,先于用户提前发现问题,提升服务可感知性,从而降低客户投诉。 2、通用原则…...
饥荒开服教程——游戏
饥荒开服教程——游戏 1. 开服环境2. 开服步骤2.1 创建集群2.2 安装服务端2.3 上传mod2.4 启动脚本2.5 上传地图2.6 设置访问令牌2.7 修改配置 3. 服务器命令3.1 关闭服务器3.2 回档 记录一些在饥荒联机版开服中遇到过的问题。 参考:3分钟创建你的饥荒联机专属服务…...
查询 npm/yarn 安装依赖的全局路径及路径修改
一、NPM 1.查询 npm 安装依赖的全局路径 npm prefix -g 2. 修改 npm 全局安装位置 npm config set prefix "D:\nodejs\node_modules\npm\node_modules" 3. 修改 npm 全局 cache 位置 npm config set cache "D:\nodejs\node_modules\npm\cache" 4. np…...
树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频
使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源: http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
蓝桥杯 2024 15届国赛 A组 儿童节快乐
P10576 [蓝桥杯 2024 国 A] 儿童节快乐 题目描述 五彩斑斓的气球在蓝天下悠然飘荡,轻快的音乐在耳边持续回荡,小朋友们手牵着手一同畅快欢笑。在这样一片安乐祥和的氛围下,六一来了。 今天是六一儿童节,小蓝老师为了让大家在节…...

ESP32读取DHT11温湿度数据
芯片:ESP32 环境:Arduino 一、安装DHT11传感器库 红框的库,别安装错了 二、代码 注意,DATA口要连接在D15上 #include "DHT.h" // 包含DHT库#define DHTPIN 15 // 定义DHT11数据引脚连接到ESP32的GPIO15 #define D…...
鸿蒙中用HarmonyOS SDK应用服务 HarmonyOS5开发一个医院挂号小程序
一、开发准备 环境搭建: 安装DevEco Studio 3.0或更高版本配置HarmonyOS SDK申请开发者账号 项目创建: File > New > Create Project > Application (选择"Empty Ability") 二、核心功能实现 1. 医院科室展示 /…...
相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)
【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

ardupilot 开发环境eclipse 中import 缺少C++
目录 文章目录 目录摘要1.修复过程摘要 本节主要解决ardupilot 开发环境eclipse 中import 缺少C++,无法导入ardupilot代码,会引起查看不方便的问题。如下图所示 1.修复过程 0.安装ubuntu 软件中自带的eclipse 1.打开eclipse—Help—install new software 2.在 Work with中…...

OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
QT3D学习笔记——圆台、圆锥
类名作用Qt3DWindow3D渲染窗口容器QEntity场景中的实体(对象或容器)QCamera控制观察视角QPointLight点光源QConeMesh圆锥几何网格QTransform控制实体的位置/旋转/缩放QPhongMaterialPhong光照材质(定义颜色、反光等)QFirstPersonC…...

七、数据库的完整性
七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...