M. T. Homer Reid MIT Home Page
Physics Problems Research teaching My Music About Me Miscellany

Impedance Matching in Circuit Simulation

A Guide for Designers
by Homer Reid

March 16, 1999

The art of impedance matching has traditionally been considered to reside squarely within the bounds of the laboratory-- designing a matching network is something you do after you've designed the circuit and have samples back from the fab to evaluate. For precision RF circuit design, however, for applications where circuits must deliver the utmost maximum gain and noise performance at the utmost minimum bias currents, thinking about matching only after the design is finished is a luxury you can ill afford. Indeed, for accurate simulations of your circuit's performance--to obtain even a rough approximation of gain and noise figure--you must include matching networks in your simulations, and as you make changes to your circuit you must update your matching networks to compensate.

It is this last fact that often constitutes the monkey wrench in automated RF design and automation. Indeed, designing a matching network is often considered something of a black art, and once you have one working you are hesistant to change anything, either in the circuit or in the network. But to explore the design parameter space thoroughly, to ensure that your design attains the highest performance feasible within its constraints, you must do just that: make a small change, re-evaluate the circuit, and see if the design improved. And the process must be repeated, not just once, but many times, perhaps hundreds of times if you're using an automated optimizer.

Now, with these changes, if you change only the circuit and keep the matching components fixed, your change might bring about some improvement in the circuit, but you will most likely not notice it. Indeed, the modification will destroy the input and/or output impedance matches, and the negative effects of reflection losses will overshadow whatever positive effects your change might have had. Instead what you need to do is to change the circuit, then recalculate values for the matching components, and then evaluate performance and decide whether the change helped or hurt.

Needless to say, you don't want to do this recalculation by hand. Instead, you can use one of two utilities I've developed to automate some or all of the procedure. In what follows, I'll explain how to do this.

The Master Equations

For obvious reasons, we would like to keep our matching network as simple as possible. Doing all our matching with just one component would be great, but is not possible; can we do it with two components? The answer, it turns out, is yes: for any combination of source and load impedances we can find a two-component matching network that makes the impedance of the load look like the complex conjugate of the impedance of the source. I have written a little memo deriving these results and the corresponding equations. Alternatively, if you don't care about the derivations and only want to see the results, I've included the following table.

To use this table, first find the real and imaginary parts of your source and load impedances: Zs=Rs + iXs, and Zl=Rl + iXl. Evaluate the condition in the third column of the table to find whether you can use the corresponding match. If your source and load impedances satisfy the condition, you can use a match of the corresponding topology; place matching components X1 and X2 between your source and load, in the configuration illustrated in the first column, and with values given by the equations in the middle column. Note that these equations give you values for the impedances the matching components must have; to calculate the component values (i.e., inductances and capacitances) you need to consider your operating frequency. This is all explained in the paper linked above.
Note that, for each topology, there are two different sets of possible component values, corresponding to the plus and minus signs in the first equation in the center column. Note also that at least one of the conditions in the third column is satisfied for any combination of source and load impedances. For some combinations, both conditions are satisfied. This means that we can always find at least two distinct matching networks, and in some cases we can find two more.

A Generalized Matching Network

Now that we have some equations, let's see how to use them in ADVICE and CELERITY. First of all, we don't know a priori what our source or load impedances are, so we don't know which of the two topologies we will be using; furthermore, even if we knew which topology, we don't know whether components X1 and X2 will be inductors or capacitors until we work out the equations and find the signs of their impedances. So basically we have no idea what the match will look like until we use ADVICE to measure the input and output impedances of our circuit.

One approach would be to start out with no matching components in our circuit, use ADVICE to measure the input and output impedances, calculate the required component values using the equations above, and then go back into our circuit file and add the new matching components. But editing the circuit file is a hassle, and if we do this then we have to reread the file into ADVICE, which is slow. So it would be best to put the matching components into the file to start out with, but initially set their values such that their effects are negligible. Later, after we measure the impedances and calculate component values, we can simply make the changes on the fly from the ADVICE command line, or (more importantly) from within a .CAL program.

So we agree to include matching components from the start. But, as we mentioned above, we don't know what the match will look like. So we need to include enough matching components that we can realize whichever we need of the two matching topologies pictured above. In other words, we need a generalized matching network. I have created such a network in SCHEMA; its external view looks like this:

