How do digital function generators generate precise frequencies?
That sort of generator uses DDS, or Direct Digital Synthesis
It keeps track of the phase of the required output in a register, and outputs the cosine of the phase.
To use nice round numbers, let's say you have a 10 MHz clock, and want to generate 1.000000 MHz. Each 100 ns clock cycle, your phase register gets incremented by 0.1 of a cycle. If you want to generate 1.000 000 001 MHz, then each clock you'd increment by 0.100 000 000 100 of a cycle.
Frequency resolution is cheap, you just give your phase register enough LSBs. In this case, mHz resolution with a 10 MHz clock, you'd need 10 digits if the sums were done in decimal, or as more likely at least 34 bits if they were done in binary. With binary arithmetic, sometimes the master clock will be a nice 'binary' frequency to get nice Hz resolution. With cheaper generators the designers often just throw another load of LSBs at the phase register, and have very fine resolution of a nasty binary Hz fraction, which is 'fine enough'. My low cost generator has μHz!
Only the top few MSBs, typically 10 to 16 depending on the quality (cost) of the output, get to drive the phase -> cosine converter. As a result, the phase at your output is never more accurate than a few parts per thousand. However, the output phase error is non-cumulative, and over time, the waveform will keep the correct average rate of change of phase (aka frequency) with respect to the clock, and to any other channels being generated by the same clock.
So the frequencies are precise, the phases approximately so. It's this approximation to phase that means that DDS outputs have phase noise spurious outputs. These cannot be seen on an oscilloscope, but will be visible on any modest spectrum analyser.
You can teardown your cheap function generator, I am certain you will find a DDS chip or a FPGA doing the same. However it is possible to increment/decrement frequency in range of milihertz but the precision is relative to XTAL precision. So you are able to get a sinewave of mHz when you subtract two generated frequencies from the same XTAL. If you would have a separate function generator, you would notice difference in frequencies of two sources.
The solution is to have a reference clock as the input of multiple function generators. GPSDO (GPS Disciplined Oscillator) can be used for precise synchronization.
Neil and Marko have already responded in great detail. From my superficial point of view: the generator contains a DAC (or several DAC channels) and performs PCM wave playback. The design tradeoffs are approximately:
- how stable a reference clock you can get
- DAC resolution (bit depth) and sampling rate are factors (and a partial mutual tradeoff)
- computing power - how many cosines (or sines) a second you can calculate, or approximate using a look-up table, down to what amplitude-wise resolution
- how smooth (and adaptive) an analog filter you can build for the DAC output
Obviously money is the overall envelope in all those items.