コンテンツにスキップ

RedPitaya アイスレーダシステム - 技術制約と設計指針

概要

このドキュメントは、RedPitaya ベースのアイスレーダシステムを含むレーダシステム全体の設計・運用で考慮すべき技術制約と特性をまとめています。システム全体の性能を左右する重要な制約事項を理解するためのリファレンスです。

具体的には、システム全体のリアルタイム性や分解能などを決定する要因について解説し、デバイスによる性能の違いを明確にします。また、HDL コードを読む開発者向けに、元の RedPitaya コードからどのような改修を行ったかについても詳述しています。

ハードウェアのシステムに対する影響

SoC と BRAM 容量

BRAM とは、Block RAM(ブロック RAM)は、FPGA 内部に搭載された高速メモリです。外部の DDR メモリと異なり、FPGA 内部の論理回路から直接アクセス可能で、レイテンシが極めて小さい(数クロック)という特徴があります。

レーダのような高速データ取得では、ADC からの連続データを一時的にバッファする必要があります。外部 DDR メモリではアクセス遅延により高速サンプリングに追従できないため、BRAM 使用が必須となります。

BRAM は容量が限られており、長時間の連続データ取得には物理的制限があります。また、BRAM の R/W にもアクセス遅延や同じアドレスに R/W を同時にできないなどの制約があるため、高速データ取得時の設計では慎重なタイミング制御が必要となります。特に複数チャンネルの同時取得や積算処理では、これらのハードウェア制約を考慮したメモリアクセスパターンの設計が不可欠です。

STEMLab125-14 は Zynq-7010、SIGNALLab250-12 は Zynq-7020 を搭載しており、それぞれ BRAM 容量が異なります。Zynq-7010 は 36Kb のブロックが 60 個で計 2,160Kb(約 270KB)、Zynq-7020 は 140 ブロックで計 5,040Kb(約 630KB)の容量を持ちます。ただし、このうちデータ保存に使用できる BRAM は限られています。

例えば、STEMLab125-14 の量子化ビット数は 14bit であるため、1 回の計測で 8,192 点のデータを取得する場合、約 114.7Kb の BRAM が必要となります。これは、ビット精度を下げるか保存データ点数を削減することで、より多くの計測を連続実行できることを意味します。また、内部的な積算処理も非常に有効です。

デバイス SoC 総 BRAM 容量 利用可能 BRAM 1 回計測容量(8192 点) 最大連続回数
STEMLab125-14 Zynq-7010 約 270KB 約 180KB 約 14.3KB(14bit) 約 12 回
SIGNALLab250-12 Zynq-7020 約 630KB 約 420KB 約 12.3KB(12bit) 約 34 回

サンプリング周波数の違いとその影響

STEMLab125-14 は 125MHz、SIGNALLab250-12 は 250MHz でサンプリングを行います。サンプリング周波数はレーダシステム全体の性能に大きく影響しますが、ここでは FPGA 実装における技術的制約について説明します。

高いサンプリング周波数は同じ時間でより多くのデータを生成するため、データ処理とストレージに大きな影響を与えます。特に生データ出力では、microSD 容量の制限やネットワーク転送時のスループットがシステムのボトルネックとなる可能性があります。

SIGNALLab250-12 は基本的に STEMLab125-14 より高性能ですが、250MHz の高速クロックにより素子の電気的特性の考慮やタイミング制御がより厳しくなり、実装の複雑度が増加します。さらに、SIGNALLab250-12 は内部で 250MHz と 125MHz の二つのクロックドメインを使用するため、クロックドメイン間の信号同期を考慮した設計が必要となります。

これらの違いにより、250-12 と 125-14 では大幅に異なる FPGA コードが必要となり、同じ機能を実装する場合でもそれぞれ個別の開発が必要です。

STEMLab125-14 と SIGNALLab250-12 の違いのまとめ

