Download this example

Download this example as a Jupyter Notebook or as a Python script.


Pre-layout signal integrity#

This example shows how to create a parameterized layout design and load the layout into HFSS 3D Layout for analysis and postprocessing.

  • Create EDB:

    • Add material.

    • Create stackup.

    • Create a parameterized via padstack definition.

    • Create ground planes.

    • Create a component.

    • Create signal vias and traces.

    • Create ground stitching vias.

    • Create HFSS analysis setup and frequency sweep.

  • Import EDB into HFSS 3D Layout:

    • Place SMA connector.

    • Analyze.

    • Plot return loss.

Here is an image of the model that is created in this example.

57f89024727b4003a2bd02bf0029197e

Keywords: HFSS 3D Layout, signal integrity.

Perform imports and define constants#

Perform required packages.

[1]:
import os
import tempfile
import time

from ansys.aedt.core import Hfss3dLayout
from ansys.aedt.core.downloads import download_file
from pyedb import Edb

Define constants.

[2]:
AEDT_VERSION = "2024.2"
NUM_CORES = 4
NG_MODE = False  # Open AEDT UI when it is launched.

Create temporary directory and download example files#

Create a temporary directory where downloaded data or dumped data can be stored. If you’d like to retrieve the project data for subsequent use, the temporary folder name is given by temp_folder.name.

[3]:
temp_folder = tempfile.TemporaryDirectory(suffix=".ansys")
sma_rf_connector = download_file(
    source="component_3d",
    name="SMA_RF_SURFACE_MOUNT.a3dcomp",
    destination=temp_folder.name,
)

Create layout design#

Import example design#

[4]:
aedb = os.path.join(temp_folder.name, "new_layout.aedb")
edbapp = Edb(edbpath=aedb, edbversion=AEDT_VERSION)
PyAEDT INFO: Logger is initialized in EDB.
PyAEDT INFO: legacy v0.31.0
PyAEDT INFO: Python version 3.10.11 (tags/v3.10.11:7d4cc5a, Apr  5 2023, 00:38:17) [MSC v.1929 64 bit (AMD64)]
PyAEDT INFO: EDB C:\Users\ansys\AppData\Local\Temp\tmpg9hgk8xx.ansys\new_layout.aedb created correctly.
PyAEDT INFO: EDB initialized.
[5]:
# Set antipad always on.
edbapp.design_options.antipads_always_on = True

Add material definitions#

[6]:
edbapp.materials.add_conductor_material(name="copper", conductivity=58000000)
edbapp.materials.add_dielectric_material(
    name="FR4_epoxy", permittivity=4, dielectric_loss_tangent=0.02
)
edbapp.materials.add_dielectric_material(
    name="solder_mask", permittivity=3.1, dielectric_loss_tangent=0.035
)
[6]:
<pyedb.dotnet.edb_core.materials.Material at 0x1a159ed01f0>

Create stackup#

[7]:
edbapp.stackup.create_symmetric_stackup(
    layer_count=4,
    inner_layer_thickness="18um",
    outer_layer_thickness="50um",
    dielectric_thickness="100um",
    dielectric_material="FR4_epoxy",
    soldermask=True,
    soldermask_thickness="20um",
)
[7]:
True

Create parameterized padstack definition#

Create signal via padstack definition.

[8]:
edbapp["$antipad"] = "0.7mm"
edbapp.padstacks.create(
    padstackname="svia", holediam="0.3mm", antipaddiam="$antipad", paddiam="0.5mm"
)
PyAEDT INFO: Padstack svia create correctly
[8]:
'svia'

Create component pin padstack definition.

[9]:
edbapp.padstacks.create(
    padstackname="comp_pin",
    paddiam="400um",
    antipaddiam="600um",
    start_layer="TOP",
    stop_layer="TOP",
    antipad_shape="Circle",
    has_hole=False,
)
PyAEDT INFO: Padstack comp_pin create correctly
[9]:
'comp_pin'

Review stackup#

[10]:
edbapp.stackup.plot(plot_definitions="svia")
../../../../_images/examples_high_frequency_layout_signal_integrity_pre_layout_22_0.png
[10]:
<module 'matplotlib.pyplot' from 'C:\\actions-runner\\_work\\pyaedt-examples\\pyaedt-examples\\.venv\\lib\\site-packages\\matplotlib\\pyplot.py'>

Create ground planes#

[11]:
board_width = "22mm"
board_length = "18mm"
board_center_point = [0, "5mm"]

gnd_l2 = edbapp.modeler.create_rectangle(
    layer_name="L2",
    net_name="GND",
    center_point=board_center_point,
    width=board_width,
    height=board_length,
    representation_type="CenterWidthHeight",
    corner_radius="0mm",
    rotation="0deg",
)