and its schematic looks like this:

The generalized matching network has a series capacitor, a series inductor, shunt capacitors on both ends, and shunt inductors on both ends. Initially, the shunt capacitors are valued at 0.1 femtofarads, and the shunt inductors at 100 millihenries. These values ensure that the shunt elements are effectively not there (open-circuits) at any operating frequency you are likely to use. Similarly, the series capacitor is initially valued at 1 microfarad, and the series inductor at 1 picohenry; the parallel combination of these elements looks just like a wire (short circuit) at reasonable frequencies. (The 10 milliohm resistors are dummies inserted to prevent ADVICE from complaining about the loop of inductors.) The point of this circuit is that it contains all the components you could possibly need to construct a two-component matching network. If you plunk down one of these things between your source and your load, you will never have to change your circuit file, no matter how much your circuits change. Instead, when you need to make a change to the matching network, you simply set the values for the components you need, and leave the rest at their default (i.e. invisible) values.

To simulate a RF circuit, such as, for example, an LNA, I would put one of these generalized matching networks between the driving source resistance (usually 50 ohms) and the input to the LNA, and another one between the output of the LNA and the input to the next stage (which might be simply a 50 ohm load resistor). Initially, the generalized matching networks behave like short circuits, and the circuit simulates as if they weren't even there. Then I measure the input impedance of my LNA, and apply the matching formulas in the table above, with RS=50 ohms and XS=0 for a purely resistive driving source, to calculate and set values for the components of the input matching network. Similarly, I measure the output impedance and calculate values for the output matching network. At this point my LNA is set up just as it will be eventually be used in real life, and I can simulate the gain, linearity, and noise figure.

For those interested, here are the SCHEMA files for my generalized matching network: MATCH.E and MATCH.1.


To make this all concrete, let's look at an actual example. Consider the following schematic diagram, which depicts a test circuit for an LNA designed to operate at 1 GHz.

The LNA is powered from a 2.7 V supply and takes a bias current from the ideal source IBIAS. This particular LNA has a gain control switch, which is controlled by the source VLOGAIN. The driving source is VIN, and the 50 ohm driving source resistance is RS. A generalized matching network, IMATCH, is inserted between RS and the LNA. Similarly, the generalized matching network OMATCH is inserted between the output of the LNA and the 50 ohm load resistance. Blocking capacitors CBLOCK1 and CBLOCK2 are inserted to protect the DC bias levels of the LNA.

The first order of business is to match the input, which requires measuring the input impedance of the LNA. To do this, we'll use current source ITEST1 to inject an AC test current into the LNA input and look at the AC voltage on node VIN. Since we want to know the input impedance of the LNA alone, we need first to take out the source resistance RS. (Remember that the components in the input matching network IMATCH are initally sized so as to be essentially invisible at 1 GHz). The procedure looks like this:

ADVICE> .out vin vin 0        % define voltage output variable
ADVICE> rs 100meg             % take out source resistance
ADVICE> itest1 0 ac 1         % define test current source
ADVICE> .ac lin 2 1g 1.1g     % do AC analysis (really only need the first frequency point)

 AC analysis completed
      2 points to frequency:  1.100E+09

ADVICE> .pr re(vin) im(vin)  % display real and imaginary parts of input impedance

 ****************   Audit Summary For LNATEST  ***************  - ADVICE -
 AC Small-signal analysis                         Temperature     25.000 Deg C
  FREQ          REAL:         IMAG:   
                VIN           VIN     

  1.000E+09    1.6142E+02   -3.8824E+02
  1.100E+09    1.4074E+02   -3.6165E+02

We used the .ac command to run the AC analysis, and the .pr command to display the results. The real and imaginary components of VIN are just the real and imaginary components of the input impedance, since the AC test source had a magnitude of 1. As you can see, at 1 GHz our LNA has an input impedance of 161.42 - 388.24i ohms.

The next step is to plug these numbers into the formulae in the above table to see what matching networks are possible. Our source impedance is ZS=RS + iXS=50 + i0 ohms, and we just measured the load impedance. With these numbers you can see right away that we fulfill the criterion for the first matching topology, but not the second. From the equations in the center column of the table above we calculate:

X2=-174 +/- 331 (ohms)
X1=-(0.690)*X2 -120 (ohms)

Suppose we arbitrarily choose the plus sign in the first equation. Then X2=-505 ohms. To realize a imaginary impedance of -505 ohms at 1 GHz we need a capacitor of value 1/(2*pi*1GHz*505)=0.315 pF. Next, with this value for X2 we obtain X1=228 ohms. To realize an imaginary impedance of 228 ohms at 1 GHz we need an inductor of value 228/(2*pi*1GHz)=36 nH.

So now we know what components we need to realize the X1 and X2 elements in our matching network. Referring back to the topology of the match as illustrated in the table above, we see that X1 is a series component, while the X2 component shunts the load. Now let's go back to ADVICE and set the appropriate values in our generalized matching network. (Note that both series components of the generalized matching network were initially valued to look like short circuits, so we need to take out whichever series component we are not using in our match. Here 'take out' means 'make look like a really big resistor').

ADVICE> ximatch.lseries 36n    % component X1 (series) 
ADVICE> ximatch.cload   0.315p % component X2 (load shunt)
ADVICE> ximatch.cseries 0.1f   % take out unused series component

To see if this worked, let's now measure the aggregate input impedance we see looking into the matching network:

ADVICE> .ac lin 2 1g 1.1g       % do AC analysis

 AC analysis completed
      2 points to frequency:  1.100E+09

ADVICE> .pr re(vin) im(vin)     & display real and imaginary components of input impedance

 *****************   Audit Summary For LNATEST ***************  - ADVICE -

 AC Small-signal analysis                         Temperature     25.000 Deg C


  FREQ          REAL:         IMAG:   
                VIN           VIN     

  1.000E+09    5.0015E+01   -2.4103E-01
  1.100E+09    4.2826E+01    3.9124E+00

Sure enough, the matching network makes the input of our LNA look like a pure 50 ohm resistance, with only a tiny reactive component. Now I can put the source resistance back in and do all manner of simulations, knowing that I'm getting proper power transfer between the source and my amp. (Of course, before doing anything else I would need to repeat the above procedure to calculate components for the output matching network).

Right now you're thinking two thoughts. One is, "This is extraordinary! I can actually design matching networks right from the ADVICE command line!" The other is, "If he expects me to crunch all those numbers each time I change my circuit, he's on drugs!" And you're right: nobody would willingly go through all that hassle by hand on each iteration of the design process. Instead, I have a couple of ways to automate the process, and with them the matter becomes really quite simple.

Automating the Procedure: The match Utility

First, I offer you the match utility, which runs from the UNIX command line, and which automatically designs matching networks for arbitrary source and load impedances. You tell match your source and load impedances, and your operating frequency, and it gives you graphical representations of either 2 or 4 possible matching networks. If you simply type match at the command prompt, you get a usage message:

% match 

usage: match freq 2.14e9 rs 12.3 xs -45.6 rl 78.9 xl -10.0

       rs -- real component of source impedance
       xs -- imag component of source impedance
       rl -- real component of load impedance
       xl -- imag component of load impedance
       freq -- operating frequency


which indicates how to specify the command line parameters (they may be given in any order). As an example of the output of the utility, let's run it on the example circuit we just looked at. Remember that our source impedance was 50 + i0 ohms, our load impedance was 161.42 - i388.24 ohms, and our operating frequency was 1 GHz. Typing this into match, we get

% match rs 50 xs 0 rl 161.42 xl -388.24 freq 1e9

For a conjugate match between 
    a source impedance of 50.00 +  0.00i ohms, and 
    a load impedance of   161.42 + -388.24i ohms 
    at 1000.000 MHz: 

SOURCE----36.38 nH-------LOAD   or   SOURCE---- 0.70 pF-------LOAD
                     |                                    |
                     |                                    |
                    0.31 pF                             24.98 nH
                     |                                    |
                     |                                    |
                    GND                                  GND

Thank you for your support.


As you can see, match calculates and displays the component values for two realizations of the matching network. (If the other topology had been possible, match would have reported the two options for that topology as well). Notice in particular that the first possibility match reported is just the matching network we arrived at earlier by hand calculation.

The match utility is useful for interactive simulations, where you want to make various changes to the circuit by hand and see immediately how they affect performance. As long as you have a couple of generalized matching networks in your circuit file, it's a simple matter to measure the input and output impedances, plug the numbers into match (run it right from the ADVICE or CELERITY command line!), and then put in whichever components match tells you to.

To get match running on your system, download the source archive and type
% make
from the command line.

Automating the Procedure: The match Function

As we mentioned above, the command-line match utility is nice for interactive simulations. There are other times when you need the entire procedure to be done automatically. For example, suppose you want to use the .LOOP command to step up your bias current from 1 to 5 milliamps in 200 uA steps and test the performance of your LNA at each current setting. In this case you will need to redesign the matching networks at each current setting, since the input and output impedances of the amp change with bias current. As another example, suppose you want to use a design optimization tool like CENTER or HOMCTR. In this case you will want to rematch the circuit before each run through the design-objective calculation, and it will have to be done automatically. (For more information about design optimization, CENTER, and HOMCTR, see my design optimization page.)

To address these issues, I have written a C function, match(), to be used with the .CAL scripting interface. The match() function automatically designs a matching network and automatically sets the necessary values in a generalized matching network. Needless to say, to use the function you need to have one of my generalized matching networks between the source and load you want to match. (You can get SCHEMA files for my generalized matching network from the links above).

The prototype for this function looks like this:

void match(char *Name, double RS, double XS, double RL, double XL, double Freq);

The Name parameter is just the name given to the generalized circuit element (MATCH subcircuit) for which you want to choose values. For example, referring to the LNA test circuit above, you would put "IMATCH" in this slot to match the input, and "OMATCH" to match the output. The other parameters are identical to the command line arguments of the match program, as discussed above. For example, RS and XS are the real and imaginary components of the source impedance (the impedance seen looking out of the SRC terminal of the generalized matching network). RL and XL are the components of the impedance seen looking out of the LOAD terminal. Freq is the operating frequency.

To use the routine, first get the source file: matchr.c. Then you can either copy the contents of the file verbatim into your .CAL file, or else you can say #include "matchr.c" to include it.

For example, to match the input of the LNA as we did in the above examples, you would include the line


somewhere within the body of your .CAL function. When this function returns, the LNA input will be correctly matched. Next you would make a similar call to match the output. After this you can proceed to make gain and noise figure measurements on your circuit.

Of course, in practice you will also need to measure the input and output impedances of your circuit before you can call match(). This can be done in a couple of different ways. One possibility, which we already discussed above, is to feed an AC test current into the input (output) node of the amp and measure the resultant AC voltage. Here you have to be careful to take out the source (load) resistances to ensure that you're measuring the characteristics of the amp alone. As an example, the following code fragment might be used in a .CAL program with the LNA test circuit above:

 #include "usercal.h"
 #include "matchr.c"                         /* include source for match() */


 Waveform Vre,Vim;
 double R,X,Freq;

 Freq=1e9;                                   /* match at 1 GHz             */
 command("rs 100meg");                       /* take out source resistance */
 command("itest1 0 ac 1");                   /* set up AC test current     */
 command(".file ofile=/dev/null");           /* flush output data queue    */
 command(".ac lin 2 %e %e",Freq,Freq+1e6);   /* do ac analysis             */
 command(".file ofile=myfile");              /* write results to myfile    */
 Vre=wave_read("file=myfile name=re(vin)");  /* vltg on input node (real)  */
 Vim=wave_read("file=myfile name=im(vin)");  /* vltg on input node (imag)  */
 R=ycond(Vre,"COND=CROSS(x=%e)",Freq);       /* real part of input impdnc  */
 X=ycond(Vim,"COND=CROSS(x=%e)",Freq);       /* imag part of input impdnc  */
 match("imatch",50.0,0.0,R,X,Freq);          /* design input matching ntwrk*/

 command("itest1 0 ac 0");                   /* turn off input test source */
 command("itest2 0 ac 1");                   /* turn on output test source */
 command("rl 100meg");                       /* take out load resistor     */
 command(".ac lin 2 %e %e",Freq,Freq+1e6);   /* do ac analysis             */
 command(".file ofile=myfile");              /* write results              */
 Vre=wave_read("file=myfile name=re(vout)"); /* vltg on output node(real)  */
 Vim=wave_read("file=myfile name=im(vout)"); /* vltg on output node(imag)  */
 R=ycond(Vre,"COND=CROSS(x=%e)",Freq);       /* real part of output impdnc */
 X=ycond(Vim,"COND=CROSS(x=%e)",Freq);       /* imag part of output impdnc */
 match("omatch",50.0,0.0,R,X,Freq);          /* design output mtchng ntwrk */

 command("itest2 0 ac 0");                   /* turn off test current      */
 command("rs 50");                           /* restore source resistance  */
 command("rl 50");                           /* restore load resistance    */

 /* LNA now matched and ready to go ... */

One slight problem with this simple approach is the following. Suppose initially neither input nor output is matched, and you start by measuring the input impedance and inserting an input matching network. Next you measure the output impedance and insert an output matching network. The problem is that now the input impedance of the amp is slightly different than it was when you first measured it (because the load conditions of the amp have changed), so the input match you just designed is a little off. So you go back and re-measure the input impedance with the output matched, and then redesign the input match. But now the output impedance changes, so the output match is slightly off again, and so on. In my experience, two iterations of the procedure usually gives sufficient accuracy. But that's still one more iteration than you'd like to have to do.

Another, more efficient, option is to carry out an S-parameter analysis and compute the input and output impedances from the S parameters. (You can measure S-parameters with, for example, Joe Havens' s-parameter routine.) This approach has the virtue of automatically taking into account the infinite recursion problem we mentioned above, so you get accurate matches the first time through.

Implementation of the match()Routine

I haven't written this section yet, because I don't think anybody is interested. (For that matter, is anybody actually reading this page in the first place?) If you are interested, please let me know, and I will die of shock. No, no, just kidding, I will simply be very happy that somebody was interested and glad to discuss the implementation of the routine.

Differential Impedance Matching

So far we have considered only single-ended signal sources and loads. However, the above considerations may be immediately extended to the case in which you need to match a differential source to a differential load. In fact, as you can readily show, the equations remain exactly the same, and all you need to do is split the series component into two halves, placing one half in each leg of the differential signal path. It looks like this:

As this figure suggests, the procedure for constructing a differential match is as follows. First measure your differential source and load impedances. Then pretend you just measured single-ended impedances, and use the formulas above to calculate the series impedance Z1 and shunt impedance Z2 needed to realize a single-ended match. Insert a component with impedance Z2 between the two branches of your differential signal. Finally, insert two components, each with impedance Z1/2, in each branch of the signal path. The above figure illustrates the procedure for the load-shunt topology. Needless to say, it works just as well for the source-shunt topology too.

A word of caution: the series components in the differential match each need to have one half the impedance of the series component in the corresponding single-ended match. This does not necessarily mean they need to have one half the value. Indeed, if the components are inductors, you need half the inductance to get half the impedance, but if the components are capacitors you need twice the capacitance to get half the impedance. Be careful!

Differential Impedance Matching in ADVICE and CELERITY

I've created a generalized differential matching network in SCHEMA to go with the generalized single-ended match introduced above. The symbol looks like this:

and the circuit schematic looks like this:

Again the circuit contains some dummy resistors to stop the simulator from complaining about loops of inductors.

As in the single-ended case, putting one of these things between source and load in your circuit file ensures never having to change the circuit file to obtain an appropriate match. The .CAL source file above also contains a routine, dmatch(), to calculate and set component values in one of these generalized networks. You use it just like you use the single-ended version:

dmatch(char *Name, double RS, double XS, double RL, double XL, double Freq);

Here Name is the name you've given to the instance of the generalized differential matching network you want to set up. RS and XS constitute the impedance you see looking out from the source terminals of the generalized match. RL and XL make up the impedance you see looking out from the load terminals. Freq is your operating frequency.

Here are the SCHEMA files for my generalized differential matching network: DMATCH.E and DMATCH.1.

Homer Reid: Impedance Matching, by Homer Reid
Last Modified: 11/16/16