按键的使用方法三:一键三用: 点击、长击和双击、

代码:

    /********************************Copyright**************************************
001 **----------------------------File information--------------------------
002 ** File name :key_function_3.v
003 ** CreateDate :2015.03
004 ** Funtions :按键的用法(三):一个按键完成单击,长击,双击的作用。
005 ** Operate on :M5C06N3L114C7
006 ** Copyright :All rights reserved.
007 ** Version :V1.0
008 **---------------------------Modify the file information----------------
009 ** Modified by :
010 ** Modified data :
011 ** Modify Content:
012 *******************************************************************************/ module key_function_3 (
clk,
rst_n, key_6, led_S,
led_L,
led_D );
input clk;
input rst_n; input key_6; output led_S;
output led_L;
output led_D; //--------------------------------------------
/* 定时:100ms,2s */
reg count_en;
localparam t_1s = 'd23999999;
localparam t_100ms = 'd2399999; // localparam t_1s = 25'd2399; /* //测试使用 */
// localparam t_100ms = 22'd239; /* //测试使用 */ localparam t_2s = 'd2; reg [:] count;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
count <= ;
end
else if(count_en)
begin
if(count == t_1s)
count <= ;
else
count <= count + ;
end
else
count <= ;
end reg [:] count1;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
count1 <= ;
end
else if(count_en)
begin
if(count1 == t_2s)
count1 <= 'd2;
else if(count == t_1s)
count1 <= count1 + ;
end
else
count1 <= ;
end //-------------------------------
/* 取key_6的上升沿和下降沿 */
reg [:] key_6_reg;
wire key_6_pos;
wire key_6_neg;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
key_6_reg <= 'b111;
end
else
begin
key_6_reg <= {key_6_reg[:],key_6};
end
end
assign key_6_pos = (key_6_reg[:] == 'b01);
assign key_6_neg = (key_6_reg[:] == 'b10); //------------------------------
/* 状态机 */
reg [:] state;
reg key_S;
reg key_L;
reg key_D;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
state <= 'd0;
count_en <= ;
key_S <= ;
key_L <= ;
key_D <= ;
end
else
begin
case(state)
'd0:
begin
count_en <= ;
key_S <= ;
key_L <= ;
key_D <= ;
if(key_6_neg) /* 按键按下 */
state <= 'd1;
else
state <= 'd0;
end
'd1:
begin
if(key_6_pos) /* 按键释放 */
begin
count_en <= ;
state <= 'd3;
end
else if((key_6_reg == 'b000)&&(count1 == t_2s)) /* 按键长击 */
begin
count_en <= ;
state <= 'd2;
key_L <= ;
end
else
count_en <= ;
end
'd2:
begin
key_L <= ;
if(key_6_pos)
state <= 'd7;
else
state <= 'd2;
end
'd3:
begin
state <= 'd4;
end
'd4: /* 决定单击还是双击 */
begin
if((key_6_neg)&&((count1 == )&&(count < t_100ms))) /* 双击 *//* 按键按下 */
begin
count_en <= ;
state <= 'd6;
key_D <= ;
end
else if((count1 == )&&(count > t_100ms)) /* 单击 */
begin
count_en <= ;
state <= 'd5;
key_S <= ;
end
else
count_en <= ;
end
'd5:
begin
state <= 'd8;
key_S <= ;
end
'd6:
begin
key_D <= ;
if(key_6_pos) /* 按键释放 */
state <= 'd8;
else
state <= 'd6;
end
'd8:
begin
state <= 'd0;
end
default:state <= 'd0;
endcase end
end reg [:] led;
always @(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
led <= 'b000;
end
else
begin
if(key_S)
led[]<= ~led[];
else if(key_L)
led[]<= ~led[];
else if(key_D)
led[]<= ~led[];
end
end //------------------------------
assign {led_D,led_L,led_S} = led; endmodule

难点:单击与双击的处理部分,状态机部分

测试代码

    /********************************Copyright**************************************
01 **----------------------------File information--------------------------
02 ** File name :key_function_testbench.v
03 ** CreateDate :2015.03
04 ** Funtions :按键功能的测试文件
05 ** Operate on :M5C06N3L114C7
06 ** Copyright :All rights reserved.
07 ** Version :V1.0
08 **---------------------------Modify the file information----------------
09 ** Modified by :
10 ** Modified data :
11 ** Modify Content:
12 *******************************************************************************/
`timescale ns/ ns
module key_function_3_tb;
reg clk;
reg rst_n; reg key_6; wire led_S;
wire led_L;
wire led_D; key_function_3 key_function_3_1(
.clk,
.rst_n, .key_6, .led_S,
.led_L,
.led_D ); parameter tck = ;
parameter t = /tck; always #(t/) clk = ~clk; initial
begin
clk = ;
rst_n = ;
key_6 = ; #(*t) rst_n = ; #(*t); /* 点击 */
#(*t) key_6 = ;
#(*t) key_6 = ;
#(*t) key_6 = ; /* 长击 */
#(*t);
#(*t) key_6 = ;
#(*t) key_6 = ;
#(*t);
#(*t) key_6 = ; /* 双击 */
#(*t);
#(*t) key_6 = ;
#(*t) key_6 = ;
#(*t) key_6 = ;
#(*t) key_6 = ;
#(*t) key_6 = ;
end endmodule

仿真波形

按键的使用方法(三)-------verilog-LMLPHP

注:参考资料来自网络。

05-11 16:54