Hi,i use Matlab/Simulink and DSP Builder for my project. In Matlab, I generate a digital source signal and program it in a LUT-Block in Simulink. This Block then sends the data to my DACs. The source signal is an overlayed signal of 10, 20 and 30 MHz. When I now check the analog signal with a spectrum analyser I can see a shift in my frequencies. The 10 MHz signal is actually at 9,99564 MHz, 20 MHz actually at 20,00656 and the 30 MHz signal at 30,00220 MHz. It is very important to reach the frequencies precisely. An ~100 Hz offset would be ok, but more than 2 KHz is too much. Why is there this frequency shift. How to avoid it? I use a 125 MHz crystal and a PLL the generate a 125 MHz clock inside the Cyclone II EP2C70. All internal and external components use the same clock. The crystal should not be the cause of this, as the frequency shift is not linear (different shift at different frequencies). Any hints on that? Thank you for your time! Leo
How did you generate the LUT? are you aware of wrap-up continuity? I mean for one cycle sinusoid your first sample should not repeat at the end of LUT as you will wrap up to start.
That also came to my mind. It's just not possible to have continuous signals for all frequencies. But I hope the reason for the shift is something else.There is no check that the phase of the signal at the end is correct (concerning to the next step, the start). There definitly is a not continous state when the LUT switches from end to start again - at least for some of the frequencies.
Phase must be continuous and can be done as follows (DDS structure):LUT to contain one full cycle: data=round(32767*sin(2*pi*(0:255)/256)); --for 256 points, 16 bits signed or data = round(32767*exp(j*2*pi*(0:255)/256))); --for sin/cos then you address the LUT with 8 MSB of large n bit accumulator then the increment value decides the frequency: incr = 2^n *f/125,000,000 As such you keep phase continuity even when you change frequencies.
Thats not exactly what I need. I need a signal which is overlayed of different other signals. As in the example in the first post. My source signal consists of 3 different signals which are overlayed.With your solution it's only possible to have one frequency at a time. I still guess that this incontinuity is not the problem of my phase shift. But I just dont know for sure. Mixed products at higher or multiple frequencies could be a consequence but a shift?
It might not be the issue of continuity, it is just a matter of exclusion.You may try generate the three frequencies then add them up in hardware rather than pre-added in LUT. I agree phase discontinuity will show as spikes rather than offset. The offset may be explained on basis of clock, heating, timing or bug.
You didn't tell yet the involved DDS phase accumulator resolution. Insufficient accumulator bitwidth or coefficient calculation error would be the only plausible explanation in my opinion, assuming your analyzer has suffcient accuracy. Dependent on the specification, a crystal oscillator must be expected to have up to 100 ppm frequency error which adds to the DDS error.You would want to check the clock frequency error separately.
Thank you for your replies.I wasn't aware of a method DDS. The problem is that my project is a little bit more complex. I need the same signal on two analog channels going through a resonator circuit. The will be a different delay on these two lines so I have to sync the signals afterwards in the FPGA. So I need to send a sync signal at the beginning. A part of my code for the signal generation:
F_sample = 125e+6; %Which is also my FPGA clock (125 MHz) samples = 8192; %Generate Source Signals steps = 0:(samples-1); for index = 1:number_of_resonators Omega = 2*pi*frequency_vector(index)/F_sample; s(index,:) = amplitude_per_resonator*sin(Omega*steps); signal_source = signal_source + s(index,:); end %Add Sync Peaks: signal_source(1,11:(length(s(1,:))+10)) = signal_source(1,:); signal_source(1,1:5) = (samples-1); signal_source(1,6:10) = 0;The frequency_vector contains the frequencies, e.g. 10, 20 and 30 Mhz. This digital signal is stored in a LUT on FPGA. My LUT is 8192 values long and addressed via a counter. During measurement the data is AD-converted and stored in RAM. Then I calculate the synced signal via the sync peak (see code) to avoid phase difference on the channels. Then this data is further processed. The frequency shift also occurs without the sync peak at the beginning. The Signal/Spectrum Analysers have a resolution in the lower Hz-range. There is no limitation here. I might try a simple DDS design now but it would be awesome to continue to use my LUT method as it is very adaptive and simple to handle. Thanks again!
Consider a simpler test. use 10,20,40MHz then you can have a continuous clean vector in pre-added in LUT. This avoids the headache of three DDS plus adder in hardware
To demonstrate:a1=sin(2*pi*(0:8189)*12.5/125); a2=sin(2*pi*(0:8189)*2*12.5/125); a3=sin(2*pi*(0:8189)*4*12.5/125); a=a1+a2+a3; %scale for LUT your LUT should run from 0 to 8189 only
Ok, that's it. The not continuous states when jumping to the start of the LUT cause these problems. With a frequency that leads to a continuous signal, as the ones in post# 11 the frequency shift is gone.The DDS solution also works perfekt. Now, I'm able to generate signals which are shifted only about 100 Hz. That remaining shift could be because of the crystal is not exactly at 125 MHz. But it's fine for my project. Thank you again for your help guys. Saved the end of my work day ;)
Great and thanks for the feedback. I have seen broken vectors causing high frequency spikes due to sudden changes but never checked frequency accuracy itself.Another related case of continuity of test vectors is the case of filtered data vector. Initially a filter produces zeros then catches up after some delay (delay pipe). In hardware filtering (not vector based input), this occurs once at the start only and can be ignored but if you produce vector then you must delete the zeros. If you do that then vector will lose continuity. The remedy is to add extra samples before filtering the vector then chopoff zeros and wrap up correctly.