Posts Tagged with "FM-7"

既に発行済みのブログであっても適宜修正・追加することがあります。
We may make changes and additions to blogs already published.

FM-7 ROM吸出し器の改版 (3)

posted by sakurai on May 15, 2020 #258

PICの開発環境

早速、開発環境とCコンパイラをインストールし、PICプログラマを購入しました。

対象となるPICマイコンは、秋月電子でも入手可能なPIC12F1501-I/Pとします。

図%%.2
図258.2 PICマイコン

Eagleによる設計

PICマイコンをプログラマブルタイマーとして使用した回路図V5を図258.3に示します。回路は多いようですが、ほとんどがコネクタであり、Arduinoが1個と今回追加した8pinのICが全てです。他はZ80コネクタ、ロジアナ用ピンヘッダ、PICプログラム用コネクタから構成されます。

図%%.3
図258.3 FM-7IntruderV5の回路図
以前に格安PCB業者を調べましたが、今回は最安だったJLCPCBにオーダーしました。5枚で送料込みで17.95 USDです。ここは安いだけでなく、製造も速くて2~3日で製造します。
図%%.4
図258.4 FM-7IntruderV5の基板図

左矢前のブログ 次のブログ右矢

FM-7 ROM吸出し器の改版 (2)

posted by sakurai on May 14, 2020 #257

DRAMの"化け"は故障とみなせる

試みに、DRAMのリフレッシュを停めると、どの程度ビット化けが起きるかを実験してみました。 注意点として、データチェックのためにリードアウトすると、リフレッシュとなってしまうということがあります。そのため、1sec毎に故障数をチェックするのではだめで、リフレッシュ停止期間を1secずつ伸ばして行き、壊れているデータの数を計数します。リフレッシュを停止しただけなので、永久故障ではないのですが、機能停止を広い意味で故障として扱うため、ここでは故障(ソフトエラー)と呼ぶことにします。

図%%.1
図257.1 リフレッシュ停止時間に対する故障割合、及び故障密度

図257.1左がリフレッシュ停止時間(sec)に対する故障バイト数の試験数に対する割合(累積故障確率関数)、図257.1右がリフレッシュ停止時間(sec)に対する1秒当たりの故障数(確率密度関数)です。このグラフはジャンクション温度により非常に変化し、当然温度が高いほうが故障しやすいわけです。

この室温では2分間でほぼ全数のバイトが化けていることになります。グラフでは分かりにくいですが、漸近値が99.2%付近となっています。100%にならない理由は、DRAMはリフレッシュが停まると\$00または\$FFになり易く、たまたま正解値が\$00または\$FFだったためと思われます。一致する確率は2/256なので、故障個数の最大は、試験バイト数\$6000個に対して$(1-\frac{2}{256})=99.2186\%$の24,384個になるはずです。実データでは139秒後に24,384個故障し、確率的な一致を除いた最大数になりました。

リフレッシュ試験

DRAM化けの試験プログラムはそのままリフレッシュ回路の試験に使用できます。リフレッシュを停止すると、正規分布を持つ確率密度に従いソフトエラーが起こります。リフレッシュ回路を追加して、さらに厳しい条件となるようにドライヤー等でDRAMを加熱し、この試験プログラムを用いて、2分程度エラーが確認されなければリフレッシュ回路はOKと判断できます。非同期DRAMのタイミングは複雑であり、RASのタイミングが規格割れしただけでソフトエラーを起こすので、試験としてはこれだけでなく、様々なタイミング切り替えを実施するほうが良いと思います。


左矢前のブログ 次のブログ右矢

FM-7 ROM吸出し器の改版

posted by sakurai on May 13, 2020 #256

FM-7 ROM吸出し器にDRAMリフレッシュ回路を追加

過去記事において、表記のボードを開発しましたが、DRAMのリフレッシュを失念していました。そこで、前回のオールソフトウエア(?)回路に対して、ハードウエアでリフレッシュ回路を追加します。バイトアクセスはオールソフトウエアで可能なことを実証できたのですが、DRAMリフレッシュは2msec以内に128カラムアドレスにアクセスが必要、という制約があるため、ソフトウエアでは厳しいと思われます。従って、ハードウエアで構成しますが、タイミング回路なので意外に回路規模を必要とします。せっかくArduino 1個で済ませたので、最小の回路構成としたいところです。

アナログタイマーIC 555

