有限状态机FiniteStateMachine例:计数器设计•设计一电路,包含基4计数器,和译码输出模块。计数器的输出(Present_value)从0到3循环;当计数值为2时,译码输出(DataOut)为“1”,否则输出“0”。Regs+1ClkPresent_valueQ(n)Next_valueQ(n+1)译码DataOutZ(n)00/001/010/111/0Regs+1ClkPresent_valueQ(n)Next_valueQ(n+1)译码DataOutZ(n)00/001/010/111/0扩展一个输入端din,当din=1时计数器递增计数;当din=0时计数器递减计数。dinDin=1Din=1Din=1Din=1Din=0Din=0Din=0Din=0Regs+/-1ClkPresent_valueQ(n)Next_valueQ(n+1)译码DataOutZ(n)再将计数器修改成一个状态转换器,状态为S0,S1,S2,S3。每个状态的取值根据具体情况而定。比如S0=00,S1=11,S3=01,S4=10。din00/001/010/111/0Din=1Din=1Din=1Din=1Din=0Din=0Din=0Din=0Regs+/-1ClkPresent_valueQ(n)Next_valueQ(n+1)译码DataOutZ(n)再将计数器修改成一个状态转换器,状态为S0,S1,S2,S3。每个状态的取值根据具体情况而定。比如S0=00,S1=11,S3=01,S4=10。dinS0/0S1/0S2/1S3/0Din=1Din=1Din=1Din=1Din=0Din=0Din=0Din=0Regs+/-1ClkPresent_valueQ(n)Next_valueQ(n+1)译码DataOutZ(n)现在我们得到了一个比较通用的时序电路,这种电路统称为状态机(StateMachine)。dinS0/0S1/0S2/1S3/0Din=1Din=1Din=1Din=1Din=0Din=0Din=0Din=0Regs+/-1ClkPresent_valueQ(n)Next_valueQ(n+1)译码DataOutZ(n)有限状态机概述•数字系统控制部分的每一个控制态可以看作一种状态,与每一个控制态相关的转换条件指定了当前状态的下一个状态和输出。•根据有限状态机的输出与当前状态与当前输入的关系,可以分成Moore型和Mealy型两种类型的有限状态机。Moore状态机和Mealy状态机•Moore状态机的输出只与当前状态有关次态逻辑状态寄存器输出逻辑输入次态现态输出时钟复位Moore状态机和Mealy状态机•Mealy状态机的输出与当前状态机及当前输入信号有关次态逻辑状态寄存器输出逻辑输入次态现态输出时钟复位状态机的表示方法•状态转换表•算法流程图•状态转换图这是最流行的表示方法状态转换图状态1状态4状态2状态3入/出入/出入/出入/出/出Mealy条件控制定序直接控制定序用VHDL描述状态机的组成•一个用来描述有限状态机功能的VHDL语言程序中应该包含以下几个内容:–(1)至少包括一个状态信号,它们用来指定有限状态机的状态;–(2)状态转移指定和输出指定,它们对应于控制单元中与每个控制步有关的转移条件;–(3)时钟信号,它一般是用来进行同步的;–(4)同步或异步复位信号。状态机的VHDL描述方式(1)单进程描述方式:单进程描述方式就是指在VHDL语言程序的结构体中,使用一个进程语句来描述有限状态机中的次态逻辑、状态寄存器和输出逻辑。(2)双进程描述方式:一个进程语句用来描述有限状态机中次态逻辑、状态寄存器和输出逻辑中的任何两个;另外一个进程则用来描述有限状态机剩余的功能。(3)三进程描述方式:一个进程用来描述有限状态机中的次态逻辑;一个进程用来描述有限状态机中的状态寄存器;另外一个进程用来描述有限状态机中的输出逻辑。状态机的VHDL描述方式描述方式进程描述功能三进程描述方式进程1:描述次态逻辑进程2:描述状态寄存器进程3:描述输出逻辑双进程描述方式形式1进程1:描述次态逻辑、状态寄存器进程2:描述输出逻辑形式2进程1:描述状态寄存器、输出逻辑进程2:描述次态逻辑形式3进程1:描述次态逻辑、输出逻辑进程2:描述状态寄存器单进程描述方式进程1:描述次态逻辑、状态寄存器和输出逻辑存储控制器idledecisionreadwritereadyread_writereadyreadyreadyreadyreadyread_write•设计一个存储控制器,它的具体要求为:(1)存储控制器能够根据微处理器的读周期或者写周期,分别对存储器输出写使能信号we和读使能信号oe;(2)存储控制器的输入信号有3个:微处理器的准备就绪信号ready、微处理器的读写信号read_write和时钟信号clk。存储控制器•列出当前状态和输出值的关系状态输出OEWEidle00decision00write01read10建立状态转换表,列出次态和转换条件当前状态次态转换条件idledecisionready=’1’decisionwritew_r=’0’readw_r=’1’writeidleready=’1’writeready=’0’readidleready=’1’readready=’0’•利用VHDL语言进行状态机描述–所有状态均可以表达为CASE-WHEN结构中的一条语句。–状态的转移通过if-then-else语句实现。CASEpresent_stateISWHENidle=输出量;IFELSEENDIF;•有些状态的转换中,在条件满足时,转换到下一个状态,否则保持原来的状态不变。这种情况对应着IF-THEN-ELSE的两个分支。•在这种情况下,ELSE分支并不是必需的。但是缺少ELSE分支,会导致额外的存储器。状态转换•状态描述的步骤:–对每一个状态建立一项CASE语句的分支WHEN状态名=–确定输出变量–通过IF-THEN-ELSE语句指定相应的次态。•例casepresent_stateis--CASE分支whenidle=oe='0';we='0';--确定输出变量if(ready='1')then--确定次态next_state=decision;elsenext_state=idle;endif;例:三进程描述方式1ARCHITECTUREfsmOFmemory_enableISTYPEstate_typeIS(idle,decision,read,write);SIGNALpresent_state,next_state:state_type;BEGINnextstate_logic:PROCESS(present_state,ready,read_write)BEGINCASEpresent_stateISWHENidle=IF(ready=‘1’)THENnext_state=decision;ELSEnext_state=idle;ENDIF;…………………ENDCASE;ENDPROCESSnextstate_logic;例:三进程描述方式2state_register:PROCESS(clk)BEGINIF(RISING_EDGE(clk))THENpresent_state=next_state;ENDIF;ENDPROCESSstate_registe例:三进程描述方式3output_logic:PROCESS(present_state)BEGINCASEWHENidle=we=‘0’;oe=‘0’;WHENdecision=we=‘0’;oe=‘0’;WHENread=we=‘0’;oe=‘1’;WHENwrite=we=‘1’;oe=‘0’;ENDCASE;ENDPROCESSoutput_logic;任务1:空调控制器S1S2S3thigh=0tlow=0thigh=0tlow=1thigh=1tlow=0thigh=0tlow=1thigh=0tlow=0thigh=1tlow=0hot=0cool=0hot=0cool=1hot=1cool=0空调控制器状态转换图任务1:空调控制器S1:表示温度适中,不高也不低,对应着输入信号thigh和tlow均为低电平(无效),空调器既不制冷也不制热,因此输出控制信号hot和cool都是低电平。S2:表示温度太低,对应着输入信号tlow为高电平,thigh为低电平,此时空调器应该工作在制热状态,相应的输出控制信号hot为高电平,cool无效。S3:表示温度太高,对应着输入信号thigh为高电平,tlow为低电平,此时空调器应该工作在制冷状态,相应的输出控制信号cool为高电平,hot无效。任务1:空调控制器状态转换表当前状态转换条件下一状态执行操作输出值S1thigh=0&tlow=1thigh=1&tlow=0S2S3制热制冷hot=1/cool=0hot=0/cool=1S2thigh=0&tlow=0thigh=1&tlow=0S1S3既不制冷也不制热制冷hot=0/cool=0hot=0/cool=1S3thigh=0&tlow=0thigh=0&tlow=1S1S2既不制冷也不制热制热hot=0/cool=0hot=1/cool=0选做:状态机的应用设计例子:设计一个二进制序列检测器,当检测到10110序列时,就输出1(一个时钟周期的脉冲)。其他情况下输出0。规定检测到一次之后,检测器复位到最初始的状态,重新从头检测。如下所示:输入:01101101101100输出:00000001000001状态转换图设计(Moore)10110S0/0S1/0S2/0S3/0S4/0S5/1Reset11001101001010110s1s2s3s4s5s0问题1:如何保证状态机在初始时状态为s0?问题2:在状态机跑飞,即脱离有效状态(s0—s5)时,如何使状态机能恢复工作Sx/0波形•波形如下图所示问题:如果需要将输出脉冲往前推一个时钟周期,该如何修改设计?1011010110s1s2s3s4s5s0输入时钟输出当前状态发现当前状态为s4,并且输入为0时,输出为1。状态转换图设计(Mealy)S0S1S2S3S4S5Reset100110100101sX/0/0/0/0/0/0/0/0/0/1/0/01011010110s1s2s3s4s5s0/00/1s0状态机的代码实现•状态定义ArchitecturertlofSynis…--其他信号定义。TypeSynFsmStateis(s0,s1,s2,s3,s4,s5);SignalSynCst,SynNst:SynFsmState;Begin…--结构体。Endrtl;状态机的代码实现•状态寄存器进程描述状态寄存器输出译码下一状态译码当前状态输出下一状态输入时钟clk•状态寄存器进程描述Process(clk,Reset)Beginif(Reset=‘1’)thenSynCst=S0;--初始状态。elsif(clk’eventandclk=‘1’)thenSynCst=SynNst;--状态转换。endif;Endprocess;状态机的代码实现•状态转换进程描述状态寄存器输出译码下一状态译码当前状态输出下一状态输入时钟clk•状态转换进程描述Process(SynCst,din)BegincaseSynCstiswhens0=whens1=…whens5=…Endcase;Endprocess;if(din=‘1’)thenSynNst=s1;elseSynNst=s0;endif;whenothers=SynNst=s0;状态机的代码实现•输出进程描述状态寄存器输出译码下一状态译码当前状态输出下一状态输入时钟clk•输出进程描述Process(SynCst)BegincaseSynCstiswhens0=when