Skip to content

Commit

Permalink
lib: rfnoc ddc/duc: Fix fractional frequency offset
Browse files Browse the repository at this point in the history
The RFNoC DDC/DUC block controllers had a bug, in which they would only
program the upper 24 bits of the 32-bit phase increment value for the
digital frequency shifter.

The DDC/DUC use a 24-bit DDS + multiplier to shift frequency digitally,
but the phase increment input to the DDS is a 32-bit value, which we
were (incorrectly) quantizing to a 24-bit value. This meant we were
artificially limiting the digital frequency accuracy, e.g., for a 200
MHz sample clock, to 200MHz / 2^{24} == (approx.) 12 Hz, which in turn
meant there was an unnecessary frequency error of up to 6 Hz (for lower
clock rates, the error would be smaller but still unnecessarily high).

This patch fixes the width of the phase increment value and allows for
sub-Hz accuracy (once again).

This bug was introduced in 699870d (first released with UHD 4.2).
  • Loading branch information
mbr0wn authored and joergho committed Nov 12, 2024
1 parent 601503e commit 635ad36
Show file tree
Hide file tree
Showing 2 changed files with 2 additions and 10 deletions.
6 changes: 1 addition & 5 deletions host/lib/rfnoc/ddc_block_control.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -653,14 +653,10 @@ class ddc_block_control_impl : public ddc_block_control
double _set_freq(
const double requested_freq, const double dds_rate, const size_t chan)
{
static int freq_word_width = 24;
double actual_freq;
int32_t freq_word;
std::tie(actual_freq, freq_word) =
get_freq_and_freq_word(requested_freq, dds_rate, freq_word_width);

// Only the upper 24 bits of the SR_FREQ_ADDR register are used, so shift the word
freq_word <<= (32 - freq_word_width);
get_freq_and_freq_word(requested_freq, dds_rate);

_ddc_reg_iface.poke32(
SR_FREQ_ADDR, uint32_t(freq_word), chan, get_command_time(chan));
Expand Down
6 changes: 1 addition & 5 deletions host/lib/rfnoc/duc_block_control.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -645,14 +645,10 @@ class duc_block_control_impl : public duc_block_control
double _set_freq(
const double requested_freq, const double dds_rate, const size_t chan)
{
static int freq_word_width = 24;
double actual_freq;
int32_t freq_word;
std::tie(actual_freq, freq_word) =
get_freq_and_freq_word(requested_freq, dds_rate, freq_word_width);

// Only the upper 24 bits of the SR_FREQ_ADDR register are used, so shift the word
freq_word <<= (32 - freq_word_width);
get_freq_and_freq_word(requested_freq, dds_rate);

_duc_reg_iface.poke32(
SR_FREQ_ADDR, uint32_t(freq_word), chan, get_command_time(chan));
Expand Down

0 comments on commit 635ad36

Please sign in to comment.