gnd_l3 = edbapp.modeler.create_rectangle(
    layer_name="L3",
    net_name="GND",
    center_point=board_center_point,
    width=board_width,
    height=board_length,
    representation_type="CenterWidthHeight",
    corner_radius="0mm",
    rotation="0deg",
)

gnd_bottom = edbapp.modeler.create_rectangle(
    layer_name="BOT",
    net_name="GND",
    center_point=board_center_point,
    width=board_width,
    height=board_length,
    representation_type="CenterWidthHeight",
    corner_radius="0mm",
    rotation="0deg",
)

Create a component#

[12]:
edbapp.padstacks.place(
    position=[0, 0],
    definition_name="comp_pin",
    net_name="SIG",
    is_pin=True,
    via_name="1",
)
[12]:
<pyedb.dotnet.edb_core.edb_data.padstacks_data.EDBPadstackInstance at 0x1e216eff970>
[13]:
comp_pins = [
    edbapp.padstacks.place(
        position=["-6mm", 0],
        definition_name="comp_pin",
        net_name="GND",
        is_pin=True,
        via_name="2",
    ),
    edbapp.padstacks.place(
        position=["6mm", 0],
        definition_name="comp_pin",
        net_name="GND",
        is_pin=True,
        via_name="3",
    ),
]
[14]:
comp_u1 = edbapp.components.create(
    pins=comp_pins,
    component_name="U1",
    component_part_name="BGA",
    placement_layer="TOP",
)
comp_u1.create_clearance_on_component(extra_soldermask_clearance=3.5e-3)
PyAEDT INFO: Correctly computed Extension at first iteration.
[14]:
True

Place vias#

Place a signal via.

[15]:
edbapp.padstacks.place(
    position=[0, 0], definition_name="svia", net_name="SIG", is_pin=False
)
[15]:
<pyedb.dotnet.edb_core.edb_data.padstacks_data.EDBPadstackInstance at 0x1e216efce50>

Place ground stitching vias.

[16]:
edbapp.padstacks.place(
    position=["-1mm", 0], definition_name="svia", net_name="GND", is_pin=False
)
edbapp.padstacks.place(
    position=["1mm", 0], definition_name="svia", net_name="GND", is_pin=False
)
edbapp.padstacks.place(
    position=[0, "-1mm"], definition_name="svia", net_name="GND", is_pin=False
)
edbapp.padstacks.place(
    position=[0, "1mm"], definition_name="svia", net_name="GND", is_pin=False
)
[16]:
<pyedb.dotnet.edb_core.edb_data.padstacks_data.EDBPadstackInstance at 0x1e219bb0ac0>

Create signal traces#

[17]:
edbapp["width"] = "0.15mm"
edbapp["gap"] = "0.1mm"

Create signal fanout.

[18]:
sig_trace = edbapp.modeler.create_trace(
    path_list=[[0, 0]],
    layer_name="BOT",
    width="width",
    net_name="SIG",
    start_cap_style="Round",
    end_cap_style="Round",
    corner_style="Round",
)
[19]:
sig_trace.add_point(x="0.5mm", y="0.5mm", incremental=True)
sig_trace.add_point(x=0, y="1mm", incremental=True)
sig_trace.add_point(x="-0.5mm", y="0.5mm", incremental=True)
sig_trace.add_point(x=0, y="1mm", incremental=True)
sig_path = sig_trace.get_center_line()

Create coplanar waveguide with ground with ground stitching vias.

[20]:
sig2_trace = edbapp.modeler.create_trace(
    path_list=[sig_path[-1]],
    layer_name="BOT",
    width="width",
    net_name="SIG",
    start_cap_style="Round",
    end_cap_style="Flat",
    corner_style="Round",
)
sig2_trace.add_point(x=0, y="6mm", incremental=True)
sig2_trace.create_via_fence(distance="0.5mm", gap="1mm", padstack_name="svia")
sig2_trace.add_point(x=0, y="1mm", incremental=True)
[20]:
True

Create trace-to-ground clearance.

[21]:
sig2_path = sig2_trace.get_center_line()
path_list = [sig_path, sig2_path]
for i in path_list:
    void = edbapp.modeler.create_trace(
        path_list=i,
        layer_name="BOT",
        width="width+gap*2",
        start_cap_style="Round",
        end_cap_style="Round",
        corner_style="Round",
    )
    edbapp.modeler.add_void(shape=gnd_bottom, void_shape=void)

Generate plot to review.

