階層構造_構文編(VHDL)

階層構造_構文編(VHDL)

 HDLで設計するときに、1つのテキストファイルですべてを記述することはありません。多くの場合、仕様書に従ってブロック別に記載していきます。

 ブロック別にHDLファイルで設計する際には、1つのブロックを1つの階層で作っていきます。そして、いくつかの階層を構成して最上位にトップファイルという統括するファイルを作成します。簡単な階層構造の例を次に示します。

 一番上位にworkという記載がありますが、これは使っている統合開発環境によって違います。その一つ下のpractice_top(rtl)と記載された部分に着目してください。

 practice_top.vhdはこのプロジェクトの最上位ファイルです。先ほど、統括する。と記載しましたが、これがそのファイルです。統合開発環境を使うと、最上位ファイルはこのように上位に位置していることがツリー構造の構成図で表示されるので、わかりやすいと思います。

 困ったことに、VHDLもVerilogも言語の仕様としては自動で最上位のファイルを見つけることができません。統合開発環境だから階層構造が分かりやすいのです。これは、半年後にプロジェクトを読み解こうとすると、必ず統合開発環境を立ち上げなくてはならない。という事につながります。

 メーカーの統合開発環境は頻繁にバージョンアップを繰り返します。したがって、半年経つとバージョンが上がっていて、古いプロジェクトファイルもそれに合わせてコンバートしなくてはならない場合があります。

 このような面倒なことが起こらないように、統合開発環境以外の仕様書でツリー構造をドキュメント化しておく事をお勧めします。ファイルが多くなると大変なのですが、その時には最上位ファイルだけを判別できるようにしてください。

 最上位さえわかれば、あとはソースコードをテキストエディターで開いて追いかける事ができます。私の場合には、最上位ファイル名に必ず top を付けるようにしています。

 それでは、practice_top.vhdのファイルを見てみましょう。

--  TITLE:					"practice_top.vhd"
--  MODULE NAME:			practice_top
--  PROJECT CODE:			
--  AUTHOR:					Norio Nakahara (****@nakaharagiken.com)
--  CREATION DATE:			2020.1.1
--  SOURCE:            		
--  LICENSE:           		Copyright (c) 2020 nakaharagiken All rights reserved. 
--  DESCRIPTION:            練習用FPGAトップファイル
--  NOTES TO USER:			
--  SOURCE CONTROL:			
--  REVISION HISTORY:  	    v0.1	2020.1.2	First edition
--
--
--
--
--
--
--
--
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_unsigned.all;
use IEEE.std_logic_arith.all;


entity practice_top is
port (
	pClock:				in	std_logic;						-- system clock
	pnreset:			in	std_logic;						-- asynchronous reset 				____reset___|~~~normal~~~
	penable:			in	std_logic;						-- enable							________|~enable~|_______
	pSwitchIn_A:		in	std_logic;						-- 入力ピンからの信号A 				
	pSwitchIn_B:		in	std_logic;						-- 入力ピンからの信号B				
	pSwitchIn_C:		in	std_logic;						-- 入力ピンからの信号C 				
	pSwitchIn_D:		in	std_logic;						-- 入力ピンからの信号D				
	pinput_sel_AB:		in	std_logic;						-- 入力ピンからのセレクト信号		___input_A__|~~input_B~~~
	pinput_sel_CD:		in	std_logic;						-- 入力ピンからのセレクト信号		___input_C__|~~input_D~~~
	poutput_ans_AB:		out	std_logic;						-- A/B選択結果信号,レジスタ付き
	poutput_ans_CD:		out	std_logic						-- C/D選択結果信号,レジスタ付き
);
end entity practice_top;

architecture rtl of practice_top is

---------------------------------------------------------------
-- SIGNALS
---------------------------------------------------------------
signal	wSwitchIn_A_DFF:		std_logic;		-- pSwitchIn_Aのメタステーブル対策後 2clock遅れ
signal	wSwitchIn_B_DFF:		std_logic;		-- pSwitchIn_Bのメタステーブル対策後 2clock遅れ
signal	wSwitchIn_C_DFF:		std_logic;		-- pSwitchIn_Cのメタステーブル対策後 2clock遅れ
signal	wSwitchIn_D_DFF:		std_logic;		-- pSwitchIn_Dのメタステーブル対策後 2clock遅れ

signal	winput_sel_AB_DFF:		std_logic;		-- pinput_sel_ABのメタステーブル対策後 2clock遅れ
signal	winput_sel_CD_DFF:		std_logic;		-- pinput_sel_CDのメタステーブル対策後 2clock遅れ

