In response to Calcul of SNR in CADENCEWatch Full Movie Online Streaming Online and Download
I generally don’t like Cadence’s FFT command as it only computes a radix2 FFT. This is great if your sampling frequency happens to be a power of two of your input frequency. Most of the time, this is the case (or close enough to be immaterial). That’s not the case with me.
I’ll save how I get a nonradix2 FFT into Cadence for later (I use Matlab). However, here’s how I compute SNR/SNDR when I have an FFT already provided:
 I run the simulation for a time period of (kcyc+ncyc)/fS. fS is the sampling frequency. kcyc is the number of cycles to leave for startup transients.
 I do an FFT over the last ncyc samples. So, even though I run the ADC for (kcyc+ncyc)/fS, I exclude the first kcyc samples. I generally use a minimum 4term BlackmanHarris window. In simulation, if you ahve the ability to pick your sample frequenciy and input frequency, you don’t need to window; your FFT frequencies will be righton with the FFT bins. I window anyway.
 I sum up +/ 5 FFT bins around the nominal input frequency. This is because I use the BH4 window, which extends the main lobe of the signal out. I’ve found that +/ 5 bins definitely catches the signal. Any additional noise it catches if usually immaterial.
 For an SNR (versus an SNDR) measurement, I subtract out any distortion. I define distortion as any oddorder harmonics of the signal (odd multiples of the input frequency) that fall within the bandwidth of interest.
 After summing up signal power, noise power, and noise+distortion power, I comute the ratios to get SNR or SNDR.
Anyway. Here’s the code to do it. Once again, I relase it under the GNU Public License to encourage others to contribute back their improvements:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

; Compute SNR based on an FFT of the output
; Copyright (c) 2008 Poojan Wagh (poojanwagh {at} circuitdesign [dot] info)
; http://www.circuitdesign.info
;
; This program is free software: you can redistribute it and/or modify
; it under the terms of the GNU General Public License as published by
; the Free Software Foundation, either version 3 of the License, or
; (at your option) any later version.
;
; This program is distributed in the hope that it will be useful,
; but WITHOUT ANY WARRANTY; without even the implied warranty of
; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
; GNU General Public License for more details.
;
; You should have received a copy of the GNU General Public License
; along with this program. If not, see <http://www.gnu.org/licenses/>.

1
2
3
4
5
6

ncyc = 1024; % number of points for fft
kcyc = 512; % number of points for startup (excluded for fft)
simtime = (ncyc+kcyc)/fS % total simulation time
fbin = fS/ncyc; % FFT bin width (Hz)
fin = 13*fbin; % Input frequency (arbitrary)
bw = round(2E6/fbin)*fbin; % bandwidth (rounded to FFT bin)

1
2
3
4
5
6
7

procedure( sumpsd( psd fstart fend)
if(fstart < fend then
integ( clip(psd fstart fend) )
else
0.0
)
)

1
2
3
4
5
6

; get power of signal centered at fc
procedure( getpow( psd fc fbin )
let( list( (speclobew 5) )
sumpsd(psd fc–speclobew*fbin fc+speclobew*fbin)
)
)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31

; compute PSD of output (abs(FFT)^2)
; I‘m currently using Matlab to do this (procedure matpsd)
; However, Cadence/Ocean’s fft() function will do equally well:
psdoutput = matpsd( dumpfile fS ncs ncyc )
; PSig = sumpsd(psdoutput fin–5*fbin fin+5*fbin) ; Signal Power
PSig = getpow(psdoutput fin fbin) ; Signal Power
PND = sumpsd(psdoutput 0 min(bw fin–6*fbin)) + sumpsd(psdoutput fin+6*fbin bw) ; Noise Power
PN = PND;
exbw = 0;
; for SNR measurement, exclude odd–mode distortion
; from 3*fin to bw
for( k 1 floor(bw/2/fin)
fex1 = (2*k+1)*fin–5*fbin
fex2 = min(bw (2*k+1)*fin+5*fbin)
psdex = sumpsd(psdoutput fex1 fex2);
; printf(“k = %u Excluding distortion from %f kHz to %f kHz (%g – %g)\n” 2*k+1 fex1 fex2 PN psdex)
PN = PN – psdex;
exbw = exbw + (fex2–fex1);
; printf(“Excluding distortion from %f kHz to %f kHz (%f kHz)\n” fex1/1.0k fex2/1.0k (fex2–fex1)/1.0k);
)
PN = PN / (1 – exbw/bw) ;compensate for frequencies we have excluded
;(assuming white noise)
SNDR = PSig/PND;
SNR = PSig/PN;
SNDRdB = db10(SNDR);
SNRdB = db10(SNR);
printf(“SNDR [%s/%s/%s]= %.2f dB\n” library cell view SNDRdB);
printf(“SNR [%s/%s/%s]= %.2f dB\n” library cell view SNRdB);
sprintf(wintitle “PSD of Digitized PWM [%s/%s/%s] SNDR = %.0f dB NSR = %.0f dB” library cell view SNDRdB SNRdB)
plot(db10(clip(psdoutput, fin–5*fbin, fin+5*fbin)) db10(psdoutput) ?expr list(“Desired Signal” wintitle))
xLimit(list(0 bw))

One Comment
Fatal error: Uncaught Error: Call to undefined function ereg() in /home/wagh/webapps/circuitdesign/wpcontent/themes/thematic/library/extensions/commentsextensions.php:262 Stack trace: #0 /home/wagh/webapps/circuitdesign/wpcontent/themes/thematic/library/extensions/discussion.php(30): thematic_commenter_link() #1 /home/wagh/webapps/circuitdesign/wpincludes/classwalkercomment.php(179): thematic_comments(Object(WP_Comment), Array, 1) #2 /home/wagh/webapps/circuitdesign/wpincludes/classwpwalker.php(144): Walker_Comment>start_el('', Object(WP_Comment), 1, Array) #3 /home/wagh/webapps/circuitdesign/wpincludes/classwalkercomment.php(139): Walker>display_element(Object(WP_Comment), Array, '5', 0, Array, '') #4 /home/wagh/webapps/circuitdesign/wpincludes/classwpwalker.php(387): Walker_Comment>display_element(Object(WP_Comment), Array, '5', 0, Array, '') #5 /home/wagh/webapps/circuitdesign/wpincludes/commenttemplate.php(2177): Walker>paged_walk(Array, '5', 0, 0, Array) #6 /home/wagh/webapps/circuitdesign/wpcon in /home/wagh/webapps/circuitdesign/wpcontent/themes/thematic/library/extensions/commentsextensions.php on line 262