乗算はたいへん(乗算1)

2018.04.02(since2017.1.1)
サイトマップ トップ < 訂正<<*> 乗算2


ひっ算 素直な解法

小学校で九九を習うので、1桁*1桁の乗算は簡単です。でも、2桁以上が入ってくると、暗算苦手でひっ算したくなります(習い事に縁がありませんでしたが、そろばん習ってた人がうらやましい話だったりします)。下左。

ことろが、10進数の2桁掛け算でも、簡単にできる例があります。例えば、69*10=690の例(上右)です。このように、10進だったら、10をかける場合は、1桁ずらすだけ:下位に0を書き加えるだけです。
2進数の場合も、同様に、2をかける(2のべき乗:2*2,2*2*2,2*2*2*2.……..)のは簡単です。

では、2のべき乗でない数字はどうするんでしょう?例えば6x6は?ひっ算で考えましょう。

案外簡単ですね?もとの数を桁に応じてちょっとずらして足し算するだけです。  でも6x60はどうですか?

 6* 60 = 6*( 32(=2^5) + 16(=2^4) + 8(=2^3) + 4(=2^2) ) =360 =168H

うーん。まあ、4組の数字を足せばいいので、できることはできますね? でも一工夫。

  60 = 64 -4 = 64 + (-4)= 2^6 -2^2  ->  60*6=(2^6-2^2)*6

これなら、ビットシフトと1回の加算(減算ともいうが負の数の加算)で,できちゃいますね。
具体的に言うと、引き算は、2の補数という概念を用いて足し算することになります。

ところで、マイナスとは何? 1-1=0、100-100=0... プラスとマイナスの同じ数を足せば0になる定義が具合良いでしょう。10進では、最初の桁に、"-"と書けばマイナス。"+"と書くか省略すれば、プラスです。2進数の場合、最上位の桁を、サインビットを名付けて、ここが1ならマイナスと定義します。例えば、5を例として、-5を考える。 5+?=0となる?は、0101(B)+(1010(B)+0001(B))=10000(B)でしょう。数値3桁に、1ビットのサインフラグを追加して4ビットで、計算結果の5桁目は、見ないことにします(4桁4桁の引き算では5桁繰り上がり無し。加算も考慮するなら、最初にもう一ケタ追加して考える)。  ここから想定できるのは、元の数に最終有効数字桁数とサインビットの分桁増やしたうえで、ビット反転し、それだけでは、”0”ではなくall”1”になるので、1を加えます。2の補数によるマイナス表現とはこういうものです。

補数を作るのは、ビットの反転と、+1の演算が面倒だと思う方へ、そこ気が付くのは素晴らしい。

実は、汎用加算器には、下位からの繰り上がり(キャリー)を加えるという機能があるのが普通です。なぜなら、汎用機を複数つかって、もっと桁数の多い計算に用いる事ができるからです。簡単に言うと、下の桁からの繰り上がり信号をもらったら、”+1”する機能を持っていて、加算結果、繰り上がりがあったら、繰り上がり信号を出力するというのが、基本仕様になります。マイコン命令に関しても単純に2レジスタ間加算する命令の他に、このキャリーを加える命令があるはずです(8ビット演算を拡張して、18ビット演算するとき、下位の計算結果の繰り上がりを、上位計算時に配慮する必要があるから。でも補数うんぬんより単にそもそも引き算命令があるのが普通。ハードは反転と+1機能を加算に追加するのが、引き算命令)。これを使えば、補数のための+1という加算は、ほどほど簡単だというのを、下図に示します。回路は加減算切り替え実施回路で、minas信号で、B(7:0)の反転:1の補数と、加算器のキャーリー入力への入力と、8ビットデータに対する最終結果桁数合わせに上位2ビット拡張(正の8ビットストレートバイナリどおしの加算を想定し、足し算による繰り上がり1ビット拡張と、サインフラグ(=0:正/1:負)1ビットで10ビット)の出力。



ただし以降の回路図、Z80プログラムとも未検証。そのうち検証方法考え付いたら、検証改定考えます。

ロジック加減算回路

固定の数字を掛けるという場合、分解して、いくつかの和を考えればできる。工夫すれば、かなり簡単な数字がある事を覚えておいてください

ここ重要(な雑談):引き算の実現の方法(2018.04.02)

(A)+(-B:2の補数化)の従来加算回路流用案 >有能さ> (A)-(B)の新引き算回路新設

機械的に引き算回路作るのは難しいわけではありませんが、別回路を用意するのはもったいないし、新規システムは危険性無いとは言えない。
従来加算回路に、単純にビット長上位に拡張(名前は単にサインフラグと呼ぶことにするという取り決め、とまあ計算結果の正負判定としてこれを残すことも必要かな?)と、2の補数変換のために、最下位ビットへの繰り上がり処理機能追加)→(他のビット相当のフルアダー化)と引き算データのビット反転の拡張するだけで、足し算引き算兼用回路に作り替えることができます。あ、ここでほめるのは、2の補数という概念を利用すると、足し算回路が、わずかに手を加えるだけで、引き算も実行できるという論理体系を考え出したことね。
ものづくりのためには、従来のものをいかに活用するか?というのも重要だったりします。アナログテレビだって、従来の白黒放送互換で、カラー位相変調というアイデア加算することによって、従来の白黒テレビでも、白黒して楽しめますというスタンスだったから、切り替えは徐々にうまくいったと考えてよいのかと思います。ブラウン管白黒テレビの時代に、100万円のハイビジョンテレビとか、50万円のディジタルテレビを導入しないと、地デジ切り替えで、一般の人テレビは見れなくなりますという話だったら反発あったと思いますよね。 技術主導で始めたアナログハイビジョン(ミューズ)とか、アナログテレビのディジタル処理すれば後わずかな追加でできるというゴーストキャンセラーとかも、単体としては、普及できなかったしねぇ

