1. 程式人生 > >VHDL有限狀態機設計例子分析

VHDL有限狀態機設計例子分析

目錄

前言:

有限狀態機機器設計技術是使用資料系統設計中的重要組成部分,也是實現效率高,高可靠和速度控制邏輯系統的重要途徑,廣義而論,只要涉及觸發器的電路,無路電路大小,都能歸結為狀態機。

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.輔助程序:

1.VHDL狀態機的一般形式

 例子:下面的例子是由兩個主控程序構成的,其中含有主控時序程序和主控組合程序(注意: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;

注意:

2.Moore有限狀態機的設計

  • 多過程結構狀態機

  • 工作時序圖和引腳圖

  • 狀態取樣圖

  • 狀態機結構圖:

  • 程式碼如如下所示:
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.模擬時序圖分析:

接著上一張圖片繼續分析:

3.序列檢測之狀態機設計

程式碼如下:

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.模擬測試: