差别

这里会显示出您选择的修订版和当前版本之间的差别。

到此差别页面的链接

两侧同时换到之前的修订记录 前一修订版
后一修订版
前一修订版
后一修订版 两侧同时换到之后的修订记录
8._计时控制 [2017/03/23 00:56]
zhijun
8._计时控制 [2017/04/03 21:04]
zhijun
行 30: 行 30:
 // V1.0     ​|2017/​03/​02 ​  ​|Initial ver // V1.0     ​|2017/​03/​02 ​  ​|Initial ver
 // -------------------------------------------------------------------- // --------------------------------------------------------------------
-// Module Function:按键消抖+// Module Function:计时器
  
-module ​debounce ​(clk,rst,key,key_pulse);+module ​segment_counter 
 +( 
 + clk , 
 + rst , 
 + hold , 
 + seg_led_1 ,​ 
 + seg_led_2 ,​ 
 +);
  
-        parameter ​      ​N ​ =  1                     //​要消除的按键的数量+ input clk,rst; 
 + input hold;
  
- input             clk+ output reg [8:​0] seg_led_1,​seg_led_2
-        ​input ​            rst+  
-        input [N-1:0]   key                       //​输入的按键  + reg clk_divided
- output  ​[N-1:0]   key_pulse                 //​按键动作产生的脉冲  + reg hold_flag;​ 
-        ​ + reg back_to_zero_flag = 0;​ 
-        reg     ​[N-1:0]   key_rst_pre               //​定义一个寄存器型变量存储上一个触发时的按键值 + reg    [6:0]   seg [9:0]  
-        reg     ​[N-1:0]   key_rst                   //定义一个寄存器变量储存储当前时刻触发的按键值 + reg [23:0] cnt
-         + reg [3:0] cnt_ge
-        ​wire ​   [N-1:0  key_edge                  ​//检测到按键由高到低变化是产生一个高脉冲 + reg [3:0] cnt_shi; 
-         +  
-        //利用非阻塞赋值特点,将两个时钟触发时按键状态存储在两个寄存器变量中 + parameter PERIOD=6000000; //1秒 
-        ​always @(posedge clk  or  negedge rst) +  
-          begin + initial  
-             if (!rst) begin + begin 
-                 ​key_rst <{N{1'b1}}               //初始化时给key_rst赋值全为1,{}中表示N个1 + seg[0] = 7'​h3f;​    //  0 
-                 key_rst_pre <{N{1'b1}}+ seg[1] = 7'h06;    //  1 
-             end + seg[2] = 7'​h5b;​  ​  // ​ 2 
-             else begin + seg[3] = 7'​h4f;​  ​  //  3 
-                 ​key_rst <key                    ​//第一个时钟上升沿触发之后key的值赋给key_rst,同时key_rst的值赋给key_rst_pre + seg[4] = 7'​h66;​  ​  // ​ 
-                 key_rst_pre <key_rst            ​//非阻塞赋值。相当于经过两个时钟触发,key_rst存储的是当前时刻key的值,key_rst_pre存储的是前一个时钟的key的值 + seg[5] = 7'​h6d;​  ​  // ​ 5 
-             end     + seg[6] = 7'​h7d;​  ​  // ​ 6 
-           end + seg[7] ​7'h07;    //  7 
-            + seg[8] ​7'h7f;    // ​ 8 
-        assign ​ key_edge ​key_rst_pre & (~key_rst);//脉冲边沿检测。当key检测到下降沿时,key_edge产生一个时钟周期的高电平 + seg[9] ​7'h6f;    //  9 
-         +/​*若需要显示A-F,解除此段注释即可 
-        reg [17:0]   cnt                      ​//产生延时所用的计数器,系统时钟12MHz,要延时20ms左右时间,至少需要18位计数器 ​     + seg[10]7'hf7;    //  A 
-         + seg[11]= 7'​h7c;​    //  b 
-        ​//产生20ms延时,当检测到key_edge有效是计数器清零开始计数 + seg[12]= 7'​h39; ​   //  
-        always @(posedge clk or negedge rst) + seg[13]7'h5e   //  d 
-           begin + seg[14]= 7'h79   //  E 
-             ​if(!rst) + seg[15]= 7'​h71; ​   ​//  F*/ 
-                cnt <= 18'h0+ end 
-             else if(key_edge) +  
-                cnt <= 18'h0+ always @ (posedge clk) begin // 用于分出一个1Hz的频率 
-             ​else + if (!rst == 1begin 
-                cnt <= cnt + 1'h1+ cnt <= 0
-             end   + clk_divided ​<= 0end 
-        ​ + else begin 
-        ​reg ​    [N-1:0]   ​key_sec_pre               //​延时后检测电平寄存器变量 + if (cnt < PERIOD-1) 
-        ​reg ​    ​[N-1:​0] ​  ​key_sec                    + cnt <= cnt + 1; 
-         + else begin 
-                     ​ + cnt <= 0; 
-        //​延时后检测key,如果按键状态变低产生一个时钟的高脉冲。如果按键状态是高的话说明按键无效 + clk_divided <= ~clk_dividedend 
-        always @(posedge clk  or  negedge rst) + end 
-          ​begin + end 
-             ​if (!rst)  +  
-                 key_sec ​<= {N{1'b1}}                + always @ (*) begin 
-             ​else if (cnt==18'​h3ffff+ if (!rst == 1
-                 key_sec ​<= key  + back_to_zero_flag ​<= 1; 
-          end + else if (((cnt_shi*10) + cnt_ge)==24
-       ​always @(posedge ​clk  ​or  ​negedge rst+ back_to_zero_flag ​<= 1
-          begin + else 
-             ​if (!rst+ back_to_zero_flag <= 0; 
-                 key_sec_pre ​<= {N{1'b1}}+ end 
-             ​else                   ​ +  
-                 key_sec_pre ​<= key_sec            ​ + always @ (posedge ​hold) 
-             end    ​ + hold_flag <= ~hold_flag;​ 
-           ​end       +  
-       assign ​ key_pulse ​key_sec_pre & (~key_sec);     ​ + always @ (posedge clk_divided ​or posedge back_to_zero_flagbegin 
-       ​ + if (back_to_zero_flag == 1) begin 
-endmodule ​+ cnt_ge <= 0; 
 + cnt_shi <= 0; end 
 + else ​if (cnt_ge == 9begin 
 + cnt_ge ​<= 0; 
 + cnt_shi <= cnt_shi + 1; end 
 + else if (hold_flag == 1) 
 + cnt_ge ​<= cnt_ge
 + else 
 + cnt_ge <= cnt_ge + 1; 
 + end 
 +  
 + always @ (cnt_ge) begin 
 + seg_led_1[8:​0] <{2'​b00,​seg[cnt_ge]};​ 
 + end 
 + 
 + always @ (cnt_shibegin 
 + seg_led_2[8:​0] <= {2'​b00,​seg[cnt_shi]}
 +  ​ end 
 +  
 +endmodule
  
 </​code>​ </​code>​
行 102: 行 129:
 \\ \\
  
-以上就是一个N位按键的消抖程序,如果有按键按下会输出一个时钟周期的高脉冲。下面我们可以试试用这个按键消抖的输出来触发LED的显示,既按键一次LED翻转。你也可以不加按键消抖试试用按键来控制LED(按一次变亮,再按一次灭掉)。 
- 
-\\ 
-下面的程序是例化调用debounce模块来控制LED 
-\\ 
-<code verilog> 
-// ******************************************************************** 
-// >>>>>>>>>>>>>>>>>>>>>>>>>​ COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<<​ 
-// ******************************************************************** 
-// File name    : top.v 
-// Module name  : top 
-// Author ​      : STEP 
-// Description ​ :  
-// Web          : www.stepfpga.com 
-//  
-// -------------------------------------------------------------------- 
-// Code Revision History :  
-// -------------------------------------------------------------------- 
-// Version: |Mod. Date:   ​|Changes Made: 
-// V1.0     ​|2017/​03/​02 ​  ​|Initial ver 
-// -------------------------------------------------------------------- 
-// Module Function:​进过按键消抖后控制led显示翻转 
- 
-module top (clk,​rst,​key,​led);​ 
- 
-        input             clk; 
-        input             rst; 
-        input           key;                       
- output ​  ​reg ​     led;        ​ 
- 
-        wire              key_pulse; 
-        ​ 
-        //​当按键按下时产生一个高脉冲,翻转一次led 
-        always @(posedge clk  or  negedge rst) 
-           begin 
-             if (!rst) ​ 
- led <= 1'b1; 
-      else if (key_pulse) 
- led <= ~led; 
-      else 
-                led <= led; 
-    ​end ​   ​ 
-         //​例化消抖module,这里没有传递参数N,采用了默认的N=1 ​     
-         ​debounce ​ u1 (                                
-                       .clk (clk), 
-                       .rst (rst), 
-                       .key (key), 
-                       ​.key_pulse (key_pulse) 
-                       ); 
- ​endmodule 
-</​code>​ 
- 
-\\ 
 ====引脚分配==== ====引脚分配====
 ------- -------
行 162: 行 136:
 |clk             ​|C1 ​              ^ |clk             ​|C1 ​              ^
 |rst             ​|L14 ​             ^ |rst             ​|L14 ​             ^
-|key             |N14             +|hold            ​|M13              ​
-|led             |N13              ^ +|seg_led_1[0] ​   ​|C12              ^ 
 +|seg_led_1[1] ​   |B14              ^ 
 +|seg_led_1[2] ​   |J1              ^ 
 +|seg_led_1[3] ​   |H1              ^ 
 +|seg_led_1[4] ​   |H2              ^ 
 +|seg_led_1[5] ​   |B12              ^ 
 +|seg_led_1[6] ​   |A11              ^ 
 +|seg_led_1[7] ​   |K1              ^ 
 +|seg_led_1[8] ​   |A12              ^ 
 +|seg_led_2[0] ​   |A10              ^ 
 +|seg_led_2[1] ​   |C11              ^ 
 +|seg_led_2[2] ​   |F2               ^ 
 +|seg_led_2[3] ​   |E1               ^ 
 +|seg_led_2[4] ​   |E2               ^ 
 +|seg_led_2[5] ​   |A9               ^ 
 +|seg_led_2[6] ​   |B9               ^ 
 +|seg_led_2[7] ​   |F1               ^ 
 +|seg_led_2[8] ​   |C9               ^
 ====小结==== ====小结====
 ------ ------
-本实验学习如何进按键消抖在很多应用情况下我们必须采取消抖才能更好地控制逻辑。在下一个实验[[8计时控制|计时控制]]中我们将学习计时的显示和控制,在这里我们要用到按键的消抖以及数码管,我们甚至可以用小脚丫做一个计时器甚至电子表+本实验主要介绍计时器的实现方式,并且包含了复位与暂停功能,读者可自修改程序内部时钟参数来调节计时时间下一节将介绍PWM调制技术的应用[[9呼吸灯|呼吸灯]]。