現在位置: ホーム / Education / 2012 / FPGAトレーニングコース / docs / Web_Intro_Verilog-HDL / 3.2 記憶素子を使った回路

3.2 記憶素子を使った回路

Web版 Verilog-HDL入門

3.2 記憶素子を使った回路

順序回路記述の前に記憶素子を使用した回路記述を説明します。

ここでは、記憶素子としてDタイプ・フリップフロップ(DFF)を想定します。他のタイプの素子については参考文献を参照してください。

DFFは単ゲートよりも機能が多いのです。以下の機能を部分的または全て持っています。

  • リセット(非同期または同期)
  • プリセット(非同期または同期)
  • クロックイネーブル

Xilinx社は正論理信号の使用を奨励していますので、ここでは正論理の信号を使用した記述から始めます。

D-type Flip Flop (DFF)

リセットやクロックイネーブルなど無いDFF単体の基本的な記述です。

クロック名をCLK、入力信号をD、出力信号をQとします。

   reg      Q;

   always @(posedge CLK)begin
      Q <= D;
   end

この文の意味を説明します。

always文

キーワードalwaysに続けて書かれている"@()"の中の条件文が成立する時にキーワードbeginendの間にある文が動作します。この場合posedge CLKが動作条件でです。posedgeはキーワードで立ち上がりエッヂを意味しています。従って、この回路はクロック入力CLKの立ち上がり時に毎回動作します。逆の言い方をすれば、クロック入力CLKの立ち上がり時だけ動作します。それ以外の時は動作しません。動作しないとは状態を保持したままになると言う意味です。

まとめるとCLKの立ち上がりエッヂの時のみ入力DをQに出力し、他の時は状態を保持します。DFFの動作になります。

動作記述の文中等号が=でなく<=である事に気がついたでしょうか。これは大小比較ではありません。実は=<=は両方使う事が出来ます。そして意味が違います。ここではDFFとして使用する場合は等号=ではなく<=を使うと覚えてください。この文章ではalways文をDFF出力以外の記述に使用しません。

always文とDFF
always文はDFF以外の回路も表現する事が出来ます。例えば、組み合わせ回路も表現できます。しかし、always文は書き方が少し複雑であり生成される回路を意識する事が難いです。最初は組み合わせ回路はassign文で記述し、DFF出力はalways文のひな形を使用すると決めて設計する方が無難です。慣れてきたら参考文献を参考にして自分に合った記述を身につけてください。

beginとend

文の構造を明示するときに使用するキーワードです。C言語のカッコ{}に似ています。

Verilog-HDLの場合、省略する事が可能です。上の例の場合下の様に書く事が出来ます。

   always @(posedge CLK)
      Q <= D;

省略する事が出来ますが構造を意識して記述する事を重視するとbegin, endの使用を勧めます。

posedgeとnegedge

posedge以外にnegedgeもあります。クロックの立下りで動作するDFFを使用する場合は下の様に記述してください。

   always @(negedge CLK)begin
      Q <= D;
   end

HDLに慣れるまではDFFはこのように書くと覚えてください。慣れてきたら文の意味を再度確認してください。実はalways文の意味と動作を厳密に結びつけようとすると解釈に疑問だでる箇所があります。私自身質問されると困る文が存在します。

同期リセット付きDFF

クロック名をCLK、リセット入力をRESET、入力信号をD、出力信号をQとします。

同期リセット付きDFFの記述は下のようになります。

   reg      Q;

   always @(posedge CLK)begin
       if(RESET) begin
           Q <= 1'b0;
       end else begin
           Q <= D;
      end
   end

if文が追加されました。ifに続く()の中の条件が成立(真の時)した時はifに続く文を実行します。このif文の条件文の意味は''RESET==1'b1''と同じ意味です。RESETが1の時下の文が実行されます。

           Q <= 1'b0;

条件が成立しないときはelseに続く下の文を実行します。

           Q <= D;

動作をまとめるとクロック入力CLKの立ち上がりエッヂでRESETが1の時は0を出力し、立ち上がりエッヂでRESETが0の時はDを出力する回路になります。同期リセット付きDFF回路です。

同期リセットおよびクロック・イネーブル付きDFF

クロック名をCLK、リセット入力をRESET、クロック・イネーブルをCE、入力信号をD、出力信号をQとします。

同期リセット付きおよびクロック・イネーブル付きDFFの記述は下のようになります。

   reg      Q;

   always @(posedge CLK)begin
       if(RESET) begin
           Q <= 1'b0;
       end else begin
           if(CE)begin
               Q <= D;
           end
      end
   end

先の例のelse文の中に下の部分が追加されました。

           if(CE)begin
               Q <= D;
           end

この文がelseの中に追加されているのでRESET=0の時にこのif文が動作することが分かります。if文の中の条件式がCE==1ですから、RESET=0かつCE=1の時のみ入力信号を出力する下の文が動作します。

               Q <= D;

CE=0の時の記述がありませんが、CE=0の時の動作はどうなるのでしょうか?記述が無い場合は状態を保持する決まりになっています。つまり、この記述ではCE=0の時は停止状態で状態を保持します。

実際の記述

上の例は全て入力をそのまま出力する物でしたが、右辺に組み合わせ回路を喜寿する事が出来ます。

例えば、組み合わせ回路で登場した2入力XORの出力にDFFを挿入した回路は以下のように記述する事が出来ます。

module XOR2_WDFF(
    CLK     , // in    : Input, System clock
    RESET   , // in    : Input, System reset
    CE      , // in    : Input, Clock enable
    IN_A    , // in    : Input
    IN_B    , // in    : Input
    O         // out   : Output
);

// ----- input/ output -----
    input           IN_A   ;
    input           IN_B   ;
    output          O      ;

    reg             O      ;

   always @(posedge CLK)begin
       if(RESET) begin
           Q <= 1'b0;
       end else begin
           if(CE)begin
               Q <= (IN_A & ~IN_B) | (~IN_A & IN_B);
           end
      end
   end

endmodule