集成电路技术分享

 找回密码
 我要注册

QQ登录

只需一步,快速开始

搜索
查看: 4456|回复: 10

紫龙笔记(1)之led流水灯综合

[复制链接]
宇宙第一帅 发表于 2016-8-18 00:53:06 | 显示全部楼层 |阅读模式
   FPGA笔记(1)
——LED_RUN综合
                                  紫龙
序言:
        今天是我在西安ZXOPEN学习的第二十五天,对于一个毫无基础的学生而言,开始无疑是痛苦的,从刚开始创建文件还需要老师一步一步教着,步骤老记不住,打了BEGIN却忘记END等等,一步一步走到现在,确实很艰难。我不是一个很聪明的学生,却有着迷之自信,带着这份麻木的不知天高地厚的自信,我一个人笑着从小学走到现在。一个人的旅途确实很孤独,不过静享这份温柔的孤独,有时却是一份惬意与自得,至少,明天阳光很好...

回归主题:
        咳咳•••说了太多无关紧要的东西,不要见怪! 很早就想发点东西来记录我的学习进程了,却一直忙于打基础(笔记班上的大神很多,像我们这种什么都不会的菜鸟,哎。。。),正好今天总结了一番,就从刚开始的LED_RUN开始吧。
正言:
LED_RUN,顾名思义,就是让LED灯“跑”起来,达到所谓的流水效果。
但是,通过FPGA并不是这么简单的说跑他就能跑。首先,我们得了解它“跑”的原理-----正如人跑一样,人跑步需要能量的提供,无能量,无驱动。哈哈,也算一个比方而已~
在我们ZX2开发板上,有四个LED灯,让他达到流水的效果,则需要LED灯依次点亮,当然这个点亮时间也有相应的要求,太快,LED闪烁太快,人眼分辨不出他流水的效果,于是这样就会出现大概三种情况:
第一种:频率太快,出现几个LED同时亮,但亮度却不饱满,这是由于LED点亮完全的时间是1MS到2MS,如果频率小于这个时间,第一个LED灯未点亮完全,第二个却开始点亮,同理第三四个。由于频率太快人眼分辨不出其闪烁,这时我们看到的现象就是LED亮度不饱满的效果。
第二种:频率刚好,达到LED点亮的饱和时。在1000HZ的时候,咱们人眼分辨不出其闪烁,看到的LED无闪烁,同时,(1*10^)/1000=1MS,其点亮时间达到1MS,也就意味着达到了LED点亮饱和时间,此时LED亮度最佳。于是我们看到的情况是四个LED灯全部点亮。
第三种:频率稍慢,这种情况,LED灯亮度达到饱和,而且,当第一个LED由亮到熄灭的时间,第二个LED灯能够及时反应过来,我们的人眼也能够清楚的分辨出来。此时LED灯将会依次点亮,达到流水的效果。
原理图如下:

今天,我将通过三种不同方式来实现流水效果,当然,我们也适量做做第二种情况。
FIRST:
      传统的一段式的状态机的方法:
module led_run(
        input clk,  //input wire clk
        input key,
       
        output reg [3:0] pio_led
        );

        reg [2:0] state;
        reg [31:0] counter;

       
        always @ (posedge clk_5 or negedge key)
        begin
                if (key == 0)  //按键按下,这为复位键,低电平有效
                        begin
                                pio_led <= 4'b1111;   //4'd15   15    4'hf
                                state <= 0;
                        end
                else
                        begin
                        case (state)
                        0 : begin
                                        pio_led <= 4'b1110;   
                                        state <= 1;
                                 end
                        1 : begin
                                        pio_led <= 4'b1101;   
                                        state <= 2;
                                 end
                        2 : begin
                                        pio_led <= 4'b1011;   
                                        state <= 3;
                                 end
                        3 : begin
                                        pio_led <= 4'b0111;   
                                        state <= 0;
                                 end         
                        default : state <= 0;
                        endcase               
                        end
        end


// 分频模块
always @ (posedge clk or negedge rst_n)
begin
        if (!rst_n)
                begin
                        clk_5 <= 0;
                        counter <= 0;
                end
        else
                begin
                        if (counter == 12500000 - 1)
                                begin       
                                        clk_5 <= ~clk_5;
                                        counter <= 0;
                                end
                        else
                                begin
                                        counter <= counter + 1;
                                end
                end
