06分频计数器之呼吸灯2
一设计功能:从灭到亮,时间为2秒,再从亮到灭也为2秒,总的时间为4秒。现象是,led灯的亮度从暗逐渐到亮的过程,再从亮逐渐变暗。
二设计实现之我看:(一)可调占空比的方波。可调占空比,是对于一个周期固定的方波信号,即方波的高电平持续时间或翻转时间不断改变。
(二)实现过程:
把2秒分成1000份,则每份为2ms,对于这两毫秒的方波,它的占空比在不断变化,如第一个为0.1%, 第二个为0.2%,依次不断增加到最大占空比1(即再把2ms分成1000份,即2us, 每次随着第N个方波的到来,方波的翻转时间随着N变化)然后回到初始值,不断循环。
三设计输入:
(一)2us的计数器:参数化设计,且每计满2us产生一个标志信号: T2us_full
parameter T2us = 7'd99; parameter T2ms = 18'd99_999;
//2us timer reg T2us_full;//count to 2us reg [6:0]div_cnt; always@(posedge clk)begin if(rst==0)begin T2us_full<=0; div_cnt<=7'd0; end else if(div_cnt==T2us)begin T2us_full<=1; div_cnt<=7'd0; end else begin T2us_full<=0; div_cnt<=div_cnt+1'b1; end end |
(二)以2us为基本计数单位的计数器:第一个模块,每计满2us计数值加一,直到最大值999(也是计到了2ms),回到初始值0。第二个模块,在第一个模块计到最大值999时,产生一个计满2ms的标志信号T2ms_full。
//2us counter reg [9:0]T2us_cnt;
always@(posedge clk)begin if(rst==0) T2us_cnt<=10'd0; else if(T2us_cnt==999) T2us_cnt<=10'd0; else if(T2us_full) T2us_cnt<=T2us_cnt+1'b1; else T2us_cnt<=T2us_cnt;
end //2ms counter reg T2ms_full; always@(posedge clk)begin if(rst==0) T2ms_full<=1'b0; else if(T2us_cnt==999)begin T2ms_full<=1'b1; end else begin T2ms_full<=1'b0; end end |
(三)2ms的方波数量的计数器:分成两部分,一是从0-999的加一模式,二是从999-0的减一模式,两个相反模式的切换是利用标志信号控制。具体过程是每计满2ms方波计数值加一,直到最大值999,再利用标志信号切换到减一模式,从999减到0时再切换为加一模式,不断循环。
//the count of wave:1000,cnt_wave. //two part:0-999 and 999-0 by dec_en reg dec_en; reg[9:0]cnt_wave; always@(posedge clk)begin if(rst==0) cnt_wave<=10'd0;
elseif(T2ms_full)begin case(dec_en) 1'b0: if(cnt_wave==999)begin cnt_wave<=cnt_wave; dec_en <=1'b1; end elsebegin cnt_wave<=cnt_wave+1'b1; end
1'b1: if(cnt_wave==10'd0)begin dec_en <=1'b0; cnt_wave<=cnt_wave; end else cnt_wave<=cnt_wave -1'b1; endcase end end |
(四)可变占空比的方波的产生和led的翻转(周期为2秒):一是产生一个方波的标志信号wave_flag。二是通过这个wave_flag的高电平控制LED的亮。
//generate wave reg wave_flag; always@(posedge clk)begin if(rst==0)begin wave_flag<=1'b0; end else if(T2us_cnt==(999-cnt_wave))begin wave_flag<=1'b1; end else if(T2us_cnt==999)begin wave_flag<=1'b0; end else begin wave_flag<=wave_flag; end end
//the control of led always@(posedge clk)begin if(rst==0)begin led<=1'b0; end else if(wave_flag==1)begin led<=1; end else begin led<=0; end end |
四:总结
(一)遇到问题:1.一是仿真时,LED的波形一直为零。
解决办法:直接把仿真时长100ns 改为100us ,再改为100ms后直到波形出现。原因是,LED灯闪烁周期至少是2ms.完整的时间为2秒,故至少是ms的量级才行。
2.烧写工程bit文件到开发板,led一直未亮。
解决办法:由于仿真正确,猜测可能是在建立工程和管脚约束方面出问题了,所以我照着正确的管脚约束文件,改了一下格式。实现LED灯闪烁。
下面表格是管脚约束文件的正确格式:
NET "clk" LOC=p24 | IOSTANDARD=LVCMOS33; NET "rst" LOC=p94 | IOSTANDARD=LVCMOS33; NET "led" LOC=p92 | IOSTANDARD=LVCMOS33; |
(二)设计过程的方法
1.照图施工(如时序图或者电路的系统框图)
第一点我的做法是,在A4纸上画出各个模块信号的时序图,如时钟信号,2us的计满标志等。通过这些波形的时序图,就能够理清思路,快速完成设计。
![]()
|
第二点,循序渐进,如不知道怎么设置占空比可变,那就先想想占空比固定的LED闪烁,分成了1秒的计数器和计满1秒后的时钟脉冲翻转,由此可以推理只需要把翻转的计数值改变,即可实现占空比变化。
(三)仿真波形:
![]()
|