Verilog

[ALTERA][Quartus][FPGA] 合成属性の書き方について調べてみた

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

先日はステートマシンの自動エンコード機能について調べてみました。

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

その続きで、合成属性の書き方についても調べてみたので備忘録として記載しておきます。

Quartusの方でステートマシンのエンコード形式を指定してしまうと全部同じ形式になってしまいますからね。使い分けしたいって時にはソースに属性を埋め込んでいかないといけません。

合成属性っていうのが一般的なのかな?昔々DesignCompiler使ってた頃はプラグマって言ってました。オプションでも通じるのかも。

調べたっていうか試行錯誤の結果ですかね。
使ったバージョンは

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

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

また、いろいろな合成属性がありますが、今回は先日のエンコード機能についてだったのでその指定のsyn_encodingについてです。

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

そして、まずソースコード記載の合成属性を活かすためには、Quartusのオプションで
State Machine ProcessingUser-Encoded
にしておく必要があるみたいです。

そうでないと、いくらソースに書いても無視され、Quartusの設定が優先されるようです。

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

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

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

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

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

で、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"
;

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

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

私がデザインコンパイラー使ってた頃はsynopsysでしたけど、あれはsynopsysのツールだったからかなぁって思ってました。共通なのか? それともデファクトスタンダードになったのか?

でもaltera使っちゃうと別ツールだとだめかも知れません。
synthesisが無難でしょうか。exemplarってのはどっから来てるんだろう?

次、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の方はちゃんと指定されているので;というよりも
最初のステートレジスタまでっていう感じかなって思います。

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

ややこしいですが、合成後のメッセージはちゃんと見とかないと思ったように合成されていないってことがありうるってことですよね。
普通Warning見ますよね?
まぁメーカーが準備するIPが山ほどWarning吐くから見る気なくなるでしょうが。。。

でも、今の部署の人たちってWarningは全無視なんですよねー。いいのかよーそれで。。。

 

コメント

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