AWG finalization

In the previous step, we implemented the AWG device starting from the derived implementation parameters. Now, we still need to make sure the AWG can be used in a larger circuit that you can tape-out on .

For this reason, we will prepare our AWG for tapeout by fixing DRC errors and route our AWG to grating couplers.

Preparing for tape-out

To prepare the AWG for tape-out, we need to make it adhere to design rules. For instance, many foundries and fabs impose design rules to avoid acute (sharp) angles. For this reason, we need to do some small changes to the layout.

This involves three activities:

  1. Fine-tuning the drawing of the star coupler contour

  2. Patching acute angles (by adding stubs)

  3. Flattening the full design to avoid snapping errors, caused by the rotation of subcell instances

Typically, making DRC-clean layouts is very foundry-specific. Therefore, Luceda IPKISS provides functionality to make the task easier:

  • Detection of acute angles in the layout

  • Stubbing of acute angles

  • Merging shapes on the same layer and other boolean operations

A list of these operations can be found in the documentation: layout operations.

Star coupler contour

The contour of the star coupler is drawn using the get_star_coupler_extended_contour function. Please check the Luceda AWG Designer documentation to learn about all the parameters that can be changed. For this example, we used the following parameters:

contour = awgd.get_star_coupler_extended_contour(
    apertures_in=sc_in_ports,
    apertures_out=sc_in_array,
    trans_in=sc_in_ports_xforms,
    trans_out=sc_in_array_xforms,
    radius_in=grating_radius_input*0.5,
    radius_out=grating_radius_input,
    extension_angles=(10, 10),
    aperture_extension=(1.0, 0.0),
    layers_in=[i3.TECH.PPLAYER.SI],
    layers_out=[i3.TECH.PPLAYER.SI],
)

Let’s have a closer look at some of these parameters:

  • The aperture_extensions parameter, if nonzero, determines whether we draw extra points along the front shape of the aperture at a certain distance. When a layer is given, this layer is matched against a waveguide window to determine the width of the window. In this example, we look for the width of the core SI layer (layer), and extend it with 1 \(\mu m\) on the input side, and 0 \(\mu m\) on the output side.

  • Using the parameter extension_angles we decide how far outwards the contour is drawn: we extend the contour region with 10 degrees on the input side, and 10 degrees on the output side.

As a result we obtain a contour which matches the apertures exactly and avoids acute angles:

../../../_images/contour_aperture_matching.png

Patching acute angles by adding stubs

One obvious design rule violation happens when two apertures are close together and the SHALLOW layer creates acute (sharp) angles (indicated by the arrows on the image below).

Sharp angles in the SHALLOW layer of an aperture array

Acute angles in the SHALLOW layer of an aperture array.

To fix those errors, we can use Luceda IPKISS’ method i3.get_stub_elements. This function takes a layout as input and returns two lists of elements, elems_add and elems_subst, that we can use to add and subtract, respectively, from the layout.

luceda-academy/training/topical_training/design_awg/example_generate_awg.py
# We look for acute angles in the SHALLOW layer, typically caused by two apertures that are close together.
elems_add, elems_subt = i3.get_stub_elements(
    layout=generated_awg_layout,
    angle_threshold=0,
    layers=[i3.TECH.PPLAYER.SHALLOW],
    grow_amount=0.001,
)

After the stubbing operation, the corrected apertures would look like this (note that we will apply the patches only in a later stage, this is only for illustration purposes):

Stubbing acute angles in the aperture array

Stubbing acute angles in the aperture array.

Flattening the AWG

Currently, our AWG consists of three instances, the input star coupler, the waveguide array, and the output star coupler. Each instance has a certain transformation applied in order to connect them together. Certainly, when there are non-orthogonal angles in these transformations or any of the underlying transformations, it is impossible to get a perfect alignment of two ports that are supposed to be connected. To solve this, we need to flatten the AWG.

On the other hand, we want to keep the netlist and model of the AWG intact, as we intend to use this for running circuit simulations. For that reason we create a new cell in which we’ll add all the information (flattened layout, but original netlist and model):

luceda-academy/training/topical_training/design_awg/example_generate_awg.py
# Wrap in a cell with a clean layout
awg_clean_layout = generated_awg_layout.layout.flat_copy() + elems_add
awg_clean = i3.EmptyCell(name="awg_clean")
awg_clean.Layout(layout=awg_clean_layout, ports=generated_awg_layout.ports)
awg_clean.Netlist(terms=generated_awg_netlist.terms)
awg_clean.CircuitModel(model=generated_awg_circuit.model)
ports = [p for p in generated_awg_layout.ports if "out" in p.name]

Note

Each design might require a slightly different approach to make the AWGs fully DRC clean. For more information on methods that help create DRC-clean layouts, you can check the Luceda IPKISS API reference: layout operations.

Using the AWG in a chip

Final layout

