fpga实操训练(按键消抖)

news2024/11/26 10:40:07

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

        之前我们谈到按键输入,其中涉及的功能就是,当按键按下的时候,led灯亮起来。等到按键弹起来的时候,led灯灭掉。这个功能实现起来是比较简单的。只需要把key和led之间做绑定就可以了。

        今天,我们实现一个复杂点的功能。这就是,当第一次按键按下、弹出来的时候,led灯亮起;第二次按键按下、弹出来的时候,led灯灭掉。这个时候应该怎么做呢?其实应该做到这两点,第一,做到按键消抖;第二,实现边沿检测。

1、按键消抖

        要做好按键消抖,那么就要设计一个简单的状态机。一个是idle状态,一个是消抖过程中的延时状态。在做好状态切换前,先锁存一下输入的数据,这个之前在按键输入那一章讲到过,

// delay to get signal from in		
always@(posedge clk or negedge rst)
	if(!rst)
		tmp0 <= 1'b0;
	else
		tmp0 <= in;


always @(posedge clk or negedge rst)
	if(!rst)
		tmp1 <= 1'b0;
	else
		tmp1 <= tmp0;

        有了tmp0和tmp1这两个信号,就可以判断信号什么时候发生了改变,

wire diff;
assign diff = tmp0 ^ tmp1;

        接着,当diff产生的时候,就可以产生一个状态机和计数器,其中状态机的代码如下,

// state machine
always @(posedge clk or negedge rst)
	if(!rst)
		state <= 2'b00;
	else
		state <= next_state;

