はじめに
VHDLでは、パッケージを使って関数や定数を定義した際、パッケージ名.関数名 という形で呼び出すことが出来ます。
パッケージがたくさんあって名前がかぶったりした時や、どの関数がどのパッケージに含まれているのか一目瞭然なので、大変重宝していたのですが、どうやら Altera の Quartus では上手くいかないことがあるようです。
おそらくこちら(Altera の Quartus で引数の有無が混在した多重定義関数をVHDLで記述する際の注意点)も根っこは同じ原因かと思われます。
トラブルが発生した環境
- Altera 社 Quartus Prime Verion 15.1.0 Build 185 10/21/2015 SJ Lite Edition
トラブルが発生した VHDL 記述
次のようにパッケージ内に引数の無い関数を定義しておきます。
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package Sample_Code is
subtype Code_Type is std_logic_vector(3 downto 0);
type Code_Vector is array (integer range <>) of Code_Type;
function New_Code_Null return Code_Type;
function New_Code_Full return Code_Type;
end Sample_Code;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package body Sample_Code is
function New_Code_Null return Code_Type is begin
return std_logic_vector'("0000");
end function;
function New_Code_Full return Code_Type is begin
return std_logic_vector'("1111");
end function;
end Sample_Code;
で、パッケージで定義した関数を、配列のインデックスの位置にパッケージ名.関数名という形で呼び出します。
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity Sample is
port (S: in std_logic; O: out std_logic_vector(3 downto 0));
end Sample;
use work.Sample_Code;
architecture RTL of Sample is
constant CODE_VEC : Sample_Code.Code_Vector(1 downto 0) := (
1 => Sample_Code.New_Code_Full,
0 => Sample_Code.New_Code_Null
);
begin
O <= CODE_VEC(1) when (S = '1') else CODE_VEC(0);
end RTL;
トラブル内容
すると、何故か、関数呼び出しのところでエラーが発生します。
Info: *******************************************************************
Info: Running Quartus Prime Analysis & Synthesis
Info: Version 15.1.0 Build 185 10/21/2015 SJ Lite Edition
Info: Processing started: Thu Feb 04 17:13:38 2016
Info: Version 15.1.0 Build 185 10/21/2015 SJ Lite Edition
Info: Processing started: Thu Feb 04 17:13:38 2016
Info: Command: quartus_map --read_settings_files=on --write_settings_files=off sample_altera -c sample_altera
Warning (20028): Parallel compilation is not licensed and has been disabled
Info (12021): Found 2 design units, including 0 entities, in source file sample_code.vhd
Info (12022): Found design unit 1: Sample_Code
Info (12022): Found design unit 2: Sample_Code-body
Info (12022): Found design unit 1: Sample_Code
Info (12022): Found design unit 2: Sample_Code-body
Info (12021): Found 2 design units, including 1 entities, in source file sample.vhd
Info (12022): Found design unit 1: Sample-RTL
Info (12023): Found entity 1: Sample
Info (12022): Found design unit 1: Sample-RTL
Info (12023): Found entity 1: Sample
Info (12127): Elaborating entity "sample" for the top level hierarchy
Error (10487): VHDL aggregate error at sample.vhd(10): aggregate for array type or record type object must cover all elements of object
Error (12153): Can't elaborate top-level user hierarchy
Error: Quartus Prime Analysis & Synthesis was unsuccessful. 2 errors, 1 warning
Error: Peak virtual memory: 854 megabytes
Error: Processing ended: Thu Feb 04 17:14:00 2016
Error: Elapsed time: 00:00:22
Error: Total CPU time (on all processors): 00:00:54
Error: Peak virtual memory: 854 megabytes
Error: Processing ended: Thu Feb 04 17:14:00 2016
Error: Elapsed time: 00:00:22
Error: Total CPU time (on all processors): 00:00:54
解決策1
次のように sample_ng.vhd を修正すると通ります。どうやらパッケージ名.関数名だとダメで、関数名だけだといいみたいです。
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity Sample is
port (S: in std_logic; O: out std_logic_vector(3 downto 0));
end Sample;
use work.Sample_Code.all;
architecture RTL of Sample is
constant CODE_VEC : Code_Vector(1 downto 0) := (
0 => New_Code_Null,
1 => New_Code_Full
);
begin
O <= CODE_VEC(1) when (S = '1') else CODE_VEC(0);
end RTL;
解決策2
次のように配列のインデックスを指定しなければ、エラーが出ないようです。。。(なんでやねん)
この方法ではもっとヒドい目にあいました。詳細は「Altera の Quartus でVHDLパッケージの引数無しの関数を呼び出すときの注意点(続編)」を参照してください。
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity Sample is
port (S: in std_logic; O: out std_logic_vector(3 downto 0));
end Sample;
use work.Sample_Code;
architecture RTL of Sample is
constant CODE_VEC : Sample_Code.Code_Vector(1 downto 0) := (
Sample_Code.New_Code_Full,
Sample_Code.New_Code_Null
);
begin
O <= CODE_VEC(1) when (S = '1') else CODE_VEC(0);
end RTL;