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

делитель частоты и джиттер

Здравствуйте!

Задача такова: имеется генератор с частотой 33 МГц и джиттером N пикосекунд (генератор подключен ко входу CLK0 ПЛИС семейства Cyclone III).

требуется на ПЛИС реализовать управляемый делитель частоты (1/2, 1/4, 1/6, 1/8, 1/10, 1/12, 1/14, 1/16). Требуется на выходе делителя получить сигнал с как можно меньшим джиттером (разумеется, джиттер меньше чем N пс получить не выйдет).

 

Моё решение:

LIBRARY ieee;
USE ieee.std_logic_1164.all;
USE ieee.std_logic_unsigned.all;

ENTITY clkdiv IS
    GENERIC
        (
            divsz : natural := 3 -- разрядность счетчика
        );    
    PORT
        (
            clk: in std_logic; -- входной клок
            div: in std_logic_vector((divsz-1) downto 0); -- коэффициент деления
            sco: out std_logic -- выходной клок
        );
END clkdiv;

ARCHITECTURE rtl OF clkdiv IS
    signal CN : std_logic_vector((divsz-1) downto 0); -- счетчик
    signal T,Q : std_logic;
BEGIN
    T<='1' when (CN=div) else '0';
    process (clk,T)
    begin
        if (falling_edge(clk)) then    -- по спаду клока
            if (T='1') then
                CN<=(others=>'0');
            else
                CN<=CN+1;
            end if;
        end if;
    end process;
    
    process (clk,T)
    begin
        if (rising_edge(clk) and (T='1')) then -- по фронту клока
            Q<=not Q;
        end if;
    end process;
    sco<=Q;
END rtl;

 

Дополнительная синхронизация (та, что по переднему фронту) внесена в схему для того, чтобы время переключения выходного сигнала не зависело от скорости работы сумматора и схемы сравнения (мало ли время срабатывания зависит от значения CN и div).

 

Вопросы:

1) насколько корректна такая реализация?

2) как такое решение может повлиять на джиттер выходного сигнала?

3) ПЛИС и джиттер - как они вообще связаны.

post-28852-1242678519_thumb.png

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


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

(разумеется, джиттер меньше чем N пс получить не выйдет.

Почему же? В принципе это возможно. Любая PLL работает как jitter cleaner. Она фильтрует джиттер с частотами выше, чем частота фильтра в петле обратной связи PLL. Если у входного клока безумно большой и высокочастотный джиттер, то Циклоновская PLL может его почистить.

 

3) ПЛИС и джиттер - как они вообще связаны.

Помнится, Альтера не гарантирует, что джиттер на выходе Циклона будет меньше чем 150 пс. Сравните типичные цифры джиттера, которую добавляет логика разного типа:

------------------------------------------------
тип                jitter, ps rms
------------------------------------------------
FPGA               33 to 50 
74LS00             5 
74HCT00            2.2
74ACT00            1
MC100EL16 (PECL)   0.7
NBSG16 (ECL)       0.2 

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


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

В своём вопросе я не конкретизировал джиттер. Я точно не могу его оценить, но думаю генератор даёт джиттер порядка <30 пикосекунд.

 

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

Если говорить о циклоновской PLL - то она добавит джиттера.

 

Помнится, Альтера не гарантирует, что джиттер на выходе Циклона будет меньше чем 150 пс. Сравните типичные цифры джиттера, которую добавляет логика разного типа:

------------------------------------------------
тип                jitter, ps rms
------------------------------------------------
FPGA               33 to 50 
74LS00             5 
74HCT00            2.2
74ACT00            1
MC100EL16 (PECL)   0.7
NBSG16 (ECL)       0.2 

 

Откуда такая информация?

 

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

По идее, в моей реализации джиттер будет зависить от джиттера переднего фронта clk и триггера Q.

 

Прошу исправить, если я где ошибаюсь.

 

P.S. У меня задача стоит тактировать сигма-дельта АЦП AD7764, судя по даташиту, джиттер на входе не должен превышать 50 пс.

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


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

Откуда такая информация?

 

Analog Devices AN-501

 

 

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

