Skip to content
VLSI Mentor

I²C · Module 19

External Pull-Ups vs Internal Weak Pull-Ups

Every FPGA pin can enable an internal pull-up from a constraints file, and it is the wrong device for a bus. Works the arithmetic both ways: what resistance each speed mode allows at a given bus capacitance, what rise time a weak internal pull-up actually produces, and why a value that costs nothing is five times too large for Fast mode.

Chapter 19.1 and 19.2 built a path from drive intent to a package pin, and neither of them can produce a HIGH. The output stage only ever pulls down; the wrapper only ever releases; the bus model asserts that a released net reads 1 and does not say why.

The why is a resistor, and on an FPGA there is a tempting shortcut: every pin has a programmable pull-up you can enable from a constraints file, at no board cost, with no component to place. This chapter is about why that shortcut does not work, stated as arithmetic rather than as a rule of thumb.

1. What Is Already Established, and What Is New Here

The general electrical argument is not this chapter's. Chapter 2.4 establishes that the restoring element is a board-level decision, one per line, and that omitting it does not give a slow bus but a bus with no HIGH at all. Chapter 11.7 derives the rise-time relationship and the Cb limits. Chapter 11.9 shows tr being spent twice — once in the clock period and once in the low phase's settling — and finds a Fast-mode-Plus deficit that is exactly tr(max).

This chapter asks one narrower question those cannot: the FPGA offers a pull-up inside the pin. Is it the right one? The answer is a number, and the number is not close.

2. The Relationship, Restated Once

A released open-drain line is an RC charge from whatever it was toward VDD:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
V(t) = VDD · (1 − e^(−t / (Rp · Cb)))

I²C measures tr between 30 % and 70 % of the swing, so the specified rise time is the interval between two points on that curve:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
t(30%) = Rp·Cb · ln(1/0.7)   =  0.3567 · Rp·Cb
t(70%) = Rp·Cb · ln(1/0.3)   =  1.2040 · Rp·Cb
──────────────────────────────────────────────
tr     = Rp·Cb · ln(0.7/0.3) =  0.8473 · Rp·Cb

That 0.8473 is the only constant in the chapter, and Chapter 11.7 derives it. Everything below is that one line rearranged.

A diagram of the pull-up charging path. A supply rail feeds a pull-up resistor, which connects to the shared SDA node. The node carries a total bus capacitance to ground, made of device pin capacitance, trace capacitance and connector capacitance. Three open-drain device pins also attach to the node and can only pull it down. The node's rise time is the product of the pull-up resistance and the total capacitance.VDDthe only source ofHIGHRpboard componentSDA nodeshared conductorrise time0.8473·Rp·CbCbpins + trace +connectorOpen-drain pinsdischarge onlychargespull LOW12
Figure 1 — the RC path that makes every rising edge on the bus. The pull-up and the total bus capacitance are in series across the supply; the open-drain pins can only discharge that capacitance, never charge it. Rp is a board component, Cb is the sum of every pin, trace and connector on the net, and their product sets tr — which Chapter 11.9 then spends twice in the timing budget.

3. What Each Speed Mode Allows

Rearranged for the largest resistor a mode tolerates:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
Rp(max) = tr(max) / (0.8473 · Cb)
modetr(max)Cb = 50 pFCb = 100 pFCb = 200 pFCb = 400 pF
Standard, 100 kHz1000 ns23.6 kΩ11.8 kΩ5.90 kΩ2.95 kΩ
Fast, 400 kHz300 ns7.08 kΩ3.54 kΩ1.77 kΩ0.89 kΩ
Fast-mode Plus, 1 MHz120 ns2.83 kΩ1.42 kΩ0.71 kΩ0.35 kΩ

Read the table by column, not by row. Doubling the capacitance halves every allowable resistance, and capacitance is the quantity that grows when someone adds a device, lengthens a trace, or fits a connector.

There is also a floor. A pull-up strong enough to charge quickly is a pull-up whose current every device must sink while holding the line LOW:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
Rp(min) = (VDD − VOL(max)) / IOL(max)
VDDVOL(max)IOL(max)Rp(min)
3.3 V0.4 V3 mA967 Ω
3.3 V0.4 V20 mA145 Ω
1.8 V0.2 V3 mA533 Ω

So for Fast mode at 100 pF and 3.3 V with an ordinary 3 mA sink capability, the legal window is:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
967 Ω  ≤  Rp  ≤  3541 Ω

which is why 1.8 kΩ, 2.2 kΩ and 3.3 kΩ are the values that keep appearing on real boards. They are not folklore; they are the middle of that window.

4. What the Internal Pull-Up Actually Produces

Now the same equation in the other direction. Given a resistance, what rise time do you get?

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
tr = 0.8473 · Rp · Cb
RpCb = 50 pFCb = 100 pFCb = 200 pFCb = 400 pF
10 kΩ424 ns847 ns1695 ns3389 ns
20 kΩ847 ns1695 ns3389 ns6778 ns
40 kΩ1695 ns3389 ns6778 ns13 557 ns
50 kΩ2118 ns4236 ns8473 ns16 946 ns

