verilog的键盘源码keypad—有去抖功能
2012-06-02
标签: 键盘

下面是转的一个源码,俺没有细看,有兴趣的看看,讲讲如何

// author: Dandy Nee

// mail:dandynee@yeah.net

// module: HW KeyScan Module

// version:0.1

// **************************

// all functions are provided as if okay

// run at your own risk

// **************************

//

// problem:there is one keyvalue valid

//indicator signal needed

//

//------------------------------------------------

//

//^ ^ ^ ^ Pull Up

//| | | |

// x0 >--|--|--|--|-

// x1 >--|--|--|--|-

// x2 >--|--|--|--|-

// x3 >--|--|--|--|-

// y0 <--+ | | |

// y1 <-----+ | |

// y2 <--------+ |

// y3 <-----------+

//

module m_keyscan(

clk,//system clk

rstb,//system a-rst, low active

//

clkdiv,//clock divide coef

//

keyvalue,//returned key

//

x,//x-row scan out

y//y-col scan in

);

inputclk, rstb;

input[19:0] clkdiv;

output [15:0] keyvalue;

output [3:0]x;

input[3:0]y;

reg [19:0] cnt;

always @(posedge clk or negedge rstb)

if(~rstb)

cnt<=0;

else

cnt <= cnt==clkdiv ? 0 : cnt+1;

reg clken;

always @(posedge clk or negedge rstb)

if(~rstb)

clken <= 0;

else

clken <= cnt==clkdiv;

reg [2:0]fsm;

always @(posedge clk or negedge rstb)

if(~rstb)

fsm <= 0;

else if(clken)

fsm <= fsm+1;//8 states

reg [15:0] keyvalue;

reg [3:0]x;

always @(posedge clk or negedge rstb)

if(~rstb)

keyvalue <= 0;

else if(clken)

case(fsm)

0: begin

x <= 4'b1110;

end

1: begin

keyvalue[3:0] <= ~y;

end

2: begin

x <= 4'b1101;

end

3: begin

keyvalue[7:4] <= ~y;

end

4: begin

x <= 4'b1011;

end

5: begin

keyvalue[11:8] <= ~y;

end

6: begin

x <= 4'b0111;

end

7: begin

keyvalue[15:12] <= ~y;

end

endcase

endmodule

本程序做的只是按键单纯挂在IO上,并不是行列扫描的。

其消抖原理:就是采用100hz作为键盘采样的时钟,作一个8bit的reg,采用移位,当按键有效时,即8bit的reg全部为1时,进行动作。两次连续按键之间的时间间隔可以设定(这个是我根据按键感觉加进去的), 下面是我用来测试的源码,调试过的。用FPGA做的。

module key_delay

(

// {{ALTERA_ARGS_BEGIN}} DO NOT REMOVE THIS LINE!

clk, key_in, rst, led

// {{ALTERA_ARGS_END}} DO NOT REMOVE THIS LINE!

);

// Port Declaration

// {{ALTERA_IO_BEGIN}} DO NOT REMOVE THIS LINE!

input clk;

input [1:0] key_in;

input rst;

output [3:0] led;

// {{ALTERA_IO_END}} DO NOT REMOVE THIS LINE!

reg [17:0] counter ;

reg [3:0] led ;

reg key_clk ;

always @(negedge rst or posedge clk)

if(!rst)

begin

counter <= 0 ;

key_clk <= 0 ;

end

else begin

if(counter >= 250000) //分出用于键盘的时钟为100hz , 需要时钟速度较高时采用流水线

begin

counter <= 0;

key_clk <= ~key_clk ;

end

else counter <= counter + 1 ;

end

reg [1:0] key_reg ; //提取分频后的键盘的时钟上升沿

always @(negedge rst or posedge clk)

if(!rst)

key_reg <= 0 ;

else key_reg <= {key_reg[0] ,key_clk } ;

wire key_all = &key_in ;

reg [7:0] shift_reg ;

reg [3:0] key_interval ;

always @(negedge rst or posedge clk)

if(!rst)

begin

shift_reg <= 0 ;

key_interval <='b_1111 ;

end

else begin

if(key_reg == 2'b01)

begin

if(shift_reg == 8'b1111_1111) //一次有效的按键

begin

shift_reg <= 0 ;

key_interval <= 0;

end

else

begin

if(key_interval =='b_1111 ) //连续按键的时间间隔(可根据需要修改)

shift_reg <= {shift_reg[6:0] , (~key_all)} ;

else key_interval <= key_interval + 1 ; //每次有效的按键后都要用计数器,计数等待。

end

end

end

always @(negedge rst or posedge clk) //用于测试按键的程序 ,通过LED移位来显示

if(!rst)

led <= 2'b01;

else

begin

if(key_reg == 2'b01)

begin

if(shift_reg == 8'b1111_1111)

begin

case(key_in)

2'b01: led <= {led[2:0] ,led[3]};

2'b10: led <= {led[0] ,led[3:1]} ;

default : led <= 4'bxxxx;

endcase

end

end

end

endmodule

可能会用到的工具/仪表
本站简介 | 意见建议 | 免责声明 | 版权声明 | 联系我们
CopyRight@2024-2039 嵌入式资源网
蜀ICP备2021025729号