surabhig.com

No shortcuts. Work for it.

FPGA-based software GNSS receiver: Tracking issues

This post discusses the results of hardware acquisition and some of the current issues I’ve come during tracking of the acquired GNSS signals.

My focus has been implementation of a real-time software GNSS receiver using an FPGA.

My equipment setup is such that I have a GNSS simulator generating GPS signals which are fed into the RF front end. The digital GPS signals are now input to the FPGA development board and this is where all the processing is done in real-time.

I spent quite some designing the flow of data signals from the simulator to the FPGA platform. Extensive work was done by me to setup the interfaces and the protocols.

I’ve managed to complete the implementation of the acquisition module and have been successfully able to acquire satellites in real-time!

I do have a persistent tracking issue however…

Issue: Tracking occurs only at regular intervals for a short duration

Below are some figures showing tracking results.

  • Figure 1: Represents the correlation strength of the IP accumulator (Inphase-Prompt). Expectations are to have a high correlation strength throughout the tracking duration. High correlation however occurs only at certain intervals.
Fig1

Figure 1

  • Figure 2: This plot compares all the accumulators (Combination of I & Q with Early, Prompt & Late). You immediately notice how all the peaks for all the accumulators occurs at the same time stamps.
Fig2

Figure 2

  • Figure 3: Becomes more obvious with this plot that ALL the accumulators have high values at similar time intervals
Fig3

Figure 3

  • Figure 4: This was an interesting plot! I basically zoomed in on the peaks to see what was going on. I noticed how the power would move from Late, Prompt to Early. Every single time. This was a noticeable trend at all the peaks.
Fig4

Figure 4

The final figure (4) told me that the PRN in the input GPS signal and the one generated on the board do not align during tracking EXCEPT at those peaks.

I went back to check my PRN generators and they work as expected. So if it is not the local PRN signals then what could it be…

That shifted my attention towards the input GPS signal itself. The sampling frequency I used was 20 MHz but perhaps it is not exactly that number? I say this because according to the set sampling frequency, there are 20,000 samples per millisecond. But clearly the PRN in the input signal is shifting (from Late to Early). So does this mean the sampling frequency (aka number of samples per milliseconds) is shifting too? I’m doubting everything at the moment but if you’ve picked up any leads from the figures please let me know as I struggle on to fix it…

Email: surabhisgp [at] gmail [dot] com

MAX2769 Evaluation Kit: Clock for GPS Receiver

This post exclusively talks about MAX2769CEVKIT.

I have used the evaluation kit for my GPS Receiver development for about ~2+years. When it came to real-time GPS signal processing, things fell apart during the signal tracking phase. After extensive debugging I realised the clock source on the MAX2769C EVKIT was not good enough to support GPS receivers. GPS receivers require a stable and accurate clock for good signal and a reference clock source running via a wire between the front end and the receiver is just a bad idea. Ideally, you want to have the clock source (or the MAX2769 chip) on the same processing board to minimise the phase noise that could be added from the environment or during transmission.

In the board setup image below, ext_clk is the 16.368 MHz clock source. The clock is fed from the front end into the Zybo. I initially wanted to use the 16.368 MHz clock for all the processing as that was the chosen sampling frequency as well. It did not work out how ever as the FIFO in Zybo (FPGA) refused to accept it as a clock signal.

On further investigating, I noticed the deteriorated clock quality received at the Zybo end.

max2769

GPS Receiver Setup (copyrighted)

The first waveform (external_ports_clk_in1) is the clock received as is at the input pin. A lot of harmonics and phase noise is present making it a useless source of clock. There was a need for clock conditioning (to remove jitter) which is why I used Xilinx’s inbuilt core Clocking Wizard. The output of the wizard core is the second waveform (clk_wiz_0_clk_out1). it certainly looks better but the FIFO would still not accept it as a legitimate source of clock. This is a very small snippet provided so there’s a possibility the harmonics and jitter show up at other intervals. The third waveform (FCLK) is simply a clock signal produced by an onboard clock available on Zybo, which is the best of all the three clock signals.

reference_clock

Clock signal comparison (on Zybo) (copyrighted)

This shows that using a clock source from the front end of MAX2769C is not the best idea and avoid it if you can. If you used the clock source successfully I would very much be interested in hearing from you!

So why not just use the good quality onboard clock? Here’s the catch… The sampling frequency/reference clock of the front end must match with that of the on board clock. Sampling frequency is set up to be 16.368 MHz. The closest frequency that the onboard clock can produce is 16.392 MHz. This might be reasonable for a lot of applications (works for GPS acquistion too!), but not for GPS tracking unfortunately (needs to be exact! and stable).

