用VHDL设计有限状态机的方法

2006-05-07 15:49:34来源: 电子技术应用


    利用VHDL设计状态机,不需要进行繁琐的状态分配、绘制状态表和化简次态方程。设计者不必使用卡诺图进行逻辑化简,不必画电路原理图,也不必搭试硬件电路进行逻辑功能的测试,所有这些工作都可以通过EDA工具自动完成。应用VHDL设计状态机的具体步骤如下:

    (1)根据系统要求确定状态数量、状态转移的条件和各状态输出信号的赋值,并画出状态转移图;

    (2)按照状态转移图编写状态机的VHDL设计程序;

    (3)利用EDA工具对状态机的功能进行仿真验证。

    下面以离心机定时顺序控制器的设计为例,说明状态机的设计方法。

2 定时顺序控制状态机的设计

   
在化工生产中,离心机用于固、液分离的工艺流程,如图1所示。

    从加料至刮刀回程循环N次之后,进入大洗网工序,随后又开始进入新一轮顺序循环工作。该系统控制器的框图如图2所示。

    图2中计数模块是由三个带异步复位和并行预置的计数器组成。其中COUNTER1是2位加/减法计数器,用于控制从加料至刮刀回程的各工序时间,其中加料和卸料工序为加计时,其余工序为减计时;COUNTER2是3位减法计数器,用于控制大洗网的时间;COUNTER3是2位加法计数器,用于控制循环工作次数。译码器用于选通与各工序相对应的预置数。图2中K1、K2分别是加料和卸料限位开关信号,R{R1、R2、R3}为计数器减为零(或循环次数等于预置数)时发出的信号,它们都可作为状态转移的控制信号。LD(LD1、LD2、LD3)为并行置数控制信号,CLR(CLR1、CLR2、CLR3)为异步清零信号,ENA(ENA1、ENA2)为计数使能信号,J为加/减计数控制信号,G(G1、A、B、C)为译码器控制信号,FO为各工序电磁阀和指示灯控制信号。

    系统工作方式如下:当系统处于初始状态或复位信号reset有效时,系统处于复位状态。按下自动工作键C0,系统进入加料工序并开始自动控制离心机的运行。以加水工序为例,首先为加水预置数状态(water_ld)时,状态机输出信号FO,开启加水电磁阀及指示灯,同时输出信号G控制选通加水时间预置数,在LD1信号的控制下,将预置数送入COUNTER1。此时ENA1=1,J=1,使计数器为减计数状态。然后,在下一个时钟周期进入加水工作状态(water),并开始减计时。当计时为零时,计数器发出借位信号R1作为此工序结束的信号送入状态机,使其转入下一个工作状态。根据系统要求可画出状态转移图如图3所示。其中图3表示各状态转移的顺序和转移条件,表1列出了与各状态相应的输出信号值。

表1 离心机控制器的各状态输出信号值

序号 状态 Clr1 clr2 Clr3 J Ena1 Ena2 G C B A Ld1 Ld2 Ld3 F0
S0 System- 1 1 0 0 0 0 1 1 0 1 0 0 1 0000000
reset
S1 Load 0 0 0 0 1 0 0 0 0 0 0 0 0 0000001
S2 One_dry_ 0 0 0 1 1 0 1 0 0 0 K1 0 0 0000010
S3 WQater_ld 0 0 0 1 10 0 1 0 0 1 R1 0 0 0000100
S4 water 0 0 0 1 1 0 0 0 0 1 0 0 0 0000100
S5 Two_dry 0 0 0 1 1 0 1 0 1 0 R1 0 0 0001000
ld
S6 Two_dry 0 0 0 1 1 0 0 0 1 0 0 0 0 0010000
S7 Unload R1 0 0 0 1 0 0 0 0 0 0 0 0 0010000
reset
S8 unload 0 0 0 0 1 0 0 0 0 0 0 0 0 0010000
S9 Return_ 0 0 0 1 1 0 1 0 1 1 K2 0 0 0100000
trip
S10 decision 1 0 0 1 1 0 R3 1 0 0 0 R3 0 0000000
S11 wash 0 0 1 1 0 1 0 0 0 0 0 1 0 1000000
S12 Cycle-ld 0 1 0 0 0 0 1 1 0 1 0 0 1 0000001

    按照状态转移图可编写状态机的VHDL源程序。采用双进程描述法设计的离心机控制器源程序如下:
    library ieee;

    use ieee.std_logic_1164.all;

    entity controller isport (c0,reset: in std_logic;

    clk1,k1,k2,r1,r2,r3: in std_logic;

    clr1,clr2,clr3,j,enal,ena2: out std_logic;

    ld1,ld2,ld3,g1,a,b,c: out std_logic;

    fo: out std_logic_vector(6 downto 0));

    end controller;architecture state_machine of controller is

    type statetype is(system_reset,load_dry,water_ld,water,two_dry_ld,

    two_dry,unload_reset,unload,return_trip,decision,wash,cycle_ld);

    signal present_state,next_state : statetype;

    begin

    state_comb:process (present_state,c0,reset,k1,k2,r1,r2,r3)begin

    if reset='1' then

    clr1<='1';clr2<='1';clr3<='1';j<='0';enal<='0';

    ena2<='0';

    fo<="0000000";ld1<='0';ld2<='0'ld3<='0';

    next_state <= system_reset;

    else

    case present_state is

    when system_reset =>

    clr1<='1';clr2<='1';clr3<='0';j<='0';

    ena1<='0';ena2<='0';

    g1<='1';c<='1';b<='0';a<='1';

    fo<="0000000";ld1<='0';ld2<='0';ld3<='1';

    if (c0='1') then

    next_state<=ldad;

    else

   next_state<=system_reset;

    end if;

    when load =>

    clr1<='0';clr2<='0';clr3<='0';j<='0';

    ena1<='1';ena2<='0';

    g1<='0';c<='0';b<='0';a<='0';

    fo<="0000001";ld1='0';ld2<='0';ld3<='0';

    if (k1='1') then

    next_state<=one_dry;

    else

    next_state<=load;

    end if;

    ……

    end case;

    end if;

    end process state_comb;

    state_clocked:process(clk1,reset)

    begin

    if reset='1' then

    present_state<=system_reset;

    elsif rising_edge(clk1) then

    present_state<=next_state;

    end if;

    end process state_clocked;

    end state_machine;

    利用EDA软件MAX+plus Ⅱ对该程序进行编译、仿真,其仿真波形见图4。

    从图4仿真波形图上可以看出,状态机的输出信号有许多“毛刺”产生。如何消除这些“毛刺”是下面将讨论的问题。

