順序回路と組み合わせ回路を意識した記述を!:触って学ぼう FPGA開発入門(6)(4/4 ページ)
7セグメントLEDを2つ使用して、60進のアップ・ダウンカウンタを作成。“無駄な資源を食わない回路”を設計するには? そのポイントを紹介
順序回路と組み合わせ回路を意識
これで60進の動作を確認できます。なお、LEDの表示がアン・ノンになっていますが、これはダイナミック点灯用のイネーブル信号(ENABLE_kHz)が、このシミュレーションでは出力されないためです。すでに実績のあるモジュールなので、あえてこの部分のシミュレーションは省略しました。
リスト8のCNT60_ALL.vをRTLのトップモジュールとして、CNT60.v、dcount.v、DECODER7.vをプロジェクトに追加し、リスト10をピン固定ファイルとし(前回のピン固定ファイルとSAの部分が異なっているので注意)、論理合成、配置配線を行い、その後ボードにダウンロードします。
いかがでしょうか? 7セグメントLEDの右側2けたで、60秒のアップダウン動作を確認できるはずです。
(省略) 4 NET "CLK" LOC = "P39" ; 5 NET "RESET" LOC = "P17" ; 6 NET "DEC" LOC = "P16" ; 7 NET "LED<0>" LOC = "P41" ; 8 NET "LED<1>" LOC = "P40" ; 9 NET "LED<2>" LOC = "P31" ; 10 NET "LED<3>" LOC = "P30" ; 11 NET "LED<4>" LOC = "P22" ; 12 NET "LED<5>" LOC = "P21" ; 13 NET "LED<6>" LOC = "P20" ; 14 NET "LED<7>" LOC = "P19" ; 15 NET "SA<0>" LOC = "P46" ; 16 NET "SA<1>" LOC = "P45" ; 17 NET "SA<2>" LOC = "P44" ; 18 NET "SA<3>" LOC = "P43" ; (省略)
リスト10 ピン固定ファイル(CNT60_ALL.ucf) |
「いちいちキャリーの作成なんて面倒! 」と思う方もいらっしゃるかもしれません。そこで、6進カウンタの方で10進カウンタの値をそのまま見るという例をリスト11に示します。
1 module CNT60(CLK, RESET, DEC, ENABLE, CNT10, CNT6); 2 input CLK, RESET, DEC, ENABLE; 3 output [3:0] CNT10; 4 output [2:0] CNT6; 5 6 reg [3:0] CNT10; 7 reg [2:0] CNT6; 8 //reg CARRY; 9 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 /* 37 always @(CNT10 or DEC) 38 begin 39 if (DEC == 1'b1) 40 if (CNT10 == 4'h9) 41 CARRY <= 1'b1; 42 else 43 CARRY <= 1'b0; 44 else 45 if (CNT10 == 4'h0) 46 CARRY <= 1'b1; 47 else 48 CARRY <= 1'b0; 49 end 50 */ 51 52 always @(posedge CLK or negedge RESET) 53 begin 54 if (RESET == 1'b0) 55 begin 56 CNT6 <= 3'b000; 57 end 58 else if (ENABLE == 1'b1) 59 // else if (ENABLE == 1'b1 && CARRY == 1'b1) 60 // else if (DEC == 1'b1) 61 if (DEC == 1'b1) 62 begin 63 if (CNT10 == 4'h9) 64 if (CNT6 == 3'b101) 65 CNT6 <= 3'b000; 66 else 67 CNT6 <= CNT6 + 3'b001; 68 end 69 else 70 begin 71 if (CNT10 == 4'h0) 72 if (CNT6 == 3'b000) 73 CNT6 <= 3'b101; 74 else 75 CNT6 <= CNT6 - 3'b001; 76 end 77 end 78 79 endmodule
リスト11 最終的な60進カウンタ(CNT60-2.v) |
この方法では、確かにキャリーの信号を作成する必要はありません。しかし、この部分も非常に大事で「==4'h9」と書いた部分は「組み合わせ回路(コンパレータ)からの出力なんだ」ということを意識しないといけないのです。
順序回路を記述している場合でも、“if文の「()」の中の条件などは、組み合わせ回路で作成されているんだ”ということを忘れないでください。
HDLソース中のif文などで同じ条件式を繰り返し記述していると、論理合成が同じ組み合わせ回路を“至る所で”作成している可能性があり、それによって回路を大きくしている場合もあるのです。無駄な資源を食わない回路の方がハードウェアとしては優秀です。特に、FPGAの資源が豊富にあるからといって、図5のような無駄な回路を作成しているようでは、ハードウェア設計者として合格点はもらえないでしょう。
最終回である今回は、設計の肝となる「順序回路と組み合わせ回路を意識しながらHDLを記述する」ことについて解説しました。HDLは、あくまでもハードウェアを設計するための記述言語ですので、設計の良しあしは記述する人がすべて握っています。できるだけ無駄なハードウェアを生成しないで、良い設計を行いましょう。
では、どうしたらそうなれるのか? ひとえに場数しかないと思います。HDLを記述してはツールでハードウェアに落として、FPGAのボードで試してみることです。昔は、こんなことをやりたくても途方もないお金を掛けないとできませんでした。現在はFPGAというデバイスがあって、ミスしても書き直せますし、非常に短時間で本物の回路を作成できます。
ハードウェア設計者の減少が叫ばれている今日このごろ、これを機会に1人でも多くの方々がFPGA設計を通して、ハードウェア設計に興味を持ってもらえたらと、切に願う次第です。(連載完)
Copyright © ITmedia, Inc. All Rights Reserved.