Переменные в VHDL: практические примеры и правила для надежного дизайна
В VHDL переменные ведут себя похоже на переменные C: их значение доступно сразу после присваивания и остается неизменным до следующего присваивания. Это делает их идеальными для временного хранения и процедурных вычислений внутри процесса.
Ключевые правила использования переменных в VHDL
- Переменные ограничены процессом, в котором они объявлены.
- У каждого процесса свой набор переменных; они не могут быть разделены между процессами.
- Объявляйте переменные между ключевыми словами
processиbegin. - Присваивания используют оператор
:=. - После присваивания переменная немедленно содержит новое значение для последующих операторов в том же процессе.
Последний пункт — мгновенное присваивание — часто является источником путаницы. Ниже приведен краткий пример, демонстрирующий, как переменная может использоваться для конкатенации двух сигналов и управления case-оператором.
VAR_CASE : process (i_clk) variable v_Choices : std_logic_vector(1 downto 0); begin v_Choices := i_select_1 & i_select_2; -- concatenation case v_Choices is when "00" => o_data <= "0001"; when "01" => o_data <= "0010"; -- additional cases omitted for brevity end case; end process VAR_CASE;
В этом фрагменте v_Choices доступен для case оператора сразу после конкатенации, иллюстрируя мгновенное обновление переменной.
Для более глубокой иллюстрации рассмотрим следующую архитектуру, отслеживающую счетчик с двумя сигнальными копиями. Хотя два сигнала выглядят идентично, только r_Var_Copy1 достигает значения 5 до сброса, потому что r_Var_Copy2 присваивается после того, как счетчик уже был сброшен в том же тактовом цикле.
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity variable_ex is port ( i_clk : in std_logic; o_done : out std_logic ); end variable_ex; architecture rtl of variable_ex is signal r_Done : std_logic := '0'; signal r_Var_Copy1 : natural range 0 to 5 := 0; signal r_Var_Copy2 : natural range 0 to 5 := 0; begin EX_VAR : process (i_clk) variable v_Count : natural range 0 to 5 := 0; begin if rising_edge(i_clk) then v_Count := v_Count + 1; r_Var_Copy1 <= v_Count; if v_Count = 5 then r_Done <= '1'; v_Count := 0; else r_Done <= '0'; end if; r_Var_Copy2 <= v_Count; end if; end process EX_VAR; o_done <= r_Done; end rtl;
Для наблюдения этого поведения в симуляции предоставлен простой тестбенч. Он переключает такт и мониторит выход o_done. При использовании ModelSim помните, что переменные появляются в окне волн только если включена опция отображения переменных симулятора.
library ieee; use ieee.std_logic_1164.all; entity variable_ex_tb is end variable_ex_tb; architecture behave of variable_ex_tb is component variable_ex port ( i_clk : in std_logic; o_done : out std_logic ); end component variable_ex; constant c_CLK_PERIOD : time := 10 ns; signal r_CLK : std_logic := '0'; signal w_DONE : std_logic; begin UUT : variable_ex port map ( i_clk => r_CLK, o_done => w_DONE ); r_CLK <= not r_CLK after c_CLK_PERIOD/2; end behave;
Этот пример подчеркивает отличия поведения переменных и сигналов: пока r_Var_Copy1 достигает 5, r_Var_Copy2 никогда не делает этого, потому что переменная сбрасывается до присваивания сигнала.
VHDL
- Пример процедуры VHDL: инкремент std_logic_vector
- Использование записей (Records) в VHDL для чистых, повторно используемых интерфейсов FIFO
- Настройка AC-анализа в SPICE: кривые, точки и параметры частотного сканирования
- Мастерство C# переменных и примитивных типов данных: полное руководство
- Освоение переменных, литералов и констант в C++: подробное руководство
- Переменные, константы и литералы в C: полное руководство
- Классы хранения в C: область видимости, время жизни и производительность
- Строки в C просто: объявление, ввод, вывод и библиотечные функции
- Типы переменных в Java: локальные, экземпляра и статические
- Переменные в C: объявление, определение, инициализация, область видимости и классы хранения