Джиттер это дрожание фронта тактового сигнала. Чем меньше джиттер тем лучше. Большой джиттер ухудшает параметры АЦП, ухудшает трассировку ПЛИС. Однако есть ситуации когда джиттер полезен. Например его можно использовать при автоматической подстройке тактовой частоты.

Давайте рассмотрим классическую задачу подключения АЦП по параллельной шине.
В общем виде схема подключения выглядит так:
image
Шина данных АЦП поступает на выводы ПЛИС, непосредственно внутри блока ввода-вывода находится DDR триггер или десериализатор и далее по параллельной шине данные поступают на FIFO. Проблема заключается в прохождении тактового сигнала. Если использовать глобальный буфер, то время распространения сигнала до буфера и обратно может составлять 5 нс. Это очень много. Это сравнимо с периодом тактовой частоты, которая легко может составлять 200-500 МГц.

Несколько слов почему это плохо. В общем случае АЦП должно работать в некотором диапазоне частот. Рассмотрим для примера ситуацию с задержкой такта на 2.8 нс, при тактовой частоте 500 МГц.
image
На первый взгляд всё прекрасно, данные АЦП прекрасно защёлкиваются. Но вот что произойдёт если частота уменьшиться до 357 МГц, это как раз и составит 2.8 нс?
image
Данные наезжают на фронт и мы получаем искажение данных. При дальнейшем уменьшении частоты наезд исчезнет и данные снова будут правильными.

Есть два классических способа решения проблемы:

1. В блоке IOB есть элемент задержки, он может установить задержку до 2.4 нс. В большинстве случаев этого достаточно.

2. Существуют специальные элементы bufio, через них путь тактовой частоты становиться гораздо короче.

К сожалению этого не всегда достаточно. Задержка может превышать 2.4 нс, особенно на больших ПЛИС. И не всегда тактовый сигнал заведён на вывод bufio.

Существует простое и элегантное решение этой проблемы. Для этого достаточно сделать так, что бы фаза внутреннего тактового сигнала всегда точно совпадала с фазой тактового сигнала АЦП. Существующие внутри ПЛИС узлы DCM, MMCM, или PLL умеют плавно изменять фазу. А вот датчиком может служить D-триггер внутри блока IOB. Вот схема включения:
image
Входной сигнал тактовой частоты проходит сквозь IOB и поступает на вход DCM, одновременно он же поступает на вход D-триггера. На тактовый вход D-триггера поступает сигнал после DCM, этот же сигнал поступает на триггеры шины данных АЦП. И вот что происходит, рассмотрим несколько ситуаций:

Ситуация 1 – фронт глобального сигнала значительно левее фронта входного сигнала. На выходе триггера – нули.
image
Ситуация 2 – фронт глобального сигнала в зоне джиттера. На выходе – случайная последовательность. Именно это и есть то самое полезное свойство джиттера. По факту появления случайной последовательности можно определить факт подстройки тактовой частоты.

Ситуация 3 – фронт глобального сигнала значительно правее входного сигнала. На выходе – единицы.

Все эти ситуации легко обрабатывается конечным автоматом. В моей реализации существует цикл накопления, в течении 1024 тактов производится подсчёт 1. Если значение счётчика больше 576, то производится сдвиг фазы влево. Если значение счётчика меньше 448, то происходит сдвиг фазы вправо.

На рисунке представлен результат моделирования компонента.

Сигнал clk_in1 – это входная тактовая частота
clk0 – подстроенная частота
clk_fd – детектор фазы
Сигнал phase_locked=1 означает что достигнута подстройка фазы.
psen – сдвиг фазы DCM
psincdec – направление сдвига фазы
shift0 – текущее значение счётчика фазы

Видно, что после подстройки существует небольшой колебательный процесс — сдвиг в пределах одного значения. В реальных системах в установившемся режиме также наблюдается изменение фазы в пределах одного-двух отсчётов. Перед началом подстройки было так:



Видно, что есть большое смещение между частотами. А после подстройки так:


Частоты совпадают.

» Готовые компоненты представлены на GitHub:

Я выложил два компонента:

ctrl_dcm_phase_v6 –DCM установлен внутри. Это для ПЛИС Spartan 3, Virtex 4, Virtex 5
ctrl_dcm_phase_v8 – внешний DCM или MMCM, это для Virtex 6, Kintex 7.

Несколько слов про моделирование. Поскольку в основе лежит случайный процесс, то это создаёт некоторые проблемы. Но они решаемые. В стенде используется компонент model_line_v1, который как раз формирует джиттер на тактовом сигнале. Для формирования джиттера используется функция UNIFORM из библиотеки math_real.

В заключении хочу отметить, что эти компоненты используются во многих наших проектах. И они нам сильно помогают.
Поделиться с друзьями
-->

