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

Посчитать пульсы за период.

8 minutes ago, Zig said:

Уточню замечание

У вас f_count считается на частоте FREQ_IN, а защелкивается в регистр COUNTER на частоте CLK.

 

И что за хитровывернутость с сигналом reset?

да. криво. понимаю.

но я не нашел другого способа защелкнуть и обнулить f_count. есть другой способ?

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

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


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

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

Так нет опоры. Задача померять асинхронно. Пины взял посто которые было удобно использовать.

 


--in entity
FREQ_IN  : in std_logic;     --AB3
FREQ_OUT1 : out std_logic;    --Y3
FREQ_OUT2 : out std_logic;    --Y4
FREQ_OUT3 : out std_logic;    --Y5

--in architecture

FREQ_OUT1 <= clk_120M;
FREQ_OUT2 <= clk_100M;
FREQ_OUT3 <= clk_60M;
                    
                    
U_PLL : pll 
port map
(
	 inclk0 => MAX10_CLK2_50,
	 c0	  => clk_100M,
	 c1	  => clk_120M,
	 c2	  => clk_150M,
	 c3	  => clk_60M
);

 

 

А вы не подумали, что я могу не знать какую fpga вы применяемое ? Более того у меня может не быть соответствующего софта, чтобы глянуть за вас распиновку. ..

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


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

7 minutes ago, Flip-fl0p said:

А вы не подумали, что я могу не знать какую fpga вы применяемое ? Более того у меня может не быть соответствующего софта, чтобы глянуть за вас распиновку. ..

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

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


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

Цитата

 

да. криво. понимаю.

но я не нашел другого способа защелкнуть и обнулить f_count. есть другой способ?

 

Так есть пару простых способов:

Первый: пишите фиговину который выдает сигнал пока у вас считается период, относительно которого вы меряете ваши "пульсы". Естественно Формируется этот сигнал в домене clk (100 Mhz).  Посредством простенького синхронизатора вы переносите этот длинный сигнал в домен FREQ_IN. В домене FREQ_IN Вы выделяете передний фронт этого длинного сигнала, посредством простейшего детектора фронтов. Этот детектированный передний фронт - сигнал начала подсчета Ваших "пульсов". Так-же Вы выделяете задний фронт этого длинного сигнала, посредством простейшего детектора фронтов. Этот детектированный фронт - счигнал окончания подсчета количества Ваших "пульсов".  Через несколько тактов (частоты FREQ_IN ) можете спокойно без всяких синхронизаторов переписать количество ваших "пульсов" в домен clk. Ибо данные у Вас стабильны и больше не меняются. Не забыть написать соответствующие констрейны что у вас доменыFREQ_IN и CLK асинхронные. К итоговой ppm добавится погрешность в пару тактов. Но тут ничего не сделать поскольку метастабильность никто не отменял.

 

Второй способ: можно попробовать увеличить частоту клока, которым Вы периоды считаете.  С частотой FREQ_IN работать не как с клоком, а как с данными.  Тогда вам достаточно просто синхронизировать частоту FREQ_IN с доменом (clk), поставить детектор фронта и считать фронты. Точность будет повыше. Но и требования к частоте clk есть, т.к она должна быть как минимум в 2 раза выше чем частота FREQ_IN (вспоминаем теорему Котельникова, часто называют критерий Накйвиста).

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


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

Вам нужен счетчик импульсов или частотомер?

Работать должен непрерывно или измеряет иногда?

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


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

On 1/26/2019 at 12:03 AM, Reanimator++ said:

Вам нужен счетчик импульсов или частотомер?

Работать должен непрерывно или измеряет иногда?

счетчик импульсов за период это по сути частотометр.

непрерывно или нет? даже не знаю. пока никакого синхронизирующего флага у меня нет.

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


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

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

счетчик импульсов за период это по сути частотометр.

непрерывно или нет? даже не знаю. пока никакого синхронизирующего флага у меня нет.

Он хоть заработал ?

Как в итоге Вы сделали ?

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


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

3 hours ago, Flip-fl0p said:

Он хоть заработал ?

Как в итоге Вы сделали ?

