ISE 下按键消抖实验

编程入门 行业动态 更新时间:2024-10-23 12:25:24

ISE 下<a href=https://www.elefans.com/category/jswz/34/1768597.html style=按键消抖实验"/>

ISE 下按键消抖实验

实验原理

按键做为基本的人机输入接口,在很多电子设计中都能见到,由于机械特性,在按键按下或 松开的时候,按键输入值是有抖动的,无论按下去是多平稳,都难以消除抖动,按键消抖方式有 很多,本实验主要是通过 FPGA 计时来消抖。实验中设计了一个计数器,当按键输入有变化时, 计时器清零,否则就累加,直到加到一个预定值(例如 10ms),就认为按键稳定,输出按键值, 这样就得到以后没有抖动的按键值。由于在很多地方需要用到按键下降沿或上升沿的检测,按键 消抖模块直接集成了上升沿和下降沿检测的功能。

 程序设计 如下图所示,通过按键消抖后,在按键按下时,十进制计数器加 1,通过数码管译码扫描后 显示出来。

按键消抖部分的原理在上节已经讲过,按键消抖部分代码写的非常精炼,阅读起来稍显费解, 建议结合仿真波形去读代码。在提供的例程文件下的 sim 文件夹中同时提供了仿真文件,可以通 过添加仿真文件来进行仿真观察代码中信号的变化。

 

 

仿真

这里我们添加了一个串口接收的激励程序 key_debounce_tb.v 文件,用来仿真按键 key 的输入。 仿真的结果如下,我们看到按键一共有 5 次被按下,但是因为前面 4 次按键按下的低电平保持时 间都小于 20ms, 这 4 次的按下都被程序判断为抖动,只有第 5 次的按键按下时间大于了 20ms, 才 判断为按键有按下,这时 button_negedge 信号产生了一个脉冲。 

