01signal.com

FPGA上のAsynchronous resets : 多くの人が信じているほど簡単ではない

このページは、 FPGAsにおける resetsに関する 3 つのシリーズの最初のページです。非常に多くの人が asynchronous resets を実際には期待どおりに動作しないことを知らずに使用しているため、この最初のページでは、トピック全体が思ったほど簡単ではない理由を説明します。

reset は本当に動作しますか?

state machineをリセットするための次の例を検討してください。これは間違っています。

always @(posedge clk or negedge resetn)
     if (!resetn)
       state <= ST_START;
     else
       case (state)
	 ST_START:
	   begin
	      state <= ST_NEXT;
	      [  ... do some stuff maybe? ... ]
	   end

	 ST_NEXT:
	   begin
	      [ ... do something ... ]
	   end
       endcase

では、 reset の何が問題なのか、疑問に思われるかもしれません。これはまさに教科書に載っている通りです! @state を実装した register を初期状態にする active low asynchronous reset。何が問題になる可能性がありますか?

説明のために、 @resetn 信号自体は問題ないと仮定しましょう。つまり、 pushbutton などに直接接続されていません。 reset 信号を生成するように設計された chip が使用されたか、 reset が FPGAによって内部的に生成された可能性があります。いずれにせよ、 reset が安定した方法でアクティブになり、十分な時間アクティブであり続け、その後非アクティブになると仮定します。まだ間違っています。

そして、私が間違っていると言うとき、明確な理由もなく FPGA がときどきおかしな動作をするような間違いを意味します。

だから問題は何ですか?まあ、 reset は十分に長くアクティブなので、 @state を確実に初期状態に戻します。しかし、非アクティブになった場合 (つまり、上記の例で '1' に戻った場合) はどうなるでしょうか?その時、関連する flip-flops が @clkの rising edges に応答し始めるはずです。

ただし、 flip-flop が reset 信号から回復し、 rising clock edgesで data input のサンプリングを開始するには、少し時間がかかります。また、 reset は定義上非同期であるため、 @clkに関連していつでも非アクティブ化される可能性があります。

@clk の最初の rising edge が resetの非アクティブ化後すぐに到着した場合、 flip-flop はこの rising edgeを無視します。 @clk に接続されているすべての flip-flops がそれを行う場合、それはまったく問題ありません。しかし、すべての flip-flops がまったく同じというわけではなく、 clock edge を他のものより少し早く取得するものもあれば、 reset の非アクティブ化を他のものより遅く取得するものもあります。

正直なところ、この説明は少し単純化されています。問題のより正確なビューについては、 timingの基本を説明するページの Recovery および Removal に関する部分を参照してください。

したがって、これは次のようになります。 運が悪いと、 reset が clockの rising edgeの近くで非アクティブになり、一部の flip-flops が最初の rising edgeに応答し、他の flip-flops がそれを無視する場合があります。実際、一部の flip-flops では、何をすべきかを決定するのに余分な時間がかかる場合があります。 flip-flops の違いを同じ chip のせいにするか、 clock skew と reset skewのせいにする: 肝心なのは、一部の flip-flops は他の clock cycle よりも 1 つ進んでいるということです。

これがいかに悪いことかを理解するために、上記の例を考えてみてください。 synthesizer がこれが state machineであると認識した場合、 one-hot encodingで state variable を実装する可能性が高くなります。つまり、 stateごとに single-bit register を割り当てます。これらの registers のそれぞれは、 state machine が関連する stateにある場合にアクティブになります。 synthesizer が、 ST_STARTという名前の state には hot_state_0 という名前の register を割り当て、 ST_NEXTには hot_state_1 を割り当てたとしましょう。明らかに、 reset は hot_state_0 をアクティブにし、 hot_state_1を非アクティブにします。

ここで、 state machine が無条件に ST_START から ST_NEXTに移動することに注意してください。したがって、 reset が解放された後、最初の clock で hot_state_0 が非アクティブになり、 hot_state_1 がアクティブになります。

しかし、 reset が不運なタイミングで非アクティブになり、一部の flip-flops が最初の clock edge を逃し、他の flip-flops が逃さない場合はどうなるでしょうか? 1 つの可能性は、 hot_state_0 が最初の clockを見逃しているが、 hot_state_1 がそれに応答することです。その結果、両方がアクティブになります。これは、 one-hot encodingでは不正な状態です。逆の場合、両方の registers が非アクティブになるため、実際には state machine のすべての one-hot registers が非アクティブになります。いずれにせよ、 state machine は合法的な状態に回復できない可能性があります。

