• ベストアンサー

verilog HDL のレジスタ記述について

こんにちは verilog初心者です。論理合成をしていて気になる点があったので質問させていただきました。 二つのクロックの立ち上がりで書き込むレジスタを記述していて、 (全て1bit、clkはクロック) always @(posedge clk1 or posedge clk2) begin q <= d; end としたところ、シミュレーションはできますが論理合成はできませんでした。 自分の持っている参考書に「複数の書き込み信号があるレジスタはない」という記述があったので一応納得しました。 ところが、 always @(posedge clk1 or posedge clk2) begin if (clk1==1) q <= d; else if (clk2==1) q <= d; end と記述すると論理合成できてしまいます。 両者の書き込み信号に対する振る舞いは同じように思うのですが、一体何が違うのでしょうか。 わかる方いましたら是非ご教示下さい。よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • monova
  • ベストアンサー率68% (68/100)
回答No.1

コンパイラや仕向けのLSIによって解釈が異なる場合もありますが… > always @(posedge clk1 or posedge clk2) begin は、clk1,clk2 に対して同時に立ち上がりが来た場合、 出力が不定になる為、普通はエラーを返してくる筈です。 FPGAに入っているFFのセルは1入力のクロック端子しか 持っていないものが多いからです。 (FFをゲートで作る場合は話が変わってきますが…) >always @(posedge clk1 or posedge clk2) begin >if (clk1==1) >q <= d; >else if (clk2==1) >q <= d; >end この場合、コンパイラに寄って、若干解釈が異なってくる場合が 有ります。 always @(posedge clk1 or posedge clk2) begin この表記だけでエラーを返すものありますが、 今回の場合、if 文以下で強引に定義付けを行っていると 思われます。 if文に else が無いようなので、clk1 = 1,clk2 = 1 の時は 不定とせず、出力変化なし と解釈しているのでは無いでしょうか? 余談ですが、 always @(posedge clk1 or posedge clk2) begin if (clk1==1) q <= d; else if (clk2==1) q <= d; end という、表記は極力避けた方が良い思います。 クロックのエッジで、FFを動作させ、 且つ、レベルで出力を決定させる様な回路は、 フィッティングレベルで配線を複雑化させてしまう 可能性があります。 また、if 文 を使用する場合、else を記述した方が バグを発生させる可能性が小さくなると思います。

ppiiko
質問者

補足

>clk1,clk2 に対して同時に立ち上がりが来た場合、出力が不定になる為、普通はエラーを返してくる筈です。 なるほど、よく分かりました。 if文であれば、同時にクロックが立ち上がっても最初に定義されたclk1のほうが優先されエラーが出ないということですね。 >レベルで出力を決定させる様な回路は、フィッティングレベルで配線を複雑化させてしまう可能性があります。 とはどのようなことでしょうか。またどのような記述にすると良いでしょうか。よろしければもう少し詳しく教えていただけると幸いです。 else文は必ず記述するようにします。

その他の回答 (4)

  • syakoten
  • ベストアンサー率44% (4/9)
回答No.5

こんにちは。 質問を拝見いたしましたが、2クロックで動作するFFが、DCのライブラリにないのでしょう。 私も、そのようなFFは見たことがありません。 (2CLKで動くFFってあるんですか?どこのベンダのライブラリです?逆にちょっと知りたいです。) 普通は、 always @(posedge clk1 or negedge rst) begin とかですよ。 気をつけなければならないのは、Verilogでは構文エラーではないものも、DCでははじかれる(そのような回路が存在しない、合成できない)ということがあるので、気をつけてください。 DCの合成レポートは非常に大切です。

ppiiko
質問者

お礼

ご指摘ありがとうございます。合成レポートは十分にチェックするようにします。

  • txdata
  • ベストアンサー率0% (0/1)
回答No.4