両デバイスの主な違いは、前述のとおり SoC と ADC の仕様にあります。ハードウェア筐体の設計では、SIGNALLab250-12 の方が冷却性能に優れた構造となっており、長時間運用時の安定性が高いと考えられます。一方、STEMLab125-14 は小型軽量で取り回しが良いため、ドローンの搭載にはこちらのほうが適しているでしょう。また、STEMLab125-14 は基板が露出しますが、物理的なスイッチへの直接アクセスが可能です。

実装複雑度の高い SIGNALLab250-12 を先行開発し、その後 STEMLab125-14 への移植を行う方針で進めています。

FPGA 実装の改修の要点

元の RedPitaya コードの制約とその対応

RedPitaya の標準スコープコードは汎用性が高く、トリガ設定や API による高レベルプログラミングに対応していますが、一回限りのデータ取得しか実行できません。アイスレーダシステムに必要な連続計測を実現するためには、HDL コードの根本的な書き換えが必要でした。

現在のコードでは以下の機能を実装しています。

  • 計測完了後、自動的にトリガ待ち状態に戻る機能(連続計測対応)
  • 取得データの BRAM 効率保存機能
  • ノイズ除去と S/N 比向上のための積算処理機能

外部トリガと ASG トリガのデバウンスについて

重要: 外部トリガ(trig_ext_i)と ASG トリガ(trig_asg_i)には500μs のデバウンス処理が実装されており、これが連続測定の処理時間に大きく影響します。

デバウンス処理の詳細

外部トリガと ASG トリガは以下のデバウンス処理を経ます:

  1. デバウンス時間: set_deb_len = 62,500 @ 125MHz = 500μs
  2. 動作: トリガー検出後、500μs 間は次のトリガーを無視
  3. 目的: 物理的なスイッチのチャタリングやアナログ信号のノイズ除去
