SSブログ
English Version

SuperSimpleController(その5)開発環境について [OriginalCPU]

 前回の記事でALUの設計がほぼ完了したのでいよいよブレッドボードでの確認作業に入っています。

 リセット後の初期化処理とアドレス0000hからのマシン語を動かすまでの動作は何とかできたのですが、現状使っているロジアナ(16ch)では一部の信号しか見れず確認作業の効率が悪いです。

 下図はジャンプ命令の動作を確認中のロジアナ画面(制御コードのソースは後述します)のキャプチャで、初期化後、0000hのNOPまでは正常に動ています。次のジャンプ命令で、赤矢印の部分でA0とA1が0になるはずが1のままですorz

動作確認作業中のロジアナ画面サンプル


 マシン語の動作を実現するためにuCODEに入れる16個の制御信号の時系列データを作り、動作確認していく作業はかなり手間がかかりそうなので、まずは環境を整えることにしました。

 現在、できている環境について以下にメモしておきます。

  1. 回路図
     確認作業時に回路図を参照したい場面が頻繁にありますが、複数の部分を見たい時等、CAD表示画面では不便なのでポップアップ表示できるようにしています。

     [uCODE]  [IRH]  [IRL]  [ALU]  [PC]  [AD]  [Reg]

  2. uCODEのコーディング
     前々回の記事でも書きましたが、マクロアセンブラ(M80)のマクロ機能を使ってコーディングしています。
     作成中のサンプルを貼っておきます。

    Simple8Z uCODEソース(作成中)
    ;++++++++++++++++++++++++++++++++++ ; uCODE data for Simple8Z ; made by skyriver ; Ver 0.01 2021/02/04 ;++++++++++++++++++++++++++++++++++ ; Simple8Z control signals bit assign (*:active low) 0001 PLW EQU 01H ; write PCL 0002 PHW EQU 02H ; write PCH 0004 FLW EQU 04H ; write FLG 0008 IRW EQU 08H ;*write IR 0010 PCS0 EQU 10H ; PCL, PHL control(S0) 0020 PCS1 EQU 20H ; PCL, PCH control(S1) 0040 MEM EQU 40H ;*select memoy not I/O 0080 ALUR EQU 80H ;*read ALU 0100 RD EQU 0100H ;*read 0200 WR EQU 0200H ;*write 0400 R0W EQU 0400H ; write R0 0800 R1W EQU 0800H ; write R1 1000 ALD EQU 1000H ; load(latch) addr into ADH, ADL 2000 ALR EQU 2000H ;*read ADL(addr low) 4000 AHR EQU 4000H ;*read ADL(addr high) 8000 PWEN EQU 8000H ; enable PLW,PHW independent Z,C flags ; low active control signals 63C8 NEGSIG EQU (IRW or MEM or ALUR or RD or WR or ALR or AHR) ; uCode last value inc-mode E2B0 LastVal EQU (NEGSIG OR PCS0 OR PCS1 OR PWEN) AND (NOT RD) AND (NOT IRW) AND (NOT MEM) E2B0 SIGNAL SET LastVal SETHI macro bit ; set sig high SIGNAL set SIGNAL OR bit endm SETLOW macro bit ; set sig low SIGNAL set SIGNAL AND NOT bit endm ACT macro bit ; set sig active IF bit AND NEGSIG SIGNAL set SIGNAL AND NOT bit ELSE SIGNAL set SIGNAL OR bit ENDIF endm CLR macro bit ; clear sig IF bit AND NEGSIG SIGNAL set SIGNAL OR bit ELSE SIGNAL set SIGNAL AND NOT bit ENDIF endm PCCLR macro ; set PC to clear-mode CLR PCS0 CLR PCS1 endm PCDEC macro ; set PC to decrement-mode ACT PCS0 CLR PCS1 endm PCLOAD macro ; set PC to load-mode CLR PCS0 ACT PCS1 endm PCINC macro ; set PC to incriment-mode ACT PCS0 ACT PCS1 endm CODE macro ; generate control data DW SIGNAL endm ENDCODE macro ; last code of each proc SIGNAL SET LastVal CODE ; set IR endm CSTART macro code ; uCODE start .xlist rept (code) * 2 - $ DB -1 endm .list ORG (code) * 2 endm 0000' ASEG ORG 0 CSTART 00H ; **** RST PCCLR CLR IRW ; have to clear IRW, for IRH's S0 quickly rise CODE 0000 E288 + DW SIGNAL ACT PLW ; set PCL ACT PHW ; set PCH CODE ; clear PC 0002 E28B + DW SIGNAL CLR PLW CLR PHW ACT RD ; memory read PCINC ; set PC to increment-mode CODE 0004 E2B8 + DW SIGNAL ENDCODE 0006 E2B0 + DW SIGNAL CSTART 08H ; **** NOP CLR IRW ; have to clear IRW at top of uCODE(if not then fetch code again) ACT PLW CODE ; inc addr 0010 E2B9 + DW SIGNAL CODE 0012 E2B9 + DW SIGNAL CODE 0014 E2B9 + DW SIGNAL ENDCODE 0016 E2B0 + DW SIGNAL CSTART 0C0H ; **** JP:0C4H JZ:0C0H JNZ:0C1H JC:0C2H JNC:0C3H CLR IRW ; have to clear IRW at top of uCODE(if not then fetch code again) ACT PLW CODE ; inc PC 0180 E2B9 + DW SIGNAL CLR PLW ACT R1W CODE ; save low addr to R1 0182 EAB8 + DW SIGNAL CLR R1W ACT PLW CODE ; inc PC 0184 E2B9 + DW SIGNAL CLR PLW CLR PWEN ; disable PLW,PHW PCLOAD ; set PC to load-mode CODE ; set load-mode 0186 62A8 + DW SIGNAL ACT PHW CODE ; write high addr to PC 0188 62AA + DW SIGNAL CLR PHW CLR RD ACT ALUR ; read R1 register CODE ; read ALU(R1:low addr) 018A 6328 + DW SIGNAL ACT PLW CODE ; set low addr to PC 018C 6329 + DW SIGNAL ACT PWEN CLR ALUR CLR PLW PCINC ; set PC to increment-mode ACT RD CLR IRW CODE ; set inc-mode, activate RD 018E E2B8 + DW SIGNAL ENDCODE 0190 E2B0 + DW SIGNAL CSTART 0F8H ; **** HALT code:F8H-FFH CLR IRW ; have to clear IRW at top of uCODE(if not then fetch code again) CODE ; inc PC 01F0 E2B8 + DW SIGNAL ENDCODE 01F2 E2B0 + DW SIGNAL END Macros: ACT CLR CODE CSTART ENDCODE PCCLR PCDEC PCINC PCLOAD SETHI SETLOW Symbols: 4000 AHR 1000 ALD 2000 ALR 0080 ALUR 0004 FLW 0008 IRW E2B0 LASTVAL 0040 MEM 63C8 NEGSIG 0010 PCS0 0020 PCS1 0002 PHW 0001 PLW 8000 PWEN 0400 R0W 0800 R1W 0100 RD E2B0 SIGNAL 0200 WR No Fatal error(s)

    ★追記 2021/02/25
     上記のようにuCODEをコーディングしていく際にある程度複雑な処理になると混乱してくるので、もっと抽象度の高い下図のようなニーモニックで処理を書いてからuCODEに変換した方が効率がいいことが判りました。
     機械語の処理内容を記述するためのマイクロコードを書くためのニーモニック(ややこしい)は何と呼んだらいいのでしょう?
     メタニーモニック(1階層下のレベルのニーモニック)とでも言うべきかw

    マイクロコード作成用のメタニーモニック

    ★追記 2021/03/19
     CALLとRETの度にR0とR1が壊れてはプログラムの実行効率が悪くなるので、R0は非破壊になるように改善しました。
     マイクロコード作成上のテクニックを垣間見ることができそうなのでメモとして貼っておきます。

    CALL(PUSH PC)とRETの改善版メタニーモニック


  3. テスト用マシン語コード
     これもマクロアセンブラを使い、コーディングしていく予定です。
     冒頭で書いたロジアナ画面での確認対象のソースは下記になります。

    テスト用サンプルソース
    ;++++++++++++++++++++++++++++++++++++++++ ; Simle8Z test program ; by skyriver ; V0.01 2021/02/08 ;++++++++++++++++++++++++++++++++++++++++ RST macro DB 00H endm NOP macro DB 08H endm JP macro adr DB 0C4H DW adr - 1 ; because increment PC after set PC endm JZ macro adr DB 0C0H DW adr - 1 endm JNZ macro adr DB 0C1H DW adr - 1 endm JC macro adr DB 0C2H DW adr - 1 endm JNC macro adr DB 0C3H DW adr - 1 endm HALT macro DB 0FFH endm ;------------------------------ 0000' ASEG ORG 0 NOP 0000 08 + DB 08H 0001 LOOP: JP LOOP 0001 C4 + DB 0C4H 0002 0000 + DW LOOP - 1 ; because increment PC after set PC HALT 0004 FF + DB 0FFH END Macros: HALT JC JNC JNZ JP JZ NOP RST Symbols: 0001 LOOP No Fatal error(s)


  4. 任意時点でのブレーク
     動作確認は基本的にはロジアナを使って確認していますが、冒頭に書いたようにある部分で想定外の状況になった場合、調査し易くするためにリセット信号とクロックをPICから供給し、任意のクロックで動作停止できる環境を作りました。

     冒頭のロジアナ画面の赤矢印の時点で停止した状態のロジアナ画面が下図になります。この状態で止まっているのでじっくり調べることができます。

    任意時点でのブレーク例

     リセットとクロック信号は「I2Cロガーの製作」の記事で書いたI2Cロガー(以前2台目として作成した物で記事とは若干違う)を使って生成しています。

    I2Cロガー(コネクタ側) I2Cロガー(USB、LED側)

    I2Cロガー(基板:部品面) I2Cロガー(基板:半田面)

     自作のセルフコンパイラであるpicle言語が動作するのでこのようなちょっとした制御には(私にとっては)最適です。

     ソースも貼っておきます。

    試験用クロック&リセット信号ジェネレータ(picle言語)
    # Clock and Reset Generator for Simple8Z test 2021/02/25 ver 0.04 # by skyriver var RegLATA,RegLATB; var Reset,Clock,Led; proc SigOn( bit ) { RegLATB[0] = RegLATB[0] | bit; } proc SigOff( bit ) { RegLATB[0] = RegLATB[0] & ~bit; } proc Init() { var Ad1pcfg; Ad1pcfg = $032c; Ad1pcfg[0] = $ffff; # set digital mode RegLATA = $02c4; RegLATB = $02cc; RegLATB[-2] = $6f7f; Reset = $8000; Clock = $1000; Led = $0080; } proc Twait( tim ) { Timer_ = tim; while ( Timer_ ) {} } proc OneClock( tim ) { Twait( tim ); SigOn( Clock ); Twait( tim ); SigOff( Clock ); } proc DispCnt( cnt ) { PrnChar_( $1b ); PrnStr_( "[57Cs" ); PrnDec_( cnt ); PrnStr_( " " ); } proc main() { var tim,until,cnt; tim = 1; Init(); SigOn( Reset ); SigOff( Clock ); PrnStr_( "Clock & Reset generator for Simple8Z debug\n" ); while (1) { SigOff( Led ); PrnStr_( "\nHow many clocks(-2:cont,-1:stop,0:step,minus:cont step) = " ); until = Input_(); if ( until = -1 ) { break; } else if ( until = -2 ) { PrnStr_( "\n** sending clock, ESC:break" ); while (1) { asm_( $A982CD ); # SigOff( Clock ); if ( InpChk_() ) { if ( InpChar_() = $1B ) { break; } } asm_( $A882CD ); # SigOn( Clock ); } } else if ( until < -2 ) { cnt = cnt - until; while ( until < 0 ) { OneClock( tim ); until = until + 1; PrnStr_( "" ); } DispCnt( cnt ); } else if ( until = 0 ) { OneClock( tim ); cnt = cnt + 1; DispCnt( cnt ); } else { SigOff( Reset ); SigOn( Led ); OneClock( tim ); Twait( tim ); SigOn( Reset ); for ( cnt = 0; cnt < until; cnt=cnt+1 ) { OneClock( tim ); PrnStr_( "" ); } } } }
    ★変更 2021/03/27
     Ver 0.04 高速(1MHz)実行機能を追加
    ★変更 2021/02/25
     Ver0.03 継続実行機能を追加
    ★変更 2021/02/24
     Ver0.02 ステップ動作機能を追加


  5. 信号レベルの確認
     調査したい状態でハードをブレークした後、信号のレベルチェックするために数十年前に購入したロジックテスタを使っています。
     長い間、使用しなかったのですが、電池を入れ替えたら問題なく動作しました。
     High/LowレベルはLEDの点灯で判るし、パルスが発生している場合もLED表示できます。

    かなり前に購入したロジックテスタ


  6. LED表示  ★追記 2021/02/12
     今後の確認作業を効率化するためにLED表示により信号レベルを確認できるようにしました。
     ブレッドボードには空スペースがほとんどないのでLED表示を小型化するために表面実装タイプのLEDと抵抗を使っています。
     基板は秋月さんから購入したSMDプロトタイピングガラスユニバーサル基板(0.3mm厚)Cタイプというものを使ってみました。フレキシブルで簡単に切断できるので使い易いです。
     パターン間隔が2.54mmではないのでピンヘッダの取付は8ピンくらいまでが限界です。
     抑える場所が狭かったので最初は2回に分けて半田付けしましたが、2個目はまとめて付けました(今回は2個作成しています)。

    クリーム半田塗布後 ヒートガンで半田付け後

    完成写真(部品面) 完成写真(裏面)


     ブレッドボードに実装した状態が下の写真になります。配線で隠れてちょっと見辛いけどロジックテスタで当たるよりは遥かに効率的です。

    R0,R1レジスタのLED表示


    ★追記 2021/02/20
     確認作業効率アップのためにアドレスバスもLDE表示するようにしました。
     今回は下の写真のSolder Flux Needle Booster(左下)を使ってみました。  半田ペーストの出力制御がちょっと難しい(タイムラグが結構あるし、手からの体温で温まって出てくる)ですが楊枝でつけるよりは効率的になりました。
     右下が半田ペースト塗布後の写真でだいたい思ったように塗れました。

    Solder Flux Needle Booster 半田ペースト塗布後

     下の写真のようにアドレスバスもLED表示できるようになりました。

    追加したアドレスバスのLED表示


    ★追記 2021/03/09
     追加してから2週間くらい経ちましたがデータバスもLED表示するようにしたので写真を貼っておきます。

    データバスのLED表示(中央手前)追加後のブレッドボード



[TOP] [ 前へ ] 連載記事 [ 次へ ]

nice!(0)  コメント(0) 
共通テーマ:趣味・カルチャー