This is to discuss features that would enable concise drawing of schematics that have (highly) repetitive circuits and/or complex net connectivity. This does not address layout replication / re-use as that is a separate problem.
Complex designs can have devices with high repetition in parallel, series, or both. You can have wide bus signals which are made up of connections to several devices with their own (wide) bus signals. You can have signals (or a vector of signals) with identical connections to a large number of repeated circuits.
Examples: daisy-chained 100x smart leds, memory arrays, multi-channel audio circuits.
Drawing repeated, identical devices or hierarchical instances require one symbol placed for each element. If each element is identical, then why can’t they all be stacked into a single drawn symbol representing all elements? The schematic could be significantly more concise, especially when all connectivity follows a regular pattern.
A challenge to supporting this is that the pins of said stacked devices are like an array. There needs to be a way to differentiate a single-net wire connecting to each pin in this array versus creating individual nets for each pin.
Altium has a solution via the “REPEAT()” function that applies to hierarchical blocks. As part of this functionality, there is minimal support for routing a regular labeled wire to a repeated instance, and “repeating” the net accordingly. However its implementation is limited and in my opinion a real pain to use.
KiCad doesn’t have equivalent functionality at the moment. At least on the wiring side, KiCad has had some work going in this direction in the form of bus vectors, bus groups, and hierarchical bus pins. They work, but there are several limitations.
- KiCad’s bus implementation can only describe sets of unique nets. Additionally, bus vectors are always sorted by ascending bit index in the background for determining connectivity.
- You cannot intentionally reverse the bit order of a bus at a bus vector pin, should that be necessary.
- You cannot create some arbitrary array of signals and connect it to a bus pin (ex:
{A B C D}
to pinFOO[3..0]
).
- For bus vector wires specifically, you can take continuous slices of a bus vector and route it to a hierarchical instance’s bus vector pin (ex: you can do bus wire
FOO[7..4]
to instance bus pinBAR[3..0]
). Great, this is useful. - Discontinuous slices of a bus vector, such as an interleaving scheme, are not possible. (ex: for a bus vector
FOO[7..0]
and some hierarchical block instancesA,B
with bus pinBAR[3..0]
, what happens if you must routeFOO[0,2,4,6]
toA.BAR[3..0]
andFOO[1,3,5,7]
toB.BAR[3..0]
?). As an aside, this use case could be enabled by adding an “index step” feature to the vector syntax. - Bus groups are even more restrictive; element names and index ranges must match between bus group wires and bus group pins.
All of this to say that there is room for improvement.
There are CAD tools in the IC design space that solved these problems decades ago. The solutions have some similarities to what Altium has, but are more flexible. Referencing the solution from from one popular tool, here’s a visual example of what this would look like in KiCad:
Explanation of the features:
- Device instances and hierarchical block instances in schematic accept a vector syntax in the reference designator describing an index range with optional step size.
prefix<start[:end[:step]]>
. These repeated instances will be elaborated in the background to individual instances namedprefix<idx>
. Examples:U0<0>
→U0<0>
(Single instance)U1<0:2>
→U1<0>, U1<1>, U1<2>
(ascending range)U2<3:0:2>
→U2<3>, U2<1>
(descending range with step)
- Hierarchical block pins (regular, not bus vector or bus group pins) are upgraded to accept the same range & step vector syntax. These are elaborated in the background into arrays of individual pins. A key feature is that you are allowed to have repeated instances of a sheet using vectored pins.
- Wires are upgraded to operate on arrays of nets. Wire labels accept an even more powerful syntax to describe net vectors, repeats, and concatenations of lists of nets. Examples:
AD<1:0>
→AD<1>, AD<0>
(basic net vector)AD<0:3:2>
→AD<0>, AD<2>
(basic net vector with index step)BC<0:1*2>
→BC<0>,BC<0>,BC<1>,BC<1>
(net vector with inner index repeat)BC<(0:1)*2>
→BC<0>,BC<1>,BC<0>,BC<1>
(net vector with outer index repeat)BC<3:2,4,0:1>
→BC<3>,BC<2>,BC<4>,BC<0>,BC<1>
(net vector with a list of index ranges)BC<(0,1*2)*2,5>
→BC<0>,BC<1>,BC<1>,BC<0>,BC<1>,BC<1>,BC<5>
(complex net vector)<*2>A
→A, A
(prefix repeat operator)A,B<1:0>,C
→A,B<1>,B<0>,C
(a list of nets and vectors)<*2>(A,<*2>B,A,C<1:0>)
→A,B,B,A,C<1>,C<0>,A,B,B,A,C<1>,C<0>
(a mix of features)
- Instances, pins, and net expressions get expand into arrays in the background. Connectivity is determined by the arrays at each index, so order matters. If there is a mismatch in signal width between a wire and some (repeated instance) pin, there are rules in certain cases to allow one side to be repeated so the widths match. Examples:
- A single-bit wire named
X
and a repeated instanceU1<0:3>
with pinCLK
.U1<i>.CLK == X
for eachi
. - A multi-bit wire named
X<0:3>
and a repeated instanceU1<0:3>
with pinCLK
.U1<i>.CLK == X<i>
for eachi
. - A multi-bit wire named
X<0:3>
and a single instanceU1
with pinCLK<0:3>
.X<i> == U1.CLK<i>
for eachi
. - A multi-bit wire named
IN<3:0>
and a repeated instanceU1<1:0>
with pinD<3:0>
.IN<0:3> == U1<i>.D<3:0>
for eachi
. - A multi-bit wire named
OUT<0:7>
and a repeated instanceU1<1:0>
with pinQ<3:0>
.OUT<0:3> == U1<1>.Q<3:0>
andOUT<4:7> == U1<0>.Q<3:0>
- A single-bit wire named
I think it would be great to implement something like what is described above. With some adaptations, I think it could be possible to integrate it with existing functionality.
- Leave bus vectors and bus groups as-is. If they are connected to a repeated instance, then simply repeat them as-is to each element. Maybe consider adding an index step feature.
- The current bus wire and pin implementation drops brackets when generating net names. IE:
AD[3]
will be netAD3
. The new features should do the same. Similar argument for sheet pins. - For instance names, it might be helpful to keep the brackets in the name to avoid name conflicts like
U4<0>
→U40
. - All elements of a repeated instance must be identical in all attributes (parameters, footprint, saved layout, etc).
Let me know what you think and please share any ideas for improvement!