• 0
Yannick

How to interface an Analog Device's ADC on the NEXYS 4 DDR using a Pmod port ?

Question

Hello !

I'm currently working on a project which consists in designing a digital lock-in amplifier on a FPGA board. For this, I am using a Nexys 4 DDR and an Analog Device's ADC (EVAL AD7984 PMDZ).

My first goal is to interface properly the ADC component with the FPGA using a Pmod port.

I have some basics knowledge about the use of Vivado so that's why I am asking you about this. I followed the tutorials about "getting started about MicroBlaze" to follow then "using Pmods IP".

My question is :

When I followed the first tutorial mentionned above, we created a a basic Microblaze block design. Do I have to use all this design or is it possible to do easier ?

And, do I have to design it with MicroBlaze or can I just write some VHDL code ?

I want in a first part, to give a signal input in the ADC and then, light a LED on the board to confirm that the FPGA is well connected with the ADC. Can you, please, give me a plan to achieve my goal ? I don't ask for a solution, I want to manage it by myself, but just some help to know what are the steps I have to follow.

 

Thank you very much ! Have a good day !

 

 

 

Edited by Yannick

Share this post


Link to post
Share on other sites

13 answers to this question

Recommended Posts

  • 1

Welcome @Yannick!

You can use either Microblaze or pure VHDL, depending on the needs of your project. If you want to do some heavier calculations involving the ADC data later, it will be easier to use Microblaze. Pure VHDL uses less onboard resources, but takes more work to do properly for complicated designs.

For your first step, you have two options, use one of the provided Pmod IPs for a dual SPI/GPIO interface, and modify the C drivers for your design on Microblaze. I do not believe any of our provided designs support an equivalent of the CNV conversion pin on your ADC, hence, tying that to a bottom-row GPIO interface is likely the way to go (perhaps hacking something together from the Pmod ACL IP core). Or, you can write a custom VHDL SPI controller, with a small top-level controller sitting above it capturing data and handling your "connection established" LED.

Which route you choose is up to you, but consider how complex your final design needs to be, Microblaze might not be worth it at this stage, but if you want to control your design through C later, you will want it.

Hope this helps,

Arthur

Share this post


Link to post
Share on other sites
  • 0

@Yannick,

May I provide you with an alternative view?

You don't need MicroBlaze at all.  Indeed, you can control your design from an external PC without MicroBlaze, and hence still "control it from C"--I do it all the time.  Sure, it's slower but ... the real issue isn't your favorite way of controlling the board as @artvvb suggests, but rather ... what do you wish to do with that ADC data?  And how fast you need the board to respond to your control inputs?

Your first step, as you suggested, is to light an LED.  Cool.  That's a nice first step.  But ... think that first step through a little more: how will you know, if something is going wrong, what is going wrong?  You need to add logic into your design to answer this question.  Indeed, the sooner you add this logic into your design, the easier things will be to debug as your design becomes more complicated.  At the same time, I doubt this is your entire project, am I right?  This is only the first step?  So, let's think this through some more.

Do you want to fill up your Nexys-4 DDR's memory with ADC data and read it back off slowly?  You might find your memory needs competing with MicroBlaze, should you choose to use MicroBlaze.

Do you want to read from the ADC, do some on-board processing, and then output the results in real-time?  In that case, depending upon the processing you wish to do, MicroBlaze may or may not be overkill.  My general rule of thumb is that if the ADC sample rate is anything above audio rates, don't use the onboard processor to process the data.  Even this isn't necessarily the best rule of thumb, depending upon how you have the processor configured.

But ... let's look at this from another standpoint, you bought an FPGA board so that you could do somethings that you couldn't do on a cheaper RPi board, right?  If all the MicroBlaze does for you is turn your FPGA into a more expensive version of an RPi, then ... something is wrong in your pocket book.

 

