27

ハードウェア図の描画に関して、ブロッキング割り当てと非ブロッキング割り当てがどのように解釈されるかについて少し混乱しています。非ブロッキング代入がレジスターを与えると推測する必要がありますか?次に、このステートメントによればc <= a+b 、cはレジスター権利ですが、aとbではありませんか?

module add (input logic clock,  
output logic[7:0] f);   

logic[7:0] a, b, c;  

always_ff @(posedge clock)  
begin   
  a = b + c;   
  b = c + a;   
  c <= a + b;  
end   

assign f = c;  

endmodule
4

6 に答える 6

45

従来のVerilogの知恵はそれをすべて間違っています。ローカル変数にブロッキング割り当てを使用しても問題はありません。ただし、これは非決定的であるため、同期通信にブロッキング割り当てを使用しないでください。

クロックされたalwaysブロック内の非ブロッキング割り当ては、セマンティクスによって指示されるように、常にフリップフロップを推測します。

Clocked Alwaysブロック内のブロッキング割り当てがフリップフロップを推測するかどうかは、それがどのように使用されるかに完全に依存します。割り当てられる前に変数が読み取られる可能性がある場合は、フリップフロップが推測されます。それ以外の場合、これは一時変数のようなものであり、いくつかの組み合わせロジックが生成されます。

于 2011-01-23T14:56:43.300 に答える
34

最初にブロック割り当てと非ブロック割り当ての違いを理解するのは、確かに少し注意が必要です。しかし、恐れることはありません-便利な経験則があります:

ブロックを使用してコンボロジックを推測する場合は、alwaysブロック割り当て(=)を使用します。シーケンシャルロジックが必要な場合はalways、非ブロッキング割り当て(<=)を備えたクロックブロックを使用します。そして、2つを混ぜないようにしてください。

上記のコードはおそらく最良の例ではありません。構築しようとしている加算器/フリップフロップ構造がわからないと、コンボフィードバックパスが発生する危険性があります(これは悪いことです)。そして、あなたは入力バスを持っていないので、あなたは本質的に、そして薄い空気から構築しようとしてaいますbc

しかし、あなたの質問に答えるために、クロックalwaysブロック内に割り当てられた変数は、ブロッキング演算子(=)を使用して割り当てられ、一種のローカル変数として使用されない限り、フリップフロップを推測します。

module add
  (
   input clock,
   input [7:0] in1,
   input [7:0] in2,
   output logic [7:0] f1, f2, f3, f4, f5
   );   


   // f1 will be a flipflop
   always_ff @(posedge clock) begin
      f1 = in1 + in2;
   end


   // f2 will be a flipflop
   always_ff @(posedge clock) begin
      f2 <= in1 + in2;
   end


   // f3 will be a flipflop
   // c1 will be a flipflop
   logic [7:0] c1;
   always_ff @(posedge clock) begin
      c1 <= in1 + in2;
      f3 <= c1 + in1;
   end


   // f4 will be a flipflop
   // c2 is used only within the always block and so is treated
   // as a tmp variable and won't be inferred as a flipflop
   logic [7:0] c2;
   always_ff @(posedge clock) begin
      c2 = in1 + in2;
      f4 = c2 + in1;
   end


   // c3 will be a flipflop, as it's used outside the always block
   logic [7:0] c3;
   always_ff @(posedge clock) begin
      c3 = in1 + in2;
   end

   assign f5 = c3 + in1;

endmodule

経験則に従い、alwaysブロック内でブロッキングと非ブロッキングの割り当てを混合しない大きな理由は、割り当てを混合すると、RTLシムとゲートシム/実際のハードウェア操作の間で深刻なシミュレーションの不一致が発生する可能性があるためです。verilogシミュレータは、まったく異なる方法で処理=<=ます。割り当てをブロックするということは、「この瞬間にすぐに変数に値を割り当てる」ことを意味します。非ブロッキング割り当てとは、「この変数に何を割り当てるかを考え出し、将来割り当てるためにそれを保存する」ことを意味します。これをよりよく理解するために読むべき良い論文は次のとおりです。http ://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdfも参照してください。

于 2011-01-11T12:27:39.760 に答える
2