module count_m10(input          clk,input          rst_n,input          en,    //Counter enableinput          clr,   //Counter synchronous reset   output reg[3:0]data,  //counter valueoutput reg     t      // carry enable signal);
always@(posedge clk or negedge rst_n) 
beginif(rst_n==0)begindata <= 4'd0;t <= 1'd0;endelse if(clr)begindata <= 4'd0;t <= 1'd0;      endelse if(en)beginif(data==4'd9)begint<= 1'b1;    //Counter to 9 to generate carrydata <= 4'd0;//Counter to 9 resetendelsebegint <= 1'b0;data <= data + 4'd1;endendelset <= 1'b0;
endendmodule
`timescale 1 ns / 100 ps
module  ax_debounce 
(input       clk, input       rst, input       button_in,output reg  button_posedge,output reg  button_negedge,output reg  button_out
);---------------- internal constants --------------
parameter N = 32 ;           // debounce timer bitwidth
parameter FREQ = 50;         //model clock :Mhz
parameter MAX_TIME = 20;     //ms
localparam TIMER_MAX_VAL =   MAX_TIME * 1000 * FREQ;
---------------- internal variables ---------------
reg  [N-1 : 0]  q_reg;      // timing regs
reg  [N-1 : 0]  q_next;
reg DFF1, DFF2;             // input flip-flops
wire q_add;                 // control flags
wire q_reset;
reg button_out_d0;------------------------------------------------------contenious assignment for counter control
assign q_reset = (DFF1  ^ DFF2);          // xor input flip flops to look for level chage to reset counter
assign q_add = ~(q_reg == TIMER_MAX_VAL); // add to counter when q_reg msb is equal to 0combo counter to manage q_next 
always @ ( q_reset, q_add, q_reg)
begincase( {q_reset , q_add})2'b00 :q_next <= q_reg;2'b01 :q_next <= q_reg + 1;default :q_next <= { N {1'b0} };endcase     
endFlip flop inputs and q_reg update
always @ ( posedge clk or posedge rst)
beginif(rst == 1'b1)beginDFF1 <= 1'b0;DFF2 <= 1'b0;q_reg <= { N {1'b0} };endelsebeginDFF1 <= button_in;DFF2 <= DFF1;q_reg <= q_next;end
endcounter control
always @ ( posedge clk or posedge rst)
beginif(rst == 1'b1)button_out <= 1'b1;else if(q_reg == TIMER_MAX_VAL)button_out <= DFF2;elsebutton_out <= button_out;
endalways @ ( posedge clk or posedge rst)
beginif(rst == 1'b1)beginbutton_out_d0 <= 1'b1;button_posedge <= 1'b0;button_negedge <= 1'b0;endelsebeginbutton_out_d0 <= button_out;button_posedge <= ~button_out_d0 & button_out;button_negedge <= button_out_d0 & ~button_out;end	
end
endmodule
module key_debounce(input        clk,input        rst_n,input        key1,output [5:0] seg_sel,output [7:0] seg_data
);
wire button_negedge; //Key falling edge
ax_debounce ax_debounce_m0
(.clk             (clk),.rst             (~rst_n),.button_in       (key1),.button_posedge  ( ),.button_negedge  (button_negedge),.button_out      ()
);wire[3:0] count;
wire t0;
count_m10 count10_m0(.clk    (clk),.rst_n  (rst_n),.en     (button_negedge),.clr    (1'b0),.data   (count),.t      (t0)
);
wire[3:0] count1;
wire t1;
count_m10 count10_m1(.clk    (clk),.rst_n  (rst_n),.en     (t0),.clr    (1'b0),.data   (count1),.t      (t1)
);
//Count decoding
wire[6:0] seg_data_0;
seg_decoder seg_decoder_m0(.bin_data  (count),.seg_data  (seg_data_0)
);wire[6:0] seg_data_1;
seg_decoder seg_decoder_m1(.bin_data  (count1),.seg_data  (seg_data_1)
);
seg_scan seg_scan_m0(.clk        (clk),.rst_n      (rst_n),.seg_sel    (seg_sel),.seg_data   (seg_data),.seg_data_0 ({1'b1,7'b1111_111}),.seg_data_1 ({1'b1,7'b1111_111}),.seg_data_2 ({1'b1,7'b1111_111}),.seg_data_3 ({1'b1,7'b1111_111}),.seg_data_4 ({1'b1,seg_data_1}),.seg_data_5 ({1'b1,seg_data_0})
);
endmodule 
module seg_decoder
(input[3:0]      bin_data,     // bin data inputoutput reg[6:0] seg_data      // seven segments LED output
);always@(*)
begincase(bin_data)4'd0:seg_data <= 7'b100_0000;4'd1:seg_data <= 7'b111_1001;4'd2:seg_data <= 7'b010_0100;4'd3:seg_data <= 7'b011_0000;4'd4:seg_data <= 7'b001_1001;4'd5:seg_data <= 7'b001_0010;4'd6:seg_data <= 7'b000_0010;4'd7:seg_data <= 7'b111_1000;4'd8:seg_data <= 7'b000_0000;4'd9:seg_data <= 7'b001_0000;4'ha:seg_data <= 7'b000_1000;4'hb:seg_data <= 7'b000_0011;4'hc:seg_data <= 7'b100_0110;4'hd:seg_data <= 7'b010_0001;4'he:seg_data <= 7'b000_0110;4'hf:seg_data <= 7'b000_1110;default:seg_data <= 7'b111_1111;endcase
end
endmodule
module seg_scan(input           clk,input           rst_n,output reg[5:0] seg_sel,      //digital led chip selectoutput reg[7:0] seg_data,     //eight segment digital tube output,MSB is the decimal pointinput[7:0]      seg_data_0,input[7:0]      seg_data_1,input[7:0]      seg_data_2,input[7:0]      seg_data_3,input[7:0]      seg_data_4,input[7:0]      seg_data_5
);
parameter SCAN_FREQ = 200;     //scan frequency
parameter CLK_FREQ = 50000000; //clock frequencyparameter SCAN_COUNT = CLK_FREQ /(SCAN_FREQ * 6) - 1;reg[31:0] scan_timer;  //scan time counter
reg[3:0] scan_sel;     //Scan select counter
always@(posedge clk or negedge rst_n)
beginif(rst_n == 1'b0)beginscan_timer <= 32'd0;scan_sel <= 4'd0;endelse if(scan_timer >= SCAN_COUNT)beginscan_timer <= 32'd0;if(scan_sel == 4'd5)scan_sel <= 4'd0;elsescan_sel <= scan_sel + 4'd1;endelsebeginscan_timer <= scan_timer + 32'd1;end
end
always@(posedge clk or negedge rst_n)
beginif(rst_n == 1'b0)beginseg_sel <= 6'b111111;seg_data <= 8'hff;endelsebegincase(scan_sel)//first digital led4'd0:beginseg_sel <= 6'b11_1110;seg_data <= seg_data_0;end//second digital led4'd1:beginseg_sel <= 6'b11_1101;seg_data <= seg_data_1;end//...4'd2:beginseg_sel <= 6'b11_1011;seg_data <= seg_data_2;end4'd3:beginseg_sel <= 6'b11_0111;seg_data <= seg_data_3;end4'd4:beginseg_sel <= 6'b10_1111;seg_data <= seg_data_4;end4'd5:beginseg_sel <= 6'b01_1111;seg_data <= seg_data_5;enddefault:beginseg_sel <= 6'b11_1111;seg_data <= 8'hff;endendcaseend
endendmodule 
`timescale 1ns/1ns
module key_debounce_tb;
reg clk;
reg rst_n;
reg key1;
wire[5:0] seg_sel;
wire[7:0] seg_data;initial
beginclk = 1'b0;rst_n = 1'b0;key1 = 1'b1;#100 rst_n = 1'b1;#2000 key1 = 1'b0;#({$random} %1000)key1 = ~key1;#({$random} %1000)key1 = ~key1;#({$random} %1000)key1 = ~key1;#({$random} %1000)key1 = ~key1;	#({$random} %10000000)key1 = ~key1;#({$random} %10000000)key1 = ~key1;	#({$random} %10000000)key1 = ~key1;#({$random} %10000000)key1 = ~key1;#({$random} %10000000)key1 = ~key1;#({$random} %10000000)key1 = ~key1;#({$random} %10000000)key1 = ~key1;#({$random} %10000000)key1 = 1'b0;#1000000000key1 = 1'b1;#({$random} %10000000)key1 = ~key1;#({$random} %10000000)key1 = ~key1;	#({$random} %10000000)key1 = ~key1;#({$random} %10000000)key1 = ~key1;#({$random} %10000000)key1 = ~key1;#({$random} %10000000)key1 = ~key1;#({$random} %10000000)key1 = ~key1;#({$random} %10000000)key1 = 1'b1;#1000000000 key1 = 1'b0;#({$random} %1000)key1 = ~key1;#({$random} %1000)key1 = ~key1;#({$random} %1000)key1 = ~key1;#({$random} %1000)key1 = ~key1;	#({$random} %10000000)key1 = ~key1;#({$random} %10000000)key1 = ~key1;	#({$random} %10000000)key1 = ~key1;#({$random} %10000000)key1 = ~key1;#({$random} %10000000)key1 = ~key1;#({$random} %10000000)key1 = ~key1;#({$random} %10000000)key1 = ~key1;#({$random} %10000000)key1 = 1'b0;#1000000000key1 = 1'b1;#({$random} %10000000)key1 = ~key1;#({$random} %10000000)key1 = ~key1;	#({$random} %10000000)key1 = ~key1;#({$random} %10000000)key1 = ~key1;#({$random} %10000000)key1 = ~key1;#({$random} %10000000)key1 = ~key1;#({$random} %10000000)key1 = ~key1;#({$random} %10000000)key1 = 1'b1;#10 $stop;end
always#10 clk = ~clk;//50Mhzkey_debounce dut(.clk     (clk),.rst_n   (rst_n),.key1    (key1),.seg_sel (seg_sel),.seg_data(seg_data)
);
endmodule 

更多推荐

ISE 下按键消抖实验

本文发布于:2023-06-27 08:19:18,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/908680.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:按键   ISE

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!