Skip to content
VLSI Mentor

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:

architecturewhat it adds to I²C§4 reference
CBUSa third wire, DLEN, and no acknowledge bit§4.1
SMBusan address resolution protocol, timeouts, tighter electricals§4.2
PMBusa standard power-converter command set, over SMBus 1.1§4.3
IPMIa request/response protocol; physically I²C but write-only§4.4
ATCAfault-tolerant thermal management over dual I²C buses§4.5
DDCdisplay 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:

situationlegal I²C?legal SMBus?
a 5 kHz bus to save poweryesno
a master that single-steps the clock for debugyesno
a bit-banged GPIO master at a few kHzyesno
a master interrupted mid-byte for 10 msyesno
a 400 kHz Fast-mode busyesno — 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²CSMBus
Is there a stretch limit?NoYes, 35 ms
A master that times out at 35 ms is...making a policy choiceconforming
A target that stretches for 50 ms is...conformingviolating
A monitor flagging a 50 ms stretch is...claiming a rule that does not existcorrect

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:

Azvya Education Pvt. Ltd.VLSI Mentor
where the 3.0 V figure comes from
   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 V

Only 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:

classIOLRp(min) at 3.3 V
SMBus low power (1.0 / 1.1)350 µA8285 Ω
I²C-bus3 mA966 Ω
SMBus high power (2.0)4 mA725 Ω

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):

modetr(max)Cb permitted at 8285 Ω
Standard-mode1000 ns142 pF
Fast-mode300 ns42 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

A four-row arrangement comparing the two profiles. The top row is the shared foundation: the same two wires, the same framing, the same addressing and the same acknowledge. Below it, two boxes side by side name the two profiles. Beneath those, five boxes give the five limits that differ between them: the clock floor, the clock ceiling, the clock stretch bound, the input thresholds, and the sink current. The bottom row states the consequence, that a part can satisfy every I2C limit and fail an SMBus system without violating any protocol rule.Identicalframing, addressing, ACKI2Cthe base specificationSMBusand PMBus over itclock floor0 Hz vs 10 kHzclock ceiling3.4 MHz vs 100 kHzstretch boundnone vs 35 msthresholdsratiometric vs absolutesink current3 mA vs 350 uA or 4 mAFive ways to failnone of them a protocolruleall five at once12

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.

Azvya Education Pvt. Ltd.VLSI Mentor
i2c_smbus_compliance.sv — five independent limits, none of which is a protocol difference
   // -----------------------------------------------------------------------------
   // 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
Azvya Education Pvt. Ltd.VLSI Mentor
i2c_smbus_compliance_tb.sv — twelve buses, each legal under one profile and not the other
   `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
Azvya Education Pvt. Ltd.VLSI Mentor
i2c_smbus_compliance.v — the same checker in Verilog-2001
   // -----------------------------------------------------------------------------
   // 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
Azvya Education Pvt. Ltd.VLSI Mentor
i2c_smbus_compliance_tb.v — the same twelve buses, independently
   `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
Azvya Education Pvt. Ltd.VLSI Mentor
i2c_smbus_compliance.vhd — the same checker in VHDL-2008
   -- ---------------------------------------------------------------------------
   -- 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;
Azvya Education Pvt. Ltd.VLSI Mentor
i2c_smbus_compliance_tb.vhd — the same twelve buses, with saturating conversions so a bad value fails rather than crashes
   -- ---------------------------------------------------------------------------
   -- 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

Azvya Education Pvt. Ltd.VLSI Mentor
terminal — three simulators, twelve buses, one finish time
   $ 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:82

All 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

#buswhat it establishes
1100 kHz, 3.3 V, 100 pF, one I²C partlegal under both profiles
2the same at 5 kHz, and at 0 Hzlegal I²C, illegal SMBus
310 kHz, then 9 kHzthe floor is inclusive
4400 kHzlegal Fast-mode I²C, above the SMBus ceiling; tr tightens
5a 200 ms stretch, then 35 ms, then 35.001 msunbounded in I²C; the bound is inclusive
6I²C + SMBus high powerthe I²C floor governs — §4.2.3's claim
7I²C + SMBus low power, 100 pF then 200 pFone 350 µA part governs; the window closes
81.8 V, then 2.1 V, then 3.3 Vthe binding threshold is the SMBus TTL VIH
9PMBus alone, then PMBus + I²CPMBus contributes 350 µA
10four violations at onceevery flag fires; the priority is the documented one
11no devices at allnot a compliant bus, under either profile
12back-to-back evaluationsdone 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 defectoutcome
Y1I²C given SMBus's 10 kHz clock floorkilled — test 2
Y2SMBus clock floor 10 kHz → 1 kHzkilled — 6 checks
Y3SMBus clock ceiling 100 kHz → 400 kHzkilled — 5 checks
Y4stretch bound 35 ms → 350 mskilled — 5 checks
Y5the SMBus VIL used in place of the VIHkilled — 4 checks
Y6low-power sink current 350 µA → 3.5 mAkilled — 11 checks
Y7the strongest device's floor taken, not the weakestkilled — test 7
Y8PMBus no longer implies the low-power classkilled — test 9
Y9the levels reported before the clock floorkilled — test 10
Y10an empty population called compliantkilled — test 11
Y11the mode ignored when sizing the rise-time ceilingkilled — 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.

Azvya Education Pvt. Ltd.VLSI Mentor
i2c_profile_cfg.sv — the same stimulus, two definitions of legal
   // 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
   endclass

13. 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

Symptom

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.

Root Cause

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.

Fix
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