差别
这里会显示出您选择的修订版和当前版本之间的差别。
两侧同时换到之前的修订记录 前一修订版 后一修订版 | 前一修订版 | ||
8._计时控制 [2017/03/23 01:00] zhijun |
8._计时控制 [2019/09/06 11:53] (当前版本) gongyu |
||
---|---|---|---|
行 1: | 行 1: | ||
- | =====计时控制===== | + | ####计时控制 |
+ | |||
+ | --- | ||
在之前的实验中我们掌握了如何进行时钟分频、如何进行数码管显示与按键消抖的处理,那么在本节实验之中,我们将会实现一个篮球赛场上常见的24秒计时器。 | 在之前的实验中我们掌握了如何进行时钟分频、如何进行数码管显示与按键消抖的处理,那么在本节实验之中,我们将会实现一个篮球赛场上常见的24秒计时器。 | ||
+ | |||
\\ | \\ | ||
- | ====硬件说明==== | + | |
- | ------- | + | ####硬件说明 |
+ | |||
+ | --- | ||
在之前的实验中我们为读者详细介绍过小脚丫MXO2板卡上的按键、数码管、LED等硬件外设,在此不再赘述。本节将实现由数码管作为显示模块,按键作为控制信号的输入(包含复位信号和暂停信号),Lattice MXO2 4000HC作为控制核心的篮球读秒系统,实现框图如下: | 在之前的实验中我们为读者详细介绍过小脚丫MXO2板卡上的按键、数码管、LED等硬件外设,在此不再赘述。本节将实现由数码管作为显示模块,按键作为控制信号的输入(包含复位信号和暂停信号),Lattice MXO2 4000HC作为控制核心的篮球读秒系统,实现框图如下: | ||
行 10: | 行 17: | ||
\\ | \\ | ||
- | ====Verilog代码==== | + | ####Verilog代码 |
- | ------ | + | |
+ | --- | ||
<code verilog> | <code verilog> | ||
行 18: | 行 26: | ||
// >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<< | // >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<< | ||
// ******************************************************************** | // ******************************************************************** | ||
- | // File name : debounce.v | + | // File name : counter.v |
- | // Module name : debounce | + | // Module name : counter |
// Author : STEP | // Author : STEP | ||
// Description : | // Description : | ||
行 30: | 行 38: | ||
// V1.0 |2017/03/02 |Initial ver | // V1.0 |2017/03/02 |Initial ver | ||
// -------------------------------------------------------------------- | // -------------------------------------------------------------------- | ||
- | // Module Function:计时器 | + | // Module Function:24秒倒计时计数器 |
- | + | ||
- | module segment_counter | + | module counter |
( | ( | ||
- | clk , | + | clk , //时钟 |
- | rst , | + | rst , //复位 |
- | hold , | + | hold , //启动暂停按键 |
- | seg_led_1 , | + | seg_led_1 , //数码管1 |
- | seg_led_2 , | + | seg_led_2 , //数码管2 |
+ | led //led | ||
); | ); | ||
+ | |||
input clk,rst; | input clk,rst; | ||
input hold; | input hold; | ||
- | + | ||
- | output reg [8:0] seg_led_1,seg_led_2; | + | output [8:0] seg_led_1,seg_led_2; |
- | + | output reg [7:0] led; | |
- | reg clk_divided; | + | |
- | reg hold_flag; | + | wire clk1h; //1Hz时钟 |
- | reg back_to_zero_flag = 0; | + | wire hold_pulse; //按键消抖后信号 |
+ | reg hold_flag; //按键标志位 | ||
+ | reg back_to_zero_flag ; //计时完成信号 | ||
reg [6:0] seg [9:0]; | reg [6:0] seg [9:0]; | ||
- | reg [23:0] cnt; | + | reg [3:0] cnt_ge; //个位 |
- | reg [3:0] cnt_ge; | + | reg [3:0] cnt_shi; //十位 |
- | reg [3:0] cnt_shi; | + | |
- | + | ||
- | parameter PERIOD=12000000; //1秒 | + | |
- | + | ||
initial | initial | ||
begin | begin | ||
行 77: | 行 85: | ||
end | end | ||
- | always @ (posedge clk) begin // 用于分出一个1Hz的频率 | + | |
- | if (!rst == 1) begin | + | |
- | cnt <= 0; | + | // 启动/暂停按键进行消抖 |
- | clk_divided <= 0; end | + | debounce U2 ( |
- | else begin | + | .clk(clk), |
- | if (cnt < PERIOD-1) | + | .rst(rst), |
- | cnt <= cnt + 1; | + | .key(hold), |
- | else begin | + | .key_pulse(hold_pulse) |
- | cnt <= 0; | + | ); |
- | clk_divided <= ~clk_divided; end | + | // 用于分出一个1Hz的频率 |
- | end | + | divide #(.WIDTH(32),.N(12000000)) U1 ( |
- | end | + | .clk(clk), |
- | + | .rst_n(rst), | |
- | always @ (*) begin | + | .clkout(clk1h) |
- | if (!rst == 1) | + | ); |
- | back_to_zero_flag <= 1; | + | //按键动作标志信号产生 |
- | else if (((cnt_shi*10) + cnt_ge)==24) | + | always @ (posedge hold_pulse) |
+ | if(!rst==1) | ||
+ | hold_flag <= 0; | ||
+ | else | ||
+ | hold_flag <= ~hold_flag; | ||
+ | //计时完成标志信号产生 | ||
+ | always @ (*) | ||
+ | if(!rst == 1) | ||
+ | back_to_zero_flag <= 0; | ||
+ | else if(cnt_shi==0 && cnt_ge==0) | ||
back_to_zero_flag <= 1; | back_to_zero_flag <= 1; | ||
else | else | ||
back_to_zero_flag <= 0; | back_to_zero_flag <= 0; | ||
- | end | + | //24秒倒计时控制 |
- | + | always @ (posedge clk1h or negedge rst) begin | |
- | always @ (posedge hold) | + | if (!rst == 1) begin |
- | hold_flag <= ~hold_flag; | + | cnt_ge <= 4'd4; |
- | + | cnt_shi <= 4'd2; | |
- | always @ (posedge clk_divided or posedge back_to_zero_flag) begin | + | end |
- | if (back_to_zero_flag == 1) begin | + | else if(hold_flag == 1)begin |
- | cnt_ge <= 0; | + | cnt_ge <= cnt_ge; |
- | cnt_shi <= 0; end | + | cnt_shi <= cnt_shi; |
- | else if (cnt_ge == 9) begin | + | end |
- | cnt_ge <= 0; | + | else if(cnt_shi==0 && cnt_ge==0) begin |
- | cnt_shi <= cnt_shi + 1; end | + | cnt_shi <= cnt_shi; |
- | else if (hold_flag == 1) | + | |
cnt_ge <= cnt_ge; | cnt_ge <= cnt_ge; | ||
+ | end | ||
+ | else if(cnt_ge==0)begin | ||
+ | cnt_ge <= 4'd9; | ||
+ | cnt_shi <= cnt_shi-1;end | ||
else | else | ||
- | cnt_ge <= cnt_ge + 1; | + | cnt_ge <= cnt_ge -1; |
+ | end | ||
+ | //计时完成点亮led | ||
+ | always @ ( back_to_zero_flag)begin | ||
+ | if (back_to_zero_flag==1) | ||
+ | led = 8'b0; | ||
+ | else | ||
+ | led = 8'b11111111; | ||
end | end | ||
- | |||
- | always @ (cnt_ge) begin | ||
- | seg_led_1[8:0] <= {2'b00,seg[cnt_ge]}; | ||
- | end | ||
- | always @ (cnt_shi) begin | + | assign seg_led_1[8:0] = {2'b00,seg[cnt_ge]}; |
- | seg_led_2[8:0] <= {2'b00,seg[cnt_shi]}; | + | |
- | end | + | assign seg_led_2[8:0] = {2'b00,seg[cnt_shi]}; |
- | + | ||
+ | |||
endmodule | endmodule | ||
行 129: | 行 153: | ||
\\ | \\ | ||
- | ====引脚分配==== | + | ####引脚分配 |
- | ------- | + | |
+ | --- | ||
设置好复位键可消抖的按键,编译完成后下载,通过按键就可以翻转LED。你也可以定义多个按键控制多个LED,还可以比较不加按键消抖情况下实际的效果对比如何。 | 设置好复位键可消抖的按键,编译完成后下载,通过按键就可以翻转LED。你也可以定义多个按键控制多个LED,还可以比较不加按键消抖情况下实际的效果对比如何。 | ||
\\ | \\ | ||
行 138: | 行 164: | ||
|hold |M13 ^ | |hold |M13 ^ | ||
|seg_led_1[0] |C12 ^ | |seg_led_1[0] |C12 ^ | ||
- | |seg_led_1[0] |C12 ^ | + | |seg_led_1[1] |B14 ^ |
- | |seg_led_1[0] |C12 ^ | + | |seg_led_1[2] |J1 ^ |
- | |seg_led_1[0] |C12 ^ | + | |seg_led_1[3] |H1 ^ |
- | |seg_led_1[0] |C12 ^ | + | |seg_led_1[4] |H2 ^ |
- | |seg_led_1[0] |C12 ^ | + | |seg_led_1[5] |B12 ^ |
- | |seg_led_1[0] |C12 ^ | + | |seg_led_1[6] |A11 ^ |
- | |seg_led_1[0] |C12 ^ | + | |seg_led_1[7] |K1 ^ |
- | |seg_led_1[0] |C12 ^ | + | |seg_led_1[8] |A12 ^ |
- | |seg_led_1[0] |C12 ^ | + | |seg_led_2[0] |A10 ^ |
- | |seg_led_1[0] |C12 ^ | + | |seg_led_2[1] |C11 ^ |
- | |seg_led_1[0] |C12 ^ | + | |seg_led_2[2] |F2 ^ |
- | |seg_led_1[0] |C12 ^ | + | |seg_led_2[3] |E1 ^ |
- | |seg_led_1[0] |C12 ^ | + | |seg_led_2[4] |E2 ^ |
- | |seg_led_1[0] |C12 ^ | + | |seg_led_2[5] |A9 ^ |
- | ====小结==== | + | |seg_led_2[6] |B9 ^ |
- | ------ | + | |seg_led_2[7] |F1 ^ |
- | 在本实验学习了如何进行按键的消抖。在很多应用情况下我们必须采取消抖才能更好地控制逻辑。在下一个实验[[8. 计时控制|计时控制]]中我们将学习计时的显示和控制,在这里我们要用到按键的消抖以及数码管,我们甚至可以用小脚丫做一个计时器甚至电子表。 | + | |seg_led_2[8] |C9 ^ |
+ | |||
+ | ####小结 | ||
+ | |||
+ | --- | ||
+ | 本实验主要介绍了计时器的实现方式,并且包含了复位与暂停功能,读者可自行修改程序内部的时钟参数来调节计时时间。下一节将介绍PWM调制技术的应用[[9. 呼吸灯|呼吸灯]]。 | ||