As a final step of this tutorial, we will prepare a test structure on a real chip so we can test the AWG. To do so, we will go through the following steps:

  • We will fan out the waveguides and route them to fiber grating couplers for testing.

  • An alignment waveguide will be added, for easier alignment of the fibers and normalizing the transmission spectrum of the AWG.

  • We will add some text labels on the chip so that we can easily recognize it under the microscope.

  • And finally, we’ll also add a company logo - that is going to look nice when taking pictures.

Fanning out the AWG outputs can easily be done with FanoutPorts. This routes them to Manhattan directions and on a regular pitch.

luceda-academy/training/topical_training/design_awg/example_generate_awg.py
# Fanout ports to horizontal on a regular pitch.
wg_tmpl = pdk.SiWireWaveguideTemplate()
wg_tmpl.Layout(core_width=0.4)

y_spacing = 25.0
awg_routed = FanoutPorts(
    name="routed_awg",
    contents=awg_clean,
    trace_template=wg_tmpl,
    port_labels=["E" + str(cnt) for cnt in range(len(ports))],
)
awg_routed_layout = awg_routed.Layout(
    bend_radius=10.0,
    target_coordinate=1450.0,
    spacing=y_spacing,
    reference_coordinate=generated_awg_layout.ports["out4"].y - 4 * y_spacing,
)


By playing a bit with the parameters we can obtain the desired layout.

../../../_images/awg_fanout.png
../../../_images/awg_fanout_zoom.png

Now, the ports of our AWG are all orthogonal and it can be easily used in a wider circuit.

Luceda IPKISS also provides functionality for adding grating couplers and other structures required to make a test structure. The IoColumn class allows us to attach cells to the grating couplers, add alignment waveguides, text labels and more.

luceda-academy/training/topical_training/design_awg/example_generate_awg.py
# Define fiber coupler adapter.
class IoFibcoup1300(IoFibcoup):
    def _default_trace_template(self):
        return wg_tmpl

    def _default_fiber_coupler(self):
        return pdk.FC_TE_1300()


# Make an AWG test structure
print("Making AWG test structure...\n")
awg_block = i3.IoColumn(name="awg_test", adapter=IoFibcoup1300)
awg_block_layout = awg_block.Layout(south_east=(3000.0, 0.0), y_spacing=25.0)
awg_block.add_blocktitle("CWDM_AWG")
awg_block.add_align(trace_template=wg_tmpl)
awg_block.add_emptyline(8)
awg_block.add(
    awg_routed,
    relative_offset=(0.0, awg_routed_layout.ports["in1"].y - awg_routed_layout.ports["out1"].y),
)

Let’s have a closer look at this code:

  • First, we define the adapter IoFibcoup to be used, which adds tapers and fiber couplers automatically.

  • We make an IoColumn, which is a kind of block to which we can add devices under test as well as fiducials. The IoColumn is made 3 mm-wide by setting its south_east corner (south-west being the origin). We set the fiber coupler pitch to 25 um and the adapter to the one we just defined.

  • Next, we add a title which will be repeated along the width of the block, defined in die_width.

  • Then, an alignment waveguide is added.

  • Finally, the AWG is added. In order to position it nicely, we add a few empty lines (of 5 um x 25 um pitch) and a vertical offset to the AWG. Obtaining the right parameters requires a little bit of playing around, but IoFibcoup provides a lot of flexibility.

As a result, we obtain the following layout:

../../../_images/awg_block.png

Ultimately, we obtain our finalized layout, ready to be incorporated on a test maskset:

../../../_images/full_gds.png

When you incorporate your own AWG into a circuit, you can reuse all existing ipkiss functionality to further continue designing. In addition to what is mentioned in this tutorial, you can:

  • Use any IPKISS container to further route the AWG inputs / outputs. See our documentation on the available containers you can use.

  • Build sweeps of AWGs with varying parameters as shown :ref:` in this example on AMF <cwdm_awg_amf>`.

  • Build more complex circuits with AWGs as subcells, from layout to circuit simulation with caphe. The samples contain an example of a circuit simulation, too.

  • Organize your AWGs in reusable libraries.

  • Using as part of designs deployed in L-edit.

You can also simulate and analyze the AWG after this step. In fact, after creating your initial script, you can organize the steps into different functions as explained in Organizing your AWG design project. Like that, you would not only have a more maintainable code, but you would also be able to simulate your AWG twice, by itself and as part of a wider circuit.

Test your knowledge

Create an AWG sweep to understand the effect of a parameter on the performance.

  1. Make a copy of luceda-academy/training/topical_training/design_awg/example_generate_awg.py (e.g. example_generate_awg2.py)

Try to sweep the following parameters:

  1. Number of arms in the AWG

  2. Length of the MMI aperture in the AWG

  3. FSR of the AWG

  4. Output spacing

Doing so will allow you to emulate the typical flow you will go through when designing your AWGs, as you will want to check what the effect of certain parameters is on your spec. Most likely, several designs will be included in your final mask.