FPGA で 8088 (D8088-2) を動かして自作PCをやる

これまでのあらすじ : https://twitter.com/tanakmura/status/1280152564898557952

FPGAHello World以上のものが書きたいという気持ちは前からあったので、この機会に少し実用的はHDLを書くことにした。

なにをやっているかの解説を書いておこう。

ソースは、 https://github.com/tanakamura/jisaku_pc_8088 ここにある(上のツイートでは、タイミング問題があってLED点灯しないことがあると書いてるが、これは多分改善してあるはず。)

こういう昔のCPUは、CPU側の命令実行とバスが直結していて、ポインタ0x80 を読むと、CPUの足に、そのまま0x80が出てくる。それを正しくハンドリングして、有効な命令バイト列を返せば、8088を動かすことが可能だ。

この実装では、この足から出てくる信号をデコードして、うまくなんとかやる回路をFPGAに実装して、8088を動かしている。

実装しているペリフェラルは以下

アドレスが18bitしかないのはアドレス線18本しかひっぱってきてないからです…(昔のCPUはアドレス線繋がなくても動くんだなぁ…)

信号の解釈は、ぐぐって出てきたPDF(色々クリアなものかは知らない…)を参考に実装している。


まず、いきなり実機でやるとしんどそうなので、tv80 をFPGAで実装して、シミュレーションとかFPGA単体で動かしたりして、8bit バス ←→ AXIバスの変換が正しく動いているかを確認した。

ただ、Z80 と 8088 はバスの信号が変わってるので、完全に同じではない、そのへんはしかたないので実機で確認した。

https://github.com/tanakamura/jisaku_pc_8088/blob/master/top_hdl/i8088_top.sv#L249 (ALE)

https://github.com/tanakamura/jisaku_pc_8088/blob/master/modules_hdl/i8088_cpu.sv#L214 (WR,RD,IO)


クロックは、DDR使ってみたかったので(結局使ってないが)、 https://reference.digilentinc.com/learn/programmable-logic/tutorials/arty-getting-started-with-microblaze-servers/start これを参考にして、83.333 MHz を AXI のバスクロックにして、それを1/15にして、5.555MHz を作ってそれを8088に入れている。D8088-2 なので、2MHz - 8MHz の間で動くはず。

AXI と CPU クロックが違うので、クロック変わるところはAXI側クロックで2回サンプリングして一致してたらAXIバスクロック側にコピーするようにしている。(これでいいかは知らない。真面目にやるなら非同期キューというものを作るらしい)

これで出たアドレスを https://github.com/tanakamura/jisaku_pc_8088/blob/master/modules_hdl/addr_converter.sv AXIアドレスにあうように変換している。


物理回路のほうは、全く初心者だったので、結構手探りだった。特に一番謎だったのは、現代のFPGAと昔のCPUの信号線を直結していいのか?という点だった。電圧違うとかだと、壊れる気がしたので、それなりに真面目に調べた。

中でも http://www.cepstrum.co.jp/hobby/5v33v/5v33v.html この「そんなに真面目に変換しないでいい」という説は採用していいのかかなり悩んだが、結局8088はクロックだけは確実に5Vを入れる必要があるということがわかって、これは採用しないことにした。あとADの8本は方向変わるので、これもどうしたらいいかよくわからなかったので。

結局よくわからんので全ての信号線に http://akizukidenshi.com/catalog/g/gM-08250/ これを入れることにした。あとから考えたら、今のFPGAの出力では昔の8088のバスを動かすだけの電流流せない可能性があったので、ちゃんとバッファありの電圧変換にしたのは余計な問題踏む確率が減るという点で正解だったと思う。


で Fritzing で超汚い回路図を書いて、ブレッドボードにして、それを奥さんに実装してもらった。Fritzingは、ブレッドボード図と回路図で整合性取れてるか調べられて、汚い回路図でもまあショートしてないかぐらいは確認できたので、まあよかったかな。
f:id:w_o:20200710002938p:plain
(あ、なおすの忘れてたけど、一番右上の2DIRはGNDに接続するのが正しいです。あと今はSSOはA17につなげてます)

(なお、これはICの幅をまちがって書いていて、実際はもう2列占有する)

ADの8本はZになる可能性があるので、10kのプルアップを入れてる。(プルアップが必要な理由も今回はじめて知りました)


最後に、spi flash へ 8088 のプログラムを書き込む時に、vivado なしでも書けるようにして、完成。
https://github.com/tanakamura/jisaku_pc_8088/blob/master/flash/flash.tcl

OpenOCD があれば、raspberry pi からでも8088 のプログラムが更新できるようになっている。(flashの0x0080_0000にプログラムを置くと、CPU の 0x10000 にマップされる)
これは将来本格的にプログラムを書くことになったときにTAT短縮のために必須の機能だと思ったので。


最初動いて、ILAで8088からの信号が届いたのが見れたときは感動しましたね。何十年も故障しないで生きててえらい!


まあ少し大きめのHDL書けたので満足かな。SystemVerilog は Verilog HDL(略してVHDL(大嘘)) より色々便利になってたのでよいと思った(まあASICで採用するのは難しいかもしれんが)

追記 : Digilent の Arty のボードファイルは、SPIのSSとIOAがいれかわっているので、そのままでは使えないです。(https://github.com/Digilent/vivado-boards/commit/9c664934db09612f4d1f4aff7b3d6a58251d9577) 手元で入れかえて使ってください。