フリップフロップの代わりにラッチが推論される理由を誰かに説明してもらえますか?
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) はラッチのように動作します。ただし、合成ツールはどちらの場合もラッチを推論します。
誰かがこれに光を当てたり、コードや波形にコメントしたりできれば、大歓迎です。