単相同期回路で設計する理由触って学ぼう FPGA開発入門(4)(2/4 ページ)

» 2007年04月12日 00時00分 公開
[鳥海佳孝 設計アナリスト,@IT MONOist]

イネーブル方式によるカウンタ記述

 それでは、どのようにしたら前回作成したカウンタを“単相同期回路の記述スタイル”に合わせることができるでしょうか?

 前回の順序回路をクロック信号に乗り換えずに設計するためには、これから解説する「イネーブル方式」の回路記述を採用します。

 前回作成した「10進カウンタ」を“1秒”で動作させて、イネーブル方式による記述スタイルに変更します。具体的にはリスト1のように記述します。


1  module UPDOWN(RESET, CLK, DEC, COUNT);
2  input RESET, CLK, DEC;
3  output [3:0] COUNT;
4  
5  parameter SEC1_MAX = 6000000; // 6MHz
6  
7  reg [22:0] tmp_count;
8  reg [3:0] COUNT_TMP;
9  wire ENABLE;
10  
11  always @(posedge CLK or negedge RESET)
12  begin
13          if (RESET == 1'b0)
14                  tmp_count <= 23'h000000;
15  //      else
16          else if (ENABLE == 1'b1)
17                  tmp_count <= 23'h000000;
18          else
19                  tmp_count <= tmp_count + 23'h1;
20  end
21  
22  // assign DIVIDE_CLK = tmp_count[22];
23  assign ENABLE = (tmp_count == (SEC1_MAX - 1))? 1'b1 : 1'b0;
24  
25  //always @(posedge DIVIDE_CLK or negedge RESET)
26  always @(posedge CLK or negedge RESET)
27  begin
28          if (RESET == 1'b0)
29                  COUNT_TMP <= 4'h0;
30          else if (ENABLE == 1'b1)
31  //      else if (DEC == 1'b1)
32                  if (DEC == 1'b1)
33                          if (COUNT_TMP == 4'h9)
34                                  COUNT_TMP <= 4'h0;
35                          else
36                                  COUNT_TMP <= COUNT_TMP + 4'h1;
37                  else
38                          if (COUNT_TMP == 4'h0)
39                                  COUNT_TMP <= 4'h9;
40                          else
41                                  COUNT_TMP <= COUNT_TMP - 4'h1;
42  end
43  
44  assign COUNT = ~COUNT_TMP;
45  
46  endmodule
リスト1 イネーブル方式による4bitの10進アップ・ダウンカウンタ(UPDOWN10-2.v

 まず、リスト1の11〜20行目にあるように、1秒で動作するカウンタを作成します。具体的には、今回扱うFPGAボードの6MHzのクロックを使用していますので、「0〜5999999」までカウントするカウンタを作成します。

 次に23行目にあるように、1秒カウンタが「5999999」のときにだけ’1’となるような信号(ENABLE)を作成します(図3)。この記述は、C言語の条件演算子と同様な記述をします。

1秒イネーブルの作り方 図3 1秒イネーブルの作り方

assign ENABLE = (tmp_count == (SEC1_MAX - 1))? 1'b1 : 1'b0;

  • tmp_count == (SEC1_MAX - 1)が真のとき→1'b1
  • tmp_count == (SEC1_MAX - 1)が偽のとき→1'b0

 このENABLE信号により、tmp_countは「5999999」の次に「0」となります。ちょうど10進カウンタのアップカウントで「9」のときに「0」に戻し、ダウンカウントで「0のときに「9」にしているのと同じ役目をすると考えるとよいでしょう。

 なお、このENABLE信号の中で使用されているSEC1_MAXは、5行目にあるように、1秒カウンタの最大値となる値をparameter文で定義します(このparameter文を使用するところが、後でこのカウンタをシミュレーションするうえで重要なポイントとなります。詳しくは後述します)。

 これで、1秒カウンタは出来上がりです。次に、このENABLE信号を使ってカウンタの動作を1秒ごとに行うように変更します。具体的には、30行目のようにENABLE信号が「1」になったときだけ動作するように、アップ・ダウンするカウント動作の記述部部分をif文で囲っています。こうすることで、ENABLEが「1」のとき(1秒に1回)だけカウント動作が行われます。

 くれぐれも、

always @(posedge ENABLE ……

などとしないでください。あくまでも、単相同期回路の記述スタイルに持ち込むことが重要なのです。

Copyright © ITmedia, Inc. All Rights Reserved.