同期リセットを利用する fpga 設計があります (他の場所で説明した理由により、非同期リセットよりも同期リセットを好みます)。デザインには 4 つの異なるクロック ドメインがあり、1 つのボタンを使用してリセット信号を生成しています。4 つのクロック ドメインのそれぞれでボタン信号をデバウンスして、1 つのソースから 4 つのドメインの同期リセットを生成します。私のデバウンス モジュールは基本的に、アサートされているリセット ボタンの N クロック サイクルをカウントします。リセットがアサートされた状態で N サイクル以上が経過した場合は、リセット信号を生成します (このモジュールのコードを以下に貼り付けます)。
最初の質問 - この方法よりもリセットを生成する良い方法はありますか?
2 つ目 (さらに興味深い質問): タイミング レポート (ザイリンクス ツールを使用) を見ると、一貫して制限信号がすべてリセット関連であることがわかります。たとえば、制限パスは、リセット ジェネレーター (デバウンサー) からステート マシンのステート レジスタまでです。リセット信号は非常にファン アウトが大きくなります (それぞれのクロック ドメイン内のすべてに影響します)。リセットによって速度が制限されていることに少し驚いています。~50% がルーティングで ~50% がロジックである 8.5 nS のようなものに制限されていることがわかりました。これを少し改善する方法について何か提案はありますか? fpga 設計で同期リセット生成をどのように処理しますか?
リセット生成のコードは次のとおりです。信号リセット信号は、デバウンスされた出力に似ていることに注意してください (たとえば、モジュールをインスタンス化すると、debounced
出力はその特定のクロック ドメインのリセットになります)。
module button_debouncer(/*AUTOARG*/
// Outputs
debounced,
// Inputs
clk, button
);
/* Parameters */
parameter WIDTH = 1;
parameter NUM_CLKS_HIGH = 12000000;
parameter log2_NUM_CLKS = 24;
/* Inputs */
input clk;
input [WIDTH-1:0] button;
/* Outputs */
output [WIDTH-1:0] debounced;
/* Regs and Wires */
reg [WIDTH-1:0] b1, b2;
reg [log2_NUM_CLKS-1:0] counter;
/* Synched to clock domain */
always @(posedge clk) begin
b1 <= button;
b2 <= b1;
end
/* Debounce the button */
always @(posedge clk) begin
if(~b2)
counter <= 0;
else if(counter < {log2_NUM_CLKS{1'b1}})
counter <= counter + 1;
end
/* Assign the output */
//wire [WIDTH-1:0] debounced = counter > NUM_CLKS_HIGH;
reg [WIDTH-1:0] debounced;
always @(posedge clk) begin
debounced <= counter > NUM_CLKS_HIGH;
end
endmodule //button_debouncer