Комментарии (15)


  1. nerudo
    14.09.2016 01:12

    Метод интересный, но есть ряд вопросов:
    1) Вроде как различные клоковые блоки умеют сами компенсировать задержки выставляя фазу генерируемого клока в соответствии с фазой целевого в нужном месте. Про Xilinx сейчас не помню, а у альтеры в PLL прям опция была.
    2) У DCM, насколько мне не изменяет память, весьма большой шаг подстройки фазы. А вот джиттер клока /в тех местах где стоит АЦП/ обычно весьма невелик. Скорее всего его постоянно будет колбасить вперед-назад, на каждом периоде принятия решения?
    3) У некоторых микросхем во входных клоковых пинах нету триггеров — и тогда появится дилемма: то ли рассчитывать на такой метод подстройки и заведомо подавать клок на обычные пины то ли подавать на клоковые, но тогда возникают проблемы с размещением триггера где-то в окрестностях.
    4) Опять-таки у альтеры на предыдущих циклонах нельзя подать клок на PLL с неклокового входа. Совсем нельзя ;)


    1. dsmv2014
      14.09.2016 07:31

      1. Они не могут компенсировать задержку на входе микросхемы.
      2. Да, обычно происходит сдвиг вперёд и назад.
      3. Такие микросхемы мне не попадались. Но вот ситуации, когда я специально выношу триггер из IOB и размещаю его рядом — такое бывает.
      4. Это вообще ужас. У Xilinx так можно делать.


    1. defecator
      14.09.2016 11:49
      +1

      Я не знаю, про какие Циклоны вы говорите,
      но у Альтеры на любых поколениях Циклонов — от первого до пятого — клок на PLL можно подать с любого входа.


      1. nerudo
        14.09.2016 12:12

        Открываем хэндбук на, к примеру 4 циклон, на картинке 5-1 на стр. 5-11 (73) и видим подключение к PLL только с dedicated clock inputs. Чтобы убедиться наверняка, читаем предложение (специально выделенное) «The general I/O pins cannot drive the PLL clock input pins» на стр. 5-18 (80). В пятом циклоне действительно клоковую структуру усложнили и можно подавать откуда угодно.


        1. jok40
          15.09.2016 08:41

          Да, в документе, на который Вы ссылаетесь, действительно есть такая фраза — «The general I/O pins cannot drive the PLL clock input pins». Однако…
          Открыл прямо сейчас проект на Cyclone IV E, поменял подключенную к PLL ножку (dedicated) на другую — первую попавшуюся под руку. Скомпилировал — скомпилировалось без ошибок. Только варнинг добавился:
          «Warning (15064): PLL „pll:PLL_INST|altpll:altpll_component|pll_altpll:auto_generated|pll1“ output port clk[1] feeds output pin „CLK_o~output“ via non-dedicated routing — jitter performance depends on switching rate of other design elements. Use PLL dedicated clock outputs to ensure jitter performance».


          1. nerudo
            15.09.2016 08:48

            Вы сейчас вроде написали про вывод клока с PLL на выходной пин. А речь шла про подачу опорного клока на PLL.


            1. jok40
              15.09.2016 08:49

              Нет, я поменял именно входную ножку. Почему варнинг ссылается на выходную — я сам не понимаю.


            1. jok40
              15.09.2016 09:48

              Прошу прощения за дезинформацию. При смене ножки на первую попавшуюся я совершенно случайно попал на другую dedicated-ножку (бывают же совпадения!). Сейчас это заметил и перешёл на ножку, которая на самом деле не является выделенной — проект перестал синтезироваться с ошибкой «Error (176554): Can't place PLL „pll:PLL_INST|altpll:altpll_component|pll_altpll:auto_generated|pll1“ — I/O pin ARDY_i (port type INCLK of the PLL) is assigned to a location which is not connected to port type INCLK of any PLL on the device».

              Так что Вы совершенно правы.


              1. Kopart
                15.09.2016 10:02

                Есть рабочий вариант как обойти эту ошибку в любом семействе.
                Поставьте примитивы lcell и затем global между пином и PLL

                Пример с примитивами
                lcell lcell (
                .in (in_clk),
                .out (out_lcell)
                );

                global global (
                .in (out_lcell),
                .out (in_pll)
                );


                1. nerudo
                  15.09.2016 10:56

                  Если бы все было так просто! Там физически нету такого соединения, которое бы шло из внутреннего интерконнекта на вход PLL.
                  Есть возможность каскадирования PLL, но для этого все равно надо чтоб клок попал на первую в ряду PLL. Там про это так написано: This input port is fed by a pin-driven dedicated GCLK, or through a clock control block if the clock control block is fed by an output from another PLL or a pin-driven dedicated GCLK. An internally generated global signal cannot drive the PLL.
                  Как они так умудрились сделать — черт их знает, загадка для меня…


  1. jok40
    14.09.2016 07:16

    Не вижу разницы между картинками ситуаций 2 и 3.


    1. dsmv2014
      14.09.2016 07:28

      Спасибо. Исправил.


  1. Katran_t
    15.09.2016 01:14

    Что Вы подразумеваете под «ухудшает трассировку ПЛИС»?
    В вашем случае расфазировка очень большая. О каком типе джиттера идет речь?


    1. dsmv2014
      15.09.2016 01:18

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


      1. Katran_t
        15.09.2016 11:23
        +1

        Здесь видимо идет речь о периодическом джиттере. Для источников тактовых сигналов он на уровне пикосекунд и менее. Тот джиттер, который Вы описываете — следствие прохождения сигнала через ПЛИС?