Полезные свойства джиттера
Давайте рассмотрим классическую задачу подключения АЦП по параллельной шине.
В общем виде схема подключения выглядит так:
Шина данных АЦП поступает на выводы ПЛИС, непосредственно внутри блока ввода-вывода находится DDR триггер или десериализатор и далее по параллельной шине данные поступают на FIFO. Проблема заключается в прохождении тактового сигнала. Если использовать глобальный буфер, то время распространения сигнала до буфера и обратно может составлять 5 нс. Это очень много. Это сравнимо с периодом тактовой частоты, которая легко может составлять 200–500 МГц.
Несколько слов почему это плохо.
В общем случае АЦП должно работать в некотором диапазоне частот.
Рассмотрим для примера ситуацию с задержкой такта на 2.8 нс, при тактовой частоте 500 МГц
На первый взгляд всё прекрасно, данные АЦП прекрасно защёлкиваются.
Но вот что произойдёт если частота уменьшиться до 357 МГц, это как раз и составит 2.8 нс?
Данные наезжают на фронт и мы получаем искажение данных. При дальнейшем уменьшении частоты наезд исчезнет и данные снова будут правильными.
Есть два классических способа решения проблемы:
1. В блоке IOB есть элемент задержки, он может установить задержку до 2.4 нс. В большинстве случаев этого достаточно.
2. Существуют специальные элементы bufio, через них путь тактовой частоты становиться гораздо короче.
К сожалению этого не всегда достаточно. Задержка может превышать 2.4 нс, особенно на больших ПЛИС. И не всегда тактовый сигнал заведён на вывод bufio.
Существует простое и элегантное решение этой проблемы. Для этого достаточно сделать так, что бы фаза внутреннего тактового сигнала всегда точно совпадала с фазой тактового сигнала АЦП. Существующие внутри ПЛИС узлы DCM, MMCM, или PLL умеют плавно изменять фазу. А вот датчиком может служить D-триггер внутри блока IOB. Вот схема включения:
Входной сигнал тактовой частоты проходит сквозь IOB и поступает на вход DCM, одновременно он же поступает на вход D-триггера. На тактовый вход D-триггера поступает сигнал после DCM, этот же сигнал поступает на триггеры шины данных АЦП.
И вот что происходит, рассмотрим несколько ситуаций:
Ситуация 1 — фронт глобального сигнала значительно левее фронта входного сигнала.
На выходе триггера — нули.
Ситуация 2 — фронт глобального сигнала в зоне джиттера
На выходе — случайная последовательность. Именно это и есть то самое полезное свойство джиттера. По факту появления случайной последовательности можно определить факт подстройки тактовой частоты.
Ситуация 3 — фронт глобального сигнала значительно правее входного сигнала.
На выходе — единицы.
Все эти ситуации легко обрабатывается конечным автоматом.
В моей реализации существует цикл накопления, в течении 1024 тактов производится подсчёт 1. Если значение счётчика больше 576, то производится сдвиг фазы влево. Если значение счётчика меньше 448, то происходит сдвиг фазы вправо.
На рисунке представлен результат моделирования компонента.
Сигнал clk_in1 — это входная тактовая частота
clk0 — подстроенная частота
clk_fd — детектор фазы
Сигнал phase_locked=1 означает что достигнута подстройка фазы.
psen — сдвиг фазы DCM
psincdec — направление сдвига фазы
shift0 — текущее значение счётчика фазы
Видно, что после подстройки существует небольшой колебательный процесс — сдвиг в пределах одного значения. В реальных системах в установившемся режиме также наблюдается изменение фазы в пределах одного-двух отсчётов.
Перед началом подстройки было так:
Видно, что есть большое смещение между частотами.
А после подстройки так:
Частоты совпадают.
Готовые компоненты представлены на GitHub:
github.com/dsmv/fpga_components
Я выложил два компонента:
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.
В заключении хочу отметить, что эти компоненты используются во многих наших проектах. И они нам сильно помогают.
Комментарии (4)
14 сентября 2016 в 01:12
0↑
↓
Метод интересный, но есть ряд вопросов:
1) Вроде как различные клоковые блоки умеют сами компенсировать задержки выставляя фазу генерируемого клока в соответствии с фазой целевого в нужном месте. Про Xilinx сейчас не помню, а у альтеры в PLL прям опция была.
2) У DCM, насколько мне не изменяет память, весьма большой шаг подстройки фазы. А вот джиттер клока /в тех местах где стоит АЦП/ обычно весьма невелик. Скорее всего его постоянно будет колбасить вперед-назад, на каждом периоде принятия решения?
3) У некоторых микросхем во входных клоковых пинах нету триггеров — и тогда появится дилемма: то ли рассчитывать на такой метод подстройки и заведомо подавать клок на обычные пины то ли подавать на клоковые, но тогда возникают проблемы с размещением триггера где-то в окрестностях.
4) Опять-таки у альтеры на предыдущих циклонах нельзя подать клок на PLL с неклокового входа. Совсем нельзя ;)14 сентября 2016 в 07:31
0↑
↓
1. Они не могут компенсировать задержку на входе микросхемы.
2. Да, обычно происходит сдвиг вперёд и назад.
3. Такие микросхемы мне не попадались. Но вот ситуации, когда я специально выношу триггер из IOB и размещаю его рядом — такое бывает.
4. Это вообще ужас. У Xilinx так можно делать.
14 сентября 2016 в 07:16
0↑
↓
Не вижу разницы между картинками ситуаций 2 и 3.14 сентября 2016 в 07:28
0↑
↓
Спасибо. Исправил.