Фазовая модуляция радиосигнала в ПЛИС

от автора

Так иногда бывает, что занимаешься одной технической проблемой, но, по мере погружения в задачу и во время поиска ее решения, появляются «побочные продукты». Так случилось и в этот раз. Я исследовал различные методы измерения временных интервалов с помощью ПЛИС. В одном из предложенных методов измерений был использован динамический сдвиг фазы тактовой частоты с 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/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *