【FPGA】用Verilog语言实现呼吸灯实验
一、模块框图
包含两个输入信号:系统时钟(sys_clk)以及复位信号(sys_rst_n)。 一个输出信号:led_out
二、大致原理
通过PWN来控制呼吸灯的亮、灭程度 前一周期为:完全熄灭 ——> 完全点亮 后一周期为:完全点亮 ——> 完全熄灭
三、波形图
1、时钟与复位信号
2、计数器
完全熄灭 ——> 完全点亮 、 完全点亮 ——> 完全熄灭 时间均为1s 由板子频率可知,1us需要50个时钟周期,1ms需要1000us,1s则需要1000ms。 将1s分成1000份,每个T为1ms(份数分得越大,呼吸效果越明显) 将每个T分成1000份,每次越变的宽度就增加一小份,即为1us
3、输出信号
当cnt_1ms计数器的值 ≤ cnt_1s计数器的值 led_out为低电平,其余时间为高电平 上半部分为: 完全熄灭 ——> 完全点亮 下半部分为:完全点亮 ——> 完全熄灭 (即led_out取反)
4、使能信号
用于区分led_out是由 完全熄灭 ——> 完全点亮 还是 完全点亮 ——> 完全熄灭。 完全熄灭 ——> 完全点亮:先低后高 完全点亮 ——> 完全熄灭:先高后低
四、代码部分
1、Verilog代码
module breath_led #( parameter CNT_1US_MAX = 6d49, parameter CNT_1MS_MAX = 10d999, parameter CNT_1S_MAX = 10d999 ) ( input wire sys_clk, input wire sys_rst_n, output reg led_out ); reg [9:0] cnt_1s; reg [9:0] cnt_1ms; reg [5:0] cnt_1us; reg cnt_en; always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1b0) cnt_1us <= 6d0; else if (cnt_1us == CNT_1US_MAX) cnt_1us <= 6d0; else cnt_1us <= cnt_1us + 6d1; always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1b0) cnt_1ms <= 10d0; else if ((cnt_1ms == CNT_1MS_MAX)&&(cnt_1us == CNT_1US_MAX)) cnt_1ms <= 10d0; else if (cnt_1us == CNT_1US_MAX) cnt_1ms <= cnt_1ms + 10d1; else cnt_1ms <= cnt_1ms; always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1b0) cnt_1s <= 10d0; else if((cnt_1s == CNT_1S_MAX)&&(cnt_1ms == CNT_1MS_MAX)&&(cnt_1us == CNT_1US_MAX)) cnt_1s <= 10d0; else if ((cnt_1ms == CNT_1MS_MAX)&&(cnt_1us == CNT_1US_MAX)) cnt_1s <= cnt_1s + 10d1; else cnt_1s <= cnt_1s; always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1b0) cnt_en <= 1b0; else if((cnt_1s == CNT_1S_MAX)&&(cnt_1ms == CNT_1MS_MAX)&&(cnt_1us == CNT_1US_MAX)) cnt_en <= ~cnt_en; else cnt_en <= cnt_en; always@(posedge sys_clk or negedge sys_rst_n) if(sys_rst_n == 1b0) led_out <= 1b1; else if(cnt_1ms <= cnt_1s) led_out <= cnt_en; else led_out <= ~cnt_en; endmodule
2、tb仿真代码
`timescale 1ns/1ns module tb_breath_led(); reg sys_clk; reg sys_rst_n; wire led_out; initial begin sys_clk = 1b1; sys_rst_n <= 1b0; #20 sys_rst_n <= 1b1; end always #10 sys_clk = ~sys_clk; breath_led #( .CNT_1US_MAX(6d4), .CNT_1MS_MAX(10d9), .CNT_1S_MAX(10d9) ) breath_led_inst ( .sys_clk(sys_clk), .sys_rst_n(sys_rst_n), .led_out(led_out) ); endmodule
五、仿真波形
经分析,与开始手动绘制的波形图吻合,结果正确,此处不再上传上版验证结果。