もう少し2進の乗算のひっ算を考えましょう。固定値掛け算なら圧縮できることを、示してきましたが、任意の8bitどおしの掛け算は省略できません。
最初の10進ひっ算と同じ問題を、2進数で、演算してみましょう。2のべき乗の和を計算することになります。

でも、先ほど述べたように、汎用乗算機は、固定の数値8DHだから、偶然0すなわち省略できる桁も、他の数字の場合に備えて、準備していなければなりません。するとひっ算も省略しないで書けば、

ところで、上の例の3つ(0の加算数えると4つ)の数の各桁の足し算するものは、標準ゲートICに見当たらないので、そのまま素直に2項の足し算するゲートICを基本に、8bit*8bit=16bitを、論理回路で実現すると 下記になります(未検証だけどまあ、間違いないでしょう)。ARMが1命令1ckで掛け算が実行できるのは、仮に下記のような回路何でしょう。ただし遅くても良いならともかく、繰り上がり信号が、下位から上位に伝搬して、変化するのが遅いので、動作を加速する工夫がいろいろ必要になります。

上記の回路はプリント基板レイアウトソフトEAGLE(のフリー版)を使って、標準ライブラリから汎用ロジックIC(74シリーズとか、個人的習慣として”TTL”と昔の名前で呼んだりする)を適当に選んで書いたもので、まったく未検証ですが、遅くてよいなら、動くと思います。 ICのセルベース設計経験者としては、無駄なトランジスタが多すぎると感じますが、何桁目だから何ビットずらすという動作、かける数の各ビットの0/1判断でかけられる数を加えるか、加えない(ANDゲートが0にしてそれを加える)かという、ひっ算のアルゴリズムを素直に表しています。 ANDデート(7408)と、4ビットフルアダー(7483)だけの回路ですから、ロジック初心者の方でも、判りやすいでしょう。

参考:
7483(フルアダー)といいながら、画像では、74LS83と表示されたりしますが、同じロジック(同じピン順で同じパッケージだとしても)でも、中の半導体の種類によって、本例のLSとか、無記名とか、HCとか、ACTとか...(その他いっぱい)あって、計算時間以外にも、デジタル信号を1と見るか0と見るかの境目電圧、それどころか、使用する電源電圧すら違う場合ありますので、本来、なにげに適当に混在できるものではありません(最悪壊れます)。
CQ出版の”最新74シリーズIC規格表’95” を手元にCADソフトでライブラリが見つけられたものを使いました。本を買わなくても今ならweb上でも、動作内容信号の意味など解るんじゃないかな?

では、これを素直に、Z80のプログラムで記述してみましょう(現行の、CISCタイプ産業用H8はもちろんRICSタイプARMなんかは、1命令で掛け算実行できます。したがって、ここは、あくまで、原始的な方法で、アルゴリズムを考えているだけだと思って下さい。Z80には、設定か数だけループを回すのに特化した命令DJNZをもっていたりします。



秋月で買ったエミュレータあった気がするけど見つけられず未確認(FDベースだったのでどのみちだめ?フリーソフトも良く分からないので、そのうち方法考えて検証します)

H8がたった20ckで乗算できるのと比べると、ずいぶん遅いですね。

ちょっと改良版:途中で残りビット0なら打ち切り例。かける数(Aレジスタ格納)が平均して127以下とかなら平均したら高速になるかな?

ハードウエアも前の一括加算ではなく、順次加算で実行する回路を示しましょう。

標準論理ゲートを使うと、欲しい機能がなかったり、その分外付けゲート追加すると、回路図大きくなるので、適当な処で妥協しました。

8bitなので、8ckで計算する回路が望ましいのですが、リセット回路が標準ロジックではちょっと面倒だったりしました。
回路は、未検証ですが、予想タイミングのようにおおむね動作すると思います。最初の初期化クロックに短いパルスがのるので、気に入らない回路で、あと、シフトレジスタ1ケ追加して、保護したいものですが、まあ、出ても大丈夫な回路構成にしたつもりです。H8の16bit乗算命令が1命令20ckというのは、上記のような、桁ごと時分割で処理する回路が採用されている可能性が高いと思います。 手を抜くと、8ビット掛け算が9ckになっていますから、命令読み込みサイクルと、実行サイクル、フラグなど後初期確定時間を考えると、その程度時間がかかるのは納得できてしまいます。

DCバスが原理的に発生しないCMOS回路において、消費電力は、駆動クロック周波数*負荷容量(コンデンサ=つながるCMOSゲートの数と配線の長さに比例します)。したがって、旧型IC設計屋さんの頭の中には、高速クロックにつながる回路は最小限にして、さらに、使わないクロックは止める(同期クロックで全部うごかすのではなく、必要なクロックを供給して必要回路だけ動かすというのが、気持ち良い回路になります。上記例でも、必要なクロックのみ使う設計になっています。 その分他の回路群とのデータ同期には、頭を使うことになります。ちなみにクロックを止めない回路は下記。 対して変わらないという話はありますが。 こんなこと考えるので論理合成ソフトになじめない悲しい老害。


サイトマップ トップ < 訂正<<*> 乗算2