📜 ⬆️ ⬇️

Phase modulation of the radio signal in the FPGA



So sometimes it happens that you are engaged in one technical problem, but as you dive into the task and while searching for its solution, “by-products” appear. It happened this time. I researched various methods for measuring time intervals using FPGAs. In one of the proposed measurement methods, a dynamic phase shift of the clock frequency with a PLL was used. Later the idea came: using the PLL properties, you can try to make the simplest radio transmitter with phase modulation in the FPGA.

And something turned out!

Perhaps you need to tell a little about what a PLL is. PLL (Phase Locked Loop) is a device phase locked loop generator. It looks like this:
')


There is a GUN - Voltage Controlled Generator. It outputs the desired frequency, which goes through a feedback to the phase detector. The phase detector determines the phase difference between the reference frequency F0 and the resulting frequency F1, the phase difference is an error signal, which is filtered out and acts on the VCO, causing it to oscillate a little faster or a little slower. So, at the output of the PLL turns out the frequency, synchronous with the reference.

In FPGA chips, for example, from Intel (eh ... there was once Altera), the MAX10 series has a built-in PLL, which looks like this:



It seems that this is something much more complex than what is depicted above. But no, if you look closely, you can see common features: VCO, Voltage Controlled Oscillator - this is VCO, Voltage Controlled Oscilator. PFD is a phase detector, LF is a Loop Filter, a phase error filter.

Among other things, the PLL inside the FPGA has a set of divisor counters. For example, the frequency divider M in the feedback circuit allows you to get at the output of the PLL frequency several times higher than the reference. There are also output counters C0-C4, which allow for five PLL outputs to get a grid of frequencies with different dividers.

There are also components inside the PLL, which for some reason are usually not depicted on the block diagrams in the Altera / Intel documentation - these are the schemes that control the reboot and reconfiguration of the PLL. Logic circuits in the FPGA can reload the divisor counter coefficients in the PLL on the fly, and they also allow you to shift the phase of the output PLL frequencies. Of course, reloading the PLL parameters on the fly is not a very simple operation, which also takes some time. But to shift the phase of the output frequency of the PLL can be quite simple and fast. Moreover, the phase resolution directly depends on the Fvco frequency. You can shift the front of the clock frequency by 1/8 of the Fvco period. For example, the input frequency at PLL Fin = 100 MHz, and the divider M in the feedback circuit to the phase detector is equal to 13. Then Fvco = 1300 MHz, and the phase resolution for the output frequency PLL Fout = 100 MHz will be only 3.46 degrees.

For the development of the project for Altera / Intel FPGA, the Quartus Prime CAD environment is used and it has the PLL instance configuration tools: Megawizard Plug-In Manager. With it, you can set the desired PLL properties:



Here you can see exactly which Fvco and phase resolution for the output frequencies.

To control the phase of the output frequencies, the PLL component has additional signals: SCANCLK, PHASESTEP, PHASEUPDOWN, PHASECOUNTERSELECT, PHASEDONE.

The Altera / Intel documentation describes how to control these signals in order to achieve a single phase shift at the selected output frequency.



It turns out this way: the PHASEUPDOWN signal determines which way to move the phase. PHASECOUNTERSELECT determines the signal of which particular PLL clock frequency will be shifted (for example, if you need to shift the frequency c1, then PHASECOUNTERSELECT = 3'b011 is in the documentation). The phase shift cycle begins with the setting of the PHASESTEP signal and ends when the PLL is set to zero PHASEDONE. If you need to shift the phase significantly, you will have to perform several such cycles. If you wish, you can even simulate all this in ModelSim, as I do, I wrote here .

Now, further - more interesting. Gently turn to my "radio transmitter":



I use the Mars Rover 3bis board on the Altera / Intel MAX10 FPGA chip. The board has a built-in programmer based on a dual-channel FTDI chip. Moreover, one channel FT2232HL is used for JTAG (FPGA boot, debugging in SignalTap), and the second channel is used for data transfer to the board, as a serial port.

Two pieces of 0.75 meter wire are connected to the board, directly to the two digital pin-outs. This is an antenna, "half-wave vibrator." Without an output analog filter on the radiated range, of course, not good, but the antenna itself is already some kind of filter, and the transmitter power is low ...

The project is written in Verilog HDL - just a couple dozen lines of code:

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 

The entire project for CAD Intel Quartus Prime can be taken on GitHub: github.com/marsohod4you/Fpga-PM-Radio .

The project has a PLL with two outputs c0 and c1, 100 MHz on each of them. The c0 output is used for clocking the entire circuit, but the c1 output is the carrier of 100 MHz, the frequency of my “radio transmitter” (FM band). That's what I'm going to modulate in phase.

I'm going to send a raw audio file from a computer to the board via the serial port. When the data format is 8 bits per audio sample, mono, 22050 Hz, the speed of the serial port is 230400 baud. In fact, every byte during a serial transfer has a start bit and one or two stop bits. If there are two stop bits, then 11 transmitted bits per data byte are obtained. This means 230400/11 = 20945 samples per second. This is certainly not ideal, not 22050, but slightly similar. Well, it will turn out that my sound is slightly lower than necessary, for my experiments it doesn’t matter ... So, there is a serial data receiver in the project.

The w_rx_byte byte received from the serial port inside the FPGA is compared with the internal variable (register) of current_pll_phase. The difference between them - this is the number of steps in the phase shift, which must be done in one direction or another. Thus, phase modulation is performed at the output c1 of the PLL.

Now the second question. Suppose that a phase modulated transmitter works, and what to listen to?

I assume that FM and FM are directly related to each other by an integral / differential law. The instantaneous frequency of a radio signal is a derivative of its phase. The derivative of the sine is the cosine. It is unlikely that a listener of a radio program will distinguish them by ear (joke). In general, I decided to try to transmit the audio file with my “radio transmitter” with phase modulation, and listen to my “radio broadcast” with an ordinary FM receiver. I use a mobile phone with a headset as an FM receiver.

Here's what it looks like:


Surprisingly, the music transmitted by me is consistently heard in the FM radio of a mobile phone at a distance of up to 10-15 meters.

PS: Radio Day is celebrated on May 7 in Russia. In 1895, Alexander Popov, an outstanding Russian physicist and inventor, at St. Petersburg University demonstrated the world's first spark wireless receiving and transmitting radio system created by him. In Russia, this fact was taken as the starting point for radio communications.

Source: https://habr.com/ru/post/328102/


All Articles