Oops...!
- - - + + + - - - + + +Contributors
- - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - + + +- + xspice capability
@@ -138,7 +138,7 @@Somebody asked about using XSPICE components in SPICE simulations with SKiDL. That wasn’t possible since PySpice didn’t really support these when I built the interface. So I added XSPICE parts to the SKiDL SPICE interface and released it as SKiDL...
-
+
Version 0.0.28 Released!
@@ -168,7 +168,7 @@
Well, that didn’t last long. I released version 0.0.27 of SKiDL yesterday, but I didn’t like having the zyc utility bundled in there because that pulls in wxpython as a requirement. That’s likely to cause problems for some people when...
@@ -189,7 +189,7 @@
-
+
Version 0.0.27 Released!
@@ -198,7 +198,7 @@
It’s been almost eleven months since I released a new version of SKiDL (not counting updates to the Github repo). So here’s a new one: version 0.0.27. You can install it using pip just like all the other releases. Check...
@@ -219,7 +219,7 @@
-
+
The Worst Part of SKiDL
@@ -228,7 +228,7 @@
I created SKiDL to replace the manual tedium of drawing schematics with the advantages of modern programming languages: iteration, abstraction, hierarchy, and modularization. But one thing always stood out as a problem: parts. Parts! PARTS!! PARTS!!! PARTS!!!! Here’s a snippet...
@@ -249,7 +249,7 @@
-
+
SKiDL at KiCon 2019
@@ -258,7 +258,7 @@
At the recent KiCon 2019, I gave a talk about SKiDL that’s a good introduction to the language and why I created it. It’s about 27 minutes in length if you can stand it. I got a lot of great...
@@ -279,7 +279,7 @@
-
+
Sweetening SKiDL
@@ -288,7 +288,7 @@
I’ve added a bit of syntactic sugar to SKiDL over the past few months: Series, Parallel, and Tee Network Constructors Bussed Part Pins Accessing Part Pins as Attributes It doesn’t change what SKiDL does, but does make it easier to...
@@ -309,7 +309,7 @@
-
+
Others Use It, Too!
@@ -318,7 +318,7 @@
It helps when other people use SKiDL; then I can coast by just showing what they’ve done. Here are two examples. Blinkenface Blinkenface is a version of “LED glasses” made with a cascaded string of APA102 RGB LEDs controlled through...
@@ -339,7 +339,7 @@
-
+
Reusability Ain't What It Used To Be
@@ -348,7 +348,7 @@
Sometimes you need a quick circuit that does one, specific thing. Other times, you want to create a general design that can be re-used in multiple instances. I’ll demonstrate the evolution from a specific to a general SKiDL design using...
@@ -369,7 +369,7 @@
-
+
Spice Simulation
@@ -381,7 +381,7 @@
@@ -402,7 +402,7 @@
-
+
An Arduino With SKiDL
@@ -411,7 +411,7 @@
It’s April 1st. It’s also Arduino Day. Really. That’s not a joke. In honor of such an august occasion, I’m going to show you how to describe an Arduino board using SKiDL. It’s really easy; just takes two steps: Find...
@@ -423,7 +423,7 @@
Page 1 of 2
- Older
+ Older
@@ -449,8 +449,8 @@
- + Version 0.0.28 Released!
@@ -168,7 +168,7 @@Well, that didn’t last long. I released version 0.0.27 of SKiDL yesterday, but I didn’t like having the zyc utility bundled in there because that pulls in wxpython as a requirement. That’s likely to cause problems for some people when...
- + Version 0.0.27 Released!
@@ -198,7 +198,7 @@It’s been almost eleven months since I released a new version of SKiDL (not counting updates to the Github repo). So here’s a new one: version 0.0.27. You can install it using pip just like all the other releases. Check...
-
+
The Worst Part of SKiDL
@@ -228,7 +228,7 @@
I created SKiDL to replace the manual tedium of drawing schematics with the advantages of modern programming languages: iteration, abstraction, hierarchy, and modularization. But one thing always stood out as a problem: parts. Parts! PARTS!! PARTS!!! PARTS!!!! Here’s a snippet...
@@ -249,7 +249,7 @@
-
+
SKiDL at KiCon 2019
@@ -258,7 +258,7 @@
At the recent KiCon 2019, I gave a talk about SKiDL that’s a good introduction to the language and why I created it. It’s about 27 minutes in length if you can stand it. I got a lot of great...
@@ -279,7 +279,7 @@
-
+
Sweetening SKiDL
@@ -288,7 +288,7 @@
I’ve added a bit of syntactic sugar to SKiDL over the past few months: Series, Parallel, and Tee Network Constructors Bussed Part Pins Accessing Part Pins as Attributes It doesn’t change what SKiDL does, but does make it easier to...
@@ -309,7 +309,7 @@
-
+
Others Use It, Too!
@@ -318,7 +318,7 @@
It helps when other people use SKiDL; then I can coast by just showing what they’ve done. Here are two examples. Blinkenface Blinkenface is a version of “LED glasses” made with a cascaded string of APA102 RGB LEDs controlled through...
@@ -339,7 +339,7 @@
-
+
Reusability Ain't What It Used To Be
@@ -348,7 +348,7 @@
Sometimes you need a quick circuit that does one, specific thing. Other times, you want to create a general design that can be re-used in multiple instances. I’ll demonstrate the evolution from a specific to a general SKiDL design using...
@@ -369,7 +369,7 @@
-
+
Spice Simulation
@@ -381,7 +381,7 @@
@@ -402,7 +402,7 @@
-
+
An Arduino With SKiDL
@@ -411,7 +411,7 @@
It’s April 1st. It’s also Arduino Day. Really. That’s not a joke. In honor of such an august occasion, I’m going to show you how to describe an Arduino board using SKiDL. It’s really easy; just takes two steps: Find...
@@ -423,7 +423,7 @@
Page 1 of 2
- Older
+ Older
@@ -449,8 +449,8 @@
- + The Worst Part of SKiDL
@@ -228,7 +228,7 @@I created SKiDL to replace the manual tedium of drawing schematics with the advantages of modern programming languages: iteration, abstraction, hierarchy, and modularization. But one thing always stood out as a problem: parts. Parts! PARTS!! PARTS!!! PARTS!!!! Here’s a snippet...
- + SKiDL at KiCon 2019
@@ -258,7 +258,7 @@At the recent KiCon 2019, I gave a talk about SKiDL that’s a good introduction to the language and why I created it. It’s about 27 minutes in length if you can stand it. I got a lot of great...
-
+
Sweetening SKiDL
@@ -288,7 +288,7 @@
I’ve added a bit of syntactic sugar to SKiDL over the past few months: Series, Parallel, and Tee Network Constructors Bussed Part Pins Accessing Part Pins as Attributes It doesn’t change what SKiDL does, but does make it easier to...
@@ -309,7 +309,7 @@
-
+
Others Use It, Too!
@@ -318,7 +318,7 @@
It helps when other people use SKiDL; then I can coast by just showing what they’ve done. Here are two examples. Blinkenface Blinkenface is a version of “LED glasses” made with a cascaded string of APA102 RGB LEDs controlled through...
@@ -339,7 +339,7 @@
-
+
Reusability Ain't What It Used To Be
@@ -348,7 +348,7 @@
Sometimes you need a quick circuit that does one, specific thing. Other times, you want to create a general design that can be re-used in multiple instances. I’ll demonstrate the evolution from a specific to a general SKiDL design using...
@@ -369,7 +369,7 @@
-
+
Spice Simulation
@@ -381,7 +381,7 @@
@@ -402,7 +402,7 @@
-
+
An Arduino With SKiDL
@@ -411,7 +411,7 @@
It’s April 1st. It’s also Arduino Day. Really. That’s not a joke. In honor of such an august occasion, I’m going to show you how to describe an Arduino board using SKiDL. It’s really easy; just takes two steps: Find...
@@ -423,7 +423,7 @@
Page 1 of 2
- Older
+ Older
@@ -449,8 +449,8 @@
- + Sweetening SKiDL
@@ -288,7 +288,7 @@I’ve added a bit of syntactic sugar to SKiDL over the past few months: Series, Parallel, and Tee Network Constructors Bussed Part Pins Accessing Part Pins as Attributes It doesn’t change what SKiDL does, but does make it easier to...
- + Others Use It, Too!
@@ -318,7 +318,7 @@It helps when other people use SKiDL; then I can coast by just showing what they’ve done. Here are two examples. Blinkenface Blinkenface is a version of “LED glasses” made with a cascaded string of APA102 RGB LEDs controlled through...
-
+
Reusability Ain't What It Used To Be
@@ -348,7 +348,7 @@
Sometimes you need a quick circuit that does one, specific thing. Other times, you want to create a general design that can be re-used in multiple instances. I’ll demonstrate the evolution from a specific to a general SKiDL design using...
@@ -369,7 +369,7 @@
-
+
Spice Simulation
@@ -381,7 +381,7 @@
@@ -402,7 +402,7 @@
-
+
An Arduino With SKiDL
@@ -411,7 +411,7 @@
It’s April 1st. It’s also Arduino Day. Really. That’s not a joke. In honor of such an august occasion, I’m going to show you how to describe an Arduino board using SKiDL. It’s really easy; just takes two steps: Find...
@@ -423,7 +423,7 @@
Page 1 of 2
- Older
+ Older
@@ -449,8 +449,8 @@
- + Reusability Ain't What It Used To Be
@@ -348,7 +348,7 @@Sometimes you need a quick circuit that does one, specific thing. Other times, you want to create a general design that can be re-used in multiple instances. I’ll demonstrate the evolution from a specific to a general SKiDL design using...
- + Spice Simulation
@@ -381,7 +381,7 @@
-
+
An Arduino With SKiDL
@@ -411,7 +411,7 @@
It’s April 1st. It’s also Arduino Day. Really. That’s not a joke. In honor of such an august occasion, I’m going to show you how to describe an Arduino board using SKiDL. It’s really easy; just takes two steps: Find...
@@ -423,7 +423,7 @@
Page 1 of 2
- Older
+ Older
@@ -449,8 +449,8 @@
- + An Arduino With SKiDL
@@ -411,7 +411,7 @@It’s April 1st. It’s also Arduino Day. Really. That’s not a joke. In honor of such an august occasion, I’m going to show you how to describe an Arduino board using SKiDL. It’s really easy; just takes two steps: Find...
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
+
@@ -79,17 +79,17 @@
- Home
+ Home
- Blog
+ Blog
- API
+ API
@@ -99,11 +99,11 @@
- About
+ About
- Feed
+ Feed
@@ -129,7 +129,7 @@
-
+
Two Easy Pieces
@@ -138,7 +138,7 @@
I really wanted to call this post Five Easy Pieces, but I’m not Jack Nicholson and I only had two simple SKiDL designs to show. So here they are. LED Clock DougE recently posted a script that will layout a...
@@ -159,7 +159,7 @@
-
+
Don't Replicate, Automate!
@@ -168,7 +168,7 @@
I used to work during summers for a bricklayer. I learned one thing there: air conditioning is pretty good stuff. (We should do more of it.) Some people think bricklaying would be a great job, kind of like playing Tetris...
@@ -189,7 +189,7 @@
-
+
A Taste of Hierarchy
@@ -198,7 +198,7 @@
In my previous blog posts, the SKiDL circuit descriptions were flat. In this post, I’ll show a bit of how to describe a circuit hierarchically. Hierarchy is typically used when there is some subcircuit that needs to be replicated several...
@@ -219,7 +219,7 @@
-
+
Names, Not Numbers
@@ -228,7 +228,7 @@
In my previous post, I showed how to use SKiDL to describe the circuit for a simple USB-to-JTAG interface circuit. That circuit used a PIC32MX microcontroller in a 28-pin SSOP package: and the corresponding SKiDL code was: pic32 = Part(pic32_lib,...
@@ -249,7 +249,7 @@
-
+
Building a USB-to-JTAG Interface Using SKiDL
@@ -258,7 +258,7 @@
This post describes using SKiDL for a USB-to-JTAG interface that was taken all the way from concept to physically building a device. The interface is pretty simple. It’s built from the following stuff: A PIC32MX220 microcontroller. A 12 MHz crystal....
@@ -267,7 +267,7 @@
@@ -329,13 +329,13 @@
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
+
+
@@ -134,91 +134,91 @@ Blog
- xspice capability
+ xspice capability
- Version 0.0.28 Released!
+ Version 0.0.28 Released!
- Version 0.0.27 Released!
+ Version 0.0.27 Released!
- The Worst Part of SKiDL
+ The Worst Part of SKiDL
- SKiDL at KiCon 2019
+ SKiDL at KiCon 2019
- Sweetening SKiDL
+ Sweetening SKiDL
- Others Use It, Too!
+ Others Use It, Too!
- Reusability Ain't What It Used To Be
+ Reusability Ain't What It Used To Be
- Spice Simulation
+ Spice Simulation
- An Arduino With SKiDL
+ An Arduino With SKiDL
- Two Easy Pieces
+ Two Easy Pieces
- Don't Replicate, Automate!
+ Don't Replicate, Automate!
- A Taste of Hierarchy
+ A Taste of Hierarchy
- Names, Not Numbers
+ Names, Not Numbers
- Building a USB-to-JTAG Interface Using SKiDL
+ Building a USB-to-JTAG Interface Using SKiDL
@@ -247,8 +247,8 @@ Blog
@@ -279,13 +279,13 @@ Blog
-
-
-
+
+
+
-
-
-
+
+
+
-
+
@@ -79,17 +79,17 @@
- Home
+ Home
- Blog
+ Blog
- API
+ API
@@ -99,11 +99,11 @@
- About
+ About
- Feed
+ Feed
@@ -133,11 +133,69 @@ TL;DR
Contents
+ - TL;DR
+
+ - Contents
+
+
- Introduction
- Installation
- - Basic Usage
- - Going Deeper
- - Going Really Deep
+ - Basic Usage
+
+
+ - Going Deeper
+
+ - Basic SKiDL Objects: Parts, Pins, Nets, Buses
+ - Creating SKiDL Objects
+ - Finding SKiDL Objects
+ - Copying SKiDL Objects
+ - Accessing Part Pins and Bus Lines
+
+
+ - Making Connections
+ - Making Serial, Parallel, and Tee Networks
+ - Aliases
+ - Units Within Parts
+ - Part Fields
+ - Hierarchy
+
+ - Subcircuits
+ - Packages
+
+
+ - Interfaces
+ - Libraries
+ - Doodads
+
+
+
+
+ - Going Really Deep
+
+ - Circuit Objects
+
+
- Converting Existing Designs to SKiDL
- SPICE Simulations
@@ -976,31 +1034,39 @@ Accessing Part Pins
[Pin U1/1/ICSPDAT/AN0/GP0/BIDIRECTIONAL, Pin U1/3/ICSPCLK/AN1/GP1/BIDIRECTIONAL, Pin U1/4/T0CKI/FOSC4/GP2/BIDIRECTIONAL]
-Since you can access part pins by number or by name using strings or regular expressions, it’s worth
+
Since you can access pins by number or by name using strings or regular expressions, it’s worth
discussing how SKiDL decides which one to select.
-When given a pin index, SKiDL prioritizes the search for the corresponding pins like so:
+When given a pin index, SKiDL stops searching and returns the matching pins as soon as one of the following conditions succeeds:
- - If one or more pin numbers match the index, then those pins are returned and the search stops.
- - If one or more pin names match the index using standard string matching, then those pins are returned and the search stops.
- - If one or more pin aliases match the index using standard string matching, then those pins are returned and the search stops.
- - If one or more pin names match the index using it as a regular expression, then those pins are returned and the search stops.
- - If one or more pin aliases match the index using it as a regular expression, then those pins are returned and the search stops.
+ - One or more pin numbers match the index.
+ - One or more pin aliases match the index using standard string matching.
+ - One or more pin names match the index using standard string matching.
+ - One or more pin aliases match the index using regular expression matching.
+ - One or more pin names match the index using regular expression matching.
-It should also be mentioned that when using the index as a regular expression,
-SKiDL surrounds it with .*
so it will match anywhere within a pin name or alias.
-Hence, if an index of D1
did not exactly match any pin number, name or alias, then it would become
-.*D1.*
and would match any pin with D1
in its name.
-You can stop this by placing start and end characters in the index like so: ^D1$
will match only D1
.
+Some parts (like microcontrollers) have long pin names that list every function a pin
+supports (e.g. ICSPCLK/AN1/GP1
).
+Employing the complete pin name is tedious to enter correctly and
+obfuscates the particular function that is being accessed.
+The pertinent substring of the pin name can be used if it is surrounded by wildcards
+(e.g., pic10['.*AN1.*']
), but that’s still a bit difficult to read.
+Therefore, a substring matching feature can be enabled on a per-part basis
+that implicitly surrounds the index with .*
so it will match anywhere within a pin name or alias.
+
+>>> pic10.match_pin_substring = True
+>>> pic10['AN1']
+Pin Pin U1/3/ICSPCLK/AN1/GP1/BIDIRECTIONAL
+
Finally, since SKiDL prioritizes pin number matches over name matches,
-what happens when you want to use a pin whose name is the same as the pin number
+what happens when you use a name that is the same as the number
of another pin?
For example, a memory chip in a BGA would have pin numbers A1
, A2
, A3
, … but might
-also have other pins used for addresses named A1
, A2
, A3
, … .
-SKiDL provides the p
and n
part attributes so you can specifically target either
-pin numbers or names:
+also have address pins named A1
, A2
, A3
, … .
+In order to specifically target either pin numbers or names,
+SKiDL provides the p
and n
part attributes:
ram['A1, A2, A3'] # Selects pin numbers A1, A2 and A3 if the part is a BGA.
ram.p['A1, A2, A3'] # Use the p attribute to specifically select pin numbers A1, A2 and A3.
@@ -1069,7 +1135,7 @@ Accessing Bus Lines
Making Connections
Pins, nets, parts and buses can all be connected together in various ways, but
-the primary rule of SKiDL connections is:
+the primary rule of SKiDL connections is:
The +=
operator is the only way to make connections!
@@ -1395,6 +1461,10 @@ Part Fields
Hierarchy
+SKiDL supports two equivalent implementations of hierarchy: subcircuits and packages.
+
+Subcircuits
+
SKiDL supports the encapsulation of parts, nets and buses into modules
that can be replicated to reduce the design effort, and can be used in
other modules to create a functional hierarchy.
@@ -1406,29 +1476,28 @@
Hierarchy
from skidl import *
import sys
+# Define a global resistor template.
+r = Part('Device', 'R', footprint='Resistor_SMD.pretty:R_0805_2012Metric', dest=TEMPLATE)
+
# Define the voltage divider module. The @subcircuit decorator
-# handles some skidl housekeeping that needs to be done.
+# handles some SKiDL housekeeping that needs to be done.
@subcircuit
def vdiv(inp, outp):
"""Divide inp voltage by 3 and place it on outp net."""
- rup = Part("Device", 'R', value='1K', footprint='Resistor_SMD.pretty:R_0805_2012Metric')
- rlo = Part("Device",'R', value='500', footprint='Resistor_SMD.pretty:R_0805_2012Metric')
- rup[1,2] += inp, outp
- rlo[1,2] += outp, gnd
+ inp & r(value='1K') & outp & r(value='500') & gnd
+
+# Declare the input, output and ground nets.
+input_net, output_net, gnd = Net('IN'), Net('OUT'), Net('GND')
-gnd = Net('GND') # GLobal ground net.
-input_net = Net('IN') # Net with the voltage to be divided.
-output_net = Net('OUT') # Net with the divided voltage.
-
# Instantiate the voltage divider and connect it to the input & output nets.
vdiv(input_net, output_net)
-generate_netlist(sys.stdout)
+generate_netlist(file_=sys.stdout)
For the most part, vdiv
is just a standard Python function:
it accepts inputs, it performs operations on them, and it could return
-outputs (but in this case, it doesn’t need to).
+results (but in this case, it doesn’t need to).
Other than the @subcircuit
decorator that appears before the function definition,
vdiv
is just a Python function and it can do anything that a Python function can do.
@@ -1469,117 +1538,119 @@ Hierarchy
can use the vdiv
module to divide a voltage multiple times:
+
from skidl import *
import sys
-# Define the voltage divider module.
-@subcircuit
+r = Part('Device', 'R', footprint='Resistor_SMD.pretty:R_0805_2012Metric', dest=TEMPLATE)
+
+@subcircuit
def vdiv(inp, outp):
- """Divide inp voltage by 3 and place it on outp net."""
- rup = Part("Device", 'R', value='1K', footprint='Resistor_SMD.pretty:R_0805_2012Metric')
- rlo = Part("Device",'R', value='500', footprint='Resistor_SMD.pretty:R_0805_2012Metric')
- rup[1,2] += inp, outp
- rlo[1,2] += outp, gnd
+ inp & r(value='1K') & outp & r(value='500') & gnd
+
+input_net, output_net, gnd = Net('IN'), Net('OUT'), Net('GND')
@subcircuit
def multi_vdiv(repeat, inp, outp):
- """Divide inp voltage by 3 ** repeat and place it on outp net."""
+ """Divide inp voltage by 3 * repeat and place it on outp net."""
for _ in range(repeat):
out_net = Net() # Create an output net for the current stage.
vdiv(inp, out_net) # Instantiate a divider stage.
inp = out_net # The output net becomes the input net for the next stage.
outp += out_net # Connect the output from the last stage to the module output net.
-gnd = Net('GND') # GLobal ground net.
-input_net = Net('IN') # Net with the voltage to be divided.
-output_net = Net('OUT') # Net with the divided voltage.
-multi_vdiv(3, input_net, output_net) # Run the input through 3 voltage dividers.
+
+input_net, output_net, gnd = Net('IN'), Net('OUT'), Net('GND')
+
+multi_vdiv(3, input_net, output_net) # Run the input through 3 voltage dividers.
-generate_netlist(sys.stdout)
+generate_netlist(file_=sys.stdout)
-(For the EE’s out there: yes, I know cascading three simple voltage dividers
+(For the EE’s out there: yes, I know cascading three simple voltage dividers
will not multiplicatively scale the input voltage because of the
-input and output impedances of each stage!
+input and output impedances of each stage!
It’s just the simplest example I could use to show hierarchy.)
-And here’s the resulting netlist:
+Subcircuits can also be configurable (after all, they’re just functions).
+The ratio of the voltage divider could be set with a parameter:
-(export (version D)
- (design
- (source "C:\TEMP\skidl tests\multi_hier_example.py")
- (date "04/20/2017 09:43 AM")
- (tool "SKiDL (0.0.12)"))
- (components
- (comp (ref R1)
- (value 1K)
- (footprint Resistor_SMD.pretty:R_0805_2012Metric)
- (fields
- (field (name keywords) "r res resistor")
- (field (name description) Resistor))
- (libsource (lib device) (part R)))
- (comp (ref R2)
- (value 500)
- (footprint Resistor_SMD.pretty:R_0805_2012Metric)
- (fields
- (field (name keywords) "r res resistor")
- (field (name description) Resistor))
- (libsource (lib device) (part R)))
- (comp (ref R3)
- (value 1K)
- (footprint Resistor_SMD.pretty:R_0805_2012Metric)
- (fields
- (field (name keywords) "r res resistor")
- (field (name description) Resistor))
- (libsource (lib device) (part R)))
- (comp (ref R4)
- (value 500)
- (footprint Resistor_SMD.pretty:R_0805_2012Metric)
- (fields
- (field (name keywords) "r res resistor")
- (field (name description) Resistor))
- (libsource (lib device) (part R)))
- (comp (ref R5)
- (value 1K)
- (footprint Resistor_SMD.pretty:R_0805_2012Metric)
- (fields
- (field (name keywords) "r res resistor")
- (field (name description) Resistor))
- (libsource (lib device) (part R)))
- (comp (ref R6)
- (value 500)
- (footprint Resistor_SMD.pretty:R_0805_2012Metric)
- (fields
- (field (name keywords) "r res resistor")
- (field (name description) Resistor))
- (libsource (lib device) (part R))))
- (nets
- (net (code 0) (name GND)
- (node (ref R2) (pin 2))
- (node (ref R4) (pin 2))
- (node (ref R6) (pin 2)))
- (net (code 1) (name IN)
- (node (ref R1) (pin 1)))
- (net (code 2) (name N$1)
- (node (ref R1) (pin 2))
- (node (ref R2) (pin 1))
- (node (ref R3) (pin 1)))
- (net (code 3) (name N$2)
- (node (ref R3) (pin 2))
- (node (ref R4) (pin 1))
- (node (ref R5) (pin 1)))
- (net (code 4) (name OUT)
- (node (ref R5) (pin 2))
- (node (ref R6) (pin 1))))
-)
+# Pass the division ratio as a parameter.
+@subcircuit
+def vdiv(inp, outp, ratio):
+ inp & r(value=1000) & outp & r(value=1000*ratio/(1-ratio)) & gnd
+
+...
+
+# Instantiate the voltage divider with a ratio of 1/3.
+vdiv(inp, outp, ratio=0.33)
+
+
+Packages
+
+The @subcircuit
decorator lets you create a hierarchical circuit where the
+subcircuits are instantiated using function calls with arguments.
+The @package
decorator is an alternative that packages a subcircuit into
+a Part
-like object with its own input and output pins that can be connected
+to other components.
+In essence, you’ve encapsulated a subcircuit into its own package with I/O pins.
+
+from skidl import *
+import sys
+
+r = Part('Device', 'R', footprint='Resistor_SMD.pretty:R_0805_2012Metric', dest=TEMPLATE)
+
+# Define the voltage divider module. The @package decorator
+# creates an interface that acts like I/O pins.
+@package
+def vdiv(inp, outp):
+ inp & r(value='1K') & outp & r(value='500') & gnd
+
+input_net, output_net, gnd = Net('IN'), Net('OUT'), Net('GND')
+
+# Instantiate the voltage divider as a package.
+divider = vdiv()
+
+# Now connect the I/O pins of the instantiated package to the input & output nets.
+divider.inp += input_net
+divider.outp += output_net
+
+generate_netlist(file_=sys.stdout)
+
+
+Subcircuits defined with @package
are also customizable via parameters:
+
+from skidl import *
+import sys
+
+r = Part('Device', 'R', footprint='Resistor_SMD.pretty:R_0805_2012Metric', dest=TEMPLATE)
+
+# Voltage divider with a parameterized division ratio.
+@package
+def vdiv(inp, outp, ratio):
+ inp & r(value=1000) & outp & r(value=1000*ratio/(1-ratio)) & gnd
+
+input_net, output_net, gnd = Net('IN'), Net('OUT'), Net('GND')
+
+# Instantiate the voltage divider with a ratio of 1/3.
+divider = vdiv(ratio=1.0/3)
+
+divider.inp += input_net
+divider.outp += output_net
+
+# You can also override the division ratio. Note that a standard
+# assignment operator is used instead of += because ratio is not an I/O pin.
+divider.ratio = 0.5
+
+generate_netlist(file_=sys.stdout)
Interfaces
Passing nets between hierarchically-organized modules can lead to long
lists of arguments.
-To make the code easier to write and understand, SKiDL supports interfaces which are simply containers that
-encapsulate a number of Bus
, Net
, or Pin
objects.
+To make the code easier to write and understand, SKiDL supports interfaces
+which are simply dictionaries that encapsulate a number of Bus
, Net
, or Pin
objects.
For example, here is an interface for a memory:
mem_intfc = Interface(
@@ -1605,8 +1676,8 @@ Interfaces
ram['A[0:19]'] += intfc.addr
ram['DQ[0:15]'] += intfc.data
ram['WE#'] += intfc.wr
- ram['OE#'] += intfc.rd
- ...
+ ram['OE#'] += intfc['rd'] # Interface members are also accessible using []'s.
+ ...
Libraries
@@ -1979,6 +2050,60 @@ Selectively Supressing ERC Messages
my_part.do_erc = False # Turns off ERC for all the pins of this part.
+Customizable ERC Using erc_assert()
+
+SKiDL’s default ERC will find commonplace design errors, but sometimes
+you’ll have special requirements.
+The erc_assert
function can be used to check these.
+
+from skidl import *
+import sys
+
+# Function to check the number of inputs on a net.
+def get_fanout(net):
+ fanout = 0
+ for pin in net.get_pins():
+ if pin.func in (Pin.INPUT, Pin.BIDIR):
+ fanout += 1
+ return fanout
+
+net1, net2 = Net('IN1'), Net('IN2')
+
+# Place some assertions on the fanout of each net.
+# Note that the assertions are passed as strings.
+erc_assert('get_fanout(net1) < 5', 'failed on net1')
+erc_assert('get_fanout(net2) < 5', 'failed on net2')
+
+# Attach some pins to the nets.
+net1 += Pin(func=Pin.OUTPUT)
+net2 += Pin(func=Pin.OUTPUT)
+net1 += Pin(func=Pin.INPUT) * 4 # This net passes the assertion.
+net2 += Pin(func=Pin.INPUT) * 5 # This net fails because of too much fanout.
+
+# When the ERC runs, it will also run any erc_assert statements.
+ERC()
+
+
+When you run this code, the ERC will output the following:
+
+ERC ERROR: get_fanout(input_net2) < 5 failed on net2 in <ipython-input-114-5b71f80eb001>:16:<module>.
+
+0 warnings found during ERC.
+1 errors found during ERC.
+
+
+You might ask: “Why not just use the standard Python assert
statement?”
+The reason is that an assertion is evaluated as soon as the assert
statement is encountered
+and might be evaluated incorrectly if the nets or other circuit objects are not yet
+completely defined.
+But the statement passed to the erc_assert
function isn’t evaluated until all the
+various parts have been connected and ERC()
is called
+(that’s why the statement is passed as a string).
+Note in the code above that when the erc_assert
function is called, no pins
+are even attached to the net1
or net2
nets, yet.
+The erc_assert
function just places the statements to be checked into a queue
+that gets evaluated when ERC()
is run.
+
Going Really Deep
If all you need to do is design the circuitry for a PCB, then you probably know
@@ -2110,8 +2235,8 @@
SPICE Simulations
- + Two Easy Pieces
@@ -138,7 +138,7 @@I really wanted to call this post Five Easy Pieces, but I’m not Jack Nicholson and I only had two simple SKiDL designs to show. So here they are. LED Clock DougE recently posted a script that will layout a...
-
+
Don't Replicate, Automate!
@@ -168,7 +168,7 @@
I used to work during summers for a bricklayer. I learned one thing there: air conditioning is pretty good stuff. (We should do more of it.) Some people think bricklaying would be a great job, kind of like playing Tetris...
@@ -189,7 +189,7 @@
-
+
A Taste of Hierarchy
@@ -198,7 +198,7 @@
In my previous blog posts, the SKiDL circuit descriptions were flat. In this post, I’ll show a bit of how to describe a circuit hierarchically. Hierarchy is typically used when there is some subcircuit that needs to be replicated several...
@@ -219,7 +219,7 @@
-
+
Names, Not Numbers
@@ -228,7 +228,7 @@
In my previous post, I showed how to use SKiDL to describe the circuit for a simple USB-to-JTAG interface circuit. That circuit used a PIC32MX microcontroller in a 28-pin SSOP package: and the corresponding SKiDL code was: pic32 = Part(pic32_lib,...
@@ -249,7 +249,7 @@
-
+
Building a USB-to-JTAG Interface Using SKiDL
@@ -258,7 +258,7 @@
This post describes using SKiDL for a USB-to-JTAG interface that was taken all the way from concept to physically building a device. The interface is pretty simple. It’s built from the following stuff: A PIC32MX220 microcontroller. A 12 MHz crystal....
@@ -267,7 +267,7 @@
- + Don't Replicate, Automate!
@@ -168,7 +168,7 @@I used to work during summers for a bricklayer. I learned one thing there: air conditioning is pretty good stuff. (We should do more of it.) Some people think bricklaying would be a great job, kind of like playing Tetris...
- + A Taste of Hierarchy
@@ -198,7 +198,7 @@In my previous blog posts, the SKiDL circuit descriptions were flat. In this post, I’ll show a bit of how to describe a circuit hierarchically. Hierarchy is typically used when there is some subcircuit that needs to be replicated several...
-
+
Names, Not Numbers
@@ -228,7 +228,7 @@
In my previous post, I showed how to use SKiDL to describe the circuit for a simple USB-to-JTAG interface circuit. That circuit used a PIC32MX microcontroller in a 28-pin SSOP package: and the corresponding SKiDL code was: pic32 = Part(pic32_lib,...
@@ -249,7 +249,7 @@
-
+
Building a USB-to-JTAG Interface Using SKiDL
@@ -258,7 +258,7 @@
This post describes using SKiDL for a USB-to-JTAG interface that was taken all the way from concept to physically building a device. The interface is pretty simple. It’s built from the following stuff: A PIC32MX220 microcontroller. A 12 MHz crystal....
@@ -267,7 +267,7 @@
- + Names, Not Numbers
@@ -228,7 +228,7 @@In my previous post, I showed how to use SKiDL to describe the circuit for a simple USB-to-JTAG interface circuit. That circuit used a PIC32MX microcontroller in a 28-pin SSOP package: and the corresponding SKiDL code was: pic32 = Part(pic32_lib,...
- + Building a USB-to-JTAG Interface Using SKiDL
@@ -258,7 +258,7 @@This post describes using SKiDL for a USB-to-JTAG interface that was taken all the way from concept to physically building a device. The interface is pretty simple. It’s built from the following stuff: A PIC32MX220 microcontroller. A 12 MHz crystal....
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
-
+
+
+
-
-
+
+
@@ -134,91 +134,91 @@ Blog
- xspice capability
+ xspice capability
- Version 0.0.28 Released!
+ Version 0.0.28 Released!
- Version 0.0.27 Released!
+ Version 0.0.27 Released!
- The Worst Part of SKiDL
+ The Worst Part of SKiDL
- SKiDL at KiCon 2019
+ SKiDL at KiCon 2019
- Sweetening SKiDL
+ Sweetening SKiDL
- Others Use It, Too!
+ Others Use It, Too!
- Reusability Ain't What It Used To Be
+ Reusability Ain't What It Used To Be
- Spice Simulation
+ Spice Simulation
- An Arduino With SKiDL
+ An Arduino With SKiDL
- Two Easy Pieces
+ Two Easy Pieces
- Don't Replicate, Automate!
+ Don't Replicate, Automate!
- A Taste of Hierarchy
+ A Taste of Hierarchy
- Names, Not Numbers
+ Names, Not Numbers
- Building a USB-to-JTAG Interface Using SKiDL
+ Building a USB-to-JTAG Interface Using SKiDL
@@ -247,8 +247,8 @@ Blog
@@ -279,13 +279,13 @@ Blog
-
-
-
+
+
+
-
-
-
+
+
+
-
+
@@ -79,17 +79,17 @@
- Home
+ Home
- Blog
+ Blog
- API
+ API
@@ -99,11 +99,11 @@
- About
+ About
- Feed
+ Feed
@@ -133,11 +133,69 @@ TL;DR
Contents
+ - TL;DR
+
+ - Contents
+
+
- Introduction
- Installation
- - Basic Usage
- - Going Deeper
- - Going Really Deep
+ - Basic Usage
+
+
+ - Going Deeper
+
+ - Basic SKiDL Objects: Parts, Pins, Nets, Buses
+ - Creating SKiDL Objects
+ - Finding SKiDL Objects
+ - Copying SKiDL Objects
+ - Accessing Part Pins and Bus Lines
+
+
+ - Making Connections
+ - Making Serial, Parallel, and Tee Networks
+ - Aliases
+ - Units Within Parts
+ - Part Fields
+ - Hierarchy
+
+ - Subcircuits
+ - Packages
+
+
+ - Interfaces
+ - Libraries
+ - Doodads
+
+
+
+
+ - Going Really Deep
+
+ - Circuit Objects
+
+
- Converting Existing Designs to SKiDL
- SPICE Simulations
@@ -976,31 +1034,39 @@ Accessing Part Pins
[Pin U1/1/ICSPDAT/AN0/GP0/BIDIRECTIONAL, Pin U1/3/ICSPCLK/AN1/GP1/BIDIRECTIONAL, Pin U1/4/T0CKI/FOSC4/GP2/BIDIRECTIONAL]
-Since you can access part pins by number or by name using strings or regular expressions, it’s worth
+
Since you can access pins by number or by name using strings or regular expressions, it’s worth
discussing how SKiDL decides which one to select.
-When given a pin index, SKiDL prioritizes the search for the corresponding pins like so:
+When given a pin index, SKiDL stops searching and returns the matching pins as soon as one of the following conditions succeeds:
- - If one or more pin numbers match the index, then those pins are returned and the search stops.
- - If one or more pin names match the index using standard string matching, then those pins are returned and the search stops.
- - If one or more pin aliases match the index using standard string matching, then those pins are returned and the search stops.
- - If one or more pin names match the index using it as a regular expression, then those pins are returned and the search stops.
- - If one or more pin aliases match the index using it as a regular expression, then those pins are returned and the search stops.
+ - One or more pin numbers match the index.
+ - One or more pin aliases match the index using standard string matching.
+ - One or more pin names match the index using standard string matching.
+ - One or more pin aliases match the index using regular expression matching.
+ - One or more pin names match the index using regular expression matching.
-It should also be mentioned that when using the index as a regular expression,
-SKiDL surrounds it with .*
so it will match anywhere within a pin name or alias.
-Hence, if an index of D1
did not exactly match any pin number, name or alias, then it would become
-.*D1.*
and would match any pin with D1
in its name.
-You can stop this by placing start and end characters in the index like so: ^D1$
will match only D1
.
+Some parts (like microcontrollers) have long pin names that list every function a pin
+supports (e.g. ICSPCLK/AN1/GP1
).
+Employing the complete pin name is tedious to enter correctly and
+obfuscates the particular function that is being accessed.
+The pertinent substring of the pin name can be used if it is surrounded by wildcards
+(e.g., pic10['.*AN1.*']
), but that’s still a bit difficult to read.
+Therefore, a substring matching feature can be enabled on a per-part basis
+that implicitly surrounds the index with .*
so it will match anywhere within a pin name or alias.
+
+>>> pic10.match_pin_substring = True
+>>> pic10['AN1']
+Pin Pin U1/3/ICSPCLK/AN1/GP1/BIDIRECTIONAL
+
Finally, since SKiDL prioritizes pin number matches over name matches,
-what happens when you want to use a pin whose name is the same as the pin number
+what happens when you use a name that is the same as the number
of another pin?
For example, a memory chip in a BGA would have pin numbers A1
, A2
, A3
, … but might
-also have other pins used for addresses named A1
, A2
, A3
, … .
-SKiDL provides the p
and n
part attributes so you can specifically target either
-pin numbers or names:
+also have address pins named A1
, A2
, A3
, … .
+In order to specifically target either pin numbers or names,
+SKiDL provides the p
and n
part attributes:
ram['A1, A2, A3'] # Selects pin numbers A1, A2 and A3 if the part is a BGA.
ram.p['A1, A2, A3'] # Use the p attribute to specifically select pin numbers A1, A2 and A3.
@@ -1069,7 +1135,7 @@ Accessing Bus Lines
Making Connections
Pins, nets, parts and buses can all be connected together in various ways, but
-the primary rule of SKiDL connections is:
+the primary rule of SKiDL connections is:
The +=
operator is the only way to make connections!
@@ -1395,6 +1461,10 @@ Part Fields
Hierarchy
+SKiDL supports two equivalent implementations of hierarchy: subcircuits and packages.
+
+Subcircuits
+
SKiDL supports the encapsulation of parts, nets and buses into modules
that can be replicated to reduce the design effort, and can be used in
other modules to create a functional hierarchy.
@@ -1406,29 +1476,28 @@
Hierarchy
from skidl import *
import sys
+# Define a global resistor template.
+r = Part('Device', 'R', footprint='Resistor_SMD.pretty:R_0805_2012Metric', dest=TEMPLATE)
+
# Define the voltage divider module. The @subcircuit decorator
-# handles some skidl housekeeping that needs to be done.
+# handles some SKiDL housekeeping that needs to be done.
@subcircuit
def vdiv(inp, outp):
"""Divide inp voltage by 3 and place it on outp net."""
- rup = Part("Device", 'R', value='1K', footprint='Resistor_SMD.pretty:R_0805_2012Metric')
- rlo = Part("Device",'R', value='500', footprint='Resistor_SMD.pretty:R_0805_2012Metric')
- rup[1,2] += inp, outp
- rlo[1,2] += outp, gnd
+ inp & r(value='1K') & outp & r(value='500') & gnd
+
+# Declare the input, output and ground nets.
+input_net, output_net, gnd = Net('IN'), Net('OUT'), Net('GND')
-gnd = Net('GND') # GLobal ground net.
-input_net = Net('IN') # Net with the voltage to be divided.
-output_net = Net('OUT') # Net with the divided voltage.
-
# Instantiate the voltage divider and connect it to the input & output nets.
vdiv(input_net, output_net)
-generate_netlist(sys.stdout)
+generate_netlist(file_=sys.stdout)
For the most part, vdiv
is just a standard Python function:
it accepts inputs, it performs operations on them, and it could return
-outputs (but in this case, it doesn’t need to).
+results (but in this case, it doesn’t need to).
Other than the @subcircuit
decorator that appears before the function definition,
vdiv
is just a Python function and it can do anything that a Python function can do.
@@ -1469,117 +1538,119 @@ Hierarchy
can use the vdiv
module to divide a voltage multiple times:
+
from skidl import *
import sys
-# Define the voltage divider module.
-@subcircuit
+r = Part('Device', 'R', footprint='Resistor_SMD.pretty:R_0805_2012Metric', dest=TEMPLATE)
+
+@subcircuit
def vdiv(inp, outp):
- """Divide inp voltage by 3 and place it on outp net."""
- rup = Part("Device", 'R', value='1K', footprint='Resistor_SMD.pretty:R_0805_2012Metric')
- rlo = Part("Device",'R', value='500', footprint='Resistor_SMD.pretty:R_0805_2012Metric')
- rup[1,2] += inp, outp
- rlo[1,2] += outp, gnd
+ inp & r(value='1K') & outp & r(value='500') & gnd
+
+input_net, output_net, gnd = Net('IN'), Net('OUT'), Net('GND')
@subcircuit
def multi_vdiv(repeat, inp, outp):
- """Divide inp voltage by 3 ** repeat and place it on outp net."""
+ """Divide inp voltage by 3 * repeat and place it on outp net."""
for _ in range(repeat):
out_net = Net() # Create an output net for the current stage.
vdiv(inp, out_net) # Instantiate a divider stage.
inp = out_net # The output net becomes the input net for the next stage.
outp += out_net # Connect the output from the last stage to the module output net.
-gnd = Net('GND') # GLobal ground net.
-input_net = Net('IN') # Net with the voltage to be divided.
-output_net = Net('OUT') # Net with the divided voltage.
-multi_vdiv(3, input_net, output_net) # Run the input through 3 voltage dividers.
+
+input_net, output_net, gnd = Net('IN'), Net('OUT'), Net('GND')
+
+multi_vdiv(3, input_net, output_net) # Run the input through 3 voltage dividers.
-generate_netlist(sys.stdout)
+generate_netlist(file_=sys.stdout)
-(For the EE’s out there: yes, I know cascading three simple voltage dividers
+(For the EE’s out there: yes, I know cascading three simple voltage dividers
will not multiplicatively scale the input voltage because of the
-input and output impedances of each stage!
+input and output impedances of each stage!
It’s just the simplest example I could use to show hierarchy.)
-And here’s the resulting netlist:
+Subcircuits can also be configurable (after all, they’re just functions).
+The ratio of the voltage divider could be set with a parameter:
-(export (version D)
- (design
- (source "C:\TEMP\skidl tests\multi_hier_example.py")
- (date "04/20/2017 09:43 AM")
- (tool "SKiDL (0.0.12)"))
- (components
- (comp (ref R1)
- (value 1K)
- (footprint Resistor_SMD.pretty:R_0805_2012Metric)
- (fields
- (field (name keywords) "r res resistor")
- (field (name description) Resistor))
- (libsource (lib device) (part R)))
- (comp (ref R2)
- (value 500)
- (footprint Resistor_SMD.pretty:R_0805_2012Metric)
- (fields
- (field (name keywords) "r res resistor")
- (field (name description) Resistor))
- (libsource (lib device) (part R)))
- (comp (ref R3)
- (value 1K)
- (footprint Resistor_SMD.pretty:R_0805_2012Metric)
- (fields
- (field (name keywords) "r res resistor")
- (field (name description) Resistor))
- (libsource (lib device) (part R)))
- (comp (ref R4)
- (value 500)
- (footprint Resistor_SMD.pretty:R_0805_2012Metric)
- (fields
- (field (name keywords) "r res resistor")
- (field (name description) Resistor))
- (libsource (lib device) (part R)))
- (comp (ref R5)
- (value 1K)
- (footprint Resistor_SMD.pretty:R_0805_2012Metric)
- (fields
- (field (name keywords) "r res resistor")
- (field (name description) Resistor))
- (libsource (lib device) (part R)))
- (comp (ref R6)
- (value 500)
- (footprint Resistor_SMD.pretty:R_0805_2012Metric)
- (fields
- (field (name keywords) "r res resistor")
- (field (name description) Resistor))
- (libsource (lib device) (part R))))
- (nets
- (net (code 0) (name GND)
- (node (ref R2) (pin 2))
- (node (ref R4) (pin 2))
- (node (ref R6) (pin 2)))
- (net (code 1) (name IN)
- (node (ref R1) (pin 1)))
- (net (code 2) (name N$1)
- (node (ref R1) (pin 2))
- (node (ref R2) (pin 1))
- (node (ref R3) (pin 1)))
- (net (code 3) (name N$2)
- (node (ref R3) (pin 2))
- (node (ref R4) (pin 1))
- (node (ref R5) (pin 1)))
- (net (code 4) (name OUT)
- (node (ref R5) (pin 2))
- (node (ref R6) (pin 1))))
-)
+# Pass the division ratio as a parameter.
+@subcircuit
+def vdiv(inp, outp, ratio):
+ inp & r(value=1000) & outp & r(value=1000*ratio/(1-ratio)) & gnd
+
+...
+
+# Instantiate the voltage divider with a ratio of 1/3.
+vdiv(inp, outp, ratio=0.33)
+
+
+Packages
+
+The @subcircuit
decorator lets you create a hierarchical circuit where the
+subcircuits are instantiated using function calls with arguments.
+The @package
decorator is an alternative that packages a subcircuit into
+a Part
-like object with its own input and output pins that can be connected
+to other components.
+In essence, you’ve encapsulated a subcircuit into its own package with I/O pins.
+
+from skidl import *
+import sys
+
+r = Part('Device', 'R', footprint='Resistor_SMD.pretty:R_0805_2012Metric', dest=TEMPLATE)
+
+# Define the voltage divider module. The @package decorator
+# creates an interface that acts like I/O pins.
+@package
+def vdiv(inp, outp):
+ inp & r(value='1K') & outp & r(value='500') & gnd
+
+input_net, output_net, gnd = Net('IN'), Net('OUT'), Net('GND')
+
+# Instantiate the voltage divider as a package.
+divider = vdiv()
+
+# Now connect the I/O pins of the instantiated package to the input & output nets.
+divider.inp += input_net
+divider.outp += output_net
+
+generate_netlist(file_=sys.stdout)
+
+
+Subcircuits defined with @package
are also customizable via parameters:
+
+from skidl import *
+import sys
+
+r = Part('Device', 'R', footprint='Resistor_SMD.pretty:R_0805_2012Metric', dest=TEMPLATE)
+
+# Voltage divider with a parameterized division ratio.
+@package
+def vdiv(inp, outp, ratio):
+ inp & r(value=1000) & outp & r(value=1000*ratio/(1-ratio)) & gnd
+
+input_net, output_net, gnd = Net('IN'), Net('OUT'), Net('GND')
+
+# Instantiate the voltage divider with a ratio of 1/3.
+divider = vdiv(ratio=1.0/3)
+
+divider.inp += input_net
+divider.outp += output_net
+
+# You can also override the division ratio. Note that a standard
+# assignment operator is used instead of += because ratio is not an I/O pin.
+divider.ratio = 0.5
+
+generate_netlist(file_=sys.stdout)
Interfaces
Passing nets between hierarchically-organized modules can lead to long
lists of arguments.
-To make the code easier to write and understand, SKiDL supports interfaces which are simply containers that
-encapsulate a number of Bus
, Net
, or Pin
objects.
+To make the code easier to write and understand, SKiDL supports interfaces
+which are simply dictionaries that encapsulate a number of Bus
, Net
, or Pin
objects.
For example, here is an interface for a memory:
mem_intfc = Interface(
@@ -1605,8 +1676,8 @@ Interfaces
ram['A[0:19]'] += intfc.addr
ram['DQ[0:15]'] += intfc.data
ram['WE#'] += intfc.wr
- ram['OE#'] += intfc.rd
- ...
+ ram['OE#'] += intfc['rd'] # Interface members are also accessible using []'s.
+ ...
Libraries
@@ -1979,6 +2050,60 @@ Selectively Supressing ERC Messages
my_part.do_erc = False # Turns off ERC for all the pins of this part.
+Customizable ERC Using erc_assert()
+
+SKiDL’s default ERC will find commonplace design errors, but sometimes
+you’ll have special requirements.
+The erc_assert
function can be used to check these.
+
+from skidl import *
+import sys
+
+# Function to check the number of inputs on a net.
+def get_fanout(net):
+ fanout = 0
+ for pin in net.get_pins():
+ if pin.func in (Pin.INPUT, Pin.BIDIR):
+ fanout += 1
+ return fanout
+
+net1, net2 = Net('IN1'), Net('IN2')
+
+# Place some assertions on the fanout of each net.
+# Note that the assertions are passed as strings.
+erc_assert('get_fanout(net1) < 5', 'failed on net1')
+erc_assert('get_fanout(net2) < 5', 'failed on net2')
+
+# Attach some pins to the nets.
+net1 += Pin(func=Pin.OUTPUT)
+net2 += Pin(func=Pin.OUTPUT)
+net1 += Pin(func=Pin.INPUT) * 4 # This net passes the assertion.
+net2 += Pin(func=Pin.INPUT) * 5 # This net fails because of too much fanout.
+
+# When the ERC runs, it will also run any erc_assert statements.
+ERC()
+
+
+When you run this code, the ERC will output the following:
+
+ERC ERROR: get_fanout(input_net2) < 5 failed on net2 in <ipython-input-114-5b71f80eb001>:16:<module>.
+
+0 warnings found during ERC.
+1 errors found during ERC.
+
+
+You might ask: “Why not just use the standard Python assert
statement?”
+The reason is that an assertion is evaluated as soon as the assert
statement is encountered
+and might be evaluated incorrectly if the nets or other circuit objects are not yet
+completely defined.
+But the statement passed to the erc_assert
function isn’t evaluated until all the
+various parts have been connected and ERC()
is called
+(that’s why the statement is passed as a string).
+Note in the code above that when the erc_assert
function is called, no pins
+are even attached to the net1
or net2
nets, yet.
+The erc_assert
function just places the statements to be checked into a queue
+that gets evaluated when ERC()
is run.
+
Going Really Deep
If all you need to do is design the circuitry for a PCB, then you probably know
@@ -2110,8 +2235,8 @@
SPICE Simulations
Blog
-Blog
Blog
- - - + + + - - - + + +TL;DR
Contents
-
+
- TL;DR
+
-
+
- Contents +
- Introduction
- Installation -
- Basic Usage -
- Going Deeper -
- Going Really Deep +
- Basic Usage + + +
- Going Deeper
+
-
+
- Basic SKiDL Objects: Parts, Pins, Nets, Buses +
- Creating SKiDL Objects +
- Finding SKiDL Objects +
- Copying SKiDL Objects +
- Accessing Part Pins and Bus Lines + + +
- Making Connections +
- Making Serial, Parallel, and Tee Networks +
- Aliases +
- Units Within Parts +
- Part Fields +
- Hierarchy
+
-
+
- Subcircuits +
- Packages +
+ - Interfaces +
- Libraries +
- Doodads + + +
+ - Going Really Deep
+
-
+
- Circuit Objects +
- Converting Existing Designs to SKiDL
- SPICE Simulations
Accessing Part Pins
[Pin U1/1/ICSPDAT/AN0/GP0/BIDIRECTIONAL, Pin U1/3/ICSPCLK/AN1/GP1/BIDIRECTIONAL, Pin U1/4/T0CKI/FOSC4/GP2/BIDIRECTIONAL]Since you can access part pins by number or by name using strings or regular expressions, it’s worth +
Since you can access pins by number or by name using strings or regular expressions, it’s worth discussing how SKiDL decides which one to select. -When given a pin index, SKiDL prioritizes the search for the corresponding pins like so:
+When given a pin index, SKiDL stops searching and returns the matching pins as soon as one of the following conditions succeeds:-
-
- If one or more pin numbers match the index, then those pins are returned and the search stops. -
- If one or more pin names match the index using standard string matching, then those pins are returned and the search stops. -
- If one or more pin aliases match the index using standard string matching, then those pins are returned and the search stops. -
- If one or more pin names match the index using it as a regular expression, then those pins are returned and the search stops. -
- If one or more pin aliases match the index using it as a regular expression, then those pins are returned and the search stops. +
- One or more pin numbers match the index. +
- One or more pin aliases match the index using standard string matching. +
- One or more pin names match the index using standard string matching. +
- One or more pin aliases match the index using regular expression matching. +
- One or more pin names match the index using regular expression matching.
It should also be mentioned that when using the index as a regular expression,
-SKiDL surrounds it with .*
so it will match anywhere within a pin name or alias.
-Hence, if an index of D1
did not exactly match any pin number, name or alias, then it would become
-.*D1.*
and would match any pin with D1
in its name.
-You can stop this by placing start and end characters in the index like so: ^D1$
will match only D1
.
Some parts (like microcontrollers) have long pin names that list every function a pin
+supports (e.g. ICSPCLK/AN1/GP1
).
+Employing the complete pin name is tedious to enter correctly and
+obfuscates the particular function that is being accessed.
+The pertinent substring of the pin name can be used if it is surrounded by wildcards
+(e.g., pic10['.*AN1.*']
), but that’s still a bit difficult to read.
+Therefore, a substring matching feature can be enabled on a per-part basis
+that implicitly surrounds the index with .*
so it will match anywhere within a pin name or alias.
>>> pic10.match_pin_substring = True
+>>> pic10['AN1']
+Pin Pin U1/3/ICSPCLK/AN1/GP1/BIDIRECTIONAL
+
Finally, since SKiDL prioritizes pin number matches over name matches,
-what happens when you want to use a pin whose name is the same as the pin number
+what happens when you use a name that is the same as the number
of another pin?
For example, a memory chip in a BGA would have pin numbers A1
, A2
, A3
, … but might
-also have other pins used for addresses named A1
, A2
, A3
, … .
-SKiDL provides the p
and n
part attributes so you can specifically target either
-pin numbers or names:
A1
, A2
, A3
, … .
+In order to specifically target either pin numbers or names,
+SKiDL provides the p
and n
part attributes:
ram['A1, A2, A3'] # Selects pin numbers A1, A2 and A3 if the part is a BGA.
ram.p['A1, A2, A3'] # Use the p attribute to specifically select pin numbers A1, A2 and A3.
@@ -1069,7 +1135,7 @@ Accessing Bus Lines
Making Connections
Pins, nets, parts and buses can all be connected together in various ways, but
-the primary rule of SKiDL connections is:
+the primary rule of SKiDL connections is:
The +=
operator is the only way to make connections!
@@ -1395,6 +1461,10 @@ Part Fields
Hierarchy
+SKiDL supports two equivalent implementations of hierarchy: subcircuits and packages.
+
+Subcircuits
+
SKiDL supports the encapsulation of parts, nets and buses into modules
that can be replicated to reduce the design effort, and can be used in
other modules to create a functional hierarchy.
@@ -1406,29 +1476,28 @@
Hierarchy
from skidl import *
import sys
+# Define a global resistor template.
+r = Part('Device', 'R', footprint='Resistor_SMD.pretty:R_0805_2012Metric', dest=TEMPLATE)
+
# Define the voltage divider module. The @subcircuit decorator
-# handles some skidl housekeeping that needs to be done.
+# handles some SKiDL housekeeping that needs to be done.
@subcircuit
def vdiv(inp, outp):
"""Divide inp voltage by 3 and place it on outp net."""
- rup = Part("Device", 'R', value='1K', footprint='Resistor_SMD.pretty:R_0805_2012Metric')
- rlo = Part("Device",'R', value='500', footprint='Resistor_SMD.pretty:R_0805_2012Metric')
- rup[1,2] += inp, outp
- rlo[1,2] += outp, gnd
+ inp & r(value='1K') & outp & r(value='500') & gnd
+
+# Declare the input, output and ground nets.
+input_net, output_net, gnd = Net('IN'), Net('OUT'), Net('GND')
-gnd = Net('GND') # GLobal ground net.
-input_net = Net('IN') # Net with the voltage to be divided.
-output_net = Net('OUT') # Net with the divided voltage.
-
# Instantiate the voltage divider and connect it to the input & output nets.
vdiv(input_net, output_net)
-generate_netlist(sys.stdout)
+generate_netlist(file_=sys.stdout)
For the most part, vdiv
is just a standard Python function:
it accepts inputs, it performs operations on them, and it could return
-outputs (but in this case, it doesn’t need to).
+results (but in this case, it doesn’t need to).
Other than the @subcircuit
decorator that appears before the function definition,
vdiv
is just a Python function and it can do anything that a Python function can do.
@@ -1469,117 +1538,119 @@ Hierarchy
can use the vdiv
module to divide a voltage multiple times:
+
from skidl import *
import sys
-# Define the voltage divider module.
-@subcircuit
+r = Part('Device', 'R', footprint='Resistor_SMD.pretty:R_0805_2012Metric', dest=TEMPLATE)
+
+@subcircuit
def vdiv(inp, outp):
- """Divide inp voltage by 3 and place it on outp net."""
- rup = Part("Device", 'R', value='1K', footprint='Resistor_SMD.pretty:R_0805_2012Metric')
- rlo = Part("Device",'R', value='500', footprint='Resistor_SMD.pretty:R_0805_2012Metric')
- rup[1,2] += inp, outp
- rlo[1,2] += outp, gnd
+ inp & r(value='1K') & outp & r(value='500') & gnd
+
+input_net, output_net, gnd = Net('IN'), Net('OUT'), Net('GND')
@subcircuit
def multi_vdiv(repeat, inp, outp):
- """Divide inp voltage by 3 ** repeat and place it on outp net."""
+ """Divide inp voltage by 3 * repeat and place it on outp net."""
for _ in range(repeat):
out_net = Net() # Create an output net for the current stage.
vdiv(inp, out_net) # Instantiate a divider stage.
inp = out_net # The output net becomes the input net for the next stage.
outp += out_net # Connect the output from the last stage to the module output net.
-gnd = Net('GND') # GLobal ground net.
-input_net = Net('IN') # Net with the voltage to be divided.
-output_net = Net('OUT') # Net with the divided voltage.
-multi_vdiv(3, input_net, output_net) # Run the input through 3 voltage dividers.
+
+input_net, output_net, gnd = Net('IN'), Net('OUT'), Net('GND')
+
+multi_vdiv(3, input_net, output_net) # Run the input through 3 voltage dividers.
-generate_netlist(sys.stdout)
+generate_netlist(file_=sys.stdout)
-(For the EE’s out there: yes, I know cascading three simple voltage dividers
+(For the EE’s out there: yes, I know cascading three simple voltage dividers
will not multiplicatively scale the input voltage because of the
-input and output impedances of each stage!
+input and output impedances of each stage!
It’s just the simplest example I could use to show hierarchy.)
-And here’s the resulting netlist:
+Subcircuits can also be configurable (after all, they’re just functions).
+The ratio of the voltage divider could be set with a parameter:
-(export (version D)
- (design
- (source "C:\TEMP\skidl tests\multi_hier_example.py")
- (date "04/20/2017 09:43 AM")
- (tool "SKiDL (0.0.12)"))
- (components
- (comp (ref R1)
- (value 1K)
- (footprint Resistor_SMD.pretty:R_0805_2012Metric)
- (fields
- (field (name keywords) "r res resistor")
- (field (name description) Resistor))
- (libsource (lib device) (part R)))
- (comp (ref R2)
- (value 500)
- (footprint Resistor_SMD.pretty:R_0805_2012Metric)
- (fields
- (field (name keywords) "r res resistor")
- (field (name description) Resistor))
- (libsource (lib device) (part R)))
- (comp (ref R3)
- (value 1K)
- (footprint Resistor_SMD.pretty:R_0805_2012Metric)
- (fields
- (field (name keywords) "r res resistor")
- (field (name description) Resistor))
- (libsource (lib device) (part R)))
- (comp (ref R4)
- (value 500)
- (footprint Resistor_SMD.pretty:R_0805_2012Metric)
- (fields
- (field (name keywords) "r res resistor")
- (field (name description) Resistor))
- (libsource (lib device) (part R)))
- (comp (ref R5)
- (value 1K)
- (footprint Resistor_SMD.pretty:R_0805_2012Metric)
- (fields
- (field (name keywords) "r res resistor")
- (field (name description) Resistor))
- (libsource (lib device) (part R)))
- (comp (ref R6)
- (value 500)
- (footprint Resistor_SMD.pretty:R_0805_2012Metric)
- (fields
- (field (name keywords) "r res resistor")
- (field (name description) Resistor))
- (libsource (lib device) (part R))))
- (nets
- (net (code 0) (name GND)
- (node (ref R2) (pin 2))
- (node (ref R4) (pin 2))
- (node (ref R6) (pin 2)))
- (net (code 1) (name IN)
- (node (ref R1) (pin 1)))
- (net (code 2) (name N$1)
- (node (ref R1) (pin 2))
- (node (ref R2) (pin 1))
- (node (ref R3) (pin 1)))
- (net (code 3) (name N$2)
- (node (ref R3) (pin 2))
- (node (ref R4) (pin 1))
- (node (ref R5) (pin 1)))
- (net (code 4) (name OUT)
- (node (ref R5) (pin 2))
- (node (ref R6) (pin 1))))
-)
+# Pass the division ratio as a parameter.
+@subcircuit
+def vdiv(inp, outp, ratio):
+ inp & r(value=1000) & outp & r(value=1000*ratio/(1-ratio)) & gnd
+
+...
+
+# Instantiate the voltage divider with a ratio of 1/3.
+vdiv(inp, outp, ratio=0.33)
+
+
+Packages
+
+The @subcircuit
decorator lets you create a hierarchical circuit where the
+subcircuits are instantiated using function calls with arguments.
+The @package
decorator is an alternative that packages a subcircuit into
+a Part
-like object with its own input and output pins that can be connected
+to other components.
+In essence, you’ve encapsulated a subcircuit into its own package with I/O pins.
+
+from skidl import *
+import sys
+
+r = Part('Device', 'R', footprint='Resistor_SMD.pretty:R_0805_2012Metric', dest=TEMPLATE)
+
+# Define the voltage divider module. The @package decorator
+# creates an interface that acts like I/O pins.
+@package
+def vdiv(inp, outp):
+ inp & r(value='1K') & outp & r(value='500') & gnd
+
+input_net, output_net, gnd = Net('IN'), Net('OUT'), Net('GND')
+
+# Instantiate the voltage divider as a package.
+divider = vdiv()
+
+# Now connect the I/O pins of the instantiated package to the input & output nets.
+divider.inp += input_net
+divider.outp += output_net
+
+generate_netlist(file_=sys.stdout)
+
+
+Subcircuits defined with @package
are also customizable via parameters:
+
+from skidl import *
+import sys
+
+r = Part('Device', 'R', footprint='Resistor_SMD.pretty:R_0805_2012Metric', dest=TEMPLATE)
+
+# Voltage divider with a parameterized division ratio.
+@package
+def vdiv(inp, outp, ratio):
+ inp & r(value=1000) & outp & r(value=1000*ratio/(1-ratio)) & gnd
+
+input_net, output_net, gnd = Net('IN'), Net('OUT'), Net('GND')
+
+# Instantiate the voltage divider with a ratio of 1/3.
+divider = vdiv(ratio=1.0/3)
+
+divider.inp += input_net
+divider.outp += output_net
+
+# You can also override the division ratio. Note that a standard
+# assignment operator is used instead of += because ratio is not an I/O pin.
+divider.ratio = 0.5
+
+generate_netlist(file_=sys.stdout)
Interfaces
Passing nets between hierarchically-organized modules can lead to long
lists of arguments.
-To make the code easier to write and understand, SKiDL supports interfaces which are simply containers that
-encapsulate a number of Bus
, Net
, or Pin
objects.
+To make the code easier to write and understand, SKiDL supports interfaces
+which are simply dictionaries that encapsulate a number of Bus
, Net
, or Pin
objects.
For example, here is an interface for a memory:
mem_intfc = Interface(
@@ -1605,8 +1676,8 @@ Interfaces
ram['A[0:19]'] += intfc.addr
ram['DQ[0:15]'] += intfc.data
ram['WE#'] += intfc.wr
- ram['OE#'] += intfc.rd
- ...
+ ram['OE#'] += intfc['rd'] # Interface members are also accessible using []'s.
+ ...
Libraries
@@ -1979,6 +2050,60 @@ Selectively Supressing ERC Messages
my_part.do_erc = False # Turns off ERC for all the pins of this part.
+Customizable ERC Using erc_assert()
+
+SKiDL’s default ERC will find commonplace design errors, but sometimes
+you’ll have special requirements.
+The erc_assert
function can be used to check these.
+
+from skidl import *
+import sys
+
+# Function to check the number of inputs on a net.
+def get_fanout(net):
+ fanout = 0
+ for pin in net.get_pins():
+ if pin.func in (Pin.INPUT, Pin.BIDIR):
+ fanout += 1
+ return fanout
+
+net1, net2 = Net('IN1'), Net('IN2')
+
+# Place some assertions on the fanout of each net.
+# Note that the assertions are passed as strings.
+erc_assert('get_fanout(net1) < 5', 'failed on net1')
+erc_assert('get_fanout(net2) < 5', 'failed on net2')
+
+# Attach some pins to the nets.
+net1 += Pin(func=Pin.OUTPUT)
+net2 += Pin(func=Pin.OUTPUT)
+net1 += Pin(func=Pin.INPUT) * 4 # This net passes the assertion.
+net2 += Pin(func=Pin.INPUT) * 5 # This net fails because of too much fanout.
+
+# When the ERC runs, it will also run any erc_assert statements.
+ERC()
+
+
+When you run this code, the ERC will output the following:
+
+ERC ERROR: get_fanout(input_net2) < 5 failed on net2 in <ipython-input-114-5b71f80eb001>:16:<module>.
+
+0 warnings found during ERC.
+1 errors found during ERC.
+
+
+You might ask: “Why not just use the standard Python assert
statement?”
+The reason is that an assertion is evaluated as soon as the assert
statement is encountered
+and might be evaluated incorrectly if the nets or other circuit objects are not yet
+completely defined.
+But the statement passed to the erc_assert
function isn’t evaluated until all the
+various parts have been connected and ERC()
is called
+(that’s why the statement is passed as a string).
+Note in the code above that when the erc_assert
function is called, no pins
+are even attached to the net1
or net2
nets, yet.
+The erc_assert
function just places the statements to be checked into a queue
+that gets evaluated when ERC()
is run.
+
Going Really Deep
If all you need to do is design the circuitry for a PCB, then you probably know
@@ -2110,8 +2235,8 @@
SPICE Simulations