連載
» 2007年06月15日 00時00分 公開

触って学ぼう FPGA開発入門(6):順序回路と組み合わせ回路を意識した記述を! (3/4)

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

最終的なハードウェア構成

 キャリー信号は、組み合わせ回路の出力として作成する必要があるので、最終的にはリスト6のようにキャリー信号を作成します(最終的な60進カウンタのリスト7では、10進カウンタに相当する部分の信号名を「COUNT_TMP」→「CNT10」に変更しています)。


(省略)
28 always @(posedge CLK or negedge RESET)
29 begin
30        if (RESET == 1'b0)
31            begin
32               COUNT_TMP <= 4'h0;
33               CARRY <= 1'b0;
34            end
35        else if (ENABLE == 1'b1)
36 //      else if (DEC == 1'b1)
37            if (DEC == 1'b1)
38                begin
39                   if (COUNT_TMP == 4'h9)
40                       COUNT_TMP <= 4'h0;
41                   else
42                       COUNT_TMP <= COUNT_TMP + 4'h1;
43                end
44            else
45                begin
46                   if (COUNT_TMP == 4'h0)
47                       COUNT_TMP <= 4'h9;
48                   else
49                       COUNT_TMP <= COUNT_TMP - 4'h1;
50                end
51 end
52
53 always @(COUNT_TMP or DEC)
54 begin
55        if (DEC == 1'b1)
56            if (COUNT_TMP == 4'h9)
57                CARRY <= 1'b1;
58            else
59                CARRY <= 1'b0;
60        else
61            if (COUNT_TMP == 4'h0)
62                CARRY <= 1'b1;
63            else
64                CARRY <= 1'b0;
65 end
(省略)
リスト6 正しいハードウェア構成によるキャリーの作り方(UPDOWN10-4.v

 作成したキャリー信号は6進カウンタと10進カウンタで参照します。このけた上げ・けた下げの信号は、ある意味1秒のイネーブルと同じ意味合いがあるととらえてもよいので、ここはif文でネストせずに、つまり優先順位としてはENABLEと同じと考えて“&&”の条件演算子で記述します。こうすることで60進カウンタがきちんと動作するのです(リスト7)。

(省略)
10  always @(posedge CLK or negedge RESET)
11  begin
12         if (RESET == 1'b0)
13             begin
14                CNT10 <= 4'h0;
15             end
16         else if (ENABLE == 1'b1)
17  //      else if (DEC == 1'b1)
18             if (DEC == 1'b1)
19                 begin
20  //                  if (CNT10 == 4'h9)
21                    if (CARRY == 1'b1)
22                        CNT10 <= 4'h0;
23                    else
24                        CNT10 <= CNT10 + 4'h1;
25                 end
26             else
27                 begin
28  //                  if (CNT10 == 4'h0)
29                    if (CARRY == 1'b1)
30                        CNT10 <= 4'h9;
31                    else
32                        CNT10 <= CNT10 - 4'h1;
33                 end
34  end
35
36  always @(CNT10 or DEC)
37  begin
38         if (DEC == 1'b1)
39             if (CNT10 == 4'h9)
40                 CARRY <= 1'b1;
41             else
42                 CARRY <= 1'b0;
43         else
44             if (CNT10 == 4'h0)
45                 CARRY <= 1'b1;
46             else
47                 CARRY <= 1'b0;
48  end
49
50  always @(posedge CLK or negedge RESET)
51  begin
52         if (RESET == 1'b0)
53             begin
54                CNT6 <= 3'b000;
55             end
56         else if (ENABLE == 1'b1 && CARRY == 1'b1)
57  //      else if (DEC == 1'b1)
58             if (DEC == 1'b1)
59                 begin
60                    if (CNT6 == 3'b101)
61                        CNT6 <= 3'b000;
62                    else
63                        CNT6 <= CNT6 + 3'b001;
64                 end
65             else
66                 begin
67                    if (CNT6 == 3'b000)
68                        CNT6 <= 3'b101;
69                    else
70                        CNT6 <= CNT6 - 3'b001;
71                 end
72  end
(省略)
リスト7 最終的な60進カウンタ(CNT60.v

 図7、リスト8のようにモジュールを接続したときのテストベンチをリスト9に示します。

最終的な60進カウンタ+7セグメントLEDデコーダのハードウェア構成 図7 最終的な60進カウンタ+7セグメントLEDデコーダのハードウェア構成
1   module CNT60_ALL(CLK, RESET, DEC, LED, SA);
2   input CLK, RESET, DEC;
3   output [7:0] LED;
4   output [3:0] SA;
5
6   reg [22:0] tmp_count;
7
8   wire [3:0] CNT10;
9   wire [2:0] CNT6;
10  wire ENABLE, ENABLE_kHz;
11  wire [7:0] LED10, LED6;
12
13  parameter SEC1_MAX = 6000000; // 6MHz
14
15  always @(posedge CLK or negedge RESET)
16  begin
17          if (RESET == 1'b0)
18                  tmp_count <= 23'h000000;
19          else if (ENABLE == 1'b1)
20                  tmp_count <= 23'h000000;
21          else
22                  tmp_count <= tmp_count + 23'h1;
23  end
24
25  assign ENABLE = (tmp_count == (SEC1_MAX - 1))? 1'b1 : 1'b0;
26  assign ENABLE_kHz = (tmp_count[11:0] == 12'hfff)? 1'b1 : 1'b0;
27
28  CNT60 i0(.CLK(CLK), .RESET(RESET), .DEC(DEC), .ENABLE(ENABLE),
29           .CNT10(CNT10), .CNT6(CNT6));
30  DECODER7 i1(.COUNT(CNT10), .LED(LED10));
31  DECODER7 i2(.COUNT({1'b0,CNT6}), .LED(LED6));
32  DCOUNT i3(.CLK(CLK), .ENABLE(ENABLE_kHz), .L1(LED10), .L2(LED6),
33          .L3(8'hff), .L4(8'hff), .SA(SA), .L(LED));
34
35  endmodule
リスト8 各モジュールのインスタンス(CNT60_ALL.v

1   module TEST_CNT60_ALL;
2   reg clk, reset, dec;
3   wire [7:0] led;
4   wire [3:0] sa;
5
6   parameter CYCLE = 100;
7   parameter SIM_SEC1_MAX = 4;
8
9   CNT60_ALL #(.SEC1_MAX(SIM_SEC1_MAX)) i1(.RESET(reset),
10                 .CLK(clk), .DEC(dec), .LED(led), .SA(sa));
11
12   always #(CYCLE/2)
13       clk = ~clk;
14
15   initial
16   begin
17      reset = 1'b0; clk = 1'b0; dec = 1'b1;
18      #CYCLE reset = 1'b1;
19      #(65*CYCLE*SIM_SEC1_MAX) dec = 1'b0;
20      #(10*CYCLE*SIM_SEC1_MAX) $finish;
21   end
22
23   initial
24      $monitor($time,,"clk=%b reset=%b dec=%b count60=%d%d", clk
, reset, dec, i1.i0.CNT6 , i1.i0.CNT10);
25
26   endmodule
リスト9 最終的な60進カウンタのテストベンチ(TEST_CNT60_ALL.v

 シミュレーション結果を画面4に示します。

最終的な60進カウンタのシミュレーション結果 画面4 最終的な60進カウンタのシミュレーション結果

Copyright © ITmedia, Inc. All Rights Reserved.