openquantumhardware / qick

QICK: Quantum Instrumentation Control Kit

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

pfb readout phase seems random while sweeping freq

Ri-chard-Wu opened this issue · comments

Hi,

We used your official bitstream "qick_training.bit" from the qce2023 repository to perform muxed readout using fullspeed signal generator and pfb readout. We found that when sweeping frequency the phase seems to be random as shown below:

image

however if I replace the pfb readout with a fullspeed readout, the phase is not random:

image

Additional info:

  • we use zcu216.

  • we use xm655 5-6GHz balun for both ADC & DAC.

  • direct loopback, DAC→ ADC.

  • gain 20000 au.

  • freq: 5780 ~ 5830 MHz

  • codes:

        class LoopbackProgram(AveragerProgram):
            def initialize(self):
                cfg=self.cfg   
                res_ch = cfg["res_ch"]
         
                self.declare_gen(ch=cfg["res_ch"], nqz=1)
                 
                for ch in cfg["ro_chs"]:
                    self.declare_readout(ch=ch, length=self.cfg["readout_length"],
                                         freq=self.cfg["pulse_freq"], gen_ch=cfg["res_ch"])
         
                freq = self.freq2reg(cfg["pulse_freq"],gen_ch=res_ch, ro_ch=cfg["ro_chs"][0])
                phase = self.deg2reg(cfg["res_phase"], gen_ch=res_ch)
                gain = cfg["pulse_gain"]
                self.default_pulse_registers(ch=res_ch, freq=freq, phase=phase, gain=gain)
        
                style=self.cfg["pulse_style"]
        
                if style in ["flat_top","arb"]:
                    sigma = cfg["sigma"]
                    self.add_gauss(ch=res_ch, name="measure", sigma=sigma, length=sigma*5)
                    
                if style == "const":
                    self.set_pulse_registers(ch=res_ch, style=style, length=cfg["length"], mode=cfg['mode'])
                elif style == "flat_top": 
                    self.set_pulse_registers(ch=res_ch, style=style, waveform="measure", length=cfg["length"])
                elif style == "arb":
                    self.set_pulse_registers(ch=res_ch, style=style, waveform="measure")
                
                self.synci(200)   
            
            def body(self): 
                self.measure(pulse_ch=self.cfg["res_ch"], 
                             adcs=self.ro_chs,
                             pins=[0], 
                             adc_trig_offset=self.cfg["adc_trig_offset"],
                             wait=True,
                             syncdelay=self.us2cycles(self.cfg["relax_delay"]))
         
        config={ 
                "res_ch": 4 ,  
                "ro_chs":[0],  
                "reps":100,  
                "relax_delay":1.0,  
                "res_phase":0,  
                "pulse_style": "const",  
                "mode": "oneshot",
                "length":200,  
                "readout_length":300,  
                "pulse_gain": 20000,  
                "pulse_freq": 6600,  
                "adc_trig_offset": 100,    
                "soft_avgs":1, 
               }
        
         
        fpts = np.arange(5780, 5830, 0.5) 
        gpts = np.arange(5000, 35000, 5000) 
        iqs_2d = []
        
        for g in tqdm(gpts):
            config["pulse_gain"]=g
            iqs=[]
            for f in fpts:
                config["pulse_freq"]=f
        
                rspec=LoopbackProgram(soccfg, config)
                avgi,avgq=rspec.acquire(soc)
                
                iqs.append(avgi[0][0] + 1j*avgq[0][0])
        
            iqs_2d.append(np.array(iqs))
        
        iqs_2d = np.array(iqs_2d)
        
        gIdx = 3
        
        plt.figure() 
        plt.plot(fpts, np.angle(iqs_2d[gIdx]), 'o-', label=f'gain {gpts[gIdx]}')
        plt.title('phase')
        plt.legend()
        
        plt.figure() 
        plt.plot(fpts, np.abs(iqs_2d[gIdx]), 'o-', label=f'gain {gpts[gIdx]}')
        plt.title('amp')
        plt.legend()
    

are we doing anything wrong?

You're not doing anything wrong, this is just a characteristic of the muxed generator and readout (see also #122 and #140). Neither is "phase-coherent" with respect to frequency changes - if you change the up-/down-conversion frequency, their phase will change unpredictably, and returning to the previous frequency will not restore the phase.

So as you discovered, if you want to do a phase measurement with a frequency sweep both your generator and readout need to be the non-muxed type. So the typical approach is to use fullspeed gen+RO to characterize each resonator, and use mux after you've chosen your optimal readout frequencies.

We do know this can be inconvenient, and we hope that whenever we update these firmware blocks they will be fully phase-coherent. And sorry for the lack of documentation on this point and for the non-fullspeed gens/ROs in general - most people using them are direct collaborators with our group and we explain this stuff when we give them the bitstream.

Thanks!