end


endmodule
个人觉得这个方法很蠢啊, = =  别见怪,其实和这个差不多的程序还有一个,这下面,换汤不换药,大家就看看就好:
module led_run(
   input clk,
        input key,
       
        output reg [3:0]poi_led
);

reg [1:0]state;
reg [31:0]counter;

parameter T=25000000-1;

always @ (posedge clk or negedge key)
  begin
     if(key==0)
      begin
                   poi_led <= 4'b1111;
                        state <= 0;
                        counter <=0;
                        end
                else
                  begin
                      case(state)
                        0:begin
                                  if (counter<T)
                                        begin
                         poi_led <= 4'b1110;
                              counter=counter+1;
                                        state <= 0;
                                        end
                                        else
                                                begin
                                                          counter<=0;
                                                        state <= 1;
                                                end
                          end
                                         
                                        1:begin
                                        if (counter<T)
                                        begin
                         poi_led <= 4'b1101;
                                        counter=counter+1;
                              state <= 1;
                                        end
                                        else
                                           begin
                                                counter<=0;
                                                state <=2;
                                                end
                                        end
                         2:begin
                                        if (counter<T)
                                        begin
                         poi_led <= 4'b1011;
                                        counter=counter+1;
                                   state <= 2;
                               end
                                         else
                                           begin
                                                counter <= 0;
                                                state <= 3;
                                                end
                                        end
                         3:begin
                                        if (counter<T)
                                        begin
                         poi_led <= 4'b0111;
                                        counter=counter+1;
                                   state <= 3;
                               end
               else
                  begin               
                                        counter <= 0;
                                   state <=0;       
                                           end
                                   end       
                            endcase
            end
end
endmodule
哈哈,大家有没有发现其实这两个都一样,没错~  后者只是省掉了一个分频模块,用一个计数器嵌套在一段式状态机中而已。 刚开始咱们都比较喜欢使用一段式状态机,但是从专业性角度来说,一段式状态机很多时候并不是适合用于大型工程中,这个问题,咱们下回再讨论。下面咱们用三段式状态机完成。
Second:
三段式状态机法:
    module led_run(
                                        input clk        ,
                                        input rst_n      ,
                                        output reg [3:0]poi_led
               );
//------middle_signal-------
reg [31:0]counter                 ;
reg  clk_out          ;
reg [3:0]CS                            ;
reg [3:0]NS                                 ;
parameter IDLE = 3'd0 ;
parameter S0 = 3'd1   ;
parameter S1 = 3'd2   ;
parameter S2 = 3'd3   ;
parameter S3 = 3'd4   ;
//-----counter--------------
always @ (posedge clk or negedge rst_n)
   begin
                if(!rst_n)
                        begin
                                counter  <= 3'd0 ;
                                clk_out  <=1     ;
                        end
                else if(counter == 12500000-1)
                        begin
                        counter <= 3'd0      ;       
                        clk_out <= ~clk_out  ;
                        end
                        else
                        counter <= counter +1;
        end

//-----FSM1-----------------
always @(posedge clk_out or negedge rst_n)
   begin
           if (!rst_n)
                   begin
                                CS <=  IDLE ;
                        end
                else
                        begin
                                CS <=  NS         ;
                        end
        end
//----FSM2------------------
always @(*)
   begin
           if (!rst_n)
                   begin
                        NS = IDLE ;
                        end
                else
                        case(        CS)
                                IDLE: NS =S0 ;    //NS        是CS的下一个状态
                        S0:                               
                                   NS = S1 ;
                        S1:
                                   NS = S2 ;
                        S2:
                              NS = S3 ;
                   S3:
                                   NS = S0 ;
                               
                                default NS = S0 ;
                        endcase
        end
//-----FSM3-------------------
always @(posedge clk or negedge rst_n)
   begin
           if (!rst_n)
                   begin
                        poi_led <= 4'b1111    ;
                        end
                else
                case (NS)
                IDLE:
                        begin
                                poi_led <= 4'b1111 ;
                        end
                S0:
                   begin
                                poi_led <= 4'b1110 ;
                        end
                S1:
                        begin
                                poi_led <= 4'b1101 ;
                        end
                S2:
                        begin
                                poi_led <= 4'b1011 ;
                        end
                S3:
                        begin
                                poi_led <= 4'b0111 ;
                        end
                default :poi_led <= 4'b1111;
           endcase
        end
