This chapter will be providing demonstrations of a novel script based schematic capture and board-level design application, called PCBScript, which enables designers to transition seamlessly between specification, pin table, schematic and board layout in an open, ASCII, single-file database. This tool automatizes design process enabling descriptive design entry using synthesis scripts. The functionality is based on a primitives library written in Perl.
PCBScript features:
The tool uses configuration parameters, pin lists of ICs, assignment and layout placement information typed in using a dedicated synthesis script. PCBScript is designed to work with Eagle, a conventional Schematic Entry, Place and Route tool.
PCBScript can create some parametrizable packages e.g. QFP packages, sockets, connectors, jumpers, a number of configurable symbols as well as the functionality to instantiate devices, to connect them with specified signals that allow to create the complete schematic of a board just by writing a script to provide all necessary information. Moreover, PCBScript allows placing the instantiated parts at board-level and routing the connections. The routing feature can be used to route signals or busses semi-automaticly, controlled by PCBScript commands that give coordinates or distances where to route. This can be done for any signal or part on the board. For more complex boards, routing busses in this way at least helps the autorouter of Eagle to route where you want.
Note: For documentation purpose, most of the following examples are structured in more than one line. But PCBScript at this stage allows inline commands only. As PCBScript is based on the script language Perl, besides dedicated PCBScript commands, that basically instantiate classes, the complete command set of Perl can be used. Experience with Perl is not required but helpful. A basic knowledge of Perl will the user allow to use more advanced features of PCBScript, to enlarge functionality or for debugging.
Design information e.g. the pin out of ICs exist or can easily be written in list or table format. The best way to get a great number of design infos is to read and extract them from files. PCBScript supports file I/O of easy structured formats like lists that contain a seperator to identify each column. A possible format could be:
** CHIP IC1 ** GND : 6 : Pwr addr4 : 7 : In addr5 : 8 : In VCC : 9 : Pwr optional ** CHIP IC2 ** ...
To read this data set, a file parser has to be initialized. Example 1 schows the intantiation of a Parser
. The Parser is implemented to read files by line.
To allow reading of different formats the Parser have to be configured.
Table 1 describes the parameters.
$parse_pins = new Parser( NAME => "pins", NUM => 2, SPLIT => "/ : /", START => "/CHIP 1/", STOP => "/CHIP 2/", OFFSET => 0, OFFSTOP => 1, GREP => "!/optional/" );
Parameter | Example | Description |
---|---|---|
NAME | "pins" | after parsing a message of the number of got "pins" is given |
NUM | 2 | the list has three columns, the Parser returns a double array, the third column is ignored |
SPLIT | "/ : /" | the separator of the list is ' : ' the complete perl syntax can be used here |
START | "/CHIP 1/" | if the string 'CHIP 1' occours in file, Parser begins reading next line |
STOP | /CHIP 1/ | reading is stopped at the end of the file or if 'CHIP 2' occours |
OFFSET | 0 | reading begins 0 number of lines after the start string |
OFFSTOP | 0 | reading stops 0 lines after the stop string |
GREP | !/optional/ | only lines with 'string' are returned, or ignores lines with 'optional' using '!' |
TAKE | 5 | reads the first 5 characters of a line, this can be used if the text format has no separators |
A package is generated by instantiating a generic package defined as a PCBScript class. The parameters of a Quad Flat Pad (QFP) package are described in table 2.
$PQFP208 = new PackQFP( NAME => "PQFP208", VALUE => "ALTERA", NUM => "208", PADL => "1.5", PADB => "0.22", PINL => "1.25", PINB => "0.22", DIST1 => "1.17", DIST2 => "0.27", DIST3 => "0.4", DIST4 => "2", DIST6 => "1.8", RADIUS => "0.7", CASEX => "14", CASEY => "14", FX => "12.75", FY => "12.75", BSC => "0.5", FILE => "QFP_PACKAGE.scr");
Parameter | Example | Description |
---|---|---|
NAME | "PQFP208" | a string representing the name of the package, if '>NAME' is used, the name can be changed in Eagle |
VALUE | "ALTERA" | additional text describing the package, if '>VALUE' is used, the value can be changed in Eagle |
NUM | "208" | number of pins |
PINL | "0.22" | length of pin |
PINB | "0.22" | width of pin |
PADL | "1.5" | length of SMD pads |
PADB | "0.25" | width of SMD pads |
DIST1 | "1.17" | length of edge indicating pin 1 |
DIST2 | "0.27" | length of edge |
DIST3 | "0.4" | distance between inner and outer border |
DIST4 | "2" | length of coordinate cross |
DIST6 | "1.8" | distance between circles and case |
RADIUS | "0.7" | radius of screw holes |
CASEX | "14" | length of case |
CASEY | "14" | width of case |
FX | "12.75" | (see Figure 1) |
FY | "12.75" | (see Figure 1) |
BSC | "0.5" | distance between pins |
FILE | "QFP_PACKAGE.scr" | output file name |
To create a QFP socket, PCBscript provides the SockQFP
class. The parameters are described in table 3.
$SOCQFP208 = new SockQFP( NAME => "SOCQ208", NUM => "208", PINL => "1.25", PINB => "0.22", PADL => "1.7", PADB => "0.22", DIST1 => "0.8", DIST2 => "0.27", DIST3 => "0.4", DIST4 => "2", DIST6 => "1.8", RADIUS => "0.7", TEXT => "YAMAICHI IC 149", CASEX => "21.8", CASEY => "21.8", CASEPAD => "16.05", FX => "12.75", FY => "12.75", BSC => "0.5", ALIGNPIN => "12.4", SCREW => "15.38", FILE => ">PACKAGE_LIB.scr");
Parameter | Example | Description |
---|---|---|
CASEPAD | "16.05" | equals FX of QFP packages (see Figure 1) |
ALIGNPIN | "12.4" | radius of alignment pin holes |
SCREW | "15.38" | radius of scres holes |
other parameters | see Table 2 QFP package |
A Dual Inline (DIL) package is instantiated using the DILPack
class. Table 4 describes the parameters.
$DIL32 = new DILPack();
Parameter | Example | Description |
---|---|---|
parameters | see Table 2 QFP package |
Connector packages are provided in the PackCon
class. The parameters are the same as described in Table 2 QFP package.
$PackCon6 = new PackCon( NAME => "CON6", NUM => "6", TEXT => ">NAME", BSC => "2.54", FILE => ">PACKAGE_LIB.scr");
The same procedure as described in section 1 allows creation of symbols required to visualize connections between Pins or SMDs. Example 6 shows the instantiation of a standard symbol with one row of pins that can be used for most applications.
$TIMERSym = new Sym( NAME => "TIMER", VALUE => "TIMER", DIST1 => "2.54", DIST2 => "5", DIST3 => "1.5", CASEX => "10", PINDATA => *TIMERPins, BSC => "3");
Parameter | Example | Description |
---|---|---|
CASEX | "10" | width of frame |
PINDATA | *TIMERPins | list of pins that can be read in using the Parser function or typed in manuallyNote: As this parameter is a list, a pointer ('*') to the list is used as a reference. |
DIST1 | "2.54" | distance between border and case |
DIST2 | "5" | distance between border and text |
DIST3 | "1.5" | distance of net edge |
other parameters | see section 1 |
Example 7 shows the instantiation of a connector symbol that can be used for connector packages, described in section 1. The parameters are the same as described in Table 6.
$Con6Sym = new ConnectorP( NAME => "CON6", NUM => "6", TEXT => ">NAME", CASEX => "5.08", DIST1 => "2.54", DIST2 => "1.9", BSC => "3");
A device connects each pin of a symbol with the equivalent pin of a package. Example 8 shows the instantiation of a device with one symbol.
$lib = new Device( NAME => "CON6", SYMBOL => $Con6Sym, PACKAGE => $PackCon6, TYPE => "Always", PREF => "CON", FILE => "DEVICES.scr");
Parameter | Example | Description |
---|---|---|
NAME | "CON6" | name of the device |
SYMBOL | $Con6Sym | reference to a symbol created bevore |
PACKAGE | $PackCon6 | reference to a package created bevore |
PREF | "CON" | prefix of the device, serves to number multiple instantiations of this device in schematics |
FILE | "DEVICES.scr" | the output file for the generated the Eagle script |
PCBscript allows to create devices with multiple symbols. For that, each symbol is added to the device using the Add
function. Example9 describes the creation of a device with 3 symbols. Note: the print command.
$Device1 = new Device( NAME => "FPGA1", PACKAGE => $SOCQFP240, PREF => "IC", BSC => "40"); $Device->Add(-50, 55, "Always", $symbol1 ); $Device->Add(0, 55, "Always", $symbol2 ); $Device->Add(50, 55, "Always", $symbol3 ); $Device->Print("SYMBOL.scr");
Parameter | Example | Description |
---|---|---|
X | -50 | x-position of symbol |
Y | 55 | y-position of symbol |
TYPE | "Always" | this symbol is always visible after instanting the device in schematics, see Eagle reference manual for more options |
SYMBOL | $symbol1 | reference to a symbol |
After executing the procedures to create devices as described in section 1, the outputfiles, that are Eagle scripts, have to executed in Eagle to create a Library and saved.
The devices (Symbol + Package) can then be added in schematics. In PCBscript a Schematic
class has to be instantiated that provides the functionality to emulate all actions a designer would perform manually in Eagle. The transfer between PCBscript and Eagle is done using Eagle scripts. In contrast to the Package and Symbol classes, which draw pins and lines as described in section 1, the Schematic
class uses Eagle commands to add and place Devices and connect them with signals and busses corresponding to the script based design entry. Each Symbol class as a dedicated algoritm for drawing the connections.
After instantiating the Schematics, any Device can be added and placed anywhere on a sheet or on different sheets. Tables 10 and 11 describe the implemented parameters for adding Devices in PCBscript. The parameter LIB can be any device, created by PCBscript as well as, edited manually in Eagle or a Device from any Eagle library. To move symbols and connect them with each other, PCBscript needs the coordinates of the symbols and each pin. One way is to edit the connections manually but this is not the intention of PCBscript. The easiest way when using "external" Devices is configuring one of the provided PCBscript classes using exactly the parameters (NUM, BSC, CASEX, ...) of the "external" device. More advanced users of PCBscript may create its own Symbols and Packages derived from existing classes, using object oriented methods as described in section 3. This guaranties matching coordinates between Symbols and nets.
$Barracuda = new Schematic( NAME => "Barracuda", TEXT => "Barracuda PreSilicon Prototype Board", LIB => "BARRACUDA.lbr", DIST1 => "15", DIST2 => "-2", BSC => "40"); $Barracuda->Add(8, 30, 300, "TIMER", $TIMERDevice );
Parameter | Example | Description |
---|---|---|
NAME | "Barracuda" | this could be the name of the project |
LIB | "BARRACUDA.lbr" | the used Eagle library |
DIST1 | "15" | length of nets (signals) |
DIST2 | "-2" | length 2 of nets (signals) |
BSC | "40" | distance between grouped symbols |
Parameter | Example | Description |
---|---|---|
SHEET | 3 | sheet number where the device is placed |
X | -50 | x-position of device |
Y | 55 | y-position of device |
BUS | 300 | y-position of master bus that connects busses of each symbol |
LIB | "TIMER" | name of device in Eagle library |
DEVICE | $TIMERDevice | reference to a device |
Devices with more than on symbol have to instantiated on sheet 1. Each Symbol can be placed to any position on any sheet using the Move
function, but at least one Symbol must stay at sheet 1.
Placing Symbols can be simplified using the Group
function, that allows multiple Symbols to be moved simultaneously and grouped together as shown in example 12.
move Symbol "PWR240" of Device "FPGA2" to sheet 4 at point (40, 40)
and move Symbols "FPGA1S" and "FPGA2S" to (35, 160) and (85, 160) on sheet 2. $Barracuda->Move(4, 40, 40, "FPGA2.PWR240" ); $Barracuda->Group(2, 35, 160, 50, "FPGA1.FPGA1S", "FPGA2.FPGA2S" );
Parameter | Example | Description |
---|---|---|
SHEET | 3 | sheet number where the symbol is placed |
X | 35 | x-position of symbol |
Y | 160 | y-position of symbol |
BSC | 50 | distance between grouped symbols |
SYMBOL | "FPGA2.PWR240", "FPGA3.PWR240" | list of Symbols (Device.Symbol delimited by point '.') |
As described above, design entry, the circuitry, the connections between the pins, can be done using the file parser functionality to get lists of signals or typing the lists manually before instantiating the Symbols. This Symbols are dedicated, that means all signals are saved in the internal datastructure of the symbol.
To reuse standard symbols more than on time in Schematics, the Assign
feature has been implemented.
This allows to connect single pins as well as bussed between devices with named signals.
Table 13 shows the syntax.
Assign("GND", "FPGA1.FPGA1S.MSEL0", "FPGA2.FPGA2S.MSEL0");
Parameter | Example | Description |
---|---|---|
SIGNAL | "GND" | signal that is assigned to each pin of the pin list |
PIN | "FPGA1.FPGA1S.MSEL0", "FPGA2.FPGA2S.MSEL0" | list of pins (Device.Symbol.Pin delimited by point '.') |
Busses can be assigned similarly as shown in example 13.
Assign("data[1..7]", "FPGA1.FPGA1A.IO_[7..14]", "FPGA2.FPGA2A.IO_[1..8]");
PCBscript supports concatenation. Different bit signals or busses can be grouped and assigned as shown in example 14.
Assign("bdmact,freeze,bus_clk,wait_mod", "CON3.MCU.MCU_[15..18]"); Assign("addbus[0..15],writdb[0..15],readdb[0..15]", "CON3.MCU.MCU_[1..48]");
Even more complicated constructs are supported to do whatever you want, as shown in example 15.
Assign("ffxx[15..0],GND,VCC,data[0..7], "CON3.MCU.MCU_[1..26]");
Assigning all Pins of an IC to VCC or GND is as easy as shown in example 16.
Assign("VCC", "FPGA2.FPGA2A.IO_[1,7,21,31..32]"); Assign("GND", "FPGA2.FPGA2A.IO_[3...4,11,15,30]");
The Connect
function creates the nets for each pin of a Symbol. Additionally, for the Standard1 Symbol, all Symbols (parameters of a function call) are connected with each other by busses as shown in example 17.
Connect(0, 171, 60, "data[0..16]", "FPGA1.FPGA1S", "FPGA2.FPGA2S");
Parameter | Example | Description |
---|---|---|
X | 0 | x-coordinate of bus |
Y | 171 | y-coordinate of bus |
BSC | 60 | distance between vertical buslines |
NAME | "data[0..16]" | name of the bus between all symbols |
SYMBOL | "FPGA1.FPGA1S", "FPGA2.FPGA2S" | list of symbols to connect |
After, the complete circuitry has been entried and all actions have been performed, an Eagle command file is created using the Print
function as shown in Example 18.
To get the complete Schematics of the circuitry, the output script has just to be executed in Eagle. If Schematics are split in different sheets, each script have to be run in Eagle, beginning with sheet 1.
Print("SCHEMATIC.scr", 1);
Parameter | Example | Description |
---|---|---|
FILE | "SCHEMATIC.scr" | output file name |
SCHEETS | 1 | optional '1' indicates the output is split into different files each representing a sheet in Eagle, without this parameter, all sheets are arranged on one page |
The board layout begins with placing the components. Each component is draged to the desired location on the board by typing the coordinates in form of a
Move
command into the script.
Move(CON1, 0.3, 2.5, 3);
Now the traces are added using the Route
command.
route Connector 1 via the coordinates
x = CON1.x, y = CON1.y x = 2.1, y = CON1.y x = 2.5, y = CON1.y x = 2.5, y = 7 x = IC2.x, y = IC2.y
Route(CON1, 2.1x, 2.5x, 7y, IC2[1..3]);
The basic concept of PCBscript is to read configuration information and produce a file output that another PCB design tool (Eagle) can input to create PCB Schematics and Layout. Eagle provides a script-interface that allows control of nearly every funtionality via script commands. PCBScript uses this interface and outputs different scripts that first create Symbols, Packages, second connect them and third create a board layout by placing the parts and routing the connections corresponding to the design entry of the PCBScript design script. To reach this, PCBScript converts design entry into different Eagle script files that are executed in Eagle.
At time of this paper, all functionality, neccessary to create the Barracuda Prototype board, has been implemented. This includes primitives to read any files to extract information as signal names, pin lists as well as IO information or assignment, routing and configuration information.
This version of PCBscript can not interact with Eagle. But Eagle privides a user language that allows writing out the internal data structure of Symbols, Packages.. . This output could be read in again by PCBscripts to create loopes of interaction between both tools to allow design optimization at a higher level. Examples 21 to 23 shows parts of PCBscript output.
Edit E100Q24V.sym; Layer 94; Pin 'CONF_DONE' In Short R0 Both 0 (-2.54 -3); Wire 0.254 (0 1.5) (0 -43.5); Layer 96; Change Size 2; Change Ratio 8; Text E100Q24V R0 (-8 -47); Edit E100Q24V.dev; Connect 'E100Q24V.TCK' '1' 'E100Q24V.CONF_DONE' '2' 'E100Q24V.nCEO' '3' 'E100Q24V.TDO' '4' \ 'E100Q24V.IO/INTDONE' '26' 'E100Q24V.TMS' '58' 'E100Q24V.TRST' '59' \ 'E100Q24V.nSTATUS' '60' 'E100Q24V.nCONFIG' '121' 'E100Q24V.MSEL1' '123' \ 'E100Q24V.MSEL0' '124' 'E100Q24V.TDI' '177' 'E100Q24V.nCE' '178' \ 'E100Q24V.DCLK' '179' 'E100Q24V.DATA0' '180';
USE BARRACUDA.lbr; Add DINA4_L R0 (0 0); Name DINA4_L (0 0); WINDOW FIT; Invoke FPGA3 FPGA3A R0 (40 160); Net RES3A_1 (40 160) (23 160) (21 162); Label (32.5 160) (25 160);
WINDOW 0.8; Display -19; Layer 20; Delete (6.25 2); Wire 0.01 (0 0) (12 0) (12 7) (0 7) (0 0); Move FPGA1 (5 5.2); Rotate (5 5.2);
Basic to PCBscript are its object oriented features, for detailed information, refer to the pan pages perlref, perlobj, and perlbot.
Creating a new Symbol is as easy as copying an empty standard package as shown in example 24, type the package name package NewSymbol;
, type the package name of the Symbol which functionality for printing, connecting signals is to be copied and save all as file 'NewSymbol.pm'.
The functionality of the new Symbol that differs from the old Symbol have to be rewritten. Copy the old subrouting and change it.
Often changed are the sub create
and sub print
function.
package NewSymbol; use Hash; use Primitives; use Pack; @ISA = qw( Symbol ); sub new { my $type = shift; my %params = @_; my $self = {}; my $i; @{$self->{SYMBOLS}} = []; for ($i=0; $i <= $#_; $i+=2) { @{$self->{$_[$i]}} = $_[$i+1]; } bless $self, $type; $#{$self->{SYMBOLS}} = -1; # initialize to 0 elements &create($self); } sub create { my $self = shift; if ( @_ ) { @pins = (); for ($i=0; $i <= $params{$prop[$i]}; $s++) { push(@pins, $s); } @{$self->{PINS}} = @pins; } } 1; # so the require or use succeeds
The concept of PCBScript is to make designing electronics with printed circuit boards easy, fast, inexpensive and fun. Before now, manual design entry has been common that is a time consuming, error-prone process. Table 16 compares manual design entry with script-based design entry using PCBscript.
Action | Manual Design Entry using Eagle |
Time | Time | PCBscript+Eagle |
---|---|---|---|---|
creating standard symbols, packages | instantiate from library | seconds | minutes | instantiate the class and configure the parameters |
adapting, changing symbols, packages | copy and modify existing objects from library | hours (depending on size) | minutes (independent of size) | instantiate the class and configure the parameters |
creating competely new symbols, packages | drawing all from the scratch | days (strongly depending on size) | hours (independent of size, dependent of complexity) | derive an existing class and modify the functionality |
entry of connectivity | drawing all manually | days (strongly depending on size), error-prone | hours (independent of size), basically no errors | use pin files or assign connections manually using scripts |
placing components in layout | placing all manually | minutes (depending on number of parts) | minutes (parts can be grouped), a snap between parts is possible (relative positioning) | type coordinates into script or snap parts together |
routing connections | route each signal manually | days (depends strongly on size) | hours (depends on complexity) | type coordinates into script or snap signals together (relative routing) |
change design | change symbol in library and change signals manually | days (strongly dependent on size) | minutes (independent of size) | just change some parameters in configuration script or pin file |
change routing | move connections manually | hours (strongly dependent on size) | minutes (if parts are snapped together) | change some values in configuration script |
add new ICs or change Symbols, Packages | use library and create Schematics, Layout again | days (strongly dependent on size) | hours (independent of size) | copy and past and adapt some commands in configuration script |