От кристалла. Значительная часть джиттера возникает за счет пологих фронтов на выходах и плавающего порога срабатывания по входам. Земля и питание внутри больших кристалллов сильно болтаются, поэтому пороги срабатывания FPGA плавают. А еще джиттера добавляет crosstalk. И т.д.

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


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

post-28852-1242678519_thumb.png

 

Мдааа. Конечно, я с Cyclon 3 не работал, но визуально схема - отвратительная (на уровне начинающего):

1. Выходной триггер имеет обратную связь, в нормальных ПЛИС в IOB это не ложиться (или у Cyclon 3 нет выходных триггеров ?) - соответственно будет прирост jitter'а за счет передачи логического сигнала к выходному буферу (обычно clock распространяеста по ПЛИС с меньшим jitter'ом, чем все остальные сигналы).

2. Э-хе-хе... Кто ж так делитель делает ??! Нормальные люди используют выходной перенос (назовём его CY) загружаемого счетчика: сам CY подается на счетный триггер, сигнал с которого подается на дополнительный выходной триггер (обязательно выходной триггер, иначе дополнительный прирост jitter’а). Дополнительно CY подаётся на вход Load это загружаемого счётчика, а вот значением, которое загружается - выбирается количество тактов, которое счетчик будет досчитывать до переноса (т.е. коэффициент деления). Такая схема значительно компактнее и быстродейственней... если конечно суметь правильно сделать тот самый загружаемый счетчик.

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


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

1. Выходной триггер имеет обратную связь, в нормальных ПЛИС в IOB это не ложиться (или у Cyclon 3 нет выходных триггеров ?)

Как раз в нормальных ПЛИС это с легкостью ложится в IOE, так как обратная связь из IOE предусмотрена. Или ложится туда через register duplication (когда на вход регистра в IOE идет тот же сигнал, что и на вход регистра-копии в LE, что делается незаметно для разработчика при place/route).

 

Ну а в остальном, по архитектуре схемы, согласен.

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


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

Или ложится туда через register duplication (когда на вход регистра в IOE идет тот же сигнал, что и на вход регистра-копии в LE, что делается незаметно для разработчика при place/route).

Да есть такой метод (и очень хорошо помогает), но в данном случае это обязательное требование (наличие Output FF), поэтому, на мой взгляд, теневое register duplication не подходит - это надо делать в явном виде, а потом еще и проконтролировать, что после оптимизаций всё получилось как задумано.

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


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

теневое register duplication не подходит - это надо делать в явном виде

Так достаточен assignment "Fast Output Register = on" для выходного пина, что и будет тем самым "явным видом", и потом хоть контролируй, хоть нет, а гарантия того, что выходной регистр сидит в IOE 100%. А уж каким методом там это в результате оптимизаций сделано IMHO не важно, хоть дупликацией, хоть фидбеком с выхода IOE. То есть, что я имею в виду - если указан констрейн, что Fast Output Register, то он ляжет в IOE, и никаких гвоздей. Не может быть регистров, которые туда не ложатся (за исключением того, что слишком много регистров одновременно пытаются запихать)

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


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

Нормальные люди используют выходной перенос (назовём его CY) загружаемого счетчика: сам CY подается на счетный триггер, сигнал с которого подается на дополнительный выходной триггер (обязательно выходной триггер, иначе дополнительный прирост jitter’а). Дополнительно CY подаётся на вход Load это загружаемого счётчика, а вот значением, которое загружается - выбирается количество тактов, которое счетчик будет досчитывать до переноса (т.е. коэффициент деления). Такая схема значительно компактнее и быстродейственней... если конечно суметь правильно сделать тот самый загружаемый счетчик.

 

Примерчик можно?

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


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

Примерчик можно?

 

Я думаю, что речь о чем-то типа того:

 

reg [2:0] tckg_prediv;
reg tckg_en;
reg [11:0] tckg_div_coeff;
reg [10:0] tckg_coeff_a, tckg_coeff_b, tckg_coeff;
reg [10:0] tckg_cnt;
reg tckg_cnt_z;
reg ckg_reg_a;

// coefficient for even halfwave
always @(posedge tckg_clk)
   tckg_coeff_b <= tckg_div_coeff[11:1] + tckg_div_coeff[0];

