diff options
author | djepson1 <daniel.jepson@ni.com> | 2018-01-18 10:40:43 -0600 |
---|---|---|
committer | Ashish Chaudhari <ashish.chaudhari@ettus.com> | 2018-03-07 12:40:28 -0800 |
commit | 7d0aec18905802ddc466e69055520e8c42cf23c8 (patch) | |
tree | fd4fb27263f06550d5697e75fd1f6a87aeaf9bb9 /mpm/python/usrp_mpm/dboard_manager | |
parent | f9a8098cae1575a34747af2e212248d3bb189783 (diff) | |
download | uhd-7d0aec18905802ddc466e69055520e8c42cf23c8.tar.gz uhd-7d0aec18905802ddc466e69055520e8c42cf23c8.tar.bz2 uhd-7d0aec18905802ddc466e69055520e8c42cf23c8.zip |
tdc: support for tdc 2.0
Diffstat (limited to 'mpm/python/usrp_mpm/dboard_manager')
-rw-r--r-- | mpm/python/usrp_mpm/dboard_manager/eiscat.py | 36 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/dboard_manager/lmk_mg.py | 4 | ||||
-rw-r--r-- | mpm/python/usrp_mpm/dboard_manager/magnesium.py | 50 |
3 files changed, 55 insertions, 35 deletions
diff --git a/mpm/python/usrp_mpm/dboard_manager/eiscat.py b/mpm/python/usrp_mpm/dboard_manager/eiscat.py index 3581784ea..808417f0c 100644 --- a/mpm/python/usrp_mpm/dboard_manager/eiscat.py +++ b/mpm/python/usrp_mpm/dboard_manager/eiscat.py @@ -498,21 +498,42 @@ class EISCAT(DboardManagerBase): )) pdac_spi.poke16(0x3, init_phase_dac_word) return LMK04828EISCAT(lmk_spi, ref_clk_freq, slot_idx) - def _sync_db_clock(synchronizer): + def _sync_db_clock(): " Synchronizes the DB clock to the common reference " - synchronizer.run_sync(measurement_only=False) - offset_error = synchronizer.run_sync(measurement_only=True) + synchronizer = ClockSynchronizer( + self.dboard_clk_control, + self.lmk, + self._spi_ifaces['phase_dac'], + 0, # register offset value. + 104e6, # TODO don't hardcode + self.ref_clock_freq, + 1.9E-12, # fine phase shift. TODO don't hardcode. This should live in the EEPROM + self.INIT_PHASE_DAC_WORD, + 0x3, + 3, # External PPS pipeline delay from the PPS captured at the FPGA to TDC input + self.slot_idx) + # The radio clock traces on the motherboard are 69 ps longer for Daughterboard B + # than Daughterboard A. We want both of these clocks to align at the converters + # on each board, so adjust the target value for DB B. This is an N3xx series + # peculiarity and will not apply to other motherboards. + trace_delay_offset = {0: 0.0e-0, + 1: 69.0e-12}[self.slot_idx] + offset = synchronizer.run( + num_meas=[512, 128], + target_offset = trace_delay_offset) + offset_error = abs(offset) if offset_error > 100e-12: - self.log.error("Clock synchronizer measured an offset of {} ps!".format( + self.log.error("Clock synchronizer measured an offset of {:.1f} ps!".format( offset_error*1e12 )) - raise RuntimeError("Clock synchronizer measured an offset of {} ps!".format( + raise RuntimeError("Clock synchronizer measured an offset of {:.1f} ps!".format( offset_error*1e12 )) else: - self.log.debug("Residual DAC offset error: {} ps.".format( + self.log.debug("Residual synchronization error: {:.1f} ps.".format( offset_error*1e12 )) + synchronizer = None self.log.debug("Clock Synchronization Complete!") # Go, go, go! if args.get("force_init", False): @@ -559,9 +580,8 @@ class EISCAT(DboardManagerBase): 1.9E-12, # TODO don't hardcode. This should live in the EEPROM self.INIT_PHASE_DAC_WORD, 2.496e9, # lmk_vco_freq - [135e-9,], # target_values 0x3, # spi_addr - self.log + self.slot_idx ) _sync_db_clock(self.clock_synchronizer) # Clocks and PPS are now fully active! diff --git a/mpm/python/usrp_mpm/dboard_manager/lmk_mg.py b/mpm/python/usrp_mpm/dboard_manager/lmk_mg.py index e7327ee83..2f4d6a192 100644 --- a/mpm/python/usrp_mpm/dboard_manager/lmk_mg.py +++ b/mpm/python/usrp_mpm/dboard_manager/lmk_mg.py @@ -17,8 +17,8 @@ class LMK04828Mg(LMK04828): """ def __init__(self, regs_iface, spi_lock, ref_clock_freq, master_clock_freq, log=None): LMK04828.__init__(self, regs_iface, log) - self.log.trace("Using reference clock frequency: {} MHz".format(ref_clock_freq/1e6)) - self.log.trace("Using master clock frequency: {} MHz".format(master_clock_freq/1e6)) + self.log.debug("Using reference clock frequency: {} MHz".format(ref_clock_freq/1e6)) + self.log.debug("Using master clock frequency: {} MHz".format(master_clock_freq/1e6)) self.spi_lock = spi_lock assert hasattr(self.spi_lock, 'lock') assert hasattr(self.spi_lock, 'unlock') diff --git a/mpm/python/usrp_mpm/dboard_manager/magnesium.py b/mpm/python/usrp_mpm/dboard_manager/magnesium.py index 0eaf25ae1..9c36abe89 100644 --- a/mpm/python/usrp_mpm/dboard_manager/magnesium.py +++ b/mpm/python/usrp_mpm/dboard_manager/magnesium.py @@ -157,6 +157,7 @@ class Magnesium(DboardManagerBase): # is at 2^15 = 32768. However, the linearity of the DAC is best just below that # point, so we set it to the (carefully calculated) alternate value instead. INIT_PHASE_DAC_WORD = 31000 # Intentionally decimal + PHASE_DAC_SPI_ADDR = 0x0 default_master_clock_rate = 125e6 default_current_jesd_rate = 2500e6 @@ -316,7 +317,7 @@ class Magnesium(DboardManagerBase): Execute necessary init dance to bring up dboard """ def _init_lmk(lmk_spi, ref_clk_freq, master_clk_rate, - pdac_spi, init_phase_dac_word): + pdac_spi, init_phase_dac_word, phase_dac_spi_addr): """ Sets the phase DAC to initial value, and then brings up the LMK according to the selected ref clock frequency. @@ -325,7 +326,7 @@ class Magnesium(DboardManagerBase): self.log.trace("Initializing Phase DAC to d{}.".format( init_phase_dac_word )) - pdac_spi.poke16(0x0, init_phase_dac_word) + pdac_spi.poke16(phase_dac_spi_addr, init_phase_dac_word) return LMK04828Mg( lmk_spi, self.spi_lock, @@ -333,33 +334,30 @@ class Magnesium(DboardManagerBase): master_clk_rate, self.log ) - def _get_clock_synchronizer(): - " Return a clock synchronizer object " - # Future Work: target_value needs to be tweaked to support - # heterogeneous rate sync. - target_value = { - 122.88e6: 128e-9, - 125e6: 128e-9, - 153.6e6: 122e-9 - }[self.master_clock_rate] - return ClockSynchronizer( + def _sync_db_clock(): + " Synchronizes the DB clock to the common reference " + synchronizer = ClockSynchronizer( dboard_ctrl_regs, self.lmk, self._spi_ifaces['phase_dac'], - 0, # register offset value. future work. + 0, # register offset value. self.master_clock_rate, self.ref_clock_freq, 860E-15, # fine phase shift. TODO don't hardcode. This should live in the EEPROM self.INIT_PHASE_DAC_WORD, - [target_value,], # target_values - 0x0, # spi_addr TODO: make this a constant and replace in _sync_db_clock as well - self.slot_idx - ) - def _sync_db_clock(synchronizer): - " Synchronizes the DB clock to the common reference " - synchronizer.check_core() - synchronizer.run_sync(measurement_only=False) - offset_error = synchronizer.run_sync(measurement_only=True) + self.PHASE_DAC_SPI_ADDR, + 5, # External PPS pipeline delay from the PPS captured at the FPGA to TDC input + self.slot_idx) + # The radio clock traces on the motherboard are 69 ps longer for Daughterboard B + # than Daughterboard A. We want both of these clocks to align at the converters + # on each board, so adjust the target value for DB B. This is an N3xx series + # peculiarity and will not apply to other motherboards. + trace_delay_offset = {0: 0.0e-0, + 1: 69.0e-12}[self.slot_idx] + offset = synchronizer.run( + num_meas=[512, 128], + target_offset = trace_delay_offset) + offset_error = abs(offset) if offset_error > 100e-12: self.log.error("Clock synchronizer measured an offset of {:.1f} ps!".format( offset_error*1e12 @@ -368,9 +366,10 @@ class Magnesium(DboardManagerBase): offset_error*1e12 )) else: - self.log.debug("Residual DAC offset error: {:.1f} ps.".format( + self.log.debug("Residual synchronization error: {:.1f} ps.".format( offset_error*1e12 )) + synchronizer = None self.log.debug("Sample Clock Synchronization Complete!") ## Go, go, go! # Sanity checks and input validation: @@ -420,11 +419,12 @@ class Magnesium(DboardManagerBase): self.master_clock_rate, self._spi_ifaces['phase_dac'], self.INIT_PHASE_DAC_WORD, + self.PHASE_DAC_SPI_ADDR, ) db_clk_control.enable_mmcm() - self.log.debug("Sample Clocks and Phase DAC Configured Successfully!") # Synchronize DB Clocks - _sync_db_clock(_get_clock_synchronizer()) + _sync_db_clock() + self.log.debug("Sample Clocks and Phase DAC Configured Successfully!") # Clocks and PPS are now fully active! self.mykonos.set_master_clock_rate(self.master_clock_rate) self.init_jesd(jesdcore, args) |