The Sine Wave Generator in the FPGA palette does what I need it to do
except it can only do "cosine" output, which is 90 degrees apart. I need 120
degrees. Not to be deterred, I opened the front panel on the Sine Wave
Generator Express VI which converted it into a normal sub-vi. I changed the
numeric constant to correspond to 120 degrees out of phase and changed the name
of the output pin.
The module won't compile. First error was a wire that was a variable type, the
fix suggested to tick a box for preallocation did not work so I made the array
a constant length of 1024 (which is what it's supposed to be). Next error was
that a vhdl file line was too long (32k characters for a max length spec of 4k
Just for grins I put the original Express VI back in with the cosine output and
it builds correctly.
There was a big caveat about changing the vi. However, I didn't think that
simple conversion to a sub-vi and the tweak of a constant value would break it.
Any way to get a modified express vi for this application, or pointers on how
to tweak the one that's there? The compilation principally breaks on VHDL line
length associated with the 1024 point array.
I can roll my own sine generator using some of the examples, not a big deal but
it will cost a bit of time. Another option might be to run two sine generators
and specify a different phase, however I'm not confident that over time they
will remain exactly synchronized. Modifying the Express VI is a much better
Thanks in advance,
Solved! Go to Solution.
The caveat about not changing the subVI is indeed critical. The code in the subVI is only used for execution on the development computer, while the actual hardware code is written in VHDL. The reason for this is that the node models a continuously running DDS engine under the hood (running at the FPGA clock rate, independent of the calling VI's loop rate).
In order to produce the same behavior in native G code, you could use the subVI code as a guide, but implement it in a Single-Cycle Timed Loop (SCTL) that runs continuously and writes its outputs to a Register. Then your main While loop would just sample the continuously-running engine outputs at whatever rate you want to run it, something like the code below. I've modernized it a bit to take advantage of features that didn't exist when it was written. This should result in pretty close to exactly the same hardware as the default configuration of the Sine Wave Generator (it's missing a few feedback node delays needed to meet timing at very high clock rates):
OK, I wondered what was going on given that the express VI description that it ran at the FPGA clock rate. I'll code it up and give it a shot.
I found out the hard way that LabVIEW 2011 does not have registers. After looking at various options I settled on FIFOs. The code presented here works well, but it doesn't save space on the FPGA over using two sine generators with a hardcoded phase difference on one of them. For now I will use the two sine generators, if that proves to be unworkable in practice due to drifting phase relationships then I'll look at this again.
The frequency and phase offset controls are fixed-point numbers formatted to zero integer bits and 32 bit word. The lower while loop is synchronized with the timed loop by the FIFO reads, FIFO timeout of 18 ticks is two more than the 2.5MHz loop which is a divide-by-16. The IF block in the lower while loop cuts the control update down to 10KHz, more than fast enough for 60Hz sines.
Great learning experience, thanks for the help.
Sorry about the Registers--that was actually my first time using them. Using 2 Sine Wave Generators is definitely a reasonable (and simple) solution. For your implementation, make sure your Sine LUT Memory is configured to use Block Memory. There is a bit of overhead involved with enable logic for the SCTL in your diagram, and the FIFO transfers cost some extra logic.
The FIFOs also add extra latency and jitter, so if you went this way I would recommend using 2-element (the minimum size allowed) Memories configured with Look-Up Table implementation to implement the Registers. Then just continuously Write to one address in the SCTL and Read from the same address at whatever rate you desire in the While loop. That way you always have instant access to the most current generated sample and can run your SCTL as fast as you want (running it faster gives better frequency resolution).
My own compile comparison of the two methods is showing a savings of 40 slices or so with the roll-your-own approach, but it's a lot cleaner to just drop the 2 Sine Wave Generators and be done with it. Another possible advantage is that with separate generators, you can choose to interpolate outputs if you need a cleaner signal. Phase drift will not be an issue--if they start in parallel under the same clock they'll execute in step forever.
OK, nice to know. The FIFOs are 2 registers long as you suggested. My total FPGA size using the express VIs is 5158 slices, so rolling my own would save a little.
I will be changing the frequency. Will the generators remain in step if they are wired together?
Frequency changes are to synchronize two generators, what happens is that either manually or automatically under tester control one frequency is varied then brought back in phase. These changes are slow, and happen infrequently: changes no faster than 20 per second, usually slower than that, max 10 times per hour that this would be done. If the 120 degree phase relationship between output 1 and output 2 drifts 2% total over a few days it's not the end of the world.
I'm not sure I follow your system requirements. By "wired together", do you mean that both Sine Wave Generators get the same frequency input? In that case, their phase relationship should remain exactly the same over time. Are you talking about synchronizing physical electrical generators? I'm having flashbacks of the one sweaty-palmed experience I had closing the breaker when the needle pointed straight up...
Yes, this is generator sync but it's only simulated so people throw those breakers with reckless abandon when the needle points straight up. My implementation of this using the Express VIs is straightforward:
I did it this way so that in future if we want to simulate failures I can wire something other than a constant .3333 to the phase offset terminal. The frequency input is wired to both express vis, this will be changing to synchronize two sets of these vis. They all start out with slightly different frequencies, then manually or under software control they are varied to get them in phase with a reference 60Hz source.
From what you said, the phase relationship between Output1 and Output2 should remain constant if the frequency input is changed while the VI is running. I'll find out!