这是一个没有零填充的卷积示例,用于 DFT(循环卷积)与线性卷积。这是长度 M=32 序列与长度 L=128 序列的卷积(使用 Numpy/Matplotlib):
f = rand(32); g = rand(128)
h1 = convolve(f, g)
h2 = real(ifft(fft(f, 128)*fft(g)))
plot(h1); plot(h2,'r')
grid()
前 M-1 个点是不同的,因为它不是零填充的,所以它短了 M-1 个点。如果您在进行块卷积,这些差异是一个问题,但是使用重叠和保存或重叠和添加等技术来克服这个问题。否则,如果您只是计算一次性过滤操作,则有效结果将从索引 M-1 开始,到索引 L-1 结束,长度为 L-M+1。
至于引用的论文,我在附录 A 中查看了他们的 MATLAB 代码。我认为他们在将 Hfinal 传递函数应用于负频率而不首先对其进行共轭时犯了一个错误。否则,您可以在他们的图表中看到时钟抖动是一个周期性信号,因此使用循环卷积可以很好地进行稳态分析。
编辑:关于共轭传递函数,PLL具有实值脉冲响应,并且每个实值信号都具有共轭对称谱。在代码中,您可以看到他们只是使用 Hfinal[Ni] 来获得负频率而不采用共轭。我绘制了从 -50 MHz 到 50 MHz 的传递函数:
N = 150000 # number of samples. Need >50k to get a good spectrum.
res = 100e6/N # resolution of single freq point
f = res * arange(-N/2, N/2) # set the frequency sweep [-50MHz,50MHz), N points
s = 2j*pi*f # set the xfer function to complex radians
f1 = 22e6 # define 3dB corner frequency for H1
zeta1 = 0.54 # define peaking for H1
f2 = 7e6 # define 3dB corner frequency for H2
zeta2 = 0.54 # define peaking for H2
f3 = 1.0e6 # define 3dB corner frequency for H3
# w1 = natural frequency
w1 = 2*pi*f1/((1 + 2*zeta1**2 + ((1 + 2*zeta1**2)**2 + 1)**0.5)**0.5)
# H1 transfer function
H1 = ((2*zeta1*w1*s + w1**2)/(s**2 + 2*zeta1*w1*s + w1**2))
# w2 = natural frequency
w2 = 2*pi*f2/((1 + 2*zeta2**2 + ((1 + 2*zeta2**2)**2 + 1)**0.5)**0.5)
# H2 transfer function
H2 = ((2*zeta2*w2*s + w2**2)/(s**2 + 2*zeta2*w2*s + w2**2))
w3 = 2*pi*f3 # w3 = 3dB point for a single pole high pass function.
H3 = s/(s+w3) # the H3 xfer function is a high pass
Ht = 2*(H1-H2)*H3 # Final transfer based on the difference functions
subplot(311); plot(f, abs(Ht)); ylabel("abs")
subplot(312); plot(f, real(Ht)); ylabel("real")
subplot(313); plot(f, imag(Ht)); ylabel("imag")

如您所见,实部具有偶数对称性,而虚部具有奇数对称性。在他们的代码中,他们只计算了对数图的正频率(足够合理)。然而,为了计算逆变换,他们通过索引 Hfinal[Ni] 使用负频率的正频率值,但忘记将其共轭。