Jump to content
  • 0

Least PL logic intensive data gathering


StudentAmsterdam

Question

Dear all,

I hated the fact the Zybo Zynq does not have a proper D/A converter on its own.
So I programmed a VHDL 1-bit delta sigma modulator according to this Link.
The delta sigma modulator is working as a charm, but I want to be able to set the frequency of the waveforms i am generating.

I want to set the frequency of the waveform by using an 1-10V input signal.
I am okay with C and VHDL but I have never used the block designs or Zynq IP & GPIO Blocks..

The PMOD connector connected to the fpga is already in use so I guess my options are.

  1.  Use a external microcontroller with ADC and use SPI to the PS part of the zybo zynq.
  2.  Use the XADC connect it to the PS and of course use a voltage divider or something
  3.  Microcontroller and just bit bang the values directly to the PL side

Are there any suggestions on the easiest way of doing this ?

ps: Is it possible to do something similar to interrupts in VHDL


 

Link to comment
Share on other sites

17 answers to this question

Recommended Posts

@StudentAmsterdam,

If all you are worried about doing is cos() and sine(), then it may be a wash as to which is better--the FPGA or the ARM.  FPGA's can calculate sines and cosines, and even arctangents, at faster than 100MHz, without ever missing a sample to handle a another piece of hardware interface that needs servicing.  If what you want, though, is a generic floating point processor that is easy to reconfigure, you might find the ARM more appropriate.

Let's see if I can separate these a bit better:

  • Use the ARM if ... you need easy reconfigurability (just compile a new program), access to all of the ugly functions out there (sine, cosine, divide, and arctan are not all that ugly), and/or floating point arithmetic
  • Use the FPGA if .... you need reliable timing, or high-speed processing---beyond what the ARM is capable of

Does that capture the differences well enough?

Dan

Link to comment
Share on other sites

@StudentAmsterdam

In Vivado IPI, re-customize the GPIO IP to set the first channel width to 32 bits, check the all outputs or all inputs block as appropriate. set the default output and tristate values as appropriate. If you want a second 32 bit output enable dual channel.

In SDK, I find it easier to work with the raw registers than with the xpgio header (I would not recommend this for any other IPs, AXI GPIO just happens to be super simple). Some super-basic sample code of how this works would be below, intended to blink each bit of both GPIO channels once per second:

#include "xparameters.h"
#include "xil_io.h"
#include "sleep.h"

#define GPIO_BASEADDR (<base address of gpio block in xparameters.h>)

int main() {
    Xil_Out32(GPIO_BASEADDR+4, 0);//set Tristate of GPIO channel one to all output
    Xil_Out32(GPIO_BASEADDR+12, 0);//set Tristate of GPIO channel two to all output
    Xil_Out32(GPIO_BASEADDR, 0);//set output of GPIO channel one to all 0
    Xil_Out32(GPIO_BASEADDR+8, 0);//set output of GPIO channel two to all 0
    while (1) {
        sleep(1);//wait 1s
        Xil_Out32(GPIO_BASEADDR, 0xFFFFFFFF);//set output of GPIO channel one to all 1
        Xil_Out32(GPIO_BASEADDR+8, 0xFFFFFFFF);//set output of GPIO channel two to all 1
        sleep(1);
        Xil_Out32(GPIO_BASEADDR, 0);//set output of GPIO channel one to all 0
        Xil_Out32(GPIO_BASEADDR+8, 0);//set output of GPIO channel two to all 0
    }
    return 0;
}

Note that BASEADDR is the address of the channel one output register, +4 is the offset for the channel one tristate register, etc. These addresses do not depend on anything like channel width.

Hope this helps,

Arthur

Link to comment
Share on other sites

@D@n

First off thanks for the assistance again.

I am just missing the part how to do this, I can see how you set an output of a led using the PS and the AXI GPIO, but if i want to send 16bits of data by using the AXI gpio.
Do i need to constraint the AXI gpio to different outputs and just read them out 1 by 1 or something?  Or how does a 32bit width output work :S

Link to comment
Share on other sites

So maybe when starting this I was a tad optimistic..

I managed reading out the Xadc on the PS-side and tweaking my PL-side delta sigma converter some more.
However i'm struggling with getting the measured Xadc value  over to a vector to use in my PL-side.

I tried a bunch of different approaches like:

Youtube TutorialJeff Johnson, AXI DMAMicrozed chronicles AXI DMA.
And several others, but for some reason I can't get any of them to work.

Even by using a simple block diagram and using the PS DRAM example codes to check writing to the DRAM isn't giving any results.
For the past weeks I have been reading up on all the latest AXI datasheets but without succes.

