Skip to content

Frequency Synthesis

The Si5351 fractional-N frequency synthesizer is the RF heart of the NanoVNA-H. It generates three simultaneous outputs: the RF stimulus signal and two Local Oscillator (LO) signals for the mixers. Understanding its operation helps explain the NanoVNA’s frequency coverage and limitations.

flowchart LR
  subgraph PLL_A[PLL A]
      VCO_A[VCO<br/>600-900 MHz]
  end

  subgraph PLL_B[PLL B]
      VCO_B[VCO<br/>600-900 MHz]
  end

  XTAL[26 MHz<br/>TCXO] --> PLL_A
  XTAL --> PLL_B

  VCO_A --> DIV0[MultiSynth 0<br/>CLK0: RF Out]
  VCO_A --> DIV1[MultiSynth 1<br/>CLK1: LO CH0]
  VCO_B --> DIV2[MultiSynth 2<br/>CLK2: LO CH1]
Frequency Coverage: 600 Hz – 2 GHz
Ultra-Low
Low
Direct
3rd Harmonic
5th Harmonic
7th Harmonic
1 kHz
100 kHz
1 MHz
10 MHz
100 MHz
290 MHz
1 GHz
2 GHz
Signal Generation Method
Direct (fundamental)
3rd harmonic
5th harmonic
7th harmonic
Dynamic Range
Direct: >70 dB
3rd Harmonic: ~50 dB
5th Harmonic: ~40 dB
7th Harmonic: ~30 dB
Harmonic threshold: ~290 MHz (SA612A) or ~300 MHz (ZeeTK NE602A)

Key specifications from si5351.c:

#define XTALFREQ 26000000U // 26 MHz reference crystal
#define PLL_N 32 // Default PLL multiplier
#define PLLFREQ (XTALFREQ * PLL_N) // 832 MHz nominal VCO

The Si5351 contains two PLLs (A and B), each with a VCO that runs at 600-900 MHz. The output frequency is:

f_out = f_xtal * (PLL_multiplier) / (MultiSynth_divider)

Where:

  • f_xtal = 26 MHz
  • PLL_multiplier = 15 to 90 (fractional)
  • MultiSynth_divider = 4 to 2048 (fractional)

The firmware uses fractional dividers to achieve fine frequency resolution:

// MultiSynth divider components
typedef struct {
uint8_t reg_addr; // Starting register address
uint32_t div; // Integer part
uint32_t num; // Numerator of fraction
uint32_t denom; // Denominator (typically 0xFFFFF for finest resolution)
} si5351_config_t;

With a 20-bit fraction (denominator = 0xFFFFF = 1,048,575), the frequency resolution is:

Resolution = f_xtal / (PLL_mult * denom) = 26e6 / (32 * 1e6) ≈ 0.8 Hz

The Si5351 has three outputs configured for different purposes:

OutputFunctionTypical Frequency
CLK0RF stimulus to DUTSweep frequency
CLK1LO for CH0 mixer (reflection)Sweep frequency + IF offset
CLK2LO for CH1 mixer (transmission)Sweep frequency + IF offset

The IF offset (typically 12 kHz) creates the intermediate frequency that the audio codec can digitize:

#define FREQUENCY_OFFSET (FREQUENCY_IF_K * 1000) // 12000 Hz
// LO frequency = RF frequency + IF offset
void si5351_set_frequency(uint32_t freq) {
si5351_set_frequency_with_offset(freq, 0, FREQUENCY_OFFSET);
}

The Si5351 cannot directly generate all frequencies from 50 kHz to 300 MHz. The firmware divides the range into bands based on VCO and divider constraints:

// Band definitions (simplified from si5351.c)
static const uint32_t band_boundaries[] = {
100000, // Band 0: Very low frequencies
500000, // Band 1: LF
5000000, // Band 2: HF low
50000000, // Band 3: HF high
140000000, // Band 4: VHF
300000000, // Band 5: Upper VHF (direct)
// Above 300 MHz: harmonic mode
};

When changing bands, the PLL may need to be reset, which takes time:

