Hatena::ブログ(Diary)

元大学院生の日記

2010-04-04 眼がかゆい

[]verilogでsignedとunsignedの乗算 19:38

verilogでsignedとunsignedの乗算をまとめてみた。


乗算結果を格納する信号のビット幅は、乗数と被乗数の幅を足した幅で用意するのが基本。

それから、オペランドは両方がsignedになるようにする。

オペランドのどちらか片方でもunsignedになると全ての演算がunsigned扱いされてしまうので要注意。3月21日の日記も参照*1

module signed_mul (
    // INPUT
    input   signed  [7:0]   DATA_A, // signed             (8bit)
    input           [3:0]   COEF,       // signedではない!  (4bit)
    // OUTPUT
    output  signed  [7+3+1:0] ANS_0,    // 8bit+4bit=12bit
    output  signed  [7+3+1:0] ANS_1,
    output  signed  [7+3+1:0] ANS_2,
    output  signed  [7+3+1:0] ANS_3
);

    // wire 宣言
    // COEFを符号拡張するためのwire
    wire    signed  [4:0]   COEF_SGN;


    // 普通に乗算(間違い)
    //   COEFがunsignedなので signed * unsignedとなり、
    //   DATA_Aがunsignedにキャストされてしまう
    assign  ANS_0 = DATA_A * COEF;


    // COEFをキャストして乗算(間違い)
    //   COEFはunsignedのつもりなのに4'b1010のように
    //   最上位ビットが1のとき、負の値にされてしまう
    assign  ANS_1 = DATA_A * $signed(COEF);


    // COEFを符号拡張して乗算(正しい)
    //   COEFはunsignedなので頭に0を付ければsignedにキャストできる
    assign  ANS_2 = DATA_A * $signed({1'b0,COEF});


    // COEFを符号拡張してsignedのwireに入れてから乗算(正しい)
    assign  COEF_SGN[4:0] = {1'b0,COEF[3:0]};
    assign  ANS_3 = DATA_A * COEF_SGN;

endmodule

*1:例えばDATA_AがsignedでもDATA_A[7:0]と書いてしまうとunsigned扱いされてしまう