按键的使用方法(三)-------verilog
按键的使用方法三:一键三用: 点击、长击和双击、
代码:
/********************************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 *******************************************************************************/ 013 014 module key_function_3 ( 015 clk, 016 rst_n, 017 018 key_6, 019 020 led_S, 021 led_L, 022 led_D 023 024 ); 025 input clk; 026 input rst_n; 027 028 input key_6; 029 030 output led_S; 031 output led_L; 032 output led_D; 033 034 //-------------------------------------------- 035 /* 定时:100ms,2s */ 036 reg count_en; 037 localparam t_1s = 25'd23999999; 038 localparam t_100ms = 22'd2399999; 039 040 // localparam t_1s = 25'd2399; /* //测试使用 */ 041 // localparam t_100ms = 22'd239; /* //测试使用 */ 042 043 localparam t_2s = 2'd2; 044 045 reg [24:0] count; 046 always @(posedge clk or negedge rst_n) 047 begin 048 if(!rst_n) 049 begin 050 count <= 0; 051 end 052 else if(count_en) 053 begin 054 if(count == t_1s) 055 count <= 0; 056 else 057 count <= count + 1; 058 end 059 else 060 count <= 0; 061 end 062 063 reg [1:0] count1; 064 always @(posedge clk or negedge rst_n) 065 begin 066 if(!rst_n) 067 begin 068 count1 <= 0; 069 end 070 else if(count_en) 071 begin 072 if(count1 == t_2s) 073 count1 <= 2'd2; 074 else if(count == t_1s) 075 count1 <= count1 + 1; 076 end 077 else 078 count1 <= 0; 079 end 080 081 //------------------------------- 082 /* 取key_6的上升沿和下降沿 */ 083 reg [2:0] key_6_reg; 084 wire key_6_pos; 085 wire key_6_neg; 086 always @(posedge clk or negedge rst_n) 087 begin 088 if(!rst_n) 089 begin 090 key_6_reg <= 3'b111; 091 end 092 else 093 begin 094 key_6_reg <= {key_6_reg[1:0],key_6}; 095 end 096 end 097 assign key_6_pos = (key_6_reg[2:1] == 2'b01); 098 assign key_6_neg = (key_6_reg[2:1] == 2'b10); 099 100 //------------------------------ 101 /* 状态机 */ 102 reg [2:0] state; 103 reg key_S; 104 reg key_L; 105 reg key_D; 106 always @(posedge clk or negedge rst_n) 107 begin 108 if(!rst_n) 109 begin 110 state <= 'd0; 111 count_en <= 0; 112 key_S <= 0; 113 key_L <= 0; 114 key_D <= 0; 115 end 116 else 117 begin 118 case(state) 119 'd0: 120 begin 121 count_en <= 0; 122 key_S <= 0; 123 key_L <= 0; 124 key_D <= 0; 125 if(key_6_neg) /* 按键按下 */ 126 state <= 'd1; 127 else 128 state <= 'd0; 129 end 130 'd1: 131 begin 132 if(key_6_pos) /* 按键释放 */ 133 begin 134 count_en <= 0; 135 state <= 'd3; 136 end 137 else if((key_6_reg == 3'b000)&&(count1 == t_2s)) /* 按键长击 */ 138 begin 139 count_en <= 0; 140 state <= 'd2; 141 key_L <= 1; 142 end 143 else 144 count_en <= 1; 145 end 146 'd2: 147 begin 148 key_L <= 0; 149 if(key_6_pos) 150 state <= 'd7; 151 else 152 state <= 'd2; 153 end 154 'd3: 155 begin 156 state <= 'd4; 157 end 158 'd4: /* 决定单击还是双击 */ 159 begin 160 if((key_6_neg)&&((count1 == 0)&&(count < t_100ms))) /* 双击 *//* 按键按下 */ 161 begin 162 count_en <= 0; 163 state <= 'd6; 164 key_D <= 1; 165 end 166 else if((count1 == 0)&&(count > t_100ms)) /* 单击 */ 167 begin 168 count_en <= 0; 169 state <= 'd5; 170 key_S <= 1; 171 end 172 else 173 count_en <= 1; 174 end 175 'd5: 176 begin 177 state <= 'd8; 178 key_S <= 0; 179 end 180 'd6: 181 begin 182 key_D <= 0; 183 if(key_6_pos) /* 按键释放 */ 184 state <= 'd8; 185 else 186 state <= 'd6; 187 end 188 'd8: 189 begin 190 state <= 'd0; 191 end 192 default:state <= 'd0; 193 endcase 194 195 end 196 end 197 198 reg [2:0] led; 199 always @(posedge clk or negedge rst_n) 200 begin 201 if(!rst_n) 202 begin 203 led <= 3'b000; 204 end 205 else 206 begin 207 if(key_S) 208 led[0]<= ~led[0]; 209 else if(key_L) 210 led[1]<= ~led[1]; 211 else if(key_D) 212 led[2]<= ~led[2]; 213 end 214 end 215 216 //------------------------------ 217 assign {led_D,led_L,led_S} = led; 218 219 endmodule 220 221 222 223 224
难点:单击与双击的处理部分,状态机部分
测试代码
/********************************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 *******************************************************************************/ 13 `timescale 1 ns/1 ns 14 module key_function_3_tb; 15 reg clk; 16 reg rst_n; 17 18 reg key_6; 19 20 wire led_S; 21 wire led_L; 22 wire led_D; 23 24 key_function_3 key_function_3_1( 25 .clk, 26 .rst_n, 27 28 .key_6, 29 30 .led_S, 31 .led_L, 32 .led_D 33 34 ); 35 36 parameter tck = 24; 37 parameter t = 1000/tck; 38 39 always #(t/2) clk = ~clk; 40 41 initial 42 begin 43 clk = 0; 44 rst_n = 0; 45 key_6 = 1; 46 47 #(100*t) rst_n = 1; 48 49 #(800*t); 50 51 52 /* 点击 */ 53 #(100*t) key_6 = 1; 54 #(300*t) key_6 = 0; 55 #(100*t) key_6 = 1; 56 57 /* 长击 */ 58 #(1000*t); 59 #(100*t) key_6 = 1; 60 #(300*t) key_6 = 0; 61 #(5000*t); 62 #(100*t) key_6 = 1; 63 64 65 /* 双击 */ 66 #(1000*t); 67 #(100*t) key_6 = 1; 68 #(300*t) key_6 = 0; 69 #(300*t) key_6 = 1; 70 #(100*t) key_6 = 0; 71 #(300*t) key_6 = 1; 72 end 73 74 endmodule 75
仿真波形
注:参考资料来自网络。