专栏中心

EEPW首页 > 专栏 > FPGA学习之——状态机实现流水灯(源码分析)

FPGA学习之——状态机实现流水灯(源码分析)

发布人:fwjie 时间:2012-02-24 来源:工程师 发布文章

Verilog HDL描述的电路大都是并行实现的,状态机就是通过不同的状态迁移来完成一些特定的顺序逻辑。

 

流水灯状态机 

用一个按键sel来控制流水灯的流向,而流水灯的流动是通过状态机来实现的,设计一个流水灯,由四个LED组成,流动间隔一秒,可以按键控制流向(向左还是右),代码如下:

/********************************文件信息**************************************

** 文件名称:state_machine

** 文件作者:樊文杰

** 创建日期:2012.02.16

** 软件平台:Quartus II 9.0

** 硬件平台:EP2C5T144C8

** 功能描述:状态机的行为级描述(顶层模块)

** 实验效果:按下复位键(P67)则四个LED全亮,松开则开始流水效果,按下SEL(P57)

**                 则在等待一次闪动后,开始向相反方向流水(原因是在下一个时钟周期内才检测按键)

**                 

**--------------------------------------修改文件的相关信息----------------------

** 修改人:

** 修改日期:           

** 版本号:

** 修改内容:

**

*******************************************************************************/

module state_machine(

       clk,                                                                 //时钟输入,20M               

       reset_n,                                                           //复位输入,低电平有效

       sel,                                                                 //流水灯方向控制端,0:按下,1:放开

       Q                                                                    //输出,1:点亮,0:熄灭

       );

       input       clk;                                                        //输入

       input       reset_n;

       input       sel;

       output   [3:0] Q;                                            //输出

       reg          [3:0] Q;                                           //寄存器定义

      

       wire        clk_out;                                           //计数的时钟,分频得到,周期:1S

       reg          [2:0] sts;                                          //状态机的状态

             

       parameter       st1 = 2'b00,                                        //状态机状态1参数定义

                            st2 = 2'b01,                                 //状态机状态2参数定义

                            st3 = 2'b10,                                 //状态机状态3参数定义

                            st4 = 2'b11;                                 //状态机状态4参数定义

                           

       //***********************************************************/

       //     模块名称:状态机描述

       //     模块功能:根据不同的状态实现流水灯的左移和右移

       //***********************************************************/

       always@(posedge clk_out or negedge reset_n)

       begin

              if(!reset_n)

                     begin

                            Q <= 4'b1111;                             //复位的时候值为灯全亮

                            sts <= st1;                                   //初始状态

                     end

              else

                     case(sts)                                            //通过不同的状态来实现流水灯的迁移

                            st1:                                            //状态1

                                   begin

                                          Q <= 4'b0001;               //第一状态的第一位输出1

                                          if(sel)

                                                 sts    <= st2;           //根据SEL判断流水灯方向

                                          else

                                                 sts <= st4;

                                   end

                            st2:

                                   begin

                                          Q <= 4'b0010;               //第二个状态第二位输出1

                                          if(sel)

                                                 sts <= st3;

                                          else

                                                 sts    <= st1;

                                   end

                            st3:

                                   begin

                                          Q <= 4'b0100;               //第三个状态第三位输出1

                                          if(sel)

                                                 sts <= st4;

                                          else

                                                 sts <= st2;

                                   end

                            st4:

                                   begin

                                          Q <= 4'b1000;               //第四个状态第四位输出1

                                          if(sel)

                                                 sts <= st1;

                                          else

                                                 sts <= st3;                                         

                                   end

                            default:

                                   sts <= st1;                                   //复位的时候为状态1

                     endcase                                     

       end

      

 

       //***********************************************************/

       //     分频模块例化

       //     从分频模块得到周期为1s 的方波

       //***********************************************************/

clk_div clk_div_0

              (

              .clk(clk),

              .reset_n(reset_n),

              .clk_out(clk_out)

              );           

Endmodule

以下是分频模块源码:

/********************************文件信息**************************************

** 文件名称:state_machine

** 文件作者:樊文杰

** 创建日期:2012.02.16

** 软件平台:Quartus II 9.0

** 硬件平台:EP2C5T144C8

** 功能描述:状态机的行为级描述(分频模块,产生周期为1S的方波)

** 实验效果:

**                 

**--------------------------------------修改文件的相关信息----------------------

** 修改人:

** 修改日期:           

** 版本号:

** 修改内容:

**

*******************************************************************************/

module clk_div(

       clk,                                                   //     时钟输入,20M

       reset_n,                                                    //     复位,高电平有效

       clk_out                                                     //     分频时钟输出

       );

      

       parameter       cnt_top = 26'd10000000;       //     分频系数

       input              clk;                              //     端口

       input              reset_n;

       output            clk_out;

       reg                 clk_out;

       reg                 [25:0]     clk_cnt;          //     时钟计数器

      

always@(posedge clk or negedge reset_n)

       begin

       if(!reset_n)                                               // 复位

              begin

                     clk_out <= 1'b0;                   //     清零

                     clk_cnt <= 0;

              end

       else

              begin

                     if(clk_cnt == cnt_top - 1)  //       0.5 S计数到

                            begin

                                   clk_out <= ~clk_out;//   分频输出(翻转电平)

                                   clk_cnt <= 0;         //     计数清零

                            end

                     else

                            clk_cnt <= clk_cnt + 1'b1;//   计数器加1                                              

              end

       end

endmodule

 

实验效果是,流水灯从LED1向LED4流动,按下sel键后在等待一次流动再向相反方向流动,按下复位键,灯全亮!

四个流水灯共四种状态来实现“流动”效果,而这四种状态是预先定义好的,通过时钟周期来向下一个状态迁移达到效果,所以就定义了st1-st4这四种状态,在每种状态中都已经定义好了LED的亮灭情况,那么为什么按下sel后再等待一次闪动才相反流动呢,因为,FPGA是按时钟周期工作的,在这个时钟周期开始时已经判断了进入哪种状态,然后执行这个状态中的已定义好的逻辑,所以这时在这种状态中并没有检测sel的状态,而是按这个时钟周期开始前的sel状态执行,然后切换状态(已经按下了sel键),在下一个时钟周期,从新检测sel并判断状态,然后才按sel的状态切换状态,从而改变流动方向,应该是这要的。

专栏文章内容及配图由作者撰写发布,仅供工程师学习之用,如有侵权或者其他违规问题,请联系本站处理。 联系我们

关键词:

相关推荐

你会问应聘模拟开发岗位的求职者什么?

基于新技术电源控制IC的绿色高效 高功率密度电源的设计

视频 2010-06-12

AI 正在学习撒谎、策划和威胁其创造者

智能计算 2025-06-30

如何让QLC技术成为主流?

2025-06-30

如何使用智能设计来加强稀土回收

Siemens对数字孪生的芯片、封装老化进行建模

力科示波器助力电源研发(上)

视频 2010-06-12

电源产品的可靠性设计(下)

视频 2010-06-12

了解ADC规格和架构:第5部分

模拟技术 2025-06-30

软银CEO孙正义:未来10年要成为全球最大超级AI平台供应商

说文解字

唐朝 2003-08-05

中国的人形机器人似乎比人类更能激发足球的兴奋

机器人 2025-06-30

Wise计划将GaN和数字控制器封装在一起

LinkSwitch-PH与LinkSwitch-PL可为LED照明提供最优化解决方案

视频 2010-06-18

力科示波器助力电源研发(下)

视频 2010-06-01

原理简单但实践复杂的总线技术:第 1 部分

更多 培训课堂
更多 焦点
更多 视频

技术专区