これは実際にはどのように見えるでしょうか?もちろんアプリケーションによって異なりますが、 reset を FPGA に再度適用するまで、何かが正しく機能しない可能性があります。この問題はランダムに発生し、必ずしも頻繁に発生するとは限らないため、この動作の理由を見つけることは非常に困難な場合があります。また、 FPGA design の compilation とは異なる動作をする可能性が高く、エレクトロニクスのボードごとに異なる可能性があります。要するに、それはあなたを狂わせることができる種類のバグです。問題の原因はこのディスカッションのトピックであるため、このディスカッションではそれほど悪くないように聞こえるかもしれません。しかし、このような不安定性が実際に発生すると、それは何にでもなる可能性があり、 FPGA に取り憑かれているように感じることがよくあります。

しかし、私はこれを常に行っており、うまくいきます!

それはそう。ほとんどの場合、一部の flip-flops が resetの後の最初の clock を見逃しても、それほど問題にはなりません。

上記の state machine の例が失敗する主な理由は、最初の clock cycleで初期状態のままになるためです。実際の designs のほとんどの state machines には、初期状態から離れる規則があるため、最初の数回の clock cyclesでは常にこの状態のままです。したがって、この間違いを回避できます。

しかし、ここに別の例があります。シンプルな counter:

reg [15:0] counter;

   always @(posedge clk or negedge resetn)
     if (!resetn)
       counter <= 0;
     else
       counter <= counter + 1;

この場合、 @counter は 16 個の flip-flopsで構成されます。これらの flip-flops のそれぞれは、 data inputで次の clock cycle のカウンターの値を受け取り、 asynchronous reset inputで @resetn のカウンターの値を受け取ります。

@resetn がアクティブな場合、 @counter は値 0 を取得し、次の clock cycle のカウンターの値は 1 です。したがって、 counter[0] を除くすべての flip-flops は、最初の clock edge を逃したかどうかにかかわらず、ゼロのままです。したがって、どちらの方法でも正しくカウントを開始します。このようなコードが書かれているほとんどの場合、カウンターが最初の clock cycle を逃したかどうかは問題ではありません。

ただし、これは別の話です。

reg [15:0] counter;

   always @(posedge clk or negedge resetn)
     if (!resetn)
       counter <= 0;
     else
       counter <= counter - 1;

小さな違いですが、大きな違いがあります。 カウンターがゼロから始まり、カウントダウンする場合、次の clock cycle でのカウンターの値は 0xffffです。つまり、すべての flip-flops は、 resetの後の最初の clock で値を変更する必要があります。したがって、 resetの後の最初の clock edge に応答する人もいれば、応答しない人もいる場合、カウンターは実質的に任意のランダムな値から開始できます。

しかし、値ゼロでカウンターをリセットしてからカウントダウンするのは誰でしょうか?

したがって、より現実的な例を次に示します。 logic を clockの周波数が半分に減少したかのように動作させる clock enable 信号 (したがって、必要に応じて multi-cycle path を許可します):

reg en;

   always @(posedge clk or negedge resetn)
     if (!resetn)
       en <= 0;
     else
       en <= !en;

   always @(posedge clk)
     if (en)
       [ ... do something ... ]

ここでは何も問題がないと考えることができます。 clock enable、 @en、 register単体なので、いつトグルし始めても大差ないのか…?問題は、 clock enable 信号は fan-outが高くなる傾向があるため、 synthesizer は fan-outの制限を超えないようにそれを複製する可能性があるということです。

Vivado synthesizer を使用した私の逸話的な実験では、 @en を実装した複製された registers のそれぞれが、独自の output signalに依存していることが示されました。言い換えれば、すべての flip-flops が次の output を決定するために使用する信号は 1 つもありませんでした。むしろ、 clockの rising edge で常に値を変更する多くの独立した flip-flops がありました。したがって、これらの flip-flops が同じ clock cycleでトグルを開始しない場合、それらの outputs は無期限に異なるままになります。

このような事故が発生した場合、 logic は完全に故障する可能性があります。したがって、 asynchronous resetに固執する場合は、少なくともすべての clock enables が単一のソースに依存していることを確認してください。

reg pre_en; // Apply some don't-touch synthesis directive on this
   reg en;

   always @(posedge clk or negedge resetn)
     if (!resetn)
       pre_en <= 0;
     else
       pre_en <= !pre_en;

   always @(posedge clk or negedge resetn)
     if (!resetn)
       en <= 0;
     else
       en <= pre_en;

   always @(posedge clk)
     if (en)
       [ ... do something ... ]

トリックは、 @pre_en が次の値を決定する register であるということです。 flip-flop には低い fan-out があり、 synthesizer に改ざんしないように指示する何らかの属性がある可能性があります。このように、確かに register単体です。 @en を実装するすべての flip-flops は @pre_enに依存しているため、次の clockでの @en の値にすべて同意します。 resetの後の最初の clock に関しては、最初の clock cycle の @en の値がとにかくゼロであるため、 flip-flopsの一部がそれを見逃しても問題ありません。

要するに、 asynchronous reset を誤って使用しても通常は問題ないということです。これは主に、 logic が clockと比較して reset が非アクティブになるタイミングの不確実性に対して通常は寛容であるためです。それにもかかわらず、不注意に asynchronous resets を適用すると、時折不正な動作が発生する可能性があり、これを解決するのは非常に困難です。

reset と clockの間で timing constraint を使用する

resetの非アクティブ化と clockの rising edge の間の不確実なタイミング関係を回避する一見明白な方法は、 reset 信号で timing constraint を使用することです。ただし、そうすることで、 reset 信号は同期になります。

しかし、どの clockと同期しますか? logic design全体に対して 1 つのグローバル asynchronous reset があると便利なことがよくあります。この reset は、1 つの特定の clockと同期している logic で作成されます。この reset を、別の clockと同期している logic と共に使用すると、 clock domain crossingになります。これはそれ自体がトピックですが、最も重要な点は、関連する pathsでツールが timing を無視する可能性があることです。

したがって、 asynchronous resets で timing constraints を使用するための出発点は、 clockごとに個別の asynchronous reset が必要であるということです。または、どうしても related clocksのグループごとに別の asynchronous reset を使用することをお勧めします。そうでなければ、 timing constraintには意味がありません。奇妙に聞こえるかもしれませんが、それは asynchronous reset が非同期ではなくなったためです。

Verilog コードが asynchronous reset のパターンを使用しているという事実は、違いはありません。 flip-flopの asynchronous reset input が使用されているかどうかも、 flip-flop が reset input を非同期と見なすように構成されているかどうかも問題ではありません。 reset が clockと同期しており、 timing constraint が使用されている場合、 reset は実質的に同期しています。この場合、 Verilog パターンを直接使用することを検討してください。

always @(posedge clk)
     if (!resetn)
       state <= ST_START;
[ ... ]

とはいえ、 timing closureでのIntelの Youtube ビデオでは、 clockと同期する asynchronous resets の使用が推奨されており、 timing constraints も使用する必要があります。 asynchronous reset の選択は、 FPGAで global routing 専用のリソースを利用するためのものです。特に大規模な FPGAsでは、 global routing でもかなりの delayを使用できるため、これは非常に奇妙です。しかし、これが理にかなっているシナリオがいくつかあることは確かです。

実際には、 asynchronous reset が効果的に同期している場合でも、 asynchronous reset を使用し続ける別の理由があります。これについては、次のページで説明します。 これにより、 reset 信号のアクティベーションを非同期的に伝播できます。これは、 ASICsのテストだけでなく、シミュレーションにも役立ちます。

同期された asynchronous reset でこの方法を使用する場合、 flip-flopsの asynchronous reset inputsに接続するすべての signal paths で timing constraint が強制されるようにすることが重要です。 reset が、宛先の flip-flopと同じ clock と同期している flip-flop によって生成されるという事実は、それらの間の path が時間調整されていること自体を保証しません。デフォルトでは、一部の timing ツールは asynchronous inputsで終わる path を無視するため、この強制を明示的に有効にする必要がある場合があります。これらの paths が実際に timing constraintsでカバーされていることを timing reports で確認してください。これに落ちるのは簡単です。

これで、 resetsに関するこのシリーズの最初のページを終了します。次のページでは、 resets のさまざまなオプションとFPGA の初期化について説明します

このページは英語から自動翻訳されています。 不明な点は元のページを参照してください。
Copyright © 2021-2024. All rights reserved. (6f913017)