呼吸灯介绍:
呼吸灯是指灯能够像人的呼吸一样,实现由暗到亮或由亮到暗的变化,通常用于消息提示功能,或者作为系统正在运行的提示。
呼吸灯原理:
通过脉冲宽度调制(PWM)实现,即通过调节占空比来对模拟信号电平进行数字编码,进而控制高电平时间
实验目的:用一个按键可以开关控制呼吸灯的呼吸与停止
模块框图:
breath_led 模块代码 (该代码参考了野火的呼吸灯代码)
链接:16. 呼吸灯 — [野火]FPGA Verilog开发实战指南——基于Altera EP4CE10 征途Pro开发板 文档 (embedfire.com)
module breath_led
(
input wire clk_50mhz , //系统时钟50Mhz
input wire rst_n , //全局复位
input wire led_flag , //输入信号,一个高电平周期
output reg led_out //输出信号,控制led灯
);
parameter CNT_1US_MAX = 6'd49 ;
parameter CNT_1MS_MAX = 10'd999 ;
parameter CNT_1S_MAX = 10'd999 ;
reg [5:0] cnt_1us ;
reg [9:0] cnt_1ms ;
reg [9:0] cnt_1s ;
reg cnt_1s_en ;
reg led_flag_h ;
//把输入信号led_flag处理为电平反转信号
always@( posedge clk_50mhz or negedge rst_n) begin
if (rst_n==1'b0) begin
led_flag_h <= 1'b0;
end
else if (led_flag == 1'b1) begin
led_flag_h <= ~led_flag_h;
end
else begin
led_flag_h <= led_flag_h;
end
end
//cnt_1us:1us计数器
always@(posedge clk_50mhz or negedge rst_n) begin
if(rst_n == 1'b0) begin
cnt_1us <= 6'b0;
end
else if(cnt_1us == CNT_1US_MAX) begin
cnt_1us <= 6'b0;
end
else begin
cnt_1us <= cnt_1us + 1'b1;
end
end
//cnt_1ms:1ms计数器
always@(posedge clk_50mhz or negedge rst_n) begin
if(rst_n == 1'b0) begin
cnt_1ms <= 10'b0;
end
else if(cnt_1ms == CNT_1MS_MAX && cnt_1us == CNT_1US_MAX) begin
cnt_1ms <= 10'b0;
end
else if(cnt_1us == CNT_1US_MAX) begin
cnt_1ms <= cnt_1ms + 1'b1;
end
end
//cnt_1s:1s计数器
always@(posedge clk_50mhz or negedge rst_n) begin
if(rst_n == 1'b0) begin
cnt_1s <= 10'b0;
end
else if(cnt_1s == CNT_1S_MAX && cnt_1ms == CNT_1MS_MAX
&& cnt_1us == CNT_1US_MAX) begin
cnt_1s <= 10'b0;
end
else if(cnt_1ms == CNT_1MS_MAX && cnt_1us == CNT_1US_MAX) begin
cnt_1s <= cnt_1s + 1'b1;
end
end
//cnt_1s_en:1s计数器使能信号
always@(posedge clk_50mhz or negedge rst_n) begin
if(rst_n == 1'b0) begin
cnt_1s_en <= 1'b0;
end
else if(cnt_1s == CNT_1S_MAX && cnt_1ms == CNT_1MS_MAX
&& cnt_1us == CNT_1US_MAX) begin
cnt_1s_en <= ~cnt_1s_en;
end
end
//led_out:输出信号连接到外部的led灯
always@(posedge clk_50mhz or negedge rst_n) begin
if(rst_n == 1'b0) begin
led_out <= 1'b0;
end
else if(led_flag_h == 1'b1) begin
led_out <= 1'b0;
end
else if((cnt_1s_en == 1'b1 && cnt_1ms < cnt_1s) ||
(cnt_1s_en == 1'b0 && cnt_1ms > cnt_1s)) begin
led_out <= 1'b0;
end
else begin
led_out <= 1'b1;
end
end
endmodule
key_filter模块代码,见我的这一篇文章 :用FPGA设计软件按键消抖-CSDN博客
key_breath_led 模块代码
module key_breath_led (
input wire clk_50mhz , //系统时钟50Mhz
input wire rst_n , //全局复位
input wire key_in , //按键输入信号
output wire led_out //输出信号,控制led灯
);
wire key_flag;
key_filter key_filter_inst
(
.clk_50mhz (clk_50mhz) , //系统时钟50Mhz
.rst_n (rst_n ) , //全局复位
.key_in (key_in ) , //按键输入信号
.key_flag (key_flag ) //key_flag为1时表示消抖后检测到按键被按下
//key_flag为0时表示没有检测到按键被按下
);
breath_led breath_led_inst
(
.clk_50mhz (clk_50mhz) , //系统时钟50Mhz
.rst_n (rst_n ) , //全局复位
.led_flag (key_flag ) , //输入信号,一个高电平周期
.led_out (led_out ) //输出信号,控制led灯
);
endmodule //key_breath_led