2010-04-04 眼がかゆい
■[メモ]verilogでsignedとunsignedの乗算
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扱いされてしまう
コメントを書く