So, going back to your questions:

  1. Do you have to follow the microblaze design?  No.  Are their easier ways?  IMHO, yes.  MicroBlaze is a proprietary CPU design.  Other, non-proprietary designs are out there.  You can find some of these on OpenCores.  I've personally been working with the ZipCPU.
  2. Do you have to design with MicroBlaze?  No.  Can you just write HDL code?  Absolutely.
  3. Plan?  Look across your whole project, and answer some questions:
    1. How do you plan on debugging your design?  When things don't work, how will you know what's not working?  (MicroBlaze is notoriously difficult to debug--it can be hard to know why it does or doesn't do something.)  I tend to use a homebrew scope to see what's going on within a design.
    2. Will your data need to be stored in that DDR3 SDRAM memory?  If so, you'll need a bus somewhere within your design.  MicroBlaze likes to connect everything up to an AXI4 bus.  I personally like the wishbone myself, but I have to convert wishbone to AXI4 to get access to anything generated by Xilinx's Memory Interface Generator (MIG).
    3. Will the FPGA be acting as a standalone device, or always connected to a PC USB umbilical cord?  I personally tend to convert the PC USB UART channel into a bus command/access channel, so I can see what I have going on.  It makes it easy to both debug, as well as command and control the FPGA from a PC.  While not necessary in your final version, you might find the scaffolding valuable along the way.
    4. How will you be controlling your design?  From C somewhere?  On a host computer?  Internal to the FPGA (MicroBlaze/ZipCPU)?  For me, I do both.  I first control things from the host PC, and then when I want to do more/faster, I move that control to the FPGA/ZipCPU and monitor it from the PC.  If I want to/need to go even faster than that, I move things into pure logic and monitor it either externally or from an onboard CPU.

Hope this helps you think through things,

Dan

Share this post


Link to post
Share on other sites
  • 0

Hello @D@n, @artvvb !

Thank you both for your answers !

Actually, I've just started an internship and the goal is to implement a digital lock in amplifier on a board, for an optic detector. Indeed, I'm starting from a photodetector and I want to go through the ADC and then the FPGA to do some on board processing. More precisely, I want to apply the principle of a lock in amplifier which is, in an easy way, to multiply the input signal with a reference (at the same frequency), and then apply a low pass filter to recover a clean signal.

So in a first part, to familiarize with the board, I wanted to put a signal from a generator until the ADC, and then light the LED on the Nexys board as I told you (before treating the real signal from the photodector). The second step would be to do the signal processing with the multiplier and the filter. But I was, and I am still, lost on how to plug and set up the ADC on the Pmod port (MicroBlaze? HDL code ? Other way ?)

So to aswer to your questions @D@n, yes I want to read from the ADC, to do some on board processing and output the results it in real time. Because, the next step of this digital lock in amplifier is to create an imaging system after collecting the clean signal from the board (photodetector -> ADC -> FPGA -> (image processing) ).

Besides, you talked about RPi board. I did not choose the board. Actually, my tutor provided me this Nexys 4 DDR and the Analog Device's ADC (This is a 18-bit resolution ADC, that's why we don't use the ADC from the board) . But I am not obliged to work on this board. I was justly wondering if working on a microcontroller should be easier. What do you think about it ?

I am also agree with the debugging point but what do you mean by "add logic into your design" ?

 

Thank you very much once again.

Share this post


Link to post
Share on other sites
  • 0

@Yannick,

I just looked up what a "digital lock-in amplifier" was.  Sounds like a fun project!

The sample rate on your ADC will dictate a lot of your choices.  For example, if you are working at a high speed sample rate (100kHz+), then you may not be able to afford the microprocessor--at least not within your processing chain.  An ADC with an 18-bit resolution is not likely to be a very high speed ADC, so ... that expands your options.

Are you familiar with cordic's at all?  You'll find them *very* valuable for creating the sin/cosine wave's necessary to get that lock in amplifier working.  You'll also find recursive averagers make for perhaps the simplest lost pass filters.

But let's get back to your question, of how to set up the ADC on the PMod port: HDL or MicroBlaze.  If you press me on this question, you'll quickly discover I have a nearly religious answer--never use MicroBlaze.  This answer isn't fair for me to give to struggling young students as yourself, so I try not to do so.  My reasons are based more along the lines of opensource principles and such.  Are there open alternatives to MicroBlaze?  Yes.  Are they as well supported as MicroBlaze is?  Not to my knowledge.  I mean, I'm personally working with the ZipCPU.  I think it's a wonderful CPU.  But with the number of problems others have had getting started with it ... MicroBlaze has a bit of an advantage there.  However if (when) things go wrong, you can at least trace the problems through an opensource design--not something you can do through MicroBlaze very well.

But, no, here's what I'm thinking of: what you want first and initially is not a CPU at all, but a means of knowing how that ADC device is responding to your commands.  The nightmare is that you would write 200+-lines of HDL, place it onto your device, and have the device not work, the LED doesn't light, etc., and then to stare at the whole thing having no idea what went wrong.  This is the nightmare I would have you avoid through a little pre-project thought.  If/when you get stuck in this nightmare scenario, you will want to be able to examine more data than just that LED to know what's going on.  Are you toggling the pins for the ADC properly?  Are you setting the clock for the ADC properly?  Are you getting data back from the ADC at all?  While LED's are wonderful, they only provide so much info. 

My solution to this problem would be to first build my way to the device I needed to work with.  I would build a bus, and in particular, one that can be read from and written to from the host machine.  I personally like the wishbone bus in its B4/pipelined mode (using MicroBlaze would require AXI later), and I like to command it over a serial port via a well defined interface.  Then I would place onto that bus some form of "scope" which can record data from your FPGA-hardware interaction, and allow you to read it back from the bus.  While you might have a CPU on the bus initially, I would leave it turned off--at least until you had your hardware running.  This gets you out of the nightmare scenario I described above--at this point, you know what is going on with your ADC, what is going on with your HDL, etc.  Once it looks like its working then its time for ....

The next step would be to have the "ADC" "device" write the RAM on your processor with samples (or otherwise record).  You would give commands from your PC/host such as: reset the ADC, send the ADC these setup parameters, etc., and go.  On "go", the ADC device within your FPGA would slowly overwrite all of your RAM.  You would then download this data to your computer and examine it with MATLAB or (my favorite) Octave.  Even better, you would build your lock-in-amplifier algorithm on the host PC, and then verify that it would work with these data samples recovered from your actual ADC.  No, you wouldn't leave it on the host PC, you would migrate it onto the FPGA, but ... wouldn't it be nice to know before stuffing it into the FPGA that it will work when it gets there?

Only at this point in your development does the CPU come into play.

This is how I personally would do it.  There are many other solutions, many using MicroBlaze, and I tend to hold a minority opinion.  ;)

