FPGA10 按键消抖

按键消抖

  • I 按键信号 “输入--处理--输出” 的过程
  • II 消抖状态机运行原理
  • III 代码
    • 1 顶层模块(top)
    • 2 计数器(counter)
    • 3 边沿检测器(abstract)
    • 4输入-消抖(状态机)-输出(key)
  • IV testbench:top_tb
  • V 前仿真
  • VI 后仿真

I 按键信号 “输入–处理–输出” 的过程

按键信号的输入(in1) 是有抖动的,经过消抖处理,以得到标准的按键信号(l___l)。
FPGA10 按键消抖_第1张图片
边沿检测器来用来检测按键按下时的下降沿,和松开时的上升沿
计数器提供延时去抖
协助状态机进行去抖操作

II 消抖状态机运行原理

FPGA10 按键消抖_第2张图片

III 代码

1 顶层模块(top)

module top(in1,clk1,rst_n1,outkey1,outflag1);

		input in1;
		input clk1;
		input rst_n1;
		wire down1;
		wire up1;
		wire cnt_full1;
		wire en_cnt1;
        output outkey1;
        output outflag1;
		
		
	abstract u1(
					.in(in1), 
					.clk(clk1),
					.rst_n(rst_n1),
					.down(down1),
					.up(up1)
					);
	
	
	counter u2(
					.clk(clk1),
					.rst_n(rst_n1),
					.cnt_full(cnt_full1),
					.en_cnt(en_cnt1)
					);
	
	
	key u3(
					.down(down1),
					.up(up1),
					.cnt_full(cnt_full1),
					.clk(clk1),
					.rst_n(rst_n1),
					.en_cnt(en_cnt1),
                    .outkey(outkey1),
                    .outflag(outflag1)
					);

	endmodule

2 计数器(counter)

module counter (clk,rst_n,cnt_full,en_cnt);

		input clk;
		input rst_n;
		input en_cnt; 
	   reg [19:0] cnt;
		output reg cnt_full;  
		
	  //系统时钟50M = 20ns 20ms = 20_000_000ns  0.2ms = 2000_000ns /20 = 1_000_000 
	  //1 000 000 换算成二进制 得到 20个二进制位
	  
	 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)	
	        cnt_full <= 1 ;
	  else 
	  		cnt_full <= 1'b0;
endmodule

3 边沿检测器(abstract)

module abstract(in, clk,rst_n,down,up);
				//in 是输入信号,down为下降沿输出端,up为上升沿输出端
				
		input in;
		input clk;
		input rst_n;
		output down;
		output up;
		reg temp1;
		reg temp2;
	
	always@(posedge clk or negedge rst_n)
			
			if(!rst_n)
			begin
				temp1 <= 1'b0;
				temp2 <= 1'b0;					
			end
			
			else
			begin
				temp1 <= in ;
				temp2 <= temp1;
			end
	assign up = temp1 & (!temp2);
	assign down = (!temp1) & temp2;

endmodule

4输入-消抖(状态机)-输出(key)

module key (down,up,cnt_full,clk,rst_n,en_cnt,outkey,outflag);
		input rst_n;
		input clk;
		input down;
		input up;
		input cnt_full;
        output reg outflag;
		output reg en_cnt;
		output reg outkey;
	
		localparam
		     DENGXIA    = 4'b0001,
		     YANSHI  = 4'b0010,
		     WENDING    = 4'b0100,
		     YANSHI2  = 4'b1000;
   	 	
   	 	reg [3:0]state; //状态寄存器
        
always@(posedge clk or negedge rst_n)

	if(!rst_n) begin
        state  <= DENGXIA;
	    en_cnt <= 1'b0;
        outkey <= 1'b1;
        outflag <=1'b0;
        
	end
	 else  begin
		case(state)
        
			DENGXIA :
                begin
                  outflag <= 1'b0; //flag
			      if(down) begin 		
			         state  <= YANSHI; 
			         en_cnt <= 1'b1;      
			      end
			      else					
			         state <= DENGXIA;
                end
            YANSHI :
			      if(cnt_full)begin  
                     outflag <=1'b1; //flag
                     outkey <= 1'b0; //out
			         state <= WENDING;  
			         en_cnt <= 1'b0; 
			       end
			      else if (up) begin  
			         state <= DENGXIA;   
			         en_cnt <= 1'b0;  
			      end
			      else 
			         state  <= YANSHI;  
			WENDING :
			    begin
			    	outflag <=1'b0;	//flag
	 				if(up) begin 	
			         state  <= YANSHI2; 
			         en_cnt <= 1'b1;   
			         end
			        else					
			          state  <= WENDING; 
			    end
			YANSHI2 :
			      if(cnt_full)begin
                     outflag <=1'b1; //flag
                     outkey <= 1'b1; //out
			         state  <= DENGXIA; 
			         en_cnt <= 1'b0; 
			       end
			      else if (down) begin  
			         state <= WENDING;   
			         en_cnt <= 1'b0;  
			      end
			      else 
			         state  <= YANSHI2;  
			default :  
					  
				begin
					state <= DENGXIA;
					en_cnt <= 1'b0;
                    outkey <=1'b1; //out
                    outflag <=1'b0;//flag
					
				end

	  endcase
	  end
	  endmodule

IV testbench:top_tb

`timescale 1ns/1ns
`define shizhong 20
module top_tb;

    reg clk2;
    reg rst_n2;
    reg in2;
    
    wire outflag2;
    wire outkey2;
    
			top u5(
				  .clk1(clk2),
				  .rst_n1(rst_n2),
				  .in1(in2),
				  .outflag1(outflag2),
                  .outkey1(outkey2)
				  );
    initial clk2 = 1;
    always#(`shizhong/2) clk2 = ~clk2;

	initial begin 
			rst_n2 = 1'b0;
			in2 = 1'b1;
			#(`shizhong*10);
			rst_n2 = 1'b1;
			
			//模拟出按键的抖动过程  按下抖动
			#(`shizhong*10 + 1);
			in2 = 0 ;
			#1000;
			in2 = 1 ;
			#2000;
			in2 = 0 ;
			#1400;
			in2 = 1 ;
			#2600;
			in2 = 0 ;
			#1300;
			in2 = 1 ;
			#200;
			
			in2 = 0 ;
			#2_000_000_000;   //按键稳定

			//释放时抖动
			in2 = 1 ;
			#2000;
			in2 = 0 ;
			#1000;
			in2 = 1 ;
			#2000;
			in2 = 0 ;
			#1000;
			in2 = 1 ;
			#2600;
			in2 = 0 ;
			#1300;
			
			in2 = 1 ;
			#2_000_000_000; //按键稳定松开

			$stop;		
	end
endmodule

V 前仿真

在这里插入图片描述

VI 后仿真

出不来 拉倒了

你可能感兴趣的:(FPGA从硬件描述到删核跑路)