Series Resistor ↔ Bandwidth

How big a series fault-limiting resistor can you put on a short chip-to-chip CMOS link before it costs you throughput? Sized for the case where two programmable devices face each other and a bad bitstream could turn both pins into outputs. Defaults are an AGRV2K↔AGRV2K link, 1 inch, 4-layer JLC 7628 microstrip.
Hammerstad/Wheeler microstrip (IPC-2141 family) · Elmore-delay RC link model with a ramp source · brute-force NRZ eye simulation. All live — every number recomputes from the fields.
Inputs
Geometry
in
mil
oz
Stackup
mm
Driver & receiver
Ω
Ω
pF
pF
ns
µA
Two Rₒ values on purpose: settling and contention sit at different points on the driver's I–V curve, and you want the optimistic one for speed and the pessimistic one for safety. Set the fault value to 0 to credit the driver with nothing at all. tᵣ is the driver's intrinsic slew — if you measured an edge at a pin, subtract this link's own RC before entering it, or you'll count it twice.
Signalling
V
V
V
Resistor placement
Budget & criteria
×τ
mA
 
Mb/s
Eye criterion what K means

A worst-case isolated bit — a long run of one level, then one opposite bit — reaches only 1 − e−K/2 of full swing at the mid-bit sample point (rising), or falls only to e−K/2 above ground (falling).

Every rate in the table scales as 1/K, so you can rescale the whole sheet from one field. Note which edge binds: CMOS input thresholds are not symmetric — on a 3.3 V rail Vᵢₗ sits at 0.24·VDD while Vᵢₕ sits at 0.61·VDD, so the falling edge runs out of room first and sets the wall.

Derived microstrip over the plane below it
The tradeoff, with R eliminated large-R asymptote
fmax = Ifault ÷ (4 · Ctot · V)
R cancels — but Ro and tr do not
Mb/s per mA — asymptote

Mind the gap between those two numbers. The clean form drops Ro and tr; exactly, f = 1 / (K·(Rₒ + V/I − 2Rₒfault)·Ctot + tᵣ). They converge only when I·Rₒ ≪ V, which at a 20 mA design point on 3.3 V is not especially true. Trust the table; the asymptote is for intuition about which way the levers push.

Picking R just picks a point on that line. The only two ways to move the line are to cut Ctot (mostly the receiver's pin capacitance — nothing you can do about it on an FPGA, so at least don't add stubs or test points) or to drop V. Switching a 3.3 V link to 1.8 V buys 1.83× the throughput at identical fault current.

Two caveats on that 1.83×. Threshold ratios are not constant across rails — VIL/VDD goes 0.24→0.35 from LVCMOS33 to LVCMOS18 — but that moves the K wall from 2.83 down to 2.10, so it helps rather than hurts. Working against you: a CMOS driver's Ro rises at lower VDD (less gate overdrive), which the constant-Ro model here doesn't capture. Treat 1.83× as the optimistic bound.

Resistor value vs. everything else click a row to load it into the eye below
Rtotalin the signal path per endexact half; round to E24 τns UIns max rateMb/s per pin DDR strobeMHz, = rate÷2 IfaultmA, one pin rail drawmA, all pins PRmW total
Red = fault current exceeds the pin abs-max you set.   = the fastest row that still stays under it — usually the one you want.   Grey rate = faster than the device ceiling, so the resistor isn't the limit; you're paying fault current for bandwidth you can't use.
What speed does each current budget buy? click a row to load it
pin budgetmA, worst-case fault R neededΩ total per endif split max rateMb/s = SDR MHz DDR strobeMHz rail drawmA, all pins
Eye diagram

All 64 six-bit NRZ patterns pushed through the single-pole RC, overlaid on a 2-UI window centred on one bit. Each pattern starts fully settled at its own first bit, so the set includes the true worst case — an infinitely long run followed by one opposite bit. The vertical line is where you sample: the assumption is that you PLL-shift or clock-divide to land dead centre, so the only question is whether the eye is open there.

Sampling slack is deliberately asymmetric. An RC eye opens late and then stays open to the end of the bit, so sampling early is the only way to fall out of it and a symmetric “±” figure would flatter the direction that actually fails. A * means the late side is clipped by the end of the bit rather than by the eye. The driver's intrinsic edge is modelled: the source ramps over tr rather than stepping, which is why the transitions have straight lead-ins. The UI that each resistor supports is then solved numerically for the settling target K implies, rather than approximated as K·τ + tr — that shortcut is fine while tr is small but claims rates whose eyes are shut once tr approaches K·τ.

What this model does and doesn't capture

At an inch, this is not a transmission-line problem. Round-trip delay is ~300 ps against a CMOS edge of 1–2 ns, so reflections are swallowed inside the edge. The series resistor is not doing termination — it is a fuse, and RC is the entire price of it. Size it on fault current alone. Watch the regime banner above: if you shorten the edge or lengthen the trace enough to flip it, the whole model below stops applying and you need real termination and an actual SI sim.

The aggregate rail current is the real hazard. One pin fighting at 80 mA is survivable-ish for a short mistake. Thirty pins at 80 mA is nearly 2.5 A dumped from VCCIO to ground, and that is what takes out a board — regulator failure, rail collapse, everything downstream browning out mid-fault. Size the rail for a contention scenario, or make sure it current-limits rather than sags.

One resistor per net is enough for protection. It's in the path no matter which end drives. Splitting it doesn't improve protection at the same total — it just gives each direction its own source termination, which at an inch you don't need. Splitting does cost less bandwidth than putting the whole value at the driver, because half of it then sits behind the trace capacitance.