signal	wseldata_AB:			std_logic;		-- pSwitchIn_A/Bのセレクト結果
signal	wseldata_CD:			std_logic;		-- pSwitchIn_C/Dのセレクト結果

---------------------------------------------------------------
-- コンポーネント宣言
---------------------------------------------------------------
component Synchronizing
port (
	clock:				in	std_logic;						-- system clock
	nreset:				in	std_logic;						-- asynchronous reset 				____reset___|~~~normal~~~
	enable:				in	std_logic;						-- enable							________|~enable~|_______
	indata:				in	std_logic;						-- 入力信号
	outdata:			out	std_logic						-- 出力信号
);
end component;

component datasel
port (
	clock:				in	std_logic;						-- system clock
	nreset:				in	std_logic;						-- asynchronous reset 				____reset___|~~~normal~~~
	enable:				in	std_logic;						-- enable							________|~enable~|_______
	SwitchIn_A:			in	std_logic;						-- 入力ピンからの信号A 				
	SwitchIn_B:			in	std_logic;						-- 入力ピンからの信号B				
	input_sel:			in	std_logic;						-- 入力ピンからのセレクト信号		___input_A__|~~input_B~~~
	output_ans:			out	std_logic						-- A/B選択結果信号,レジスタ付き
);
end component;




begin


---------------------------------------------------------------
-- pSwitchIn_Aのメタステーブル対策
---------------------------------------------------------------
inst_SwitchIn_A_Synchronizing : Synchronizing
port map(
	clock			=>	pClock,				--	in	std_logic	system clock
	nreset			=>	pnreset,			--	in	std_logic	asynchronous reset 				____reset___|~~~normal~~~
	enable			=>	'1',				--	in	std_logic	enable							________|~enable~|_______
	indata			=>	pSwitchIn_A,		--	in	std_logic	入力信号
	outdata			=>	wSwitchIn_A_DFF		--	out	std_logic	出力信号
);

---------------------------------------------------------------
-- pSwitchIn_Bのメタステーブル対策
---------------------------------------------------------------
inst_SwitchIn_B_Synchronizing : Synchronizing
port map(
	clock			=>	pClock,				--	in	std_logic	system clock
	nreset			=>	pnreset,			--	in	std_logic	asynchronous reset 				____reset___|~~~normal~~~
	enable			=>	'1',				--	in	std_logic	enable							________|~enable~|_______
	indata			=>	pSwitchIn_B,		--	in	std_logic	入力信号
	outdata			=>	wSwitchIn_B_DFF		--	out	std_logic	出力信号
);

---------------------------------------------------------------
-- pSwitchIn_Cのメタステーブル対策
---------------------------------------------------------------
inst_SwitchIn_C_Synchronizing : Synchronizing
port map(
	clock			=>	pClock,				--	in	std_logic	system clock
	nreset			=>	pnreset,			--	in	std_logic	asynchronous reset 				____reset___|~~~normal~~~
	enable			=>	'1',				--	in	std_logic	enable							________|~enable~|_______
	indata			=>	pSwitchIn_C,		--	in	std_logic	入力信号
	outdata			=>	wSwitchIn_C_DFF		--	out	std_logic	出力信号
);

---------------------------------------------------------------
-- pSwitchIn_Dのメタステーブル対策
---------------------------------------------------------------
inst_SwitchIn_D_Synchronizing : Synchronizing
port map(
	clock			=>	pClock,				--	in	std_logic	system clock
	nreset			=>	pnreset,			--	in	std_logic	asynchronous reset 				____reset___|~~~normal~~~
	enable			=>	'1',				--	in	std_logic	enable							________|~enable~|_______
	indata			=>	pSwitchIn_D,		--	in	std_logic	入力信号
	outdata			=>	wSwitchIn_D_DFF		--	out	std_logic	出力信号
);

---------------------------------------------------------------
-- pinput_sel_ABのメタステーブル対策
---------------------------------------------------------------
inst_pinput_sel_AB_Synchronizing : Synchronizing
port map(
	clock			=>	pClock,				--	in	std_logic	system clock
	nreset			=>	pnreset,			--	in	std_logic	asynchronous reset 				____reset___|~~~normal~~~
	enable			=>	'1',				--	in	std_logic	enable							________|~enable~|_______
	indata			=>	pinput_sel_AB,		--	in	std_logic	入力信号
	outdata			=>	winput_sel_AB_DFF	--	out	std_logic	出力信号
);

