Hey all,
I am trying to automate clock-driven digital signal track widths and clearances using custom rules on KiCad 8.0.8.
My basic idea is that single-ended signals would be 50 ohm on any layer and the clearance would be 2W, or two times the track width. I know 3W is the general rule of thumb, but some areas get too crowded with that clearance. Similarly, differential signals have their track widths, clearances and gaps defined per characteristic impedance and layer, but this time with a 3W clearance.
Here are my rules so far. First, I have some connector and ICs with 0.5mm or 0.4mm pitch, and the default clearances are way too high for them:
(rule "pad_clearance"
(condition "A.Type == 'Pad'")
(constraint clearance (min 0.1mm)))
(I probably could and should limit that rule to a specific set of components in the future.)
Next, I define the single-ended signal tracks:
(rule "single_50ohm_layer1"
(condition "(A.Type == 'Track') && (A.NetClass == 'Default') && A.existsOnLayer('F.Cu')")
(constraint track_width (opt 0.1565mm))
(constraint clearance (min 0.313mm)))
This is repeated for every signal layer on the board. I’m lazy and I’m using the Default netclass for digital signals as they’re the most common type on my board.
Next, similar rules for differential pairs:
(rule diff_90ohm_layer1
(condition "(A.Type == 'Track') && (A.inDiffPair('*/PCIe*') || A.inDiffPair('*/USB*')) && A.existsOnLayer('F.Cu')")
(constraint track_width (opt 0.1575mm))
(constraint clearance (min 0.315mm))
(constraint diff_pair_gap (min 0.1mm) (opt 0.2mm) (max 0.25mm)))
Again, this is permutated for each signal layer and characteristic impedance. (I just realized I should define a netclass for each characteristic impedance level instead of using the net names above. Oh well.)
I also found out that I need to add a rule to keep the differential pair members from requiring clearance from each other:
(rule "ignore_diff_pair_member_clearance"
(condition "AB.isCoupledDiffPair()")
(constraint clearance (min 0.1mm)))
Now, finally, the difficult part and the one I haven’t solved satisfactorily: how to adjust the neckdown when connecting to components. I’m not sure if neckdown refers to just track widths, but so far I haven’t tried to automate those, just the clearances. Here’s what I have:
(rule "neck_down"
(condition "A.intersectsCourtyard('*')")
(constraint clearance (min 0.1mm)))
While this rule does its job, it makes working with tracks awfully sluggish. There’s a good 1-second delay when starting or finishing a new track segment. I suspect the intersectsCourtyard
condition with a wildcard does some O(M*N) looping through the available footprints and board components.
I also tried this but it didn’t work. (Why?)
(rule "neck_down"
(condition "A.Type == 'Track' && B.Type == 'Pad'")
(constraint clearance (min 0.1mm)))
Ideally, I would like to keep the neckdown rule somewhat general to make it easy to migrate the rules file between projects. How would you suggest it to be done?