As a work around I changed the sampling frequency for MAX2769C to 20 MHz (a round number). But there is no way of confirming if this change was actually implemented on the front end. I’m working on GPS data acquistion and will later process it on my PC-based software GPS receiver to check if the sampling frequency did actually change to 20 MHz.

But another uncertainity with using an onboard clock to reference the arrival of the front end data is the phase difference or the delay between the two signals. I’m not sure how that will work out but its something to test for the future.

 

Data acquisition using AXI DMA (ZC706)

I made the switch from Altera to Xilinx a few years ago but haven’t updated the website much. I hope to write more tutorials like this one hoping it helps others who need it (& hopefully won’t have to struggle as much as I had to).

This tutorial uses DMA in Scatter/Gather (SG) mode and will only be used to collect data from the FPGA/PL and store it in memory where the PS/Zynq processor can access/read it.

Firstly, please follow this tutorial that shows you how to setup the DMA in a loop mode. The PS sends some info to the FIFO via a DMA and then receives the same info back in the PS (via the DMA) which confirms the DMA functions properly.

For my project, I only wanted the DMA to write data to memory so I modified somethings from the tutorial in the link. Below are the steps you need to follow.

  1. Select only Write channel
    Capture1

    DMA settings

    Capture2

    DMA connections

2. View full block design

3. If you looked at the full block design you will see the connections running between the blocks. The only custom IP used is the packetgen_axi_v1. This block collects 1-bit data (from a pin, more on this later) and packs it into 32-bit words and transmits it to the FIFO over the AXI.  It is very easy to write this custom IP but if you can’t email me and I’d be able to help you with it.

4. The din input to the custom IP comes from an external pin on the board which is connected to a RF front end. My project collects data from the front end and saves it in memory where the software can later easily access it.

5. Synthesize, Implement and Generate Bitstream for the project. Export the project and launch SDK. Create an application project with hello world.

6. Copy paste the example code from

C:\Xilinx\SDK\version)\data\embeddedsw\XilinxProcessorIPLib\drivers\axidma_v(ver)\

examples\xaxidma_example_sg_poll.c

7. Here you need to edit out all the parts of the code which involve Tx…

8. In the CheckData() loop instead of checking every individual value received value, just print it out. Also, my custom IP requires a ‘capture_start’ signal from the processor after which it starts collecting data and storing in memory. That collected data will be outputted by the CheckData() function.

9. I highly recommend understanding xaxidma.h header file and all the functions. It will help you customise your application.

10. Program your device and then run the SDK application and you should be able to see a successful run.

 

My next step is to implement a cyclic BD which will continously collect data for a certain period of time. I will post my progress shortly.

 

If you have any comments or suggestions please feel free to leave them below.

Phase Increment Calculator for NCO

This Phase Increment Calculator is built specifically for hardware implementation of a Numerically Controlled Oscillator (NCO).

Specify the desired frequency of the output signal of the NCO, the system (or input) clock frequency and the accumulator bit width, to obtain the accumulator value you should use for the NCO.

Equation:

f_out = [phase_inc/(2N)] * input_clk

Review code: 2-bit Signal Generator (NCO) in Verilog

1.7. Using Altera’s FFT Megacore Function

Diving straight into the topic, Altera’s FFT IP is simple to use. With thorough review of the FFT core manual, implementing it gets easier.

Download Altera’s FFT Megacore Function Manual

For my research I needed an FFT function that could transform a long sequence (32,768 samples). Altera has 4 different types of cores available to suit several applications. I compared them all and made an estimate using Quartus and concluded with this table:

Altera_FFT_core_comparison

These estimates can be found using the FFT Megacore Function settings – Parameterization.

For my application, I needed 3 FFT cores:
1) To transform input signal
2) To transform reference signal
3) Inverse FFT the prodect of signals in 1 & 2.

However, each FFT core occupies a significant portion of the FPGA memory bits and hence I decided to implement just one FFT and use it 3 times. (FFT core can be used for Inverse FFT as well with modification of control signals)

This is the schematic of the design:

Altera_FFT_Megacore_design

The FIFO (First-In, First-Out) is there so that no samples are lost or corrupted before or after tranformation.

While working with Cyclone V SoC, I relayed the information from ARM to the FPGA, transformed it and sent all the data back to ARM.

FFT in hardware does indeed take a shorter time that its equivalent software implementation.