Последняя версия

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity FCOUNTER is
  port(
    RST			:in std_logic; 
  	 CLK        :in std_logic;
  	
    FREQ_IN    :in std_logic;               
	 PERIOD     :in  Std_logic_vector(15 downto 0)  := X"0064"; 
    COUNTER    :out Std_logic_vector(31 downto 0) 
    
  );
end FCOUNTER;

architecture STRUCTURE of FCOUNTER is

signal ms_clock :std_logic := '0';
signal reset :std_logic := '0';
signal f_count : std_logic_vector(31 downto 0) := (others=>'0');
signal ms_count : std_logic_vector(15 downto 0) := (others=>'0');
signal count : std_logic_vector(31 downto 0) := (others=>'0');

begin

process(FREQ_IN, reset)
begin 

    if (FREQ_IN'event and FREQ_IN = '1') then
        f_count <= count + '1';
    end if;
	 
	 if (reset = '1') then
	    COUNTER <= f_count; --ticks per period
		 f_count <= (others=>'0');
	 end if;


end process;


process(ms_clock)
begin

    if (rising_edge(ms_clock)) then
	 
	    ms_count <= ms_count + '1'; 
		 
		if ( ms_count = PERIOD) then  --milliseconds
		    ms_count <= (others=>'0');
			 reset <= '1';
		end if;
		
		if (reset = '1') then
			    reset <= '0';
			end if;
			
	 end if;
	 
end process;


process(CLK) --100 Mhz
begin

    if (rising_edge(CLK)) then
	 
	    count <= count + '1'; 
		 
		               --49999
		if (count = X"0000C34F") then  --50000 - 500us
		    count <= (others=>'0');
		    ms_clock <= not ms_clock; --tick 500us
		end if;
		
    end if;		
	 
end process;



end STRUCTURE;

На периоде 1 сек. погрешность +/- 2ppm.

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

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


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

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

Последняя версия

На периоде 1 сек. погрешность +/- 2ppm.

 

А Вы упертый товарищ...

Какая-то у Вас странная забава. Задать вопрос, получить ответы. Но в итоге сделать по-своему и при этом неправильно... Да Ваш код может даже почти всегда считает правильно. Однако у него есть один серьезнейший недостаток:

В момент совпадения фронта FREQ_IN и сигнала reset Вы на выходе иногда будете получать очень "странный" результат. Ну что же. Ждем от Вас новой темы с вопросом, почему Ваш "идеальный" код сбоит. 

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


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

2 jenya7

Ну и если уж все равно наплевали на метастабильность, то зачем было делать ms_clock?

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


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

9 minutes ago, Flip-fl0p said:

А Вы упертый товарищ...

Какая-то у Вас странная забава. Задать вопрос, получить ответы. Но в итоге сделать по-своему и при этом неправильно... Да Ваш код может даже почти всегда считает правильно. Однако у него есть один серьезнейший недостаток:

В момент совпадения фронта FREQ_IN и сигнала reset Вы на выходе иногда будете получать очень "странный" результат. Ну что же. Ждем от Вас новой темы с вопросом, почему Ваш "идеальный" код сбоит. 

я понял. следующий шаг добавить еще один флаг синхронизирующий  FREQ_IN и период.

5 minutes ago, dvladim said:

2 jenya7

Ну и если уж все равно наплевали на метастабильность, то зачем было делать ms_clock?

считать период?

 

ой. извиняюсь. моя ошибка.

вот последняя версия.

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.std_logic_arith.all;
use IEEE.STD_LOGIC_UNSIGNED.ALL;


entity FCOUNTER is
  port(
    RST			:in std_logic; 
  	 CLK        :in std_logic;
  	
    FREQ_IN    :in std_logic;               
	 PERIOD     :in  Std_logic_vector(15 downto 0)  := X"03E8"; 
    COUNTER    :out Std_logic_vector(31 downto 0) 
    
  );
end FCOUNTER;


architecture STRUCTURE of FCOUNTER is

signal ms_clock :std_logic := '0';
signal reset :std_logic := '0';
signal f_count : std_logic_vector(31 downto 0) := (others=>'0');
signal ms_count : std_logic_vector(15 downto 0) := (others=>'0');
signal count : std_logic_vector(31 downto 0) := (others=>'0');

signal clk1 : std_logic := '0';
signal clk2 : std_logic := '0';
signal clk3 : std_logic := '0';
signal clk4 : std_logic := '0';

begin

clk3 <= not clk1 and clk2;

process(FREQ_IN, reset)
begin 

    if (FREQ_IN'event and FREQ_IN = '1') then
        f_count <= f_count + '1';
    end if;
	 
	 if (reset = '1') then
	    --COUNTER <= f_count; --ticks per period
		 f_count <= (others=>'0');
	 end if;


end process;

process(CLK) --100 Mhz
begin

    if (rising_edge(CLK)) then
	 
	    count <= count + '1'; 
		               --99999
		if (count = X"0001869F") then  --100000 - 1ms
		    count <= (others=>'0');
		    ms_count <= ms_count + '1'; 
		end if;
		 
		if (ms_count = PERIOD) then  --milliseconds
		    ms_count <= (others=>'0');
			 
			 COUNTER <= f_count; --ticks per period
			 
			 reset <= '1';
		end if;
	  
		if (reset = '1') then  --do it one clock
		    reset <= '0';
		end if;
		
    end if;		
	 
end process;

end STRUCTURE;

 

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

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


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

Вот один из вариантов решения задачи.

Из готовых модулей его можно собрать минут за 5.

library IEEE;
    use IEEE.std_logic_1164.all;
    use IEEE.numeric_std.all;


entity freq_meter is
    port
    (
        clk                : in  std_ulogic;                       -- Частота основной логики измерения
        start              : in  std_ulogic;                       -- Запуск измерения
        meas_time          : in  std_ulogic_vector(31 downto 0);   -- measurement_time

        meas_freq          : in  std_ulogic;                       -- Measured frequency         
        result             : out std_ulogic_vector(31 downto 0);   -- measurement result
        result_valid       : out std_ulogic                        -- Сигнал валидности result (сформируйте его уже сами)

    );
end entity;


architecture RTL of freq_meter is

    signal prd_counter             : unsigned(31 downto 0) := (others => '0');  -- Наш счетчик периода
    
    --=====================================================================
    -- Наш JK-триггер, можно без него, написав простенький автомат
    -- Но лично мне с триггером понятнее.
    --=====================================================================
    signal J                       : std_ulogic;                                 -- Сигнал установки триггера
    signal K                       : std_ulogic;                                 -- Сигнал сброса триггера
    signal Q                       : std_ulogic := '0';                          -- Выход триггера
    
    signal syncronizer             : std_ulogic_vector(2 downto 0) := (others => '0'); -- Синхронизатор с клоковым доменом meas_freq
    signal edge_detector           : std_ulogic := '0';                                -- DFF Для детектирования фронтов
    signal Redge                   : std_ulogic;                                       -- Сигнал-флаг детектированного переднего фронта
    signal Fedge                   : std_ulogic;                                       -- Сигнал-флаг детектированного заднего фронта
    
    signal meas_counter            : unsigned(31 downto 0) := (others => '0');         -- Счетчик, который считает "пульсы" за период
    
begin
    -- Алгоритм такой: пришла команда запуска - мы загружаем в вычитающий счетчик период измерения
    -- Одновременно с загрузкой данных в счетчик, мы усанавливаем наш JK триггер в единичку.
    -- Когда счетчик отсчитает наш период (от значения meas_time до 0) у нас сбросится JK триггер.
    -- Таким несложным способом мы формируем длинный сигнал пока у нас счетчик отсчитывает период
    
    --===============================================================================================
    -- Счетчик с синхронной загрузкой. У меня это всегда отдельный модуль с параметрами
    --===============================================================================================
    counter_sload : process(clk)
    begin
        if (rising_edge(clk)) then
            prd_counter <= prd_counter - "1";        -- Вычитающий счетчик
            if (start = '1') then                    -- Когда пришла команда начать измерения
                prd_counter <= unsigned(meas_time);  -- Загружаем в счетчик период измерения
            end if;
        end if;
    end process;
    
    --===========================================================
    -- JK триггер.  У меня это отдельный модуль с параметарми
    --===========================================================
    JKFF : process(clk)
        variable JplusK : unsigned(1 downto 0) := (others => '0');
    begin
        if (rising_edge(clk)) then
           JplusK := J & K;
            case JplusK is 
                when  "00"    => Q <=     Q;  
                when  "01"    => Q <=    '0'; 
                when  "10"    => Q <=    '1'; 
                when  "11"    => Q <= not Q; 
                when  others  => null;
            end case;
        end if;
    end process;
    
    J <= start;                                                     -- Пришла команда запуска устанавливаем JK в единицу
    K <= '1' when (prd_counter = (31 downto 0 => '0')) else '0';    -- Счетчик отсчитал период - сбрасываем наш JK тригер

    
    --==================================================================================
    -- Сдвиговый регистр синхронизатор
    -- У меня это тоже отдельный модуль, с правильными атрибутами синтеза
    -- Этим регистром мы переносим наш длинный сигнал c JK триггера в домен meas_freq
    --==================================================================================
    process(meas_freq)
    begin
        if (rising_edge(meas_freq)) then
            syncronizer <= syncronizer(syncronizer'left - 1 downto 0) & q; 
        end if;
    end process;
    
    --=========================================================================
    -- DFF Триггер для детектирования фронтов
    -- У меня это тоже отдельный модуль...
    --=========================================================================
    process(meas_freq)
    begin
        if (rising_edge(meas_freq)) then
            edge_detector <= syncronizer(syncronizer'left);
        end if;
    end process;

    Redge <= not edge_detector and syncronizer(syncronizer'left);    -- Детектируем передний фронт 
    Fedge <= not syncronizer(syncronizer'left)  and edge_detector;   -- Детектируем задний   фронт                
    
    --======================================================================
    -- Считаем количество "пульсов" за период
    -- И опять, же у меня это всегда отдельный модуль с параметрами.
    --======================================================================
    process(meas_freq)
    begin
        if (rising_edge(meas_freq)) then
            meas_counter <= meas_counter + "1";
            if (Redge = '1') then                         -- Передним фронтом нашего длинного сигнала 
                meas_counter <= (others => '0');          -- Сбрасываем счетчик (подготсвливаем для счета)
            end if;
        end if;
    end process;
    
    process(meas_freq)
    begin
        if (rising_edge(meas_freq)) then
            if (Fedge = '1') then                            -- Задним фронтом 
                result <= std_ulogic_vector(meas_counter);   --  Мы переписываем результат в отдельный триггер
            end if;
        end if;
    end process;
  
  -- Чтобы было совсем правильно, надо сформировать сигнал result_valid, который сообщает, что данные result правильные, и их можно забрать.
  -- Естественно, что result_valid должен быть синхронен домену CLK.
  -- А сам result можно не синхронизировать.... если будет result_valid.
  -- Но это уже сами.
  -- Вообще, есть много вариантов измерителя "пульсов" за период. Можно вообще попробовать применить счетчик Грея. 
  -- Всё в Ваших руках
    
end architecture;

 

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


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

On 1/27/2019 at 10:36 AM, jenya7 said:

счетчик импульсов за период это по сути частотометр.

непрерывно или нет? даже не знаю. пока никакого синхронизирующего флага у меня нет.

Еще раз.

Частотомеров разных видов очень много. Вам таки надо измерять частоту или считать импульсы за период? Если измерять частоту то с какой точностью и за какое время?

Если это таки частотомер то он может измерить частоту, затем подождать немного, а затем снова измерять? Или нельзя пропустить ни одного импульса?

Что является источником опорного сигнала?

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


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

интересно а это должно работать если частота больше тактирующей частоты?

process(meas_freq)
    begin
        if (rising_edge(meas_freq)) then
            meas_counter <= meas_counter + "1";
            if (Redge = '1') then                         -- Передним фронтом нашего длинного сигнала 
                meas_counter <= (others => '0');          -- Сбрасываем счетчик (подготсвливаем для счета)
            end if;
        end if;
    end process;

у меня FPGA клокируется от осцилятора 30 мега а на ножку приходит 100 мега.

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

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


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

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

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