4558D が 2023年10月05日01時30分56秒 に編集
初版
タイトルの変更
Z80 CPUをPICマイコンで動かしてLチカしてみた
タグの変更
Z80
ワンボードコンピュータ
メモリエミュレータ
PIC16F877A
8bitBUS
LH0080A
LH0081A
メイン画像の変更
記事種類の変更
製作品
Lチカの変更
ライセンスの変更
(CC BY-NC-SA 4+) Creative Commons Attribution-NonCommercial-ShareAlike CC BY-NC-SA version 4.0 or later
本文の変更
# はじめに Z80は、アメリカの半導体メーカー・ザイログにより1976年に発売され、現代でも同社で製造が続けられている8bit CPUである。単一電源動作や単相クロック動作が可能であり、当時他社から発売されていたほかのCPUと比較して非常に使いやすい特徴を持ったICであり、その使いやすさから広く普及した。 このZ80シリーズには、日系電機メーカーを含む各社セカンドソース品が出ている。著者も先日、SHARP製セカンドソース品であるLH0080A(CPU)とLH0082A(PIO)を入手したので、現代技術をフル活用して動かせるようにしてみた。 本記事では、Z80を動かすために作成したワンボードコンピュータについて、制作したハードウェアと、搭載したPICで実現した機能を紹介したい。 # Z80を用いたコンピュータ 今回作成したワンボードコンピュータの説明をする前に、まずZ80を用いて作成されるコンピュータについて説明する。 ## 一般的なアーキテクチャ ### アーキテクチャ全体と各部の機能 CPUにZ80を用いてコンピュータを製作する場合、そのアーキテクチャは一般的に下図のようになる。 ![一般的なアーキテクチャ](https://camo.elchika.com/e50b7c6973cfc3d39ac984e780b799bd008d5564/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f38623938623232322d616463342d343636332d616530342d6361303264303433383638322f31376261323539362d306261632d343332322d623336332d393063623936386432633161/) 上図のコンピュータはCPUを中心に、メモリ(ROM/RAM)、クロック、ペリフェラル(周辺機器)、アドレスデコーダといった機能ブロックで構成されている。 - CPU:アドレスを指定してメモリ(ROM)から命令を読み出し、読みだした命令を解読(デコード)して実行する装置。コンピュータの中核をなす。 - メモリ:機械語の命令や数値などを記録したり読み出したりできる装置。読み出し専用のROMと読み書きできるRAMがあり、前者は機械語で書かれたプログラムを、後者は数値を主に記録する。 - クロック:CPUやペリフェラルの動作を同期させるための一定周期の信号を供給する装置。 - ペリフェラル:コンピュータ外部と接続したりCPUでは実装コストの高い機能を実現したりする装置。Z80シリーズでは本記事で使用するPIOの他、シリアル通信を行うSIO、タイマのCTC等がある。 - アドレスデコーダ:CPUからのアドレス指定に応じて、使用するメモリやペリフェラルを割り振る装置。 Z80シリーズでは、CPUに加えて必要なペリフェラルが一通り揃っており、これらはZ80 CPUの動作を最適化させるように設計されていたため、Z80シリーズの普及に一役買ったとされている。 ### 各機能ブロックに使う部品 先ほど紹介した各機能ブロックの実現は、Z80を用いたコンピュータでは以下の部品で実装されることが多い。 - CPU:Z80 CPU、もしくは、そのセカンドソース品が使用される。 - メモリ:ROMはUVEPROMやEEPROMを、RAMはDRAMやSRAMを良く用いる。 - クロック:水晶発振回路や専用ICを使用する。 - ペリフェラル:Z80シリーズの各種IC(PIO, CTC, SIO ... etc.)の他、他社CPUの周辺ICが使用されることもある。 - アドレスデコーダ:標準ロジックICで構成することが多い。 「Z80を用いたコンピュータ」を銘打つ以上、CPUについては当然Z80 CPUが用いられたわけだが、Z80シリーズで用意されているペリフェラル類も含め、その他機能ブロックの実装に対しては「機能が実行できればなんでもあり」である。この「なんでもあり」な自由度もZ80普及の一助となっていると考えられるが、裏を返せば、これを実現するためにはZ80の仕様や各機能ブロックの実装に用いるデバイスの仕様について熟知している必要があり、コンピュータが動くかどうかはひとえに設計者の腕にゆだねられるということである。つまり、設計が難しい(めんどくさい)のである。 今回作成したワンボードコンピュータでは、こうした「設計の難しさ」をなるべく取り除く工夫を凝らした。次章では、その設計思想と実現方法を詳細に紹介していきたい。 # 今回作成したZ80ワンボードコンピュータ ## 設計目標と設計思想 今回作成したZ80ワンボードコンピュータの設計目標は、「今までZ80を扱ったことがない人が手軽にZ80の使用方法を習得すること」である。この目標は、設計時の著者のレベルに合わせたためである。PICマイコン等になるべく近い感覚でZ80コンピュータを開発できることを重視した。この目標を実現するために、以下の設計思想を掲げて設計した。 1. ROM・RAMはPICマイコンによるメモリエミュレータで実装する。 1. プログラムの読み書きや実行中の動作モニタを、Tera Term上で行えるようにする。 1. ハードウェア面での設計ミスに対してリカバリーしやすいようにする。 1. コンピュータとして最低限の構成にして、使用する部品点数をなるべく少なくする。 1については先述した通り、Z80が多用されていた当時に使われていたようなUVEPROMやDRAMは、それまで触れたことがない人にとって扱いが難しいために設定した。ただでさえ、Z80は命令数が多い(80種類以上)ために扱いが難しいのに、それ以上に苦労の種を増やすのは望ましくない。 2については、一般的なZ80コンピュータでは、プログラムの読み書きとデバッグに大きなハードルを感じるため設定した。プログラムの読み出しや書き込みをTera Term上でキーボード入力でできるようにすることで、プログラミングがしやすくなるし、プログラムの実行時にプログラムに対するCPUの動作を画面上に可視化することで、動作や効率のよい使い方を習得できるのではないかと考えた。 3については、Z80を用いたコンピュータは、ワンチップマイコンと比較して構成要素が多いため、ハードウェア面での設計ミスは必ず起こると考えたことにより設定した。著者自身、Z80に触れるのが初めてであり、動作に問題のない回路を一発で作り上げる自信がなかった。このため、HALTインジケータのバッファにあえて74HC00を1ゲートだけ使用し、残りをリカバリー用のロジックに転用できるように設計した。 4は3の目的とも重複するが、機能を足せば足すほど使用するICの数が増え、回路も複雑化するからである。また、複雑化させてしまうとリカバリーが難しくなるため、今回はできる限り使用素子数を抑えるようにした。ただし、今後の拡張を考え、各種バスや制御信号は外部に引き出せるようにした。 以上の設計思想を踏まえ、ハードウェアとソフトウェアの構成を検討した。 ## ハードウェア 前節で述べた設計思想を元に検討したアーキテクチャは下図のとおりである。全体のブロック構成としては、Z80 CPU (LH0080A)を中心に、出力のLEDと入力のSWをPIO (LH0081A)を介して接続し、メモリエミュレータ、クロックジェネレータ、バスモニタとして使用するPIC16F877Aを接続した。 ![ワンボードコンピュータのアーキテクチャ](https://camo.elchika.com/9ca4b2a379b26893a5176aa4e989faaec184e3e2/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f38623938623232322d616463342d343636332d616530342d6361303264303433383638322f38333663633732642d366635612d346431372d616533612d383431366361363634623132/) このアーキテクチャをベースに、電源、リセット回路、HALTインジケータや、外部接続用のコネクタを付けた回路が以下のようになる。設計思想で述べた通り、HALTインジケータに用いたNAND(74HC00)の残りのユニットは、PCB設計の段階では全ピンオープンにし、はんだ付けする段階で入力ピンをGNDに配線するようにした。 ![回路図](https://camo.elchika.com/38c03ef9fb4d4968a8464a79f6dee8f3a4eaa4f1/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f38623938623232322d616463342d343636332d616530342d6361303264303433383638322f31373262653631632d363234642d346337652d393332662d653638343437666664373538/) この回路を、下図のような10cm×10cmのPCBにレイアウトした。 ![PCBレイアウト](https://camo.elchika.com/98b254f59449ea5aa090cee66e18aaebdaa57dd3/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f38623938623232322d616463342d343636332d616530342d6361303264303433383638322f39643339663361612d303939392d346435652d396238372d316630363035343039363330/) また、作成したPCBに部品実装や配線を施し、実際に完成したハードウェアは以下のようになる。裏面の画像を見ればわかる通り、白いワイヤで配線の修正を行っており、設計思想で触れたリカバリー用のロジックを早速活用した。 ![作成したワンボードコンピュータ(表面)](https://camo.elchika.com/a1ad6eb3a5a80ae8cd60c0f8f9fed54063e89f87/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f38623938623232322d616463342d343636332d616530342d6361303264303433383638322f65366364303030652d623365372d343930652d623037642d343934653435613739396339/) ![作成したワンボードコンピュータ(裏面)](https://camo.elchika.com/4262835f520a4e06b3844009eeb7833f8b24a7a5/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f38623938623232322d616463342d343636332d616530342d6361303264303433383638322f36396630383963312d313834382d343037312d616139352d643232376531346330633261/) ## ソフトウェア (PIC16F877A) 本節では、搭載したPIC16F877Aのソフトウェアについて概要を簡単に解説する。 ### 全体の動作 PICマイコンは、全体として以下の4個の機能を持っている。 1. 仮想ROMに記録されたプログラムの実行 2. 仮想ROMの読み出し 3. 仮想ROMの書き込み 4. バスモニタ(プログラム実行と並行) これら機能の状態遷移図は下図のようになっている。電源投入直後は、1の仮想ROMに記録されたプログラムを実行する。この時、何らかのキーボード入力が入るとプログラム実行を停止し、実行させる機能選択の画面に遷移する。ユーザーにより実行する機能が選択されると、その機能が実行され、各機能で決められた遷移条件を満たすと、再び機能選択画面に戻る。以上が全体の動作の流れとなる。次節からは、これら機能の概要を説明していきたい。 ![PICプログラムの状態遷移](https://camo.elchika.com/2131c7d345640cda9c7254ec95a9512728df501e/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f38623938623232322d616463342d343636332d616530342d6361303264303433383638322f37623265373262662d633031302d346337622d623261612d616139663864333732303832/) ### 1. 仮想ROMの実行機能 この機能では、Z80を動作させ、仮想ROMに書かれたプログラムを実行する。この機能の実現のために、以下で述べるクロックジェネレータとメモリエミュレータを実装した。 #### クロックジェネレータ 次節以降で述べるメモリエミュレータやバスモニタの実装を容易化するために、PICのタイマー割り込みで40Hz~10kHzのクロックを生成し、CPUとPIOに供給するようにしている。クロック周波数は、電源オン直後のプログラム実行では200Hzに、バスモニタ使用時は50Hzに固定で設定され、それ以外のプログラム実行時にはTera Term上でユーザーによって指定できる。 #### メモリエミュレータ 設計思想でも触れた通り、今回作成したワンボードコンピュータは、ROM/RAMの機能をPIC16F877Aを用いたメモリエミュレータを用いている。PIC16F877Aでデータ保持用に自由に使える領域として、揮発性メモリからなる汎用レジスタと、不揮発性メモリからなるEEPPROMがあるため、前者をRAMとして、後者をROMとして割り振っている。(下図) ![メモリエミュレータの動作イメージ](https://camo.elchika.com/8d804f77fcfad8626dc2ee570b6468312589a7fa/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f38623938623232322d616463342d343636332d616530342d6361303264303433383638322f37613733653234312d303333632d346161382d616531392d623934363230343736373738/) Z80 CPUは、ROMとRAMを同じアドレス空間(メモリ空間)を使用しているため、互いに同一のデータバスと同一のアドレスバスでアクセスできる。お互いの区別はそれぞれに振られたメモリアドレスのみによって行うため、PICマイコンの条件分岐のみで容易に実現できる。また、メモリアクセス時には、CPUから制御信号(M1, MREQ, RD, WR)が送られてため、PICでこれらの信号の動きをモニタすることでデータの送受のタイミングを検知できる。 以上から、Z80のROM/RAMは、以下のような手順でPICを動作させることで、その動作を再現することができる。 1. クロック立ち上げのタイミングでアドレスバスと制御信号を確認し、メモリアクセスがあるかとアクセスしているメモリがROMとRAMのどちらか、RAMの場合はリード/ライトのどちらかを確認する。 1. ROMの読み出しの場合はEEPROMからデータを読み出し、RAMの読み書きの場合は汎用レジスタに確保したRAM用領域にアクセスしてデータを送受する。 ### 2,3. EEPROMプログラム機能 メモリエミュレータの機能を実装するだけであれば、Z80のプログラムは、PICのソースコード上に書けば十分である。しかし、この方法では、プログラムを変更するたびにPICのファームウェアを書き換える必要があり、そのたびにMPLABやプログラマを起動させなければならず、非常に手間である。そこで、PICのUARTを用いて、Tera Term上で動作するバイナリエディタを作成し、このエディタ上でプログラムを書き込めるようにした。 ![実装したプログラム書き込み機能](https://camo.elchika.com/012daf4b6078acc62f01eb095d05d3d66fab1bc0/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f38623938623232322d616463342d343636332d616530342d6361303264303433383638322f39386637373062302d353161332d343731312d616564622d636439316365623136346663/) また、過去に書き込んだプログラムの確認や、プログラムの書き込みの成否を確認するために、EEPROMの読み出し機能を実装した。 ![実装したプログラム読み出し機能](https://camo.elchika.com/011627363ca11448bfa6115b7e0c5d8f942e603e/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f38623938623232322d616463342d343636332d616530342d6361303264303433383638322f39653964323435662d663438372d346363632d386532312d383534643161356232626663/) ### 4. バスモニタ プログラム動作中に、アクセス中のメモリアドレスとデータバスの内容、そして、実行中のサイクルをTeraTerm上にモニターする機能である。Z80から送られるアドレスバス、データバス、制御信号を読み取り、それらをシリアル通信でモニターすることで実現している。 クロック周波数が高いと、おそらくシリアル通信が追いつかなくなることが原因で機能しなくなるため、このモードでプログラムを実行する時はクロック周波数を50Hzに固定して動作させるようにしている。 ![実装したバスモニタ機能](https://camo.elchika.com/192ddec7511ec2da529e533f5da5f751fc41c745/687474703a2f2f73746f726167652e676f6f676c65617069732e636f6d2f656c6368696b612f76312f757365722f38623938623232322d616463342d343636332d616530342d6361303264303433383638322f35666135636165302d323831642d346464622d396137342d326337353336653237643139/) # 実際の動作 ## Z80とPIOを用いたLチカ 作成したワンボードコンピュータの動作テストのため、Z80の機械語でLチカさせてみた。以下では、作成したプログラムと、それによるワンボードコンピュータの動作を紹介する。 ### Lチカさせるためのプログラム 作成したワンボードコンピュータの動作テストを行うために以下の動作を行うプログラムを作成した。 1. PIOのBポート(PB)からスイッチのOn/Offを読み取る。 2. 1でOffを読み取ったビットに対してLEDを点灯させ、Onを読み取ったビットに対してLEDを消灯させる。 3. LEDを消灯させる。 4. 1に戻る。 プログラム自体は、スイッチの情報を読み取り、その情報を元にLチカする、という、現代的なマイコンでもよくやられているようなLチカである。なお、プログラムの単純化のため、点滅の間に特にdelayなどは入れていない。動作テスト時は、クロック周波数を低く設定しているため、LEDの点滅は十分に確認することができた。 作成したプログラムは以下のようになる。なお、プログラムはZ80の機械語で記述し、コメントにニーモニックと動作を記載している。 ```C:Lチカプログラム 0x26, 0x00, // LD H, 0x00 0x2E, 0x1e, // LD L, 0x1e // ジャンプ先を0x001e番地に指定 0x3E, 0xcf, // LD A, 0xcf // Aポートをビットモードに設定 0xd3, 0x81, // OUT (0x81), A // Aポートの制御語へ書き込み 0x3E, 0x00, // LD A, 0x00 // Aポートをすべて出力に指定 0xd3, 0x81, // OUT (0x81), A // Aポートの制御語へ書き込み 0x3E, 0x07, // LD A, 0x0f // Aポートの割り込みなし。 0xd3, 0x81, // OUT (0x81), A // Aポートの制御語へ書き込み 0x00, // NOP // 何もしない 0x00, // NOP // 何もしない 0x3E, 0xcf, // LD A, 0xcf // Bポートをビットモードに設定 0xd3, 0x83, // OUT (0x83), A // Bポートの制御語へ書き込み 0x3E, 0xff, // LD A, 0xff // Bポートをすべ入力に指定 0xd3, 0x83, // OUT (0x83), A // Bポートの制御語へ書き込み 0x3E, 0x07, // LD A, 0x07 // Bポートの割り込みなし。 0xd3, 0x83, // OUT (0x83), A // Bポートの制御語へ書き込み 0xdb, 0x82, // IN A, (0x82) // Bポートの情報をAレジスタに読み込む 0xd3, 0x80, // OUT (0x80), A // Aポートのデータへ書き込み 0x3e, 0x00, // LD A, 0x00 // Aレジスタに0x00を書き込む (消灯) 0xd3, 0x80, // OUT (0x80), A // Aポートのデータへ書き込み 0xe9, // JP (HL) // HLレジスタで指定したアドレス(0x001e番地)にジャンプ ``` ### 作成したコンピュータの動作 作成したプログラムで実際でLチカする様子は、以下ツイートのようになった。Bポートのスイッチの情報を読み取り、AポートのLEDに反映させてLチカすることができ、今回作成したワンボードコンピュータを用いてLチカを成功させることができたことが分かる。 @[twitter](https://twitter.com/electrotelecast/status/1702927075991334978?s=20) ## プログラマの動作 作成したワンボードコンピュータを、シリアルポートを介してTera Termに接続されると、以下ツイートの2枚目の動画のように、キー入力によって画面遷移し、各機能を実行させることができる。 @[twitter](https://twitter.com/electrotelecast/status/1700417922592866373?s=20) # まとめ Z80 CPUを動かすためのワンボードコンピュータと、Z80の機械語でLチカプログラムを作成することで、Z80を用いてLチカすることに成功した。本記事の締めくくりとして、今回達成できたことと、今後達成していきたい課題点を以下にまとめる。 ==達成できた点 ・PICマイコンを使うことでシンプルな回路構成でZ80を動作させることに成功した。 ・PICにメモリエミュレータ、機械語エディタ、バスモニタを実装することにより、Z80のプログラミングやデバッグをしやすくした。 ・Z80を機械語でプログラムし、Lチカさせることに成功した。== ++今後の課題 ・ROMとRAMをさらに大容量化して動作させること。 ・クロック周波数の最大を10kHzよりも高く設定できるようにすること。 ・PIO以外のペリフェラルを使えるようにすること。++ # 謝辞 本記事で紹介したZ80ワンボードコンピュータの作成にあたり、設計ツイートや動作ツイートに対し、多くの反響や助言を賜りました。この場を借りて感謝申し上げます。 # 参考文献 [1] 鈴木哲哉, ザイログZ80伝説, 2020 [2] 横田英一, Z-80の使い, オーム社, 1993 [3] 額田忠之, Z80ファミリ・ハンドブック, CQ出版, 1985 [4] 渡波郁, CPUの作り方, 毎日コミュニケーションズ, 2003