最初に思いついたのは小型のタイマーICである555です。ところがこれはアナログICであり、時定数設定のためにRやCを複数必要とします。さらに、リフレッシュ周期だけでなくリフレッシュパルス幅を確保しようとすると、555の2個入りを使用する必要があるだけでなく、外付けCRも倍の数になり、シンプルになりません。設計してみたものの嫌になりました。

図%%.1
図256.1 NE555回路図

プログラマブルタイマーPIC

そこで、プログラマブルタイマーで検討したところ、PICマイコンを使用すれば、開発環境その他は必要となりますが、8pinのIC1個で行けそうです。デジタルのほうがシンプルで、かつ調整も無くて好きです。

図%%.2
図256.2 バス権調停信号図

PICのリフレッシュアルゴリズム

リフレッシュアルゴリズムは以下のように考えています。

  • 6809が\$FD05に1を書き、Z80W信号をLにします(Z80W=$6809/\overline{\text{Z80}}$)。
  • ArduinoはPICからのバス権の要求RFREQが無ければ、RFGNTをLにしてバスを獲得します。バスアクセスはQB/EBをアサートすることで行います(RFGNT=$\text{PIC}/\overline{\text{Arduino}}$)。
  • Z80W信号がLの際に、PICから周期的にRFREQをHとしてバス権要求をArduinoに通知します。
  • Arduinoはバスアクセス中であれば終了後にバス権を放し、PICにRFGNTをHとして通知します。
  • PICはRFGNTがHであればリフレッシュ可能と判断し、*REFCKをLとします。
  • バス調停のオーバヘッドを削減するため、PICは*REFCKは4回アサートします。その代わり、リフレッシュ周期は1/4の16KHzとなります。
  • リフレッシュが終了すると、PICはRFREQをLにします。
  • ArduinoはPICがバス権を放したと判断してRFGNTをLにしてバスを獲得します。

図%%.3
図256.3 バス権調停タイミングチャート

左矢前のブログ 次のブログ右矢

6809 IPの修正 (2)

posted by sakurai on October 3, 2019 #162

6809 IPは、Verilogステートマシン設計されているため、Vivadoのロジックシミュレータでステート毎に値をチェックして行きました。飛び先である\$FF12を用意されているものの、PCに書き込まれていないことが判りました。とは言え、JMP命令は正しくデコードされ、内部信号のop_JMP(JMP命令であることを示すデコード信号)は正しく出力されています。

図%%.1
図162.1 修正前の6809CPUの動作

ステート遷移を修正し、レジスタ書き込みで終わっている箇所をジャンプステートに修正し、さらに、PCへの書き込みアサートを追加しました。

ステートの遷移は、修正前が、0f,16, 17, 18, 19, 11, 12, (09=次の命令フェッチ)のようになっているのに対して、修正後は0f, 16, 17, 18, 19, 1b, (09=次の命令フェッチ)のように遷移し、かつ、オレンジ色で示したk_write_pc信号がアサートされ、new_pcである\$FF12\$FF12がPCにセットされています。結果として正しく\$FF12にジャンプしています。

図%%.2
図162.2 修正後の6809CPUの動作

修正前は誤ってステートが、\$11(SEQ_GRAL_ALU), \$12(SEQ_GRAL_WBACK)と、レジスタ書き込みのステート遷移となっているのに対して、修正後は\$1b(SEQ_JMP_LOAD_PC)と、JMP命令のステートに遷移しています。

例えばメインフレームのような大型機をどのようにテストしているかと言えば、もちろん単体命令をひとつづつテストすることも行いますが、キャッシュ、仮想記憶、ページングの記憶階層があります。そのためのタイミングによるバグの可能性があるので、ランダム試験を実施します。命令を乱数で発生し、ただし不正命令とはならないように制約をかけ、ソフトシミュレータで正解値を取得します。これを論理シミュレータにかけ、結果値であるレジスタの値やメモリの値が正しいかをチェックします。メモリの値はひとつずつチェックすることなく、領域のチェックサムを取ることで確認します。

さらにこれを発展させ、実機にランダムプログラム生成プログラムを載せて、実行時に正解値を生成しチェックします。一見バグ値どうしを比較してOKとなりそうですが、いろいろと条件を変え、命令をページクロスさせて前半と後半でキャッシュやページのヒットミスを変えることで、演算値が変わることがあり得ます。これはプロセッサがパイプライン動作していることから、バグによってはタイミングによって結果が変わることがありうるためです。

