構成要素:D flip-flop
同期設計のすべてが1つの小さなハードウェア、D flip-flopに戻ります。クロック入力、データ入力、データ出力を持ちます。各クロック立ち上がりエッジでDの値を捕捉し、次のエッジまで保持します。それだけです。
Verilogでは:
always @(posedge clk) begin
q <= d;
end
3行、1つのflip-flop。<=は非blockingで、これがまさに実際のflip-flopの振る舞いです(Blocking vs Non-blockingで扱いました)。posedge clk感応性が順序を作ります。
組み合わせロジックを挟んで多数を積み重ねれば、構築したい任意の同期回路ができます。
reset付きregister
実際の設計には常にresetが必要です。電源投入時や要求時にシステムを既知のstateにする方法:
これは 同期reset です。reset条件が他の入力と同様にクロックエッジで評価されます。合成ツールはデータ入力に2-to-1 muxを持つflip-flopを生成します。resetが高のときmuxはゼロを、そうでないときはdを供給します。
ほとんどの設計では、同期resetが正しい選択です。タイミングがシンプルで、FPGAとうまく付き合い、reset signalはどこから来ても構いません - 専用のクロック整列ソースは不要です。
イネーブル付きregister
時に、何かが指示したときだけ更新するregisterが欲しくなります。クロック同期ブロック 内 でifを使い、欠落したelseの暗黙の「前の値を保持」動作に頼ります:
これが定番の「ロードイネーブル付きregister」です。あちこちに登場します。設定register、下流が準備できたときだけ進むパイプラインステージ、一時停止と再開するカウンタ。最後のelseの省略はクロック同期ブロック内では意図的かつ安全です。flip-flopはすでに前の値を覚えているので、「何もしない」は「保持」を意味します。
組み合わせブロックで同じコードはラッチを推論します。異なるルール、同じ構文。
カウンタ
カウンタは、次の値が現在値プラス1のregisterです:
カウンタはenableが高のときすべてのクロックサイクルでインクリメントします。16サイクル後、0にラップして戻ります(4ビットと宣言し、15 + 1は0にオーバーフローするから)。そのラッピングはNビット算術に内在し、実ハードウェアカウンタの振る舞いそのものです。
Shift Register
flip-flopを積み重ねるとshift registerになります。コツは、すべてのシフトを1つの非blocking文で行うことです:
本体はout <= {out[WIDTH-2:0], in} - 現在のoutの下位ビットと新しいinを連結し、全体を代入します。非blockingなので、右辺は左辺が更新する前に 古い outを読みます。効果は1クロックサイクルでのきれいなNビットシフトです。
これはshift registerパターンの最小形です。LFSR、シリアル送信器、デシリアライザ、データがクロックごとにflip-flopチェーンを通って動くあらゆる設計に一般化します。
パイプライン
パイプラインは、組み合わせロジックで分離されたregisterのチェーンです。各ステージは前のステージのデータを処理し、次のステージに供給します:
3ステージ、3サイクルのレイテンシ、しかしパイプラインが満ちれば1サイクルごとに新しい結果。データは3つのflip-flopを通るのでレイテンシは3クロック、3ステージすべてが異なる入力で同時に動くのでスループットは1演算/クロックです。
これが高性能設計がスループット目標を達成する方法です。ステージを短く保ち、より深くパイプライン化し、並列処理に仕事をさせます。
非同期reset(必要なときに)
resetをアサートするのにクロックエッジを待てない場合があります。チップが電源オフされている、クロックがゲートされている、外部ウォッチドッグが線を引っ張っている。その場合:
always @(posedge clk or negedge reset_n) begin
if (~reset_n) q <= 0;
else q <= d;
end
感応リストにクロックエッジ と resetエッジの両方があります。flip-flopはどちらにも即座に反応します。reset_nは慣例によりactive-low(低のときアサート)なので、テストが~reset_nです。
非同期resetにはトレードオフがあります。タイミング解析が難しく、解除時に注意深く扱わないとメタステーブルが起こり、すべてのFPGAアーキテクチャでポータブルではありません。デフォルトで同期resetを使い、設計が要求するときだけasyncを使ってください。
次に読むもの
これで任意の同期データパスを構築できます。次のドキュメント有限状態機械は、クロック同期registerとcase文を組み合わせて標準FSM慣用句を生成します。すべてのコントローラ、プロトコルエンジン、デジタル設計の意思決定ブロックの主役です。
よくある質問
Verilogのクロック同期ロジックとは?
更新がクロックsignalでゲートされるロジック。標準慣用句はalways @(posedge clk) target <= next_value;で、clkの各立ち上がりエッジでtargetがnext_valueを捕捉します。その1行がハードウェアのflip-flopを記述します。組み合わせロジックを挟んで多数を積み重ねれば、カウンタ、shift register、パイプライン、つまりあらゆる同期設計を構築できます。
Verilogの同期resetと非同期resetの違いは?
同期resetはalways @(posedge clk) if (reset) ...を使い、resetは他の入力と同様クロックエッジでサンプルされます。非同期resetはalways @(posedge clk or negedge reset_n) if (~reset_n) ...を使い、ブロックはクロックエッジまたはresetアサートのどちらかで起動するので、resetが即座に効きます。同期がデフォルトの選択で、非同期はクロックが死んでいてもresetが効くことが保証されなければならないときに使います。
Verilogでパイプラインを構築するには?
always @(posedge clk) stageN_reg <= stageN_combinational;の複数ステージを積み重ねます。各ステージの組み合わせロジックが次のステージのregisterに供給され、すべてのregisterが同じクロックエッジで捕捉します。結果は、毎サイクル新しいデータが入り、Nサイクル後に出てくるパイプラインで、クロックごとに1結果のスループットです。
Verilogのshift registerとは?
各flip-flopの出力が次のflip-flopの入力に供給されるflip-flopのチェーンです。各クロックエッジですべてのビットが1位置シフトします。Verilogの定番版は非blocking代入を使います:out <= {out[N-2:0], in};。その1行で、inから毎サイクル1ビットを取るNビットshift registerを作ります。