Beispiel #1
0
 def set_clk_safe_state(self):
     """
     Disable all components that could react badly to a sudden change in
     clocking. After calling this method, all clocks will be off. Calling
     _reinit() will turn them on again.
     """
     if self._init_args is None:
         # Then we're already in a safe state
         return
     # Put the ADC and the DAC in a safe state because they receive a LMK's clock.
     # The DAC37J82 datasheet only recommends disabling its analog output before
     # a clock is provided to the chip.
     self.dac.tx_enable(False)
     self.adc.power_down_channel(True)
     with open_uio(
         label="dboard-regs-{}".format(self.slot_idx),
         read_only=False
     ) as radio_regs:
         # Clear the Sample Clock enables and place the MMCM in reset.
         db_clk_control = DboardClockControl(radio_regs, self.log)
         db_clk_control.reset_mmcm()
         # Place the JESD204b core in reset, mainly to reset QPLL/CPLLs.
         jesdcore = nijesdcore.NIJESDCore(radio_regs, self.slot_idx,
                                          **RhodiumInitManager.JESD_DEFAULT_ARGS)
         jesdcore.reset()
Beispiel #2
0
    def init(self, args):
        """
        Run the full initialization sequence. This will bring everything up
        from scratch: The LMK, JESD cores, the AD9695, the DAC37J82, and
        anything else that is clocking-related.
        Depending on the settings, this can take a fair amount of time.
        """
        # Input validation on RX margin tests (@ FPGA and DAC)
        # By accepting the rx_eyescan/tx_prbs argument being str or bool, one may
        # request an eyescan measurement to be performed from either the USRP's
        # shell (i.e. using --default-args) or from the host's MPM shell.
        perform_rx_eyescan = False
        if 'rx_eyescan' in args:
            perform_rx_eyescan = (args['rx_eyescan'] == 'True') or (args['rx_eyescan'] == True)
        if perform_rx_eyescan:
            self.log.trace("Adding RX eye scan PMA enable to JESD args.")
            self.JESD_DEFAULT_ARGS["enable_rx_eyescan"] = True
        perform_tx_prbs = False
        if 'tx_prbs' in args:
            perform_tx_prbs = (args['tx_prbs'] == 'True') or (args['tx_prbs'] == True)

        # Latency across the JESD204B TX/RX links should remain constant and
        # deterministic across the supported sampling_clock_rate values.
        # After testing the roundtrip latency (i.e. FPGA -> TX -> RX -> FPGA),
        # it was found that a different set of SYSREF delay values are required
        # for sampling_clock_rate = 400 MSPS to achieve latency consistency.
        self.JESD_DEFAULT_ARGS['rx_sysref_delay'] = \
          self.RX_SYSREF_DLY_DIC[self.rh_class.sampling_clock_rate]

        # Bringup Sequence.
        #   1. Prerequisites (include opening mmaps)
        #   2. Initialize LMK and bringup clocks.
        #   3. Synchronize DB Clocks.
        #   4. Initialize FPGA JESD IP.
        #   5. DAC Configuration.
        #   6. ADC Configuration.
        #   7. JESD204B Initialization.
        #   8. CPLD Gain Tables Initialization.

        # 1. Prerequisites
        # Open FPGA IP (Clock control and JESD core).
        self.log.trace("Creating gain table object...")
        self.gain_table_loader = GainTableRh(
            self._spi_ifaces['cpld'],
            self._spi_ifaces['cpld_gain_loader'],
            self.log)

        with open_uio(
            label="dboard-regs-{}".format(self.rh_class.slot_idx),
            read_only=False
        ) as radio_regs:
            self.log.trace("Creating dboard clock control object")
            db_clk_control = DboardClockControl(radio_regs, self.log)
            self.log.trace("Creating jesdcore object")
            jesdcore = nijesdcore.NIJESDCore(radio_regs,
                                             self.rh_class.slot_idx,
                                             **self.JESD_DEFAULT_ARGS)

            # 2. Initialize LMK and bringup clocks.
            # Disable FPGA MMCM's outputs, and assert its reset.
            db_clk_control.reset_mmcm()
            # Always place the JESD204b cores in reset before modifying the clocks,
            # otherwise high power or erroneous conditions could exist in the FPGA!
            jesdcore.reset()
            # Configure and bringup the LMK's clocks.
            self.log.trace("Initializing LMK...")
            self.rh_class.lmk = self._init_lmk(
                self._spi_ifaces['lmk'],
                self.rh_class.ref_clock_freq,
                self.rh_class.sampling_clock_rate,
                self._spi_ifaces['phase_dac'],
                self.INIT_PHASE_DAC_WORD,
                self.PHASE_DAC_SPI_ADDR
            )
            self.log.trace("LMK Initialized!")
            # Deassert FPGA's MMCM reset, poll for lock, and enable outputs.
            db_clk_control.enable_mmcm()

            # 3. Synchronize DB Clocks.
            # The clock synchronzation driver receives the master_clock_rate, which for
            # Rhodium is half the sampling_clock_rate.
            self._sync_db_clock(
                radio_regs,
                self.rh_class.ref_clock_freq,
                self.rh_class.sampling_clock_rate / 2,
                args)

            # 4. DAC Configuration.
            self.dac.config()

            # 5. ADC Configuration.
            self.adc.config()

            # 6-7. JESD204B Initialization.
            self.init_jesd(jesdcore, self.rh_class.sampling_clock_rate)
            # [Optional] Perform RX eyescan.
            if perform_rx_eyescan:
                self.log.info("Performing RX eye scan on ADC to FPGA link...")
                self._rx_eyescan(jesdcore, args)
            # [Optional] Perform TX PRBS test.
            if perform_tx_prbs:
                self.log.info("Performing TX PRBS-31 test on FPGA to DAC link...")
                self._tx_prbs_test(jesdcore, args)
            # Direct the garbage collector by removing our references
            jesdcore = None
            db_clk_control = None

        # 8. CPLD Gain Tables Initialization.
        self.gain_table_loader.init()

        return True
