雾盈 发表于 2016-7-31 15:22:07

雾盈FPGA笔记之(一):基于FPGA的呼吸灯简单实验(Verilog)

本帖最后由 雾盈 于 2016-8-2 18:23 编辑

基于FPGA的呼吸灯简单实验程序(Verilog)

                                                                                                2016-07-27          雾盈

1、呼吸灯
呼吸灯最早是由苹果公司发明并应用于笔记本睡眠提示上。
呼吸灯其实是微电脑控制下,由暗渐亮,然后再由亮渐暗,模仿人呼吸方式的LED灯

2.呼吸灯原理
LED的亮度与流过的电流成正比。在一定的频率之下,如果占空比是0,则LED不亮;如果占空比是100%,则LED最亮;
如果占空比刚好是50%,则LED亮度适中。如果我们让占空比从0~100%变化,再从100%~0不断变化,就可以实现LED一呼一吸的效果。
其波形占空比示意图如图2.1所示:

3.呼吸灯程序设计思路
(1)首先确定PWM的频率为1Khz
(2)由频率算出周期 T = 1/f = 1ms
(3)根据每次呼1s,吸1s,算出计数值 1s/1ms=1000
(4)然后将1ms分成1000份,每一份是1us
(5)写三个 1us、1ms、1s的3个计数器count1、 count2、 Count3,最后count2和count3进行比较

4.程序框图
如图4.1所示


5.状态机设计
可以将呼吸灯运行过程归为两个状态:S0:由灭渐亮;S1:由亮渐灭。
这里就会有两个问题需要我们解决,
1.        状态的翻转
2.        在一个状态里如何使pwm波的占空比实现逐增或逐减。

先说第一个问题,两个状态的翻转
        由下面的时序图(图)可以看出来,两个状态的翻转只是由时间决定的,S0状态和S1状态分别持续1s,
可以将它看成周期为2s的时钟信号,每当flag_1s信号到来一次,状态就翻转一次。


                                        if(flag_1s)
                                                state <= ~state;
                                        else       
                                                state <= state;

然后再来说第二个问题,在一个状态下如何实现PWM波占空比逐增逐减的过程。
以S0状态下,LED由灭渐亮,PWM波占空比由百分之百逐渐减小至零为例:
我们发现让count2与count3比较,其结果clk_out会出现这种占空比逐渐减小的结果。
此段代码如下:

                        0:begin // led    from low to high                                  
                                        if(count2 < count3)
                                                        begin
                                                           clk_out <= 1'b0;
                                                        end
                                        else begin
                                                           clk_out <= 1'b1;
                                                       end
于是,由反逻辑可以轻易知道在S1状态下,如何使其输出的clk_out占空比由小到大的方法,这样就可以实现LED 的由亮渐灭。

        记: 整个呼吸灯程序设计主要内容大致如此,末尾附上源代码及其仿真波形,以下为程序设计中我所遇到的问题,
给可能出现同样问题的童鞋提供一些参考。

我想问问,怎么在文章中间添加图片,不然好多问题无法讲清楚。

附源代码:
modulebreathe_led(
                          input                clk,
                          input                rst_n,
                          
                          outputreg        led
);
        parameter COUNT_MAX = 10'd999;        // 过
        parameter COUNT_LIT = 6'd45;
//        parameter COUNT_LIT = 6'd9;
//        parameter COUNT_MAX = 10'd9;
//       
        reg count1;
        reg count2;
        reg count3;
       
        wire flag_1ms;
        wire flag_1s;
        wire flag_1us;
       
        reg state;
        reg clk_out;
        //count1
        always @ (posedge clk or negedge rst_n)
begin
   if(!rst_n)
      begin
                        count1 <= 1'b0;                               
      end
   elsebegin
         if(count1 < COUNT_LIT)
                        begin
                          count1 <= count1 + 1'b1;       
                        end       
                        else begin
                              count1 <= 6'd0;                               
                               end                       
             end
end
        assign flag_1us = (count1 == COUNT_LIT)? 1'b1 : 1'b0;
       
        //count2
        always @ (posedge clk or negedge rst_n)
begin
   if(!rst_n)
      begin
                   count2 <= 10'd0;                         
      end
   elsebegin   
                        /* if(flag_1us)
                                begin                                  
                                if(count2 == COUNT_MAX)
                                        begin
                                       count2 <= 10'd0;                               
                                        end
                                else begin                                       
                                        count2 <= count2 + 1'b1;
                                       end
                                end       
                        else begin
                                       count2 <= 10'd0;
                               end               */       
                               
                        if(flag_1us & count2 < COUNT_MAX)
                          begin
                                  count2 <= count2 + 1'b1;
                          end
                        else if(count2 == COUNT_MAX & count1 == COUNT_LIT)
                                begin
                                count2 <= 1'b0;
                               end
         end
end
       
        assign flag_1ms = (count2 == COUNT_MAX)? (1'b1 & flag_1us):1'b0;
       
       
       
        // count3
        always @ (posedge clk or negedge rst_n)
begin
   if(!rst_n)
      begin
                        count3 <= 10'd0;                       
      end
   elsebegin
                       /* if(flag_1ms)
                                begin
                     if(count3 == COUNT_MAX)
                                       begin
                                       count3 <= 10'd0;                               
                                        end
                                else begin                                        
                                       count3 <= count3 + 1'b1;
                                      end
                                end       
                        else begin
                                     count3 <= 10'd0;
                               end */
                       if(flag_1ms & count3 < COUNT_MAX)
                               begin
                                  count3 <= count3 + 1'b1;
                                end
                        else if(count3 == COUNT_MAX & count2 == COUNT_MAX & count1 == COUNT_LIT)
                                        begin
                                         count3 <= 1'b0;
                                       end
             end
end                       
       
        assign flag_1s = (count3 == COUNT_MAX)?(1'b1 & flag_1ms):1'b0;       
       
       

        always @ (posedge clk or negedge rst_n)
begin
   if(!rst_n)
      begin
                        clk_out <= 1'b0;
                        state <= 1'b0;
      end
   elsebegin
             case(state)
                                0:begin // led    from low to high                                  
                                        if(count2 < count3)
                                                        begin
                                                           clk_out <= 1'b0;
                                                        end
                                        else begin
                                                           clk_out <= 1'b1;
                                                       end                                               
                               
                                        if(flag_1s)
                                                state <= ~state;
                                        else       
                                                state <= state;                                       
                                  end
                                1:begin // led       from high to low
                                               if(count2 < count3)
                                                                        begin
                                                                        clk_out <= 1'b1;
                                                                        end
                                                  else         begin
                                                                     clk_out <= 1'b0;
                                                                        end                                                                         
                               
                                  end
                                                        default: state <= 1'b0;
                        endcase
                       
          end
end       
               
              
        always @ (posedge clk or negedge rst_n)
begin
   if(!rst_n)
      begin
                  led <= 4'b1111;
      end
   elsebegin
          led <= {4{clk_out}};
             end
end
//        assignled = (!rst_n)?1'b0:{4{clk_out}};
       

               
               
               






               
                       
endmodule






fpga_wuhan 发表于 2016-8-1 09:52:43

赞一个,顶一个!

雾盈 发表于 2016-7-31 15:26:20

我就想知道怎么在文章中间添加图片,谁能告诉我?

zhiweiqiang33 发表于 2016-8-2 10:14:36

谢谢分享,正在学习中;坚持关注;

雾盈 发表于 2016-8-2 10:46:04

zhiweiqiang33 发表于 2016-8-2 10:14
谢谢分享,正在学习中;坚持关注;

支老师还亲自顶贴啊:handshake

zhiweiqiang33 发表于 2016-8-2 19:21:38

必须力挺你,:lol

陈飞龙 发表于 2016-8-3 10:30:06

不错,加油:):):)

Adamancy 发表于 2016-8-10 15:59:13

               为什么中间少了几个

zhiweiqiang33 发表于 2016-8-10 17:47:30

学习了 资料写的很基础很全面 基础入门资料 谢谢

芙蓉王 发表于 2016-8-12 16:32:19

                   感谢分享
页: [1] 2
查看完整版本: 雾盈FPGA笔记之(一):基于FPGA的呼吸灯简单实验(Verilog)