реклама на сайте
подробности

 
 
> Детектор наличия частоты., Гугл молчит. Не строить же велосипед.
MegaVolt
сообщение Jun 8 2015, 09:29
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 779
Регистрация: 3-01-05
Из: Минск
Пользователь №: 1 783



Нужно детектировать наличие частоты. Опорная частота присутствует.

Классика предлагает ставить счётчик и смотреть периодически что он насчитал. Так вот ищу решение для однобитного счётчика. Т.е. самый быстрый детектор.

Что то не могу правильно у гугла спросить. Неужели нет стандартного правильного решения для случая не кратных частот?
Go to the top of the page
 
+Quote Post
 
Start new topic
Ответов (1 - 11)
MegaVolt
сообщение Jun 8 2015, 12:50
Сообщение #2


Знающий
****

Группа: Свой
Сообщений: 779
Регистрация: 3-01-05
Из: Минск
Пользователь №: 1 783



Короче наваял велосипед.

1. Детектит отсутствие клока в течении Alarm_Time тактов опорной частоты (за счёт синхронизатора выходной сигнал задержан на 2 такта относительно реально отсутствующей частоты. Т.е. частоты нет N тактов но об этом мы узнаём на N+2 такте)
2. Входная частота полностью асинхронная единственое условие Fвх < Fоп/2. Метастабильность учтена.
3. Единичный входной импульс считает наличием частоты.
4. На сигнал Not_Use нужно повесить таймспек на минимальную длинну. Для Xilinx MaxDelay.

Замечания и предложения приветствуются.

Код
----------------------------------------------------------------------------------
-- Company:
-- Engineer:
--
-- Create Date:    13:52:23 06/08/2015
-- Design Name:
-- Module Name:    Clock_Detector - Behavioral
-- Project Name:
-- Target Devices:
-- Tool versions:
-- Description:
--
-- Dependencies:
--
-- Revision:
-- Revision 0.01 - File Created
-- Additional Comments:
--
----------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--use IEEE.NUMERIC_STD.ALL;

-- Uncomment the following library declaration if instantiating
-- any Xilinx primitives in this code.
--library UNISIM;
--use UNISIM.VComponents.all;

entity Clock_Detector is
    Generic (
      Alarm_time      : integer range 2 to 250000 := 4
    );
    Port ( ClkX : in  STD_LOGIC;
           Clk : in  STD_LOGIC;
           Detect : out  STD_LOGIC);
end Clock_Detector;

architecture Behavioral of Clock_Detector is

  function getlog2 (int : in integer) return integer is
    variable log2 : natural := 0;
  begin
    if (int = 0) then
      log2 := 0;
    elsif (int <= 2) then
      log2 := 1;
    else
      log2 := getlog2((int/2) + (int rem 2)) + 1;
    end if;
    return log2;
  end function getlog2;

constant Count_MSB         : natural := getlog2(Alarm_Time);
  
signal Not_Use :std_logic;
signal ClkX_Shift : std_logic;
signal ClkX_Shift1 : std_logic;
signal ClkX_Rise_Sync: std_logic;
signal Count :std_logic_vector(Count_MSB downto 0);
alias Overflow: std_logic is Count(Count_MSB);

begin

process (Clk)
begin  
   if (Clk'event and Clk = '1') then
     Not_Use <= ClkX;
     ClkX_Shift <= Not_Use;
     ClkX_Shift1 <= ClkX_Shift;
   end if;
end process;

ClkX_Rise_Sync <= not ClkX_Shift1 and ClkX_Shift;

process (Clk, ClkX_Rise_Sync)
begin
   if ClkX_Rise_Sync='1' then
      Count <= conv_std_logic_vector((2**Count_MSB-Alarm_Time),Count_MSB+1);
   elsif Clk='1' and Clk'event then
      if (not Overflow)='1' then
         Count <= Count + 1;
      end if;
   end if;
end process;

Detect <= not Overflow;

end Behavioral;


И ещё: чтобы эта дрянь не преобразовывала триггеры в сдвиговый регистр дописать вот это:

-- Synplify Pro: disable shift-register LUT (SRL) extraction
attribute syn_srlstyle : string;
attribute syn_srlstyle of NOT_USE : signal is "registers";
attribute syn_srlstyle of ClkX_Shift : signal is "registers";

-- Xilinx XST: disable shift-register LUT (SRL) extraction
attribute shreg_extract : string;
attribute shreg_extract of NOT_USE : signal is "no";
attribute shreg_extract of ClkX_Shift : signal is "no";
Go to the top of the page
 
+Quote Post
des00
сообщение Jun 8 2015, 13:26
Сообщение #3


Вечный ламер
******

Группа: Модераторы
Сообщений: 7 248
Регистрация: 18-03-05
Из: Томск
Пользователь №: 3 453



Цитата(MegaVolt @ Jun 8 2015, 19:50) *
2. .....единственое условие Fвх < Fоп/2......
3. Единичный входной импульс считает наличием частоты.

попса wink.gif но скорее всего, в ваших условиях, работать будет.


--------------------
Go to the top of the page
 
+Quote Post
MegaVolt
сообщение Jun 8 2015, 13:29
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 779
Регистрация: 3-01-05
Из: Минск
Пользователь №: 1 783



Цитата(des00 @ Jun 8 2015, 16:26) *
попса wink.gif но скорее всего, в ваших условиях работать будет.
C огромным интересом гляну на альтернативы. Желательно в том же объёме ресурсов. Готов смотреть на них даже в ссылках sm.gif

Хотя в чём проблема поделить входную частоту не понимаю sad.gif
Go to the top of the page
 
+Quote Post
des00
сообщение Jun 8 2015, 13:37
Сообщение #5


Вечный ламер
******

Группа: Модераторы
Сообщений: 7 248
Регистрация: 18-03-05
Из: Томск
Пользователь №: 3 453



Цитата(MegaVolt @ Jun 8 2015, 20:29) *
C огромным интересом гляну на альтернативы. Желательно в том же объёме ресурсов. Готов смотреть на них даже в ссылках sm.gif

Ресурсов больше, но и уровень контроля за частотой выше и любые частоты :
CODE

module clk_los_ctrl
#(
parameter int pREFFREQ_HZ = 48_000_000 ,
parameter int pFREQ_HZ = 48_000_000 ,
parameter int pPPM = 100
)
(
iclk ,
ireset ,
irefclk ,
olos
);

