新しいFPGAボードであるCmod A7ボードで開発中のオリジナル16ビットCPUコアMoscoviumに於いて、前回、Xilinx Artix-7ファミリの大容量RAMマクロをたっぷり使った、メインメモリの拡張を実施しました。
同時に、RAMマクロには、メインメモリ以外にも使い道があるという話も致しました。
今回は、RAMマクロの、メインメモリ以外の用途である日本語フォントFONTJPユニットと、unicode⇔S-JIS変換UNISJIユニットを移植して行きます。
以下の記事で設計した、8×8[ドット]日本語フォントデータを読み出し可能なI/Oユニットです。
「#18-4 Moscoviumと日本語フォント」
軽く「おさらい」しながら、移植のポイントを押さえて行きましょう。以下にFONTJPユニットのブロック図を示します。
※薄黄色の箱はCPUからアクセス可能なI/Oレジスタ、薄緑色の箱はハードマクロ、青破線はRTLとハードマクロの境界線です。
記憶データは1ドット当たり1ビットなので、フォントデータは1文字=8×8[ドット]=64ビットのデータを占めます。フォントROMには、1サイクルで1文字分のフォントデータを読み出すことができるよう、64ビット幅のROMマクロを使っています。
1サイクルで64ビット読み出せれば良いので、普通のシングルポートROMマクロを使っています。回路部分は純粋なRTLなので、Vivadoでもそのまま論理合成可能です。ROMマクロ部分だけをVivadoの36KビットRAMマクロに合わせて変更すれば良いのです。
使用した36KビットRAMマクロ数は、こちらで確認してください。
フォントROMに記憶するデータは、以下にリンクするOlive+のスクリプトで各自生成して使ってもらいます。詳しい生成手順は、こちらをご覧ください。
スクリプト:fontjp_gen_mif.olv
※スクリプト(.olv)の実行には拙作Olive+をWindowsにインストールしてください。
以前使っていたPrimerボード(中華製FPGA、👎thumbs-down)では、あまり馴染みのないMIFファイルと言う形式でROMデータを指定していました。
新しいCmod A7ボードのVivadoでは、Verilog-HDLが規定するMEMファイル形式のファイルを使うことができます。
スクリプト先頭付近の変数gen_vlog_memを以下の様に設定して生成してください。
var gen_vlog_mem=true; // Verilog-HDL用MEMファイルを生成する
※ダウンロードした状態だと、「false」となっていて、MIFファイルが出力されます。
完成したファイルを「fontjp.mem」にリネームして、Vivadoプロジェクトディレクトリの所定のディレクトリにコピーします。
ディレクトリパス:MCOC_HDL/ip/fontjp.mem
GitHubに登録されているファイル(fontjp.mem)は中身が空のダミーなので、生成したファイルで上書きしてください。
以下の記事で設計した、unicode⇔S-JISコード間の相互変換が可能なI/Oユニットです。
「#22-1 文字コード変換回路」
軽く「おさらい」しながら、移植のポイントを押さえて行きましょう。以下にFONTJPユニットのブロック図を示します。
※薄黄色の箱はCPUからアクセス可能なI/Oレジスタ、薄緑色の箱はハードマクロ、青破線はRTLとハードマクロの境界線です。
「逆引き」とは即ち、テーブル全体を検索して合致するデータを見つける作業です。
上に示したブロック図の通り、同時に12文字分のデータを検索して一致するデータを見つけるため、変換テーブルROMは、1サイクルで12文字分のデータ、従って12文字×16ビット(※)=192ビットのデータを読み出す必要があります。
192ビットのシングルポートROMを使っても良かったのですが、96ビットのデュアルポートROMとして、2つのポートから別々なアドレスを読み出すことで、192ビット/1サイクルの読み出しを実行しました。
この様に単純な作業を並列して同時に実行できるのは、ソフトウェアには真似できない、ハードウェアの特権です。
※16ビットunicodeが対象のため。
回路部分は純粋なRTLなので、Vivadoでもそのまま論理合成可能です。ROMマクロ部分だけをVivadoの36KビットRAMマクロに合わせて変更すれば良いのです。
使用した36KビットRAMマクロ数は、こちらで確認してください。
変換テーブルROMに記憶するデータは、以下にリンクするOlive+のスクリプトで各自生成して使ってもらいます。詳しい生成手順は、こちらをご確認ください。
スクリプト:unisji_mkmif.olv
※スクリプト(.olv)の実行には拙作Olive+をWindowsにインストールしてください。
以前使っていたPrimerボード(中華製FPGA、boooo👎)では、あまり馴染みのないMIFファイルと言う形式でROMデータを指定していました。
新しいCmod A7ボードのVivadoでは、Verilog-HDLが規定するMEMファイル形式のファイルを使うことができます。
スクリプト先頭付近の変数gen_vlog_memを以下の様に設定して生成してください。
var gen_vlog_mem=true; // Verilog-HDL用MEMファイルを生成する
※ダウンロードした状態だと、「false」となっていて、MIFファイルが出力されます。
完成したファイルを「unisji.mem」にリネームして、Vivadoプロジェクトディレクトリの所定のディレクトリにコピーします。
ディレクトリパス:MCOC_HDL/ip/unisji.mem
GitHubに登録されているファイル(unisji.mem)は中身が空のダミーなので、生成したファイルで上書きしてください。
Cmod A7ボード用Moscoviumマイコンの設計データ(Vivadoプロジェクト)は、GitHubにて配布しております。以下バナーよりアクセスしてください。
ダウンロード方法などについては、トップのREADME.mdをご覧ください。
今回までに移植を完了したユニットは、以下の通りです。
これによって、以下の型名が解禁されました。
この先の実験では、上の中からMCOC115US0816を使いますので、コンパイルしてCmod A7ボード(FPGA)に書き込んでおいてください。
デザイン(回路)をCmod A7ボードに書き込む手順については、こちらをご確認ください。
Vivadoでのコンパイル(論理合成・配置配線)結果を以下にまとめます。
コンパイル結果:
どういう訳か、UNISJIユニットの変換テーブルROM(96ビット×1,344ライン=15.75Kバイト)に、36KビットRAMマクロ数が5.5個と報告されました(普通に考えると、必要数は6個のハズ)。中途半端なサイズ(非2冪数)のROMなので、どういう理屈か良く解りませんが、深く考えるのは止めました。Vivadoの報告通りに記載してあります。
前節の通り、コンパイルしたところ、FONTJPユニットとUNISJIユニットで、合計22個(小数点以下切り上げ)の36KビットRAMマクロを使いました。命令ROM容量を最小の4Kバイト(RAMマクロ1個)に抑えたとしても、残った27個で構成可能な拡張RAM(E-RAM)ユニットは、最大108Kバイト(=4Kバイト×27個)分です。最大の2冪数に切り下げると、ようやく64Kバイトを確保できる、と言う所ですね。
やはり、仕様上最大とした128Kバイトは確保できないのね……。
この様な実例の通り、RAMマクロが大量に必要なアプリケーションを作るのであれば、もっと上位のFPGAチップ(Artix-7ファミリXC7A100T等)を使う事を検討してください。
※「大は小を兼ねる」ので、なるべく上位のチップを選択するのは間違いではありませんが、上位チップは高額になるので、費用対効果を考えた上で選択するべきです。
シリアルモニタから文字列を受信して、外部OLEDディスプレイ(下図)に表示するプログラムを作り、後ほど実験に使います。
以下に、完成したプログラムをリンクしておきます。
プログラム:oled_kprint.asm
こちらに従ってアセンブルし、Cmod A7ボードに転送してお使いください。Moscoviumマイコンに転送すると、シリアルモニタから、以下のコマンドを受け付けています。
コマンド仕様:
動作検証の手順としては、【prn】コマンドでFONTJPユニットの動作を確認したら、【uprn】コマンドでUNISJIユニットの動作を確認する、と言う順番です。
実験の準備として、Cmod A7ボードとOLEDディスプレイを以下の様に接続してください。
Cmod A7ボード (Moscoviumマイコン) |
接続 | OLEDディスプレイ |
VU (VBUS、5V) | → | VCC |
GND | ⇔ | GND |
stws_scl (18 PIN) | ⇔ | SCL |
stws_sda (19 PIN) | ⇔ | SDA |
Moscoviumマイコンのピン配置表はこちらです。デザインはMCOC115US0816をCmod A7ボード(FPGA)へ書き込んでおいてください。
OLEDディスプレイは、ボード上のレギュレータで3.3Vへ降圧しているので、VCCには5Vを接続します。I2C端子は3.3V定格なので、Cmod A7ボードと直結できます。詳しくはこちら。
以下に、実験中の様子を示します。
以降、Cmod A7ボードとの通信は、S-JISおよび、UTF-8符号化した日本語文字列を送受信できる必要があるので、Tera Term等、文字符号化方式を設定可能な通信ソフトウェアを使用してください。
Tera Termから、「KanjiCodeメニュー ⇒ Recv/Send: Shift_JIS」を実行して、S-JIS符号化に設定したら、以下サンプルの様に実験を始めましょう。
実験サンプル:【 】内はシリアルモニタからの送信データ
【prn,0,S-JISエンコード文字列】
OK: prn
OLEDディスプレイにS-JIS符号化した文字列が表示されたはずです。
プログラムの動作としては、FONTJPユニットからS-JISコードのフォントデータを取り出して、OLEDディスプレイに描画しました。FONTJPユニットが正常に機能していなければ、OLEDディスプレイに正しく表示されないはずです。
今度はTera Termで「KanjiCodeメニュー ⇒ Recv/Send: UTF-8」を実行し、UTF-8符号化に設定して続けます。
【uprn,1,UTF-8変換、表示サンプル】
OK: uprn
UTF-8で送信した文字列データをプログラム(oled_kprint.asm)がUTF-8 → unicode → S-JIS変換(UNISJIユニット)して、OLEDディスプレイに描画しました。UNISJIユニットが正常動作していない場合は、文字化けしたデータが表示されてしまうはずです。
当方の実験では、図に示した通り、正常に表示されました。OKです。実験を終了します。
こうして見ると、フォントROMは結構なサイズですね。これでも8×8[ドット]の日本語フォントで妥協しているのですがね……。複雑な漢字まで視認可能な16×16[ドット]フォントではROM容量が×4倍となって、XC7A35TのRAMマクロでは足りなくなってしまいます。中々……。