Common Cellsライブラリには、ready/validハンドシェイクプロトコルに対応したレジスタの実装が5つ用意されている:
stream_register.sv: シンプルなストリームレジスタfall_through_register.sv: フォールスルー動作を持つレジスタspill_register.sv: 完全な組み合わせパス切断を行うスピルレジスタ(後方互換性ラッパー)spill_register_flushable.sv: フラッシュ機能付きスピルレジスタisochronous_spill_register.sv: 等時性クロックドメイン間用スピルレジスタ
5つの実装の比較
設計思想と用途の違い
| 実装 | 組み合わせパス切断 | フォールスルー | フラッシュ機能 | クロックドメイン | 用途 |
|---|---|---|---|---|---|
stream_register |
部分的 | なし | なし | 単一 | シンプルなパイプライン |
fall_through_register |
部分的 | あり | なし | 単一 | 低レイテンシが必要な場合 |
spill_register |
完全 | なし | なし | 単一 | 完全なパス切断が必要 |
spill_register_flushable |
完全 | なし | あり | 単一 | フラッシュ機能が必要 |
isochronous_spill_register |
完全 | なし | なし | 等時性複数 | クロックドメイン間転送 |
性能特性
レイテンシ:
fall_through_register: 最小(フォールスルー時は0サイクル)stream_register: 1サイクルspill_register系: 1〜2サイクル(データの流れに依存)isochronous_spill_register: クロック比に依存
スループット:
- すべての実装が、バックプレッシャーがない場合に最大スループットを達成可能
fall_through_registerは、出力側が常にreadyな場合に最高のスループットを提供
リソース使用量:
stream_register: 最小(1レジスタ)fall_through_register: 小(FIFOベースだがDEPTH=1)spill_register_flushable: 中(2レジスタ)isochronous_spill_register: 中(2段メモリ + ポインタ)
使用推奨
- シンプルなパイプライン:
stream_registerを使用 - 低レイテンシが必要:
fall_through_registerを使用 - 完全な組み合わせパス切断が必要:
spill_registerまたはspill_register_flushableを使用 - フラッシュ機能が必要:
spill_register_flushableを使用 - 等時性クロックドメイン間転送:
isochronous_spill_registerを使用
1. stream_register.sv:シンプルなストリームレジスタ
基本設計方針
stream_register.svは、ready/validハンドシェイクプロトコルに対応した最もシンプルなレジスタ実装である。
このレジスタは、すべての組み合わせパスを完全には切断しない。
特に、valid信号とdata信号には組み合わせパスが残る可能性がある。
パラメータ定義
module stream_register #( parameter type T = logic // Vivado requires a default value for type parameters. ) ( input logic clk_i, // Clock input logic rst_ni, // Asynchronous active-low reset input logic clr_i, // Synchronous clear input logic testmode_i, // Test mode to bypass clock gating // Input port input logic valid_i, output logic ready_o, input T data_i, // Output port output logic valid_o, input logic ready_i, output T data_o );
T: データ型(デフォルトはlogic)clk_i: クロック信号rst_ni: 非同期アクティブローリセットclr_i: 同期クリア信号testmode_i: テストモード(クロックゲーティングのバイパス用)
実装
logic reg_ena; assign ready_o = ready_i | ~valid_o; assign reg_ena = valid_i & ready_o; // Load-enable FFs with synch clear `FFLARNC(valid_o, valid_i, ready_o, clr_i, 1'b0 , clk_i, rst_ni) `FFLARNC(data_o, data_i, reg_ena, clr_i, T'('0), clk_i, rst_ni)
ready信号の生成
ready_o = ready_i | ~valid_o
この式は、以下の2つの条件のいずれかが満たされれば、入力側にreadyを返すことを意味する:
- 出力側がready:
ready_i = 1の場合、常にready_o = 1 - レジスタが空:
valid_o = 0の場合、常にready_o = 1
つまり、レジスタが空であるか、または出力側がデータを受け取る準備ができていれば、新しいデータを受け入れることができる。
レジスタイネーブル信号
reg_ena = valid_i & ready_o
レジスタは、入力側が有効なデータを提供し(valid_i = 1)、かつレジスタが受け入れ可能な場合(ready_o = 1)にのみ更新される。
レジスタ更新
valid_oレジスタ:ready_oが有効な場合にvalid_iをラッチdata_oレジスタ:reg_enaが有効な場合にdata_iをラッチ
組み合わせパスの問題
stream_registerは、以下の組み合わせパスを切断しない:
valid_i→ready_o(ready_o = ready_i | ~valid_oの計算にvalid_oが使用されるが、これはレジスタ出力)data_i→data_o(直接的なパスはないが、reg_enaの計算にready_oが使用され、これはvalid_oに依存)
完全な組み合わせパス切断が必要な場合は、spill_registerを使用する必要がある。