Is it possible to transform kiwi sdr on Xilinx Zynq FPGA a single chip solution [for GPS only]

edited September 16 in KiwiSDR Discussion
Dear John,

I'm working on GPS receiver n I'm interested to transform GPS solution on Xilinx Zynq family fpga which has both Arm processor as well Artix 7 FPGA in build, so I started to convert the source code compatible with Zynq family, I have Zedboard first I tried only FPGA source code and Programmed Zedboard, and deed the connection between Zedboard, Kiwi SDR GPS front end and beagle bone black (Here I connected only SPI interface signal to Beagle and zedboard) powered through Kiwi Board with common ground and GPS Input signals Kiwi Front end GCLK, GSGN, GMAG to Zedboard, So my design flow as:
1) GPS signal I'm giving to Zedboard (FPGA Programm's Running on Zedboard)
2) As zedboard connected to Beagle through SPI Interface so data will transfer between Zedboard and Beagle (Same Cape Installed on Beagle Supplied with Kiwi SDR board)

But I'm getting issues as: Actually my Beagle bone got connected to PC but not opening Kiwisdr admin page,  so please guide me. Or any extra signal's to be communicated between Beagle and Zedboard

Comments

  • jksjks
    Accepted Answer
    Hi. Yes, what you want to do is possible. But it is a lot of work. It is maybe easier to start with the GPS code that does not have the Kiwi SDR code parts: http://www.jks.com/sdgps/sdgps.html This code just runs a program on the Beagle that prints messages with no web interface and no complications of all the Kiwi SDR code.

    1) How are you wiring the Beagle SPI to the Zedboard? Are you using the same SPI pins as go from Beagle to Kiwi FPGA? This is tricky because those same pins are used to download/program the Kiwi FPGA. Did you somehow electrically isolate the Kiwi FPGA from those SPI pins? Otherwise you have to depend on the Kiwi FPGA power-up state to leave those pins in high-impedance mode. It is possible this is okay even if you did not isolate the pins.

    2) Did you disable the code in the Kiwi server that programs the Kiwi FPGA?

    3) Admin page not connecting: In the browser open the "javascript console window" and look for error messages. Each browser has a different way of doing this. On Firefox from the top menu bar select: Tools > Web Developer > Web Console and then make sure the Console tab is selected.

    4) Do you get any error messages on the Beagle console when you run the Kiwi server?

    Navnath123
  • Thanks You So Much,

    As you suggested I will start with sdgps.
    1) Yes I'm using the same SPI pins

    2) No I haven't disabled the Kiwi Server program, Actually my intention is to simply change the FPGA device, As well I'm programming Zedboard through usb so I think it will work

    3) I'm using the same Image file come up with kiwi board. I'm new to beagle so I don't know more about Beagle.

    I will do the excise you suggested.
    Once again thank you.

  • Hi John,

    As I'm again started with the SDGPS code execution, link provided by you, and it's working fine (Really I'm so much excited) and giving Positional solution in simulation mode using raw gps data.

    1) Now I wanted to execute the same for real time GPS positional solution, as I have Zedboard FPGA (Instead of XuLa2 FPGA board) on that I will execute and port verilog codes, by using kiwi RF front end signals (GCLK ,SIGN) will be connected to FPGA board and finally SPI signals connections between FPGA Zedboard and Beagle bone black.

    2) Right now Beagle bone Black is executing all the files including CPU files (those are converted from verilog to C for simulation purpose), My doubt is will it be necessary to disable cpu codes from beagle for real time gps solution when using with FPGA verilog codes with beagle bone board.

    Thanks

     
  • jksjks
    edited November 6 Accepted Answer
    Hi. Yes, to use real-time GPS data from the Kiwi GPS front-end chip you will need to run the code on the embedded processor on the FPGA. This is the code (sdgps/asm/gps.asm) that runs in the little FPGA embedded processor (sdgps/a_ise/gps_iq15_1/cpu.v) that also has a C-code simulation (sdgps/cpu/cpu.c).

    This is because for real-time GPS data this code needs to run PLL loop filter code at 1 kHz.
    See Andrew's description here: http://www.aholme.co.uk/GPS/Main.htm

    I don't think my simulation code is fast enough to do this in real-time. Anyway, the simulation code only simulates both the GPS FPGA logic (e.g. sdgps/a_ise/gps_iq15_1/demod.v) and the embedded processor together. It does not know how to work with the GPS logic running in the actual FPGA but the embedded processor simulated. But this embedded processor is quite simple and shouldn't be much of a problem to get working on the Zynq.

    There is another problem to consider. My old "sdgps" project that you have running is targeted for a Spartan-6. But also for the Xilinx ISE toolchain. I believe Zynq requires the newer Vivado toolchain. So you will have to make some adjustment, e.g. instead of a .ucf format file for the FPGA pin mappings you will need a .xcf format file. And the definitions for the required Xilinx IP blocks is a little different. The GPS part of the newer KiwiSDR project targets the Artix-7 which of course requires Vivado. So you will find a .xcf file there and the Vivado-compatible IP block definitions.

    After this is working there is the question of moving the C/C++ code off the Beagle into the Arm processor of the Zynq. But that is a separate consideration.

    And now for something new: The "sdgps" project just outputs to the terminal as you know. And the GPS in the KiwiSDR project has this nice web interface as part of the admin page. What I've been working on the last few days is a version of the KiwiSDR project that has most of the "SDR" code removed. This will leave just the GPS code. There will be fewer files, it will compile much faster and be much easier to understand. The KiwiSDR project is currently at https://github.com/jks-prv/Beagle_SDR_GPS so I will make a new project called https://github.com/jks-prv/Beagle_GPS in a few days. I'm not sure if this will help you for using the Zedboard but I've had several requests for a version of the Kiwi for people who just want to do GPS development / experimentation and don't care about SDR.

    Navnath123
  • edited November 7
    hi Mr. John,

    I am also working on same,

    Taken the sdgps folder containing cpu, cpp and asm folders in it along with lunix env-settings, i am trying to cross compile on the hardware having arm compiler.
    can u please guide the steps to cross-compile only files having processor application.
    In the procedure I am modifying the make file to provide required flags and disabled the simulation mode of FPGA.
    any specific version tools to be used....

  • soumyalp: Are you asking how to compile the sdgps code when not in simulation mode, and the Verilog is to be used on the actual FPGA? And second, how to make the Makefile work on an arm-based development host? Okay, let's answer those questions.

    The Makefile is written to automatically detect two situations:
    1) It us being compiled on a Beagle running Debian and assumes an FPGA is being used. This is done by not defining CFG_FPGA_SIM in CFLAGS which then is not passed to any of the compiled code.
    2) It is being compiled on a "development machine", like a pc or laptop running Windows, Linux or OS X , and CFG_FPGA_SIM should be defined in CFLAGS to use the simulation code.

    This detection is done by looking for the file /etc/dogtag which will be on Beagle Debian systems and not on development machines. You need to change the Makefile to modify or remove this check and define (or not define) CFG_FPGA_SIM directly. You need to have some knowledge about Makefiles to do this.

    Cross-compiling: Do you mean compiling on a pc running Windows or Linux and cross-compiling the C++ parts of sdgps for an Arm processor? (e.g. an Arm inside a Zynq). This might be difficult because it isn't just the C++ code from sdgps but also the FFTW library is needed and there might be issues trying to cross-compile it. I'm not sure. Doesn't the Arm on the Zynq run a small Linux distribution that already has C++ compile tools and the ability to install the FFTW package? That would be much easier.

  • Thank you John.

    I was trying to do it on Angstrom, so I was getting errors...

    It compiles in Beagle having Debian.


  • A long, long time ago I had a Makefile for sdgps that worked with both Angstrom and Debian. But after a while it because too difficult to keep the Angstrom port working. There is really no reason to run Angstrom anymore. Especially with the newer Beagles that have 4GB eMMC.

  • Hi John
    I have tried it on two hardware platforms as:

    1) I connected Beaglebone with Kiwi SDR Board on top of it and changed its BB_CS[1] to pin no 16 as per kiwi hardware requirement (Actually in your hardware its BB_CS[1] to pin no 24)
    2) Also I connected through jumper wires from Zedboard (Kiwi RF Front end to Zedboard) to Beagle Bone same as per your hardware pin configuration.

    I got the error output as mention below.

    Note: Currently I run gps.bin files without using .dts .dtb files.
    Steps:
    1) I had taken your SDGPS code and disabled simulation code(DCFG_FPGA_SIM and commented out CPU_MAIN_NAME in cpu.c, demod in demod.c, gps  in gps.c files).
    I am able to build code successfully and able to see gps.bin file. 
    Then I tried to run bin file but got below errors.
    debian@beaglebone:~/sdgps$
    debian@beaglebone:~/sdgps$ sudo ./gps.bin
    CLKS: pmux 0x2 g0 0x2 spi0 0x2 g1 0x2 g2 0x2 g3 0x2
    PMUX: sclk 0x27 miso 0x27 mosi 0x27 cs0 0x27 gpio0_15 0x27
    assert "PMUX_SPI0_SCLK == PMUX_IN" failed at cpp/peri.cpp:206
    debian@beaglebone:~/sdgps$
    Can you please help me out why I am getting PMUX as 0x27 and CLKS as 0x2?, but i think it should be 0x30 for PMUX_IN & for PMUX_OUT it should be 0x10

    2) Then I tried to comment assert functions in peri.cpp files and build the code again.
    I run the gps.bin file and found below errors
    debian@beaglebone:~/sdgps$ sudo ./gps.bin
    CLKS: pmux 0x2 g0 0x2 spi0 0x2 g1 0x2 g2 0x2 g3 0x2
    PMUX: sclk 0x27 miso 0x27 mosi 0x27 cs0 0x27 gpio0_15 0x27
    SPI: config 0x311 irqena 0x0 module 0x1
    SPI1: conf 0x0 stat 0x0 ctrl 0x0
    SPI0: conf 0x180903c8 stat 0x2e ctrl 0x0

       CH    PRN    SNR   RSSI   GAIN   BITS   WDOG     SUB
    1
    2
    3
    4
    5
    6
    7
    8
    9
       10
       11
       12

    GOOD
      LAT
      LON
      ALT
    TIME
    FIXES
    TTFF
      RUN 0:00
      MAP
      DECIM: 32  FFT: 65472 -> 2046  CCF: 0.000s  MIN_SIG: 16
    FPGA not responding
    debian@beaglebone:~/sdgps$
    This time I have seen "FPGA not responding" error. 

    Is it required to use .dtb file for Beaglebone board or I can run sdgps directly without pushing .dts .dtb files in beaglebone board.

  • jksjks
    edited November 9
    The whole pmux / device-tree situation of the BeagleBone.org project has been a complete disaster. Early on I almost gave up on the Beagle because of it. Even after I had locked-in the Beagle to the project they kept changing the way that stuff worked. I can't tell you how many hours I wasted trying to keep up. It is the main reason the Kiwi ships with a fixed Debian distribution and any support is void if you do an "apt-get upgrade" (people do it anyway).

    I should mention that today I pushed the new https://github.com/jks-prv/Beagle_GPS repository. So you might want to consider using that instead of sdgps. It doesn't have the Verilog simulation that is in sdgps though.

    Give me some time to try sdgps on the Kiwi board and see if I can figure it out..

  • Hi John,

    Thanks for your continuous support, It's really helpful for me.

    I had enabled SPI (SDGPS) for debian and now able to see PMUX as per expectation(PMUX: sclk 0x30 miso 0x30 mosi 0x10 cs0 0x10 gpio0_15 0x37)
    I am using kiwiSDR hardware and generated bit file for xilinx ARTIX 7 FPGA, programing through beaglebone.
    Beaglebone able to communicate with FPGA board successfully. Please find the below result.

    debian@beaglebone:~/sdgps$ sudo ./gps.bin
    CLKS: pmux 0x2 g0 0x2 spi0 0x2 g1 0x2 g2 0x30000 g3 0x30000
    PMUX: sclk 0x30 miso 0x30 mosi 0x10 cs0 0x10 gpio0_15 0x37
    SPI: config 0x311 irqena 0x0 module 0x1
    SPI1: conf 0x0 stat 0x0 ctrl 0x0
    SPI0: conf 0x180903c8 stat 0x2e ctrl 0x0


       CH    PRN    SNR   RSSI   GAIN   BITS   WDOG     SUB
    1 *    2     10
    2
    3
    4
    5
    6
    7
    8
    9
       10
       11
       12

    GOOD
      LAT
      LON
      ALT
    TIME
    FIXES
    TTFF
      RUN 0:01
      MAP
      DECIM: 16  FFT: 65472 -> 4092  CCF: 0.453s  MIN_SIG: 16

    I am not able to get acquisition result as per the expectation and just getting channel 1 result with repetition of PRN no(between 1 to 32).  
    I am confused with DECIM value. If I modify DECIM value 1 to 16, FFT and CCF also getting changed.
    Will you please suggest any changes in source code to realize real time GPS solution?

  • jksjks
    edited November 10
    I'm just starting to look at this now (it's early morning here). A lot of things have to work correctly for you to begin seeing sat acquisitions. It's good that you're getting past the "FPGA not responding" message in sdgps/cpp/main.cpp:main() because that means the embedded cpu code was downloaded properly and running on the FPGA and responding to the CmdPing command sent over the SPI from Beagle to FPGA.

    DECIM is the decimation factor used on the incoming GPS sample data. This is a feature I added so the size of the acquisition FFTs could be reduced and hence their runtime. I forget what CCF stands for, but it's the number of seconds per acquisition FFT. When DECIM is 1, and the FFT size is 65472, CCF is about 4 seconds. This is for FFTs running on a Beagle. They will be much faster on a more powerful host (e.g. pc). Increasing DECIM is not free however. In exchange for smaller FFTs you get less resolution (accuracy) of the initial code phase. The tracking loop that comes after acquisition has to tolerate this. It's a trade off. But the Kiwi requires it because a large FFT would ruin the realtime response requirements on the Beagle.

    So keep DECIM at 1 to remove the added complexity and possible problems. I'll try it on the Kiwi hardware now and see if I can get it to work.

  • Hi John,

    It's Great to share, 

    I'm able to observe the complete real time GPS solution using KiwiSDR hardware from SDGPS source code,

    As per your guidelines initially I kept decim 1 and observed results but it's taking so much time for acquisition( attaching the captured result), then I changed it to 4 and its working fine and giving better accuracy and better TTFF as well.

     I wanted to drop you a note to express my personal gratitude for your effort and extra time.
    Its really  a great experience to learn such new technology and observe the real time results.

    Now my next aim is to develop a single board solution (I know It's long run process but still more enthusiastic to learn the technology ), so please give me your valuable views on hardware development, as well I'm looking for low power consumption development too, 
    1) First I'm thinking to follow the same hardware you used for SDGPS like Spartan 6 and Beagle bone, My approach is to develop single PCB having RF front end SE4150+FPGA+Beagle Bone Black (Only processor, DDR and Flash Memory)

    2) Secondly I'm thinking to follow the same hardware used for KiwiSDR like Artix-7 FPGA and Beagle bone, My approach is to develop single PCB having RF front end SE4150+FPGA+Beagle Bone Black (Only processor, DDR and Flash Memory)

    Will you please suggest me which platform will be worth or may be suitable or you may suggest new approach for single board solution,because right now I'm using Separate Kiwi Hardware and Beagle bone black.


    SDGPS_working_result_top02.jpg
    1366 x 768 - 89K
  • jksjks
    edited November 12
    Okay, that's great news. Lots to discuss:

    1) I spent all day yesterday backporting the Kiwi pmux code into sdgps but can't get it to work. It should be simple, but something is wrong. So I'm glad you got it working.

    2) I don't know why using DECIM = 1 would be worse than = 4. It should be better. Looking at your screenshot: if you're only seeing 2 sats after 10 minutes then the GPS antenna must not have a good view of the full sky. You should have 6 or more sats showing. Those two signals shown are very strong.

    3) Building a low-cost, software-define GPS board (essentially a KiwiSDR without the SDR front end and expensive 14-bit ADC) is a very interesting idea. I have thought about this myself. 

    You could do this as a "cape" board for the BeagleBone like KiwiSDR. But I would also now consider using the new Octavo Beagle SoC chip (https://octavosystems.com/octavo_products/osd335x-sm). Most new Beagle variants are using it because it makes the design process so simple. There are some cost considerations, i.e. in small volumes the Octavo is about the same cost as an entire BeagleBone board. But there are other costs to consider as well. It would be really nice to have the entire solution on a single PCB.

    You may not need DDR external to the FPGA (unless you need it to use the Zynq ARM core). It's a pain to route the equal-distance traces, although some CAD packages help with this task. The Artix-7 A35T has lots of BRAMs, especially if you're only using the GPS Verilog and not Kiwi's SDR Verilog which consumes almost all of them. You might be able to fit the GPS Verilog into a smaller Artix-7 (A15T or A12T). That would save a lot of cost. Check the Spartan-7 family as well. The cost is probably the same or cheaper than Spartan-6. A couple years ago I found Artix-7 was the same price as Spartan-6 and offered twice the BRAMs etc. That's why I use it.

    4) You might see if you can get https://github.com/jks-prv/Beagle_GPS working. It has an arg to show console output like sdgps ("-stats 1" or use the script "./g") But it will also provide the nice web interface. It also has a 32-bit SPI interface instead of the 8-bit SPI in sdgps.

  • Hi John,

    1) As I tested Beagle_GPS using Kiwi Hardware and Beagle it's working fine and giving results in GUI.

    2) I think to work for pmux code into sdgps, In sdgps chip select[1] is at pin location 24(Beagle) but in kiwi its on pin no 16(Beagle), because while testing SDGPS codes using Kiwi Hardware I'm connecting through direct jumper wires if I mount kiwi on top of Beagle its not working, so i think this may be the issue you are facing.  
    3) As you suggested the hardware platform OSD335x really its amazing size wise, will save lot of space.

    4) I have one query if I change RF front end like Max2769 or NT1065 multi channel RF front end receiver and changing the sampling frequency  with changing IF frequency will it be easy to modify SDGPS source to work with new Sampling frequency or New IF, or what are the possibility we need to take care for further processing.
  • jksjks
    edited November 13
    I was trying to use the Kiwi pmux code because it makes it easier to move the CS1 pin. But it was harder to back-port this code into sdgps than I thought it would be.

    If the GPS clock is different you must change a few things. I'll talk about the Beagle_GPS code below.

    1) In gps/gps.h change the constants FC, FS and FS_I to match what your front-end chip produces.

    2) Further down you'll see the constants FFT_LEN and NSAMPLES are a function of FS_I. So this will be the size of the acquisition FFT assuming no decimation (DECIM = 1). But there are several aspects of the Verilog that depend on these constants, and they are not automatically taken into account as FS and FS_I are changed. So you have to check the sizes and adjust the Verilog if necessary. For the SE4150L the clock is 16.368 MHz, so FFT_LEN and NSAMPLES is 65472. In verilog/gps/sampler.v the size of the sampler memory is 1-bit by 64k (65536). So NSAMPLES just fits. If your clock if faster you need to increase the size of the memory. Some chips like the MAX can give you a range of output clock frequencies which helps. If your clock is slower it doesn't matter -- the buffer will just be larger than it needs to be. The code in gps/search.cpp:Sample() and e_cpu/kiwi.gps.asm:CmdGetGPSSamples() always moves the correct amount of data.

    3) The other piece of Verilog that changes depending on clock frequency is the maximum size of the integrators in the tracking loops. Look at Andrew's article: http://www.aholme.co.uk/GPS/Main.htm ;Go down to the tracking loop diagram in yellow and green. See how the yellow parts are in the FPGA hardware clocked at 10 MHz? The 10 MHz shown is the front end clock rate, so on the Kiwi this is really 16.368 MHz. The integrators shown (sigma symbols with n = 1 .. 10000) accumulate the input bit stream for one PRN repetition period (one millisecond). 10 MHz times one milliseconds is 10000. So the integrators must be at least 14-bits wide (2^14 = 16384, 2^13 = 8192 would be too small).

    For the Kiwi clock the value is 16368. I can't remember why but I ended up using 16-bits (2^16 = 65536). I think there is some rounding in the integrators that would cause 2^14 to overflow in some cases, so at least 15-bit would be needed (see the business with the "lsb" register). This integrator width is in verilog/gps/demod.v Go to the comment that says "Down-convert to baseband". Then you'll see the integrator registers defined with [16:1] i.e. 16-bits. The integrator values are transferred all the way to the e_cpu code. So further down you'll see the serial transmission code that also takes the 16-bit register width into account.

    If your clock rate fits into 16-bits (with some margin) then there is no need to change any of this. It should just work. I forgot another complication. The code in e_cpu/kiwi.gps.asm:GPS_Method() assumes the IQ samples will fit into an unsigned 16-bit value initially. If you need more than this then that code will have to be rewritten. Eventually 32 and 64-bit values are used for the loop filtering code. But you'd have to change the initial IQ processing 16-bit code to be 32-bit or something.




    Navnath123
  • Hi John,

    As now I'm trying SDGPS Solution using other custom FPGA board, without using Kiwi FPGA,

    1) I tried with Zynq FPGA so, I change the XDC file as per the new FPGA i.e Zynq and connected the spi signals to Beagle bone board
    2) But here I'm configuring (bit file) Zynq FPGA through JTAG so I programmed it through JTAG.
    3) I executed ./gps.bin from beagle, its showing as "fpga not responding",
    4) I'm not sure that ./asm/gps.bin will be configured through SPI interface or we need to do with other technique, may be because of the file (./asm/gps.bin), first command "CmdPing" may not be responding from FPGA.

    So please guide me how to resolve the problem.

    Thanks.
  • jksjks
    edited November 25
    To get the "ping" check to work a lot of things must be working correctly. The ping code running in main.cpp on the Beagle sends a ping command down the SPI to the embedded processor (ecpu) running on the FPGA. Code on the ecpu then returns a value over SPI that is checked by main.cpp and produces the "FPGA is not responding" message if the wrong value is received. It will also print this if anything else is broken. Like the SPI is not really moving data correctly. Code for the ecpu must also have been downloaded to it successfully over the SPI before the ping will work.

    So you should probably try to debug each of these things separately to make sure they are working. For example you can check the SPI by doing a write/read test from main.cpp Send a data pattern with spi_set() and see if you can read it back with spi_get(). I'm talking about the sdgps code here. I forget the exact details about how to do this, but it is possible.

    To debug the ecpu see if you add an output to an FPGA pin that can be changed by code running on the ecpu. This is a little complicated with sdgps because you'll have to change the verilog a little bit. Look at the bottom of the host.v file. See how there is some verilog to change outputs called led0/1? Add some code that says:
    always @ (posedge clk) if (men_rd) led0FF <= men_dout[0];
    That will make led0FF follow bit0 of a "wrevt GET_MEMORY" instruction in the ecpu code. Then modify the ecpu code to send a pattern on bit0 you can then check with a scope on the FPGA pin. That will tell you is the ecpu is running code properly or not.

    Now comment out the code in main.cpp:fpga_init() that loads the ecpu code (asm/gps.bin) over SPI. Instead, use Vivado to set the initial values of the first few locations of the cpu.v cpu_ram:BRAM to the ecpu instructions that send the pattern to led0. Look at the asm/gps.h file that the ecpu assembler generates. Those are [address, instruction] pairs for the simulator code. So the instruction value is what you want to get Vivado to initialize the cpu_ram:BRAM with.

    This is complicated stuff and I can't guide you exactly. You have to be creative about finding ways to debug things. You might have to add some output wires in Verilog to the SPI module to see if it getting the correct data and/or operating properly. Be sure that your SPI signals are okay. Especially that BBB_CS_N[1:0] is correct during the SPI transfer.

Sign In or Register to comment.