I will provide more elaborate description and Verilog code in the next few days.
If you do not see it here sooner, you can reach me on my email as well : surabhisgp@gmail.com

2-bit Signal Generator (NCO) in Verilog

Recently started using version control BitBucket and I must say sharing code is definitely easier.

So here is the link to the code that generates sin and cos signals according to the required frequency.

https://bitbucket.org/snippets/surabhisgp/Rnyaq

It is 2 bit only because the range of values is between [-1,1].

If you are looking for something in the range of [0,1], that would make it a 1 bit NCO which is even easier (you just have to ignore the LSB). Focus only on sin[1] or cos[1].

This module is great if you have to quickly test something like demodulators etc.

If you figure there are issues or even found a simpler way please feel free to share them.

Alright, I’m onto figuring out the next task, atan in verilog!

P.S. I’m also going to make sharing the code easier on the blog… will try to embed it here.

1.6. Using Nios II Software Build Tools for Eclipse

Before you move on to the software design, make sure the top level module doesn’t have any errors. Of course you won’t know the logical errors until you get to the software design.

Moving on, you will find the Nios II SBT for Eclipse under Tools in the Quartus window.

Choose the default workspace (which should mostly be your project space). Then, to create a new file, choose “Nios II Application and BSP from template”. This will make Nios refer to the design files you created in Quartus. This is a critical link between not just Quartus and Eclipse, but also your hardware and software design.

As shown in the screenshot above, choose the sopcinfo file from the project folder. The Nios CPU name should show. If you have used multiple cpu’s, you must choose the appropriate one. Name your project and for the project template, choose ‘Hello World’. Since we have a SDRAM in our design, we can afford to use this template. If you are using only on-chip memory, then you must choose ‘Hello World Small’, this will shrink the program size and just enough to fit on the on-chip memory.

Hit ‘Finish’ and it should create a bunch of files in the sub-window in the left. In the hello_world.c file the following program was written:

/*

 * “Hello World” example.

 *

 * This example prints ‘Hello from Nios II’ to the STDOUT stream. It runs on

 * the Nios II ‘standard’, ‘full_featured’, ‘fast’, and ‘low_cost’ example

 * designs. It runs with or without the MicroC/OS-II RTOS and requires a STDOUT

 * device in your system’s hardware.

 * The memory footprint of this hosted application is ~69 kbytes by default

 * using the standard reference design.

 *

 * For a reduced footprint version of this template, and an explanation of how

 * to reduce the memory footprint for a given application, see the

 * “small_hello_world” template.

 *

 */

Note: A lot of the statements here may be redundant, but hey, it works 🙂

Then build the program and wait for a ‘Build Finished’ statement. You may face some issue/errors here. One of them can say ‘Permission denied’  which is also the most common one. In such a case open Nios II SBT via Start->All Programs->altera and make sure to roght click on Eclipse and choose “Run as Administrator”. This should solve the problem.

Past all this, you have to RUN the program!

Choose a New Configuration under Run. Choose the project .elf file if its not selected by default. Also select the Target Connection tab and choose the USB Blaster. Check the Ignore mismatched system ID and Ignore mismatched system timestamp if and only if you encounter a problem later during execution of the file. Usually this doesn’t cause a problem.

Then save the configuration and simply Run. It should start processing and soon you will the output on your LCD screen!

Success!

At the time of writing this, I have boxed up my amazing Alter DE2-115 kit and brought in an evenmore interesting platform, Cyclone V SX (SoC). So I will no longer post about Cyclone IV but will post about the latest version of Cyclone series. It also has an ARM core! I’m so excited to be working with it. I will however be pleased to answer an questions about any of these kits!

1.5. Using Quartus Programmer

This part onward is my favourite. Actually doing business with the electronics stuff.

Before we ‘burn’ the design onto our chip, let’s get some of the technicalities out of the way. Setting up USB Blaster is easier than I expected it to be. Plug in the USB into your laptop/PC and wait for the driver to get installed. Chances are that it won’t find the appropriate driver, in which case, you direct it to the driver location. Go to the folder which contains Altera>>Quartus>>drivers>>usb blaster

Note: Do not choose the sub folder x32/x64.

This should install the USB Blaster driver and then you are good to go!

Well, almost.

To open the Programmer window, find it under the Tools tab in the Quartus window.

Most things remain unchanged except for the Hardware Setup. Select USB Blaster as the hardware. The file that is important in this case is the .sof file. Check ‘Program & Configure’ and then hit ‘Start’. Minimise this window once the green bar hits 100%.

That was easy wasn’t it?

