ブログの練習

ブログを書く練習です。
最近はレトロな計算機(電卓、マイコン、パソコンなど)
に関することを書き始めました。

Intel 4004 (その9) メモリ領域へのアクセス

2023-02-16 12:56:56 | マイコン(4004)

この2週間ほどプログラムの作成に注力していてブログにまとめるのを後回しにしていたのでネタが貯まっています。プログラムや回路図はもう少し整理してからGitHubで公開する予定ですが、いろいろ忘れそうなので、途中経過を備忘録としてブログに残しておきます。

今回はメモリ領域へのアクセスについて書きます。なお、4004のメモリ領域はデータ領域(4002)とプログラム領域(4298経由)で明確に分かれていて、空間もアクセス方法も全く別のものです。

前回までに、Lチカやシリアル通信が動くことを確認しました。ここで使っている機能は、
(1) CPU(4004)内の機能(命令実行、内部レジスタ、TEST端子入力)
(2) メモリインターフェースを介したプログラム領域ROMの読み込み(4289経由での2716へのアクセス)
(3) データ領域RAM(4002)の出力ポートへの書き込み
です。未確認な機能に、
(4) データ領域RAMの読み書き
(5) プログラム領域RAMの読み書き(4289経由での6116へのアクセス)
があります。
(4)と(5)を確認するための簡易的なモニタープログラムを作成しました。メモリの読み書きがちゃんとできるかを確認するのが目的なので機能は最小限、操作性は二の次です。

まずは(4)のデータ領域RAMの読み書きから。たいていのCPUにはアドレスを指定してメモリを読み書きする命令、例えば8080ならHLレジスタをアドレスにしたMOV A, M とか MOV M, Aなどがあります。しかし4004にはそんな便利な命令はありません。
データ領域は一応12bitのアドレス空間になっているのですが、
上位4bitをCM0~CM3に出力するためのDCL命令。
下位8bitをあらかじめメモリに伝えておくSRC命令。
4bitのデータ(キャラクタと呼ぶようです)を読み出すRDM命令と書き込みのWRM命令。
を使ってアクセスします。例えば、000H番地の4bitを読むには、

LDM 0
DCL
FIM P0, 00H
SRC P0
RDM

のようになります。
メモリを1バンクしか使わない小規模なシステム(4002-1を2つと4002-2を2つまで)であればDCLは省略できます。今の実験ボードは4002-1を4つの2バンクで作ってしまったのですが、-1を2つか、-1と-2の2つに変更しようと思ってます。メモリアクセスのたびに上位4bitを気にするのは結構面倒な上にプログラム用のメモリも浪費してしまうので。
4004はもともと電卓を作るために開発されており、メモリ空間下位4bit分(16個)のキャラクタをひとまとめにして「レジスタ」と呼び、1つのレジスタで1つの数値を表現するという使い方が想定されています。
SRC命令で指定している8bitは上位から、2bitでチップ指定、2bitでレジスタ指定、4bitでキャラクタ指定というわけです。
各レジスタには(16個のキャラクタとは別に)4つの「ステータスキャラクタ」があり、そこへのアクセスのためにRD0~3, WD0~3という特別な命令が用意されています。ステータスキャラクタは数値の符号や指数の格納用に用意されたようです。
1つの4002はレジスタ4つ分のメモリを持っており、容量は全部で4 * (16+4) * 4bit = 320 bitになります。データシートの最初に書かれている「Four Registers of 20 4bit Characters」の意味が理解できました。
簡易モニターでは、バンクとチップを指定して4つのレジスタに読み書きする機能を実装しました。動作の様子が冒頭の画像(と下の方に貼った動画)です。