Does this help?

Dan

Share this post


Link to post
Share on other sites
  • 0

Hello @D@n !

I'm finally trying to use the JXADC first to acquire a digital signal. I'm currently displaying the channel 3 (AD2N, AD2P) voltage on the LEDs. I use the DRP interface to  collect the data in entry of the channel 3 by the DO[15:0] bus. But there's something I don't understand when I read the UG480, page 25. It's written that the 4 LSB are "Note", what does it mean ?

When I display the voltage on the LEDs, the first four are always lighted, I don't understand why.

Share this post


Link to post
Share on other sites
  • 0

@Yannick,

On 3/4/2017 at 8:46 AM, D@n said:

Your first step, as you suggested, is to light an LED.  Cool.  That's a nice first step.  But ... think that first step through a little more: how will you know, if something is going wrong, what is going wrong?  You need to add logic into your design to answer this question.  Indeed, the sooner you add this logic into your design, the easier things will be to debug as your design becomes more complicated.  At the same time, I doubt this is your entire project, am I right?  This is only the first step?  So, let's think this through some more.

How do you plan on debugging your design?  When things don't work, how will you know what's not working?  (MicroBlaze is notoriously difficult to debug--it can be hard to know why it does or doesn't do something.)  I tend to use a homebrew scope to see what's going on within a design.

So ... what's going on internal to your design?  Can you tell?

Dan

Share this post


Link to post
Share on other sites
  • 0

@Yannick,

Sorry, took me a moment to find UG480.  The note means that the 12'bit ADC is placing the 12-valid bits into the upper 12'bits of a 16'bit value.  The user guide suggests that these bits "can be used to minimize quantization effects or improve resolution through averaging or filtering."  This comment makes absolutely no sense to me.  I'd just understand the user guide to say that the bottom four bits are invalid, and understand that I don't want to pay attention to them.

Dan

Share this post


Link to post
Share on other sites
  • 0

Hey @D@n !
 

  • 16 hours ago, D@n said:

    This comment makes absolutely no sense to me.  I'd just understand the user guide to say that the bottom four bits are invalid, and understand that I don't want to pay attention to them

    I had the same opinion, thank you to confirm :) !
     

     

    17 hours ago, D@n said:

    So ... what's going on internal to your design?  Can you tell?

    Before implementing an other ADC by plugging it on the PMOD, we finally decided to try to use the internal ADC even if the resolution is 12bit. Maybe it would be enough, we don't know for the moment so let's try :) !
    So I used the XADC wizard and I wrote some VHDL code (definitely not using MicroBlaze ^^ ) to convert a voltage which enter in an auxiliary channel (AD2P/AD2N) on the JXADC, and to display the digital conversion on the LEDs. It seems to work because when I have 0 V none of them light and when I have 1V they all light. But I'm checking if the intermediaries steps well correspond. I was justly wondering how to check efficiently and easily if the conversion is well done (avoiding conversion binary -> decimal and display on 7-segment..). Because playing with the LED's and checking which of them are lighted to try to guess the binary code seem to be a bit archaic ahah. Indeed, some of them are sometimes lighted at half  ! So that's where I am for the moment, thank you for asking :).

