Не имея доступа к игровой площадке Modelsim или EDA, образец кода был проанализирован с помощью ghd, который выдает ошибки, аналогичные описанным Modelsim, которые случайно описывают реальную проблему:
ghdl -a --std=08 mbrandalero.vhdl
mbrandalero.vhdl:14:35:error: no declaration for "param_a" in package interface "p"
mbrandalero.vhdl:15:36:error: no declaration for "param_a" in package interface "p"
mbrandalero.vhdl:18:14:error: entity 'module_x' was not analyzed
mbrandalero.vhdl:33:35:error: no declaration for "param_a" in package interface "p"
mbrandalero.vhdl:34:36:error: no declaration for "param_a" in package interface "p"
mbrandalero.vhdl:37:14:error: entity 'module_y' was not analyed
ghdl:error: compilation error
(Все единицы дизайна объединены в один файл с ошибки, возникающие для объявлений сигналов портов в зависимости от PARAM_A
в Module_X
и Module_Y
.)
Проблема видимости указана в стандарте IEEE 1076-2008:
4.7 Объявления пакета
Элементы, объявленные немедленно в простом или обобщенном объявлении пакета с отображением c, становятся видимыми при выборе в пределах заданной единицы дизайна везде, где имя этого пакета видно в данной единице. Такие предметы также могут быть сделаны непосредственно видимыми с помощью соответствующего условия использования (см. 12.4). Элементы, объявленные сразу в объявлении пакета без проверки, не могут быть видны за пределами пакета.
Здесь дженерики объявляются немедленно в пакете с неустановленным экземпляром, который не был создан до разработки. Имя экземпляра пакета (p
) является видимым, но не является универсальными c константами (PARAM_A
и PARAM_B
) до разработки экземпляра компонента instance_X
в Module_Y
и предположительно entity work.Module_Y
в более высокая точка в иерархии дизайна. Это включает в себя видимость путем использования выбранных имен.
Очевидно, что экземпляры обобщенных c экземпляров не предназначены для использования в объявлениях предложений порта.
Существует ли альтернатива сопоставлению инстанцированный пакет как универсальный c?
Да. Решая проблему, показанную в примере кода, и отмечая, что вы пытаетесь использовать один и тот же экземплярный пакет вниз по иерархии дизайна, вы можете создать экземпляр пакета p в качестве основного модуля проектирования и добавить этот модуль проектирования в различные контекстные предложения (Module_X
, Module_Y
, следующий более высокий уровень в иерархии дизайна):
package generic_parameters is
generic (PARAM_A: natural; PARAM_B: natural);
end package generic_parameters;
package p is new work.generic_parameters -- ADDED primary unit declaration
generic map (PARAM_A => 4, PARAM_B => 2);
library ieee;
use ieee.std_logic_1164.all;
use work.p.all; -- ADDED use clause
entity module_X is
-- generic (package p is new work.generic_parameters generic map (<>));
port (
A: in std_logic_vector(PARAM_A - 1 downto 0); -- WAS p.PARAM_A
B: out std_logic_vector(PARAM_A - 1 downto 0) -- WAS p.PARAM_A
);
end entity module_X;
architecture RTL of module_X is
begin
B <= not(A);
end architecture RTL;
library ieee;
use ieee.std_logic_1164.all;
-- use ieee.numeric_std.all; -- NOT USED
use work.p.all; -- ADDED USE CLAUSE
entity module_Y is
-- generic (package p is new work.generic_parameters generic map (<>));
port (
A: in std_logic_vector(PARAM_A - 1 downto 0); -- WAS p.PARAM_A
B: out std_logic_vector(PARAM_A - 1 downto 0) -- WAS p.PARAM_A
);
end entity module_Y;
architecture RTL of module_Y is
begin
instance_X:
entity work.module_X
-- generic map (p => p)
port map (
A => A,
B => B
);
end architecture RTL;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.p.all;
entity module_y_tb is
end entity;
architecture foo of module_y_tb is
signal A: std_logic_vector (PARAM_A - 1 downto 0);
signal B: std_logic_vector (PARAM_A - 1 downto 0);
begin
UUT:
entity work.module_y
port map (
A => A,
B => B
);
STIMULUS:
process
begin
for i in 0 to 15 loop
A <= std_logic_vector (to_unsigned(i, A'LENGTH));
wait for 10 ns;
end loop;
wait;
end process;
end architecture;
Ввиду того, что здесь не было обобщенных предложений c, они были просто закомментированы, экземпляры пакета были элементом.
Испытательный стенд выдает:
![module_y_tb.jpg](https://i.stack.imgur.com/id4Iq.jpg)
Единственный недостаток состоит в том, что все различные первичные блоки зависят от одной и той же анализируемой библиотечной единицы (пакета *) 1045 *) заключается в том, что если это изменяет все расчетные единицы с зависимостями порядка анализа от него, требуется повторный анализ.
Существует несколько способов справиться с этим:
Предоставить несколько пакетов, чтобы уменьшить зависимость порядка анализа.
Использовать константу generi c типа записи (где su перенесено на всю цепочку инструментов). Можно добавить «запасные» элементы для использования перед повторным анализом всей затронутой части иерархии проекта. Передайте константу generi c типа записи, чтобы уменьшить сложность текста в выражениях generi c.
Значение константы записи может быть определено с использованием нечистой функции, читающей файл через текст. Это происходит во время разработки и широко поддерживается поставщиками синтеза и моделирования.
Вопросы об этих потенциальных решениях могут касаться определенных проблем c. Модифицированный пример кода, показанный выше, отвечает требованиям этого вопроса, который не требует привязки ко времени разработки. Все экземпляры пакета будут использовать пакет верхнего уровня.
Использование константы записи вместо экземпляра пакета
package generic_parameters is
generic (PARAM_A: natural; PARAM_B: natural);
type param_rec is record -- list of parameters
A: natural;
B: natural;
end record;
constant PARAM: param_rec := (PARAM_A, PARAM_B);
end package generic_parameters;
package p is new work.generic_parameters
generic map (PARAM_A => 4, PARAM_B => 2);
library ieee;
use ieee.std_logic_1164.all;
use work.p.all;
entity module_X is
generic (param: param_rec);
port (
A: in std_logic_vector(param.A - 1 downto 0);
B: out std_logic_vector(param.A - 1 downto 0)
);
end entity module_X;
architecture RTL of module_X is
begin
B <= not A;
end architecture RTL;
library ieee;
use ieee.std_logic_1164.all;
use work.p.all;
entity module_Y is
generic (param: param_rec);
port (
A: in std_logic_vector(param.A - 1 downto 0);
B: out std_logic_vector(param.A - 1 downto 0)
);
end entity module_Y;
architecture RTL of module_Y is
begin
instance_X:
entity work.module_X
generic map (param => param)
port map (
A => A,
B => B
);
end architecture RTL;
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use work.p.all;
entity module_y_tb is -- TOP LEVEL of design hierarch
end entity;
architecture foo of module_y_tb is
signal A: std_logic_vector (PARAM_A - 1 downto 0);
signal B: std_logic_vector (PARAM_A - 1 downto 0);
constant tb_param: param_rec := (A => 4, B => 2);
begin
UUT:
entity work.module_y
generic map (param => param)
port map (
A => A,
B => B
);
STIMULUS:
process
begin
for i in 0 to 15 loop
A <= std_logic_vector (to_unsigned(i, A'LENGTH));
wait for 10 ns;
end loop;
wait;
end process;
end architecture;
Это позволит выполнять замены для каждого родового c отображать так же, как при создании экземпляра пакета, с учетом ограничений, требующих сопоставления элементов между формальными и фактическими значениями в списках ассоциаций портов.