次にプログラム領域のメモリアクセスです。プログラム領域は上記データ領域とは別に存在する12bitのアドレス空間です。こちらはデータ領域に比べるとわりと素直な空間になっており、データも8bit幅あります。ただし、条件分岐(JCN, ISZ)や間接ジャンプ(JIN)、間接メモリ読み込み(FIN)は8bitしか指定できないので、256byte単位の同一ページにしか分岐やアクセスできないという制約があります。12bitフルに指定できるのは無条件ジャンプ(JUN)とサブルーチンコール(JMS)だけです。
また、書き込み命令(WPM)はありますが、読み込み命令(RPM)は4040で拡張された命令で、4004にはありません。FINを使えば読めるだろうと思っていて、実際読めたのですが、書き込みの方に落とし穴がありました。
実験ボードでは、000H~7FFHの2kBをROM、800H~FFFHの2kBをRAMに割り当てています。
4289から出力されるアドレスは、上位4bit(C3~0)と下位8bit(A7~0)と名前が分かれていますが、命令読み込み時はC3~0はA11~8相当になります。C3~0は実質A11~8だよねと思ってメモリ周りの回路を組んでいたのですが、データシートの下記記述を見て唖然としました。
During execution of WPM or RPM, the 4289 does not transfer the high order 4bits of the SRC register to C0-C3. Instead,it forces all 4 chip select output buffers to a logic "1" state
WPM命令による書き込みの際はall 1になってしまうようです。確かに言われてみればSRCレジスタは8bitなので、上位4bitを含めた12bitを指定するには足りません。にしても、FINみたいに現在のPCの上位4bitをC0-3に出力するぐらいのことをしてくれるかと思っていたのですが、確認不足でした。
ポートなり別なところ(CPUのCM0~3あたり)から4bit指定できるようにすればなんとかなりそうですが、追加の回路を作るにしてもレベル変換等面倒なので、とりあえずRAMへの書き込み時の上位4bitはall 1で、F00H~FFFHの256byteのみで我慢することにしました。

4289からRAMへのアクセスは、4bitづつ2回に分けて、データバスではなくI/Oポート経由で行われます。最初は、1回目と2回目を示すF/L信号の解釈を間違えていたのでうまく動かず、オシロで観測して間違いに気づきました。~FLは、1回目がH、2回目がLです。

でもやっぱりデータシートにLでOPR、HでOPAって書いてあるから逆な気がするなあ。と思って再度よく読んだところ、自分の間違いに気がつきました。命令実行サイクルだとOPR、OPAの順に現れるので、OPR(上位4bit)が先(1回目)、OPA(下位4bit)が2回目のアクセスだと思っていたのですが、プログラムメモリ操作はOPAが先、OPRが後とちゃんと書いてありました。
"Hence, odd numberd program memory operations select OPA and even numberd program memory operation select OPR (starting with #1 from reset)"
1回目は0じゃなくて1なのか~。そういえば、Intelなのに先に上位を書くのに違和感を感じていたんだよなあ。結局最初の回路で正しかったのか。あとで回路を戻してプログラムを修正しておかなくては。

間違いがもう一つ。I/Oポートのデータは4002の出力ポートのように、H(Vss, +5V)で"0"、L(Vss-6.5~-12V)で"1"だと思っていたのですが、"l/O /Pos."って書いてありました。データバスの74LS540をLS541に変更です。


I/Oポートは+5Vで"1"なのはいいのですが、"0"は-1.5~-7VなのでTTLに継げるにはダイオードと制限抵抗が必須です。試しにダイオード(とLS540)を外してみたら-7Vが観測できました。


そんなこんなで、数々の間違いを修正したところ、ちゃんと動作するようになりました。この動画はプログラム領域とデータ領域への読み書きの様子です。
(さっき気がついたFL信号、OPA、OPRの順序の間違いの修正前ですが。)


この末尾の"34 C0"というのが、メモリを読むサブルーチン

FIN P2
BBL 0

で、レジスタP0(8bit)で指定されるこのメモリページ(F00H~FFFH)の値をレジスタP2に入れて戻ります。


次回は電卓プログラムについて書きます。

コメント    この記事についてブログを書く
  • X
  • Facebookでシェアする
  • はてなブックマークに追加する
  • LINEでシェアする
« Intel 4004 (その8) シリアル... | トップ | Intel 4004 (その10) 電卓を... »
最新の画像もっと見る

コメントを投稿

マイコン(4004)」カテゴリの最新記事