And thank you very much once again for your answers !

Share this post


Link to post
Share on other sites
  • 0

@Yannick,

My favorite test to tell if the conversion is well done would be to place a nice, clean, sine wave into the input.  I'd pick a frequency near fs/4, and then I'd capture a couple waveforms, map them to a sine wave and compare.  I'd then repeat at something like fs/256 or fs/1024 or some such, and check again.  In both cases, grabbing a couple of copies of the full waveform.

By watching how the sine wave you capture compares to a true sine wave, you should be able to find and ring out any imperfections in your system.  Chief and first among those, IMHO, would be making sure you had all the wires and formats right.  (Ex. nothing bit/byte swapped)  Histograms make great tools for finding format issues.  (Incidentally, live historgrams in FPGA logic are *really* easy to do ...)

This is part of the reason why I was hoping to encourage you to move beyond the LED's.

Dan

Share this post


Link to post
Share on other sites
  • 0

It seems to be a good idea @D@n!

But what is "fs" ? Why fs/4 ? and last one, how would you proceed to " capture a couple waveforms, map them to a sine wave and compare" ?

 

Edited by Yannick

Share this post


Link to post
Share on other sites
  • 0

@Yannick,

Sorry ... I used terms without explaining them.  I was using "fs" to reference your sample frequency.  "fs/4" then is one fourth of your sampling frequency.  "capture a couple of waveforms" wasn't right, it should "capture a couple of wavelengths".  Sorry.  By "map them to a sine wave", I mean take a linear least squares fit between the sampled values and a sine (and cosine) wave, so as to back out the amplitude and phase prior to a comparison.

The trick is ... to get there, you need to be able to record your samples to memory, and then read them back into your computer for processing--whether by MATLAB or Octave.  Pushing that a touch further, it means you need to have some form of bus internal to your design (necessary for reading/writing RAM), and that this bus needs to have at least two masters: one would be your XADC testing routine, the second .. whatever is reading the results off and sending them to your PC for inspection.  One example of such a program/design (without the XADC, sorry ...) would be the S6SoC I've been working on.  Look at the alttoplevel.v interface on down--it allows complete control of an internal bus from an external computer.  Although the design is intended for a CMod S6, I think I can safely guarantee that you have enough logic on your Nexys 4 DDR device to run (most) of it.  Using such an interface, you can build C++ code that interacts with an FPGA using a very simple interface, and ... then see what's going on within your FPGA.

This may be a longer discussion than you want on the forum.  Feel free to contact me at freenode IRC on the #digilent-fpga channel, if you'd like to chat further and in real time.

Dan

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now