Данная статья продолжение серии топиков Элемент задержки на VHDL, Элемент задержки на VHDL. Другой взгляд о элементах задержки на VHDL реализованных в ПЛИС.
Акцент будет сделан на конкретный прикладной пример, который любой желающий может запустить в симуляторе или реальном железе. Пример создан для удобной симуляции в среде Xilinx ISE с использованием Modelsim SE и с минимальными изменениями реализован в полноценное IP Core.
Постановка задачи
Осуществить сдвиг фазы импульсного сигнала на заданную величину (длительность импульса произвольна), возможно не синхронного с частотой работы логики ядра. Сделать это без перезагрузки или выключения модуля/устройства.
Инструменты
ДИП свич 8 позиций, на котором выставляется код задержки в двоичном коде (величина сдвига). Hard или Soft Reset — начальных сброс, установка параметров по умолчанию. Опорная частота 100 MHz, т.е 10 ns минимальное время смещения.
Реализация
Импульсом буду называть логическую единицу — 1.
Паузой, логический ноль — 0.
Код реализован в виде машины состояний, которая на мой взгляд благодаря пошаговой структуре и возможности дать внятное имя каждому этапу, весьма проста и понятна.
Помимо комментариев к коду, прилагается файл симуляции testbench.
Диаграмма конечного автомата:
Основная логика. Код отслеживает изменение уровня сигнала, далее запускается счетчик, когда его значение становится равным выставленному сдвигу, на выход подается тот же уровень, что и отслеживается и так по кругу.
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; use ieee.std_logic_arith.all; use ieee.std_logic_unsigned.all; entity freq_shift_half_cycle is Port ( Bus2IP_Clk : in STD_LOGIC; -- частота работы логики Bus2IP_Reset : in STD_LOGIC; -- сброс Clk_in : in STD_LOGIC; -- входной сигнал Shift_reg : in STD_LOGIC_VECTOR (7 downto 0); -- знчение задержки в тактах Bus2IP_Clk counter_reg_test : out STD_LOGIC_VECTOR (7 downto 0); -- тестовый счетчик Clk_out : out STD_LOGIC -- выходной сигнал ); end freq_shift_half_cycle; architecture Behavioral of freq_shift_half_cycle is type state_type is (set_level, wait_high_low, wait_low_high); -- описание машины состояний signal current_stage : state_type; signal counter_shift : STD_LOGIC_VECTOR (7 downto 0); -- внутренний счетчик begin shift_fsm : process (Bus2IP_Reset, Bus2IP_Clk, Clk_in, Shift_reg) begin if Shift_reg = x"00" or Bus2IP_Reset = '1' then -- если задержка нулевая или подан reset Clk_out <= Clk_in; counter_shift <= x"01"; counter_reg_test <= x"01"; -- тестовый счетчик current_stage <= set_level; elsif (Bus2IP_Clk'event and Bus2IP_Clk = '1') then case current_stage is when set_level => if counter_shift = Shift_reg then -- после выставленной задержки, подаём на выход 0 или 1 if Clk_in = '1' then Clk_out <= '1'; current_stage <= wait_high_low; else Clk_out <= '0'; current_stage <= wait_low_high; end if; counter_shift <= x"01"; counter_reg_test <= x"01"; -- тестовый счетчик elsif counter_shift < Shift_reg then counter_shift <= counter_shift + 1; counter_reg_test <= counter_shift + 1; -- тестовый счетчик current_stage <= set_level; end if; when wait_high_low => -- ждем переключения 1 на 0 и возвращаемся в set_level if Clk_in = '1' then current_stage <= wait_high_low; else current_stage <= set_level; end if; when wait_low_high => -- ждем переключения 0 на 1 и возвращаемся в set_level if Clk_in = '0' then current_stage <= wait_low_high; else current_stage <= set_level; end if; when others => current_stage <= set_level; end case; end if; end process shift_fsm; end Behavioral;
Код симуляции для Modelsim:
LIBRARY ieee; USE ieee.std_logic_1164.ALL; -- Uncomment the following library declaration if using -- arithmetic functions with Signed or Unsigned values --USE ieee.numeric_std.ALL; ENTITY testbench_half_cycle IS END testbench_half_cycle; ARCHITECTURE behavior OF testbench_half_cycle IS -- Component Declaration for the Unit Under Test (UUT) COMPONENT freq_shift_half_cycle PORT( Bus2IP_Clk : IN std_logic; Bus2IP_Reset : IN std_logic; Clk_in : IN std_logic; Shift_reg : IN std_logic_vector(7 downto 0); counter_reg_test : OUT std_logic_vector(7 downto 0); Clk_out : OUT std_logic ); END COMPONENT; --Inputs signal Bus2IP_Clk : std_logic := '0'; signal Bus2IP_Reset : std_logic := '0'; signal Clk_in : std_logic := '0'; signal Shift_reg : std_logic_vector(7 downto 0) := (others => '0'); --Outputs signal counter_reg_test : std_logic_vector(7 downto 0); signal Clk_out : std_logic; -- Clock period definitions constant Bus2IP_Clk_period : time := 10 ns; constant Clk_in_period : time := 100 ns; BEGIN -- Instantiate the Unit Under Test (UUT) uut: freq_shift_half_cycle PORT MAP ( Bus2IP_Clk => Bus2IP_Clk, Bus2IP_Reset => Bus2IP_Reset, Clk_in => Clk_in, Shift_reg => Shift_reg, counter_reg_test => counter_reg_test, Clk_out => Clk_out ); -- Clock process definitions Bus2IP_Clk_process :process begin Bus2IP_Clk <= '1'; wait for Bus2IP_Clk_period/2; Bus2IP_Clk <= '0'; wait for Bus2IP_Clk_period/2; end process; Clk_in_process :process begin Clk_in <= '1'; wait for Clk_in_period/2; Clk_in <= '0'; wait for Clk_in_period/2; -- wait for 1000 ns; end process; -- Stimulus process stim_proc: process begin -- hold reset state for 100 ns. Bus2IP_Reset <= '1'; wait for 500 ns; Bus2IP_Reset <= '0'; wait for 5000 ns; Shift_reg <= x"01"; -- выставляется задержка wait for 5000 ns; Shift_reg <= x"00"; wait for 5000 ns; Shift_reg <= x"04"; wait for Bus2IP_Clk_period*10; -- insert stimulus here wait; end process; END;
Опытный электронщик мог заметить недостатки данного кода, а именно. Выставленная задержка не должна превышать:
— длительности импульса, если длительность импульса меньше длительности паузы;
— длительности паузы, если длительность паузы меньше длительности импульса.
Т.е. величина фазового сдвига не должна превышать 180° как для 0 так и для 1 в случае импульсного сигнала.
На схеме ниже вы можете видеть, как осуществляется сдвиг фазы входного сигнала на 40 ns в реальном так сказать времени, с задержкой в работе логики:
Далее идет демонстрация ситуации если подстраиваемый сигнал и опорная частота асинхронны:
Предлагаю вам, проанализировать данную ситуацию и сделать собственные выводы.
Буду рад вашим комментариям и замечаниям, с помощью которых в следующей статье, этот код будет дополнен новыми функциональными возможностями.
Спасибо за внимание.
ссылка на оригинал статьи http://geektimes.ru/post/266218/
Добавить комментарий