Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[SOLVED] AEL script drawning algorithm for Octagonal Inductor

Status
Not open for further replies.

fred3991

Member level 1
Joined
Nov 26, 2020
Messages
33
Helped
0
Reputation
0
Reaction score
0
Trophy points
6
Activity points
613
Hello!
I'm trying to create ael script for octagonal inductor like this
1632225986057.png


Using google,I have already created an element cell, and found ael code for a simple square coil, successfully added ael macro and everything looks to work.
The script code is below
The very basics of AEL and function purposes are known to me.

Code:
defun artwork_ind(width, spacing, turn, outerX, outerY)
{
    decl MI=130;
    decl i;
    de_set_path_corner(PREF_SQUARE_PATH);
    de_set_layer(MI);
    for(i=0; i<int(turn); i++)
    {
        de_set_path_width(width);
            if(i==turn-1)
            {
                 de_add_path();
                    de_add_point(-0.5* (outerX-width)+i*(spacing+width), -0.5*outerY+i*(spacing+width) - (i!=0) *spacing) ;
                    de_add_point(-0.5* (outerX-width)+i*(spacing+width), 0.5*(outerY-width)-i* (spacing+width));
                    de_add_point(0, 0.5*(outerY-width) -i* (spacing+width) );
                    de_add_point(0, 0);
                     de_end();

            }
            else
            {
                    de_add_path();
                        de_add_point(-0.5* (outerX-width) +i* (spacing+width), -0.5*outerY+i*(spacing+width) - (i!=0)*spacing) ;
                        de_add_point(-0.5* (outerX-width) +i* (spacing+width), 0.5* (outerY-width) -i*  (spacing+width));
                        de_add_point( 0.5* (outerX-width) -i* (spacing+width), 0.5* (outerY-width) -i*  (spacing+width));
                        de_add_point( 0.5* (outerX-width) -i* (spacing+width), -0.5* (outerY-width) +i* (spacing+width));
                        de_add_point(-0.5* (outerX-width) +(i+1) * (spacing+width)-0.5*width, -0.5* (outerY-width)+i*(spacing+width));
                    de_end();
            }
}
de_end_command();
de_set_layer(MI) ;
de_define_port(0, 0, 0, 1, "P1");
de_define_port(-0.5* (outerX-width), -0.5*outerY, 0, 2, "P2");
}

But I ran into the following issues when creating the octagonal inductance coil shown in the picture above:
Can anyone suggest an approximate algorithm for how it should be drawn?
Where to start?
As input data for drawing I will have: outer diameter, conductor width, number of turns.
Also, the original coil from the library has an average diameter, the gap is automatically calculated - so I want to get those parameters in my ael script too
Also, I'm interested in the question - how to get into the grid, so that I won't have problems with DRC later?
What geometric features of the coil should be taken into account?

And in general, write everything, which you would find useful, I would be very grateful!
 

Solution
I have coded such octagon inductors for my ADS Inductor Toolkit. I would recommend to start at the terminals (outside) and then draw towards the inside, with user defined width and spacing.
The check if the geometry "works", i.e. inner diameter is large enough to draw a valid layout including crossovers, can be done upfront in a callback for the parameter dialog. But yes, that was a trick part to get all these calculations right.

To be DRC clean and draw exact 45°, my code calculates the segment length and then draws relative with that exact offset value in x and y direction. If you start from a "snapped" point, that will give a valid layout with exact 45° segments. You can query the grid size (database resolution) using...
I have coded such octagon inductors for my ADS Inductor Toolkit. I would recommend to start at the terminals (outside) and then draw towards the inside, with user defined width and spacing.
The check if the geometry "works", i.e. inner diameter is large enough to draw a valid layout including crossovers, can be done upfront in a callback for the parameter dialog. But yes, that was a trick part to get all these calculations right.

To be DRC clean and draw exact 45°, my code calculates the segment length and then draws relative with that exact offset value in x and y direction. If you start from a "snapped" point, that will give a valid layout with exact 45° segments. You can query the grid size (database resolution) using tech_get_layout_resolution(), but depending on when/where you call that it might not return a useful value, so I use a safe fallback value such as 10nm.
 

Solution
I have coded such octagon inductors for my ADS Inductor Toolkit. I would recommend to start at the terminals (outside) and then draw towards the inside, with user defined width and spacing.
The check if the geometry "works", i.e. inner diameter is large enough to draw a valid layout including crossovers, can be done upfront in a callback for the parameter dialog. But yes, that was a trick part to get all these calculations right.

To be DRC clean and draw exact 45°, my code calculates the segment length and then draws relative with that exact offset value in x and y direction. If you start from a "snapped" point, that will give a valid layout with exact 45° segments. You can query the grid size (database resolution) using tech_get_layout_resolution(), but depending on when/where you call that it might not return a useful value, so I use a safe fallback value such as 10nm.
Yes, our lab used your Inductor ToolKit a few years ago when we designed the IHP PDK. As I remember, you also did a substrate for EM analysis in the IHP library. Recently, a PhD student was showing S-parameters results of EM simulation and measurement of a fabricated buffer amplifier crystal - the similarity of the results is unbelievable. They are almost exactly the same.:oops:👏(y)

And now about the coil. I'm thinking of starting with a simple octagon - guard ring for the coil (green outline around the coils) - to get an exact 45 degrees, I solved the equation for an isosceles triangle (bottom left of the coil). The problem now is how to round the value in microns to two decimal places in the AEL. Because cosine 45 = sqrt(2)/2) = 0.707106.......
I can't find the right function in the ADS AEL documentation, there is only round() which rounds to integers...for example I have d = 58.45984654.... and I need d = 58.46;
How do I do this?
 

For snapping to grid, I use the code below.
fputs(stderr) is just debugging output to check this function, remove comment to make it active

defun gridsnap(a)
// snap to database grid
{

decl snapped = 1.0*round(a*database_resolution)/database_resolution;
// fputs(stderr, strcat("input value to snapping = ", identify_value(a)));
// fputs(stderr, strcat("snapped value = ", identify_value(snapped),"\n"));
return snapped;
}
 

thank you very much!
All coordinates of the vertices of the octagon match the coordinates of the coil guard ring from the library.

I think further will be easier, with the coil itself)
Thanks again for the helpful tips)

Code:
defun gridsnap(a)
    {
        decl database_resolution = tech_get_layout_resolution("myPDK");
        decl snapped = 1.0*round(a*database_resolution)/database_resolution;
        return snapped;
    }


defun artwork_ind(width, spacing, turn, outerX, outerY)
{
    decl Bfmoat = 79;

    decl guardRingD = 30;
    decl x0 = 0.0;
    decl y0 = 0.0;

    decl widthG = gridsnap(outerX+guardRingD*2);
    decl d =  gridsnap(widthG*(sqrt(2)-1));
    decl k = gridsnap(d/sqrt(2));

    decl i;

    de_set_layer(Bfmoat);


de_add_polyline();
    de_add_point(x0,y0); //A1
    de_add_point(x0-d/2,y0); //A2   
    de_add_point(x0-d/2-k,k);  // A3
    de_add_point(x0-d/2-k,k+d);  // A4
    de_add_point(x0-d/2,2*k+d);  // A5
    de_add_point(x0-d/2+d,2*k+d);  // A6
    de_add_point(x0-d/2+d+k,k+d);  // A7
    de_add_point(x0-d/2+d+k,k);  // A8
    de_add_point(x0+d/2,y0);  // A9
    de_add_point(x0,y0);  // A1
de_end();

    
de_end_command();
de_set_layer(Bfmoat);
}
 

Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top