You are basically done with the hardware design. Congratulations!

Next Post: #6 Using Quartus Eclipse SBT

1.4. Top Level Module Design with VHDL (Example)

After you have your Qsys design ready, you need to move onto defining your top level module. This is nothing but the hardware description or how I like to visualize it is, connecting the hardware peripherals with the software design (from Qsys).

*For the previous steps refer to older posts.*

I will be using the same example I used in the previous post (#3) that is:

AIM: To display “Hello World” on the LCD display using Nios II processor. 


Before we proceed with coding of the top level design, let us get over with ‘Pin Assignments’. In he Quartus window, go to Assignments -> Import Assignments.

Now, to choose the pin assignment file you need the CD that came with the Altera development board. Browse within the CD and search for a file with extension .csv (usually).

Once you’ve assigned Pins, go back to the Quartus Window and again under Assignments go to Assignment Editor. A new Assignment Editor tab should open. For now, leave it open as we will be referring to this later.



So, firstly, create a new VHDL file. (File>>New>>Design>>VHDL File)


Now, the HDL Example from Qsys must be included here. Then build the rest of your code around this. 

When defining your entity, refer to the pins in the Assignment Editor.

Architecture is the place you define the connections between the software and hardware components. (See Example code below).


Note: Update to the Qsys design. I have now also included SDRAM (see image below). I had to add this as on-chip memory is insufficient for most of the processing (further steps). Make sure you change the Reset Vector Memory & Exception Vector Memory (of the Nios processor) to SDRAM.



VHDL code is as below:



WARNING: The variables in VHDL code here depend on the names assigned in the Qsys design. Please make the changes accordingly. Also, the development board I am using is Cyclone IV EP4CE115F. The pin names may change with boards.

After you write this, an important step before you hit Compile:

Go to Project>> Add/Remove Files in Project

    Browse for  <your_filename>.qip file and add it to the project. (In the project folder, it is usually under         synthesis). For some reason this file is not automatically read during compilation and you may get errors.


Wait for the compilation process to complete, which usually takes a couple of minutes depending on your    project. 

When you see compilation successful, it is ready to transfer the design onto the development board!



Next post: Using Quartus Programmer

1.3. Guide to Qsys Design with Nios Processor (Example)

Before you begin with the designing steps, you are expected to have a detailed system schematic of your project. Since the Altera boards have hardware and software components, your system must be distinctly separated into the two categories.

In this post I will be using a simple example which will make explaining easier.

AIM: To display “Hello World” on the LCD display using Nios II processor.

For the rest of my blog posts I will be using the same example.

Always begin with the Qsys design first. In the Quartus window, go to Tools->Qsys.

Another window pops open which most likely looks like this:

In the Library section, you will find all the components/peripherals/features that you can build with. I will start with the Nios processor found under Embedded Processors. An additional window will open where you coon choose among Nios II/e/f/s. I will choose the Nios II/e version because it is the simplest version and also my system doesn’t require the processor to have specific features. We will come back to this window to select Reset Vector Memory and Exception Vector Memory later. Click Finish and now it will appear in the System Contents. 

You have to add 3 more components if you wish to use the Nios processor. They are Timer, JTAG UART and on-chip memory. All of them can be found in the Library. Add them as it is.

Since we will also be using the LCD, add the component too.

Your System Contents should look like this now (with a long list of errors):

I have renamed some of the components just for convenience.

Next step is to make the connections!

Things to keep in mind when making connections:

1. Make sure you connect the data and instruction master to the on-chip memory slave.

2. Make the IRQ connections.

3. If you get ‘memory overlap’ errors, check the Address Map tab. If there is an address overlap, go to System->Assign Base Addresses. This should solve that problem.

4. In the lcd component, external is not connected to anything. Just click where it says ‘Double click to export’.

4. Finally, go back to the Nios processor component and choose on-chip memory as the Reset Vector Memory and Exception Vector Memory.

Hopefully you now have 0 errors and 0 warnings!

Next is to Generate.

Only changes you make here is while choosing between VHDL/Verilog. I am more comfortable using VHDL so that’s what I select and then click Generate.

Once generated sucessfully, go to the Generate tab again and select ‘HDL Example’. Select the appropriate option i.e. VHDL/Verilog and you will see few lines of code below it, something like this:

Now this is the code that you will use in your top level design. For now, you are done with the Qsys design! Close the Qsys window and go back to the Quartus one.

Next steps in the next post!

« Older posts

© 2018 surabhig.com

Theme by Anders NorenUp ↑