インテル® Quartus® Prime プロ・エディションのユーザーガイド: デザインの推奨事項

ID 683082
日付 8/03/2023
Public
ドキュメント目次

1.6.2. クロックの多重化

クロックの多重化は、同じロジック機能を異なるクロックソースで動作させる場合に使用することがあります。 このタイプのロジックは、グリッチを引き起こし、それによって機能的な問題が発生する可能性があります。組み合わせロジックに固有の遅延もまた、タイミングの問題につながる可能性があります。クロックの多重化は、さまざまなデザイン規則チェックおよびタイミング解析ツールで警告が発行される原因となります。

ロジックの多重化を使用する代わりに、専用のハードウェアを使用して、可能な場合にクロックの多重化を実行します。例えば、特定のインテルFPGAデバイスで利用可能なクロックのスイッチオーバー機能またはクロック・コントロール・ブロックを使用することができます。これらの専用ハードウェア・ブロックでは、グリッチを回避し、グローバルな低スキュー配線ラインを使用することを保証します。また、クロックラインのロジック遅延によるデバイスのホールド時間の問題を避けることができます。インテルFPGAデバイスは、PLLのダイナミック・リコンフィグレーションもサポートします。これは、デバイスの動作時にクロックレートを変更する最も安全で堅牢な方法です。

デザインのクロックが多すぎてクロック・コントロール・ブロックを使用できない場合、またはダイナミック・リコンフィグレーションがデザインにおいて複雑すぎる場合は、クロック・マルチプレクサーをロジックセルに実装することができます。ただし、この実装を使用する場合は、入力の同時トグルを検討し、グリッチのない遷移を確保します。

図 3. 6入力LUTのシンプルなクロック・マルチプレクサー

各デバイスのデータシートには、LUTの機能とは別に、入力信号の同時トグル時にLUT出力がどのようにグリッチするかが記載されています。4:1のMUX機能はデータ入力の同時トグル時に検出可能なグリッチを生成しませんが、多重化ロジックのセル実装には大きなグリッチが発生するものもあります。よって、このクロック・マルチプレクサー構造は推奨されません。この実装の別の問題は、clk_select 信号が変化している際に出力が不規則に動作することです。この動作により、システムクロックから供給されているすべてのレジスターでタイミング違反が発生し、メタスタビリティーが発生する可能性があります。

より洗練されたクロック選択構造により、同時トグルと切り替えの問題を解消することができます。

図 4. グリッチのないクロック・マルチプレクサー構造

この構造は、任意の数のクロックチャネルに一般化することができます。このデザインでは、他のすべてのクロックが少なくとも数サイクル非アクティブになるまでどのクロックもアクティブにならず、クロックがLowの際にアクティブ化が発生することが保証されます。このデザインでは、synthesis_keep ディレクティブを右側のANDゲートに適用します。これにより、clk_out ORゲートの入力に同時トグルがないことを保証します。

注: クロック A からクロック B に切り替えるには、クロック A が少なくとも数サイクル動作し続ける必要があります。クロック A がすぐに停止すると、デザインは動かなくなります。この例では、選択信号は「ワンホット」コントロールとして実装されていますが、必要に応じて他のエンコーディングを使用することができます。入力側のロジックは非同期であり、重要ではありません。このデザインは、切り替えプロセス時の極端なグリッチを許容することができます。

Verilog HDLにおけるクロック多重化デザインでのグリッチ回避

この例は、Verilog-2001で機能します。

module clock_mux (clk,clk_select,clk_out);

	parameter num_clocks = 4;

	input [num_clocks-1:0] clk;
	input [num_clocks-1:0] clk_select; // one hot
	output clk_out;

	genvar i;

	reg [num_clocks-1:0] ena_r0;
	reg [num_clocks-1:0] ena_r1;
	reg [num_clocks-1:0] ena_r2;
	wire [num_clocks-1:0] qualified_sel;

	// A look-up-table (LUT) can glitch when multiple inputs 
	// change simultaneously. Use the keep attribute to
	// insert a hard logic cell buffer and prevent 
	// the unrelated clocks from appearing on the same LUT.

	wire [num_clocks-1:0] gated_clks /* synthesis keep */;

	initial begin
		ena_r0 = 0;
		ena_r1 = 0;
		ena_r2 = 0;
	end

	generate
		for (i=0; i<num_clocks; i=i+1) 
		begin : lp0
			wire [num_clocks-1:0] tmp_mask;
			assign tmp_mask = {num_clocks{1'b1}} ^ (1 << i);

			assign qualified_sel[i] = clk_select[i] & (~|(ena_r2 & tmp_mask));

			always @(posedge clk[i]) begin
				ena_r0[i] <= qualified_sel[i];    	
				ena_r1[i] <= ena_r0[i];    	
			end

			always @(negedge clk[i]) begin
				ena_r2[i] <= ena_r1[i];    	
			end

			assign gated_clks[i] = clk[i] & ena_r2[i];
		end
	endgenerate

	// These will not exhibit simultaneous toggle by construction
	assign clk_out = |gated_clks;

endmodule