FPGA学习第一天——呼吸灯

一、基本原理

  FPGA板载LED灯的亮暗可以由电压控制,电压高时会比较亮,FPGA较难直接控制端口电压,所以通过PWM波不同的占空比来模拟电压的高低。

二、实验目标

  今天所用板卡为高云的Tang primer 20k,根据板卡原理图可知,当LED端口为0时灯泡亮起。

f82e6c766f2a4ae7bab194bccd6e72e3.jpg

   我们希望灯泡可以在一秒内缓缓亮起,然后在一秒内缓缓暗去,当然这个时间可以自定义。

三、实验分析

  为了体现占空比的变化,也就是电压的变化,可以将亮起的一秒钟分成若干等分,每一份的占空比依次递减,直到最后一份整个时间段里全为0。同理,可以将熄灭的一秒钟也分成若干等分(不必和亮起一致,看自己需求,本实验亮起和熄灭分成相同等分),占空比依次递增,直到最后整个时间段里全为1。这里将一秒分为1000份,在一定的范围内,份数越多,效果越细腻。

  时钟为27Mhz,1s等于27×10的6次方个周期,分成1000份,每一份就有27×10的3次方个周期,让其PWM波占空比依次减小,第一个时间段内占空比应该为1,也就是27×10的3次方个周期LED均为1。第二个时间段内选取其中一小部分为0,为了呼吸灯效果的均匀,每一个时间段为0的周期数应该比前一个多27个时钟周期,这样到最后一个时间段内占空比就接近于0,也就是完全亮的状态。

f54e8de1064448398ea03b4f3b6addd0.jpg

四、代码

module breath_led(
        input           wire            sys_clk         ,
        input           wire            sys_rst_n       ,
        output          reg             led             );
        
        
        parameter       base=27,
                        max1=27_000,
                        max2=1000;
                        
                        
                        
        reg         [14:0]          cnt1        ;//每个时间段内的周期数
        reg         [9:0]           cnt2        ;//总时间段数
        reg                         flag        ;//判断现在时亮起状态还是熄灭状态的标志
        
        
        always@(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
        flag<=1'b0;
        else if(cnt2==max2-2'd2&&cnt1==max1-1'b1)
        flag<=1'b1;
        else if(cnt2==1&&cnt1==max1-1'b1&&flag==1'b1)
        flag<=1'b0;
        else
        flag<=flag;
        end
        
        always@(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
        cnt1<=15'b0;
        else if(cnt1==max1-1'b1)
        cnt1<=15'b0;
        else
        cnt1<=cnt1+1'b1;
        end
        
        always@(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
        cnt2<=10'b0;
        else if(cnt1==max1-1'b1&&flag==1'b0)
        cnt2<=cnt2+1'b1;
        else if(cnt1==max1-1'b1&&flag==1'b1)
        cnt2<=cnt2-1'b1;
        else
        cnt2<=cnt2;
        end
        
        always@(posedge sys_clk or negedge sys_rst_n) begin
        if(!sys_rst_n)
        led<=1'b1;
        else if(cnt1<=base*cnt2)
        led<=1'b0;
        else
        led<=1'b1;
        end
        
        endmodule
        

五、测试代码

`timescale  1ns/1ns
module breath_led_tb();

reg            sys_clk      ; 
reg            sys_rst_n    ; 
wire             led        ;   

breath_led breath_led_inst(
       . sys_clk     (sys_clk    )   ,
       . sys_rst_n   (sys_rst_n  )   ,
       . led         (led        )   );


always#19 sys_clk=~sys_clk;

initial begin
sys_clk=1'b0;
sys_rst_n=1'b0;
#50
sys_rst_n=1'b1;
end


endmodule

六、上板验证

呼吸灯上板

七、问题分析

  • 第一次做,我感觉效果不太好,灯亮暗得太快了,而且暗下去时感觉并没有完全暗下去,下次可以试试暗下去之后等个半秒钟再亮起来
  • 代码中用了一个乘法器,个人感觉这一块还可以优化,最好不用乘法器,资源消耗太大了,我还没想到更好的方法,大家有懂的一起讨论。

  • 11
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值