VHDLの構造化プログラミング手法
−コンポーネントを用いたタイマー回路の設計−
ver.2 (2007.5.7)
井澤 裕司
1.はじめに
本章では,「
VHDL
」 の「
構造化プログラミング手法
」 として,「
コンポーネント
」 を用いた
回路記述方法について,解説します.
「
回路規模
」 が大きくなると,「
VHDLのソースコード
」 が肥大化し,「
全体の構造
」 が把握し難く,
「
拡張性
」 ,「
汎用性
」 に欠ける記述となってしまいます.
これを避けるため,目的とする回路の機能や構造を分析して,単純ながら 「
汎用性
」 のある 「
部品
」 を,
「
コンポーネント
」 として定義し,
これを「
階層的
」 に組み合わせる「
構造化プログラミング
」 が用いられます.
本授業の目的である 「
CPUの設計
」 にも,この 「
構造化プログラミング
」を用いていますので,
使いこなせるよう,しっかり学習して下さい.
2.タイマーの回路構成
ここでは,例として 2つの 「
7セグメントLED
」を用いた「
タイマー回路
」を設計します.
具体的には,「
カウンタ
」を用いて「
24MHzのクロック
」を分周し,ほぼ「
1Hzのクロック
」を生成します.
次に,このクロックを2つの 「
10進カウンタ
」 に入力して 「
00
」から「
99
」 までの 「
2桁の数字
」 を,
2つの「
7セグメントLED
」に表示する回路を設計します.
なお,今回は「
分周カウンタ
」 と2つの 「
10進カウンタ
」 をまとめて,1つの「
部品
」すなわち,
「
コンポーネント
」 として記述します.
また,「
0000
」から「
1001
」 までの 「
2進化10進符号
」を入力とし,「
7セグメントLED
」を制御する
「
デコーダ回路
」も,
「
コンポーネント
」 として記述します.
以下に,設計する 「
タイマー回路
」 の回路構成を示します.
3. コンポーネントの仕様
(1)
カウンタ ( counter )
コンポーネント名 | counter |
入 力 | クロック CLK |
出 力 |
@ 2進化10進符号(上位)
CNT_TMP_H
(
"0000"〜"1001"
) A 2進化10進符号(下位) CNT_TMP_L ( "0000"〜"1001" ) |
(2)
デコーダ ( decoder )
コンポーネント名 | decoder |
入 力 |
2進化10進符号
CNT_TMP_X
(
"0000"〜"1001"
) |
出 力 |
7セグメントLED駆動信号
LED_X
(
"abcdefg1"
) |
上で述べた 「
コンポーネントの仕様
」 に従って,具体的な「
VHDL
」 を記述します.
はじめに,「
counter
」 ,次に 「
decoder
」 の 「
VHDL
」を記述します.
最後に,「
timer
」 本体を記述し,その中で上記回路を「
コンポーネント
」 として呼び出します.
「
コンポーネント
」 を呼び出す場合は,
本体の先頭に,例えば 「
component counter
」 〜 「
end component;
」のような記述が必要となります.
これらは「
counter
」 本体の「
entity counter is
」 〜 「
end counter;
」をコピーして編集すればよいでしょう.
「
timer
」 本体で,1つの「
counter
」 と2つの「
decoder
」を,それぞれ「
C1
」,「
C2
」,「
C3
」のように定義し,
「
入出力信号
」と「
signal文
」で定義した「
内部信号
」を用いて,それらの接続関係を記述します.
なお,「
counter
」 や 「
decoder
」 の 「
VHDL
」を「
別ファイル
」に分けて記述することもできます.
その場合は,ファイルを同じ「
プロジェクトフォルダ
」 の中に保存して,「
プロジェクト管理のコマンド
」 を用い,
「
同じプロジェクト
」 として登録する必要があります.
例えば 「
QuartusU
」の場合は,メニューの「
Project
」 , 「
Add/Remove Files in Project
」の
のコマンドを使用します.
timer.vhd
-- timer.vhd
-- Y.Izawa
-- H19.5.1
library
IEEE;
use
IEEE.std_logic_1164.
all
;
use
IEEE.std_logic_unsigned.
all
;
entity counter is | |||||
port ( | |||||
CLK | : | in | std_logic ; | ||
CNT_L | : | out | std_logic_vector(3 downto 0); | ||
CNT_H | : | out | std_logic_vector(3 downto 0) | ||
); | |||||
end counter; |
architecture
RTL
of
counter
is
signal | C_TIMER | : | std_logic_vector (23 downto 0); |
signal | C_TMP_L | : | std_logic_vector (3 downto 0); |
signal | C_TMP_H | : | std_logic_vector (3 downto 0); |
begin | |||||||
process (CLK) | |||||||
begin | |||||||
if (CLK'event and CLK = '1') then | |||||||
if C_TIMER = "111111111111111111111111" then | |||||||
C_TIMER <= "000000000000000000000000" ; | |||||||
if C_TMP_L = "1001" then | |||||||
C_TMP_L <= "0000" ; | |||||||
if C_TMP_H = "1001" then | |||||||
C_TMP_H <= "0000" ; | |||||||
else | |||||||
C_TMP_H <= C_TMP_H + 1; | |||||||
end if ; | |||||||
else | |||||||
C_TMP_L <= C_TMP_L + 1; | |||||||
end if ; | |||||||
else | |||||||
C_TIMER <= C_TIMER + 1; | |||||||
end if ; | |||||||
end if ; | |||||||
end process ; | |||||||
CNT_L <= C_TMP_L; | |||||||
CNT_H <= C_TMP_H; | |||||||
end RTL; |
library
IEEE;
use
IEEE.std_logic_1164.
all
;
use
IEEE.std_logic_unsigned.
all
;
entity decoder is | |||||
port ( | |||||
CNT | : | in | std_logic_vector(3 downto 0); | ||
LED | : | out | std_logic_vector(7 downto 0) | ||
); | |||||
end
decoder; |
architecture RTL of decoder is | ||||||
begin | ||||||
process (CNT) | ||||||
begin | ||||||
case CNT is | ||||||
when "0000" => LED <= "00000011" ; | -- 0 | |||||
when "0001" => LED <= "10011111" ; | -- 1 | |||||
when "0010" => LED <= "00100101" ; | -- 2 | |||||
when "0011" => LED <= "00001101" ; | -- 3 | |||||
when "0100" => LED <= "10011001" ; | -- 4 | |||||
when "0101" => LED <= "01001001" ; | -- 5 | |||||
when "0110" => LED <= "01000001" ; | -- 6 | |||||
when "0111" => LED <= "00011111" ; | -- 7 | |||||
when "1000" => LED <= "00000001" ; | -- 8 | |||||
when "1001" => LED <= "00001001" ; | -- 9 | |||||
when others => LED <= "11111111" ; | ||||||
end | case ; | |||||
end process ; | ||||||
end RTL; |
library
IEEE;
use
IEEE.std_logic_1164.
all
;
use
IEEE.std_logic_unsigned.
all
;
entity timer is | |||||
port | |||||
( | |||||
CLK | : | in | std_logic ; | ||
LED_L | : | out | std_logic_vector(7 downto 0); | ||
LED_H | : | out | std_logic_vector(7 downto 0) | ||
); | |||||
end
timer; |
architecture RTL of timer is | |||||||||
component counter | |||||||||
port | |||||||||
( | |||||||||
CLK | : | in | std_logic; | ||||||
CNT_L | : | out | std_logic_vector(3 downto 0); | ||||||
CNT_H | : | out | std_logic_vector(3 downto 0) | ||||||
); | |||||||||
end component ; | |||||||||
component decoder | |||||||||
port | |||||||||
( | |||||||||
CNT | : | in | std_logic_vector(3 downto 0); | ||||||
LED | : | out | std_logic_vector(7 downto 0) | ||||||
); | |||||||||
end component; |
signal | CNT_TMP_L | : | std_logic_vector(3 downto 0); | |||||||
signal | CNT_TMP_H | : | std_logic_vector(3 downto 0); |
begin | |||||||||
C1 | : | counter | port | map | (CLK, CNT_TMP_L, CNT_TMP_H); | ||||
C2 | : | decoder | port | map | (CNT_TMP_L, LED_L); | ||||
C3 | : | decoder | port | map | (CNT_TMP_H, LED_H); | ||||
end RTL; |
5. FPGAへの実装
最後に,設計した回路を下のような「
FPGAの評価ボード
」 へ実装して,動作の確認を行います.
このボードは「
CQ出版社
」 の「
FLEX10KE評価キット
」 という機種で,
約「
1700
」 の「
ロジック・エレメント
」 が使用できます.
「
QuartusU
」 のメニュー 「
Assignments
」 から,使用する「
FPGAデバイス
」 を選択します.
「
Family
」 には 「
FLEX10KE
」, 「
Device
」 には 「
EPF10K30EQC208-3
」 を設定して下さい.
次に,メニューの 「
Assignments
」 から 「
Pins
」 を選択して,「
入出力ピンの設定
」 を行います.
上で示した「
タイマー回路
」 の「
回路構成
」 を参照して,
使用する「
ピン番号
」 を入力します.
なお,「
茶色の数字
」が「
ピン番号
」 を表しています.
これらの詳細については,「
VHDL開発ツール(QuartusU)の使用法
」 の第7章
「
FPGAデバイスの設定と入出力ピンの配置
」 を参照して下さい.
6. まとめ
本章では,「
VHDL
」 の「
構造化プログラミング手法
」 として,「
コンポーネント
」 を用いた
回路記述方法を紹介しました.
「
CPUの設計
」 にも,この 「
構造化プログラミング
」を用いていますので,
使いこなせるよう,努力して下さい.
「
疑問点
」 や「
不明な点
」 ,「
解りにくい箇所
」 がありましたら,メール等でご連絡いただければ幸いです.