Skip to content
VLSI Mentor

I²C · Module 7

The End-of-Transfer NACK

A master reading from a slave has no length field and no command for 'stop'. What it has is the acknowledge slot — so it ends a read by withholding one. The fifth NACK condition is not an error; it is the only way the conversation can be terminated.

Chapter 7.3 established that on a read the master acknowledges each data byte. This chapter is about the consequence of that, and it is larger than it first appears: if the master produces the acknowledges, then the master also controls the only channel through which the transfer can be ended.

1. The Problem the NACK Solves

Consider what a master-receiver actually needs to communicate, and what it has available.

It needs to tell the slave stop sending. And it has nothing to send it with.

Look at what is genuinely unavailable:

There is no length field. Chapter 7.1 quoted the specification: "The number of bytes that can be transmitted per transfer is unrestricted." No count precedes the data, so the slave cannot know in advance how many bytes are wanted.

The master cannot transmit during a read. SDA is being driven by the slave for all eight bits of every data byte. There is no spare slot in which the master could send a command, because the data occupies every one.

A STOP cannot be issued mid-byte. A STOP requires SDA to rise while SCL is high, and during a read's data bits SDA belongs to the slave. The master cannot produce framing in the middle of a byte the slave is transmitting — it would be fighting the slave for the line.

So the master has exactly one interval per byte in which it, and not the slave, controls SDA: the acknowledge slot. That is the entire communication channel available to a master-receiver, and it carries one bit.

Azvya Education Pvt. Ltd.VLSI Mentor
MATHEMATICAL DERIVATION — the master's channel during a read
   Per byte, nine bit slots:

     slots 1..8   SDA driven by the SLAVE   (the data)        master: read-only
     slot  9      SDA driven by the MASTER  (the acknowledge) master: 1 bit

   So a master-receiver's entire outbound bandwidth during a read is:

       1 bit per byte  =  1 bit per 9 bit slots  =  11.1% of the bus

   and it must carry the only message the master needs to send:

       ACK   = "another byte, please"
       NACK  = "that was the last one"

   One bit, two meanings, and the second one is a TERMINATION. The specification
   lists it as the fifth reason a NACK occurs:

       "A master-receiver must signal the end of the transfer to the slave
        transmitter."

   Note the word MUST. This is not a convention or an optimisation -- it is the
   defined mechanism, and there is no alternative.

That framing is worth holding onto, because it reverses the usual reading. A NACK is not an error that happens to be reused for termination. For a master-receiver, termination is what the NACK is for, and the four error conditions of Chapter 7.2 are the other users of the same bit.

2. What the Specification Says, Exactly

Two places, and they agree.

From the list of five NACK conditions in §3.1.6:

  1. A master-receiver must signal the end of the transfer to the slave transmitter.

And from §3.1.10, describing a master reading a slave:

At the moment of the first acknowledge, the master-transmitter becomes a master-receiver and the slave-receiver becomes a slave-transmitter. This first acknowledge is still generated by the slave. The master generates subsequent acknowledges. The STOP condition is generated by the master, which sends a not-acknowledge just before the STOP condition.

The last clause is the pattern in one line: NACK, then STOP. In that order, and the NACK comes first because it is what tells the slave to release SDA so that the master can produce framing on it.

That ordering is not stylistic. Think about what the STOP requires: SDA must rise while SCL is high, which means the master must own SDA. During a read the slave owns it — right up until the slave is told the transfer is over. The NACK is what hands SDA back.

The final byte of a read — the master withholds the acknowledge

9 cycles
Nine clock periods. SDA carries the final data byte across the first eight intervals, driven by the slave, and stays high in the ninth interval because the master declined to pull it low. A driver row shows S for slave across the data bits and M for master in the ninth interval.slave drives the dataslave drives the dataNACK, then STOPNACK,then STOPthe slave transmits the last bytethe slave transmits thelast byteNACK — the master says stopNACK — the master says stopsclsda001000101driverSSSSSSSSMt0t1t2t3t4t5t6t7t8
Figure 1 — the last byte of a read. The slave drives all eight data bits, then releases; the master leaves the ninth slot high. That absent acknowledge is the fifth NACK condition, and it is what tells the slave to stop driving SDA so the master can issue the STOP that follows.

3. The Pattern, for Any Length

The rule generalises to one line: acknowledge every byte you want another after, and NACK the one you do not.

bytes requestedacknowledge pattern
1NACK
2ACK, NACK
3ACK, ACK, NACK
nACK × (n − 1), then NACK

Two things about that table catch people out.

A one-byte read contains no acknowledge at all from the master. The only byte is the last byte, so it is NACKed immediately. A master implementation that acknowledges "each byte" and then NACKs "at the end" will send two answers for one byte — or, more commonly, acknowledge the only byte and then have nothing left to NACK.

The decision is made before the byte's acknowledge slot, not after the byte. The master has to know, at the ninth clock pulse of byte k, whether byte k+1 is wanted. For a fixed-length read that is trivial. For a length the master discovers from the data — a length byte in the payload, or a terminator — it means the decision logic has to run within one byte time, which is the awkward case §8 returns to.

4. What Breaks When the Master Forgets

The failure is worth walking through because it is symmetric to Chapter 7.3 §10 and produces a different symptom.

If a master acknowledges the byte it meant to be last, the slave draws the only conclusion available to it: another byte is wanted. So it transmits one. The slave is behaving correctly; it was told to continue.

What happens next depends on the slave and is uniformly unhelpful:

the slave...and the master reads...
has more data (a longer register block)bytes it did not ask for, silently
has reached the end of its register spacewrapped-around data, or a fixed fill value
auto-increments past the end of a memorydata from the beginning, or undefined contents
holds SDA low while fetchinga stalled bus, because the master is not clocking

And the master, having finished, now wants to issue a STOP — but the slave is still driving SDA, because nobody told it to stop. A master that issues a STOP anyway is attempting to raise SDA while the slave may be holding it low, and the wired-AND of Chapter 2.5 means the master simply loses: SDA stays low and no STOP is produced.

That is the mechanism by which a missing final NACK becomes a hung bus rather than a data error. The transfer never ends, the bus never returns to idle, and the next transfer cannot begin. Module 16 covers recovery; the point here is that the cause is one withheld bit.

5. The Sequencer in Three Languages

A counter, a comparison against one, and a STOP request. Small, and the comparison is the part worth defending.

