この記事の前提
- P-1で、中古のKintex-7 PCIeカードにMicroBlazeを載せ、LED・DDR3・温度センサを動かしました
- 対象はVivado/Vitis 2023.2で作成した、当時の手元プロジェクトです
- この記事では、残っているブロックデザイン、XSA、Vitis platformの生成ファイル、Implementationレポートから、構成を読み直します
- PCIeホストからの認識とDMA転送はまだ扱いません。P-3以降のテーマです
- ファイルの値は、すべて同じ時点の成果物とは限りません。値が食い違う場合は無理に一つへまとめず、どの成果物の値かを分けて記載します
はじめに
P-1を書くために当時のメモを見返したとき、書き留めてあったタイミング値がどうも腑に落ちませんでした。そこでVivadoプロジェクトを開き、最終レポートと実行ログを確認したところ、メモの数値には取り違えがありました。
一方で、プロジェクトにはメモより確かな情報も残っていました。
- MicroBlazeのクロック、データ幅、アドレス幅
- GPIO、I2C、MDM、DDR3のアドレス
- Vitisがメモリテスト用に生成したDDR3の範囲
- BSPの標準入出力先
- XDMAの設定
- LUT、FF、BRAM、GTXの使用量
- routed timing reportの最終値
この記事の結論は、次の一文です。
昔の設計を復元するときの判断基準
人のメモだけを「正」にせず、実行画面、ソフトウェア生成物、XSA、Vivadoレポートを役割ごとに読み分けます。
今回読み解く構成
図では、P-1で実際に確認した経路を実線、IPを組み込んだだけで未評価のPCIeホスト経路を破線で分けます。
構成の中心は100MHz動作のMicroBlazeです。ローカルBRAMから起動し、AXI経由でGPIO、I2C、MIG、MDM、XDMAへ接続しています。
| 項目 | 手元の設計データで確認できた値 |
|---|---|
| FPGA | Kintex-7 XC7K480T(-2FFG1156I) |
| MicroBlaze | 100MHz、32bitデータ |
| アドレス幅 | 36bit |
| ローカルBRAM | 512KB |
| D-cache | 4KB。ただしP-1のメモリテスト時は無効 |
| DDR3 | Vitis実行時は2チャネル×2GB |
| 標準入出力 | MDMのJTAG UART |
| XDMA | Gen2 x8、AXI Memory Mapped、128bit、250MHz設定 |
32bit CPUなのに、アドレスは36bit
MicroBlazeの生成パラメータには、次の値が残っていました。
C_DATA_SIZE = 32
C_ADDR_SIZE = 36
C_M_AXI_DP_ADDR_WIDTH = 36
C_M_AXI_DC_ADDR_WIDTH = 36
データレジスタは32bitですが、アドレスまで32bitとは限りません。今回のVitis実行時のDDR3は、4GB境界より上に配置されていました。
DDR3 channel 0: 0x100000000 から2GB
DDR3 channel 1: 0x180000000 から2GB
0x100000000は、32bitアドレスで表せる範囲の一つ上です。そのため、MicroBlaze側にも36bitの拡張アドレスが必要になります。
AMDのMicroBlaze資料でも、32bitプロセッサでC_ADDR_SIZEを36bitにすると、64GBまでの拡張アドレスを扱う構成になると説明されています。ただし、32bitポインタを前提とするドライバなどには制約があるため、アドレスを広げればすべての既存コードがそのまま動くわけではありません。
今回のアプリケーション本体、スタック、ヒープは、DDR3ではなく512KBのローカルBRAMに置かれていました。4GBを超えるDDR3は、メモリテスト関数へ拡張アドレスを渡して評価しています。
Vitisが生成したメモリ範囲を見る
Vitis applicationには、ハードウェア情報から生成されたmemory_config_g.cが残っています。
struct memory_range_s memory_ranges[] = {
{
"mig_7series_0_c0_memaddr",
"mig_7series_0",
0x100000000,
2147483648,
},
{
"mig_7series_0_c1_memaddr",
"mig_7series_0",
0x180000000,
2147483648,
},
};
P-1のTCF Debug Terminalにも同じアドレスとサイズが表示されていました。したがって、「その画面で動かしたVitis applicationが認識していた範囲」は、この生成ファイルと実行画面を組にして確認できます。
2GB全域をテストしたわけではない
メモリテストの呼び出しは次の内容でした。
Xil_TestMem32(
range->base & LOWER_4BYTES_MASK,
(range->base & UPPER_4BYTES_MASK) >> 32,
1024, 0xAAAA5555, XIL_TESTMEM_ALLMEMTESTS);
Xil_TestMem16(
range->base & LOWER_4BYTES_MASK,
(range->base & UPPER_4BYTES_MASK) >> 32,
2048, 0xAA55, XIL_TESTMEM_ALLMEMTESTS);
Xil_TestMem8(
range->base & LOWER_4BYTES_MASK,
(range->base & UPPER_4BYTES_MASK) >> 32,
4096, 0xA5, XIL_TESTMEM_ALLMEMTESTS);
32bit MicroBlazeで4GBを超える領域へアクセスするため、テスト関数にはアドレスの下位32bitと上位側を分けて渡しています。どの呼び出しも、テストする範囲は先頭4KBです。32bit、16bit、8bitのアクセス幅で複数パターンを試していますが、2GB全域を走査してはいません。
ここから言えるのは、次の範囲までです。
- 2つのDDRチャネルがVitis applicationから見えている
- 各領域の先頭4KBについて、基本的な読み書きが通った
- MicroBlaze→AXI→MIG→DDR3の経路が少なくともこの条件では動いた
全容量の保証、アドレス線の網羅、長時間負荷、帯域、温度変化を含む安定性は別の評価です。「PASSED」という文字だけを見て、4GBすべてを検査したと解釈しないようにします。この範囲の広さの比較は、P-1の図(2GBに対する先頭4KB)にまとめています。
TCF Debug Terminalの正体はMDM
P-1の実行画面には、TCF Debug Virtual Terminal - MicroBlaze Debug Moduleと表示されています。BSPのsystem.mssにも次の設定が残っていました。
PARAMETER stdin = mdm_1
PARAMETER stdout = mdm_1
また、ブロックデザインのMDMはC_USE_UART=1です。つまり、今回のprint()出力とキー入力は、物理的なUART端子やPCIeを通ったものではありません。
経路は、開発PCからJTAG、MDMのJTAG UARTを経由し、MicroBlazeの標準入出力へつながります。この関係は冒頭の構成図にも示しました。
この経路を押さえておくと、「画面にUARTターミナルが出ているのに、カード上のTX/RXはどこか」という混乱を避けられます。物理UARTを外へ出したい場合は、UART IP、ピン制約、レベル変換やUSB-UARTブリッジを別に用意します。
Vivado BD、XSA、Vitis platformの値が食い違った
ここが、今回いちばん実務的だった点です。
手元に残る現在のVivadoブロックデザインと、Vitis applicationが使用していたmemory_config_g.cを比べると、DDR3のアドレス配置が一致しませんでした。
| 確認元 | channel 0 | channel 1 |
|---|---|---|
| P-1の実行画面/Vitis生成ファイル | 0x100000000 |
0x180000000 |
| 現在保存されているVivado BD | 0x80000000 |
0x100000000 |
図の上段はP-1を実行した当時に確認できる一組、下段は現在手元に残るVivado BDです。ハードウェアが同じでも、異なる時点の成果物を横につなげて一つのBuildとして扱うことはできません。
どちらかを都合よく書き換えて、同じ設計だったことにはできません。考えられるのは、Vivado側でアドレスを変更したあとVitis platformを更新していない、別の時点のXSAを取り込んだ、または後からVivadoプロジェクトだけを変更した、といった状況です。
ここでは、用途ごとに「正」を分けます。
- 当時の実行画面を説明する:実行画面と、そのVitis applicationが持つ生成ファイル
- 現在のハードウェアを再ビルドする:現在のVivado BDから新しく書き出したXSA
- VivadoとVitisを接続する:どのXSAからplatformを生成したか
- 出荷物を再現する:bitstream、XSA、application ELF、生成日時やcommitを一組で保存
XSAはVivado側のハードウェア構成をVitisへ渡す境目です。VivadoとVitisの画面を別々に保存するだけでは、あとから同じ組み合わせを再現できないことがあります。
XDMAはどこまで準備されていたか
ブロックデザインにはXDMAが入り、次の設定が残っていました。
| 設定 | 値 |
|---|---|
| PCIeリンク設定 | Gen2、x8、5.0GT/s |
| AXIインターフェース | AXI Memory Mapped |
| AXIデータ幅 | 128bit |
| AXIクロック | 250MHz |
| 読み/書きチャネル | 各2チャネル設定 |
ただし、これは「IPがその設定で組み込まれている」という事実です。ホストPCからの列挙、BARの確認、ドライバ、DMA転送、帯域はまだ確認していません。
設定値と実測結果を混ぜないため、P-2ではここまでに留めます。
Implementation結果から規模を見る
手元に残るimpl_1の配置後レポートでは、次の使用量でした。
| リソース | 使用量 | デバイス全体 | 使用率 |
|---|---|---|---|
| Slice LUT | 66,127 | 298,600 | 22.15% |
| Slice Register | 68,622 | 597,200 | 11.49% |
| Block RAM Tile | 160.5 | 955 | 16.81% |
| GTXE2_CHANNEL | 8 | 32 | 25.00% |
| PCIeハードブロック | 1 | 1 | 100.00% |
MicroBlazeだけなら小規模ですが、2チャネルMIGとXDMAまで含めると、BRAM、GTX、PCIeハードブロックも使います。ソフトCPUを載せたという一言だけでは見えない、実際の構成規模です。
同じImplementation runの最終routed timing reportは、WNS -0.012ns、TNS -0.023ns、Failing Endpoints 2でした。bitstreamは生成されていますが、判定はTiming constraints are not metです。
ここでも、次の二つは分けて扱います。
- P-1でLED(GPIO)、DDR3、温度センサ(I2C)が動いた
- 静的タイミング解析を通過した
前者は確認できましたが、後者は未達です。限定的に実機が動いたことは、全条件でタイミングを満たす保証にはなりません。
後から困らないために、何を一組で残すか
今回のような復元作業を減らすなら、最低限次を同じBuild IDへ結び付けて残します。
- Vivadoプロジェクトのcommit ID
- bitstream
- XSA
- Vitis platformの生成元XSA
- applicationのcommit IDとELF
- Address Editorまたは生成済みアドレス情報
- utilization report
- timing summary report
- 実行ログと評価条件
スクリーンショットは当時の状況を伝えるのに強い一方、設定全体の再現には足りません。逆にプロジェクトだけ残っていても、どのbitstreamを実機へ書いたかが分からなければ、実行結果と結び付きません。
まとめ
- 32bit MicroBlazeでも、今回のDDR3配置に合わせて36bitアドレスを使用していた
- Vitis実行時は2チャネル×2GBのDDR3が見えていた
- メモリテストの
PASSEDは各チャネル先頭4KBの結果であり、全域試験ではない - TCF Debug Terminalの標準入出力は、PCIeでも物理UARTでもなくMDMのJTAG UARTだった
- Vivado BDとVitis生成ファイルに差がある場合、実行時の説明と現在の再ビルドで参照する成果物を分ける
- XDMAは組み込まれているが、PCIeホストからのDMA転送はまだ評価していない
- 実機動作とタイミング収束は、別の判定として残す
この先のP-3では、ホストPCからカードがどう見えるかを確認し、BAR、ドライバ、XDMA、DDR3までの経路を一つずつ試してみます。P-2は、手元に残った設計データを読み直してみた記録として、ここで一区切りです。設定値と実測結果を混ぜないことだけは意識しつつ、中古ボードで遊んでみた範囲をまとめました。

