I²C · Module 7
The ACK/NACK Cycle — What the Ninth Clock Proves
An acknowledge is one device pulling SDA low for one clock pulse. A not-acknowledge is nobody doing anything. That asymmetry decides how the bus behaves when a device is absent, and it is why an ACK proves far less than engineers assume.
Chapter 7.1 established that every byte costs nine clock pulses and that the transmitter's job in the ninth is to stop driving. This chapter is about what happens in the slot it vacated.
It is the most important single bit on the bus, and the most over-interpreted.
1. The Definition, and the Asymmetry Inside It
UM10204 §3.1.6:
The acknowledge takes place after every byte. The acknowledge bit allows the receiver to signal the transmitter that the byte was successfully received and another byte may be sent. The master generates all clock pulses, including the acknowledge ninth clock pulse.
The Acknowledge signal is defined as follows: the transmitter releases the SDA line during the acknowledge clock pulse so the receiver can pull the SDA line LOW and it remains stable LOW during the HIGH period of this clock pulse. Set-up and hold times (specified in Section 6) must also be taken into account.
When SDA remains HIGH during this ninth clock pulse, this is defined as the Not Acknowledge signal.
Read the last two paragraphs together and the asymmetry is unmistakable:
| what it is | who does something | |
|---|---|---|
| ACK | SDA pulled LOW for the ninth pulse | the receiver acts |
| NACK | SDA remains HIGH | nobody acts |
A NACK is not a signal. It is the absence of one. There is no NACK driver, no NACK level anybody asserts, nothing transmitted. The pull-up network of Chapter 2.4 produces the high level because the transmitter released and nothing else pulled down.
That single fact explains most of this chapter, and it has an immediate consequence that is worth stating before anything else: a bus with nothing attached NACKs everything, correctly, with no device participating. The default answer on this bus is "no", and it costs nothing to produce. That is a deliberate and rather elegant piece of design — the failure mode requires no working hardware.
ACK — the receiver pulls the ninth slot low
9 cyclesNACK — nobody pulls the ninth slot low
9 cycles2. The Acknowledge Is a Bit Like Any Other
One sentence in the definition is easy to skim past and it carries real design weight:
...and it remains stable LOW during the HIGH period of this clock pulse. Set-up and hold times (specified in Section 6) must also be taken into account.
So the acknowledge obeys Chapter 4.2's data-valid rule exactly like a data bit. It is established while SCL is low, held stable through the high period, and released afterwards — and the setup and hold parameters that govern ordinary bits govern it too.
Three consequences:
The receiver must establish the acknowledge while SCL is low. A receiver that decided late and pulled SDA down during the high period would be producing an SDA edge while SCL is high — which Chapter 5.1 established is reserved framing, so it would emit a START or STOP into the middle of a transfer. The decision has to be made in time.
That is a real latency requirement on a slave. Between the eighth rising edge and the ninth falling edge, a slave has to have decided whether it can take the byte. On a fast bus that is not much time, and it is the reason the specification offers clock stretching — Chapter 7.1 §8 quoted the slave's right to hold SCL low precisely when it cannot decide in time.
And the transmitter must sample the answer on the rising edge, for the same reason it samples data there. The block in §5 does exactly that, and a mutation that samples on the falling edge is caught by a test that releases the far end as SCL falls.
3. The Five Reasons for a NACK
UM10204 lists them, and they are worth reading as five genuinely different situations rather than one error condition:
There are five conditions that lead to the generation of a NACK:
- No receiver is present on the bus with the transmitted address so there is no device to respond with an acknowledge.
- The receiver is unable to receive or transmit because it is performing some real-time function and is not ready to start communication with the master.
- During the transfer, the receiver gets data or commands that it does not understand.
- During the transfer, the receiver cannot receive any more data bytes.
- A master-receiver must signal the end of the transfer to the slave transmitter.
Grouping them by what they actually tell you:
| # | situation | who NACKs | what it means for the master |
|---|---|---|---|
| 1 | nothing at that address | nobody — the pull-up answers | the device is absent, unpowered, or at a different address |
| 2 | the device is busy | the addressed slave | retry later; the device exists |
| 3 | the content was not understood | the addressed slave | a protocol or register-map disagreement |
| 4 | the device is full | the addressed slave | stop sending; what arrived so far is probably fine |
| 5 | the master is finished | the master | not an error at all |
Two observations about that table are the whole point of it.
Condition 1 is produced by nobody. It is the only one that requires no participating device, and it is the reason an address scan works: writing an address and observing the ninth slot tells you whether anything is there, with no cooperation needed from the device.
Condition 5 is not an error. It is a master-receiver deliberately saying "that was the last byte I want", and it is the normal, correct ending of every read on this bus. Chapter 7.4 is entirely about it. A driver that logs every NACK as an error will log one per read, forever, and the noise will hide conditions 1 through 4.
4. What an ACK Does Not Prove
This is the section to remember, because an acknowledge is routinely treated as a delivery receipt and it is nothing of the kind.
An ACK proves exactly one thing: some device pulled SDA low during that ninth clock pulse. Everything below is outside what the bit can carry.
It does not prove the data was correct. There is no checksum, parity or CRC at this layer. A byte corrupted by a marginal edge arrives, gets sampled as something, and is acknowledged — the receiver has no way to know it is wrong and nothing to compare it against.
It does not prove the device understood it. Condition 3 exists for the case where a device can tell, but a device writing an unrecognised value into a register it does have will acknowledge happily.
It does not prove the device will act on it. An acknowledge is per byte, and it happens the instant the byte arrives. Whether the command is executed, whether an EEPROM write reaches the cell, whether a configuration takes effect — none of that is in scope. An EEPROM acknowledges the byte and then spends milliseconds writing it, during which it will NACK everything (condition 2).
It does not prove that exactly one device answered. This is the one that surprises people. The wired-AND of Chapter 2.5 makes several devices pulling SDA low indistinguishable from one. Chapter 6.2 relies on that deliberately — several devices acknowledge a 10-bit prefix — and Chapter 6.4 shows what it costs when two devices share an address by accident.
It does not prove the right device answered. The acknowledge carries no identity. If two devices answer one address, the acknowledge is identical to a correct one — which is why Chapter 6.4 recommends reading an identifying register rather than trusting a successful transfer.
And it does not prove the transfer was legal. Chapter 5.5 §12 catalogued framing that is well formed in shape and illegal in timing. Every byte of such a transfer can be acknowledged.
information in the acknowledge slot = 1 bit
distinct meanings the specification assigns = 5 (the NACK conditions)
identity of the responder = not carried
count of responders = not carried
integrity of the data = not carried
eventual effect of the byte = not carried
An acknowledge is a LIVENESS signal, not a delivery receipt: it says something
was listening at that instant. Every other property has to come from somewhere
else -- an identifying register read, a read-back of what was written, a status
bit, or a device-level protocol layered on top.5. The Acknowledge Slot in Three Languages
Small, and every line of it is a decision from §1 to §3.
// The ninth clock pulse of a byte. ACK is SDA pulled LOW; NACK is SDA left HIGH.
// This block drives the slot when this device owns it, and samples the resolved
// level in every case -- because a transmitter must read the answer it was given.
module i2c_ack_slot (
input logic clk,
input logic rst_n,
input logic scl_in, // observed bus level
input logic sda_in, // observed bus level
input logic ack_slot, // from the byte shifter: the ninth clock
input logic we_acknowledge, // 1 = this device owns the slot for this byte
input logic send_ack, // 1 = acknowledge (pull LOW); 0 = NACK (release)
output logic sda_drive_low, // DRIVE INTENT for the ninth slot only
output logic ack_bit, // the raw level sampled in the ninth slot
output logic ack_received, // 1 = ACK, because the bit was LOW
output logic nack_received, // 1 = NACK, because the bit was HIGH
output logic ack_valid // pulse: the ninth bit has been sampled
);
logic scl_q;
logic scl_rise, scl_fall;
logic slot_q;
assign scl_rise = !scl_q && scl_in;
assign scl_fall = scl_q && !scl_in;
// ACK is the LOW level. Naming both directions explicitly is not redundancy:
// "the acknowledge bit was 0" and "the byte was acknowledged" are the same
// fact stated with opposite polarity, and conflating them is the classic bug.
//
// These are LEVELS describing the MOST RECENT acknowledge slot, not pulses.
// A sequencer asks "was the last byte acknowledged?" several cycles after the
// slot ended, so a one-cycle pulse would be unusable to it; `ack_valid` is the
// pulse that says a new answer has landed. Out of reset, before any slot has
// happened, ack_bit is 1 and so the reported state is NACK -- the safe
// direction, because assuming an acknowledge nobody gave is how a transmitter
// walks off the end of a transfer.
assign ack_received = !ack_bit;
assign nack_received = ack_bit;
always_ff @(posedge clk) begin
if (!rst_n) begin
scl_q <= 1'b1; // idle bus: released, therefore high
slot_q <= 1'b0;
sda_drive_low <= 1'b0; // RELEASE on reset
ack_bit <= 1'b1; // an unanswered slot reads as a NACK
ack_valid <= 1'b0;
end else begin
ack_valid <= 1'b0;
scl_q <= scl_in;
slot_q <= ack_slot;
if (!ack_slot) begin
// Outside the ninth clock this block never touches the bus.
sda_drive_low <= 1'b0;
end else begin
// Entering the slot, or already in it with SCL low: this is the only
// legal moment to establish the level, because SDA may not move
// while SCL is high.
if ((!slot_q || scl_fall) && !scl_in)
sda_drive_low <= we_acknowledge && send_ack;
if (scl_rise) begin
// The receiver's answer is read in the HIGH period of the ninth
// pulse -- the same data-valid window as any other bit.
ack_bit <= sda_in;
ack_valid <= 1'b1;
end
end
end
end
endmodule module i2c_ack_slot_tb;
logic clk = 1'b0, rst_n, scl_in;
logic ack_slot, we_acknowledge, send_ack;
logic sda_drive_low, ack_bit, ack_received, nack_received, ack_valid;
int errors = 0;
// Wired-AND of the DUT's driver and the testbench's far end, plus a pull-up.
logic far_drive_low = 1'b0;
wire sda_bus = ~(sda_drive_low | far_drive_low);
i2c_ack_slot dut (.clk(clk), .rst_n(rst_n), .scl_in(scl_in), .sda_in(sda_bus),
.ack_slot(ack_slot), .we_acknowledge(we_acknowledge), .send_ack(send_ack),
.sda_drive_low(sda_drive_low), .ack_bit(ack_bit), .ack_received(ack_received),
.nack_received(nack_received), .ack_valid(ack_valid));
always #5 clk = ~clk;
initial begin #40000; $display("FAIL: watchdog expired"); $finish; end
// Continuous data-valid monitor: the acknowledge is a bit like any other and
// must not move while SCL is high.
logic scl_q2, sda_q2;
int dv_violations = 0;
always @(posedge clk) if (rst_n) begin
if (scl_q2 && scl_in && (sda_bus !== sda_q2)) dv_violations++;
scl_q2 <= scl_in; sda_q2 <= sda_bus;
end
int n_valid = 0;
always @(posedge clk) if (rst_n && ack_valid) n_valid++;
logic captured_bit;
// Run one acknowledge slot. `far_acks` is what the OTHER end does.
task automatic run_ack_slot(input logic mine, input logic ack, input logic far_acks);
we_acknowledge = mine; send_ack = ack;
scl_in = 1'b0; repeat (1) @(negedge clk);
ack_slot = 1'b1; repeat (2) @(negedge clk);
far_drive_low = far_acks; repeat (1) @(negedge clk);
scl_in = 1'b1; repeat (1) @(negedge clk);
captured_bit = sda_bus; // what a scope sees
repeat (1) @(negedge clk);
// Release the far end AT THE SAME MOMENT SCL falls. This is legal -- SDA may
// move once SCL is low -- and it is what distinguishes a design that sampled
// the answer on the RISING edge from one that sampled it on the falling edge:
// the two now see different values.
scl_in = 1'b0; far_drive_low = 1'b0; repeat (1) @(negedge clk);
ack_slot = 1'b0; repeat (2) @(negedge clk);
endtask
initial begin
rst_n = 1'b0; scl_in = 1'b1; ack_slot = 1'b0;
we_acknowledge = 1'b0; send_ack = 1'b0;
scl_q2 = 1'b1; sda_q2 = 1'b1;
repeat (3) @(negedge clk);
if (sda_drive_low !== 1'b0) begin $display("FAIL: reset did not release SDA"); errors++; end
// An unanswered slot must read as a NACK, not as an ACK: the safe default.
if (ack_bit !== 1'b1) begin $display("FAIL: ack_bit does not default to NACK"); errors++; end
rst_n = 1'b1; @(negedge clk);
// 1 -- WE acknowledge. The bus must be LOW in the slot, and the block must
// read back the level it is itself producing.
run_ack_slot(1'b1, 1'b1, 1'b0);
if (captured_bit !== 1'b0) begin $display("FAIL: our ACK did not pull the bus low"); errors++; end
if (ack_received !== 1'b1) begin $display("FAIL: ACK not reported as received"); errors++; end
if (nack_received !== 1'b0) begin $display("FAIL: NACK reported alongside an ACK"); errors++; end
// 2 -- WE NACK. A NACK is not a signal: it is the ABSENCE of one, so the
// block must leave the line alone and the pull-up produces the HIGH.
run_ack_slot(1'b1, 1'b0, 1'b0);
if (captured_bit !== 1'b1) begin $display("FAIL: our NACK did not leave the bus high"); errors++; end
if (nack_received !== 1'b1) begin $display("FAIL: NACK not reported"); errors++; end
if (ack_received !== 1'b0) begin $display("FAIL: ACK reported alongside a NACK"); errors++; end
// 3 -- the slot is NOT ours and the far end acknowledges. We must not drive,
// and must still read the answer -- a transmitter has to learn it.
run_ack_slot(1'b0, 1'b1, 1'b1);
if (ack_received !== 1'b1) begin
$display("FAIL: did not read the far end's ACK"); errors++; end
// 4 -- the slot is not ours and NOBODY acknowledges. The pull-up makes it a
// NACK, which is exactly specification condition 1: no receiver present.
run_ack_slot(1'b0, 1'b1, 1'b0);
if (nack_received !== 1'b1) begin
$display("FAIL: an unanswered slot must read as a NACK"); errors++; end
// 5 -- send_ack must be ignored when the slot is not ours. A device that
// acknowledged a byte it did not receive would corrupt the handshake.
run_ack_slot(1'b0, 1'b1, 1'b0);
if (captured_bit !== 1'b1) begin
$display("FAIL: drove an acknowledge slot it does not own"); errors++; end
// 6 -- exactly one ack_valid per slot: five slots, five pulses.
if (n_valid != 5) begin
$display("FAIL: expected 5 ack_valid pulses, saw %0d", n_valid); errors++; end
// 7 -- outside the slot the block never drives, whatever the inputs say.
we_acknowledge = 1'b1; send_ack = 1'b1; ack_slot = 1'b0;
repeat (4) @(negedge clk);
if (sda_drive_low !== 1'b0) begin
$display("FAIL: drove SDA outside the acknowledge slot"); errors++; end
if (dv_violations != 0) begin
$display("FAIL: %0d data-valid violations in the acknowledge slot", dv_violations); errors++; end
if (errors == 0)
$display("PASS: ACK is a pulled-low slot, NACK is an absent one, %0d slots, zero data-valid violations",
n_valid);
else $display("FAIL: %0d error(s)", errors);
$finish;
end
endmodule // The ninth clock pulse of a byte. ACK is SDA pulled LOW; NACK is SDA left HIGH.
// This block drives the slot when this device owns it, and samples the resolved
// level in every case -- because a transmitter must read the answer it was given.
module i2c_ack_slot (
input wire clk,
input wire rst_n,
input wire scl_in, // observed bus level
input wire sda_in, // observed bus level
input wire ack_slot, // from the byte shifter: the ninth clock
input wire we_acknowledge, // 1 = this device owns the slot for this byte
input wire send_ack, // 1 = acknowledge (pull LOW); 0 = NACK (release)
output reg sda_drive_low, // DRIVE INTENT for the ninth slot only
output reg ack_bit, // the raw level sampled in the ninth slot
output wire ack_received, // 1 = ACK, because the bit was LOW
output wire nack_received, // 1 = NACK, because the bit was HIGH
output reg ack_valid // pulse: the ninth bit has been sampled
);
reg scl_q, slot_q;
wire scl_rise = ~scl_q & scl_in;
wire scl_fall = scl_q & ~scl_in;
// LEVELS describing the MOST RECENT slot, not pulses: a sequencer asks whether
// the last byte was acknowledged several cycles later. Out of reset the state is
// NACK, which is the safe direction.
assign ack_received = ~ack_bit;
assign nack_received = ack_bit;
always @(posedge clk) begin
if (!rst_n) begin
scl_q <= 1'b1; // idle bus: released, therefore high
slot_q <= 1'b0;
sda_drive_low <= 1'b0; // RELEASE on reset
ack_bit <= 1'b1; // an unanswered slot reads as a NACK
ack_valid <= 1'b0;
end else begin
ack_valid <= 1'b0;
scl_q <= scl_in;
slot_q <= ack_slot;
if (!ack_slot) begin
sda_drive_low <= 1'b0;
end else begin
// Establish the level only while SCL is low: SDA may not move
// while SCL is high.
if ((!slot_q || scl_fall) && !scl_in)
sda_drive_low <= we_acknowledge & send_ack;
if (scl_rise) begin
// The answer is read in the HIGH period of the ninth pulse.
ack_bit <= sda_in;
ack_valid <= 1'b1;
end
end
end
end
endmodule module i2c_ack_slot_tb;
reg clk, rst_n, scl_in;
reg ack_slot, we_acknowledge, send_ack;
wire sda_drive_low, ack_bit, ack_received, nack_received, ack_valid;
integer errors;
// Wired-AND of the DUT's driver and the testbench's far end, plus a pull-up.
reg far_drive_low;
wire sda_bus = ~(sda_drive_low | far_drive_low);
i2c_ack_slot dut (.clk(clk), .rst_n(rst_n), .scl_in(scl_in), .sda_in(sda_bus),
.ack_slot(ack_slot), .we_acknowledge(we_acknowledge), .send_ack(send_ack),
.sda_drive_low(sda_drive_low), .ack_bit(ack_bit), .ack_received(ack_received),
.nack_received(nack_received), .ack_valid(ack_valid));
initial clk = 1'b0;
always #5 clk = ~clk;
initial begin #40000; $display("FAIL: watchdog expired"); $finish; end
// Continuous data-valid monitor: the acknowledge is a bit like any other and
// must not move while SCL is high.
reg scl_q2, sda_q2;
integer dv_violations;
always @(posedge clk) if (rst_n) begin
if (scl_q2 && scl_in && (sda_bus !== sda_q2)) dv_violations = dv_violations + 1;
scl_q2 <= scl_in; sda_q2 <= sda_bus;
end
integer n_valid;
always @(posedge clk) if (rst_n && ack_valid) n_valid = n_valid + 1;
reg captured_bit;
// Run one acknowledge slot. far_acks is what the OTHER end does.
task run_ack_slot; input mine; input ack; input far_acks; begin
we_acknowledge = mine; send_ack = ack;
scl_in = 1'b0; repeat (1) @(negedge clk);
ack_slot = 1'b1; repeat (2) @(negedge clk);
far_drive_low = far_acks; repeat (1) @(negedge clk);
scl_in = 1'b1; repeat (1) @(negedge clk);
captured_bit = sda_bus; // what a scope sees
repeat (1) @(negedge clk);
// Release the far end AT THE SAME MOMENT SCL falls -- legal, and it is what
// distinguishes a rising-edge sampler from a falling-edge one.
scl_in = 1'b0; far_drive_low = 1'b0; repeat (1) @(negedge clk);
ack_slot = 1'b0; repeat (2) @(negedge clk);
end endtask
initial begin
errors = 0; dv_violations = 0; n_valid = 0; far_drive_low = 1'b0;
rst_n = 1'b0; scl_in = 1'b1; ack_slot = 1'b0;
we_acknowledge = 1'b0; send_ack = 1'b0;
scl_q2 = 1'b1; sda_q2 = 1'b1;
repeat (3) @(negedge clk);
if (sda_drive_low !== 1'b0) begin $display("FAIL: reset did not release SDA"); errors = errors + 1; end
// An unanswered slot must read as a NACK, not as an ACK: the safe default.
if (ack_bit !== 1'b1) begin $display("FAIL: ack_bit does not default to NACK"); errors = errors + 1; end
rst_n = 1'b1; @(negedge clk);
// 1 -- WE acknowledge. The bus must be LOW in the slot, and the block must
// read back the level it is itself producing.
run_ack_slot(1'b1, 1'b1, 1'b0);
if (captured_bit !== 1'b0) begin $display("FAIL: our ACK did not pull the bus low"); errors = errors + 1; end
if (ack_received !== 1'b1) begin $display("FAIL: ACK not reported as received"); errors = errors + 1; end
if (nack_received !== 1'b0) begin $display("FAIL: NACK reported alongside an ACK"); errors = errors + 1; end
// 2 -- WE NACK. A NACK is not a signal: it is the ABSENCE of one, so the
// block must leave the line alone and the pull-up produces the HIGH.
run_ack_slot(1'b1, 1'b0, 1'b0);
if (captured_bit !== 1'b1) begin $display("FAIL: our NACK did not leave the bus high"); errors = errors + 1; end
if (nack_received !== 1'b1) begin $display("FAIL: NACK not reported"); errors = errors + 1; end
if (ack_received !== 1'b0) begin $display("FAIL: ACK reported alongside a NACK"); errors = errors + 1; end
// 3 -- the slot is NOT ours and the far end acknowledges. We must not drive,
// and must still read the answer -- a transmitter has to learn it.
run_ack_slot(1'b0, 1'b1, 1'b1);
if (ack_received !== 1'b1) begin
$display("FAIL: did not read the far end's ACK"); errors = errors + 1; end
// 4 -- the slot is not ours and NOBODY acknowledges. The pull-up makes it a
// NACK, which is exactly specification condition 1: no receiver present.
run_ack_slot(1'b0, 1'b1, 1'b0);
if (nack_received !== 1'b1) begin
$display("FAIL: an unanswered slot must read as a NACK"); errors = errors + 1; end
// 5 -- send_ack must be ignored when the slot is not ours. A device that
// acknowledged a byte it did not receive would corrupt the handshake.
run_ack_slot(1'b0, 1'b1, 1'b0);
if (captured_bit !== 1'b1) begin
$display("FAIL: drove an acknowledge slot it does not own"); errors = errors + 1; end
// 6 -- exactly one ack_valid per slot: five slots, five pulses.
if (n_valid != 5) begin
$display("FAIL: expected 5 ack_valid pulses, saw %0d", n_valid); errors = errors + 1; end
// 7 -- outside the slot the block never drives, whatever the inputs say.
we_acknowledge = 1'b1; send_ack = 1'b1; ack_slot = 1'b0;
repeat (4) @(negedge clk);
if (sda_drive_low !== 1'b0) begin
$display("FAIL: drove SDA outside the acknowledge slot"); errors = errors + 1; end
if (dv_violations != 0) begin
$display("FAIL: %0d data-valid violations in the acknowledge slot", dv_violations); errors = errors + 1; end
if (errors == 0)
$display("PASS: ACK is a pulled-low slot, NACK is an absent one, %0d slots, zero data-valid violations",
n_valid);
else $display("FAIL: %0d error(s)", errors);
$finish;
end
endmodule library ieee;
use ieee.std_logic_1164.all;
-- The ninth clock pulse of a byte. ACK is SDA pulled LOW; NACK is SDA left HIGH.
-- This block drives the slot when this device owns it, and samples the resolved
-- level in every case -- because a transmitter must read the answer it was given.
entity i2c_ack_slot is
port (
clk : in std_logic;
rst_n : in std_logic;
scl_in : in std_logic; -- observed bus level
sda_in : in std_logic; -- observed bus level
ack_slot : in std_logic; -- from the byte shifter: the ninth clock
we_acknowledge : in std_logic; -- 1 = this device owns the slot
send_ack : in std_logic; -- 1 = ACK (pull LOW); 0 = NACK (release)
sda_drive_low : out std_logic; -- DRIVE INTENT, ninth slot only
ack_bit : out std_logic; -- the raw level sampled in the slot
ack_received : out std_logic; -- 1 = ACK, because the bit was LOW
nack_received : out std_logic; -- 1 = NACK, because the bit was HIGH
ack_valid : out std_logic -- pulse: the ninth bit was sampled
);
end entity;
architecture rtl of i2c_ack_slot is
signal scl_q : std_logic := '1'; -- idle bus: released, therefore high
signal slot_q : std_logic := '0';
signal abit : std_logic := '1'; -- an unanswered slot reads as a NACK
signal scl_rise, scl_fall : std_logic;
begin
scl_rise <= (not scl_q) and scl_in;
scl_fall <= scl_q and (not scl_in);
ack_bit <= abit;
-- LEVELS describing the MOST RECENT slot, not pulses: a sequencer asks whether
-- the last byte was acknowledged several cycles later. Out of reset the reported
-- state is NACK, which is the safe direction.
ack_received <= not abit;
nack_received <= abit;
process (clk)
begin
if rising_edge(clk) then
if rst_n = '0' then
scl_q <= '1';
slot_q <= '0';
sda_drive_low <= '0'; -- RELEASE on reset
abit <= '1';
ack_valid <= '0';
else
ack_valid <= '0';
scl_q <= scl_in;
slot_q <= ack_slot;
if ack_slot = '0' then
sda_drive_low <= '0';
else
-- Establish the level only while SCL is low.
if (slot_q = '0' or scl_fall = '1') and scl_in = '0' then
sda_drive_low <= we_acknowledge and send_ack;
end if;
if scl_rise = '1' then
-- The answer is read in the HIGH period of the ninth pulse.
abit <= sda_in;
ack_valid <= '1';
end if;
end if;
end if;
end if;
end process;
end architecture; library ieee;
use ieee.std_logic_1164.all;
entity i2c_ack_slot_tb is
end entity;
architecture sim of i2c_ack_slot_tb is
signal clk : std_logic := '0';
signal rst_n : std_logic := '0';
signal scl_in : std_logic := '1';
signal ack_slot : std_logic := '0';
signal we_acknowledge : std_logic := '0';
signal send_ack : std_logic := '0';
signal sda_drive_low, ack_bit, ack_received, nack_received, ack_valid : std_logic;
signal far_drive_low : std_logic := '0';
signal sda_bus : std_logic;
signal n_valid, dv_violations : natural := 0;
signal test_done : std_logic := '0';
begin
sda_bus <= not (sda_drive_low or far_drive_low);
dut : entity work.i2c_ack_slot
port map (clk => clk, rst_n => rst_n, scl_in => scl_in, sda_in => sda_bus,
ack_slot => ack_slot, we_acknowledge => we_acknowledge, send_ack => send_ack,
sda_drive_low => sda_drive_low, ack_bit => ack_bit,
ack_received => ack_received, nack_received => nack_received,
ack_valid => ack_valid);
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;
monitor : process (clk)
variable scl_q2 : std_logic := '1';
variable sda_q2 : std_logic := '1';
begin
if rising_edge(clk) then
if rst_n = '1' then
if scl_q2 = '1' and scl_in = '1' and sda_bus /= sda_q2 then
dv_violations <= dv_violations + 1;
end if;
scl_q2 := scl_in; sda_q2 := sda_bus;
if ack_valid = '1' then n_valid <= n_valid + 1; end if;
end if;
end if;
end process;
stim : process
variable errs : natural := 0;
variable captured_bit : std_logic;
procedure waitn (n : in positive) is
begin
for i in 1 to n loop wait until falling_edge(clk); end loop;
end procedure;
-- Run one acknowledge slot. far_acks is what the OTHER end does.
procedure run_ack_slot (mine, ack, far_acks : in std_logic) is
begin
we_acknowledge <= mine; send_ack <= ack;
scl_in <= '0'; waitn(1);
ack_slot <= '1'; waitn(2);
far_drive_low <= far_acks; waitn(1);
scl_in <= '1'; waitn(1);
captured_bit := sda_bus; -- what a scope sees
waitn(1);
-- Release the far end AT THE SAME MOMENT SCL falls -- legal, and it is
-- what distinguishes a rising-edge sampler from a falling-edge one.
scl_in <= '0'; far_drive_low <= '0'; waitn(1);
ack_slot <= '0'; waitn(2);
end procedure;
begin
waitn(3);
if sda_drive_low /= '0' then
report "reset did not release SDA" severity error; errs := errs + 1; end if;
if ack_bit /= '1' then
report "ack_bit does not default to NACK" severity error; errs := errs + 1; end if;
rst_n <= '1'; waitn(1);
-- 1: WE acknowledge -- the bus must be LOW and we read back our own level.
run_ack_slot('1', '1', '0');
if captured_bit /= '0' then
report "our ACK did not pull the bus low" severity error; errs := errs + 1; end if;
if ack_received /= '1' then
report "ACK not reported as received" severity error; errs := errs + 1; end if;
if nack_received /= '0' then
report "NACK reported alongside an ACK" severity error; errs := errs + 1; end if;
-- 2: WE NACK -- a NACK is the ABSENCE of a signal; the pull-up makes the HIGH.
run_ack_slot('1', '0', '0');
if captured_bit /= '1' then
report "our NACK did not leave the bus high" severity error; errs := errs + 1; end if;
if nack_received /= '1' then
report "NACK not reported" severity error; errs := errs + 1; end if;
if ack_received /= '0' then
report "ACK reported alongside a NACK" severity error; errs := errs + 1; end if;
-- 3: not our slot, far end acknowledges -- we must not drive, and must read it.
run_ack_slot('0', '1', '1');
if ack_received /= '1' then
report "did not read the far end's ACK" severity error; errs := errs + 1; end if;
-- 4: not our slot and NOBODY acknowledges -- specification condition 1.
run_ack_slot('0', '1', '0');
if nack_received /= '1' then
report "an unanswered slot must read as a NACK" severity error; errs := errs + 1; end if;
-- 5: send_ack must be ignored when the slot is not ours.
run_ack_slot('0', '1', '0');
if captured_bit /= '1' then
report "drove an acknowledge slot it does not own" severity error; errs := errs + 1; end if;
-- 6: exactly one ack_valid per slot.
if n_valid /= 5 then
report "expected 5 ack_valid pulses" severity error; errs := errs + 1; end if;
-- 7: outside the slot the block never drives, whatever the inputs say.
we_acknowledge <= '1'; send_ack <= '1'; ack_slot <= '0';
waitn(4);
if sda_drive_low /= '0' then
report "drove SDA outside the acknowledge slot" severity error; errs := errs + 1; end if;
if dv_violations /= 0 then
report "data-valid violations in the acknowledge slot" severity error;
errs := errs + 1; end if;
if errs = 0 then
report "i2c_ack_slot self-check complete: ACK is a pulled-low slot, NACK is an "
& "absent one, " & integer'image(n_valid)
& " slots, zero data-valid violations" severity note;
else
report "i2c_ack_slot self-check FAILED" severity error;
end if;
test_done <= '1';
wait;
end process;
end architecture;5a. Three Decisions Worth Defending
ack_received and nack_received are latched levels, not pulses. A sequencer asks "was the last byte acknowledged?" several cycles after the slot ended — Chapter 7.4's sequencer does exactly that — so a one-cycle pulse would be unusable to it. ack_valid is the pulse that says a new answer has landed; the decode is a level describing the most recent one.
Out of reset the reported state is NACK. ack_bit resets to 1, so before any slot has happened the block reports not-acknowledged. That is the safe direction: assuming an acknowledge nobody gave is how a transmitter walks off the end of a transfer, and §1 established that "no" is the bus's natural default anyway.
Both polarities are named explicitly. ack_bit is the raw wire level; ack_received is the interpretation. Keeping both is not redundancy — "the acknowledge bit was 0" and "the byte was acknowledged" are the same fact with opposite polarity, and every inversion bug in this area comes from a design that only kept one of them and then had to remember which way round it was.
5b. Verified Execution and Cross-Language Parity
| language | simulator | result | completes at |
|---|---|---|---|
| SystemVerilog | Icarus Verilog, -g2012 | PASS | 530 ns |
| Verilog-2005 | Icarus Verilog, -g2005 | PASS | 530 ns |
| VHDL | nvc 1.23.0 | PASS | 530 ns |
| SystemVerilog | Verilog-2005 | VHDL | |
|---|---|---|---|
| slot tracking | logic slot_q | reg slot_q | signal slot_q |
| polarity decode | assign on !ack_bit | assign on ~ack_bit | not abit |
| drive condition | we_acknowledge && send_ack | we_acknowledge & send_ack | we_acknowledge and send_ack |
| internal latched bit | output register read directly | output register read directly | internal abit, driven to the port |
The VHDL version routes ack_bit through an internal signal because the architecture reads that value to compute the two decodes, and VHDL's port modes make reading an out port awkward. The Verilog versions can read an output register freely. The hardware is one flip-flop either way.
i2c_ack_slot — establishing and sampling the answer
10 cycles6. What the Testbench Proves
Five slots, chosen so that every combination of who owns the slot and what the answer is appears:
| step | who owns it | answer | required result |
|---|---|---|---|
| 1 | us | ACK | the bus goes low, and we read back our own level |
| 2 | us | NACK | the bus stays high — we assert nothing |
| 3 | the far end | ACK | we do not drive, and we still read the answer |
| 4 | the far end | none | NACK — condition 1, with no device participating |
| 5 | the far end | (we are told to ACK) | we ignore send_ack — the slot is not ours |
Plus two invariants: exactly one ack_valid per slot, and zero SDA edges while SCL is high across the whole simulation.
Step 2 is more interesting than it looks. "We NACK" means the block does nothing at all. Verifying that a device correctly produces a NACK is verifying that it correctly stays out of the way, and the only observable is that the pull-up wins. A design that drove a one instead of releasing would pass a naive check of the bus level and be electrically wrong on an open-drain bus.
Step 5 is the safety check. A device that acknowledged a byte it was not the receiver of would corrupt the handshake — the transmitter would believe the wrong device took its byte. send_ack has to be gated on ownership, and Chapter 7.3 is entirely about computing that ownership correctly.
The far end releases as SCL falls, deliberately. That makes the value present at the falling edge differ from the value during the high period, which is what distinguishes a design that samples on the rising edge from one that samples on the falling edge. §7's second mutation is caught by exactly this and by nothing else.
7. Mutation Testing
Six faults injected into the verified RTL. All six caught.
| mutation | what it breaks | result |
|---|---|---|
| acknowledge by releasing instead of pulling low | the polarity of the whole mechanism | FAIL — the ACK did not pull the bus low |
| sample the answer on the falling edge | reads a line permitted to be moving | FAIL — caught by the release-as-SCL-falls stimulus |
| drive a slot this device does not own | forges an acknowledge for another device's byte | FAIL — an unanswered slot read as ACK |
| drive outside the slot | corrupts data bits | FAIL — drove SDA outside the slot |
| ACK and NACK decodes swapped | every answer is inverted | FAIL — ACK not reported |
| reset defaults to ACK | an unstarted block claims a byte was acknowledged | FAIL — the reset check |
Two are worth a note.
The falling-edge mutation initially survived. The original testbench held the far end's level until after SCL had gone low, so the falling-edge sample saw the same value as the rising-edge one — the two designs were indistinguishable under that stimulus. Releasing the far end as SCL falls is legal (SDA may move once SCL is low) and makes the two differ. This is the same shape as Chapter 7.1's survivor: a timing fault is only observable if the stimulus changes something between the two candidate sampling instants.
The reset-default mutation is the cheapest real bug in the module. A block that reports "acknowledged" before it has seen a single acknowledge hands a false positive to whatever consumes it, at the worst possible moment — the first byte after reset. §5a's reasoning is why the default is NACK, and the mutation confirms a test actually pins it down.
8. What the Master Does Next
The specification gives the master exactly two options after a NACK:
The master can then generate either a STOP condition to abort the transfer, or a repeated START condition to start a new transfer.
There is no third option, and in particular there is no "carry on and hope". A NACK means the receiver is not accepting more bytes, so continuing to clock them out is transmitting into a device that has said it is not listening.
The two options map onto the two situations cleanly:
| after a NACK the master wants to... | issue | why |
|---|---|---|
| give up on this transfer entirely | STOP | releases the bus; costs the bus-free interval of Chapter 5.3 |
| try something else without losing the bus | repeated START | keeps ownership, per Chapter 5.4 |
The repeated-START option is the interesting one for a retry. A master that NACKs on the address because the device was busy (condition 2) can retry immediately with an Sr, without releasing the bus to a competing controller — which on a multi-controller segment is the difference between a retry and a lost turn.
9. Verification Connection — Checking the Answer, and Checking the Question
An environment needs two different kinds of check around the acknowledge, and conflating them produces a monitor that cannot explain a failure.
// PROPERTY 1 -- protocol legality. The transmitter must have released. This is a
// statement about the DUT's obligation and holds for every byte, forever.
property transmitter_released_for_the_answer;
@(posedge clk) disable iff (!rst_n)
(ack_slot && we_are_transmitting) |-> !sda_drive_low;
endproperty
// PROPERTY 2 -- the acknowledge is a data bit and obeys the data-valid rule. A
// receiver that decides late emits FRAMING, not a late acknowledge.
property ack_stable_through_scl_high;
@(posedge clk) disable iff (!rst_n)
(ack_slot && $past(scl_in) && scl_in) |-> $stable(sda_in);
endproperty
// COVERAGE -- the five NACK conditions are five DIFFERENT situations, and a suite
// that only ever produces condition 1 has not tested acknowledgement at all.
covergroup ack_reason_cg @(posedge clk);
option.per_instance = 1;
cp : coverpoint nack_reason iff (ack_valid && nack_seen) {
bins absent = { NACK_NO_DEVICE }; // condition 1
bins busy = { NACK_BUSY }; // condition 2
bins not_understood = { NACK_BAD_CONTENT }; // condition 3
bins full = { NACK_FULL }; // condition 4
bins end_of_read = { NACK_MASTER_DONE }; // condition 5 -- NOT an error
}
// And the one that matters most in practice: an ACK on every byte of a long
// transfer is the common case, so cover the LENGTH at which a NACK appeared.
cp_pos : coverpoint byte_index_of_nack iff (nack_seen) {
bins on_address = { 0 };
bins first_data = { 1 };
bins later_data = { [2:255] };
}
endgroupThree observations.
The two properties check different things and both are needed. The first says the transmitter got out of the way; the second says whoever answered did so legally. A design can satisfy one and violate the other, and a single combined check cannot say which happened.
Condition 5 belongs in the coverage model, not in an error list. A master-receiver's final NACK is correct behaviour. Modelling it as a covered reason rather than as a failure is what keeps the error report meaningful — and it is the single most common mistake in I²C verification environments.
Covering the position of the NACK is worth more than covering that one occurred. A NACK on the address byte and a NACK on the twentieth data byte exercise entirely different paths in both the DUT and the driver. The cp_pos coverpoint asks the question a debug engineer actually asks first.
10. FPGA and ASIC Implications
The slave's decision latency is a real constraint. Between the eighth rising edge and the ninth falling edge, a slave must decide whether to acknowledge. At 400 kHz that is on the order of a microsecond; with an input filter and a synchroniser in the path it is less. A device that cannot decide in time must stretch the clock rather than answer late, because answering late means emitting framing.
The acknowledge output is the same open-drain cell as everything else. There is no separate acknowledge pin and no special driver — it is the same tristate enable, asserted for one clock pulse. On an FPGA, the mistake to avoid is the one from Chapter 5.1 §9: driving the buffer's data input low with the enable already asserted is correct; driving the data input high to "send a NACK" is not, because that drives a one onto an open-drain bus.
Sampling the answer needs the same synchronised input as the data. A transmitter reads the ninth slot through exactly the path it reads data bits through. There is no reason for a separate path and a good reason against one — two paths can disagree about what the bus did.
On an ASIC, expose the last acknowledge to software. A status bit saying whether the most recent byte was acknowledged, and ideally which byte index NACKed, turns §3's five-way ambiguity into something a driver can act on. Chapter 3.4 established that such status bits want write-one-to-clear semantics, because a driver must be able to distinguish one NACK from three.
11. Debugging — The EEPROM That Lost Half Its Writes
A configuration store that acknowledged every byte and remembered some of them
Pitfall — treating an acknowledge as proof that a write took effect
// A driver writes a configuration block to an EEPROM, byte by byte, and checks
// the acknowledge after each one:
//
// for (i = 0; i < len; i++) {
// i2c_start();
// i2c_write_byte(EEPROM_ADDR7 << 1); // address + W
// i2c_write_byte(reg_base + i); // register pointer
// i2c_write_byte(data[i]);
// if (!i2c_get_ack()) return -EIO; // "the byte did not land"
// i2c_stop();
// }
// return 0; // "all bytes landed"
//
// Every acknowledge is checked. The error path exists and works. The loop returns
// success only if every single byte was acknowledged. By the standards of most
// driver code this is careful.Configuration is written, the driver reports success, and on the next power cycle some of the block has reverted to its previous contents. Not all of it -- a prefix, usually, and the amount that survives varies between boards and between runs on the same board.
Reading the block back IMMEDIATELY after writing it returns the correct data, every time. So the driver's own verification passes, and the problem only appears across a power cycle, which points everyone at the EEPROM's retention specification or at the supply.
Slowing the bus down makes it better. Adding delays between bytes makes it go away entirely -- which looks exactly like a timing or signal-integrity problem and consumed a week of scope time.
The acknowledge was doing its job perfectly. It was being asked the wrong question.
An EEPROM acknowledges a byte when it RECEIVES it. Committing that byte to the non-volatile cell is a separate, much slower operation -- typically milliseconds -- that begins after the STOP. During that internal write cycle the device is busy, and section 3's condition 2 says exactly what it will do about any new transfer: NACK it, because it "is unable to receive or transmit because it is performing some real-time function".
So the sequence was:
write byte 0 -> ACK -> STOP -> EEPROM begins its internal write cycle write byte 1 -> the address byte is NACKed, device busy -> driver returns -EIO? NO: get_ack() was checked only after the DATA byte, and the transfer never got that far
Whether byte 1 landed depended on whether the EEPROM had finished its internal cycle, which depended on bus speed and on the device's own timing. Faster bus -> the next write arrives sooner -> more bytes lost. That is why slowing down "fixed" it, and why adding delays fixed it completely: the delay was accidentally implementing the acknowledge-polling the driver should have been doing.
The immediate read-back succeeded because the EEPROM serves reads from the data it has RECEIVED, not only from committed cells -- so the driver verified its own writes against a buffer that had not yet been committed.
Section 4 is the general statement: an acknowledge proves a byte was received at that instant. It says nothing about whether the device will act on it, and nothing about when that action completes.
// Poll for the device to become ready again, which is what the specification's
// condition 2 is FOR -- the NACK is the device telling you it is busy:
//
// for (i = 0; i < len; i++) {
// write_one_byte(reg_base + i, data[i]);
// // "acknowledge polling": address the device repeatedly until it answers.
// // A NACK here is not an error, it is the expected in-progress signal.
// deadline = now() + EEPROM_WRITE_TIMEOUT;
// do {
// i2c_start();
// ok = i2c_write_byte(EEPROM_ADDR7 << 1); // address only
// i2c_stop();
// } while (!ok && now() < deadline);
// if (!ok) return -ETIMEDOUT;
// }
//
// The lessons, in order of how far they generalise.
//
// 1. AN ACKNOWLEDGE IS A LIVENESS SIGNAL, NOT A RECEIPT. Section 4 lists what it
// does not prove; "the device will act on this" is on that list. Any device
// with an internal operation slower than the bus needs a completion check that
// is NOT the acknowledge -- polling, a status register, or a busy pin.
//
// 2. A NACK IS NOT ALWAYS AN ERROR. Condition 2 is a device saying "not yet" and
// condition 5 is a master saying "I am done". A driver that maps every NACK to
// -EIO cannot implement acknowledge polling at all, and will log one spurious
// error per read for the life of the product.
//
// 3. READ-BACK THROUGH THE SAME PATH PROVES LESS THAN IT APPEARS TO. Verifying a
// write by reading it back immediately can be satisfied by an uncommitted
// buffer. The verification that matters crosses the boundary you care about --
// here, a power cycle.
//
// 4. "SLOWING IT DOWN FIXES IT" USUALLY MEANS A MISSING HANDSHAKE, NOT A TIMING
// VIOLATION. A genuine timing violation gets worse with temperature and
// loading; a missing wait-for-ready gets better with any delay at all. The two
// are distinguishable by asking whether the fix is a delay or a CHECK.
//
// And the bench habit: when an acknowledge is involved, ask what question it
// answered. "Did a device pull SDA low in that slot" is the only question it can
// answer, and it is rarely the question the code wanted.12. Common Misconceptions
"A NACK is a signal the device sends." A NACK is the absence of a signal — nobody pulls the line down and the pull-up leaves it high. That is why a bus with nothing attached NACKs correctly.
"An ACK is SDA high, because high means yes." An ACK is SDA low. The polarity is the opposite of the intuitive one, and it follows from the bus being open-drain: the only thing a device can actively do is pull low.
"A NACK means an error." Sometimes. Condition 2 means "busy, try again" and condition 5 means "the master is finished" — and condition 5 ends every single read on the bus. A driver mapping all NACKs to errors logs one per read forever.
"An ACK means the byte was delivered and accepted." It means some device pulled SDA low at that instant. It says nothing about correctness, understanding, eventual effect, how many devices answered, or which one did.
"An ACK confirms the write is stored." §11 is an entire failure resting on this. A device acknowledges receipt; a slow internal operation completes later, and the device will NACK during it.
"A receiver can decide late and pull SDA down during the high period." That produces an SDA edge while SCL is high, which is reserved framing — so it emits a START or STOP mid-transfer. A device that cannot decide in time must stretch the clock instead.
"The transmitter should drive a one in the ninth slot so the receiver can override it." Nothing on this bus drives a one, and there is nothing to override — the transmitter releases and the pull-up does the rest.
"The master can continue clocking after a NACK." The specification gives two options: STOP or repeated START. Continuing means transmitting into a device that has said it is not listening.
13. Reason It Through
A bus has no devices attached at all. What does the master observe when it addresses one, and what produced that observation?
A NACK, produced by nothing. The master releases SDA after the eighth bit, no device pulls it low, and the pull-up leaves it high — which is by definition a not-acknowledge. This is condition 1, and it is the only NACK condition that requires no participating device, which is exactly why an address scan works.
Why must a slave establish its acknowledge while SCL is low rather than deciding during the high period?
Because SDA may only change while SCL is low. Pulling SDA down during the high period is an SDA edge inside a high phase, which is reserved framing — the device would emit a START or STOP into the middle of a transfer rather than a late acknowledge. If it cannot decide in time, its legitimate option is to hold SCL low and stretch the clock.
A master writes twenty bytes and the nineteenth is NACKed. Which conditions are plausible, and which are eliminated?
Conditions 3 and 4 — the receiver did not understand that byte, or it has no room for more. Condition 1 is eliminated because the address was acknowledged, so a device is present. Condition 5 is eliminated because the master is transmitting, not receiving. Condition 2 is possible but less likely mid-transfer than at the start. The position of the NACK did most of that narrowing, which is why a frame decoder records every byte's answer.
Two devices accidentally share an address and both acknowledge. What does the master see, and what would reveal the problem?
Exactly the same acknowledge it would see from one device — the wired-AND makes two devices pulling low indistinguishable from one. Nothing in the acknowledge reveals it. What reveals it is reading an identifying register: two devices transmitting different IDs produce the bitwise AND of them, which is almost never a valid ID, whereas two similar data values AND to something plausible.
A driver's writes to an EEPROM succeed according to every acknowledge, and some are lost across a power cycle. Slowing the bus helps. What is the mechanism, and why is "slowing helps" the clue?
The EEPROM acknowledges receipt and then spends milliseconds committing the byte, NACKing everything during that window. Later writes arrive while it is busy and are refused. Slowing the bus accidentally supplies the wait the driver should have implemented as acknowledge polling — and that is the tell: a genuine timing violation worsens with temperature and loading, while a missing handshake is cured by any delay at all. The distinction is whether the fix is a delay or a check.
Why is a mutation that samples the acknowledge on the falling edge hard to catch?
Because the answer is usually still present at the falling edge — a far end that holds its level until after SCL has gone low makes the two sampling instants indistinguishable. Catching it requires stimulus that changes SDA between the two candidate instants, which the testbench does by releasing the far end exactly as SCL falls.
14. Understanding Check
15. Summary
An ACK is a pulled-low ninth bit; a NACK is nobody doing anything. The asymmetry means a bus with no devices NACKs correctly, with no hardware participating — the default answer is "no" and it is free.
The acknowledge is a bit like any other. It obeys the data-valid rule, so a receiver must establish it while SCL is low; deciding late means emitting framing, not answering late.
Five conditions produce a NACK, and one bit cannot distinguish them. Narrowing them is done from outside the slot: which byte NACKed, how far into the transfer, whether it reproduces, and whether the master was reading.
Condition 5 is not an error. A master-receiver's final NACK ends every read, and treating it as a failure is the most common mistake in I²C driver and verification code alike.
An acknowledge is a liveness signal, not a receipt. It does not prove correctness, understanding, eventual effect, responder count, responder identity, or timing legality — and §11 is a production failure resting on the third of those.
Out of reset, report NACK. The safe default, matching what the bus itself does.
After a NACK the master has exactly two options: STOP, or repeated START to retry without losing the bus.
A timing fault is only observable if the stimulus changes something between the candidate sampling instants — the reason the falling-edge mutation needed a far end that releases exactly as SCL falls.
16. What Comes Next
The slot is now understood: what goes in it, what it means, and what it does not. What has been quietly assumed throughout is that somebody knows whose job it is to fill it — and this chapter's block takes that as an input called we_acknowledge without ever computing it.
Chapter 7.3 computes it, and resolves the question that confuses more beginners than any other on this bus: the acknowledge belongs to the receiver of a byte, which means the direction of the byte decides who answers — not whether a device is the master or the slave.
Browse the full path on the I²C tutorials index. For the slot this chapter fills, see Byte and Bit Transmission; for why several devices answering is indistinguishable from one, Wired-AND.
Continue learning
Related tutorials
- Related topic
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.
- Related topic
Master-Transmitter and Slave-Receiver Roles
A write has two sides and they are not symmetrical. This chapter splits the responsibilities bit slot by bit slot, then builds the slave-receiver that owns the register pointer, the auto-increment and the two NACK conditions the specification grants a receiver.
- Related topic
Why I²C Clock Stretching Exists
The one mechanism that lets a target push back on a clock it does not own. Covers the mismatch it solves, the specification's two stretching levels, and why 'optional' makes a non-stretching bus an electrical contract.
- Related topic
Bus Idle and the Framing Primitives
Module 4 proved that an SDA edge while SCL is high cannot be data, and that the bus reserves the pattern. This chapter collects that debt: what an idle bus is, why a shared bus must delimit its own transfers, and why exactly two reserved edges produce exactly three framing events.
