前回、Cmod A7ボードへの移植を完了したオリジナル16ビットCPUコアMoscoviumのタイミング結果報告で、今まで見えていなかったクリティカルパスが見えてきました。
現在公開しているGitHub上のデザインデータは、そのクリティカルパスを対策した後のデータとなっているのですが、今回は、クリティカルパス対策の設計変更に関して報告します。
今までPrimerボード(TD IDE)を使った設計では、CPUの命令レジスタir → ALU → 汎用レジスタRxなど、CPU内部パスがクリティカルパスとして報告されていました。これは、ごく普通の結果なため、特に疑いもせずここまで来てしまいました。
ところが、新しいCmod A7ボード(Vivado)を使ってコンパイル(論理合成・配置配線)したところ、見慣れない新しいパスがクリティカルパスとして報告されました。
新らしいクリティカルパス:
命令レジスタir → メモリバスアドレス出力 → ROMマクロアドレス入力
結果としてメットはしていたのですが、結構厳しめなスラックで、あまりタイミング的に余裕が有りませんでした。このSTA結果を見て、設計変更が必要だと考えたのです。
もう少し詳しく見て行きます。
Vivado等が提供するROMマクロは、一般的に、読み出しレイテンシ1のインターフェイスとなっています。
読み出しレイテンシ1とは、ROMマクロに対してアドレスを入力すると、次のclk↑でデータが出力され始める事を指します。
読み出しレイテンシについて、以前使ったSDRAMの図を使って説明します。
参考)SDRAM等の場合、
CASレイテンシnの場合、nサイクル後ろのclk↑でデータが出力されるので、それを取り込むタイミングはn+1サイクル後のclk↑です。
SDRAMは記憶容量が大きいため、ビット線・ワード線の配線長が長く、既成容量が大きいという特徴があります。結果として読み出しに時間がかかります。更に、D(Dynamic)-RAMは、「破壊読み出し」と言って、一度データを読み出してしまうと、そのデータは失われてしまうのです。そこで、SDRAM内部では、読み出した後で、同じデータを再書き込むという回路が動作します。
この様な内部動作のため、アドレス・コマンド入力からデータを出力できるまでに2〜3[サイクル]を要するのです。
SDRAMの場合、CASレイテンシ(2〜3[サイクル])の間に、同じカラム内のデータを一気に読み出すことで、一旦データ出力を開始すると、1データ/1サイクルで高速にデータを出力することができます。
RAMマクロの場合、SDRAMに比べて高速に読み出すことができるので、2〜3[サイクル]と言う長いレイテンシは必要ありませんが、最低限1サイクルのレイテンシを持っているのが普通です。
Moscoviumのメモリバス側からのオペランドアクセスでは、通常通り、読み出しレイテンシ1を期待しています。
しかし、フェッチの場合だけはアドレス入力と同相でデータが出力される、読み出しレイテンシ0という特殊なROMを前提としていました。
Vivadoもそうですが、TD IDEに用意されたROMマクロも、読み出しレイテンシ1のインターフェイスになっていたことから、仕様が合いませんでした。
そこで、ROMマクロを逆相クロックで駆動して、疑似的に読み出しレイテンシ0を実現したのです(下図)。
上側にタイミング図、下側に、それと対比したブロック図を示した図です。
設計当初の目論見としては、addrもdataも、fcpu=24MHzに対しては十分速いため、問題なくSTAも通るだろうと考えていました。実際、TD IDEでは、このパスがクリティカルパスとして報告されたことが無かったため、すっかり忘れていました。
Vivadoでは、いきなりこのパスがクリティカルパスとして報告されたため、設計変更に踏み切った訳です。
※TD IDEが何故、このパスを報告してこなかったのかは、不明。所詮、中華品質の開発ツールなので、今更深追いしても無意味、無視。
故意犯だったとは言え、改定が必要なほどクリティカルであると判った以上、設計変更を実施したいと思います。
VivadoのSTAが報告してきたクリティカルパスを、冷静になって良〜く見直してみたところ、実は、こちらに図示したパスではないことが判明しました。……いや、場所としてはROMマクロのアドレスセットアップタイミング不足で合っているのですが……。
Vivadoが報告してきたクリティカルパスは、フェッチ側パスではなく、オペランド(データ)アクセス側パスだったのです。
Moscoviumはハーバードアーキテクチャなので、フェッチバスとメモリバスが分離しています。命令ROMには、Moscoviumが実行すべきプログラムを格納するのはもちろんのこと、シリアルモニタへ送信する文字列データや、定数配列などのデータも格納するため、命令フェッチだけでなく、オペランドアクセスも発生するのです。
フェッチパス側は、こちらの図の様に、プログラムカウンタ値がそのまま、フェッチアドレスとして出力されていたため、アドレス出力遅延時間は短く、当初想定通り、全く問題なしでした。
一方、メモリバス側は、命令を復号した結果、初めて、何の値をアドレスバスに出力すべきか判るため、アドレス出力遅延時間は長く、遅いパスとなっていました。そこへもってきて、フェッチ側の読み出しレイテンシ0を実現するための逆相クロック駆動に引きずられ、メモリバス側も半相転送になっており、これがクリティカルパスとなっていました。
ああ、なるほどね〜。この図を描いた時点で、すっかり頭から抜け落ちていたんだな〜、メモリバス側の回路、描いてないもんな〜。
しかも、TD IDEのSTAでは何も報告が無かったので、全く気が付いていませんでした。
以下に設計変更後のブロック図を示します。
IF → IDステージと、MA → WBステージについて描いたブロック図とタイミング図です。今度はちゃんと、フェッチバス側(F-bus)と、メモリバス側(M-bus)、両方を図に書き込んであります。お陰でちょっとゴチャッとして見難いですが……。
設計変更の要点:
何やら、良いこと尽くしですよね?今まで何でそうしなかったんだ?って事になってしまいますね……。以下、言い訳しておきます。
なので、今回みたいにSTAのクリティカルパスとして報告が上がれば、重い腰を上げて対策に乗り出すけど、そうでなければ、様子を見るケースでした。
※中華品質のTD IDEに文句たれても仕方ないけど、上の状況を見る限り、STAでクリティカルパスとして報告しなかったTD IDEの罪は大きい。やはり、中華製品とは離別して大正解だった。
Moscoviumはパイプライン設計には、なっていません。詳しくはこちら。動作上は、「2段パイプライン」とは言えるけど、2段なんてパイプラインじゃないよね?って事です。
パイプライン設計を採用しなかったお陰で、以下の様な利点を獲得しています。
以下に、設計変更前・後のブロック/タイミング図を示し(再掲)、実行ステージとの対応を取っておきます。
タイミングが緩和されたこともさることながら、何より、読み出しレイテンシ0という、特殊なROMを使用しなくて良くなったことが(もちろん、逆相クロックを排除できたことも含めて)、最大の収穫でした。
今回までに移植完了したI/Oユニットは以下の通りです。
Cmod A7ボード用Moscoviumマイコンの設計データ(Vivadoプロジェクト)は、GitHubにて配布しております。以下バナーよりアクセスしてください。
今回リリースしたI/Oユニットによって、以下の型名が解禁されました。
ざっとですが、シミュレーションで動作確認してあります。
※Nihoniumコアを搭載した型名が解禁できていないのですが、IPとしてはリリースしてあります。VHファイルを直接編集すると、マイコンの構成を変更することができます。
デザイン(回路)をCmod A7ボードに書き込む手順については、こちらをご確認ください。
「#27-4 移植後の検証」にて作成したMCOC115CA0408に対して、元の型名のまま、以下のI/Oユニットを追加しました。
Vivadoでのコンパイル(論理合成・配置配線)結果を以下にまとめます。
コンパイル結果:
Cmod A7ボードに搭載されたArtix-7ファミリXC7A35T FPGAチップの実力に対しては、まだまだ規模の小さいデザインではありますが、fcpu=24MHzに於いてセットアップスラック=約10nsと、余裕があります。今回報告した設計変更の賜物です。
I/Oユニットを追加したMCOC115CA0408(改)を使用して、LEDキャンドルを移植してみました。
プログラム:mcoc_candle_ca7.asm
色相変換テーブル:mcoc_candle_hue.incl
1/fゆらぎ乱数列データ:mcoc_candle.incl
昔Moscovium用に作成したプログラム(mcoc_candle.asm、「#15-10 汎用16ビットタイマユニット」)の焼き直しです。LEDキャンドルの動作原理となる、1/fゆらぎ乱数列に関しては、こちらの逆引き索引から参照してください。
元のプログラム(mcoc_candle.asm)は、まだMoscoviumマイコンの端子配置などが固まる前に作成したプログラムであるため、オンボードRGB LEDへ汎用16ビットタイマTIM162ユニットのPWM出力端子を割り当てないと実行できない、変則的なプログラムでした。つまり、このプログラム専用の制約ファイルが必要だったのです。
今回はオンボードRGB LEDの制御に、専用のLED駆動用PWMタイマTIMLED5ユニットを使用できるので、汎用のプログラムと、なっています。
※汎用だけど、TIMLED5ユニットと、mulur命令の実装を必須としています。
プログラムをMoscoviumマイコンに書き込む手順については、こちらをご覧ください。
前節でリリースしたデザイン(MCOC115CA0408)と、プログラム(mcoc_candle_ca7.asm)をCmod A7ボードへ書き込むと、特にシリアルモニタから操作しなくても、LEDキャンドルとしてオンボードRGB LEDが瞬いているはずです。
元のプログラム(mcoc_candle.asm)では、なるべくロウソクの炎の色に近づけるようにRGB LEDの色合いを調整して、エミュレートに主眼を置いていました。
ですが、どんなに、ろうそくの炎をエミュレートした所で結局LEDなんですよね……。限界があります。
今回は開き直って、見栄えがする様にRGB LEDが、どんどん色を変えながら瞬きます。色は色相(Hue)0〜360°をくるくる回るので、綺麗に虹色に光ります(下図)。
色相(Hue) → RGB変換は、何気に面倒な処理だったりするので、変換テーブル(mcoc_candle_hue.incl)を用意して変換しました。
以下の動画でご確認ください。
虹色に瞬く実際のロウソクなんて存在しないでしょうから、新鮮で綺麗でしょう?
Cmod A7ボードへの移植のついでに、気になっていた箇所を訂正しながら進めています。今回のフェッチレイテンシの設計変更は少しインパクトが大きかったため、スーパスケイラ版まで手が回りませんでした。一歩一歩、進めて行こうと思います。