Can someone point me in the right direction? 
To repeat myself, my goal is to send a 16 bit value over from the PS side to the PL side.
thanks in advance

 

EDIT:

edit: I was trying to learn more about using the GPIO pins, and came across the following video: https://www.youtube.com/watch?v=JPVTVNtJ7R4

Which is basically exactly the same as interfacing LEDs or buttons through ps side.

Is it possible to just make add a 16 bit wide axi gpio block to the design and interface it through xpar axi gpio 0 device through the PS block???

Link to comment
Share on other sites

Yes I am aware of the limitations and max ratings of the Xadc and the IO pins.
 

Thanks all for the help,
I think I am still gonna try to receive data from the XADC by using the ARM, and send this data to the FPGA.
It might not be the best or cleanest way, but I think it has a lot of educational value in both interfacing between the ARM and FPGA and learning how to use the XADC.
Its a toy project after all.

I have read that it is possible for the ARM to communicate with the Xadc through the internal Jtag connection,
Maybe store this value in the BRAM and read it with the FPGA.

Doesnt sound like least intenstive data gathering anymore but hopefully a lot of learning experiences.

 

Link to comment
Share on other sites

Don't know why this ( or anything for that matter.. ) just popped into my conscientiousness but be careful connecting anything to an FPGA pin. DO worry about static discharge. DO make sure that your don't exceed the input voltage limits or try to ground a driven output. The XADC A/D input pins on the Zybo "must be limited to 1V peak to peak" as per the Zybo User's Manual. You no doubt know that current doesn't flow without a closed loop. If we're talking about a 1.2V battery that can source 1 mA that's one thing. If we're talking about playing around with a 440V mains then you need to carefully consider all of the possible ways to close that loop that aren't obvious. Same idea applies to not exceeding a peak-peak limit; think 440 mains. I have my doubts about how happy you will will be with a 20-turn pot to obtain a 24-bit value. Compare how many values a 2^12 bit A/D can provide to how many values are in a 2^24 std_logic_vector. But don't let me discourage healthy experimentation. 

Link to comment
Share on other sites

Yeah, the ARM has that nifty NEON extension with an FPU. Floating point or some reasonable semblance to it is a bit more difficult to implement in logic, at least directly. But by using the magic of a lookup table any complex mathematics can be implemented. When I first started out as a "digital engineer" many decades ago the first microprocessor that was available to replace lots of MSI components was an unambitious 8-bit  Motorola 6800 operating at the fantastic speed of 1 MHz. No floating point, but a lot of lookup tables, a lot of complex mathematics. Imagine the giddiness when the 2 MHz version came out. Still we managed to control multiple servo motors and lots of complicated electro-mechanical equipment.  I don't reminisce about the "good old days" fondly but a lot of the creative ways we did then to accomplish things are still as relevant as ever. And by the way while there's no arguing about the dynamic range of double precision floating point the precision may not be sufficient. Single precision floating point is worse.

So at the risk of being Captain Obvious I'll tell you what you already know. If you want to use C to program a micro-controller and the ARM/Xilinx ecosystem provides everything that you need then perhaps using the PL as a peripheral to the ARM is the way to go. But you've already broken out of that mindset because you figured out that you can do something more interesting and useful for your purposes by implementing a feature in the PL. I just want to encourage that spirit and suggest that you shouldn't see the FGPA as a poor cousin to any CPU architecture. If you're looking to expand your mental horizons try thinking about the ARM as a peripheral to the PL.

I'm just happy to hear from someone identifying themselves as a student asking really good questions and a penchant for thinking.

 

Link to comment
Share on other sites

I want to use the ARM so I can later on add arithmetic functions like noise and complex calculations to the waveform, that is why i want the ARM to output the bitstream to the fpga.
Because as far as my knowledge goes, The ARM is a better choice for doing calculations with cos() and other complex functions.

Link to comment
Share on other sites

I thought that this bit of "wisdom" gained from experience might be useful to you or anyone reading this thread.

Anything that you create using the ARM board design methodology is likely to to get broken with each new release of your FPGA vendor's tool set. This is true for all of the FPGA vendors who offer devices with an embedded ARM. Some make chore of supporting designs through tool set versions more painful than others. Frequently this involves software and HDL design components. Also, porting your work to another FPGA vendor's device will be non-trivial. Anything that you create using an HDL is immune to FPGA tool set version releases ( unless you need to take advantage of support for new HDL version extensions which is pretty rare ) . Also, porting your work to another device is a lot easier, except for things like PLLs, block memory, SERDES and the like. With HDL you have total control over what your design does and how it does it. As a student his may not seem to be a particularly important issue. Once you start accumulating a body of design work it will be; trust me on this.

Link to comment
Share on other sites

