In my design, I'm using a 19.2MHz crystal and outputting a variety of clocks at 1.8V. I don't have a lot of choice of the 19.2MHz--it's required by the CPU I'm clocking on OUT0.
A 19.2MHz crystal requires reprogramming the feedback divider from defaults to keep the VCO within limits (and if you don't do this, the frequency will skew with time and temperature and the math for computing a specific output frequency is not at all correct). Committing the new feedback divider seems to require triggering "calibration_start" (register 0x1c, bit D7). This causes OUT0 to drop out while calibration is running. As I'm using OUT0 to clock the CPU which is sending I2C commands to do the recalibration, the dropout will actually cause the CPU to hang until a power cycle.
The oscilloscope showing this dropout on OUT0 after triggering calibration_start.
My questions:
1) Is there any way to prevent the dropout on OUT0 and still correct the feedback divider?
Assuming I must OTP program to avoid this... Step 1 of OTP Programming says "Connect all VDD pins to a single 3.3V".
2) Is 3.3V actually necessary to program? VDDD/VDDA and all VDDOs in my design are 1.8V.
3) Is it possible to just run 3.3V to VDDA/VDDD instead of "all VDD pins"? I do not want to run 3.3V to the VDDO clock outputs which are connected to inputs that can only take 1.8V.
4) Is there a test fixture I can purchase to program these devices before placing them in-circuit? I know you have a custom service, but I use this chip for a wide variety of designs and do not want them all pre-programmed for just one project.
Thanks in advance!
Recommended sequence:1. Set 0x6F[1] (PLL_Lock_Bypass) to 1.2. Toggle 0x1C[7] (Calibration_Start) (to 0 and back to 1).3. Monitor 0x99[2] (Calibration_Done), wait for 1.4. Monitor 0x9D[7] (PLL_Lock), wait for 1.5. Reset 0x6F[1] (PLL_Lock_Bypass) to 0.>> What is the penalty of "lock bypass"?Register bit 0x6F[1] is a test register to control the state of the outputs while the APLL is not locked. It does not control the APLL.
import ftdi_mpsse #Import the module import time import sys #if len(sys.argv) > 1: # select_config = int(sys.argv[1]) #else: # select_config = 0 i2c = ftdi_mpsse.i2c(serial_number='A') #Connect to the FTDI chip ## Device address 0xD0 1101 0000 => 7-bit 0x68 ## Device address 0xD4 1101 0100 => 7-bit 0x6A VC6E ## Device address 0xA0 1010 0000 => 7-bit 0x50 ## Device address 0xAA 1010 1010 => 7-bit 0x55 ProXO ## Device address 0xB6 1011 0110 => 7-bit 0x5B ClockMatrix i2c.ReadAtOffset(0x6A, 0x00, 2, offset_size=1, disable_restart=0) # Dummy read, else first read starts incorrectly, cause unknown print(' 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F') print('0x00 :' + ''.join([' 0x{:02X}'.format(ord(x)) for x in i2c.ReadAtOffset(0x6A, 0x00, 16, offset_size=1, disable_restart=0)])) print('0x10 :' + ''.join([' 0x{:02X}'.format(ord(x)) for x in i2c.ReadAtOffset(0x6A, 0x10, 16, offset_size=1, disable_restart=0)])) print('0x20 :' + ''.join([' 0x{:02X}'.format(ord(x)) for x in i2c.ReadAtOffset(0x6A, 0x20, 16, offset_size=1, disable_restart=0)])) print('0x30 :' + ''.join([' 0x{:02X}'.format(ord(x)) for x in i2c.ReadAtOffset(0x6A, 0x30, 16, offset_size=1, disable_restart=0)])) print('0x40 :' + ''.join([' 0x{:02X}'.format(ord(x)) for x in i2c.ReadAtOffset(0x6A, 0x40, 16, offset_size=1, disable_restart=0)])) print('0x50 :' + ''.join([' 0x{:02X}'.format(ord(x)) for x in i2c.ReadAtOffset(0x6A, 0x50, 16, offset_size=1, disable_restart=0)])) print('0x60 :' + ''.join([' 0x{:02X}'.format(ord(x)) for x in i2c.ReadAtOffset(0x6A, 0x60, 16, offset_size=1, disable_restart=0)])) print('0x70 :' + ''.join([' 0x{:02X}'.format(ord(x)) for x in i2c.ReadAtOffset(0x6A, 0x70, 16, offset_size=1, disable_restart=0)])) print('0x80 :' + ''.join([' 0x{:02X}'.format(ord(x)) for x in i2c.ReadAtOffset(0x6A, 0x80, 16, offset_size=1, disable_restart=0)])) print('0x90 :' + ''.join([' 0x{:02X}'.format(ord(x)) for x in i2c.ReadAtOffset(0x6A, 0x90, 16, offset_size=1, disable_restart=0)])) print('Read starting Calibration results register 0x99') reg99 = ord(i2c.ReadAtOffset(0x6A, 0x99, 1, offset_size=1, disable_restart=0)) print('reg99 was 0x{:02X}'.format(reg99) ) print('Set register 0x6F[1] (PLL_Lock_Bypass) to 1') reg6F = ord(i2c.ReadAtOffset(0x6A, 0x6F, 1, offset_size=1, disable_restart=0)) print('reg6F was 0x{:02X}'.format(reg6F) ) reg6F = reg6F | 0x01 print('reg6F set 0x{:02X}'.format(reg6F) ) i2c.WriteAtOffset(0x6A, offset=0x6F , data=chr(reg6F), offset_size=1) reg6F = ord(i2c.ReadAtOffset(0x6A, 0x6F, 1, offset_size=1, disable_restart=0)) print('reg6F now 0x{:02X}'.format(reg6F) ) print('Toggle register 0x1C[7] (Calibration_Start)') reg1C = ord(i2c.ReadAtOffset(0x6A, 0x1C, 1, offset_size=1, disable_restart=0)) print('reg1C was 0x{:02X}'.format(reg1C) ) reg1C = reg1C & 0x7F print('reg1C set 0x{:02X}'.format(reg1C) ) i2c.WriteAtOffset(0x6A, offset=0x1C , data=chr(reg1C), offset_size=1) reg1C = ord(i2c.ReadAtOffset(0x6A, 0x1C, 1, offset_size=1, disable_restart=0)) print('reg1C now 0x{:02X}'.format(reg1C) ) reg1C = reg1C | 0x80 print('reg1C set 0x{:02X}'.format(reg1C) ) i2c.WriteAtOffset(0x6A, offset=0x1C , data=chr(reg1C), offset_size=1) reg1C = ord(i2c.ReadAtOffset(0x6A, 0x1C, 1, offset_size=1, disable_restart=0)) print('reg1C now 0x{:02X}'.format(reg1C) ) print('Read register 0x99[2] (Calibration_Done) status bit') reg99 = ord(i2c.ReadAtOffset(0x6A, 0x99, 1, offset_size=1, disable_restart=0)) cal_status = (reg99 & 0x04) >> 2 while (cal_status == 0): print('.') time.sleep(0.01) reg99 = ord(i2c.ReadAtOffset(0x6A, 0x99, 1, offset_size=1, disable_restart=0)) cal_status = (reg99 & 0x04) >> 2 reg99 = ord(i2c.ReadAtOffset(0x6A, 0x99, 1, offset_size=1, disable_restart=0)) print('reg99 is now 0x{:02X}'.format(reg99) ) print('Calibration_Done = {}'.format(cal_status)) print('Read register 0x9D[7] (PLL_Lock) status bit') reg9D = ord(i2c.ReadAtOffset(0x6A, 0x9D, 1, offset_size=1, disable_restart=0)) lock_status = (reg9D & 0x80) >> 7 while (lock_status == 0): print('.') time.sleep(0.01) reg9D = ord(i2c.ReadAtOffset(0x6A, 0x9D, 1, offset_size=1, disable_restart=0)) lock_status = (reg9D & 0x80) >> 7 reg9D = ord(i2c.ReadAtOffset(0x6A, 0x9D, 1, offset_size=1, disable_restart=0)) print('reg9D is now 0x{:02X}'.format(reg9D) ) print('PLL_Lock = {}'.format(lock_status)) print('Reset register 0x6F[1] (PLL_Lock_Bypass) to 0') reg6F = ord(i2c.ReadAtOffset(0x6A, 0x6F, 1, offset_size=1, disable_restart=0)) print('reg6F was 0x{:02X}'.format(reg6F) ) reg6F = reg6F & 0xFE print('reg6F set 0x{:02X}'.format(reg6F) ) i2c.WriteAtOffset(0x6A, offset=0x6F , data=chr(reg6F), offset_size=1) reg6F = ord(i2c.ReadAtOffset(0x6A, 0x6F, 1, offset_size=1, disable_restart=0)) print('reg6F now 0x{:02X}'.format(reg6F) ) time.sleep(0.1) #print('Config %d' % select_config) print(' 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F') print('0x00 :' + ''.join([' 0x{:02X}'.format(ord(x)) for x in i2c.ReadAtOffset(0x6A, 0x00, 16, offset_size=1, disable_restart=0)])) print('0x10 :' + ''.join([' 0x{:02X}'.format(ord(x)) for x in i2c.ReadAtOffset(0x6A, 0x10, 16, offset_size=1, disable_restart=0)])) print('0x20 :' + ''.join([' 0x{:02X}'.format(ord(x)) for x in i2c.ReadAtOffset(0x6A, 0x20, 16, offset_size=1, disable_restart=0)])) print('0x30 :' + ''.join([' 0x{:02X}'.format(ord(x)) for x in i2c.ReadAtOffset(0x6A, 0x30, 16, offset_size=1, disable_restart=0)])) print('0x40 :' + ''.join([' 0x{:02X}'.format(ord(x)) for x in i2c.ReadAtOffset(0x6A, 0x40, 16, offset_size=1, disable_restart=0)])) print('0x50 :' + ''.join([' 0x{:02X}'.format(ord(x)) for x in i2c.ReadAtOffset(0x6A, 0x50, 16, offset_size=1, disable_restart=0)])) print('0x60 :' + ''.join([' 0x{:02X}'.format(ord(x)) for x in i2c.ReadAtOffset(0x6A, 0x60, 16, offset_size=1, disable_restart=0)])) print('0x70 :' + ''.join([' 0x{:02X}'.format(ord(x)) for x in i2c.ReadAtOffset(0x6A, 0x70, 16, offset_size=1, disable_restart=0)])) print('0x80 :' + ''.join([' 0x{:02X}'.format(ord(x)) for x in i2c.ReadAtOffset(0x6A, 0x80, 16, offset_size=1, disable_restart=0)])) print('0x90 :' + ''.join([' 0x{:02X}'.format(ord(x)) for x in i2c.ReadAtOffset(0x6A, 0x90, 16, offset_size=1, disable_restart=0)]))