---------------------------------------------------------------
-- pinput_sel_CDのメタステーブル対策
---------------------------------------------------------------
inst_pinput_sel_CD_Synchronizing : Synchronizing
port map(
	clock			=>	pClock,				--	in	std_logic	system clock
	nreset			=>	pnreset,			--	in	std_logic	asynchronous reset 				____reset___|~~~normal~~~
	enable			=>	'1',				--	in	std_logic	enable							________|~enable~|_______
	indata			=>	pinput_sel_CD,		--	in	std_logic	入力信号
	outdata			=>	winput_sel_CD_DFF	--	out	std_logic	出力信号
);

---------------------------------------------------------------
-- SwitchIn_A,SwitchIn_Bの切り替え
---------------------------------------------------------------
inst_AB_datasel : datasel
port map(
	clock			=>	pClock,				--	in	std_logic						-- system clock
	nreset			=>	pnreset,			--	in	std_logic						-- asynchronous reset 				____reset___|~~~normal~~~
	enable			=>	'1',				--	in	std_logic;						-- enable							________|~enable~|_______
	SwitchIn_A		=>	wSwitchIn_A_DFF,	--	in	std_logic;						-- 入力ピンからの信号A 				
	SwitchIn_B		=>	wSwitchIn_B_DFF,	--	in	std_logic;						-- 入力ピンからの信号B				
	input_sel		=>	winput_sel_AB_DFF,	--	in	std_logic;						-- 入力ピンからのセレクト信号		___input_A__|~~input_B~~~
	output_ans		=>	wseldata_AB			--	out	std_logic						-- A/B選択結果信号,レジスタ付き
);

---------------------------------------------------------------
-- SwitchIn_C,SwitchIn_Dの切り替え
---------------------------------------------------------------
inst_CD_datasel : datasel
port map(
	clock			=>	pClock,				--	in	std_logic						-- system clock
	nreset			=>	pnreset,			--	in	std_logic						-- asynchronous reset 				____reset___|~~~normal~~~
	enable			=>	'1',				--	in	std_logic;						-- enable							________|~enable~|_______
	SwitchIn_A		=>	wSwitchIn_C_DFF,	--	in	std_logic;						-- 入力ピンからの信号A 				
	SwitchIn_B		=>	wSwitchIn_D_DFF,	--	in	std_logic;						-- 入力ピンからの信号B				
	input_sel		=>	winput_sel_CD_DFF,	--	in	std_logic;						-- 入力ピンからのセレクト信号		___input_A__|~~input_B~~~
	output_ans		=>	wseldata_CD			--	out	std_logic						-- C/D選択結果信号,レジスタ付き
);


poutput_ans_AB <= wseldata_AB;
poutput_ans_CD <= wseldata_CD;

end architecture rtl;

 統合開発環境の場合、HDLのトップファイルを図形エディターでブロック図化して描く事ができます。クライアントから、最上位はブロック図で描く事。という仕様の場合もあります。

 私個人は指示の無い限りトップファイルもHDLで記述します。それは、先に述べたように統合開発環境はバージョンアップが激しくて、トップファイルを開くのに苦労することがあるからです。

 また、トップファイルはFPGAの出力ピンに直結するファイルになります。したがって、入出力ピンの仕様や意味をコメントで記述したくなります。これも図形エディターでは残しにくい情報です。

 トップファイルに限らず、下位層と接続する場合にはコンポーネントを宣言します。上のファイルの場合、61行目がコンポーネント宣言です。71行目にもコンポーネント宣言があります。このように、下位層に接続するファイルはコンポーネント宣言します。

 コンポーネント宣言すると、それを使うことができます。初心者はココで混乱することが多いようです。92行目がコンポーネント61行目で宣言したコンポーネントを接続している部分です。Synchronizingというコンポーネントをinst_SwitchIn_A_Synchronizingという名前で接続しています。この行をインスタンスといいますが、名前は自由です。私は頭にinst_を付けるようにしています。

 インスタンス部分で、各入出力に信号を => で接続しています。矢印の向きがロジック記述と逆なので注意してください。

 104行目にも同じSynchronizingというコンポーネントを使用しています。このように、コンポーネントを使いまわすことができます。

 同じようにdataselのコンポーネントも165行目と178行目で使いまわしています。

 階層構造の書き方はそのままシミュレーションの書き方になります。コンポーネント宣言がわかりにくいですが、下位層のファイル入出力宣言をコピペして使いますので、慣れれば機械的な作業になります。