推論されたラッチとそれが内部的に必要な理由を理解しようとしましたが、十分な詳細を持つリソースを見つけることができませんでした。
ネットが既知の値に割り当てられていない組み合わせブロック内でラッチが推論されます。それ自体にネットを割り当てても、ラッチは推測されます。ラッチは、感度リストとフィードバックループを形成する信号の欠落によって推測することもできます。
Verilog/SystemVerilogで意図されたラッチを推論する適切な方法は次のとおりです。
/* Verilog */ //// /* SystemVerilog */
always @* //// always_latch
begin //// begin
if (en) q = d; //// if (en) q = d;
end //// end
感度リストに欠落している信号(これが@*
を使用する必要がある理由です):
always @(a or b) // inferred latch :: "c" missing for the sensitivity list.
begin
out = a + b + c;
end
欠落状態:
always @*
begin
case(in[1:0])
2'b00: out = 1'b0;
2'b01: out = 1'b1;
2'b10: out = 1'b1;
// inferred latch "out" :: missing condition 2'b11/default
endcase
end
always @*
begin
next0 = flop0;
next1 = flop1;
// inferred latch "next2" :: missing initial condition
next3 = flop3;
case(a[2:0])
3'b001: next0 = in;
3'b010: if(b) next1 = in;
3'b100: if(c) next2 = in;
default: if(!b&&!c) next3 = in;
endcase
end
フィードバックループ:
assign out = en ? in : out; // inferred latch "out" :: feedback to mux
assign a = en ? z : c;
// ... any amount of code between ...
assign z = en ? a : y; // inferred latch "a" :: feedback chain
always_latch
を使用します。always @*
またはSystemVerilogのalways_comb
で定義する必要があります。case
ステートメントにはdefault
条件が必要です。if
ステートメントには、対応するelse
が必要です。case
またはif
の前)の初期値を与えます。always_comb
を使用すると、リンティングツールと論理的等価性チェックツールで推論されたラッチを特定できます。最悪のシナリオでは、すべてのロジックを同期ブロック内に配置します。すべての推論されたラッチは推論されたフリップフロップになります。これは、不必要にゲート数を増やし、ルーティングを増やし、タイミングに影響を与える可能性があるため、通常は悪い考えです。
ラッチは、組み合わせロジックの出力に未定義の状態がある場合、つまり以前の値を保持する必要がある場合に推論されます。
組み合わせロジックには、状態を保持するフリップフロップがないため、出力は常に入力によって定義される必要があります。
短い例は次のとおりです。
always @* begin
if (a == 1'b1) begin
b = x|y|z;
end
end
b
とはa == 1'b0
。 b
はオーバーライドされないため、その値を保持します。状態の概念がない場合、その値を保持するにはどうすればよいですか。ラッチを推測して状態を導入する必要があります。これは通常、非常に悪いことです。
ラッチを暗示してタイミングなどに注意することができますが、推論されたラッチは名目上バグのあるコードからのものです。
ラッチは組み合わせのalwaysブロックでのみ生成されます。シーケンシャルロジックはラッチを生成しません。
トランスペアレントラッチの作成方法とラッチの推論を回避する方法 の詳細については、