目次
前
次
VHDLステートマシン記述作成(AWK)
VHDLを利用して、CPLD/FPGA内部にデジタル回路の
情報を記述します。
VHDLを使うのは、ステートマシンを簡単に記述できる
ことが挙げられます。これで、マイコンのような動作
をデジタル回路で実現できます。
ステートマシンは、状態遷移図に相当する動作と
等価な動きをします。状態遷移図の例は、以下。
ステートマシンは、カウンタを利用しますが
外部からの指定条件で、カウンタの動作を止
めたり、次の値に遷移するのを待たせること
ができます。
カウンタはクロックで動きますが、クロックが
入ったとしても、次の値に遷移するか、現在値
に留まるのかを、条件により指定します。
簡単なステートマシンの記述は、以下。
process (nRESET,CLOCK)
begin
if ( nRESET = '0' ) then
iSTATE <= "00" ;
iGSTATE <= '0' ;
elsif rising_edge(CLOCK) then
case conv_integer(iSTATE) is
-- wait trigger
when 0 => if ( iSTRG = '1' ) then
iSTATE <= "01" ;
else
iSTATE <= "00" ;
end if ;
-- reset and send trigger
when 1 => iSTATE <= "11" ;
-- wait trigger
when 3 => if ( iURES = '1' ) then -- answer back
iSTATE <= "10" ;
iGSTATE <= '1' ;
elsif ( iTOUT = '1' ) then -- time out
iSTATE <= "10" ;
iGSTATE <= '0' ;
else
iSTATE <= "11" ;
end if ;
-- return first state
when 2 => iSTATE <= "00" ;
-- default
when others =>
iSTATE <= "00" ;
end case ;
end if ;
end process ;
ステートマシンは、ベースとなるカウンタのビット数を
2から5程度にしますが、4ステートを扱うことが多い
ので、2ビットとして考えます。
2ビットカウンタは、状態変化するビットが1個に限定
したジョンソンカウンタを使います。状態は、2進数で
見ると00→01→11→10と変化します。
この方式でスクリプトを作成しました。
{
printf("process (nRESET,CLOCK)\n")
printf("begin\n")
printf(" if ( nRESET = '0' ) then\n")
printf(" %s <= \"00\" ;\n",$1)
printf(" elsif rising_edge(CLOCK) then\n")
printf(" case conv_integer( %s ) is\n",$1)
printf(" -- wait trigger \n")
printf(" when 0 => if ( %s = '1' ) then\n",$2)
printf(" %s <= \"01\" ;\n",$1)
printf(" else\n")
printf(" %s <= \"00\" ;\n",$1)
printf(" end if ;\n")
printf(" -- \n")
printf(" when 1 => %s <= \"11\" ;\n",$1)
printf(" -- \n")
printf(" when 3 => %s <= \"10\" ;\n",$1)
printf(" -- return first state\n")
printf(" when 2 => %s <= \"00\" ;\n",$1)
printf(" -- default\n")
printf(" when others => \n")
printf(" %s <= \"00\" ;\n",$1)
printf(" end case ;\n")
printf(" end if ;\n")
printf("end process ;\n")
}
2つのパラメータを利用します。
カウンタを扱う変数名と条件を指定する変数を
用意し、テキストファイルに入れ当てはめます。
条件が増えたり、遷移の仕方が複雑になるときは
テキストエディタで変更すればよいと割切ります。
叩き台になるコードを短時間で作成することを
考え、複雑な処理に変更するのは叩き台を利用
するとします。
次のようにCUIで使います。
パラメータは、テキストファイルに入れています。
内容は、以下としました。
iSTATE iTRG
生成されるコードは、I/Oリダイレクトを使い
テキストファイルに保存すれば、使い回しが
効きます。
パラメータを次のように変更しての動作確認も
してあります。
iBSTA iWTRG
ステート値が順番に+1される場合のAWKスクリプトは
以下とします。
BEGIN {
print "process (nRESET,CLOCK)"
print "begin"
print " if ( nRESET = '0' ) then"
}
{
last = $2
printf(" %s <= 0 ;\n",$1)
printf(" elsif rising_edge(CLOCK) then\n")
printf(" case %s is\n",$1)
for ( i = 0 ; i < last ; i++ ) {
printf(" -- \n")
printf(" when %d => %s <= ",i,$1)
if ( i == last-1 ) {
printf(" 0 ;\n")
} else {
printf(" %d ;\n",i+1)
}
}
printf(" -- default\n")
printf(" when others => %s <= 0 ;\n",$1)
printf(" end case ;\n")
}
END {
print " end if ;"
print "end process ;"
}
パラメータを次のように指定して動作確認します。
iSTATE 4
CUIでは、次のようになります。
目次
前
次