{ "cells": [ { "cell_type": "markdown", "id": "0ae4e520", "metadata": {}, "source": [ "# Pre-layout signal integrity\n", "This example shows how to create a parameterized layout design\n", "and load the layout into HFSS 3D Layout for analysis and postprocessing.\n", "\n", "- Create EDB:\n", "\n", " - Add material.\n", " - Create stackup.\n", " - Create a parameterized via padstack definition.\n", " - Create ground planes.\n", " - Create a component.\n", " - Create signal vias and traces.\n", " - Create ground stitching vias.\n", " - Create HFSS analysis setup and frequency sweep.\n", "\n", "- Import EDB into HFSS 3D Layout:\n", "\n", " - Place SMA connector.\n", " - Analyze.\n", " - Plot return loss." ] }, { "cell_type": "markdown", "id": "690575d1", "metadata": {}, "source": [ "Here is an image of the model that is created in this example.\n", "\n", "\n", "\n", "Keywords: **HFSS 3D Layout**, **signal integrity**." ] }, { "cell_type": "markdown", "id": "97d951d0", "metadata": {}, "source": [ "## Perform imports and define constants\n", "Perform required packages." ] }, { "cell_type": "code", "execution_count": null, "id": "4b3fbed8", "metadata": {}, "outputs": [], "source": [ "import os\n", "import tempfile\n", "import time\n", "\n", "from ansys.aedt.core import Hfss3dLayout\n", "from ansys.aedt.core.downloads import download_file\n", "from pyedb import Edb\n" ] }, { "cell_type": "markdown", "id": "4cdd4256", "metadata": {}, "source": [ "Define constants." ] }, { "cell_type": "code", "execution_count": null, "id": "64982223", "metadata": { "lines_to_next_cell": 2 }, "outputs": [], "source": [ "AEDT_VERSION = \"2024.2\"\n", "NUM_CORES = 4\n", "NG_MODE = False # Open AEDT UI when it is launched." ] }, { "cell_type": "markdown", "id": "7215a265", "metadata": {}, "source": [ "## Create temporary directory and download example files\n", "\n", "Create a temporary directory where downloaded data or\n", "dumped data can be stored.\n", "If you'd like to retrieve the project data for subsequent use,\n", "the temporary folder name is given by ``temp_folder.name``." ] }, { "cell_type": "code", "execution_count": null, "id": "ba1b18b3", "metadata": { "lines_to_next_cell": 2 }, "outputs": [], "source": [ "temp_folder = tempfile.TemporaryDirectory(suffix=\".ansys\")\n", "sma_rf_connector = download_file(\n", " source=\"component_3d\",\n", " name=\"SMA_RF_SURFACE_MOUNT.a3dcomp\",\n", " destination=temp_folder.name,\n", ")" ] }, { "cell_type": "markdown", "id": "09e32e8a", "metadata": {}, "source": [ "# Create layout design" ] }, { "cell_type": "markdown", "id": "072330ce", "metadata": {}, "source": [ "## Import example design" ] }, { "cell_type": "code", "execution_count": null, "id": "bba99d81", "metadata": {}, "outputs": [], "source": [ "aedb = os.path.join(temp_folder.name, \"new_layout.aedb\")\n", "edbapp = Edb(edbpath=aedb, edbversion=AEDT_VERSION)" ] }, { "cell_type": "code", "execution_count": null, "id": "acc20c2d", "metadata": {}, "outputs": [], "source": [ "# Set antipad always on.\n", "edbapp.design_options.antipads_always_on = True" ] }, { "cell_type": "markdown", "id": "929a6ae1", "metadata": {}, "source": [ "## Add material definitions" ] }, { "cell_type": "code", "execution_count": null, "id": "fe079ddb", "metadata": {}, "outputs": [], "source": [ "edbapp.materials.add_conductor_material(name=\"copper\", conductivity=58000000)\n", "edbapp.materials.add_dielectric_material(\n", " name=\"FR4_epoxy\", permittivity=4, dielectric_loss_tangent=0.02\n", ")\n", "edbapp.materials.add_dielectric_material(\n", " name=\"solder_mask\", permittivity=3.1, dielectric_loss_tangent=0.035\n", ")" ] }, { "cell_type": "markdown", "id": "349125ee", "metadata": {}, "source": [ "## Create stackup" ] }, { "cell_type": "code", "execution_count": null, "id": "f126af05", "metadata": {}, "outputs": [], "source": [ "edbapp.stackup.create_symmetric_stackup(\n", " layer_count=4,\n", " inner_layer_thickness=\"18um\",\n", " outer_layer_thickness=\"50um\",\n", " dielectric_thickness=\"100um\",\n", " dielectric_material=\"FR4_epoxy\",\n", " soldermask=True,\n", " soldermask_thickness=\"20um\",\n", ")" ] }, { "cell_type": "markdown", "id": "d3efa496", "metadata": {}, "source": [ "## Create parameterized padstack definition" ] }, { "cell_type": "markdown", "id": "dd1c7329", "metadata": {}, "source": [ "Create signal via padstack definition." ] }, { "cell_type": "code", "execution_count": null, "id": "3564d917", "metadata": {}, "outputs": [], "source": [ "edbapp[\"$antipad\"] = \"0.7mm\"\n", "edbapp.padstacks.create(\n", " padstackname=\"svia\", holediam=\"0.3mm\", antipaddiam=\"$antipad\", paddiam=\"0.5mm\"\n", ")" ] }, { "cell_type": "markdown", "id": "6a8edcd6", "metadata": {}, "source": [ "Create component pin padstack definition." ] }, { "cell_type": "code", "execution_count": null, "id": "ca5e6416", "metadata": {}, "outputs": [], "source": [ "edbapp.padstacks.create(\n", " padstackname=\"comp_pin\",\n", " paddiam=\"400um\",\n", " antipaddiam=\"600um\",\n", " start_layer=\"TOP\",\n", " stop_layer=\"TOP\",\n", " antipad_shape=\"Circle\",\n", " has_hole=False,\n", ")" ] }, { "cell_type": "markdown", "id": "1e110f26", "metadata": {}, "source": [ "## Review stackup" ] }, { "cell_type": "code", "execution_count": null, "id": "965266c7", "metadata": {}, "outputs": [], "source": [ "edbapp.stackup.plot(plot_definitions=\"svia\")" ] }, { "cell_type": "markdown", "id": "1043ccfd", "metadata": {}, "source": [ "## Create ground planes" ] }, { "cell_type": "code", "execution_count": null, "id": "1334de70", "metadata": {}, "outputs": [], "source": [ "board_width = \"22mm\"\n", "board_length = \"18mm\"\n", "board_center_point = [0, \"5mm\"]\n", "\n", "gnd_l2 = edbapp.modeler.create_rectangle(\n", " layer_name=\"L2\",\n", " net_name=\"GND\",\n", " center_point=board_center_point,\n", " width=board_width,\n", " height=board_length,\n", " representation_type=\"CenterWidthHeight\",\n", " corner_radius=\"0mm\",\n", " rotation=\"0deg\",\n", ")\n", "\n", "gnd_l3 = edbapp.modeler.create_rectangle(\n", " layer_name=\"L3\",\n", " net_name=\"GND\",\n", " center_point=board_center_point,\n", " width=board_width,\n", " height=board_length,\n", " representation_type=\"CenterWidthHeight\",\n", " corner_radius=\"0mm\",\n", " rotation=\"0deg\",\n", ")\n", "\n", "gnd_bottom = edbapp.modeler.create_rectangle(\n", " layer_name=\"BOT\",\n", " net_name=\"GND\",\n", " center_point=board_center_point,\n", " width=board_width,\n", " height=board_length,\n", " representation_type=\"CenterWidthHeight\",\n", " corner_radius=\"0mm\",\n", " rotation=\"0deg\",\n", ")" ] }, { "cell_type": "markdown", "id": "d5192ef4", "metadata": {}, "source": [ "## Create a component" ] }, { "cell_type": "code", "execution_count": null, "id": "974a9e4b", "metadata": {}, "outputs": [], "source": [ "edbapp.padstacks.place(\n", " position=[0, 0],\n", " definition_name=\"comp_pin\",\n", " net_name=\"SIG\",\n", " is_pin=True,\n", " via_name=\"1\",\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "b22aa788", "metadata": {}, "outputs": [], "source": [ "comp_pins = [\n", " edbapp.padstacks.place(\n", " position=[\"-6mm\", 0],\n", " definition_name=\"comp_pin\",\n", " net_name=\"GND\",\n", " is_pin=True,\n", " via_name=\"2\",\n", " ),\n", " edbapp.padstacks.place(\n", " position=[\"6mm\", 0],\n", " definition_name=\"comp_pin\",\n", " net_name=\"GND\",\n", " is_pin=True,\n", " via_name=\"3\",\n", " ),\n", "]" ] }, { "cell_type": "code", "execution_count": null, "id": "0e97402e", "metadata": { "lines_to_next_cell": 2 }, "outputs": [], "source": [ "comp_u1 = edbapp.components.create(\n", " pins=comp_pins,\n", " component_name=\"U1\",\n", " component_part_name=\"BGA\",\n", " placement_layer=\"TOP\",\n", ")\n", "comp_u1.create_clearance_on_component(extra_soldermask_clearance=3.5e-3)" ] }, { "cell_type": "markdown", "id": "f06b93e2", "metadata": {}, "source": [ "## Place vias" ] }, { "cell_type": "markdown", "id": "2757e87d", "metadata": {}, "source": [ "Place a signal via." ] }, { "cell_type": "code", "execution_count": null, "id": "cc6aa9fd", "metadata": {}, "outputs": [], "source": [ "edbapp.padstacks.place(\n", " position=[0, 0], definition_name=\"svia\", net_name=\"SIG\", is_pin=False\n", ")" ] }, { "cell_type": "markdown", "id": "36fb6c04", "metadata": {}, "source": [ "Place ground stitching vias." ] }, { "cell_type": "code", "execution_count": null, "id": "aeea4fe0", "metadata": {}, "outputs": [], "source": [ "edbapp.padstacks.place(\n", " position=[\"-1mm\", 0], definition_name=\"svia\", net_name=\"GND\", is_pin=False\n", ")\n", "edbapp.padstacks.place(\n", " position=[\"1mm\", 0], definition_name=\"svia\", net_name=\"GND\", is_pin=False\n", ")\n", "edbapp.padstacks.place(\n", " position=[0, \"-1mm\"], definition_name=\"svia\", net_name=\"GND\", is_pin=False\n", ")\n", "edbapp.padstacks.place(\n", " position=[0, \"1mm\"], definition_name=\"svia\", net_name=\"GND\", is_pin=False\n", ")" ] }, { "cell_type": "markdown", "id": "f1d9a259", "metadata": {}, "source": [ "## Create signal traces" ] }, { "cell_type": "code", "execution_count": null, "id": "2331d93d", "metadata": {}, "outputs": [], "source": [ "edbapp[\"width\"] = \"0.15mm\"\n", "edbapp[\"gap\"] = \"0.1mm\"" ] }, { "cell_type": "markdown", "id": "37002f10", "metadata": {}, "source": [ "Create signal fanout." ] }, { "cell_type": "code", "execution_count": null, "id": "99af96ca", "metadata": {}, "outputs": [], "source": [ "sig_trace = edbapp.modeler.create_trace(\n", " path_list=[[0, 0]],\n", " layer_name=\"BOT\",\n", " width=\"width\",\n", " net_name=\"SIG\",\n", " start_cap_style=\"Round\",\n", " end_cap_style=\"Round\",\n", " corner_style=\"Round\",\n", ")" ] }, { "cell_type": "code", "execution_count": null, "id": "a9c52d2e", "metadata": {}, "outputs": [], "source": [ "sig_trace.add_point(x=\"0.5mm\", y=\"0.5mm\", incremental=True)\n", "sig_trace.add_point(x=0, y=\"1mm\", incremental=True)\n", "sig_trace.add_point(x=\"-0.5mm\", y=\"0.5mm\", incremental=True)\n", "sig_trace.add_point(x=0, y=\"1mm\", incremental=True)\n", "sig_path = sig_trace.get_center_line()" ] }, { "cell_type": "markdown", "id": "966d2a09", "metadata": {}, "source": [ "Create coplanar waveguide with ground with ground stitching vias." ] }, { "cell_type": "code", "execution_count": null, "id": "40ba6772", "metadata": {}, "outputs": [], "source": [ "sig2_trace = edbapp.modeler.create_trace(\n", " path_list=[sig_path[-1]],\n", " layer_name=\"BOT\",\n", " width=\"width\",\n", " net_name=\"SIG\",\n", " start_cap_style=\"Round\",\n", " end_cap_style=\"Flat\",\n", " corner_style=\"Round\",\n", ")\n", "sig2_trace.add_point(x=0, y=\"6mm\", incremental=True)\n", "sig2_trace.create_via_fence(distance=\"0.5mm\", gap=\"1mm\", padstack_name=\"svia\")\n", "sig2_trace.add_point(x=0, y=\"1mm\", incremental=True)" ] }, { "cell_type": "markdown", "id": "bf2a194d", "metadata": {}, "source": [ "Create trace-to-ground clearance." ] }, { "cell_type": "code", "execution_count": null, "id": "1b58d926", "metadata": {}, "outputs": [], "source": [ "sig2_path = sig2_trace.get_center_line()\n", "path_list = [sig_path, sig2_path]\n", "for i in path_list:\n", " void = edbapp.modeler.create_trace(\n", " path_list=i,\n", " layer_name=\"BOT\",\n", " width=\"width+gap*2\",\n", " start_cap_style=\"Round\",\n", " end_cap_style=\"Round\",\n", " corner_style=\"Round\",\n", " )\n", " edbapp.modeler.add_void(shape=gnd_bottom, void_shape=void)" ] }, { "cell_type": "markdown", "id": "90b88dee", "metadata": {}, "source": [ "Generate plot to review." ] }, { "cell_type": "code", "execution_count": null, "id": "9e5f9a18", "metadata": {}, "outputs": [], "source": [ "edbapp.nets.plot()" ] }, { "cell_type": "markdown", "id": "dad8db8b", "metadata": {}, "source": [ "## Create ports" ] }, { "cell_type": "markdown", "id": "3aa2e3fa", "metadata": {}, "source": [ "Create a wave port." ] }, { "cell_type": "code", "execution_count": null, "id": "8a5c6680", "metadata": {}, "outputs": [], "source": [ "sig2_trace.create_edge_port(\n", " name=\"p1_wave_port\",\n", " position=\"End\",\n", " port_type=\"Wave\",\n", " reference_layer=None,\n", " horizontal_extent_factor=10,\n", " vertical_extent_factor=10,\n", " pec_launch_width=\"0.01mm\",\n", ")" ] }, { "cell_type": "markdown", "id": "a33ef7d2", "metadata": {}, "source": [ "## Create HFSS analysis setup" ] }, { "cell_type": "code", "execution_count": null, "id": "a3e9c658", "metadata": {}, "outputs": [], "source": [ "setup = edbapp.create_hfss_setup(\"Setup1\")\n", "setup.set_solution_single_frequency(\"5GHz\", max_num_passes=1, max_delta_s=\"0.02\")\n", "setup.hfss_solver_settings.order_basis = \"first\"" ] }, { "cell_type": "markdown", "id": "3ee0b2c8", "metadata": {}, "source": [ "Add a frequency sweep to the setup.\n", "\n", "When the simulation results are to\n", "be used for transient SPICE analysis, you should\n", "use the following strategy:\n", "\n", "- DC point\n", "- Logarithmic sweep from 1 kHz to 100 MHz\n", "- Linear scale for higher frequencies" ] }, { "cell_type": "code", "execution_count": null, "id": "3f94b7d8", "metadata": {}, "outputs": [], "source": [ "setup.add_frequency_sweep(\n", " \"Sweep1\",\n", " frequency_sweep=[\n", " [\"log scale\", \"10MHz\", \"100MHz\", 3],\n", " [\"linear scale\", \"0.1GHz\", \"5GHz\", \"0.2GHz\"],\n", " ],\n", ")" ] }, { "cell_type": "markdown", "id": "5cd75c98", "metadata": {}, "source": [ "## Save and close EDB" ] }, { "cell_type": "code", "execution_count": null, "id": "5b58f80d", "metadata": {}, "outputs": [], "source": [ "edbapp.save()\n", "edbapp.close()" ] }, { "cell_type": "markdown", "id": "2cf571e0", "metadata": {}, "source": [ "# Analyze in HFSS 3D Layout" ] }, { "cell_type": "markdown", "id": "84d1c467", "metadata": {}, "source": [ "## Load EDB into HFSS 3D Layout." ] }, { "cell_type": "code", "execution_count": null, "id": "e052ad6c", "metadata": {}, "outputs": [], "source": [ "h3d = Hfss3dLayout(aedb, version=AEDT_VERSION, non_graphical=NG_MODE, new_desktop=True)" ] }, { "cell_type": "markdown", "id": "31a4343d", "metadata": {}, "source": [ "## Place SMA RF connector" ] }, { "cell_type": "code", "execution_count": null, "id": "25612ada", "metadata": {}, "outputs": [], "source": [ "comp = h3d.modeler.place_3d_component(\n", " component_path=sma_rf_connector,\n", " number_of_terminals=1,\n", " placement_layer=\"TOP\",\n", " component_name=\"sma_rf\",\n", " pos_x=0,\n", " pos_y=0,\n", " create_ports=True,\n", ")\n", "comp.angle = \"90deg\"" ] }, { "cell_type": "markdown", "id": "ce207751", "metadata": {}, "source": [ "## Release AEDT" ] }, { "cell_type": "code", "execution_count": null, "id": "4c54c510", "metadata": {}, "outputs": [], "source": [ "h3d.save_project()\n", "h3d.release_desktop()\n", "# Wait 3 seconds to allow AEDT to shut down before cleaning the temporary directory.\n", "time.sleep(3)" ] }, { "cell_type": "markdown", "id": "cf2b3856", "metadata": {}, "source": [ "## Clean up\n", "\n", "All project files are saved in the folder ``temp_dir.name``.\n", "If you've run this example as a Jupyter notebook, you\n", "can retrieve those project files. The following cell\n", "removes all temporary files, including the project folder." ] }, { "cell_type": "code", "execution_count": null, "id": "ce2f19dc", "metadata": {}, "outputs": [], "source": [ "temp_folder.cleanup()" ] } ], "metadata": { "jupytext": { "cell_metadata_filter": "-all", "main_language": "python", "notebook_metadata_filter": "-all" } }, "nbformat": 4, "nbformat_minor": 5 }