赞
踩
网上找资料时一般出现的是led灯1s从暗到亮,下一个1s从亮到暗,所以在此记录一篇2s的呼吸灯,也为日后自己复习提供一点帮助,结尾有源码。
四个LED灯2s从暗到亮,下一个2s从亮到暗,循环显示。
在fpga中,呼吸灯的实现是通过控制占空比的多少,输出两段,第一段:由暗到亮,占空比由0%到100%逐步递增,第二段:由亮到暗,占空比由100%到0%逐步递减
端口信号 | 信号类别 | 信号名称 | 信号作用 |
---|---|---|---|
input | wire | clk | 时钟信号 |
input | wire | rst_n | 复位信号 |
output | reg | led | led信号 |
该图是用time gen来画的
这部分是从暗到亮的仿真波形,在breath_led一行我们可以很明显的看到从一开始基本看不见1111,到后面1111的占空比逐步扩大。
这部分则是从亮到暗,breath_led一行,0000的占空比逐步扩大
module breath_led ( input clk , input rst_n , output reg [3:0] breath_led ); parameter MAX_2us = 10'd99 ; //2us //之所以2ms和2s都是999,这是因为这两个的开始信号我分别设置为cnt_2us的结束信号、cnt_2ms的结束信号 //记了1000次的us信号就等于2ms,2s也是这个道理 parameter MAX_2ms = 19'd999; //2ms = 1000 * 2us parameter MAX_2s = 19'd999; //2s = 1000 * 2ms reg [9:0] cnt_2us; reg [18:0] cnt_2ms; reg [18:0] cnt_2s; reg [1:0] flag; //状态转变标志,判断是从暗到亮还是从亮到暗 wire add_cnt_2us; //计数器开始信号 wire end_cnt_2us; //计数器结束信号 wire add_cnt_2ms; wire end_cnt_2ms; wire add_cnt_2s; wire end_cnt_2s; always @(negedge rst_n or posedge clk) begin if (!rst_n) begin cnt_2us <= 6'd0; end else if (add_cnt_2us) begin if (end_cnt_2us) begin cnt_2us <= 6'd0; end else begin cnt_2us <= cnt_2us + 6'd1; end end else begin cnt_2us <= cnt_2us; end end assign add_cnt_2us = 1'd1; assign end_cnt_2us = add_cnt_2us && cnt_2us == MAX_2us; always @(negedge rst_n or posedge clk) begin if (!rst_n) begin cnt_2ms <= 6'd0; end else if (add_cnt_2ms) begin if (end_cnt_2ms) begin cnt_2ms <= 6'd0; end else begin cnt_2ms <= cnt_2ms + 6'd1; end end else begin cnt_2ms <= cnt_2ms; end end assign add_cnt_2ms = end_cnt_2us; assign end_cnt_2ms = add_cnt_2ms && cnt_2ms == MAX_2ms; always @(negedge rst_n or posedge clk) begin if (!rst_n) begin cnt_2s <= 6'd0; end else if (add_cnt_2s) begin if (end_cnt_2s) begin cnt_2s <= 6'd0; end else begin cnt_2s <= cnt_2s + 6'd1; end end else begin cnt_2s <= cnt_2s; end end assign add_cnt_2s = end_cnt_2ms; assign end_cnt_2s = add_cnt_2s && cnt_2s == MAX_2s; //每隔两秒,信号翻转,进入下一状态 always @(posedge clk or negedge rst_n)begin if(!rst_n)begin flag <= 1'b0; end else if(end_cnt_2s)begin flag <= ~flag;//1s取反 end else begin flag <= flag; end end always @(negedge rst_n or posedge clk) begin if (!rst_n) begin breath_led <= 4'b0000; end //状态一:从暗到亮 else if (!flag)begin breath_led <= (cnt_2s > cnt_2ms)?4'b1111:4'b0000; end //状态二:从亮到暗 else if (flag) begin breath_led <= (cnt_2s > cnt_2ms)?4'b0000:4'b1111; end else begin breath_led <= breath_led; end end endmodule
`timescale 1ns/1ns module breath_led_tb (); //激励信号 reg clk; reg rst_n; //响应信号 wire [3:0] breath_led; parameter CYCLE = 20; //完整代码中的计数时间长,故在此重新赋予短时的参数,以便观察结果 parameter MAX_2us = 10; parameter MAX_2ms = 20; parameter MAX_2s = 20; //产生时钟信号 always #(CYCLE/2) clk = ~clk; //产生激励 initial begin clk = 1'b0; rst_n = 1'b0; #(CYCLE); rst_n = 1'b1; #(2*(MAX_2us)*(MAX_2ms)*(MAX_2s)*CYCLE);//检测一个大周期:从暗到亮,从亮到暗 $stop; end //实例化 breath_led #( .MAX_2us(MAX_2us), .MAX_2ms(MAX_2ms), .MAX_2s(MAX_2s) ) u_breath_led( .clk(clk), .rst_n(rst_n), .breath_led(breath_led) ); endmodule
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。