always@(*)
	if(!rst)
		next_state <= 2'b00;
	else begin
		case (state)
			2'b00:
				if(diff)
					next_state <= 2'b01;
				else
					next_state <= 2'b00;
			
			2'b01:
				if(count == 32'd199_9999)
					next_state <= 2'b00;
				else
					next_state <= 2'b01;
				
			default:
				next_state <= 2'b00;
		endcase
	end

        这是一个经典的三段式状态机写法。没有diff发生的时候,next_state是2'b00。如果diff发生,那么next_state切换成2’b01。等到count变成32’d199_9999的时候,next_state重新变成2'b00。在状态机中谈到了count,接着可以看看count是怎么写的,

always@(posedge clk or negedge rst)
	if(!rst)
		count <= 32'b0;
	else if(state == 2'b01) begin
		if(diff)
			count <= 32'b0;
		else if(count != 32'd199_9999)
			count <= count + 1;
		else
			count <= 32'b0;
	end 

        从上面的代码可以看出,rst复位的时候,count为0。等到state切换为2'b01的时候,count准备递增。如果在这过程中发生了二次抖动,则count重新计数,否则在计数到32'd199_9999之前一直在递增。等递增到32'd199_9999的时候,恢复为0。在state处于其他状态的时候,count都是设置为0。

2、边沿触发检测

        要做到边沿触发检测,一般需要两级寄存器进行检测。等到发现两个寄存器的数值不同的时候,这个时候其实就发生了边沿触发,

// delay one clock for out2
always@(posedge clk or negedge rst)
	if(!rst)
		out1 <= 1'b0;
	else if(count == 32'd199_9999)
		out1 <= tmp1;
		
always@(posedge clk or negedge rst)
	if(!rst)
		out2 <= 1'b0;
	else 
		out2 <= out1;		

// output signal here		
always@(posedge clk or negedge rst)
	if(!rst)
		led <= 1'b0;
	else if(out2 && ~out1)
		led <= ~led;

        这里当count为32'd199_9999的时候,把tmp1的信号传递给out1,下一个时钟,再从out1传递给out2。在这过程当中,如果某一个时刻发现out2和out1不相等的时候,其实边沿触发就发生了。out2&~out1代表的是下降沿,~out2&out1代表的是上升沿。

3、开始实验

        等到代码都编写好之后,最重要的就是把pin脚配置好,烧入到fpga当中。

注:

        最后给出完整的代码,有需要的同学可以好好看下。

//
// led_test
// author: feixiaoxing
// 2022.12.13
//

module led_test(clk, rst, in, led);

input clk;
input rst;
input in;
output led;

wire clk;
wire rst;
wire in;

reg led;
reg out1;
reg out2;

reg[31:0] count;
reg tmp0;
reg tmp1;

reg[1:0] state;
reg[1:0] next_state;

wire diff;
assign diff = tmp0 ^ tmp1;

always @(posedge clk or negedge rst)
	if(!rst)
		state <= 2'b00;
	else
		state <= next_state;

always@(*)
	if(!rst)
		next_state <= 2'b00;
	else begin
		case (state)
			2'b00:
				if(diff)
					next_state <= 2'b01;
				else
					next_state <= 2'b00;
			
			2'b01:
				if(count == 32'd499_9999)
					next_state <= 2'b00;
				else
					next_state <= 2'b01;
				
			default:
				next_state <= 2'b00;
		endcase
	end
		
always@(posedge clk or negedge rst)
	if(!rst)
		count <= 32'b0;
	else if(state == 2'b01) begin
		if(diff)
			count <= 32'b0;
		else if(count != 32'd499_9999)
			count <= count + 1;
		else
			count <= 32'b0;
	end else
		count <= 32'b0;

// delay to get signal from in		
always@(posedge clk or negedge rst)
	if(!rst)
		tmp0 <= 1'b0;
	else
		tmp0 <= in;


always @(posedge clk or negedge rst)
	if(!rst)
		tmp1 <= 1'b0;
	else
		tmp1 <= tmp0;

// delay one clock for out2
always@(posedge clk or negedge rst)
	if(!rst)
		out1 <= 1'b0;
	else if(count == 32'd499_9999)
		out1 <= tmp1;
		
always@(posedge clk or negedge rst)
	if(!rst)
		out2 <= 1'b0;
	else 
		out2 <= out1;		

// output signal here		
always@(posedge clk or negedge rst)
	if(!rst)
		led <= 1'b0;
	else if(out2 && ~out1)
		led <= ~led;

endmodule

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/86234.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

NLP领域表达退化各向异性理解及对应策略总结

前言&#xff1a;今年8月份在与同学撰写deepfake相关论文的过程中偶然听导师提到各向同性与各向异性这两个词&#xff0c;当时以为这是cv领域的概念&#xff0c;回去一查发现是物理领域的&#xff0c;就没再深究。最近看到一篇使用对比学习解决开放式长文本生成中模型退化问题的…

在 Spring Boot 中使用 HikariCP 连接池

目前星标 12K&#xff0c;被使用次数更是达到了 43.1K。再来看看它的自我介绍。 牛逼的不能行啊&#xff0c;原来 Hikari 来源于日语&#xff0c;“光”的意思&#xff0c;这意味着快得像光速一样吗&#xff1f;讲真&#xff0c;看简介的感觉就好像在和我的女神“汤唯”握手一样…

基于SSM的企业管理系统

项目描述 临近学期结束&#xff0c;还是毕业设计&#xff0c;你还在做java程序网络编程&#xff0c;期末作业&#xff0c;老师的作业要求觉得大了吗?不知道毕业设计该怎么办?网页功能的数量是否太多?没有合适的类型或系统?等等。这里根据疫情当下&#xff0c;你想解决的问…

[ vulhub漏洞复现篇 ] GhostScript 沙箱绕过(任意命令执行)漏洞CVE-2019-6116

&#x1f36c; 博主介绍 &#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 _PowerShell &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 &#x1f389;点赞➕评论➕收藏 养成习…

软件测试面试必看,资深测试工程师面试题集锦 全网首发

全网首发&#xff0c;最牛的全套软件测试 &#xff0c;自动化测试面试题&#xff0c;这些面试题都在文章末尾&#xff0c;有需要的可以自取 废话少说直接开始咱们今天的整体内容&#xff0c; 1.自我介绍&#xff1f; 我是谁、工作几年、你上家公司做什么、负责什么、你的优势…

史上最全事件相机DVS/Event-based Camera的介绍和分析综述文章

史上最全事件相机DVS/Event-based Camera的介绍和分析1. DVS 的一些介绍2. 基于事件的视觉传感器发展现状与趋势3. 事件相机的动态范围&#xff1a;信噪比动态范围DR结论4. 新型相机DVS/Event-based camera的发展及应用应用点传统相机的缺点事件相机的优点5. 事件相机在无人驾驶…

[技巧]还在使用RDP远程windows?OpenSSH远程win10操作系统!

文章目录前言一、Win10开启OpenSSH服务1.1 查看本机是否安装了openssh1.2 下载openssh1.3 查看ssh是否安装1.4 安装openssh服务端1.5 启动openssh服务1.6 查看openssh服务是否启动正常二、开始远程2.1 在目标机器上查看用户名2.2 使用ssh命令远程三、常见问题3.1 ssh命令登陆提…

C# 接口

一 接口 接口&#xff08;interface&#xff09;实际上是一个约定。 如&#xff1a;ICloneable,IComparable; 接口是抽象成员的集合&#xff1b; ICIonable含有方法clone(); IComparable含有方法compare(); 接口是一个引用类型&#xff0c;比抽象类更抽象。 帮助实现多重继承…

配置本地Git从Gitlab上拉取项目

配置本地Git从Gitlab上拉取项目 安装git&#xff1a; https://git-scm.com/downloads git官网下载安装包&#xff0c;安装时一路next即可 ①配置用户名&#xff0c;邮箱 创建一个文件夹&#xff0c;任意位置即可鼠标右键选择&#xff0c;git bash here配置提交人姓名、邮箱 g…

一起学习用Verilog在FPGA上实现CNN----(二)卷积层设计

1 打开Vivado工程 Vivado工程文件如图&#xff1a; 打开Vivado软件&#xff0c;打开工程&#xff0c;如图&#xff1a; 自动升级到当前版本&#xff0c;如图&#xff1a; 暂时选择现有开发板的型号&#xff0c;如图&#xff1a; 出现一条警告性信息&#xff0c;暂时先不管&…

2023年第五届人工智能与机器学习国际会议(FAIML 2023)

2023年第五届人工智能与机器学习国际会议(FAIML 2023) 重要信息 会议网址&#xff1a;www.faiml.org 会议时间&#xff1a;2023年4月14-16日 召开地点&#xff1a;中国北京 截稿时间&#xff1a;2023年3月15日 录用通知&#xff1a;投稿后2周内 收录检索&#xff1a;EI,S…

差分进化算法在图像处理中的应用研究(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 本文为Storn和Price制定的著名差分进化计算智能算法的实现。该算法使用Otsu准则作为适应度函数&#xff0c;可用于使用多个阈值…

为什么球的表面积不能用周长积分而体积可以用面积积分?

问题描述&#xff1a; 将面积从最底下一层层叠到最上面可以得到球体积的正确公式 但是将周长从最底下一层层叠到最上面会得到错误结果&#xff0c;错误结果的几何意义是什么&#xff1f;以及是在什么地方积错了&#xff1f; 解答一&#xff1a; 首先&#xff0c; ∫−RR2πR2…

计算机研究生就业方向之去央企(国企)信息化部门

我一直跟学生们说你考计算机的研究生之前一定要想好你想干什么&#xff0c;如果你只是转码&#xff0c;那么你不一定要考研&#xff0c;至少以下几个职位研究生是没有啥优势的&#xff1a; 1&#xff0c;软件测试工程师&#xff08;培训一下就行&#xff09; 2&#xff0c;前…

C语言:星期一问题

题目需求 整个20世纪&#xff08;1901年1月1日至2000年12月31日之间&#xff09;&#xff0c;一共有多少个星期一&#xff1f; (不要告诉我你不知道今天是星期几哈) 请用一段程序实现了这一功能。 算法思路 判断1901年1月1日到2000年12月31的每一天是星期几&#xff0c;如果是星…

前端开发:JS中关于正则表达式的使用汇总

前言 在前端开发过程中&#xff0c;关于正则表达式的使用也是必备技能&#xff0c;尤其是在实际业务需求的时候&#xff0c;需要处理一些不能按照正常语句操作的逻辑&#xff0c;如前端开发中的字符匹配、参数处理等都需要正则表达式来匹配截取处理。虽然正则表达式在程序开发中…

01-18-spark-入门简介-部署入门

01-spark-入门简介&#xff1a; Spark 是一种基于内存的快速、通用、可扩展的大数据分析计算引擎。 一次性数据计算&#xff1a;框架在处理数据的时候&#xff0c;从存储设备中读取数据&#xff0c;进行逻辑操作&#xff0c;然后将结果存储到介质中。 Hadoop 的 MR 框架和 S…

直播技术分享:千万级直播系统后端架构设计的方方面面

1、引言 本文以TFBOYS“日光旅行”七周年这场直播演唱会为案例&#xff0c;为你分享大型直播系统后端架构设计的方方面面&#xff0c;包括&#xff1a;基本架构、稳定性保障、安全性障、监控报警、应急预案等技术范畴。 案例中的这次演唱会采用了在线实时互动及演唱会现场的多…

【能效管理】关于某项目配套渗滤液工程电能管理系统的设计和应用

摘要&#xff1a; 介绍老港综合填埋场二期配套渗滤液工程电能管理系统&#xff0c;采用智能电力仪表采集配电现场的各种电参量。系统采用现场就地组网的方式&#xff0c;组网后通过现场总线通讯并远传至后台&#xff0c;通过Acrel-3000电能管理系统实现配电回路用电的实时监控…

服开与编排,老兵新传

前段时间&#xff0c;有同学问&#xff1a;编排与服开是什么关系&#xff1f;现在运营商都建设编排系统&#xff0c;那是不是服务开通以后就退出 OSS 舞台了&#xff1f;为什么会出现编排&#xff1f;这些问题对于行业老兵来说感慨万千&#xff0c;而对于新兵来说就要通过追溯其…