Azvya Education Pvt. Ltd.VLSI Mentor
i2c_master_rx_ack_sequencer.sv — SYNTHESIZABLE RTL. Acknowledge every byte but the last; the last one is how the master says stop.
   // A master-receiver's acknowledge policy. The specification makes it condition 5
   // of the five NACK conditions: "A master-receiver must signal the end of the
   // transfer to the slave transmitter." So the master acknowledges every byte it
   // wants another after, and NACKs the last one -- the NACK is how it says "stop".
   module i2c_master_rx_ack_sequencer #(
       parameter int CNT_W = 8
   )(
       input  logic clk,
       input  logic rst_n,
       input  logic start_read,              // pulse: begin a read of n_bytes
       input  logic [CNT_W-1:0] n_bytes,     // how many bytes to read; zero is illegal
       input  logic byte_received,           // pulse: a data byte has arrived
       output logic send_ack,                // what to drive in the ninth slot
       output logic read_active,
       output logic request_stop,            // pulse: issue the STOP now
       output logic [CNT_W-1:0] remaining,
       output logic cfg_error                // a zero-length read was requested
   );
       // A zero-byte read is not a short read, it is a contradiction: the master would
       // have to answer a byte it never asked the slave to send. Refuse it rather than
       // silently reading one byte, which is what a design that clamps would do.
       assign cfg_error = (n_bytes == '0);

       // ACK every byte except the last. `remaining` still holds the count INCLUDING
       // the byte currently on the bus, so the last byte is the one where it reads 1 --
       // which is why this is a comparison against 1 and not against 0.
       assign send_ack = read_active && (remaining > {{(CNT_W-1){1'b0}}, 1'b1});

       always_ff @(posedge clk) begin
           if (!rst_n) begin
               read_active  <= 1'b0;
               remaining    <= '0;
               request_stop <= 1'b0;
           end else begin
               request_stop <= 1'b0;

               if (start_read && !cfg_error) begin
                   read_active <= 1'b1;
                   remaining   <= n_bytes;
               end else if (read_active && byte_received) begin
                   if (remaining <= {{(CNT_W-1){1'b0}}, 1'b1}) begin
                       // That was the last byte. It was NACKed, and a NACK must be
                       // followed by a STOP or a repeated START -- never by more clocks.
                       read_active  <= 1'b0;
                       remaining    <= '0;
                       request_stop <= 1'b1;
                   end else begin
                       remaining <= remaining - 1'b1;
                   end
               end
           end
       end
   endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
i2c_master_rx_ack_sequencer_tb.sv — SELF-CHECKING TESTBENCH, SIMULATION ONLY. Records the whole acknowledge pattern for reads of 1, 2, 3, 4 and 5 bytes.
   module i2c_master_rx_ack_sequencer_tb;
       localparam int CNT_W = 8;

       logic clk = 1'b0, rst_n, start_read, byte_received;
       logic [CNT_W-1:0] n_bytes;
       logic send_ack, read_active, request_stop, cfg_error;
       logic [CNT_W-1:0] remaining;
       int errors = 0;

       i2c_master_rx_ack_sequencer #(.CNT_W(CNT_W)) dut (.*);

       always #5 clk = ~clk;
       initial begin #40000; $display("FAIL: watchdog expired"); $finish; end

       int n_stop = 0;
       always @(posedge clk) if (rst_n && request_stop) n_stop++;

       // Record the acknowledge decision for every byte of a read, so the whole
       // PATTERN can be checked rather than just the final byte.
       logic ack_log [0:15];
       int   n_logged;
       // Module scope: an initialised declaration inside a loop block is static in
       // SystemVerilog, and overriding the lifetime is not portable across tools.
       logic expect_ack;

       task automatic do_read(input int count);
           n_logged = 0;
           n_bytes = count[CNT_W-1:0];
           start_read = 1'b1; @(negedge clk); start_read = 1'b0; @(negedge clk);
           for (int b = 0; b < count; b++) begin
               // Sample the decision at the moment the acknowledge slot would use it,
               // BEFORE the byte is declared received.
               ack_log[n_logged] = send_ack; n_logged++;
               byte_received = 1'b1; @(negedge clk); byte_received = 1'b0; @(negedge clk);
           end
       endtask

       task automatic check_pattern(input int count, input int step);
           // Expected: ACK for every byte but the last, NACK for the last.
           for (int i = 0; i < count; i++) begin
               expect_ack = (i < count - 1);
               if (ack_log[i] !== expect_ack) begin
                   $display("FAIL: step %0d -- byte %0d of %0d: send_ack %0b, expected %0b",
                            step, i + 1, count, ack_log[i], expect_ack);
                   errors++;
               end
           end
           if (n_logged != count) begin
               $display("FAIL: step %0d -- logged %0d decisions for %0d bytes", step, n_logged, count);
               errors++;
           end
       endtask

       initial begin
           rst_n = 1'b0; start_read = 1'b0; byte_received = 1'b0; n_bytes = 8'd0;
           repeat (3) @(negedge clk);
           if (read_active !== 1'b0) begin $display("FAIL: read_active out of reset"); errors++; end
           rst_n = 1'b1; @(negedge clk);

           // 1 -- a ONE-byte read. The only byte is the last byte, so it is NACKed
           //      immediately. There is no ACK at all in a single-byte read.
           do_read(1);
           check_pattern(1, 1);
           if (n_stop != 1) begin $display("FAIL: expected one STOP request, saw %0d", n_stop); errors++; end
           if (read_active !== 1'b0) begin $display("FAIL: still active after a one-byte read"); errors++; end

           // 2 -- a THREE-byte read: ACK, ACK, NACK.
           n_stop = 0;
           do_read(3);
           check_pattern(3, 2);
           if (n_stop != 1) begin $display("FAIL: expected one STOP after three bytes"); errors++; end

           // 3 -- a FIVE-byte read, to show the pattern is not hard-coded to a length.
           n_stop = 0;
           do_read(5);
           check_pattern(5, 3);
           if (n_stop != 1) begin $display("FAIL: expected one STOP after five bytes"); errors++; end

           // 4 -- a ZERO-byte read is a contradiction and must be refused outright.
           n_bytes = 8'd0;
           @(negedge clk);
           if (cfg_error !== 1'b1) begin $display("FAIL: a zero-byte read was not flagged"); errors++; end
           n_stop = 0;
           start_read = 1'b1; @(negedge clk); start_read = 1'b0; repeat (3) @(negedge clk);
           if (read_active !== 1'b0) begin
               $display("FAIL: began a zero-byte read"); errors++; end
           if (n_stop != 0) begin $display("FAIL: a refused read still requested a STOP"); errors++; end

           // 5 -- no acknowledge decision leaks out when no read is active. A master
           //      that acknowledged outside a read would answer somebody else's byte.
           if (send_ack !== 1'b0) begin
               $display("FAIL: send_ack asserted while idle"); errors++; end

           // 6 -- back-to-back reads must not inherit state from each other.
           n_stop = 0;
           do_read(2); check_pattern(2, 6);
           do_read(4); check_pattern(4, 6);
           if (n_stop != 2) begin
               $display("FAIL: expected two STOP requests over two reads, saw %0d", n_stop); errors++; end

           if (errors == 0)
               $display("PASS: ACK every byte but the last, NACK the last, STOP after it; zero-length refused");
           else $display("FAIL: %0d error(s)", errors);
           $finish;
       end
   endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
i2c_master_rx_ack_sequencer.v — SYNTHESIZABLE RTL. The same sequencer in Verilog-2005.
   // A master-receiver's acknowledge policy. The specification makes it condition 5
   // of the five NACK conditions: "A master-receiver must signal the end of the
   // transfer to the slave transmitter." So the master acknowledges every byte it
   // wants another after, and NACKs the last one -- the NACK is how it says "stop".
   module i2c_master_rx_ack_sequencer #(
       parameter integer CNT_W = 8
   )(
       input  wire clk,
       input  wire rst_n,
       input  wire start_read,              // pulse: begin a read of n_bytes
       input  wire [CNT_W-1:0] n_bytes,     // how many bytes to read; zero is illegal
       input  wire byte_received,           // pulse: a data byte has arrived
       output wire send_ack,                // what to drive in the ninth slot
       output reg  read_active,
       output reg  request_stop,            // pulse: issue the STOP now
       output reg  [CNT_W-1:0] remaining,
       output wire cfg_error                // a zero-length read was requested
   );
       // A zero-byte read is a contradiction, not a short read: the master would have
       // to answer a byte it never asked for. Refuse rather than silently clamp.
       assign cfg_error = (n_bytes == {CNT_W{1'b0}});

       // ACK every byte except the last. `remaining` still INCLUDES the byte currently
       // on the bus, so the last byte is the one where it reads 1.
       assign send_ack = read_active && (remaining > {{(CNT_W-1){1'b0}}, 1'b1});

       always @(posedge clk) begin
           if (!rst_n) begin
               read_active  <= 1'b0;
               remaining    <= {CNT_W{1'b0}};
               request_stop <= 1'b0;
           end else begin
               request_stop <= 1'b0;

               if (start_read && !cfg_error) begin
                   read_active <= 1'b1;
                   remaining   <= n_bytes;
               end else if (read_active && byte_received) begin
                   if (remaining <= {{(CNT_W-1){1'b0}}, 1'b1}) begin
                       // That was the last byte. It was NACKed, and a NACK must be
                       // followed by a STOP or a repeated START -- never by more clocks.
                       read_active  <= 1'b0;
                       remaining    <= {CNT_W{1'b0}};
                       request_stop <= 1'b1;
                   end else begin
                       remaining <= remaining - 1'b1;
                   end
               end
           end
       end
   endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
i2c_master_rx_ack_sequencer_tb.v — SELF-CHECKING TESTBENCH, SIMULATION ONLY. The same cases in Verilog idiom.
   module i2c_master_rx_ack_sequencer_tb;
       localparam integer CNT_W = 8;

       reg clk, rst_n, start_read, byte_received;
       reg [CNT_W-1:0] n_bytes;
       wire send_ack, read_active, request_stop, cfg_error;
       wire [CNT_W-1:0] remaining;
       integer errors, n_stop, n_logged, b, i;

       i2c_master_rx_ack_sequencer #(.CNT_W(CNT_W)) dut (.clk(clk), .rst_n(rst_n),
           .start_read(start_read), .n_bytes(n_bytes), .byte_received(byte_received),
           .send_ack(send_ack), .read_active(read_active), .request_stop(request_stop),
           .remaining(remaining), .cfg_error(cfg_error));

       initial clk = 1'b0;
       always #5 clk = ~clk;
       initial begin #40000; $display("FAIL: watchdog expired"); $finish; end

       always @(posedge clk) if (rst_n && request_stop) n_stop = n_stop + 1;

       // Record the acknowledge decision for every byte of a read, so the whole
       // PATTERN can be checked rather than just the final byte.
       reg ack_log [0:15];
       reg expect_ack;

       task do_read; input integer count; begin
           n_logged = 0;
           n_bytes = count[CNT_W-1:0];
           start_read = 1'b1; @(negedge clk); start_read = 1'b0; @(negedge clk);
           for (b = 0; b < count; b = b + 1) begin
               // Sample the decision at the moment the acknowledge slot would use it,
               // BEFORE the byte is declared received.
               ack_log[n_logged] = send_ack; n_logged = n_logged + 1;
               byte_received = 1'b1; @(negedge clk); byte_received = 1'b0; @(negedge clk);
           end
       end endtask

       task check_pattern; input integer count; input integer step; begin
           // Expected: ACK for every byte but the last, NACK for the last.
           for (i = 0; i < count; i = i + 1) begin
               expect_ack = (i < count - 1);
               if (ack_log[i] !== expect_ack) begin
                   $display("FAIL: step %0d -- byte %0d of %0d: send_ack %0b, expected %0b",
                            step, i + 1, count, ack_log[i], expect_ack);
                   errors = errors + 1;
               end
           end
           if (n_logged != count) begin
               $display("FAIL: step %0d -- logged %0d decisions for %0d bytes", step, n_logged, count);
               errors = errors + 1;
           end
       end endtask

       initial begin
           errors = 0; n_stop = 0; n_logged = 0;
           rst_n = 1'b0; start_read = 1'b0; byte_received = 1'b0; n_bytes = 8'd0;
           repeat (3) @(negedge clk);
           if (read_active !== 1'b0) begin $display("FAIL: read_active out of reset"); errors = errors + 1; end
           rst_n = 1'b1; @(negedge clk);

           // 1 -- a ONE-byte read. The only byte is the last byte, so it is NACKed
           //      immediately. There is no ACK at all in a single-byte read.
           do_read(1);
           check_pattern(1, 1);
           if (n_stop != 1) begin $display("FAIL: expected one STOP request, saw %0d", n_stop); errors = errors + 1; end
           if (read_active !== 1'b0) begin $display("FAIL: still active after a one-byte read"); errors = errors + 1; end

           // 2 -- a THREE-byte read: ACK, ACK, NACK.
           n_stop = 0;
           do_read(3);
           check_pattern(3, 2);
           if (n_stop != 1) begin $display("FAIL: expected one STOP after three bytes"); errors = errors + 1; end

           // 3 -- a FIVE-byte read, to show the pattern is not hard-coded to a length.
           n_stop = 0;
           do_read(5);
           check_pattern(5, 3);
           if (n_stop != 1) begin $display("FAIL: expected one STOP after five bytes"); errors = errors + 1; end

           // 4 -- a ZERO-byte read is a contradiction and must be refused outright.
           n_bytes = 8'd0;
           @(negedge clk);
           if (cfg_error !== 1'b1) begin $display("FAIL: a zero-byte read was not flagged"); errors = errors + 1; end
           n_stop = 0;
           start_read = 1'b1; @(negedge clk); start_read = 1'b0; repeat (3) @(negedge clk);
           if (read_active !== 1'b0) begin
               $display("FAIL: began a zero-byte read"); errors = errors + 1; end
           if (n_stop != 0) begin $display("FAIL: a refused read still requested a STOP"); errors = errors + 1; end

           // 5 -- no acknowledge decision leaks out when no read is active. A master
           //      that acknowledged outside a read would answer somebody else's byte.
           if (send_ack !== 1'b0) begin
               $display("FAIL: send_ack asserted while idle"); errors = errors + 1; end

           // 6 -- back-to-back reads must not inherit state from each other.
           n_stop = 0;
           do_read(2); check_pattern(2, 6);
           do_read(4); check_pattern(4, 6);
           if (n_stop != 2) begin
               $display("FAIL: expected two STOP requests over two reads, saw %0d", n_stop); errors = errors + 1; end

           if (errors == 0)
               $display("PASS: ACK every byte but the last, NACK the last, STOP after it; zero-length refused");
           else $display("FAIL: %0d error(s)", errors);
           $finish;
       end
   endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
i2c_master_rx_ack_sequencer.vhd — SYNTHESIZABLE RTL. The same sequencer in VHDL.
   library ieee;
   use ieee.std_logic_1164.all;
   use ieee.numeric_std.all;

   -- A master-receiver's acknowledge policy. The specification makes it condition 5
   -- of the five NACK conditions: "A master-receiver must signal the end of the
   -- transfer to the slave transmitter." So the master acknowledges every byte it
   -- wants another after, and NACKs the last one -- the NACK is how it says "stop".
   entity i2c_master_rx_ack_sequencer is
       generic (
           CNT_W : positive := 8
       );
       port (
           clk           : in  std_logic;
           rst_n         : in  std_logic;
           start_read    : in  std_logic;                     -- pulse: begin a read
           n_bytes       : in  unsigned(CNT_W - 1 downto 0);  -- zero is illegal
           byte_received : in  std_logic;                     -- pulse: a byte arrived
           send_ack      : out std_logic;                     -- drive in the ninth slot
           read_active   : out std_logic;
           request_stop  : out std_logic;                     -- pulse: issue the STOP
           remaining     : out unsigned(CNT_W - 1 downto 0);
           cfg_error     : out std_logic                      -- zero-length read
       );
   end entity;

   architecture rtl of i2c_master_rx_ack_sequencer is
       constant ZERO : unsigned(CNT_W - 1 downto 0) := (others => '0');
       constant ONE  : unsigned(CNT_W - 1 downto 0) := to_unsigned(1, CNT_W);
       signal rem_i    : unsigned(CNT_W - 1 downto 0) := (others => '0');
       signal active_i : std_logic := '0';
   begin
       -- A zero-byte read is a contradiction, not a short read: the master would have
       -- to answer a byte it never asked for. Refuse rather than silently clamp.
       cfg_error <= '1' when n_bytes = ZERO else '0';

       remaining   <= rem_i;
       read_active <= active_i;

       -- ACK every byte except the last. rem_i still INCLUDES the byte currently on the
       -- bus, so the last byte is the one where it reads 1.
       send_ack <= '1' when (active_i = '1' and rem_i > ONE) else '0';

       process (clk)
       begin
           if rising_edge(clk) then
               if rst_n = '0' then
                   active_i     <= '0';
                   rem_i        <= (others => '0');
                   request_stop <= '0';
               else
                   request_stop <= '0';

                   if start_read = '1' and n_bytes /= ZERO then
                       active_i <= '1';
                       rem_i    <= n_bytes;
                   elsif active_i = '1' and byte_received = '1' then
                       if rem_i <= ONE then
                           -- That was the last byte. It was NACKed, and a NACK must be
                           -- followed by a STOP or a repeated START, never more clocks.
                           active_i     <= '0';
                           rem_i        <= (others => '0');
                           request_stop <= '1';
                       else
                           rem_i <= rem_i - 1;
                       end if;
                   end if;
               end if;
           end if;
       end process;
   end architecture;
Azvya Education Pvt. Ltd.VLSI Mentor
i2c_master_rx_ack_sequencer_tb.vhd — SELF-CHECKING TESTBENCH, SIMULATION ONLY. The same cases with assert report severity.
   library ieee;
   use ieee.std_logic_1164.all;
   use ieee.numeric_std.all;

   entity i2c_master_rx_ack_sequencer_tb is
   end entity;

   architecture sim of i2c_master_rx_ack_sequencer_tb is
       constant CNT_W : positive := 8;

       signal clk           : std_logic := '0';
       signal rst_n         : std_logic := '0';
       signal start_read    : std_logic := '0';
       signal byte_received : std_logic := '0';
       signal n_bytes       : unsigned(CNT_W - 1 downto 0) := (others => '0');
       signal send_ack, read_active, request_stop, cfg_error : std_logic;
       signal remaining     : unsigned(CNT_W - 1 downto 0);

       signal n_stop    : natural := 0;
       signal test_done : std_logic := '0';
   begin
       dut : entity work.i2c_master_rx_ack_sequencer
           generic map (CNT_W => CNT_W)
           port map (clk => clk, rst_n => rst_n, start_read => start_read, n_bytes => n_bytes,
                     byte_received => byte_received, send_ack => send_ack,
                     read_active => read_active, request_stop => request_stop,
                     remaining => remaining, cfg_error => cfg_error);

       clk <= not clk after 5 ns;

       watchdog : process
       begin
           wait for 40 us;
           if test_done = '0' then
               report "watchdog expired -- the design never reached the expected state"
                   severity failure;
           end if;
           wait;
       end process;

       count : process (clk)
       begin
           if rising_edge(clk) then
               if rst_n = '1' and request_stop = '1' then n_stop <= n_stop + 1; end if;
           end if;
       end process;

       stim : process
           variable errs     : natural := 0;
           type log_t is array (0 to 15) of std_logic;
           variable ack_log  : log_t := (others => '0');
           variable n_logged : natural := 0;
           variable base     : natural := 0;

           procedure waitn (n : in positive) is
           begin
               for i in 1 to n loop wait until falling_edge(clk); end loop;
           end procedure;

           procedure do_read (count : in positive) is
           begin
               n_logged := 0;
               n_bytes <= to_unsigned(count, CNT_W);
               start_read <= '1'; waitn(1); start_read <= '0'; waitn(1);
               for b in 1 to count loop
                   -- Sample the decision at the moment the acknowledge slot would use
                   -- it, BEFORE the byte is declared received.
                   ack_log(n_logged) := send_ack; n_logged := n_logged + 1;
                   byte_received <= '1'; waitn(1); byte_received <= '0'; waitn(1);
               end loop;
           end procedure;

           procedure check_pattern (count : in positive; step : in natural) is
               variable expect_ack : std_logic;
           begin
               for i in 0 to count - 1 loop
                   if i < count - 1 then expect_ack := '1'; else expect_ack := '0'; end if;
                   if ack_log(i) /= expect_ack then
                       report "step " & integer'image(step) & ": byte " & integer'image(i + 1)
                            & " of " & integer'image(count) & " had the wrong acknowledge"
                           severity error;
                       errs := errs + 1;
                   end if;
               end loop;
               if n_logged /= count then
                   report "step " & integer'image(step) & ": wrong number of decisions logged"
                       severity error; errs := errs + 1;
               end if;
           end procedure;
       begin
           waitn(3);
           if read_active /= '0' then
               report "read_active out of reset" severity error; errs := errs + 1; end if;
           rst_n <= '1'; waitn(1);

           -- 1: a ONE-byte read -- the only byte is the last, so it is NACKed at once.
           base := n_stop;
           do_read(1); check_pattern(1, 1);
           if (n_stop - base) /= 1 then
               report "expected one STOP request" severity error; errs := errs + 1; end if;
           if read_active /= '0' then
               report "still active after a one-byte read" severity error; errs := errs + 1; end if;

           -- 2: a THREE-byte read: ACK, ACK, NACK.
           base := n_stop;
           do_read(3); check_pattern(3, 2);
           if (n_stop - base) /= 1 then
               report "expected one STOP after three bytes" severity error; errs := errs + 1; end if;

           -- 3: FIVE bytes, to show the pattern is not hard-coded to a length.
           base := n_stop;
           do_read(5); check_pattern(5, 3);
           if (n_stop - base) /= 1 then
               report "expected one STOP after five bytes" severity error; errs := errs + 1; end if;

           -- 4: a ZERO-byte read is a contradiction and must be refused outright.
           n_bytes <= (others => '0'); waitn(1);
           if cfg_error /= '1' then
               report "a zero-byte read was not flagged" severity error; errs := errs + 1; end if;
           base := n_stop;
           start_read <= '1'; waitn(1); start_read <= '0'; waitn(3);
           if read_active /= '0' then
               report "began a zero-byte read" severity error; errs := errs + 1; end if;
           if (n_stop - base) /= 0 then
               report "a refused read still requested a STOP" severity error; errs := errs + 1; end if;

           -- 5: no acknowledge decision leaks out while idle.
           if send_ack /= '0' then
               report "send_ack asserted while idle" severity error; errs := errs + 1; end if;

           -- 6: back-to-back reads must not inherit state from each other.
           base := n_stop;
           do_read(2); check_pattern(2, 6);
           do_read(4); check_pattern(4, 6);
           if (n_stop - base) /= 2 then
               report "expected two STOP requests over two reads" severity error;
               errs := errs + 1; end if;

           if errs = 0 then
               report "i2c_master_rx_ack_sequencer self-check complete: ACK every byte but the "
                    & "last, NACK the last, STOP after it; zero-length refused" severity note;
           else
               report "i2c_master_rx_ack_sequencer self-check FAILED" severity error;
           end if;
           test_done <= '1';
           wait;
       end process;
   end architecture;

5a. Why the Comparison Is Against One

Azvya Education Pvt. Ltd.VLSI Mentor
MATHEMATICAL DERIVATION — off-by-one, and why this is the safe formulation
   `remaining` still INCLUDES the byte currently on the bus. So during byte k of an
   n-byte read:

       remaining = n - k + 1

   and the LAST byte is the one where remaining = 1, not 0. Hence:

       send_ack = (remaining > 1)

   Check the boundaries:

       n = 1:  byte 1 -> remaining = 1 -> send_ack = 0   NACK immediately.   correct
       n = 3:  byte 1 -> remaining = 3 -> send_ack = 1   ACK
               byte 2 -> remaining = 2 -> send_ack = 1   ACK
               byte 3 -> remaining = 1 -> send_ack = 0   NACK               correct

   The two adjacent formulations are both wrong, and wrong in opposite directions:

       send_ack = (remaining > 0)   ->  ACKs the last byte too.  Section 4's hang.
       send_ack = (remaining > 2)   ->  NACKs one byte early.    Short read.

   Both are single-character edits, both compile, and both are caught by section 7 --
   but only because the testbench checks the WHOLE PATTERN rather than the final
   byte. A test that verified "the last byte is NACKed" passes the second fault.

And a zero-byte read is refused rather than clamped. A read of zero bytes is not a short read; it is a contradiction — the master would have to answer a byte it never asked the slave to send. cfg_error reports it and the sequencer does not start. Clamping to one byte would be worse than refusing, because the master would then receive a byte it did not request and the driver would have no way to know.

5b. Verified Execution and Cross-Language Parity

languagesimulatorresultcompletes at
SystemVerilogIcarus Verilog, -g2012PASS490 ns
Verilog-2005Icarus Verilog, -g2005PASS490 ns
VHDLnvc 1.23.0PASS490 ns
SystemVerilogVerilog-2005VHDL
counterlogic [CNT_W-1:0]reg [CNT_W-1:0]unsigned(CNT_W-1 downto 0)
the constant one{{(CNT_W-1){1'b0}}, 1'b1}same replicationto_unsigned(1, CNT_W) constant
zero test== '0== {CNT_W{1'b0}}= ZERO constant
pattern log in the TBlogic ack_log [0:15]reg ack_log [0:15]array (0 to 15) of std_logic

The VHDL version names ZERO and ONE as constants rather than rebuilding them at each use, which is the form where a width mistake is a compile error. The Verilog replications are correct and are the kind of expression worth a second look in review — a CNT_W-2 where CNT_W-1 belongs changes the comparison silently, which is exactly §7's first mutation.

i2c_master_rx_ack_sequencer — ACK, ACK, NACK, STOP

10 cycles
Ten internal clock cycles. A start read pulse loads a remaining count of three. Three byte received pulses arrive in turn and the remaining count steps down from three to two to one to zero. The send ack output is high for the first two bytes and low for the third, and a request stop pulse follows the third byte.read of three bytes beginsread of three bytes beginsbyte 1: ACKbyte 1: ACKsend_ack falls before the last slotsend_ack falls before thelast slotbyte 3: NACKbyte 3: NACKSTOP requestedSTOP requestedclkstart_readbyte_receivedremaining0332211000read_activesend_ackrequest_stopt0t1t2t3t4t5t6t7t8t9
Figure 2 — a three-byte read, from the simulation, on the internal clock. The remaining count is loaded with three and decrements as each byte arrives. send_ack is high while more bytes are wanted and falls before the third byte's acknowledge slot — so the third byte is NACKed. The STOP request follows immediately, which is the NACK-then-STOP ordering the specification requires. SIMULATION-DERIVED figure.

6. What the Testbench Proves

The suite runs reads of 1, 2, 3, 4 and 5 bytes and records the acknowledge decision for every byte, then compares the whole pattern.

stepread lengthrequired pattern
11NACK — and exactly one STOP request
23ACK, ACK, NACK
35ACK, ACK, ACK, ACK, NACK
40refused: cfg_error, no read, no STOP
5idlesend_ack is low when no read is active
62 then 4both patterns correct, two STOP requests — no state carried over

Recording the pattern rather than the final byte is the decision that gives this suite its power. A test asserting "the last byte was NACKed" passes a design that NACKs every byte, and passes a design that NACKs one byte early. Only comparing the full sequence against ACK×(n−1)+NACK distinguishes them, and §7's first two mutations are exactly those two faults.

Step 1 is the boundary that a length-agnostic implementation gets wrong. A one-byte read has zero acknowledges and one NACK. An implementation built around "acknowledge, then eventually NACK" has no correct behaviour for n = 1.

Step 5 matters because the output is a decision, not a state. A master that asserted send_ack while idle would be prepared to acknowledge a byte belonging to a transfer it is not part of — and on a multi-controller bus, that means answering another controller's read.

Step 6 catches state leakage. Back-to-back reads of different lengths must not inherit a count. A design that failed to clear remaining on completion would produce a correct first read and a wrong second one.

7. Mutation Testing

Five faults injected into the verified RTL. All five caught.

mutationwhat it breaksresult
remaining > 2 — NACK one byte earlya short read; the caller silently loses the last byteFAIL — byte 2 of 3 was NACKed
send_ack = read_active — ACK the last byte too§4's hangFAIL — byte 1 of 1 was ACKed
load n_bytes - 1one byte short, every timeFAIL — byte 2 of 3
never request the STOPthe NACK-then-STOP sequence never completesFAIL — no STOP request
accept a zero-length reada byte arrives that nobody asked forFAIL — began a zero-byte read

The first two are the pair worth dwelling on, because they are adjacent single-character edits with opposite consequences:

  • > 2 NACKs one byte early. The read is short, the caller gets n−1 bytes, and — crucially — the bus ends up in a perfectly legal state. Nothing hangs. The bug is a quiet data loss that looks like a device returning less than expected.
  • read_active alone ACKs the last byte. The read is long, the slave keeps sending, and the bus hangs because the slave never releases SDA for the STOP.

One is silent and one is loud, and a suite that only checked the final byte's acknowledge would catch the loud one and ship the silent one. That asymmetry — where the more dangerous-looking fault is the easier to detect — is a recurring shape, and it is the argument for checking patterns rather than endpoints.

8. When the Length Is Not Known in Advance

The sequencer in §5 takes a byte count, which covers most real reads: a datasheet says a register block is six bytes, so the master reads six. But some protocols layered on I²C put the length in the data, and that case is worth naming because it constrains the design.

The difficulty is timing. The master must decide byte k's acknowledge during byte k's ninth clock pulse — so if the length arrives in byte k, the decision logic has one byte time at most, and if the length arrives in byte 1 the master must act on it by the ninth pulse of byte 1.

Three workable approaches, in increasing order of cost:

approachhow it workscost
fixed lengththe master knows from the datasheetnone; use it whenever possible
length-prefixed, split transferread the length byte as a complete one-byte read, then start a second read of that many bytesan extra framing event and bus-free interval, or a repeated START
decide in one byte timecombinational path from the received byte to send_ackreal timing pressure, and clock stretching as the fallback

The second is almost always the right answer, and Chapter 5.4 is why it is cheap: a repeated START lets the master do the length read and the data read without releasing the bus, so no other controller can interpose between them. That turns "read a variable-length block" into two fixed-length reads inside one transaction — which needs no new mechanism at all.

9. Verification Connection — The Final NACK Is Not an Error

This is the single most common misconfiguration in I²C verification environments, and it is worth stating bluntly: a checker that flags every NACK will flag one per read, forever.

Azvya Education Pvt. Ltd.VLSI Mentor
UVM CONCEPT — VERIFICATION ONLY. Classifying a NACK by position and direction.
   // A NACK is only an error if it was not the fifth condition. Deciding that needs
   // two pieces of context the acknowledge bit does not carry: was the master
   // RECEIVING, and was this the byte it intended to be last?
   typedef enum { NACK_EXPECTED_END, NACK_UNEXPECTED } nack_class_e;

   function nack_class_e i2c_scoreboard::classify_nack(i2c_frame f, int byte_index);
       if (f.is_read && byte_index == f.expected_length - 1)
           return NACK_EXPECTED_END;      // condition 5 -- correct, and required
       return NACK_UNEXPECTED;            // conditions 1 to 4 -- report it
   endfunction

   // The property worth asserting is the POSITIVE obligation, not the absence of
   // NACKs: a read MUST end with one, and it must be on the last byte.
   property read_ends_with_a_nack;
       @(posedge clk) disable iff (!rst_n)
       (read_frame_complete) |-> (last_byte_was_nacked);
   endproperty
   assert property (read_ends_with_a_nack)
       else $error("a read completed without the master NACKing its final byte");

   // And the mirror: no byte BEFORE the last may be NACKed by the master, because
   // that is a short read rather than a termination.
   property no_early_master_nack;
       @(posedge clk) disable iff (!rst_n)
       (master_nacked && read_active) |-> (remaining == 1);
   endproperty

Three observations.

The useful assertion is positive. "A read ends with a NACK" catches the §4 hang directly, and it is impossible to express as "no NACKs occurred". Environments that only watch for unexpected NACKs cannot detect a missing required one — which is the more dangerous fault.

Classification needs context from outside the bit. Direction and position. That is the same conclusion Chapter 7.2 reached about narrowing the five conditions, and it is why the frame decoder of Chapter 7.5 records every byte's acknowledge together with its index.

The second property catches the silent fault. master_nacked |-> remaining == 1 fails on the early-NACK mutation of §7 — the one that produces a short read and a legal-looking bus. Without it, that fault reaches a scoreboard as "the DUT returned fewer bytes than expected", which is usually blamed on the DUT.

10. FPGA and ASIC Implications

The acknowledge decision must be ready before the ninth falling edge. send_ack is combinational from remaining in §5, so it is stable as soon as the count is — which is one clock after the previous byte completed. That is the right structure: a design that computed the decision when the slot arrived would be doing arithmetic in the tightest available window.

Expose the remaining count to software. A driver that can read how many bytes are still expected can recover sensibly from an aborted transfer, and a debugger can tell a short read from a hung one at a glance. It costs nothing beyond wiring an existing register to the bus.

A hardware master should refuse a zero-length read, not clamp it. §5a's reasoning: clamping delivers a byte the driver did not request, with no indication. cfg_error turns a driver bug into an immediate, attributable report — the same argument Chapter 5.5 §9a made for refusing an illegal timing configuration.

The NACK-then-STOP ordering has to be enforced by the sequencer, not by software. §2 established that the NACK is what hands SDA back so the STOP can be produced. A design that let firmware request a STOP independently of the acknowledge decision permits the ordering to be violated — and the result is §4's hang, produced by correct-looking driver code.

Variable-length reads want the two-transfer structure of §8, not a fast decision path. Closing a combinational path from the received byte to the acknowledge decision inside one byte time is possible and is a timing risk for no benefit, when a repeated START achieves the same thing with no timing pressure at all.

11. Debugging — The Bus That Locked Up on the Last Register

A driver that read six bytes correctly and then never released the bus

Pitfall — acknowledging every byte of a read, including the last one
Buggy Code
// A master driver reads a block of registers. Its inner loop is symmetric and tidy:
//
//     for (i = 0; i < len; i++) {
//         buf[i] = i2c_read_byte();
//         i2c_send_ack();              // "confirm every byte we received"
//     }
//     i2c_stop();
//
// Every byte read is acknowledged, which reads as careful and is how a WRITE loop
// is correctly structured -- acknowledge what you received, then finish. The
// engineer's mental model is that the acknowledge confirms receipt, so confirming
// all of them is thorough.
//
// It is the one place on this bus where being thorough is the bug: the last
// acknowledge is not a confirmation, it is a REQUEST FOR ANOTHER BYTE.
Symptom

Reads return correct data. All six bytes are right, every time, on every board.

Then the bus stops working. The next transfer -- to any device -- gets no acknowledge, and a capture shows SDA stuck low with SCL idle high. Power-cycling recovers it; a software reset of the master does not.

The failure is 100% reproducible after any read and never occurs after a write, which correctly points at the read path. But the read path returned perfect data, so the investigation goes looking for something that happens AFTER the data is collected -- the STOP generation, the peripheral's teardown, the interrupt handler.

A capture of the end of the read shows the master's STOP attempt: SCL goes high, and SDA does not. The master appears to fail to generate a STOP, which sends everyone into the framing chapter looking for a timing violation.

Root Cause

The master asked for a seventh byte and then tried to end the conversation.

Section 1 is the mechanism: during a read, the acknowledge slot is the master's ONLY outbound channel, and an ACK in it means "another byte, please". The loop acknowledged byte 6, so the slave -- behaving perfectly correctly -- began transmitting byte 7 and pulled SDA low for its first bit.

The master then attempted a STOP. A STOP needs SDA to RISE while SCL is high, and SDA was being held low by the slave. Chapter 2.5's wired-AND decides that contest unambiguously: the master releases, the slave pulls, and the line stays LOW. No STOP is produced.

So the bus is left with the slave mid-byte, waiting for clocks that will never come, holding SDA low. Every subsequent transfer fails because the bus is not free -- and a reset of the MASTER cannot fix it, because the stuck device is the SLAVE. That is why power-cycling worked and a software reset did not, and that detail was available from the beginning as the strongest clue in the whole investigation.

Note why the data was perfect. All six requested bytes were transferred correctly and acknowledged correctly. The fault is entirely in the SEVENTH byte, which the driver never reads and never sees. A read loop that validates the data it collected cannot detect this, because the data it collected is right.

And note why writes are unaffected: on a write the SLAVE acknowledges, so the master's acknowledge logic is not used at all. Section 7.3's table has exactly one row where the master answers, and this bug lives only in that row.

Fix
// NACK the last byte -- and note the loop structure changes, not just a flag:
//
//     for (i = 0; i < len; i++) {
//         buf[i] = i2c_read_byte();
//         if (i < len - 1) i2c_send_ack();     // more wanted
//         else             i2c_send_nack();    // that was the last
//     }
//     i2c_stop();                              // now legal: the slave has released
//
// Section 5's sequencer is this rule in hardware, and its comparison against ONE
// rather than zero is the same boundary -- section 5a derives why.
//
// The lessons, ordered by how far they generalise.
//
//   1. ON A READ, AN ACK IS A REQUEST, NOT A RECEIPT. That is the whole chapter. A
//      write loop acknowledges what it received; a read loop requests what it wants
//      next. The two look identical in code and mean opposite things, which is why
//      transplanting the write loop's structure is such a natural mistake.
//
//   2. "SDA STUCK LOW AND A RESET DOES NOT HELP" MEANS THE SLAVE IS STUCK. A master
//      reset cannot clear a line another device is holding. That single observation
//      distinguishes a master fault from a slave left mid-transfer, and it was
//      visible before any capture was taken.
//
//   3. A FAILED STOP IS USUALLY NOT A FRAMING BUG. A STOP that does not appear is
//      most often a STOP that could not be produced, because somebody else owned
//      SDA. Ask who is holding the line before checking the timing that would have
//      produced the edge.
//
//   4. VALIDATING THE DATA YOU COLLECTED CANNOT FIND THIS. The bug is in a byte the
//      driver never requested and never reads. Section 9's positive assertion --
//      "a read must end with a NACK on its final byte" -- catches it; no amount of
//      payload checking does.
//
// The design habit: write down the acknowledge pattern for n = 1 before writing the
// loop. A one-byte read has ZERO acknowledges and one NACK, and any loop structure
// that cannot express that is wrong for every length.

12. Common Misconceptions

"A NACK always means something went wrong." The fifth condition is a master-receiver ending a transfer, and it happens at the end of every read on the bus. Treating it as an error produces one spurious error per read.

"The master should acknowledge every byte it receives." On a read, an acknowledge is a request for another byte, not a receipt. The last byte must be NACKed.

"A one-byte read has one acknowledge." It has none from the master, and one NACK. Any loop structure that cannot express that is wrong for every length.

"The STOP can come first and the NACK is a formality." The NACK is what makes the STOP possible — it tells the slave to release SDA. The specification's order is NACK then STOP, and reversing it means the master cannot produce the STOP at all.

"If the master forgets the NACK, it just reads one extra byte." It reads an extra byte and cannot end the transfer, because the slave is still driving SDA. The result is a hung bus, not a data error.

"Resetting the master will clear a stuck bus." Not if the thing holding SDA low is the slave. §11's failure survives a master reset for exactly that reason, and that observation is the fastest way to tell the two cases apart.

"Checking that the last byte was NACKed is sufficient verification." It passes a design that NACKs one byte early — a silent short read. Only comparing the whole pattern distinguishes the two.

"A variable-length read needs a fast decision path." It needs two fixed-length reads joined by a repeated START, which costs no timing pressure and no new mechanism.

13. Reason It Through

Why can a master-receiver not simply send a "stop sending" command?

Because it has nowhere to send it. During a read the slave drives SDA for all eight data bits of every byte, so the master's only outbound interval is the acknowledge slot — one bit per byte. A STOP cannot be issued mid-byte either, because SDA belongs to the slave then. The one bit has to carry the termination, which is what the fifth NACK condition is.

What is the acknowledge pattern for a four-byte read, and for a one-byte read?

ACK, ACK, ACK, NACK for four bytes. For one byte: just a NACK, with no acknowledge at all — the only byte is the last byte.

Why must the NACK precede the STOP rather than follow it?

Because a STOP requires the master to raise SDA while SCL is high, and during a read the slave owns SDA. The NACK is what tells the slave the transfer is over so it releases the line. Attempt the STOP first and the slave is still driving — the wired-AND keeps SDA low and no STOP edge is produced.

A master acknowledges the last byte of a read and then issues a STOP. Describe what happens on the wire.

The slave interprets the acknowledge as a request and begins transmitting another byte, pulling SDA low for its first bit. The master releases SDA and raises SCL expecting a STOP, but the slave is holding SDA low, so the line does not rise and no STOP occurs. The bus is left with the slave mid-byte waiting for clocks, holding SDA low, and no subsequent transfer can begin.

A bus is stuck with SDA low and resetting the master does not clear it. What does that tell you immediately?

That the device holding SDA is not the master. A master reset returns the master's own drive intent to released, which cannot affect a line another device is pulling down — so the stuck device is a slave, almost certainly left mid-byte by a transfer that was never properly terminated. That single observation separates a master fault from an unterminated read before any capture is taken.

Your test asserts that the final byte of every read was NACKed, and it passes. What fault can still be present?

A NACK one byte early — the read returns n−1 bytes and ends legally, so the final byte transferred was indeed NACKed and the assertion holds. The missing byte is a silent data loss that looks like the device returning less than expected. Catching it requires comparing the whole acknowledge pattern, or asserting that a master NACK only occurs when one byte remains.

14. Understanding Check

15. Summary

A master-receiver has one outbound bit per byte — the acknowledge slot — because the slave drives all eight data bits and a STOP cannot be issued mid-byte. That one bit has to carry the termination.

So the NACK is the termination, and the specification lists it as the fifth condition with the word must. It is not an error reused for convenience.

The pattern is ACK × (n−1) then NACK, and a one-byte read therefore has no acknowledge at all.

NACK then STOP, in that order, because the NACK is what hands SDA back so the framing edge can be produced.

Forgetting the final NACK hangs the bus. The slave sends another byte, holds SDA low, and the master's STOP cannot raise the line — so the transfer never ends, and a master reset cannot fix it.

The comparison is against one, not zero, because the count still includes the byte on the bus — and the two adjacent formulations fail in opposite directions, one loudly and one silently.

Check the whole acknowledge pattern, not the final byte. The silent fault survives an endpoint check.

Variable-length reads split into two fixed-length reads joined by a repeated START, which costs no timing pressure.

In verification, assert the positive obligation. A rule that only flags unexpected NACKs cannot see a missing required one.

16. What Comes Next

Four chapters have built the byte and its acknowledge from the bottom: nine clock pulses, what goes in the ninth, who owns it, and how a master uses it to end a read. Every one of them worked on a fragment — one byte, one slot, one decision.

Chapter 7.5 closes the module by putting the fragments together: a decoder that takes the raw two wires and produces a complete frame — framing, address, direction, every data byte and every acknowledge — which is both the thing a protocol monitor publishes and the thing an engineer does by eye when reading a capture.

Browse the full path on the I²C tutorials index. For the rule that makes the master the acknowledger here, see Who Acknowledges When; for the five conditions this is the fifth of, The ACK/NACK Cycle.

Continue learning