NOM

National Semiconductor社のMM57109は、Number Oriened Microprocessorとも呼ばれ、浮動小数点演算専用の、マイクロプロセッサ的にも動作させることのできるLSIです。ただ、内容は電卓用LSIと同様のもので、外部とのインターフェースを他のマイクロコンピュータから利用しやすい形式に変更したようなLSIです。
MM57109はローコストながら低速のp-MOSプロセスで製造され、電源電圧9 V(+5 Vと-4 V)、最高クロック周波数400 kHzで動作します。肝心の演算速度はというと、四則演算で50 ms程度、三角関数で500 ms程度と、実に電卓的なスピードになっています。

MM57109
プラスチック28ピンDIPに納められています。これは久我様よりいただいたものです。

ピン配置は次のようになっています。
  I1/D1  1     28 DA1
  I2/D2  2     27 DA2
  I3/D3  3     26 DA3
  I4/D4  4     25 DA4
I5/ADR*  5     24 I6/JC
    SYNC 6     23 BR*
    OSC  7     22 DAS*
   ISEL  8     21 VDD
   HOLD  9     20 DO4
   R/W* 10     19 DO3
    POR 11     18 DO2
    RDY 12     17 DO1
  ERROR 13     16 F1
     F2 14     15 VSS
双方向の信号は存在せず、入力信号か出力信号かのどちらかしかありません。
VSSとVDDが電源ピンで、VSS - VDDが7.9 Vから9.5 Vで動作します。通常、TTLとインターフェース可能にするため、VSSに+5 V、VDDに-4 Vを与えて、9 Vの電源電圧で動作させます。以後、入出力電圧範囲について触れる場合には、この条件で考えることにします。
クロックはOSC端子から与えます。+4 Vから-2.5 Vまでの振幅を持つ320 kHzから400 kHzの間の周波数のクロック信号が必要です。動作周波数範囲が狭いのもp-MOSの特徴ですね。
PORはパワーオンリセット信号、HOLDはホールド信号で、ともに入力信号ですが、この2本だけ入力電圧レベルが特別で、Hが2 V以上、Lが-2.5 V以上となっていて、クロック信号と同様に通常のTTL出力を接続することができません。HOLD信号は命令実行を一時停止させるための信号です。
SYNC信号はマイクロサイクルごとにLパルスを出力する信号で、このLSIの内部処理の区切りを示しています。400 kHzクロック時に1マイクロサイクルは10 usとなります。後述しますが、四則演算には約5000マイクロサイクル必要だったりします。
RDY信号はHOLD信号と対になる出力信号で、次の命令の実行準備ができたときにHになります。HOLDがLなら8マイクロサイクルだけHになって、Lになる時に次の命令を読み込んで実行します。HOLDがHなら、HOLDがLになるまでHを出力し続け、それから命令読み込んで実行します。メモリないしCPUとの同期のために使います。
BR信号は分岐を意味する出力信号で、Lパルスで外部に用意したプログラムカウンタに分岐先アドレスをロードするタイミングを示します。
ISEL信号はI1/D1 - I4/D4およびI5/ADR*とI6/JCに命令を与えるべきかデータなどを与えるべきかを指示する出力信号です。
R/W*信号はOUT命令などで外部メモリやレジスタにデータを書き込むタイミングでLパルスを出力する出力信号です。
I6/JC信号は入力信号で、ISEL信号によって命令のMSBを読み込むかTJC命令の分岐条件を読み込むかが決まります。
I5/ADR*信号も入力信号で、ISEL信号によって命令の第5ビットないしAIN命令に対するデータ準備完了ステータスが読み込まれます。
I4/D4 - I1/D1信号は同じくISEL信号によって命令かデータのどちらかが読み込まれる入力信号です。
DA4 - DA1信号は出力信号で、デジットアドレスの意味です。AIN, IN, OUT命令の時に、データの桁アドレスを出力します。
DAS*信号はデジットアドレスストローブで、DA4 - DA1信号が有効であることを意味します。
DO4 - DO1はOUT命令のときにデータが出力されます。
F1とF2は命令でパルス出力を自由に出すことができるフラグ出力です。
ERROR信号は演算エラーのときセットされ、ECLR命令でリセットされるエラー出力です。