#define DELAY_BAND_1_2 US2ST(100) // Same band: 100 us
#define DELAY_BAND_3_4 US2ST(300) // Adjacent band: 300 us
#define DELAY_BANDCHANGE US2ST(5000) // Major band change: 5 ms
#define DELAY_RESET_PLL_AFTER 4000 // After PLL reset: 4 ms

The firmware optimizes VCO frequency selection to:

  1. Keep VCO in its optimal range (600-900 MHz)
  2. Minimize spurious outputs
  3. Reduce phase noise
// Calculate optimal PLL frequency for desired output
static void si5351_set_frequency_with_offset(uint32_t freq, uint32_t offset, uint32_t if_freq) {
uint32_t pllfreq;
uint32_t multi_synth_div;
// Choose PLL multiplier to keep VCO in range
if (freq < 8000000) {
multi_synth_div = 900000000 / freq; // Use high VCO for low freq
pllfreq = freq * multi_synth_div;
} else {
multi_synth_div = ... ; // Complex selection logic
pllfreq = ... ;
}
// Configure PLL and output divider
si5351_setupPLL(SI5351_REG_PLL_A, XTALFREQ, pllfreq);
si5351_setupMultisynth(SI5351_REG_MSNA_BASE, pllfreq, freq, ...);
}

Output drive strength affects signal level and harmonic content:

#define SI5351_CLK_DRIVE_STRENGTH_2MA 0x00
#define SI5351_CLK_DRIVE_STRENGTH_4MA 0x01
#define SI5351_CLK_DRIVE_STRENGTH_6MA 0x02
#define SI5351_CLK_DRIVE_STRENGTH_8MA 0x03

The firmware typically uses 8 mA drive for maximum signal level:

void set_power(uint8_t value) {
si5351_set_power(value); // 0-3 maps to 2-8 mA
}

For accurate phase measurements, the RF and LO signals must maintain a stable phase relationship. The Si5351 achieves this by:

  1. Common reference: Both PLLs use the same 26 MHz TCXO
  2. Simultaneous update: All outputs are updated together
  3. PLL reset synchronization: Resets are coordinated across outputs
void si5351_reset_pll(void) {
// Reset both PLLs simultaneously
uint8_t reset = SI5351_PLL_RESET_A | SI5351_PLL_RESET_B;
si5351_write_reg(SI5351_REG_PLL_RESET, reset);
}

Below ~50 kHz, the Si5351’s minimum output divider (4) cannot achieve the required division ratio. The firmware uses special techniques:

Standard Si5351 reaches down to ~8 kHz with maximum division ratios.

#ifdef __ZEETK__
#define FREQUENCY_MIN 600 // 600 Hz with SJWCH5351
#else
#define FREQUENCY_MIN 1600 // 1.6 kHz with Si5351
#endif

The Si5351 is configured via I2C registers. Key operations:

static void si5351_setupPLL(uint8_t pllSource, uint32_t ref_freq, uint32_t pll_freq) {
// Calculate feedback divider
uint32_t P1 = 128 * pll_mult - 512;
uint32_t P2 = 128 * pll_frac_num / pll_frac_denom;
uint32_t P3 = pll_frac_denom;
// Write to PLL registers
si5351_write_reg(pllSource + 0, (P3 >> 8) & 0xFF);
si5351_write_reg(pllSource + 1, P3 & 0xFF);
si5351_write_reg(pllSource + 2, (P1 >> 16) & 0x03);
// ... remaining registers
}
static void si5351_setupMultisynth(uint8_t output, uint32_t pll_freq,
uint32_t out_freq, uint8_t r_div) {
// Calculate output divider
uint32_t divider = pll_freq / out_freq;
uint32_t P1 = 128 * divider - 512;
// ... configure multisynth registers
}
ParameterValueNotes
Reference26 MHz TCXODetermines absolute accuracy
VCO range600-900 MHzSweet spot for low phase noise
Direct output600 Hz - 200+ MHzLimited by Si5351 architecture
Frequency resolution< 1 Hz20-bit fractional dividers
Settling time0.1 - 5 msDepends on frequency change
Output level~ -10 dBmAt 8 mA drive strength

Learn how the NanoVNA extends frequency coverage above 300 MHz in Harmonic Mixing.