音声や音楽波形など正負の極性をもつ情報をデジタル処理する場合には2の補数(two's complement)と呼ばれる形式がよく使われています。これ、計算しようとするたびに調べ直して、しかもその度に間違えてましたので自分用に整理してみました。
2の補数
教科書には、負の数値の表現方法として3種類が載っていました。
極性振幅表示:10進数を2進数に変換して、符号ビットを最上位ビットに付加
1の補数表示:極性振幅表示の符号ビットをのぞく全てのビットを反転
2の補数表示:1の補数表示の符号ビットをのぞく2進数に1を加える
Verilogで2の補数の計算
(1)正負の反転
全ビットを反転させて1を加える。
input [7:0] a;
output [7:0] answer;
assign answer = ~a + 1;
(2)加算
Webの解説記事から引用します。加算によって最上位ビットからの繰り上がりが発生した場合、その繰り上がりは無視する。
加算した結果も、2の補数によって表現されている。
加算した結果が2の補数で表現可能な範囲に収まらない場合、オーバーフローが発生する。(正しく計算されない)
え~と、繰り上がりを無視してそのまま加算してOKということです。8ビットの加算例: a + b
input [7:0] a, b;
output [7:0] answer;
assign answer = a + b;
なおビット幅が異なる数を加算するには、符号拡張を行い相互のビット幅を揃えます。
また、加算結果がオーバーフローしたら当然ながら正しい結果が得られません。次の条件に該当していたらオーバーフローが発生していることになるそうです。
最上位ビットが0の数どうしを加算した結果、最上位ビットが1になった
(つまり、非負の数どうしの加算結果が負の数になった)
最上位ビットが1の数どうしを加算した結果、最上位ビットが0になった
(つまり、負の数どうしの加算結果が非負の数になった)
(3)減算
負の数の加算として計算します。(例) 3 - 1 → 3 + (-1)
8ビットの減算例: a - b
input [7:0] a, b;
output [7:0] answer;
assign answer = a + (~b + 1);
(4)乗算
絶対値で計算したうえで、最後に符号を付ける。
例: a * b
input [7:0] a, b;
output [14:0] answer;
wire [6:0] abs_a, abs_b;
wire [13:0] abs_mul;
assign abs_a = a[7] ? (~a[6:0]) +1 : a[6:0];
assign abs_b = b[7] ? (~b[6:0]) +1 : b[6:0];
assign abs_mul = abs_a * abs_b;
assign answer = (a[7] ^ b[7]) ? {1'b1, ~abs_mul + 1} : {1'b0, abs_mul};
参考資料
・辻井重男 久保田一(1993) わかりやすいディジタル信号処理 オーム社
・基本情報技術者口座 - 1の補数と2の補数で2進数のマイナスの数値を表現する
・とあるソフトウェア開発者のブログ - 2の補数を理解する (2)
2012年6月19日火曜日
登録:
コメントの投稿 (Atom)
0 件のコメント:
コメントを投稿