D4 - D1信号やDO4 - DO1信号で入出力されるデータはBCDデータで、命令に応じて入出力が行われます。命令は、CPUの出力ポートからRDY信号とHOLD信号でタイミングを作成して与えることもできますし、MM57109外部に用意したプログラムカウンタによって自動的にメモリから読み込むこともできます。プログラムカウンタを用意すれば、条件分岐命令なども使えて、複雑な計算をCPUを介さずに自動実行することすら可能ですが、その分岐命令時のアドレスを与える回路などもすべて外部で用意しなくてはならず、かなり複雑な外部回路が必要となります。また、CPUがいちいち制御するにしても、単なる数値の入力だけで4 msくらい必要になったりして、タイミングが中途半端に遅くてプログラムを組みにくかったりします。よくあるパターンだと、命令については出力ポートからCPUがタイミングをとって与えるけれども、数値の入出力については外部に小容量のメモリを用意して、そこからMM57109が自分で読み込んだり逆に書き込んだりできるようにして、演算や入出力が終わったタイミングで割り込みを要求するようなインターフェース法が使われます。
入出力がBCDデータというのも特徴的で、サイズは大きくなりますが、演算結果をLEDや端末へ出力するのには便利です。なお演算の有効数字は8桁で、さらに指数部はBCDで2桁分。まさに関数電卓的なLSIです。

内部レジスタとして、演算データを格納する内部スタックとしてX, Y, Z, Tの4個のレジスタがあります。スタックトップがXで、スタックの底がTとなっていて、一般の2項演算命令ではXとYの二つをポップして演算を行い、結果をXにプッシュしなおすことになります。そのとき、1レベルだけスタックの深さが変化しますから、Tレジスタには0が入ります。このほかにMレジスタがあって、関数電卓の「メモリ」と同じように使えます。スタックに対して演算を行いますから、ちょうど逆ポーランド式入力の電卓と同じ形の命令体系ですね。

次は命令についてですけど、大きく分けると、置数入力、移動、数学演算、クリア、分岐、入出力、モード制御の7種類に分類できます。
まずは置数入力命令。
Mnemonic code   実行時間  動作
0       00         /238   数値入力0。最初の桁が入力されたときにスタックプッシュが行われる。
1       01         /238   数値入力1。2桁目からはプッシュ動作はせずにXの数値が一桁上位にシフト
2       02         /238   数値入力2。されてから、その新たな最下位桁に追加される。
3       03         /238   数値入力3。
4       04         /238   数値入力4。
5       05         /238   数値入力5。
6       06         /238   数値入力6。
7       07         /238   数値入力7。
8       10         /238   数値入力8。
9       11         /238   数値入力9。
DP      12         /152   Decimal Point, 小数点入力。
EE      13         /151   Enter Exponent, 指数部入力指示。
CS      14         /166   Change Sign, 仮数部ないし指数部の符号を変更する。
PI      15         /1312  Constant pi, 3.1415927 -> X, スタックはプッシュされない。
EN      41         /552   Enter, 数値入力後処理を行い、次の数値入力の準備を行う。
NOP     77         /122   No Operation, 数値入力後処理のみ行う。
HALT    17         /134   Halt, RDY = 1としHOLD = 1を待つ。NOPと同動作だが入力後処理を行わない。
Mnemonicは命令ニーモニックを意味し、codeの欄にはI6 - I1に与えるべき命令コードを8進数で書いてあります。実行時間は命令実行に必要な平均マイクロサイクル数と最大マイクロサイクル数を平均/最大の形で記入してあります。前述のように400 kHzクロック周波数のとき1マイクロサイクルは10 usですから、大まかに命令実行時間がわかります。
このグループは、最初は把握しにくいですが、要は電卓のキーをたたく動作とまったく同じ動作を行うようになっています。
0 - 9, DP, PI命令が最初に実行されるとスタックが1レベル移動して、空になったスタックトップのXレジスタに数値が入れられます。そのあとで続けて0 - 9, DP, PI命令などが実行されると、スタック操作は行われずにXレジスタの数値が変化します。すると、23を入力するときと、2と3の二つの数値を入力するときにはどうするかという問題が生じますが、その場合には二つの数値の区切りとしてEN命令を実行します。EN命令では数値を内部形式に正規化するとともに、スタック操作をあらかじめ行ってしまいます。したがって、EN命令の直後に0 - 9などの命令を実行すると、スタック操作を行いません。スタック操作を一切行いたくない場合はEN命令の代わりにNOP命令を利用します。HALT命令は実際には何も行わない命令で、たとえば1 HALT 3の順に命令を実行しても13という数値がXレジスタに入ります。
なお、たとえば最初の数値入力で行われるスタック操作などの前処理には、上記の表で示した以外にさらに多くのマイクロサイクルが必要とされます。