Receiver-end placement is the fastest option and the sheet models it: the trace capacitance charges through Ro alone, and only the pin capacitance sees the resistor. The asymptotic win is Ctot/Cpin — about 60% at the defaults, and ~38% by 220 Ω. (Splitting asymptotes to ~23%.) You give up source termination, which at an inch is free. The counter-argument the other way: with R at the driver, the trace sits at high impedance while it settles, which makes it a much better crosstalk victim than a line driven from Ro alone.

Don't rely on programmable drive strength or open-drain as the protection. Dropping to the weakest drive setting would give you a big Ro for free with no BOM. But on AGRV2K those are bitstream-time only, not runtime-tunable, and a wrong bitstream is precisely the fault you are defending against. The physical resistor is the thing that survives a bad bitstream. That is the entire reason it exists.

Driver-vs-driver is not the only fault mode, and it may not be the worst. The contention current modelled here assumes both devices are powered and configured. At least as likely on a two-FPGA board: one device drives while the other's VCCIO is off or still ramping. Current then flows through the receiving pin's ESD clamp into an unpowered rail, and the governing limit is a latch-up injection spec — commonly ~10 mA/pin, tighter than the DC abs-max this sheet defaults to. Power sequencing, hot-socket behaviour, and the device's pre-configuration pin state are all outside this model. Note also that the abs-max itself is unverified: the AGRV2K brief has no electrical characteristics section, so both ends of the safety inequality rest on assumption.

Above roughly a kilohm, DC effects bind before RC does — and none of them are modelled. Receiver input leakage of ±10 µA across 10 kΩ is 100 mV of DC offset eating straight into a low-side margin that is only ~0.35 V at K=4 (the eye panel now reports this). Worse, an internal pull-up or pull-down forms a divider with the series resistor: a 10 kΩ pull against a 10 kΩ series R halves the swing outright, and even a 50 kΩ pull costs 17%. That is not hypothetical here — the threat model is a bad bitstream, and a bitstream that enables a pull is exactly as likely as one that enables an output.

What the model ignores: Ro is a fixed linear resistance in both directions, which a real CMOS driver is not — it is current-limited (weaker than linear) mid-swing and more conductive near the rail, so the error has opposite signs for settling and for fault current. That is why the two Ro fields exist. The trace is lumped rather than distributed, valid only while the line stays electrically short. Solder mask is ignored, which understates εeff and overstates Z0 by a few percent — roughly cancelling the residual error in the thickness correction. Crosstalk, SSO/ground bounce, and supply noise all eat into the margin the eye shows. The resistor's own ~0.1–0.3 pF of parasitic shunt is neglected, which at very high R slightly helps. And the receiver-end and split topologies are genuinely two-pole; the sheet collapses each to the single pole given by its Elmore delay, which is the conservative direction — a real two-pole step reaches the threshold slightly sooner than its Elmore time constant suggests.

The number to verify before trusting any of this is Cpin. Every rate scales as 1/Ctot and the receiver pin is the majority of it. The AGRV2K Rev 3.0 brief has no electrical characteristics section at all — no DC characteristics, no absolute maximums, and the string “pF” does not appear in it. The AG32 MCU reference manual's IO table gives only VIL/VIH/VOL/VOH/RPU/RPDno GPIO input capacitance anywhere in either document. So 5.5 pF is an industry-typical figure, not an AGM-published one. The one adjacent datum: the ADC pins (muxed with ordinary GPIO) spec an input sampling capacitance of 8–10 pF — itself inconsistent between two tables, and a sample-and-hold cap rather than pad capacitance, but it points upward from 5.5. Measure it: drive a pin through a known large series R and scope the far end's RC.

Ro = 45 Ω is also unverified, and it is the one default that errs toward danger. The AG32 manual gives VOH/VOL without any IOL/IOH test conditions, which makes them useless for drive characterisation. The empirical prior for a plain 3.3 V CMOS pad is more like 12–30 Ω. A lower Ro means a higher fault current for the same resistor — at R=0 the difference is 37 mA (at 45 Ω) versus 83 mA (at 20 Ω). That is why the fault column has its own Ro for fault field, defaulted to 20 Ω, and why the solver sizes the resistor from that rather than from the settling value. Push it to 0 for the answer that credits the driver with nothing at all — the only assumption a bad bitstream cannot invalidate. Worth noting how much protection you were leaning on: at 3.3 V, holding 20 mA takes 165 Ω of loop resistance, so crediting two 45 Ω drivers would have had the silicon supply 55% of your safety margin — the same silicon whose misconfiguration is the fault being defended against.

AGRV2K reality check measured, not datasheet
  • Fabric Fmax: 105–172 MHz on real designs (routing-limited, not cell-limited). 100 MHz is the robust target; 125 MHz is seed-dependent.
  • No hardened DDR I/O register (IO_TYPE : RIO) — DDR has to be built in fabric. The fabric ODDR wall is ~260 Mb/s per pin (130 MHz strobe) but that came from a best-of-4-seeds run under a deliberately over-tight constraint. The validated design point is 160 Mb/s (80 MHz strobe) at +2.8 ns slack with no seed sensitivity.
  • Drive strength is not a known quantity. The toolchain exposes {2, 4, 8, 12} mA, but that enum has no vendor source — the pad has a 4-bit, 16-level drive field whose mA mapping has never been measured. Slew is one bit whose polarity is assumed, and the CLI refuses to set it at all. Neither is runtime-tunable or modelled by the STA.
  • So 200 Mb/s is the defensible ceiling (the sheet's default) — 260 is a best-seed wall, and it needs a 130 MHz strobe, which contradicts the 100 MHz robust target in the first bullet. Below the crossover marked in the table, the silicon is your limit and extra fault current buys nothing.