【数电实验6】Verilog—按键防抖动设计

这篇具有很好参考价值的文章主要介绍了【数电实验6】Verilog—按键防抖动设计。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【2022.05西南交大数电实验】

【本代码及波形已通过老师验收。仅供参考。

【参考博客:Verilog实现独立按键消抖(状态机)_ty_xiumud的博客-CSDN博客_verilog按键消抖】

【参考视频(强推这个up主):[录播] 数字电子技术实验_哔哩哔哩_bilibili】 

【2022.05.11更新:目前仅有一人反映,拨动开关(不是按钮开关)关闭时计数的,有助教判为一验不过。该情况则是需要改为在高电平时计数。修改建议:在s1高电平稳定时的key_flag取1,s2计数满后认定为低电平稳定的key_flag取为0:

S1:	
						begin
							key_flag   <= 1'b1;	
							key_state  <= 1'b1;	
							en_counter <= 1'b0;	
S2:	
						if(cnt_full)	//计数满,说明达到稳定状态,关闭计数器,进入下一个状态
							begin
								state      <= S3;
								en_counter <= 1'b0;
								key_flag   <= 1'b0;
								key_state  <= 1'b0;

这样跑出来的波形是这样:

【数电实验6】Verilog—按键防抖动设计

因大部分人反映用正文代码验收无问题,就不再修改正文代码。

目录

1 Quartus代码编写

2 test代码生成

3 ModelSim仿真

4 实验记录

5 其他

5.1 显示单位的切换

5.2 缩放界面


1 Quartus代码编写

module yck_1716_6_1(clk, rst_n, key_in, key_flag, key_state, codeout, Q, CO);

input clk;        //时钟50MHz
input rst_n;      //复位信号
input key_in;     //按键输入


output key_state;		//按键状态,高电平为未按下,低电平为按下状态
output key_flag;		//经消抖后可确认的按下动作

output CO;		//进位信号
output reg [6: 0] codeout;
output reg [3: 0] Q;	


parameter   S1 = 2'b00,		//松开稳定时
            S2 = 2'b01,		//按下毛刺时
            S3 = 2'b10,		//按下稳定时
            S4 = 2'b11;		//松开毛刺时
				


/*===============================================================20ms计数器=============================================================*/
reg en_counter;	//计数使能
reg [19:0] cnt;	//计数
reg cnt_full;

//只有当计数使能为高电平的时候,计数器才会计数
always@(posedge clk or negedge rst_n)
	begin
		if(!rst_n)
			cnt <= 0;
		else if(en_counter)
			cnt <= cnt + 1'b1;
		else 
			cnt <= 0;
	end
	
