« 携帯でスミスチャート | トップページ | アドバンスドJTAGファンクションジェネレータの紹介ページ »

2007.11.14

ステートマシンがOneHotになるのを防止する

XILINXのFPGAで、ステートマシンが思い通りに動かないときがあります。

XILINXのXSTは、ステートマシンをOne Hotで作ろうとします。
たとえユーザが最適化したステート割り当てを考えて、
VHDLやVerilogで、エンコード方法まで丁寧に記述しても、勝手にOneHot化してくれます。

つまり、
case hoge_state is
when "000" =>
・・・ hoge_state <="001";
when "001"=>
・・
when others=>
・・・ hoge_state <="000";
・・

このように記述しても、hoge_state(0)やhoge_state(1)という信号がそのデザインで直接参照されないようであれば、XSTは気を利かせてステートマシンがOneHot化し、信号を消してしまうのです。

そのときXSTは、こんなメッセージを出します。
INFO:Xst:2117 - HDL ADVISOR - Mux Selector of Case statement line 479 was re-encoded using one-hot encoding. The case statement will be optimized (default statement optimization), but this optimization may lead to design initialization problems. To ensure the design works safely, you can:
- add an 'INIT' attribute on signal - use the attribute 'signal_encoding user' to avoid onehot optimization
- use the attribute 'safe_implementation yes' to force XST to perform a safe (but less efficient)

リセット時に全部のFFがゼロになったり、ノイズやその他の原因で未定義のステートに入ったときが怖いです。
これでもちゃんと動いてくれればよいのですが、動いてくれないことが多いです。
確かにワンホットは高速なのですが、困ります。

例えば、hoge_state(2 downto 0)を3ビットの信号とすると、
XSTは最大8個のワンホット用のフリップフロップを作ります。
したがって、最大256個のステートが存在してしまうわけですが、
どうやらXSTがワンホット化したステートマシンでは、
変なステートに入ってしまうと、when othersで定義した式さえ実行されないことがあるようなのです。

もちろん、ステートマシンにリセットの記述を入れればいいのですが、
ステートマシンを適切にリセットしていない場合、
正しいステートから開始せず、そのステートマシンの
ステートや出力信号は信頼できないものになります。

これを防止するには、
testpoint <= hoge_state(0)のように、
ステートマシンの信号のうちの1本を抜き出すようにして、論理合成で消えないようにするという手や、
Translateのオプションでステートマシンのエンコード方法を指定する方法があります。

ただ、信号の1本を抜き出す方法は面倒だし、
Translateのオプションで指定する方法ではデザイン全体に効いてしまいます。

上記のINFO:Xst:2117のメッセージによると、
初期値に問題があるから'signal_encoding user' を設定しろ、と読めます。

そこで、次のようにしてみました。

architecture Behavioral of main is
・・・
signal hoge_state : std_logic_vector(2 downto 0);
attribute SIGNAL_ENCODING : string;
attribute SIGNAL_ENCODING of hoge_state : signal is "user";
・・・
begin

ワンホット化させたくないステートマシン、つまり、自分でエンコードの方法を指定したステートマシンについては、SIGNAL_ENCODINGをUSERに設定することによって、自分で指定したエンコードで合成してくれるようになりました。

論理合成中のメッセージは、次のようになりました。
Set property "SIGNAL_ENCODING = user" for signal .

これで、リセットを入れなくても変なステートに入ることはなくなりました。
XSTは、ユーザが定義したとおりにステートマシンを作ってくれるようになりました。

ステートマシンが思うように動かない場合、SIGNAL_ENCODINGを試してみてはいかがでしょうか。

|

« 携帯でスミスチャート | トップページ | アドバンスドJTAGファンクションジェネレータの紹介ページ »

コメント

コメントを書く



(ウェブ上には掲載しません)




« 携帯でスミスチャート | トップページ | アドバンスドJTAGファンクションジェネレータの紹介ページ »