3 在状态机设计中如何消除“毛刺”

   
在同步电路中,一般情况下,“毛刺”不会产生重大影响。因为“毛刺”仅发生在时钟有效边沿之后的一小段时间内,只要在下一个时钟有效边沿到来之前“毛刺”消失即中。但是,由于状态机的输出信号都是作为其它功能模块的控制信号,如果这些控制信号作为异步控制(如本系统中的CLR)、三态使能控制或时钟信号来使用,则将会使受模块发生误动作,造成系统工作混乱。因此,在这种情况下必须保证状态机的输出没有“毛刺”。

    消除状态机输出信号的“毛刺”有以下三种方案:

    ·在状态机输出信号较少的情况下,直接把状态作为输出信号;

    ·对于顺序迁移的状态机,选择雷格码作为状态编码;

    ·在Moore型或Mealy型状态机基础上,用时钟同步输出信号。

    本设计采用后两种方案,较简便。雷格码的特点是:当状态机改变状态时,状态向量中仅1位发生变化。与前面用可枚举类型定义的状态变量不同,现在选用常数来指定各状态变量的取值为格雷码。修改部分设计程序如下:

    architecture state_machine of controller1 is

    signal present_state,next_state:std_logic_vector(3 downto 0);

    constant load:std_logic_vector(3 downto 0):="0001";

    constant one_dry: std_logic_vector(3 downto 0):="0011";

    constant water_ld;std_logic_vector(3 downto 0):="0010";

    constant water:std_logic_(3 downto 0):="0110";

    constant two_dry_ld:std_logic_vector(3 downto 0):="0111";

    constant two_dry:std_logic_vector(3 downto 0);="0101";

    constant unload_reset:std_logic_vector(3 downto 0):="0100";

    constant unload:std_logic_vector(3 downto 0);="1100";

    constant return_trip:std_logic_vector(3 downto 0):="1101";

    constant decision:std_logic_vector(3 downto 0):="1111";

    constant wash:std_logic_vector(3 downto 0):="1110";

    constant cycle_ld:std_logic_vector(3 downto 0):="1010";

    ……

    若要安全消除状态机的“毛刺”,则应采用第三种方案。这时,设计程序要作相应改变,状态的转移和输出信号的赋值要写在同一步时钟进程中。

    综上所述,采用VHDL设计状态机,能够大大降低设计难度。使用双进程描述风格编写VHDL设计程序,可以清楚地在一个进程中确定状态的转移和对输出的赋值,而且具有易于建立、理解和维护的优点。特别针对大型或具有大量状态转移和输出信号的状态机设计,将会更加显示出它的优势。对于状态机输出信号所产生的“毛刺”,可以按照系统的要求,根据不同的情况采用相应的设计方案予以消除。

编辑: 引用地址:http://www.eeworld.com.cn/designarticles/sensor/200605/1496.html
本网站转载的所有的文章、图片、音频视频文件等资料的版权归版权所有人所有,本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如果本网所选内容的文章作者及编辑认为其作品不宜公开自由传播,或不应无偿使用,请及时通过电子邮件或电话通知我们,以迅速采取适当措施,避免给双方造成不必要的经济损失。
论坛活动 E手掌握
微信扫一扫加关注
论坛活动 E手掌握
芯片资讯 锐利解读
微信扫一扫加关注
芯片资讯 锐利解读
推荐阅读
全部

小广播

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 安防电子 医疗电子 工业控制

北京市海淀区知春路23号集成电路设计园量子银座1305 电话:(010)82350740 邮编:100191

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号 电信业务审批[2006]字第258号函 京公海网安备110108001534 Copyright © 2005-2016 EEWORLD.com.cn, Inc. All rights reserved