Skip navigation
All Places > Keysight Blogs > EEsof EDA > Blog
1 2 3 Previous Next

EEsof EDA

123 posts
IC-CAP comes with a powerful library of transforms and examples to help with model parameter extraction but when implementing custom analysis routines, it is sometimes necessary to use Python with external Python libraries like Numpy or SciPy for manipulating your measured data. Numpy, in particular, has a rich set of numerical processing features.  Why not leverage these functions and libraries?

Sounds good, but you should not blindly use 3rd party libraries without understanding the performance or accuracy of the functions and whether or not they meet your requirements. An example is computing the first order derivative of an I-V curve, a common task in device modeling. There are multiple methods for computing the derivative using finite differences, which can produce different results due to round-off errors or other numerical artifacts. I'm going to demonstrate several methods for computing a derivative and compare the results to show you how to evaluate and implement the best numerical method for your application.

What is a Derivative?


Definition 1:
The mathematical definition of the derivative of a function f(x) at point x is to take a limit as "h" goes to zero of the following expression:

df/dx ~ ( f(x+h) - f(x) ) / h

Approximations of this form are called "finite differences", of which there are many variations.

Definition 2:
A better way of numerically computing the derivative for the same value of "h" is by taking a symmetrical interval around x as follows:

df/dx ~ ( f(x + h/2) - f(x - h/2) ) / h

This particular difference formula is often called a "second-order centered difference" method, while Definition 1 is known as a "first-order forward difference" method. Since these numerical methods are really just approximations, the "second-order" and "first-order" refer to the accuracy.  Second-order means that the error in the approximation decreases with decreasing h proportional to h*h, while first-order decreases only proportional to h.
If we think about "h" as a Dx,  we can see from the figure above that the symmetrical central difference method provides a better estimate of the derivative at point x.
Finite difference method for computing derivatives
(Image courtesy of Wikimedia.  By Kakitc - Own work, CC BY-SA 4.0)

 

 

The python_derivative_v1_1.mdl IC-CAP model file attached at the bottom of this post includes several transforms to compute the derivative:

 

  • Using Python Numpy functions - gradient() and diff()

  • Using the PEL (Programming Extraction Language) derivative function explored in a transform named Test_PEL

 

 

I will illustrate the use of IC-CAP's built-in derivative functions in PEL as follows.


########################################################################################
#  Test_PEL 
#  Computes the derivative of I-V data using PEL derivative2 function
########################################################################################
complex x[34] x[0]=0 x[1]=0.05 x[2]=0.1 x[3]=0.15 x[4]=0.2...x[33]=1.65
complex y[34] y[0]=8.33E-12 y[1]=3.607E-11 y[2]=1.577E-10 y[3]=6.9396E-10 y[4]=3.0463E-9...y[33]=1.7874E-5

der = derivative2(x,y,1,34)

print der

complex gm.M.11[size(der)]

i=0
while i < 34
  gm.M.11[i] = der[i]
  i = i + 1
end while
return gm

 

I wanted to implement the same derivative calculation using the IC-CAP Python environment. I've developed a new library for implementing some numerical methods including two different derivative functions that can be called from our transforms. This ic_math.py file is included as an attachment to this article. Download the file and copy it to your ICCAP_USER_PYTHON_PATH (typically "C:\Users\<username>\iccap\python").

 

In my first attempt, I used the diff function from the Numpy library as shown in the function icm_derivative_npdiff code listing from ic_math.py:

 

import numpy as np

def icm_derivative_npdiff(x,y):
   # create numpy array and initialize
   dydx = np.zeros([len(x),])
   # create numpy arrays
   dx = np.zeros([len(x),1])
   dy = np.zeros([len(y),1])

   # flatten and copy arrays
   dx.flat[:] = x
   dy.flat[:] = y
   # compute diff function for x and y values
   # uses first order forward differencing method
   ddx = np.diff(x)
   ddy = np.diff(y)
   # compute the derivative
   dydx = ddy/ddx

   return dydx

 

Now that we have the function defined in our library we can import it from our Test_npdiff transform and call the function to compute the derivative of our sample I-V data set.

 

 

#############################################################################################

#  Test_npdiff.py 
#  Computes the derivative of I-V data using Numpy Diff function
#############################################################################################
from iccap import set_return_array
import numpy as np
import ic_math as m

# Using I-V data Id vs. Vg
x = np.array([0, 0.025, 0.05, 0.075, 0.1, 0.125, 0.15, 0.175, 0.2, 0.225, 0.25, 0.275, 0.3, 0.325, 0.35, 0.375, 0.4, 0.425, 0.45, 0.475, 0.5])

 

y = np.array([1E-14, 5.1E-14, 1.23E-13, 2.52E-13, 4.58E-13, 8.73E-13, 1.612E-12, 2.932E-12, 5.418E-12, 1.0036E-11, 1.8614E-11, 3.4948E-11, 6.5647E-11, 1.23711E-10, 2.33938E-10, 4.42538E-10, 8.39282E-10, 1.59355E-9, 3.04727E-9, 5.797E-9])

 

# forward difference approximation

dydx = m.icm_derivative_npdiff(x,y)

if debug: print dydx

 

gm = [ dydx[i] for i in range(0,len(x)-1) ]

if debug: print "initial gm = {}".format(gm)

 

# insert dydx starting element to gm at index = 0

# dydx array has 1 less value due to diff function return

gm.insert(0,1E-10)

if debug: print "gm = {}".format(gm)

 

set_return_array("M", gm)

 

In my experience, this is usually adequate and the error is negligible when performing extractions of threshold voltage Vth from the Id vs. Vg characteristics of a MOSFET transistor.  During this calculation, we compute the derivative of Id with respect to Vg and then find the maximum of the derivative (i.e. Gm_max).  At that interpolated Vg, we define a linear function whose slope is equal to Gm_max to superimpose on the IdVg curves. This is illustrated in Ma Long's blog post entitled "Device Modeling 101 - How to Extract Threshold Voltage of MOSFETs." The error in performing these steps is usually greater than any round-off error that may have occurred in computing the derivative. In other words, the simple forward difference approximation for the derivative is usually close enough for this application. 

 

After running the Test_npdiff transform and comparing the results to the built-in IC-CAP PEL function, I noticed that there was a discrepancy in the computed derivatives, especially in the first points of the I-V curve. The numpy.diff() function was slightly under-estimating the derivative even-though the overall slope of the line was pretty close. The maximum error was at the lower boundary of the curve. Furthermore, the vector returned was one point less in length.  When plotting the derivative result against the original I-V data, I had to pad the first point to realign the data points.

 

iccap_derivative_comparison_plot

 

Was there an error in my math?  Looking at the PEL implementation of the derivative, I noticed that it was using a central difference approximation method which is often more accurate. The simple algorithm shown above using numpy.diff() uses the forward difference approximation method, which can be subject to round-off errors when the step size is small. 

 

After some more investigation into the Numpy library functions, I discovered a function that will produce the same result of the Test_PEL transform - the numpy.gradient() function. This function uses the second order accurate central difference method for most of the vector. Furthermore, the vector length is preserved, by gracefully handling the lower and upper boundaries. To evaluate this method, I created an additional Python function in the ic_math library called icm_derivative_npgrad to implement the gradient method as shown below in the code listing:

 

def icm_derivative_npgrad( x, y, e1, e2 ):
   # create numpy array and initialize
   dydx = np.zeros([len(x),])
   # create numpy arrays
   dx = np.zeros([len(x),1])
   dy = np.zeros([len(y),1])

   # flatten and copy arrays
   dx.flat[:] = x
   dy.flat[:] = y

   # compute gradient function for x and y values
   # uses second order central differencing method
   ddx = np.gradient(x, edge_order=e1)
   ddy = np.gradient(y, edge_order=e2)

   # compute the derivative
   dydx = ddy/ddx
   return dydx

 

 

Now we can call the new icm_derivative_npgrad function from our transform named Test_npgrad which will uses the gradient function.

 

#############################################################################################
#  Test_npgrad.py 
#  Computes the derivative of I-V data using Numpy Gradient function
#############################################################################################
from iccap import set_return_array
import numpy as np
import ic_math as m

 

# using I-V data Id vs. Vg
x = np.array([0, 0.025, 0.05, 0.075, 0.1, 0.125, 0.15, 0.175, 0.2, 0.225, 0.25, 0.275, 0.3, 0.325, 0.35, 0.375, 0.4, 0.425, 0.45, 0.475, 0.5])

 

y = np.array([1E-14, 5.1E-14, 1.23E-13, 2.52E-13, 4.58E-13, 8.73E-13, 1.612E-12, 2.932E-12, 5.418E-12, 1.0036E-11, 1.8614E-11, 3.4948E-11, 6.5647E-11, 1.23711E-10, 2.33938E-10, 4.42538E-10, 8.39282E-10, 1.59355E-9, 3.04727E-9, 5.797E-9])

 

# forward difference approximation

dydx = m.icm_derivative_npgrad(x,y,1,2)

if debug: print dydx

 

gm = [ dydx[i] for i in range(0,len(x)-1) ]

if debug: print "initial gm = {}".format(gm)

 

set_return_array("M", gm)

 

You may notice that I've used a new function set_return_array() added to the IC-CAP 2018 Python API which returns a list from a temporary variable to the Transform dataset. This allows this data to be accessible for plotting and is analogous to the RETURN statement in PEL. 

 

As you can see from the table below, the icm_derivative_npgrad function yields exactly the same results as the PEL derivative2 function.  Meanwhile, the numpy.diff function underestimates the derivative.  I padded the numpy.diff() generated gm data so the first point is non-zero and of the same magnitude of the other data to allow easily plotting the results above.  See that the blue and green traces in the graph above are right on top of each other.

 

 

 

iccap derivative comparison table

 

Conclusion

There have been some requests on the SciPy forums to improve the derivative function in the SciPy math libraries to include more accurate methods for calculating the derivative.  But it is up to the open-source community to prioritize the development and release this feature. For now you can still use functions like numpy.gradient() to perform the same derivative computation as the built-in libraries in IC-CAP.  This kind of trade-off between accuracy is quite common with numerical methods for computing derivatives. There are some other 3rd Party libraries that support other methods for numerical differentiation but often require more compute time.  

In my previous post, I showed you the "all-in-one" method for adding your Verilog-A models to ADS. In this post, I'll show you another method called "shared library." It's a bit more work to set up, but it saves time in the long run because it avoids duplication of effort in each new project. If you give a project workspace to a colleague you have to remember to give the referenced library also. In fact, this shared library method is just good not only for Verilog-A components but also for component models of other types (e.g. netlist-based models/model cards). It's a good method anytime you have component models that are common to several projects. Like last time, there are quite a few steps, but each one is really easy.

Shared Library

  1. Launch ADS. From the ADS Main Window menu bar, select File-->New-->Workspace
  2. In the "New Workspace" dialog box, give your new workspace a name such as shared_wrk 
  3. Click on the "Create Workspace" button
  4. Right click on the workspace folder (it has a green "W" on it) and from the popup context menu, select the bottom option namely "Explore In File System". On Windows, File Explorer opens and you can see all the files in your workspace.
  5. In File Explorer, right click and select New-->Folder
  6. Name the folder veriloga (This name is in the simulator's search path by default, so you can be sure your Verilog code will be found when it comes time to compile and link it.)
  7. Open the new folder and create a new plain text file called resistor.vams . Using your favorite text editor, open the blank file and copy-paste the Verilog code from the previous posting into it. Save and close the file. Close File Explorer.
  8. From the ADS Main Window menu bar, select File-->New-->Schematic
    (There is also a short cut icon:New Schematic Window iconif you prefer)
  9. In the "New Schematic" dialog box, give the cell a name such as resistor_va. You are creating not only a schematic but also a cell. The schematic is a view into that cell, and a cell is simply a piece of circuitry in your design hierarchy. It is important that the cell name, resistor_va in our case, is different from the module name, resistor , in the Verilog code. If the two have the same name, it creates an ambiguity that the simulator cannot resolve. A name pairing convention like resistor_va for the cell and resistor for the module is convenient to show which ADS cell refers to which Verilog code module.
  10. Click on the "Create Schematic" button
  11. From the newly created Schematic window menu bar, select "Insert-->Pin". The cursor will change to the "ghost" of a pin.
  12. Place two pins by clicking once anywhere on the schematic canvas, shift left a bit, click again, then hit the Escape key. You don't need to wire them to anything. We are going to "wire" them to the Verilog code in the next few steps. 
  13. From the Schematic window menu bar select File-->Design Parameters.
  14. In the Design Parameters dialog box's General Cell Definition tab, set the Component Instance Name to whatever prefix you want instances to have. For example, accepting the default X will result in instances being called X1, X2, X3, etc. You might want to pick R or something.
  15. In the Simulation panel, select "Built-in Component" from the Model drop down list and over-type the text resistor in the "Simulate As" edit box, i.e. the module name in the line  module resistor(p, n); of your Verilog code. 
  16. Switch to Cell Parameters tab of the Design Parameters dialog box. Remember the line parameter real r=0.0; in the Verilog code? Here is where you connect to it. In the Edit Parameter: Parameter Name edit box type r, leave the Value Type as "Real", set Default Value to 0, set Parameter Type/Unit to Resistance, and type "Resistance in ohms" for the parameter description.
  17. Look to the left side of the same tab, and click on the "Add" button. The r parameter will be added to the parameter list box.
  18. Click OK to dismiss the Design Parameters dialog box.
  19. Go back to the schematic window, and select File-->Save.
  20. So far we only have a schematic view into our cell. Next we create a symbol view into that same cell. A symbol view is kind of a "black box" view of the cell. (Later on we'll drag and drop the symbol view onto a testbench schematic to instantiate it.) To create a symbol, select Window-->Symbol from the schematic window menu bar.
  21. In the New Symbol dialog box, keep the default cell name resistor_va and click the Create Symbol button. 
  22. In the Symbol Generator dialog box, select the Copy/Modify tab, then select "Lumped-Components" from the Symbol category drop down list. Click on the resistor icon. The Symbol name edit box will populate as ads_rflib:R . Click OK to dismiss the Symbol Generator dialog box.
  23. In the Symbol drawing canvas you can see the symbol as been automatically created. (As you get more advanced, you can draw your own symbols if you are feeling artistic!)
  24. From the Symbol window menu bar, select File-->Save. We are done with this window, so you can close it if you like.
  25. Go back to the ADS Main Window, Folder View tab. Click on the little arrow to open the resistor_va cell folder. (Cell folders have a C on them.) You can see that your cell now has two views: the original schematic view and the new symbol view.
  26. In the Main window, select the Library View tab. When you created the workspace, ADS automatically created a default library under it. The default name is created by replacing the _wrk suffix with a _lib suffix. So in our case it is called shared_lib. Right click on the library and select Configure Library... from the popup context menu.
  27. In the Library Configuration Editor, Simulation tab, click on the Browse... button to the right of the Verilog-A directory edit box. Browse up one level and select the veriloga folder. Alternatively, you can just type ..\veriloga into the edit box. The relative path-name is preferred over an absolute path because if you give the library to a colleague, they might install it with different root name. Dismiss the Library Configuration Editor by clicking on the OK button. It reminds you that changes will take effect next time you open it. Click OK.
  28. From the main window menu bar, select File-->Close Workspace. We are done with the shared library for now.
  29. From the ADS Main Window menu bar, select File-->New-->Workspace...
  30. From the New Workspace dialog box, give it a name like project1_wrk and then click the Create Workspace button.
  31. From the Main window menu bar, select File-->Manage Libraries...
  32. From the Manage Libraries dialog box, click on the "Add Library Definition File..." button.
  33. From the Select Library Definition File browser, navigate to the previous workspace (i.e. your shared_wrk folder) and locate and select a file called lib.defs then click the Open button.
  34. Dismiss the Manage Libraries dialog box by clicking on the Close button.
  35. In the Main window, click on the little arrow by the resistor_va cell folder. You should see schematic and symbol views of the cell.
  36. From the Main window menu bar, select File-->New-->Schematic... and name its cell something like testbench.
  37. Create Arrange the Main window and the new testbench schematic window side-by-side.
  38. Click and drag the resistor_va symbol from the Main window to the testbench schematic window. Instantiate your resistor by clicking anywhere on the schematic canvas. Set it to 2 ohms.
  39. Create a simple testbench like this:
    testbench
  40. Click on the Simulate icon or select Simulate-->Simulate or just hit the F7 shortcut key. The first time you simulate, there is a short pause while ADS compiles the Verilog code. It saves the compiled model, so if you don't touch the code, there is no need to re-compile the next time you run it.
  41. From the Data Display window, insert a plot, and select the Vout and branch current (_ub_p_n_i) traces:
    voltage and current through 2 ohm resistor
    I added some markers and played around with the axis and trace settings.

Success! Now you create project_2, project_3 and so on. Repeat steps 29-41 for each new project to refer to your shared library thus reusing it.

 

In the next posting, we'll return to the main topic: how to translate the analog parts of VHDL-AMS to Verilog-A. Part 1 was a resistor. Part 4 will be a comparison of how the two languages handle time derivatives using the capacitor and inductor as examples.

In my previous post, I showed you how to create the Verilog-A code for a component model. In this post I'll show you how to import that code into ADS. If you don't have access to ADS or you're not familiar with it, I suggest you read our Quick Start Guide first.

 

There are two strategies for adding component models to an ADS workspace, let's call them "all-in-one" and "shared library" methods. "All-in-one" is the simplest and as the same suggests it is self-contained. "Shared library" is a bit more work to set up, but it saves time in the long run because it avoids duplication of effort: Each new project can reference the same library of components. If you give this type of project workspace to a colleague you'll have to remember to give the referenced library also.

 

I'll do the all-in-one method in this post and the shared library in the next. There are quite a few steps, but each one is really easy.

All-in-one method

  1. Launch ADS. From the ADS Main Window menu bar, select File-->New-->Workspace
  2. In the "New Workspace" dialog box, give your new workspace a name such as verilog_test1_wrk 
  3. Click on the "Create Workspace" button
  4. Right click on the workspace folder (it has a green "W" on it) and from the popup context menu, select the bottom option namely "Explore In File System". On Windows, File Explorer opens and you can see all the files in your workspace.
  5. In File Explorer, right click and select New-->Folder
  6. Name the folder veriloga (This name is in the simulator's search path by default, so you can be sure your Verilog code will be found when it comes time to compile and link it.)
  7. Open the new folder and create a new plain text file called resistor.vams . Using your favorite text editor, open the blank file and copy-paste the Verilog code from the previous posting into it. Save and close the file. Close File Explorer.
  8. From the ADS Main Window menu bar, select File-->New-->Schematic
    (There is also a short cut icon:New Schematic Window iconif you prefer)
  9. In the "New Schematic" dialog box, give the cell a name such as MyR. The schematic is a view into cell. A cell is simply a piece in your design hierarchy.
  10. Click on the "Create Schematic" button
  11. From the newly created Schematic window menu bar, select "Insert-->Pin". The cursor will change to the "ghost" of a pin.
  12. Place two pins by clicking once anywhere on the schematic canvas, shift left a bit, click again, then hit the Escape key. You don't need to wire them to anything. We are going to "wire" them to the Verilog code in the next few steps. 
  13. From the Schematic window menu bar select File-->Design Parameters.
  14. In the Design Parameters dialog box's General Cell Definition tab, set the Component Instance Name to whatever prefix you want instances to have. For example, accepting the default X will result in instances being called X1, X2, X3, etc.
  15. In the Simulation panel, select "Built-in Component" from the Model drop down list and over-type the text resistor in the "Simulate As" edit box. This text should match the module name in the line  module resistor(p, n); of your Verilog code. One warning: it is important that the cell name, MyR in our case, is different from the module name resistor. If the two have the same name, it creates an ambiguity that the simulator cannot resolve. If you have a big component library, you might want to consider a name pairing convention like resistor_va for the cell and resistor for the module so you easily know which ADS cell refers to which code module.
  16. Switch to Cell Parameters tab of the Design Parameters dialog box. Remember the line parameter real r=0.0; in the Verilog code? Here is where you connect to it. In the Edit Parameter: Parameter Name edit box type r, leave the Value Type as "Real", set Default Value to 0, set Parameter Type/Unit to Resistance, and type "Resistance in ohms" for the parameter description.
  17. Look to the left side of the same tab, and click on the "Add" button. The r parameter will be added to the parameter list box.
  18. Click OK to dismiss the Design Parameters dialog box.
  19. Go back to the schematic window, and select File-->Save.
  20. So far we only have a schematic view into our cell. Next we create a symbol view into that same cell. A symbol view is kind of a "black box" view of the cell. (Later on we'll drag and drop the symbol view onto a testbench schematic to instantiate it.) To create a symbol, select Window-->Symbol from the schematic window menu bar.
  21. In the New Symbol dialog box, keep the default cell name MyR and click the Create Symbol button. 
  22. In the Symbol Generator dialog box, select the Copy/Modify tab, then select "Lumped-Components" from the Symbol category drop down list. Click on the resistor icon. The Symbol name edit box will populate as ads_rflib:R . Click OK to dismiss the Symbol Generator dialog box.
  23. In the Symbol drawing canvas you can see the symbol as been automatically created. (As you get more advanced, you can draw your own symbols if you are feeling artistic!)
  24. From the Symbol window menu bar, select File-->Save. We are done with this window, so you can close it if you like.
  25. Go back to the ADS Main Window. Click on the little arrow to open the MyR cell folder. (Cell folders have a C on them.) You can see that your cell now has two views: the original schematic view and the new symbol view.
  26. From the ADS Main Window menu bar, create a schematic of a second cell by selecting File-->New--Schematic... as before. This will be our top-level cell. Call this new cell "testbench."
  27. Arrange the Main window and the new testbench schematic window side-by-side.
  28. Click and drag the MyR symbol from the Main window to the testbench schematic window. Instantiate your resistor by clicking anywhere on the schematic canvas. Set it to 2 ohms.
  29. Create a simple testbench like this:
    testbench
  30. Click on the Simulate icon or select Simulate-->Simulate or just hit the F7 shortcut key. The first time you simulate, there is a short pause while ADS compiles the Verilog code. It saves the compiled model, so if you don't touch the code, there is no need to re-compile the next time you run it.
  31. From the Data Display window, insert a plot, and select the Vout and branch current (_ub_p_n_i) traces:
    voltage and current through 2 ohm resistor

Success!

The next posting shows you the shared library method. A lot of the steps are the same, except we create separate workspaces for our component library and our test bench, and link the two.

Verilog-AMS and VHDL-AMS are hardware description languages, capable of describing mixed-signal (i.e. analog and digital) hardware. In this series of postings, we’ll be talking about Verilog-A (i.e. the officially defined subset of Verilog-AMS that supports analog) and “VHDL-A” (not officially defined, but defined here as "the parts of VHDL-AMS that supports analog").

 

ADS support Verilog-A but not VHDL-A so this series of posting will explain how to create a Verilog-A model if all you have to start from is a VHDL-A model. It isn’t a comprehensive Verilog or VHDL reference manual: you can find plenty of those by searching on the Internet. The idea here is to get you started. You’ll have to refer to those other resources for the in-depth information. Another good resource is Best Practices for Compact Modeling in Verilog-A, J. Electron Devices Soc. (Aug. 2015) by Colin C. McAndrew et al. It's not about how to code models in Verilog-A, it's about how to code them well. 

 

Let jump right in and compare how the two languages express the simplest possible analog component, the resistor:

 

Code fragment 1a: Resistor in VHDL-A

use electrical_system.all;
entity resistor is
   generic (r: real := 0.0);
   port(terminal p, n: electrical);
end entity resistor;
architecture signal_flow of resistor is
   quantity vr across ir through p to n;
begin
   vr == ir * r;
end architecture signal_flow;

 

Code fragment 1b: Resistor in Verilog-A

`include "disciplines.vams"

module resistor(p, n);
     parameter real r=0.0;
     inout p, n;
     electrical p, n;
     analog begin
           V(p,n) <+ I(p,n)  * r;
     end
endmodule

Both code fragments start by including standard libraries:

VHDL-A has:

use electrical_system.all;

…and Verilog-A has:

`include "disciplines.vams"

We won’t go into the contents of these yet. Suffice it to say that they serve a similar purpose, namely to save you from writing the basic “plumbing” required to set up your model.

 

The two languages diverge in the next lines.

 

VHDL-A divides the code up into entity and architecture sections. The entity keyword is used to introduce the description of the interface of the component. Here we define ports p and n and a parameter, r. Then, the architecture keyword is used to introduce the description of its internal details. An entity can have more than one architecture ("polymorphism"), so we have to give each one a name, signal_flow in this case, so we can specify which morphology we want to use later on. To implement an architecture with ohmic behavior, we first state explicitly that the voltage V and current I are the across and through variables, respectively, of our ports with:

quantity vr across ir through p to n

 

(Side note: The terminology “through and across variables” comes from the mathematics of the class of problem that all SPICE-like solvers solve, namely differential algebraic equations or DAEs. In Verilog-A, through and across variables like voltage and currents are called "natures" and a pair of related through and across variables is called a "discipline." Voltage and current natures, plus some other information like tolerances, form the electrical discipline. Confusingly, VHDL-A uses the term "nature" where Verilog-A uses "discipline.")

 

Then we specify Ohm’s law, V=IR, for the branch constitutive equation:

 

 vr == ir * r

The "double equal signs" operator implies the simulator should force the equation to be true for every time step in the simulation: it isn’t a one-time assignment like the a = b in C and Java nor the a := b in Pascal and ADA. (And it isn't at all like the equality test A == B in C and Java.)

 

In contrast, Verilog-A combines the entity/architecture ideas. The module keyword is used to introduce both interface (the parameter, inout, and electrical lines) and the internals (the block that is bounded by analog begin end ).

The line:

V(p,n) <+ I(p,n)  * r;

...is called a contribution statement. It is similar to the one in VHDL with double equals == except that the operator in Verilog-A is <+ .

(Side note: Why <+ ? It's because Verilog-A allows multiple contributions to add to the voltage V(p,n). For example,

V(p,n) <+ V(p2,n2);

V(p,n) <+ V(p3,n3);

…is equivalent to:

V(p,n) <+ V(p2,n2)+ V(p3,n3);

)

Similar to == in VHDL, <+ in Verilog-A implies the simulator should do whatever it takes to force the equation to be true for every time step in the simulation.

 

In Verilog-A, there is no need for a line like quantity vr across ir through p to n that we had in VHDL because the functions V() and I() are defined in the included library and thereby associated with any instances in the electrical discipline.

 

So, that's a component. Part 2 shows you how include the Verilog-A version into ADS create a testbench that instantiates the component, adds some stimulus, and shows you the response.

 

 

IC-CAP comes with a powerful API for accessing internal variables and data structures. In what follows, we will illustrate an example of accessing a Setup's Inputs and Outputs to obtain parameter values for the bias conditions for our custom Python measurement routines using the TableVar object.

 

What might be a typical approach?
When configuring a source measurement unit (SMU) to define start and stop voltages for a measurement sweep, you might use multiple setup variables stored in the Setup Variables table like this:

 

Setup Variables in IC-CAP

 

Then use some Python statements to read the parameter values from the table.

 

# query setup variables
vg_start = SVar("vgstart").get_val()
vg_stop = SVar("vgstop").get_val()
vg_step = SVar("vgstep").get_val()
vg_pts = SVar("vgpts").get_val().split(".")

 

But instead, I'm going to show you how to read the measurement configuration values entered in the Measure/Simulate tab and use these values in your Python code.

 

Measure/Simulate Tab


This allows you to set parameters in the Measure/Simulate tab just like when using the native IC-CAP instrument drivers in normal Measure mode.  Now you can use the built-in IC-CAP user interface to modify the parameters. In using this method, you will have to select the Extract/Optimize tab, select the transform and then click the Execute button to invoke your custom Python transform.

 

Prerequisites

 

If you have not already setup your Python virtual environment and have IC-CAP installed, please refer to my previous article Measuring Sub-Threshold MOSFET Characteristics Using a Quasi-Static I-V Method.

 

Depending on whether you are using an older Agilent 4156B/C or a newer Keysight E5270B for your SMU, you may download and open one of the IC-CAP model files included at the end of this post.

  • py_api_demo_5270_v.2.0.mdl
  • py_api_demo_4156_v.2.0.mdl 

The Python code included for the E5270B can be applied to the B1500A with almost no modification as their command sets are very similar. Similarly, the code for the 4156B/C can be used with a 4142B with minor modification because we are using the US42 command mode using Flex commands. 

 

I recommend saving the *.mdl to C:\Keysight\ICCAP_2018\examples\python.  

 

Load the IC-CAP Model File

 

Assuming you saved the model file to the location above, click File/Examples... and select: 

python\py_api_demo_5270_v.2.0.mdl.

 

Go to the DUT/Setup called dc/idvg_quasi. Select the Measure/Simulate tab and observe the settings for the Inputs and Outputs. Notice that we have set conditions to make the Id vs. Vg measurement using IC-CAP's built-in drivers. Now select the Setup Variables tab and review the variable table.

 

Name            Value               Comment
drain           1                   Drain SMU Channel
gate            2                   Gate SMU Channel
source          3                   Source SMU Channel
substrate       4                   Substrate SMU Channel
interface       GPIB0:17::INSTR     VISA instrument resource
visaResponse                        VISA response string
error_status    32,48,128           Status bytes to check for errors
error_command   ERR?,EMG?,ERRX?     Commands to process error events
hold_bias       0.0                 Bias applied during hold time period
hold            0.5                 Hold time before first measurement, in seconds
delay           0.1                 Delay time
step_delay      0.2                 Step delay time

 

Certain measurement configuration parameters like hold, delay and step delay parameters would normally be set in the Instrument Options of the IC-CAP instrument driver, but because we have not configured an IC-CAP instrument driver, we will read these parameters from the Setup Variables instead.

# add variables for instrument options and other variables
polarity = MVar("POLARITY").get_val() 

# get setup variables
hold=float(SVar("hold").get_val())
delay=float(SVar("delay").get_val())
step_delay=float(SVar("step_delay").get_val())

...

 

In our previous IC-CAP model file, the bias conditions for the gate sweep, drain, source and substrate values were stored in the Setup Variables table then read from table and assigned to local variables.  In this latest version we have removed these values from the SVars table and will define them in the _init Python transform, as shown below.

 

Note: You may need to change the SMU channel assignments ('drain', 'gate', 'source', 'substrate') to match the configuration of your instrument. For example, your Drain SMU Channel may be slot 5, not slot 1.

 

Exploring the _init transform

 

Select the Extract/Optimize tab and then select the _init transform.

 

New initialization code has been added to the _init transform relative to previous versions of the example mdl files. In this example, we will use functions provided by IC-CAP to query the settings of the Inputs from the user interface in the Measure/Simulate tab to set the measurement conditions for our quasi-static "Id vs. Vg" MOSFET measurement. 

 

idvg_quasi Init transform

 

The following Python local variables in our _init transform will be used to store the measurement parameters from the defined Inputs.

Variable Name   Description
vgstart         Gate sweep start voltage
vgstop          Gate sweep stop voltage
vgstep          Gate step size
vgpts           Gate points
igcompl         Gate current compliance
vdvalue         Drain voltage (constant)
idcompl         Drain current compliance
vsvalue         Source voltage (constant)
iscompl         Source current compliance
vbvalue         Bulk voltage (constant)
ibcompl         Bulk current compliance

 

We will use these variables the instrument specific SMU commands to programmatically control the quasi-static sweep. 

 

Setup Object and Methods

 

Instead of using the IC-CAP function call SVar(“Varname”).get_val(), we will be using the TableVar object provided by IC-CAP's Python environment.  Thanks to the iccap python module, we can programmatically define, manipulate and query DUTs, SetupsTransforms, Inputs and Outputs.  In order to access the TableVar object of the Input and query its values, we will need a reference to its parent Setup object.

 

Let’s define an object representing the idvg_quasi Setup by name. You will find these two statements in the _run transform.

 

s = Setup("/py_api_demo_5270/dc/idvg_quasi")
setupName = s.get_fullname()

 

We can now query this object for its properties (assuming debug = 1)

 

# query setup
if debug: print "fullname:",s.get_fullname()
if debug: print "name:", s.name
if debug: print "mytype:", s.mytype

 

Setup query response:

fullname: /py_api/demo/5270/dc/idvg_quasi

name: idvg_quasi

mytype: Setup

 

With a for loop, we can query the sweeps defined for the Setup.  

 

# query sweeps with order
if debug:
   for sweepid.range(1,2):
      inputobj = set.get_sweep(sweepid)
      if inputobj == None: break
      print "Sweep ", sweepid, s.get_fullname()

In this case, we have only a 1st order sweep.

Sweep query response:

Sweep 1 /py_api_demo_5270/dc/idvg_quasi

 

Now, I will show you how to query some of the other parent/child hierarchies so that you get an idea of the type of information that is available to your Python programs.

 

We can query the setup object for children objects in its hierarchy.

 

# query child objects and type
if debug:
   print "child objects of Setup:"
   for objchildtype in s.childtypetuple:
      print objchildtype
      for objchild in s.get_child_objects(objchildtype):
         print " ", objchild.name
         print

 

Child object query response:

child objects of Setup:

Input

      vd

      vg

      vs

      vb

Output

      id

Transform

      _run

      _init

      _setup_iv

      _meas_iv

      _close

      _calc_vth

      README

SVar

      fileName_PATH

      fileName_PATH

      drain

      gate

      source

      substrate

      interface

      visaResponse

      error_status

      error_command

      hold_bias

      hold

      delay

      step_delay

      MDM_FILE_PATH

      MDM_FILE_NAME

Plot

      ThresholdVoltageIdsvsVgs

 

One may query any Setup for these properties and then assign them to local variables for use in your Python code.

 

Input/Output Objects

 

We will read the Input values from the IC-CAP TableVar objects and assign them to a Python string variable. Let's start with the Sweep parameters for the vg source.

 

vg = Input(setupName + "/vg")

 

The full statement will expand to Input("/py_api_demo_5270/dc/idvg_quasi/vg").  Like the Setup object,  the Input object also provides functions for returning information like full_name, name, and type.

 

# build full name for the sweep input
sweepName = vg.get_fullname()

 

Using the Input object vg, we set a variable sweepName for the fullname returned from the Input, we can read each of the vg Input's sweep TableVar parameters including: Compliance, Start, Stop, Step Size and # of Points.

 

igcompl = TableVar(sweepName + "/Compliance")
vgstart = TableVar(sweepName + "/Start")
vgstop = TableVar(sweepName + "/Stop")
vgstep = TableVar(sweepName + "/Step Size")
vgpts = TableVar(sweepName + "/# of Points")

 

We now have pointers to the following:

 

iccap_idvg_quasi_input_vg

 

We can now query various properties of our newly created TableVar object.

# query TableVar
if debug: print "fullname :", igcompl.get_fullname()
if debug: print "name :", igcompl.name
if debug: print "mytype :", igcompl.mytype
if debug: print "value :", igcompl.get_val()
if debug: print

# query TableVar
if debug: print "fullname :", vgstart.get_fullname()
if debug: print "name :", vgstart.name
if debug: print "mytype :", vgstart.mytype
if debug: print "value :", vgstart.get_val()
if debug: print

 

With the debug flag enabled, we obtained the following results in the IC-CAP Output window:

full_name : /py_api_demo_5270/dc/idvg_quasi/vg/Compliance
name : Compliance
mytype : TableVar
value : 0.1

full_name : /py_api_demo_5270/dc/idvg_quasi/vg/Start

name : Start

mytype : TableVar

value : 0.0

 

...

 

Using the TableVarObject.get_val() method, we define local variables and cast the returned string to an appropriate float or integer types for later calculations.

 

# set gate sweep parameter values
vg_start = float(vgstart.get_val())
vg_stop = float(vgstop.get_val())
vg_step = float(vgstep.get_val())
ig_compl = float(igcompl.get_val())
vg_points = int(vgpts.get_val().split('.')[0])

 

The type or polarity (NMOS or PMOS) is read from the Model Variable Table as specified in the beginning of the _init transform variables presented above. If its value is PMOS, the values for the gate and drain biases are multiplied by -1, which will appropriately handle the device polarity. 

 

# get the device polarity from the model variable table
polarity = MVar("POLARITY").get_val()
 

 

We can use the value of polarity to invert the sign on Vgs  appropriately for the device type.

 

if polarity == "PMOS":
   vg_start *= -1
   vg_stop *= -1
   vg_step *= -1

 

Querying Constant Input Variable Properties

 

What if the input variable is not swept but is a constant? The Input vd is defined as a CON (constant source type) so the only available properties are the bias value and the compliance.

 

vd = Input(setupName + "/vd")

 

The input vd is queried from just like the vg sweep variable.

 

# build full name for the constant input
constName = vd.get_fullname()

 

Using the Input object vd we set a variable constName for the fullname returned from the Input, we can read each of the vd Input's TableVar parameters including: Compliance and Value.

 

 

idcompl = TableVar(constName + "/Compliance")
vdvalue = TableVar(constName + "/Value")

 

Again, we may query various properties of our TableVar object. A couple examples are provided as follows.

 

# query TableVar
if debug: print "fullname :", idcompl.get_fullname()
if debug: print "name :", idcompl.name
if debug: print "mytype :", idcompl.mytype
if debug: print "value :", idcompl.get_val()
if debug: print

# query TableVar
if debug: print "fullname :", vdvalue.get_fullname()
if debug: print "name :", vdvalue.name
if debug: print "mytype :", vdvalue.mytype
if debug: print "value :", vdvalue.get_val()
if debug: print

 

Executing the code statements above with the debug flag enabled will produce the following in the IC-CAP Output window:

 

full_name : /py_api_demo_5270/dc/idvg_quasi/vd/Compliance

name : Compliance

type : TableVar

value : 0.1

 

full_name : /py_api_demo_5270/dc/idvg_quasi/vd/Value

name : Value

mytype : TableVar

value : 3.0

 

Using the TableVarObject.get_val() method, we define local variables, having cast the returned string to the appropriate float or integer types for later calculations.

 
# set drain parameter values
id_compl = float(idcompl.get_val())
vd_value = float(vdvalue.get_val())

 

Again we can use the value of polarity to invert the sign on Vds appropriately for the device type.

 

if polarity == "PMOS":
   vd_value *= -1

 

A similar approach is implemented to query the constant type inputs vs and vb. 

 

Conclusion

 

With the this modified _init transform, we can now read the bias settings and compliance settings from the Measurement/Simulate tab for the idvg_quasi Setup.

 

iccap_idvg_quasi_run

 

To run this, we will not click the Measure button in Measure/Simulate tab, but instead navigate to the Extract/Optimize tab, select the _run transform and click the Execute button to perform the measurement.

 

Using these powerful IC-CAP objects and functions from the API, you can easily implement custom measurement and extraction routines to provide familiar usage modalities for your engineers who are familiar with the standard IC-CAP user interface.  I hope the information presented here provides some insight to the internal objects, functions and data types available to you through the Python environment within IC-CAP and will help you in implementing your own custom measurements.  More detailed information on all the information presented here can be found in the IC-CAP Python programming examples or the IC-CAP User's Manual.

 

References

IC-CAP 2018 user-manual and documentation

Example model file "py_api_demo.mdl" under Macros


Related Links

 

I'm sure most of you have heard about WBG semiconductors recently; specifically Silicon Carbide (SiC) and Gallium Nitride (GaN).  The primary, but not exclusive, context was probably related to Power Electronics.  So let's explore at a high level why this technology is increasingly getting more and more attention in the Industry.  It basically comes down to simply 3 things – smaller, faster and more efficient electronics.

 

WBG can operate at higher temperatures, handle 10x higher voltages and eliminate up to 90% of the power losses in electricity transfer compared to current technology.  This will result in lower cost electronics and save billions of $s in energy.

 

Power supplies including adapters used to charge laptops, cell phones and tablets use at least 2% of all US energy. WBG can make chargers 3-5 x smaller and cut the heat loss by 75-80%.  This is equivalent to the power generated by 3 Hoover Dams a year!

 

LEDs use WBG semiconductors to produce 10x more light per watt of energy than incandescent bulbs and last 30x longer.

 

At today's energy costs WBG semiconductors are expected to save $250 Billion in cumulative energy costs by 2030.  As more renewable power is connected to the grid we will rely more on WBG electronics to transfer electricity. WBG semiconductors will reduce power losses in transmission by up to 75% leading to smaller power stations and lower cost for renewable energy.  This in turn will lead to lower cost electronics and billions of dollars in energy savings.

 

For Power Devices:

The advantages of SiC over Si for power devices include lower losses for higher efficiency, higher switching frequencies for more compact designs, robustness in harsh environments, and high breakdown voltages.  SiC also exhibits significantly higher thermal conductivity than Si, with temperature having little influence on its switching and thermal characteristics.  This allows operation of SiC devices in temperatures far beyond 150° C, the maximum operating temperature of Si, as well as a reduction in thermal management requirements for lower cost and smaller form factors.

 

For RF Devices:

GaN offers key advantages over silicon.  The high power density of GaN leads to smaller devices as well as smaller designs due to reduced input and output capacitance requirements, an increase in operational bandwidth, and easier impedance matching.  GaN's high breakdown field allows higher voltage operation and also eases impedance matching.  The broadband capability of GaN devices provides coverage for a broad frequency range to support both the application's center frequency as well as the signal modulation bandwidth.  Additional advantages of GaN include lower losses for higher efficiency, and high-temperature operation (in the case of GaN on bulk-GaN substrate).

 

In conclusion, WBG semiconductors will make the next generation of electronics smaller, faster and more efficient – there is little question on this point. This will have huge ramifications for the entire energy/electronics industry – from power stations to renewable energy to electric automobiles to personal computing and communication. All aspects of our lives will be positively impacted by this revolution.  The question for us is not if, but when, the current design methodology and models will hit the proverbial brick wall? 

Please register for a webinar I'm presenting Sept 6th, 2018 at 1PM EDT. The title is Designing Switched-Mode Power Supplies in the High di/dt Era. I hope you will attend!

While IC-CAP is equipped with a powerful library of transforms and examples for performing model parameter extraction, we may extend this power using the built-in Python support in IC-CAP to access external Python libraries, especially when developing new behavioral models or implementing custom analysis routines.

 

In my previous article, I showed how to implement a quasi-static measurement in a series of IC-CAP transforms, demonstrating the flexibility of the data handling capabilities in IC-CAP.  Python modules like pyvisawrapper.py and dataparser.py modules extended the data parsing using external libraries. In this article, I will show you how you can also easily implement custom parameter extraction routines using Python in IC-CAP. Leveraging the work I presented in my previous blog entitled "Measuring Sub-Threshold MOSFET Characteristics Using a Quasi-Static I-V Method", I'll discuss a custom Python transform for extracting the Vth parameter (gate threshold voltage) on the quasi-static Id vs. Vg sweep data of a p-channel MOSFET.

 

We will be implementing the ICON (constant current) method for extracting Gate Threshold Voltage (Vth) from the Id vs. Vg data. This is a popular method due to its simplicity. Other popular methods ( i.e. Id_sat or Max_Gm methods ) can be similarly implemented using custom Python classes and functions.

 

Prerequisites

 

Depending on whether you happen to have an E5270B (or B1500A) or an older 4156C, you might prefer to download the complete IC-CAP model file py_new_api_basic_demo_5270.mdl or py_new_api_basic_demo_4156.mdl attached at the end of this post.

E5270BAgilent 4156C

 

Each model file contains the complete Python source code used to implement the quasi-static measurement. I recommend saving these *.mdl files to C:\Keysight\ICCAP_2018\examples\python, as I described in my previous article Measuring Sub-Threshold MOSFET Characteristics Using a Quasi-Static I-V Method. In these .mdl files we previously created the global arrays vvalue[ ] and ivalue[ ] in the _run transform for storing our forced voltage and measured current data values. In the _calc_vth transform we will access these arrays to extract the Vth value by calling an external Python script extract_vth_cc.py also attached below. You should copy the extract_vth_cc.py to your C:\Users\<username>\iccap\python directory or the directory specified by the environment variable ICCAP_USER_PYTHON_PATH.

 

Load the IC-CAP Model File

 

Assuming you saved the model file to the examples folder (C:\Keysight\ICCAP_2018\examples\python), click 'File/Examples...' and select: python\py_api_new_basic_demo_5270.mdl. (or *_4156.mdl).

 

Select the idvg_quasi Setup, go to the 'Extract / Optimize' tab and then select the _run transform.

The following arrays are defined to store the local I-V measured data:

 

# global list of values
vvalue = []
ivalue = []

...

 

Notice that the global namespace is set in the Function field by selecting PythonGlobal. This gives us access to the ivalue[] and vvalue[] along with vg_points (from the vgpts Setup Variable) which will be used in the extract_vth_cc function _calc_vth() below.

Go to the end of the _run transform and uncomment the following lines of code:

 

# calculate vth
if bOk: iccap_func("_calc_vth","execute")

...

 

Select the idvg_quasi Setup, go to the 'Extract / Optimize' tab and then select the _calc_vth transform.

 

from extract_vth_cc import * 
#################################################################
# _calc_vth.py
#
# Calculate Threshold voltage for IdVg measurement

# Uses _extract_vth which implement Icon method (IdVg@Vb=0)
#
# Device parameters

# W = channel width (um)
# L = channel length (um)
# M = channel mask multiplier
# deltaW = channel width variation
# deltaL = channel length variation 
#
################################################################# 
# get W, L from Model Variables
W = float(MVar("W").get_val())
L = float(MVar("L").get_val())
M = 1.0
icon = 1E-8
deltaW = 0
deltaL = 0
if debug: print "W = {} L = {} M = {} icon = {}
                 deltaW = {} deltaL = {}\n".format(W,L,M,icon,deltaW,deltaL)

if polarity == "PMOS":
   icon *= -1
 
# get Id[] Vg[] from _run
ids = ivalue[:vg_points]
vgs = vvalue[:vg_points] 

# get Id_Vg @ Vb=0
evt = extract_vth_cc(ids, vgs, W, L, M, deltaW, deltaL, icon)
vth = evt.calculate() 

print "vth = ", vth

 

The _calc_vth transform instantiates the extract_vth_cc class and initializes it by passing the measured data arrays ids and vgs along with the device geometry W, L, deltaW, deltaL and icon parameter (constant current value for extracting the gate threshold voltage). Once the extract_vth_cc instance is created, the calculate() function (or method) is called to return the Vgs that gives the current closest to the icon value.

 

Open the Python source code in your favorite editor.

 

Review the implementation of the extract_vth_cc class and calculate method.

 

extract_vth_cc.py source code listing

import numpy as np
from iccap import MVar
##############################################################################
#
# Global variables
#
##############################################################################
# enable/disable debug prints
debug = int(MVar("debug").get_val()) 

# extract_vth_cc script for extracting threshold voltage
class extract_vth_cc:    
   def __init__(self,id,vg,W,L,M,deltaW,deltaL,icon):
       """
       Initialize extract_vth_cc class.

       This function initializes the class used to extract Vth using
       the ICON method.

       Args:
          self:      This instance of the extract_vth_cc class.
           id:        Drain current array values.
           vg:        Gate voltage array values.
           W:         Device channel width.
           L:         Device channel length.
           M:         Channel mask multiplier.
          deltaW:    Channel width variation.
           deltaL:    Channel length variation.
           icon:      Constant current to extract Vth.

       Kwargs:
       Returns:       instance of class

       Raises:
       """
       self.id = id  # a list []
       self.vg = vg  # a list []
       self.W = W
       self.L = L
       self.M = M
       self.deltaW = deltaW
       self.deltaL = deltaL
       self.icon = icon
      
       # calculate and return Vth
       def calculate(self):
          """
          Calculates the gate threshold voltage.

          This function extracts the extrapolated Vth value by using
          the ICON method.

          Args:
             self:      This instance of the extract_vth_cc class.

          Kwargs:

          Returns:
             Vth:       Interpolated gate threshold voltage at icon.

          Raises:
          """
        
        # initialize local variables 
        vth =1E-30
        type = 1       # nmos        
        vg = self.vg
        id = self.id

        # create numpy array and initialize
        nid = np.zeros([len(id),1])
        
        # copy id to numpy array and flatten
        nid.flat[:] = id

        # compute the id reference value from device geometry
        iref = self.icon * self.M * (self.W - self.deltaW)/(self.L - self.deltaL)
        if debug: print "iref = {}".format(iref)
        
        # return the index closest to the reference value
        idx = (np.abs(nid - iref)).argmin()
        if debug: print "idx = {} id = {}".format(idx, id[idx])        
        
        # check if vg is negative - PMOS device type
        if vg[idx] < 0:
             type = -1   # pmos
        
        # return vg @ iref
        Vth = vg[idx]
        return Vth

 

Notice the use of Numpy arrays in the code above. The Numpy python module provides very convenient methods for processing array variables. (You'll never go back to PEL...) The zeros method creates a new Numpy array the length of the data ("len(id)") and initializes all values to 0.  Once the Numpy array is created and initialized, the flat method is used to iterate the 1D array while copying the id array values to the local nid array. The algorithm scales the constant current icon based on device geometry to calculate a reference current iref. Using this iref value, the index of the data point is returned which is closest to our target. This resulting index is used to return the value of the element of the vg array which is the Vth value.

 

Conclusion

 

You can quickly create reusable custom extractions or analysis routines using Python to start building your own modeling library. I hope this quick example of extracting gate threshold voltage will serve as a starting point for developing your own custom routines for use in IC-CAP. In follow on articles, I will demonstrate additional features of IC-CAP to streamline and customize your Python transforms using the IC-CAP's built-in user interface elements and TableVars to allow using parameter inputs in the Measure / Simulate tab to provide user-entered data to your Python transforms.

 

Related Links

 

Measuring Sub-Threshold MOSFET Characteristics Using a Quasi-Static I-V Method

How to Extract Threshold Voltage of MOSFETs

Python Programming Integration with IC-CAP

Negative Bias Temperature Instability (NBTI) refers to a positive shift in threshold voltage in CMOS devices, hastened by negative gate voltages and high temperatures.  Resulting in lower device currents and lower transconductances, NBTI presents a device reliability concern, especially as gate-oxides become thinner and as device geometries continue to become smaller.  Reliability engineers have tried to characterize this phenomenon by applying a series of biases to stress the device for increasing time intervals, while measuring device parameters such as gate threshold voltage (Vth) after each stress period. In this way, they will observe an accelerated lifetime of the part.  Due to a self-healing process known as recovery, the device can appear to partially return to its pre-stress state, causing the test results to often overestimate the lifetime of the device.  To compensate for NBTI recovery, engineers at X-FAB Semiconductor proposed a Recovery Correction Method (RCM) [1] when measuring NBTI induced threshold voltage degradation in high-K CMOS transistors. The RCM method could be an excellent alternative to using the more typical extrapolation of Vth degradation model data to estimate NBTI lifetime. With RCM, the effect of NBTI is modeled using a curve fitting technique to estimate the lifetime of the device, even in the presence of recovery. Thus, one could eliminate the need for expensive and specialized hardware setup and complicated triggering associated with popular fast-IV pulse NBTI systems [2]. 

 

Intrigued by the potential of RCM, I wanted to explore device recovery times using a quasi-static DC-IV measurement of the sub-threshold region. To properly measure the influence of delays between stress and measurement, I needed very accurate measurements for both p-channel and n-channel MOSFET devices. Shown in Figure 1 below, each quasi-static measurement will be nestled between stress events.  By varying the time between a stress event and a measurement, and further modifying the measurement times during the Vth measurement, we can explore the nature of the NBTI recovery more precisely.  

 

Figure 1. NBTI Stress-Measurement timing diagram. [4]

 

Quasi-static DC IV

I performed multiple measurements on p-channel devices while adjusting delay time and the step delay of the sweep as shown in Figure 2. This measurement method is commonly known as quasi-static DC IV

 

fig.1. Quasi-static Measurement

Figure 2. Quasi-Static Bias for Each Step of Vg During the Vth Measure Cycle in Figure 1.

 

Quasi-static measurements can more accurately characterize the energy levels of interface traps at the Si/SiO2 interface, commonly understood as the underlying mechanism for NBTI. It has numerous advantages over a standard curve tracer sweep.

  1. Multiple samples used for averaging, filtering out noise.
  2. Staircase sweep mode performed by series of high-speed single spot measurements.
  3. Ability to set current and power compliance during each measurement point during the voltage sweep.
  4. Ability to set a user defined ramp rate (dV/dt) of the voltage sweep.
    ( Sampling interval = delay + step delay = dt )

 

Low-voltage, sub-threshold measurements of small geometry MOSFETs are difficult to measure using conventional NBTI measurements. However, using Python, I was able to program Keysight’s E5270B Precision IV Analyzer with multiple high-resolution SMUs to perform accurate current measurements over swept applied voltages with varying source and measurement delays, to better characterize the recovery mechanism in these devices. 

 

Writing a Set of Custom Transforms in IC-CAP

 

The programming guide for the E5270B lists a quasi-static pulsed measurement mode built into the command set of the instrument. [5] That’s great; however, it requires a (stop - start) voltage > 10 V. Unfortunately, that would damage my devices, which have a maximum voltage rating of only +/- 3.3 V. I therefore determined that I needed to create my own custom quasi-static measurement routine by implementing a series of custom IC-CAP transforms in Python. Since I would likely switch to the Keysight B1500A Semiconductor Device Parameter Analyzer in the future, my solution must support diverse instrument choices. The specific instrument control commands may vary slightly from one instrument to another.

 

Leveraging the work I presented in my previous blog entitled "Using a Python VISA API within IC-CAP for Instrument Control", I'll present custom transforms for a quasi-static measurement of an Id vs. Vg sweep on a p-type MOSFET.

I hope you find this example helpful in developing your own application-specific measurements.

 

Prerequisites

 

The complete IC-CAP model file py_new_api_basic_demo.mdl with the Python source code used to implement the quasi-static measurement is attached at the end of this post. I recommend saving this *.mdl to C:\Keysight\ICCAP_2018\examples\python

 

  1. Install IC-CAP 2018, under Windows 7 or 10 in the default installation directory; typically C:\Keysight\ICCAP_2018.
  2. Install the Keysight IO Libraries 17.x software. The visa32.dll and visa64.dll dynamic link libraries are located in the C:\Windows\system32 directory.
  3. Configure and confirm communication with your instruments using the 'Keysight Connection Expert' software.
  4. Install and configure your Python virtual environment, and define the appropriate IC-CAP environment variables. Please refer to my previous blog article Extending the Power of IC-CAP Software with Python -- PyVISA Control for a detailed explanation on creating Python virtual environments and loading external Python libraries. Change references to the virtual environment name icenv to icenv2018 (or a name of your choice..) and replace IC-CAP_2016_01 with IC-CAP_2018.
  5. Download the pyvisawrapper.py and dataparser.py scripts attached to this post.The pyvisawrapper.py utility described in my previous article "Using a Python VISA API within IC-CAP for Instrument Control" is used to manage communication with the instrument. The script called dataparser.py enables parsing and processing ASCII data retrieved from the instrument's data buffer.
  6. Confirm you have the environment variable ICCAP_USER_PYTHON_PATH defined in your Windows environment: 

    Tools> Programs> Advanced System Settings: Environment Variables. The location specified by this variable is added to the directories IC-CAP will search to find python scripts. (For an IC-CAP installation, the directory containing the 'factory' python files is typically: C:\Keysight\ICCAP_2018\iccap\lib\python).

  7. The pyvisawrapper.py and dataparser.py files should be placed in the directory specified by the variable ICCAP_USER_PYTHON_PATH. 

  8. Several Python module libraries are referenced in the _run transform to provide support for parsing arrays, writing CSV files and other functions. You will need to install these modules in the Python virtual environment using PIP (package manager for Python) .

   

The required Python modules include the following: 

  • pathlib2 - a backport of the new features in Python 3 for creating and managing file paths,
  • csv - a package for writing and reading comma separated values - already included in Python27
  • imp - a package for dynamically importing Python modules - already included in Python27

 

Activate and verify the Python 2.7 virtual environment by checking the system path 'sys.path' and system prefix 'sys.prefix.' To do this, open a Windows command shell and perform the following steps:

 

Activate the (icenv2018) virtual environment

C:\Users\username> workon icenv2018

(icenv) C:\Keysight\IC-CAP_2018\tools\win32_64>

Change the directory to virtual env (icenv)

C:\Users\username> cdvirtualenv

Check the Python interpreter version for (icenv2018)

(icenv) C:\Users\username\Envs\icenv> python -V

The version should return:

Python 2.7.13

 

Start the interactive Python interpreter for the virtual environment.

(icenv) C:\Users\username\Envs\icenv2018> python

You should see something like the following:

Python 2.7.13 (default, Mar 29 2017, 13:31:10) [MSC v.1900 64 bit (AMD64)] on win32

Type "help", "copyright", "credits" or "license" from more information.

>>>

Now, enter the following commands at the Python >>> interactive prompt:

>>> import sys 
>>> print sys.prefix

You should see something like the following:

C:\Users\username\Envs\icenv2018

Now type:

>>> print sys.path

You should see something like the following:

[''\,C:\\Users\\username\\Envs\\icenv2018\\Scripts\\python27.zip', 
'C:\\Users\\username\\Envs\\icenv2018\\DLLs',
'C:\\Users\\username\\Envs\\icenv2018\\lib',
'C:\\Users\\username\\Envs\\icenv2018\\lib\plat-win',
'C:\\Users\\username\\Envs\\icenv2018\\lib-tk',
'C:\\Users\\username\\Envs\\icenv2018\\Scripts',
'C:\\Keysight\\ICCAP_2018\\tools\\win32_64\\Lib',
'C:\\Keysight\\ICCAP_2018\\tools\\win32_64\\DLLs',
'C:\\Keysight\\ICCAP_2018\\tools\\win32_64\\lib-tk',
'C:\\Users\\username\\Envs\\icenv2018\\lib\\site-packages',
'C:\\Keysight\\ICCAP_2018\\tools\\win32_64']

To exit the virtual Python interpreter type:

>>> quit()

(icenv) C:\Users\username\Envs\icenv2018>

Leave the virtual environment by typing:

(icenv) C:\Users\username\Envs\icenv2018> deactivate

C:\Users\username\Envs\icenv2018>

 

This completes the prerequisites.Your icenv virtual Python environment is configured and ready to be used from IC-CAP. In the following section, I will provide a step-by-step guide on the construction and use of this example.

 

Load the IC-CAP Model File

 

Assuming you saved the model file to the examples folder (C:\Keysight\ICCAP_2018\examples\python), click 'File/Examples...' and select: python\py_api_new_basic_demo_5270.mdl. (The model file is attached at end of this post along with a version supporting the Agilent 4156 Semiconductor Parameter Analyzer.)

 

iccap_file_open_mdl_5270

 

Before starting to write the code it is convenient to add some User variables to IC-CAP's Model Variables Table to aid in configuring the device parameters and measurement conditions.

 

Click on the 'Model Variables' Tab

 

 

 

 

Note the 'debug' variable defined in the 'Model Variables' Table.

Name            Value               Comment
debug           1                   Enable/disable global debug print statements

This enables the reporting of useful diagnostic information.

 

Select the idvg_quasi Setup, go to the 'Measure / Simulate' tab and observe the Inputs vd, vg, vb, and the Output id, defined to contain the data we will be acquiring from our transforms.

 

 

The vg Input has the Sweep Type defined to be Lin(linear). We will build an equivalent data vector for the vg Input using the _meas_iv transform.

 

Select the 'Setup Variables' tab under the setup idvg_quasi.

 idvg_quasi setup variables table

 

Notice the following variables defined in the idvg_quasi 'Setup Variables' Table.

Name            Value               Comment
drain           1                   Drain SMU Channel
gate            2                   Gate SMU Channel
source          3                   Source SMU Channel
substrate       4                   Substrate SMU Channel
interface       GPIB0:17::INSTR     VISA instrument
visaResponse                        VISA response string
error_status    32,48,128           Error codes
error_command   ERR?,EMG?,ERRX?     Command to process errors
hold_bias       0.0                 Bias applied during hold time period
hold            0.5                 Hold time before first measurement, in seconds
delay           0.1                 Delay time
step_delay      0.2                 Step delay time
vgstart         0.0                 Gate sweep start voltage
vgstop          3.0                 Gate sweep stop voltage
vgstep          0.1                 Gate step size
vgpts           31                  Gate points
igcompl         1E-1                Gate current compliance
vdvalue         3.0                 Drain voltage (constant)
idcompl         1E-1                Drain current compliance
vsvalue         0.0                 Source voltage (constant)
iscompl         1E-1                Source current compliance
vbvalue         0.0                 Bulk voltage (constant)
ibcompl         1E-1                Bulk current compliance

 

These set the measurement parameters that will be sent to the SMU.  You may need to change the SMU channel assignments ('drain', 'gate', 'source', 'substrate') to match the configuration of your instrument.  For example, your 'drain' (Drain SMU Channel) may be slot 5, not slot 1, etc.

 

In the 'Setup' named idvg_quasi, select the 'Extract/Optimize' tab. 

 

The following transforms are defined:

  1. _run - the main Transform that calls other Transforms and provides functions for processing the measurement data and writing data files.
  2. _init - reads values from the IC-CAP Setup Variable Table ("SVar") and initializes parameters for the measurement
  3. _setup_iv - sends commands to configure the instrument for upcoming measurement
  4. _meas_iv - sends commands to instrument to perform actual measurement, including channel specific ranging, bias application, compliance and measurement triggering
  5. _close - turns off biases, disconnects outputs, and closes the VISA session.

 

Note: The _run Transform contains code calling the 'activate_this.py' script, which will activate the virtual python environment. Modify the path defined for the 'activate_this' variable, to the correct setting for the environment.

 

idvg_quasi setup _run transform

 

Notice the 'Function' definitions for the python transforms, _run, _init, etc. are set to 'PythonGlobal' Information, including the data and variables, will be shared in the global transform space. To perform the quasi-static DC measurement, select the _run transform from the 'Extract/Optimize' tab and click Execute

 

The _run will call the other transforms in the order needed. The resultant data can be plotted as shown in the 'ThreshholdVoltageIdsvsVgs' plot under the idvg_quasi Setup.

 

################################################################# 
#
# Perform measurement
#
#################################################################
# open communications interface 
vl = visaOpenSession(intr)
if debug and vl: print "VISA resource: {} found".format(intr) 

# forward call additional transforms
if bOk: iccap.iccap_func("_init","execute")
if bOk: iccap.iccap_func("_setup_iv","execute")
if bOk: iccap.iccap_func("_meas_iv","execute") 

# zero channels and close GPIB interface
if bOk: iccap.iccap_func("_close","execute") 

if debug: print "_run - complete bOk: ", bOk

 

There are several necessary lines in the _run script that import the correct Python modules for use in the other transforms. The first two statements in the script below activate and execute the Python interpreter in the virtualenv named icenv2018 that was previously installed. (As mentioned earlier, the path to the 'activate_this.py' script should be modified to be correct for the current user environment)

################################################################# 
# _run.py # # Main execute file for IdVg measurement

#################################################################
activate_this = "/Users/<USERNAME>/Envs/icenv2018/Scripts/activate_this.py"
execfile(activate_this, dict(__file__=activate_this)) 
# imports
from iccap import icfuncs as f, SVar, MVar, get_dataset, set_dataset, Setup, TableVar
from pyvisawrapper import *
from numpy import *
import itertools
import pathlib2 as pl
import csv
import math
import time
import imp

 

The imp package has been added to aid in re-initializing our external modules while debugging.  IC-CAP imports these external modules only once when it starts the Python environment. If you make changes to the module code in an external editor, the changes will not be updated until the next time you start IC-CAP. To work around this issue you can use the imp.reload( ) function to reload the modules during execution of the _run transform.

 

###################################################################

#
# Global variables
#
###################################################################
pv = imp.reload(pv)    
dp = imp.reload(dp)    
from pyvisawrapper import *    
from dataparser import * 

...
  

  

 

Here we are setting some global variables by reading the Model and Setup Variable Table variables defined in an earlier step. Via this method, one can quickly change global values in the appropriate table, rather than needing to modify Python code in each transform individually. 

 

# defaults from the model variables table

# get debug enable/disble
debug = int(MVar("debug").get_val())   # enable debug print

...

 

The MVar command gets the values from the 'Model Variables' Table.  The get_val( ) function returns the value of the variable in the table, and assigns it to the specified local variable. I usually specify variables (and their values) in the Model Variable Table that apply to all Setups in the IC-CAP model file, which is the case here.

 

# get channels from setup variables table 
drnSMUChan = SVar("drain").get_val()
gateSMUChan = SVar("gate").get_val()
srcSMUChan = SVar("source").get_val()
subSMUChan = SVar("bulk").get_val() 

intr = SVar("interface").get_val()

rsp = SVar("visaResponse")
stat = SVar("error_status").get_val().split(",")
err = SVar("error_command").get_val().split(",")
...

 

The SVar command gets the values from the 'Setup Variables' Table. I usually specify values in the Setup Variables Table that apply to a particular Setup. This supports the case where you might want to have different channels defined for other measurements or even specify a different instrument in the 'interface' variable for a different measurement setup.

 

 

Open _init transform

 

The _init transform reads the Setup Variable table values and assigns them to local variables to be used later when updating parameters for the instrument commands.

 

iccap_setup_idvg_quasi_init

 

The type or polarity (NMOS or PMOS) is read from the Model Variable Table. If its value is PMOS, the values for the gate and drain biases and compliance are multiplied by -1, which will provide negative bias to the device terminals.

 

################################################################# 
# _init.py
#
# Initialize global variables and parameters for IdVg_Quasi

################################################################# 
if debug: print "_init - enter: bOk =", bOk 

# add variables for sweep source and other variables
polarity = MVar("POLARITY").get_val() 

# get setup variables
hold=float(SVar("hold").get_val())
delay=float(SVar("delay").get_val())
step_delay=float(SVar("step_delay").get_val()) 
vg_start=float(SVar("vgstart").get_val())
vg_stop=float(SVar("vgstop").get_val())
vg_step=float(SVar("vgstep").get_val())
ig_compl=float(SVar("igcompl").get_val()) 

if polarity == "PMOS":    
   vg_start *= -1    
   vg_stop *= -1    
   vg_step *= -1    
   ig_compl *= -1
if debug:
   print "vg start = {} vg stop = {} vg step = {}".format(vg_start, vg_stop, vg_step)

vg_points = int(SVar("vgpts").get_val().split('.')[0]) 
vd_value=float(SVar("vdvalue").get_val())
id_compl=float(SVar("idcompl").get_val())

if polarity == "PMOS":    
   vd_value *= -1    
   id_compl *= -1

if debug: print "vd value = {}".format(vd_value) 

vs_value=float(SVar("vsvalue").get_val())
is_compl=float(SVar("iscompl").get_val()) 
vb_value=float(SVar("vbvalue").get_val())
ib_compl=float(SVar("ibcompl").get_val())

if polarity == "PMOS":    
   is_compl *= -1    
   ib_compl *= -1 

if debug: print "_init - exit:", bOk

 

 

Open _setup_iv transform

 

The _setup_iv transform sends commands to initialize the instrument and set specific features.

 

iccap_setup_idvg_quasi_setup_iv

 

The FMT11 command sets the data return format to ASCII. We will discuss that in detail further below, when we look at how to parse the data returned from the instrument's data buffer. (See the E5270B Programming Manual for details)

 

# set data format to binary 4 bytes 
cmd = "FMT11"
if bOk: bOk = visaWrite(vl, cmd, 10000, stat, err) 

 

 

Open the _meas_iv transform

 

The _meas_iv transform performs the quasi-static measurement.

 

iccap_setup_idvg_quasi_meas_iv

 

# perform quasi-spot sampling measurement with auto ranging 
for i in range(0, vg_points):    
   # calculate next voltage step    
   value = float(vg_start) + (float(vg_step)*i)     

   # append value to vvalue[] list    
   vvalue.append(value)     

   # set wait hold, delay to 0.0000 and step_delay will be handled by     
   cmd = "WT " + str(hold) + "," + str(delay) + "," + str(step_delay)    
   if bOk: bOk = visaWrite(vl, cmd, 10000, stat, err)     

   # set quasi-pulse parameters start = stop    
   cmd = "WV" + gateSMUChan + ",1,0," + str(value) + "," + str(value) + ",1," + str(ig_compl)    
   if bOk: bOk = visaWrite(vl, cmd, 10000, stat, err)     

   ...

   # trigger the measurement    
    cmd = "XE"    
    if bOk: bOk = visaWrite(vl, cmd, 10000, stat, err)     

   ...

 

For each iteration of the 'for' loop, the WT command sets the Hold, Delay and Step Delay time of the measurement as depicted in Figure 2 above. The Start and Stop value for the WV staircase sweep command is set to the same Vg value. This effectively performs a single point sweep at each specified Vg step. The XE command triggers the measurement. Once complete, the data value is retrieved from the instrument data buffer by calling the get_Measured_Data( ) function. (The get_Measured_Data() function is defined in the _run transform).

 

We previously created the global arrays vvalue[ ] and ivalue[ ] for storing our forced voltage and measured current data values.

 

# global list of values
vvalue = []
ivalue = [] 

...

 

The get_Measured_Data( ) function retrieves the data from the instrument data buffer and uses the dataparser.py  script to process the returned data packets.

 

# measurement complete so get the data     
if bOk: bOk = get_Measured_Data(i)
...

 

The data format for the E5270B is formatted based on the FMT command. This discussion assumes a FMT11 

command was sent to the instrument in the _setup_iv transform.

 

The ASCII data values are expected to be in returned in the following format: (FMT11 is 13 digits data with header)

 

ABCDDDDDDDDDDDDD  

   A: Status. One character.
   B: Channel number. One character.
   C: Data type. One character.
   D: Data. Twelve digits or 13 digits.

 

An example of the data returned from the instrument is  NAI+1.23684-E09.  

 

Within the _run transform, the get_Measured_Data() function calls get_ASCII_Data_Info( ) function, which uses dictionary utility functions to return a parsed data packet in ASCII format along with any error status.

 

The script dataparser.py makes use of nested Python dictionaries to decompose the ASCII data values character-by-character by checking each against the key for each section of the dictionary. This script also implements classes which provide custom assertions that can be checked during the parsing of the data, providing specific error detection and reporting using the IC-CAP python treat_error() function to display the errors. You can open this script in any text editor and check out the source code to get an idea of how it works.  You can also modify this script to process other data formats including ones that provide other types of preambles and data resolution.

 

################################################################# 
#
# Decode data packet
#
#################################################################
def get_ASCII_Data_Info(data, verbose=False):    
   """    
   Get the ASCII data value for parsing.     

   This function parsing data values returned from the instrument. Nested    
   data dictionaries are used for processing each element of the data value    
   including tags appended to the data value to provide measurement status.      

   Args:        
      data:       Data value to be parsed.        
      verbose:    Boolean value to provide more information to the calling                     
                  program. In this case IC-CAP will fill message text for treat_error function.    
   Kwargs:     
   Returns:        
      bOk:        Boolean value to report the success or failure of the function execution.        
      data:       Data value passed from calling progam.        
      stat:       Measuremetn status for data value.        
      chan:       Measurement channel for data value.        
      type:       Measurement data type ( current or voltage )        
      sign:       Polarity of the data value.        
      value:      Real value of the data.     

   Raises:        
      DataError        
      MeasError     
   """     
   bOk = True     
   mstat   = data[0]    
   mchan   = data[1]    
   mtype   = data[2]    
   msign   = data[3]     
   value   = data[4:16]     
  
   # for k,s in data:    
   stat   = getFromDict(dataDict, ['A', mstat])    
   chan   = getFromDict(dataDict, ['B', mchan])    
   type   = getFromDict(dataDict, ['C', mtype])    
   sign   = getFromDict(dataDict, ['D', msign])    
   svalue = float(value)     

   # 199.9999E+99 is a bad data point then set bad data points to 9999.9999    
   try:        
      bOk = checkValue(svalue)                            
   except DataError as inst:        
      if verbose: treat_error(inst, printit=True)        
      bOk = False    
   else:        
      bOk = True     

   # check the sign and multiply by -1    
   if msign == '-':        
      svalue *= -1.0 
  
   # check for errors and if verbose is true then display them        
   try:        
      bOk = checkDataIsValid(stat)    
   except MeasError as inst:        
      if verbose: treat_error(inst, printit=True)    
   else:        
   bOk = True          
  
   return bOk, { 'data':data, 'stat':stat, 'chan':chan, 'type':type, 'sign':sign,
                 'value':svalue

## end of dataparser.py

 

Each data packet processed by the get_Measured_Data( ) function is appended to the global vvalue[ ] and ivalue[ ] arrays. When all data has been measured and parsed, the global array values are copied into IC-CAP data structures using ('M', 11) format with a 'for' loop with range set to the number of points in the sweep. Once the data are copied into the appropriate IC-CAP data array structures, the data can be plotted. We can also call other functions to export the data and write the results to both IC-CAP MDM and CSV file formats.

 

################################################################# 
#
# Build iccap measured data values
#
#################################################################
dI = Transform(setupName + "/id")
gV = Transform(setupName + "/vg") 

# create data dictionaries for I-V data
dsI = {    
   ('M','11'): [ ivalue[i] for i in range(vg_points) ], 
}
dsV = {    
   ('M','11'): [ vvalue[i] for i in range(vg_points) ], 
} 

# set the dataset in data dictionaries set_dataset(dI.get_fullname(), dsI)
if debug: print "Id :", dI set_dataset(gV.get_fullname(), dsV)
if debug: print "Vg :", gV  # export measured data to iccap mdm file
if bOk: bOk = export_Measured_Data() 

# write test results to CSV file
if bOk: bOk = write_Results(vg_points)            

...

 

Open the Plots Tab

 

Click the Display Plot button to view the data.

 

create_idvg_plot

 

The plot results are shown in the new plot window.

 

 

Open the _close transform

 

This transform sets all bias to zero volts and disconnects the SMU outputs.

# close GPIB0 
if (vl): visaClear(vl) 
if (vl): visaCloseSession(vl) 

if debug: print "_close - exit bOk: ",bOk

 

NOTE: It is important to close the current VISA session when the transform finishes so that subsequent executions will not cause errors to occur when trying to perform the visaOpenSession command.

 

Conclusion

 

This implementation of the quasi-static measurement as a series of IC-CAP transforms demonstrates the flexibility and data handling capabilities of IC-CAP.  Using IC-CAP along with extending the Python modules like the pyvisawrapper.py and dataparser.py modules that I included as attachments to this article you can easily implement custom measurement and extraction routines. In a future article I'll show you how to implement additional transforms for extracting parameters along with other the custom Python code for performing parameter extraction on the Id vs. Vg sweep data of the p-channel MOSFET. 

 

 

References

[1] Vincent King Soon Wong, Hong Seng Ng, Florinna Sim., "Influence of Measurement System on Negative Bias Temperature Instability Characterization: Fast BTI vs Conventional BTI vs Fast Wafer Level Reliability". Internataional Journal of Electronics and Communication Engineering, Vol: 10, No: 12, 2016

[2] Wong, V. K. S., Ng, H. S., & Sim, P. C. (2015, December). "Impact of NBTI Recovery, Measurement System and Testing Time on NBTI Lifetime Estimation". 2015 International Conference on Advanced Manufacturing and Industrial Application. Atlantis Press.

[3] A.E. Islam, E. N. Kumar, H. Das1, S. Purawat, V. Maheta, H. Aono, E. Murakami, S. Mahapatra, and M.A. Alam "Theory and Practice of On-the-fly and Ultra-fast VT Measurements for NBTI Degradation: Challenges and Opportunities". Published 2007 in 2007 IEEE International Electron Devices Meeting.

[4] Keysight Technologies Application Note B1500-6, "Accurate NBTI Characterization Using Timing-on-the-fly Sampling Mode", Dec 2017.

[5] Keysight E5270B Programming Guide.

 

Related Links

 

rajsodhi, co-author

ShuangCai 

Many of you already know that Keysight's IC-CAP software provides an open flexible architecture that supports many industry standard and proprietary models. It also provides drivers for a range of popular test instruments required to make characterization measurements for extracting device model parameters and performing optimizations. But did you know that you can customize your IC-CAP environment to tackle your own measurement challenges?

 

This might be very welcome news if you are working with cutting-edge devices and need more than the capabilities already provided by IC-CAP. For many of these devices, skirting the limits of today’s technology often means that the measurement capabilities required are a moving target. And that can be a costly and time-consuming proposition if you have to buy and integrate new software tools every time you need new functionality. Your ability to automate these advanced measurements may even mean the difference between the success or failure of your project.

 

What if you need to implement your own behavioral model in Verilog-A along with custom parameter extraction routines? What if you want to create new measurement routines for controlling an arbitrary waveform generator? What if you want to add a time-domain measurement capability using an oscilloscope to capture your device’s fast pulse response? 

 

I faced such a scenario in my work at nSpace Labs, where I'm developing custom models for memristors and adding advanced measurement routines using the Keysight B1500A Semiconductor Device Analyzer. This analyzer is configured with multiple high-resolution SMUs (Source Measurement Units) and an integrated B1530A WGFMU (Waveform Generator/Fast Measurement Unit) to apply pulsed and arbitrary waveforms to the memristor’s electrodes, while simultaneously performing Fast-IV measurements. I needed to communicate with the WGFMU via GPIB using a Keysight provided software library and API for the WGFMU, something that is not currently supported by IC-CAP.

 

To take advantage of the WGFMU capabilities, I decided to use the Python programming language, included in all recent versions of IC-CAP, and PyVISA—a Python module that enables control of all kinds of measurement devices independent of the interface (e.g., GPIB, RS-232, USB or LAN). Utilizing IC-CAP's integrated Python environment, I was able to extend the software’s built-in measurement capabilities by integrating the third-party libraries and Python modules I needed for my application. This enabled me to programmatically generate the waveforms using Python, and then send the appropriate commands to the WGFMU for pulsing and simultaneously making Fast-IV measurements on my devices.

 

It took some effort, but I figured out how to install the WGFMU library and PyVISA package within a virtual Python environment for use with Keysight IC-CAP 2016. Now, I'd like to share with you the procedure for using some free Python packages and modules to extend the capabilities of IC-CAP. Using the WGFMU measurement routines that I have developed in Python, I am now able to extract and optimize parameters for my memristor model and have the ability to more accurately simulate the incremental conductance change of the memristor when a series of pulses are applied. Having more accurate models and the accompanying time-based measurement data provide me with a better understanding of the performance of the memristor-based circuits that I am designing. For you personally, extending the capabilities of IC-CAP means you can realize a significant return on your investment in your IC-CAP software, because you can now customize your environment to tackle whatever measurement challenge you might face.

 

Back to Basics

Before I delve into how to add PyVISA to a virtual Python environment, let’s discuss a few of the basics. First and foremost, the reason this is even possible is because the authors of IC-CAP developed a link between Python and IC-CAP back in 2013. The link provided in the iccap.py module significantly expanded the flexibility and extensibility of the IC-CAP platform. The most common modules for engineering and scientific programming in Python are also currently included in the IC-CAP 2016 Python environment:

  1. Numpy: A fundamental package for numerical analysis including math functions, arrays and matrix operations.
  2. SciPy: A package for scientific and engineering computations.
  3. Matplotlib: A 2D plotting package that outputs plots in multiple popular graphics formats.
  4. PySide: A library that can be used for implementing custom graphical user interfaces using Qt.

 

         

 

Prerequisites

There are a few things you’ll need to do prior to undertaking the installation of the PyVISA package:

  • Install IC-CAP_2016_01 or later, under Windows 7 in the default installation directory, which is typically C:\Keysight\ICCAP_2016_01.
  • Install the Keysight IO Libraries 17.x software and configure it to use the VISA library visa32.dll. This dynamic link library will be installed in the C:\Windows\system32directory.
  • Configure and test communication with your instruments using the Keysight Connection Expert software.                  

If you are new to IC-CAP software or Keysight IO Libraries, you’ll first want to get up to speed by checking out the links at the end of this article. If you are new to Python programming, I suggest you read the “About Python” section and check out the links at the end of this article before attempting this configuration.

 

Why Configure a Virtual Python Environment?

Sometimes, adding an incompatible module to a Python environment can cause it to become corrupted. Since IC-CAP ships with its own Python environment, you’ll have to be careful, or risk having to reinstall IC-CAP if problems arise. One way to avoid this problem is to use a virtual Python environment that can be implemented using two Python packages,"virtualenv" and “virtualenvwrapper-win,” which are designed to make it easy for users to create and manage completely isolated Python environments on the same computer.

 

By installing a separate virtual Python environment in your own user directory, you avoid breaking the IC-CAP installed environment, especially when potentially installing modules not compatible with the Python version shipped with your software. If you later upgrade to a newer version of IC-CAP, or if you need to reinstall the software for any reason, you’ll avoid having to reinstall all your third-party Python packages, assuming you have a backup of your home directory. 

 

The steps I’ve outlined for installing and configuring a virtual Python environment will allow you to install any third-party Python packages you want to use with IC-CAP. Key to this process is the installation of a standalone Python interpreter that includes PIP, a package manager needed to install the virtualenv and virtualenvwrapper-win. Having a stand-alone system Python environment is also great for developing experimental Python scripts and debugging in programming tools outside of the IC-CAP environment.

 

Overview

The following is a high-level overview of the procedure:

  • Install the Python 2.7 system environment
  • Install the virtualenv and virtualenvwrapper-win modules using PIP
  • Create your virtual Python environment for use with IC-CAP
  • Verify your new virtual Python environment
  • Configure the project directory for easy access to IC-CAPs Python interpreter
  • Install the PyVISA package using PIP in the virtual Python environment
  • Take PyVISA for a test drive using the virtual Python environment console
  • Write a macro within IC-CAP to activate the visual Python environment and use PyVISA

 

Step-By-Step Process for Installing the PyVISA Package

 

Step 1: Install the Python 2.7 system environment

Install the latest stable Python 2.7 release, which is currently version 2.7.13. Download Python 2.7.13 for Windows 64-bit from python.org. Python 2.7 is used because Python 3.x is not currently available for IC-CAP. Choose the default installation location, which is “C:\Python27”.

 

                                                                                                

Add the Python 2.7 directories to the Windows PATH environment variable. This may be done through the Environment variables in Windows under the Advancedtab in computer Advanced system settings in Computer properties.

 

NOTE: The username in the command prompt is the name of the current user logged in to your Windows 7 machine. This generic name is a place holder for the commands listed below and represent the current user's home directory. The commands you will need to type are displayed in green throughout this article.

 

Check your Python installation.

 

C:/Users/usernamepython –V

Python 2.7.13

 

Step 2: Install the virtualenv and virtualenvwrapper-win modules using PIP

To install virtualenv type:

C:> pip install virtualenv

 

This should install virtualenv.exe into the C:\Python27\Scripts directory

 

To install virtualenvwrapper-win type:

C:> pip install virtualenvwrapper-win

 

This should install a set of useful batch '.bat' files that wrap the virtualenv functions and make creating and

managing virtual Python environments easier. These files should be installed in the C:\Python27\Scripts directory.

 

Check your virtualenv installation:

C:> virtualenv –-version

15.1.0

                          

Step 3: Create your virtual Python environment for use with IC-CAP

Create the virtual environment using the virtualenvwrapper-win provided batch file mkvirtualenv and name it icenv.

Type the following at the command prompt:

 

C:\Users\usernamemkvirtualenv -p C:\Keysight\ICCAP_2016_01\tools\win32_64\python.exe icenv

 

NOTE: The -p option allows you to specify the IC-CAP Python 2.7.3 default environment to create our

virtual Python environment. Virtualenv creates the \Envs\icenv directory and copies the specified Python

interpreter and default modules to your \Users\username directory. 

 

Assuming everything succeeds with no errors or warnings, then we should get the following text:

 

Running virtualenv with interpreter C:\Keysight\ICCAP_2016_01\tools\win32_64\python.exe

New python executable in C:\Users\username\Envs\icenv\Scripts\python.exe

Installing setuptools, pip, wheel...done.

 

NOTE: The previous step creates the directory 'C:\Users\username\Envs\icenv' and copies the Python default

environment from C:\Keysight\ICCAP_2016_01\tools\win32_64. The contents of this '\Envs\icenv' directory

will now be the default Python configuration for IC-CAP 2016.

 

Use the cdvirtualenv batch file to easily change the directory to the icenv virtual Python environment we just created.

 

(icenv) C:\Users\username> cdvirtualenv

 

The command prompt should change to the following:

 

(icenv) C:\Users\username\Envs\icenv >

 

NOTE: This is the activated state for the icenv virtual Python environment. The 'activate.bat' file was called

during the mkvirtualenv command, which makes the following changes: 1) Prepending the virtual

environment's path to the Windows 7 system PATH environment variable so that it will be the first Python

interpreter found when searching for the python.exe. 2) Modifies the shell property to display the (icenv), which

denotes the virtual environment that is currently active. If no virtual environment is activated, the system  Python

is active by default.

 

Step 4: Verify your new virtual Python environment

Verify the activated Python 2.7 environment by checking the system path 'sys.path' and system prefix 'sys.prefix'

 

(icenv) C:\Users\username\Envs\icenv> python -V

Python 2.7.3

 

Start the interactive Python interpreter for the virtual environment.

 

(icenv) C:\Users\username\Envs\icenv> python

     

      You should see something like the following:

Python 2.7.3 (default, Feb 1 2013, 15:22:31) [MSC v.1700 64 bit (AMD64)] on win32

Type "help", "copyright", "credits" or "license" from more information.

>>>

 

Now, enter the following commands at the Python interactive prompt:

>>> import sys

>>> print sys.prefix

C:\Users\username\Envs\icenv

>>> print sys.path

['', C:\\Users\<username>\Envs\\icenv\\Scripts\\python27.zip', 

'C:\\Users\\<username>\\Envs\\icenv\\DLLs',
'C:\\Users\\<username>\\Envs\\icenv\\lib',
'C:\\Users\\<username>\\Envs\\icenv\\lib\\plat-win',
'C:\\Users\\<username>\\Envs\\icenv\\lib-tk',
'C:\\Users\\<username>\\Envs\\icenv\\Scripts',

'C:\\Users\\<username>\\Envs\\icenv\\DLLs',
'C:\\Keysight\\ICCAP_2016_01\\tools\\win32_64\\Lib',
'C:\\Keysight\\ICCAP_2016_01\\tools\\win32_64\\DLLs',
'C:\\Keysight\\ICCAP_2016_01\\tools\\win32_64\\lib-tk',
'C:\\Users\\<username>\\Envs\\icenv\\lib\\site-packages'
'C:\\Users\\<username>\\Envs\\icenv\\DLLs',
'C:\\Keysight\\ICCAP_2016_01\\tools\\win32_64']

>>> quit()

(icenv) C:\Users\username\Envs\icenv>

 

To exit the icenv virtual environment and return to the system Python environment, type the following at the command prompt:

 

(icenv) C:\Users\username\Envs\icenv> deactivate

C:\Users\username\Envs\icenv>

 

Start the interactive Python interpreter for the system Python

 

C:\Users\username> python

 

You should see something like the following:

Python 2.7.13 (v2.7.3:a06454b1afa1, Dec 17 2016, 20:54:40) [MSC v.1500 64 bit (AMD64)] on win32

Type "help", "copyright", "credits" or "license" from more information.

>>>

 

Now, enter the following commands at the Python interactive prompt:

 

>>> import sys

>>> print sys.prefix

C:\Python27

>>> print sys.path

['','C:\\WINDOWS\\SYSTEM32\\python27.zip', 'C:\\Python27\\DLLs',

'C:\\Python27\\lib', 'C:\\Python27\\lib\\plat-win',  'C:\\Python27\\lib\\lib-tk',

'C:\\Python27', 'C:\\Python27\\lib\\site- packages']

>>> quit()

C:\Users\username>

 

To reactivate the icenv virtual environment, use the virtualenvwrapper batch file 'workon.bat' by typing:

 

C:\Users\username\Envs\icenv> workon icenv

(icenv) C:\Users\username\Envs\icenv>

 

Step 5: Configure the project directory for easy access to IC-CAP’s Python interpreter

Here, we will set the project directory for the icenv virtual environment to IC-CAP's '\tools\win32_64' directory. This makes it easier to execute the built-in Python interpreter and import the IC-CAP included modules and Python tools.

Now you will no longer have to type the full path to access these tools.

 

NOTE: Anything you install using PIP while in the icenv virtual environment will still be installed

in the C:\Users\username\Envs\icenv.

 

Set the project directory to the ICCAP_2016_01 default Python path by typing the following:

 

(icenv) C:\Users\username\Envs\icenv> setprojectdir C:\Keysight\ICCAP_2016_01\tools\win32_64

 

"C:\Keysight\ICCAP_2016_01\tools\win32_64" is now the project directory for virtualenv

"C:\Users\username\Envs\icenv"

 

"C:\Keysight\ICCAP_2016_01\tools\win32_64" added to

C:\Users\username\Envs\icenv\Lib\site-packages\virtual_path_extensions.pth

 

Check that the project directory is set properly.

 

(icenv) C:\Users\username\Envs\icenv> cdproject

(icenv) C:\Keysight\ICCAP_2016_01\tools\wind32_64>

 

Return to the virtual environment directory.

 

(icenv) C:\Keysight\ICCAP_2016_01\tools\wind32_64> cdvirtualenv

(icenv) C:\Users\username\Envs\icenv>

 

Step 6: Install the PyVISA package using PIP in the virtual Python environment

Install PyVISA 1.8 using PIP.

 

(icenv) C:\Users\username\Envs\icenv> pip install pyvisa

 

Check that PyVISA was installed correctly to your (icenv) virtual python environment.

 

(icenv) C:\Users\username> cd C:\Users\username\Envs\icenv\lib\site-packages

(icenv) C:\Users\username\Envs\icenv\lib\site-packages > dir

 

The directory listing should now include the visa.py, visa.pyc, [pyvisa], and [PyVISA-1.8.dist-info] folders.

 

Step 7: Take PyVISA for a test drive using the virtual Python environment console 

You should have already installed the VISA drivers for your interface, either GPIB or PXI, and configured the system to use the software. Perform a "Scan for Instruments" to automatically add the instruments on your system to the VISA resources. Then, start an interactive Python shell and enter the following commands:

 

       (icenv) C:\Users\<username>>\Envs\icenv> python

 

       >>> import sys

       >>> import visa

       >>> print sys.path

        ['',  C:\\Users\<username>\Envs\\icenv\\Scripts\\python27.zip',

       'C:\\Users\\<username>\\Envs\\icenv\\DLLs',

       'C:\\Users\\<username>\\Envs\\icenv\\lib',

       'C:\\Users\\<username>\\Envs\\icenv\\lib\\plat-win',

       'C:\\Users\\<username>\\Envs\\icenv\\lib-tk',

       'C:\\Users\\<username>\\Envs\\icenv\\Scripts',

       'C:\\Users\\<username>\\Envs\\icenv\\DLLs',

       'C:\\Keysight\\ICCAP_2016_01\\tools\\win32_64\\Lib',

       'C:\\Keysight\\ICCAP_2016_01\\tools\\win32_64\\Lib',

       'C:\\Keysight\\ICCAP_2016_01\\tools\\win32_64\\DLLs',

       'C:\\Keysight\\ICCAP_2016_01\\tools\\win32_64\\lib-tk',

       'C:\\Users\\<username>\\Envs\\icenv\\lib\\site-packages',

       'C:\\Users\\<username>\\Envs\\icenv\\DLLs',

       'C:\\Keysight\\ICCAP_2016_01\\tools\\win32_64']

 

      >>> rm = visa.ResourceManager()

      >>> print rm

      Resource Manager of Visa Library at C:\Windows\system32\visa32.dll

   

      >>> print rm.list_resources()

      (u'GPIB0::16::INSTR',)

 

NOTE: An instrument was found on interface GPIB0 at address 16. Now quit the Python session and deactivate the virtual Python environment.

 

     >>> quit()

     (icenv) C:\Users\username>\Envs\icenv> deactivate

           

     C:\Users\username>

 

Step 8: Write a macro within IC-CAP to activate the icenv environment and use PyVISA

Open the project \examples\demo_features\5x3_PYTHON_PROGRAMMING\1_py_api_demo.

 

  1. Select the Macros tab.                                                                                                                                                           
  2. Click the “New... button to create a new macro.                                                                                                               
  3. Enter the name _init_pyvisa.                                                                                                                                                                                                                                                                                                                                                                                                        
  4. Select the Python (Local Namespace) radio button for the Macro Type.                                                                                                                                                                                                                                                                           
  5. Enter the following Python code in the editor window.                                                                                                                                                                         

     

  6. In Line #1 make sure to use the path of your home directory (where you created your icenv virtual Python environment), in this case, the 'C\Users\username\Envs\icenv\Scripts\' path.

  7. The script activate_this.py changes the current system PATH to prepend the (icenv) virtual Python environment to the existing PATH environment variable. This makes it the first location searched by the Windows OS when attempting to load a module (i.e., visa). The path entry 'C:\Users\marendall\Envs\icenv\lib\site-packages' will also be prepended to the system PATH environment variable and will be made available to IC-CAP's Python environment.

  8. Line #2 contains the execfile() function, which is called to launch the activate_this.py script. You can view the contents of this file in your favorite text editor or standalone Python IDE.

  9. Line #5 is where we import the visa.py module functionality into our IC-CAP Python environment.

  10. Line #10 gets the default VISA resource manager, which for our system is the visa32.dll installed with the Keysight IO Libraries in the C:\Windows\system32 directory.

  11. Line #13 calls the list_resources() function in the visa32 DLL library to return the current system resources

    previously configured with Keysight Connection Expert. This function returns a list of all the configured

    resources for the system as a Python List.

  12. In line #15 we print the result of the open_resource('GPIB0::16::INSTR') function, which should just return the     string 'GPIB Instrument at GPIB0::16::INSTR' if there are no errors.

  13. Line #17 closes the current communication session.

 

NOTE:  In practice you’ll want to code the statement in line #15 to be something like the following:

sl = rm.open_resource(r), where r is the resource string ('GPIB0::16::INSTR') and sl points to the object of the

opened VISA resource.

 

You can use call functions on this object by typing something like:

sl.write( cmd, termination='\r'), where cmd = "*RST" with the termination='r' being the carriage-return termination character to append to the end of the command string. This command will perform a GPIB reset on the instrument.

 

You can also use other available visa functions listed in the PyVISA docs, like sending: 

gpib_response = sl.read(termination= '\r') to read the response from the instrument's ouput buffer.

 

In a follow-on article I’ll show you how to create a PyVISA wrapper to simplify programming using these common

functions, but we’ll also be writing helper functions to check for instrument errors and display messages to the user.

 

NOTE: You should always close the VISA session when you are done with a resource. Not properly closing the session

will cause errors if you attempt to re-open the same resource later.                      

 

Step 9: Save and execute the macro within IC-CAP

Save the macro in the model file \Users\username\iccap\python\examples\1_py_api_demo.mdl or some other

suitable directory in your home directory.

 

  1. Click the Save button on the main toolbar, or select File->Save As from the main menu.        

  2. Select the macro _init_pyvisa from the Select Macro list.   

  3. Click the Execute button.                                                                                                                                                                                                                     

  4. Check the results of the script execution in the IC-CAP Status Window.                                                                             

                                                                                                

The full content of the status window should read:

 

['C:\\Users\\<username>\\Envs\\icenv\\Lib\\site-packages',

'C:\\Keysight\\ICCAP_2016_01\\bin\\python27.zip',

'C:\\Keysight\\ICCAP_2016_01\\tools\\win32_64\\DLLs',

'C:\\Keysight\\ICCAP_2016_01\\tools\\win32_64\\lib',

'C:\\Keysight\\ICCAP_2016_01\\tools\\win32_64\\lib\\plat-win',

'C:\\Keysight\\ICCAP_2016_01\\tools\\win32_64\\lib\\lib-tk',

'C:\\Keysight\\ICCAP_2016_01\\bin',

'C:\\Keysight\\ICCAP_2016_01\\tools\\win32_64',

'C:\\Keysight\\ICCAP_2016_01\\tools\\win32_64\\lib\\site-packages',

'C:\\Keysight\\ICCAP_2016_01\\tools\\win32_64\\Lib',

'C:\\Keysight\\ICCAP_2016_01\\iccap\\lib\\python',

'C:\\Users\\<username>\\iccap\\python']

C:\Users\<username>\Envs\icenv

Resource Manager of Visa Library at C:\Windows\system32\visa32.dll

(u'GPIB0::16::INSTR')

GPIBInstrument at GPIB0::16::INSTR

 

The Bottom Line

If you completed all of these steps successfully, you should now be able access the full capabilities of PyVISA from IC-CAP 2016. That means you can create transforms for instrument control and data acquisition over any supported interface.

 

Hopefully this information will be beneficial to those wanting to customize their IC-CAP 2016 installation to take full advantage of the many powerful Python packages available for download, or to write their own custom Python/PyVISA measurement routines. This method can also be used to install additional virtual Python environments for use with other Keysight products like WaferPro Express 2016. In a future blog post, I’ll outline the steps to do just that. In the meantime, for more information on IC-CAP or Keysight IO Libraries, go to www.keysight.com/find/eesof-iccap and www.keysight.com/find/IOlibraries, respectively.

 

References:

About Python

If you are new to Python programming, here’s some information to help you follow the steps in this blog.  

  • Python is an"interpreted" language, which means it generally executes commands typed by the user in an interactive command shell. This is convenient for testing program statements to learn the Python syntax. However, a more common means of writing a Python program is to create a Python script file with the '.py' extension. Say you created an example program and save it as 'example.py.' To run the program, you simply type 'python example.py' at the command shell prompt.
  • Python scripts, which are often called modules, can also be used for creating libraries of functionality, and are distributed along with program resources in packages.
  • Packages can be installed and combined with user-generated code to extend a program's functionality.  
  • PIP is the Python package installer that integrates with PyPI.orgthe Python Package Index. It is a repository of numerous free Python applications, utilities and libraries. PIP allows you to download and install packages from the package index without manually downloading, uncompressing and installing the package via the command 'python setup.py install'. PIP also checks for package dependencies and automatically downloads and installs those as well. 
  • An environment is a folder (directory) that contains everything a Python project (application) needs to run in an organized, isolated manner. When its initiated, it automatically comes with its own Python interpretera copy of the one used to create italongside its very own PIP. 

 

Links:

Keysight EEsof EDA’s Advanced Design System (ADS) software can help you overcome your signal and power integrity challenges. As the world’s leading electronic design automation for RF/MW and high-speed digital applications, ADS features a host of new technologies designed to improve productivity, including two EM software solutions specifically created to help signal and power integrity engineers improve high-speed link performance in PCB designs. 

Below are ten ways ADS can solve your most common SI/PI Design Challenges.

 

1. ADS provides speed and accuracy for your SI EM characterization

Don't be slowed down by increasing data rates. ADS provides two EM analysis solutions - SIPro and PIPro - that are specifically designed to handle high data rates, without sacrificing accuracy or speed. The limiting factor of 3D-EM technology for SI analysis is simply the scale and complexity of PCB designs. However, SIPro focuses on enabling SI EM analysis of high-speed links on large, complex high-speed PCBs, while PIPro is used for PI EM analysis of power distribution networks, including DC IR drop analysis, AC PDN impedance analysis, and power plane resonance analysis. 

 

Figure 1. SIPro delivers results approaching the accuracy of full-wave 3D-EM solutions, but in a fraction of the time.

 

2. ADS simplifies the use of S-parameter files for your parts

Imagine you’ve just downloaded an S-parameter file for a part you are considering; in this case, a high-speed connector for a backplane. It has a large number of ports on it, so you want to first inspect the quality of the data and then use it in your simulation. How do you wire it up? Which ports are paired?

Traditionally, the answer might be to open up the data in a text editor. However, with ADS’s S-Parameter Checker, designers can now easily view the contents of any S-parameter file without having to setup an S-parameter test bench simulation. This allows them to directly plot the individual relations they wish to see, and shows them the port names against each pin. It also tells designers if the file is passive or reciprocal, as well as the number of data points in the file and the frequency range it covers. Designers can even use S-Parameter Checker to rename, re-order and reduce the number of ports, which enables them to save a new, more usable S-parameter file (Figure 2).

 

 

Figure 2. The S-Parameter Checker allows design engineers to easily rename, re-order and reduce the number of ports.

 

3. ADS provides access to industry-leading channel simulator technology

ADS's channel simulator technology sprung forth in 2009 when transient simulation (SPICE) couldn’t address the measurement of margin-to-mask for really low bit-error-rates (BER), as demanded by high-speed link designs.

Dr. Fangyi Rao's 2006 patent to correct for passivity, while ensuring causality, ensured ADS to be regarded as the msot accurate solution for handling cascades of S-parameter models combined with circuit models in one schematic. The pace of innovation continues today with ADS's Channel Simulator still the industry-standard model. Additionally, the Channel Simulator now supports IBIS package (.pkg) entries directly and more extensively before.

 

Figure 3. With ADS, designers can mix-and-match models from IBIS, IBIS-AMI, SPICE, and generic built-in models.

 

4. ADS stays ahead of technology waves (such as PAM-4)

Market pressures on IP routers set an expectation to do more at a lower cost per bit. However, to go faster and provide a single 100-Gbps electrical lane across the distance of a typical backpane is beyond present day technology. 

The solution lies in Pulsed-Amplitude Modulation (PAM) for high speed serial links. PAM represents a revolutionary step in the industry, but comes with its own unique set of challenges as well. For example, we can transmit a PAM-4 symbol at 28 Gbaud and deliver 56 Gbps at the other end, but the IC's use more power and the signal itself has a reduced Signal-to-Noise ratio (SNR). 

Whether you are challenged with managing complexity while reducing production cost, or researching how to go further and faster on low-loss materials and fabrication processes,

 

 Figure 4. ADS supports PAM-4 simulations, which offers a viable alternative to NRZ. 

 

 

5. ADS accelerates DDR4 simulation methodologies

In simulations, how do you check compliance against the mask? Keysight EDA offers a novel DDR Bus simulator specifically designed to accomplish this task. It is a bit-by-bit channel simulator for parallel buses. It characterizes all transmitter paths at once, and calculates the BER contours for each eye at the receive side, together with the measurements for margin to mask. 

The simulator is unique in that it correctly handles the asymmetric rise and falling edges found with single-ended signals.The Tx and Rx models can be used to drive IBIS models, or mixed with SPICE models. The speed of the simulator allows it to be used in place to transient simulation for many pre-layout tasks, where the designer wants to sweep multiple parameters, or investigate performance movements. Together with batch simulation, it is a powerful tool for pre-layout design exploration, as well as post-layout verification for compliance.

 

Figure 5. Keysight EEsof EDA's DDR Bus simulator is a bit-by-bit channel simulator for parallel buses.

 

6. ADS puts power in the hands of designers

Power Integrity has become an ever-increasing challenge in modern day high-speed systems, driven by three main forces: higher device integration, lower IC supply voltages, and smaller real estate on the PCB. These modern challenges have forced engineers out of their notebooks and into true PI-DC simulators in order to take into account the real physical layout of the power delivery network (PDN). 

With ADS and the new PIPro suite of EM simulators, designers receive visual feedback in just second on exactly what the voltage distribution looks like for the selected power and ground nets. ADS also allows designers to check the current flow through individual vias and the voltage and current at specific locations like individual pins on the sinks and voltage regulator module (VRM). This information is easily reported in a sortable table. Vias that carry too much current can be highlighted in the layout for easy identification (Figure 6).

 

Figure 6. Vias carrying too much current can be highlighted in the layout for easy identification.

 

7. ADS enables flat PDN impedance responses

Once the initial pre-layout design has been created, the first-pass of the PCB layout can be imported into ADS 2016 for analysis using PIPro EM technology. PIPro’s net-driven user interface allows designers to quickly select the power and ground nets for the PDN network they want to simulate, choose simulation models for each of the components (e.g., decaps, EMI filters, inductors, and resistors, etc.), and setup the PI-AC simulator to compute the PDN impedance of the distributed layout with components in place. 

Since the PI-AC simulator has EM technology designed specifically for this purpose, a very accurate result is returned in minutes, not days. Designers can then use ADS 2016’s field visualization, PDN impedance and S-parameter plotting to determine if there are problems with the current PDN design, and to check coupling from one capacitor to the next. With just one click, a schematic representation is generated to transfer the EM-characterized model, together with circuit models of the components.  This back-annotation to an ADS Schematic enables  one smooth cohesive workflow. Designers can then apply their behavioral VRM model, and further tune the decaps for final verification/optimization.

 

Figure 7. Increasing the decoupling capacitance while increasing ESR improves impedance response flatness.

 

8. ADS enables electro-thermal simulation

As power delivery networks are forced into tighter PCB real-estate, the power plane becomes far from idealized.  Usually the once perfect plane is perforated heavily with clearance holes from stitching vias, and it can be a struggle for the layout engineer to get the required current up into the package of the device that requires it, without passing through narrow traces of metal.  Calculating an accurate IR-Drop is important for the PI designer, but also knowing the absolute temperature that the PDN traces, vias and chip die will reach, is invaluable information.   High temperatures can cause reliability issues; as the temperature cycles from on/off states can cause the via barrels to weaken and crack over time.

It is not intuitive to the designer whether a via is undersized for the current that is passing through it.  The temperature rise is very dependent on the width of the traces attached to it.  Secondly, resistance of a trace increases with temperature, requiring simulation analyses to determine the final steady state condition.  For every 10 degC change in temperature we see a 4% change in resistance of a trace. These observations point to a need to simulate the PDN design with a DC IR Drop electro-thermal solution.    

ADS provides a fully-automated integrated Electrical-Thermal-Electrical iterative simulation.  Users receive the most accurate representation of DC IR Drop results by taking into account local resistivity changes due to heating. The additional Thermal-only simulation, gives the user the ability to perform thermal floor planning.

With ADS you can easily copy existing DC IR Drop simulation setup to new Electro-Thermal simulation and visualize a list the temperature of planes, pins and vias.

 

Figure 8. DC IR Drop Electro-Thermal analysis - visualization of temperature.

 

9. ADS has an interconnect toolbox (Via Designer and CILD)

The signal integrity design challenge is not just to successfully recover the transmitter signal at the receiver, but to understand what is controlling the performance.  What are the significant margin eaters and which ones can I optimize?

Typical connections between a transmitter and a receiver include some section of application specific custom PCB routing.  ADS has a signal integrity tool box to help explore the design trade-offs and deal with the complex interaction between stack-up, transmission line losses, and via topology.

Designing the PCB interconnect starts with some sort of PCB stack-up definition in order to start evaluating the different types of possible transmission line topologies.  Once the transmission lines are optimized for impedance and losses, then one needs to look at via performance to transition between layers. Anyone of these steps has cost and performance trade-offs that can impact the other, resulting in a complex inter-relationship to determine which feature is the real margin eater:  Layer Count, Line Z, Via Backdrills, Material, Layout Density, etc.

ADS provides an Interconnect Tool Box that includes Substrate Editor, Controlled Impedance Line Designer, and Via Designer to simplify the pre-layout PCB interconnect investigation.

Figure 9. This type of pre-layout investigation enables an engineer to understand what is controlling the design margins and make informed cost vs. performance decisions.

 

10. ADS embodies the Keysight philosophy:

Hardware + Software + People = Insights

With Keysight's greater software-centric solutions focus, Keysight EEsof EDA plays a leading role in virtual compliance testing. Through Compliance Test Benches in ADS, designers can now take ADS simulated waveforms and test them against the same gold suite of compliance tests used on the bench with final verification hardware to attain the utmost confidence in a designs's compliance.

Further bolstering these capabilities in ADS is the support Keysight EDA offers its customers. That support includes a world-wide technical support presence, expert Application Engineers and consultative Field Sales Engineers. This support, together with Keysight’s hardware and software solutions and technical expertise gives customers greater insight and in turn, greater chance of success.

 

 

Keysight ADS further cements its leading position in electronic design software with continued advances for circuit simulation, layout and layout verification, silicon RFIC, and just as critically, signal and power integrity.

 

Welcome to Tim’s Blackboard! This is the place to find discussions on interesting topics related to signal integrity and power integrity. Find other cool posts here!

 

Last time on Tim’s Blackboard, we talked about linear Feed-Forward Equalization (FFE). This week, we will discuss the nonlinear Decision Feedback Equalization (DFE).

 

All the ADS content shown is in the attached workspace. Make sure you download the attached workspace and apply for a free trial to apply DFE to your own channel!

 

Introduction

When I first learned about decision feedback equalization, one of the bullet points is, “it is a nonlinear equalizer”, but I never knew why. Today, I will answer the question:

What makes DFE a nonlinear equalizer? 

Decision Feedback Equalization Technique

Shown in Fig. 1, decision feedback equalizer (DFE) can open a closed eye. Nonetheless, the signature of an opened DFE eye is different than other equalizations. There are kinks in the eye diagram. To examine the eye diagram a little closer, we apply single pulse analysis to look at the blink of an eye.

 

Fig. 1: Keysight ADS channel simulation demonstrating Decision Feedback Equalization (DFE) with different number of taps. DFE exhibits kinks in the eye.

 

Just like the eye diagram, we expect the single pulse response after decision feedback equalization to also have kinks. Sure enough, in Fig. 2, we see the kinks in the equalized single pulse response.

 

Fig. 2: Equalized single pulse response shows how DFE corrects post-cursor ISI on a single pulse that has all 0’s but a single 1. DFE inserts negative amplitudes after the received “1” pulse to better detect the next 0.

 

Taking a closer look, one observes that since the single pulse has all 0’s but a single 1 in Fig. 2, as soon as DFE algorithm sees a 1, it tries to reduce inter-symbol interference (ISI) by adding negative amplitudes so that the following low voltage is lower, allowing better detection of the next 0.

 

By the same token, when we send a single pulse that has all 1’s but a single 0, we should expect that as soon as the algorithm sees a 0, it tries to reduce ISI by adding positive amplitudes, allowing better detection of the next 1.

 

Fig. 3: Equalized single pulse response shows how DFE corrects post-cursor ISI on a single pulse that has all 1’s but a single 0. DFE inserts positive amplitudes after the received “0” pulse to better detect the next 1.

 

Result shown in Fig. 3 is consistent with our expectation. DFE algorithm is reducing ISI based on the detected data (symbol).

 

Fig. 4: Comparison between received waveform and equalized waveform shows how DFE acts on the received waveform.  

 

By comparing the received waveform and waveform after DFE, as seen in Fig. 4, we can further see the action of DFE algorithm, but the question remains:

What makes DFE a nonlinear equalizer?

Symbol Detection and Decision: A Nonlinear Filter

At the arrival of received data (symbols), DFE algorithm detects and makes a decision. Assuming the decision is correct, proper tap values are chosen and feedback to the originally received data.   

 

Fig. 5: An example of a symbol detector. Because the output does not scale linearly with the input, a symbol detector is nonlinear.  

 

Shown in Fig. 5 is a symbol detection processing block. As the input doubles from 0.6 V to 1.2 V, the output does not double. Consequently, symbol detection is nonlinear. In turn, decision feedback equalization is also nonlinear.

But how do we make sure the detection is correct?

Fig. 6 is an illustration of DFE block diagram. The received symbol first undergo feedforward equalization so that the symbol detector can make the correct decisions. After the symbol detector makes a decision, the result goes through a feedback filter to be combined with the previously detected symbol.  

 

Fig. 6: Decision Feedback Equalizer (DFE) block diagram. A feedforward filter is at the front end of DFE to help the symbol detector make a correct decision. Each decision then goes through feedback filter to be combined with previous symbol.

 

Because the input to the feedback filter consists of the sequence of decisions from previously detected symbols, which it uses to remove the portion of the ISI caused by those symbols, DFE only removes post-cursor ISI. Moreover, since DFE assumes that past symbol decisions are correct. Incorrect decisions from the symbol detector corrupt the filtering of the feedback loop. As a result, the inclusion of the feedforward filter on the front end is crucial in minimizing the probability of error [1].

 

Realization of Decision Feedback Equalization

Given the basic algorithm of DFE, I decided to design my own DFE, see Fig. 7.

.

Fig. 7: Demonstration of a homemade DFE in Keysight ADS. See attached workspace for detail.

 

Knowing the input sequence is going to be a single “1” pulse, i.e. all 0's but and single 1, I first changed the feedback filter coefficients, V_tap1 and V_tap2, until the post-cursor ISI is reduced enough. Then, I adjusted the delay of the two taps so the corrections take place at the right time. When all was said and done, I had created a homemade 2-tap DFE. Fig. 8 shows the equalized single pulse response.

 

Fig. 8: Applying homemade 2-tap DFE to a single pulse.

 

In the process of creating a homemade DFE, I learned that DFE algorithm is not trivial. It requires many moving pieces to align. Besides the correct symbol detection, the timing and feedback filter coefficients (tap values) also need to be appropriately selected for different channels.

 

Fig. 9: DFE algorithm is readily available in Keysight ADS channel simulation. There are several adaptive algorithms to choose from.

 

Good news! To help expedite the simulating and testing process, DFE algorithms are implemented and readily available in ADS. ADS helps you test the amount of stress your channel can handle with DFE and adaptive DFE enabled, see Fig. 9. 

 

Summary of Equalizations

After today, we have talked about all three equalizations,

·        Continuous Time Linear Equalization (CTLE),

·        Feed Forward Equalization (FFE),

·        Decision Feedback Equalization (DFE).

 

Below is a summary of the equalizations.

Table 1: Summary of Equalization Techniques 

 

Each of the equalizations has its own personality. While CTLE is sitting in the analog world, operating in the frequency domain, in the digital realm, FFE and DFE are working comfortably in the time domain.

 

Of course, each personality has its strength and weakness, and so does each equalization. In the near future, I will examine the pros and cons of equalization techniques. Make sure you bookmark the blog and check back regularly.    

 

For the upcoming post, I will take a step back and ask the question:

What is Signal Integrity? 

Until next time, make sure you download the attached workspace and apply for a free trial to apply DFE to your own channel!

 

References

[1]       S. H. Hall, Advanced signal integrity for high-speed digital designs. 2009.

 

kaelly_farnham

What is PathWave?

Posted by kaelly_farnham Employee Feb 14, 2018

PathWave is the new design and test software platform from Keysight Technologies. It combines design software, instrument control, and application-specific test software in an open development environment.

 

PathWave was the big news that Keysight unveiled at DesignCon at the beginning of February 2018.

 

PathWave at DesignConPathWave design and test software platform

PathWave signs were all over the DesignCon floor and meeting rooms. PathWave is an open, scalable, and predictive software platform that integrates hardware and software at every stage in the product development workflow. The PathWave software platform provides you with flexible and immediate access to the design and test tools you need, when you need them. 

 

Kaelly delivers flash seminar at DesignCon

 

At the show, I delivered a Flash Seminar about PathWave that was standing room only. Customers were very excited to hear how this new platform will affect them. It will help all engineers who work in design and test save time by connecting and integrating their workflows.

 

How does PathWave save me time? This was the most common question I got from engineers at the show.

 

The PathWave platform is built on a software framework that will connect all software and hardware in design, test, measurement, and analysis. On top of the framework, PathWave offers plug-ins and applications, enabling engineers to customize the environment for their specific tasks. It’s the customization combined with the interoperability provided by the common framework that allows for the most time savings. Below is an example.

 

 

PathWave Semiconductor Manufacturer Example

PathWave will connect and integrate the entire design and test workflow as shown in this example of a test setup for a semiconductor manufacturer.

 

PathWave can be customized for many applications, and above is just one example of a semiconductor manufacturer who needs to save test time because they are missing production targets. This customer struggled because they had a growing number of test parameters, were spending too much money on separate software test modules, and had a complex architecture that wasn’t easy to develop in, visualize data flows, or debug.  

 

With Keysight PathWave, their entire workflow will be connected and integrated with one single platform.  If desired, they’ll automatically get updates for all new releases of the software. They can save even more test time by pushing all the computations to the cloud or a local cloud. They’ll be able to connect to 3rd party hardware, so they can connect to existing equipment they already have. They can choose a software environment that includes a lightweight sequencer, plugin templates, package manager as well as development GUI, results and timing analyzers for best test team collaboration and efficiencies.  They can rely on consistent measurements from early validation to final manufacturing. 

 

And with Analytics as a big part of PathWave, they will be able to gather, store, and perform analytics on their test equipment and manufacturing data, improving productivity and asset utilization with the built-in predictive algorithms.

 

This is just one example of how PathWave is saving engineers time. For more information, check out PathWave online or contact Keysight.

Phased Array Systems have been around for decades, mostly confined to the aerospace industry; but with 5G development underway, phased arrays are becoming more common and in demand. In order to successfully design and deploy a product the first time, engineers should know how to avoid costly mistakes by using new techniques and simulation methodologies.

 

Mistake 1: Not predicting the far field spurious emissions in the simulation.

Whether you have an Aerospace/Defense or a commercial communications system, it must pass the test of a spurious emission mask (SEM). The masks are specific to each application, but the requirement remains the same. In the case of phased array, due to the added spatial dimension, the SEM test is more elaborate and is conducted in an anechoic chamber. The SEM test is conducted over the entire sphere (4π solid angle) for all the desired beam directions in both azimuth and elevation.

 

This very laborious procedure will be repeated if the spurious emissions are found the first time in the chamber and then have to be corrected in the design and brought back to the chamber. Therefore, if one can predict them upfront in the design cycle, the time spent in the anechoic chamber can be greatly reduced.

 

Figure 1. Predicting the desired beam directions up front in the design cycle, the time spent in the anechoic chamber can be greatly reduced.

 

This video goes into detail about how these spurious emissions can be predicted.

 

Mistake 2: Failing to explore the design thoroughly in the simulation phase.

Why would anybody not explore the design and simulation space?  There can be many reasons, but most likely it's due to the simulation speed and the accuracy of the modeling tool. One troubling behavior of phased arrays is coupling between the elements. The cost of a phased array is directly proportional to the size of the array. It is tempting to reduce the inter-element spacing, but unfortunately, that leads to increased coupling between the elements.

 

The coupling can happen in a few ways. If the lines in the feed network are close, they get coupled. An element not only transmits but can also potentially receive the energy from the adjacent radiating elements. This appears as the reflected energy back into the element’s input.

 

A third mechanism can also happen; if the elements are realized on the same substrate, higher order surface modes can be excited, propagated, and ultimately radiated. All these effects might cause loss of directivity in certain directions called blind angles. Unless one models the coupling effects and impedance mismatches accurately and explores the design over all the scan angles, these blind spots cannot be uncovered. A typical simulation shows a mild form of loss of directivity shown in the figure below.

 

Figure 2. Antenna coupling can cause loss of directivity in certain directions, called blind angles.

 

Mistake 3: Relying on simple spreadsheet calculations.

It is very popular to use spreadsheets to design RF systems. While it is true that they are readily available and quick to simulate, spreadsheets lack the capability to model and simulate. They cannot model multi-ports, RF mismatches, finite isolation, frequency response, accurate non-linearity, collated or uncollated noise, etc.

 

These common limitations become severe limitations when you start designing phased arrays. You need insights into all the paths, and phased arrays can have up to 400. You need to look into all the 400 paths to understand the behavior; because in a phased array, you cannot simulate one page and scale it up to 400 paths. You need to consider all of them simultaneously to achieve accurate results.

 

Figure 3. Phased array system design is much more complex than a single path RF system design. Designers cannot scale up the analysis of a single RF path analysis to a full array.

 

Under certain conditions, the amplifiers in the array are compressed. Due to this compression, the spurious radiation is violating the SEM as shown in the figure below.

 

Figure 4. SystemVue helps designers catch spurious radiation that violates the spurious emission mask, and can identify which amplifiers are driven into compression or saturation.

 

That's because some of the amplifiers in some of the chains are being driven into compression or even saturation. So how do you identify these amplifiers? Modern tools, such as SystemVue, make it easy to identify them and understand where the non-linearity is coming from.

 

 

Modern design simulation and modeling technologies will make it easy for engineers to avoid these costly mistakes. Watch Keysight’s latest video, How to Avoid Costly Mistakes in Designing Phased Array Systems, to receive greater insights on how to work around these common errors and download the workspace he uses in the video.

 

 

 

 Start your free trial of SystemVue today!

 

 

 

 

 

ICCAP - External Simulator interface

 

IC-CAP is a tool that enables modeling engineers to extract device model parameters using the simulator of their choice. For each model parameter extraction, measured data is compared against simulated data, and parameters are optimized to achieve the closest fit to the measured data. Because different simulators may use different syntax or "templates," adding a new simulator that is not supported requires its output to be adapted to one of these templates. For example LTSpiceIV uses a syntax that is very similar to SPICE3. IC-CAP supports the following simulator syntax:

  • SPICE2
  • SPICE
  • HPSPICE
  • HSPICE
  • Eldo
  • SPECTRE443
  • spicemodeads
  • SmartSpice
  • spmodeads
  • SPECTRE
  • Saber
  • hpeesofsim (native ADS syntax)
  • spmodeads (Spectre syntax)
  • hspicemodeads (Hspice syntax)

 

To make a link between IC-CAP and some external simulator, one must edit the config file $ICCAP_ROOT/iccap/lib/usersimulators.

usersimulators

 

In this config file, every line represents instructions on how to connect a different simulator to IC-CAP. The format is presented as follows:

simulator_name template_name path_name host_name pipe_capability

If the hostname is blank (or ""), then we assume the simulation will run on the same computer as IC-CAP. Some example entries are shown in the usersimulators file below.

usersimulators example file

Note: Lines with leading # sign are comments.

 

To link to an external simulator, the steps are as follows:

  1. Install the simulator program, making note of where the binary executable file resides. Also, verify that you have a valid license.
  2. Append or edit the entry in the $ICCAP_ROOT/iccap/lib/usersimulators config file for the external simulator in question.
  3. Re-start IC-CAP.
  4. In the model file where the simulator is to be used, specify the SIMULATOR variable to that simulator's name defined in the usersimulators file.

 

Troubleshooting

Should you encounter any problem, please try the following procedure, as it will usually allow you to figure out the problem. If that doesn't work, simply collect information from the steps in this procedure, as well as any pop-up error messages, and send it to the IC-CAP support team.

  1. Turn on IC-CAP's Status window, and check to see if any warning or error message appears.
    Illustration on how to bring up status window.

  2. Further, turn on the Simulation Debugger window. Check the netlist created by IC-CAP and the simulator's output files.
    how to get simulation debugger from IC-CAP

Note: Once the problem is addressed, it's recommended that you close the Simulation Debugger window. Leaving it open will slow down the overall simulation speed due to additional input/output interaction.

 

Using this process, you can quickly and easily link IC-CAP to a supported external simulator.

 

ShuangCai