VHDLのテンプレートを紹介

VHDLのテンプレートを紹介

 初心者がVHDLを記述するにあたり、構文を学ぶ必要があります。コンピュータ言語と同じようにVHDLやVerilogなどのハードウェア記述言語にも構文があります。

 まず、VHDLを記述するにあたり、テキストエディターでファイルを作ります。Intel社やXilinx社などのFPGAメーカーが提供している開発環境を使う場合には、テキストエディターは無くても構いません。開発環境に組み込まれています。しかし、日本語が使えない事が多いので、私はテキストエディターを別途用意しています。

 VHDLを記述するにあたり、大文字と小文字は関係ありません。”Test”も”test”も同じとみなされますので注意してください。また、よくある過ちの中で、全角スペースがあります。日本語文字(半角カタカナ含)や全角文字はコメントでは使えますが、構文の中では使わないルールです。

 まず全体の構成を示します。上から「ライブラリ宣言」「エンティティ」「アーキテクチャ」の順に記述します。最後にテンプレートを記述しますので、それも参照してください。

 ライブラリ宣言の所には、VHDLのパッケージやライブラリを記述します。VHDL標準のパッケージもありますし、自分で作ることもできますが、初心者はオマジナイだと思っていて良いと思います。上達してくると、VHDLで記述したい内容によって使うパッケージやライブラリが増えていきます。それまでは、上記のマネをしていてください。

 エンティティは「外部とのインタフェース」を記述します。最近はIT用語としてもエンティティという言葉を使うようになってきました。エンティティー名というのは、VHDLの部品名だと思ってください。

 部品(=エンティティ)は1つのファイルの中に何個書いても良いのですが、慣れるまでは1つにしておきましょう。そしてエンティティ名=ファイル名としておくと、後からエンティティを探すのに便利です。

 エンティティ名の命名規則というのもありますが。VHDLの予約語は使えません。特殊文字(*,^,<,>など)も使えません。命名規則は特に覚える必要はなく、使ってはイケない文字を使った場合には、コンパイラがエラーを出しますので、その都度確認すれば良いでしょう。

 普通にアルファベット(大文字、小文字、数字)と”_”で作っておけば間違いありません。VHDLで作りたい名前にします。hogeなどの意味のない名前は使わないようにします。数字は最初と最後には使わないようにするのが良いでしょう。

 エンティティ部のイメージを示します。作りたいモ部品と考えてください。部品というのは、プログラムの高級言語(C言語など)でいうところの関数と同じ考えです。

 すると、上図のように例えば、足し算をするような回路を作る場合、エンティティ名は”plus”としました。IOピンはそのモジュールの入力・出力ピンです。これらをまとめて、エンティティ部に記載します。

 前にも記載しましたが、エンテイティ=ファイル名とするとわかりやすいので、この場合はplus.vhdというファイル名のテキストファイルを作成します。

 記載の方法はいろいろとあります。私は1行に1つの入力ピンもしくは出力ピンを記載するようにしています。このようにすることで、各ピンのコメントを記載しやすくしています。1行に何本ものピンを記載する人もいます。

 エンティティは本来、()で囲われた中にピンを記載するので、ピン記載の最後には;がありませんので注意してください。たとえば以下のようになります。

entity plus is port(
dat_a: in std_logic;
dat_c: in std_logic;
dat_out out std_logic
); end plus;

このような記載の場合でも、()で囲われた部分に着目した書き方をすると

entity plus is port(dat_a: in std_logic; dat_c: in std_logic; dat_out out std_logic);
end plus;

