## 计时控制 在之前的实验中我们掌握了如何进行时钟分频、如何进行数码管显示与按键消抖的处理,那么在本节实验之中,我们将会实现一个篮球赛场上常见的24秒计时器。 \\ ### 1. 硬件说明 在之前的实验中我们为读者详细介绍过小脚丫MXO2板卡上的按键、数码管、LED等硬件外设,在此不再赘述。本节将实现由数码管作为显示模块,按键作为控制信号的输入(包含复位信号和暂停信号),Lattice MXO2 4000HC作为控制核心的篮球读秒系统,实现框图如下: {{ ::计时器框图.png?800 |}} \\ ### 2. Verilog代码 // ******************************************************************** // >>>>>>>>>>>>>>>>>>>>>>>>> COPYRIGHT NOTICE <<<<<<<<<<<<<<<<<<<<<<<<< // ******************************************************************** // File name : counter.v // Module name : counter // Author : STEP // Description : // Web : www.stepfpga.com // // -------------------------------------------------------------------- // Code Revision History : // -------------------------------------------------------------------- // Version: |Mod. Date: |Changes Made: // V1.0 |2017/03/02 |Initial ver // -------------------------------------------------------------------- // Module Function:24秒倒计时计数器 module counter ( clk , //时钟 rst , //复位 hold , //启动暂停按键 seg_led_1 , //数码管1 seg_led_2 , //数码管2 led //led ); input clk,rst; input hold; output [8:0] seg_led_1,seg_led_2; output reg [7:0] led; wire clk1h; //1Hz时钟 wire hold_pulse; //按键消抖后信号 reg hold_flag; //按键标志位 reg back_to_zero_flag ; //计时完成信号 reg [6:0] seg [9:0]; reg [3:0] cnt_ge; //个位 reg [3:0] cnt_shi; //十位 initial begin seg[0] = 7'h3f; // 0 seg[1] = 7'h06; // 1 seg[2] = 7'h5b; // 2 seg[3] = 7'h4f; // 3 seg[4] = 7'h66; // 4 seg[5] = 7'h6d; // 5 seg[6] = 7'h7d; // 6 seg[7] = 7'h07; // 7 seg[8] = 7'h7f; // 8 seg[9] = 7'h6f; // 9 /*若需要显示A-F,解除此段注释即可 seg[10]= 7'hf7; // A seg[11]= 7'h7c; // b seg[12]= 7'h39; // C seg[13]= 7'h5e; // d seg[14]= 7'h79; // E seg[15]= 7'h71; // F*/ end // 启动/暂停按键进行消抖 debounce U2 ( .clk(clk), .rst(rst), .key(hold), .key_pulse(hold_pulse) ); // 用于分出一个1Hz的频率 divide #(.WIDTH(32),.N(12000000)) U1 ( .clk(clk), .rst_n(rst), .clkout(clk1h) ); //按键动作标志信号产生 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; else back_to_zero_flag <= 0; //24秒倒计时控制 always @ (posedge clk1h or negedge rst) begin if (!rst == 1) begin cnt_ge <= 4'd4; cnt_shi <= 4'd2; end else if(hold_flag == 1)begin cnt_ge <= cnt_ge; cnt_shi <= cnt_shi; end else if(cnt_shi==0 && cnt_ge==0) begin cnt_shi <= cnt_shi; cnt_ge <= cnt_ge; end else if(cnt_ge==0)begin cnt_ge <= 4'd9; cnt_shi <= cnt_shi-1;end else 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 assign seg_led_1[8:0] = {2'b00,seg[cnt_ge]}; assign seg_led_2[8:0] = {2'b00,seg[cnt_shi]}; endmodule \\ ### 3. 引脚分配 设置好复位键可消抖的按键,编译完成后下载,通过按键就可以翻转LED。你也可以定义多个按键控制多个LED,还可以比较不加按键消抖情况下实际的效果对比如何。 \\ ^信号 ^引脚 ^ |clk |C1 ^ |rst |L14 ^ |hold |M13 ^ |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 ^ ### 4. 小结 本实验主要介绍了计时器的实现方式,并且包含了复位与暂停功能,读者可自行修改程序内部的时钟参数来调节计时时间。下一节将介绍PWM调制技术的应用[[9. 呼吸灯|呼吸灯]]。