乗算器のRTL記述

[] [] []


FPGAには乗算器ブロックや、さらに積和用の加算器がついたDSPブロックが備わっている。これらを使うにはIPモジュールとして生成してRTL記述中にインスタンシエートするのが一般的だが、レジスタ段数や符号有無が見えないので可読性が悪いし、ツールバージョンやターゲットデバイスが変わるたびに生成し直さなければならないので移植性もよくない。そこで、RTL記述で書いた方が可読性や移植性はよくなる

1) 符号つき18x18乗算器、入出力レジスタつき

/* 18x18 multiplier */

reg[17:0] a_reg;

reg[17:0] b_reg;

reg[35:0] p_reg;

always @(posedge clk) //()乗算器の入出力レジスタにはリセットを付けない方がよい

    begin

    a_reg <= a;

    b_reg <= b;

    p_reg <= $signed(a_reg) * $signed(b_reg);

    end

ここで $signed( ) は強制的に符号付きと解釈させVerilog関数である。乗算は変数が符号付きか符号なしかで乗算結果が違うので、このように明示的に指定した方が安全である。 (補足 - 符号付き変数)

乗算器はDSPブロックを使わずにLUTでも実現できる。DSPブロックの数が足りないとき意図的にLUTを使うには積のwire変数に合成制約で指定する。このとき合成制約はreg変数ではなくwire変数に指定しないと効かないので注意。

/* 18x18 multiplier */

reg[17:0] a_reg;

reg[17:0] b_reg;

reg[35:0] p_reg;

(* mult_style="value" *) wire[35:0] p; // XSTの場合 value={auto|block|lut}

(* use_dsp48 ="value" *) wire[35:0] p; // Viavdoの場合 value={yes|no}

(* syn_multstyle="value" *) wire[35:0] p; // QuartusIIの場合 value={dsp|logic}

assign p = $signed(a_reg) * $signed(b_reg);

always @(posedge clk)

    begin

    a_reg <= a;

    b_reg <= b;

    p_reg <= p;

    end

あるいは、(*... *) moduleと指定すればモジュール内の演算子全部に効く。


[] [] []