3. spill_register.sv:後方互換性ラッパー
基本設計方針
spill_register.svは、spill_register_flushableのラッパーモジュールであり、後方互換性を維持するために提供されている。
flush_i信号を常に1'b0に固定して、フラッシュ機能なしのスピルレジスタとして動作する。
実装詳細
module spill_register #( parameter type T = logic, parameter bit Bypass = 1'b0 // make this spill register transparent ) ( input logic clk_i , input logic rst_ni , input logic valid_i , output logic ready_o , input T data_i , output logic valid_o , input logic ready_i , output T data_o ); spill_register_flushable #( .T(T), .Bypass(Bypass) ) spill_register_flushable_i ( .clk_i, .rst_ni, .valid_i, .flush_i(1'b0), .ready_o, .data_i, .data_o, .valid_o, .ready_i, .data_o ); endmodule
flush_iを1'b0に固定することで、フラッシュ機能を無効化している。
実際の動作はspill_register_flushableに委譲されるため、詳細は次節を参照。
4. spill_register_flushable.sv:フラッシュ可能なスピルレジスタ
基本設計方針
spill_register_flushable.svは、完全に組み合わせパスを切断するスピルレジスタの実装である。
AレジスタとBレジスタの2段構成により、入力と出力の間のすべての組み合わせパスを確実に切断する。
さらに、flush_i信号により、レジスタ内のデータを強制的にクリアすることができる。
パラメータ定義
module spill_register_flushable #( parameter type T = logic, parameter bit Bypass = 1'b0 // make this spill register transparent ) ( input logic clk_i , input logic rst_ni , input logic valid_i , input logic flush_i , output logic ready_o , input T data_i , output logic valid_o , input logic ready_i , output T data_o );
T: データ型Bypass: バイパスモード(1の場合、レジスタをバイパスして直接接続)
2段レジスタ構成
スピルレジスタは、AレジスタとBレジスタの2段構成で実装されている:
// The A register. T a_data_q; logic a_full_q; logic a_fill, a_drain; always_ff @(posedge clk_i or negedge rst_ni) begin : ps_a_data if (!rst_ni) a_data_q <= T'('0); else if (a_fill) a_data_q <= data_i; end always_ff @(posedge clk_i or negedge rst_ni) begin : ps_a_full if (!rst_ni) a_full_q <= 0; else if (a_fill || a_drain) a_full_q <= a_fill; end // The B register. T b_data_q; logic b_full_q; logic b_fill, b_drain; always_ff @(posedge clk_i or negedge rst_ni) begin : ps_b_data if (!rst_ni) b_data_q <= T'('0); else if (b_fill) b_data_q <= a_data_q; end always_ff @(posedge clk_i or negedge rst_ni) begin : ps_b_full if (!rst_ni) b_full_q <= 0; else if (b_fill || b_drain) b_full_q <= b_fill; end
各レジスタには、データを保持する*_data_qと、レジスタが満杯かどうかを示す*_full_qの2つのフリップフロップがある。
制御ロジック
// Fill the A register when the A or B register is empty. Drain the A register // whenever it is full and being filled, or if a flush is requested. assign a_fill = valid_i && ready_o && (!flush_i); assign a_drain = (a_full_q && !b_full_q) || flush_i; // Fill the B register whenever the A register is drained, but the downstream // circuit is not ready. Drain the B register whenever it is full and the // downstream circuit is ready, or if a flush is requested. assign b_fill = a_drain && (!ready_i) && (!flush_i); assign b_drain = (b_full_q && ready_i) || flush_i; // We can accept input as long as register B is not full. // Note: flush_i and valid_i must not be high at the same time, // otherwise an invalid handshake may occur assign ready_o = !a_full_q || !b_full_q; // The unit provides output as long as one of the registers is filled. assign valid_o = a_full_q | b_full_q; // We empty the spill register before the slice register. assign data_o = b_full_q ? b_data_q : a_data_q;
Aレジスタの制御
a_fill: AレジスタまたはBレジスタが空で、かつフラッシュが要求されていない場合に、入力データをAレジスタに格納a_drain: Aレジスタが満杯でBレジスタが空の場合、またはフラッシュが要求された場合に、AレジスタからBレジスタへデータを転送
Bレジスタの制御
b_fill: Aレジスタからデータが転送されたが、出力側がreadyでない場合に、Bレジスタにデータを格納b_drain: Bレジスタが満杯で出力側がreadyな場合、またはフラッシュが要求された場合に、Bレジスタからデータを出力
出力信号の生成
ready_o: AレジスタまたはBレジスタのいずれかが空であれば、入力を受け入れることができるvalid_o: AレジスタまたはBレジスタのいずれかが満杯であれば、有効なデータを出力できるdata_o: Bレジスタが満杯の場合はb_data_qを、そうでない場合はa_data_qを出力
フラッシュ機能
flush_iが有効な場合、AレジスタとBレジスタの両方が強制的にドレインされる:
assign a_fill = valid_i && ready_o && (!flush_i);
assign a_drain = (a_full_q && !b_full_q) || flush_i;
// Fill the B register whenever the A register is drained, but the downstream
// circuit is not ready. Drain the B register whenever it is full and the
// downstream circuit is ready, or if a flush is requested.
assign b_fill = a_drain && (!ready_i) && (!flush_i);
assign b_drain = (b_full_q && ready_i) || flush_i;
組み合わせパス切断の保証
2段レジスタ構成により、以下の組み合わせパスが確実に切断される:
valid_i→ready_o:ready_oはa_full_qとb_full_qのみに依存(レジスタ出力)data_i→data_o: データは必ずAレジスタまたはBレジスタを経由ready_i→ready_o:ready_oはa_full_qとb_full_qのみに依存