Verilog实现4位按键消抖,分别控制一个LED

  • 代码思路(完整代码在后)
  • 完整代码

参考:(主要是第一篇,第二篇不严谨)
《按键消抖与LED控制》实验的个人思考与总结
Verilog实现的多个按键消抖(具体模块可用)

代码思路(完整代码在后)

之前的一篇博文中,
FPGA触摸按键控制LED——拓展:按下之后LED闪烁,再次按下停止闪烁
介绍了使用下降沿来判断按键按下并做出反应的方式,那么这次有4个按键,其实同样可以使用这种方法进行采样。但是,这种方法有一个缺点,如果采样的时候有抖动,就会发生误判,只能寄希望于,这个抖动确实很短,人眼观察不到这个细微抖动带来的led的状态的变化。

但是这里我们进行改进。我们之前学过,按键消抖,需要20ms的延时判断,之前是我们计数器只有按键按下,计数器才开始计数,计数满-1就置位flag,说明被按下。这里我们改变思路,每20ms进行一次按键值采样,将两次采样值进行取下降沿操作,得到的值为1的那位就是被按下的按键。
具体思路如下:

我们每20ms进行一次按键值第一次将4位按键信号相与,检测信号的下降沿,只要信号发生下降沿就说明此时按键有抖动,20ms的计数器清零,之前我们的计数器是用来计数按键按下到达20ms的,只要按键为电平就清零,但这里的方式稍微不同,我们采取每20ms保存一次键值,如果抖动,就将计数器清零,直到计数器满才取一次键值,我们取到的就是按键稳定时候的键值,然后将两次的键值进行取下降沿操作,此时取到的下降沿(也就是变量中为一的那一位)就代表了按键的对应位确实被按下了。

首先定义

module key_led
#(parameter KEY_20MS = 999_999
)
(input   wire        sys_clk     ,  input   wire        sys_rst_n   ,  input   wire [3:0]  key_in       ,  output  wire [3:0]  led_out
);

将4位按键相与

reg key_rst;//检测是否有按键按下,并且同步到时钟下always @(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)key_rst <= 1'b1;elsekey_rst <= key_in[3] & key_in[2] & key_in[1] & key_in[0];//将四个按键的值存进,只要有一位被按下就会发生跳变
end

然后对此信号打一拍,之后取下降沿

reg key_rst_reg;//对key_rst进行延一拍always @(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)key_rst_reg <= 1'b1;elsekey_rst_reg <= key_rst;
end//检测下降沿操作
wire key_en = (~key_rst) & key_rst_reg;

只要下降沿信号置位,说明此时还在按键不稳定的状态,计数器清零。因为计数器清零就代表不对按键值采样,所以这是符合逻辑的。

reg [19:0]   cnt_20ms;//20ms计数器//cnt_20ms 计数器
always@(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)cnt_20ms <= 20'd0;else if(key_en)         //检测到抖动cnt_20ms <= 20'd0;else                     cnt_20ms <= cnt_20ms + 20'd1;
end

然后就是对按键值进行采样,以及进行延一拍的操作


reg [3:0] key_flag;//作为按键检测标志位always@(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)key_flag <= 4'b1111;else   if(cnt_20ms == KEY_20MS)//每20ms保存一次键值 key_flag <= key_in;
endreg [3:0] key_flag_reg;//延一拍always@(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)key_flag_reg <= 4'b1111;else  key_flag_reg <= key_flag;
end

最后对按键值进行取下降沿,然后选择LED


