The Designer's Guide Community Forum
https://designers-guide.org/forum/YaBB.pl
Measurements >> Other Measurements >> Query regarding DFT function in Spectre
https://designers-guide.org/forum/YaBB.pl?num=1220511510

Message started by shaikh_sarfraz on Sep 3rd, 2008, 11:58pm

Title: Query regarding DFT function in Spectre
Post by shaikh_sarfraz on Sep 3rd, 2008, 11:58pm

Hi,
I need to simulate an ADC for SNR values.
I am using coherent sampling technique.
I am applying a sinusoidal wave at the input of ADC and generating a staircase at the output.

Then I am using DFT (rectangular window) to get the frequency domain output. As the output of DFT is in complex form, I am converting it magnitude form by squaring and adding the real and imaginary part and then taking the square root.

Now my query is:
1).  How to find the RMS value of Noise?
     I am taking the square of each noise magnitude, then taking its
     mean and then taking the root.
     Is this the correct way, I mean do we simply need to add the
     square of noise components and take the root or should we take
     the mean of it.

To cut it short:
Is the magnitude form (which I am getting from the complex output ) of DFT output is the RMS value or not?

Best Regards
Sarfraz

Title: Re: Query regarding DFT function in Spectre
Post by als on Sep 4th, 2008, 4:44am

Shaikh,

 If you have access to ViVA, SNR [SNHR] is now available in
the calculator. The spectrum function allows designers to calculate
all the standard parameters: SINAD, SFDR, SNR, THD, and ENOB.
If you don't have access to ViVA, then you will need to write your
OCEAN function to do the calculation.

                                                        Best Regards,

                                                            Sheldon


Title: Re: Query regarding DFT function in Spectre
Post by shaikh_sarfraz on Sep 4th, 2008, 7:09am

Hi,
Thanks for your inputs.
But the problem is, I donnot have Viva.
I am writing functions in Ocean.

I am getting the staircase output. And from that I am getting the DFT plot (4096 point DFT with rectangular windowing).
Can any body give some hint on how to proceed from here to get the SNR? (I will be using OCEAN)

Best Regards
Sarfraz

Title: Re: Query regarding DFT function in Spectre
Post by pancho_hideboo on Sep 4th, 2008, 11:32pm


shaikh_sarfraz wrote on Sep 3rd, 2008, 11:58pm:
Is the magnitude form (which I am getting from the complex output ) of DFT output is the RMS value or not?

Answer is no. It is peak value.
You should learn fourier series theory.


shaikh_sarfraz wrote on Sep 4th, 2008, 7:09am:
I am getting the staircase output.

Usually we use sinusoidal output for evaluating SINAD, SFDR, SNR, THD, and ENOB.

Staircase output(Ramp Code) is for static DNL and INL evaluation.

You might mean zero order hold output with " staircase output" ?


shaikh_sarfraz wrote on Sep 4th, 2008, 7:09am:
And from that I am getting the DFT plot (4096 point DFT with rectangular windowing).
Can any body give some hint on how to proceed from here to get the SNR? (I will be using OCEAN)

Just do coding with following definition of SNR.

Your question is
  Laguage issue when you write codes using Cadence Ocean ?
or
  Just you don't understand mathematical definitions of SINAD, SFDR, SNR, THD, and ENOB ?

If you can understand mathematical definitions of SINAD, SFDR, SNR, THD, and ENOB, coding tasks are very easy whatever language you use.

For example, I wrote such code using C-language long long ago for actual measurement using logic analyzer(state analyzer).
And long ago I rewrote this C code to Ocean and M-file of MATLAB easily.

If you can access MATLAB, the following might be also useful a little.
http://www.designers-guide.org/Forum/YaBB.pl?num=1213204643



Title: Re: Query regarding DFT function in Spectre
Post by pancho_hideboo on Sep 4th, 2008, 11:52pm

As simple reference, this is only SNR evaluation.
If you apply this to ADC, you have to convert digital code to integer or real number.

============================================

base_dir = getWorkingDir()
;
awvSetOptionValue('dateStamp t)
awvSetOptionValue('displayGrids t)
awvSetOptionValue("cursorPrecision" 9)
awvSetOptionValue("displayAxesBy125" t)
;;;
circuit_dir = "aho_boke_kasu_nasu"
;;;
;sim_data = "schematic"
sim_data = "cnr_15db"
result_dir = strcat(base_dir "/simulation/" circuit_dir "/spectre/" sim_data)
openResults( strcat(result_dir "/psf") )
;
wid = newWindow()
addTitle("SINAD/SNR Test of aho_boke_kasu_nasu")
;
dump_file = "/tmp/aho.dat"
myPort = outfile( dump_file )
;
f0 = 10.7MHz
fin = 1.0kHz
VCrms = 1.0
CNR = 15.0
fmax = 80kHz
;np = 10.0
VNrms = VCrms * 10**(-CNR/20.0)
tstart = 0.5*(1.0/fin)
;tstop = tstart + np*(1.0/fin)
;
pi = acos(-1.0)
;
selectResult('tran)

Vsignal = v("/Vsignal")
Vnoise = v("/Vnoise")
Vin = v("/Vin")
Vin_clipped1 = v("/Vin_clipped1")
Vout = v("/Vout")
Vout1 = v("/Vout1")

time_vec = drGetWaveformXVec( Vin )
tstop = drGetElem( time_vec, drVectorLength(time_vec)-1 )
printf("tstop = %g[msec]\n", tstop/1m)

fnyquist = fmax
finaltime = tstop - tstart
delta_f = 1.0 / finaltime
N = round(2*fnyquist * finaltime)
ip = round(log(N)/log(2))
NN = 2**ip
if( NN < N then NN=2**(ip+1) )
fnyquist = NN / (2.0*finaltime)
printf("N = %d --> N = %d\n", N NN)
;
Vout_freq = dft(Vout tstart tstop N "Rectangular" 1 1)
Vout1_freq = dft(Vout1 tstart tstop N "Rectangular" 1 1)

signal_pwr = 0.5 * mag(value(Vout_freq fin))**2
signal1_pwr = 0.5 * mag(value(Vout1_freq fin))**2

noise_pwr = 0.0
noise1_pwr = 0.0

dist_pwr = 0.0
dist1_pwr = 0.0

ipeak = round(fin/delta_f)
printf("ipeak = %d\n", ipeak)

nmax = round(fmax/delta_f)
if( nmax * delta_f < fmax then ++nmax )
if( nmax > NN/2 then nmax = NN/2)
printf("fmax = %g[kHz]\n", nmax * delta_f / 1k)

for( i 1 ipeak-1
     freq = i * delta_f
     noise_pwr = noise_pwr + 0.5*mag(value(Vout_freq freq))**2
     noise1_pwr = noise1_pwr + 0.5*mag(value(Vout1_freq freq))**2
)
for( i ipeak+1 nmax
     freq = i * delta_f
     noise_pwr = noise_pwr + 0.5*mag(value(Vout_freq freq))**2
     noise1_pwr = noise1_pwr + 0.5*mag(value(Vout1_freq freq))**2
       if( mod(i ipeak) == 0 then
         dist_pwr = dist_pwr + 0.5*mag(value(Vout_freq freq))**2
         dist1_pwr = dist1_pwr + 0.5*mag(value(Vout1_freq freq))**2
     )
)

fprintf(myPort "Signal Voltage = %g [Vrms]\n", sqrt(signal_pwr))
fprintf(myPort "Signal Voltage1 = %g [Vrms]\n", sqrt(signal1_pwr))

fprintf(myPort "\n")
fprintf(myPort "Noise+Distortion Voltage = %g [Vrms]\n", sqrt(noise_pwr))
fprintf(myPort "Noise+Distortion Voltage1 = %g [Vrms]\n", sqrt(noise1_pwr))

fprintf(myPort "\n")
fprintf(myPort "Noise Voltage = %g [Vrms]\n", sqrt(noise_pwr-dist_pwr))
fprintf(myPort "Noise Voltage1 = %g [Vrms]\n", sqrt(noise1_pwr-dist1_pwr))

sinad = signal_pwr / noise_pwr
sinad1 = signal1_pwr / noise1_pwr

thd = dist_pwr / signal_pwr
thd1 = dist1_pwr / signal1_pwr

if( ipeak == 1
then
     snr = 10**(200.0/10.0)
     snr1 = 10**(200.0/10.0)
else
     snr = 1.0 / (1.0 / sinad - thd)
     snr1 = 1.0 / (1.0 / sinad1 - thd1)
)

fprintf(myPort "\n")
fprintf(myPort "SINAD = %2.1f [dB]\n", 10.0*log10(sinad) )
fprintf(myPort "SINAD1 = %2.1f [dB]\n", 10.0*log10(sinad1) )

fprintf(myPort "\n")
fprintf(myPort "SNR = %2.1f [dB]\n", 10.0*log10(snr) )
fprintf(myPort "SNR1 = %2.1f [dB]\n", 10.0*log10(snr1) )

fprintf(myPort "\n")
fprintf(myPort "THD = %g [%%]\n", sqrt(thd)*100.0 )
fprintf(myPort "THD1 = %g [%%]\n", sqrt(thd1)*100.0 )

close( myPort )
edit( sprintf(nil "%s" dump_file) )
;view(dump_file nil "Results of SINAD/SNR")

bid = currentSubwindow(1)
addSubwindowTitle( sprintf(nil "Carrier=%2.1f[Vrms]@%2.1fMHz , CNR=%2.1f[dB]" VCrms f0/1M CNR) )
t1 = tstop-3.0/f0
t2 = tstop
dt = (1.0/f0)/500.0
plot( sample(Vsignal t1 t2 "linear" dt) ?expr '("Vsignal") )
plot( sample(Vnoise t1 t2 "linear" dt) ?expr '("Vnoise") )
plot( sample(Vin t1 t2 "linear" dt) ?expr '("Vin") )
plot( sample(Vin_clipped1 t1 t2 "linear" dt) ?expr '("Vin_clipped1") )
awvSetXAxisLabel(wid "time [sec]"  ?subwindow bid)
awvSetYAxisLabel(wid 1 "Amplitude [volt]" ?subwindow bid)
displayMode("strip")
yLimit( list(-1.5 1.5) ?stripNumber 1 )
yLimit( list(-1.5 1.5) ?stripNumber 2 )
yLimit( list(-1.5 1.5) ?stripNumber 3 )
yLimit( list(-1.5 1.5) ?stripNumber 4 )

addSubwindow()
bid = currentSubwindow(2)
addSubwindowTitle( sprintf(nil "fsignal=%2.1f[kHz]" fin/1k) )
t1 = tstop - 1.0*(1.0/fin)
t2 = tstop
dt = (1.0/fin)/500.0
plot( sample(Vout t1 t2 "linear" dt) ?expr '("Vout") )
plot( sample(Vout1 t1 t2 "linear" dt) ?expr '("Vout1") )
awvSetXAxisLabel(wid "time [sec]"  ?subwindow bid)
awvSetYAxisLabel(wid 1 "Amplitude [volt]" ?subwindow bid)
;plotStyle('joined)
displayMode("strip")
yLimit( list(-1.5 1.5) ?stripNumber 1 )
yLimit( list(-1.5 1.5) ?stripNumber 2 )

addSubwindow()
bid = currentSubwindow(3)
addSubwindowTitle( sprintf(nil "fnyquist=%2.1f[kHz] , delta_f=%2.1f[kHz]" fnyquist/1k delta_f/1k) )
plot( db20(Vout_freq) ?expr '("Vout_freq") )
plot( db20(Vout1_freq) ?expr '("Vout1_freq") )
;plotStyle('joined)
displayMode("strip")
awvSetXAxisLabel(wid "frequency [Hz]"  ?subwindow bid)
awvSetYAxisLabel(wid 1 "Spectrum [dB]" ?subwindow bid)
xLimit( list(0 15k) )
yLimit( list(-70 10) ?stripNumber 1 )
yLimit( list(-70 10) ?strip

Title: Re: Query regarding DFT function in Spectre
Post by shaikh_sarfraz on Sep 14th, 2008, 11:45pm

Hi,
Thanks for your response. It was of great help to me.
Let me know if my understanding is correct:
1).  From the FFT plot we can get
     Signal power (rms) = 0.5*Vsig**2

2). Noise power (rms) = 0.5*Vn1**2 + 0.5*Vn2**2 ......+0.5*Vnn**2

SNR = 10log(Signal(rms) / Noise(rms))


Best Regards
Sarfraz

Title: Re: Query regarding DFT function in Spectre
Post by ywguo on Sep 23rd, 2008, 8:40pm

Hi Sarfraz,

You are correct except that is not rms value, but 2nd power of the rms value.


Yawei

Title: Re: Query regarding DFT function in Spectre
Post by shaikh_sarfraz on Sep 25th, 2008, 7:25am

Ok..that should be 2 nd power of RMS noise.......
Thanks Yawei

The Designer's Guide Community Forum » Powered by YaBB 2.2.2!
YaBB © 2000-2008. All Rights Reserved.