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;