I²C · Module 15
SMBus and PMBus — Stricter Profiles Built on I²C
SMBus uses I²C hardware and the same protocol, yet an I²C-compliant part can fail an SMBus system five separate ways. Covers the clock floor I²C does not have, the 35 ms stretch bound, absolute versus ratiometric thresholds, and why one 350 uA device collapses a bus to a few tens of picofarads.
The specification is unusually direct about how much SMBus and I²C have in common, and the sentence is worth reading twice because it is the source of all the trouble:
Nothing about the framing differs. Not the START, not the STOP, not the nine-bit byte, not the acknowledge, not the addressing. A capture of an SMBus transaction and a capture of an I²C transaction are the same picture.
And yet an I²C-compliant device can fail in an SMBus system five separate ways, none of which is a protocol difference. All five are limits — numbers where I²C either has no bound at all or has a looser one.
That is what makes this failure mode expensive. There is nothing to see on a protocol analyser, because nothing prohibited is happening.
1. Other Buses Built On These Two Wires
That last clause is the hopeful reading and it is true for I/O expanders. It is not true for anything with timing requirements or an unusual output stage, and §4.2 onwards is where the specification says so.
The five architectures §4 names, and what each adds:
| architecture | what it adds to I²C | §4 reference |
|---|---|---|
| CBUS | a third wire, DLEN, and no acknowledge bit | §4.1 |
| SMBus | an address resolution protocol, timeouts, tighter electricals | §4.2 |
| PMBus | a standard power-converter command set, over SMBus 1.1 | §4.3 |
| IPMI | a request/response protocol; physically I²C but write-only | §4.4 |
| ATCA | fault-tolerant thermal management over dual I²C buses | §4.5 |
| DDC | display identity and capabilities, at Standard-mode | §4.6 |
Two of those are worth a note before SMBus takes the rest of the chapter.
CBUS is the one that changes the frame. §4.1: "CBUS receivers can be connected to the Standard-mode I²C-bus. However, a third bus line called DLEN must then be connected and the acknowledge bit omitted." An extra wire and no ninth bit — which is why it gets its own reserved address, 0000 001X, "to which no I²C-bus compatible device responds". Chapter 6.3 listed that row; this is what it is for. It is also the reason Table 10 carries a tHD;DAT of 5.0 µs for CBUS compatible masters and nothing for anyone else.
IPMI is write-only, and says so. §4.4's bullet list includes "Physically I²C but write-only (master capable devices); hot swap not required". A bus that is physically I²C and gives up reads is the same trade Chapter 14.3 found in Ultra Fast-mode, arrived at from the software side instead of the electrical one.
2. What SMBus Actually Is
Two things there explain almost everything that follows.
The Address Resolution Protocol is the feature I²C most conspicuously lacks. Chapter 15.2 §2 established that I²C has no way to enumerate a bus — addresses are assigned by the board designer and the Device ID only confirms an identity you already expected. SMBus solves that in software, which is why hot-plug works there and does not here.
"The quickly decreasing power supply budget of portable equipment" is why the electricals were loosened downward. The original SMBus class was built around Smart Batteries, and a battery's I²C interface runs on the battery. That constraint produced the 350 µA sink current of §6, which is the single most consequential number in this chapter.
So SMBus is not a stricter I²C in every direction. It is tighter on timing and looser on drive, and the combination is what catches designs out.
3. The Clock Has A Floor
Look at the shape of the two ranges. Every I²C mode starts at 0 Hz. SMBus starts at 10 kHz.
I²C is a DC bus. There is no such thing as a clock that is too slow, because there is no lower bound on the clock at all — a master may stop mid-transfer and resume a second later, and Module 12 is built on a target doing exactly that to the master.
SMBus cannot allow that, because it has timeouts (§5), and a timeout and an unbounded clock are incompatible by construction. The 10 kHz floor is not a performance requirement; it is the consequence of having a timeout at all.
The practical failures this produces:
| situation | legal I²C? | legal SMBus? |
|---|---|---|
| a 5 kHz bus to save power | yes | no |
| a master that single-steps the clock for debug | yes | no |
| a bit-banged GPIO master at a few kHz | yes | no |
| a master interrupted mid-byte for 10 ms | yes | no |
| a 400 kHz Fast-mode bus | yes | no — above the ceiling |
Four of those five are things people do routinely, and a bit-banged master on a loaded CPU is the commonest of all. §9's checker treats the floor and the ceiling as two separate flags because they call for opposite fixes.
4. The Ceiling Is Lower, Too
100 kHz. That is Standard-mode and nothing above it.
So Chapter 14.1's Fast-mode, Fast-mode Plus and Chapter 14.2's Hs-mode are all outside SMBus, and a device that advertises Fast-mode capability is advertising something an SMBus system cannot use. The bus is not broken at 400 kHz — every I²C rule is satisfied — it is simply not an SMBus.
That combination, a floor and a lower ceiling, gives SMBus a clock window one decade wide where I²C's Standard-mode window is infinite at the bottom and the same at the top.
5. Clock Stretching Is Bounded
This is the one that most directly contradicts something established earlier in the curriculum.
Chapter 12.4 was built entirely around the first half of that: I²C places no bound on a stretch, so any timeout a master implements is a policy decision rather than a specification requirement, and a monitor that reports a long stretch as a protocol violation is claiming a rule nobody wrote.
SMBus writes the rule. 35 ms.
The same design decision is a policy in one profile and a requirement in the other, and the code is identical. Only the justification changes — and the justification is what a reviewer reads.
That is worth being precise about, because it is the sort of distinction that gets lost:
| I²C | SMBus | |
|---|---|---|
| Is there a stretch limit? | No | Yes, 35 ms |
| A master that times out at 35 ms is... | making a policy choice | conforming |
| A target that stretches for 50 ms is... | conforming | violating |
| A monitor flagging a 50 ms stretch is... | claiming a rule that does not exist | correct |
Which means a timeout implementation is portable and its documentation is not. The same 35_000 constant is a reasonable default on I²C and a requirement on SMBus, and only the comment beside it tells the next engineer which claim is being made.
6. The Thresholds Are Absolute, Not Ratiometric
Those two numbers are input thresholds — TTL's classic VIL(max) of 0.8 V and VIH(min) of 2.1 V — and getting that right is the whole of the analysis. They are not output levels, because on an open-drain bus nobody drives a high at all: the pull-up does, and it drives to VDD.
So the wire carries exactly two levels, and there are four checks rather than four levels:
the wire carries: HIGH = VDD (made by the pull-up)
LOW <= VOL(max) = 0.4 V (made by whoever pulls)
1. SMBus receiver sees HIGH = VDD, needs >= 2.1 V -> VDD >= 2.100 V <== BINDING
2. SMBus receiver sees LOW = 0.4 V, needs <= 0.8 V -> always satisfied
3. I2C receiver sees HIGH = VDD, needs >= 0.7 x VDD -> always satisfied
4. I2C receiver sees LOW = 0.4 V, needs <= 0.3 x VDD -> VDD >= 1.333 VOnly check 1 binds, and it binds on the SMBus side: an absolute 2.1 V threshold against a bus whose high level is whatever the pull-up's supply happens to be. The specification's 3.0 V is that 2.1 V plus roughly 0.9 V of margin for supply tolerance and for a VOL above 0.4 V under load.
Which is exactly what §4.2.1's phrasing means, and the phrasing is precise if you read it slowly. "If the I²C device is below 3.0 V" is about the I²C device's supply, because that supply sets the bus high level:
A 1.8 V I²C part pulls the bus up to 1.8 V. An SMBus receiver needs 2.1 V and never sees a high at all. The I²C part is behaving perfectly; the level it produces is simply below an absolute threshold.
And note what this is not. It is not a level-shifting problem in the usual sense — there is no 5 V device damaging a 1.8 V input. Both devices are within their absolute maximums and both are reading the same wire correctly by their own rules. The rules disagree.
7. Three Sink Currents, Three Pull-Up Floors
Here is where this chapter connects to Chapter 14.4, and the connection is sharper than the earlier chapters' numbers suggested.
Chapter 14.4 §2 established Equation 2: Rp(min) = (VDD − VOL(max)) / IOL. Three sink currents therefore give three floors, and at 3.3 V with VOL = 0.4 V:
| class | IOL | Rp(min) at 3.3 V |
|---|---|---|
| SMBus low power (1.0 / 1.1) | 350 µA | 8285 Ω |
| I²C-bus | 3 mA | 966 Ω |
| SMBus high power (2.0) | 4 mA | 725 Ω |
And the governing floor on a mixed bus is the largest of them — the weakest device — because a resistor small enough to be overcome by a 350 µA output stage does not become acceptable just because a 4 mA part is also present.
7a. The Specification's Own Claim, Checked
"SMBus 'high power' devices and I²C-bus devices will work together if the pull-up resistor is sized for 3 mA." That holds, and the reason is visible in the table: the I²C floor of 966 Ω is above the high-power floor of 725 Ω, so a resistor sized for I²C is already large enough for a 4 mA SMBus part. Sizing for the I²C device satisfies both.
Test 6 in §9 confirms it, and also confirms the converse the specification leaves implicit: the sentence is about the high power class only. The low-power class does not mix.
7b. What One 350 µA Device Does To A Bus
Run Equation 1 backwards from the low-power floor. At 3.3 V the floor is 8285 Ω, and Cb(max) = tr(max) / (0.8473 × Rp):
| mode | tr(max) | Cb permitted at 8285 Ω |
|---|---|---|
| Standard-mode | 1000 ns | 142 pF |
| Fast-mode | 300 ns | 42 pF |
Against I²C's own 400 pF allowance, and against the 1221 pF a 3 mA device tolerates in Standard-mode.
One SMBus low-power device on a bus caps the total capacitance at about 142 pF — roughly a third of what I²C permits, and about fourteen device pins' worth before a single centimetre of trace.
Which is the quantitative answer to a question that otherwise looks like folklore: why does a Smart Battery live on its own short bus? Because a 350 µA output stage forces an 8.3 kΩ pull-up, an 8.3 kΩ pull-up gives an RC rise that only a very small capacitance can fit inside 1 µs, and a laptop's main management bus has far more than 142 pF on it.
Test 7 in §9 walks that: a low-power part on 100 pF in Standard-mode fits; the same part on 200 pF does not, and the checker attributes the failure to the pull-up rather than to anything about speed.
8. PMBus Inherits The Weaker Class
Read that last sentence against §4.2.3, which puts 1.0 and 1.1 in the low power class.
A PMBus device is a 350 µA device. Nothing in the name says so, and the chain that establishes it runs through two separate sections.
So a PMBus part brings §7b's 142 pF ceiling with it. That is a significant constraint on a power-management bus, which in a real system is exactly the bus most likely to be long and heavily populated — a controller plus several point-of-load converters spread across a board.
§9's checker therefore treats has_pmbus as implying the low-power sink current, and test 9 asserts it, because the inference is two documents deep and easy to miss.
The other two architectures §4 describes are worth one line each, since a design may meet them:
ATCA (§4.5) requires "hardware and software to manage the dual I²C-buses", specifically "a buffered dual I²C-bus with rise time accelerators, and 3-state capability" — which is Chapter 14.4 §8's buffer and switched-pull-up remedies made mandatory rather than optional.
DDC (§4.6) "calls for compliance with the I²C-bus standard mode specification" — the least demanding profile in the chapter, and the reason a monitor's EDID can be read by almost anything.
9. The Two Profiles, Side By Side
The top box is the reason this is hard and the bottom box is the consequence. Everything a protocol analyser can see lives in the top box.
10. The Compliance Checker in Three Languages
The design takes a device population and a set of bus parameters and answers two questions separately: is this a legal I²C bus, and is it also a legal SMBus bus. Keeping them separate is the point — a bus can be the first and not the second, and the useful output is which limit the second one broke.
It also extends Chapter 14.4's solver rather than duplicating it: the same Equation 1 and Equation 2, with the sink current now selected by the weakest class present instead of by the speed mode.
// -----------------------------------------------------------------------------
// i2c_smbus_compliance.sv
// I2C / SMBus / PMBus dual-profile compliance checker (UM10204 4.2, 4.2.1,
// 4.2.2, 4.2.3, 4.3, and Chapter 14.4's Equations 1 and 2).
//
// Section 4.2.1 says the two protocols "are basically the same: A SMBus master is
// able to control I2C devices and vice versa at the protocol level." That sentence
// is true and it is the reason the failures are so hard to find: nothing about the
// framing, the addressing or the acknowledge differs. What differs is a handful of
// LIMITS, and a part can satisfy every one of I2C's and violate SMBus's.
//
// Five independent ways an I2C-compliant bus fails SMBus:
//
// 1. THE CLOCK HAS A FLOOR. "The SMBus clock is defined from 10 kHz to 100 kHz
// while I2C can be 0 Hz to..." -- I2C has no minimum at all, because it is a
// DC bus. An I2C bus at 5 kHz is perfectly legal and not SMBus compliant.
// 2. THE CLOCK HAS A LOWER CEILING. 100 kHz. A Fast-mode bus is out.
// 3. CLOCK STRETCHING IS BOUNDED. "There is no limit in the I2C-bus protocol as
// to how long this delay can be, whereas for a SMBus system, it would be
// limited to 35 ms." Chapter 12.4 established that an I2C timeout is a POLICY;
// in SMBus it is a REQUIREMENT, and that is the same fact seen from the other
// side.
// 4. THE THRESHOLDS ARE ABSOLUTE, NOT RATIOMETRIC. SMBus inputs are TTL:
// VIL(max) 0.8 V, VIH(min) 2.1 V. I2C inputs are 0.3/0.7 x VDD. On an
// open-drain bus nobody drives a HIGH -- the pull-up does, to VDD -- so the
// binding check is that VDD itself must clear the SMBus receiver's 2.1 V.
// A 1.8 V I2C part is behaving perfectly and produces a HIGH no SMBus device
// can see. Section 4.2.1's "not a problem if VDD > 3.0 V" is that 2.1 V plus
// margin for supply tolerance and for a VOL above 0.4 V under load.
// 5. THE SINK CURRENTS DIFFER THREE WAYS. Section 4.2.3: 350 uA for SMBus low
// power, 3 mA for I2C, 4 mA for SMBus high power, all at VOL = 0.4 V. Through
// Equation 2 those become three different pull-up FLOORS, and a mixed bus is
// governed by the weakest device on it. One 350 uA part forces a floor nearly
// nine times higher than I2C's, and Equation 1 then collapses the allowed
// capacitance by the same factor.
//
// And PMBus is not a separate electrical profile: 4.3 says "PMBus devices use the
// SMBus Version 1.1 plus extensions for transport", and 4.2.3 puts 1.0 and 1.1 in
// the LOW POWER class. So declaring a PMBus device declares a 350 uA sink.
// -----------------------------------------------------------------------------
module i2c_smbus_compliance #(
parameter int VOL_MV = 400 // VOL(max), the level the sink current is rated at
) (
input logic clk,
input logic rst_n,
input logic calc, // one pulse: evaluate the inputs below
input logic [13:0] vdd_mv, // bus supply, mV (sets the HIGH level)
input logic [10:0] cb_pf, // estimated bus capacitance, pF
input logic [11:0] fscl_khz, // intended clock, kHz
input logic [21:0] max_stretch_us, // longest stretch any target may take, us
// ---- the device population ---------------------------------------------
input logic has_i2c, // an ordinary I2C part, 3 mA
input logic has_smbus_lp, // SMBus 1.0/1.1 low power, 350 uA
input logic has_smbus_hp, // SMBus 2.0 high power, 4 mA
input logic has_pmbus, // PMBus: SMBus 1.1, therefore ALSO 350 uA
// ---- results -----------------------------------------------------------
output logic done,
output logic [15:0] weakest_iol_ua, // the sink current that sets the floor
output logic [19:0] rp_floor_ohm, // Equation 2 at that current
output logic [19:0] rp_ceil_ohm, // Equation 1 at the mode's tr and this Cb
output logic [15:0] cb_max_pf, // capacitance the floor permits
output logic pullup_ok, // a legal resistor exists for the population
output logic i2c_ok, // the bus is a legal I2C bus
output logic smbus_ok, // the bus is also a legal SMBus bus
output logic viol_fscl_low, // below SMBus's 10 kHz floor
output logic viol_fscl_high, // above SMBus's 100 kHz ceiling
output logic viol_stretch, // a stretch longer than 35 ms
output logic viol_levels, // VDD below the SMBus TTL VIH
output logic [2:0] fail_code // the highest-priority SMBus failure
);
// Section 4.2.1 and 4.2.2, as constants.
localparam [11:0] SMBUS_FSCL_MIN_KHZ = 12'd10;
localparam [11:0] SMBUS_FSCL_MAX_KHZ = 12'd100;
localparam [21:0] SMBUS_STRETCH_MAX_US = 22'd35000; // 35 ms
localparam [13:0] SMBUS_VIH_MV = 14'd2100; // TTL HIGH threshold
// Section 4.2.3, the three sink currents at VOL = 0.4 V.
localparam [15:0] IOL_SMBUS_LP = 16'd350;
localparam [15:0] IOL_I2C = 16'd3000;
localparam [15:0] IOL_SMBUS_HP = 16'd4000;
// Chapter 14.4's Equation 1 constant: 1000 / 0.8473, scaled by 1000.
localparam [31:0] K_RC = 32'd1180220;
localparam [2:0] F_OK = 3'd0,
F_FSCL_LOW = 3'd1,
F_FSCL_HIGH = 3'd2,
F_STRETCH = 3'd3,
F_LEVELS = 3'd4,
F_PULLUP = 3'd5;
// The rise-time allowance follows from the intended clock, because the mode
// does. Table 10: 1000 ns Standard, 300 ns Fast, 120 ns Fast-mode Plus.
function [15:0] tr_max_ns (input [11:0] f_khz);
if (f_khz <= 12'd100) tr_max_ns = 16'd1000;
else if (f_khz <= 12'd400) tr_max_ns = 16'd300;
else tr_max_ns = 16'd120;
endfunction
logic [31:0] floor_lp, floor_i2c, floor_hp, worst, ceil_v, num;
logic [15:0] worst_iol;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
done <= 1'b0;
weakest_iol_ua <= 16'd0;
rp_floor_ohm <= 20'd0;
rp_ceil_ohm <= 20'd0;
cb_max_pf <= 16'd0;
pullup_ok <= 1'b0;
i2c_ok <= 1'b0;
smbus_ok <= 1'b0;
viol_fscl_low <= 1'b0;
viol_fscl_high <= 1'b0;
viol_stretch <= 1'b0;
viol_levels <= 1'b0;
fail_code <= F_OK;
end else if (calc) begin
// ---- the floor is set by the WEAKEST device present ---------------
// Equation 2 per class; the governing value is the largest, because a
// resistor small enough to beat a 350 uA output stage does not exist
// just because a 4 mA part is also on the bus.
worst = 32'd0;
worst_iol = 16'd0;
if (vdd_mv > VOL_MV) begin
num = ({18'd0, vdd_mv} - VOL_MV) * 32'd1000; // mV -> uV
// PMBus rides on SMBus 1.1, which 4.2.3 places in the LOW POWER
// class, so it contributes the same 350 uA as an SMBus 1.0 part.
if (has_smbus_lp || has_pmbus) begin
floor_lp = num / {16'd0, IOL_SMBUS_LP};
if (floor_lp > worst) begin worst = floor_lp; worst_iol = IOL_SMBUS_LP; end
end
if (has_i2c) begin
floor_i2c = num / {16'd0, IOL_I2C};
if (floor_i2c > worst) begin worst = floor_i2c; worst_iol = IOL_I2C; end
end
if (has_smbus_hp) begin
floor_hp = num / {16'd0, IOL_SMBUS_HP};
if (floor_hp > worst) begin worst = floor_hp; worst_iol = IOL_SMBUS_HP; end
end
end
rp_floor_ohm <= (worst > 32'h000F_FFFF) ? 20'hFFFFF : worst[19:0];
weakest_iol_ua <= worst_iol;
// ---- Equation 1: the rise-time ceiling for this capacitance -------
if (cb_pf != 11'd0)
ceil_v = (K_RC * {16'd0, tr_max_ns(fscl_khz)}) / (32'd1000 * {21'd0, cb_pf});
else
ceil_v = 32'h000F_FFFF;
rp_ceil_ohm <= ceil_v[19:0];
// ---- and the capacitance that floor permits ----------------------
if (worst != 32'd0)
cb_max_pf <= (K_RC * {16'd0, tr_max_ns(fscl_khz)}) / (32'd1000 * worst);
else
cb_max_pf <= 16'd0;
pullup_ok <= (worst != 32'd0) && (worst <= ceil_v);
// ---- I2C legality -------------------------------------------------
// I2C has NO clock floor and no stretch bound, so only the electrical
// window can make a bus illegal as an I2C bus.
i2c_ok <= (worst != 32'd0) && (worst <= ceil_v);
// ---- SMBus legality, five independent checks ----------------------
viol_fscl_low <= (fscl_khz < SMBUS_FSCL_MIN_KHZ);
viol_fscl_high <= (fscl_khz > SMBUS_FSCL_MAX_KHZ);
viol_stretch <= (max_stretch_us > SMBUS_STRETCH_MAX_US);
viol_levels <= (vdd_mv < SMBUS_VIH_MV);
smbus_ok <= !(fscl_khz < SMBUS_FSCL_MIN_KHZ)
&& !(fscl_khz > SMBUS_FSCL_MAX_KHZ)
&& !(max_stretch_us > SMBUS_STRETCH_MAX_US)
&& !(vdd_mv < SMBUS_VIH_MV)
&& (worst != 32'd0) && (worst <= ceil_v);
// Priority order for the single reported cause. The clock floor comes
// first because it is the difference people are least aware of.
if (fscl_khz < SMBUS_FSCL_MIN_KHZ) fail_code <= F_FSCL_LOW;
else if (fscl_khz > SMBUS_FSCL_MAX_KHZ) fail_code <= F_FSCL_HIGH;
else if (max_stretch_us > SMBUS_STRETCH_MAX_US) fail_code <= F_STRETCH;
else if (vdd_mv < SMBUS_VIH_MV) fail_code <= F_LEVELS;
else if (worst == 32'd0 || worst > ceil_v) fail_code <= F_PULLUP;
else fail_code <= F_OK;
done <= 1'b1;
end else begin
done <= 1'b0;
end
end
endmodule `timescale 1ns/1ps
// -----------------------------------------------------------------------------
// i2c_smbus_compliance_tb.sv
// Independent oracle for i2c_smbus_compliance.
//
// The bench recomputes every floor and ceiling with its own integer arithmetic,
// spelled out, and never calls the DUT's functions. Two checks are against the
// specification's own prose rather than against the implementation:
//
// * 4.2.3 states that SMBus high-power and I2C parts "will work together if the
// pull-up resistor is sized for 3 mA". Test 6 confirms the I2C floor is the
// governing one in that mixture, which is what makes the statement true.
// * 4.2.1's "not a problem if VDD > 3.0 V" is checked at 1.8 V, 2.1 V and 3.3 V
// in test 8, and the binding threshold is shown to be the SMBus TTL VIH.
// -----------------------------------------------------------------------------
module i2c_smbus_compliance_tb;
localparam [2:0] F_OK = 3'd0, F_FSCL_LOW = 3'd1, F_FSCL_HIGH = 3'd2,
F_STRETCH = 3'd3, F_LEVELS = 3'd4, F_PULLUP = 3'd5;
logic clk = 1'b0;
logic rst_n = 1'b0;
logic calc = 1'b0;
logic [13:0] vdd_mv = 14'd3300;
logic [10:0] cb_pf = 11'd100;
logic [11:0] fscl_khz = 12'd100;
logic [21:0] max_stretch_us = 22'd0;
logic has_i2c = 1'b1;
logic has_smbus_lp = 1'b0;
logic has_smbus_hp = 1'b0;
logic has_pmbus = 1'b0;
logic done, pullup_ok, i2c_ok, smbus_ok;
logic [15:0] weakest_iol_ua, cb_max_pf;
logic [19:0] rp_floor_ohm, rp_ceil_ohm;
logic viol_fscl_low, viol_fscl_high, viol_stretch, viol_levels;
logic [2:0] fail_code;
integer errors = 0;
i2c_smbus_compliance #(.VOL_MV(400)) dut (
.clk(clk), .rst_n(rst_n), .calc(calc),
.vdd_mv(vdd_mv), .cb_pf(cb_pf), .fscl_khz(fscl_khz),
.max_stretch_us(max_stretch_us),
.has_i2c(has_i2c), .has_smbus_lp(has_smbus_lp),
.has_smbus_hp(has_smbus_hp), .has_pmbus(has_pmbus),
.done(done), .weakest_iol_ua(weakest_iol_ua),
.rp_floor_ohm(rp_floor_ohm), .rp_ceil_ohm(rp_ceil_ohm),
.cb_max_pf(cb_max_pf), .pullup_ok(pullup_ok),
.i2c_ok(i2c_ok), .smbus_ok(smbus_ok),
.viol_fscl_low(viol_fscl_low), .viol_fscl_high(viol_fscl_high),
.viol_stretch(viol_stretch), .viol_levels(viol_levels),
.fail_code(fail_code));
always #5 clk = ~clk;
// The bench's own arithmetic.
function integer exp_floor (input integer vdd, input integer iol);
begin exp_floor = ((vdd - 400) * 1000) / iol; end
endfunction
function integer exp_ceil (input integer tr, input integer cb);
begin exp_ceil = (1180220 * tr) / (1000 * cb); end
endfunction
function integer exp_tr (input integer f_khz);
begin
if (f_khz <= 100) exp_tr = 1000;
else if (f_khz <= 400) exp_tr = 300;
else exp_tr = 120;
end
endfunction
task ck (input [200*8:1] what, input integer got, input integer exp);
begin
if (got !== exp) begin
$display(" FAIL %0s: got %0d expected %0d", what, got, exp);
errors = errors + 1;
end
end
endtask
task ck_bit (input [200*8:1] what, input got, input exp);
begin
if (got !== exp) begin
$display(" FAIL %0s: got %0b expected %0b", what, got, exp);
errors = errors + 1;
end
end
endtask
task check_bus (input integer vdd, input integer cb, input integer f_khz,
input integer stretch_us, input integer pop);
begin
@(negedge clk);
vdd_mv = vdd[13:0];
cb_pf = cb[10:0];
fscl_khz = f_khz[11:0];
max_stretch_us = stretch_us[21:0];
has_i2c = pop[0];
has_smbus_lp = pop[1];
has_smbus_hp = pop[2];
has_pmbus = pop[3];
calc = 1'b1;
@(posedge clk); @(negedge clk);
calc = 1'b0;
@(posedge clk); @(negedge clk);
end
endtask
initial begin
$display("=== i2c_smbus_compliance: same protocol, five different limits ===");
@(negedge clk); rst_n = 1'b0;
repeat (3) @(posedge clk);
@(negedge clk); rst_n = 1'b1;
@(posedge clk);
// ----------------------------------------------------------------
// T1. A plain Standard-mode I2C bus at 100 kHz, 3.3 V, 100 pF, one I2C
// part. Legal as both an I2C bus and an SMBus bus.
// ----------------------------------------------------------------
check_bus(3300, 100, 100, 0, 4'b0001);
$display("T1 a 100 kHz 3.3 V bus is legal under both profiles");
ck("T1 floor from 3 mA", rp_floor_ohm, exp_floor(3300, 3000));
ck("T1 the binding sink current", weakest_iol_ua, 3000);
ck("T1 ceiling", rp_ceil_ohm, exp_ceil(1000, 100));
ck_bit("T1 I2C ok", i2c_ok, 1'b1);
ck_bit("T1 SMBus ok", smbus_ok, 1'b1);
ck("T1 no failure", fail_code, F_OK);
// ----------------------------------------------------------------
// T2. THE CLOCK FLOOR. The same bus at 5 kHz. I2C has no minimum, so it
// is still a perfectly legal I2C bus. SMBus's floor is 10 kHz.
// ----------------------------------------------------------------
check_bus(3300, 100, 5, 0, 4'b0001);
$display("T2 5 kHz: legal I2C, illegal SMBus");
ck_bit("T2 still a legal I2C bus", i2c_ok, 1'b1);
ck_bit("T2 not SMBus", smbus_ok, 1'b0);
ck_bit("T2 clock floor violated", viol_fscl_low, 1'b1);
ck("T2 reported as the clock floor", fail_code, F_FSCL_LOW);
// and 0 Hz -- a stopped clock -- is also legal I2C. It is a DC bus.
check_bus(3300, 100, 0, 0, 4'b0001);
ck_bit("T2 a stopped clock is legal I2C", i2c_ok, 1'b1);
ck_bit("T2 a stopped clock is not SMBus", smbus_ok, 1'b0);
// ----------------------------------------------------------------
// T3. The boundary. 10 kHz exactly is compliant; 9 kHz is not.
// ----------------------------------------------------------------
check_bus(3300, 100, 10, 0, 4'b0001);
$display("T3 the 10 kHz floor is inclusive");
ck_bit("T3 10 kHz is SMBus compliant", smbus_ok, 1'b1);
check_bus(3300, 100, 9, 0, 4'b0001);
ck_bit("T3 9 kHz is not", smbus_ok, 1'b0);
// ----------------------------------------------------------------
// T4. THE CLOCK CEILING. A Fast-mode bus at 400 kHz is a legal I2C bus
// and exceeds SMBus's 100 kHz maximum.
// ----------------------------------------------------------------
check_bus(3300, 100, 400, 0, 4'b0001);
$display("T4 400 kHz: legal Fast-mode I2C, above the SMBus ceiling");
ck_bit("T4 legal I2C", i2c_ok, 1'b1);
ck_bit("T4 not SMBus", smbus_ok, 1'b0);
ck_bit("T4 ceiling violated", viol_fscl_high, 1'b1);
ck("T4 reported", fail_code, F_FSCL_HIGH);
// the rise-time allowance tightened with the mode, as Table 10 requires
ck("T4 ceiling now uses Fast-mode tr", rp_ceil_ohm, exp_ceil(300, 100));
// ----------------------------------------------------------------
// T5. THE STRETCH BOUND. Chapter 12.4's no-assumption rule, seen from the
// SMBus side. A 200 ms stretch is legal I2C -- there is no limit at
// all -- and four times SMBus's 35 ms.
// ----------------------------------------------------------------
check_bus(3300, 100, 100, 200000, 4'b0001);
$display("T5 a 200 ms stretch: unbounded in I2C, four times the SMBus limit");
ck_bit("T5 legal I2C", i2c_ok, 1'b1);
ck_bit("T5 not SMBus", smbus_ok, 1'b0);
ck_bit("T5 stretch violated", viol_stretch, 1'b1);
ck("T5 reported", fail_code, F_STRETCH);
// 35 ms exactly is allowed; one microsecond more is not.
check_bus(3300, 100, 100, 35000, 4'b0001);
ck_bit("T5 35 ms exactly is compliant", smbus_ok, 1'b1);
check_bus(3300, 100, 100, 35001, 4'b0001);
ck_bit("T5 35.001 ms is not", smbus_ok, 1'b0);
// ----------------------------------------------------------------
// T6. THE SPECIFICATION'S OWN CLAIM. 4.2.3: SMBus high-power and I2C
// parts "will work together if the pull-up resistor is sized for
// 3 mA". That holds because the I2C floor is the LARGER of the two,
// so sizing for it satisfies both.
// ----------------------------------------------------------------
check_bus(3300, 100, 100, 0, 4'b0101); // I2C + SMBus high power
$display("T6 4.2.3: sizing for 3 mA serves I2C and SMBus high power");
ck("T6 the I2C floor governs", weakest_iol_ua, 3000);
ck("T6 floor value", rp_floor_ohm, exp_floor(3300, 3000));
ck_bit("T6 both profiles ok", smbus_ok, 1'b1);
// proof it is the larger: the high-power floor alone is smaller
check_bus(3300, 100, 100, 0, 4'b0100); // SMBus high power alone
ck("T6 high power alone has a lower floor", rp_floor_ohm, exp_floor(3300, 4000));
if (exp_floor(3300, 4000) >= exp_floor(3300, 3000)) begin
$display(" FAIL T6 the 4 mA floor should be BELOW the 3 mA floor");
errors = errors + 1;
end
// ----------------------------------------------------------------
// T7. THE LOW-POWER CLASS IS THE ONE THAT DOES NOT MIX. A single 350 uA
// SMBus part forces a floor nearly nine times I2C's, and Equation 1
// then collapses the permitted capacitance to a few tens of pF.
// ----------------------------------------------------------------
check_bus(3300, 100, 100, 0, 4'b0011); // I2C + SMBus low power
$display("T7 one 350 uA part governs the whole bus");
ck("T7 the 350 uA floor governs", weakest_iol_ua, 350);
ck("T7 floor value", rp_floor_ohm, exp_floor(3300, 350));
ck("T7 permitted capacitance", cb_max_pf,
exp_ceil(1000, exp_floor(3300, 350)));
// At 100 pF in Standard-mode it still fits. Doubling the capacitance to
// 200 pF closes the window, and staying at 100 kHz keeps every OTHER SMBus
// limit satisfied so the pull-up is the only cause.
check_bus(3300, 200, 100, 0, 4'b0011);
ck("T7 the ceiling at 200 pF", rp_ceil_ohm, exp_ceil(1000, 200));
ck_bit("T7 no legal resistor", pullup_ok, 1'b0);
ck_bit("T7 not even a legal I2C bus", i2c_ok, 1'b0);
ck("T7 reported as the pull-up", fail_code, F_PULLUP);
// And at Fast-mode speed the SAME bus fails the clock ceiling too, which
// outranks the pull-up in the reported cause. Both flags stand; the single
// fail_code names the higher-priority one.
check_bus(3300, 200, 400, 0, 4'b0011);
ck_bit("T7 pull-up still empty", pullup_ok, 1'b0);
ck_bit("T7 and the clock ceiling", viol_fscl_high, 1'b1);
ck("T7 the clock ceiling is reported", fail_code, F_FSCL_HIGH);
// ----------------------------------------------------------------
// T8. THE LEVELS. 4.2.1's threshold, checked at three supplies. The
// binding value is the SMBus TTL VIH of 2.1 V, because the bus HIGH
// is whatever the pull-up's supply is.
// ----------------------------------------------------------------
check_bus(1800, 100, 100, 0, 4'b0001);
$display("T8 a 1.8 V bus cannot present a HIGH an SMBus input can see");
ck_bit("T8 1.8 V: still a legal I2C bus", i2c_ok, 1'b1);
ck_bit("T8 1.8 V: levels violated", viol_levels, 1'b1);
ck_bit("T8 1.8 V: not SMBus", smbus_ok, 1'b0);
ck("T8 reported as levels", fail_code, F_LEVELS);
check_bus(2100, 100, 100, 0, 4'b0001);
ck_bit("T8 2.1 V exactly clears the TTL threshold", viol_levels, 1'b0);
ck_bit("T8 2.1 V is SMBus compliant", smbus_ok, 1'b1);
check_bus(3300, 100, 100, 0, 4'b0001);
ck_bit("T8 3.3 V is comfortable", viol_levels, 1'b0);
// ----------------------------------------------------------------
// T9. PMBUS INHERITS THE LOW-POWER CLASS. 4.3 says PMBus uses SMBus 1.1
// for transport and 4.2.3 puts 1.1 in the low-power class, so a PMBus
// part contributes 350 uA -- the same floor as an SMBus 1.0 part, and
// nothing in the word "PMBus" says so.
// ----------------------------------------------------------------
check_bus(3300, 100, 100, 0, 4'b1000); // PMBus alone
$display("T9 a PMBus device is a 350 uA device");
ck("T9 PMBus contributes 350 uA", weakest_iol_ua, 350);
ck("T9 same floor as SMBus 1.0", rp_floor_ohm, exp_floor(3300, 350));
check_bus(3300, 100, 100, 0, 4'b1001); // PMBus + I2C
ck("T9 PMBus still governs against an I2C part", weakest_iol_ua, 350);
// ----------------------------------------------------------------
// T10. Multiple violations at once: 5 kHz, 1.8 V, a 100 ms stretch and a
// low-power part on 400 pF. Every flag must fire, and the single
// reported cause must be the documented highest priority.
// ----------------------------------------------------------------
check_bus(1800, 400, 5, 100000, 4'b0011);
$display("T10 four simultaneous violations, each flagged");
ck_bit("T10 clock floor", viol_fscl_low, 1'b1);
ck_bit("T10 stretch", viol_stretch, 1'b1);
ck_bit("T10 levels", viol_levels, 1'b1);
ck_bit("T10 pull-up", pullup_ok, 1'b0);
ck_bit("T10 not SMBus", smbus_ok, 1'b0);
ck("T10 the clock floor is reported first", fail_code, F_FSCL_LOW);
// ----------------------------------------------------------------
// T11. An empty population has no floor at all, and must not be reported
// as a compliant bus. A checker that returns "ok" for a bus with no
// devices is answering the wrong question.
// ----------------------------------------------------------------
check_bus(3300, 100, 100, 0, 4'b0000);
$display("T11 a bus with no devices is not a compliant bus");
ck("T11 no binding current", weakest_iol_ua, 0);
ck("T11 no floor", rp_floor_ohm, 0);
ck_bit("T11 no legal resistor", pullup_ok, 1'b0);
ck_bit("T11 not I2C ok", i2c_ok, 1'b0);
ck_bit("T11 not SMBus ok", smbus_ok, 1'b0);
ck("T11 reported as the pull-up", fail_code, F_PULLUP);
// ----------------------------------------------------------------
// T12. done is a single-cycle pulse, not a level.
// ----------------------------------------------------------------
@(negedge clk);
vdd_mv = 14'd3300; cb_pf = 11'd100; fscl_khz = 12'd100;
max_stretch_us = 22'd0; has_i2c = 1'b1;
has_smbus_lp = 1'b0; has_smbus_hp = 1'b0; has_pmbus = 1'b0;
calc = 1'b1;
@(posedge clk); @(negedge clk);
ck_bit("T12 done pulsed", done, 1'b1);
calc = 1'b0;
@(posedge clk); @(negedge clk);
ck_bit("T12 done cleared", done, 1'b0);
$display("T12 done is a pulse, not a level");
if (errors == 0)
$display("=== i2c_smbus_compliance: ALL CHECKS PASSED ===");
else
$display("=== i2c_smbus_compliance: %0d CHECK(S) FAILED ===", errors);
$finish;
end
endmodule // -----------------------------------------------------------------------------
// i2c_smbus_compliance.sv
// I2C / SMBus / PMBus dual-profile compliance checker (UM10204 4.2, 4.2.1,
// 4.2.2, 4.2.3, 4.3, and Chapter 14.4's Equations 1 and 2).
//
// Section 4.2.1 says the two protocols "are basically the same: A SMBus master is
// able to control I2C devices and vice versa at the protocol level." That sentence
// is true and it is the reason the failures are so hard to find: nothing about the
// framing, the addressing or the acknowledge differs. What differs is a handful of
// LIMITS, and a part can satisfy every one of I2C's and violate SMBus's.
//
// Five independent ways an I2C-compliant bus fails SMBus:
//
// 1. THE CLOCK HAS A FLOOR. "The SMBus clock is defined from 10 kHz to 100 kHz
// while I2C can be 0 Hz to..." -- I2C has no minimum at all, because it is a
// DC bus. An I2C bus at 5 kHz is perfectly legal and not SMBus compliant.
// 2. THE CLOCK HAS A LOWER CEILING. 100 kHz. A Fast-mode bus is out.
// 3. CLOCK STRETCHING IS BOUNDED. "There is no limit in the I2C-bus protocol as
// to how long this delay can be, whereas for a SMBus system, it would be
// limited to 35 ms." Chapter 12.4 established that an I2C timeout is a POLICY;
// in SMBus it is a REQUIREMENT, and that is the same fact seen from the other
// side.
// 4. THE THRESHOLDS ARE ABSOLUTE, NOT RATIOMETRIC. SMBus inputs are TTL:
// VIL(max) 0.8 V, VIH(min) 2.1 V. I2C inputs are 0.3/0.7 x VDD. On an
// open-drain bus nobody drives a HIGH -- the pull-up does, to VDD -- so the
// binding check is that VDD itself must clear the SMBus receiver's 2.1 V.
// A 1.8 V I2C part is behaving perfectly and produces a HIGH no SMBus device
// can see. Section 4.2.1's "not a problem if VDD > 3.0 V" is that 2.1 V plus
// margin for supply tolerance and for a VOL above 0.4 V under load.
// 5. THE SINK CURRENTS DIFFER THREE WAYS. Section 4.2.3: 350 uA for SMBus low
// power, 3 mA for I2C, 4 mA for SMBus high power, all at VOL = 0.4 V. Through
// Equation 2 those become three different pull-up FLOORS, and a mixed bus is
// governed by the weakest device on it. One 350 uA part forces a floor nearly
// nine times higher than I2C's, and Equation 1 then collapses the allowed
// capacitance by the same factor.
//
// And PMBus is not a separate electrical profile: 4.3 says "PMBus devices use the
// SMBus Version 1.1 plus extensions for transport", and 4.2.3 puts 1.0 and 1.1 in
// the LOW POWER class. So declaring a PMBus device declares a 350 uA sink.
// -----------------------------------------------------------------------------
// (Verilog-2001 -- structurally identical to the SystemVerilog above.)
module i2c_smbus_compliance #(
parameter VOL_MV = 400 // VOL(max), the level the sink current is rated at
) (
input wire clk,
input wire rst_n,
input wire calc, // one pulse: evaluate the inputs below
input wire [13:0] vdd_mv, // bus supply, mV (sets the HIGH level)
input wire [10:0] cb_pf, // estimated bus capacitance, pF
input wire [11:0] fscl_khz, // intended clock, kHz
input wire [21:0] max_stretch_us, // longest stretch any target may take, us
// ---- the device population ---------------------------------------------
input wire has_i2c, // an ordinary I2C part, 3 mA
input wire has_smbus_lp, // SMBus 1.0/1.1 low power, 350 uA
input wire has_smbus_hp, // SMBus 2.0 high power, 4 mA
input wire has_pmbus, // PMBus: SMBus 1.1, therefore ALSO 350 uA
// ---- results -----------------------------------------------------------
output reg done,
output reg [15:0] weakest_iol_ua, // the sink current that sets the floor
output reg [19:0] rp_floor_ohm, // Equation 2 at that current
output reg [19:0] rp_ceil_ohm, // Equation 1 at the mode's tr and this Cb
output reg [15:0] cb_max_pf, // capacitance the floor permits
output reg pullup_ok, // a legal resistor exists for the population
output reg i2c_ok, // the bus is a legal I2C bus
output reg smbus_ok, // the bus is also a legal SMBus bus
output reg viol_fscl_low, // below SMBus's 10 kHz floor
output reg viol_fscl_high, // above SMBus's 100 kHz ceiling
output reg viol_stretch, // a stretch longer than 35 ms
output reg viol_levels, // VDD below the SMBus TTL VIH
output reg [2:0] fail_code // the highest-priority SMBus failure
);
// Section 4.2.1 and 4.2.2, as constants.
localparam [11:0] SMBUS_FSCL_MIN_KHZ = 12'd10;
localparam [11:0] SMBUS_FSCL_MAX_KHZ = 12'd100;
localparam [21:0] SMBUS_STRETCH_MAX_US = 22'd35000; // 35 ms
localparam [13:0] SMBUS_VIH_MV = 14'd2100; // TTL HIGH threshold
// Section 4.2.3, the three sink currents at VOL = 0.4 V.
localparam [15:0] IOL_SMBUS_LP = 16'd350;
localparam [15:0] IOL_I2C = 16'd3000;
localparam [15:0] IOL_SMBUS_HP = 16'd4000;
// Chapter 14.4's Equation 1 constant: 1000 / 0.8473, scaled by 1000.
localparam [31:0] K_RC = 32'd1180220;
localparam [2:0] F_OK = 3'd0,
F_FSCL_LOW = 3'd1,
F_FSCL_HIGH = 3'd2,
F_STRETCH = 3'd3,
F_LEVELS = 3'd4,
F_PULLUP = 3'd5;
// The rise-time allowance follows from the intended clock, because the mode
// does. Table 10: 1000 ns Standard, 300 ns Fast, 120 ns Fast-mode Plus.
function [15:0] tr_max_ns (input [11:0] f_khz);
if (f_khz <= 12'd100) tr_max_ns = 16'd1000;
else if (f_khz <= 12'd400) tr_max_ns = 16'd300;
else tr_max_ns = 16'd120;
endfunction
reg [31:0] floor_lp, floor_i2c, floor_hp, worst, ceil_v, num;
reg [15:0] worst_iol;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
done <= 1'b0;
weakest_iol_ua <= 16'd0;
rp_floor_ohm <= 20'd0;
rp_ceil_ohm <= 20'd0;
cb_max_pf <= 16'd0;
pullup_ok <= 1'b0;
i2c_ok <= 1'b0;
smbus_ok <= 1'b0;
viol_fscl_low <= 1'b0;
viol_fscl_high <= 1'b0;
viol_stretch <= 1'b0;
viol_levels <= 1'b0;
fail_code <= F_OK;
end else if (calc) begin
// ---- the floor is set by the WEAKEST device present ---------------
// Equation 2 per class; the governing value is the largest, because a
// resistor small enough to beat a 350 uA output stage does not exist
// just because a 4 mA part is also on the bus.
worst = 32'd0;
worst_iol = 16'd0;
if (vdd_mv > VOL_MV) begin
num = ({18'd0, vdd_mv} - VOL_MV) * 32'd1000; // mV -> uV
// PMBus rides on SMBus 1.1, which 4.2.3 places in the LOW POWER
// class, so it contributes the same 350 uA as an SMBus 1.0 part.
if (has_smbus_lp || has_pmbus) begin
floor_lp = num / {16'd0, IOL_SMBUS_LP};
if (floor_lp > worst) begin worst = floor_lp; worst_iol = IOL_SMBUS_LP; end
end
if (has_i2c) begin
floor_i2c = num / {16'd0, IOL_I2C};
if (floor_i2c > worst) begin worst = floor_i2c; worst_iol = IOL_I2C; end
end
if (has_smbus_hp) begin
floor_hp = num / {16'd0, IOL_SMBUS_HP};
if (floor_hp > worst) begin worst = floor_hp; worst_iol = IOL_SMBUS_HP; end
end
end
rp_floor_ohm <= (worst > 32'h000F_FFFF) ? 20'hFFFFF : worst[19:0];
weakest_iol_ua <= worst_iol;
// ---- Equation 1: the rise-time ceiling for this capacitance -------
if (cb_pf != 11'd0)
ceil_v = (K_RC * {16'd0, tr_max_ns(fscl_khz)}) / (32'd1000 * {21'd0, cb_pf});
else
ceil_v = 32'h000F_FFFF;
rp_ceil_ohm <= ceil_v[19:0];
// ---- and the capacitance that floor permits ----------------------
if (worst != 32'd0)
cb_max_pf <= (K_RC * {16'd0, tr_max_ns(fscl_khz)}) / (32'd1000 * worst);
else
cb_max_pf <= 16'd0;
pullup_ok <= (worst != 32'd0) && (worst <= ceil_v);
// ---- I2C legality -------------------------------------------------
// I2C has NO clock floor and no stretch bound, so only the electrical
// window can make a bus illegal as an I2C bus.
i2c_ok <= (worst != 32'd0) && (worst <= ceil_v);
// ---- SMBus legality, five independent checks ----------------------
viol_fscl_low <= (fscl_khz < SMBUS_FSCL_MIN_KHZ);
viol_fscl_high <= (fscl_khz > SMBUS_FSCL_MAX_KHZ);
viol_stretch <= (max_stretch_us > SMBUS_STRETCH_MAX_US);
viol_levels <= (vdd_mv < SMBUS_VIH_MV);
smbus_ok <= !(fscl_khz < SMBUS_FSCL_MIN_KHZ)
&& !(fscl_khz > SMBUS_FSCL_MAX_KHZ)
&& !(max_stretch_us > SMBUS_STRETCH_MAX_US)
&& !(vdd_mv < SMBUS_VIH_MV)
&& (worst != 32'd0) && (worst <= ceil_v);
// Priority order for the single reported cause. The clock floor comes
// first because it is the difference people are least aware of.
if (fscl_khz < SMBUS_FSCL_MIN_KHZ) fail_code <= F_FSCL_LOW;
else if (fscl_khz > SMBUS_FSCL_MAX_KHZ) fail_code <= F_FSCL_HIGH;
else if (max_stretch_us > SMBUS_STRETCH_MAX_US) fail_code <= F_STRETCH;
else if (vdd_mv < SMBUS_VIH_MV) fail_code <= F_LEVELS;
else if (worst == 32'd0 || worst > ceil_v) fail_code <= F_PULLUP;
else fail_code <= F_OK;
done <= 1'b1;
end else begin
done <= 1'b0;
end
end
endmodule `timescale 1ns/1ps
// -----------------------------------------------------------------------------
// i2c_smbus_compliance_tb.sv
// Independent oracle for i2c_smbus_compliance.
//
// The bench recomputes every floor and ceiling with its own integer arithmetic,
// spelled out, and never calls the DUT's functions. Two checks are against the
// specification's own prose rather than against the implementation:
//
// * 4.2.3 states that SMBus high-power and I2C parts "will work together if the
// pull-up resistor is sized for 3 mA". Test 6 confirms the I2C floor is the
// governing one in that mixture, which is what makes the statement true.
// * 4.2.1's "not a problem if VDD > 3.0 V" is checked at 1.8 V, 2.1 V and 3.3 V
// in test 8, and the binding threshold is shown to be the SMBus TTL VIH.
// -----------------------------------------------------------------------------
// (Verilog-2001 -- structurally identical to the SystemVerilog above.)
module i2c_smbus_compliance_tb;
localparam [2:0] F_OK = 3'd0, F_FSCL_LOW = 3'd1, F_FSCL_HIGH = 3'd2,
F_STRETCH = 3'd3, F_LEVELS = 3'd4, F_PULLUP = 3'd5;
reg clk = 1'b0;
reg rst_n = 1'b0;
reg calc = 1'b0;
reg [13:0] vdd_mv = 14'd3300;
reg [10:0] cb_pf = 11'd100;
reg [11:0] fscl_khz = 12'd100;
reg [21:0] max_stretch_us = 22'd0;
reg has_i2c = 1'b1;
reg has_smbus_lp = 1'b0;
reg has_smbus_hp = 1'b0;
reg has_pmbus = 1'b0;
wire done, pullup_ok, i2c_ok, smbus_ok;
wire [15:0] weakest_iol_ua, cb_max_pf;
wire [19:0] rp_floor_ohm, rp_ceil_ohm;
wire viol_fscl_low, viol_fscl_high, viol_stretch, viol_levels;
wire [2:0] fail_code;
integer errors = 0;
i2c_smbus_compliance #(.VOL_MV(400)) dut (
.clk(clk), .rst_n(rst_n), .calc(calc),
.vdd_mv(vdd_mv), .cb_pf(cb_pf), .fscl_khz(fscl_khz),
.max_stretch_us(max_stretch_us),
.has_i2c(has_i2c), .has_smbus_lp(has_smbus_lp),
.has_smbus_hp(has_smbus_hp), .has_pmbus(has_pmbus),
.done(done), .weakest_iol_ua(weakest_iol_ua),
.rp_floor_ohm(rp_floor_ohm), .rp_ceil_ohm(rp_ceil_ohm),
.cb_max_pf(cb_max_pf), .pullup_ok(pullup_ok),
.i2c_ok(i2c_ok), .smbus_ok(smbus_ok),
.viol_fscl_low(viol_fscl_low), .viol_fscl_high(viol_fscl_high),
.viol_stretch(viol_stretch), .viol_levels(viol_levels),
.fail_code(fail_code));
always #5 clk = ~clk;
// The bench's own arithmetic.
function integer exp_floor (input integer vdd, input integer iol);
begin exp_floor = ((vdd - 400) * 1000) / iol; end
endfunction
function integer exp_ceil (input integer tr, input integer cb);
begin exp_ceil = (1180220 * tr) / (1000 * cb); end
endfunction
function integer exp_tr (input integer f_khz);
begin
if (f_khz <= 100) exp_tr = 1000;
else if (f_khz <= 400) exp_tr = 300;
else exp_tr = 120;
end
endfunction
task ck (input [200*8:1] what, input integer got, input integer exp);
begin
if (got !== exp) begin
$display(" FAIL %0s: got %0d expected %0d", what, got, exp);
errors = errors + 1;
end
end
endtask
task ck_bit (input [200*8:1] what, input got, input exp);
begin
if (got !== exp) begin
$display(" FAIL %0s: got %0b expected %0b", what, got, exp);
errors = errors + 1;
end
end
endtask
task check_bus (input integer vdd, input integer cb, input integer f_khz,
input integer stretch_us, input integer pop);
begin
@(negedge clk);
vdd_mv = vdd[13:0];
cb_pf = cb[10:0];
fscl_khz = f_khz[11:0];
max_stretch_us = stretch_us[21:0];
has_i2c = pop[0];
has_smbus_lp = pop[1];
has_smbus_hp = pop[2];
has_pmbus = pop[3];
calc = 1'b1;
@(posedge clk); @(negedge clk);
calc = 1'b0;
@(posedge clk); @(negedge clk);
end
endtask
initial begin
$display("=== i2c_smbus_compliance: same protocol, five different limits ===");
@(negedge clk); rst_n = 1'b0;
repeat (3) @(posedge clk);
@(negedge clk); rst_n = 1'b1;
@(posedge clk);
// ----------------------------------------------------------------
// T1. A plain Standard-mode I2C bus at 100 kHz, 3.3 V, 100 pF, one I2C
// part. Legal as both an I2C bus and an SMBus bus.
// ----------------------------------------------------------------
check_bus(3300, 100, 100, 0, 4'b0001);
$display("T1 a 100 kHz 3.3 V bus is legal under both profiles");
ck("T1 floor from 3 mA", rp_floor_ohm, exp_floor(3300, 3000));
ck("T1 the binding sink current", weakest_iol_ua, 3000);
ck("T1 ceiling", rp_ceil_ohm, exp_ceil(1000, 100));
ck_bit("T1 I2C ok", i2c_ok, 1'b1);
ck_bit("T1 SMBus ok", smbus_ok, 1'b1);
ck("T1 no failure", fail_code, F_OK);
// ----------------------------------------------------------------
// T2. THE CLOCK FLOOR. The same bus at 5 kHz. I2C has no minimum, so it
// is still a perfectly legal I2C bus. SMBus's floor is 10 kHz.
// ----------------------------------------------------------------
check_bus(3300, 100, 5, 0, 4'b0001);
$display("T2 5 kHz: legal I2C, illegal SMBus");
ck_bit("T2 still a legal I2C bus", i2c_ok, 1'b1);
ck_bit("T2 not SMBus", smbus_ok, 1'b0);
ck_bit("T2 clock floor violated", viol_fscl_low, 1'b1);
ck("T2 reported as the clock floor", fail_code, F_FSCL_LOW);
// and 0 Hz -- a stopped clock -- is also legal I2C. It is a DC bus.
check_bus(3300, 100, 0, 0, 4'b0001);
ck_bit("T2 a stopped clock is legal I2C", i2c_ok, 1'b1);
ck_bit("T2 a stopped clock is not SMBus", smbus_ok, 1'b0);
// ----------------------------------------------------------------
// T3. The boundary. 10 kHz exactly is compliant; 9 kHz is not.
// ----------------------------------------------------------------
check_bus(3300, 100, 10, 0, 4'b0001);
$display("T3 the 10 kHz floor is inclusive");
ck_bit("T3 10 kHz is SMBus compliant", smbus_ok, 1'b1);
check_bus(3300, 100, 9, 0, 4'b0001);
ck_bit("T3 9 kHz is not", smbus_ok, 1'b0);
// ----------------------------------------------------------------
// T4. THE CLOCK CEILING. A Fast-mode bus at 400 kHz is a legal I2C bus
// and exceeds SMBus's 100 kHz maximum.
// ----------------------------------------------------------------
check_bus(3300, 100, 400, 0, 4'b0001);
$display("T4 400 kHz: legal Fast-mode I2C, above the SMBus ceiling");
ck_bit("T4 legal I2C", i2c_ok, 1'b1);
ck_bit("T4 not SMBus", smbus_ok, 1'b0);
ck_bit("T4 ceiling violated", viol_fscl_high, 1'b1);
ck("T4 reported", fail_code, F_FSCL_HIGH);
// the rise-time allowance tightened with the mode, as Table 10 requires
ck("T4 ceiling now uses Fast-mode tr", rp_ceil_ohm, exp_ceil(300, 100));
// ----------------------------------------------------------------
// T5. THE STRETCH BOUND. Chapter 12.4's no-assumption rule, seen from the
// SMBus side. A 200 ms stretch is legal I2C -- there is no limit at
// all -- and four times SMBus's 35 ms.
// ----------------------------------------------------------------
check_bus(3300, 100, 100, 200000, 4'b0001);
$display("T5 a 200 ms stretch: unbounded in I2C, four times the SMBus limit");
ck_bit("T5 legal I2C", i2c_ok, 1'b1);
ck_bit("T5 not SMBus", smbus_ok, 1'b0);
ck_bit("T5 stretch violated", viol_stretch, 1'b1);
ck("T5 reported", fail_code, F_STRETCH);
// 35 ms exactly is allowed; one microsecond more is not.
check_bus(3300, 100, 100, 35000, 4'b0001);
ck_bit("T5 35 ms exactly is compliant", smbus_ok, 1'b1);
check_bus(3300, 100, 100, 35001, 4'b0001);
ck_bit("T5 35.001 ms is not", smbus_ok, 1'b0);
// ----------------------------------------------------------------
// T6. THE SPECIFICATION'S OWN CLAIM. 4.2.3: SMBus high-power and I2C
// parts "will work together if the pull-up resistor is sized for
// 3 mA". That holds because the I2C floor is the LARGER of the two,
// so sizing for it satisfies both.
// ----------------------------------------------------------------
check_bus(3300, 100, 100, 0, 4'b0101); // I2C + SMBus high power
$display("T6 4.2.3: sizing for 3 mA serves I2C and SMBus high power");
ck("T6 the I2C floor governs", weakest_iol_ua, 3000);
ck("T6 floor value", rp_floor_ohm, exp_floor(3300, 3000));
ck_bit("T6 both profiles ok", smbus_ok, 1'b1);
// proof it is the larger: the high-power floor alone is smaller
check_bus(3300, 100, 100, 0, 4'b0100); // SMBus high power alone
ck("T6 high power alone has a lower floor", rp_floor_ohm, exp_floor(3300, 4000));
if (exp_floor(3300, 4000) >= exp_floor(3300, 3000)) begin
$display(" FAIL T6 the 4 mA floor should be BELOW the 3 mA floor");
errors = errors + 1;
end
// ----------------------------------------------------------------
// T7. THE LOW-POWER CLASS IS THE ONE THAT DOES NOT MIX. A single 350 uA
// SMBus part forces a floor nearly nine times I2C's, and Equation 1
// then collapses the permitted capacitance to a few tens of pF.
// ----------------------------------------------------------------
check_bus(3300, 100, 100, 0, 4'b0011); // I2C + SMBus low power
$display("T7 one 350 uA part governs the whole bus");
ck("T7 the 350 uA floor governs", weakest_iol_ua, 350);
ck("T7 floor value", rp_floor_ohm, exp_floor(3300, 350));
ck("T7 permitted capacitance", cb_max_pf,
exp_ceil(1000, exp_floor(3300, 350)));
// At 100 pF in Standard-mode it still fits. Doubling the capacitance to
// 200 pF closes the window, and staying at 100 kHz keeps every OTHER SMBus
// limit satisfied so the pull-up is the only cause.
check_bus(3300, 200, 100, 0, 4'b0011);
ck("T7 the ceiling at 200 pF", rp_ceil_ohm, exp_ceil(1000, 200));
ck_bit("T7 no legal resistor", pullup_ok, 1'b0);
ck_bit("T7 not even a legal I2C bus", i2c_ok, 1'b0);
ck("T7 reported as the pull-up", fail_code, F_PULLUP);
// And at Fast-mode speed the SAME bus fails the clock ceiling too, which
// outranks the pull-up in the reported cause. Both flags stand; the single
// fail_code names the higher-priority one.
check_bus(3300, 200, 400, 0, 4'b0011);
ck_bit("T7 pull-up still empty", pullup_ok, 1'b0);
ck_bit("T7 and the clock ceiling", viol_fscl_high, 1'b1);
ck("T7 the clock ceiling is reported", fail_code, F_FSCL_HIGH);
// ----------------------------------------------------------------
// T8. THE LEVELS. 4.2.1's threshold, checked at three supplies. The
// binding value is the SMBus TTL VIH of 2.1 V, because the bus HIGH
// is whatever the pull-up's supply is.
// ----------------------------------------------------------------
check_bus(1800, 100, 100, 0, 4'b0001);
$display("T8 a 1.8 V bus cannot present a HIGH an SMBus input can see");
ck_bit("T8 1.8 V: still a legal I2C bus", i2c_ok, 1'b1);
ck_bit("T8 1.8 V: levels violated", viol_levels, 1'b1);
ck_bit("T8 1.8 V: not SMBus", smbus_ok, 1'b0);
ck("T8 reported as levels", fail_code, F_LEVELS);
check_bus(2100, 100, 100, 0, 4'b0001);
ck_bit("T8 2.1 V exactly clears the TTL threshold", viol_levels, 1'b0);
ck_bit("T8 2.1 V is SMBus compliant", smbus_ok, 1'b1);
check_bus(3300, 100, 100, 0, 4'b0001);
ck_bit("T8 3.3 V is comfortable", viol_levels, 1'b0);
// ----------------------------------------------------------------
// T9. PMBUS INHERITS THE LOW-POWER CLASS. 4.3 says PMBus uses SMBus 1.1
// for transport and 4.2.3 puts 1.1 in the low-power class, so a PMBus
// part contributes 350 uA -- the same floor as an SMBus 1.0 part, and
// nothing in the word "PMBus" says so.
// ----------------------------------------------------------------
check_bus(3300, 100, 100, 0, 4'b1000); // PMBus alone
$display("T9 a PMBus device is a 350 uA device");
ck("T9 PMBus contributes 350 uA", weakest_iol_ua, 350);
ck("T9 same floor as SMBus 1.0", rp_floor_ohm, exp_floor(3300, 350));
check_bus(3300, 100, 100, 0, 4'b1001); // PMBus + I2C
ck("T9 PMBus still governs against an I2C part", weakest_iol_ua, 350);
// ----------------------------------------------------------------
// T10. Multiple violations at once: 5 kHz, 1.8 V, a 100 ms stretch and a
// low-power part on 400 pF. Every flag must fire, and the single
// reported cause must be the documented highest priority.
// ----------------------------------------------------------------
check_bus(1800, 400, 5, 100000, 4'b0011);
$display("T10 four simultaneous violations, each flagged");
ck_bit("T10 clock floor", viol_fscl_low, 1'b1);
ck_bit("T10 stretch", viol_stretch, 1'b1);
ck_bit("T10 levels", viol_levels, 1'b1);
ck_bit("T10 pull-up", pullup_ok, 1'b0);
ck_bit("T10 not SMBus", smbus_ok, 1'b0);
ck("T10 the clock floor is reported first", fail_code, F_FSCL_LOW);
// ----------------------------------------------------------------
// T11. An empty population has no floor at all, and must not be reported
// as a compliant bus. A checker that returns "ok" for a bus with no
// devices is answering the wrong question.
// ----------------------------------------------------------------
check_bus(3300, 100, 100, 0, 4'b0000);
$display("T11 a bus with no devices is not a compliant bus");
ck("T11 no binding current", weakest_iol_ua, 0);
ck("T11 no floor", rp_floor_ohm, 0);
ck_bit("T11 no legal resistor", pullup_ok, 1'b0);
ck_bit("T11 not I2C ok", i2c_ok, 1'b0);
ck_bit("T11 not SMBus ok", smbus_ok, 1'b0);
ck("T11 reported as the pull-up", fail_code, F_PULLUP);
// ----------------------------------------------------------------
// T12. done is a single-cycle pulse, not a level.
// ----------------------------------------------------------------
@(negedge clk);
vdd_mv = 14'd3300; cb_pf = 11'd100; fscl_khz = 12'd100;
max_stretch_us = 22'd0; has_i2c = 1'b1;
has_smbus_lp = 1'b0; has_smbus_hp = 1'b0; has_pmbus = 1'b0;
calc = 1'b1;
@(posedge clk); @(negedge clk);
ck_bit("T12 done pulsed", done, 1'b1);
calc = 1'b0;
@(posedge clk); @(negedge clk);
ck_bit("T12 done cleared", done, 1'b0);
$display("T12 done is a pulse, not a level");
if (errors == 0)
$display("=== i2c_smbus_compliance: ALL CHECKS PASSED ===");
else
$display("=== i2c_smbus_compliance: %0d CHECK(S) FAILED ===", errors);
$finish;
end
endmodule -- ---------------------------------------------------------------------------
-- i2c_smbus_compliance.vhd
-- I2C / SMBus / PMBus dual-profile compliance checker (UM10204 4.2, 4.2.1,
-- 4.2.2, 4.2.3, 4.3, and Chapter 14.4's Equations 1 and 2).
-- Behavioural twin of i2c_smbus_compliance.sv / .v.
--
-- Section 4.2.1 says the two protocols "are basically the same: A SMBus master is
-- able to control I2C devices and vice versa at the protocol level." That is true,
-- and it is why the failures are hard to find: nothing about the framing, the
-- addressing or the acknowledge differs. What differs is a handful of LIMITS.
--
-- Five independent ways an I2C-compliant bus fails SMBus:
-- 1. THE CLOCK HAS A FLOOR. SMBus is 10 kHz to 100 kHz; I2C has no minimum at
-- all, because it is a DC bus. An I2C bus at 5 kHz is legal and not SMBus.
-- 2. THE CLOCK HAS A LOWER CEILING: 100 kHz. A Fast-mode bus is out.
-- 3. CLOCK STRETCHING IS BOUNDED. "There is no limit in the I2C-bus protocol as
-- to how long this delay can be, whereas for a SMBus system, it would be
-- limited to 35 ms." An I2C timeout is a POLICY; in SMBus it is a REQUIREMENT.
-- 4. THE THRESHOLDS ARE ABSOLUTE, NOT RATIOMETRIC. SMBus inputs are TTL: VIL
-- 0.8 V, VIH 2.1 V; I2C inputs are 0.3/0.7 x VDD. On an open-drain bus nobody
-- drives a HIGH -- the pull-up does, to VDD -- so the binding check is that
-- VDD itself must clear the SMBus receiver's 2.1 V.
-- 5. THE SINK CURRENTS DIFFER THREE WAYS: 350 uA low power, 3 mA I2C, 4 mA high
-- power, all at VOL = 0.4 V. Through Equation 2 those are three pull-up
-- FLOORS, and a mixed bus is governed by the weakest device on it.
--
-- And PMBus is not a separate electrical profile: 4.3 says PMBus uses "the SMBus
-- Version 1.1 plus extensions for transport", and 4.2.3 puts 1.0 and 1.1 in the
-- LOW POWER class. Declaring a PMBus device declares a 350 uA sink.
-- ---------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity i2c_smbus_compliance is
generic (
VOL_MV : integer := 400 -- VOL(max), the level the sink current is rated at
);
port (
clk : in std_logic;
rst_n : in std_logic;
calc : in std_logic; -- one pulse: evaluate the inputs
vdd_mv : in unsigned(13 downto 0); -- bus supply, mV (sets the HIGH)
cb_pf : in unsigned(10 downto 0); -- estimated bus capacitance, pF
fscl_khz : in unsigned(11 downto 0); -- intended clock, kHz
max_stretch_us : in unsigned(21 downto 0); -- longest stretch any target takes
-- the device population
has_i2c : in std_logic; -- an ordinary I2C part, 3 mA
has_smbus_lp : in std_logic; -- SMBus 1.0/1.1 low power, 350 uA
has_smbus_hp : in std_logic; -- SMBus 2.0 high power, 4 mA
has_pmbus : in std_logic; -- PMBus: SMBus 1.1, therefore ALSO 350 uA
-- results
done : out std_logic;
weakest_iol_ua : out unsigned(15 downto 0); -- the current that sets the floor
rp_floor_ohm : out unsigned(19 downto 0); -- Equation 2 at that current
rp_ceil_ohm : out unsigned(19 downto 0); -- Equation 1 at this Cb
cb_max_pf : out unsigned(15 downto 0); -- capacitance the floor permits
pullup_ok : out std_logic;
i2c_ok : out std_logic;
smbus_ok : out std_logic;
viol_fscl_low : out std_logic;
viol_fscl_high : out std_logic;
viol_stretch : out std_logic;
viol_levels : out std_logic;
fail_code : out unsigned(2 downto 0)
);
end entity i2c_smbus_compliance;
architecture rtl of i2c_smbus_compliance is
-- Sections 4.2.1 and 4.2.2, as constants.
constant SMBUS_FSCL_MIN_KHZ : integer := 10;
constant SMBUS_FSCL_MAX_KHZ : integer := 100;
constant SMBUS_STRETCH_MAX_US : integer := 35000; -- 35 ms
constant SMBUS_VIH_MV : integer := 2100; -- TTL HIGH threshold
-- Section 4.2.3, the three sink currents at VOL = 0.4 V.
constant IOL_SMBUS_LP : integer := 350;
constant IOL_I2C : integer := 3000;
constant IOL_SMBUS_HP : integer := 4000;
-- Chapter 14.4's Equation 1 constant: 1000 / 0.8473, scaled by 1000.
constant K_RC : integer := 1180220;
constant HUGE : integer := 1048575; -- 2**20 - 1
constant F_OK : integer := 0;
constant F_FSCL_LOW : integer := 1;
constant F_FSCL_HIGH : integer := 2;
constant F_STRETCH : integer := 3;
constant F_LEVELS : integer := 4;
constant F_PULLUP : integer := 5;
-- The rise-time allowance follows from the intended clock, because the mode
-- does. Table 10: 1000 ns Standard, 300 ns Fast, 120 ns Fast-mode Plus.
function tr_max_ns (f_khz : integer) return integer is
begin
if f_khz <= 100 then return 1000;
elsif f_khz <= 400 then return 300;
else return 120;
end if;
end function;
-- Saturating conversions. These matter for mutation testing as much as for
-- correctness: an out-of-range value into to_unsigned aborts the simulation,
-- which is indistinguishable from a tool failure. Clamping makes a bad mutant
-- produce a wrong NUMBER that the bench reports as a failed check.
function clamp16 (v : integer) return unsigned is
begin
if v > 65535 then return to_unsigned(65535, 16);
elsif v < 0 then return to_unsigned(0, 16);
else return to_unsigned(v, 16);
end if;
end function;
function clamp20 (v : integer) return unsigned is
begin
if v > HUGE then return to_unsigned(HUGE, 20);
elsif v < 0 then return to_unsigned(0, 20);
else return to_unsigned(v, 20);
end if;
end function;
begin
process (clk, rst_n)
variable num, worst, ceil_v : integer;
variable worst_iol : integer;
variable f_i, vdd_i, cb_i, str_i : integer;
variable fl : integer;
begin
if rst_n = '0' then
done <= '0';
weakest_iol_ua <= (others => '0');
rp_floor_ohm <= (others => '0');
rp_ceil_ohm <= (others => '0');
cb_max_pf <= (others => '0');
pullup_ok <= '0';
i2c_ok <= '0';
smbus_ok <= '0';
viol_fscl_low <= '0';
viol_fscl_high <= '0';
viol_stretch <= '0';
viol_levels <= '0';
fail_code <= to_unsigned(F_OK, 3);
elsif rising_edge(clk) then
if calc = '1' then
vdd_i := to_integer(vdd_mv);
cb_i := to_integer(cb_pf);
f_i := to_integer(fscl_khz);
str_i := to_integer(max_stretch_us);
-- ---- the floor is set by the WEAKEST device present -------------
-- Equation 2 per class; the governing value is the largest, because a
-- resistor small enough to beat a 350 uA output stage does not exist
-- just because a 4 mA part is also on the bus.
worst := 0;
worst_iol := 0;
if vdd_i > VOL_MV then
num := (vdd_i - VOL_MV) * 1000; -- mV -> uV
-- PMBus rides on SMBus 1.1, which 4.2.3 places in the LOW POWER
-- class, so it contributes the same 350 uA as an SMBus 1.0 part.
if has_smbus_lp = '1' or has_pmbus = '1' then
fl := num / IOL_SMBUS_LP;
if fl > worst then worst := fl; worst_iol := IOL_SMBUS_LP; end if;
end if;
if has_i2c = '1' then
fl := num / IOL_I2C;
if fl > worst then worst := fl; worst_iol := IOL_I2C; end if;
end if;
if has_smbus_hp = '1' then
fl := num / IOL_SMBUS_HP;
if fl > worst then worst := fl; worst_iol := IOL_SMBUS_HP; end if;
end if;
end if;
rp_floor_ohm <= clamp20(worst);
weakest_iol_ua <= clamp16(worst_iol);
-- ---- Equation 1: the rise-time ceiling for this capacitance -----
if cb_i /= 0 then
ceil_v := (K_RC * tr_max_ns(f_i)) / (1000 * cb_i);
else
ceil_v := HUGE;
end if;
rp_ceil_ohm <= clamp20(ceil_v);
-- ---- and the capacitance that floor permits --------------------
if worst /= 0 then
cb_max_pf <= clamp16((K_RC * tr_max_ns(f_i)) / (1000 * worst));
else
cb_max_pf <= (others => '0');
end if;
if worst /= 0 and worst <= ceil_v then
pullup_ok <= '1';
else
pullup_ok <= '0';
end if;
-- ---- I2C legality ----------------------------------------------
-- I2C has NO clock floor and no stretch bound, so only the electrical
-- window can make a bus illegal as an I2C bus.
if worst /= 0 and worst <= ceil_v then
i2c_ok <= '1';
else
i2c_ok <= '0';
end if;
-- ---- SMBus legality, five independent checks -------------------
if f_i < SMBUS_FSCL_MIN_KHZ then viol_fscl_low <= '1';
else viol_fscl_low <= '0'; end if;
if f_i > SMBUS_FSCL_MAX_KHZ then viol_fscl_high <= '1';
else viol_fscl_high <= '0'; end if;
if str_i > SMBUS_STRETCH_MAX_US then viol_stretch <= '1';
else viol_stretch <= '0'; end if;
if vdd_i < SMBUS_VIH_MV then viol_levels <= '1';
else viol_levels <= '0'; end if;
if f_i >= SMBUS_FSCL_MIN_KHZ and f_i <= SMBUS_FSCL_MAX_KHZ
and str_i <= SMBUS_STRETCH_MAX_US and vdd_i >= SMBUS_VIH_MV
and worst /= 0 and worst <= ceil_v then
smbus_ok <= '1';
else
smbus_ok <= '0';
end if;
-- Priority order for the single reported cause. The clock floor comes
-- first because it is the difference people are least aware of.
if f_i < SMBUS_FSCL_MIN_KHZ then fail_code <= to_unsigned(F_FSCL_LOW, 3);
elsif f_i > SMBUS_FSCL_MAX_KHZ then fail_code <= to_unsigned(F_FSCL_HIGH, 3);
elsif str_i > SMBUS_STRETCH_MAX_US then fail_code <= to_unsigned(F_STRETCH, 3);
elsif vdd_i < SMBUS_VIH_MV then fail_code <= to_unsigned(F_LEVELS, 3);
elsif worst = 0 or worst > ceil_v then fail_code <= to_unsigned(F_PULLUP, 3);
else fail_code <= to_unsigned(F_OK, 3);
end if;
done <= '1';
else
done <= '0';
end if;
end if;
end process;
end architecture rtl; -- ---------------------------------------------------------------------------
-- i2c_smbus_compliance_tb.vhd
-- Independent oracle for i2c_smbus_compliance. Behavioural twin of the
-- SystemVerilog and Verilog benches.
--
-- The bench recomputes every floor and ceiling with its own integer arithmetic and
-- never calls the DUT's functions. Two checks are against the specification's own
-- prose rather than against the implementation:
--
-- * 4.2.3 states that SMBus high-power and I2C parts "will work together if the
-- pull-up resistor is sized for 3 mA". Test 6 confirms the I2C floor is the
-- governing one in that mixture, which is what makes the statement true.
-- * 4.2.1's "not a problem if VDD > 3.0 V" is checked at 1.8 V, 2.1 V and 3.3 V
-- in test 8, and the binding threshold is shown to be the SMBus TTL VIH.
-- ---------------------------------------------------------------------------
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity i2c_smbus_compliance_tb is
end entity i2c_smbus_compliance_tb;
architecture sim of i2c_smbus_compliance_tb is
constant TCLK : time := 10 ns;
constant F_OK : integer := 0;
constant F_FSCL_LOW : integer := 1;
constant F_FSCL_HIGH : integer := 2;
constant F_STRETCH : integer := 3;
constant F_LEVELS : integer := 4;
constant F_PULLUP : integer := 5;
signal clk : std_logic := '0';
signal rst_n : std_logic := '0';
signal calc : std_logic := '0';
signal vdd_mv : unsigned(13 downto 0) := to_unsigned(3300, 14);
signal cb_pf : unsigned(10 downto 0) := to_unsigned(100, 11);
signal fscl_khz : unsigned(11 downto 0) := to_unsigned(100, 12);
signal max_stretch_us : unsigned(21 downto 0) := to_unsigned(0, 22);
signal has_i2c : std_logic := '1';
signal has_smbus_lp : std_logic := '0';
signal has_smbus_hp : std_logic := '0';
signal has_pmbus : std_logic := '0';
signal done, pullup_ok, i2c_ok, smbus_ok : std_logic;
signal weakest_iol_ua, cb_max_pf : unsigned(15 downto 0);
signal rp_floor_ohm, rp_ceil_ohm : unsigned(19 downto 0);
signal viol_fscl_low, viol_fscl_high, viol_stretch, viol_levels : std_logic;
signal fail_code : unsigned(2 downto 0);
signal halt : boolean := false;
begin
dut : entity work.i2c_smbus_compliance
generic map (VOL_MV => 400)
port map (
clk => clk, rst_n => rst_n, calc => calc,
vdd_mv => vdd_mv, cb_pf => cb_pf, fscl_khz => fscl_khz,
max_stretch_us => max_stretch_us,
has_i2c => has_i2c, has_smbus_lp => has_smbus_lp,
has_smbus_hp => has_smbus_hp, has_pmbus => has_pmbus,
done => done, weakest_iol_ua => weakest_iol_ua,
rp_floor_ohm => rp_floor_ohm, rp_ceil_ohm => rp_ceil_ohm,
cb_max_pf => cb_max_pf, pullup_ok => pullup_ok,
i2c_ok => i2c_ok, smbus_ok => smbus_ok,
viol_fscl_low => viol_fscl_low, viol_fscl_high => viol_fscl_high,
viol_stretch => viol_stretch, viol_levels => viol_levels,
fail_code => fail_code);
clkgen : process
begin
while not halt loop
clk <= '0'; wait for TCLK/2;
clk <= '1'; wait for TCLK/2;
end loop;
wait;
end process;
stim : process
variable err : integer := 0;
-- The bench's own arithmetic.
function exp_floor (vdd : integer; iol : integer) return integer is
begin return ((vdd - 400) * 1000) / iol; end function;
function exp_ceil (tr : integer; cb : integer) return integer is
begin return (1180220 * tr) / (1000 * cb); end function;
procedure ck (what : string; got : integer; exp : integer) is
begin
if got /= exp then
report " FAIL " & what & ": got " & integer'image(got)
& " expected " & integer'image(exp) severity note;
err := err + 1;
end if;
end procedure;
procedure ck_bit (what : string; got : std_logic; exp : std_logic) is
begin
if got /= exp then
report " FAIL " & what & ": got " & std_logic'image(got)
& " expected " & std_logic'image(exp) severity note;
err := err + 1;
end if;
end procedure;
procedure check_bus (vdd : integer; cb : integer; f_khz : integer;
stretch_us : integer; pop : std_logic_vector(3 downto 0)) is
begin
wait until falling_edge(clk);
vdd_mv <= to_unsigned(vdd, 14);
cb_pf <= to_unsigned(cb, 11);
fscl_khz <= to_unsigned(f_khz, 12);
max_stretch_us <= to_unsigned(stretch_us, 22);
has_i2c <= pop(0);
has_smbus_lp <= pop(1);
has_smbus_hp <= pop(2);
has_pmbus <= pop(3);
calc <= '1';
wait until rising_edge(clk); wait until falling_edge(clk);
calc <= '0';
wait until rising_edge(clk); wait until falling_edge(clk);
end procedure;
begin
report "=== i2c_smbus_compliance: same protocol, five different limits ==="
severity note;
wait until falling_edge(clk);
rst_n <= '0';
for k in 0 to 2 loop wait until rising_edge(clk); end loop;
wait until falling_edge(clk);
rst_n <= '1';
wait until rising_edge(clk);
-- T1. A plain Standard-mode bus: legal under both profiles.
check_bus(3300, 100, 100, 0, "0001");
report "T1 a 100 kHz 3.3 V bus is legal under both profiles" severity note;
ck("T1 floor from 3 mA", to_integer(rp_floor_ohm), exp_floor(3300, 3000));
ck("T1 the binding sink current", to_integer(weakest_iol_ua), 3000);
ck("T1 ceiling", to_integer(rp_ceil_ohm), exp_ceil(1000, 100));
ck_bit("T1 I2C ok", i2c_ok, '1');
ck_bit("T1 SMBus ok", smbus_ok, '1');
ck("T1 no failure", to_integer(fail_code), F_OK);
-- T2. THE CLOCK FLOOR. 5 kHz is legal I2C and illegal SMBus.
check_bus(3300, 100, 5, 0, "0001");
report "T2 5 kHz: legal I2C, illegal SMBus" severity note;
ck_bit("T2 still a legal I2C bus", i2c_ok, '1');
ck_bit("T2 not SMBus", smbus_ok, '0');
ck_bit("T2 clock floor violated", viol_fscl_low, '1');
ck("T2 reported as the clock floor", to_integer(fail_code), F_FSCL_LOW);
check_bus(3300, 100, 0, 0, "0001");
ck_bit("T2 a stopped clock is legal I2C", i2c_ok, '1');
ck_bit("T2 a stopped clock is not SMBus", smbus_ok, '0');
-- T3. The boundary: 10 kHz compliant, 9 kHz not.
check_bus(3300, 100, 10, 0, "0001");
report "T3 the 10 kHz floor is inclusive" severity note;
ck_bit("T3 10 kHz is SMBus compliant", smbus_ok, '1');
check_bus(3300, 100, 9, 0, "0001");
ck_bit("T3 9 kHz is not", smbus_ok, '0');
-- T4. THE CLOCK CEILING. 400 kHz is legal Fast-mode I2C.
check_bus(3300, 100, 400, 0, "0001");
report "T4 400 kHz: legal Fast-mode I2C, above the SMBus ceiling" severity note;
ck_bit("T4 legal I2C", i2c_ok, '1');
ck_bit("T4 not SMBus", smbus_ok, '0');
ck_bit("T4 ceiling violated", viol_fscl_high, '1');
ck("T4 reported", to_integer(fail_code), F_FSCL_HIGH);
ck("T4 ceiling now uses Fast-mode tr",
to_integer(rp_ceil_ohm), exp_ceil(300, 100));
-- T5. THE STRETCH BOUND: Chapter 12.4's rule from the SMBus side.
check_bus(3300, 100, 100, 200000, "0001");
report "T5 a 200 ms stretch: unbounded in I2C, four times the SMBus limit"
severity note;
ck_bit("T5 legal I2C", i2c_ok, '1');
ck_bit("T5 not SMBus", smbus_ok, '0');
ck_bit("T5 stretch violated", viol_stretch, '1');
ck("T5 reported", to_integer(fail_code), F_STRETCH);
check_bus(3300, 100, 100, 35000, "0001");
ck_bit("T5 35 ms exactly is compliant", smbus_ok, '1');
check_bus(3300, 100, 100, 35001, "0001");
ck_bit("T5 35.001 ms is not", smbus_ok, '0');
-- T6. 4.2.3's own claim: sizing for 3 mA serves I2C and SMBus high power.
check_bus(3300, 100, 100, 0, "0101");
report "T6 4.2.3: sizing for 3 mA serves I2C and SMBus high power" severity note;
ck("T6 the I2C floor governs", to_integer(weakest_iol_ua), 3000);
ck("T6 floor value", to_integer(rp_floor_ohm), exp_floor(3300, 3000));
ck_bit("T6 both profiles ok", smbus_ok, '1');
check_bus(3300, 100, 100, 0, "0100");
ck("T6 high power alone has a lower floor",
to_integer(rp_floor_ohm), exp_floor(3300, 4000));
if exp_floor(3300, 4000) >= exp_floor(3300, 3000) then
report " FAIL T6 the 4 mA floor should be BELOW the 3 mA floor" severity note;
err := err + 1;
end if;
-- T7. The LOW-POWER class is the one that does not mix.
check_bus(3300, 100, 100, 0, "0011");
report "T7 one 350 uA part governs the whole bus" severity note;
ck("T7 the 350 uA floor governs", to_integer(weakest_iol_ua), 350);
ck("T7 floor value", to_integer(rp_floor_ohm), exp_floor(3300, 350));
ck("T7 permitted capacitance",
to_integer(cb_max_pf), exp_ceil(1000, exp_floor(3300, 350)));
-- Doubling the capacitance to 200 pF closes the window; staying at 100 kHz
-- keeps every OTHER SMBus limit satisfied so the pull-up is the only cause.
check_bus(3300, 200, 100, 0, "0011");
ck("T7 the ceiling at 200 pF", to_integer(rp_ceil_ohm), exp_ceil(1000, 200));
ck_bit("T7 no legal resistor", pullup_ok, '0');
ck_bit("T7 not even a legal I2C bus", i2c_ok, '0');
ck("T7 reported as the pull-up", to_integer(fail_code), F_PULLUP);
-- At Fast-mode speed the SAME bus also fails the clock ceiling, which
-- outranks the pull-up in the reported cause.
check_bus(3300, 200, 400, 0, "0011");
ck_bit("T7 pull-up still empty", pullup_ok, '0');
ck_bit("T7 and the clock ceiling", viol_fscl_high, '1');
ck("T7 the clock ceiling is reported", to_integer(fail_code), F_FSCL_HIGH);
-- T8. THE LEVELS. The binding value is the SMBus TTL VIH of 2.1 V.
check_bus(1800, 100, 100, 0, "0001");
report "T8 a 1.8 V bus cannot present a HIGH an SMBus input can see"
severity note;
ck_bit("T8 1.8 V: still a legal I2C bus", i2c_ok, '1');
ck_bit("T8 1.8 V: levels violated", viol_levels, '1');
ck_bit("T8 1.8 V: not SMBus", smbus_ok, '0');
ck("T8 reported as levels", to_integer(fail_code), F_LEVELS);
check_bus(2100, 100, 100, 0, "0001");
ck_bit("T8 2.1 V exactly clears the TTL threshold", viol_levels, '0');
ck_bit("T8 2.1 V is SMBus compliant", smbus_ok, '1');
check_bus(3300, 100, 100, 0, "0001");
ck_bit("T8 3.3 V is comfortable", viol_levels, '0');
-- T9. PMBus inherits the low-power class.
check_bus(3300, 100, 100, 0, "1000");
report "T9 a PMBus device is a 350 uA device" severity note;
ck("T9 PMBus contributes 350 uA", to_integer(weakest_iol_ua), 350);
ck("T9 same floor as SMBus 1.0", to_integer(rp_floor_ohm), exp_floor(3300, 350));
check_bus(3300, 100, 100, 0, "1001");
ck("T9 PMBus still governs against an I2C part",
to_integer(weakest_iol_ua), 350);
-- T10. Multiple violations at once; the reported cause is the documented
-- highest priority.
check_bus(1800, 400, 5, 100000, "0011");
report "T10 four simultaneous violations, each flagged" severity note;
ck_bit("T10 clock floor", viol_fscl_low, '1');
ck_bit("T10 stretch", viol_stretch, '1');
ck_bit("T10 levels", viol_levels, '1');
ck_bit("T10 pull-up", pullup_ok, '0');
ck_bit("T10 not SMBus", smbus_ok, '0');
ck("T10 the clock floor is reported first",
to_integer(fail_code), F_FSCL_LOW);
-- T11. An empty population is not a compliant bus.
check_bus(3300, 100, 100, 0, "0000");
report "T11 a bus with no devices is not a compliant bus" severity note;
ck("T11 no binding current", to_integer(weakest_iol_ua), 0);
ck("T11 no floor", to_integer(rp_floor_ohm), 0);
ck_bit("T11 no legal resistor", pullup_ok, '0');
ck_bit("T11 not I2C ok", i2c_ok, '0');
ck_bit("T11 not SMBus ok", smbus_ok, '0');
ck("T11 reported as the pull-up", to_integer(fail_code), F_PULLUP);
-- T12. done is a single-cycle pulse.
wait until falling_edge(clk);
vdd_mv <= to_unsigned(3300, 14); cb_pf <= to_unsigned(100, 11);
fscl_khz <= to_unsigned(100, 12); max_stretch_us <= to_unsigned(0, 22);
has_i2c <= '1'; has_smbus_lp <= '0'; has_smbus_hp <= '0'; has_pmbus <= '0';
calc <= '1';
wait until rising_edge(clk); wait until falling_edge(clk);
ck_bit("T12 done pulsed", done, '1');
calc <= '0';
wait until rising_edge(clk); wait until falling_edge(clk);
ck_bit("T12 done cleared", done, '0');
report "T12 done is a pulse, not a level" severity note;
if err = 0 then
report "=== i2c_smbus_compliance: ALL CHECKS PASSED ===" severity note;
else
report "=== i2c_smbus_compliance: " & integer'image(err)
& " CHECK(S) FAILED ===" severity note;
end if;
halt <= true;
wait;
end process;
end architecture sim;10a. Seven Decisions Worth Defending
i2c_ok and smbus_ok are separate outputs, and i2c_ok ignores the clock entirely. I²C has no clock floor and no stretch bound, so nothing about frequency or stretching can make a bus illegal as an I²C bus — only the electrical window can. Mutation Y1 gives I²C the 10 kHz floor and two checks fail, because test 2 asserts that a 5 kHz bus is still legal I²C.
The floor is the maximum over the population, not the minimum. The weakest device governs. Written as a running maximum so adding a class cannot accidentally lower the floor. Mutation Y7 inverts one of the comparisons and test 7 catches it — see §11 for why a first attempt at that mutation was provably equivalent.
PMBus is folded into the low-power class in one place, with the citation. if (has_smbus_lp || has_pmbus) is the entire implementation of a two-document inference, and mutation Y8 removes the || has_pmbus to confirm something depends on it.
The level check compares VDD against the SMBus VIH, not against a computed ratio. §6's derivation shows only that one check binds, and implementing the other three would be arithmetic that can never fail. A checker that computes all four and reports the first failure would be reporting an ordering rather than a physics.
Five violation flags plus one fail_code. All five conditions are evaluated and reported individually, and fail_code names the highest-priority one for a caller that wants a single answer. Test 10 drives four simultaneous violations and asserts that every flag fires and that the priority is the documented one — mutation Y9 reorders the priority and is killed.
An empty population is not compliant. A checker asked about a bus with no devices must not answer "fine". The worst != 0 guard appears in pullup_ok, i2c_ok and smbus_ok independently, and mutation Y10 removed it from just one of them — which survived the first run, because no test checked that one output. §11.
The rise-time allowance follows the intended clock. A bus configured for 400 kHz is a Fast-mode bus and gets Fast-mode's 300 ns, which tightens the ceiling and can close a window that was open at 100 kHz. Mutation Y11 makes every bus Standard-mode and one check fails.
10b. Verified Execution
$ iverilog -g2012 -o d i2c_smbus_compliance.sv i2c_smbus_compliance_tb.sv && ./d
=== i2c_smbus_compliance: same protocol, five different limits ===
T1 a 100 kHz 3.3 V bus is legal under both profiles
T2 5 kHz: legal I2C, illegal SMBus
T3 the 10 kHz floor is inclusive
T4 400 kHz: legal Fast-mode I2C, above the SMBus ceiling
T5 a 200 ms stretch: unbounded in I2C, four times the SMBus limit
T6 4.2.3: sizing for 3 mA serves I2C and SMBus high power
T7 one 350 uA part governs the whole bus
T8 a 1.8 V bus cannot present a HIGH an SMBus input can see
T9 a PMBus device is a 350 uA device
T10 four simultaneous violations, each flagged
T11 a bus with no devices is not a compliant bus
T12 done is a pulse, not a level
=== i2c_smbus_compliance: ALL CHECKS PASSED ===
i2c_smbus_compliance_tb.sv:306: $finish called at 700000 (1ps)
$ iverilog -g2005 -o v i2c_smbus_compliance.v i2c_smbus_compliance_tb.v && ./v
=== i2c_smbus_compliance: same protocol, five different limits ===
T1 a 100 kHz 3.3 V bus is legal under both profiles
T2 5 kHz: legal I2C, illegal SMBus
T3 the 10 kHz floor is inclusive
T4 400 kHz: legal Fast-mode I2C, above the SMBus ceiling
T5 a 200 ms stretch: unbounded in I2C, four times the SMBus limit
T6 4.2.3: sizing for 3 mA serves I2C and SMBus high power
T7 one 350 uA part governs the whole bus
T8 a 1.8 V bus cannot present a HIGH an SMBus input can see
T9 a PMBus device is a 350 uA device
T10 four simultaneous violations, each flagged
T11 a bus with no devices is not a compliant bus
T12 done is a pulse, not a level
=== i2c_smbus_compliance: ALL CHECKS PASSED ===
i2c_smbus_compliance_tb.v:307: $finish called at 700000 (1ps)
$ nvc --std=2008 -a i2c_smbus_compliance.vhd i2c_smbus_compliance_tb.vhd
$ nvc --std=2008 -e i2c_smbus_compliance_tb && nvc --std=2008 -r i2c_smbus_compliance_tb --stop-time=500us
** Note: 0ms+0: === i2c_smbus_compliance: same protocol, five different limits ===
Process :i2c_smbus_compliance_tb:stim at i2c_smbus_compliance_tb.vhd:82
** Note: 70ns+1: T1 a 100 kHz 3.3 V bus is legal under both profiles
Process :i2c_smbus_compliance_tb:stim at i2c_smbus_compliance_tb.vhd:82
** Note: 100ns+1: T2 5 kHz: legal I2C, illegal SMBus
Process :i2c_smbus_compliance_tb:stim at i2c_smbus_compliance_tb.vhd:82
** Note: 160ns+1: T3 the 10 kHz floor is inclusive
Process :i2c_smbus_compliance_tb:stim at i2c_smbus_compliance_tb.vhd:82
** Note: 220ns+1: T4 400 kHz: legal Fast-mode I2C, above the SMBus ceiling
Process :i2c_smbus_compliance_tb:stim at i2c_smbus_compliance_tb.vhd:82
** Note: 250ns+1: T5 a 200 ms stretch: unbounded in I2C, four times the SMBus limit
Process :i2c_smbus_compliance_tb:stim at i2c_smbus_compliance_tb.vhd:82
** Note: 340ns+1: T6 4.2.3: sizing for 3 mA serves I2C and SMBus high power
Process :i2c_smbus_compliance_tb:stim at i2c_smbus_compliance_tb.vhd:82
** Note: 400ns+1: T7 one 350 uA part governs the whole bus
Process :i2c_smbus_compliance_tb:stim at i2c_smbus_compliance_tb.vhd:82
** Note: 490ns+1: T8 a 1.8 V bus cannot present a HIGH an SMBus input can see
Process :i2c_smbus_compliance_tb:stim at i2c_smbus_compliance_tb.vhd:82
** Note: 580ns+1: T9 a PMBus device is a 350 uA device
Process :i2c_smbus_compliance_tb:stim at i2c_smbus_compliance_tb.vhd:82
** Note: 640ns+1: T10 four simultaneous violations, each flagged
Process :i2c_smbus_compliance_tb:stim at i2c_smbus_compliance_tb.vhd:82
** Note: 670ns+1: T11 a bus with no devices is not a compliant bus
Process :i2c_smbus_compliance_tb:stim at i2c_smbus_compliance_tb.vhd:82
** Note: 700ns+1: T12 done is a pulse, not a level
Process :i2c_smbus_compliance_tb:stim at i2c_smbus_compliance_tb.vhd:82
** Note: 700ns+1: === i2c_smbus_compliance: ALL CHECKS PASSED ===
Process :i2c_smbus_compliance_tb:stim at i2c_smbus_compliance_tb.vhd:82All three at 700 ns — the shortest run in the module, because the checker is arithmetic with no protocol to sequence. Test 1 and test 6 are the two that matter most: the first establishes a bus legal under both profiles as a baseline, and the second reproduces §4.2.3's own claim about sizing for 3 mA.
10c. What The Testbench Proves
| # | bus | what it establishes |
|---|---|---|
| 1 | 100 kHz, 3.3 V, 100 pF, one I²C part | legal under both profiles |
| 2 | the same at 5 kHz, and at 0 Hz | legal I²C, illegal SMBus |
| 3 | 10 kHz, then 9 kHz | the floor is inclusive |
| 4 | 400 kHz | legal Fast-mode I²C, above the SMBus ceiling; tr tightens |
| 5 | a 200 ms stretch, then 35 ms, then 35.001 ms | unbounded in I²C; the bound is inclusive |
| 6 | I²C + SMBus high power | the I²C floor governs — §4.2.3's claim |
| 7 | I²C + SMBus low power, 100 pF then 200 pF | one 350 µA part governs; the window closes |
| 8 | 1.8 V, then 2.1 V, then 3.3 V | the binding threshold is the SMBus TTL VIH |
| 9 | PMBus alone, then PMBus + I²C | PMBus contributes 350 µA |
| 10 | four violations at once | every flag fires; the priority is the documented one |
| 11 | no devices at all | not a compliant bus, under either profile |
| 12 | back-to-back evaluations | done is a pulse, not a level |
Test 2 is the chapter's central asymmetry, measured. A 5 kHz bus and a stopped bus are both legal I²C and neither is SMBus. The stopped-clock case is the stronger half: 0 Hz is inside every I²C mode's range.
Test 3 and test 5's second halves test boundaries inclusively. 10 kHz passes and 9 kHz fails; 35 000 µs passes and 35 001 µs fails. A limit tested only well inside and well outside leaves the comparison operator unconstrained.
Test 6 checks the specification's sentence and then checks why it is true. It asserts the I²C floor governs in the mixture, and then evaluates the high-power class alone to confirm its floor is genuinely lower. Without the second half the first is a coincidence.
Test 7 is the Smart Battery result. A low-power part with 100 pF fits in Standard-mode; the same part with 200 pF has no legal resistor, and the reported cause is the pull-up rather than the clock. The follow-up at 400 kHz then shows both the pull-up and the clock ceiling failing, with the documented priority choosing between them.
Test 11 exists because a checker that answers "compliant" about an empty bus is answering the wrong question, and because one of its three guards was missing and no test had noticed. §11.
11. Mutation Testing
Eleven defects injected into the SystemVerilog checker.
| # | injected defect | outcome |
|---|---|---|
| Y1 | I²C given SMBus's 10 kHz clock floor | killed — test 2 |
| Y2 | SMBus clock floor 10 kHz → 1 kHz | killed — 6 checks |
| Y3 | SMBus clock ceiling 100 kHz → 400 kHz | killed — 5 checks |
| Y4 | stretch bound 35 ms → 350 ms | killed — 5 checks |
| Y5 | the SMBus VIL used in place of the VIH | killed — 4 checks |
| Y6 | low-power sink current 350 µA → 3.5 mA | killed — 11 checks |
| Y7 | the strongest device's floor taken, not the weakest | killed — test 7 |
| Y8 | PMBus no longer implies the low-power class | killed — test 9 |
| Y9 | the levels reported before the clock floor | killed — test 10 |
| Y10 | an empty population called compliant | killed — test 11 |
| Y11 | the mode ignored when sizing the rise-time ceiling | killed — test 11's ceiling |
Eleven of eleven, and two of them needed work before they were honest mutations.
Y10 was a coverage gap. The first version removed the worst != 0 guard from pullup_ok alone. It survived — because test 11 checked i2c_ok, smbus_ok and fail_code, each of which carries its own guard, and never checked pullup_ok. That is a bench hole rather than a design question, and the fix was one line: test 11 now asserts pullup_ok is low too.
Y7's first form was provably equivalent, and the proof is about evaluation order. The original mutation changed the low-power branch's test from floor_lp > worst to worst == 0. It survived, and the reason is that the low-power class is evaluated first, with worst still zero — so both conditions are true whenever a low-power part is present, and the 350 µA floor is the largest of the three, so no later branch can displace it.
A running-maximum loop whose largest candidate is evaluated first cannot distinguish "greater than the running value" from "the running value is empty". The mutation was unobservable by construction, not by omission.
The replacement inverts a comparison that genuinely discriminates — floor_i2c > worst becomes floor_i2c < worst, which on a low-power-plus-I²C bus lets the 966 Ω I²C floor displace the 8285 Ω low-power one, exactly the "take the strongest" error the mutation is named for. Test 7 kills it, and the equivalence is recorded in the suite with its proof.
Y6's eleven checks are worth contrasting with Y1's two. Changing the low-power sink current by a factor of ten breaks every floor, ceiling and verdict that depends on it, across four tests. Giving I²C a clock floor breaks exactly the two assertions that say I²C has no clock floor. Both are single-constant edits; the blast radius differs by a factor of five, and that is a property of the suite rather than of the mutations.
12. Verification Connection — Two Profiles, One Agent
An environment that must verify a device against both profiles faces a choice that looks like configuration and is really about what counts as a failure.
// The protocols are "basically the same", so ONE agent drives both profiles and
// the difference lives entirely in what the checkers consider legal. Building two
// agents would duplicate the framing logic and let the two copies drift.
//
// What must NOT be shared is the legality predicate, because a stimulus that is
// correct under one profile is a violation under the other -- and an environment
// that applies the stricter predicate to I2C stimulus fails on conforming traffic.
class i2c_profile_cfg extends uvm_object;
`uvm_object_utils(i2c_profile_cfg)
typedef enum { PROFILE_I2C, PROFILE_SMBUS } profile_e;
profile_e profile = PROFILE_I2C;
// Section 4.2.1 and 4.2.2. Zero and 'unbounded' are the I2C values, and they
// are not placeholders -- I2C genuinely has no clock floor and no stretch bound.
function int unsigned fscl_min_khz();
return (profile == PROFILE_SMBUS) ? 10 : 0;
endfunction
function int unsigned fscl_max_khz();
return (profile == PROFILE_SMBUS) ? 100 : 3400;
endfunction
// Returned as a 0 meaning 'no bound'. A caller that forgets to special-case
// zero would enforce an instant timeout, so the accessor is named to warn.
function int unsigned stretch_max_us_or_zero_if_unbounded();
return (profile == PROFILE_SMBUS) ? 35_000 : 0;
endfunction
function int unsigned vdd_min_mv();
// The binding check is the SMBus TTL VIH against the bus HIGH, which is VDD.
return (profile == PROFILE_SMBUS) ? 2100 : 0;
endfunction
function int unsigned iol_ua(bit low_power);
if (profile == PROFILE_I2C) return 3000;
return low_power ? 350 : 4000;
endfunction
endclass13. FPGA and ASIC Implications
Size the pull-up for the weakest device, and know which one that is. §7's three floors differ by more than an order of magnitude, and the governing one is set by whichever part has the lowest rated sink current — which may be a battery gauge nobody thought of as a constraint. A bus designed around a 3 mA assumption and then populated with a 350 µA part has a pull-up eight times too small for it.
A PMBus device is a 350 µA device. §8. The inference runs through two sections and is easy to miss, and the consequence is §7b's 142 pF.
SMBus's 10 kHz floor makes a bit-banged master risky. A GPIO-driven master on a preemptible CPU can be interrupted mid-transfer for milliseconds, which on I²C is legal and on SMBus trips a timeout. Either use a hardware I²C block or disable preemption around the transfer — and the second is a system-level commitment, not a driver detail.
The 35 ms bound is a constraint on the target, not only the master. §4.2.2's closing sentence — "Slave devices are not then allowed to hold the clock LOW too long" — means a design with a long internal operation cannot simply stretch through it on an SMBus bus. It must NACK and let the master retry, which changes the device's interface, not just its timing.
Below about 2.1 V, an open-drain bus cannot serve an SMBus input at all. §6. No amount of pull-up sizing fixes it, because the problem is the supply, and the remedy is a level translator rather than a resistor.
And 100 kHz is the ceiling. A design that wants SMBus compliance cannot also advertise Fast-mode operation on the same bus. It can support both modes and be SMBus-compliant in only one of them, which is worth stating in a datasheet explicitly rather than leaving a customer to discover.
14. Debugging — The Battery Gauge That Broke A Working Bus
A 3.3 V Standard-mode bus with six I²C devices works reliably with a 1 kΩ pull-up. A battery fuel gauge is added on a later board revision. After the change the gauge is unreadable — every transfer to it NACKs — and two of the six original devices begin failing intermittently. Removing the gauge restores the bus completely.
The gauge is an SMBus 1.1 part, which UM10204 4.2.3 places in the low-power class at 350 uA. Its output stage cannot sink the 2.9 mA a 1 kOhm pull-up at 3.3 V demands, so it pulls the line to 1.1 V and never produces a valid LOW -- the NACK the master sees is the gauge acknowledging and failing to be heard. The pull-up needs to be at least 8285 ohm for that part, roughly eight times its fitted value. The two other failures are a separate consequence: nothing was wrong with them at 1 kOhm, and they were only noticed once someone started looking, because the gauge's partial pull was raising the bus LOW level for everybody during its acknowledge slot.
Either move the gauge to its own bus segment behind a buffer, sized at 8.2 kOhm with the small capacitance that permits -- about 142 pF in Standard-mode -- or replace the gauge with an SMBus 2.0 high-power part, whose 4 mA sink is comfortably served by the existing 1 kOhm. Do not simply raise the main bus pull-up to 8.2 kOhm: Equation 1 then caps the whole bus at 142 pF, and a six-device bus with real trace length is already well past that.Three things generalise.
The gauge was acknowledging. It pulled the line as hard as it could and the result was not a logic low. "Not acknowledging" and "acknowledging inaudibly" look identical to a master and are completely different faults — and only a scope on the device pin separates them.
The failing part was the one that conformed to a different profile. Nothing was broken. An SMBus 1.1 part on an I²C-sized pull-up is a specification mismatch, and the specification that describes it is two sections away from the one that describes the bus.
The fix is a topology decision, not a component value. Raising the pull-up to suit the gauge breaks the capacitance budget for everyone else — §7b's 142 pF is the reason — so the gauge gets its own segment or the gauge gets replaced. That is the same conclusion Chapter 14.4 §8 reached about buffers, arrived at from a device class instead of from a trace length.
15. Common Misconceptions
"SMBus is a different protocol." §4.2.1: "basically the same… at the protocol level". The framing, addressing and acknowledge are identical. §1.
"An I²C-compliant part works on an SMBus bus." It may fail five ways, none of them a protocol rule. §3 through §7.
"SMBus is just I²C with timeouts." It also has a clock floor, a lower ceiling, absolute thresholds, and two sink-current classes one of which is weaker than I²C's.
"A slow bus is always safe." I²C has no clock minimum; SMBus's is 10 kHz, and below it SMBus devices may time out. §3.
"There is no limit on clock stretching." There is none in I²C. SMBus bounds it at 35 ms, and the same timeout code is a policy in one profile and a requirement in the other. §5.
"The 0.8 V and 2.1 V figures are output levels." They are TTL input thresholds. On an open-drain bus nobody drives a high — the pull-up does, to VDD — which is why the binding check is VDD ≥ 2.1 V. §6.
"SMBus devices drive harder than I²C devices." The high-power class does, at 4 mA. The low-power class sinks 350 µA, an order of magnitude less than I²C's 3 mA. §7.
"SMBus and I²C parts always mix if the resistor is sized for 3 mA." That is §4.2.3's claim about the high power class specifically. A low-power part needs roughly 8.3 kΩ at 3.3 V. §7a.
"PMBus is SMBus with extra commands." It is SMBus 1.1 with extra commands, and 1.1 is the low-power electrical class. §8.
"A NACK means the device did not respond." It may have responded and failed to pull the line to a valid low, which is what an underdriven output stage does. §14.
16. Reason It Through
A bus runs at 8 kHz to save power. Legal?
As I²C, yes — every mode's range starts at 0 Hz and there is no lower bound. As SMBus, no: below 10 kHz "the SMBus devices may time-out". The bus is not broken; it is not an SMBus. §3.
A target stretches SCL for 60 ms. Who is at fault?
On I²C, nobody — there is no limit, and a master that gave up is making a policy choice it should document. On SMBus the target is violating the 35 ms bound, and §4.2.2's closing sentence puts the obligation on the slave explicitly. Same waveform, two verdicts. §5.
A 1.8 V I²C device shares a bus with an SMBus device. What fails?
The bus high level is 1.8 V, set by the pull-up supply. The SMBus receiver's TTL VIH is 2.1 V, so it never sees a high. No resistor value fixes it; the supply is the problem and a level translator is the remedy. §6.
What pull-up does a 350 µA SMBus part need at 3.3 V, and what does that cost?
Rp(min) = (3300 − 400)/0.35 mA = 8285 Ω. Running Equation 1 backwards in Standard-mode, Cb(max) = 1000 ns / (0.8473 × 8285) = 142 pF. So the part forces an 8.3 kΩ pull-up and caps the whole segment at about 142 pF — a third of I²C's allowance. §7b.
Why does §4.2.3's "sized for 3 mA" claim hold for high-power parts and not low-power ones?
Because the I²C floor at 3.3 V is 966 Ω and the high-power floor is 725 Ω, so a resistor sized for I²C is already large enough for a 4 mA part — the I²C floor is the larger of the two and satisfying it satisfies both. The low-power floor is 8285 Ω, far above the I²C floor, so sizing for I²C leaves a 350 µA part unable to pull the line low at all. §7a.
A PMBus converter is added to a 400 pF bus. What breaks?
PMBus is SMBus 1.1, which is the low-power class at 350 µA, so the converter needs an 8.3 kΩ pull-up and permits about 142 pF. On 400 pF the window is empty: the floor exceeds the rise-time ceiling and no resistor satisfies both. The converter needs its own segment. §8.
Why should an I²C stretch-timeout assertion be disabled rather than given a very large bound?
Because a large bound still asserts that a rule exists. I²C places no limit, so any bound will eventually fire on conforming behaviour, and the resulting waiver teaches reviewers to ignore the checker. The honest structure is no assertion plus a coverpoint on the duration. §12.
17. Understanding Check
18. Summary
The protocols are the same and the limits are not. §4.2.1 says an SMBus master can control I²C devices and vice versa at the protocol level, and a capture cannot tell the two apart.
Five independent ways an I²C-compliant bus fails SMBus, and none of them is a protocol rule: the clock floor, the clock ceiling, the stretch bound, the input thresholds, and the sink current.
I²C has no clock floor. Every mode starts at 0 Hz because it is a DC bus. SMBus starts at 10 kHz, and that floor exists because SMBus has a timeout.
SMBus bounds clock stretching at 35 ms where Chapter 12.4 established that I²C bounds it not at all. The same timeout constant is a policy choice in one profile and a requirement in the other, and only the comment beside it says which.
SMBus thresholds are absolute, I²C's are ratiometric. The binding check is that VDD must clear the SMBus TTL VIH of 2.1 V, because the bus high level is VDD — which is what §4.2.1's "if the I²C device is below 3.0 V" is about.
Three sink currents, three pull-up floors, and the weakest device governs: 8285 Ω for a 350 µA part at 3.3 V against 966 Ω for I²C.
So one SMBus low-power device caps a bus at about 142 pF in Standard-mode — a third of I²C's allowance, and the quantitative reason a Smart Battery gets its own segment.
§4.2.3's "sized for 3 mA" claim is about the high-power class only, and it holds because the I²C floor is the larger of the two. The low-power class does not mix.
A PMBus device is a 350 µA device, by a chain that runs through two sections and is nowhere stated in one place.
And a NACK can be a device acknowledging inaudibly — pulling as hard as it can and not reaching a valid low, which is what an underdriven output stage does on an over-tight pull-up.
19. What Comes Next
Three chapters have been about features and profiles. Chapter 15.4 is about what to do when the bus has stopped working entirely.
The specification's answer is four sentences long, and the striking thing about it is that it says two different things about two different wires. For a data line held low there is a protocol remedy: nine clock pulses, within which the offending device should let go. For a clock line held low there is no protocol remedy at all — only a hardware reset, or cycling power to invoke the mandatory power-on reset.
That asymmetry is not an omission. The nine pulses are pulses on SCL, so a master cannot issue them on a line something else is holding down. The remedy that works for the line the master shares is structurally unavailable for the line the master owns — and a recovery block that does not distinguish the two cases will attempt the impossible one and report success.
Continue learning
Related tutorials
- Related topic
I²C Stretch Bounds, Timeouts and the No-Assumption Rule
The specification places no limit on how long a slave may hold the clock, so every timeout is a system policy rather than a compliance check. Includes the recovery asymmetry most engineers know only half of.
- Related topic
tr, tf and Cb — The I²C Electrical Envelope
The only parameters an RTL designer cannot control, and the only edge with a minimum as well as a maximum. Derives the pull-up sizing window and finds that Fast-mode at the maximum bus capacitance does not close with a resistor at all.
- Related topic
Choosing a Speed Mode — Pull-Ups, Capacitance and Design Cost
The pull-up resistor has one floor and two independent ceilings, and the interval between them is sometimes empty. Reproduces UM10204's own worked example, shows a Fast-mode bus at its own capacitance limit has no legal resistor, and explains why Fast-mode Plus is a 20 mA output stage rather than a faster one.
- Related topic
Acknowledge Polling and Device-Busy Behavior
The standard way to wait for a device that has stopped answering, and the three completely different situations it cannot tell apart. Explains why a polling loop must be bounded, why the bound is a policy decision rather than a conformance requirement, and why the honest output of a failed poll is that the cause is unknown.