//保存按键值
wire [3:0] key_out = (~key_flag) & key_flag_reg;reg [3:0] led_reg;always@(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)led_reg <= 4'b0000;else beginif(key_out == 4'b0001) led_reg[0] <= ~led_out[0];if(key_out == 4'b0010) led_reg[1] <= ~led_out[1];if(key_out == 4'b0100) led_reg[2] <= ~led_out[2];if(key_out == 4'b1000) led_reg[3] <= ~led_out[3];end
endassign led_out[0] = led_reg[0];
assign led_out[1] = led_reg[1];
assign led_out[2] = led_reg[2];
assign led_out[3] = led_reg[3];

完整代码

module key_led
#(parameter KEY_20MS = 999_999
)
(input   wire        sys_clk     ,  input   wire        sys_rst_n   ,  input   wire [3:0]  key_in       ,  output  wire [3:0]  led_out
);/*
还是有两个part,一个part用来检测按键是否按下,输入key_in,输出key_out,为第几位
第二个part用来运行蜂鸣器,根据按键值case,未按下的,不响,按下就DO RE MI FA四个输出对于一位的按键消抖,我们在前面的教程中学过两节按键检测,一节是按键消抖的课
一节是触摸按键的检测,是通过取下降沿的方式检测按键按下的信号,
对于此处检测4个按键,我们将上述两种方法合二为一,第一次将4位按键信号相与,
检测信号的下降沿,只要信号发生下降沿就说明此时按键有抖动,20ms的计数器清零,
之前我们的计数器是用来计数按键按下到达20ms的,只要按键为电平就清零,
但这里的方式稍微不同,我们采取每20ms保存一次键值,如果抖动,就将计数器清零,
直到计数器满才取一次键值,我们取到的就是按键稳定时候的键值,
然后将两次的键值进行取下降沿操作,此时取到的下降沿(也就是变量中为一的那一位)
就代表了按键的对应位确实被按下了。*/reg key_rst;//检测是否有按键按下,并且同步到时钟下always @(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)key_rst <= 1'b1;elsekey_rst <= key_in[3] & key_in[2] & key_in[1] & key_in[0];//将四个按键的值存进,只要有一位被按下就会发生跳变
endreg key_rst_reg;//对key_rst进行延一拍always @(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)key_rst_reg <= 1'b1;elsekey_rst_reg <= key_rst;
end//检测下降沿操作
wire key_en = (~key_rst) & key_rst_reg;reg [19:0]  cnt_20ms;//20ms计数器//cnt_20ms 计数器
always@(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)cnt_20ms <= 20'd0;else if(key_en)         //检测到抖动cnt_20ms <= 20'd0;else                     cnt_20ms <= cnt_20ms + 20'd1;
endreg [3:0] key_flag;//作为按键检测标志位always@(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)key_flag <= 4'b1111;else    if(cnt_20ms == KEY_20MS)//每20ms保存一次键值 key_flag <= key_in;
endreg [3:0] key_flag_reg;//延一拍always@(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)key_flag_reg <= 4'b1111;else  key_flag_reg <= key_flag;
end//保存按键值
wire [3:0] key_out = (~key_flag) & key_flag_reg;reg [3:0] led_reg;always@(posedge sys_clk or negedge sys_rst_n) beginif(!sys_rst_n)led_reg <= 4'b0000;else beginif(key_out == 4'b0001) led_reg[0] <= ~led_out[0];if(key_out == 4'b0010) led_reg[1] <= ~led_out[1];if(key_out == 4'b0100) led_reg[2] <= ~led_out[2];if(key_out == 4'b1000) led_reg[3] <= ~led_out[3];end
endassign led_out[0] = led_reg[0];
assign led_out[1] = led_reg[1];
assign led_out[2] = led_reg[2];
assign led_out[3] = led_reg[3];endmodule

Verilog实现4位按键消抖,分别控制一个LED相关推荐

  1. verilog常用模块1——按键消抖模块详解

    按键消抖模块key_filter 1. 原理介绍 如图,按键未按下时keys信号为高电平,按下则为低电平:通过检测keys信号电平,就可以判断按键状态. 但反作用弹簧会导致抖动现象,电平信号出现一段不 ...

  2. Verilog实现4位按键分别控制蜂鸣器发出不同音阶(未完成,请指导)

    实验任务: 使用板载4位独立按键,进行4位按键消抖检测,当没有按键按下时不响,按下则发出声响,分别为 DO RE MI FA. 实验思路 还是有两个part,一个part用来检测按键是否按下,输入ke ...

  3. FPGA学习-Verilog实现独立按键消抖

    文章目录 前言 一.独立按键消抖原理 二.按键消抖程序实现(Verilog) 1.按键触发判断 2.计数器模块实现 3.按键状态更新 4.按键控制led亮灭 三.仿真测试文件编写 四.编译结果 前言 ...

  4. 【Verilog HDL 训练】第 09 天(按键消抖)

    5月7日 按键防抖 1. 用verilog实现按键抖动消除电路,抖动小于15ms,输入时钟12MHz. 在编写Verilog代码之前,先分析下一些前提问题,首先是几个按键(1个,多个),我们以1个和三 ...

  5. 基于verilog按键消抖设计

    关于键盘的基础知识,我就以下面的一点资料带过,因为这个实在是再基础不过的东西了.然后我引两篇我自己的博文,都是关于按键消抖的,代码也正是同目录下project里的.这两篇博文都是ednchina的博客 ...

  6. c语言实现按键的抖动与消除,【Verilog HDL 训练】第 09 天(按键消抖)

    5月7日 按键防抖 1. 用verilog实现按键抖动消除电路,抖动小于15ms,输入时钟12MHz. 在编写Verilog代码之前,先分析下一些前提问题,首先是几个按键(1个,多个),我们以1个和三 ...

  7. Verilog功能模块 —— 按键消抖

    一. 什么是按键消抖 按键消抖_百度百科 (baidu.com) 按键消抖通常的按键所用开关为机械弹性开关,当机械触点断开.闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上稳定地接通,在断 ...

  8. Verilog中按键消抖检测的实现

    Verilog按键消抖是FPGA学习时的一个入门教程,为避免眼高手低,还是再次分析与记录一下.此处着重介绍按键消抖的基本原理,对按键消抖与检测的关键技术进行分析,并进行功能仿真. 一.按键消抖基本原理 ...

  9. verilog基础-状态机之FPGA独立按键消抖设计与验证(熟练testbench的写法)

    独立按键消抖设计与验证 本实验主要是为了锻炼状态机的思维模式以及熟练掌握TB的写法 本节主要收获了:define的用法,另外就是,顶层的input在TB中是reg的真正含义,其实就是把激励当做寄存器来 ...

最新文章

  1. abaqus二次开发python 建立集合,ABAQUS二次开发-Python脚本运行方式
  2. Simulink仿真---PMSM滞环电流控制仿真模型学习
  3. Python学习笔记:安装python
  4. dubbo启动时检查服务
  5. Nginx静态资源压缩实战内容介绍
  6. java的Swing里怎么new一条线_java – 在JFrame上绘制一条线
  7. docker build 中的上下文路径
  8. java类spring加载_spring的加载机制?
  9. 同时运行两个PHP吗,PHP-避免由两个工作人员同时运行后台作业
  10. Ubuntu 搭建SVN服务器(SVN Server)
  11. 云服务器上Mongodb被拖库,黑客向我勒索0.015 BTC
  12. Android8 for 9300,三星G9300官方固件rom刷机包 G9300ZCS3CRI1 安卓8.0
  13. 135编辑器怎么复制html,135编辑器复制粘贴文字的方法
  14. POJ 2079 求最大三角形面积
  15. 文件包含小总结 By Assassin
  16. CASS中基于高程点并生成等高线的方法
  17. jsp+java中小学排课系统
  18. 【学习笔记】使用魔数快速求平方根
  19. Tecohoo VD-206全高清视频会议摄像机
  20. 招标投标中各流程时间期限的规定

热门文章

  1. PaddlePaddle 复现 YOLOX
  2. java毕业设计某服装店购物网站源码+lw文档+mybatis+系统+mysql数据库+调试
  3. 为什么要用 UML 建模之建模的重要性
  4. 破茧成蝶之用户体验设计师的成长之路-设计实施
  5. java 实现发送短信验证码
  6. webform计算某几列结果_1+x 证书 Web 前端开发初级实操考试(试卷5 )
  7. 【PaperReading】Toward a gold standard for benchmarking gene set enrichment analysis
  8. 英特尔12代酷睿处理器正式发布,驱动人生助力相关驱动下载升级
  9. moco的使用,moco测试前端页面、moco的启动、moco前端测试工具、moco的例子
  10. 微信小程序开发:如何快速实现添加一条分割线的项目需求