Verilog HDL 論理合成テクニック

論理合成ツールはRTLを元に論理合成を行います。しかし、例えばファンアウトはどうするかとか、最適化してほしくない回路があった場合など、それらに対して制約を与えることが可能です。

私はAlteraメインなので、Xilinx系のツールは結構未確認のものもあるので、間違っていたら教えて下さい。

full case

Synopsys

case(state) // synopsys full_case
  2'h0:
  2'h1:
  2'h2:
endcase
 

この場合、stateが2'h3の時はdon't careとなり、ラッチは生成されない。

Verilog 2001 attribute for Altera

(* full_case *)case(state) 
  2'h0:
  2'h1:
  2'h2:
endcase
 

この場合もstateが2'h3の時はdon't careとなり、ラッチは生成されない。

しかし、full-caseは基本的に書かずに、defaultで全パターンを記述するべきかと思います(Alteraもそれを推奨してる)。

論理合成除外ディレクティブ

//synopsys translate_off
$display("test");
//synopsys translate_on
always@...

論理合成に関係ない記述がRTLファイルにある場合、上記のディレクティブを用いることで除外可能、Synopsys系ツールやQuartusIIで有効になる。

Altera QuartusIIでのみ除外させる場合は

//altera translate_off
$display("test");
//altera translate_on
always@...

しかし、通常RTLに合成対象ではない記述は書くべきではない(RTLスタイルガイドより

負荷のないレジスタの削除禁止

例えばcase文で再上位1bitは常に0にしかならない場合など、使用されない常に固定された値となるレジスタは論理合成時に削除される場合がある。それを防止するには以下のとおり記述する。

Verilog 2001 attribute for Altera

(* syn_noprune = 1 *) reg [3:0] b_state;

Verilog 2001 attribute for Xilinx(XST/Vivado)

(* optimize_primitives = "no" *) reg [3:0] b_state;   //XST
(* dont_touch = "true" *) reg [3:0] b_state;   //Vivado

ファンアウトの設定

1つのレジスタ出力に対して複数の負荷がある場合ドライブ能力の限界に達し、十分な速度でドライブできなくなる。これを防止するためにレジスタの複製を行いファンアウトを制限するには以下のように指定する。

例として、100以上のファンアウトがある場合レジスタを強制的に複製する。

Verilog 2001 attribute for Altera

(* syn_maxfan = 100 *) reg [3:0] b_state;

Verilog 2001 attribute for Xilinx(XST/Vivado)

(* max_fanout = 100 *) reg [3:0] b_state;   //XST/Vivado

レジスタの複製禁止

例えばメタステーブル防止回路のように、2つのレジスタで受けたりする場合、そのレジスタを複製されたら問題になる。 レジスタの複製を防止するには以下のように指定する

Verilog 2001 attribute for Altera

(* syn_replicate = 0 *) reg b_as_data;

Verilog 2001 attribute for Xilinx(XST/Vivado)

(* register_duplication = "no" *) reg b_as_data;  //XST
(* dont_touch = "true" *) reg b_as_data;  //Vivado

明示的にメモリをBlock-Memoryで構成する

Mega WizardやCore generatorなどを使用しなくとも、アトリビュートを与えるだけでブロックRAMを明示的に使用することが可能になる。

Verilog 2001 attribute for Altera

M-RAM : ブロックRAM

M4K : M4KブロックRAM

M512 : M512ブロック

logic : 通常のロジックセル

(* ramstyle = "M-RAM" *) reg [7:0] b_memory[0:127];

Verilog 2001 attribute for Xilinx

auto : 最適なインプリメント方法がXSTで自動的に設定される

distributed : 分散RAMにインプリメントされる。

block : ブロックRAMを使用する。

(* ram_style = "block" *) reg [7:0] b_memory[0:127];  //For XST

明示的に乗算器をハードマクロ(DSP)で構成する

論理合成する際に、DSPを用いるか、ロジックセルを用いるか指定したい場合は以下のアトリビュートを指定する

Verilog 2001 attribute for Altera

dsp : DSPブロックを用いる

logic : 汎用ロジックセルを用いて合成する

wire [7:0] a, b;
wire [15:0] result;
assign result = a * (* multstyle = "dsp" *) b;

Verilog 2001 attribute for Xilinx

auto : auto

block : ブロックモジュールを使う

lut : スライスベース

wire [7:0] a, b;
wire [15:0] result;
assign result = a * (* mult_style = "block" *) b;    //for XST

2014/01/19 上記のコードでは指定が有効にならないみたいなので、以下が適切なようです。

wire [7:0] a, b;
(* mult_style="block" *) wire [15:0] result;
assign result = a * b;    //for XST

合成の最適化での削除を無効化

例えば宣言されたけど使用されていないレジスタなどを、SignalTap2などを使って実機でデバッグするときに、普通に合成してしまうと論理合成の最適化で消されてしまいます。最適化で残したい信号があるときは以下のように指定します。

Verilog 2001 attribute for Altera

(* syn_preserve = 1 *) reg [3:0] b_signal;