For the curious:
The protocol used by SD-cards is synchronous, Each package is ACKed after sending and the full process must happen in one clock tick, so the signal MUST travel twice the cable length in one clock tick. Indeed, you need some margin to get things working stable. You can do the maths for “standard” transmission speeds in PCB tracks (about 50% of light speed, i.e. 15 cm/ns).
Asking the IA, she tells:
Track Length Guidelines by Protocol
| SD Card Mode / Type | Frequency | Max Track Length | Length Matching (Skew) |
|---|---|---|---|
| Legacy SPI Mode | 100 kHz – 25 MHz | Up to 45 cm (18") | Not critical (within 500 mils) |
| Default SD / SDIO | Up to 25 MHz | Up to 25 cm (10") | Match within 2.5 mm (100 mils) |
| High-Speed SD Mode | Up to 50 MHz | Up to 12 cm (4.7") | Match within 1.5 mm (60 mils) |
| UHS-I (SDR50 / DDR50) | Up to 100 MHz | Up to 10 cm (4") | Match within 0.5 mm (20 mils) |
| UHS-I (SDR104) | Up to 208 MHz | Under 5 cm (2") | Match within 0.25 mm (10 mils) |
Of course, we are talking of UHS-I (SDR104) SD-cards ![]()
For the zynthian main board we tried to reduce the length and matching the length as much as possible, but as you can see the margin is really tight, so here the issues with some cards.
BTW, note the new position of the SD-card connector in the main board. I had to short the distance and improve the wiring so the sdcard synchronous signal could travel the distance in less than half period at the faster frequencies supported by the Pi5. FYI, RPI5 supports SDR104 cards at full speed, what means the bus frequency is 208MHz, compared with the RPI4 that only supports DDR50 with the data bus running at 48MHz. If you do some calculations, you can see how close to the physical limit we are, so every mm counts and i had to deploy “best practices” for routing high frequency signals. Much fun when it finally worked!
This is the detail of routing:
Note the track-length matching, to keep the signal synced and the “big” separation between tracks to avoid cross-talking.
Regards,
