mirror of
https://github.com/EttusResearch/uhd.git
synced 2026-10-25 17:36:10 +00:00
mpm: apply linting to x4xx_rfdc_regs.py
This commit is contained in:
parent
894ecb691e
commit
be2e0a5c24
@ -8,45 +8,48 @@ X4xx RFDC register control
|
||||
"""
|
||||
|
||||
import time
|
||||
from usrp_mpm.sys_utils.uio import UIO
|
||||
|
||||
from usrp_mpm.chips.ic_reg_maps.x4xx_rfdc_regmap import x4xx_rfdc_regmap_t
|
||||
from usrp_mpm.mpmutils import poll_with_timeout
|
||||
from usrp_mpm.periph_manager.x4xx_clock_lookup import MMCM_LOCKGROUP_LOOKUP, MMCM_FILTERGROUP_LOOKUP
|
||||
from usrp_mpm.periph_manager.x4xx_clock_lookup import (
|
||||
MMCM_FILTERGROUP_LOOKUP,
|
||||
MMCM_LOCKGROUP_LOOKUP,
|
||||
)
|
||||
from usrp_mpm.sys_utils.uio import UIO
|
||||
|
||||
# Number of ADCs and DACs in the RFDC.
|
||||
NUM_CONVERTERS = 16
|
||||
|
||||
|
||||
class RfdcRegsControl:
|
||||
"""
|
||||
Control the FPGA RFDC registers external to the XRFdc API
|
||||
"""
|
||||
|
||||
mmcm_clock_map = {
|
||||
'prc': 0,
|
||||
'data_clk': 1,
|
||||
'data_clk_2x': 3,
|
||||
'rfdc_clk': 2,
|
||||
'rfdc_clk_x2': 4,
|
||||
"prc": 0,
|
||||
"data_clk": 1,
|
||||
"data_clk_2x": 3,
|
||||
"rfdc_clk": 2,
|
||||
"rfdc_clk_x2": 4,
|
||||
# These are synonymous to rfdc_clk
|
||||
'r0_clk': 2,
|
||||
'r0_clk_2x': 4,
|
||||
'r1_clk': 5,
|
||||
'r1_clk_2x': 6,
|
||||
"r0_clk": 2,
|
||||
"r0_clk_2x": 4,
|
||||
"r1_clk": 5,
|
||||
"r1_clk_2x": 6,
|
||||
}
|
||||
|
||||
def __init__(self, label, log):
|
||||
self.log = log.getChild("RfdcRegs")
|
||||
self.regs = UIO(
|
||||
label=label,
|
||||
read_only=False
|
||||
)
|
||||
self.regs = UIO(label=label, read_only=False)
|
||||
self._regs = x4xx_rfdc_regmap_t()
|
||||
# All registers that we need to know the value of from the beginning we
|
||||
# need to read out here. Note that we can't yet read all registers when
|
||||
# this class is instantiated, as the RFDC itself is still being held in
|
||||
# reset. See also reset().
|
||||
self._update_reg('CAL_ENABLE_DB0_CHAN0')
|
||||
self._update_reg('FABRIC_DSP_INFO_BW')
|
||||
self._update_reg('RFDC_INFO_DB0_XTRA_RESAMP')
|
||||
self._update_reg("CAL_ENABLE_DB0_CHAN0")
|
||||
self._update_reg("FABRIC_DSP_INFO_BW")
|
||||
self._update_reg("RFDC_INFO_DB0_XTRA_RESAMP")
|
||||
for conv in range(NUM_CONVERTERS):
|
||||
self._update_reg("RFDC_INFO_BLOCK_MODE", conv)
|
||||
self._regs.save_state()
|
||||
@ -59,24 +62,28 @@ class RfdcRegsControl:
|
||||
Resets the state of the register object. Call this after pulling the
|
||||
RFDC out of reset.
|
||||
"""
|
||||
self._update_reg('CAL_ENABLE_DB0_CHAN0')
|
||||
self._update_reg('IQ_SWAP_DAC_DB0_CHAN0')
|
||||
self._update_reg('IQ_SWAP_DAC_DB1_CHAN0')
|
||||
self._update_reg("CAL_ENABLE_DB0_CHAN0")
|
||||
self._update_reg("IQ_SWAP_DAC_DB0_CHAN0")
|
||||
self._update_reg("IQ_SWAP_DAC_DB1_CHAN0")
|
||||
self._regs.save_state()
|
||||
|
||||
def get_num_rx_channels(self):
|
||||
"""
|
||||
Returns the number of RX channels as defined in the RFDC register.
|
||||
"""
|
||||
return [getattr(self._regs, f'FABRIC_DSP_INFO_DB0_RX_CNT'),
|
||||
getattr(self._regs, f'FABRIC_DSP_INFO_DB1_RX_CNT')]
|
||||
return [
|
||||
getattr(self._regs, f"FABRIC_DSP_INFO_DB0_RX_CNT"),
|
||||
getattr(self._regs, f"FABRIC_DSP_INFO_DB1_RX_CNT"),
|
||||
]
|
||||
|
||||
def get_num_tx_channels(self, board=0):
|
||||
"""
|
||||
Returns the number of TX channels as defined in the RFDC register.
|
||||
"""
|
||||
return [getattr(self._regs, f'FABRIC_DSP_INFO_DB0_TX_CNT'),
|
||||
getattr(self._regs, f'FABRIC_DSP_INFO_DB1_TX_CNT')]
|
||||
return [
|
||||
getattr(self._regs, f"FABRIC_DSP_INFO_DB0_TX_CNT"),
|
||||
getattr(self._regs, f"FABRIC_DSP_INFO_DB1_TX_CNT"),
|
||||
]
|
||||
|
||||
def get_converter_mapping(self):
|
||||
"""
|
||||
@ -98,6 +105,7 @@ class RfdcRegsControl:
|
||||
This means there are 2 dboards. On the first dboard, we have 2 channels,
|
||||
and channel 0 uses tile 0, block 1.
|
||||
"""
|
||||
|
||||
# define helper function to extract content from device memory
|
||||
def get_tuple(db, channel, is_adc):
|
||||
for i in range(NUM_CONVERTERS):
|
||||
@ -115,15 +123,11 @@ class RfdcRegsControl:
|
||||
raise ValueError(f"Could not find mapping for {db}, {channel}, {is_adc}")
|
||||
|
||||
adc_mapping = tuple(
|
||||
tuple(
|
||||
get_tuple(db, chan, True) for chan in range(num_channels)
|
||||
)
|
||||
tuple(get_tuple(db, chan, True) for chan in range(num_channels))
|
||||
for db, num_channels in enumerate(self.get_num_rx_channels())
|
||||
)
|
||||
dac_mapping = tuple(
|
||||
tuple(
|
||||
get_tuple(db, chan, False) for chan in range(num_channels)
|
||||
)
|
||||
tuple(get_tuple(db, chan, False) for chan in range(num_channels))
|
||||
for db, num_channels in enumerate(self.get_num_tx_channels())
|
||||
)
|
||||
return adc_mapping, dac_mapping
|
||||
@ -134,15 +138,14 @@ class RfdcRegsControl:
|
||||
"""
|
||||
assert db_idx in (0, 1)
|
||||
return {
|
||||
'num_rx_chans': getattr(self._regs, f'FABRIC_DSP_INFO_DB{db_idx}_RX_CNT'),
|
||||
'num_tx_chans': getattr(self._regs, f'FABRIC_DSP_INFO_DB{db_idx}_TX_CNT'),
|
||||
'bw': self._regs.FABRIC_DSP_INFO_BW,
|
||||
'extra_resampling': getattr(self._regs, f'RFDC_INFO_DB{db_idx}_XTRA_RESAMP'),
|
||||
'spc_rx': 2**getattr(self._regs, f'RFDC_INFO_DB{db_idx}_SPC_RX'),
|
||||
'spc_tx': 2**getattr(self._regs, f'RFDC_INFO_DB{db_idx}_SPC_TX'),
|
||||
"num_rx_chans": getattr(self._regs, f"FABRIC_DSP_INFO_DB{db_idx}_RX_CNT"),
|
||||
"num_tx_chans": getattr(self._regs, f"FABRIC_DSP_INFO_DB{db_idx}_TX_CNT"),
|
||||
"bw": self._regs.FABRIC_DSP_INFO_BW,
|
||||
"extra_resampling": getattr(self._regs, f"RFDC_INFO_DB{db_idx}_XTRA_RESAMP"),
|
||||
"spc_rx": 2 ** getattr(self._regs, f"RFDC_INFO_DB{db_idx}_SPC_RX"),
|
||||
"spc_tx": 2 ** getattr(self._regs, f"RFDC_INFO_DB{db_idx}_SPC_TX"),
|
||||
}
|
||||
|
||||
|
||||
def get_threshold_status(self, db_idx, channel, threshold_idx):
|
||||
"""
|
||||
Retrieves the status bit for the given threshold block
|
||||
@ -178,16 +181,18 @@ class RfdcRegsControl:
|
||||
info = self.get_rfdc_info(db_idx)
|
||||
assert 0 <= channel < info["num_tx_chans"]
|
||||
assert enable in [False, True]
|
||||
setattr(self._regs, f'CAL_ENABLE_DB{db_idx}_CHAN{channel}', int(enable))
|
||||
setattr(self._regs, f"CAL_ENABLE_DB{db_idx}_CHAN{channel}", int(enable))
|
||||
self._commit()
|
||||
|
||||
def enable_iq_swap(self, enable, db_id, chan_idx, is_dac):
|
||||
assert db_id in (0, 1)
|
||||
num_channels = self.get_num_tx_channels()[db_id] if is_dac else self.get_num_rx_channels()[db_id]
|
||||
num_channels = (
|
||||
self.get_num_tx_channels()[db_id] if is_dac else self.get_num_rx_channels()[db_id]
|
||||
)
|
||||
assert chan_idx in range(num_channels)
|
||||
assert int(is_dac) in (0, 1)
|
||||
addr_name = f'IQ_SWAP_{"DAC" if is_dac else "ADC"}_DB{db_id}_CHAN{chan_idx}'
|
||||
enum_name = addr_name + '_t'
|
||||
enum_name = addr_name + "_t"
|
||||
setattr(self._regs, addr_name, getattr(self._regs, enum_name)(enable))
|
||||
self._commit()
|
||||
|
||||
@ -198,10 +203,11 @@ class RfdcRegsControl:
|
||||
"""
|
||||
Put MMCM into reset, or take it out of reset
|
||||
"""
|
||||
self._regs.MMCM_RESET = \
|
||||
self._regs.MMCM_RESET_t.MMCM_RESET_ENABLE \
|
||||
if reset \
|
||||
self._regs.MMCM_RESET = (
|
||||
self._regs.MMCM_RESET_t.MMCM_RESET_ENABLE
|
||||
if reset
|
||||
else self._regs.MMCM_RESET_t.MMCM_RESET_DISABLE
|
||||
)
|
||||
self._commit()
|
||||
|
||||
def reconfigure_mmcm(self, use_regs=True):
|
||||
@ -222,9 +228,10 @@ class RfdcRegsControl:
|
||||
# poke directly instead.
|
||||
self._poke(
|
||||
self._regs.get_addr("MMCM_LOAD_SEN"),
|
||||
self._regs.get_reg(self._regs.get_addr("MMCM_LOAD_SEN")))
|
||||
self._regs.get_reg(self._regs.get_addr("MMCM_LOAD_SEN")),
|
||||
)
|
||||
|
||||
self.log.trace('MMCM Configuration applied, now waiting for MMCM to lock...')
|
||||
self.log.trace("MMCM Configuration applied, now waiting for MMCM to lock...")
|
||||
self.wait_for_mmcm_drp_done()
|
||||
self.clear_data_clk_unlocked()
|
||||
self._commit()
|
||||
@ -236,9 +243,9 @@ class RfdcRegsControl:
|
||||
removed when this is resolved in digital.
|
||||
"""
|
||||
time.sleep(1)
|
||||
self._regs.CLEAR_DATA_CLK_UNLOCKED=self._regs.CLEAR_DATA_CLK_UNLOCKED_t(1)
|
||||
self._regs.CLEAR_DATA_CLK_UNLOCKED = self._regs.CLEAR_DATA_CLK_UNLOCKED_t(1)
|
||||
self._commit()
|
||||
self._regs.CLEAR_DATA_CLK_UNLOCKED=self._regs.CLEAR_DATA_CLK_UNLOCKED_t(0)
|
||||
self._regs.CLEAR_DATA_CLK_UNLOCKED = self._regs.CLEAR_DATA_CLK_UNLOCKED_t(0)
|
||||
self._commit()
|
||||
|
||||
def wait_for_mmcm_locked(self, timeout=0.001):
|
||||
@ -247,12 +254,14 @@ class RfdcRegsControl:
|
||||
The datasheet specifies a 100us max lock time
|
||||
"""
|
||||
self.wait_for_mmcm_drp_done()
|
||||
|
||||
def check_lock():
|
||||
self._update_reg('MMCM_LOCKED')
|
||||
self._update_reg("MMCM_LOCKED")
|
||||
if self._regs.MMCM_LOCKED:
|
||||
self.log.trace("RF MMCM lock detected.")
|
||||
return True
|
||||
return False
|
||||
|
||||
poll_sleep_ms = 0.2
|
||||
if not poll_with_timeout(check_lock, timeout * 1000, poll_sleep_ms):
|
||||
self.log.error("MMCM failed to lock in the expected time.")
|
||||
@ -271,11 +280,12 @@ class RfdcRegsControl:
|
||||
# of the MMCM, so we'll check this bit is also de-asserted, which it
|
||||
# should be according to pg065.
|
||||
poll_sleep_ms = 0.2
|
||||
|
||||
def check_reconfig_done():
|
||||
self._update_reg('MMCM_LOAD_SEN')
|
||||
self._update_reg("MMCM_LOAD_SEN")
|
||||
return not self._regs.MMCM_LOAD_SEN
|
||||
if not poll_with_timeout(
|
||||
check_reconfig_done, timeout * 1000, poll_sleep_ms):
|
||||
|
||||
if not poll_with_timeout(check_reconfig_done, timeout * 1000, poll_sleep_ms):
|
||||
self.log.error("MMCM failed to confirm DRP in the expected time.")
|
||||
raise RuntimeError("MMCM failed to confirm DRP in the expected time.")
|
||||
# We need to tell the reg cache that the value changed back:
|
||||
@ -308,12 +318,12 @@ class RfdcRegsControl:
|
||||
self._regs.MMCM_DIV_HI_TIME = 0
|
||||
self._regs.MMCM_DIV_NO_COUNT = 1
|
||||
self._regs.MMCM_DIV_EDGE = 0
|
||||
elif div_val % 2: # Odd divisions
|
||||
elif div_val % 2: # Odd divisions
|
||||
self._regs.MMCM_DIV_LO_TIME = div_val_by_2 + 1
|
||||
self._regs.MMCM_DIV_HI_TIME = div_val_by_2
|
||||
self._regs.MMCM_DIV_NO_COUNT = 0
|
||||
self._regs.MMCM_DIV_EDGE = 1
|
||||
else: # Even divisions
|
||||
else: # Even divisions
|
||||
self._regs.MMCM_DIV_LO_TIME = div_val_by_2
|
||||
self._regs.MMCM_DIV_HI_TIME = div_val_by_2
|
||||
self._regs.MMCM_DIV_NO_COUNT = 0
|
||||
@ -331,42 +341,43 @@ class RfdcRegsControl:
|
||||
|
||||
Does not commit register values!
|
||||
"""
|
||||
assert clock_name in self.mmcm_clock_map \
|
||||
or (isinstance(clock_name, int) and 0 <= clock_name <= 6)
|
||||
clock_idx = clock_name if isinstance(clock_name, int) \
|
||||
else self.mmcm_clock_map.get(clock_name)
|
||||
assert clock_name in self.mmcm_clock_map or (
|
||||
isinstance(clock_name, int) and 0 <= clock_name <= 6
|
||||
)
|
||||
clock_idx = (
|
||||
clock_name if isinstance(clock_name, int) else self.mmcm_clock_map.get(clock_name)
|
||||
)
|
||||
div_val_int = int(div_val)
|
||||
assert 1 <= div_val_int <= 128
|
||||
div_val_int_by2 = div_val_int // 2
|
||||
div_val_frac = div_val - div_val_int
|
||||
assert div_val_frac == 0.0 or \
|
||||
(clock_idx == 0 and ((div_val_frac / 0.125) % 1 == 0))
|
||||
assert div_val_frac == 0.0 or (clock_idx == 0 and ((div_val_frac / 0.125) % 1 == 0))
|
||||
if div_val_int == 1:
|
||||
setattr(self._regs, f'CLKOUT{clock_idx}_LO_TIME', 0)
|
||||
setattr(self._regs, f'CLKOUT{clock_idx}_HI_TIME', 0)
|
||||
setattr(self._regs, f'CLKOUT{clock_idx}_NO_COUNT', 1)
|
||||
setattr(self._regs, f'CLKOUT{clock_idx}_EDGE', 0)
|
||||
setattr(self._regs, f"CLKOUT{clock_idx}_LO_TIME", 0)
|
||||
setattr(self._regs, f"CLKOUT{clock_idx}_HI_TIME", 0)
|
||||
setattr(self._regs, f"CLKOUT{clock_idx}_NO_COUNT", 1)
|
||||
setattr(self._regs, f"CLKOUT{clock_idx}_EDGE", 0)
|
||||
elif div_val_int == 128:
|
||||
# The 128 case is undocumented in pg065 and xapp888, but the MMCM
|
||||
# does have a documented max division of 128, and a division value
|
||||
# of 0 is invalid so it can be used for this case. This was confirmed
|
||||
# by setting the division to 128 in the clock wizard GUI and reading
|
||||
# out the resulting register value.
|
||||
setattr(self._regs, f'CLKOUT{clock_idx}_LO_TIME', 0)
|
||||
setattr(self._regs, f'CLKOUT{clock_idx}_HI_TIME', 0)
|
||||
setattr(self._regs, f'CLKOUT{clock_idx}_NO_COUNT', 0)
|
||||
setattr(self._regs, f'CLKOUT{clock_idx}_EDGE', 0)
|
||||
elif div_val_int % 2: # Odd divisions
|
||||
setattr(self._regs, f'CLKOUT{clock_idx}_LO_TIME', div_val_int_by2 + 1)
|
||||
setattr(self._regs, f'CLKOUT{clock_idx}_HI_TIME', div_val_int_by2)
|
||||
setattr(self._regs, f'CLKOUT{clock_idx}_NO_COUNT', 0)
|
||||
setattr(self._regs, f'CLKOUT{clock_idx}_EDGE', 1)
|
||||
else: # Even divisions
|
||||
setattr(self._regs, f'CLKOUT{clock_idx}_LO_TIME', div_val_int_by2)
|
||||
setattr(self._regs, f'CLKOUT{clock_idx}_HI_TIME', div_val_int_by2)
|
||||
setattr(self._regs, f'CLKOUT{clock_idx}_NO_COUNT', 0)
|
||||
setattr(self._regs, f'CLKOUT{clock_idx}_EDGE', 0)
|
||||
setattr(self._regs, f'CLKOUT{clock_idx}_MX', 0)
|
||||
setattr(self._regs, f"CLKOUT{clock_idx}_LO_TIME", 0)
|
||||
setattr(self._regs, f"CLKOUT{clock_idx}_HI_TIME", 0)
|
||||
setattr(self._regs, f"CLKOUT{clock_idx}_NO_COUNT", 0)
|
||||
setattr(self._regs, f"CLKOUT{clock_idx}_EDGE", 0)
|
||||
elif div_val_int % 2: # Odd divisions
|
||||
setattr(self._regs, f"CLKOUT{clock_idx}_LO_TIME", div_val_int_by2 + 1)
|
||||
setattr(self._regs, f"CLKOUT{clock_idx}_HI_TIME", div_val_int_by2)
|
||||
setattr(self._regs, f"CLKOUT{clock_idx}_NO_COUNT", 0)
|
||||
setattr(self._regs, f"CLKOUT{clock_idx}_EDGE", 1)
|
||||
else: # Even divisions
|
||||
setattr(self._regs, f"CLKOUT{clock_idx}_LO_TIME", div_val_int_by2)
|
||||
setattr(self._regs, f"CLKOUT{clock_idx}_HI_TIME", div_val_int_by2)
|
||||
setattr(self._regs, f"CLKOUT{clock_idx}_NO_COUNT", 0)
|
||||
setattr(self._regs, f"CLKOUT{clock_idx}_EDGE", 0)
|
||||
setattr(self._regs, f"CLKOUT{clock_idx}_MX", 0)
|
||||
if clock_idx == 0:
|
||||
div_val_frac_code = int(div_val_frac / 0.125)
|
||||
self._regs.CLKOUT0_FRAC_EN = int(div_val_frac != 0)
|
||||
@ -384,15 +395,17 @@ class RfdcRegsControl:
|
||||
|
||||
For clock_name, see set_mmcm_output_div().
|
||||
"""
|
||||
assert clock_name in self.mmcm_clock_map \
|
||||
or (isinstance(clock_name, int) and 0 <= clock_name <= 6)
|
||||
clock_idx = clock_name if isinstance(clock_name, int) \
|
||||
else self.mmcm_clock_map.get(clock_name)
|
||||
self._update_reg(f'CLKOUT{clock_idx}_LO_TIME')
|
||||
self._update_reg(f'CLKOUT{clock_idx}_NO_COUNT')
|
||||
lo_time = getattr(self._regs, f'CLKOUT{clock_idx}_LO_TIME')
|
||||
hi_time = getattr(self._regs, f'CLKOUT{clock_idx}_HI_TIME')
|
||||
no_count = getattr(self._regs, f'CLKOUT{clock_idx}_NO_COUNT')
|
||||
assert clock_name in self.mmcm_clock_map or (
|
||||
isinstance(clock_name, int) and 0 <= clock_name <= 6
|
||||
)
|
||||
clock_idx = (
|
||||
clock_name if isinstance(clock_name, int) else self.mmcm_clock_map.get(clock_name)
|
||||
)
|
||||
self._update_reg(f"CLKOUT{clock_idx}_LO_TIME")
|
||||
self._update_reg(f"CLKOUT{clock_idx}_NO_COUNT")
|
||||
lo_time = getattr(self._regs, f"CLKOUT{clock_idx}_LO_TIME")
|
||||
hi_time = getattr(self._regs, f"CLKOUT{clock_idx}_HI_TIME")
|
||||
no_count = getattr(self._regs, f"CLKOUT{clock_idx}_NO_COUNT")
|
||||
div_val = 1 if no_count else lo_time + hi_time
|
||||
if div_val == 0:
|
||||
div_val = 128
|
||||
@ -416,12 +429,12 @@ class RfdcRegsControl:
|
||||
self._regs.CLKFBOUT_HI_TIME = 0
|
||||
self._regs.CLKFBOUT_NO_COUNT = 1
|
||||
self._regs.CLKFBOUT_EDGE = 0
|
||||
elif div_val_int % 2: # Odd divisions
|
||||
elif div_val_int % 2: # Odd divisions
|
||||
self._regs.CLKFBOUT_LO_TIME = div_val_int_by2 + 1
|
||||
self._regs.CLKFBOUT_HI_TIME = div_val_int_by2
|
||||
self._regs.CLKFBOUT_NO_COUNT = 0
|
||||
self._regs.CLKFBOUT_EDGE = 1
|
||||
else: # Even divisions
|
||||
else: # Even divisions
|
||||
self._regs.CLKFBOUT_LO_TIME = div_val_int_by2
|
||||
self._regs.CLKFBOUT_HI_TIME = div_val_int_by2
|
||||
self._regs.CLKFBOUT_NO_COUNT = 0
|
||||
@ -438,8 +451,8 @@ class RfdcRegsControl:
|
||||
|
||||
# Fetch the register values from LUTs.
|
||||
# LUTs' first index corresponds to FB_DIV = 1
|
||||
lock_lookup = MMCM_LOCKGROUP_LOOKUP[div_val-1]
|
||||
filt_lookup = MMCM_FILTERGROUP_LOOKUP[div_val-1]
|
||||
lock_lookup = MMCM_LOCKGROUP_LOOKUP[div_val - 1]
|
||||
filt_lookup = MMCM_FILTERGROUP_LOOKUP[div_val - 1]
|
||||
|
||||
# Lock lookup distribution (from XAPP888):
|
||||
# LOCKREG1[9:0] = lock_lookup[29:20]
|
||||
@ -449,11 +462,13 @@ class RfdcRegsControl:
|
||||
# LOCKREG3[9:0] = lock_lookup[19:10]
|
||||
self._regs.MMCM_LOCKREG1 = (lock_lookup & 0x003FF00000) >> 20
|
||||
|
||||
self._regs.MMCM_LOCKREG2 = (lock_lookup & 0x00000003FF) >> 0 | \
|
||||
(lock_lookup & 0x07C0000000) >> (30-10)
|
||||
self._regs.MMCM_LOCKREG2 = (lock_lookup & 0x00000003FF) >> 0 | (
|
||||
lock_lookup & 0x07C0000000
|
||||
) >> (30 - 10)
|
||||
|
||||
self._regs.MMCM_LOCKREG3 = (lock_lookup & 0x00000FFC00) >> 10 | \
|
||||
(lock_lookup & 0xF800000000) >> (35-10)
|
||||
self._regs.MMCM_LOCKREG3 = (lock_lookup & 0x00000FFC00) >> 10 | (
|
||||
lock_lookup & 0xF800000000
|
||||
) >> (35 - 10)
|
||||
|
||||
# Filter lookup distribution (from XAPP888):
|
||||
# FILTREG1[15] = filt_lookup[9]
|
||||
@ -463,14 +478,18 @@ class RfdcRegsControl:
|
||||
# FILTREG2[12:11] = filt_lookup[4:3]
|
||||
# FILTREG2[8:7] = filt_lookup[2:1]
|
||||
# FILTREG2[4] = filt_lookup[4]
|
||||
self._regs.MMCM_FILTREG1 = (filt_lookup & 0x200) << (15 - 9) | \
|
||||
(filt_lookup & 0x180) << (11 - 7) | \
|
||||
(filt_lookup & 0x4) << ( 8 - 6)
|
||||
self._regs.MMCM_FILTREG1 = (
|
||||
(filt_lookup & 0x200) << (15 - 9)
|
||||
| (filt_lookup & 0x180) << (11 - 7)
|
||||
| (filt_lookup & 0x4) << (8 - 6)
|
||||
)
|
||||
|
||||
self._regs.MMCM_FILTREG2 = (filt_lookup & 0x20) << (15 - 5) | \
|
||||
(filt_lookup & 0x18) << (11 - 3) | \
|
||||
(filt_lookup & 0x6) << ( 7 - 1) | \
|
||||
(filt_lookup & 0x1) << ( 4 - 0)
|
||||
self._regs.MMCM_FILTREG2 = (
|
||||
(filt_lookup & 0x20) << (15 - 5)
|
||||
| (filt_lookup & 0x18) << (11 - 3)
|
||||
| (filt_lookup & 0x6) << (7 - 1)
|
||||
| (filt_lookup & 0x1) << (4 - 0)
|
||||
)
|
||||
self._commit()
|
||||
|
||||
def set_gated_clock_enables(self, value=True):
|
||||
@ -479,77 +498,65 @@ class RfdcRegsControl:
|
||||
|
||||
This disables/enables the clock buffers on the MMCM.
|
||||
"""
|
||||
self._regs.RF_PLL_ENABLE_DATA_CLK = \
|
||||
self._regs.RF_PLL_ENABLE_DATA_CLK_t(int(value))
|
||||
self._regs.RF_PLL_ENABLE_DATA_CLK_x2 = \
|
||||
self._regs.RF_PLL_ENABLE_DATA_CLK_x2_t(int(value))
|
||||
self._regs.RF_PLL_ENABLE_RF0_CLK = \
|
||||
self._regs.RF_PLL_ENABLE_RF0_CLK_t(int(value))
|
||||
self._regs.RF_PLL_ENABLE_RF0_CLK_x2 = \
|
||||
self._regs.RF_PLL_ENABLE_RF0_CLK_x2_t(int(value))
|
||||
self._regs.RF_PLL_ENABLE_RF1_CLK = \
|
||||
self._regs.RF_PLL_ENABLE_RF1_CLK_t(int(value))
|
||||
self._regs.RF_PLL_ENABLE_RF1_CLK_x2 = \
|
||||
self._regs.RF_PLL_ENABLE_RF1_CLK_x2_t(int(value))
|
||||
self._regs.RF_PLL_ENABLE_DATA_CLK = self._regs.RF_PLL_ENABLE_DATA_CLK_t(int(value))
|
||||
self._regs.RF_PLL_ENABLE_DATA_CLK_x2 = self._regs.RF_PLL_ENABLE_DATA_CLK_x2_t(int(value))
|
||||
self._regs.RF_PLL_ENABLE_RF0_CLK = self._regs.RF_PLL_ENABLE_RF0_CLK_t(int(value))
|
||||
self._regs.RF_PLL_ENABLE_RF0_CLK_x2 = self._regs.RF_PLL_ENABLE_RF0_CLK_x2_t(int(value))
|
||||
self._regs.RF_PLL_ENABLE_RF1_CLK = self._regs.RF_PLL_ENABLE_RF1_CLK_t(int(value))
|
||||
self._regs.RF_PLL_ENABLE_RF1_CLK_x2 = self._regs.RF_PLL_ENABLE_RF1_CLK_x2_t(int(value))
|
||||
self._commit()
|
||||
|
||||
def set_reset_adc_dac_chains(self, reset=True):
|
||||
""" Resets or enables the ADC and DAC chain for the given dboard """
|
||||
"""Resets or enables the ADC and DAC chain for the given dboard"""
|
||||
if not reset:
|
||||
# We actually don't keep the converters in reset, so this is a no-op.
|
||||
self._converter_chains_in_reset = False
|
||||
return
|
||||
if self._converter_chains_in_reset:
|
||||
self.log.debug('Converters are already in reset. '
|
||||
'The reset bit will NOT be toggled.')
|
||||
self.log.debug("Converters are already in reset. " "The reset bit will NOT be toggled.")
|
||||
return
|
||||
|
||||
# The actual reset procedure
|
||||
def _check_for_done(db_idx, xdc):
|
||||
""" Query a specified done bit. 'xdc' must be either 'ADC' or 'DAC. """
|
||||
assert xdc in ('ADC', 'DAC')
|
||||
"""Query a specified done bit. 'xdc' must be either 'ADC' or 'DAC."""
|
||||
assert xdc in ("ADC", "DAC")
|
||||
assert db_idx in (0, 1)
|
||||
reg_name = f'RFDC_DB{db_idx}_{xdc}_RESET_DONE'
|
||||
reg_name = f"RFDC_DB{db_idx}_{xdc}_RESET_DONE"
|
||||
self._update_reg(reg_name)
|
||||
return getattr(self._regs, reg_name)
|
||||
|
||||
reset_timeout = 5000 # ms
|
||||
poll_sleep = 1 # ms
|
||||
reset_timeout = 5000 # ms
|
||||
poll_sleep = 1 # ms
|
||||
|
||||
def poll_for_done(db_idx, xdc):
|
||||
""" Shorthand for poll_with_timeout on the DONE bits """
|
||||
"""Shorthand for poll_with_timeout on the DONE bits"""
|
||||
return poll_with_timeout(
|
||||
lambda: _check_for_done(db_idx, xdc), reset_timeout, poll_sleep)
|
||||
lambda: _check_for_done(db_idx, xdc), reset_timeout, poll_sleep
|
||||
)
|
||||
|
||||
# Reset the ADC chains
|
||||
self.log.trace('Resetting ADC chain')
|
||||
self._regs.RFDC_DB0_ADC_RESET = \
|
||||
self._regs.RFDC_DB0_ADC_RESET_t.RFDC_DB0_ADC_RESET_ENABLE
|
||||
self._regs.RFDC_DB1_ADC_RESET = \
|
||||
self._regs.RFDC_DB1_ADC_RESET_t.RFDC_DB1_ADC_RESET_ENABLE
|
||||
self.log.trace("Resetting ADC chain")
|
||||
self._regs.RFDC_DB0_ADC_RESET = self._regs.RFDC_DB0_ADC_RESET_t.RFDC_DB0_ADC_RESET_ENABLE
|
||||
self._regs.RFDC_DB1_ADC_RESET = self._regs.RFDC_DB1_ADC_RESET_t.RFDC_DB1_ADC_RESET_ENABLE
|
||||
self._commit()
|
||||
for db_idx in (0, 1):
|
||||
if not poll_for_done(db_idx, 'ADC'):
|
||||
self.log.error("Timeout while resetting ADC chains.")
|
||||
raise RuntimeError("Timeout while resetting ADC chains.")
|
||||
self._regs.RFDC_DB0_ADC_RESET = \
|
||||
self._regs.RFDC_DB0_ADC_RESET_t.RFDC_DB0_ADC_RESET_DISABLE
|
||||
self._regs.RFDC_DB1_ADC_RESET = \
|
||||
self._regs.RFDC_DB1_ADC_RESET_t.RFDC_DB1_ADC_RESET_DISABLE
|
||||
if not poll_for_done(db_idx, "ADC"):
|
||||
self.log.error("Timeout while resetting ADC chains.")
|
||||
raise RuntimeError("Timeout while resetting ADC chains.")
|
||||
self._regs.RFDC_DB0_ADC_RESET = self._regs.RFDC_DB0_ADC_RESET_t.RFDC_DB0_ADC_RESET_DISABLE
|
||||
self._regs.RFDC_DB1_ADC_RESET = self._regs.RFDC_DB1_ADC_RESET_t.RFDC_DB1_ADC_RESET_DISABLE
|
||||
self._commit()
|
||||
# Reset the DAC chains
|
||||
self.log.trace('Resetting DAC chain')
|
||||
self._regs.RFDC_DB0_DAC_RESET = \
|
||||
self._regs.RFDC_DB0_DAC_RESET_t.RFDC_DB0_DAC_RESET_ENABLE
|
||||
self._regs.RFDC_DB1_DAC_RESET = \
|
||||
self._regs.RFDC_DB1_DAC_RESET_t.RFDC_DB1_DAC_RESET_ENABLE
|
||||
self.log.trace("Resetting DAC chain")
|
||||
self._regs.RFDC_DB0_DAC_RESET = self._regs.RFDC_DB0_DAC_RESET_t.RFDC_DB0_DAC_RESET_ENABLE
|
||||
self._regs.RFDC_DB1_DAC_RESET = self._regs.RFDC_DB1_DAC_RESET_t.RFDC_DB1_DAC_RESET_ENABLE
|
||||
self._commit()
|
||||
for db_idx in (0, 1):
|
||||
if not poll_for_done(db_idx, 'DAC'):
|
||||
self.log.error("Timeout while resetting DAC chains.")
|
||||
raise RuntimeError("Timeout while resetting DAC chains.")
|
||||
self._regs.RFDC_DB0_DAC_RESET = \
|
||||
self._regs.RFDC_DB0_DAC_RESET_t.RFDC_DB0_DAC_RESET_DISABLE
|
||||
self._regs.RFDC_DB1_DAC_RESET = \
|
||||
self._regs.RFDC_DB1_DAC_RESET_t.RFDC_DB1_DAC_RESET_DISABLE
|
||||
if not poll_for_done(db_idx, "DAC"):
|
||||
self.log.error("Timeout while resetting DAC chains.")
|
||||
raise RuntimeError("Timeout while resetting DAC chains.")
|
||||
self._regs.RFDC_DB0_DAC_RESET = self._regs.RFDC_DB0_DAC_RESET_t.RFDC_DB0_DAC_RESET_DISABLE
|
||||
self._regs.RFDC_DB1_DAC_RESET = self._regs.RFDC_DB1_DAC_RESET_t.RFDC_DB1_DAC_RESET_DISABLE
|
||||
self._commit()
|
||||
self._converter_chains_in_reset = True
|
||||
|
||||
@ -557,7 +564,7 @@ class RfdcRegsControl:
|
||||
"""
|
||||
Debugging API to dump the RFDC interface status.
|
||||
"""
|
||||
self._update_reg('STATUS_RFDC_DB0_DAC_TREADY')
|
||||
self._update_reg("STATUS_RFDC_DB0_DAC_TREADY")
|
||||
# pylint: disable=f-string-without-interpolation
|
||||
# pylint: disable=invalid-name
|
||||
r = self._regs
|
||||
@ -590,12 +597,12 @@ class RfdcRegsControl:
|
||||
# Internal helpers
|
||||
###########################################################################
|
||||
def _poke(self, addr, val):
|
||||
""" Shorthand for self.regs.poke32 """
|
||||
"""Shorthand for self.regs.poke32"""
|
||||
with self.regs:
|
||||
self.regs.poke32(addr, val)
|
||||
|
||||
def _peek(self, addr):
|
||||
""" Shorthand for self.regs.peek32 """
|
||||
"""Shorthand for self.regs.peek32"""
|
||||
with self.regs:
|
||||
result = self.regs.peek32(addr)
|
||||
return result
|
||||
|
||||
Loading…
Reference in New Issue
Block a user