- - PR -
連載第5回「階層構造を意識した設計スタイルとは?」では、10進のアップ・ダウンカウンタと7セグメントLEDのデコーダのモジュールをそれぞれインスタンスして接続し、動作させました。
最終回となる今回は、7セグメントLEDを2つ使用して、60進のアップ・ダウンカウンタを作成します。「それほど難しくないだろう」と思われるかもしれませんが、実際に何の情報もないと結構手間取ります。今回の内容は、この連載で一番強調したかった“HDLによるハードウェア設計のエッセンス”が盛り込まれていますので期待してください。
| 関連記事: | |
| いまさら聞けない FPGA入門 | |
| 連載:触って学ぼう FPGA開発入門 | |
ダイナミック点灯の原理
今回使用している「EDX-002」は、ボード上での配線の引き回しを少なくするために、7セグメントLEDの点灯に“ダイナミック点灯”の手法を使用しています。具体的な原理は図1のとおりです。
![]() |
| 図1 ダイナミック点灯の原理 |
「点灯させたい7セグメントLEDの選択を行う信号(SA)を出力し、その選択された7セグメントLEDに表示したい値を出力する」というのが基本動作です。また、EDX-002の仕様では選択されていない7セグメントLEDにはハイ・インピーダンスの信号を割り当てることになっています。
この一連の動作をリスト1に示します。
1 module DCOUNT (CLK, ENABLE, L1, L2, L3, L4, SA, L);
2 input CLK, ENABLE;
3 input [7:0] L1, L2, L3, L4;
4 output [3:0] SA;
5 output [7:0] L;
6
7 parameter MAX_COUNT = 3'b111;
8 reg [2:0] sa_count_tmp;
9 reg [3:0] sa_count;
10 reg [7:0] L_tmp;
11
12 assign SA[3] = (sa_count[3]==1'b0)? 1'b0 : 1'bz;
13 assign SA[2] = (sa_count[2]==1'b0)? 1'b0 : 1'bz;
14 assign SA[1] = (sa_count[1]==1'b0)? 1'b0 : 1'bz;
15 assign SA[0] = (sa_count[0]==1'b0)? 1'b0 : 1'bz;
16 assign L = L_tmp;
17
18 always @(posedge CLK)
19 begin
20 if (ENABLE==1'b1)
21 if (sa_count_tmp==MAX_COUNT)
22 sa_count_tmp <= 3'b000;
23 else
24 sa_count_tmp <= sa_count_tmp + 1'b1;
25 end
26
27 always @(posedge CLK)
28 begin
29 if (sa_count_tmp[0]==1'b0)
30 begin
31 sa_count <= 4'b1111;L_tmp <= L_tmp;
32 end
33 else
34 case (sa_count_tmp[2:1])
35 2'b00:begin
36 sa_count <= 4'b1110;L_tmp <= L4;
37 end
38 2'b01:begin
39 sa_count <= 4'b1101;L_tmp <= L3;
40 end
41 2'b10:begin
42 sa_count <= 4'b1011;L_tmp <= L2;
43 end
44 2'b11:begin
45 sa_count <= 4'b0111;L_tmp <= L1;
46 end
47 default:begin
48 sa_count <= 4'bxxxx;L_tmp <= 8'bxxxxxxxx;
49 end
50 endcase
51 end
52
53 endmodule
リスト1 ダイナミック点灯させるためのモジュール(dcount.v)
18〜25行目
sa_count_tmpという3bitのカウンタで0〜7までカウント。このときにENABLE信号(kHzオーダーで1回有効になる信号)が‘1’のときにのみカウントアップ
27〜51行目
このカウンタの値が奇数(sa_count_tmp[0]が‘1’)のときに、出力したい7セグメントLEDのデコーダの信号を選択
12〜15行目
選択していない7セグメントLEDにはハイ・インピーダンスを出力
今回の7セグメントLEDの2けたの点灯には、このモジュール(リスト1)を用います。
回路構成の検討
まず、60進カウンタを設計するに当たり、どのようにこのカウンタを構成するのかを考えてみましょう。
単純に考えると「0〜59」、すなわち60回カウントすればいいので、「6bitのカウンタを作成すれば簡単に実現できる! 」と思い付きます。
しかし、最終的に7セグメントLEDに出力するためには、10の位と1の位に6bitのカウンタの値を分けなくてはなりません。
分ける方法はいくつかありますが、ソフトウェア開発が得意な方の場合、
- 1の位:60進カウンタ%10(10で割った余り)
- 10の位:60進カウンタ/10(10で割った商)
で、求めることを思い浮かべるのではないでしょうか? 確かに、アルゴリズム的には正しいのですが、残念ながら上記のような「%」や「/」の使い方は、論理合成ツールがサポートしていません。つまり、回路が作成できないので、RTLではないということになります。ということで、この方法は「使用不可」です。
気を取り直して、さらに考えてみましょう。
次に思い付くのは、「6bitのカウンタの値を10の位と1の位にデコードして分ける」という方法です(リスト2)。
(省略)
8 always @(count60)
9 case (count60)
10 6'd0:{cnt10,cnt1}=7'h0_0;
11 6'd1:{cnt10,cnt1}=7'h0_1;
12 6'd2:{cnt10,cnt1}=7'h0_2;
13 6'd3:{cnt10,cnt1}=7'h0_3;
14 6'd4:{cnt10,cnt1}=7'h0_4;
15 6'd5:{cnt10,cnt1}=7'h0_5;
16 6'd6:{cnt10,cnt1}=7'h0_6;
17 6'd7:{cnt10,cnt1}=7'h0_7;
18 6'd8:{cnt10,cnt1}=7'h0_8;
19 6'd9:{cnt10,cnt1}=7'h0_9;
20 6'd10:{cnt10,cnt1}=7'h1_0;
21 6'd11:{cnt10,cnt1}=7'h1_1;
22 6'd12:{cnt10,cnt1}=7'h1_2;
23 6'd13:{cnt10,cnt1}=7'h1_3;
24 6'd14:{cnt10,cnt1}=7'h1_4;
25 6'd15:{cnt10,cnt1}=7'h1_5;
26 6'd16:{cnt10,cnt1}=7'h1_6;
27 6'd17:{cnt10,cnt1}=7'h1_7;
28 6'd18:{cnt10,cnt1}=7'h1_8;
29 6'd19:{cnt10,cnt1}=7'h1_9;
30 6'd20:{cnt10,cnt1}=7'h2_0;
31 6'd21:{cnt10,cnt1}=7'h2_1;
32 6'd22:{cnt10,cnt1}=7'h2_2;
33 6'd23:{cnt10,cnt1}=7'h2_3;
34 6'd24:{cnt10,cnt1}=7'h2_4;
35 6'd25:{cnt10,cnt1}=7'h2_5;
36 6'd26:{cnt10,cnt1}=7'h2_6;
37 6'd27:{cnt10,cnt1}=7'h2_7;
38 6'd28:{cnt10,cnt1}=7'h2_8;
39 6'd29:{cnt10,cnt1}=7'h2_9;
40 6'd30:{cnt10,cnt1}=7'h3_0;
41 6'd31:{cnt10,cnt1}=7'h3_1;
42 6'd32:{cnt10,cnt1}=7'h3_2;
43 6'd33:{cnt10,cnt1}=7'h3_3;
44 6'd34:{cnt10,cnt1}=7'h3_4;
45 6'd35:{cnt10,cnt1}=7'h3_5;
46 6'd36:{cnt10,cnt1}=7'h3_6;
47 6'd37:{cnt10,cnt1}=7'h3_7;
48 6'd38:{cnt10,cnt1}=7'h3_8;
49 6'd39:{cnt10,cnt1}=7'h3_9;
50 6'd40:{cnt10,cnt1}=7'h4_0;
51 6'd41:{cnt10,cnt1}=7'h4_1;
52 6'd42:{cnt10,cnt1}=7'h4_2;
53 6'd43:{cnt10,cnt1}=7'h4_3;
54 6'd44:{cnt10,cnt1}=7'h4_4;
55 6'd45:{cnt10,cnt1}=7'h4_5;
56 6'd46:{cnt10,cnt1}=7'h4_6;
57 6'd47:{cnt10,cnt1}=7'h4_7;
58 6'd48:{cnt10,cnt1}=7'h4_8;
59 6'd49:{cnt10,cnt1}=7'h4_9;
60 6'd50:{cnt10,cnt1}=7'h5_0;
61 6'd51:{cnt10,cnt1}=7'h5_1;
62 6'd52:{cnt10,cnt1}=7'h5_2;
63 6'd53:{cnt10,cnt1}=7'h5_3;
64 6'd54:{cnt10,cnt1}=7'h5_4;
65 6'd55:{cnt10,cnt1}=7'h5_5;
66 6'd56:{cnt10,cnt1}=7'h5_6;
67 6'd57:{cnt10,cnt1}=7'h5_7;
68 6'd58:{cnt10,cnt1}=7'h5_8;
69 6'd59:{cnt10,cnt1}=7'h5_9;
70 default:{cnt10,cnt1}=7'hx;
71 endcase
(省略)
リスト2 10の位と1の位分離デコーダ部分(cnt60_dec.v)
しかし、この方法では図2のように7セグメントLEDのデコーダの前に1の位と10の位を分けるデコーダが入るので、回路が大きくなり、LEDの出力まで考えるといままでのデコーダ出力よりも遅くなってしまいます(今回のようなLED表示に関しては、本来それほど神経をとがらせる必要はありません)。つまり、今回の場合には60進カウンタを作成するという方法は、あまり得策とはいえません。
![]() |
| 図2 60進カウンタを作成したときのハードウェア構成 |
そこで、いちいち10の位と1の位を分けるデコーダを作成することがないように、カウンタをあらかじめ「10進カウンタ」と「6進カウンタ」に分けて設計します(図3)。こうすれば、いままでと同様にカウンタの出力をそのまま7セグメントLEDのデコーダに接続できます。
![]() |
| 図3 10進と6進カウンタを作成したときのハードウェア構成 |
関連記事 半導体/エレクトロニクス
- 連載:イチから作って丸ごと学ぶ! H8マイコン道
- 特集:組み込みシステムに吹く“仮想化”の風
- 連載:組み込みマルチコア進化論(連載中)
- 連載:必修! FPGAタイミング解析の基礎(全5回)
- 連載:−ザ・組み込み−ソフトウェアのハードウェア化(連載中)
- 連載:S08ではじめるマイコン制御プログラミング(全6回)
- 連載:マイコン制御基礎の次(連載中)
- 連載:マイコン制御基礎の基礎(全10回)
- 連載:マイコン制御基礎以前(全10回)
- 連載:H8で学ぶマイコン開発入門(全13回)
- 連載:触って学ぼう FPGA開発入門(全6回)
- 連載:FPGA開発テクニック、チューニングの心得(全6回)
- 特集:いまさら聞けない FPGA入門
- 連載:バラして納得! 電子部品入門(全18回)
- 連載:完全マスター! 電子回路ドリル III(全14回)
- 連載:完全マスター! 電子回路ドリル II(全25回)
- 連載:完全マスター! 電子回路ドリル(全25回)
- 目指せ! 電子回路マスターへの道
- 目指せ! 電子回路マスターへの道 Part2
- 分かっておきたい、IP活用の落とし穴
組み込み開発フォーラム 新着記事
- フルスクラッチの“Hello World”を動かしてみよう(2011/3/31)
- FlexRayプロトコルの概要(その2)(2011/3/29)
- JASA、東北地域に拠点を置く会員企業を支援(2011/3/25)
- NEC、震災の影響を受けた4拠点の生産再開を発表(2011/3/23)
- 内部ブロック図の基礎と共通要素(2011/3/22)
- インテル、被災地におけるITインフラの復旧を支援(2011/3/22)
- Facts on AUTOSAR/AUTOSAR導入の現実(2011/3/18)
- 計測器・震災被害ホットラインを開設、テクトロニクス(2011/3/18)
- ZMP、地震の揺れを多角的に計測するアプリ無償配布(2011/3/16)
- メンター、3Dテレビ・マルチメディア検証プラットフォーム(2011/3/16)
- 【番外編】タチの良い計測値、悪い計測値とは?(2011/3/15)
- tarファイルシステムをAndroidに組み込む!!(2011/3/10)













