这是本文档旧的修订版!
	
		|   银杏科技有限公司旗下技术文档发布平台   | 
	
	
		| 技术支持电话 | 0379-69926675-801 | 
	
	
		| 技术支持邮件 | Gingko@vip.163.com | 
	
	
		| 技术论坛 | http://www.eeschool.org | 
	
	
		|   版本   |   日期   |   作者   |   修改内容   | 
	
	
		|   V1.0   |   2020-05-20   |   gingko   |   初次建立   | 
	
 
实验八:计数器实验——呼吸灯
一、实验目的与意义
 掌握计数器原理及使用方法;
 
 掌握ISE开发软件的使用方法。
 
 
二、实验设备及平台
- 
 
 USB-CABLE(或相同功能)的仿真器。
 
 Micro USB线缆。
 
 ISE开发平台。
 
 电脑一台。
 
 
三、实验原理
 计数器是实现计数的一种最基本的加法运算。在FPGA中计数器的实质其实就是对驱动参考时钟进行计数,每当触发条件满足,计数器的寄存器参数实现自加,累加到某个状态进行清零操作。FPGA中常用计数器对系统时钟进行计数,实现时钟分频、定时器、延时、计数、控制等功能,是FPGA实现功能中常用的一种逻辑电路和时序控制方式。
 
 呼吸灯在生活中也较为常见,一般是通过控制LED的亮度渐变实现的。以本实验要实现的呼吸灯为例,要实现的效果为渐渐变亮,亮度最大后再渐渐变暗,最后熄灭,如此往复循环。LED的亮度变化是通过控制LED单位时间内亮的时间占比实现的;比如以10个时钟周期作为1个单位时间周期,当LED亮的时间持续2个时钟周期,熄灭的时间持续8个时钟周期,那么,当时钟周期较小时,每秒由成千上万个这样的单位时间构成;反馈到人的眼睛,由于视觉暂留,眼睛看不到很高频率的闪烁,而是看到LED的亮度很低。同理,当10个时钟周期里持续8个时钟周期的亮,则看起来亮度就高。
 
 呼吸灯的呼吸效果是如何实现的呢?以本实验为例,呼吸周期为2秒,则从暗到亮的过程持续1秒,从亮到暗的过程持续1秒。在从暗到亮的过程中,假如这1秒分成1000个单位时间周期,则每个单位时间周期里LED亮的时间都要比前一个久一点。同理,从亮到暗的过程则是每个时间单位周期里LED亮的时间都要比前一个短一点。
 
 以本实验呼吸灯亮的这1秒过程为例来阐述。系统时钟为25MHz,机1秒钟内有25M个系统时钟周期。将1秒分成5000个单位时间周期,每个单位时间周期持续5000个系统时钟周期。
 
 那么,只需将这5000个单位时间周期内LED亮的时间从0~5000逐渐增加,这1秒LED看起来就是逐渐变亮的;同理也可以控制LED灯逐渐变暗。
 
 
四、代码讲解
 原理部分讲解了呼吸灯的实现原理。下面通过代码讲解如何实现LED呼吸的效果。
 
 首先定义变量cnt1和cnt2;cnt1是对单位时间周期内系统时钟进行计数,cnt2是对单位时间周期(即cnt1)进行计数,那么cnt1*cnt2=25M,。然后定义变量flag,每过1秒翻转1次,则可以在flag的不同状态控制LED是渐亮还是渐灭。
 
 具体的LED在1个单位时间周期内亮的时间持续多少个系统时钟周期,是通过cnt1和cnt2的值比较判断的。由于cnt2是逐1自加的,那么每次在cnt1从1累加到4999的过程中,cnt2是不变的,而且每次cnt1累加的过程中,cnt2总比前一个值大1;那么,在cnt1累加的过程中,小于cnt2的值的时候,控制led亮,在cnt2累加的过程中即可实现led逐渐变亮。逐渐变暗的过程同理,只需控制cnt1大于cnt2的时候led亮即可。
 
  * 代码如下:
//-------------------cnt1--------------------//
//对系统时钟进行计数
always@(posedge clk_25M or negedge rst_n)
	if(!rst_n)
			cnt1<=13'd0;
	else	if(cnt1==13'd4999)
			cnt1<=13'd0;
	else
			cnt1<=cnt1+1'd1;
//------------------cnt2-------------------//
//对cnt1进行计数		
always@(posedge clk_25M or negedge rst_n)
	if(!rst_n)
			cnt2<=13'd0;
	else if((cnt1==13'd4999)&&(cnt2==13'd4999))
			cnt2<=13'd0;
	else if(cnt1==13'd4999)
			cnt2<=cnt2+1'd1;
//-----------------flag--------------------//
//flag为1时led逐渐变亮,flag为0时逐渐变暗
reg flag;
always@(posedge clk_25M or negedge rst_n)
	if(!rst_n)
			flag<=1'd0;
	else if((cnt2==13'd0)&&(cnt1==13'd0))
			flag<=~flag;
//-----------------led--------------------//
//控制LED在哪个范围内亮和灭
always@(posedge clk_25M or negedge rst_n)
	if(!rst_n)
			led_r<=1'd1;
	else if((flag==1'd1)&&(cnt2<cnt1))
			led_r<=1'd0;
		else if((flag==1'd0)&&(cnt2>cnt1))
			led_r<=1'd0;
	else 
			led_r<=1'd1;
 
五、实验步骤及实验结果
1、将硬件正确连接,如图8.1所示。
2、将编写好的代码进行编译,并下载到开发板中;
3、观察实验现象——FPGA_LED逐渐变亮然后逐渐变暗,循环进行。
 
六、拓展实验
 调整LED灯的呼吸周期。
 
 通过计数器,控制led熄灭之后延迟一段时间再逐渐变亮。