こんにちは。 always文の定義からするとシミュレーションはどちらでもできます。 但し論理合成を前提にする場合はかなり制約を受けます。 それは同期式回路設計を前提にLSIの論理セルや論理合成ツールが設計されていることが多いためです。 同期式設計でクロックを2系用意するのはおすすめしませんが、 あえて記述すると次のように記述するといいでしょう。 always @(posedge clk1) begin  q1 <= d; end always @(posedge clk2) begin  q2 <= d; end assign q = q1 | q2; FPGA用などフリーの合成ツールの論理合成では、 always @( a 0r b )内の  第一項a クロック → posedge clk  立ち上がりエッジラッチ  第二項b リセット → posedge rst  省略時はリセットなし になることが殆どです。これはFPGAの内部単位セル(Logic Element)がクロック1系統、非同期リセット1系統のマルチプレクサデータ入力付きエッジラッチとしてあらかじめ組み込まれているためです。 第一項aのposedgeをなくすとレベルラッチになるはずですが、どうマッピング(配線)されるか分りません。なお二項目bは、posedgeをつけても非同期リセット線にマッピングされます。 通常はリセットをつないで初期化することが多いので、 次の形式を基本にするとたいてい論理合成できます。 always @( posedge clk or posedge rst ) begin  if( rst ) q <= 0;       q <= d; end 以上から同期式回路設計の場合 clk1,clk2より倍速以上のクロックclkをシステムクロックとして用意しリセットrstも追加して次のように記述します。 assign clkor = clk1 | clk2; always @( posedge clk or posedge rst ) begin  if ( rst ) q <= 0;  else if ( clkor ) q <= d; end この記述は確実に合成できて動作します。 質問で合成できた後半の式も似ていますね。ですがclk1かclk2のどちらかがdとANDをとって非同期リセットラインにマッピングされる可能性があり正しく動作しないかもしれません。

ppiiko
質問者

お礼

わかりやすい解説ありがとうございます。とても参考になりました。

  • monova
  • ベストアンサー率68% (68/100)
回答No.3

No.1 です。 補足…と、いいますか私の思いこみで、 always @(posedge clk1 or posedge clk2) begin を、非同期クリアDFFとしての使用を前提に答えてしまいました。 申し訳ありません。 clk1 、もしくは、clk2 を同期クリア or ロードとして使うのなら この表記はありだと思います。 例 (clk2 で同期クリア) output q; reg q; always @(posedge clk1 or posedge clk2) begin if(clk2) q<=0; else q<=d; end と、なります。 今回の様に、clk1,clk2 の両方で d(入力) のラッチを試みる場合 先に、clk1 と clk2 の OR をとってしまうのが素直な流れでは ないでしょうか? assign clk = clk1 | clk2; always @(posedge clk) begin if(clk1) q<=d; end しかし、基本的にはクロックラインに 論理ゲートを通す事は トラブルの元になるので避けた方が良いとは思います。 (例外もありますが) 今回は、最終的にどの様に動作させたいのか私には解らないので clk1 と clk2 の OR でラッチして良いのかハッキリと答えられません。 シミュレーションで動作の違いを見たいだけなら OR を 通してみるのも有りだと思います。 >レベルで出力を決定させる様な回路は、フィッティングレベルで配線を複雑化させてしまう可能性があります。 これは、実務上の話なので、シミュレーションしかしないのであれば あまりに気にしなくもてよいです。 参考までに… フィッティングとは、verilog記述した回路を実際のFPGAなりLSIに配線を行う データを作成する事を言います。 (ツールや会社によって言い方が異なるかもしれませんが…) verilog で回路を書くという事は、最終的には何らかのハードウェアに書き込む 訳ですよね。 その際、不必要に配線を長くしたり、セルを消費する様な回路は 出来るだけ避けておきたいのです。 (回路が煩雑になっても必要な回路は当然あります) この辺りは、言語記述を回路図に置き換えてみると、回路が煩雑になりそうか 推察できます。

ppiiko
質問者

お礼

今回は全く別の動作をする回路を記述していたのですが、途中で今回質問したものと似たような動作をする回路で躓いてしまい、その部分を抽出して質問させていただきました。 疑問を解決させていただいただけでなく、設計上の注意点等も教えていただけてとても感謝しています。ありがとうございました。

  • ss__s
  • ベストアンサー率0% (0/1)
回答No.2

どのようなプリミティブがライブラリにあるか(FPGA or LSIなど)によっても異なるとは思いますが、 非同期セットリセットのFFが推定されているのではないでしょうか。 論理合成された回路を確認するのが一番と思いますが、このような回路になっているのではないでしょうか。 assign clk = 0; assign ar = (clk1 && !d) || ((clk2 && !d) && !clk1) assign as = (clk1 && d) || ((clk2 && d) && !clk1); always @ ( posedge clk or posedge ar or posedge as ) begin if ( ar ) begin q = 0; end else if ( as ) begin q = 1; end else begin q = d; end end

ppiiko
質問者

お礼

自分は学生であり、企業のライブラリを使用させていただいて論理合成しているので、合成後のファイルを見ても確認することができない状況です。 今度フリーの論理合成ソフトを探してやってみようと思います。 ありがとうございました。

関連するQ&A

専門家に質問してみよう