def plot_lf_ideal_pn(pn_dco, pn_dco_df, fclk, _type, m, n, k, fz, fp, delay, mode="tdc", sigma_ph=0.1, steps=100, fmin=1e1, fmax=1e7, *args, **kwargs): df = fmax/steps freqs = np.geomspace(fmin, fmax, int(steps)) # a = pll_otf2(freqs, M, N, KDCO, KP, FZ, FP, DELAY) g = pll_tf_(freqs, _type, k, fz, fp, delay) # g = a/(1+a) kpn = pn_dco*pn_dco_df**2 ndco = np.abs(1-g)**2*kpn/freqs**2 ndco[np.where(g==1)] = 0 # ndco = min_ro_pn(fclk*n, freqs, pn_dco, pn_dco_df)*np.abs(1-g)**2 if mode is "tdc": ntdc = tdc_pn(fclk, n, m, g) if mode is "bbpd": ntdc = bbpd_pn(fclk, n, sigma_ph, g) # ntdc = tdc_pn(fclk, n, m, g) # ntdc = tdc_pn(fclk, n, g, 1/float(m*fclk)) plt.semilogx(freqs, 10*np.log10(ntdc), label="Detector - ideal") plt.semilogx(freqs, 10*np.log10(ndco), label="DCO - ideal") plt.semilogx(freqs, 10*np.log10(ndco+ntdc), label="Total - ideal",color="C6") plt.legend() plt.grid() plt.title("SSB Phase noise") plt.xlabel("Frequency [Hz]") plt.ylabel("Phase noise [dBc]")
def plot_lf_ideal_pn_full(div_jit, pn_dco, pn_dco_df, kdco, fclk, _type, m, n, k, fz, fp, delay, b1, b2, steps=100, fmin=1e1, fmax=1e7, *args, **kwargs): df = fmax/steps freqs = np.geomspace(fmin, fmax, int(steps)) lf_params = dict(_type=_type, k=k, fz=fz, fp=fp, delay=delay) # a = pll_otf2(freqs, M, N, KDCO, KP, FZ, FP, DELAY) g = pll_tf(freqs, _type, k, fz, fp, delay) # g = a/(1+a) kpn = pn_dco*pn_dco_df**2 ndco = np.abs(1-g)**2*kpn/freqs**2 ndco[np.where(g==1)] = 0 # ndco = min_ro_pn(fclk*n, freqs, pn_dco, pn_dco_df)*np.abs(1-g)**2 ntdc = tdc_pn(fclk, n, m, g) # ntdc = tdc_pn(fclk, n, g, 1/float(m*fclk)) nlf = lf_pn(freqs, fclk, lf_params, kdco, b1, b2) ndiv = div_pn(fclk, n, div_jit, g) plt.semilogx(freqs, 10*np.log10(ntdc), label="TDC") plt.semilogx(freqs, 10*np.log10(ndco), label="DCO") plt.semilogx(freqs, 10*np.log10(nlf), label="Loop filter") plt.semilogx(freqs, 10*np.log10(ndiv), label="Divider") plt.semilogx(freqs, 10*np.log10(ndco+ntdc+nlf+ndiv), label="Total") plt.legend() plt.grid() plt.title("SSB Phase noise") plt.xlabel("Frequency [Hz]") plt.ylabel("Phase noise [dBc]")
def pll_pn_power_est(tf, tf_params, pn_dco, pn_dco_df, m, n, kdco, fclk, fmax, mode="tdc", sigma_ph=0.1, points=1025, plot=False): """ points must be 2**k+1 for some integer k for Romberg integration """ kpn = pn_dco * pn_dco_df**2 freqs = np.linspace(0, fmax - fmax / points, points) fbin = fmax / points g = tf(freqs, **tf_params) ndco = np.abs(1 - g)**2 * kpn / freqs**2 ndco[np.where(g == 1)] = 0 # ntdc = tdc_pn(fclk, n, g, 1/float(m*fclk)) # ntdc = tdc_pn(fclk, n, m, g) if mode is "tdc": ntdc = tdc_pn(fclk, n, m, g) elif mode is "bbpd": ntdc = bbpd_pn(fclk, n, sigma_ph, g) if plot: plt.semilogx(freqs[1:], 10 * np.log10(ndco[1:] + ntdc[1:])) plt.show() # print("^^^^^^^^^^^ %f"%(2*scipy.integrate.romb(ndco+ntdc, dx=fbin))) # print(sigma_ph, mode) return 2 * scipy.integrate.romb(ndco + ntdc, dx=fbin)
def plot_loop_filter(pn_dco, pn_dco_df, fclk, _type, m, n, k, ki, fz, fp, delay, bw, a0, a1, b0, b1, b2, mode="tdc", sigma_ph=0.1, steps=100, fmax=1e7, *args, **kwargs): freqs = np.geomspace(1, fmax, int(steps)) # a = pll_otf2(freqs, M, N, KDCO, KP, FZ, FP, DELAY) g = pll_tf(freqs, _type, k, fz, fp, delay) # g = a/(1+a) kpn = pn_dco*pn_dco_df**2 plt.subplot(1,3,1) # plt.semilogx(freqs, 20*np.log10(np.abs(solpf(freqs, fn, damping))), label="Ideal") plt.semilogx(freqs, 20*np.log10(np.abs(g)), label="G(f)") plt.semilogx(freqs, 20*np.log10(np.abs(1-g)), label="1-G(f)") plt.legend() plt.grid() plt.title("Closed loop responses") plt.xlabel("Frequency [Hz]") plt.ylabel("Gain [dB]") plt.subplot(1,3,2) # ndco = min_ro_pn(fclk*n, freqs, pn_dco, pn_dco_df)*np.abs(1-g)**2 ndco = np.abs(1-g)**2*kpn/freqs**2 ndco[np.where(g==1)] = 0 # ntdc = tdc_pn(fclk, n, g, 1/float(m*fclk)) if mode is "tdc": ntdc = tdc_pn(fclk, n, m, g) if mode is "bbpd": ntdc = bbpd_pn(fclk, n, sigma_ph, g) plt.semilogx(freqs, 10*np.log10(ntdc), label="TDC") plt.semilogx(freqs, 10*np.log10(ndco), label="DCO") plt.semilogx(freqs, 10*np.log10(ndco+ntdc), label="Combined") plt.legend() plt.grid() plt.title("SSB Phase noise") plt.xlabel("Frequency [Hz]") plt.ylabel("Phase noise [dBc]") plt.subplot(1,3,3) w, h = scipy.signal.freqz([a0, a1], [b0, b1, b2], fs=fclk) _h = lf(w[1:], _type, ki, fz, fp) plt.title("Ideal versus discrete loop filter") plt.xlabel("Frequency [Hz]") plt.ylabel("Gain [dB]") plt.semilogx(w[1:], 20*np.log10(np.abs(h[1:])), label="Discrete") plt.semilogx(w[1:], 20*np.log10(np.abs(_h)), label="Ideal") plt.grid() plt.legend()
def plot_tdc_pn(pn_dco, pn_dco_df, fclk, _type, m, n, k, ki, fz, fp, delay, bw, a0, a1, b0, b1, b2, steps=100, fmax=1e7, label="", *args, **kwargs): freqs = np.geomspace(1, fmax, int(steps)) # a = pll_otf2(freqs, M, N, KDCO, KP, FZ, FP, DELAY) g = pll_tf(freqs, _type, k, fz, fp, delay) # g = a/(1+a) ntdc = tdc_pn(fclk, n, m, g) # ntdc = tdc_pn(fclk, n, g, 1/float(m*fclk)) plt.semilogx(freqs, 10*np.log10(ntdc), label="TDC %s"%label) plt.legend() plt.grid() plt.title("SSB Phase noise") plt.xlabel("Frequency [Hz]") plt.ylabel("Phase noise [dBc]")
def pll_pn_power_est2(tf, tf_params, pn_dco, pn_dco_df, m, n, kdco, fclk, fmax, points=1025): freqs = np.linspace(0, fmax - fmax / points, points) fbin = fmax / points g = tf(freqs, **tf_params) ndco = min_ro_pn(fclk * n, freqs, pn_dco, pn_dco_df) * np.abs(1 - g)**2 ndco[np.where(g == 1)] = 0 # ntdc = tdc_pn(fclk, n, g, 1/float(m*fclk)) ntdc = tdc_pn(fclk, n, m, g) return np.sum(2 * (ndco + ntdc)) * fbin
def plot_total_pn(pn_dco, pn_dco_df, fclk, _type, m, n, k, ki, fz, fp, delay, bw, a0, a1, b0, b1, b2, steps=100, fmax=1e7, label="", *args, **kwargs): freqs = np.geomspace(1, fmax, int(steps)) # a = pll_otf2(freqs, M, N, KDCO, KP, FZ, FP, DELAY) g = pll_tf(freqs, _type, k, fz, fp, delay) # g = a/(1+a) kpn = pn_dco*pn_dco_df**2 # ndco = min_ro_pn(fclk*n, freqs, pn_dco, pn_dco_df)*np.abs(1-g)**2 ndco = np.abs(1-g)**2*kpn/freqs**2 ndco[np.where(g==1)] = 0 ntdc = tdc_pn(fclk, n, m, g) # ntdc = tdc_pn(fclk, n, g, 1/float(m*fclk)) plt.semilogx(freqs, 10*np.log10(ndco+ntdc), label="Total %s"%label) plt.legend() plt.grid() plt.title("SSB Phase noise") plt.xlabel("Frequency [Hz]") plt.ylabel("Phase noise [dBc]")