//计数满信号(数数到1000000计数满时间到。1000000是1M,当基于clk信号频率进行计数时,cnt_full走过(1/50M)s*1M的时间,即20ms)
always@(posedge clk or negedge rst_n)	//当clk接50MHz的信号时,相当于clk在1s内进行了50M次计数,相邻上升沿相间(1/50M)s
begin
	if(!rst_n)
		cnt_full <= 1'b0;
	else if(cnt == 20'd1000000)	//1000000的二进制数有20位(2^20=1048576)
		cnt_full <= 1'b1;
	else 
		cnt_full <= 1'b0;
end



/*==============================================================判断边沿模块=============================================================*/
reg key_tmp0,key_tmp1;

always@(posedge clk or negedge rst_n)
	begin
		if(!rst_n)
			begin
				key_tmp0 <= 1'b1;
				key_tmp1 <= 1'b1;
			end
			
		else
			begin
				key_tmp0 <= key_in;		//key_in按键输入
				key_tmp1 <= key_tmp0;	
			end
			
	end

wire pedge,nedge;
assign nedge = (!key_tmp0) & key_tmp1;        //下降沿(下一clk时为0,上一clk时为1)
assign pedge = key_tmp0 & (!key_tmp1);        //上升沿(下一clk时为1,上一clk时为0)



/*=============================================================状态机模块================================================================*/
reg [1:0] state;
reg key_flag;		//经消抖后可确认的按下动作
reg key_state;		//按键状态,高电平为未按下,低电平为按下状态

always@(posedge clk or negedge rst_n)
	begin
		
		if(!rst_n)
			begin
				state      <= S1; 
				en_counter <= 1'b0;	//计数器归零
				key_state  <= 1'b1;	//按键未按下
				key_flag   <= 1'b0;
			end
		
		else 
			begin
				case(state)
					
					S1:	//高电平(松开稳定)
						begin
							key_flag   <= 1'b0;	//按键未按下,不计
							key_state  <= 1'b1;	//按键松开状态
							en_counter <= 1'b0;	//计数器归零
							
							if(nedge)	//检测到下降沿,进入下一个状态同时打开计数器
								begin
									state      <= S2;
									en_counter <= 1'b1;	//计数器使能
								end
							
							else 
								state <= state;	//保持目前状态    
						end
					
					S2:	//下降沿抖动(按下毛刺)
						if(cnt_full)	//计数满,说明达到稳定状态,关闭计数器,进入下一个状态
							begin
								state      <= S3;
								en_counter <= 1'b0;	//计数器归零
								key_flag   <= 1'b1;	//按键可确认已按下
								key_state  <= 1'b0;	//按键按下状态
							end
						
						else if(pedge)	//检测到上升沿(毛刺),跳回S1状态同时关闭计数器
							begin
								en_counter <= 1'b0;	//计数器归零
								state      <= S1;
							end
						
						else 
							state <= state;	//保持目前状态
							
					S3:	//低电平(按下稳定)
						begin
							key_flag <= 1'b0;	//一个按键周期测到一次就行,现在可清零了(后面代码编写只在意其posedge)
							
							if(pedge)	//检测到上升沿,进入下一个状态同时打开计数器
								begin
									state      <= S4;
									en_counter <= 1'b1;	//计数器使能
								end
							
							else 
								state <= state;	//保持目前状态
						end
					
					S4:	//上升沿抖动(松开毛刺)
						if(cnt_full)
							begin
								state     <= S1;
								key_state <= 1'b1;
							end
						
						else 
							if(nedge)
								begin
									en_counter <= 1'b0;	//计数器归零
									state      <= S3;					 		
								end 
							else 
								state <= state;	//保持目前状态
					
					default:
						state <= S1;
						
					endcase
	
			end
	
	end

	

/*===========================================================计数值输出与译码器模块========================================================*/
always@(posedge key_flag,negedge rst_n)	//key_flag:经消抖后可确认的按下动作
	if(!rst_n)
		Q <= 0;
	else
		begin
			if(Q < 4'd9)
				Q <= Q + 1'b1;
			else
				Q <= 4'b0;
		end
	
	assign CO = (rst_n & Q == 4'd9);
	
always@(Q)
	begin
		case(Q)
			4'd0:codeout <= 7'b1111110;
			4'd1:codeout <= 7'b0110000;
			4'd2:codeout <= 7'b1101101;
			4'd3:codeout <= 7'b1111001;
			4'd4:codeout <= 7'b0110011;
			4'd5:codeout <= 7'b1011011;
			4'd6:codeout <= 7'b1011111;
			4'd7:codeout <= 7'b1110000;
			4'd8:codeout <= 7'b1111111;
			4'd9:codeout <= 7'b1111011;
		default:codeout <= 7'bx;
	endcase
end



endmodule

2 test代码生成

         对 yck_1716_6_1.v 进行 Start Compilation 【数电实验6】Verilog—按键防抖动设计,而后自动生成test bench代码(如果没有Start Compilation 直接生成test bench代码会报错的)

【注:若出现Can't generate test bench files -- select a valid simulation tool,则通过菜单栏Assignments—Settings弹出窗口中EDA Tool Settings—Simulation设置为ModelSim,重新编译即可解决:【数电实验6】Verilog—按键防抖动设计

        得到测试v文件的步骤见上一博客【数电实验5】Verilog—可控分频器设计 & ModelSim的使用_kokoのadventure的博客-CSDN博客_可控分频器设计

        测试v文件的代码如下:

`timescale 1 ns/ 1 ns
module yck_1716_6_1_vlg_tst();
// constants                                           
// general purpose registers

// test vector input registers
reg clk;
reg key_in;
reg rst_n;
// wires                                               
wire CO;
wire [3:0]  Q;
wire [6:0]  codeout;
wire key_flag;
wire key_state;

// assign statements (if any)                          
yck_1716_6_1 i1 (
// port map - connection between master ports and signals/registers   
	.CO(CO),
	.Q(Q),
	.clk(clk),
	.codeout(codeout),
	.key_flag(key_flag),
	.key_in(key_in),
	.key_state(key_state),
	.rst_n(rst_n)
);
initial                                                
begin                                                  
// code that executes only once                        
// insert code here --> begin                          
		clk    = 1'b0;
		rst_n  = 1'b0;
		key_in = 1'b1;
		// Wait 100 ns for global reset to finish
		#200
      rst_n = 1'b1;
// --> end                                             
$display("Running testbench");                       
end

always
	begin

		 key_in = 1'b0;#1000000;
		 key_in = 1'b1;#1000000;
		 key_in = 1'b0;#1000000;
		 key_in = 1'b1;#1000000;
		 key_in = 1'b0;#1000000;
		 key_in = 1'b1;#1000000;
		 key_in = 1'b0;#1000000;
		 key_in = 1'b1;#1000000;
		 key_in = 1'b0;#1000000;
		 key_in = 1'b1;#1000000;
		 key_in = 1'b0;#(50*1000000);
		 
		 key_in = 1'b1;#1000000;
		 key_in = 1'b0;#1000000;
		 key_in = 1'b1;#1000000;
		 key_in = 1'b0;#1000000;
		 key_in = 1'b1;#1000000;
		 key_in = 1'b0;#1000000;
		 key_in = 1'b1;#1000000;
		 key_in = 1'b0;#1000000;
		 key_in = 1'b1;#1000000;
		 key_in = 1'b0;#1000000;
		 key_in = 1'b1;#(50*1000000);
	end
                                                    
always                                                 
// optional sensitivity list                           
// @(event1 or event2 or .... eventn)                  
begin                                                  
// code executes for every event on sensitivity list   
// insert code here --> begin                          
		 #10 clk = ~clk;		// (1/50M)/2 ns = 10 ns												 
// --> end                                             
end                                                    
endmodule

3 ModelSim仿真

        相关步骤见上一博客【数电实验5】Verilog—可控分频器设计 & ModelSim的使用_kokoのadventure的博客-CSDN博客_可控分频器设计

         测试波形如下:

        10ms毛刺区: 

【数电实验6】Verilog—按键防抖动设计

 【数电实验6】Verilog—按键防抖动设计

4 实验记录

【数电实验6】Verilog—按键防抖动设计

Top-level Entity name

Family

Device

yck_1716_5_1

Cyclone IV E

EP4CE6E22C8

Total logic elements

Total registers

Total pins

59 / 6,272 ( < 1 % )

34

17 / 92 ( 18 % )

Total memory bits

Embedded Multiplier 9-bit elements

Total PLLs

0 / 276,480 ( 0 % )

0 / 30 ( 0 % )

0 / 2 ( 0 % )

信号名

主板器件

PIN

信号名

主板器件

PIN

clk

50MHz

PIN_90

Q[3]

IO3/LED3

PIN_54

rst_n

Key0/SW0/LED8

PIN_24

Q[2]

IO2/LED2

PIN_52

key_in

Key1/SW1/LED9

PIN_31

Q[1]

IO1/LED1

PIN_50

codeout[6]

a

PIN_112

Q[0]

IO0/LED0

PIN_46

codeout[5]

b

PIN_100

codeout[4]

c

PIN_104

codeout[3]

d

PIN_111

codeout[2]

e

PIN_106

codeout[1]

f

PIN_110

codeout[0]

g

PIN_103

5 其他

5.1 显示单位的切换

        Wave—WavePreference 

【数电实验6】Verilog—按键防抖动设计

         显示ms:

【数电实验6】Verilog—按键防抖动设计

         显示Hz:

【数电实验6】Verilog—按键防抖动设计

5.2 缩放界面

        ctrl + 滚轮缩放界面(慢一点,modelsim加载很慢)文章来源地址https://www.toymoban.com/news/detail-438604.html

到了这里,关于【数电实验6】Verilog—按键防抖动设计的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 北邮22级信通院数电:Verilog-FPGA(12)第十二周实验(1)设计一个汽车尾灯自动控制系统

    北邮22信通一枚~ 跟随课程进度更新北邮信通院数字系统设计的笔记、代码和文章 持续关注作者 迎接数电实验学习~ 获取更多文章,请访问专栏: 北邮22级信通院数电实验_青山如墨雨如画的博客-CSDN博客   目录 一.题目要求 二.代码部分 2.1  car_system.v  2.2  divide.v 三.管脚分配

    2024年02月05日
    浏览(58)
  • 【数电实验7】Verilog—外星萤火虫

    【2022.05西南交大数电实验】 【本代码及波形已通过老师验收。 仅供参考 。 】 【 参考博客 :[数电实验]外星萤火虫设计_难凉oh的博客-CSDN博客】 【 建议 :有些口语化的注释看完删掉比较好哈,怕老师查验的时候看起来太明显咯】 最后一次数电实验啦!!完结撒花~~祝大家

    2024年02月08日
    浏览(47)
  • 【数电实验3】Verilog—1位十进制可逆计数器

    【2022.04西南交大数电实验】 【2022.04.17 更新修改了一个错误: ~clr改为了clr: 另外 ,把代码修得整齐好看了一点】 【代码参考博主weixin_49270464,已进行适当修改,符合实验要求。本代码及波形已通过老师验收。仅供参考。】    信号名 主板器件 PIN 信号名 主板器件 PIN clr

    2024年02月06日
    浏览(53)
  • FPGA编程,verilog实现简易电梯控制系统,某大学数电实验课设

    开发环境:Vivado 2020.1 使用编程语言:Verilog 开发板芯片:xc7a35tftg256-1(具体开发板型号未知,不同版本的开发板可能某些元件的引脚电平会不同,可能需要根据自己手上的开发板版本做一些修改) 项目基本介绍: 1、实现2层楼的简易电梯控制系统。 2、电梯有4个按键。   

    2024年02月09日
    浏览(44)
  • 北邮22级信通院数电:Verilog-FPGA(10)第十周实验 实现移位寄存器74LS595

    北邮22信通一枚~ 跟随课程进度更新北邮信通院数字系统设计的笔记、代码和文章 持续关注作者 迎接数电实验学习~ 获取更多文章,请访问专栏: 北邮22级信通院数电实验_青山如墨雨如画的博客-CSDN博客 目录 一.代码部分  二.管脚分配 三.实现过程讲解及效果 shift_register.v d

    2024年02月05日
    浏览(62)
  • verilog学习笔记- 11)按键控制蜂鸣器实验

    蜂鸣器按照驱动方式主要分为有源蜂鸣器和无源蜂鸣器,其主要区别为蜂鸣器内部是否含有震荡源。一般的有源蜂鸣器内部自带了震荡源,只要通电就会发声。而无源蜂鸣器由于不含内部震荡源,需要外接震荡信号才能发声。                                          

    2024年02月02日
    浏览(42)
  • verilog学习笔记- 10)按键控制 LED 灯实验

    目录 简介: 实验任务: 硬件设计: 程序设计: 下载验证 : 总结与反思: 按键开关是一种电子开关,属于电子元器件类。我们的开发板上有两种按键开关:第一种是本实验所使用的轻触式按键开关,使用时以向开关的操作方向施加压力使内部电路闭合接通,当撤销压力时

    2023年04月16日
    浏览(43)
  • 北邮22级信通院数电:Verilog-FPGA(6)第六周实验:全加器(关注我的uu们加群咯~)

    北邮22信通一枚~ 跟随课程进度更新北邮信通院数字系统设计的笔记、代码和文章 持续关注作者 迎接数电实验学习~ 获取更多文章,请访问专栏: 北邮22级信通院数电实验_青山如墨雨如画的博客-CSDN博客 目录 一.verilog 代码 add.v 二.管脚分配 三.实验效果 3.1说明 ​编辑 3.2实验

    2024年02月06日
    浏览(45)
  • 北邮22级信通院数电:Verilog-FPGA(12)第十二周实验(2)彩虹呼吸灯(bug已解决 更新至3.0)

    北邮22信通一枚~ 跟随课程进度更新北邮信通院数字系统设计的笔记、代码和文章 持续关注作者 迎接数电实验学习~ 获取更多文章,请访问专栏: 北邮22级信通院数电实验_青山如墨雨如画的博客-CSDN博客 目录 一.代码部分 1.1一些更新和讲解 1.2改正后的代码  二.管脚分配 三

    2024年02月04日
    浏览(50)
  • 数电实验6:可控分频器设计

    学习 ModelSim 仿真方法。 巩固 Verilog HDL 时序电路设计。 FPGA 开发板上有一个 50MHz 的高频时钟。设计一个可控分频器,clk_in 为分频器时钟输入, sel为选择开关, clk_out为分频器信号输出。当sel=0时,fclk_out=sn[2:0]Hz;当 sel=1 时, fclk_out=sn[4:0] Hz。 clk_out 的占空比 D=28%;(D=tH/T,

    2024年02月05日
    浏览(39)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包