At a modest 100 pF — a small board, a few devices, no connector:

internal RptrStandard (1000 ns)Fast (300 ns)Fm+ (120 ns)
10 kΩ847 nspasses, with 15 % marginfails, 2.8× overfails, 7.1× over
20 kΩ1695 nsfails, 1.7× overfails, 5.6× overfails, 14× over
40 kΩ3389 nsfails, 3.4× overfails, 11× overfails, 28× over

This is not a marginal call to be resolved by measurement on a good day. It is an order-of-magnitude mismatch, and it is why the resistor is a board component.

5. Why the Failure Is Worse Than "Slow"

A too-weak pull-up does not produce a bus that runs at a lower speed. It produces a bus that is intermittently wrong at the speed you configured, which is a far harder thing to diagnose.

Chapter 11.9 shows tr being charged to the budget twice — once as part of the clock period and once inside the low phase, where the data must settle before the next rising edge. So a rise time over budget attacks two different obligations at once:

The period obligation is the forgiving one. If the line has not reached 70 % when the controller drives SCL low again, the edge is late, and a controller generating SCL from its own counter does not know or care.

The setup obligation is where data is lost. A receiver samples SDA at the SCL rising edge. If SDA is still climbing through the undefined region at that instant, the sampled value depends on where the threshold happens to sit for that device, at that temperature, at that supply voltage.

When does the line become valid, relative to the sampling edge?

8 cycles
A conceptual eight-cycle waveform. SCL rises at cycle four. With a correctly sized pull-up, SDA reaches a valid high at cycle two, two cycles before the sampling edge. With a weak pull-up, SDA only reaches a valid high at cycle five, one cycle after the sampling edge, so the sample at cycle four is taken during the transition.sized: validsized: validweak: not yetweak: notyetSCL rises: the sampling instantSCL rises: the samplinginstantSCLSDA Rp sizedSDA Rp weakt0t1t2t3t4t5t6t7
A digital waveform cannot draw an RC ramp, and this one does not try. The real line does not step from 0 to 1 — it climbs through an undefined band, and 'not valid yet' means the sample lands inside that band. RTL simulation cannot produce this picture at all, which is Chapter 19.7's subject.
Figure 2 — CONCEPTUAL, not simulated. The same bit with two pull-up values, drawn as the one thing a digital waveform can honestly show: WHEN each line reaches a valid HIGH, relative to the sampling edge. With a sized resistor SDA is valid two cycles before SCL rises. With a weak resistor it becomes valid one cycle after — so the sample at the rising edge is taken while the line is still in transition, and its value is decided by the receiver's threshold rather than by the transmitter.

The consequence is a fault that tracks temperature, supply and which device is transmitting, and that disappears when a scope probe adds its own capacitance — or, worse, when someone slows the bus down to debug it, since halving the clock relieves the period obligation and can mask the setup one.

6. So What Is the Internal Pull-Up For?

It is a real feature with real uses, none of which is a bus.

Keeping an unused input from floating. A CMOS input left floating draws current and picks up noise. A weak pull-up answers that completely, and nothing about it needs to be fast.

Defaulting a configuration or strap pin. Read once at power-on, microseconds available, no edge rate requirement.

Holding a reset or interrupt line idle where the timing requirement is "eventually".

What those share is that nothing measures the rising edge. The moment an edge rate enters a timing budget — which for I²C is immediately, and twice — a weak pull-up is the wrong component.

7. Working a Real Choice

The method, in the order the quantities become known:

1. Count the capacitance, do not assume it. Sum every device's pin capacitance from its datasheet, add the trace, add every connector. If a daughter board can be attached, add its contribution too — and note that Cb then becomes a function of what is plugged in.

2. Take tr(max) from the speed you actually need, not the fastest the parts support.

3. Compute the ceiling. Rp(max) = tr(max) / (0.8473 · Cb).

4. Compute the floor from the weakest sink on the bus: Rp(min) = (VDD − VOL(max)) / IOL(max). The weakest device sets this, not the FPGA.

5. Check the window is not empty. If Rp(min) > Rp(max) there is no legal resistor, and the fix is architectural — fewer devices, a shorter bus, a slower mode, a bus buffer, or splitting the segment. Chapter 11.9 reaches exactly this outcome and calls it result 3.

6. Choose inside the window with margin at both ends, then measure the edge on hardware. The arithmetic assumes a single lumped RC; a real board is neither single nor lumped.

7. Leave the FPGA's internal pull-up disabled unless you are deliberately using it for step 4 of bring-up.

8. ASIC Contrast, Briefly

The arithmetic is identical; the authority differs. An ASIC I/O ring can include a genuine open-drain cell with a specified IOL at a specified VOL, so step 4's floor is a number you own rather than one you look up per family. Some ASIC pad libraries also offer a controlled on-chip pull-up characterised well enough to appear in a budget — which is a different proposition from an FPGA's weak pull-up, and the difference is characterisation, not topology.

What does not change is that Cb lives on the board. No amount of on-chip capability makes the bus capacitance smaller.

9. Misconceptions

10. Debugging

The bus works on the evaluation board and fails with the sensor module fitted

Pitfall — internal pull-ups enabled in the constraints file, and no external resistors fitted
Buggy Code
# The FPGA constraints for an I2C bus, on a board whose pull-up footprints were
# left unpopulated because "the FPGA can do it":
#
#   set_property PULLUP true   [get_ports sda_pin]
#   set_property PULLUP true   [get_ports scl_pin]
#
# (Property names are vendor-specific; the shape is what matters.) The bus was
# configured for Fast mode, 400 kHz, because the sensor supports it.
#
# The reasoning was: the pins need to idle high, the FPGA can make them idle high,
# so the resistors are redundant and the BOM gets two fewer parts.
#
# What the reasoning leaves out is that the specification does not constrain the
# idle LEVEL. It constrains the RISE TIME -- and it does so twice, once in the
# clock period and once in the low phase where data must settle before the next
# rising edge (Chapter 11.9).
#
# Effective internal pull-up for this family and I/O bank: roughly 20 kilohm.
# Measured bus capacitance, FPGA board alone:            about  55 pF
# Measured bus capacitance, with the sensor module:      about 140 pF
Symptom

On the FPGA board alone, with a single on-board EEPROM: every transfer succeeds. Thousands of transfers, no errors, at 400 kHz. This is what made the design pass review.

With the sensor module fitted through its connector: roughly one transfer in twenty fails. The failures are not clustered on a particular register or a particular device, and they move when the lab temperature changes. Reading the same register in a tight loop gives occasional wrong values rather than errors -- data corruption, not NACKs.

Two observations made during debugging pointed the wrong way and cost a day:

- attaching a scope probe to SDA made the failures MORE frequent, which looked like the probe was injecting noise; - reducing the clock to 100 kHz made them stop, which looked like a timing margin problem in the controller.

A scope on SDA, triggered on SCL's rising edge, shows the actual fault: SDA is still climbing through the middle of its swing when SCL rises. The rising edge is a visible exponential curve about 1.2 microseconds long, not an edge.

Root Cause

tr = 0.8473 * Rp * Cb, and with a 20 kilohm internal pull-up:

board alone, 55 pF -> 0.8473 * 20e3 * 55e-12 = 932 ns with the module, 140 pF -> 0.8473 * 20e3 * 140e-12 = 2372 ns

Against a Fast-mode limit of 300 ns, BOTH configurations are illegal -- the board alone is 3.1x over. It passed anyway because nothing sampled inside the undefined band often enough to notice: at 400 kHz the low phase is long enough that a 932 ns edge still settles before the next rising edge, most of the time, for those two devices' thresholds.

Fitting the module raised Cb by 2.5x, so tr rose by 2.5x to 2372 ns, and the edge no longer settles inside the low phase. Now the sampling instant lands mid-swing, and the sampled value is decided by each receiver's threshold -- hence wrong DATA rather than protocol errors, and hence the temperature dependence.

Both misleading observations are explained by the same equation:

- the scope probe ADDS capacitance, raising Cb and making tr worse. The probe was not injecting noise; it was joining the circuit. - lowering the clock lengthens the low phase, so the slow edge has time to settle before the next sampling instant. It masked the fault without fixing anything, and it is why "it works at 100 kHz" must never be read as evidence that the electricals are legal.

The fix is to fit external resistors. The window, from Section 3, at 140 pF and 3.3 V with a 3 mA sink: Rp(min) = 967 ohm, Rp(max) = 300e-9/(0.8473*140e-12) = 2529 ohm. A 1.8 kilohm pair sits comfortably inside it. The internal pull-ups must then be DISABLED, or they parallel with the fitted resistors and raise the sink current every device sees.

The evidence that would have caught this before the board was built is the arithmetic in Section 3 -- two multiplications, done at schematic review, with a Cb that included the connector.

11. Reason It Through

12. Questions

13. What This Chapter Settled

tr = 0.8473 · Rp · Cb, and both ends of Rp are constrained: the ceiling by the rise time the mode allows, the floor by the current the weakest device can sink. For Fast mode at 100 pF and 3.3 V that window is roughly 970 Ω to 3.5 kΩ, which is where the familiar 1.8 kΩ, 2.2 kΩ and 3.3 kΩ values come from.

An FPGA's internal weak pull-up is an order of magnitude outside that window. It is a genuine feature for holding unused inputs and strap pins, where nothing measures the edge — and on an I²C bus, two things measure the edge, twice each.

With the pull-up justified, the bus now has a real HIGH and a real rising edge, and that edge takes time. The next problem follows directly: those two lines are asynchronous to the FPGA's clock, and the edge that takes 250 ns to arrive may be sampled by a flip-flop at any point during it. Chapter 19.4 owns the argument Module 18 deliberately deferred — what a synchronizer protects, and what simulation can and cannot prove about it.

Continue learning

Related tutorials