乗算器
乗算器(じょうざんき)とは、二つの数について乗算を行うための電子回路であり、#デジタル乗算器と#アナログ乗算器がある。
デジタル乗算器
デジタル乗算器を実装するには様々な技法が考えられる。 多くの技法は分割した部分の積を計算し、それを加算してまとめることで実現する。 このやり方は、小学校で習う十進整数の筆算による乗算と似ている。 しかし、乗算器ではそれを二進数で実現する。
符号無整数の場合の例
ここでは、例示のために8ビットの符号無整数の乗算について説明する。 乗算器の入力であるふたつの数を <math>a[7:0]</math> と <math>b[7:0]</math> とし、ビット配列とみなす。 この場合、8回の 1ビット乗算で 8つの部分積を求める。<math>a</math>の各ビットを<math>b</math>にかける。 つまり、それは <math>a</math> のビットを取り出して、その値に応じて <math>00000000</math> か <math>11111111</math> のどちらかのビットパターンを作り、ビット演算で論理積(<math>\mbox{AND}</math>)を実行するのと等しい。
<math> \begin{cases} p_0[7:0] = a[0] \times b[7:0] = \{a[0]\}\ \mbox{AND}\ b[7:0]\\ p_1[7:0] = a[1] \times b[7:0] = \{a[1]\}\ \mbox{AND}\ b[7:0]\\ p_2[7:0] = a[2] \times b[7:0] = \{a[2]\}\ \mbox{AND}\ b[7:0]\\ p_3[7:0] = a[3] \times b[7:0] = \{a[3]\}\ \mbox{AND}\ b[7:0]\\ p_4[7:0] = a[4] \times b[7:0] = \{a[4]\}\ \mbox{AND}\ b[7:0]\\ p_5[7:0] = a[5] \times b[7:0] = \{a[5]\}\ \mbox{AND}\ b[7:0]\\ p_6[7:0] = a[6] \times b[7:0] = \{a[6]\}\ \mbox{AND}\ b[7:0]\\ p_7[7:0] = a[7] \times b[7:0] = \{a[7]\}\ \mbox{AND}\ b[7:0] \end{cases} </math>
次に最終的な積を求めるため、部分積を以下のように足し合わせる。
<math>p_0[7]</math> | <math>p_0[6]</math> | <math>p_0[5]</math> | <math>p_0[4]</math> | <math>p_0[3]</math> | <math>p_0[2]</math> | <math>p_0[1]</math> | <math>p_0[0]</math> | ||||||||
<math>+</math> | <math>p_1[7]</math> | <math>p_1[6]</math> | <math>p_1[5]</math> | <math>p_1[4]</math> | <math>p_1[3]</math> | <math>p_1[2]</math> | <math>p_1[1]</math> | <math>p_1[0]</math> | <math>0</math> | ||||||
<math>+</math> | <math>p_2[7]</math> | <math>p_2[6]</math> | <math>p_2[5]</math> | <math>p_2[4]</math> | <math>p_2[3]</math> | <math>p_2[2]</math> | <math>p_2[1]</math> | <math>p_2[0]</math> | <math>0</math> | <math>0</math> | |||||
<math>+</math> | <math>p_3[7]</math> | <math>p_3[6]</math> | <math>p_3[5]</math> | <math>p_3[4]</math> | <math>p_3[3]</math> | <math>p_3[2]</math> | <math>p_3[1]</math> | <math>p_3[0]</math> | <math>0</math> | <math>0</math> | <math>0</math> | ||||
<math>+</math> | <math>p_4[7]</math> | <math>p_4[6]</math> | <math>p_4[5]</math> | <math>p_4[4]</math> | <math>p_4[3]</math> | <math>p_4[2]</math> | <math>p_4[1]</math> | <math>p_4[0]</math> | <math>0</math> | <math>0</math> | <math>0</math> | <math>0</math> | |||
<math>+</math> | <math>p_5[7]</math> | <math>p_5[6]</math> | <math>p_5[5]</math> | <math>p_5[4]</math> | <math>p_5[3]</math> | <math>p_5[2]</math> | <math>p_5[1]</math> | <math>p_5[0]</math> | <math>0</math> | <math>0</math> | <math>0</math> | <math>0</math> | <math>0</math> | ||
<math>+</math> | <math>p_6[7]</math> | <math>p_6[6]</math> | <math>p_6[5]</math> | <math>p_6[4]</math> | <math>p_6[3]</math> | <math>p_6[2]</math> | <math>p_6[1]</math> | <math>p_6[0]</math> | <math>0</math> | <math>0</math> | <math>0</math> | <math>0</math> | <math>0</math> | <math>0</math> | |
<math>+</math> | <math>p_7[7]</math> | <math>p_7[6]</math> | <math>p_7[5]</math> | <math>p_7[4]</math> | <math>p_7[3]</math> | <math>p_7[2]</math> | <math>p_7[1]</math> | <math>p_7[0]</math> | <math>0</math> | <math>0</math> | <math>0</math> | <math>0</math> | <math>0</math> | <math>0</math> | <math>0</math> |
<math>P[15]</math> | <math>P[14]</math> | <math>P[13]</math> | <math>P[12]</math> | <math>P[11]</math> | <math>P[10]</math> | <math>P[9]</math> | <math>P[8]</math> | <math>P[7]</math> | <math>P[6]</math> | <math>P[5]</math> | <math>P[4]</math> | <math>P[3]</math> | <math>P[2]</math> | <math>P[1]</math> | <math>P[0]</math> |
別の言い方をすると、<math>P[15:0]</math> は <math>p_0</math> + <math>p_1</math>の1ビット左シフト + <math>p_2</math>の2ビット左シフト + … + <math>p_{15}</math>の15ビット左シフトに等しく、最終的に 符号なしの16ビットの積が求められる。
符号付整数の場合
<math>b</math> が符号付整数だった場合、部分積を符号拡張した上で足し合わせる必要がある。<math>a</math> が符号付整数だった場合、部分積の <math>p[7]</math> を足すのではなく、それ以外の合計から引かなければならない。
上で説明した乗算器を2の補数による符号付整数を扱えるように修正するには、足し合わせる際に以下のように一部の項を逆転させ、かつ <math>p[0]</math> と <math>p_7</math> の左端に <math>1</math> を補う。ここで負号(<math>-</math>)の意味に注意されたい。これは符号の反転ではなく、ビットの反転である。各部分積 <math>p_i</math> の最上位ビットが反転されているのは、符号拡張を省くためである。<math>p_7</math> が逆に最上位以外のビットが反転されているのは、減算を加算で表すためである。これは2の補数の性質を巧妙に利用したものである。
<math>1</math> | <math>-p_0[7]</math> | <math>+p_0[6]</math> | <math>+p_0[5]</math> | <math>+p_0[4]</math> | <math>+p_0[3]</math> | <math>+p_0[2]</math> | <math>+p_0[1]</math> | <math>+p_0[0]</math> | |||||||
<math>-p_1[7]</math> | <math>+p_1[6]</math> | <math>+p_1[5]</math> | <math>+p_1[4]</math> | <math>+p_1[3]</math> | <math>+p_1[2]</math> | <math>+p_1[1]</math> | <math>+p_1[0]</math> | <math>0</math> | |||||||
<math>-p_2[7]</math> | <math>+p_2[6]</math> | <math>+p_2[5]</math> | <math>+p_2[4]</math> | <math>+p_2[3]</math> | <math>+p_2[2]</math> | <math>+p_2[1]</math> | <math>+p_2[0]</math> | <math>0</math> | <math>0</math> | ||||||
<math>-p_3[7]</math> | <math>+p_3[6]</math> | <math>+p_3[5]</math> | <math>+p_3[4]</math> | <math>+p_3[3]</math> | <math>+p_3[2]</math> | <math>+p_3[1]</math> | <math>+p_3[0]</math> | <math>0</math> | <math>0</math> | <math>0</math> | |||||
<math>-p_4[7]</math> | <math>+p_4[6]</math> | <math>+p_4[5]</math> | <math>+p_4[4]</math> | <math>+p_4[3]</math> | <math>+p_4[2]</math> | <math>+p_4[1]</math> | <math>+p_4[0]</math> | <math>0</math> | <math>0</math> | <math>0</math> | <math>0</math> | ||||
<math>-p_5[7]</math> | <math>+p_5[6]</math> | <math>+p_5[5]</math> | <math>+p_5[4]</math> | <math>+p_5[3]</math> | <math>+p_5[2]</math> | <math>+p_5[1]</math> | <math>+p_5[0]</math> | <math>0</math> | <math>0</math> | <math>0</math> | <math>0</math> | <math>0</math> | |||
<math>-p_6[7]</math> | <math>+p_6[6]</math> | <math>+p_6[5]</math> | <math>+p_6[4]</math> | <math>+p_6[3]</math> | <math>+p_6[2]</math> | <math>+p_6[1]</math> | <math>+p_6[0]</math> | <math>0</math> | <math>0</math> | <math>0</math> | <math>0</math> | <math>0</math> | <math>0</math> | ||
<math>1</math> | <math>+p_7[7]</math> | <math>-p_7[6]</math> | <math>-p_7[5]</math> | <math>-p_7[4]</math> | <math>-p_7[3]</math> | <math>-p_7[2]</math> | <math>-p_7[1]</math> | <math>-p_7[0]</math> | <math>0</math> | <math>0</math> | <math>0</math> | <math>0</math> | <math>0</math> | <math>0</math> | <math>0</math> |
<math>P[15]</math> | <math>P[14]</math> | <math>P[13]</math> | <math>P[12]</math> | <math>P[11]</math> | <math>P[10]</math> | <math>P[9]</math> | <math>P[8]</math> | <math>P[7]</math> | <math>P[6]</math> | <math>P[5]</math> | <math>P[4]</math> | <math>P[3]</math> | <math>P[2]</math> | <math>P[1]</math> | <math>P[0]</math> |
なお、乗数も被乗数も負の場合算術オーバーフローが発生するが、無視すればよい。
実装
古い乗算器アーキテクチャでは、シフターとアキュムレータを使って部分積を足し合わせる必要があった。また、部分積ひとつを計算するのに 1クロックサイクルを要した。最近の乗算器アーキテクチャは、Baugh–Wooley algorithm、テンプレート:仮リンク、en:Dadda multiplier等を使用して、1クロックサイクルで部分積をすべて加算する。ウォレス木型乗算器の性能は、被乗数の一方にブースの乗算アルゴリズムを施して加算すべき部分積の数を減らすことで、さらに向上させることが出来る。
アナログ乗算器
アナログに乗算を実行する回路で、周波数帯域の変換等に用いられる。 一般的な実装方法は <math>AB=\mathrm{e}^{\log{}A+\log{}B}</math> という等式を利用するものである[2]。
基本的な原理は次のものである。
- バイポーラトランジスタで <math>V_{BE}\propto\log{}I_C</math> となることを利用して、入力信号の対数を得る。
- オペアンプで加算する。
- 1と同様に <math>I_C\propto\mbox{e}^{V_{BE}}</math> を利用して2.で得た和の指数を取る(これが2数の積)。
(ただし、アナログ回路なので実際には各ステップは、ほぼ瞬時に進む。)
2の部分を減算に変更すれば、同様の原理で除算も可能。