ロジックICでスタック作った
ロジックICの組み合わせでスタックを作りました。スタックとはコンピュータで用いられるデータの保存方式の一つで後入れ先出し方式の構造を持っているものです。
制作中の自作CPUに組み込まれていますが今回はその前段階にブレッドボード上で実験した様子を動画にしてみました。
ロジックICでスタック作ってみた【電子工作】 - ニコニコ動画
RX220 E2データフラッシュ 使い方
RX220のE2データフラッシュを使用するためのコードを書いたので公開します。といってもルネサス公式のサンプルプログラムそのままですが。これにより電源を落としてもE2データフラッシュに書き込んだデータなら保持することができるようになります。
自分の環境ではRXにプログラムを書き込むとROM内が消去されるみたいです。
ROMに書き込みや消去を行うにはそれなりに時間がかかるのでdelay関数をつくる必要があります。
18/3/16追記 E2ROM.cに一部バグがありました。修正済みです。
E2ROM.h
E2ROM.c
使用例
E2データフラッシュ領域の先頭へ0xFFFFを書き込み、その後読み出す。
自作CPU #16 RIIC設定
ブートローダであるRX220にアドレスバスとかクロックとかリセットとか一部のレジスタ等をつなげまくったのでほとんどのピンを使った。しかしRAMへのデータ線はRXには繋がっていない。64ピンを使ったがピン数が足らないのでIOエクスパンダを使った。 MCP23017というやつこのIOエクスパンダはI2Cで通信する仕様でこのためにRX220のRIICという機能を使った。送信はスムーズに行えた。
IOエクスパンダに出力Hを設定したときの波形
しかしながら受信で手間取った。受信関数については公式のサンプルプログラムを参考に作りました。だけど少し手直しが必要でRIIC0.ICMR3.BIT.ACKBT=1を書く前にRIIC0.ICMR3.BIT.ACKWP=1を実行する必要があったみたいです。これに気付くのにずいぶん時間が掛かってしまった。
追記 どうやら公式資料ではRIICの初期化でRIIC0.ICMR3.BIT.ACKWP=1を実行していたみたいです。
サンプルプログラム
https://elearning.renesas.com/pluginfile.php/355/mod_folder/content/0/RX_MCU_Japanese/RX63N_RIIC.pdf
RIIC初期化関数
マスター受信関数
自作CPU #15 外部端子割り込みと周辺機能って同時に使用できるんですね
開発中の4ビットCPUの名前を発表します。
TTM4
と名付けました。実はずっと前からこの名前をつけていました、この名前はとりあえずの仮名としてつけていて後からもっと良い名前をつけようと思っていたのですが結構かっこ良いし、ずっと開発中TTM4と自分の中で呼んでいたので愛着がわきました。
由来は
ちかちか祭り4bit
です。名前をつける必要性が生じたときにブレッドボードでチカチカしていたLEDが目に留まってこの名前になりました。あくまで仮名のつもりだったので
開発の参考にさせていただいた"CPUの創り方"で紹介されているTD4と名前が似ちゃってます。
さてこのTTM4にはブートローダが載っています。パソコンで言うところのBIOSで、プログラムをROMからRAMへ読み込むのが主な役目です。
ブートローダにはRX220というマイコンを採用しました。ブートローダの方が圧倒的に高性能だというツッコミはなしで。秋月電子で売ってます。
RX220マイコン R5F52206BDFM: マイコン関連 秋月電子通商 電子部品 ネット通販
採用した理由は
- 5Vで動作すること
- ピン数が多い
- 秋月で売ってる
- 自分がさわったことがあるので開発しやすい
RX220にはクロックジェネレータから生成したクロックやリセット、一部のレジスタ、アドレスバスなど繋いであります。パソコンとシリアル通信も可能ですので工夫すればパソコンからTTM4をコントロールできます。
今はそのためのプログラムを書いている途中です。
TTM4はLEDがたくさん付いているのでその点滅で動作の様子がわかります。しかしクロックの周波数を上げていくと点滅が早すぎて人間には動いているのか、止まっているのか判断できません。そこでRXでクロックをカウントしパソコンへカウンタを表示させるようにしました。このカウンタにはRX220の周辺機能のTMRという機能を使いました。TMRの初期化関数を下に示したいと思います。37ピンを使ってます。
これでカウンタはできたのですが、RXをクロックの立ち上がりに動作させる必要性が出てきました。外部端子状態変化割り込みで立ち上がりを検出するのが良いと思ったのですが37ピンはすでに周辺機能に割り当てられているのでTMRと同時に使用はできないと思ってました、端子に周辺機能を割り当てるレジスタには外部端子割り込みと周辺機能割り当てが別で設定できるようになっていたのを見て、ためしに同時に設定したら使えました。
外部端子割り込み初期化同じく37ピン
外部端子割り込みと周辺機能が同時に使用できるとは自分はいままで知りませんでした。他のマイコンもそうなんですかね?自分が無知なだけですか?
自作CPU #14 スタックが動いた!
前回の記事でかいた通り、自作CPUでスタックへPUSH命令が実行できませんでした。
そこでロジックアナライザーを使って解析したら原因が判明しました。
波形
CLK:クロック
SPC:SPへのクロック
WE:スタックを構成するRAMへの書き込みパルス
SP-D/U:SPのカウント方向を制御
AD0:PCの最下位ビット
00番地にpush命令、01番地に00番地へジャンプという命令を書き込みクロック1MHzでテストしてみました。AD0はプログラムカウンタの最下位ビットです。クロックの立ち上がりでアドレスが切り替わりメモリから読み出し、制御バスの値が切り替わるのですが、そのうちの一つで今回の命令で関係あるのがsp-D/Uです。これはスタックポインタのカウント方向を制御するビットで0の時カウントアップ、1の時カウントダウンとなります。
PUSH命令はカウントダウンする必要があるので00番地の命令が読み出されると1になるはずです。
普通クロックの立ち上がりで命令をロードした後、次のクロックの立ち上がりの時に実行完了するのですが、つまり00番地がカウント命令なら次の01番地の命令をリードするクロックの立ち上がりでカウントする。しかしPUSH命令のときは少し特殊でスタックポインタは常にデータが入っている先頭をさしますので次のクロックの立ち上がりまでに
SPの値を-1
スタックを構成するRAMへデータ書き込み
を行う必要がありました。そこで
命令が読み出されるクロックの立ち上がりをトリガーにしてマルチバイブレータでパルスを生成、その後クロックの立下りをトリガーにしてRAMへの書き込みパルスを生成
という仕組みをつくりました。
しかしサンプリングされた波形をみてみると
00番地の命令をロードした後、SPCにマルチバイブレータにより 生成されるべきクロックが確認できません。これの原因は明白でSP-D/Uのロードに時間がかかっているせいです。SPCはマルチプレクサを通して、クロックとマルチバイブレータとで切り替えています。この切り替えもSP-D/Uが行っているので、ロードに時間がかかるとSPCにパルスが出てこなかったのだろうと思います。
そこでクロックの立ち上がりをトリガーにするのではなくSP-D/Uをトリガーにするように変更してみました。SP-D/Uが立ち上がるのはPUSH命令の時だけで他の命令では常に0ですので期待通りの動作が実現できると思います。
パターンを切ってつなぎ変えました。
修正後動作確認しましたら無事PUSH命令を実行できました。
修正後の波形 SPCに短いパルスが確認できる
スタックは今回のCPU作りで最も気合をいれて設計したうちの一つなので無事動かせて一安心です。
自作CPU #13 PUSHがうまくできない
自作CPUにはスタックを構成して載せました。しかし動作確認をしているとスタックへデータを積み上げるPUSH操作がうまくできないことが分かりました。ブレッドボード上で実験していた時はできていたのに…普通こういう回路を組む時、スタックの操作は数クロック使ってやると思います。しかし私のは、CPUの創り方のTD4を大元にしていますので、すべての命令が1クロックで実行されます。PUSH、POPも例外でなく、1クロックで実行できるようにしています。PUSHはスタックポインタを先にデクリメントしてデータを格納、POPはデータを取り出してからインクリメントしないといけないので、(スタックポインタを操作する順番が違う)マルチプレクサやらマルチバイブレータをつかってなんとか1クロックで実行できるようにしました。
実験中
弄っているうちにどうやら手でマシン語を操作する分には期待通りの動作をしていることが分かりました。プログラムを書き込んで実行させるとダメみたいです。