Как стать автором
Поиск
Написать публикацию
Обновить

Сдвиг фазы сигнала на VHDL

Время на прочтение4 мин
Количество просмотров9.4K
Данная статья продолжение серии топиков Элемент задержки на VHDL, Элемент задержки на VHDL. Другой взгляд о элементах задержки на VHDL реализованных в ПЛИС.

Акцент будет сделан на конкретный прикладной пример, который любой желающий может запустить в симуляторе или реальном железе. Пример создан для удобной симуляции в среде Xilinx ISE с использованием Modelsim SE и с минимальными изменениями реализован в полноценное IP Core.

Постановка задачи


Осуществить сдвиг фазы импульсного сигнала на заданную величину (длительность импульса произвольна), возможно не синхронного с частотой работы логики ядра. Сделать это без перезагрузки или выключения модуля/устройства.

Инструменты


ДИП свич 8 позиций, на котором выставляется код задержки в двоичном коде (величина сдвига). Hard или Soft Reset — начальных сброс, установка параметров по умолчанию. Опорная частота 100 MHz, т.е 10 ns минимальное время смещения.

Реализация


Импульсом буду называть логическую единицу — 1.
Паузой, логический ноль — 0.

Код реализован в виде машины состояний, которая на мой взгляд благодаря пошаговой структуре и возможности дать внятное имя каждому этапу, весьма проста и понятна.

Помимо комментариев к коду, прилагается файл симуляции testbench.

Диаграмма конечного автомата:

image

Основная логика. Код отслеживает изменение уровня сигнала, далее запускается счетчик, когда его значение становится равным выставленному сдвигу, на выход подается тот же уровень, что и отслеживается и так по кругу.

freq_shift_half_cycle.vhd
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:

testbench_half_cycle.vhd
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 в реальном так сказать времени, с задержкой в работе логики:



Далее идет демонстрация ситуации если подстраиваемый сигнал и опорная частота асинхронны:



Предлагаю вам, проанализировать данную ситуацию и сделать собственные выводы.

Буду рад вашим комментариям и замечаниям, с помощью которых в следующей статье, этот код будет дополнен новыми функциональными возможностями.

Спасибо за внимание.
Теги:
Хабы:
Всего голосов 10: ↑9 и ↓1+8
Комментарии5

Публикации

Ближайшие события