diff options
| -rw-r--r-- | mpm/python/usrp_mpm/dboard_manager/magnesium.py | 62 | ||||
| -rw-r--r-- | mpm/python/usrp_mpm/nijesdcore.py | 44 | 
2 files changed, 65 insertions, 41 deletions
| diff --git a/mpm/python/usrp_mpm/dboard_manager/magnesium.py b/mpm/python/usrp_mpm/dboard_manager/magnesium.py index bf0bc0409..7dc1f4b29 100644 --- a/mpm/python/usrp_mpm/dboard_manager/magnesium.py +++ b/mpm/python/usrp_mpm/dboard_manager/magnesium.py @@ -273,64 +273,76 @@ class Magnesium(DboardManagerBase):      def init_jesd(self, uio):          """ -        Bring up the JESD link between Mykonos and the N310 +        Bring up the JESD link between Mykonos and the N310.          """ -        self.log.trace("Creating jesdcore object") -        self.jesdcore = nijesdcore.NIMgJESDCore(uio) +        # CPLD Register Definition +        MYKONOS_CONTROL = 0x13 -        self.log.trace("Checking JESD core...") +        self.log.trace("Creating jesdcore object") +        self.jesdcore = nijesdcore.NIMgJESDCore(uio, self.slot_idx)          self.jesdcore.check_core() -        self.log.trace("Initializing LMK...")          self.jesdcore.unreset_qpll() -          self.jesdcore.init() -        self.log.trace("Resetting Mykonos...") - -        # YIKES!!! Where does this go?!? CPLD? -        # self.jesdcore.reset_mykonos() #not sure who owns the reset -        self.cpld_poke16(0x13, 0x1) -        self.cpld_poke16(0x13, 0x0) +        self.log.trace("Pulsing Mykonos Hard Reset...") +        self.cpld_regs.poke16(MYKONOS_CONTROL, 0x1) +        time.sleep(0.001) # No spec here, but give it some time to reset. +        self.cpld_regs.poke16(MYKONOS_CONTROL, 0x0) +        time.sleep(0.001) # No spec here, but give it some time to enable.          self.log.trace("Initializing Mykonos...")          self.mykonos.begin_initialization() +        # Multi-chip Sync requires two SYSREF pulses at least 17us apart.          self.jesdcore.send_sysref_pulse() +        time.sleep(0.001)          self.jesdcore.send_sysref_pulse()          self.mykonos.finish_initialization() -        self.log.trace("Starting Mykonos framer...") -        self.mykonos.start_jesd_tx() -        self.jesdcore.send_sysref_pulse() -        self.log.trace("Resetting FPGA deframer...") -        self.jesdcore.init_deframer() -        self.log.trace("Resetting FPGA framer...") +        self.log.trace("Starting JESD204b Link Initialization...") +        # Generally, enable the source before the sink. Start with the DAC side. +        self.log.trace("Starting FPGA framer...")          self.jesdcore.init_framer()          self.log.trace("Starting Mykonos deframer...")          self.mykonos.start_jesd_rx() - -        self.log.trace("Enable LMFC and send") +        # Now for the ADC link. Note that the Mykonos framer will not start issuing CGS +        # characters until SYSREF is received by the framer. Therefore we enable the +        # framer in Mykonos and the FPGA, send a SYSREF pulse to everyone, and then +        # start the deframer in the FPGA. +        self.log.trace("Starting Mykonos framer...") +        self.mykonos.start_jesd_tx() +        self.log.trace("Enable FPGA SYSREF Receiver.")          self.jesdcore.enable_lmfc()          self.jesdcore.send_sysref_pulse() -        time.sleep(0.2) +        self.log.trace("Starting FPGA deframer...") +        self.jesdcore.init_deframer() + +        # Allow a bit of time for CGS/ILA to complete. +        time.sleep(0.100) +          if not self.jesdcore.get_framer_status(): +            self.log.error("FPGA Framer Error!")              raise Exception('JESD Core Framer is not synced!')          if ((self.mykonos.get_deframer_status() & 0x7F) != 0x28): +            self.log.error("Mykonos Deframer Error: 0x{:X}".format((self.mykonos.get_deframer_status() & 0x7F)))              raise Exception('Mykonos Deframer is not synced!')          if not self.jesdcore.get_deframer_status(): +            self.log.error("FPGA Deframer Error!")              raise Exception('JESD Core Deframer is not synced!') -        if (self.mykonos.get_framer_status() & 0xFF) != 0x3E: +        if ((self.mykonos.get_framer_status() & 0xFF) != 0x3E): +            self.log.error("Mykonos Framer Error: 0x{:X}".format((self.mykonos.get_framer_status() & 0xFF)))              raise Exception('Mykonos Framer is not synced!') -        if (self.mykonos.get_multichip_sync_status() & 0xB) != 0xB: +        if ((self.mykonos.get_multichip_sync_status() & 0xB) != 0xB):              raise Exception('Mykonos multi chip sync failed!') +        self.log.info("JESD204B Link Initialization & Training Complete") -        self.log.trace("JESD fully synced and ready")      def dump_jesd_core(self): +        radio_regs = UIO(label="dboard-regs-{}".format(self.slot_idx))          for i in range(0x2000, 0x2110, 0x10):              print(("0x%04X " % i), end=' ')              for j in range(0, 0x10, 0x4): -                print(("%08X" % self.radio_regs.peek32(i + j)), end=' ') +                print(("%08X" % radio_regs.peek32(i + j)), end=' ')              print("") diff --git a/mpm/python/usrp_mpm/nijesdcore.py b/mpm/python/usrp_mpm/nijesdcore.py index 519f7822c..c3f1342db 100644 --- a/mpm/python/usrp_mpm/nijesdcore.py +++ b/mpm/python/usrp_mpm/nijesdcore.py @@ -31,6 +31,17 @@ class NIMgJESDCore(object):      Arguments:      regs -- regs class to use for peek/poke      """ +     +    MGT_RECEIVER_CONTROL       = 0x2040 +    MGT_RX_DESCRAMBLER_CONTROL = 0x2050 +    MGT_TRANSMITTER_CONTROL    = 0x2060 +    MGT_TX_TRANSCEIVER_CONTROL = 0x2064 +    MGT_TX_SCRAMBLER_CONTROL   = 0x2068 +    SYSREF_CAPTURE_CONTROL     = 0x2078 +    JESD_SIGNATURE_REG         = 0x2100 +    JESD_REVISION_REG          = 0x2104 +     +          def __init__(self, regs, slot_idx=0):          self.regs = regs          self.log = get_logger("NIMgJESDCore-{}".format(slot_idx)) @@ -47,11 +58,11 @@ class NIMgJESDCore(object):          Verify JESD core returns correct ID          """          self.log.trace("Checking JESD Core...") -        if self.regs.peek32(0x2100) != 0x4A455344: +        if self.regs.peek32(self.JESD_SIGNATURE_REG) != 0x4A455344:              raise Exception('JESD Core signature mismatch! Check that core is mapped correctly') -        #if self.regs.peek32(0x2104) != 0xFF +        #if self.regs.peek32(JESD_REVISION_REG) != 0xFF          #error here for date revision mismatch -        self.log.trace("JESD Core build code: {0}".format(hex(self.regs.peek32(0x2104)))) +        self.log.trace("JESD Core build code: {0}".format(hex(self.regs.peek32(self.JESD_REVISION_REG))))          self.log.trace("DB Slot #: {}".format( (self.regs.peek32(0x630) & 0x10000) >> 16  ))          self.log.trace("DB PID: {:X}".format( self.regs.peek32(0x630) & 0xFFFF ))          return True @@ -59,34 +70,34 @@ class NIMgJESDCore(object):      def init_deframer(self):          " Initialize deframer "          self.log.trace("Initializing deframer...") -        self.regs.poke32(0x2040, 0x2) -        self.regs.poke32(0x2050, 0x0) +        self.regs.poke32(self.MGT_RECEIVER_CONTROL, 0x2) +        self.regs.poke32(self.MGT_RX_DESCRAMBLER_CONTROL, 0x0)          self._gt_reset('rx', reset_only=False) -        self.regs.poke32(0x2040, 0x0) +        self.regs.poke32(self.MGT_RECEIVER_CONTROL, 0x0)      def init_framer(self):          " Initialize framer "          self.log.trace("Initializing framer...")          # Disable DAC Sync from requesting CGS & Stop Deframer -        self.regs.poke32(0x2060, 0x2002) +        self.regs.poke32(self.MGT_TRANSMITTER_CONTROL, 0x2002)          # Reset, unreset, and check the GTs          self._gt_reset('tx', reset_only=False)          # MGT phy control... enable TX Driver Swing -        self.regs.poke32(0x2064, 0xF0000) +        self.regs.poke32(self.MGT_TX_TRANSCEIVER_CONTROL, 0xF0000)          time.sleep(0.001)          # Bypass scrambler and disable char replacement -        self.regs.poke32(0x2068, 0x1) +        self.regs.poke32(self.MGT_TX_SCRAMBLER_CONTROL, 0x1)          # Check for Framer in Idle state -        rb = self.regs.peek32(0x2060) +        rb = self.regs.peek32(self.MGT_TRANSMITTER_CONTROL)          if rb & 0x100 != 0x100:              raise Exception('TX Framer is not idle after reset')          # Enable the framer and incoming DAC Sync -        self.regs.poke32(0x2060, 0x1000) -        self.regs.poke32(0x2060, 0x0001) +        self.regs.poke32(self.MGT_TRANSMITTER_CONTROL, 0x1000) +        self.regs.poke32(self.MGT_TRANSMITTER_CONTROL, 0x0001)      def get_framer_status(self):          " Return True if framer is in good status " -        rb = self.regs.peek32(0x2060) +        rb = self.regs.peek32(self.MGT_TRANSMITTER_CONTROL)          self.log.trace("FPGA Framer status: {0}".format(hex(rb & 0xFF0)))          if rb & (0b1 << 8) == 0b1 << 8:              self.log.warning("Framer warning: Framer is Idle!") @@ -98,7 +109,7 @@ class NIMgJESDCore(object):      def get_deframer_status(self):          " Return True if deframer is in good status " -        rb = self.regs.peek32(0x2040) +        rb = self.regs.peek32(self.MGT_RECEIVER_CONTROL)          self.log.trace("FPGA Deframer status: {0}".format(hex(rb & 0xFFFFFFFF)))          if rb & (0b1 << 2) == 0b0 << 2:              self.log.warning("Deframer warning: Code Group Sync failed to complete!") @@ -117,13 +128,14 @@ class NIMgJESDCore(object):          self._gt_reset('tx', reset_only=True)          self._gt_reset('rx', reset_only=True)          self._gt_pll_lock_control() -        self.regs.poke32(0x2078, 0x40) +        # Disable SYSREF Sampler +        self.regs.poke32(self.SYSREF_CAPTURE_CONTROL, 0x9800040)      def enable_lmfc(self):          """          Enable LMFC generator in FPGA. This step is woefully incomplete, but this call will work for now.          """ -        self.regs.poke32(0x2078, 0) +        self.regs.poke32(self.SYSREF_CAPTURE_CONTROL, 0x9800000)      def send_sysref_pulse(self):          """ | 
