
Так иногда бывает, что занимаешься одной технической проблемой, но, по мере погружения в задачу и во время поиска ее решения, появляются «побочные продукты». Так случилось и в этот раз. Я исследовал различные методы измерения временных интервалов с помощью ПЛИС. В одном из предложенных методов измерений был использован динамический сдвиг фазы тактовой частоты с PLL. Позже пришла идея: используя свойства PLL можно попробовать сделать в ПЛИС простейший радиопередатчик с фазовой модуляцией.
Пожалуй нужно немного рассказать, что такое PLL.
PLL (Phase Locked Loop) — это устройство фазовой автоподстройки частоты генератора. Выглядит примерно вот так:

Здесь есть ГУН — Генератор, Управляемый Напряжением. Он выдает желаемую частоту, которая через обратную связь идет на фазовый детектор. Фазовый детектор определяет разность фаз между опорной частотой F0 и получившейся частотой F1, разность фаз — это сигнал ошибки, который отфильтровывается и воздействует на ГУН, заставляя его колебаться чуть быстрее или чуть медленнее. Так, на выходе ФАПЧ получается частота, синхронная с опорной.
В микросхемах ПЛИС, например, от компании Интел (эх… когда-то была Альтера) серии MAX10 есть встроенный PLL, который выглядит вот так:

Кажется, что это что-то гораздо более сложное, чем то, что изображено выше. Но нет, если присмотреться внимательно, то видны общие черты: ГУН, Генератор Управляемый Напряжением — это VCO, Voltage Controlled Oscilator. PFD — это фазовый детектор, LF — Loop Filter, фильтр фазовой ошибки.
Кроме всего прочего, PLL внутри ПЛИС имеет набор счетчиков делителей. Например, делитель частоты M в цепи обратной связи позволяет получить на выходе PLL частоту в несколько раз выше, чем опорная. Так же имеются выходные счетчики C0-C4, которые позволяют на пяти выходах PLL получить сетку частот с разными делителями.
Есть внутри PLL еще компоненты, которые почему-то обычно не изображаются на структурных схемах в документации Altera/Intel — это схемы управляющие перезагрузкой и перенастройкой PLL. Логические схемы в ПЛИС могут на лету перезагружать коэффициенты счетчиков делителей в PLL и еще они позволяют сдвигать фазу выходных частот PLL. Конечно, перезагрузить на лету параметры PLL — это не очень простая операция, которая к тому же занимает определенное время. А вот сдвигать фазу выходной частоты PLL можно довольно просто и быстро. Причем, разрешающая способность по фазе напрямую зависит от частоты Fvco. Сдвигать фронт тактовой частоты можно на 1/8 периода Fvco. Например, входная частота на PLL Fin=100МГц, а делитель M в цепи обратной связи к фазовому детектору равен 13-ти. Тогда Fvco=1300МГц, а разрешение по фазе для выходной частоты PLL Fout=100МГц будет составлять всего 3,46 градуса.
Для разработки проекта для ПЛИС Altera/Intel используется среда САПР Quartus Prime и в ней есть средства настройки экземпляров PLL: Megawizard Plug-In Manager. С его помощью можно устанавливать нужные свойства PLL:

Здесь как раз и видно какие получаются Fvco и разрешение по фазе для выходных частот.
Для управления фазой выходных частот у компонента PLL есть дополнительные сигналы: SCANCLK, PHASESTEP, PHASEUPDOWN, PHASECOUNTERSELECT, PHASEDONE.
В документации Altera/Intel написано, как управлять этими сигналами, чтобы получить единичный сдвиг фазы на избранной выходной частоте.

Получается так: сигнал PHASEUPDOWN определяет в какую сторону нужно двигать фазу. PHASECOUNTERSELECT определяет сигнал какой именно тактовой частоты PLL будет сдвинут (например, если нужно сдвинуть частоту c1, то PHASECOUNTERSELECT=3’b011 — это есть в документации). Цикл сдвига фазы начинается с установки сигнала PHASESTEP и заканчивается, когда PLL выставит в ноль PHASEDONE. Если нужно сдвинуть фазу значительно, то придется выполнить несколько таких циклов. Все это при желании можно даже просимулировать в ModelSim, как это делается я писал вот здесь.
Теперь, дальше — интереснее. Плавно перехожу к моему «радиопередатчику»:

