連載
» 2007年03月16日 00時00分 公開

順序回路の基本! カウンタを作成しよう触って学ぼう FPGA開発入門(3)(2/3 ページ)

[鳥海佳孝 設計アナリスト,@IT MONOist]

4bitフリーランカウンタを作成しよう(2)

4bitフリーランカウンタのテストベンチ

 早速、FPGAボード上で動作させてみましょう!といいたいところですが、まずはテストベンチを作成し、シミュレーションを実行します。

 以下に4bitフリーランカウンタのテストベンチの記述を示します。


1  module TEST_COUNT4;
2  reg clk, reset;
3  wire [3:0] count;
4  
5  parameter CYCLE = 100;
6  
7  COUNT4 i1(.RESET(reset), .CLK(clk), .COUNT(count));
8  
9  always #(CYCLE/2)
10         clk = ~clk;
11 
12 initial
14         reset = 1'b0; clk = 1'b0; ←時刻0
15         #CYCLE reset = 1'b1; ←時刻100
16         #(20*CYCLE) reset = 1'b0; ←時刻2100
17         #CYCLE reset = 1'b1; ←時刻2200
18         #(20*CYCLE) $finish; ←時刻4200、シミュレーションを終了
19 end
20 
21 initial
22         $monitor($time,,"clk=%b reset=%b count=%b", clk, reset, count);
23 
24 endmodule
リスト2 4bitのフリーランカウンタのテストベンチ(T_COUNT4.v

2行目

 9行目のalways文中の「clk」信号、14〜17行目のinitial文中の「clk」「reset」信号が手続き的代入文の中で使用されているので、それぞれの信号をreg宣言します。

3行目

 「count」信号が、reg宣言またはwire宣言をしなければならない信号としてまだ残っています。count信号は、bit幅が1bitではないのでwire宣言を省略できません(注)。そのため、4bitのwire宣言を行います。

※注:
Verilog-HDLの文法では、1bitのwire宣言は省略可能(宣言不要)となっています。


5行目

 parameter文で、このシミュレーションにおける1クロックサイクルの長さを指定します。このparameter文の値を変更すれば、クロックの周波数を変更できるので非常に便利です。

9〜10行目

 クロックのような繰り返し「0」「1」になるパルスを生成する典型的な記述です。この場合には、時刻50ユニットごとにclk信号が反転されます(注)。

※注:
「#」で時間の経過を指定することができます。


14行目

 reset信号とclk信号の時刻0での値を代入します。特にこのclk信号の初期化は大変重要です。これを忘れてしまうと、うまくclkを生成することができません。

 ちなみに、最新のVerilog-HDLの規格では、「reg clk = 1'b0;」のようにreg宣言時に初期値を与えることも可能です(この場合、initial文中での初期化は不要)。

15行目〜18行目

 時刻100ユニットでreset信号を「1'b1」にして、時刻2100ユニット(100+2000)でreset信号を「1'b0」にします。さらに、時刻2200ユニット(100+2000+100)でreset信号を再び「1'b1」にして、時刻4200ユニット(100+2000+100+2000)で$finish(シミュレーションを終了)します。

シミュレーションの実行

 これで、RTLとテストベンチが完成しました。それでは、ModelSimを使ってシミュレーションを実行してみましょう。前回までの記事を参考にコンパイル、シミュレート、実行をして、波形表示で動作を確認してください。

 画面1のように動作すれば問題ありません。

波形表示によるシミュレーション結果の確認 画面1 波形表示によるシミュレーション結果の確認

 画面1では、結果を確認しやすくするためにカウンタの値を整数値で表示しています。この表示を行うには、「wave-default(波形表示のウィンドウ)」の左側リストから表示を変更したい信号を右クリックして[ショートカットメニュー]−[Radix]−[Unsigned]を選択します(画面2)。

整数値でカウンタを表示 画面2 整数値でカウンタを表示

FPGAボード上での動作確認

 これで、シミュレーションでの動作確認が取れました。それでは、RTLをFPGAのボード上で動かしてみましょう。

 ここでは、手早く動作を確認するために4bitのカウンタの値を赤色LEDにそのまま出力しています。以下のピンアサインを行って、論理合成、配置配線を実行してください。

I/O Name Loc
CLK P39
RESET P17
COUNT<0> P68
COUNT<1> P67
COUNT<2> P66
COUNT<3> P65

1  NET "CLK"  LOC = "P39"  ;
2  NET "RESET"  LOC = "P17"  ;
3  NET "COUNT<0>"  LOC = "P68"  ;
4  NET "COUNT<1>"  LOC = "P67"  ;
5  NET "COUNT<2>"  LOC = "P66"  ;
6  NET "COUNT<3>"  LOC = "P65"  ;
リスト3 4bitのフリーランカウンタのピンアサイン(COUNT4.ucf

 特に問題がなければ、ボード上に設計データ(bitファイル)をダウンロードします。

 いかがでしょうか?

 ボード上で確認してみると、すべての赤色LEDが点灯したような状態になっていると思います。

 赤色LEDは、なぜカウント動作をしてくれないのでしょうか?

 それは、カウンタが6MHzで動作しているからです。実際は正しくカウント動作をしているのですが、高速過ぎて人間の目には「すべてのLEDが点灯しているだけ」のように見えているのです。

分周クロックの導入

 このままでは、ボード(赤色LED)上で正しくカウンタが動作しているかを確認することができません。そこで、カウンタのクロックを遅くする方法を紹介します。

 あまり良い方法ではありませんが(その理由は、次回説明します)、今回は6MHzのクロックを分周してカウンタに渡して動作させます。

 分周するクロックを入れるために、リスト1を以下のように変更します。

1  module COUNT4(RESET, CLK, COUNT);
2  input RESET, CLK;
3  output [3:0] COUNT;
4  
5  reg [22:0] tmp_count;
6  reg [3:0] COUNT;
7  
8  always @(posedge CLK or negedge RESET)
9  begin
10         if (RESET == 1'b0)
11                 tmp_count <= 23'h000000;
12         else
13                 tmp_count <= tmp_count + 23'h1;
14 end
15 
16 assign DIVIDE_CLK = tmp_count[22];
17 
18 always @(posedge DIVIDE_CLK or negedge RESET)
19 begin
20         if (RESET == 1'b0)
21                 COUNT <= 4'h0;
22         else
23                 COUNT <= COUNT + 4'h1;
24 end
25 
26 endmodule
リスト4 4bitのフリーランカウンタの修正版(COUNT4-2.v

 変更したポイントは、下記のとおりです。

  • 6MHz以上数えられるように23bitのフリーランのカウンタ(tmp_count)を用意(5行目)
  • フリーランのカウンタの最上位bit(22bit目)をカウンタのクロックとして入力(16行目)

 この変更を行ったら、ISE WebPACKで論理合成、配置配線を行い、設計データをFPGAのボードにダウンロードします。

 今回はいかがでしょうか? カウンタの動作を確認できたと思います。ただし、赤色LEDは負論理なのでLEDの動作はカウントダウンしています。

 このシミュレーションを行うには、かなりのクロック数が必要となりますので、まともにシミュレーションするのは現実的ではありません(カウントが1つアップするだけでも、気の遠くなるようなクロック数が必要となります)。この課題を克服するためのシミュレーションテクニックに関しては「単相同期回路設計」の解説と併せて次回紹介する予定です。

Copyright © ITmedia, Inc. All Rights Reserved.