DynamicPLLConfig freezes RFSoC4x2

Dear PYNQ Community,

The system environment I am working on:

  • Ubuntu 20.04.6 LTS
  • Vivado 2022.1
  • PYNQ 3.0.1

I have developed a small project on RFSoC4x2 which uses a DMA to read stored IQ samples and send them to RF data converter. The Scatter-Gather mode of DMA is enabled so the IQ samples can be sent in cyclic mode. The Overlay is shown blow:

rfsoc_ofdm.pdf (210.9 KB)

The project is built by modifying the rfsoc_ofdm example, where I

  • upgraded the example project to Vivado 2022.1 by modifying the unmatched IP version in rfsoc_ofdm.tcl
  • replaced the transmitter chain with a DMA and removed the receiver chain.
  • Otherwise I kept it unchanged to the example design.

The Overlay class is also based on the rfsoc_ofdm by removing the OFDM transmitter and receiver setup parts:

from pynq import Overlay
import ipywidgets as ipw
import os
import xrfdc
import xrfclk

from rfsoc_ofdm import clocks

class Overlay(Overlay):
    """
    """
    
    def __init__(self, bitfile_name=None, init_rf_clks=True, **kwargs):
        """
        """

        # Generate default bitfile name
        if bitfile_name is None:
            this_dir = os.path.dirname(__file__)
            bitfile_name = os.path.join(this_dir, 'rfsoc_ofdm', 'bitstream', 'rfsoc_ofdm.bit')

        # Create Overlay
        super().__init__(bitfile_name, **kwargs)

        # Determine board and set PLL appropriately
        board = os.environ['BOARD']
        
        # Extract friendly dataconverter names
        if board == 'RFSoC4x2':
            self.dac_tile = self.rfdc.dac_tiles[2]
            self.dac_block = self.dac_tile.blocks[0]
            self.adc_tile = self.rfdc.adc_tiles[2]
            self.adc_block = self.adc_tile.blocks[1]
        elif board in ['ZCU208', 'ZCU216']:
            self.dac_tile = self.rfdc.dac_tiles[2]
            self.dac_block = self.dac_tile.blocks[0]
            self.adc_tile = self.rfdc.adc_tiles[1]
            self.adc_block = self.adc_tile.blocks[0]
        elif board == 'RFSoC2x2':
            self.dac_tile = self.rfdc.dac_tiles[1]
            self.dac_block = self.dac_tile.blocks[0]
            self.adc_tile = self.rfdc.adc_tiles[2]
            self.adc_block = self.adc_tile.blocks[0]
        elif board == 'ZCU111':
            self.dac_tile = self.rfdc.dac_tiles[1]
            self.dac_block = self.dac_tile.blocks[2]
            self.adc_tile = self.rfdc.adc_tiles[0]
            self.adc_block = self.adc_tile.blocks[0]
        else:
            raise RuntimeError('Unknown error occurred.') # shouldn't get here
        
        # Start up LMX clock
        if init_rf_clks:
            clocks.set_custom_lmclks()

        if board == 'ZCU216':
            fs = 1920.00
        else:
            fs = 3840.00

        self.configure_adcs(sample_freq=fs)
        self.configure_dacs()

        
    def configure_adcs(self, pll_freq=384.00, sample_freq=3840.00, nyquist_zone=1, centre_freq=-600):
        """
        """
        
        # self.adc_tile.DynamicPLLConfig(1, pll_freq, sample_freq)
        self.adc_block.NyquistZone = nyquist_zone
        self.adc_block.MixerSettings = {
            'CoarseMixFreq'  : xrfdc.COARSE_MIX_BYPASS,
            'EventSource'    : xrfdc.EVNT_SRC_TILE,
            'FineMixerScale' : xrfdc.MIXER_SCALE_1P0,
            'Freq'           : centre_freq,
            'MixerMode'      : xrfdc.MIXER_MODE_R2C,
            'MixerType'      : xrfdc.MIXER_TYPE_FINE,
            'PhaseOffset'    : 0.0
        }
        self.adc_block.UpdateEvent(xrfdc.EVENT_MIXER)
        self.adc_tile.SetupFIFO(True)
        

    def configure_dacs(self, pll_freq=384.00, sample_freq=3840.00, nyquist_zone=1, centre_freq=600):
        """
        """
        
        # self.dac_tile.DynamicPLLConfig(1, pll_freq, sample_freq)
        self.dac_block.NyquistZone = nyquist_zone
        self.dac_block.MixerSettings = {
            'CoarseMixFreq'  : xrfdc.COARSE_MIX_BYPASS,
            'EventSource'    : xrfdc.EVNT_SRC_IMMEDIATE,
            'FineMixerScale' : xrfdc.MIXER_SCALE_1P0,
            'Freq'           : centre_freq,
            'MixerMode'      : xrfdc.MIXER_MODE_C2R,
            'MixerType'      : xrfdc.MIXER_TYPE_FINE,
            'PhaseOffset'    : 0.0
        }
        self.dac_block.UpdateEvent(xrfdc.EVENT_MIXER)
        self.dac_tile.SetupFIFO(True)

And how I load the bitstreams: (because the project is based on the rfsoc_ofdm example, the bitstream name is kept unchanged)

from pynq import PL
from pynq import allocate
import numpy as np

ol = Overlay(bitfile_name='./bitstreams/rfsoc_ofdm.bit')

The problem is, in the methods configure_adcs and configure_dacs, if I call DynamicPLLConfig, the bitstream can not be loaded, the whole system on the board gets stuck and has no response (ping also doesn’t work) and I have to shut it down and restart it manually. If I comment the lines calling DynamicPLLConfig, everything works fine, the bitstream can be loaded and all the subsequent steps (read IQ samples in cyclic mode, send to RFDC DAC) have no problem.

I have been trying to figure out why this problem happens since a few days but haven’t found any valuable information online. Could you please help me with it?

Hi,

I attached the block design tcl file here, in case you want to reproduce it. There is no additional IP required. Thanks!

ssb_tx.tcl (52.7 KB)