5. isochronous_spill_register.sv:等時性クロックドメイン間スピルレジスタ
基本設計方針
isochronous_spill_register.svは、等時性(isochronous)クロックドメイン間でデータを転送するためのスピルレジスタである。
等時性とは、2つのクロックドメインが同じクロック源から派生し、整数倍の関係にあることを意味する。
このモジュールは、2段のデュアルクロックFIFOとして実装されており、ソースクロックドメインとデスティネーションクロックドメインで異なるクロックを使用する。
パラメータ定義
module isochronous_spill_register #( /// Data type of spill register. parameter type T = logic, /// Make this spill register transparent. parameter bit Bypass = 1'b0 ) ( /// Clock of source clock domain. input logic src_clk_i, /// Active low async reset in source domain. input logic src_rst_ni, /// Source input data is valid. input logic src_valid_i, /// Source is ready to accept. output logic src_ready_o, /// Source input data. input T src_data_i, /// Clock of destination clock domain. input logic dst_clk_i, /// Active low async reset in destination domain. input logic dst_rst_ni, /// Destination output data is valid. output logic dst_valid_o, /// Destination is ready to accept. input logic dst_ready_i, /// Destination output data. output T dst_data_o );
等時性クロックドメインとは、以下の条件を満たすクロックドメインである:
- 同じクロック源から派生: ソースとデスティネーションのクロックは、同じ基準クロックから生成される
- 整数倍の関係: 一方のクロック周波数が他方の整数倍である(例: 2倍、1/2倍)
- 静的タイミング解析(STA)でカバー可能: クロック間のタイミング関係が既知であり、STAツールで解析可能
推奨されるSDC制約の例:
create_generated_clock dst_clk_i -name dst_clk -source src_clk_i -divide_by 2
2段FIFO実装
等時性スピルレジスタは、2段のメモリと読み書きポインタで構成される:
/// Read/write pointer are one bit wider than necessary. /// We implicitly capture the full and empty state with the second bit: /// If all but the topmost bit of `rd_pointer_q` and `wr_pointer_q` agree, the /// FIFO is in a critical state. If the topmost bit is equal, the FIFO is /// empty, otherwise it is full. logic [1:0] rd_pointer_q, wr_pointer_q; // Advance write pointer if we pushed a new item into the FIFO. (Source clock domain) `FFLARN(wr_pointer_q, wr_pointer_q+1, (src_valid_i && src_ready_o), '0, src_clk_i, src_rst_ni) // Advance read pointer if downstream consumed an item. (Destination clock domain) `FFLARN(rd_pointer_q, rd_pointer_q+1, (dst_valid_o && dst_ready_i), '0, dst_clk_i, dst_rst_ni) T [1:0] mem_d, mem_q; `FFL(mem_q, mem_d, (src_valid_i && src_ready_o), '0, src_clk_i, src_rst_ni) always_comb begin mem_d = mem_q; mem_d[wr_pointer_q[0]] = src_data_i; end assign src_ready_o = (rd_pointer_q ^ wr_pointer_q) != 2'b10; assign dst_valid_o = (rd_pointer_q ^ wr_pointer_q) != '0; assign dst_data_o = mem_q[rd_pointer_q[0]];
ポインタベースのフル/エンプティ検出
読み書きポインタは1ビット幅広く設計されており、最上位ビットを使用してフル/エンプティ状態を検出する:
- エンプティ状態:
rd_pointer_q == wr_pointer_q(最上位ビットを含むすべてのビットが一致) - フル状態:
rd_pointer_q[1] != wr_pointer_q[1]かつrd_pointer_q[0] == wr_pointer_q[0](最上位ビットのみが異なる)
この方式により、ポインタの比較のみでフル/エンプティ状態を判定でき、カウンタベースの実装よりも効率的である。
制約と注意事項
- 整数倍の関係: ソースとデスティネーションのクロックは整数倍の関係でなければならない
- STAカバレッジ: すべてのタイミングパスがSTAでカバーされている必要がある
- 同期化不要: 等時性クロックドメイン間では、グレイコード同期化などの特別な同期化機構は不要
- どちらのクロックが速くても可: ソースが速くても、デスティネーションが速くても動作する