13

次のコード セクション (同じブロック) を言います。

A <= 1
A <= 2

変数 A には常に 2 が割り当てられますか? または、競合状態が発生し、1 つまたは 2 つが割り当てられますか?

ノンブロッキング代入についての私の理解では、将来的に変数 A を代入するのはハードウェア次第なので、ランダムな結果になる可能性があります。ただし、これは直感的ではありません。シミュレーションでは常に 2 が割り当てられることが示されていますが、これがハードウェア合成の場合に確実に当てはまるかどうかを知りたいです。

4

4 に答える 4

14

A はシミュレーションでは 2 になり、最後に定義された値が有効になります。それらが同じブロックにない場合、シミュレーションで最後に定義されたものに関して、シミュレータ スケジューラに応じて競合状態が発生する可能性があります。

この手法がかなり多く使用されているのを見てきましたが、合成後に予期しない結果が発生したことはありません。

Verilog IEEE 1364-2005 セクション 11.4.1 決定論から

begin-end ブロック内のステートメントは、その begin-end ブロックに現れる順序で実行されます。モデル内の他のプロセスを優先して、特定の begin-end ブロック内のステートメントの実行を中断できます。ただし、begin-end ブロック内のステートメントは、ソースに表示される順序以外で実行されることはありません。

これは、セクション 4.6 決定論として SystemVerilog-IEEE1800 2012 にもあります。

これの使用法は、その出力をまばらに定義する FSM である可能性があります。

always @(posedge clk) begin
  out_one <= 1'b0;
  out_two <= 1'b0;
  out_thr <= 1'b0;
  case (state)
    2'd1 : out_one <= 1'b1;
    2'd2 : out_two <= 1'b1;
    2'd3 : out_thr <= 1'b1;
  endcase
end
于 2013-03-31T17:35:39.550 に答える
9

Aシミュレーションでも合成でも、コード内の の最終値について非決定論的なものは何もありません。

ただし、厳密に言えば、デザインに のトリガーが含まれている場合、シミュレーションと合成が一致しない可能性がありますA。次の例を検討してください。

module test(input clk, output reg a, b);
  always @(posedge clk) begin
    a <= 0;
    a <= 1;
  end

  initial b = 0;
  always @(posedge a) begin
    b <= !b;
  end
endmodule

そしてテストベンチ:

module tb;
  reg clk = 0;
  always #5 clk = ~clk;

  wire a, b;
  test uut (clk, a, b);

  initial begin
    $monitor("clk=%b a=%b b=%b", clk, a, b);
    repeat (100) @(posedge clk);
    $finish;
  end
endmodule

シミュレーション中、 update と の両方a <= 0a <= 1NBA イベント リージョンにプッシュされ、順番に実行されるため、a常に設定されます。ただし、 も実行されるため、クロック サイクルごとa <= 0にゼロ幅の負のパルスがオンになります。aこのパルスは、2 番目の常にブロックをトリガーします。これはシミュレーション出力です (Icarus Verilog および Modelsim でテスト済み)。

clk=0 a=x b=0
clk=1 a=1 b=1
clk=0 a=1 b=1
clk=1 a=1 b=0
clk=0 a=1 b=0
clk=1 a=1 b=1
clk=0 a=1 b=1
clk=1 a=1 b=0
clk=0 a=1 b=0
clk=1 a=1 b=1
clk=0 a=1 b=1
clk=1 a=1 b=0
clk=0 a=1 b=0
...

ただし、合成ではa、定数値 1 とb定数値 0 が割り当てられるだけです。(Yosys および Xilinx Vivado でテスト済み)。したがって、合成後のシミュレーション出力は次のようになります。

clk=0 a=1 b=0
clk=1 a=1 b=0
clk=0 a=1 b=0
clk=1 a=1 b=0
clk=0 a=1 b=0
clk=1 a=1 b=0
clk=0 a=1 b=0
clk=1 a=1 b=0
clk=0 a=1 b=0
clk=1 a=1 b=0
clk=0 a=1 b=0
clk=1 a=1 b=0
clk=0 a=1 b=0
clk=1 a=1 b=0

(理論的には、最初の行はまだ と言うことができますが、テストの両方のツールが行っa=xたように、適切な合成ツールはすべてa-flip-flop を最適化します。)

それ以外には、そのコードに潜在的な問題はありません.@Morganが彼の答えで正しく指摘したように、これは、条件付き割り当てを使用して特殊なケースをエンコードする前に、出力信号の「デフォルト値」を定義するための非常に一般的なコーディング手法です(ifおよび/またはcase)。

于 2015-09-24T04:56:46.103 に答える
1

IEEE Std (1800-2009 など) の「決定論」セクションによると、これらのステートメントが begin-end ブロックにある場合、A には常にシミュレーションで値 2 が割り当てられます。

ただし、Std はコードの合成方法を保証しません。結果のゲートは、おそらく合成ツールに依存します。しかし、優れた RTL リンティング ツールは、そのような不適切なコーディングを識別します。Cadence の Hal lint ツールが警告を発します。

于 2013-03-30T12:55:14.507 に答える