// coefficient for odd halfwave
always @(posedge tckg_clk)
   tckg_coeff_a <= tckg_div_coeff[11:1];
   
// additional optional pre-divider with enable (control[7])
always @(posedge tckg_clk)
  tckg_prediv <= control[7] ? (tckg_prediv + 1'b1) : 3'h0;

// pre-divider zero pass
always @(posedge tckg_clk)
  tckg_en <= !(|tckg_prediv);

// main divider zero pass
always @(posedge tckg_clk)
  tckg_cnt_z <= tckg_cnt == 11'h001;
  
// output T-ff;  ckg_reg_a is output of generated frequency
always @(posedge tckg_clk)
  if (tckg_en && tckg_cnt_z)
    ckg_reg_a <= ~ckg_reg_a;

// coefficient mux for even/odd halfwaves
always @(posedge tckg_clk)
  if (tckg_en && tckg_cnt_z) 
    tckg_coeff <= ckg_reg_a ? tckg_coeff_b : tckg_coeff_a;

// carry pipeline for main divider
reg [1:0] cntc;
always @(posedge tckg_clk)
  if (tckg_en)
  begin
    cntc[0] <= tckg_cnt[3:0] == 4'h1;
    cntc[1] <= tckg_cnt[7:0] == 8'h1;
  end

// main divider itself
always @(posedge tckg_clk)
  if (tckg_en)
    if (tckg_cnt_z) tckg_cnt <= tckg_coeff; else 
      begin
        tckg_cnt[3:0] <= tckg_cnt[3:0] - 1'b1;
        tckg_cnt[7:4] <= tckg_cnt[7:4] - cntc[0];
        tckg_cnt[10:8] <= tckg_cnt[10:8] - cntc[1];
      end

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


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

Я думаю, что речь о чем-то типа того:

 

Счетчик впечатляет конечно.

Но речь ведь шла о выходном клоке. Самого интересного нет.

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


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

Но речь ведь шла о выходном клоке. Самого интересного нет.

 

Для тех, кто в танке, повторяю кусок кода еще раз методом copy-paste:

 

// output T-ff;  ckg_reg_a is output of generated frequency
always @(posedge tckg_clk)
  if (tckg_en && tckg_cnt_z)
    ckg_reg_a <= ~ckg_reg_a;

 

Способ засовывания этого триггера в IOE уже дело вкуса. Я предпочитаю констрейн "Fast Output Register", а кто-то пропускает через еще один триггер, указывая видимо констрейн уже ему, но это мелочи, не заслуживающие внимания.

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


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

Для тех, кто в танке, повторяю кусок кода еще раз методом copy-paste:

 

Конечно, это не Корней Чуковский. Но все равно спасибо.

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


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

То есть, что я имею в виду - если указан констрейн, что Fast Output Register, то он ляжет в IOE, и никаких гвоздей. Не может быть регистров, которые туда не ложатся (за исключением того, что слишком много регистров одновременно пытаются запихать)

Совсем не уверен. Если триггер не может туда лечь, он не ляжет, причем без предупреждений. (Altera, IMHO, проверять лениво)

 

Я думаю, что речь о чем-то типа того:

Более чем впечатляет.

 

Я бы так:

always @(posedge clk)
begin
    if (counter == 3'b0)
    begin
        out <= ~out;
        counter <= (divider[3:1] - 1'b1);
    end
    else
        counter <= counter - 1'b1;
end

А если есть желание избавиться от джиттера ПЛИС, то надо вынести последний триггер за пределы ПЛИС.

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


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

Совсем не уверен. Если триггер не может туда лечь, он не ляжет, причем без предупреждений. (Altera, IMHO, проверять лениво)

А я уверен. Если насильно register duplication не отключили, то если триггер не может туда лечь, то туда ложится копия этого триггера. Если отключили, то сами виноваты, констрейны это святое ;) По крайней мере вышеприведенный ckg_reg_a ложится и в альтере (cyclone-ii), и в LatticeXP без каких либо противопоказаний.

 

Я бы так:

Ну да, в контексте конкретной задачи от автора поста самое оно, и десяток строк против килобайта текста. Моя же цель была слегка посложнее, и на частотах аццких.

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


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

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

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

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

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

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

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

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

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

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