计时控制


在之前的实验中我们掌握了如何进行时钟分频、如何进行数码管显示与按键消抖的处理,那么在本节实验之中,我们将会实现一个篮球赛场上常见的24秒计时器。


硬件说明


在之前的实验中我们为读者详细介绍过小脚丫MXO2板卡上的按键、数码管、LED等硬件外设,在此不再赘述。本节将实现由数码管作为显示模块,按键作为控制信号的输入(包含复位信号和暂停信号),Lattice MXO2 4000HC作为控制核心的篮球读秒系统,实现框图如下:


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


引脚分配


设置好复位键可消抖的按键,编译完成后下载,通过按键就可以翻转LED。你也可以定义多个按键控制多个LED,还可以比较不加按键消抖情况下实际的效果对比如何。

信号 引脚
clk C1
rst L14
hold M13
segled1[0] C12
segled1[1] B14
segled1[2] J1
segled1[3] H1
segled1[4] H2
segled1[5] B12
segled1[6] A11
segled1[7] K1
segled1[8] A12
segled2[0] A10
segled2[1] C11
segled2[2] F2
segled2[3] E1
segled2[4] E2
segled2[5] A9
segled2[6] B9
segled2[7] F1
segled2[8] C9

小结


本实验主要介绍了计时器的实现方式,并且包含了复位与暂停功能,读者可自行修改程序内部的时钟参数来调节计时时间。下一节将介绍PWM调制技术的应用呼吸灯