1

フリップフロップの代わりにラッチが推論される理由を誰かに説明してもらえますか?

always_ff @ (posedge clk, negedge rst) 
begin
  if (!rst)
    a <= '0;
end

常にブロックが信号エッジに敏感であるという事実は、フリップフロップを推測するのに十分ではありません。この場合、リセットの負のエッジがトリガーされると、0 が取得されます。それ以外の場合は、以前の値が保持されます。

この質問は、このstackoverflowの質問から選択された最良の回答から来ています:
System Verilog always_latch vs. always_ff

================================================== =========================

これまでにわかったことをここで共有します。これがフリップフロップではなくラッチに合成される理由は、割り当ての右側が定数であるためです。この場合、ラッチとフリップフロップの動作は同等です。これは、信号エッジで入力値をキャッチするか (フリップフロップ)、入力としてラッチが有効になっている間 (ラッチ) に入力値をキャッチするかは問題ではないためです。変わりません。したがって、合成ツールは、より少ないリソースを使用する要素、つまりラッチを選択します。

一方、割り当ての右側に VARIABLE がある場合、入力がエッジ (フリップフロップ) でサンプリングされるか、入力ラッチ中にサンプリングされるかが問題になるため、合成ではフリップフロップを推論する必要があります。有効 (ラッチ) です。これは、2 つの論理要素が NOT EQUIVALENT であることを意味します。

ここに例があります。最初の 2 つの always ブロックは (Quartus 14 では) ラッチに合成されますが、これは定数のため同等であるため問題ありません。ただし、3. と 4. の always ブロックもラッチに合成されます。これは意図した動作ではなく、これらのブロックは同等ではありません。3. ブロックは警告を出しますが、4. は出ません。

 module ff_latch(
   input logic clk,
   input logic nrst,
   input logic a,
   output logic t, x, y, z
 );

    always_ff @(posedge clk, negedge nrst) 
       begin
          if (!nrst)
           t <= 0;
       end

    always_latch
       begin
          if (!nrst)
           x <= 0;
       end

    always_ff @(posedge clk, negedge nrst) 
       begin
          if (!nrst)
           y <= a;
       end

    always_latch
       begin
          if (!nrst)
           z <= a;
       end

endmodule: ff_latch

私は特にフリップフロップが必要だと言ったので(エッジトリガー付き)、この動作は正しくありません。コーディングがあいまいであるということではなく、常にブロック 3. と 4. が明確に異なります。これは、上記のシミュレーションからの次の波形で確認できます。

ここに画像の説明を入力

ブロック 3. (tb_y) は非同期フリップフロップのように動作し、ブロック 4. (tb_z) はラッチのように動作します。ただし、合成ツールはどちらの場合もラッチを推論します。

誰かがこれに光を当てたり、コードや波形にコメントしたりできれば、大歓迎です。

4

2 に答える 2

4

このコードはラッチのように動作するため、シンセサイザーはラッチを推測します。フリップフロップのようには動作しません。それはそれと同じくらい簡単です。

このコードがどのように動作するかを考えてみてください。最初は の値はaになります'x。がrstローにアサートされると、aになり'0ます。その後、永遠aに残ります。'0したがって、 の状態aは、入力の現在の状態だけでなく、過去の状態にも依存します。したがって、組み合わせロジックではなく、順序ロジックがあります。フリップフロップはクロック エッジで状態を変更します。ではない。always ブロックが信号エッジに敏感であるという事実は関係ありません。これは、内部のコードがその信号エッジ ( の正のエッジ) で実行されることを意味します。しかし、それが発生すると何も起こらないため、このコードはラッチのように動作します。aclk

于 2016-06-01T14:40:53.723 に答える
1

クロックのポーズエッジで何が起こるかを指定していないためです。またはそのポーズエッジにまったくa依存していないかのようです。clkあなたの説明はすべて、when にa設定されているということです。さらに、他のすべての場合に以前の値を保持すると (暗黙的に) 言います。これは、ラッチによって実装できます。0rst=0a

@posedge of があるからといって、clkそのブロック内のすべての変数がフロップとして合成されるわけではないことに注意してください。aclk のポーズエッジでブロックがアクティブ化されたときの非ブロッキング割り当ても必要です。ここを参照してください。

同じ機能を実装するためにフロップが必要な場合は、これを試すことができます。

always_ff @ (posedge clk or negedge rst) 
begin
  if (!rst)
    a <= '0;
  else 
    a <= a;  //Here, we are specifying what happens @posedge of clk
end
于 2016-06-01T23:49:51.243 に答える