In my previous project post, I walked through the digital art of bit banging using Python on a Raspberry Pi to interface with a DDS signal generator module PCB based on the AD9850. Since bit banging is a matter of manually creating an interface in software, having a tool to debug/verify said digital interface is pretty vital.
A logic analyzer is the tool for the job here and I've been looking to test out the logic analyzer function in WaveForms that's running off my Eclypse Z7 development board. Lots of commercial test equipment have FPGAs at their core so I was interested to see an embedded Linux image released to make one of my regular FPGA development boards dual purpose essentially by being able to run a program like WaveForms to turn it into a USB scope.
Digilent covered all the bases in this guide here for how to install WaveForms image on the Eclypse Z7 and connect it to the WaveForms GUI running on a host PC. I'm starting my hardware setup from the point picking up after the setup of WaveForms with the Eclypse.
Hardware SetupThe DDS signal generator I purchased came with pre-soldered headers, 1x10 on each side. One side is just the parallel data input for the frequency/phase control word to the AD9850, while the rest of the digital interface (data clock, reset, etc.) as well as the analog sine wave outputs are on the opposite 1x10 header.
As I explained in my previous post, I chose to go with the serial data input. This was in part to make life easier with less connections to hook up to both the Raspberry Pi that was driving the interface as well as the Eclypse board with the logic analyzer.
The digital IO inputs in the WaveForms image for the Eclypse Z7 are mapped to its 2 Pmod headers on the bottom of the board.
While the Help tab in the WaveForms outlines the pinout of the DIO to Pmod pins, I made this excel sheet diagram to give added context of orientation with the pinout of the 2 Pmods:
I also used the Digitizer Zmod to measure the analog sine wave output from the DDS module so with it in the Zmod port on the top side of the Eclypse board and jumper cables from the breadboard with the DDS module to the Pmod header below it. So for a better visualization, I added it to my excel sheet:
Which those connections mapped in the excel above between the Eclypse board and the breadboard with the DDS module turned into this nice little jumper and SMA cable setup:
After powering on the Ecylpse board and launching WaveForms, select the Eclypse Z7 from the list of devices to set it as the target in the WaveForms GUI. Then a tab with the logic analyzer functions can be opened by selecting Logic from the Welcome tab.
Upon launching the logic analyzer add each digital IO from the DDS interface as a signal. Click the green + button and select Signal:
Select each of the connected DIO signals and give it the appropriate interface name from the target being measured. I simply started with DIO0 where I had the data interface clock (W_CLK) connected:
Then when through and added the other there interface signals: FQ_UD, data, and reset:
With the given speed of the processor on the Raspberry Pi and that I was using Python, the data clock (W_CLK) turned out to be 25kHz which has a period of 40us. Each control word had a total of 40 bits. So I set the time base of the logic analyzer to 200us per division to capture as much as possible on the screen at once while still be able to easily read it.
I had mentioned that the serial interface of the AD9850 was very similar to a SPI interface with just some special requirements of the behavior of the relative chip select signal (frequency update/FQ_UD). So I also added the same pins as a SPI interface to the logic analyzer window (quite a handy feature of WaveForms that one can add the same DIO signal for measurement multiple times).
I didn't set a specific trigger, opting to just let the logic analyzer free run since my Python script on the Raspberry Pi would continue to transmit control words until manually interrupted by a keyboard interrupt.
And to my pleasant surprise, interface looked right on the first pass. The only tweak I had to make was to add three clock pulses in-between the RESET signal being pulsed and the next FQ_UD pulse (as specified by the AD9850 datasheet). I noticed on some passes though, there was a pause on the whole interface after the first W_CLK in a transaction. I never figured out what caused this as it was not a part of the code in my Python script, but it didn't seem to have any affect on the output so I'm not going to worry about it for now.
Initially I was only seeing a DC output at the max peak voltage of 1v on the analog outputs of the DDS module which led me down a rabbit hole of needlessly changing my Python script but I ultimately ended up changing it back to what it was before.
I eventually figured out that I was accidentally saturating the oscillator on the DDS module by powering it at 5v instead of the proper 3.3v (check all of your data sheets kids...). Once I changed the Vcc input of the DDS module to 3.3v, I was able to see the appropriate frequency/phase sine wave on the analog output from the AD9850:
Now that I know how to get the desired sine wave output from this little DDS module, I'm curious to see what projects that I can build with this little board. It's perfect for some basic SDR projects to output an IF (intermediate frequency) signal since it goes up to 40MHz so that'll be something to explore.
Comments
Please log in or sign up to comment.