通常、TD4、およびその命令を実行できる自作CPUの Kageki では、プログラムカウンタが4ビットなので、16ワードまでのプログラムしか扱えない。
しかし、この長さでは、複雑なプログラムを組もうとすると容量オーバーになってしまうことが多い。
そこで、今回は、本体には手を加えず、ROM部分の回路に工夫をすることで16ワードを超えるプログラムを扱う方法を考えた。
作戦
TD4やKagekiで使うROMは、4ビットのアドレスを入力すると対応する8ビットのデータが出力されるものである。
本体のクロックやリセットは供給されない。
出力しているデータは、ROM側から参照できる。
また、TD4やKagekiには、命令としては未定義のビット列が存在する。
そこで、
- 現在のデータの上位4ビットが(未定義の命令から選んだ)キーのビット列になっていれば
- ROMにアクセスする時のアドレスの上位4ビットをデータの下位ビットに設定する
という処理を行い、ROMのデータを格納する部分に8ビットでアクセスするようにすることにした。
未定義のビット列は4種類あるので、理論上最大10ビットのアドレスを用いることができるが、8ビットにすることで既存のROMインターフェースを再利用しやすくなる。
この処理により、アドレスの上位ビットを設定するデータの所にアクセスしようとすると、次のクロックを待たずに切り替え先にかわりにアクセスすることになる。
なお、本体のリセットに対応するため、ROMの16の倍数のアドレス (0番地を除く) はアドレスの上位4ビットを0にするデータにしておくべきである。
ハードウェアとしては、以下のような構造を想定する。
本体のクロックよりは十分高速だが、クロックとクロックの間でアドレスやデータの変化が完了する程度には低速のクロックを用いる。
例えば1MHz程度にするといいだろう。
変化途中のデータに誤って反応しないよう、クロック2回分のデータが一致した時にのみ切り替えを行う。
プログラム例
先日のガッテンRのようなものを拡張し、入力ポートのビット2 (0-origin) に1を入力すると「R」のかわりに「FB」を出力するようにした。
上位4ビットが 1010
のときにアドレスの上位ビットを切り替え、これを BNK
と表す。
位置 機械語 アセンブリ言語
--------------------------------
00 01111000 MOV B, 1000
01 00100000 KEY0: IN A
02 00001000 ADD A, 1000
03 11100001 JNC KEY0
04 00100000 KEY1: IN A
05 00001000 ADD A, 1000
06 11101000 JNC SEL
07 11110100 JMP KEY1
08 00000100 SEL: ADD A, 0100
09 11101011 JNC PLAYR
0A 10100010 BNK 0010
0B 10100001 PLAYR: BNK 0001
0C xxxxxxxx
0D xxxxxxxx
0E xxxxxxxx
0F xxxxxxxx
10 10100000 BNK 0000
11 10100000 RRET: BNK 0000
12 10010000 R0: OUT B
13 10110000 OUT 0000
14 10010000 OUT B
15 00000000 ADD A, 0000
16 00000000 ADD A, 0000
17 10110000 OUT 0000
18 10010000 OUT B
19 10110000 OUT 0000
1A 11110001 JMP RRET
1B 11110010 JMP R0
1C xxxxxxxx
1D xxxxxxxx
1E xxxxxxxx
1F xxxxxxxx
20 10100000 BNK 0000
21 10010000 F0: OUT B
22 10110000 OUT 0000
23 10010000 OUT B
24 10110000 OUT 0000
25 10010000 OUT B
26 00000000 ADD A, 0000
27 11111011 JMP F1
28 xxxxxxxx
29 xxxxxxxx
2A 11110001 JMP F0
2B 10110000 F1: OUT 0000
2C 10010000 OUT B
2D 10110000 OUT 0000
2E 00000000 ADD A, 0000
2F 10100011 BNK 0011
30 10100000 BNK 0000
31 10100000 FBRET: BNK 0000
32 10010000 B0: OUT B
33 00000000 ADD A, 0000
34 00000000 ADD A, 0000
35 10110000 OUT 0000
36 10010000 OUT B
37 10110000 OUT 0000
38 10010000 OUT B
39 10110000 OUT 0000
3A 10010000 OUT B
3B 10110000 OUT 0000
3C 11110001 JMP FBRET
3D xxxxxxxx
3E xxxxxxxx
3F 11110010 JMP B0
拡張ROMの実装
今回は、Software ROM Board 用のソフトウェアとして実装した。
hardware_cpu/software_rom_bank16_hex.ino at main · mikecat/hardware_cpu
このソフトウェアは、HEXファイルをシリアル通信で送り込むことで、ROMのデータを書き換えることができる。
以下は、今回のプログラム例のHEXファイルのデータである。
:10000000782008E12008E8F404EBA2A1FFFFFFFF3D
:10001000A0A090B0900000B090B0F1F2FFFFFFFF01
:10002000A090B090B09000FBFFFFF1B090B000A3A3
:10003000A0A0900000B090B090B090B0F1FFFFF29F
:00000001FF
実行結果
Pmod ENC のBTN端子を入力ポートのビット3に、SWT端子を入力ポートのビット2に接続した。
また、出力ポートに Dice Board を接続した。
20Hzのクロックで実行した。
スイッチの切り替えによって「R」と「FB」を出し分けることができている。