按键使用方法(二)------verilog

这里我们要验证一键两用的情况:点击与长击,单击与双击

  代码:

 

    /********************************Copyright**************************************                           
    **----------------------------File information--------------------------
    ** File name  :key_function_2.v  
    ** CreateDate :2015.03
    ** Funtions   :按键的用法(二):点击和长击,单击和双击
    ** Operate on :M5C06N3L114C7
    ** Copyright  :All rights reserved. 
    ** Version    :V1.0
    **---------------------------Modify the file information----------------
    ** Modified by   :
    ** Modified data :        
    ** Modify Content:
    *******************************************************************************/
     
001     module  key_function_2  (
002                                         clk,
003                                         rst_n,
004                       
005                                         key_4,
006                                         key_5,
007                                         
008                                         led_d41,
009                                         led_d42,
010                                         led_d51,
011                                         led_d52
012                                         
013                                             );
014     input          clk;
015     input          rst_n;
016     
017     input          key_4;                 //按键的点击与长击:按下按键后,2S内松开按键则为点击,2s后松开按键为长击,默认未按下为高。
018     input          key_5;                /*按键的单击和双击,完成第一次按键后100ms之内第二次按下按键则为双击,否则为单击    */  
019     
020     output         led_d41;
021     output         led_d42;
022     output         led_d51;
023     output         led_d52;
024     
025     //---------------------------
026     //定时2s
027     reg              cnt_en;
028     localparam  t_1s = 25'd23999999;        /* //实际使用 */  
029    // localparam  t_1s = 25'd239;           /* //测试使用 */
030        
031     localparam  t_2s = 2'd2;
032     reg      [24:0]      cnt;
033     always @(posedge clk or negedge rst_n)
034     begin
035      if(!rst_n)
036       begin
037            cnt <= 0;
038        end
039      else if(cnt_en)
040        begin
041           if(cnt == t_1s)
042                     cnt <= 0;
043                else 
044                    cnt <= cnt + 1;
045        end
046       else
047              cnt <= 0;    
048      end
049     
050     reg     [1:0]   cnt1;
051     always @(posedge clk or negedge rst_n)
052     begin
053      if(!rst_n)
054       begin
055           cnt1 <= 0;
056        end
057      else if(cnt_en)
058        begin
059             if(cnt1 == 2'd2)
060                 cnt1 <= 2'd2;
061             else if(cnt == t_1s)
062                  cnt1 <= cnt1 + 1;
063        end
064       else
065              cnt1 <= 0;
066      end
067        
068     //-------------------------------
069     /* 取key_4的上升沿和下降沿   */
070     reg    [2:0]    key_4_reg;
071     wire            key_4_pos;
072     wire            key_4_neg;
073     always @(posedge clk or negedge rst_n)
074     begin
075      if(!rst_n)
076       begin
077           key_4_reg  <= 3'b111;
078        end
079      else 
080        begin
081           key_4_reg  <= {key_4_reg[1:0],key_4};
082        end
083      end
084        assign  key_4_pos = (key_4_reg[2:1] == 2'b01);
085        assign  key_4_neg = (key_4_reg[2:1] == 2'b10);
086     
087     //------------------------------
088     /*  状态机 */
089      reg   [2:0]   state1;
090      reg           key_S;
091        reg           key_L;
092        always @(posedge clk or negedge rst_n)
093         begin
094          if(!rst_n)
095           begin
096               state1 <= 'd0;
097                     cnt_en <= 0;
098                     key_S <= 0;
099                     key_L <= 0;
100            end
101          else 
102            begin
103              case(state1)
104                     'd0:
105                        begin
106                              cnt_en <= 0;
107                                key_S  <= 0;
108                          key_L  <= 0;
109                          if(key_4_neg)          /* 按键按下  */ 
110                                  state1 <= 'd1;
111                                else
112                                    state1 <= 'd0;
113                         end
114                        'd1:
115                          begin
116                                if(key_4_pos)            /* 按键释放   */
117                                    begin
118                                        cnt_en <= 0;    
119                                        state1 <= 'd2;
120                                        key_S  <= 1;  
121                                     end
122                                else if((key_4_reg==3'b000)&&(cnt1 == 2'd2))   /* 按键一直为低,延时2s之后  */
123                                    begin
124                                        cnt_en <= 0;    
125                                        state1 <= 'd3;
126                                        key_L  <= 1;
127                                     end
128                                else 
129                                   cnt_en <= 1;                                    
130                                end
131                     'd2:                       /* 点击   */ 
132                        begin
133                                key_S  <= 0;  
134                                  state1 <= 'd5;
135                                end
136                     'd3:
137                        begin
138                   key_L  <= 0;
139                                 state1 <= 'd4;
140                                end
141                        'd4:
142                          begin
143                                if(key_4_pos)
144                                 state1 <= 'd5; 
145                                 else
146                                     state1 <= 'd4;
147                                end
148                        'd5:
149                          begin
150                                    state1 <= 'd0;
151                                end                            
152                      default:state1 <= 'd0;
153                    endcase
154                    
155            end
156          end
157            
158     reg        led_s;
159     reg        led_l;
160     always @(posedge clk or negedge rst_n)
161     begin
162      if(!rst_n)
163       begin
164          led_s <= 0;
165        end
166      else if(key_S)
167        begin
168          led_s <= ~led_s;
169        end
170      end
171        
172     always @(posedge clk or negedge rst_n)
173     begin
174      if(!rst_n)
175       begin
176          led_l <= 0;
177        end
178      else if(key_L)
179        begin
180          led_l <= ~led_l;
181        end
182      end 
183     
184    //------------------------------------ 
185     localparam  t_100ms = 22'd2399999;          /* //实际使用 */  
186    // localparam  t_100ms = 22'd23;          /* //测试使用 */
187     reg     [21:0]     cnnt;
188     reg                cnnt_en;
189     always @(posedge clk or negedge rst_n)
190     begin
191      if(!rst_n)
192       begin
193         cnnt <= 0;
194        end
195      else  if(cnnt_en)
196        begin
197          if(cnnt == t_100ms )
198                   cnnt <= t_100ms;
199                else 
200                     cnnt <= cnnt + 1;
201        end
202        else 
203             cnnt <= 0;
204      end
205    //-------------------------------
206     /* 取key_5的上升沿和下降沿   */
207     reg    [2:0]    key_5_reg;
208     wire            key_5_pos;
209     wire            key_5_neg;
210     always @(posedge clk or negedge rst_n)
211     begin
212      if(!rst_n)
213       begin
214           key_5_reg  <= 3'b111;
215        end
216      else 
217        begin
218           key_5_reg  <= {key_5_reg[1:0],key_5};
219        end
220      end
221        assign  key_5_pos = (key_5_reg[2:1] == 2'b01);
222        assign  key_5_neg = (key_5_reg[2:1] == 2'b10);
223        
224     //------------------------------
225     /*  状态机 */
226      reg   [2:0]   state2;
227      reg           key_SS;
228        reg           key_D;
229        always @(posedge clk or negedge rst_n)
230         begin
231          if(!rst_n)
232           begin
233               state2 <= 'd0;
234                     cnnt_en <= 0;
235                     key_SS <= 0;
236                     key_D <= 0;
237            end
238          else 
239            begin
240              case(state2)
241                     'd0:
242                        begin
243                              cnnt_en <= 0;
244                                key_SS  <= 0;
245                          key_D  <= 0;
246                          if(key_5_neg)          /*第一次 按键按下  */ 
247                                  state2 <= 'd1;
248                                else
249                                    state2 <= 'd0;
250                         end
251                        'd1:
252                          begin
253                              if(key_5_pos)            /*第一次 按键释放   */     
254                                  begin
255                                        state2 <= 'd2;    
256                                     end
257                               else     
258                                    state2 <= 'd1;     
259                            end
260                        'd2:
261                          begin
262                                if((key_5_neg)&&(cnnt < t_100ms))    
263                                    begin
264                                        cnnt_en <= 0;    
265                                        state2 <= 'd3;
266                                        key_D  <= 1; 
267                                    end
268                                else if(cnnt ==t_100ms)    
269                                  begin
270                                        cnnt_en <= 0;    
271                                        state2 <= 'd4;
272                                        key_SS  <= 1;                                            
273                                        end
274                                else 
275                                    cnnt_en <= 1;    
276                                end
277                        'd3: 
278                          begin
279                                key_D  <= 0;     
280                                if(key_5_pos)    
281                                    state2 <= 'd5;   
282                                end
283                        'd4: 
284                          begin                
285                                key_SS  <= 0;    
286                                state2 <= 'd5;
287                          end
288                        'd5:
289                          begin
290                                 state2 <= 'd0;    
291                                end                        
292                      default:state2 <= 'd0;
293                    endcase
294                    
295            end
296          end
297            
298     reg        led_signal;
299     reg        led_double;
300     always @(posedge clk or negedge rst_n)
301     begin
302      if(!rst_n)
303       begin
304          led_signal <= 0;
305        end
306      else if(key_SS)
307        begin
308          led_signal <= ~led_signal;
309        end
310      end
311        
312     always @(posedge clk or negedge rst_n)
313     begin
314      if(!rst_n)
315       begin
316          led_double <= 0;
317        end
318      else if(key_D)
319        begin
320          led_double <= ~led_double;
321        end
322      end 
323        
324     //------------------------
325      assign led_d41 = led_s;
326        assign led_d42 = led_l; 
327      assign led_d51 = led_signal;
328        assign led_d52 = led_double;    
329     
330     endmodule
331
332
333     
View Code

 

仿真代码:

  

    /********************************Copyright**************************************                           
    **----------------------------File information--------------------------
    ** File name  :key_function_testbench.v  
    ** CreateDate :2015.03
    ** Funtions   :按键功能的测试文件
    ** Operate on :M5C06N3L114C7
    ** Copyright  :All rights reserved. 
    ** Version    :V1.0
    **---------------------------Modify the file information----------------
    ** Modified by   :
    ** Modified data :        
    ** Modify Content:
    *******************************************************************************/
001    `timescale 1 ns/1 ns
002
003    module  key_function_2_tb;
004     reg          clk;
005     reg          rst_n;
006     
007     reg          key_4;                 //按键的点击与长击:按下按键后,2S内松开按键则为点击,2s后松开按键为长击,默认未按下为高。
008     reg          key_5;                /*按键的单击和双击,完成第一次按键后100ms之内第二次按下按键则为双击,否则为单击    */  
009     
010     wire         led_d41;
011     wire         led_d42;
012     wire         led_d51;
013     wire         led_d52;
014     
015     
016    key_function_2   key_function_2(
017                                                             .clk,
018                                                             .rst_n,
019                                                             
020                                                             .key_4,
021                                                             .key_5,
022                                                             
023                                                             .led_d41,
024                                                             .led_d42,
025                                                             .led_d51,
026                                                             .led_d52
027                                                             
028                                                                 );
029     
030     parameter  tck = 24;
031    parameter  t = 1000/tck;
032
033    always  #(t/2)   clk = ~clk;
034
035        initial 
036            begin
037          clk = 0;
038                rst_n = 0;
039                key_4 = 1;
040                key_5 = 1;
041                
042              #(100*t)  rst_n = 1;
043                /* 点击 */
044                #(100*t)  key_4 = 1;
045              #(60*t)   key_4 = 0;
046                #(100*t)  key_4 = 1;
047                
048                /* 长击 */
049                #(100*t);
050                #(100*t)  key_4 = 1;
051              #(60*t)   key_4 = 0;
052                #(1000*t);
053                #(100*t)  key_4 = 1;
054                
055                /* 单击 */
056                #(2000*t);
057                #(100*t)  key_5 = 1;
058              #(300*t)   key_5 = 0;
059                #(100*t)  key_5 = 1;
060                
061                
062                /* 双击 */
063                #(2000*t);
064                #(100*t)  key_5 = 1;
065              #(300*t)  key_5 = 0;
066                #(300*t)  key_5 = 1;
067                #(10*t)   key_5 = 1;
068              #(10*t)   key_5 = 0;
069                #(300*t)  key_5 = 1;
070                
071                
072            end
073            
074        endmodule 
075                
076
View Code

 

仿真波形:

1、点击与长击

 

 

2、单击与双击

  

 

注:参考资料来自网络。

 

posted @ 2015-03-26 11:26  远航路上ing  阅读(1211)  评论(0编辑  收藏  举报