JanDecaluweの答えに追加したいだけです。Jan Decaluweが説明していることを実際に使用しているコードは、実際にはほとんどないようですが、それは絶対に正しいものです。カミングス氏のおかげで、ブロッキングステートメントと非ブロッキングステートメントの混合はタブーになりました。

問題は、ほとんどの場所でローカル変数にブロッキングステートメントを使用することを避けており、Googleの即時検索スペースには、それがどのように行われるかの例を示すコードがほとんどないことです。Janが述べたコーディングスタイルを見つけた唯一の場所は、この記事の勝者のコードです。そしてこれ、偶然出くわした

于 2014-01-15T05:35:26.290 に答える
2

私もこれに苦労しました。

ただし、最初に、非ブロッキングまたはブロッキングは、実際にはラッチ/ffが作成されるかどうかとは関係がないことを理解する必要があります。

それらの違いについては、この時点で簡単に(最初に)理解できます。ブロッキングを使用する場合、変数を使用すると、ブロックセンテンスのLHSに変更されたものが更新されて使用される可能性があるため、ブロックセンテンスのLHSが値を割り当てるまで実行できませんでした。ただし、非ブロックの場合、次の文と並行して次の文をブロックしません(実際には、RHS計算を最初に実行する必要がありますが、混乱する場合は無視してください)。LHSは、今回の実行では変更/更新されません(次回、常にブロックが再度トリガーされたときに更新されます)。そして、次の文は、実行サイクルの終わりに更新された古い値を使用します。

a = 0; b= 0;
a = 1;
b = a;
--> output a = 1, b = 1;
a = 0; b= 0;
a <= 1;
b = a;
--> output a = 1, b = 0;

重要なポイントの1つは、コード内に(常にブロックする)値が割り当てられていないが発生する可能性のあるケース変数があるかどうかを確認することです。値を渡さずにその場合が発生した場合は、値を保持するためにラッチ/ffが作成されます。

例えば、

always @(*) begin
    if(in) out = 1;
    else out = 0;
end
--> this end without latch/ff
always @(*) begin
    if(in) out = 1;
end
--> this end with one latch/ff to keep value when in = 0, as it might happen and you didn't assign value to out as in=1 do. 

以下もラッチ/ffを作成する可能性があります。

always @(*) begin
    if(in) a = 1;
    else b = 1;
end

-> in = 1、b割り当てなし、in=0で割り当てなしのラッチ/ffsが作成されました。

また、clkのポーズを感知するalways @(posedge clk)と、latch/ffで終了します。clkの場合、負のエッジが存在する必要があり、何もしないため、古い値をすべて保持するためにラッチ/ffsが作成されます。

于 2014-06-25T17:33:20.670 に答える
0

あなたが書いた同じコードがゲートレベルで変換された場合に何が起こるかを理解する必要があるだけで、デジタルドメインのVerilogをいつでも解釈できます。私は個人的にseqでノンブロッキングを使用するか、組み合わせてブロッキングを使用するという規則に従わないでください、これはあなたの思考を制限します。コードのデジタル側に固執するのはここだけです。コードがゲートレベルに変換された場合に何が起こるかを確認してください。

  1. 最初に全加算器が作成されます-入力aとb
    1. 出力はフリップフロップに送られ、clkと同期する出力を作成します
    2. 割り当てがブロックされているため、新しいaが次の完全に追加されたものに適用され、この新しいaとcが入力として使用されます。その出力は、dffcsyncに移動してclkに新しいbを作成します。
    3. 今b=c+aなので; ブロッキングステートメントがあるので、bはこの新しいbに更新されます
    4. ここで、そのc <= a + bが発生します。これで、入力としてaとbを持ち、clkへのdff同期に進む全加算器が作成されます。ここで、a=cと言うような他の条件があります。
    5. 次に、非ブロッキングステートメントによって作成されたばかりの新しいcではなく古いcを持つdffが作成され、clkへのこのdff同期の出力はaに送られ、aが更新されます。

ラウール・ジャインに感謝します

于 2014-09-29T13:36:28.590 に答える
0

私はあなたの質問に答えることができますが、これには1つの論文が最適だと思うので、CliffordCummingsのこの論文を読むことをお勧めします。それはあなたのすべての疑問を取り除き、それに加えてVerilogのあなたの理解を強化します。

http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA_rev1_2.pdf

于 2014-12-09T03:13:59.133 に答える