У нас на сайте уже была пара статей про PLL.
PLL - это, если говорить просто, встроенный в ПЛИС генератор тактовых частот. Он позволяет из одной входной тактовой частоты синтезировать несколько других с иной заданной частотой, скважностью и, при желании, с некоторым начальным сдвигом фазы.
Наша статья "Использование PLL" довольно подробно рассказывала как создать и настроить PLL в Altera Quartus II MegaWizard PlugIn-Manager. С тех пор прошло довольно много времени и теперь, в Quartus Prime, доступ к визарду осуществляется через пункт меню Tools => IP Catalog. Модуль PLL создается с помощью этого каталога. В нем выбираете Library => Basic Functions => Clocks; PLLs and Resets => PLL => ALTPLL. Остальные настройки - все как и раньше.
Сейчас я хочу рассказать о возможности динамически сдвигать фазу тактовой частоты PLL. Эта возможность есть в PLL таких FPGA, как Cyclone III, Cyclone IV, в MAX10 и других. Сказать по правде я и сам вот только что ознакомился с этой функцией в PLL. Просто раньше у меня в этом не было никакой необходимости, а сейчас появился проект, где это может понадобиться. Сдвиг фазы PLL - это похоже единственный способ аккуратно управлять задержками сигналов.
Давайте попробуем поэкспериментировать с фазой тактовой частоты.
Нам понадобится оригинальная документация компании Altera/Intel https://www.altera.com/en_US/pdfs/literature/hb/max-10/ug_m10_clkpll.pdf
Итак, в визарде есть закладка под номером 2: PLL Reconfiguration. там внизу ставим галочку: Create optional inputs for dynamic phase reconfiguration.
Как только ставим галочку, то слева визард показывает блок PLL и в нем появляются новые входы и выходы, которых раньше не было.
Это входы
- phasecounterselect[2..0]
- phaseupdown
- phasestep
- scanclk
и выход
- phasedone
С помощью этих сигналов можно управлять фазами любой выходной тактовой частоты PLL.
При этом, все операции по перенастройке PLL осуществляются на частоте scanclk. Она должна быть не выше 100МГц по документации MAX10. По другим FPGA нужно читать и уточнять - не знаю, думаю где-то так же.
Сигнал phasecounterselect[2..0] позволяет выбрать, какой именно из внутренних счетчиков PLL будет изменяться. В документации на PLL ПЛИС MAX10 есть вот такая таблица:
Таким образом, если нужно сдвинуть фазу выходной тактовой частоты c0, то нужно ставить phasecounterselect = 3'b010. Если сдвигаем по фазе тактовую частоту c1, то phasecounterselect = 3'b011.
Фазовый сдвиг выходной тактовой частоты инициируется установкой сигнала phasestep в логическую единицу. Это будет начало транзакции по сдвигу фазы. За одну "транзакцию" фаза избранной частоты сдвигается на один шаг фазы (об этом чуть позже). По окончании сдвига фазы тактовой частоты PLL выставляет сигнал phasedone. Если требуется сдвинуть фазу еще, то нужно сперва опустить phasestep в логический ноль, и затем опять установить в единицу, начиная следующую транзакцию.
Сигнал phaseupdown определяет направление сдвига фазы, вперед или назад.
Теперь главный вопрос: а на сколько собственно мы можем сдвинуть фазу тактовой частоты? В документации четко написано, что шаг фазового сдвига - это 1/8 периода частоты VCO PLL. VCO - внутренний генератор управляемый напряжением. К сожалению, в визарде PLL нет возможности явно выставлять желаемую частоту Fvco. Ее можно только посмотреть какая получится при наших настройках.
Например: если входная частота на PLL 100МГц и выходную частоту PLL я ставлю 100МГц, то визард сам говорит, что Fvco внутри PLL будет 600МГц.
Это значит, что разрешение по фазе, один фазовый сдвиг тактовой частоты можно сделать примерно на 7,5 градусов, то есть можно сдвинуть фронт частоты на 208,33 пикосекунд. А можно ли повысить разрешение?
Мне удалось подобрать вот такие коэффициенты:
- выход PLL c0, коэффициент умножения 98, коэффициент деления 99, результирующая частота ~98.974359МГц
- выход c1 - такая же, с коэффициентами 98/99
- выход c2 - 91/99, выходная частота примерно 91.904762
При этом я вижу, что Fvco = 1286,666МГц, а разрешение по фазе стало 97,15 пикосекунд. Это очень высокая разрешающая способность по фазе.
В документации на PLL есть вот такая временная диаграмма, показывающая, как производится динамический сдвиг фазы:
Я предлагаю, попробовать просимулировать это дело в ModelSim.
Делаю простой проект в Intel Quartus Prime Lite, где нет практически ничего, кроме одной PLL и простейшей логики, которая периодически сдвигает фазу выходной частоты c1. Модуль верхнего уровня проекта я написал на Verilog:
module top(
input wire KEY0,
input wire KEY1,
input wire CLK100MHZ,
inout wire [19:0]IO,
output wire [7:0]LED
);
wire wc0;
wire wc1;
wire wc2;
wire wlocked;
wire wpdone;
reg phase_step = 1'b0;
mypll mypll_ (
.areset( 1'b0 ),
.inclk0( CLK100MHZ ),
.phasecounterselect( 3'b011 ),
.phasestep( phase_step ),
.phaseupdown( 1'b1 ),
.scanclk( wc0 ),
.c0( wc0 ),
.c1( wc1 ),
.c2( wc2 ),
.locked( wlocked ),
.phasedone( wpdone )
);
reg [3:0]cnt = 0;
always @( posedge wc0 )
cnt <= cnt + 1;
always @( negedge wc0 )
if( cnt==4'hF )
phase_step <= 1'b1;
else
if( wpdone==1'b0 )
phase_step <= 1'b0;
assign LED = 0;
assign IO[0] = wc0;
assign IO[1] = wc1;
assign IO[19:2] = 0;
endmodule
Я делаю проект как бы для платы Марсоход3bis и чипом ПЛИС MAX10. Поэтому у меня здесь есть входные сигналы KEY0 и KEY1, которые сейчас не используются, но пусть будут.. Выходные сигналы LED не используются, но на выходы IO[0] и IO[1] я вывел выходы c0 и c1 из PLL. Это чтобы их удобно было наблюдать в симуляторе.
Здесь в проекте все процессы происходят на частоте c0, и эта же частота подается на scanclk. По спаду этой же частоты устанавливается и сбрасывается phase_step.
Тестбенч для симуляции не делает ничего особенного, ну вот только подает на тестируемый модуль исходную тактовую частоту 100МГц.
Вот тестбенч:
`timescale 1ns / 10ps
module testbench();
//assume basic clock is 100Mhz
reg clk;
initial clk=0;
always
#5 clk = ~clk;
wire [7:0]w_led;
wire [19:0]w_io;
top top_inst(
.CLK100MHZ( clk ),
.KEY0( 1'b1 ),
.KEY1( 1'b1 ),
.IO( w_io ),
.LED( w_led )
);
endmodule
Поскольку я хочу посмотреть на довольно малые сдвиги фаз тактовых частот, то я бы, конечно, хотел провести временную симуляцию проекта в ModelSim. Для этого я указал в настройках проекта, что я буду использовать ModelSim-Altera для симуляции. При этом я ожидал увидеть сгенерированные выходные файлы проектов типа SDO или SDF.
К сожалению мой квартус иного мнения.
При компиляции проекта он выдает сообщение: Warning (10905): Generated the EDA functional simulation netlist because it is the only supported netlist type for this device. Получается, что для микросхем MAX10 пока можно сделать только функциональную симуляцию? Квартус сгенерировал мне только файл top.vo
Ну ладно, пробую так. Создаю в ModelSim новый проект и библиотеку work, добавляю в нее мои два файла tb.v и top.vo, компилирую их в ModelSim. В начале симуляции нужно еще указать используемые библиотеки: altera_mf_ver, altera_ver и fiftyfivenm_ver. Подробнее о симуляции PLL в ModelSim можно посмотреть вот здесь.
Что я вижу на временных диаграммах: Модуль top периодически выставляет сигнал phase_step и PLL отвечает коротким импульсом в ноль сигналом phasedone.
Если сделать zoom и попытаться рассмотреть подробнее фазы тактовых частот, то сразу становится видно, что фаза сигнала IO[1], который у меня подключен к выходу PLL с1 уходит вперед сразу после сигнала phasedone:
Получается, что в симуляции я уже могу видеть как сдвигается фаза тактовой частоты. Кстати, обратите внимание, насколько мал шаг фазы по сравнению с периодом самой частоты. Эффект сдвига фазы можно попробовать использовать в схемах измерения задержки синалов, в рефлектометрах и прочих измерителях.
Я постараюсь сделать проект простого измерителя, который сможет оценивать задержку распространения сигнала с точностью около 100 пикосекунд.
Подробнее...