移動関係の命令には次のものがあります。
Mnemonic code   実行時間  動作
ROLL    43         /905   スタックの内容を回転する。X -> T, T -> Z, Z -> Y, Y -> X
POP     56         /448   スタックポップ。Y -> X, Z -> Y, T -> Z, 0 -> T
XEY     60         /652   X exchange Y, X <-> Y
XEM     33         /812   X exchange M, X <-> M
MS      34         /839   Memory Store, X -> M
MR      35         /1385  Memory Recall, M -> X
LSH     36         /168   Left Shift, 仮数部を1桁だけ左にシフトする。
RSH     37         /173   Right Shift, 仮数部を1桁だけ右にシフトする。
まぁ、特に解説もいらないでしょう。

数学演算命令はMM57109の目的ともいえるもので、四則演算から関数までそれなりに充実しています。
Mnemonic code   実行時間  動作
+       71     2200/6600  X + Y -> X, スタックはZ -> Y, T -> Z, 0 -> Tとなる。
-       72     2200/6600  X - Y -> X, スタックはZ -> Y, T -> Z, 0 -> Tとなる。
*       73     3200/22700 X * Y -> X, スタックはZ -> Y, T -> Z, 0 -> Tとなる。
/       74     7800/22300 X / Y -> X, スタックはZ -> Y, T -> Z, 0 -> Tとなる。
YX      79    55400/99500 X**Y -> X, スタックはZ -> Y, T -> Z, 0 -> Tとなる。
INV +   40 71  1700/5500  M + X -> M
INV -   40 72  1700/5500  M - X -> M
INV *   40 73  2700/21400 M * X -> M
INV /   40 74  7300/21100 M / X -> M
1/X     67     4500/22800 1 / X -> X
SQRT    64     7000/30200 Square root, SQRT(X) -> X
SQ      63     3000/21900 Square, X**2 -> X
10X     62    27400/96500 Ten to X, 10**X -> X
EX      61    30800/93900 E to X, Exp(X) -> X
LN      65    24800/92000 Natural log of X, ln(X) -> X
LOG     66    30700/92600 Base 10 log of X, log(X) -> X
SIN     44    56200/95900 Sine X, sin(X) -> X
COS     45    56200/95900 Cosine X, cos(X) -> X
TAN     46    35000/97600 Tangent X, tan(X) -> X
INV SIN 40 44 54000/93900 Inverse Sine X, Asin(X) -> X
INV COS 40 45 54000/93900 Inverse Cosine X, Acos(X) -> X
INV TAN 40 46 30200/92900 Inverse Tangent X, Atan(X) -> X
DTR     55     9600/41700 Degrees to Radians, 角度を度からラジアンに変換。
RTD     54     9600/41700 Radians to Degrees, 角度をラジアンから度に変換。
四則演算はスタックトップへの操作のほかにメモリとの四則演算も用意されています。まさにメモリは関数電卓のメモリの役目を果たしています。ニーモニックにも注目してほしいのですが、メモリへの四則演算はINVというものが 前置されています。後の方のINV SIN命令なんかでもわかるように、このINVというのは関数電卓にありがちなINVキーと同じもので、特殊な操作であることを示す前置コードになっているわけです。コードのほうを見ると、INV部分が40に対応していることがわかります。40 71などの40が前置された命令は2 Byte命令になります。
それにしても、乗算で最悪22700マイクロサイクル、つまり0.2秒以上、初等関数の場合には最悪で1秒弱の計算時間が必要になるというのは、あまりに遅いと感じられるかもしれません。8 bitマイクロプロセッサのソフトウェアによる浮動小数点演算より1桁くらいは遅い計算速度です。内部は一種のp-MOSプロセス低速低機能プロセッサのマイクロプログラム制御によるソフトウェア処理ですから、普通のマイクロプロセッサより遅くなってもしかたありません。まぁ、当時の関数電卓用LSIの演算性能も似たりよったりでした。=キーを押してから表示まで1秒くらいかかっても、関数電卓なら気にもならない時間です。しかし、たとえばある計算のために四則演算が10回程度に三角関数計算が3回ほど必要だとしたら、5秒くらい待たされてしまうかもしれません。そんなとき、ユーザがコンピュータも頑張っているなぁと感心している人ばかりならかまいませんが、そんな人でもじきに不満に思うようになりそうです。とはいえ、このMM57109が使われていた1970年代後半ではEPROMが2 KByte分で1 - 2万円くらいしていたうえに、組み込み用機器のプログラミングを浮動小数点演算が自由に使えるコンパイラで行うこともできないような時期でしたから、数千円で購入できたMM57109は結構便利に使えたりしたのです。まさに関数電卓並みの速度で、比較的単純な計算しかしないのなら、プログラマブルな電卓を利用すればよさそうですが、関数電卓にセンサ類をインターフェースしたりはできませんから、低速でもかまわない計測機器や自動制御装置で、センサの値をなんらかの数式で補正して表示したり、その補正結果をもとに制御を行うような場合、MM57109はそれなりに便利に使えます。同時期にAm9511という、8 bitプロセッサのソフトウェア演算よりは一桁高速に演算を行う浮動小数点演算LSIもありましたが、価格もMM57109より一桁は高価なので、本当に高速演算が必要な用途以外にはおいそれと採用できません。関数電卓用LSIと同程度の性能ではあっても、関数電卓用LSIに近い価格で入手できる利点はあなどれません。それにしても、実行時間の項にこれだけ桁の多い数字の並ぶのも珍しいかもしれませんね。繰り返しになりますが、400 kHzクロックのとき実行時間の項の単位は10 usとなります。

