半導体設計民主化のための自作RISC-V SoC実践編

PicoRV32 と Wishbone で作る、フィジカルAI時代の実用オリジナルチップ

← 講義ポータルに戻る 実験並走記録 本章のRTLは骨格・未検証

第10章 カメラ・表示 ― 「目」と「画面」、そして正直な限界

身体に、見て・聞いて・話し・動く力が付きました。残る感覚は視覚です。本章では、表示(画面に出す)カメラ(取り込む)を扱います。ただし、ここはこれまでの章と性格が違います。映像は帯域も処理もメモリも、桁違いに重い。だから本章の主役は「すごい映像処理」ではなく、「何ができて、どこからが基板化(第14章)や上位連携(ネット越しAI)の話になるのか」を、正直に線引きすることです。誇張せず、できることとできないことを誠実に示します。

本章の留保(毎章の約束+"限界"の明示)。 掲載するRTLは骨格・未検証で、完全な動くコードと検証は専用ビルド工程へ回します。そして本章はとりわけ、「これは現実的でない」と正直に言う場面が多くなります。解像度・フレームレート・必要メモリといった数字は、構成で大きく変わるため断定せず、目安として示します。実際に作る際は、使うカメラ・表示デバイスのデータシートと、手元のメモリ資源で必ず確かめてください([改訂マーカー:解像度・帯域・メモリ])。

10.1 なぜ「入出力・限界」の章なのか

これまでの周辺(GPIO・通信・音声・モータ)は、扱うデータが細いか、連続でも1チャンネルでした。映像は違います。たとえば 640×480 の1フレームは約30万画素。色を付ければ1フレームで数百KB、これを毎秒何十枚も流せば、たちまち帯域とメモリの壁に当たります。小さなFPGAと入門ボードで、これをそのまま捌くのは無理がある――この現実を最初に共有しておきます。だからこそ本章は「限界の地図」を描くことに価値があります。

10.2 まず表示 ― Basys 3 には VGA が載っている

良い知らせから。音声(第8章)と違い、Basys 3 には VGA 出力が載っています(各色4ビット=12ビット色、と案内されています)。つまり画面に出す側は、外付けなしで今すぐ始められます。VGAは古い規格ですが、FPGA学習では定番で、同期信号さえ正しく作れば映像が出る素直さがあります。まずはここで「画面が光る」達成を取りに行きます。

10.3 VGAの仕組み ― 同期信号を正確に刻むだけ

VGAは、画素クロックに合わせて左から右・上から下へ点を走査し、水平同期(HSYNC)と垂直同期(VSYNC)で「行の折り返し」「画面の先頭」を知らせる方式です。640×480@60Hz なら画素クロックは約25MHz。可視領域の前後に帰線期間(フロント/同期/バックポーチ)があり、その分だけカウンタは可視サイズより大きく回ります。

 640x480@60Hz のタイミング(規格値・目安。実機で要確認)
 ───────────────────────────────────────────────────────────────
   画素クロック ≈ 25MHz
   水平:可視640 + フロント16 + 同期96 + バック48 = 800 画素/行
   垂直:可視480 + フロント10 + 同期 2 + バック33 = 525 行/画面
   HSYNC/VSYNC の極性は、いずれも負論理とされる
 ───────────────────────────────────────────────────────────────
   ※ カウンタ(hcnt,vcnt)を回し、その値から「同期パルス」と「表示中か」を作る

芯になるのは2つのカウンタです。水平カウンタが1行(800)を数え終えるたびに垂直カウンタを1進め、垂直が1画面(525)を数え終えたら先頭へ戻る。同期パルスと「いま表示領域内か(描画してよいか)」は、このカウンタ値の範囲比較で作ります。

