Verilog

[FPGA][ALTERA][Quartus] ステートマシンの合成属性について調べてみた

← ポチっていただけると嬉しいです

前回はステートマシンのQuartusのオプションについて見たかと思います。

[FPGA][ALTERA] ステートマシンの自動エンコード機能
社内FPGA派遣業のお話の続き。今回はステートマシンです ソースコードを見てたら、各設計者が一生懸命ステートの値を決めていて、モジュールによってはワンホットだったり、バイナリだったりグレイだったりとそれぞれのようです。 書いている人によるポ...

今回はソースに埋め込む合成属性?オプション?プラグマ?なんて呼ぶのがメジャーなのかわかりませんが、その書き方について調べてみました。

調べたっていうか試行錯誤の結果です。

使ったQuartusのバージョンは

Quartus Prime Version 21.1.1 Build 850 06/23/2022 SJ Lite Edition

StandardやProだとどうなるかわかりませんし、バージョンが変わると変わってくる可能性が無いとも言えません。

まず書き込む場所ですが、てっきりcase文のところかと思ってましたが違うようでステートのレジスタに対して指定するっていう形になります。
言われてみればcase文のところはparallel_caseとかfull_caseでしたからね。

そして、まず、ソースコード記載の合成属性を活かすためには、Quartusのオプションで
State Machine Processing を User-Encoded
にしておく必要があるみたいです。
そうでないと、いくらソースに書いても無視され、Quartusの設定が優先されるようです。

で、こんな感じでステートのレジスタの所に記載します。

(* syn_encoding = "gray" *) reg [7:0] STATE;

これはVerilog-2001の形式で、
Verilog-1995だと

reg [7:0] STATE1_C /* synthesis syn_encode = "gray" */;

となります。
QuartusではVerilogのバージョン指定を特にして無くても(Default設定)どちらも認識してくれたようです。

で、2001形式の方ですが、別にregの前に書かなくても良いようです。

(* syn_encoding = "gray" *)
reg [7:0] STATE;

でもOKでしたし、もっというと、その間に別の文が入っても問題なかったです。

(* syn_encoding = "gray" *)
reg [3:0] HOGE;
reg [7:0] STATE;

また、

(* syn_encoding = "one-hot" *)
(* syn_encoding = "gray" *)
reg [7:0] STATE;

と、した場合は、上書きされたよっていうWarningが出力され
後に指定した方が生きました

次、Verilog-1995の方ですが、よく見てください。

reg [7:0] STATE1_C /* synthesis syn_encode = "gray" */;

regの終わりの;よりも前に指定していないといけません。

reg [7:0] STATE1_C; /* synthesis syn_encode = "gray" */

と書きがちですが、これだと無視されました。

なので、//のコメントの書き方ですと同じ行に;がいれられないので、

reg [7:0] STATE1_C // synthesis syn_encode = "gray"
;

ってな2行な書き方にしないといけないってことになります。

また、synthesisっていうキーワードですが、
pragma, synopsys, exemplar, altera でもいいみたいです。

私がはるか昔DesignCompiler使ってた頃はsynopsysでしたけど、あれはsynopsysのツールだったからかなぁって思ってました。
共通なのか。。。
でもaltera使っちゃうと別ツールだとだめかも知れません。
そう考えるとsynthesisが無難でしょうか。

次、1995/2001両形式の属性指定を指定するとどちらが優先されるのか?

(* syn_encoding = "one-hot" *) reg [7:0] STATE1_C /* synthesis syn_encoding = "johnson" */ ;
(* syn_encoding = "johnson" *)
reg [7:0] STATE1_C /* synthesis syn_encoding = "one-hot" */ ;

いずれの書き方も2001の方が優先されました。
上書きされたっていうWarningが出てくるのでてっきり後に書いてある1995の方が上書きするのかな?って思ったんですがそうではなかったようです。

つまり 強さで言うと
Quartus>Verilog-2001>Verilog-1995 のようです。

では、複数のステートマシンでそれぞれ別々に指定したい場合はどうすべきか?

ためしに以下のようにして2つのステートマシンをつくってみたらちゃんと、それぞれの指定通りになりました。

(* syn_encoding = "one-hot" *)
reg [7:0] STATE1_C;
(* syn_encoding = "johnson" *)
reg [7:0] STATE2_C;

ただし、1個だけ指定した場合

(* syn_encoding = "johnson" *)
reg [7:0] STATE1_C;
reg [7:0] STATE2_C;

STATE2の方は(多分デフォルトの)ワンホットになってしまいました。

(* syn_encoding = "johnson" *) reg [7:0] STATE1_C;
reg [7:0] STATE2_C;

これもいっしょ。
2001形式の書き方でも;までしか有効じゃないんだなって思おうとしますが、先に書いたように

(* syn_encoding = "johnson" *)
reg [3:0] A;
reg [7:0] STATE1_C;
reg [7:0] STATE2_C;

と書いた場合は、STATE1の方はちゃんと指定されているので;というよりも、
最初のステートレジスタまでっていう感じかなって思います。

なので、指定するのであれば、各ステートマシンのレジスタ定義ごとに全て指定していったほうがトラブルが少ないってことになりますね。

いやぁ調べていくとややこしいんですね。

 

コメント

タイトルとURLをコピーしました