VHDLで定数とジェネリックマップを活用し柔軟なモジュール設計を実現
再利用可能なモジュールを作成することは効率的なVHDL設計の基盤ですが、微細なバリエーションが重複コードを強いることがあります。ジェネリックとジェネリックマップは、モジュールのパラメータをコンパイル時に構成可能にし、コードをDRY(Don't Repeat Yourself)かつ保守しやすく保ちます。
定数は同じ値を繰り返しハードコーディングすることを防ぎます。信号ベクトル幅や他のコンパイル時パラメータの定義に最適で、ジェネリック定数にマッピングすることもできます。シグナルや変数とは異なり、定数の値はエラボレーション後に不変であり、設計全体で一貫性を保証します。
この記事はBasic VHDL Tutorialsシリーズの一部です。
前回のチュートリアルでは、バス幅8ビットの4入力マルチプレクサを作成しました。今度は異なる幅の類似MUXが必要になった場合、モジュール全体をコピペするだけが選択肢ではありません。
代わりに、希望バス幅を保持する定数を宣言し、その定数をモジュールにジェネリックとして渡します。幅を変更する必要がある場所は、テストベンチ内の定数宣言のみです。
VHDLでの定数宣言構文:
constant <constant_name> : <type> := <value>;
定数はファイルの宣言部でシグナルと共に、またはプロセス内で変数と共に配置できます。
モジュールに定数を公開するには、エンティティ宣言でgenericキーワードを使用:
entity <entity_name> is
generic(
<entity_constant_name> : <type> [:= default_value];
...
);
port(
<entity_signal_name> : in|out|inout <type>;
...
);
end entity;
ジェネリックモジュールを他の場所でインスタンス化する際は、ジェネリックマップとポートマップを使用:
<label> : entity <library_name>.<entity_name>(<architecture_name>)
generic map(
<entity_constant_name> => <value_or_constant>,
...
)
port map(
<entity_signal_name> => <local_signal_name>,
...
);
演習
このビデオチュートリアルでは、ジェネリック4入力MUXモジュールの作成とインスタンス化をVHDLで歩いていきます。
テストベンチ – ジェネリックMUX
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity T16_GenericMapTb is
end entity;
architecture sim of T16_GenericMapTb is
constant DataWidth : integer := 8;
signal Sig1 : signed(DataWidth-1 downto 0) := x"AA";
signal Sig2 : signed(DataWidth-1 downto 0) := x"BB";
signal Sig3 : signed(DataWidth-1 downto 0) := x"CC";
signal Sig4 : signed(DataWidth-1 downto 0) := x"DD";
signal Sel : signed(1 downto 0) := (others => '0');
signal Output : signed(DataWidth-1 downto 0);
begin
i_Mux1 : entity work.T16_GenericMux(rtl)
generic map(DataWidth => DataWidth)
port map(
Sel => Sel,
Sig1 => Sig1,
Sig2 => Sig2,
Sig3 => Sig3,
Sig4 => Sig4,
Output => Output
);
process is
begin
wait for 10 ns; Sel <= Sel + 1;
wait for 10 ns; Sel <= Sel + 1;
wait for 10 ns; Sel <= Sel + 1;
wait for 10 ns; Sel <= Sel + 1;
wait for 10 ns; Sel <= "UU";
wait;
end process;
end architecture;
ジェネリックMUXモジュール
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity T16_GenericMux is
generic(DataWidth : integer);
port(
-- Inputs
Sig1 : in signed(DataWidth-1 downto 0);
Sig2 : in signed(DataWidth-1 downto 0);
Sig3 : in signed(DataWidth-1 downto 0);
Sig4 : in signed(DataWidth-1 downto 0);
Sel : in signed(1 downto 0);
-- Output
Output : out signed(DataWidth-1 downto 0)
);
end entity;
architecture rtl of T16_GenericMux is
begin
process(Sel, Sig1, Sig2, Sig3, Sig4) is
begin
case Sel is
when "00" => Output <= Sig1;
when "01" => Output <= Sig2;
when "10" => Output <= Sig3;
when "11" => Output <= Sig4;
when others => Output <= (others => 'X');
end case;
end process;
end architecture;
ModelSim波形(タイムラインにズームイン):

分析
テストベンチでDataWidthを一度定義するだけで、モジュールコードに触れずに任意のバス幅に同じMUXを適応できます。波形はハードコード版と同一機能を確認。

まとめ
- 定数は繰り返しハードコード値を排除し、可読性向上とエラー削減に寄与。
- ジェネリックはモジュールを高度に構成可能にし、設計全体での再利用性を高める。
次のチュートリアルへ »
VHDL
- PIC18マイクロコントローラ:特徴、性能、使い方
- プロセス内プロシージャでVHDLステートマシンをクリーンに設計
- VHDLにおける不純関数の活用:FSMの可読性と保守性向上
- VHDL関数マスター:効率的な設計のための実践ガイド
- VHDLプロシージャ活用:再利用可能なコードで設計をシンプルに
- VHDLで定数とジェネリックマップを活用し柔軟なモジュール設計を実現
- VHDLポートマップインスタンス化マスター:実践ガイド
- VHDLのCase-When文マスター:効率的なマルチプレクサ設計
- VHDLのsigned/unsigned型マスター:実践ガイド
- VHDLの条件分岐をマスター:If-Then-Elsif-Else の完全解説
- 無料VHDLシミュレータ&エディタ導入ガイド:学生向けステップバイステップ