if ((ext_trig_debp == 20'h0) && (ext_trig_in[1] && !ext_trig_in[2]))
   ext_trig_debp <= set_deb_len ; // ~0.5ms
else if (ext_trig_debp != 20'h0)
   ext_trig_debp <= ext_trig_debp - 20'd1 ;

高速化の選択肢

  1. デバウンス時間の短縮(観測プログラムで設定変更):
// observe.c内で設定変更
write_reg(mem, 0x90, 10);  // 10クロック = 80ns@125MHz
  1. アナログトリガーの使用:
  2. ADC A/B チャンネルトリガー(TRIG_SRC_CHB等)
  3. デバウンス処理なし、即座にエッジ検出

外部からのクリーンなデジタル信号(ファンクションジェネレータ等)使用時は、デバウンス時間を大幅に短縮しても問題ありません。ただし、レーダーシステムでの反射波検出等、物理現象に依存する場合は適切なデバウンス時間の設定が重要です。

連続計測のための再 ARM の仕組み

RedPitaya の標準コードは一回限りの測定しか実行できませんが、アイスレーダシステムでは連続的な測定が必要です。この機能を実現するため、自動再 ARM 機構を実装しています。

標準コードとの違い

標準 RedPitaya コード:

  1. PS(プロセッサ)からadc_arm_doパルスで測定開始
  2. トリガー検出 → データ取得 → 測定完了
  3. 再測定には PS 側からの明示的な ARM 操作が必要

改修後のコード:

  1. 最初の測定開始は同じ
  2. 測定完了後、FPGA 内部で自動的に次の測定準備
  3. PS 側の介入なしに連続測定が可能

実装の詳細

REARM_DELAY 機構(red_pitaya_scope-250-12-sum-128-20.v: line 490-541):

parameter REARM_DELAY_COUNT = 48000;  // 192μs@250MHz

// 測定完了検出
always @(posedge adc_clk2d_i) begin
    if (adc_dly_end) begin  // 測定完了時
        edge_detected <= 1'b1;
        dly_counter <= 16'd0;
    end else if (edge_detected) begin
        if (dly_counter < REARM_DELAY_COUNT - 1) begin
            dly_counter <= dly_counter + 1;
        end else begin
            rearm_pulse <= 1'b1;  // 48,000クロック後にパルス生成
            edge_detected <= 1'b0;
        end
    end
end

// 自動ARM生成
adc_arm_do <= (sys_wen && sys_wdata[0]) || rearm_pulse_sync;

動作シーケンス:

  1. 測定実行: データ取得+積分処理(実際の処理時間)
  2. REARM_DELAY: 48,000 クロック(192μs)の固定遅延
  3. rearm_pulse 生成: 内部でadc_arm_do相当のパルス発生
  4. 次の測定開始: 自動的にトリガー待ち状態へ

なぜ REARM_DELAY が必要か

  • データ取得完了からメモリ整理まで一定時間が必要
  • PS-FPGA 間の同期を確実にするためのマージン
  • 次の測定開始前の安定化時間

PS 側での制御:

// 最初のARM操作のみでOK
write_reg(mem, ARM_OFFSET, ARM_ENABLE);

// 以降は自動的に連続測定が継続
// 停止時のみ明示的なリセット
write_reg(mem, ARM_OFFSET, 0x2);  // adc_rst_do

FPGA 側の状態管理:

  • coh_completeフラグで PS 側に測定完了を通知
  • PS 側がデータ取得完了後、adc_rst_doで停止
  • 停止されるまで無限に連続測定を継続

この仕組みにより、一度 ARM 操作を行えば、PS 側の追加操作なしに高速な連続測定が実現されています。

積算処理の 4 段パイプライン

積算処理では、取得したデータを既存の BRAM 内容に加算して保存する必要があります。しかし、BRAM の物理的制約により、単純な read-modify-write 処理では 250MHz での動作が困難です。この問題を解決するため、4 段パイプラインを実装しています。

BRAM アクセスの制約

FPGA 内 BRAM の制約:

  • 同一アドレスに対する同時読み書きは不可
  • 読み出しレイテンシ:通常 1 クロック
  • 高速クロック(250MHz)では読み出しから書き戻しまでの時間が不足

素直な実装の問題:

// これは動作しない例
always @(posedge clk) begin
    old_data <= bram[addr];          // クロック1で読み出し
    new_data <= old_data + input;    // クロック2で加算
    bram[addr] <= new_data;          // クロック3で書き戻し
end

→ 読み出しと書き戻しのタイミング競合により正常動作しない

4 段パイプライン設計

実装されたパイプライン(red_pitaya_scope-250-12-sum-128-20.v: line 415-449):

parameter ACC_ADDR = 2'd0;  // アドレス設定
parameter ACC_READ = 2'd1;  // 読み出し
parameter ACC_ADD  = 2'd2;  // 加算処理
parameter ACC_WRITE = 2'd3; // 書き戻し

always @(posedge adc_clk_i) begin
    case (acc_step)
        ACC_ADDR: begin
            // ステージ1: BRAMアドレス設定
            bram_addr <= phase_addr;
            acc_step <= ACC_READ;
        end

        ACC_READ: begin
            // ステージ2: データ読み出し(1クロック待機)
            prev_data <= sum_store[bram_addr];
            new_data <= temp_store[phase_addr];
            acc_step <= ACC_ADD;
        end

        ACC_ADD: begin
            // ステージ3: 積算計算
            sum_data <= prev_data + new_data;
            acc_step <= ACC_WRITE;
        end

        ACC_WRITE: begin
            // ステージ4: 結果をBRAMに書き戻し
            sum_store[bram_addr] <= sum_data;
            // 次のアドレスまたはフェーズ遷移
        end
    endcase
end

処理効率:

  • 8,191 データポイント × 4 段 = 32,764 クロック
  • 250MHz で約 131μs(理論値)
  • 単純実装より確実な動作を実現

メモリアクセスの分離:

  1. 読み出しフェーズで既存データ取得
  2. 演算フェーズで加算処理(BRAM アクセスなし)
  3. 書き込みフェーズで結果保存
  4. アドレス更新で次の処理準備

実装上の注意点

タイミング制約:

  • 各段階で 1 クロック確実に待機
  • BRAM の読み出しレイテンシを考慮
  • 書き込み完了を待ってから次のアクセス

状態管理:

// 4段パイプラインでは状態遷移が重要
if (phase_addr < CYCLE_DATA_POINT_MAX) begin
    phase_addr <= phase_addr + 1;
    acc_step <= ACC_ADDR;  // 次のデータへ
end else begin
    phase <= PHASE_WAIT;   // 全データ処理完了
end

メモリ効率:

  • 積算用 BRAM(sum_store)と一時 BRAM(temp_store)の分離
  • 読み書き競合の回避
  • 高速クロックでの安定動作

この 4 段パイプライン設計により、BRAM の物理的制約下でも確実な積算処理が実現されています。ただし、パイプライン段数分だけ処理サイクルが増加するため、REARM_DELAY はこれを考慮した設定となっています。

階層構造が BRAM 処理に与える影響

FPGA 合成ツールでは、深いネスト構造を持つロジックがBRAM アクセスタイミングに悪影響を与える場合があります。これは配置配線最適化時の制約が原因で、論理的には正しいコードでも物理実装で問題が生じます。

ネスト構造による問題

合成ツールの制約:

  • 深い条件分岐は複雑な組み合わせロジックを生成
  • BRAM アクセス制御信号の遅延増加
  • 250MHz 高速クロックでのタイミング違反の原因

実際に発生した問題例:

// 深いネスト構造(問題のあるコード)
always @(posedge adc_clk_i) begin
    if (adc_rstn_i == 1'b0) begin
        // リセット処理
    end else begin
        if (phase == PHASE_ACCUMULATE) begin
            case (acc_step)
                ACC_ADDR: begin
                    if (some_condition) begin
                        if (another_condition) begin
                            // さらに深いネスト
                            sum_store[addr] <= data;  // ここでタイミング問題
                        end
                    end
                end
            endcase
        end
    end
end

→ BRAM への書き込みが失敗し、データ異常が発生

解決策:階層の簡素化

現在の実装では、深いネスト構造を避けるため、条件分岐の階層を意図的に浅く設計しています:

// 階層を浅く保った実装(現在のコード)
always @(posedge adc_clk_i) begin
    if (adc_rstn_i == 1'b0) begin
        // リセット処理(階層レベル1)
        phase <= PHASE_WAIT;
        cycle_count <= 0;
        coh_complete <= 0;
    end else begin
        case (phase)  // 階層レベル2
            PHASE_ACQUIRE: begin
                // データ取得処理(最大階層レベル3で制限)
                if (condition) begin
                    // 処理
                end
            end
            PHASE_ACCUMULATE: begin
                // 積算処理(最大階層レベル3で制限)
                case (acc_step)
                    // 4段パイプライン処理
                endcase
            end
        endcase
    end
end

PS 連携を前提とした制御設計

深いネスト構造を避けた結果、adc_rst_do信号を待ち受けるタイミングについて制約を課した設計になっています。これにより階層が簡素化される一方、PS 側は適切なタイミングでadc_rst_do信号を送信する必要があります。具体的には、coh_complete = 1後に、PS 側は必ずadc_rst_doを送信する必要があります。

observe.c でリセット信号を出力するコード:

// observe.c内での確実なリセット処理
while (running) {
    if (run_measurement(&bs_config, &measure_config)) {
        // 測定完了後、必ずリセット
        write_reg(mem, ARM_OFFSET, 0x2);  // adc_rst_do
    }
}

この設計により、複雑な条件分岐を避けながら、PS-FPGA 協調によるシステムを実現しています。