Phase shifters

SiFab contains electro-optic components that modulate the phase of the light when a voltage difference is applied.

PhaseShifterWaveguide

This PCell is an electro-optical waveguide with adjustable length. The p-n junction is centered in the middle of the optical waveguide and can be offset by tuning the property junction_offset. Many other properties can be controlled and are listed below.

  • The width and offset of the doped regions:

    • p_width
    • pplus_offset
    • pplus_extension
    • n_width
    • nplus_offset
    • nplus_extension
  • The offset of the contacts and vias:

    • nr_contact_rows_p
    • nr_contact_rows_n
    • contact_offset_p
    • contact_offset_n
    • contact_pitch
    • m1_width
    • m1_offset
    • m2_width
    • m2_offset
    • nr_via_rows
    • via_pitch
    • via_offset
from si_fab import all as pdk
from ipkiss3 import all as i3

# Phase Shifter
ps = pdk.PhaseShifterWaveguide(length=20.0,
                               trace_template=pdk.RWG450(),
                               junction_offset=-0.1,
                               p_width=4.0,
                               pplus_offset=1.5,
                               pplus_extension=0.25,
                               n_width=4.0,
                               nplus_offset=1.5,
                               nplus_extension=0.25,
                               nr_contact_rows_p=3,
                               nr_contact_rows_n=3,
                               contact_offset_p=2.025,
                               contact_offset_n=2.025,
                               contact_pitch=0.6,
                               m1_width=3.6,
                               m1_offset=2.0,
                               m2_width=2.8,
                               m2_offset=3.2,
                               nr_via_rows=4,
                               via_pitch=0.6,
                               via_offset=3.8)


ps_lv = ps.Layout()
ps_lv.visualize(annotate=True)
xs = ps_lv.cross_section(cross_section_path=i3.Shape([(1.0, -8.0), (1.0, 8.0)]))
xs.visualize()
ps_lv.write_gdsii("ps.gds")
../../../../../../../../_images/example_phase_shifter_00.png
../../../../../../../../_images/example_phase_shifter_01.png

Model and simulation recipes

The phase of the waveguide is calculated using the effective index (\(n_{eff}\)) of the trace template (trace_template) used to draw the waveguide. The model of the heater adds a phase modulation to the phase of the waveguide that is calculated as follows:

\[\Delta \Phi = \frac{\pi L V_d}{ V_{\pi} L_{\pi}}\]

where

  • \(L\) is the length of the phase shifter;
  • \(V_d\) is the voltage drop over the phase shifter junction;
  • \(V_{\pi} L_{\pi}\) is the efficiency of the phase shifter.

The voltage \(V_d\) is associated with a delay \(\tau\) that is, in first approximation, equal to \(RC\). The resistance \(R\) equals the output impedance of the driving electronics. The capacitance \(C\) equals the total electrical capacitance over the junction, which is usually dominated by the junction capacitance. This model does not account for the voltage dependence of \(V_{\pi} L_{\pi}\) and \(\tau\). In addition, their values are not linked to the layout and need to be calculated or measured independently.

Using the simulation recipe simulate_phaseshifter, one can easily check the phase shift achieved by a specified voltage, as well as the speed to achieve this response. Here we apply a voltage of \(V_{\pi} L_{\pi}\) V on a modulator that has length of 1 cm, which gives a phase shift of \(\pi\).

from si_fab import all as pdk
from si_fab.components.phase_shifter.simulate.simulate import simulate_phaseshifter
import pylab as plt
import numpy as np
import os

# Phase Shifter
name = "simple_step"
results_array = []
length = 1e4
ps = pdk.PhaseShifterWaveguide(length=length,
                               trace_template=pdk.RWG450(),
                               junction_offset=-0.1)
vpi_lpi = 1.2
Cl = 1.1e-15  # F/um
R = 50
tau = ps.length * Cl * R
ps.CircuitModel(vpi_lpi=vpi_lpi)


results = simulate_phaseshifter(cell=ps,
                                nsteps=1000,
                                dt=5e-12,
                                step_amplitude=vpi_lpi,
                                center_wavelength=1.5,
                                simulate_sources=True,
                                simulate_circuit=True,
                                debug=False)
times = results["timesteps"]
results_array.append(results)


def phase_unwrap_normalize(results):
    unwrapped = np.unwrap(np.angle(results))
    return (unwrapped-unwrapped[1] * np.ones(unwrapped.shape))/np.pi


outputs = ["in", "elec1", "elec2", "out"]
process = [np.real, np.real, np.real, phase_unwrap_normalize]
ylabels = ["V/m", "V", "V", "rad"]
fig, axs = plt.subplots(nrows=len(outputs), ncols=1, figsize=(6, 8))

for cnt, (f, pn, ylabel) in enumerate(zip(process, outputs, ylabels)):
    axs[cnt].set_title(pn)
    axs[cnt].plot(times, f(results[pn]), label="length: {}".format(length))
    axs[cnt].set_ylabel(ylabel)

plt.tight_layout()
fig.savefig(os.path.join("{}.png".format(name)), bbox_inches='tight')
../../../../../../../../_images/simple_step.png