Как использовать константы и общую карту в VHDL
Создание модулей — отличный способ повторного использования кода, но часто вам нужен один и тот же модуль с меньшими вариациями в вашем дизайне. Это то, для чего предназначены дженерики и универсальная карта. Это позволяет сделать определенные части модуля настраиваемыми во время компиляции.
Константы используются, когда мы хотим избежать ввода одного и того же значения снова и снова. Их можно использовать для определения битовой ширины векторов сигналов во время компиляции, и они даже могут быть сопоставлены с универсальными константами. Константы можно использовать вместо сигналов и переменных в любом месте кода, но их значения нельзя изменить после компиляции.
Эта запись в блоге является частью серии учебных пособий по основам VHDL.
В предыдущем уроке мы создали модуль мультиплексора с 4 входами и шириной шины 8 бит. Но что, если нам нужен еще и аналогичный MUX с другой шириной шины? Единственное решение — скопировать код в новый модуль и изменить номера?
К счастью, нет.
Можно создавать константы в VHDL, используя следующий синтаксис:constant <constant_name> : <type> := <value>;
Константы можно объявлять вместе с сигналами в декларативной части VHDL-файла или вместе с переменными в процессе.
Константы можно передавать в модуль через объект с помощью generic
ключевое слово. Синтаксис создания объекта для модуля, который принимает общие константы, следующий:entity <entity_name> is
generic(
<entity_constant_name> : <type> [:= default_value];
...
);
port(
<entity_signal_name> : in|out|inout <type>;
...
);
end entity;
Синтаксис создания универсального модуля в другом файле VHDL:<label> : entity <library_name>.<entity_name>(<architecture_name>)
generic map(
<entity_constant_name> => <value_or_constant>,
...
)
port map(
<entity_signal_name> => <local_signal_name>,
...
);
Упражнение
В этом видеоруководстве мы узнаем, как создать и создать экземпляр модуля с универсальными константами в 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 -- An Instance of T16_GenericMux with architecture rtl 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); -- Testbench process 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); -- Outputs 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 => -- 'U', 'X', '-', etc. Output <= (others => 'X'); end case; end process; end architecture;
Окно сигнала в ModelSim после того, как мы нажали кнопку «Выполнить» и увеличили временную шкалу:
Анализ
Мы создали модуль MUX с настраиваемой шириной шины. Теперь ширина шины указана только в одном месте, в файле тестового стенда. Мы можем легко изменить его, чтобы создать мультиплексор с другой шириной шины.
Если мы сравним форму волны с формой из предыдущего урока, мы увидим, что поведение идентично. Это потому, что мы вообще не изменили поведение кода.
Вывод
- Константы можно использовать, чтобы избежать жесткого кодирования значений в нескольких местах.
- Универсальные шаблоны можно использовать, чтобы сделать модули более адаптируемыми.
Перейти к следующему руководству »
VHDL
- Как использовать процедуру в процессе в VHDL
- Как использовать нечистую функцию в VHDL
- Как использовать функцию в VHDL
- Как использовать процедуру в VHDL
- Как использовать константы и общую карту в VHDL
- Как использовать создание экземпляра карты портов в VHDL
- Как использовать оператор Case-When в VHDL
- Как использовать Signed и Unsigned в VHDL
- Как бесплатно установить симулятор и редактор VHDL
- Микроконтроллер PIC18:что это такое и как его использовать