aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mpm/python/usrp_mpm/cores/nijesdcore.py66
-rw-r--r--mpm/python/usrp_mpm/cores/tdc_sync.py4
-rw-r--r--mpm/python/usrp_mpm/dboard_manager/magnesium.py3
-rw-r--r--mpm/python/usrp_mpm/dboard_manager/mg_init.py7
4 files changed, 50 insertions, 30 deletions
diff --git a/mpm/python/usrp_mpm/cores/nijesdcore.py b/mpm/python/usrp_mpm/cores/nijesdcore.py
index d6f465c53..90b45430f 100644
--- a/mpm/python/usrp_mpm/cores/nijesdcore.py
+++ b/mpm/python/usrp_mpm/cores/nijesdcore.py
@@ -1,5 +1,5 @@
#
-# Copyright 2017 Ettus Research, a National Instruments Company
+# Copyright 2017-2018 Ettus Research, a National Instruments Company
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
@@ -8,11 +8,12 @@ JESD FPGA Core Interface
"""
import time
+from six import iteritems
from builtins import hex
from builtins import object
from usrp_mpm.mpmlog import get_logger
-class NIMgJESDCore(object):
+class NIJESDCore(object):
"""
Provide interface for the FPGA JESD Core.
Works with Magnesium/Mykonos daughterboards only.
@@ -21,6 +22,13 @@ class NIMgJESDCore(object):
regs -- regs class to use for peek/poke
"""
+ # Bump this whenever we stop supporting older FPGA images or boards.
+ # YYMMDDHH
+ OLDEST_COMPAT_VERSION = 0x17122214
+ # Bump this whenever changes are made to the host code.
+ CURRENT_VERSION = 0x18071209
+
+ # Register offsets for JESD core.
DB_ID = 0x0630
MGT_QPLL_CONTROL = 0x2000
MGT_PLL_POWER_DOWN_CONTROL = 0x200C
@@ -38,31 +46,37 @@ class NIMgJESDCore(object):
JESD_REVISION_REG = 0x2104
JESD_OLD_COMPAT_REV_REG = 0x2108
+ # NIJESDCore configuration attributes.
+ # These parameters should be set per board (ie. Mg, Rh, etc.) at the creation
+ # of the NIJESDCore object. Use **kwargs to pass a dict which keys correspond
+ # to the parameter's name (eg. {"lmfc_divider": 12, ...}).
+ JESDCORE_DEFAULTS = {"qplls_used" : 1, # Number of QPLLs used.
+ "cplls_used" : 0, # Number of CPLLs used.
+ "rx_lanes" : 4, # Number of RX lanes used.
+ "tx_lanes" : 4, # Number of TX lanes used.
+ "bypass_descrambler": True, # Bypass the desrambler IP.
+ "bypass_scrambler" : True, # Bypass the scrambler IP.
+ "lmfc_divider" : 10, # Number of FPGA clock cycles per LMFC period.
+ "rx_sysref_delay" : 10, # Cycles of delay added to RX SYSREF
+ "tx_sysref_delay" : 10, # Cycles of delay added to TX SYSREF
+ "tx_driver_swing" : 0b1111, # See UG476, TXDIFFCTRL
+ "tx_precursor" : 0b00000, # See UG476, TXPRECURSOR
+ "tx_postcursor" : 0b00000} # See UG476, TXPOSTCURSOR
- def __init__(self, regs, slot_idx=0):
+ def __init__(self, regs, slot_idx=0, **kwargs):
self.regs = regs
self.log = get_logger("NIJESD204bCore-{}".format(slot_idx))
assert hasattr(self.regs, 'peek32')
assert hasattr(self.regs, 'poke32')
- # FutureWork: The following are constants for the Magnesium board. These need
- # to change to variables to support other interfaces.
- self.qplls_used = 1
- self.cplls_used = 0
- self.rx_lanes = 4
- self.tx_lanes = 4
- self.bypass_descrambler = False
- self.bypass_scrambler = True
- self.lmfc_divider = 20 # Number of FPGA clock cycles per LMFC period.
- self.rx_sysref_delay = 8 # Cycles of delay added to RX SYSREF
- self.tx_sysref_delay = 11 # Cycles of delay added to TX SYSREF
- self.tx_driver_swing = 0b1111 # See UG476, TXDIFFCTRL
- self.tx_precursor = 0b00000 # See UG476, TXPRECURSOR
- self.tx_postcursor = 0b00000 # See UG476, TXPOSTCURSOR
- # Bump this whenever we stop supporting older FPGA images or boards.
- # YYMMDDHH
- self.oldest_compat_version = 0x17122214
- # Bump this whenever changes are made to the host code.
- self.current_version = 0x17122214
+ # Initialize the driver's attributes with the default value, or a user-given
+ # value if the attribute key exists in kwargs.
+ for key, default_value in iteritems(self.JESDCORE_DEFAULTS):
+ setattr(self, key, kwargs.get(key, default_value))
+ assert type(getattr(self, key)) == type(default_value), \
+ "Invalid type for attribute {}".format(key)
+ self.log.trace("Initialized attribute {0} = {1}."
+ .format(key, getattr(self, key)))
+
def check_core(self):
"""
@@ -76,15 +90,15 @@ class NIMgJESDCore(object):
# Host Current Rev >= FPGA Oldest Compatible Rev
fpga_current_revision = self.regs.peek32(self.JESD_REVISION_REG) & 0xFFFFFFFF
fpga_old_compat_revision = self.regs.peek32(self.JESD_OLD_COMPAT_REV_REG) & 0xFFFFFFFF
- if fpga_current_revision < self.oldest_compat_version:
+ if fpga_current_revision < self.OLDEST_COMPAT_VERSION:
self.log.error("Revision check failed! MPM oldest supported revision "
"(0x{:08X}) is too new for this FPGA revision (0x{:08X})."
- .format(self.oldest_compat_version, fpga_current_revision))
+ .format(self.OLDEST_COMPAT_VERSION, fpga_current_revision))
raise RuntimeError('This MPM version does not support the loaded FPGA image. Please update images!')
- if self.current_version < fpga_old_compat_revision:
+ if self.CURRENT_VERSION < fpga_old_compat_revision:
self.log.error("Revision check failed! FPGA oldest compatible revision "
"(0x{:08X}) is too new for this MPM version (0x{:08X})."
- .format(fpga_current_revision, self.current_version))
+ .format(fpga_current_revision, self.CURRENT_VERSION))
raise RuntimeError('The loaded FPGA version is too new for MPM. Please update MPM!')
self.log.trace("JESD Core current revision: 0x{:08X}".format(fpga_current_revision))
self.log.trace("JESD Core oldest compatible revision: 0x{:08X}".format(fpga_old_compat_revision))
diff --git a/mpm/python/usrp_mpm/cores/tdc_sync.py b/mpm/python/usrp_mpm/cores/tdc_sync.py
index bb94d9826..f7ed09b7d 100644
--- a/mpm/python/usrp_mpm/cores/tdc_sync.py
+++ b/mpm/python/usrp_mpm/cores/tdc_sync.py
@@ -1,5 +1,5 @@
#
-# Copyright 2017 Ettus Research, a National Instruments Company
+# Copyright 2017-2018 Ettus Research, a National Instruments Company
#
# SPDX-License-Identifier: GPL-3.0-or-later
#
@@ -109,7 +109,7 @@ class ClockSynchronizer(object):
self.ref_clk_freq*1e-6))
raise RuntimeError("TDC does not support the selected reference clock rate!")
self.supported_radio_clk_freqs = [104e6, 122.88e6, 125e6, 153.6e6, 156.25e6, \
- 200e6, 250e6]
+ 200e6, 245.76e6, 250e6]
if self.radio_clk_freq not in self.supported_radio_clk_freqs:
self.log.error("Clock synchronizer does not support the selected radio clock"
" frequency. Selected rate: {:.2f} MHz".format(
diff --git a/mpm/python/usrp_mpm/dboard_manager/magnesium.py b/mpm/python/usrp_mpm/dboard_manager/magnesium.py
index 06dff175f..ca3c74e4b 100644
--- a/mpm/python/usrp_mpm/dboard_manager/magnesium.py
+++ b/mpm/python/usrp_mpm/dboard_manager/magnesium.py
@@ -422,7 +422,8 @@ class Magnesium(DboardManagerBase):
db_clk_control = DboardClockControl(dboard_ctrl_regs, self.log)
db_clk_control.reset_mmcm()
# Place the JESD204b core in reset, mainly to reset QPLL/CPLLs.
- jesdcore = nijesdcore.NIMgJESDCore(dboard_ctrl_regs, self.slot_idx)
+ jesdcore = nijesdcore.NIJESDCore(dboard_ctrl_regs, self.slot_idx,
+ **MagnesiumInitManager.JESD_DEFAULT_ARGS)
jesdcore.reset()
# The reference clock is handled elsewhere since it is a motherboard-
# level clock.
diff --git a/mpm/python/usrp_mpm/dboard_manager/mg_init.py b/mpm/python/usrp_mpm/dboard_manager/mg_init.py
index 62cc27a4f..d2b597c21 100644
--- a/mpm/python/usrp_mpm/dboard_manager/mg_init.py
+++ b/mpm/python/usrp_mpm/dboard_manager/mg_init.py
@@ -76,6 +76,11 @@ class MagnesiumInitManager(object):
# Variable PPS delay before the RP/SP pulsers begin. Fixed value for the
# N3xx devices.
N3XX_INT_PPS_DELAY = 4
+ # JESD core default configuration.
+ JESD_DEFAULT_ARGS = {"bypass_descrambler": False,
+ "lmfc_divider" : 20,
+ "rx_sysref_delay" : 8,
+ "tx_sysref_delay" : 11}
def __init__(self, mg_class, spi_ifaces):
self.mg_class = mg_class
@@ -525,7 +530,7 @@ class MagnesiumInitManager(object):
read_only=False
) as dboard_ctrl_regs:
self.log.trace("Creating jesdcore object...")
- jesdcore = nijesdcore.NIMgJESDCore(dboard_ctrl_regs, slot_idx)
+ jesdcore = nijesdcore.NIJESDCore(dboard_ctrl_regs, slot_idx, **self.JESD_DEFAULT_ARGS)
# Now get cracking with the actual init sequence:
self.log.trace("Creating dboard clock control object...")
db_clk_control = DboardClockControl(dboard_ctrl_regs, self.log)