endmodule
三段式的状态机,通俗点说:第一段,是对状态的初始赋值,第二段,是对状态的转移,第三段是对状态的描述。三段式咱们以后工作上用到得会很多,因此,尽管咱们不熟练,硬着头皮也多练。
Thired:
  第三种,也是我认为最简便的一种,这是用线性序列机完成的。对于线性序列机,大致结构如下:
                1:输入输出端口,这个基本上每个独立程序都有;
                2:计数器count的定义;
                3:case(count)。
由于我们使用线性序列机,在case(count)中,当我们count达到一个固定值,我们对输出赋值,但是,此后到第二个固定count值,其输出将会保持不变。
module lsm(
                        input  clk     ,
                        input  rst_n   ,
                        output reg [3:0]poi_led
                           );
                       
//------middle_signal-------
reg [31:0]count;       
//-------lsm1---------------
always @(posedge clk)
         begin
                if(!rst_n || count==80000000)
                        begin
                        count<=0                          ;
                        end
                else
                        count <= count+1 ;
         end
//------lsm2------------------
always @(posedge clk)
        begin
                if(!rst_n)
                        begin
                                poi_led<=4'b1111                                ;
                        end
                else
                case(count)
                0:poi_led<=4'b1110                                        ;
                20000000:poi_led<=4'b1101              ;
                40000000:poi_led<=4'b1011              ;
                60000000:poi_led<=4'b0111              ;
                endcase
        end                       
endmodule               
        是不是很简单呢?序列机方法和其他相比,既简单又易于整理改变。 三种方法咱们都可以通过改变程序中的数值如第一个中的T值,第二个中的counter值,第三个中count值,来实现全亮到led流水灯的转变,也可以改变led位选来实现各种操作,如警报,交互点亮等等,当然,这也是大家自己练习的小操作了。下次我整理一到三段式的区别以及用法,第一次发帖,水平不够,见谅哈~                                                                       
zhiweiqiang33 发表于 2016-8-18 09:07:55 | 显示全部楼层
万事开头难,具备坚韧不拔的耐力,遇到问题迎刃而解,慢慢的能力就提升,当然这个过程很痛苦也很刺激;坚持,
Esmiamor 发表于 2016-8-18 11:01:26 | 显示全部楼层
                加油。
 楼主| 宇宙第一帅 发表于 2016-8-18 17:58:31 | 显示全部楼层

恩恩  谢谢
 楼主| 宇宙第一帅 发表于 2016-8-18 17:59:31 | 显示全部楼层
zhiweiqiang33 发表于 2016-8-18 09:07
万事开头难,具备坚韧不拔的耐力,遇到问题迎刃而解,慢慢的能力就提升,当然这个过程很痛苦也很刺激;坚持 ...

恩恩  我会加油的 男人   没有不行这个道理
zhiweiqiang33 发表于 2016-8-18 19:25:06 | 显示全部楼层
力挺同学 ,加油;
芙蓉王 发表于 2016-8-19 09:09:11 | 显示全部楼层
                      同学加油,很看好你
陈飞龙 发表于 2016-8-25 15:33:06 | 显示全部楼层
:o:o:o:o:o:o:o:o:o:o:o:o:o:o:o:o:o:o
 楼主| 宇宙第一帅 发表于 2016-8-25 22:45:42 | 显示全部楼层

阿龙!!!终于看到我了  注意到我的昵称没?!!!  你的书就没发给我啊 ,心疼 ,今天晚上我发一个计算器的,正在弄,你也太让我心寒了
Blondie 发表于 2016-8-26 09:19:45 | 显示全部楼层
                           
您需要登录后才可以回帖 登录 | 我要注册

本版积分规则

关闭

站长推荐上一条 /1 下一条

QQ|小黑屋|手机版|Archiver|fpga论坛|fpga设计论坛 ( 京ICP备20003123号-1 )

GMT+8, 2025-6-28 09:13 , Processed in 0.138000 second(s), 19 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表