Я использую плату Марсоход3bis на чипе ПЛИС Altera/Intel MAX10. Плата имеет встроенный программатор на базе двухканального чипа FTDI. Причем один канал FT2232HL используется под JTAG (загрузка ПЛИС, отладка в SignalTap), а второй канал используется для передачи данных в плату, как последовательный порт.
К плате, прямо к двум цифровым пинам-выходам подключены два куска провода по 0,75 метра. Это антенна, «полуволновый вибратор». Без выходного аналогового фильтра на излучаемый диапазон, конечно, не хорошо, но сама антенна уже какой-то фильтр, да и мощность передатчика невелика…
Проект написан на языке Verilog HDL — всего-то пара десятков строк кода:
module top( input wire CLK100MHZ, input wire key0, input wire key1, input wire FTDI_BD0, //serial RX line output wire [19:0]io ); wire wc0; wire wc1; wire wlocked; wire wpdone; wire up_down; reg pstep; wire scanclk; assign scanclk = wc0; reg [7:0]cnt8; always @( posedge scanclk ) cnt8 <= cnt8 + 8'h01; mypll mypll_ ( .areset( ~key0 ), .inclk0(CLK100MHZ), .phasecounterselect( 3'b011 ), .phasestep( pstep ), .phaseupdown( up_down ), .scanclk(scanclk), .c0(wc0), .c1(wc1), .locked(wlocked), .phasedone( wpdone ) ); wire [7:0]w_rx_byte; wire w_byte_ready; reg [1:0]byte_rdy; always @( posedge wc0 ) byte_rdy <= {byte_rdy[0],w_byte_ready}; serial receiver( .reset( ~wlocked ), .clk100( wc0 ), //100MHz .rx( FTDI_BD0 ), .sbyte( 8'h00 ), .send( 1'b0 ), .rx_byte( w_rx_byte ), .rbyte_ready( w_byte_ready ), .tx(), .busy(), .rb() ); reg [7:0]current_pll_phase = 0; wire [7:0]signal; assign signal = w_rx_byte[7:0]; assign up_down = signal>current_pll_phase; reg [3:0]state = 0; always @( negedge scanclk ) begin case(state) 0: begin //wait recv byte if( byte_rdy ) state <= 1; end 1: begin //do we really need to change phase? if( current_pll_phase==signal ) state <= 0; else state <= 2; end 2: begin //wait phase done if( ~wpdone ) state <= 3; end 3: begin state <= 4; end 4: begin state <= 1; end endcase if( pstep && (~wpdone) ) if( up_down ) current_pll_phase <= current_pll_phase + 6'h1; else current_pll_phase <= current_pll_phase - 6'h1; if( ~wpdone ) pstep <= 1'b0; else if( state==2 ) pstep <= 1'b1; end assign io[17:0] = 0; assign io[18] = wc1; assign io[19] = ~wc1; endmodule
Весь проект для САПР Intel Quartus Prime можно взять на GitHub: github.com/marsohod4you/Fpga-PM-Radio.
В проекте есть PLL с двумя выходами c0 и c1, на каждом из них 100МГц. Выход c0 используется для тактирования всей схемы, а вот выход c1 — это и есть несущая 100МГц, частота моего «радиопередатчика» (FM-диапазон). Ее я и собираюсь модулировать по фазе.
Я собираюсь посылать сырой аудиофайл с компьютера в плату через последовательный порт. При формате данных 8 бит на одну аудиовыборку, моно, 22050Гц, наиболее удобна скорость последовательного порта 230400 бод. В самом деле, каждый байт при последовательной передаче имеет старт бит и один или два стоп бита. Если два стоп бита, то получается 11 передаваемых бит на байт данных. Значит 230400/11=20945 выборок в секунду. Это конечно не идеал, не 22050, но чуть-чуть похоже. Ну получится у меня звук немного ниже, чем нужно, мне для моих экспериментов не важно… Итак в проекте есть приемник последовательных данных.
Полученный из последовательного порта байт w_rx_byte внутри ПЛИС сравнивается с внутренней переменной (регистром) current_pll_phase. Разница меж ними — это и есть количество шагов по сдвигу фазы, которые нужно сделать в одну или другую сторону. Таким образом выполняется фазовая модуляция на выходе c1 у PLL.
Теперь второй вопрос. Предположим, что передатчик с фазовой модуляцией работает, а чем слушать?
Я исхожу из того, что ФМ и ЧМ непосредственно связаны друг с другом интегральным/дифференциальным законом. Мгновенная частота радиосигнала — это производная от его фазы. Производная синуса — это косинус. Вряд ли слушатель радиопередачи отличит их на слух (шутка). В общем, я решил попробовать передавать аудио файл моим «радиопередатчиком» с фазовой модуляцией, а слушать мою «радиопередачу» обычным FM-приемником. Я использую мобильный телефон с гарнитурой в качестве FM приемника.
Вот как это выглядит:
Удивительно, но передаваемая мной музыка устойчиво слышна в FM радиоприемнике мобильного телефона на расстоянии до 10-15 метров.
PS: В России 7 мая отмечается День радио. В 1895 году выдающийся русский физик и изобретатель Александр Попов в Санкт-Петербургском университете продемонстрировал созданную им первую в мире искровую беспроводную приемо-передающую радиосистему. В России этот факт был принят за точку отсчета начала радиосвязи.
ссылка на оригинал статьи https://habrahabr.ru/post/328102/
Добавить комментарий