目录
1.VHDL状态机的一般形式
2.Moore有限状态机的设计
3.序列检测之状态机设计
前言:
有限状态机机器设计技术是使用数据系统设计中的重要组成部分,也是实现效率高,高可靠和速度控制逻辑系统的重要途径,广义而论,只要涉及触发器的电路,无路电路大小,都能归结为状态机。
1.说明部分:
说明部分使用TYPE语句定义新的数据类型,此数据类型为枚举类型,其元素通常都用状态机的状态来定义,状态变量(如次态和现态)应定义为信号,便于信息的传递,并将状态机的数据类型定义为含有既定状态元素的新定义的数据类型。说明部分,一般放在结构体ARCITECTURE和BEGIN之间,如下:
ARCHITECTURE ....IS
TYPE FSM_ST IS(S0,S1,S2,S3);
SIGNAL current_state,next_state :FSM_ST;
BEGIN
2.主控时序进程:
3.主控组合过程:
4.辅助进程:
例子:下面的例子是由两个主控进程构成的,其中含有主控时序进程和主控组合进程(注意:c_st表示current_state):
结构图如下:
程序如下:
library ieee;
use ieee.std_logic_1164.all;
entity FSM_EXP is
port( clk,reset :in std_logic; --状态机工作时钟和复位信号
state_input :in std_logic_vector(0 to 1); --来自外部的状态机控制信号
comb_outputs:out integer range 0 to 15); --状态机对外部发出的控制信号
end FSM_EXP;
architecture BHV of FSM_EXP is
TYPE FSM_ST is (s0,s1,s2,s3,s4); --数据类型定义,定义为状态符号
signal c_st,next_state :FSM_ST; --将现态和次态定义为新的数据类型为FSM_ST
begin
REG:process(reset,clk) begin --主控时序进程
if reset='0' then c_st<=s0; --检测到复位信号,复位后回到初始状态s0
elsif clk='1' and clk'event then c_st<=next_state;
end if;
end process REG;
COM:process(c_st,state_input) begin
case c_st is
when s0=> comb_outputs<=5; --进入状态s0后输出5
if state_input="00" then next_state<=s0; -
else next_state<=s1;
end if;
when s1=> comb_outputs<=8; --进入状态s1,输出8
if state_input="01" then next_state<=s1;
else next_state<=s2;
end if;
when s2=> comb_outputs<=12; --进入状态s2输出12
if state_input="10" then next_state<=s0; --注意,停留在状态3会返回到状态0
else next_state<=s3;
end if;
when s3=> comb_outputs<=14;
if state_input="11" then next_state<=s3;
else next_state<=s4;
end if;
when s4=> comb_outputs<=9;next_state<=s0; --到了状态4之后也会自动返回状态0
when others => next_state<=s0;
end case;
end process COM;
end BHV;
仿真测试:
接着执行下一步:
接着执行:
接着执行:
根据上面的程序,下一个上升沿就会把next_state的值更新到c_st的状态,也就是c_st又为s0,输出的数值为5;
注意:
library ieee;
use ieee.std_logic_1164.all;
entity ADC0809 is
port(
D : in std_logic_vector(7 downto 0);--模拟来自0809的A/D转换芯片转换好的数据
CLK,RST : in std_logic;--状态机工作时钟和系统复位时钟
EOC : in std_logic;--状态转换指示,低电平表示正字转换
ALE :out std_logic;--8个模拟信号通信地址锁存信号
START,OE :out std_logic;--转换启动信号和数据输出三态控制信号
ADDA,LOCK_T :out std_logic;--信号通道控制信号和锁存测试信号
Q :out std_logic_vector(7 downto 0));--转换输出信号
end ADC0809;
architecture BHV of ADC0809 is
TYPE states is(s0,s1,s2,s3,s4);--使用TYPE定义各状态
signal cs,next_state:states:=s0;--定义现态和次态量,类型是states,并s0的状态赋值给next_state
signal REGL :std_logic_vector(7 downto 0);--定义一个REGL信号,用于接受转换完成的信号D
signal LOCK :std_logic;--定义锁存信号
begin
ADDA<='0'; LOCK_T<=LOCK;
COM:process(cs,EOC) begin --组合进程,规定各状态转换方式
case cs is
when s0=> ALE<='0';START<='0';OE<='0';LOCK<='0';next_state<=s1;
when s1=> ALE<='1';START<='1';OE<='0';LOCK<='0';next_state<=s2;
when s2=> ALE<='0';START<='0';OE<='0';LOCK<='0';
if (EOC='1') then next_state<=s3; --当EOC=1代表转换已经结束,可以进入下一状态s3
else next_state<=s2;--否则转换没有结束,继续在s2状态进行等待转换结束
end if;
when s3=> ALE<='0';START<='0';OE<='1';LOCK<='0';next_state<=s4;
when s4=> ALE<='0';START<='0';OE<='1';LOCK<='1';next_state<=s0;
when others => ALE<='0';START<='0';OE<='0';LOCK<='0';next_state<=s0;
end case;
end process COM;
REG: process(CLK,RST) begin --时序进程,在时钟的控制下,进行现态和次态的交换
if rst='1' then cs<=s0;
elsif clk'event and clk='1' then cs<=next_state;
end if;
end process REG;
LATCH1: process(LOCK) begin --锁存器进程,当LOCK=1时执行,把数据锁存起来
if LOCK='1' AND lock'event then REGL <=D;
end if;
end process LATCH1;
Q <= REGL; --把锁存的数据赋值给Q进行输出
end BHV;
代码分析:
1.在实体定义输入输出端口
2.结构体的整体框架:
3.组合进程的分析:
4.时序进程分析:
5.锁存进程
6.仿真时序图分析:
接着上一张图片继续分析:
代码如下:
library ieee;
use ieee.std_logic_1164.all;
entity SCHK is
port(
CLK,DIN,RST: in std_logic;
SOUT :out std_logic);
end SCHK;
architecture BHV of SCHK is
TYPE states is(s0,s1,s2,s3,s4,s5,s6,s7,s8);
signal ST,NST:states:=s0;
begin
COM: process(ST,DIN) begin
case ST is
when s0=> if DIN='1' then NST<=s1; else NST<=s0; end if;
when s1=> if DIN='1' then NST<=s2; else NST<=s0; end if;
when s2=> if DIN='0' then NST<=s3; else NST<=s0; end if;
when s3=> if DIN='1' then NST<=s4; else NST<=s0; end if;
when s4=> if DIN='0' then NST<=s5; else NST<=s0; end if;
when s5=> if DIN='0' then NST<=s6; else NST<=s0; end if;
when s6=> if DIN='1' then NST<=s7; else NST<=s0; end if;
when s7=> if DIN='1' then NST<=s8; else NST<=s0; end if;
when s8=> if DIN='0' then NST<=s3; else NST<=s0; end if;
when others => NST<=s0;
end case;
end process COM;
REG:process(CLK,RST) begin
if RST='1' then ST<=s0;
elsif CLK'event and CLK='1' then ST<=NST;
end if;
end process REG;
SOUT <= '1' when ST=s8 else '0';
end BHV;
代码分析:
1.实体部分
2.结构体部分:
3.结构体的组合进程分析:
4.时序进程,当ST进入状态s8时,说明已经完成了一次序列的检测,输入SOUT=1,否则输出0:
注意:此处检测序列可以是重复的,如上如所述。
5.仿真测试: