[USRP-users] CBX-120: Integer-N PLL Tuning accuracy

Merlin Chlosta merlin.chlosta+gnuradio at ruhr-uni-bochum.de
Wed Mar 2 01:41:09 EST 2016


Hi all,

I attempted to operate the X300/CBX-120 in direct-conversion mode to avoid DSP tuning.

Tune Request:
> uhd::tune_request_t tune_req = uhd::tune_request_t(d_freqs[freq_index]);
> tune_req.dsp_freq_policy = uhd::tune_request_t::POLICY_MANUAL;
> tune_req.rf_freq_policy = uhd::tune_request_t::POLICY_MANUAL;
> tune_req.rf_freq = d_freqs[freq_index];
> tune_req.dsp_freq = 0;
> tune_req.target_freq = d_freqs[freq_index];
> tune_req.args = uhd::device_addr_t("mode_n=integer")

My assumption was that every center frequency
tune_req.rf_freq = master_clock_rate * N/R with 1<=R<=1023 and 16<=N<=65535
is possible. (R, N from MAX2870 PLL data sheet. Simplified without the other divisors. tune_req.rf_freq == vco_freq). But if you tune the CBX-120 to some frequencies the MAX2870 PLL should be able to generate, the loop to find R will exit before an exact match was found.

Find R, N (shortened, see link for full code):

> for(R = int(ref_freq*(1+D)/(target_pfd_freq*(1+T))); R <= r_range.stop(); R++)
> {
>     pfd_freq = ref_freq*(1+D)/(R*(1+T));
>     //keep the PFD frequency at or below target
>     if (pfd_freq > target_pfd_freq)
>         continue;
>
>     N = int((vco_freq/pfd_freq)/fb_divisor);
>     BS = std::ceil(pfd_freq / BS_FREQ);
>         if(BS <= MAX_BS_VALUE) break;
> }
https://github.com/EttusResearch/uhd/blob/master/host/lib/usrp/common/max287x.hpp#L465

Example: To set vco_freq = 3.075e9 with ref_freq=120e6, we'd need R=32, N=801.
target_pfd_freq = 25e6 in db_cbx.cpp.
D=0; T=0;
This is what the loop does:

First iteration:
R=int(ref_freq/target_pfd_freq)=4
pfd_freq=ref_freq/R=30e6
→ pdf_freq > target_pfd_freq = true
→ continue loop

Second iteration:
R=5
pfd_freq=ref_freq/R=24e6
→ pfd_freq > target_pfd_freq = false
→ found R=5

N=int(vco_freq/pdf_freq)=int(128.125)=128

BS-condition is fulfilled, break loop, we're finished.

R=5, N=128
However this is not the frequency we wanted to tune to, 3.075e9 vs. 3.072e9

To tune to the exact frequency if possible, the driver could check if a exact R, N combination exists.
> for(R = r_range.start(); R <= r_range.stop(); R++) {
>     if (ref_freq % R == 0) {
>         if (vco_freq % (ref_freq/R) == 0) {
>             // R found
>         }
>     }
> }

Is there a reason why this is not done at the moment?

--Merlin Chlosta




More information about the USRP-users mailing list