state machineの作り方

ポイントは三つ。
1、state のタイプ宣言は以下の通り。

type STATE is ( STA0 , STA1 , STA2 );
signal CURRENT_STATE,NEXT_STATE : STATE;

現在のステートと次のステートを作っておく。
「次」とは、次のクロックのことを指す。

2、clkでステートを入れ替える。

3、(NEXT_STATEを作る+current stateに応じた出力を出す)processのセンシティビティリストは、
・CURRENT_STATE
・CURRENT_STATEに加えて、次のSTATEを決定するのに必要なsignal
を入れる。
あと、忘れがちなcase記法を復習しておく。

case STATE is
    when <STATE1> =>
        ....
    when <STATE2> =>
        ....
        ....
    when others =>
        ....
end case;

ここの when は、以下のように書くことも許されている。

when <STATE1>|<STATE2>|...|<STATEn> =>....
when <STATE1> to <STATEn> =>....

クロックを入れたい場合(たとえばstate Aに入ってから10クロック目にstate Bに移行したい)は、以下のようにする。

architecture....
    ....
    signal count : Integer range 0 to 15;
    ....
begin
    ....
--counter process
process(clk,reset)begin
    if(reset='1')then
        count<=0;
    elsif(clk'event and clk='1')then
        if(CURRENT_STATE=stateA)then
            count<=count+1;
        else
            count<=0;--important!!
        end if;
    end if;    
end process;

process(CURRENT_STATE,sig1,sig2,count)begin
    case CURRENT_STATE is
        when stateA =>
            ....
            if(count=10)then
                NEXT_STATE<=stateB;
            else
                NEXT_STATE<=stateA;
            end if;
        when stateB=>
            ....
    end case;
end process;

まとめて一例を。

entity MULSTATE is
    port( clk,reset : std_logic;
             sig : std_logic;
             out1,out2 : std_logic);
end MULSTATE;

architecture RTL of MULSTATE is
--state definition
type STATE is (STA0,STA1,STA2);
signal CURRENT_STATE,NEXT_STATE : STATE;

begin

--Flip Flop for remember the state.
process ( clk , reset ) begin
    if(reset='1')then 
        CURRENT_STATE<=STA0;  --load the initial state
    elsif ( clk'event and clk ='1')then
        CURRENT_STATE<=NEXT_STATE;-- load the next state
    end if;
end process;

--state exchange process
process(CURRENT_STATE,sig)begin
    case CURRENT_STATE is
        when STA0 =>
            out1<='0';
            out2<='0';--output some signals to the external module
--set next state
            if(sig='0')then
                NEXT_STATE<=STA2;
            else
                NEXT_STATE<=STA1;
            end if;
        when STA1=>
            out1<='1';
            out2<='0';--output some signals to the external module
--set next state
            if(sig='0')then
                NEXT_STATE<=STA0;
            else
                NEXT_STATE<=STA2;
            end if;
        when STA2=>
            out1<='1';
            out2<='1';--output some signals to the external module
--set next state
            if(sig='0')then
                NEXT_STATE<=STA1;
            else
                NEXT_STATE<=STA0;
            end if;
    end case;
end process;

end RTL;