//------------------------------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------------------------------

input logic iclk ;
input logic ireset ;
input logic irefclk ;
output logic olos ;

//------------------------------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------------------------------

localparam int cCLK_CNT_W = clogb2(pFREQ_HZ);
localparam bit [63 : 0] cPPMFREQ = (pREFFREQ_HZ * pPPM)/1_000_000 ;
localparam int cREFCLK_CNT_W = clogb2(pREFFREQ_HZ + cPPMFREQ);

logic [cREFCLK_CNT_W-1 : 0] refclk_cnt;
logic refclk_window_start;
logic refclk_window_end;
logic refclk_window;
logic refclk_done;

logic clr;
logic clr_at_clk;

logic ppm_ok;

logic [cCLK_CNT_W-1 : 0] clk_cnt;
logic clk_cnt_done;
logic clk_cnt_done_at_ref_clk;
//------------------------------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------------------------------
// synthesis translate_off
initial begin : ini
refclk_cnt = '0;
refclk_window_start = '0;
refclk_window_end = '0;
refclk_window = '0;
refclk_done = '0;

clr = '0;
ppm_ok = '0;

clk_cnt = '0;
clk_cnt_done = '0;
end
// synthesis translate_on
//------------------------------------------------------------------------------------------------------
// count reference frequency
//------------------------------------------------------------------------------------------------------

always_ff @(posedge irefclk) begin
if (clr)
refclk_cnt <= '0;
else
refclk_cnt <= refclk_cnt + 1'b1;
//
// window
refclk_window_start <= (refclk_cnt == (pREFFREQ_HZ - cPPMFREQ - 2));
refclk_window_end <= (refclk_cnt == (pREFFREQ_HZ + cPPMFREQ - 2));

if (refclk_window_start)
refclk_window <= 1'b1;
else if (refclk_window_end)
refclk_window <= 1'b0;
//
// decision
{clr, refclk_done} <= {refclk_done, refclk_window_end};

if (refclk_window & clk_cnt_done_at_ref_clk)
ppm_ok <= 1'b1;
else if (refclk_done) begin
ppm_ok <= 1'b0;
olos <= ~ppm_ok;
end
end

//------------------------------------------------------------------------------------------------------
// synchronizers
//------------------------------------------------------------------------------------------------------

pulse_synchronizer
#(
.pLENGTH ( 3 )
)
clk_cnt_done_synchronizer // iclk -> irefclk
(
.clkin ( iclk ) , .resetin ( 1'b0 ) , .sin ( clk_cnt_done ) ,
.clkout ( irefclk ) , .resetout ( ) , .sout ( clk_cnt_done_at_ref_clk )
);

pulse_synchronizer
#(
.pLENGTH ( 3 )
)
clr_cnt__synchronizer // irefclk -> iclk
(
.clkin ( irefclk ) , .resetin ( 1'b0 ) , .sin ( clr ) ,
.clkout ( iclk ) , .resetout ( ) , .sout ( clr_at_clk )
);

//------------------------------------------------------------------------------------------------------
// count frequency
//------------------------------------------------------------------------------------------------------

always_ff @(posedge iclk) begin
if (clr_at_clk) begin
clk_cnt <= '0;
clk_cnt_done <= 1'b0;
end
else begin
clk_cnt <= clk_cnt + 1'b1;
clk_cnt_done <= (clk_cnt == (pFREQ_HZ-1));
end
end


endmodule



Цитата(MegaVolt @ Jun 8 2015, 20:29) *
Хотя в чём проблема поделить входную частоту не понимаю sad.gif

В наличии требования делать это руками, все это увеличивает NRE, что по началу кажется пустяком, но со временем понимаешь что это совсем не пустяк


--------------------
Go to the top of the page
 
+Quote Post
MegaVolt
сообщение Jun 9 2015, 06:21
Сообщение #6


Знающий
****

Группа: Свой
Сообщений: 779
Регистрация: 3-01-05
Из: Минск
Пользователь №: 1 783



Цитата(des00 @ Jun 8 2015, 16:37) *
Ресурсов больше, но и уровень контроля за частотой выше и любые частоты :
И время работы нехилое sad.gif
Мне нужен контроль за сбоями а не за самой частотой. Причём быстрый.
Цитата
В наличии требования делать это руками, все это увеличивает NRE, что по началу кажется пустяком, но со временем понимаешь что это совсем не пустяк

NRE это кто? По поводу требования делать руками... это же демка принципа а не финальная девайсина. Делитель дописать не проблема который в зависимости от заданных частот сам делит.

Хотя считать ppm в железе неожиданный подход sm.gif))
Go to the top of the page
 