骨格・未検証
// vga_count.v ― VGAの画素カウンタ(骨格・未検証)
//   このカウンタ値から、HSYNC/VSYNC と「表示中フラグ」を範囲比較で作る。
//   表示色は、表示中のとき framebuffer(外部RAM/低解像度BRAM)から引く(10.4)。
module vga_count (
    input            pix_clk,      // 約25MHz(640x480@60Hz)
    output reg [9:0] hcnt = 0,     // 0..799(可視640 + 帰線160)
    output reg [9:0] vcnt = 0      // 0..524(可視480 + 帰線 45)
);
    always @(posedge pix_clk)
        if (hcnt == 10'd799) begin
            hcnt <= 0;
            vcnt <= (vcnt == 10'd524) ? 10'd0 : vcnt + 1'b1;
        end else
            hcnt <= hcnt + 1'b1;
endmodule

※画素クロックは要・現物確認。 25MHz は 100MHz からクロック生成(MMCM/PLL)で作るのが定石、とされます。正確な分周・逓倍はFPGAのクロックリソース依存なので、専用工程で実機に合わせて確定します([改訂マーカー:画素クロック生成])。同期の極性・ポーチ値も、最終的に実機の表示で詰めます。

10.4 フレームバッファの壁 ― 全画面はBRAMに入らない

表示の本当の難所は、同期信号ではなく「何を表示するか=フレームバッファ」です。ここで正直な計算をします。

 フレームバッファの重さ(目安)
 ───────────────────────────────────────────────────────────────
   640×480 × 1バイト/画素 ≈ 300KB     … Basys 3 の内蔵BRAM(数百Kビット級)では入らない
   160×120 × 1バイト/画素 ≈ 19KB      … 低解像度なら内蔵BRAMでも現実的
   文字/タイル方式                      … 「文字コードの格子」を持ち、絵柄は小さなROMから引く
 ───────────────────────────────────────────────────────────────
   → 全画面のフルカラーは「外部RAM(第4章)」前提。内蔵だけなら低解像度かタイル。

つまり選択肢は三つ。(1) 低解像度にして内蔵BRAMに収める、(2) 文字/タイル方式で「絵そのもの」でなく「並べる部品の番号」を持つ、(3) 外部RAM(第4章で見送った大容量メモリ)を実装してフルフレームを置く。本講座は、まず(1)か(2)で「映像の芯」を学び、フルフレームの(3)は外部RAMを本格実装する段(第11章のMicroPythonや第14章の基板化)へ送る、という段取りにします。

10.5 現実解としての小型ディスプレイ ― 既存の通信を再利用する

「大画面フルカラー」でなくてよいなら、もっと軽い表示が手に入ります。しかも新規IPはほぼ不要。第5章で作った通信を再利用できるからです(第6章のmicroSD/無線と同じ発想)。

SPI接続の小型TFT

SPI(第5章)で小さなカラー液晶に描く。spi_wb を再利用。全画面の帯域は要らず、必要な部分だけ書き換える運用に向く。

I2C接続の小型OLED

I2C(第5章)でモノクロOLEDに文字や簡単な図を出す。i2c を再利用。ステータス表示やデバッグ表示の定番。

※どの表示が最適かは用途次第(断定回避)。 解像度・色・速度・配線数のトレードオフがあり、唯一の正解はありません。VGA(内蔵・大画面だが帯域とメモリが要る)、SPI TFT(小型・部分更新が軽い)、I2C OLED(極小・文字向き)を、作るものに合わせて選ぶのが本講座の立場です。具体デバイスの型番・初期化手順は現物のデータシートで確認します。

10.6 カメラ ― ここが本当の難所

表示が「内蔵VGAで今すぐ」だったのに対し、カメラ(取り込み)は本章最大の難所です。理由は、入ってくるデータが速く・大量・止められないからです。

入口:並列(DVP)インターフェース

入門向けのカメラモジュールは、画素クロック+同期(HREF/VSYNC)+8bitデータの並列(DVP)で画素を吐く、とされる。FPGAはこれを取りこぼさず受ける。

壁:受けた画素の置き場

毎フレーム数百KBが流れ込む。内蔵BRAMには入りきらず、外部RAM(第4章)か、その場で間引き/縮小して小さくするしかない。

さらに高解像度のカメラは MIPI CSI のような高速シリアルを使い、これは専用の物理層・ハードIPが要る領域で、入門FPGA+小型ボードの素直な範囲を超えます(第6章のRFアナログ、第9章の大電力と同じ「FPGA単体では届かない」線引き)。本講座が現実的に扱うのは、並列(DVP)の低〜中解像度カメラまでです。

10.7 正直な線引き ― できること/できないこと

本章の核心を、表にして正直に示します(いずれも目安。手元の資源で変わります)。

 カメラ・表示で「できること / できないこと」(目安・断定しない)
 ───────────────────────────────────────────────────────────────
   ◎ できる        ・VGAでパターン/低解像度/文字・タイルを表示
                    ・SPI/I2Cの小型ディスプレイに表示(既存再利用)
                    ・並列(DVP)カメラから低解像度の静止画〜低フレームを取り込む
                    ・取り込み画像へ軽い前処理(縮小・しきい値・単純フィルタ)
   △ 条件つき      ・フルフレーム表示/取り込み → 外部RAM(第4章/第14章)が前提
   × 現実的でない  ・高解像度フルモーション動画のリアルタイム処理
                    ・MIPI高速カメラ(専用PHY/ハードIPの領域)
                    ・ボード単体での本格的な画像認識(→ネット越しAIへ)
 ───────────────────────────────────────────────────────────────

10.8 カメラの設定と取り込み ― 既存IPの再利用+小さなFSM

並列カメラを使う場合、仕事は二つに分かれます。(A) 設定(B) 取り込みです。

※カメラの固有名・作法は断定しません。 入門で使われる並列カメラには定番のモジュールがいくつかある、とされますが、ピン配置・レジスタ設定・対応解像度・入手性は版で変わります。本文では型番を断定せず、要求(解像度・色・フレーム)を言語化してから現物のデータシートで選び、SCCB/DVPの作法を一次情報で確認します([改訂マーカー:使用カメラの現物])。

10.9 役割分担 ― 軽い前処理はFPGA、重い認識はネット越しAI

視覚こそ、旗印「ボード=身体、頭脳=ネット越し」が最も効く領域です。FPGAの並列性は、ライン単位の軽い前処理(縮小、グレースケール化、しきい値、単純なエッジ抽出)には強い。けれど「何が写っているか」を理解する重い推論は、本ボード単体では担いません。

誇張はしません。 現実的な流れは、FPGAで取り込み→縮小・軽い前処理→(必要なら)通信で送り→ネット越しAIが認識→結果を受けて動く(第9章のモータ等)です。ボードは「目と、目の前処理」までを正確に担い、意味の理解はAPIに委ねる。この分担なら、小さなFPGAでも視覚を実用の入口に置けます。本格的なオンボード画像認識を約束はしません。
発展:なぜ「縮小してから送る」が効くのか

ネット越しAIに画像を送るとき、フル解像度をそのまま送るのは帯域も時間も無駄になりがちです。多くの認識タスクは小さな画像でも十分な精度が出ます。FPGAの段で間引き・縮小・前処理を済ませておけば、送るデータが小さくなり、通信(第5〜6章)の負荷も下がります。「身体の側で賢く減らしてから、頭脳に渡す」――これが小型ボードで視覚を活かす定石です。

10.10 メモリマップに「表示/カメラ」を足す(設計案)

表示とカメラも、これまでどおりWishboneに足します。ただしフレームバッファ本体は大きいので、これは外部RAM前提の設計案になります(小規模なら低解像度BRAMで代替)。

 メモリマップへの追記(設計案。番地は実装で確定)
 ───────────────────────────────────────────────────────────────
   0x0〜0xA   既存+音声(0x9)+モータ(0xA)(第8・9章の設計案)
   0xB 〜     表示(VGA制御:framebufferの先頭/解像度/有効化)   ← 新設(予約)
   0xC 〜     カメラ(取り込み制御:開始/停止/ステータス/格納先) ← 新設(予約)
   (別領域) framebuffer 本体 … 外部RAM(第4章/第14章)。低解像度なら内蔵BRAM
 ───────────────────────────────────────────────────────────────
   ※ VGAは framebuffer を読み、カメラFSMは framebuffer に書く。間をどう調停するかは設計判断。

10.11 【確認】この章の最小確認

欲張らず、表示→静止画→1フレームの順で、できる範囲を確実に積み上げます。

  1. 表示(FPGA)。 vga_count にクロックを与え、同期と表示フラグからVGAにテストパターン(色帯/格子)を出す。まず「画面が正しく光る」を達成。
  2. 小型表示(FPGA)。 SPI TFT または I2C OLED(既存再利用)に、文字や図形を表示。部分更新の軽さを体感。
  3. 静止画取り込み(FPGA)。 並列カメラをI2C系で低解像度に設定し、取り込みFSMで1フレームをBRAMへ格納 → VGA/小型表示に出して「撮れた」を確認。
  4. 前処理(FPGA)。 取り込み画像を縮小/グレースケール化し、必要なら通信(第5〜6章)でネット越しAIへ送る土台を作る。
[改訂マーカー] 本章で実機実測して確定する値:画素クロックの生成(MMCM/PLL)、VGAの同期極性・ポーチ、framebufferの解像度と置き場(内蔵/外部RAM)、使用カメラの現物(DVP/SCCBの作法・対応解像度)、取り込みFSMのタイミング、Pmod割り当て、追加後のFPGA利用率・BRAM使用量。完全な動くRTLと検証は、設計合意済みの専用ビルド工程でまとめて実施します。

10.12 この章のまとめ

これで身体は、五感と運動の骨格がそろいました。ここまでは「ハードができる/できない」の話が中心でしたが、次章からは「使えるボードにするための土台」=ソフトに踏み込みます。ツールチェーン、Arduinoコア、ブートローダ、そしてMicroPythonへの道筋――第11章:ソフトの足場(Arduino/MicroPython)です。