赞
踩
一、 设计目的
实现一个呼吸流水灯,在1s内由暗变亮,下1s再由亮变暗。
二、 设计思路
设计一个占空比逐步增加的方波,实现由暗变亮;然后占空比逐渐变小,实现由亮变暗。每一个led灯完成这样的操作后,切换到下一个led实现流水效果。
三、 实现逻辑概述
首先假定占空比的减小速率为0.1%,于是先将1s分成1000个ms,每一个ms之间占空比的差值为0.1。
在每一个1ms内,显然我们要实现指定占空比的方波,因此我们设定一个计数器从0开始计数,比如在第一个1ms内我们希望占空比为0,led在整个1ms内为高电平,在第二个1ms内占空比为99.9%(低电平持续时间占0.1%),因此我们在计数器小于1时拉低led,之后拉高;在第三个1ms计数器小于3时拉低,以此类推,我们可以发现,每次count的比较对象从0增长到1000,恰好可以对应我们此时计数器所处的第几个ms,因此可以直接通过比较这两个计数器的值来决定led是处于低电平还是高电平。
除此之外,为了方便观察,我们希望在每个1ms内,指定占空比的方波可以维持的稍微就一些方便观察,因此我们设计了一个中间计数器count_us。由于时钟周期为10ns,而之前我们已经将1s分为了1000ms,接下来我们对1ms做如下处理,从底层向上看,之前我们提到通过比较count和第几个1ms来决定其占空比,因此count的阈值对应1000,这样一来需要花费100010即10000ns可以得到一次指定占空比的方波,而之前已经分成了1000份1ms,因此我们可以让该指定占空比的方波在这个1ms内重复1s/100010000ns=100次,来满足设计要求,同时也方便观察。
所以我们将三个计数器依次设置为count_ms、count_us、count_num,分别表示目前是第几个1ms、当前1ms的第几个方波、当前方波的计数值。
总结如下:
各个1ms内的100个cycle相同,将指定方波波形重复100次。
四、实现代码
(1)设计文件
module breathe
#(
parameter TIME_US = 100 ,
parameter TIME_MS = 1000 ,
parameter NUMBER = 1000
)
(
input sys_clk_p,
input sys_clk_n,
input rst_n,
output reg [7:0] led
);
wire enable;
reg enable_reg;
always@(posedge clk or negedge rst_n)
begin
if(~rst_n)begin
enable_reg<=0;
end
else
enable_reg <= enable;
end
reg [9:0] count_phase; //计数何时到达1us,每到1us时归0
reg [9:0] count_us; //单位为1us,计数到1ms时归0
reg [9:0] count_ms; //单位为1ms,计数到1s时归0
//计时至1us
always @(posedge clk or negedge rst_n) begin
if(~rst_n) begin
count_phase <= 0;
end else if(count_phase == NUMBER - 1)begin
count_phase <= 0 ;
end
else if(enable)
count_phase <= count_phase + 1;
end
//计时至1ms
always @(posedge clk or negedge rst_n) begin
if(~rst_n) begin
count_us <= 0;
end else if(count_us== TIME_US - 1 && count_phase == NUMBER - 1)begin //每计数到1000个us归0,然后开始新一轮占空比
count_us <= 0;
end
else if(count_phase == NUMBER - 1)
count_us <= count_us + 1;
end
reg flag_1s = 0;
//计时至1s
always@(posedge clk or negedge rst_n)
begin
if(~rst_n)
count_ms <= 0;
else if(count_ms == TIME_MS && ~flag_1s && count_us == TIME_US - 1 && count_phase == NUMBER - 1)
begin
count_ms <= count_ms - 1 ;
flag_1s <= 1;
end
else if(count_ms == 0 && flag_1s && count_us == TIME_US - 1 && count_phase == NUMBER - 1)
begin
count_ms <= count_ms + 1 ;
flag_1s <= 0;
end
else if(count_us == TIME_US - 1 && ~flag_1s && count_phase == NUMBER - 1)
count_ms <= count_ms + 1;
else if(count_us == TIME_US - 1 && flag_1s && count_phase == NUMBER - 1)
count_ms <= count_ms - 1;
end
reg flag_1s_reg;
wire flag_neg;
assign led_on = (count_phase < count_ms && enable)? 0:1;
always @(posedge clk or negedge rst_n) begin
if(~rst_n) begin
flag_1s_reg <= 0;
end else begin
flag_1s_reg <= flag_1s;
end
end
assign flag_neg = flag_1s_reg & ~flag_1s;
reg [2:0]count_num;
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
count_num<=0;
else if(flag_neg)
count_num <= count_num + 1;
end
always@(posedge clk or negedge rst_n)
begin
if(!rst_n)
begin
led<=8'hff;
end
else case(count_num)
3'b000 : led <= {led_on,7'b1111111};
3'b001 : led <= {1'b1,led_on,6'b111111};
3'b010 : led <= {2'b11,led_on,5'b11111};
3'b011 : led <= {3'b111,led_on,4'b1111};
3'b100 : led <= {4'b1111,led_on,3'b111};
3'b101 : led <= {5'b11111,led_on,2'b11};
3'b110 : led <= {6'b111111,led_on,1'b1};
3'b111 : led <= {7'b1111111,led_on};
endcase
end
clk_wiz_0 clock_gen
(
// Clock out ports
.clk_out1(clk), // 50MHz
.clk_out2(clk_out2), //25MHz
// Status and control signals
.resetn(rst_n), // input resetn
.locked(enable), // output locked
// Clock in ports
.clk_in1_p(sys_clk_p), // input clk_in1_p
.clk_in1_n(sys_clk_n)
);
endmodule
(2)仿真激励
module tb_breathe ();
reg clk_in;
reg rst_n;
wire sys_clk_p = clk_in;
wire sys_clk_n = ~clk_in;
wire led_0;
wire led_1;
wire led_2;
wire led_3;
wire led_4;
wire led_5;
wire led_6;
wire led_7;
always #5 clk_in = ~clk_in;
initial begin
clk_in = 0;
rst_n = 0;
#200 rst_n = 1;
end
breathe #(
.TIME_US(10),
.TIME_MS(100),
.NUMBER(100)
) inst_breathe (
.sys_clk_p (sys_clk_p),
.sys_clk_n (sys_clk_n),
.rst_n (rst_n),
.led_0 (led_0),
.led_1 (led_1),
.led_2 (led_2),
.led_3 (led_3),
.led_4 (led_4),
.led_5 (led_5),
.led_6 (led_6),
.led_7 (led_7)
);
endmodule
五、 仿真结果
为了仿真方便,我们取的几个阈值并没有按照实际的1s来取,而是将其先分为100份,占空比按照1%变化,然后一个cycle重复10次,一个cycle的时长为100*10=1000ns。
观察图中可以发现实现了呼吸效果。
如图,在18ms内的10个cycle,重复的是相同占空比的波形。
观察图中可以发现占空比逐渐减小,低电平持续时间在一个cycle内逐步减小,直到全为低电平然后占空比再逐渐增加,低电平持续时间在一个cycle内逐步减小。
flag信号由0至1表示led灯由暗变亮的过程实现完成,接下来由亮变暗,低电平持续时间减小,flag信号由1变0表示由亮变暗过程完成。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。