Yes, If you use the DRP to access the XADC registers in your PL logic and have an Input port in your ZYNQ entity the ARM can read the A/D. It's quite likely that there's already IP in available in the ZYNQ ARM ecosystem that does this for you; so you most likely don't have to use the PL. As to using BRAM, I'd use that for streaming data to the PL side logic. A simple output port should do.

Here's my main point. Why do you want to tie the ARM into your design so intimately? You can to everything that you've described in the PL using VHDL or Verilog. The ARM might be interested in knowing what's going on if, say, your ZYBO is part of an Ethernet controlled system that reports current DDS frequency or D/A output to a remote controller.

A lot of pretty complicated stuff can be implemented in logic using state machines. If your state machine starts getting too large or complicated you can design a simple programmable controller to simplify that. It what you want to do starts getting too complicated for your simple controller there's an ARM for that. The ARM is great for using a high level program like C or Python to do really complicated stuff that you want to change on the fly without reconfiguring the device. Random logic in an FPGA ( or PL in the ZYNQ ) is great for doing a lot of concurrent processing that requires very low latency, high frequency timing, and any custom function that you want total control over.

Link to comment
Share on other sites

35 minutes ago, zygot said:

The other approach is to create the normal block diagram with either dual port BRAM with an interface to one side as external IO or just a simple IO port. Then you can get Vivado to create a toplevel entity describing the entire thing. This entity can then be instantiated by a wrapper file that you write, set as a new toplevel entity and proceed from there. That last approach is a whole lot easier than the first one.

If understood correctly,
I would be able to use the XADC connected to the CPU to read out the analog value.
Then use the BRAM to interface the value between the CPU and FPGA side?

Is this correct?

Link to comment
Share on other sites

To my way of thinking the ZYNQ is a terrific way to have a CPU with an FPGA peripheral; or visa versa. First of all let me congratulate you on creating your DAC and DDS in the PL without using IP from other sources. You questions mirror those of others who seem to be having a hard time "getting" the ZYNQ concept. The concept of an interrupt is one of a CPU. For an FPGA everything is simply logic. Both VHDL and Verilog use the concept of concurrent processes. Use the CPU for what programmable fixed computing architectures do best and use the PL for what arrays of "digital logic" do best. I've used two approaches to tie my FPGA designs to the ARM CPU. One is to create my own IP and use the excellent Xilinx hardware/software tool-chains to close the loop on the larger design. The other approach is to create the normal block diagram with either dual port BRAM with an interface to one side as external IO or just a simple IO port. Then you can get Vivado to create a toplevel entity describing the entire thing. This entity can then be instantiated by a wrapper file that you write, set as a new toplevel entity and proceed from there. That last approach is a whole lot easier than the first one. I suggest to everyone using an FPGA with an embedded ARM to learn how to do both.

You are well on your way to figuring out the amazing possibilities offered by ZYNQ.  Wonderful! 

Link to comment
Share on other sites

Dear D@n,

Your approach is a drastic overhaul of the entire system, I would like to keep my current Delta Sigma Modulator design.
To elaborate some more, the waveform is now produced by a DDS in which I can change the frequency by setting a 24-bit register controlling the frequency.
I have attached two pictures of testing the Delta Sigma Modulator design.

All I like to do is being able to change this 24-bit value by using a 20 turns accuracy potentiometer.

Nevertheless is the FM signal a very interesting project, which I will definitely use for one of my other ongoing projects ;) 

 

IMG-20170709-WA0031.jpeg

IMG-20170709-WA0033.jpeg

Link to comment
Share on other sites

@StudentAmsterdam,

Yeah, I've never used the block design methodology of Vivado either.  It might be one of the reasons why I've avoided the Zynq.  :D

But to your question, you can create a delta-sigma output pin, and control the frequency of the "waveform" being sent out there.

Here's a project that creates an FM signal and dumps it out a GPIO pin, using the GPIO as a D/A.  I tested this from a Spartan 6, running off of an 80MHz clock and "broadcasting" on ~90MHz FM.  While I didn't use a SERDES for the test, I might recommend using one.  Needless to say, I got some range (18" or so) from it, so ... it works, just ... not well.  The core component of the project is controlled via a wishbone (not AXI) bus, allowing the CPU on board to change frequencies as desired in order to broadcast the "music" output.  (I played Queen on the local Christian radio station ...)

You can read more about the timing underneath this technique here, or the angular units I used here.

Were I to try to improve on this design, I'd switch to a SERDES to get my sampling rate up above 400MHz, and I'd use a better antenna.  (I didn't have any wires connected to my GPIO's at all.  I've now got some paperclips opened up that I'd like to try.  The only problem is--they're too thick to fit in the PMod holes, and I haven't filed them down yet.)

Dan

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...