クリア命令には次の2種類があります。
Mnemonic code   実行時間  動作
MCLR    57         /734   Master Clear, 前レジスタの初期化および有効数字8桁の浮動小数点モードに設定。
ECLR    53         /163   Error Clear, エラーフラグのクリア。
MCLR命令はパワーオンリセットと同じことを行う命令です。あとは自明ですね。
XやMの内容だけをクリアする命令は存在しません。それも後述のIN命令などで0をXに入力したり、あるいはPOP命令でXの内容を捨てることによって代用できるでしょう。

分岐命令については次のものがあります。
Mnemonic code   実行時間  動作
JMP     25 xx      /186   Jump, 2 Byte目のアドレスにジャンプする。
TJC     20 xx      /208   Test Jump Condition, JC = 1のときにジャンプする。
TERR    24 xx      /191   Test Error, エラーフラグがセットされているとジャンプする。
TX=0    21 xx      /278   Test X = 0, X = 0ならジャンプする。
TXF     23 xx      /277   Test |x| < 1, abs(x) < 1ならジャンプする。
TXLT0   22 xx      /197   Test X < 0, xが負の数ならジャンプする。
IBNZ    31 xx      /2314  Increment memory and Branch if M != 0, Mをインクリメントして0以外なら分岐する。
IBNZ    32 xx      /2314  Decrement memory and Branch if M != 0, Mをデクリメントして0以外なら分岐する。
これらの分岐命令はすべて2 Byte命令で、2 Byte目にジャンプ先アドレスを指定します。しかし、2 Byte目はMM57109によって読み出されても、MM57109自身は利用しません。ちょうど、2 Byte目のデータを読み出しているタイミングで、分岐する場合に限ってBR*パルスを出力しますから、そのBR*パルスを利用して外部プログラムカウンタにデータをロードすることによって分岐命令の機能を実現します。逆にいえば、プログラムカウンタをMM57109外部に用意したインターフェース以外の、メインのCPUのI/Oポートから直接MM57109を操作したりするインターフェースの場合には、ほとんど役に立ちません。もちろん、その場合でもBR*パルスをメインのプロセッサの割り込み信号などに使用すれば、条件成立によってプロセッサに割り込みをかけることも可能ですけど。

