文章插图
文章插图
文章插图
表1 图2状态机实例的二维表格表示(动作/下一状态)图2为一个状态机实例的状态转移图,它的含义是:在s0状态,如果发生e0事件,那幺就执行a0动作,并保持状态不变;如果发生e1事件,那幺就执行a1动作,并将状态转移到s1态;如果发生e2事件,那幺就执行a2动作,并将状态转移到s2态;在s1状态,如果发生e2事件,那幺就执行a2动作,并将状态转移到s2态;在s2状态,如果发生e0事件,那幺就执行a0动作,并将状态转移到s0态;有限状态机不仅能够用状态转移图表示,还可以用二维的表格代表 。一般将当前状 态号写在横行上,将事件写在纵列上,如表1所示 。其中“--”表示空(不执行动作,也 不进行状态转移),“an/sn”表示执行动作an,同时将下一状态设定为sn 。表1和图2表示 的含义是完全相同的 。观察表1可知,状态机可以用两种方法实现:竖着写(在状态中判断事件)和横着写( 在事件中判断状态) 。这两种实现在本质上是完全等效的,但在实际操作中,效果却截然 不同 。竖着写C代码片段cur_state = nxt_state;switch(cur_state){ //在当前状态中判断事件case s0: //在s0状态 if(e0_event){ //如果发生e0事件,那幺就执行a0动作,并保持状态不变;执行a0动作;//nxt_state = s0; //因为状态号是自身,所以可以删除此句,以提高运行速度 。}else if(e1_event){ //如果发生e1事件,那幺就执行a1动作,并将状态转移到s1态;执行a1动作;nxt_state = s1;}else if(e2_event){ //如果发生e2事件,那幺就执行a2动作,并将状态转移到s2态;执行a2动作;nxt_state = s2;}break;case s1: //在s1状态if(e2_event){ //如果发生e2事件,那幺就执行a2动作,并将状态转移到s2态;执行a2动作;nxt_state = s2;}break;case s2: //在s2状态if(e0_event){ //如果发生e0事件,那幺就执行a0动作,并将状态转移到s0态;执行a0动作;nxt_state = s0;}}横着写(在事件中判断状态)C代码片段//e0事件发生时,执行的函式void e0_event_function(int * nxt_state){int cur_state;cur_state = *nxt_state;switch(cur_state){case s0: //观察表1,在e0事件发生时,s1处为空case s2:执行a0动作;*nxt_state = s0;}}//e1事件发生时,执行的函式void e1_event_function(int * nxt_state){int cur_state;cur_state = *nxt_state;switch(cur_state){case s0: //观察表1,在e1事件发生时,s1和s2处为空执行a1动作;*nxt_state = s1;}}//e2事件发生时,执行的函式void e2_event_function(int * nxt_state){int cur_state; cur_state = *nxt_state;switch(cur_state){case s0: //观察表1,在e2事件发生时,s2处为空case s1:执行a2动作;*nxt_state = s2;}}其它Moore状态机其Moore状态图如图1所示 。S0/0S1/1S3/0S2/100110011其中S0/0所代表的意思为现在是状态S0且输出为0,状态图最主要是将每个状态都给予一个编号,详细描述如下:1) 在某状态时,列出所有的输出条件 。2) 在某状态时,当输入信号是什幺则会跳至哪一个状态 。3) 在某状态时,当输入信号是什幺则会维持原状态不变 。可以将图1的Moore状态机写成状态表如表1.表1 Moore状态表现态次态输出输入X=0X=1X=0X=1S0S0S100S1S1S211S2S3S000S3S0S300状态表主要描述它与状态图的关係,再设计状态机电路是,需要先定义状态机的变数,定义状态机的变数时使用枚举类型来定义,如下範例所示:Type State is (S0,S1,S2,S3)接下来,状态会被加以编码 。其状态编码方式如下:(1) 时序编码(Sequential)将每个状态以二进制来做编码 。(2)格雷码(Gray)也是将四个State以二进制来编码,不过不同的是每次编码只会差一个位,其主要缺点是状态改变是要依序改变才可以,若状态不是依序是,则Gray编码不适用 。(3) 独热码(One hot)独热码状态编码的特色为每一个状态均有自己的触发器,所以若有N个状态就也存在有N个触发器,在任一时刻只会有一组状态编码,缺点是会产生较大的电路,但是相对的使用独热码状态编码对帧错相当有帮助 。三种格式之状态编码如表2所示 。状态时序编码Gray编码One hot编码S000000001S101010010S210110100S311101000从状态编码表可以看出时序编码和Gray编码均是用二个位来做编码,而以独热码作为编码方式则编码位增加至四个位,所以电路比其他两种编码方式都大一些 。所以可以使用属性来定义编码方式,若要编码成独热码编码,则可加上:Type State is (S0,S1,S2,S3);Attribute encoding of state;Type is “0001 0010 0100 1000”;在设计状态机时,通常使用进程语句来描述状态机,其中进程语句又可以分为三种方式:n 一个进程利用一个进程来描述状态的转换及输出信号的定义 。n 两个进程一个为时序电路主要负责状态变数的更新,此进程为同步电路,而另一个进程语句主要是描述下次态变数和输出的更新 。n 三个进程第一个进程主要负责状态变数的更新,第二个进程语句负责描述次态变数,而最后一个则是负责输出信号的更新 。有了以上的初步观念,可以设计图1四个状态的Moore状态机 。範例首先根据之前的状态表编写VHDL程式如下所示:Library ieee;Use ieee.std_logic_1164.all;Use ieee.numeric_std.all;Entity moore_fsm isPort(clk : in std_logic;rstn : in std_logic;x : in std_logic;output : out std_logic);End moore_fsm;Architecture rtl of moore_fsm isType state is (s0,s1,s2,s3); ---状态定义Signal current_state : state; ---现态Signal next_state : state; ---次态BeginStatefsm: process(rstn, x, current_state)BeginIf rstn = ‘0’ then --异步resetnext_state <= s0;output <= ‘0’;elsecase current_state iswhen s0 =>if x =’0’ thennext_state <= s0;elsenext_state <= s1;end if;output <= ‘0’;when s1 =>if x =’0’ thennext_state <= s1;elsenext_state <= s2;end if;output <= ‘1’;when s2 =>if x =’0’ thennext_state <= s3;elsenext_state <= s0;end if;output <= ‘0’;when s3 =>if x =’0’ then next_state <= s0;elsenext_state <= s3;end if;output <= ‘0’;end case;end if;end process statefsm;stat: process(clk) --current_stateànext_statebeginif rising_edge (clk) thencurrent_state <=next_state;end if;end process stat;end rtl;1) 编码方式预设为时序编码2) 使用两个进程语句来设计状态机其综合电路如图2 所示 。其状态图如图3 所示 。Moore FSM 模拟波形如图4 所示 。模拟结果说明:(1) 由于reset 为异步reset ,所以当reset在150ns~200ns为0时,则状态图会从s1回到s0.(2) 在50 ns时输入x为0且现态为1,在70 ns 时clk上升沿触发且x为1,则current_state会变成next_state s2;Mealy状态机接下来我们要介绍Mealy状态机,它和输入、输出、状态皆有关 。它的状态图、状态表与Moore状态机都有所不同,输出会随输入变化而变化 。如图5 所示 。0/0图5:S0S1S3S20/11/10/10/01/11/0 1/0若现态为s0输入为0时,则次态为s0且输出为0;若现态为s0输入为1时,则次态为s1且输出为1 。根据这个规则,列出Mealy状态机的状态表如表3 。现态次态 输出输入X=0X=1X=0X=1S0S0S101S1S2S110S2S3S001S3S0S310其Mealy状态机的VHDL如下所示:Library ieee;Use ieee.std_logic_1164.all;Use ieee.numeric_std.all;Entity melay_fsm isPort(clk: : in std_logic;rstn : in std_logic;x : in std_logic;output : out std_logic);End moore_fsm;Architecture rtl of moore_fsm is Type state is (s0,s1,s2,s3); ---状态定义Signal current_state : state; ---现态Signal next_state : state; ---次态BeginStatefsm: process(rstn, x, current_state)BeginIf rstn = ‘0’ then --异步resetnext_state <= s0;output <= ‘0’;elsecase current_state iswhen s0 =>if x =’0’ thennext_state <= s0;elsenext_state <= s1;end if;if x= ‘0’ thenoutput <= ‘0’;elseoutput <= ‘1’;end if;when s1 =>if x =’0’ thennext_state <= s2;elsenext_state <= s1;end if;if x= ‘0’ thenoutput <= ‘1’;elseoutput <= ‘0’;end if;when s2 =>if x =’0’ thennext_state <= s3;elsenext_state <= s0;end if;if x= ‘0’ thenoutput <= ‘0’;elseoutput <= ‘1’;end if;when s3 =>if x =’0’ thennext_state <= s0;elsenext_state <= s3;end if;if x= ‘0’ thenoutput <= ‘1’;elseoutput <= ‘0’;end if;end case;end if;end process statefsm;stat: process(clk) --current_stateànext_statebeginif prsing_edge (clk) then current_state <=next_state;end if;end process stat;end rtl;Mealy状态机综合电路如图6 所示 。