aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormichael-west <michael.west@ettus.com>2021-12-09 16:22:28 -0800
committerAaron Rossetto <aaron.rossetto@ni.com>2022-01-10 16:19:11 -0600
commit699870d7dec67b43c08e55fcc1d4e159a337c49a (patch)
tree4bb85f94157425a4f32d028ec8cdd8d5eaa36a8f
parent5d80e28752d2b6f202480ce591f142f5e6f90139 (diff)
downloaduhd-699870d7dec67b43c08e55fcc1d4e159a337c49a.tar.gz
uhd-699870d7dec67b43c08e55fcc1d4e159a337c49a.tar.bz2
uhd-699870d7dec67b43c08e55fcc1d4e159a337c49a.zip
RFNoC: Fix DSP frequency accuracy
The host code was calculating and programming a 32-bit value for the DSP frequency, but the DDS modules in the FPGA only use the upper 24-bits. This led to inaccurate frequency values being returned. This change corrects the resolution of the value on the host side so an accurate value is returned. Signed-off-by: michael-west <michael.west@ettus.com>
-rw-r--r--host/lib/include/uhdlib/usrp/cores/dsp_core_utils.hpp15
-rw-r--r--host/lib/rfnoc/ddc_block_control.cpp7
-rw-r--r--host/lib/rfnoc/duc_block_control.cpp7
-rw-r--r--host/lib/usrp/cores/dsp_core_utils.cpp9
4 files changed, 26 insertions, 12 deletions
diff --git a/host/lib/include/uhdlib/usrp/cores/dsp_core_utils.hpp b/host/lib/include/uhdlib/usrp/cores/dsp_core_utils.hpp
index 74b4c3848..6371eb2e5 100644
--- a/host/lib/include/uhdlib/usrp/cores/dsp_core_utils.hpp
+++ b/host/lib/include/uhdlib/usrp/cores/dsp_core_utils.hpp
@@ -9,16 +9,19 @@
#include <tuple>
-/*! For a requested frequency and sampling rate, return the
- * correct frequency word (to set the CORDIC) and the actual frequency.
+/*! For a requested frequency, sampling rate, and frequency word width (in
+ * number of bits), return the correct frequency word (to set the CORDIC or
+ * DDS) and the actual frequency.
*/
void get_freq_and_freq_word(const double requested_freq,
const double tick_rate,
double& actual_freq,
- int32_t& freq_word);
+ int32_t& freq_word,
+ int word_width = 32);
-/*! For a requested frequency and sampling rate, return the
- * correct frequency word (to set the CORDIC) and the actual frequency.
+/*! For a requested frequency, sampling rate, and frequency word width (in
+ * number of bits), return the correct frequency word (to set the CORDIC or
+ * DDS) and the actual frequency.
*/
std::tuple<double, int> get_freq_and_freq_word(
- const double requested_freq, const double tick_rate);
+ const double requested_freq, const double tick_rate, int word_width = 32);
diff --git a/host/lib/rfnoc/ddc_block_control.cpp b/host/lib/rfnoc/ddc_block_control.cpp
index df606f11b..12e89961d 100644
--- a/host/lib/rfnoc/ddc_block_control.cpp
+++ b/host/lib/rfnoc/ddc_block_control.cpp
@@ -541,10 +541,15 @@ private:
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);
+ 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);
+
_ddc_reg_iface.poke32(
SR_FREQ_ADDR, uint32_t(freq_word), chan, get_command_time(chan));
return actual_freq;
diff --git a/host/lib/rfnoc/duc_block_control.cpp b/host/lib/rfnoc/duc_block_control.cpp
index ac9629ec4..487e4b8ff 100644
--- a/host/lib/rfnoc/duc_block_control.cpp
+++ b/host/lib/rfnoc/duc_block_control.cpp
@@ -525,10 +525,15 @@ private:
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);
+ 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);
+
_duc_reg_iface.poke32(
SR_FREQ_ADDR, uint32_t(freq_word), chan, get_command_time(chan));
return actual_freq;
diff --git a/host/lib/usrp/cores/dsp_core_utils.cpp b/host/lib/usrp/cores/dsp_core_utils.cpp
index 868e47234..5575d9775 100644
--- a/host/lib/usrp/cores/dsp_core_utils.cpp
+++ b/host/lib/usrp/cores/dsp_core_utils.cpp
@@ -17,7 +17,8 @@ static const int32_t MIN_FREQ_WORD = std::numeric_limits<int32_t>::min();
void get_freq_and_freq_word(const double requested_freq,
const double tick_rate,
double& actual_freq,
- int32_t& freq_word)
+ int32_t& freq_word,
+ int word_width)
{
const double freq = uhd::math::wrap_frequency(requested_freq, tick_rate);
@@ -33,7 +34,7 @@ void get_freq_and_freq_word(const double requested_freq,
*/
freq_word = 0;
- static const double scale_factor = std::pow(2.0, 32);
+ static const double scale_factor = std::pow(2.0, word_width);
if ((freq / tick_rate) >= (MAX_FREQ_WORD / scale_factor)) {
/* Operation would have caused a positive overflow of int32. */
freq_word = MAX_FREQ_WORD;
@@ -51,10 +52,10 @@ void get_freq_and_freq_word(const double requested_freq,
}
std::tuple<double, int> get_freq_and_freq_word(
- const double requested_freq, const double tick_rate)
+ const double requested_freq, const double tick_rate, int word_width)
{
double actual_freq;
int32_t freq_word;
- get_freq_and_freq_word(requested_freq, tick_rate, actual_freq, freq_word);
+ get_freq_and_freq_word(requested_freq, tick_rate, actual_freq, freq_word, word_width);
return std::make_tuple(actual_freq, freq_word);
}