[22]:
edbapp.nets.plot()
PyAEDT INFO: Nets Point Generation time 0.016 seconds
../../../../_images/examples_high_frequency_layout_signal_integrity_pre_layout_44_1.png
[22]:
<module 'matplotlib.pyplot' from 'C:\\actions-runner\\_work\\pyaedt-examples\\pyaedt-examples\\.venv\\lib\\site-packages\\matplotlib\\pyplot.py'>

Create ports#

Create a wave port.

[23]:
sig2_trace.create_edge_port(
    name="p1_wave_port",
    position="End",
    port_type="Wave",
    reference_layer=None,
    horizontal_extent_factor=10,
    vertical_extent_factor=10,
    pec_launch_width="0.01mm",
)
[23]:
('p1_wave_port',
 <pyedb.dotnet.edb_core.edb_data.ports.WavePort at 0x1e216e85870>)

Create HFSS analysis setup#

[24]:
setup = edbapp.create_hfss_setup("Setup1")
setup.set_solution_single_frequency("5GHz", max_num_passes=1, max_delta_s="0.02")
setup.hfss_solver_settings.order_basis = "first"

Add a frequency sweep to the setup.

When the simulation results are to be used for transient SPICE analysis, you should use the following strategy:

  • DC point

  • Logarithmic sweep from 1 kHz to 100 MHz

  • Linear scale for higher frequencies

[25]:
setup.add_frequency_sweep(
    "Sweep1",
    frequency_sweep=[
        ["log scale", "10MHz", "100MHz", 3],
        ["linear scale", "0.1GHz", "5GHz", "0.2GHz"],
    ],
)
[25]:
<pyedb.dotnet.edb_core.sim_setup_data.data.sweep_data.SweepData at 0x1e219c38e20>

Save and close EDB#

[26]:
edbapp.save()
edbapp.close()
[26]:
True

Analyze in HFSS 3D Layout#

Load EDB into HFSS 3D Layout.#

[27]:
h3d = Hfss3dLayout(aedb, version=AEDT_VERSION, non_graphical=NG_MODE, new_desktop=True)
PyAEDT INFO: Python version 3.10.11 (tags/v3.10.11:7d4cc5a, Apr  5 2023, 00:38:17) [MSC v.1929 64 bit (AMD64)]
PyAEDT INFO: PyAEDT version 0.12.dev0.
PyAEDT INFO: Initializing new Desktop session.
PyAEDT INFO: Log on console is enabled.
PyAEDT INFO: Log on file C:\Users\ansys\AppData\Local\Temp\pyaedt_ansys_cbdd3c22-2ca7-4016-891c-2feee53baffb.log is enabled.
PyAEDT INFO: Log on AEDT is enabled.
PyAEDT INFO: Debug logger is disabled. PyAEDT methods will not be logged.
PyAEDT INFO: Launching PyAEDT with gRPC plugin.
PyAEDT INFO: New AEDT session is starting on gRPC port 63141
PyAEDT INFO: AEDT installation Path C:\Program Files\AnsysEM\v242\Win64
PyAEDT INFO: Ansoft.ElectronicsDesktop.2024.2 version started with process ID 6536.
PyAEDT INFO: EDB folder C:\Users\ansys\AppData\Local\Temp\tmpg9hgk8xx.ansys\new_layout.aedb has been imported to project new_layout
PyAEDT INFO: Active Design set to 0;Cell_2L1NUR
PyAEDT INFO: Aedt Objects correctly read

Place SMA RF connector#

[28]:
comp = h3d.modeler.place_3d_component(
    component_path=sma_rf_connector,
    number_of_terminals=1,
    placement_layer="TOP",
    component_name="sma_rf",
    pos_x=0,
    pos_y=0,
    create_ports=True,
)
comp.angle = "90deg"
PyAEDT INFO: Loading Modeler.
PyAEDT INFO: Modeler loaded.
PyAEDT INFO: EDB loaded.
PyAEDT INFO: Layers loaded.
PyAEDT INFO: Primitives loaded.
PyAEDT INFO: Modeler class has been initialized! Elapsed time: 0m 0sec

Release AEDT#

[29]:
h3d.save_project()
h3d.release_desktop()
# Wait 3 seconds to allow AEDT to shut down before cleaning the temporary directory.
time.sleep(3)
PyAEDT INFO: Project new_layout Saved correctly
PyAEDT INFO: Desktop has been released and closed.

Clean up#

All project files are saved in the folder temp_dir.name. If you’ve run this example as a Jupyter notebook, you can retrieve those project files. The following cell removes all temporary files, including the project folder.

[30]:
temp_folder.cleanup()

Download this example

Download this example as a Jupyter Notebook or as a Python script.