FPGA standalone SDR receiver

    Earlier, I wrote about a home-made SDR receiver based on the DE0-nano debug board. Like most other SDR receivers, it was not able to work without connecting to a computer. At the same time, there was still a large number of unused resources in the used FPGA, so I decided to make the receiver completely autonomous.
    About how the whole SDR receiver works, and how to implement it - further.

    A little about the previous project

    The task of any receiver is to amplify the signal from the antenna, select the desired high-frequency signal, transfer it to the low-frequency region (most often audio), and demodulate the resulting signal. A difficult problem in this case is precisely the separation of a certain high-frequency signal from the entire radio air. Usually the desired signal is located relatively in a narrow frequency band (most amateur radio signals have a width of less than 4 kHz), and next to it are other radio signals, the reception of which will only interfere. Therefore, analog amateur radio receivers are quite complex, they have to do several frequency conversions, and install fairly complex bandpass filters. The presence of various signal modulation methods also requires the introduction of a receiver set of demodulators.

    With the spread of powerful computing technology, it became possible to transfer part of the receiver functionality to a computer. Due to digital signal processing, it is possible to create very effective band-pass filters (even low-pass ones), demodulate any type of signal, and display the spectrum of the received signal.

    In most modern receivers, a signal is transferred from a higher frequency to a lower one by mixing (multiplying) the original signal with the signal from the reference oscillator, a local oscillator. As a result, a signal appears at the mixer output with a frequency equal to the frequency difference between the original signal and the local oscillator.
    However, in this case, signals can be received that are both lower and higher than the local oscillator frequency (frequencies A and B in the figure). This phenomenon is called a “mirror channel”. To combat it, analog receivers share filters and transfer to intermediate frequencies.

    There is another method of suppressing a mirror channel — phase, using quadrature signal mixing ( method description ). A feature of this method is that for its implementation in the receiver, two phase shifters of a sufficiently high order must be implemented, and their characteristics must be identical, which requires accurate selection of components and complicates the design of the receiver and its adjustment.

    Since several different signals can be processed in exactly the same way digitally, it is now possible to create fairly simple but effective receivers. In such receivers, the signal after the quadrature mixer is filtered from RF signals, amplified, digitized by the ADC and transmitted to a computer or DSP. This technology is used in most SDR receivers.
    The structural diagram of such a receiver:

    If you have a suitable high-speed ADC and FPGA, you can even digitally convert and decimate the resulting signal in digital form. This type of receiver is called DDC (Digital Down Conversion). Due to the fact that there are practically no analog components in such a receiver, a very high “mirror channel” suppression coefficient can be obtained.
    This is the receiver I described earlier. It included an external ADC and FPGAs implemented in FPGAs, a digital signal generator, CIC and FIR filters, as well as modules for transmitting the received information to a computer. The receiver provided via Ethernet a data stream of 16 bits x 50 ksps x 2 channels.

    And now it’s worth moving on to describing an SDR receiver capable of working autonomously.

    Isolation of the signal and its demodulation

    Earlier in my receiver, these operations were performed by a computer. Now it was required to implement them on the FPGA.
    Block diagram of the resulting demodulator:
    Since I wanted to be able to change the frequency of the received signal without changing the main frequency of the receiver tincture, it was necessary to add an additional generator and a complex multiplier to the demodulator block. The generator (NCO1) forms a sine wave and a cosine wave, and can be tuned in the range of 0-25 kHz.
    To transfer the desired signal to the region of zero frequencies, a quadrature multiplier is used. An important feature of its operation is that complex signals are multiplied, and no mirror channel arises at its output.
    There is also a module that allows you to swap the buses connecting the NCO1 and the multiplier, thereby changing the direction of the signal shift (this module is not shown in the diagram).
    Signal Transfer Result:

    However, the above frequency transfer does not solve the problem of the mirror channel.
    The phase of the signals at the output of the quadrature mixer depends on their position relative to the local oscillator frequency: those above this frequency will have a phase difference in channels I and Q of +90 degrees, below -90 degrees.
    Thus, if we additionally shift all the signals in channel I by +90 degrees, then the phase difference of the signals will be either 180 or 0 degrees. It is enough to add the resulting signals to each other, and the unwanted mirror channel will be suppressed (the addition of signals with a phase difference of 180 degrees gives zero). If, instead of adding, subtract the signals - it will be the mirror channel that will be received - this way you can switch the type of received band: LSB / USB.

    To perform a phase shift, a digital phase-shifting filter, a Hilbert Transform, is introduced into the demodulator module . It carries out a phase shift of all frequency components of the signal by 90 degrees.
    The filter was calculated using the FDATool tool included with Matlab. In fact, a Hilbert filter is just a kind of FIR filter with certain coefficients. FDATool even allows you to generate VHDL code for the resulting filter. The order of the filter used is 65.
    A feature of the Hilbert filter is that at frequencies 0 and Fs / 2 its transmittance tends to 0. In this case, this means that frequencies in the low-frequency range from 0 to ~ 500 Hz will not be accepted.

    The Hilbert filter delays the signal by N / 2 samples, where N is the order of the filter. To compensate for this effect, a delay line (FIFO buffer) is introduced into channel Q, which delays the signal by 34 samples.

    After the signals of channels I and Q are combined, the resulting signal must be filtered out by passing the signals in the 0-3 kHz band to the output. This is to facilitate the reception of SSB signals, which usually have such a band. I note that if several radio stations operating by telegraph fall into this band, then all of them will be heard.
    As a filter, a ready-made FIR filter from Quartus is used. It has an order of 32, the coefficients for it were also calculated in FDATool.
    Frequency response of the resulting filter:
    All demodulator modules have a resolution of 12 bits. A lower bit depth would not produce a very high-quality sound, a larger one would require more FPGA resources, which were clearly not enough. The clock frequency for all modules is a frequency of 50 kHz (data flow rate at the output of decimation filters).

    Sound output

    In order to output the sound signal from the FPGA, I used a PWM driver. This is not the best way to create an audio signal, but the easiest. The clock frequency of the PWM driver is selected high enough - 100 MHz. With such a frequency, with a bit depth of 12 bits, the PWM pulse frequency is 24 kHz.

    Since the received signals have a very large dynamic range, for normal reception in the design had to introduce programmed automatic gain control (AGC). It is implemented quite simply - if the amplitude of the signal at the output of the demodulator is too large, the AGC module attenuates the signal at the input of the demodulator (the Right Shifter block included in it is used for this purpose). The signal is attenuated 2 ^ N times due to a simple shift, which is not very convenient, but it is very easily implemented in software and practically does not require FPGA resources. If within 0.2 seconds the signal at the output of the demodulator is low, then the attenuation of the signal is reduced. The disadvantage of this method is that gain switching is sometimes pretty audible.

    FFT, spectrum display and receiver control

    Earlier, I was already working on a DE0-nano to work with a VGA monitor . I also experimented with the FFT module .
    Thus, it was enough to transfer the available modules to the receiver design, and connect the outputs of decimation filters to the input of the FFT module - and it became possible to observe the spectrum of the radio signal in the band + -25 kHz from the frequency of the main local oscillator - NCO2. The sound demodulator and FFT work independently, so that you can change the frequency of the received signal without changing the frequency of the receiver settings.
    The FFT module - ready from Quartus, with a length of 512 points, works in conjunction with the window function module.

    Traditionally, when displaying a spectrum, its logarithmic representation is used. However, it didn’t seem very informative to me, in addition, the hardware module for calculating the logarithm took up too many FPGA resources, and the calculation of the logarithm for the software turned out to be too long. So the value of the spectrum amplitude before being displayed on the screen simply decreases by 2 ^ N times, the number N can be changed programmatically.

    In this project, capturing data from the FFT module, outputting data to a VGA screen, working with SDRAM, and controlling the receiver is done using the SOPC system, which includes the NIOS II software processor.
    Simplified SOPC block diagram:

    I decided to use a mouse with a PS / 2 interface to control the receiver. He is quite simple, all communication goes on two wires. On the Altera website, among the examples for some debug boards, a module for SOPC designed to work with PS / 2 was explicitly mentioned. I came across a code (I can’t specify any links, because I couldn’t find the necessary ones again). The found example had to be changed to work with my system frequency, but at the beginning it still didn’t work at first. The situation was complicated by the fact that the PS / 2 bus is bidirectional, with five volts, and the FPGA runs from 3.3V. As it turned out, in order for the mouse to work normally, you need to supply 5V to it (the mouse does not start at 3.3V), in the Quartus settings the outputs used for PS / 2 should be indicated as working from 3.3V (the rest of the outputs are set to 2.5 V). Also, for reliable operation, we had to install a 470pF capacitor between the CLK line and the ground. Maybe,
    Next, I managed to establish a connection with the mouse from Nios, but here a problem arose - I could not adjust the frequency of data output by the mouse. As it turned out later, it was a problem of a specific kind of mouse. Working with the mouse at the program level is not complicated - after initialization, when moving, it sends 3 bytes to the FPGA, which the mouse controller receives in SOPC. It also generates an interrupt for Nios, in the handler of which Nios calculates the new coordinates of the cursor.

    The interface implemented on Nios allows you to observe the spectrum, the "waterfall", control the receiver settings (main local oscillator), adjust the frequency of sound reception, the type of received band - USB / LSB. The tuning frequency can be changed by clicking on the corresponding figure on the frequency indicator with the left / right mouse button (in the same way, the frequency can be changed in many computer SDR programs). The frequency of sound reception settings can be changed by clicking with the mouse in the right place on the spectrum or “waterfall”.

    Block diagram of the entire receiver:

    Scheme in Quartus

    FPGA resources used by the project

    As I wrote above, in the process of creating a project there were certain difficulties associated with the volume of the project. It uses a large number of filters, which occupy a place both in logic elements (LE) and use hardware multipliers. When setting the parameters of each block, I had to choose what filter length to use. Due to a lack of resources, some filters had to be switched to symmetric mode, which halved the number of multipliers used by the filter. Nevertheless, the parameters of the Hilbert filter and the FIR filter in the demodulator came out rather mediocre (in computer programs they are much more efficient). It is worth noting that in the resulting design, FPGA resources are not used to their full potential - the clock frequency of most modules is 50 kHz, although they can operate at a much higher frequency.
    Also, quite a lot of resources are occupied by SOPC together with Nios - more than 6000 LE.
    In total, the project uses:
    LE: 21,445 / 22,320 (96%)
    9-bit multipliers: 98/132 ( 74%)
    As you can see, almost all LE FPGAs are used.

    Receiver general view: Close-up: Screen view during operation (during CQ WW RTTY DX Contest): SSB reception: Receiver operation video:

    From the video you can judge the quality of the receiver. It is worth noting that the sound is a little better by ear than by phone recording on video. Also, as I mentioned earlier in a previous post, the antenna used is not the best.
    The receiver managed to receive rtty signals (the PDA connected to the receiver decoded them), JT65 signals were received (they were decoded on a computer). The German radio station broadcasting meteofax was well heard.

    Link to the project

    Also popular now: