Using LTspice as a Schematic Capture Tool for FreePCB

Introduction

Designing printed circuit boards (PCBs) for audio and other projects can be an exercise in frustration when you're first starting out. Part of this stems from the user-unfriendly nature of a lot of the available PCB design packages out there - even ones that cost a lot of money. I have recently been using the free, open-source program FreePCB for PCB layout. I really like this program a lot. It is very easy to learn and use and has well-written documentation including a tutorial. The FreePCB web site has a friendly support forum, as well as download links for the software and its documentation. Its user interface is effective and allows you to get work done quickly. However, this program does not have a schematic capture facility. It's assumed that you already have a netlist, which you import and use to create the PC board. This is because the main program is the work of one person, Allan Wright. This concentration on PCB layout alone means that what the program does, it does very well. By working through the tutorial, you'll see that the user interface design has features that are specifically created to maximize productivity. Maximum board size is 60 by 60 inches, and the number of copper layers can be as large as 16. This means you can create complex boards with professional quality.

This leaves the issue of what to use for schematic capture. I'm not very familiar with the available standalone schematic capture programs out there, but one popular one is is the freeware TinyCAD. However, I am a regular user of the freeware SPICE simulator from Linear Technology called LTspice. As part of a recent project, I had done a full simulation of a circuit containing about 100 components and needed to make a PCB of the design. One possibility would have been to redraw the schematic from scratch in a standalone schematic capture program. I had heard that it was possible to export a netlist from LTspice and import it into FreePCB. However, the available information on how to make this work was very sketchy. The LTspice documentation on netlist export is sparse. I was too lazy to redraw the schematic in a separate schematic editor, and I was also worried that in doing so I might introduce wiring errors in my design. So I decided to see if I could make the netlist export from LTspice work for this task. In this way, the netlist would be created from a schematic that had been checked for errors to the extent that the simulations run correctly. This page describes the things I found along the way that were necessary to make the whole process work without errors in the resulting PCB. If you decide to use LTspice and FreePCB together, following the steps here will prevent you from making some of the same errors that I did at the start.

Caveats

The techniques described here are not for everybody. They make the most sense for people who are already using LTspice for circuit simulation, and have a working simulation of an actual circuit design from which they want to create a PCB design. The SPICE techniques described here could be considered somewhat obscure or complex by some. Weigh your options carefully when deciding what tool to use for schematic capture. Should you decide to use LTspice in this role, these techniques will give you correct results when applied correctly. But if you are not already using LTspice as part of your design process, other schematic capture approaches may be more appropriate for your project.

What Can Go Wrong

In SPICE analysis, there is no concept of a pin number per se. And yet in LTspice you can choose to export a netlist of type, say, PADS, and it will dutifully create it, complete with pin numbers for all the devices. So a major question becomes, How does LTspice assign pin numbers to devices? And if they are not correct, the question becomes, "How do I get LTspice to assign the correct pin numbers"?

How To Get The Pin Numbers Right

Answering the questions above turns out to be the key to making the LTspice netlist export work properly. The trick to understanding how LTspice assigns pin numbers is "pin number in exported netlist = SPICE netlist order". SPICE has a required netlist order for each terminal of each built-in device type, and also for subcircuits. That is, if you were making a SPICE simulation by creating a SPICE netlist by hand with a text editor, the order in which you must specify such things as base, emitter and collector for a BJT is not optional. It's fixed by how SPICE works. Here are some examples.

Diode (see this online SPICE manual topic)
General form:
DXXXXXXX N+ N- MNAME
<OFF> <IC=VD> <TEMP=T>

Specific example:
D1 2 10 DIODE_MODEL

BJT (see this online SPICE manual topic)
General form:
QXXXXXXX NC NB NE <NS> MNAME
<OFF> <IC=VBE, VCE> <TEMP=T>

Specific example:
Q23 10 24 13 QMOD

Lets assume we're exporting a PADS netlist. For the diode example above, the anode (N+) is first in SPICE netlist order, while the cathode (N-) is second. D1 is the reference designator, while DIODE_MODEL is the name of the model. So according to the rule above, LTspice will export the PADS netlist with pin 1 of D1 connected to node 2 and pin 2 of D1 connected to node 10. Now, in FreePCB, as long as all diode footprints are defined such that pin 1 is the anode and pin 2 is the cathode, everything will work out fine. This is indeed the case for all of FreePCB's built-in diode footprints, so no special steps are required for diodes. The only concern with diodes is that if you need to create new footprints, remember to always make pin 1 the anode and pin 2 the cathode.

Another important part type should also be mentioned here, though it's not part of standard SPICE - the polarized electrolytic capacitor. If one were to simulate using the standard SPICE "C" component for a polarized electrolytic capacitor, the simulator wouldn't care, but when exporting a netlist, there would be a 50/50 chance of getting its polarity wrong. For this reason, it's essential to use the LTspice-specific "POLCAP" element for polarized electrolytics. When using POLCAP, one can observe the SPICE netlist and see that it ends up using a normal SPICE "C" element. However, it can also be seen that a consistent netlist order is followed for POLCAP. That convention results in the positive terminal of the capacitor always being listed first in the SPICE netlist. Therefore, when exporting a PADS netlist, the positive terminal of polarized electrolytic capacitors will always be assigned to pin 1 according to the "pin number in exported netlist = SPICE netlist order" rule. In the case of diodes, we are lucky because all the built-in diode footprints in FreePCB have the anode associated with pin 1 - the same as the exported netlist. Unfortunately, this is not the case with the built-in electrolytic capacitor footprints of FreePCB. They all associate pin 1 with the negative terminal.

There really is no perfect solution for the pin number discrepancy between exported POLCAP elements and the built-in FreePCB polarized capacitor footprints. Jumping ahead a bit, I verify the footprint of each component I want to use in my PCB design, give it a unique name, and put it into my own library. Then I know that things like the hole size and pad diameter will be correct given the lead diameter, and that the lead spacing will be okay. I do not use unverified footprints, only those from my own library. Because I go through this process anyway, my solution is to modify existing FreePCB polarized capacitor footprints by making pin 1 the positive terminal, and save them to my own library. On the positive side, the excellent FreePCB footprint editor and footprint wizard make this a snap.

BJT Example

Let's look at a BJT example. The netlist order rules above state that for the exported PADS netlist, the collector will always be pin 1, the base pin 2, and the emitter pin 3. But the pin assignments of actual BJTs will often not match this convention. So we need some method of pin swapping for BJTs. We could make different footprints in FreePCB for different devices. In such a scenario, pin 1 might be, say, the middle pin. This is a terrible solution though. The BJT data sheets clearly define what pins are 1, 2 and 3 are in terms of their physical location on the device, and which pins are E, B and C. Creating footprints that violate this relationship is not a good idea. A better way is to do the pin swapping from within SPICE. How do we do this? Enter the "pin-swapping subcircuit". Below is an example.

* This is a pin-swapping subcircuit to get package pin numbers
* correct for netlist export to PCB programs
.SUBCKT 2N5551_pkg E B C
Q1 C B E 2N5551
.model 2N5551 NPN(...)
.ENDS 2N5551_pkg

Here I've defined a subcircuit named 2N5551_pkg. I've assumed that you're going to use this subcircuit file for two purposes: first to define the model parameters for the device (in the ".model" directive above), and second to define the subcircuit itself with the appropriate pin swapping. In the .MODEL statement above, to the right of "NPN", I've omitted the actual parameters and put an ellipsis in their place to avoid obscuring the concept with the many details of a typical model definition. Often only node numbers are used in subcircuits, but notice how the use of E, B and C clarifies things here. On the line that says "Q1 C B E 2N5551" you always put C first, then B, then E. This never changes, and is a result of the SPICE netlist order rules for built-in BJT models as mentioned above. The pin swapping occurs on the first line, where it says .SUBCKT 2N5551_pkg E B C. Using the "pin number in exported netlist = netlist order of SPICE netlist" rule above, we see now that pin 1 will be E, pin 2 will be B, and pin 3 will be C. Now the pin numbering of the subcircuit matches that of the datasheet by virtue of the netlist order of E, B and C in the .SUBCKT declaration.

Okay, so we've figured out how to do the pin swapping. How do we put this all together so that when were creating a schematic, we can graphically drop a device in place and have the appropriate subcircuit be used? And how do we make sure that the graphical representation of a pin, say, a transistor collector, is assigned to the correct node of the associated subcircuit (and by our work above, to the correct pin number)? The answer is in the use of the LTspice symbol files (.asy files). When you drop a standard NPN transistor onto an LTspice schematic, the built-in LTspice symbol file called "npn.asy" is used. You tell LTspice which model is to be associated with this symbol file, and it assumes the symbol will always be associated with a .MODEL statement in a library on its search path. Because of this assumption and the required netlist order in a BJT .MODEL statement, LTspice will always assign the collector to netlist order 1, the base to netlist order 2, and the emitter to netlist order 3 for the built-in BJT models. But in general, we need to change this. Since netlist order in our subcircuit is equivalent to pin number, we will need, in general, different netlist orders for different devices. So we can no longer use the same symbol file (.asy file) for every device of the same type (such as NPN BJT, PNP BJT, etc.). The least confusing way to do this is to have a unique symbol file for each and every BJT part number in use. The steps to do this are as follows:

  1. Make a copy of npn.asy or pnp.asy as appropriate.
  2. Name it, e.g. 2N5551_pkg.asy.
  3. Open the e.g.2N5551_pkg.asy in LTspice.
  4. Do an "Edit, Attributes" (Ctrl-A).
  5. In the "Prefix" field, replace "QN" with "X" (no quotes). The "X" tells LTspice to use a subcircuit rather than a built-in model.
  6. In the "Value" field, replace "NPN" with e.g. "2N5551_pkg" (no quotes). This is the subcircuit name from the first non-comment line of the subcircuit file we wish to use (see the example above).
  7. In the "ModelFile" field, put, e.g. "2N5551.sub" (without quotes). This is the name of the subcircuit file associated with this device.
  8. Right-click on each pin and set the "netlist order" equal to the physical pin number for that pin. For example, the collector of a 2N5551 is pin 3 (node order 3), the base is pin 2 (node order 2) and the emitter is pin 1 (node order 1). Think "node order = pin number" here!
  9. Save the symbol file as, e.g. 2N5551_pkg.asy.

Now the 2N5551.sub and 2N5551_pkg.asy are "connected" to each other by virtue of the steps we've performed above. Then you place them in the same directory as the project you're working on. When you want to add an instance of the packaged 2N5551, you do an F2 (Edit component), then in the top directory combo box, you choose the current directory. The 2N5551_pkg will be displayed. Then you just drag one onto your schematic. Subcircuit and symbol file examples for the 2N5551 and 2N5401 can be downloaded here. To make similar ones for other BJT types, you can just copy the appropriate files (depending on if you want an NPN or PNP device) and edit the copies.

Op-Amp Subcircuit Example

An example of a pin-swapping subcircuit and its associated LTspice symbol file can be downloaded here. This example uses the Analog Devices OP27 subcircuit model. Inside the zip file, one of the files you'll find is the symbol file op27_dip8.asy. I just "borrowed" a .asy op-amp file from one of the built-in LTspice op-amp library parts and made a few modifications to it. Creating symbol (.asy) files from scratch using the LTspice symbol editor is a real pain, so try to reuse a similar file from the LTspice part library if possible.

If you open op27_dip8.asy in LTspice and right-click on the square box at each pin, you'll see that the "netlist order" field for each pin has been changed to the physical pin number of the device. The normal LTspice op-amp models only use netlist order from 1 to 5 corresponding to the pin count on the symbol itself. To get the pin numbers correct for an actual part, we need a pin-swapping subcircuit that maps the netlist order of the Analog Devices OP27 subcircuit model (which only goes from 1 to 5) to the physical pin number of the real part (which goes from 1 to 8).

When looking at op27_dip8.asy, do a Ctrl-A and you'll see that the "Value" field has been set to "op27dip8". That's the name of the pin-swapping subcircuit inside the op27.mod model file (also included in this zip file). Also note that the "ModelFile" field has been set to "op27.mod". That's the text file containing the subcircuit. Try looking at op27.mod in a text editor. At the top of the file is the normal OP27 subcircuit provided by Analog Devices, completely unchanged. Note that this subcircuit only has 5 external connections (as specified in its ".SUBCKT" line). We need 7 pins though. Normally we would need 8, but pin 8 is unused. In other words, we only need to add unused "filler" pins for those unused pins whose numbers are in between used pins.

At the bottom of the file, you'll see the text "Added by Andy". This is the pin-swapping subcircuit called out in the .asy file as "op27dip8". Its form is very simple and reproduced below. Note that the Analog Devices-provided subcircuit is called "OP27" while the pin-swapping subcircuit is called "OP27dip8".

.SUBCKT OP27dip8 1 2 3 4 5 6 7
X1 3 2 7 4 6 OP27
.ENDS

This accomplishes the following:

  1. Netlist order 1 in AD subcircuit (=non-inverting) is mapped to pin 3.
  2. Netlist order 2 in AD subcircuit (=inverting) is mapped to pin 2.
  3. Netlist order 3 in AD subcircuit (=positive supply) is mapped to pin 7.
  4. Netlist order 4 in AD subcircuit (=negative supply) is mapped to pin 4.
  5. Netlist order 5 in AD subcircuit (=output) is mapped to pin 6.

One can see how this could be extended to, say, quad op-amps. Instead of defining a single instance X1 in between the ".SUBCKT" and ".ENDS" directives, one could define four of them, say, X1, X2, X3 and X4. Then each of the connections for each instance could be associated with the correct external pin.

Op-Amp Subcircuit Test Projects And Netlist Export

A zip file containing two test projects for the OP27 subcircuit and symbol files can be downloaded here. Let's look first at the LTspice project file op_amp_test.asc in that zip file. The schematic is shown below in Figure 1.

Test Project For OP27 Subcircuit
Figure 1. Test Project For OP27 Subcircuit

Some of the elements, such as the op-amp and its feedback resistors, will of course end up in the final design on the PCB. But others, such as the positive and negative power supplies, the input signal source, and the load resistor R4 are not meant to be part of the final design at all, only the simulation. As a general rule, such components should not be hard wired into the design. Rather, they should be grouped together in one place and the electrical connections made not by wires, but by tagging the appropriate nodes with the node name of where they are to be connected. Figure 1 illustrates this technique. Also, nodes that have importance to the physical design, such as inputs, outputs, power supply voltages and so on should be labeled with human readable names using the LTspice Edit, Label Net command (F4).

You should find that this simulation runs without error. Since the op-amp subcircuit model works okay in this test project, we can try exporting a netlist using Tools, Export Netlist, and selecting the PADS netlist type. When you do this, the output netlist looks as follows.

*PADS2000*
*E:\Some\Path\op_amp_test.asc Wed Apr 04 15:41:02 2007*
*PART*
R1 100k
R2 10k
R3 1k
C1 0.1u
C2 0.1u
V1 15
V2 15
V3 0
R4 10k
U1 op27dip8
*NET*
*SIGNAL* in
R1.1 V3.1 U1.3
*SIGNAL* 0
R1.2 R3.2 C1.2 C2.2 V1.2 V2.1 V3.2 R4.2
*SIGNAL* out
R2.1 R4.1 U1.6
*SIGNAL* N001
R2.2 R3.1 U1.2
*SIGNAL* pos_15
C1.1 V1.1 U1.7
*SIGNAL* neg_15
C2.1 V2.2 U1.4
*SIGNAL* MP_00
U1.1
*SIGNAL* MP_01
U1.5
*END*

If you look through this netlist, youll see the op-amp pin numbers are correct. You'll also see some things we dont want. The voltage sources V1, V2 and V3 are in there, as well as the load resistor R4. None of these parts are meant to be in the final design. We do not want to edit the netlist to remove them though, because references to these parts will be scattered throughout the netlist, making editing very error-prone. Fortunately, weve separated these parts out in the project by not hardwiring them, making them easy to delete. The file op_amp_test_no_sources.asc, also contained in the zip file above, is a copy of op_amp_test.asc but with the voltage sources and R4 deleted. The modified schematic is shown below in Figure 2.

OP27 Test Project With Sources and Loads
Figure 2. OP27 Test Project With Sources and Loads Removed

If we export a PADS netlist using this project, we end up with a netlist file as shown below.

*PADS2000*
*E:\Some\Path\op_amp_test_no_sources.asc Wed Apr 04 16:35:34 2007*
*PART*
R1 100k
R2 10k
R3 1k
C1 0.1u
C2 0.1u
U1 op27dip8
*NET*
*SIGNAL* in
R1.1 U1.3
*SIGNAL* 0
R1.2 R3.2 C1.2 C2.2
*SIGNAL* out
R2.1 U1.6
*SIGNAL* N001
R2.2 R3.1 U1.2
*SIGNAL* pos_15
C1.1 U1.7
*SIGNAL* neg_15
C2.1 U1.4
*SIGNAL* MP_00
U1.1
*SIGNAL* MP_01
U1.5
*END*

This is what we want. All sources and loads that only make sense in the context of simulation have been removed. This is a netlist that we're almost ready to import into FreePCB. But there is one more thing thats of interest in typical circuits before we try to do so. In the process of simulating the circuit, many changes are normally made. Components have probably been added or removed. Often this results in missing reference designators. We want consecutive reference designators with no missing ones for the final design. Otherwise, when the parts list is made, confusion can result due to the apparent missing parts. There is a simple way to do this, though it's not documented in the LTspice help. Simply press Ctrl-Alt-Shift-R and that will renumber the reference designators consecutively.

Things To Consider Before Exporting Your Netlist

BJT Reference Designator Considerations

Earlier we saw that for BJTs using a normal .MODEL representation rather than a pin-swapping subcircuit, the pin numbering will always be C=1, B=2, E=3 in the exported netlist. Any BJT having a different pin numbering scheme requires a pin-swapping subcircuit. But what if the actual BJT really does have the C=1, B=2, E=3 pin assignment? Should you use a .MODEL representation for such BJTs, or should a subcircuit with a one-to-one pin numbering relationship be used? One consideration is the reference designators. For BJTs using the .MODEL representation, reference designators in the schematic and netlist will be of the form Q1, Q2, Q3 etc. For BJTs using pin-swapping subcircuits, the reference designators are of the form U1, U2, U3 etc., as if they were ICs. So if there's a mixture of .MODEL and subcircuit representations, there will be a mixture of "Q" and "U" reference designators for the BJTs. When I tried it this way, I found the inconsistency in the form of the reference designators confusing. Another point of confusion for me was the status of BJTs having a .MODEL representation. I could never remember whether such BJTs simply had the correct pin numbering to start with, or if I they really needed the pins swapped and I had simply forgotten to do so. For these reasons, I ended up creating pin-swapping subcircuits for all the BJTs I used, even if not all of them needed the swapping.

Testing the Pin-Swapping Subcircuits

The first time I tried out pin-swapping subcircuits in a real project, I was working on a voltage regulator. I swapped the BJT models for subcircuits and ran a DC operating point simulation. The DC output voltages were all correct, so I initially thought everything was okay with the subcircuits and symbol files. But then I did a View, SPICE error log in LTspice. This displays all the device operating points. What I found was that the VBE values of some BJTs were completely wrong, and the VCB values were about 0.6V. This showed that the collector and emitter were swapped either in the subcircuit or the symbol file. I checked my subcircuit definitions, and they were okay. Then I looked at the symbol files (.asy files) for the devices. It turns out I had forgotten to change the netlist order (= pin number!) of the pins in the symbol files. Correcting these fixed the problem. Before the fix, I got the right output voltage numbers because the problem devices were in the reverse active region, working just enough to get a correct DC operating point. The actual circuit would have blown up from reverse VBE breakdown, so the device operating points in the LTspice error log should be looked at carefully before exporting the netlist to make sure both the subcircuit and symbol files are correct.

Fixing Up The Netlist And Importing It

Repeated below is the first part of the netlist I included above.

*PADS2000*
*PART*
R1 100k
R2 10k
R3 1k
C1 0.1u
C2 0.1u
U1 op27dip8
*NET*
*SIGNAL* in
(Remainder of netlist omitted)

Older version of FreePCB do not accept the "PADS2000" netlist type, so if you are using an old version, you'll need to change "PADS2000" to "PADS-PCB" above for FreePCB to recognize the format. In any event, changing "PADS2000" to "PADS-PCB" can't hurt. But most importantly, each component must be associated with a FreePCB footprint. If the netlist were to be imported as-is, FreePCB wouldnt recognize the second field in each row (the component value). FreePCB wants to see footprint names in the second column, not component values. There are several ways to accomplish this. For the first PCB I ever created using LTspice netlist export, I imported the netlist as-is, only changing "PADS2000" to "PADS-PCB". Then I began adding footprints in FreePCB and assigning them to the parts within FreePCB. When you first import such a netlist into FreePCB, you'll see no part outlines at all, because there is no footprint assigned to any part. Then, as you create footprints and assign them to the appropriate parts, the parts will appear in the FreePCB rat's nest. The trouble is, they all end up being stacked on top of each other in the rat's nest. Then you have to drag them off to another location where they are separate from other parts and out of the way. This is a nuisance, so it's best to not do the conversion this way.

A better way is to create all the necessary footprints first before importing the netlist. Looking at the netlist above, you can see that copying the text between "*PART*" and "*NET*" into a spreadsheet is a great way to start a parts list. The next step should be to insert a new column for the FreePCB footprint name immediately to the right of the reference designator column in the spreadsheet, leaving the names initially blank.. As part of determining what the resistor power dissipations, capacitor voltages and so on should be, and figuring out which part types to use, I also create a column called "part type". An example of a part type is "1/4 W 1% Metal Film Resistor". If I know the packages for similar part types will be different, I ensure that the part type names are unique. Once I figure out the part types for all the parts, I sort the spreadsheet by part type. This groups all parts of the same type together. Then, for each part type, I create or locate an appropriate footprint in FreePCB. For each footprint created or located, I paste its name into the appropriate rows of the "footprint name" column. Grouping all parts of the same type together makes this step much easier because you end up pasting the footprint name into multiple contiguous cells of the spreadsheet.

Once these steps are done, you're ready to modify the netlist. To do this, I highlight the two spreadsheet columns containing the reference designator and FreePCB footprint name, copy them, and paste them such that they overwrite the original reference designators and values of the exported netlist. The resulting netlist for the op-amp circuit above is shown below.

*PADS-PCB*
*E:\Some\Path\op_amp_test_no_sources.asc Wed Apr 04 16:35:34 2007*
*PART*
R1 RL07
R2 RL07
R3 RL07
C1 CK05
C2 CK05
U1 8DIP300
*NET*
*SIGNAL* in
R1.1 U1.3
*SIGNAL* 0
R1.2 R3.2 C1.2 C2.2
*SIGNAL* out
R2.1 U1.6
*SIGNAL* N001
R2.2 R3.1 U1.2
*SIGNAL* pos_15
C1.1 U1.7
*SIGNAL* neg_15
C2.1 U1.4
*SIGNAL* MP_00
U1.1
*SIGNAL* MP_01
U1.5
*END*

The component values have now been replaced with FreePCB footprint names. This file is now ready to import into FreePCB. It can be downloaded here. To import it, you must first create an empty project in FreePCB using File, New. Once the project has been created, choose File, Import Netlist and select the netlist file name. The results should look something like Figure 3 below. You can try this yourself using the netlist linked above.

FreePCB Appearance After Netlist Import
Figure 3. FreePCB Appearance After Netlist Import

Notice that FreePCB has separated the parts for you so they're not all stacked on top of one another. Now you're ready to draw the board outline, place the parts and start routing!