ということで、メインフレーム並みの信頼性を保証するなら、上記のようなテストを実施しなければなりません。


左矢前のブログ 次のブログ右矢

6809 IPの修正

posted by sakurai on September 27, 2019 #161

FM=7のハードウェアエミュレーションをFPGAで実行するプロジェクトを遂行していましたが、FM-7のROMイメージもZ80カードI/Fを用いることにより、すんなり抜き出すことができました。

それをVivadoに持ち込むにあたって、COEファイルという形式に変換し、OpenCoresからダウンロードした6809を動かしたのですが、動作しないようです。実機の動作と比較するために、実機にはロジックアナライザを接続しました。

前記事のArduino-Z80I/FカードにはFM-7の内部バスが現れているので、実はArduinoは動かさなくても、ロジックアナライザを接続すれば、メインCPUである6809の動作が把握できます。ロジックアナライザも昔は数百万円したかと思いますが、私の購入したものは17,000円くらいでした。これで32CH 200K 400MSa/sですから、アドレス、データ、主要制御信号を観測するのに十分です。

●Arduinoマイコンが870円(送料別) https://www.banggood.com/RobotDyn-Mega-2560-PRO-Embed-CH340G-ATmega2560-16AU-Development-Module-Board-With-Pin-Headers-For-Arduino-p-1397734.html

●ボード作成が5枚で4.9 USD https://www.fusionpcb.jp/

●コネクタは少々高くて743円(送料別) https://jp.rs-online.com/web/p/pcb-headers/6020498/

●ロジックアナライザは消耗品ではないので高いですが、それでも17,299円 https://www.banggood.com/Hantek-4032L-Logic-Analyzer-32Channels-USB-Oscilloscope-Handheld-2G-Memory-Depth-Osciloscopio-Portat-p-1376105.html

のように比較的気軽に試すことができます。

さて、このような環境でFPGAのシミュレーションを実行したら、おかしな点を見つけました。具体的にはJMP命令が動作しません。著者に連絡を取り、報告したところ、「It doesn't surprise me that a couple (or more) things do not work.」とのことで、自分でなんとかするしかなさそうです。FM-7システムの中で6809をデバッグするのは大変なので、新たに図のような単体テスト環境を作成しました。

図%%.1
図161.1 6809 IP単体試験回路図

6809 CPUに、リセット、クロック、ROMを接続しただけです。RAMはありません。このROMに以下のようなテストプログラムを置き、実行させたところ、

FF00         start  org   \$ff00
           
FF00 8EFF12         ldx   #lab1
           ;    jmp   0,x
FF03 6E00          fcb   \$6e,\$00
           
FF05 8EFF15     lab2  ldx   #lab3
FF08 6E01          jmp   1,x
               
FF0A 8EFF12     lab4  ldx   #lab1
FF0D 6E84          jmp   ,x
FF0F 7EFF0F         jmp *
               
FF12 7EFF05     lab1  jmp   lab2
FF15 12       lab3  nop
FF16 7EFF0A         jmp   lab4
           
FFFE             org   \$fffe
FFFE FF00          fdb   start
           ;
0000             end

最初の\$FF03番地のJMPを、JMPせずに実行してしまいます。JMP命令でもインデックスアドレシングのみ動作しないようです。ちなみに、JMP ,XとJMP 0,Xは動作は同じですが、オペコードは異なります(\$6E,\$00と\$6E,\$84)。が、動作が同じであるため、JMP ,Xと書いてもJMP 0,Xのオペコードがアセンブラから出力されるため、やむなく上記のようにFCBで記述しました。


左矢前のブログ 次のブログ右矢

FM-7 ROM吸出し器の製作 (5)

posted by sakurai on August 29, 2019 #160

サブシステムのROM吸出しの際に、サブシステムの動作確認をするために、Arduinoからランダムなボックスフィルを実行してみました。いかにもFBASICで描画しているように見えますが、Z80カードのエミュレーションをArduinoがやっています。その様子を図160.1に示します。

図%%.1
図160.1 サブシステムの動作

以下の動作を実行するスケッチを作成しました。

  • \$FD05のMSBが0になるのを待つ
  • \$FD05のMSBを1に(サブシステムをHALT)、LSBを1に(メインシステムをHALTしZ80側に)するーつまり\$FD05に\$81をwrite
  • 共有メモリにLineコマンド及びランダムな座標パラメータを書き込む
  • \$FD05のMSBを0に(サブシステムHALTの解除)、LSBを1に(メインシステムをZ80側のまま)するーつまり\$FD05に\$01をwrite
  • 最初に戻りループ

