【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

五、仿真波形

经分析,与开始手动绘制的波形图吻合,结果正确,此处不再上传上版验证结果。

经验分享 程序员 微信小程序 职场和发展