入出力命令には次の命令があります。
Mnemonic code   実行時間  動作
IN      27         /395   Multi-digit input to X, Xに数値を入力する。スタックはプッシュされる。
OUT     26         /583   Multi-digit output from X, Xの内容を出力する。
AIN     16         /284   Asynchronous Input, 1桁ずつ読み込む。
SF1     47         /163   Set Flag 1, F1に1を出力。
PF1     50         /185   Pulse Flag 1, F1に1パルスを出力、すでに1のときは0を出力。
SF2     51         /163   Set Flag 2, F2に1を出力。
PF2     52         /185   Pulse Flag 2, F2に1パルスを出力、すでに1のときは0を出力。
PRW1    75         /130   Pulse R/W* 1, R/W*に0パルスを出力。
PRW2    76         /130   Pulse R/W* 2, R/W*に0パルスを出力。
置数関係の命令では1桁ずつ電卓のキーを押すのと同じようにして数値を入力していましたが、メインのCPUから数値を与えるためには不便です。やはりひとまとまりの数値を一度に与えたいわけで、そのための命令がIN命令です。IN命令を実行すると、特定のタイミングで数値の各桁を入力するように信号が出力されます。それに合わせてCPUからデータを順番に与えたり、メインのCPUとMM57109とのローカルな共有メモリを用意しておいてそこから自動的にMM57109が読み込むような外部回路を付加させることもできます。
IN命令の逆がOUT命令です。
また、置数命令で1桁ごとに数値を入力するのと同じように、1桁ずつデータとして数値を与える命令がAIN命令です。
その他、MM57109の特定の端子を操作するための命令も、このグループに含まれています。

モード制御命令には次の3種類があります。
Mnemonic code   実行時間  動作
TOGM    42         /157   Toggle Mode, 浮動小数点とEタイプの間のモード切り替え。
SMDC    30 xx      /163   Set Mantissa Digit Count, 仮数部の有効桁数を指定する。
INV     40         /166   Inverse Mode, INV命令を構成する。
IN命令やOUT命令で使用される入出力データフォーマットには、浮動小数点タイプとEタイプの2種類があります。そのどちらを使うか指示するのがTOGM命令です。なお、リセット時ないしMCLR命令後には、浮動小数点タイプを利用するモードになります。
SMDCは2 Byte目で仮数部の有効桁数を指示します。1から8までの値を指示できます。リセット後ないしMCLR命令後には8桁まで有効という設定になります。
INV命令はINV SIN命令とかINV +命令に使われているプリフィックス命令ですね。

入出力に使われるデータ形式には浮動小数点タイプとEタイプがあります。その形式について、それぞれ説明します。
浮動小数点タイプはこのような入出力形式となります。
 
DA4 - DA1 小数点位置 D4/DO4 D3/DO3 D2/DO2 D1/DO1
2 S 0 0 0
3 小数点位置
4 11 最上位桁
5 10 ...
... ... ...
MDC + 3 12 - MDC 最下位桁

この表の上から下へ入出力が行われます。DA4 - DA1は、IN/OUT命令実行時にMM57109が出力する桁アドレス信号で、何番目のデータを入出力しているか外部に通知する信号を10 進数表示してあります。MDCはSMDC命令で指定される有効桁数で、通常は8です。Sは数値の符号ビットで0が正、1が負を意味します。
IN命令による入力時には、D4 - D1端子から、まず符号ビットを含む4 bitデータが読み込まれ、次に小数点位置が読み込まれます。小数点位置は10進数で4から11までの範囲の値を指定でき、表の第2列目に記入されている値と同じ数が入っている欄の桁と次の桁の間に小数点があると解釈されます。つまり小数点位置が11で最上位桁のデータが1、次の桁のデータが0だとすると、1.0xxxxxxという場所に小数点があると解釈されます。最上位桁からMDC個数分の4 bit BCD表示のデータが読み込まれて、数値がMM57109内部で組み立てられます。
OUT命令の場合には、データがDO4 - DO1端子から出力されることを除いて、IN命令と同じように出力が行われます。
Eタイプはこのようになっています。
 
DA4 - DA1 D4/DO4 D3/DO3 D2/DO2 D1/DO1
0 指数部上位桁
1 指数部下位桁
2 Sm 0 0 Se
3 - - - -
4 最上位桁(小数点はこの直後)
5 ...
... ...
MDC + 3 最下位桁

ここでSmは仮数部の符号、Seは指数部の符号で、ともに0が正、1が負を意味します。第4語目は無視されます。
指数部も仮数部も、すべてBCD表示のデータとして扱われます。
このように、どちらのデータ形式もBCD表示を基本にしているので、非常に簡単にLEDに数値を表示したり、文字コードに変換して入出力を行うことができます。反面、A/D, D/Aコンバータを用いて外部の何かを制御するための関数計算に利用しようとすると、BCDコード入出力のA/D, D/Aコンバータは種類が少なく価格が高めなこともありますし、少し余計な手間かコストが必要となります。

Return to IC Collection