というような記載になります。したがって、()で囲われた最後の記述には;が無い事に注意してください。

 以上をまとめると次のような記述方法になります。赤線が引かれた部分は決まった事なので、そのままマネします。

 次にアーキテクチャ部を記述します。アーキテクチャ部には、回路の中身を書きます。ここがVHDLで「設計」する部分になります。一つのエンティティにいくつもアーキテクチャを作ることができますが、私は一つのエンティティに一つのアーキテクチャを作っています。周りのエンジニアもほぼ同様です。つまり、一つのファイルに一つのエンティティ、一つのアーキテクチャとすることで、メンテナンス性を良くしています。

 アーキテクチャ名も自由に記述できるのですが、一般的にアーキテクチャ名は内部の構造を示す名称にするので、論理合成用のソースコードかシミュレーション用のソースコードかの区別としている事が多いようです。

 たとえば、アーキテクチャ名として、RTLと記述すれば論理合成用(つまり回路設計)、SIMとすればシミュレーション用。という具合です。

 他に見たことのある命名例としては、behavior、Simulation、bodyなどです。多くのエンジニアはアーキテクチャ名を自由に記述することはありません。回路記述用途のファイルなのか、シミュレーション用のファイルなのか。という2択ぐらいの範囲です。

 アーキテクチャ名はどうするのか? という質問は多いのですが、あまり悩まずにRTLかSIMしか使わない。という事で問題ありません。

 アーキテクチャ部の構造は以下のようになっています。赤線が引かれた部分は決まった事なので、そのままマネします。

 良く忘れるのが最後の 「end アーキテクチャ名;」 です。アーキテクチャ名をRTLとしたならば、最後も 「end RTL; 」で終わり。という事になります。

 VHDLを設計する上で以上のような書式にしたがってファイルを作成するのですが、これらの順序だとか単語を毎回記述していると間違いも起きますので、tンプレートを用意して、そのファイルをベースとして設計を行うと便利です。

 以下にVHDLのテンプレート例を紹介します。回路は適当なので動作しません。

----------------------------------------------------------------------------------------------------
--  TITLE:					vhdl_template.vhd						
--  MODULE NAME:			vhdl_template							
--  PROJECT CODE:													
--  AUTHOR:															
--  CREATION DATE:													
--  SOURCE:            												
--  LICENSE:           		Copyright (c) 2021 nakaharagiken.com	
--  DESCRIPTION:            										
--  NOTES TO USER:      											
--  REVISION HISTORY:  	    v0.1									
--
--
--
--
--
--


-------------------------------------------------------------
-- ライブラリ宣言
-------------------------------------------------------------
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
use IEEE.std_logic_arith.all;

-------------------------------------------------------------
-- エンティティ宣言
-------------------------------------------------------------
entity vhdl_template is port(
	clock:					in		std_logic;
	nreset:					in		std_logic;
	aaaa:					in		std_logic;
	bbbb:					out		std_logic;
	cccc:					inout	std_logic_vector(7 downto 0);
	dddd:					in		std_logic_vector(7 downto 0);
	eeee:					out		std_logic
);
end vhdl_template;


-------------------------------------------------------------
-- アーキテクチャ宣言
-------------------------------------------------------------
architecture RTL of vhdl_template is

-- 内部シグナル
signal		raa:					std_logic;
signal		rbb:					std_logic_vector(7 downto 0);
signal		rcc:					std_logic_vector(7 downto 0);
signal		wdd:					std_logic;
signal		wee:					std_logic_vector(7 downto 0);

-- 定数記述
constant	BANDNUM:				std_logic_vector(12 downto 0) := "0000000011001";

-- 変数記述
type		STATE_S is (S0,S1,S2,S3);
signal		STATE:					STATE_S;

-- 下位モジュールのエンティティ名
component comm
port(
	band_val:				in		std_logic_vector(12 downto 0);
	DATA_IN:				in		std_logic_vector(7 downto 0);
	RX:						in		std_logic;
	DATA_OUT:				out		std_logic_vector(7 downto 0);
	TX:						out		std_logic;
);
end component;


begin	-- architecture の begin

-- 下位モジュールの接続
inst_comm : comm
port map(
	band_val		=>	BANDNUM,
	DATA_IN			=>	rbb,
	RX				=>	raa,
	DATA_OUT		=>	wee,
	TX				=>	wdd
);

-- 順序回路
process (clock,nreset) begin
	if nreset = '0' then
		raa	<= '0';
		rbb	<= (others => '0');
		rcc	<= (others => '0');
		STATE <= S0;
	elsif clock' event and clock = '1' then
		case STATE is
			when S0 =>	if (wdd = '1') then	
							STATE <= S1;
						else
							STATE <= S0;
						end if;
						raa	<= '0';
						rbb	<= (others => '0');
						rcc	<= (others => '0');
			when S1 =>	raa	<= '0';
						rbb	<= cccc;
						STATE <= S2;
			when S2 =>	raa	<= '1';
						rcc	<= wee;
						STATE <= S3;
			when S3 =>	raa	<= '0';
						STATE <= S0;
			when others => STATE <= S0;
		end case;
	end if;
end process;

-- 組合せ回路、出力
bbbb <= wdd;
cccc <= rcc when (raa = '1') else dddd;
eeee <= raa

end RTL;	-- アーキテクチャ宣言の end