FPGA按键消抖,按键点灯

该文描述了一个使用Verilog编写的顶层文件,包括按键消抖和LED控制模块。按键消抖模块通过检测按键输入并消除抖动,提供稳定的按键状态输出。LED控制模块根据按键状态改变LED灯的状态。整个设计旨在处理硬件系统中的输入信号处理和输出显示。
摘要由CSDN通过智能技术生成

顶层文件

输入:Clk(时钟),Rst_n(复位信号),key_in0(按键输入),key_in1(按键输入)
输出:led(4个led灯)

module key_led_top(Clk,Rst_n,key_in0,key_in1,led);

	input Clk;
	input Rst_n;
	input key_in0;
	input key_in1;
	
	output [3:0]led;
	
	wire key_flag0,key_flag1;
	wire key_state0,key_state1;

	key_filter key_filter0(  //调用按键消抖模块
		.Clk(Clk),
		.Rst_n(Rst_n),
		.key_in(key_in0),
		.key_flag(key_flag0),
		.key_state(key_state0)
	);
	
	key_filter key_filter1(   //调用按键消抖模块
		.Clk(Clk),
		.Rst_n(Rst_n),
		.key_in(key_in1),
		.key_flag(key_flag1),
		.key_state(key_state1)
	);
	
	led_ctrl led_ctrl0(  //调用控制led模块
		.Clk(Clk),
		.Rst_n(Rst_n),
		.key_flag0(key_flag0),
		.key_flag1(key_flag1),
		.key_state0(key_state0),
		.key_state1(key_state1),
		.led(led)
	);

endmodule

按键消抖模块:

输入:Clk(时钟信号),Rst_n(复位信号),key_in(按键输入)
输出:key_flag(检测到按键标志位,为1为有按键输入),key_state(按键稳定标志位,为0位有按键输入)
在这里插入图片描述
在这里插入图片描述

module key_filter(Clk,Rst_n,key_in,key_flag,key_state);

	input Clk;
	input Rst_n;
	input key_in;
	
	output reg key_flag;
	output reg key_state;
	
	localparam
		IDEL		= 4'b0001,
		FILTER0	= 4'b0010,
		DOWN		= 4'b0100,
		FILTER1 	= 4'b1000;
		
	reg [3:0]state;
	reg [19:0]cnt;
	reg en_cnt;	//使能计数寄存器
	
//对外部输入的异步信号进行同步处理
	reg key_in_sa,key_in_sb;
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)begin
		key_in_sa <= 1'b0;
		key_in_sb <= 1'b0;
	end
	else begin
		key_in_sa <= key_in;
		key_in_sb <= key_in_sa;	
	end
	
	reg key_tmpa,key_tmpb;
	wire pedge,nedge;
	reg cnt_full;//计数满标志信号
	
//使用D触发器存储两个相邻时钟上升沿时外部输入信号(已经同步到系统时钟域中)的电平状态
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)begin
		key_tmpa <= 1'b0;
		key_tmpb <= 1'b0;
	end
	else begin
		key_tmpa <= key_in_sb;
		key_tmpb <= key_tmpa;	
	end

//产生跳变沿信号	
//key_tmpa,key_tmpb本身一直为0,key_in_sb为输入信号,
//经过赋值之后key_tmpa变成输入信号(也就是相对于过去为高电平),
//key_tmpb依旧为0,所以!key_tmpa & key_tmpb; key_tmpa取反为0和b相同则为下降沿
//在key_tmpa已经是当前高电平的情况下key_tmpa & (!key_tmpb);key_tmpb取反为0和b相同则为上升沿
	assign nedge = !key_tmpa & key_tmpb; 
	assign pedge = key_tmpa & (!key_tmpb);
	
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)begin
		en_cnt <= 1'b0;
		state <= IDEL;
		key_flag <= 1'b0;
		key_state <= 1'b1;
	end
	else begin
		case(state)
			IDEL :
				begin
					key_flag <= 1'b0;
					if(nedge)begin //检测到下降沿
						state <= FILTER0;//切换状态
						en_cnt <= 1'b1; //计数器使能,只有使能才能开始计数
					end
					else
						state <= IDEL;//没有就保持
				end
					
			FILTER0:
				if(cnt_full)begin //计数满的标志
					key_flag <= 1'b1;
					key_state <= 1'b0;
					en_cnt <= 1'b0;
					state <= DOWN;
				end
				else if(pedge)begin
					state <= IDEL;
					en_cnt <= 1'b0;
				end
				else
					state <= FILTER0;
					
			DOWN:
				begin
					key_flag <= 1'b0;
					if(pedge)begin
						state <= FILTER1;
						en_cnt <= 1'b1;
					end
					else
						state <= DOWN;
				end
			
			FILTER1:
				if(cnt_full)begin
					key_flag <= 1'b1;
					key_state <= 1'b1;
					en_cnt <= 1'b0;
					state <= IDEL;
				end
				else if(nedge)begin
					en_cnt <= 1'b0;
					state <= DOWN;
				end
				else
					state <= FILTER1;
			
			default:
				begin 
					state <= IDEL; 
					en_cnt <= 1'b0;		
					key_flag <= 1'b0;
					key_state <= 1'b1;
				end
				
		endcase	
	end
	
	//计数器
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		cnt <= 20'd0;  
	else if(en_cnt)
		cnt <= cnt + 1'b1;
	else
		cnt <= 20'd0;
	
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		cnt_full <= 1'b0;
	else if(cnt == 999_999) //时钟20ns一次,20毫秒就计数到1,000,000
		cnt_full <= 1'b1;
	else
		cnt_full <= 1'b0;	
endmodule

led控制

输入:Clk,Rst_n,key_flag0,key_flag1,key_state0,key_state1,
输出:led

module led_ctrl(Clk,Rst_n,key_flag0,key_flag1,key_state0,key_state1,led);

	input Clk;
	input Rst_n;
	input key_flag0,key_flag1;
	
	input key_state0,key_state1;
	
	output [3:0]led;
	
	reg [3:0]led_r;
	
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		led_r <= 4'b0000;
	else if(key_flag0 && !key_state0)
		led_r <= led_r + 1'b1;
	else if(key_flag1 && !key_state1)
		led_r <= led_r - 1'b1;
	else
		led_r <= led_r;
		
	assign led = ~led_r;  //板子上led灯1灭,0亮
		
endmodule

引脚配置

在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值