狀態機的HDL設計與模擬驗證
作者:毛蘢瑋 / Saint
掘金:https://juejin.im/user/5aa1f89b6fb9a028bb18966a
微博:https://weibo.com/5458277467/profile?topnav=1&wvr=6&is_all=1
GitHub:github.com/saint-000
CSDN: https://me.csdn.net/qq_40531974
狀態機的HDL設計與模擬驗證
一、實驗原理:
狀態機由狀態暫存器和組合邏輯電路構成,能夠根據控制訊號按照預先設定的狀態進行狀態轉移,是協調相關訊號動作、完成特定操作的控制中心。狀態機分為三大型別:
1. Moore狀態機:次態=f(現狀),輸出=f(現狀),即輸出訊號是直接由狀態暫存器譯碼得到
2.Mealy狀態機:次態=f(現狀,輸入),輸出=f(現狀,輸入),即以現時的輸入訊號結合即
將變成次態的現狀編碼成訊號輸出。
3.混合型狀態機
二、實驗目的:
在實驗中經常會涉及到狀態的改變,有時候任何狀態之間都可以互相切換,如果直接用常規的編寫方式對於一些沒有規律的或則極其複雜的設計而言效率是非常低的。我們通過三段式的狀態機程式碼的編寫,體會該框架的綜合性,熟悉了相應的編碼方式後可以將其用來帶入其他模組程式碼的編寫。
三、實驗內容:
摩爾狀態機的VHDL程式碼錄入及波形模擬。
四、實驗器材(裝置、元器件):
①軟體Active-HDL9.2 ②Windows作業系統
五、(1)選擇器
實驗步驟:
1.開啟Active-HDL9.2,頁面會跳出提示框,可以選擇之前建立好的檔案開啟,也可以建立新的設計檔案,這裡我們對選擇器進行建立新的設計,故點選Create new workspace,然後
設定Workspace name為Moore。
2. 建立一個空的設計,新增一些基本資訊,輸入設計檔名。
3.在軟體中點選File,選擇New然後點選建立VHDL Source,對設計模型的實體,構造體進行命名,命名為Moore,此處四選一資料選擇器的構造體填behavior,我們採用行為級描述。
4.在描述埠的時候輸入輸出應用不同的埠方向,rst,clk,x設為輸入埠,z設為輸出埠。
5.完成了埠設定軟體會自動生成好基本的程式碼框架,我們在此基礎上進行程式的編寫。
程式碼如下:
library IEEE;
use IEEE.STD_LOGIC_1164.all;
entity Moore is
port(
rst : in STD_LOGIC;
clk : in STD_LOGIC;
X : in STD_LOGIC;
Z : out STD_LOGIC
);
end Moore;
--}} End of automatically maintained section
architecture behavior of Moore is
TYPE state_type is (S0,S1,S2,S3);
SIGNAL current_state,next_state:state_type;
begin
SYNCH:PROCESS(clk,rst)
begin
if clk'EVENT AND clk='1'THEN
if rst='1'THEN
current_state<=S1;
else
current_state<=next_state;
end if;
end if;
end process;
STATE_TRANS:PROCESS(current_state,X)
begin
case current_state is
WHEN S0=>
IF X='0'THEN
next_state<=S0;
ELSE
next_state<=S2;
END IF;
WHEN S1=>
IF X='0'THEN
next_state<=S0;
ELSE
next_state<=S2;
END IF;
WHEN S2=>
IF X='0'THEN
next_state<=S2;
ELSE
next_state<=S3;
END IF;
WHEN S3=>
IF X='0'then
next_state<=S3;
ELSE
next_state<=S1;
END IF;
WHEN others=>
next_state<=S1;
END CASE;
END PROCESS;
OUTPUT_GEN:PROCESS(current_state)
begin
CASE current_state is
WHEN S0=>
Z<='0';
WHEN S1=>
Z<='1';
WHEN S2=>
Z<='1';
WHEN S3=>
Z<='0';
WHEN others=>
Z<='0';
END CASE;
END PROCESS;
-- enter your statements here --
end behavior;
6.把完成的程式碼進行編譯,編譯好的檔案出現子項,其對應於檔案中的實體和構造體,我們將出現的子項設為頂層,其目的是優先進行模擬,有時候多專案在同一個工作環境中,我們需選定優先模擬物件,然後進行模擬。
7.將待測訊號載入到波形視窗,然後對各項輸入訊號設定波形訊號,加激勵進行模擬。
六、摩爾狀態機
實驗資料及結果分析:
對於摩爾狀態機而言,其輸出值僅由其當前狀態確定。與Mealy不同,它的輸出值由其當前狀態和輸入值決定。我們在波形圖上可以發現當前狀態為S0時,輸出Z=0,當前狀態為S1時,輸出Z=1,當前狀態為S2時,輸出Z=1,當前狀態為S3時,輸出Z=0。觀察模擬波形結果對比moore型狀態機的狀態轉換表驗證設計。
七、實驗結論:
描述狀態機有三種方法:狀態轉移圖、狀態轉移表、HDL描述,狀態轉移圖直觀,設計用,而HDL語言方便描述,實現時用;本次實驗對moore狀態機進行了HDL描述,通過對設計程式碼各個語法的編寫思想,我們可以將狀態機兩個定義,三個程序的編寫方式套用到其他複雜模組功能描述上,減小了程式設計難度。
八、總結及心得體會:
(1)分析狀態機特點:
1. 對於狀態的描述一般先宣告一個列舉資料型別,語句如下:
Type state_type is(idle,tap1,tap2,tap3,tap4);
2. 對於儲存當前狀態的物件一般用是一個訊號,即:
Signal state: state_type;
3. 對於狀態機的下一個狀態的判斷一般是通過對時鐘上升沿判斷的if then else 語句內嵌
case when 語句
4. 對於狀態機的輸出則可以用一個條件或者選擇訊號宣告語句,或者再用一個case語句來
實現訊號輸出。
(2)Moore狀態機:在時鐘脈衝的有限個門延時之後,輸出達到穩定。輸出會在一個完整的時鐘週期內保持穩定,即使在該時鐘內輸入訊號改變了,輸出訊號也不改變。輸入對輸出的影響要到下個時鐘才能反應出來。所以對於摩爾狀態機的設計中,體會到了其獨特的編碼方式具有模板性,程式設計模式較為簡單,但同時也要注意對非法狀態的處理,提高系統的可靠性和穩定性。
九、對本實驗過程及方法、手段的改進建議:
對於本實驗我們採用的是程式碼錄入,我們還可以嘗試用FSM(狀態圖編輯器)錄入方式。
編譯生成源程式程式碼:
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.std_logic_unsigned.all;
entity \ Moore \ is
port (
clk: in STD_LOGIC;
rst: in STD_LOGIC;
X: in STD_LOGIC;
Z: out STD_LOGIC);
end \ Moore \;
architecture \behavior \ of \ Moore \ is
-- SYMBOLIC ENCODED state machine: Sreg0
type Sreg0_type is (
S2, S3, S1, S0
);
-- attribute enum_encoding of Sreg0_type: type is ... -- enum_encoding attribute is not supported for symbolic encoding
signal Sreg0, NextState_Sreg0: Sreg0_type;
-- Declarations of pre-registered internal signals
begin
----------------------------------------------------------------------
-- Machine: Sreg0
----------------------------------------------------------------------
------------------------------------
-- Next State Logic (combinatorial)
------------------------------------
Sreg0_NextState: process (X, Sreg0)
begin
NextState_Sreg0 <= Sreg0;
-- Set default values for outputs and signals
Z <= '1';
case Sreg0 is
when S2 =>
z<='1';
if x='1' then
NextState_Sreg0 <= S3;
elsif x='0' then
NextState_Sreg0 <= S2;
end if;
when S3 =>
z<='0';
if x='1' then
NextState_Sreg0 <= S1;
elsif x='0' then
NextState_Sreg0 <= S3;
end if;
when S1 =>
z<='1';
if x='1' then
NextState_Sreg0 <= S2;
elsif x='0' then
NextState_Sreg0 <= S0;
end if;
when S0 =>
Z<='0';
if X='0' then
NextState_Sreg0 <= S0;
elsif x='1' then
NextState_Sreg0 <= S2;
end if;
--vhdl_cover_off
when others =>
null;
--vhdl_cover_on
end case;
end process;
------------------------------------
-- Current State Logic (sequential)
------------------------------------
Sreg0_CurrentState: process (clk, rst)
begin
if rst='1' then
Sreg0 <= S1;
elsif clk'event and clk = '1' then
Sreg0 <= NextState_Sreg0;
end if;
end process;
end \behavior \;