左矢前のブログ 次のブログ右矢

FM-7 ROM吸出し器の製作 (4)

posted by sakurai on August 28, 2019 #159

メインシステムROMの吸出しは非常に単純で、アドレスをセットして、データをリードするだけでしたが、サブシステムのROMはサブシステム側に依頼しないと読み出せません。従って、前に述べたように、メンテナンスコマンド(いわゆるYAMAUCHIコマンド$\dagger$)を用いてブロックコピーし、分割読み出しすることになります。これは、サブシステムのROMが10,240バイトもあるのに比べて、窓である共有メモリがわずか128バイトしかなく、コマンドにいくらか使用するため、データ転送用の窓を64バイトとしているためです。そのため、この転送を160回繰り返します。64バイト毎に16進ダンプを行います。

FM-7/8 Subシステムメンテナンスコマンドのページ(魚拓)を参考にスケッチを作成します。作成したスケッチをここに置きました。

図%%.1
図159.1 サブROMコピーの動作図

いちいちサブシステムを止めてコマンドを(2度)発行してダンプを行うので、かなり面倒でしたが、このスケッチにより得られたダンプ画面の最初と最後を示します。

d800 00 00 00 00 00 00 00 00 70 40 70 1a 7a 0e 0a 0a
d810 70 40 70 12 74 08 14 22 70 40 70 42 74 08 14 22
d820 70 40 70 40 7e 04 04 04 e0 80 e0 8c f2 12 12 0d
d830 20 50 70 52 54 18 14 12 70 48 70 4c 74 04 04 07
:
ffc0 02 10 ae a4 10 9f 47 bd b5 9c bd 9b 35 be 01 82
ffd0 20 d3 be 01 84 ae 02 20 a9 bd 02 69 34 ff 86 00
ffe0 1f 8b 10 ff 03 16 10 fe 03 16 bd 9b 35 86 2a 8d
fff0 e0 00 e0 00 e0 00 fd ac e0 6e e0 00 fe bf e0 00

同じくネットで入手したSubrom_c.romと比較したところ、全てのバイトが一致しました。若干疑問なのは、スクラッチから作成したと言われているROMデータが実ROMデータを全て一致するということがあるのだろうかということです。とりあえず、実機から抜き出したROMデータを使用している分には問題が無いので、気にしないことにします。

$\dagger$山内さんは入社した時の課内ソフトウェアグループのサブシステムチームのリーダでした。


左矢前のブログ 次のブログ右矢

FM-7 ROM吸出し器の製作 (3)

posted by sakurai on August 27, 2019 #158

Arduino Mega 2560 Proの端子図を図158.1及び図158.2に示します。

図%%.1
図158.1 Arduino Mega 2560 Proの端子図

図%%.2
図158.2 Arduino Mega 2560 Proの端子図(右側の端子)

アドレス、データ、制御信号を全てソフトコントロールしています。スケッチはここに置きました。ただし、初版からデータピンの位置を変更しているため、ボードの版数に合わせて適宜修正する必要があります。

これにより吸い出したfbasic30 ROM(\$8000~\$FBFF)生データの一部を示します。

8000 8e 80 13 ce 01 f9 c6 0a bd 85 97 8e 80 26 c6 0a
8010 7e 85 97 06 80 1d 80 5a 09 80 1d 80 77 a0 a0 a0
8020 a0 a0 a0 a0 a0 a0 06 80 30 80 5a 01 80 71 80 77
8030 43 48 41 49 ce 45 52 41 53 c5 4c 4c 49 53 d4 4c
:
:
fbc0 e1 7e 9b 50 7e 8d d1 7e af 1a 7e 96 63 7e b2 34
fbd0 7e b0 ee 7e af 11 7e cc 37 7e af 97 7e ce dc 7e
fbe0 ce df 7e b0 44 7e e3 4d 7e da f9 7e da ef 7e d4
fbf0 df 7e c2 8c 7e c6 7a 7e da f6 f1 7d 86 84 84 8b

このままCOEファイルに変換するか、あるいはバイナリにすれば、前稿のスクリプトが使えますが、簡単なのでこのままawkによりCOE化することにします。