Beispiel #3
0
    def init(self, args):
        """
        Run the full initialization sequence. This will bring everything up
        from scratch: The LMK, JESD cores, the AD9695, the DAC37J82, and
        anything else that is clocking-related.
        Depending on the settings, this can take a fair amount of time.
        """
        # Input validation on RX margin tests (@ FPGA and DAC)
        # By accepting the rx_eyescan/tx_prbs argument being str or bool, one may
        # request an eyescan measurement to be performed from either the USRP's
        # shell (i.e. using --default-args) or from the host's MPM shell.
        perform_rx_eyescan = False
        if 'rx_eyescan' in args:
            perform_rx_eyescan = (args['rx_eyescan']
                                  == 'True') or (args['rx_eyescan'] == True)
        if perform_rx_eyescan:
            self.log.trace("Adding RX eye scan PMA enable to JESD args.")
            self.JESD_DEFAULT_ARGS["enable_rx_eyescan"] = True
        perform_tx_prbs = False
        if 'tx_prbs' in args:
            perform_tx_prbs = (args['tx_prbs'] == 'True') or (args['tx_prbs']
                                                              == True)

        # Latency across the JESD204B TX/RX links should remain constant and
        # deterministic across the supported sampling_clock_rate values.
        # After testing the roundtrip latency (i.e. FPGA -> TX -> RX -> FPGA),
        # it was found that a different set of SYSREF delay values are required
        # for sampling_clock_rate = 400 MSPS to achieve latency consistency.
        self.JESD_DEFAULT_ARGS['rx_sysref_delay'] = \
          self.RX_SYSREF_DLY_DIC[self.rh_class.sampling_clock_rate]

        # Bringup Sequence.
        #   1. Prerequisites (include opening mmaps)
        #   2. Initialize LMK and bringup clocks.
        #   3. Synchronize DB Clocks.
        #   4. Initialize FPGA JESD IP.
        #   5. DAC Configuration.
        #   6. ADC Configuration.
        #   7. JESD204B Initialization.
        #   8. CPLD Gain Tables Initialization.

        # 1. Prerequisites
        # Open FPGA IP (Clock control and JESD core).
        self.log.trace("Creating gain table object...")
        self.gain_table_loader = GainTableRh(
            self._spi_ifaces['cpld'], self._spi_ifaces['cpld_gain_loader'],
            self.log)

        with open_uio(label="dboard-regs-{}".format(self.rh_class.slot_idx),
                      read_only=False) as radio_regs:
            self.log.trace("Creating dboard clock control object")
            db_clk_control = DboardClockControl(radio_regs, self.log)
            self.log.trace("Creating jesdcore object")
            jesdcore = nijesdcore.NIJESDCore(radio_regs,
                                             self.rh_class.slot_idx,
                                             **self.JESD_DEFAULT_ARGS)

            # 2. Initialize LMK and bringup clocks.
            # Disable FPGA MMCM's outputs, and assert its reset.
            db_clk_control.reset_mmcm()
            # Always place the JESD204b cores in reset before modifying the clocks,
            # otherwise high power or erroneous conditions could exist in the FPGA!
            jesdcore.reset()
            # Configure and bringup the LMK's clocks.
            self.log.trace("Initializing LMK...")
            self.rh_class.lmk = self._init_lmk(
                self._spi_ifaces['lmk'], self.rh_class.ref_clock_freq,
                self.rh_class.sampling_clock_rate,
                self._spi_ifaces['phase_dac'], self.INIT_PHASE_DAC_WORD,
                self.PHASE_DAC_SPI_ADDR)
            self.log.trace("LMK Initialized!")
            # Deassert FPGA's MMCM reset, poll for lock, and enable outputs.
            db_clk_control.enable_mmcm()

            # 3. Synchronize DB Clocks.
            # The clock synchronzation driver receives the master_clock_rate, which for
            # Rhodium is half the sampling_clock_rate.
            self._sync_db_clock(radio_regs, self.rh_class.ref_clock_freq,
                                self.rh_class.sampling_clock_rate / 2, args)

            # 4. DAC Configuration.
            self.dac.config()

            # 5. ADC Configuration.
            self.adc.config()

            # 6-7. JESD204B Initialization.
            self.init_jesd(jesdcore, self.rh_class.sampling_clock_rate)
            # [Optional] Perform RX eyescan.
            if perform_rx_eyescan:
                self.log.info("Performing RX eye scan on ADC to FPGA link...")
                self._rx_eyescan(jesdcore, args)
            # [Optional] Perform TX PRBS test.
            if perform_tx_prbs:
                self.log.info(
                    "Performing TX PRBS-31 test on FPGA to DAC link...")
                self._tx_prbs_test(jesdcore, args)
            # Direct the garbage collector by removing our references
            jesdcore = None
            db_clk_control = None

        # 8. CPLD Gain Tables Initialization.
        self.gain_table_loader.init()

        return True