Tang Nano 1kでも使える小さなCPU第2弾、今回はIM6100(PDP-8)です。
以前、このCPUに興味を持ち、エミュレータを作りました。
http://kwhr0.g2.xrea.com/pdp8.html
のように、B言語コンパイラが使えます。
B言語には型がないので、直接扱えるデータ(とアドレス)は12ビットです。
その範囲内で済むアプリケーションでは、アセンブラより楽です。
すでにエミュレータは作ってどんなCPUか分かっているので、
それをもとにVerilogで書き起こし、エミュレータと同じ動作になるまでデバッグ。
ここまでは順調でした。
今回は意外なことで困りました。
queen.bを書き換えてビルドして、FPGAに書き込んでも以前と変わらないのです。
一通り、ファイルの更新日時を確認すると必要なものはちゃんと更新されています。
シェルスクリプトで書き込んでいるので
違う.fsファイルを指定していないか確認したのですが、合っています。
はて?
いろいろ調べて、src/の上の階層のプロジェクトファイルのところに間違ってコピーした古いメモリ初期化ファイルが残っていました。
Verilogの中でファイル名だけ指定して$readmemhすると、同じ階層から読むものと思いきや、
プロジェクトファイルの階層を優先するとは...
それを消したら正常に更新されるようになりました。
もう一つ、今回はBSRAMを16ビット幅で使うので、Tang Nano 1kでもデュアルポートで使えることを確認してから設計しました。
BSRAM一つならちゃんと動作したのですが、二つにしたところP&Rでエラーが出ます。
エラー内容を見ると、データを8ビットずつに分割しています。
ああそうか、16ビット幅のまま出力にセレクタを入れるよりスマートです。
しかし、それではデュアルポートで使えないのでエラーが出ると。
論理合成はデバイスの制限を考慮せずに行われています。
仕方がないので、GW1NZを定義すると16ビット幅で使うコードを書き加えました。
サンプルはエミュレータのとき書いたN-queenをグラフィック表示用に書き換えました。
putchar()で標準出力(元々はテレタイプ)に送る部分を、I2Cに置き換えます。
Queenがどのような配置になるか表示しながらカウントするようにしました。
I2Cの速度が全体の実行時間に大きく影響を及ぼすので、どこまで速くできるか試したところ、2.8MHzまで動きました。
無難な400kHzでは114秒かかったのが、2.8MHzだと27秒になりました。
CPUのクロックはタイミングエラーが出ないギリギリで46MHz強です。
IM6100の1命令の実行クロック数(サイクル数の倍)は間接アドレシングを使う場合30〜44、その他で20〜30ですが、
このCPUは前者が3、後者が2です。CPIは10倍以上改善しています。
GW1で実チップ500MHz程度が可能です。
大きさは350Logic未満でした。
https://github.com/kwhr0/f6100
OLED基板に個体差があるかもしれないのでi2c.vは400kHzにしてあります。
以下は実行中の様子です。
ハードは前回の使い回しなので使用しない部品も付いていますが...
LEDは実行中は緑で、終了すると赤になります。