ネットで入手したFM-7エミュレータ用のROMデータと実機から吸い上げた生データを比較したところ、fbasic30.coeは全てのバイトが一致しました。 一方boot.coeは末尾の2 lineが不一致となりました。エミュレータ用のROMでは0xffとなっていますが、実機のROMは割込みベクタが置かれているためにデータが入っています。

エミュレータ用ROMの末尾32バイト:

ffe0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff
fff0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff

実機ROMの末尾32バイト:

ffe0 ff ff ff ff ff ff 01 04 ff ff ff ff ff ff ff ff
fff0 ff ff 01 d1 01 d4 01 e0 01 dd 01 d7 01 da fe 00

ところが、「FM-7ユーザーズマニュアルシステム仕様」を見ると、\$FFE0~\$FFFFはベクトル領域となっており、boot ROMではないため、これで全てのバイトが一致しました。

末尾32バイトはベクトル領域というRAM領域でジャンプテーブルとなっています。飛び先のRAMの内容を含めて表にまとめます。

図%%.3
図158.3 割込みベクタまとめ表
FIRQ割込みハンドラは\$C953から、IRQ割込みハンドラは\$D2FCからのようです。本カードにより(メインCPUを停止し)\$AAを書き込んだところ、以下のようになったため、\$FFE0~\$FFFDはRAM、\$FFFE~$\$FFFFはROMのようです。

ffe0 aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa aa
fff0 aa aa aa aa aa aa aa aa aa aa aa aa aa aa fe 00


左矢前のブログ 次のブログ右矢

FM-7 ROM吸出し器の製作 (2)

posted by sakurai on August 26, 2019 #157

ArduinoとPCはUSBケーブルで接続し、それを通じてプログラムするのですが、そのケーブルを通じて通信することができます。具体的にはArduino側でprintln()関数を実行すると、PC側でArduino IDEの機能であるシリアルモニターを立ち上げておけば、データを表示することができるので、これを利用します。ちなみに、Arduino IDEの機能であるシリアルプロッターという便利なものがあり、Arduino側でデータを出力すれば、IDE側でグラフをリアルタイムで書いてくれ、オートスケールまでしてくれます。

面倒なのはArduino側で並列データの概念が無く、bitの入出力しかないため、アドレスのライトはbitに分解し、データのリードはbitを統合してやる必要があることです。以下にパラシリ、シリパラ変換を示します。

16ビットアドレスの分解(パラ⇒シリ)

int apb = 54;
boolean b;
unsigned address = 0x8000;
unsigned ad;
 :
ad = address;
for (int i = 0; i < 16; i++) {
 b = ad & 1;
 digitalWrite(apb+i, b);
 ad = ad >> 1;
}

このコードの動作図を図157.1に示します。

図%%.1
図157.1 パラシリ動作図解

8ビットデータの組み上げ(シリ⇒パラ)

int dpb = 39;
boolean b;
unsigned data;
 :
data = 0;
for (int i = 0; i < 8; i++) {
 data = data << 1;
 b = digitalRead(dpb-i);
 data = data | b;
}

このコードの動作図を図157.2に示します。

図%%.2
図157.2 シリパラ動作図解

左矢前のブログ 次のブログ右矢

FM-7 ROM吸出し器の製作

posted by sakurai on August 24, 2019 #156

設計編はこちらです。

FusionPCBからベースボードが届きました。今回はベンダによる部品実装は無しで、2層ボードのみの製造なので4.9 USD+配送料と、格安です。 今回は製造に6.85日、DHLによる配送に3.34日かかりました。

図%%.1
図156.1 FM-7ROM吸出しベースボード

ベースボードとArduino Mega 2560 Proボード及び40pinコネクタの写真です。この他に動作確認用のLED及びそのドライバTr、抵抗があります。

費用は配送料別で、Arduino Mega 2650 Proが975円、基板が上記のように522円、コネクタが(写真のコネクタではなく、純正のFCN-365P040-AU)が743円、合計2,240円でした。この他に配送料が若干かかっていますが、2つの目的である、

  • FM-7側にソフトウェアを置かないこと(FM-7側にはファイルシステムが無いため管理できない)
  • 価格が安いこと

が達成できました。

図%%.2
図156.2 部品一式

組み立てました。動作確認をするため、基本動作に無関係なLED等は未実装としています。

図%%.3
図156.3 FM-7 ROM吸出し器

左矢前のブログ 次のブログ右矢


ページ: