Перейти к содержанию
    

Два разных клока в одном процесе.

Можно так сделать?

CLK = 120 Mhz
MS_CLK = 100 Mhz
 
constant TICKS_FOR_1MS : std_logic_vector(31 downto 0) := X"000186A0"; 

process (CLK)
begin  		
    if (count_reset = '1') then
       ticks_counter <= (others => '0');
       ms_counter <= (others => '0');
    else
       if (rising_edge(MS_CLK)) then
           ticks_counter <= ticks_counter + '1';
           if (ticks_counter = TICKS_FOR_1MS) then
                ticks_counter <= (others => '0');
                ms_counter <= ms_counter + '1';
            end if;
        end if;
    end if;
end process;

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

12 минут назад, jenya7 сказал:

Можно так сделать?


CLK = 120 Mhz
MS_CLK = 100 Mhz
 
constant TICKS_FOR_1MS : std_logic_vector(31 downto 0) := X"000186A0"; 

process (CLK)
begin  		
    if (count_reset = '1') then
       ticks_counter <= (others => '0');
       ms_counter <= (others => '0');
    else
       if (rising_edge(MS_CLK)) then
           ticks_counter <= ticks_counter + '1';
           if (ticks_counter = TICKS_FOR_1MS) then
                ticks_counter <= (others => '0');
                ms_counter <= ms_counter + '1';
            end if;
        end if;
    end if;
end process;

 

Сделать можно. Работать не будет. Изучайте как работает список чувствительности в VHDL. Эта тема обсасывалась уже 100 раз на форуме. Подсказка:  в VHDL список чувствительности не влияет на синтез (Qartus и Vivado). Вы описали обычную пару счетчиков. 

Правильно делать: 2 процесса на разных частотах. И сигнал из одного процесса переносить в другой через CDC синхронизаторы, удлинители сигнала и детекторы фронта. 

Совсем правильно делать: по возможности на одной частоте. 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

14 minutes ago, Flip-fl0p said:

Сделать можно. Работать не будет. Изучайте как работает список чувствительности в VHDL. Эта тема обсасывалась уже 100 раз на форуме. Подсказка:  в VHDL список чувствительности не влияет на синтез (Qartus и Vivado). Вы описали обычную пару счетчиков. 

Правильно делать: 2 процесса на разных частотах. И сигнал из одного процесса переносить в другой через CDC синхронизаторы, удлинители сигнала и детекторы фронта. 

 

а так?

cnt_rst3 <= not cnt_rst2 and cnt_rst1; 

process (CLK)
begin 
   if (rising_edge(CLK)) then	
	    cnt_rst1 <= count_reset;
       cnt_rst2 <= cnt_rst1;
	end if;
end process;


process (MS_CLK)
begin  

if (rising_edge(MS_CLK)) then		
    if (cnt_rst3 = '1') then
		  ticks_counter <= (others => '0');
		  ms_counter <= (others => '0');
	 else
	     ticks_counter <= ticks_counter + '1';
        if (ticks_counter = TICKS_FOR_1MS) then
		     ticks_counter <= (others => '0');
		     ms_counter <= ms_counter + '1';
        end if;
	end if;
end if;
		    
end process;

 

Изменено пользователем jenya7

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

6 минут назад, jenya7 сказал:

 

а так?


cnt_rst3cnt_rst3 <= not cnt_rst2 and cnt_rst1; 

process (CLK)
begin 
   if (rising_edge(CLK)) then	
	    cnt_rst1 <= count_reset;
       cnt_rst2 <= cnt_rst1;
	end if;
end process;


process (MS_CLK)
begin  

if (rising_edge(MS_CLK)) then		
    if (cnt_rst3 = '1') then
		  ticks_counter <= (others => '0');
		  ms_counter <= (others => '0');
	 else
	     ticks_counter <= ticks_counter + '1';
        if (ticks_counter = TICKS_FOR_1MS) then
		     ticks_counter <= (others => '0');
		     ms_counter <= ms_counter + '1';
        end if;
	end if;
end if;
		    
end process;

 

И так плохо. Где перенос сигнала cnt_rest3 из домена CLK в домен MS_CLK ? Вы неправильно сигнал переносите.

1. Сначала формируем сигнал.

2. Удлиняем его на время, чтобы его длительность была гарантированно больше чем 2 периода частоты MS_CLK

3. Переносим через синхронизатор.

4. Выделяем фронт в домене MS_CLK.

PS. Источник сигнала, который Вы переносите через домен должен быть порожден регистром, а не комбинационной логикой. Поэтому в зависимости от логики удлинения сигнала возможно надо будет сигнал защелкнуть на регистре в домене CLK.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 minute ago, Flip-fl0p said:

И так плохо. Где перенос сигнала cnt_rest3 из домена CLK в домен MS_CLK ? Вы неправильно сигнал переносите.

1. Сначала формируем сигнал.

2. Удлиняем его на время, чтобы его длительность была гарантированно больше чем 2 периода частоты MS_CLK

3. Переносим через синхронизатор.

4. Выделяем фронт в домене MS_CLK.

пункт 2 не понятен - как удлиняем?

то есть можно конечно, у меня обнуление идет в другом процессе

case LaunchState is
  
when ST_STATE_1 =>
  count_reset <= '1';

when ST_STATE_2 =>
  count_reset <= '0';

можно добавить промежуточный стейт но что то не нравиться мне такое решение.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

11 минут назад, jenya7 сказал:

пункт 2 не понятен - как удлиняем?

то есть можно конечно, у меня обнуление идет в другом процессе


case LaunchState is
  
when ST_STATE_1 =>
  count_reset <= '1';

when ST_STATE_2 =>
  count_reset <= '0';

можно добавить промежуточный стейт но что то не нравиться мне такое решение.

У Вас сейчас сигнал cnt_rest3  формируется в домене CLK(120 Mhz). Передаете Вы  его в домен 100 МHz. Думаю очевидно что период 8,33ns меньше чем 10 ns. Если просто передавать сигнал с меньшим в периодов в домен с большим периодом могут возникнуть ситуации, когда сигнал не попадет на передний фронт тактового сигнала домена с большим периодом, и просто потеряется. Ваша задача сделать так, чтобы сигнал, который Вы перекидываете между доменами имел длительность как минимум 2 периода частоты 100 Мгц. Т.е 20ns.

20ns/8,33ns = 2,4. Т.е сигнал должен иметь длительность не менее 3 такта частоты 120 Мгц. 

В случае, если не стоит цель сэкономить ресурсы, можно сделать схему с внутренним Handshakе, которая будет гарантированно переводить сигнал из домена А в домен Б при любых соотношениях частот. Однако придется потратить дополительные ресурсы на это.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

16 minutes ago, Flip-fl0p said:

У Вас сейчас сигнал cnt_rest3  формируется в домене CLK(120 Mhz). Передаете Вы  его в домен 100 МHz. Думаю очевидно что период 8,33ns меньше чем 10 ns. Если просто передавать сигнал с меньшим в периодов в домен с большим периодом могут возникнуть ситуации, когда сигнал не попадет на передний фронт тактового сигнала домена с большим периодом, и просто потеряется. Ваша задача сделать так, чтобы сигнал, который Вы перекидываете между доменами имел длительность как минимум 2 периода частоты 100 Мгц. Т.е 20ns.

20ns/8,33ns = 2,4. Т.е сигнал должен иметь длительность не менее 3 такта частоты 120 Мгц. 

В случае, если не стоит цель сэкономить ресурсы, можно сделать схему с внутренним Handshakе, которая будет гарантированно переводить сигнал из домена А в домен Б при любых соотношениях частот. Однако придется потратить дополительные ресурсы на это.

 

 может так тогда?

process (CLK)
begin 
   if (rising_edge(CLK)) then	
		 if (count_reset = '1') then
		     locked_reset <= '1';
		 end if;
	end if;
	
	if (locked_reset = '1') then
	    del := del + 1;
		 if (del = 2) then
           del := 0;
		   locked_reset <= '0';
		 end if;
	end if;
end process;


process (MS_CLK)
begin  

if (rising_edge(MS_CLK)) then		
    if (locked_reset = '1') then
		  ticks_counter <= (others => '0');
		  ms_counter <= (others => '0');
	 else
	     ticks_counter <= ticks_counter + '1';
        if (ticks_counter = TICKS_FOR_1MS) then
		     ticks_counter <= (others => '0');
		     ms_counter <= ms_counter + '1';
        end if;
	end if;
end if;
		    
end process;

а сколько ресурсов берёт Handshakе?

Изменено пользователем jenya7

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

4 минуты назад, jenya7 сказал:

 может так тогда?

 

 

Значица так. Берете 2 разных цветных пишущих изделия и рисуете схему. Каждый домен своим цветом. Когда схему нарисуете и выложите сюда - можно будет продолжить разговор. Не вижу смысла дальше что-то Вам объяснять. Пересечения CDC - это базовые вещи, которые должен знать каждый, кто работает с FPGA. Изучайте матчасть.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 minute ago, Flip-fl0p said:

Значица так. Берете 2 разных цветных пишущих изделия и рисуете схему. Каждый домен своим цветом. Когда схему нарисуете и выложите сюда - можно будет продолжить разговор. Не вижу смысла дальше что-то Вам объяснять. Пересечения CDC - это базовые вещи, которые должен знать каждый, кто работает с FPGA. Изучайте матчасть.

я сделал то что вы предлагали - удлинение сигнала.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1 минуту назад, jenya7 сказал:

я сделал то что вы предлагали - удлинение сигнала.

А кто будет выполнять пункты:

Цитата

 

3. Переносим через синхронизатор.

4. Выделяем фронт в домене MS_CLK.

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

а если вынести в отдельный модуль с асинхронным рисетом?

entity MS_COUNT is
generic
(
    TICKS_FOR_1MS : std_logic_vector(31 downto 0);
	COUNTER_LENGTH : integer
);
port
(
    CLK    : in std_logic;
	RST    : in std_logic;
	 
	 COUNTER : out std_logic_vector(15 downto 0)
);
end MS_COUNT;

architecture behavior of MS_COUNT is

signal ticks_counter : std_logic_vector(31 downto 0);
signal ms_counter    : std_logic_vector(COUNTER_LENGTH-1 downto 0) := X"00";

begin

COUNTER <= ms_counter;

process(CLK, RST)
begin

    if RST = '1' then
        ticks_counter <= (others => '0');
		  ms_counter <= (others => '0');
    elsif rising_edge(CLK) then
        ticks_counter <= ticks_counter + '1';
        if (ticks_counter = TICKS_FOR_1MS) then
		      ticks_counter <= (others => '0');
		      ms_counter <= ms_counter + '1';
		  end if;	
    end if;
	 
end process;


end behavior;

 

Изменено пользователем jenya7

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

6 минут назад, jenya7 сказал:

а если вынести в отдельный модуль с асинхронным рисетом?

 

 

Асинхронный сброс должен иметь синхронное снятие. https://www.eetimes.com/how-do-i-reset-my-fpga/ Вместо CDC синхронизатора нужно будет ставить reset bridge. Так-что таки придется сделать синхронизатор :biggrin:

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

15 hours ago, jenya7 said:

elsif rising_edge(CLK) then

ticks_counter <= ticks_counter + '1';

if (ticks_counter = TICKS_FOR_1MS) then

ticks_counter <= (others => '0');

ms_counter <= ms_counter + '1';

end if;

end if;

Я уже немного подзабыл специфику VHDL, но кажется так нельзя делать. В языке нет переприсвоения, соответственно придётся писать так:

elsif rising_edge(CLK) then 
	if (ticks_counter = TICKS_FOR_1MS) then
		ticks_counter <= (others => '0');
		ms_counter <= ms_counter + '1';
	else
		ticks_counter <= ticks_counter + '1';
	end if; 
end if;

Впринципе второй модуль выглядит вполне синтезабельным. И ресетить можно через CDC с определёнными оговорками и головной болью для человека, который будет писать констрейны.

з.ы. Синхронизатор - это просто 2 флопа включенных последовательно и работающих на другой частоте. Такая схема с очень большой долей вероятности предотвратит метастабильность на входе последующей логики.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

14 minutes ago, Nick_K said:

Я уже немного подзабыл специфику VHDL, но кажется так нельзя делать. В языке нет переприсвоения, соответственно придётся писать так:

Впринципе второй модуль выглядит вполне синтезабельным. И ресетить можно через CDC с определёнными оговорками и головной болью для человека, который будет писать констрейны.

з.ы. Синхронизатор - это просто 2 флопа включенных последовательно и работающих на другой частоте. Такая схема с очень большой долей вероятности предотвратит метастабильность на входе последующей логики.

модуль компилируется. но проблема в том что сигнал рисета приходит от процесса на 120 Мега в процесс 100 Мега и я могу его пропустить.

решил заморочиться и сделать модуль счетчика и модуль формирования сигнала рисета

Spoiler

entity MS_COUNT is
generic
(
    TICKS_FOR_1MS : std_logic_vector(31 downto 0);
	 COUNTER_LENGTH : integer
);
port
(
    CLK    : in std_logic;
	 RST    : in std_logic;
	 
	 COUNTER : out std_logic_vector(COUNTER_LENGTH-1 downto 0)
);
end MS_COUNT;

architecture behavior of MS_COUNT is


signal rst_1 : std_logic;
signal rst_2 : std_logic;
signal rst_3 : std_logic;

signal ticks_counter : std_logic_vector(31 downto 0);
signal ms_counter    : std_logic_vector(COUNTER_LENGTH-1 downto 0) := (others => '0');

begin

rst_3 <= not rst_2 and rst_1; --rising

COUNTER <= ms_counter;

process (CLK)
begin
    if (rising_edge(CLK)) then
	     rst_1 <= RST;
		  rst_2 <= rst_1;
	 end if;
end process;


process(CLK)
begin

    if (rising_edge(CLK)) then
	 
	     if (rst_3 = '1') then
		      ticks_counter <= (others => '0');
				ms_counter <= (others => '0');
		  else
            ticks_counter <= ticks_counter + '1';
            if (ticks_counter = TICKS_FOR_1MS) then
		          ticks_counter <= (others => '0');
		          ms_counter <= ms_counter + '1';
            end if;
        end if;  
		  
	 end if;	
	 
end process;

end behavior;


entity PULSE_FORMER is
generic
(
	 DELAY : integer
);
port
(
    CLK    : in std_logic;
	SIG_IN : in std_logic;
	 
	SIG_OUT : out std_logic;
);
end PULSE_FORMER;

architecture behavior of PULSE_FORMER is


signal sig_1 : std_logic;
signal sig_2 : std_logic;
signal sig_3 : std_logic;

signal rise_sig : std_logic;


begin

SIG_OUT <= rise_sig;

sig_3 <= not sig_2 and sig_1; --rising

process (CLK)
begin

    if (rising_edge(CLK)) then
	 
	     sig_1 <= SIG_IN;
		  sig_2 <= sig_1;	  
	 end if;
	 
end process;


process(CLK)
variable del : integer := 0;
begin

    if (rising_edge(CLK)) then
	 
	     if (sig_3 = '1') then
		     rise_sig <= '1';
		 end if;
	
	    if (rise_sig = '1') then
	        del := del + 1;
		     if (del = DELAY) then
			     del := 0;
		        rise_sig <= '0';
		     end if;
	    end if;
		  
	 end if;	
	 
end process;

end behavior;

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2 часа назад, jenya7 сказал:

модуль компилируется. но проблема в том что сигнал рисета приходит от процесса на 120 Мега в процесс 100 Мега и я могу его пропустить.

решил заморочиться и сделать модуль счетчика и модуль формирования сигнала рисета

  Показать содержимое


entity MS_COUNT is
generic
(
    TICKS_FOR_1MS : std_logic_vector(31 downto 0);
	 COUNTER_LENGTH : integer
);
port
(
    CLK    : in std_logic;
	 RST    : in std_logic;
	 
	 COUNTER : out std_logic_vector(COUNTER_LENGTH-1 downto 0)
);
end MS_COUNT;

architecture behavior of MS_COUNT is


signal rst_1 : std_logic;
signal rst_2 : std_logic;
signal rst_3 : std_logic;

signal ticks_counter : std_logic_vector(31 downto 0);
signal ms_counter    : std_logic_vector(COUNTER_LENGTH-1 downto 0) := (others => '0');

begin

rst_3 <= not rst_2 and rst_1; --rising

COUNTER <= ms_counter;

process (CLK)
begin
    if (rising_edge(CLK)) then
	     rst_1 <= RST;
		  rst_2 <= rst_1;
	 end if;
end process;


process(CLK)
begin

    if (rising_edge(CLK)) then
	 
	     if (rst_3 = '1') then
		      ticks_counter <= (others => '0');
				ms_counter <= (others => '0');
		  else
            ticks_counter <= ticks_counter + '1';
            if (ticks_counter = TICKS_FOR_1MS) then
		          ticks_counter <= (others => '0');
		          ms_counter <= ms_counter + '1';
            end if;
        end if;  
		  
	 end if;	
	 
end process;

end behavior;


entity PULSE_FORMER is
generic
(
	 DELAY : integer
);
port
(
    CLK    : in std_logic;
	SIG_IN : in std_logic;
	 
	SIG_OUT : out std_logic;
);
end PULSE_FORMER;

architecture behavior of PULSE_FORMER is


signal sig_1 : std_logic;
signal sig_2 : std_logic;
signal sig_3 : std_logic;

signal rise_sig : std_logic;


begin

SIG_OUT <= rise_sig;

sig_3 <= not sig_2 and sig_1; --rising

process (CLK)
begin

    if (rising_edge(CLK)) then
	 
	     sig_1 <= SIG_IN;
		  sig_2 <= sig_1;	  
	 end if;
	 
end process;


process(CLK)
variable del : integer := 0;
begin

    if (rising_edge(CLK)) then
	 
	     if (sig_3 = '1') then
		     rise_sig <= '1';
		 end if;
	
	    if (rise_sig = '1') then
	        del := del + 1;
		     if (del = DELAY) then
			     del := 0;
		        rise_sig <= '0';
		     end if;
	    end if;
		  
	 end if;	
	 
end process;

end behavior;

 

 

 

Так чего мы ждем ?! Вкорячить синхронизатор на нужный сигнал и горя не знать. Почему еще не сделали это ?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...