+Quote Post
andrew_b
сообщение Jun 9 2015, 06:39
Сообщение #7


Профессионал
*****

Группа: Свой
Сообщений: 1 975
Регистрация: 30-12-04
Из: Воронеж
Пользователь №: 1 757



Никогда -- запомните -- никогда не используйте в качестве асинхронного сброса выход комбинаторной функции. Малейшая "иголка" -- и неожиданный сброс.
Go to the top of the page
 
+Quote Post
MegaVolt
сообщение Jun 9 2015, 07:50
Сообщение #8


Знающий
****

Группа: Свой
Сообщений: 779
Регистрация: 3-01-05
Из: Минск
Пользователь №: 1 783



Цитата(andrew_b @ Jun 9 2015, 09:39) *
Никогда -- запомните -- никогда не используйте в качестве асинхронного сброса выход комбинаторной функции. Малейшая "иголка" -- и неожиданный сброс.
Само собой. Не досмотрел скопипастил не от туда.
Спасибо за замечание.

Код счётчика должен быть таким:
Код
process (Clk, ClkX_Rise_Sync)
begin
  if Clk='1' and Clk'event then
    if ClkX_Rise_Sync='1' then
      Count <= conv_std_logic_vector((2**Count_MSB-Alarm_Time),Count_MSB+1);
    elsif (not Overflow)='1' then
         Count <= Count + 1;
    end if;
  end if;
end process;


Сообщение отредактировал MegaVolt - Jun 9 2015, 07:57
Go to the top of the page
 
+Quote Post
XVR
сообщение Jun 9 2015, 09:45
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847



Код
module FreqDetector #(parameter BITS=3)
(
input clk,
input freq_pulse,
output freq_detected
)

reg [BITS-1:0] dly_line;

always @(posedge clk)
dly_line <= (dly_line<<1) |  freq_pulse;

assign freq_detect = | dly_line;

endmodule

На freq_pulse должны быть единичные импульсы (в клоковом домене clk). Если детектируемый сигнал может застрять в состоянии 1, то нужно добавить выделение фронтов.

Ну и всякие цепи сброса тоже не помешают sm.gif
Go to the top of the page
 
+Quote Post
MegaVolt
сообщение Jun 9 2015, 10:16
Сообщение #10


Знающий
****

Группа: Свой
Сообщений: 779
Регистрация: 3-01-05
Из: Минск
Пользователь №: 1 783



Цитата(XVR @ Jun 9 2015, 12:45) *
На freq_pulse должны быть единичные импульсы (в клоковом домене clk).

С частотой следования не меньше Fclk/4. Если реже детектор будет детектировать паузы между импульсами.
Go to the top of the page
 
+Quote Post
XVR
сообщение Jun 9 2015, 10:46
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 3 123
Регистрация: 7-04-07
Из: Химки
Пользователь №: 26 847



Цитата(MegaVolt @ Jun 9 2015, 13:16) *
С частотой следования не меньше Fclk/4. Если реже детектор будет детектировать паузы между импульсами.
Угу. Если нужно меньше - увеличиваете параметр BITS до нужного значения. Но если параметр BITS приходится увеличивать очень сильно, то лучше воспользоваться одной из версий со счетчиком rolleyes.gif

Go to the top of the page
 
+Quote Post
des00
сообщение Jun 10 2015, 04:44
Сообщение #12


Вечный ламер
******

Группа: Модераторы
Сообщений: 7 248
Регистрация: 18-03-05
Из: Томск
Пользователь №: 3 453



Цитата(MegaVolt @ Jun 9 2015, 13:21) *
Мне нужен контроль за сбоями а не за самой частотой. Причём быстрый.

сбои могут быть разного вида, детекторы переходов работают не всегда. но в вашем случае вполне возможно что и работает.
Цитата
NRE это кто?

NRE = Non recursive engineering. Один из основных терминов рассчета трудозатрат в IT проектах. Чем NRE выше, тем проект дороже во всех смыслах. Поэтому делать код Ready-To-Reuse зело полезно.


--------------------
Go to the top of the page
 
+Quote Post

Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 18th July 2025 - 11:45
Рейтинг@Mail.ru


Страница сгенерированна за 0.01457 секунд с 7
ELECTRONIX ©2004-2016