I²C · Module 9
Master-Receiver and Slave-Transmitter Roles
The master still owns SCL while the slave owns SDA — and the slave-transmitter has no way to refuse anything, because the ninth bit is not its to drive. This chapter derives that asymmetry and builds the slave side of a read.
Chapter 8.2 split a write into its two halves and found them asymmetrical. This chapter does the same for a read, and the asymmetry it finds is much sharper — sharp enough to change what a device can be designed to do.
The one-line version: a slave-receiver can say no; a slave-transmitter cannot.
A slave-receiver owns the ninth bit, so two of the specification's five NACK conditions are its to produce. A slave-transmitter owns bits one through eight and nothing else. The ninth bit belongs to the master, because the master is the receiver. So a slave-transmitter has no NACK available to it, no error code, and no field in the frame to put one in — and everything in §3 follows from that.
There is also a division of the two wires that trips people up on first contact, and it is worth settling immediately.
1. The Master Still Owns the Clock
In a read the data flows from slave to master. The clock does not change direction at all.
So during a read:
| wire | owned by | for how long |
|---|---|---|
| SCL | the master, always | the entire transfer, including the ninth pulse of every byte |
| SDA, bits 1–8 of a data byte | the slave | until the next S or Sr |
| SDA, bit 9 of a data byte | the master | until the next S or Sr |
| SDA, all nine bits of the address byte | master for 1–8, slave for 9 | that byte only |
The thing to hold onto is that the master clocks data it does not drive. It produces nine pulses per byte and supplies the content of only one of them. This is why a slave-transmitter is a fundamentally reactive device: it cannot advance the transfer, cannot slow it except by the one mechanism Module 12 covers, and cannot end it. It answers the clock it is given.
2. Nine Slots, and the Handover Inside the Byte
Here is one data byte of a read at slot resolution, with ownership drawn as its own rows. Compare it against Chapter 8.2 §2's figure: the drives SDA and samples SDA rows are swapped.
Read data byte 0xC3 — 1100 0011 — then the master's ACK
9 cyclesThree design rules are visible in that figure, and all three are the mirror of a rule established for the write.
The slave must release before the ninth slot, and it releases because the slot arrived — not because of the data. The byte 0xC3 is chosen deliberately: its LSB is 1, so SDA is already high at the end of the eighth slot. A slave that forgot to release would leave SDA high through the ninth slot, the master's ACK would be overridden by nothing, and the slot would read correctly by accident. Send 0xC2 instead and the same bug holds SDA low, the master's ACK is indistinguishable from the slave's leftover bit, and — worse — a NACK becomes impossible to express. Chapter 7.2 §4 found the identical trap on the transmitting master; it is the same trap, on the other device.
Nobody drives SDA high, ever. Chapter 2.3 applies to every cell of that figure. When the slave "drives a 1" it releases and the pull-up does the work. This is why the fill decision in §3 has a physically correct default rather than an arbitrary one.
The two sides run on opposite clock edges and neither may choose otherwise. The slave changes SDA on SCL falling; the master samples on SCL rising. For the ninth slot they swap. Chapter 7.1 §3 derived this from the data-valid window, and the consequence here is the one that matters for the design: the byte to transmit must be ready before the slot in which its first bit is driven, and the acknowledge must be consumed before the next byte is fetched.
3. A Slave-Transmitter Cannot Refuse
This is the chapter's centre. Chapter 8.2 §3 gave a slave-receiver two NACK conditions from §3.1.6 — data it does not understand, and no room for more. Both are exercised by driving the ninth bit.
A slave-transmitter does not drive the ninth bit. So:
| situation | what a slave-receiver does | what a slave-transmitter can do |
|---|---|---|
| the pointer names no register | NACK — condition 3 | nothing |
| no more data can be accepted | NACK — condition 4 | nothing |
| the read has run past the last register | — | nothing |
| the device is busy and needs time | NACK — condition 2, or stretch | stretch SCL only |
| the transfer should end | — | nothing: only the master can end it |
Four of those five rows are "nothing", and that is not an omission in the protocol so much as a consequence of the acknowledge being the receiver's signal. A transmitter that has nothing useful to send must send something anyway, because the master is clocking and the bus has no idle state inside a byte.
So the question a real device must answer is: what do you transmit when there is nothing to transmit? There are three available answers and they are not equally good.
That last point is worth keeping as a general principle: when the physical default of a bus produces a particular value, making that value the deliberate value costs nothing and converts an accident into a specification.
4. The Pointer Must Survive the Repeated START
A read almost never appears alone. The overwhelmingly common shape is a combined transfer: write the register pointer, repeated START, read the data. The specification describes exactly this, and its note is the one that constrains the design.
Those two notes pull in opposite directions and the design must satisfy both.
Note 4 says the repeated START resets the bus logic. Unconditionally, and even for a malformed Sr. So the transfer state — which byte we are on, how many we have sent, whether we are transmitting — must all clear.
Note 1 says the pointer written before the Sr is still in effect after it. That is the entire mechanism of a register read. If the Sr cleared the pointer, the read would start from register zero and the combined format would not work.
So the register pointer is the one piece of state that outlives a repeated START, and everything else goes. In the design below that is three lines of exception and a comment explaining why, and mutation B5 injects the natural-looking mistake of clearing it along with the rest.
5. The Slave-Transmitter as a Pipeline
Before the code, the block structure. Note what enters from the left and what does not.
As in Chapter 8.2, nothing in that diagram touches SDA or SCL. The block emits a byte and a release decision; the byte engine puts them on the wire. That is what makes it synthesisable on the system clock and testable with no bus model at all — the testbench in §6 drives framing pulses and byte requests directly.
6. The Slave-Transmitter in Three Languages
Three states, and the third one is where the acknowledge is consumed:
| state | meaning |
|---|---|
ST_IDLE | not addressed, not a read, or the master has ended the transfer |
ST_SEND | waiting to be asked for the next byte; fetches and presents it |
ST_SLOT | the ninth slot: SDA released, the master answers, and the answer decides what happens next |
// The slave-transmitter half of a read. It is the mirror of Chapter 8.2's
// slave-receiver, and the mirror is not symmetrical -- which is the whole point.
//
// A slave-RECEIVER owns the ninth bit, so it can refuse: conditions 3 and 4 of
// section 3.1.6 are its to produce. A slave-TRANSMITTER owns bits 1 through 8 and
// NOTHING ELSE. The ninth bit belongs to the master, because the master is the
// receiver. So this block has no way to say no. There is no NACK available to it, no
// error code, and no field in the frame to put one in.
//
// That is not a gap in the design. It is a property of the protocol, and every
// decision below follows from it.
module i2c_slave_read_transmitter #(
parameter int REG_ADDR_W = 4,
parameter int REG_COUNT = 12,
// What to transmit when the pointer has run past the end. 0xFF is not an arbitrary
// choice: on an open-drain bus a transmitter that drives nothing reads as all ones
// at the far end, so 0xFF is what the master would see anyway. Transmitting it
// deliberately makes the behaviour defined rather than incidental.
parameter logic [7:0] FILL = 8'hFF
)(
input logic clk,
input logic rst_n,
// ---- framing and addressing, from Modules 5 and 6 ----
input logic frame_start, // pulse: S or Sr
input logic frame_stop, // pulse: P
input logic addressed, // this transfer is for us (6.5)
input logic dir_is_read, // the latched R/W (6.5)
// ---- the register pointer, written by a preceding WRITE phase ----
// Specification note 1 to section 3.1.10: "The internal memory location must be
// written during the first data byte. After the START condition and slave address
// is repeated, data can be transferred." So the pointer must SURVIVE the repeated
// START that turns the write phase into a read phase -- see section 5a.
input logic ptr_load,
input logic [REG_ADDR_W-1:0] ptr_in,
// ---- the byte engine, from Chapter 7.1 ----
input logic byte_request, // pulse: the engine needs the next byte NOW
input logic ack_valid, // pulse: the master's ninth-bit answer is in
input logic ack_from_master, // 1 = ACK, send another. 0 = NACK, we are done.
// ---- the register file read side ----
// reg_addr is COMBINATIONAL from `ptr`, which is the exact OPPOSITE of the write
// port in Chapter 8.2 -- and the asymmetry is forced, not stylistic. See section 5a.
output logic [REG_ADDR_W-1:0] reg_addr,
input logic [7:0] reg_rdata,
// ---- what this block drives on the bus ----
output logic [7:0] tx_byte,
output logic tx_valid, // pulse: tx_byte is the byte to send
output logic transmitting, // this device owns bits 1..8 of the current byte
// The transmitter MUST release SDA for the ninth slot so the master can answer.
// This is asserted from the slot itself, never from the byte's value: Chapter 7.2
// section 4 showed that a byte whose LSB is 0 leaves SDA low anyway, so a design
// keyed to the data looks correct for half of all bytes.
output logic release_for_ack,
// ---- status ----
output logic [REG_ADDR_W-1:0] ptr,
output logic [7:0] bytes_sent,
output logic overread, // we transmitted FILL: past the end
output logic ended // pulse: the master NACKed; we stopped
);
typedef enum logic [1:0] {
ST_IDLE, // not addressed, or not a read, or the master has ended it
ST_SEND, // a byte is in flight, bits 1..8
ST_SLOT // the ninth slot: SDA released, the master answers
} state_e;
state_e state;
// Once the master has NACKed, this transfer is OVER -- and `addressed` is still
// asserted, because the address decoder of Chapter 6.5 holds its verdict until the
// next addressing. Without this latch the block re-arms on the very next cycle and
// transmits again, which puts a byte on the wire after the master has said stop.
// That byte holds SDA low through the master's STOP and prevents it forming: the
// bus hang of Chapter 7.4, produced by the SLAVE rather than the master.
//
// It is the mirror of Chapter 8.2's rule that a slave which has refused a byte says
// nothing further until re-addressed. Here it is the master who said no, and the
// consequence for this block is the same.
logic finished;
logic past_end;
assign past_end = (ptr >= REG_COUNT[REG_ADDR_W-1:0]);
// A WRITE port registers the address ALONGSIDE the data, because the pointer has
// already advanced by the time the write lands (Chapter 8.2, mutation B3). A READ
// port must do the opposite: present the address so that reg_rdata is already valid
// in the cycle the byte is captured. A registered reg_addr here would capture the
// data belonging to the PREVIOUS address -- the same off-by-one, mirrored.
//
// This is correct for a combinational register file. A register file with a
// REGISTERED read port needs one fetch cycle ahead of the capture, exactly as
// Chapter 8.1's WS_FETCH does; section 9 covers what that costs here.
assign reg_addr = ptr;
always_ff @(posedge clk) begin
if (!rst_n) begin
state <= ST_IDLE;
ptr <= '0;
tx_byte <= 8'h00;
tx_valid <= 1'b0;
transmitting <= 1'b0;
release_for_ack <= 1'b0;
bytes_sent <= 8'h00;
overread <= 1'b0;
ended <= 1'b0;
finished <= 1'b0;
end else begin
tx_valid <= 1'b0;
ended <= 1'b0;
// The pointer is loaded by the write phase and is the ONE piece of state
// that outlives the repeated START below.
if (ptr_load) ptr <= ptr_in;
if (frame_stop) begin
state <= ST_IDLE;
transmitting <= 1'b0;
release_for_ack <= 1'b0;
finished <= 1'b0;
end else if (frame_start) begin
// Specification note 4: a device must reset its bus logic on an S or Sr
// "such that they all anticipate the sending of a slave address". So the
// transfer state goes, unconditionally -- but `ptr` does NOT, because
// note 1 requires it to survive exactly this event.
state <= ST_IDLE;
transmitting <= 1'b0;
release_for_ack <= 1'b0;
bytes_sent <= 8'h00;
overread <= 1'b0;
finished <= 1'b0;
end else if (addressed && dir_is_read && !finished && state == ST_IDLE) begin
// Addressed for a read: we are the transmitter from here.
state <= ST_SEND;
end else begin
case (state)
ST_SEND: begin
if (byte_request) begin
// A slave-transmitter cannot refuse. If the pointer is past
// the end there is no register to read, and there is no way
// to say so on the bus -- so transmit a DEFINED fill byte
// and raise a flag this device's own driver can read back.
// Wrapping to register 0 is rejected for the reason Chapter
// 8.2 section 3 gives: it returns plausible wrong data.
if (past_end) begin
tx_byte <= FILL;
overread <= 1'b1;
end else begin
tx_byte <= reg_rdata; // already valid: reg_addr = ptr
ptr <= ptr + 1'b1;
end
tx_valid <= 1'b1;
transmitting <= 1'b1;
bytes_sent <= bytes_sent + 8'd1;
state <= ST_SLOT;
end
end
ST_SLOT: begin
// Release for the whole slot. Asserted on entry to the slot and
// held, so there is no window in which this device is still
// driving while the master is trying to pull SDA low.
transmitting <= 1'b0;
release_for_ack <= 1'b1;
if (ack_valid) begin
release_for_ack <= 1'b0;
if (ack_from_master) begin
// "send me another"
state <= ST_SEND;
end else begin
// The fifth NACK condition: "a master-receiver must
// signal the end of the transfer to the slave
// transmitter." This is that signal arriving. Stop
// transmitting NOW -- a byte sent after a NACK would
// hold SDA low through the master's STOP and prevent
// it forming at all.
state <= ST_IDLE;
ended <= 1'b1;
finished <= 1'b1;
end
end
end
default: begin
transmitting <= 1'b0;
release_for_ack <= 1'b0;
end
endcase
end
end
end
endmodule `timescale 1ns/1ps
module i2c_slave_read_transmitter_tb;
localparam int REG_ADDR_W = 4;
localparam int REG_COUNT = 12;
localparam logic [7:0] FILL = 8'hFF;
logic clk = 1'b0;
always #5 clk = ~clk;
logic rst_n = 1'b0;
logic frame_start = 1'b0, frame_stop = 1'b0;
logic addressed = 1'b0, dir_is_read = 1'b0;
logic ptr_load = 1'b0;
logic [REG_ADDR_W-1:0] ptr_in = '0;
logic byte_request = 1'b0, ack_valid = 1'b0, ack_from_master = 1'b1;
logic [REG_ADDR_W-1:0] reg_addr;
logic [7:0] reg_rdata;
logic [7:0] tx_byte;
logic tx_valid, transmitting, release_for_ack;
logic [REG_ADDR_W-1:0] ptr;
logic [7:0] bytes_sent;
logic overread, ended;
int errors = 0;
i2c_slave_read_transmitter #(.REG_ADDR_W(REG_ADDR_W), .REG_COUNT(REG_COUNT), .FILL(FILL))
dut (.*);
initial begin #200000; $display("FAIL: watchdog expired"); $finish; end
// The register file. Register k holds 0xk0 + k, so every register has a distinct,
// recognisable value and an off-by-one in the pointer is visible in the data.
logic [7:0] regs [0:15];
initial for (int i = 0; i < 16; i++) regs[i] = 8'((i << 4) | i);
assign reg_rdata = regs[reg_addr];
// ---- a continuous safety check ------------------------------------------------
// This device must never be driving the data bits and releasing for the
// acknowledge at the same instant. On an open-drain bus that would mean holding
// SDA low through the slot the master needs in order to answer.
always @(posedge clk) if (rst_n)
if (transmitting && release_for_ack) begin
$display("FAIL: transmitting and release_for_ack asserted together at t=%0t", $time);
errors++;
end
// ---- observation --------------------------------------------------------------
logic [7:0] sent_log [0:15];
int n_sent, n_ended;
logic obs_clear = 1'b0;
always @(posedge clk) if (rst_n) begin
if (obs_clear) begin n_sent = 0; n_ended = 0; end
else begin
if (tx_valid) begin if (n_sent < 16) sent_log[n_sent] = tx_byte; n_sent++; end
if (ended) n_ended++;
end
end
task automatic clear_obs();
obs_clear = 1'b1; @(negedge clk); obs_clear = 1'b0; @(negedge clk);
endtask
task automatic pulse_start(); frame_start = 1'b1; @(negedge clk); frame_start = 1'b0; @(negedge clk); endtask
task automatic pulse_stop(); frame_stop = 1'b1; @(negedge clk); frame_stop = 1'b0; @(negedge clk); endtask
task automatic load_ptr(input logic [REG_ADDR_W-1:0] v);
ptr_in = v; ptr_load = 1'b1; @(negedge clk); ptr_load = 1'b0; @(negedge clk);
endtask
// Address this device for a read: framing, then the decoder's verdict.
task automatic begin_read();
pulse_start();
addressed = 1'b1; dir_is_read = 1'b1;
repeat (2) @(negedge clk);
endtask
// One byte: the engine asks for it, the byte goes out, then the master answers in
// the ninth slot. `answer` is the MASTER's acknowledge -- 1 to continue, 0 to end.
task automatic wire_byte(input logic answer);
byte_request = 1'b1; @(negedge clk); byte_request = 1'b0; @(negedge clk);
// the ninth slot: the transmitter must have released by now
if (transmitting !== 1'b0) begin
$display("FAIL: still driving the data bits during the ninth slot"); errors++; end
if (release_for_ack !== 1'b1) begin
$display("FAIL: did not release SDA for the acknowledge slot"); errors++; end
ack_from_master = answer;
ack_valid = 1'b1; @(negedge clk); ack_valid = 1'b0; @(negedge clk);
endtask
initial begin
repeat (3) @(negedge clk);
if (transmitting !== 1'b0) begin $display("FAIL: driving out of reset"); errors++; end
if (release_for_ack !== 1'b0) begin $display("FAIL: releasing out of reset"); errors++; end
rst_n = 1'b1; @(negedge clk);
// ---- 1: a 3-byte read from pointer 2. The auto-increment must land on
// registers 2, 3 and 4 -- and the register VALUES prove it, because each
// register holds a distinct recognisable byte.
load_ptr(4'd2);
begin_read();
clear_obs();
wire_byte(1'b1); wire_byte(1'b1); wire_byte(1'b0); // ACK, ACK, NACK
if (n_sent !== 3) begin
$display("FAIL: transmitted %0d bytes, expected 3", n_sent); errors++; end
if (sent_log[0] !== 8'h22 || sent_log[1] !== 8'h33 || sent_log[2] !== 8'h44) begin
$display("FAIL: sent 0x%02h,0x%02h,0x%02h, expected 0x22,0x33,0x44",
sent_log[0], sent_log[1], sent_log[2]); errors++; end
if (bytes_sent !== 8'd3) begin
$display("FAIL: bytes_sent = %0d, expected 3", bytes_sent); errors++; end
if (overread !== 1'b0) begin
$display("FAIL: spurious overread on an in-range read"); errors++; end
// ---- 2: the NACK ended it. `ended` must have pulsed exactly once, and a
// further byte_request must transmit NOTHING -- a byte sent after the
// master's NACK holds SDA low through the STOP and prevents it forming.
if (n_ended !== 1) begin
$display("FAIL: %0d ended pulses, expected 1", n_ended); errors++; end
byte_request = 1'b1; @(negedge clk); byte_request = 1'b0; @(negedge clk);
if (transmitting !== 1'b0) begin
$display("FAIL: transmitted a byte AFTER the master's NACK"); errors++; end
if (n_sent !== 3) begin
$display("FAIL: %0d bytes sent, expected 3 -- one escaped after the NACK", n_sent);
errors++; end
pulse_stop();
addressed = 1'b0;
// ---- 3: the pointer SURVIVES a repeated START. Specification note 1 to
// section 3.1.10 requires exactly this: the location is written during
// the write phase, then "after the START condition and slave address is
// repeated, data can be transferred".
load_ptr(4'd5);
pulse_start(); // the Sr that turns a write into a read
if (ptr !== 4'd5) begin
$display("FAIL: the repeated START destroyed the register pointer (%0d)", ptr);
errors++; end
addressed = 1'b1; dir_is_read = 1'b1;
repeat (2) @(negedge clk);
clear_obs();
wire_byte(1'b0);
if (sent_log[0] !== 8'h55) begin
$display("FAIL: post-Sr read sent 0x%02h, expected 0x55 from register 5",
sent_log[0]); errors++; end
pulse_stop();
addressed = 1'b0;
// ---- 4: OVER-READ. Pointer 11 is the last valid register, so the first byte
// is real and everything after it is past the end. A slave-transmitter
// cannot refuse, so it must send a DEFINED fill -- and must NOT wrap to
// register 0, which would return plausible wrong data.
load_ptr(4'd11);
begin_read();
clear_obs();
wire_byte(1'b1); wire_byte(1'b1); wire_byte(1'b0);
if (sent_log[0] !== 8'hBB) begin
$display("FAIL: register 11 read as 0x%02h, expected 0xbb", sent_log[0]);
errors++; end
if (sent_log[1] !== FILL || sent_log[2] !== FILL) begin
$display("FAIL: past the end sent 0x%02h,0x%02h, expected fill 0x%02h twice",
sent_log[1], sent_log[2], FILL); errors++; end
if (sent_log[1] === 8'h00 || sent_log[2] === 8'h00) begin
$display("FAIL: an over-read WRAPPED to register 0"); errors++; end
if (overread !== 1'b1) begin
$display("FAIL: overread not flagged"); errors++; end
pulse_stop();
addressed = 1'b0;
// ---- 5: a transfer addressed to SOMEBODY ELSE. This device must not drive
// a single bit, however many bytes the engine asks for.
load_ptr(4'd3);
pulse_start();
addressed = 1'b0; dir_is_read = 1'b1;
repeat (2) @(negedge clk);
clear_obs();
byte_request = 1'b1; @(negedge clk); byte_request = 1'b0; @(negedge clk);
if (transmitting !== 1'b0 || n_sent !== 0) begin
$display("FAIL: transmitted during somebody else's read"); errors++; end
pulse_stop();
// ---- 6: addressed for a WRITE. This block is the READ transmitter, so it
// must stay silent -- the mirror of Chapter 8.2's test 6. The pointer is
// left at a VALID register so that a block which ignored dir_is_read
// would actually transmit, rather than being caught by an over-read for
// the wrong reason.
load_ptr(4'd6);
pulse_start();
addressed = 1'b1; dir_is_read = 1'b0;
repeat (2) @(negedge clk);
clear_obs();
byte_request = 1'b1; @(negedge clk); byte_request = 1'b0; @(negedge clk);
if (transmitting !== 1'b0 || n_sent !== 0) begin
$display("FAIL: the read transmitter drove a byte during a WRITE"); errors++; end
if (overread !== 1'b0) begin
$display("FAIL: a write transfer produced an overread verdict"); errors++; end
pulse_stop();
addressed = 1'b0;
// ---- 7: a frame_start clears the transfer state but NOT the pointer. Both
// halves matter: note 4 demands the reset, note 1 demands the exception.
load_ptr(4'd7);
begin_read();
clear_obs();
wire_byte(1'b1);
if (bytes_sent !== 8'd1) begin
$display("FAIL: setup for test 7 -- bytes_sent = %0d", bytes_sent); errors++; end
pulse_start();
if (bytes_sent !== 8'd0) begin
$display("FAIL: a repeated START did not clear bytes_sent (%0d)", bytes_sent);
errors++; end
if (transmitting !== 1'b0 || release_for_ack !== 1'b0) begin
$display("FAIL: still driving after a repeated START"); errors++; end
if (ptr !== 4'd8) begin
$display("FAIL: the pointer should be 8 after one byte from 7, saw %0d", ptr);
errors++; end
pulse_stop();
addressed = 1'b0;
if (errors == 0)
$display("PASS: auto-increment correct, releases every slot, stops on the master's NACK, fills past the end without wrapping, pointer survives Sr");
else $display("FAIL: %0d error(s)", errors);
$finish;
end
endmodule // The slave-transmitter half of a read. (Verilog-2001) It is the mirror of Chapter 8.2's
// slave-receiver, and the mirror is not symmetrical -- which is the whole point.
//
// A slave-RECEIVER owns the ninth bit, so it can refuse: conditions 3 and 4 of
// section 3.1.6 are its to produce. A slave-TRANSMITTER owns bits 1 through 8 and
// NOTHING ELSE. The ninth bit belongs to the master, because the master is the
// receiver. So this block has no way to say no. There is no NACK available to it, no
// error code, and no field in the frame to put one in.
//
// That is not a gap in the design. It is a property of the protocol, and every
// decision below follows from it.
module i2c_slave_read_transmitter #(
parameter REG_ADDR_W = 4,
parameter REG_COUNT = 12,
// What to transmit when the pointer has run past the end. 0xFF is not an arbitrary
// choice: on an open-drain bus a transmitter that drives nothing reads as all ones
// at the far end, so 0xFF is what the master would see anyway. Transmitting it
// deliberately makes the behaviour defined rather than incidental.
parameter [7:0] FILL = 8'hFF
)(
input wire clk,
input wire rst_n,
// ---- framing and addressing, from Modules 5 and 6 ----
input wire frame_start, // pulse: S or Sr
input wire frame_stop, // pulse: P
input wire addressed, // this transfer is for us (6.5)
input wire dir_is_read, // the latched R/W (6.5)
// ---- the register pointer, written by a preceding WRITE phase ----
// Specification note 1 to section 3.1.10: "The internal memory location must be
// written during the first data byte. After the START condition and slave address
// is repeated, data can be transferred." So the pointer must SURVIVE the repeated
// START that turns the write phase into a read phase -- see section 5a.
input wire ptr_load,
input wire [REG_ADDR_W-1:0] ptr_in,
// ---- the byte engine, from Chapter 7.1 ----
input wire byte_request, // pulse: the engine needs the next byte NOW
input wire ack_valid, // pulse: the master's ninth-bit answer is in
input wire ack_from_master, // 1 = ACK, send another. 0 = NACK, we are done.
// ---- the register file read side ----
// reg_addr is COMBINATIONAL from `ptr`, which is the exact OPPOSITE of the write
// port in Chapter 8.2 -- and the asymmetry is forced, not stylistic. See section 5a.
output wire [REG_ADDR_W-1:0] reg_addr,
input wire [7:0] reg_rdata,
// ---- what this block drives on the bus ----
output reg [7:0] tx_byte,
output reg tx_valid, // pulse: tx_byte is the byte to send
output reg transmitting, // this device owns bits 1..8 of the current byte
// The transmitter MUST release SDA for the ninth slot so the master can answer.
// This is asserted from the slot itself, never from the byte's value: Chapter 7.2
// section 4 showed that a byte whose LSB is 0 leaves SDA low anyway, so a design
// keyed to the data looks correct for half of all bytes.
output reg release_for_ack,
// ---- status ----
output reg [REG_ADDR_W-1:0] ptr,
output reg [7:0] bytes_sent,
output reg overread, // we transmitted FILL: past the end
output reg ended // pulse: the master NACKed; we stopped
);
localparam ST_IDLE = 2'd0; // not addressed, or not a read, or the master ended it
localparam ST_SEND = 2'd1; // a byte is in flight, bits 1..8
localparam ST_SLOT = 2'd2; // the ninth slot: SDA released, the master answers
reg [1:0] state;
// Once the master has NACKed, this transfer is OVER -- and `addressed` is still
// asserted, because the address decoder of Chapter 6.5 holds its verdict until the
// next addressing. Without this latch the block re-arms on the very next cycle and
// transmits again, which puts a byte on the wire after the master has said stop.
// That byte holds SDA low through the master's STOP and prevents it forming: the
// bus hang of Chapter 7.4, produced by the SLAVE rather than the master.
//
// It is the mirror of Chapter 8.2's rule that a slave which has refused a byte says
// nothing further until re-addressed. Here it is the master who said no, and the
// consequence for this block is the same.
reg finished;
wire past_end;
assign past_end = (ptr >= REG_COUNT[REG_ADDR_W-1:0]);
// A WRITE port registers the address ALONGSIDE the data, because the pointer has
// already advanced by the time the write lands (Chapter 8.2, mutation B3). A READ
// port must do the opposite: present the address so that reg_rdata is already valid
// in the cycle the byte is captured. A registered reg_addr here would capture the
// data belonging to the PREVIOUS address -- the same off-by-one, mirrored.
//
// This is correct for a combinational register file. A register file with a
// REGISTERED read port needs one fetch cycle ahead of the capture, exactly as
// Chapter 8.1's WS_FETCH does; section 9 covers what that costs here.
assign reg_addr = ptr;
always @(posedge clk) begin
if (!rst_n) begin
state <= ST_IDLE;
ptr <= {REG_ADDR_W{1'b0}};
tx_byte <= 8'h00;
tx_valid <= 1'b0;
transmitting <= 1'b0;
release_for_ack <= 1'b0;
bytes_sent <= 8'h00;
overread <= 1'b0;
ended <= 1'b0;
finished <= 1'b0;
end else begin
tx_valid <= 1'b0;
ended <= 1'b0;
// The pointer is loaded by the write phase and is the ONE piece of state
// that outlives the repeated START below.
if (ptr_load) ptr <= ptr_in;
if (frame_stop) begin
state <= ST_IDLE;
transmitting <= 1'b0;
release_for_ack <= 1'b0;
finished <= 1'b0;
end else if (frame_start) begin
// Specification note 4: a device must reset its bus logic on an S or Sr
// "such that they all anticipate the sending of a slave address". So the
// transfer state goes, unconditionally -- but `ptr` does NOT, because
// note 1 requires it to survive exactly this event.
state <= ST_IDLE;
transmitting <= 1'b0;
release_for_ack <= 1'b0;
bytes_sent <= 8'h00;
overread <= 1'b0;
finished <= 1'b0;
end else if (addressed && dir_is_read && !finished && state == ST_IDLE) begin
// Addressed for a read: we are the transmitter from here.
state <= ST_SEND;
end else begin
case (state)
ST_SEND: begin
if (byte_request) begin
// A slave-transmitter cannot refuse. If the pointer is past
// the end there is no register to read, and there is no way
// to say so on the bus -- so transmit a DEFINED fill byte
// and raise a flag this device's own driver can read back.
// Wrapping to register 0 is rejected for the reason Chapter
// 8.2 section 3 gives: it returns plausible wrong data.
if (past_end) begin
tx_byte <= FILL;
overread <= 1'b1;
end else begin
tx_byte <= reg_rdata; // already valid: reg_addr = ptr
ptr <= ptr + 1'b1;
end
tx_valid <= 1'b1;
transmitting <= 1'b1;
bytes_sent <= bytes_sent + 8'd1;
state <= ST_SLOT;
end
end
ST_SLOT: begin
// Release for the whole slot. Asserted on entry to the slot and
// held, so there is no window in which this device is still
// driving while the master is trying to pull SDA low.
transmitting <= 1'b0;
release_for_ack <= 1'b1;
if (ack_valid) begin
release_for_ack <= 1'b0;
if (ack_from_master) begin
// "send me another"
state <= ST_SEND;
end else begin
// The fifth NACK condition: "a master-receiver must
// signal the end of the transfer to the slave
// transmitter." This is that signal arriving. Stop
// transmitting NOW -- a byte sent after a NACK would
// hold SDA low through the master's STOP and prevent
// it forming at all.
state <= ST_IDLE;
ended <= 1'b1;
finished <= 1'b1;
end
end
end
default: begin
transmitting <= 1'b0;
release_for_ack <= 1'b0;
end
endcase
end
end
end
endmodule `timescale 1ns/1ps
module i2c_slave_read_transmitter_tb; // Verilog-2001
localparam REG_ADDR_W = 4;
localparam REG_COUNT = 12;
localparam [7:0] FILL = 8'hFF;
reg clk = 1'b0;
always #5 clk = ~clk;
reg rst_n = 1'b0;
reg frame_start = 1'b0, frame_stop = 1'b0;
reg addressed = 1'b0, dir_is_read = 1'b0;
reg ptr_load = 1'b0;
reg [REG_ADDR_W-1:0] ptr_in = {REG_ADDR_W{1'b0}};
reg byte_request = 1'b0, ack_valid = 1'b0, ack_from_master = 1'b1;
wire [REG_ADDR_W-1:0] reg_addr;
wire [7:0] reg_rdata;
wire [7:0] tx_byte;
wire tx_valid, transmitting, release_for_ack;
wire [REG_ADDR_W-1:0] ptr;
wire [7:0] bytes_sent;
wire overread, ended;
integer errors = 0;
integer i;
i2c_slave_read_transmitter #(.REG_ADDR_W(REG_ADDR_W), .REG_COUNT(REG_COUNT), .FILL(FILL))
dut (.clk(clk), .rst_n(rst_n), .frame_start(frame_start), .frame_stop(frame_stop),
.addressed(addressed), .dir_is_read(dir_is_read), .ptr_load(ptr_load),
.ptr_in(ptr_in), .byte_request(byte_request), .ack_valid(ack_valid),
.ack_from_master(ack_from_master), .reg_addr(reg_addr), .reg_rdata(reg_rdata),
.tx_byte(tx_byte), .tx_valid(tx_valid), .transmitting(transmitting),
.release_for_ack(release_for_ack), .ptr(ptr), .bytes_sent(bytes_sent),
.overread(overread), .ended(ended));
initial begin #200000; $display("FAIL: watchdog expired"); $finish; end
// The register file. Register k holds 0xk0 + k, so every register has a distinct,
// recognisable value and an off-by-one in the pointer is visible in the data.
reg [7:0] regs [0:15];
initial for (i = 0; i < 16; i = i + 1) regs[i] = ((i << 4) | i);
assign reg_rdata = regs[reg_addr];
// ---- a continuous safety check ------------------------------------------------
// This device must never be driving the data bits and releasing for the
// acknowledge at the same instant. On an open-drain bus that would mean holding
// SDA low through the slot the master needs in order to answer.
always @(posedge clk) if (rst_n)
if (transmitting && release_for_ack) begin
$display("FAIL: transmitting and release_for_ack asserted together at t=%0t", $time);
errors = errors + 1;
end
// ---- observation --------------------------------------------------------------
reg [7:0] sent_log [0:15];
integer n_sent = 0, n_ended = 0;
reg obs_clear = 1'b0;
always @(posedge clk) if (rst_n) begin
if (obs_clear) begin n_sent = 0; n_ended = 0; end
else begin
if (tx_valid) begin if (n_sent < 16) sent_log[n_sent] = tx_byte; n_sent = n_sent + 1; end
if (ended) n_ended = n_ended + 1;
end
end
task clear_obs; begin
obs_clear = 1'b1; @(negedge clk); obs_clear = 1'b0; @(negedge clk);
end endtask
task pulse_start; begin frame_start = 1'b1; @(negedge clk); frame_start = 1'b0; @(negedge clk); end endtask
task pulse_stop; begin frame_stop = 1'b1; @(negedge clk); frame_stop = 1'b0; @(negedge clk); end endtask
task load_ptr;
input [REG_ADDR_W-1:0] v;
begin
ptr_in = v; ptr_load = 1'b1; @(negedge clk); ptr_load = 1'b0; @(negedge clk);
end
endtask
// Address this device for a read: framing, then the decoder's verdict.
task begin_read;
begin
pulse_start;
addressed = 1'b1; dir_is_read = 1'b1;
repeat (2) @(negedge clk);
end
endtask
// One byte: the engine asks for it, the byte goes out, then the master answers in
// the ninth slot. `answer` is the MASTER's acknowledge -- 1 to continue, 0 to end.
task wire_byte;
input answer;
begin
byte_request = 1'b1; @(negedge clk); byte_request = 1'b0; @(negedge clk);
// the ninth slot: the transmitter must have released by now
if (transmitting !== 1'b0) begin
$display("FAIL: still driving the data bits during the ninth slot"); errors = errors + 1; end
if (release_for_ack !== 1'b1) begin
$display("FAIL: did not release SDA for the acknowledge slot"); errors = errors + 1; end
ack_from_master = answer;
ack_valid = 1'b1; @(negedge clk); ack_valid = 1'b0; @(negedge clk);
end
endtask
initial begin
repeat (3) @(negedge clk);
if (transmitting !== 1'b0) begin $display("FAIL: driving out of reset"); errors = errors + 1; end
if (release_for_ack !== 1'b0) begin $display("FAIL: releasing out of reset"); errors = errors + 1; end
rst_n = 1'b1; @(negedge clk);
// ---- 1: a 3-byte read from pointer 2. The auto-increment must land on
// registers 2, 3 and 4 -- and the register VALUES prove it, because each
// register holds a distinct recognisable byte.
load_ptr(4'd2);
begin_read;
clear_obs;
wire_byte(1'b1); wire_byte(1'b1); wire_byte(1'b0); // ACK, ACK, NACK
if (n_sent !== 3) begin
$display("FAIL: transmitted %0d bytes, expected 3", n_sent); errors = errors + 1; end
if (sent_log[0] !== 8'h22 || sent_log[1] !== 8'h33 || sent_log[2] !== 8'h44) begin
$display("FAIL: sent 0x%02h,0x%02h,0x%02h, expected 0x22,0x33,0x44",
sent_log[0], sent_log[1], sent_log[2]); errors = errors + 1; end
if (bytes_sent !== 8'd3) begin
$display("FAIL: bytes_sent = %0d, expected 3", bytes_sent); errors = errors + 1; end
if (overread !== 1'b0) begin
$display("FAIL: spurious overread on an in-range read"); errors = errors + 1; end
// ---- 2: the NACK ended it. `ended` must have pulsed exactly once, and a
// further byte_request must transmit NOTHING -- a byte sent after the
// master's NACK holds SDA low through the STOP and prevents it forming.
if (n_ended !== 1) begin
$display("FAIL: %0d ended pulses, expected 1", n_ended); errors = errors + 1; end
byte_request = 1'b1; @(negedge clk); byte_request = 1'b0; @(negedge clk);
if (transmitting !== 1'b0) begin
$display("FAIL: transmitted a byte AFTER the master's NACK"); errors = errors + 1; end
if (n_sent !== 3) begin
$display("FAIL: %0d bytes sent, expected 3 -- one escaped after the NACK", n_sent);
errors = errors + 1; end
pulse_stop;
addressed = 1'b0;
// ---- 3: the pointer SURVIVES a repeated START. Specification note 1 to
// section 3.1.10 requires exactly this: the location is written during
// the write phase, then "after the START condition and slave address is
// repeated, data can be transferred".
load_ptr(4'd5);
pulse_start; // the Sr that turns a write into a read
if (ptr !== 4'd5) begin
$display("FAIL: the repeated START destroyed the register pointer (%0d)", ptr);
errors = errors + 1; end
addressed = 1'b1; dir_is_read = 1'b1;
repeat (2) @(negedge clk);
clear_obs;
wire_byte(1'b0);
if (sent_log[0] !== 8'h55) begin
$display("FAIL: post-Sr read sent 0x%02h, expected 0x55 from register 5",
sent_log[0]); errors = errors + 1; end
pulse_stop;
addressed = 1'b0;
// ---- 4: OVER-READ. Pointer 11 is the last valid register, so the first byte
// is real and everything after it is past the end. A slave-transmitter
// cannot refuse, so it must send a DEFINED fill -- and must NOT wrap to
// register 0, which would return plausible wrong data.
load_ptr(4'd11);
begin_read;
clear_obs;
wire_byte(1'b1); wire_byte(1'b1); wire_byte(1'b0);
if (sent_log[0] !== 8'hBB) begin
$display("FAIL: register 11 read as 0x%02h, expected 0xbb", sent_log[0]);
errors = errors + 1; end
if (sent_log[1] !== FILL || sent_log[2] !== FILL) begin
$display("FAIL: past the end sent 0x%02h,0x%02h, expected fill 0x%02h twice",
sent_log[1], sent_log[2], FILL); errors = errors + 1; end
if (sent_log[1] === 8'h00 || sent_log[2] === 8'h00) begin
$display("FAIL: an over-read WRAPPED to register 0"); errors = errors + 1; end
if (overread !== 1'b1) begin
$display("FAIL: overread not flagged"); errors = errors + 1; end
pulse_stop;
addressed = 1'b0;
// ---- 5: a transfer addressed to SOMEBODY ELSE. This device must not drive
// a single bit, however many bytes the engine asks for.
load_ptr(4'd3);
pulse_start;
addressed = 1'b0; dir_is_read = 1'b1;
repeat (2) @(negedge clk);
clear_obs;
byte_request = 1'b1; @(negedge clk); byte_request = 1'b0; @(negedge clk);
if (transmitting !== 1'b0 || n_sent !== 0) begin
$display("FAIL: transmitted during somebody else's read"); errors = errors + 1; end
pulse_stop;
// ---- 6: addressed for a WRITE. This block is the READ transmitter, so it
// must stay silent -- the mirror of Chapter 8.2's test 6. The pointer is
// left at a VALID register so that a block which ignored dir_is_read
// would actually transmit, rather than being caught by an over-read for
// the wrong reason.
load_ptr(4'd6);
pulse_start;
addressed = 1'b1; dir_is_read = 1'b0;
repeat (2) @(negedge clk);
clear_obs;
byte_request = 1'b1; @(negedge clk); byte_request = 1'b0; @(negedge clk);
if (transmitting !== 1'b0 || n_sent !== 0) begin
$display("FAIL: the read transmitter drove a byte during a WRITE"); errors = errors + 1; end
if (overread !== 1'b0) begin
$display("FAIL: a write transfer produced an overread verdict"); errors = errors + 1; end
pulse_stop;
addressed = 1'b0;
// ---- 7: a frame_start clears the transfer state but NOT the pointer. Both
// halves matter: note 4 demands the reset, note 1 demands the exception.
load_ptr(4'd7);
begin_read;
clear_obs;
wire_byte(1'b1);
if (bytes_sent !== 8'd1) begin
$display("FAIL: setup for test 7 -- bytes_sent = %0d", bytes_sent); errors = errors + 1; end
pulse_start;
if (bytes_sent !== 8'd0) begin
$display("FAIL: a repeated START did not clear bytes_sent (%0d)", bytes_sent);
errors = errors + 1; end
if (transmitting !== 1'b0 || release_for_ack !== 1'b0) begin
$display("FAIL: still driving after a repeated START"); errors = errors + 1; end
if (ptr !== 4'd8) begin
$display("FAIL: the pointer should be 8 after one byte from 7, saw %0d", ptr);
errors = errors + 1; end
pulse_stop;
addressed = 1'b0;
if (errors == 0)
$display("PASS: auto-increment correct, releases every slot, stops on the master's NACK, fills past the end without wrapping, pointer survives Sr");
else $display("FAIL: %0d error(s)", errors);
$finish;
end
endmodule library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
-- The slave-transmitter half of a read. It is the mirror of Chapter 8.2's
-- slave-receiver, and the mirror is not symmetrical -- which is the whole point.
--
-- A slave-RECEIVER owns the ninth bit, so it can refuse: conditions 3 and 4 of
-- section 3.1.6 are its to produce. A slave-TRANSMITTER owns bits 1 through 8 and
-- NOTHING ELSE. The ninth bit belongs to the master, because the master is the
-- receiver. So this block has no way to say no. There is no NACK available to it, no
-- error code, and no field in the frame to put one in.
--
-- That is not a gap in the design. It is a property of the protocol, and every
-- decision below follows from it.
entity i2c_slave_read_transmitter is
generic (
REG_ADDR_W : positive := 4;
REG_COUNT : positive := 12;
-- What to transmit when the pointer has run past the end. 0xFF is not an
-- arbitrary choice: on an open-drain bus a transmitter that drives nothing
-- reads as all ones at the far end, so 0xFF is what the master would see
-- anyway. Transmitting it deliberately makes the behaviour defined.
FILL : std_logic_vector(7 downto 0) := x"FF"
);
port (
clk : in std_logic;
rst_n : in std_logic;
-- framing and addressing, from Modules 5 and 6
frame_start : in std_logic; -- pulse: S or Sr
frame_stop : in std_logic; -- pulse: P
addressed : in std_logic; -- this transfer is for us (6.5)
dir_is_read : in std_logic; -- the latched R/W (6.5)
-- the register pointer, written by a preceding WRITE phase.
-- Specification note 1 to section 3.1.10: "The internal memory location must be
-- written during the first data byte. After the START condition and slave
-- address is repeated, data can be transferred." So the pointer must SURVIVE
-- the repeated START that turns the write phase into a read phase.
ptr_load : in std_logic;
ptr_in : in unsigned(REG_ADDR_W - 1 downto 0);
-- the byte engine, from Chapter 7.1
byte_request : in std_logic; -- pulse: the engine needs the next byte NOW
ack_valid : in std_logic; -- pulse: the master's ninth-bit answer is in
ack_from_master : in std_logic; -- 1 = ACK, send another. 0 = NACK, we are done.
-- the register file read side. reg_addr is COMBINATIONAL from ptr, which is the
-- exact OPPOSITE of the write port in Chapter 8.2 -- forced, not stylistic.
reg_addr : out unsigned(REG_ADDR_W - 1 downto 0);
reg_rdata : in std_logic_vector(7 downto 0);
-- what this block drives on the bus
tx_byte : out std_logic_vector(7 downto 0);
tx_valid : out std_logic; -- pulse: tx_byte is the byte to send
transmitting : out std_logic; -- this device owns bits 1..8 of the current byte
-- The transmitter MUST release SDA for the ninth slot so the master can answer.
-- Asserted from the slot itself, never from the byte's value: Chapter 7.2
-- section 4 showed that a byte whose LSB is 0 leaves SDA low anyway, so a design
-- keyed to the data looks correct for half of all bytes.
release_for_ack : out std_logic;
-- status
ptr : out unsigned(REG_ADDR_W - 1 downto 0);
bytes_sent : out unsigned(7 downto 0);
overread : out std_logic; -- we transmitted FILL: past the end
ended : out std_logic -- pulse: the master NACKed; we stopped
);
end entity;
architecture rtl of i2c_slave_read_transmitter is
type state_t is (
ST_IDLE, -- not addressed, or not a read, or the master has ended it
ST_SEND, -- a byte is in flight, bits 1..8
ST_SLOT -- the ninth slot: SDA released, the master answers
);
signal state : state_t := ST_IDLE;
-- Once the master has NACKed, this transfer is OVER -- and `addressed` is still
-- asserted, because the address decoder of Chapter 6.5 holds its verdict until the
-- next addressing. Without this latch the block re-arms on the very next cycle and
-- transmits again, which puts a byte on the wire after the master has said stop.
-- That byte holds SDA low through the master's STOP and prevents it forming: the
-- bus hang of Chapter 7.4, produced by the SLAVE rather than the master.
signal finished : std_logic := '0';
signal ptr_i : unsigned(REG_ADDR_W - 1 downto 0) := (others => '0');
signal past_end : std_logic;
begin
-- A WRITE port registers the address ALONGSIDE the data, because the pointer has
-- already advanced by the time the write lands (Chapter 8.2, mutation B3). A READ
-- port must do the opposite: present the address so that reg_rdata is already valid
-- in the cycle the byte is captured. A registered reg_addr here would capture the
-- data belonging to the PREVIOUS address -- the same off-by-one, mirrored.
reg_addr <= ptr_i;
ptr <= ptr_i;
past_end <= '1' when ptr_i >= to_unsigned(REG_COUNT, REG_ADDR_W) else '0';
process (clk)
begin
if rising_edge(clk) then
if rst_n = '0' then
state <= ST_IDLE;
ptr_i <= (others => '0');
tx_byte <= (others => '0');
tx_valid <= '0';
transmitting <= '0';
release_for_ack <= '0';
bytes_sent <= (others => '0');
overread <= '0';
ended <= '0';
finished <= '0';
else
tx_valid <= '0';
ended <= '0';
-- The pointer is loaded by the write phase and is the ONE piece of
-- state that outlives the repeated START below.
if ptr_load = '1' then ptr_i <= ptr_in; end if;
if frame_stop = '1' then
state <= ST_IDLE;
transmitting <= '0';
release_for_ack <= '0';
finished <= '0';
elsif frame_start = '1' then
-- Specification note 4: a device must reset its bus logic on an S or
-- Sr "such that they all anticipate the sending of a slave address".
-- So the transfer state goes, unconditionally -- but ptr_i does NOT,
-- because note 1 requires it to survive exactly this event.
state <= ST_IDLE;
transmitting <= '0';
release_for_ack <= '0';
bytes_sent <= (others => '0');
overread <= '0';
finished <= '0';
elsif addressed = '1' and dir_is_read = '1' and finished = '0'
and state = ST_IDLE then
-- Addressed for a read: we are the transmitter from here.
state <= ST_SEND;
else
case state is
when ST_SEND =>
if byte_request = '1' then
-- A slave-transmitter cannot refuse. If the pointer is
-- past the end there is no register to read, and there
-- is no way to say so on the bus -- so transmit a
-- DEFINED fill byte and raise a flag this device's own
-- driver can read back. Wrapping to register 0 is
-- rejected for the reason Chapter 8.2 section 3 gives:
-- it returns plausible wrong data.
if past_end = '1' then
tx_byte <= FILL;
overread <= '1';
else
tx_byte <= reg_rdata; -- valid: reg_addr = ptr_i
ptr_i <= ptr_i + 1;
end if;
tx_valid <= '1';
transmitting <= '1';
bytes_sent <= bytes_sent + 1;
state <= ST_SLOT;
end if;
when ST_SLOT =>
-- Release for the whole slot. Asserted on entry and held, so
-- there is no window in which this device is still driving
-- while the master is trying to pull SDA low.
transmitting <= '0';
release_for_ack <= '1';
if ack_valid = '1' then
release_for_ack <= '0';
if ack_from_master = '1' then
state <= ST_SEND; -- "send me another"
else
-- The fifth NACK condition: "a master-receiver must
-- signal the end of the transfer to the slave
-- transmitter." This is that signal arriving. Stop
-- transmitting NOW -- a byte sent after a NACK would
-- hold SDA low through the master's STOP and prevent
-- it forming at all.
state <= ST_IDLE;
ended <= '1';
finished <= '1';
end if;
end if;
when others =>
transmitting <= '0';
release_for_ack <= '0';
end case;
end if;
end if;
end if;
end process;
end architecture; library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
-- Every signal here has exactly ONE driving process, because VHDL permits one driver
-- per signal -- and the SystemVerilog and Verilog testbenches were written to the same
-- discipline so that the matching finish time between the three means something.
entity i2c_slave_read_transmitter_tb is
end entity;
architecture sim of i2c_slave_read_transmitter_tb is
constant REG_ADDR_W : positive := 4;
constant REG_COUNT : positive := 12;
constant FILL : std_logic_vector(7 downto 0) := x"FF";
signal clk : std_logic := '0';
signal rst_n : std_logic := '0';
signal frame_start, frame_stop : std_logic := '0';
signal addressed, dir_is_read : std_logic := '0';
signal ptr_load : std_logic := '0';
signal ptr_in : unsigned(REG_ADDR_W - 1 downto 0) := (others => '0');
signal byte_request, ack_valid : std_logic := '0';
signal ack_from_master : std_logic := '1';
signal reg_addr : unsigned(REG_ADDR_W - 1 downto 0);
signal reg_rdata : std_logic_vector(7 downto 0);
signal tx_byte : std_logic_vector(7 downto 0);
signal tx_valid, transmitting, release_for_ack : std_logic;
signal ptr : unsigned(REG_ADDR_W - 1 downto 0);
signal bytes_sent : unsigned(7 downto 0);
signal overread, ended : std_logic;
-- The register file. Register k holds 0xk0 + k, so every register has a distinct,
-- recognisable value and an off-by-one in the pointer is visible in the data.
type reg_arr is array (0 to 15) of std_logic_vector(7 downto 0);
function init_regs return reg_arr is
variable r : reg_arr;
begin
for i in 0 to 15 loop
r(i) := std_logic_vector(to_unsigned(i * 16 + i, 8));
end loop;
return r;
end function;
constant REGS : reg_arr := init_regs;
-- observation, owned solely by the observe process
type byte_arr is array (0 to 15) of std_logic_vector(7 downto 0);
signal sent_log : byte_arr := (others => (others => '0'));
signal n_sent, n_ended : natural := 0;
signal obs_clear : std_logic := '0';
signal errs_cont : natural := 0; -- errors found by the continuous check
signal test_done : std_logic := '0';
begin
dut : entity work.i2c_slave_read_transmitter
generic map (REG_ADDR_W => REG_ADDR_W, REG_COUNT => REG_COUNT, FILL => FILL)
port map (clk => clk, rst_n => rst_n, frame_start => frame_start,
frame_stop => frame_stop, addressed => addressed,
dir_is_read => dir_is_read, ptr_load => ptr_load, ptr_in => ptr_in,
byte_request => byte_request, ack_valid => ack_valid,
ack_from_master => ack_from_master, reg_addr => reg_addr,
reg_rdata => reg_rdata, tx_byte => tx_byte, tx_valid => tx_valid,
transmitting => transmitting, release_for_ack => release_for_ack,
ptr => ptr, bytes_sent => bytes_sent, overread => overread,
ended => ended);
clk <= not clk after 5 ns;
reg_rdata <= REGS(to_integer(reg_addr));
watchdog : process
begin
wait for 400 us;
if test_done = '0' then
report "watchdog expired -- the design never reached the expected state"
severity failure;
end if;
wait;
end process;
-- ---- a continuous safety check ------------------------------------------------
-- This device must never be driving the data bits and releasing for the
-- acknowledge at the same instant. On an open-drain bus that would mean holding
-- SDA low through the slot the master needs in order to answer.
safety : process (clk)
begin
if rising_edge(clk) and rst_n = '1' then
if transmitting = '1' and release_for_ack = '1' then
report "transmitting and release_for_ack asserted together" severity error;
errs_cont <= errs_cont + 1;
end if;
end if;
end process;
-- ---- observation --------------------------------------------------------------
observe : process (clk)
begin
if rising_edge(clk) and rst_n = '1' then
if obs_clear = '1' then
n_sent <= 0; n_ended <= 0;
else
if tx_valid = '1' then
if n_sent < 16 then sent_log(n_sent) <= tx_byte; end if;
n_sent <= n_sent + 1;
end if;
if ended = '1' then n_ended <= n_ended + 1; end if;
end if;
end if;
end process;
-- ---- stimulus ----------------------------------------------------------------
stim : process
variable errs : 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 clear_obs is
begin
obs_clear <= '1'; waitn(1); obs_clear <= '0'; waitn(1);
end procedure;
procedure pulse_start is
begin
frame_start <= '1'; waitn(1); frame_start <= '0'; waitn(1);
end procedure;
procedure pulse_stop is
begin
frame_stop <= '1'; waitn(1); frame_stop <= '0'; waitn(1);
end procedure;
procedure load_ptr (v : in natural) is
begin
ptr_in <= to_unsigned(v, REG_ADDR_W);
ptr_load <= '1'; waitn(1); ptr_load <= '0'; waitn(1);
end procedure;
procedure begin_read is
begin
pulse_start;
addressed <= '1'; dir_is_read <= '1';
waitn(2);
end procedure;
-- One byte: the engine asks for it, the byte goes out, then the master answers
-- in the ninth slot. `answer` is the MASTER's acknowledge -- 1 continue, 0 end.
procedure wire_byte (answer : in std_logic) is
begin
byte_request <= '1'; waitn(1); byte_request <= '0'; waitn(1);
-- the ninth slot: the transmitter must have released by now
if transmitting /= '0' then
report "still driving the data bits during the ninth slot" severity error;
errs := errs + 1; end if;
if release_for_ack /= '1' then
report "did not release SDA for the acknowledge slot" severity error;
errs := errs + 1; end if;
ack_from_master <= answer;
ack_valid <= '1'; waitn(1); ack_valid <= '0'; waitn(1);
end procedure;
begin
waitn(3);
if transmitting /= '0' then
report "driving out of reset" severity error; errs := errs + 1; end if;
if release_for_ack /= '0' then
report "releasing out of reset" severity error; errs := errs + 1; end if;
rst_n <= '1'; waitn(1);
-- 1: a 3-byte read from pointer 2. The auto-increment must land on registers 2,
-- 3 and 4 -- and the register VALUES prove it, because each register holds a
-- distinct recognisable byte.
load_ptr(2);
begin_read;
clear_obs;
wire_byte('1'); wire_byte('1'); wire_byte('0'); -- ACK, ACK, NACK
if n_sent /= 3 then
report "transmitted the wrong number of bytes, expected 3" severity error;
errs := errs + 1; end if;
if sent_log(0) /= x"22" or sent_log(1) /= x"33" or sent_log(2) /= x"44" then
report "payload wrong -- expected 0x22, 0x33, 0x44" severity error;
errs := errs + 1; end if;
if bytes_sent /= to_unsigned(3, 8) then
report "bytes_sent wrong, expected 3" severity error; errs := errs + 1; end if;
if overread /= '0' then
report "spurious overread on an in-range read" severity error;
errs := errs + 1; end if;
-- 2: the NACK ended it. `ended` must have pulsed exactly once, and a further
-- byte_request must transmit NOTHING -- a byte sent after the master's NACK
-- holds SDA low through the STOP and prevents it forming.
if n_ended /= 1 then
report "wrong number of ended pulses, expected 1" severity error;
errs := errs + 1; end if;
byte_request <= '1'; waitn(1); byte_request <= '0'; waitn(1);
if transmitting /= '0' then
report "transmitted a byte AFTER the master's NACK" severity error;
errs := errs + 1; end if;
if n_sent /= 3 then
report "a byte escaped after the NACK" severity error; errs := errs + 1; end if;
pulse_stop;
addressed <= '0';
-- 3: the pointer SURVIVES a repeated START. Specification note 1 to section
-- 3.1.10 requires exactly this.
load_ptr(5);
pulse_start; -- the Sr that turns a write into a read
if ptr /= to_unsigned(5, REG_ADDR_W) then
report "the repeated START destroyed the register pointer" severity error;
errs := errs + 1; end if;
addressed <= '1'; dir_is_read <= '1';
waitn(2);
clear_obs;
wire_byte('0');
if sent_log(0) /= x"55" then
report "post-Sr read did not send register 5" severity error;
errs := errs + 1; end if;
pulse_stop;
addressed <= '0';
-- 4: OVER-READ. Pointer 11 is the last valid register, so the first byte is
-- real and everything after it is past the end. A slave-transmitter cannot
-- refuse, so it must send a DEFINED fill -- and must NOT wrap to register 0,
-- which would return plausible wrong data.
load_ptr(11);
begin_read;
clear_obs;
wire_byte('1'); wire_byte('1'); wire_byte('0');
if sent_log(0) /= x"BB" then
report "register 11 read wrongly, expected 0xbb" severity error;
errs := errs + 1; end if;
if sent_log(1) /= FILL or sent_log(2) /= FILL then
report "past the end did not send the fill byte twice" severity error;
errs := errs + 1; end if;
if sent_log(1) = x"00" or sent_log(2) = x"00" then
report "an over-read WRAPPED to register 0" severity error; errs := errs + 1; end if;
if overread /= '1' then
report "overread not flagged" severity error; errs := errs + 1; end if;
pulse_stop;
addressed <= '0';
-- 5: a transfer addressed to SOMEBODY ELSE. This device must not drive a single
-- bit, however many bytes the engine asks for.
load_ptr(3);
pulse_start;
addressed <= '0'; dir_is_read <= '1';
waitn(2);
clear_obs;
byte_request <= '1'; waitn(1); byte_request <= '0'; waitn(1);
if transmitting /= '0' or n_sent /= 0 then
report "transmitted during somebody else's read" severity error;
errs := errs + 1; end if;
pulse_stop;
-- 6: addressed for a WRITE. This block is the READ transmitter, so it must stay
-- silent -- the mirror of Chapter 8.2's test 6. The pointer is left at a VALID
-- register so that a block which ignored dir_is_read would actually transmit,
-- rather than being caught by an over-read for the wrong reason.
load_ptr(6);
pulse_start;
addressed <= '1'; dir_is_read <= '0';
waitn(2);
clear_obs;
byte_request <= '1'; waitn(1); byte_request <= '0'; waitn(1);
if transmitting /= '0' or n_sent /= 0 then
report "the read transmitter drove a byte during a WRITE" severity error;
errs := errs + 1; end if;
if overread /= '0' then
report "a write transfer produced an overread verdict" severity error;
errs := errs + 1; end if;
pulse_stop;
addressed <= '0';
-- 7: a frame_start clears the transfer state but NOT the pointer. Both halves
-- matter: note 4 demands the reset, note 1 demands the exception.
load_ptr(7);
begin_read;
clear_obs;
wire_byte('1');
if bytes_sent /= to_unsigned(1, 8) then
report "setup for test 7 wrong" severity error; errs := errs + 1; end if;
pulse_start;
if bytes_sent /= to_unsigned(0, 8) then
report "a repeated START did not clear bytes_sent" severity error;
errs := errs + 1; end if;
if transmitting /= '0' or release_for_ack /= '0' then
report "still driving after a repeated START" severity error;
errs := errs + 1; end if;
if ptr /= to_unsigned(8, REG_ADDR_W) then
report "the pointer should be 8 after one byte from 7" severity error;
errs := errs + 1; end if;
pulse_stop;
addressed <= '0';
if errs + errs_cont = 0 then
report "i2c_slave_read_transmitter self-check complete: auto-increment "
& "correct, releases every slot, stops on the master's NACK, fills past "
& "the end without wrapping, pointer survives Sr" severity note;
else
report "i2c_slave_read_transmitter self-check FAILED" severity error;
end if;
test_done <= '1';
wait;
end process;
end architecture;6a. Five Decisions Worth Defending
reg_addr is COMBINATIONAL from the pointer — the exact opposite of Chapter 8.2's write port. This is the chapter's sharpest mirror and it is forced rather than stylistic.
A write port must register the address alongside the data, because the pointer has already advanced by the time the write lands; a combinational address presents the advanced pointer and every byte goes one register too high (that chapter's mutation B3).
A read port must do the opposite: present the address so that reg_rdata is already valid in the cycle the byte is captured. A registered reg_addr here would capture the data belonging to the previous address — the same off-by-one, reflected. That bug was in the first version of this design, caught by reading the code rather than by simulation, and mutation B7 re-injects it.
The rule underneath both: a write captures what the pointer WAS; a read must present what the pointer IS. Copying one port's style to the other produces an off-by-one in whichever direction you copied.
A registered-output register file needs a fetch cycle, and this design does not have one. The combinational read port above is correct for flops or distributed RAM. Put the register file in a block RAM with a registered output and reg_rdata lags by a cycle, so the byte must be fetched one request ahead — exactly Chapter 8.1's WS_FETCH. §10 covers what that costs; the point here is that the requirement is a property of the memory, not of the protocol.
The finished latch exists because addressed outlives the transfer. After the master's NACK this transfer is over, but the address decoder of Chapter 6.5 holds its verdict until the next addressing — so addressed is still asserted. Without the latch the block re-arms on the very next cycle and transmits again. §11 is that bug in full, because it was real and its consequence is the bus hang of Chapter 7.4 produced by the slave rather than the master.
It is also the mirror of Chapter 8.2 §5a's rule that a slave which has refused a byte stays silent until re-addressed. There it was the slave who said no; here it is the master. The consequence for the block is the same: an ended transfer must not restart itself.
release_for_ack is asserted on entry to the slot and held for the whole slot. Not pulsed, and not derived from the byte's value. A pulse would leave a window in which this device is still driving while the master is trying to pull SDA low, and a value-derived release looks correct for every byte whose LSB is 0. The testbench carries a continuous check that transmitting and release_for_ack are never both asserted, which is the kind of property that belongs in an always-on check rather than in a step of a test.
The over-read fill is a parameter, not a magic number. FILL = 8'hFF with a comment giving the physical reason (§3): an undriven open-drain line reads as all ones, so 0xFF is what the master sees from a silent slave anyway. Making it a parameter also lets a device that documents a different sentinel — some return 0x00, some return the last valid byte — use the same block honestly.
6b. Verified Execution
$ iverilog -g2012 -o b0 i2c_slave_read_transmitter.sv i2c_slave_read_transmitter_tb.sv && ./b0
PASS: auto-increment correct, releases every slot, stops on the master's NACK, fills
past the end without wrapping, pointer survives Sr
i2c_slave_read_transmitter_tb.sv:220: $finish called at 1040 (1ps)
$ iverilog -g2005 -o b1 i2c_slave_read_transmitter.v i2c_slave_read_transmitter_tb.v && ./b1
PASS: auto-increment correct, releases every slot, stops on the master's NACK, fills
past the end without wrapping, pointer survives Sr
i2c_slave_read_transmitter_tb.v:235: $finish called at 1040 (1ps)
$ nvc -a i2c_slave_read_transmitter.vhd i2c_slave_read_transmitter_tb.vhd
$ nvc -e i2c_slave_read_transmitter_tb && nvc -r i2c_slave_read_transmitter_tb --stop-time=500us
** Note: 1040ns+0: i2c_slave_read_transmitter self-check complete: auto-increment
correct, releases every slot, stops on the master's NACK, fills past the end
without wrapping, pointer survives SrAll three at 1040 ns.
7. What the Testbench Proves
The register file is initialised so that register k holds 0xk0 | k — register 2 holds 0x22, register 11 holds 0xBB. Every register therefore has a distinct, recognisable value, which is what makes an off-by-one visible in the data rather than only in a mismatch count.
| # | stimulus | what it establishes |
|---|---|---|
| 1 | read 3 bytes from pointer 2 | the auto-increment lands on r2, r3, r4 — 0x22, 0x33, 0x44 |
| 2 | the master NACKs byte 3 | ended pulses once, and a further byte request transmits nothing |
| 3 | pointer 5, then an Sr, then a read | the pointer survived: the byte is 0x55 |
| 4 | read past register 11 | the fill byte 0xFF, overread flagged, and no wrap to r0 |
| 5 | a transfer addressed elsewhere | not a single bit driven |
| 6 | addressed for a write | silent — and the pointer is left at a valid register so the test cannot pass for the wrong reason |
| 7 | an Sr mid-read | transfer state cleared, pointer preserved and advanced |
| — | every cycle | transmitting and release_for_ack are never both asserted |
| — | every byte | the device has released before the ninth slot opens |
Test 6 deserves the note attached to it. Chapter 8.2 §6 records a mutation that survived because the stimulus byte was out of range, so a direction-ignoring mutant was caught by the bound check rather than by the direction check. The same trap exists here in mirror image: if the pointer were left past the end, a mutant that ignored dir_is_read would transmit the fill byte and the test would still see "not real data". Leaving the pointer at register 6 means a mutant that ignores the direction has to transmit 0x66, which the check catches for the right reason. The same class of false pass, anticipated rather than discovered — which is what a lesson from an earlier chapter is for.
The two continuous checks are worth separating from the numbered tests. They hold at every cycle of every scenario, including scenarios added later by somebody who has not read this chapter. transmitting && release_for_ack is a structural impossibility on an open-drain bus — it means holding SDA low through the slot the master needs — so it belongs in an always-on check rather than in a step.
8. Mutation Testing
Ten defects injected into the SystemVerilog design.
| # | injected defect | outcome |
|---|---|---|
| B1 | SDA is never released for the acknowledge slot | killed |
| B2 | the device keeps driving through the slot | killed — still driving during the ninth slot |
| B3 | an over-read wraps to register 0 | killed — sent 0xCC, 0xDD, expected fill |
| B4 | transmitting continues after the master's NACK | killed — 4 bytes sent, expected 3 |
| B5 | a repeated START clears the pointer (violates note 1) | killed — sent 0x00, 0x11, 0x22 |
| B6 | the pointer does not auto-increment | killed — sent 0x22, 0x22, 0x22 |
| B7 | reg_addr presents the already-advanced pointer | killed — sent 0x33, 0x44, 0x55 |
| B8 | a write transfer is treated as a read | killed |
| B9 | the device transmits when not addressed | killed |
| B10 | the master's NACK is read as an ACK | killed |
Ten injected, ten killed, no survivors and no invalid mutants.
B5, B6 and B7 produce three different wrong payloads and that is the whole value of distinct register contents. Read them together:
- correct:
0x22, 0x33, 0x44 - B5 (pointer cleared by the Sr):
0x00, 0x11, 0x22— the right shape, wrong starting point - B6 (no auto-increment):
0x22, 0x22, 0x22— right start, no movement - B7 (address one ahead):
0x33, 0x44, 0x55— right shape, shifted by one
A testbench whose register file held the same value everywhere would report "mismatch" for all three and leave you to work out which from a waveform. With distinct values the failure message is the diagnosis. Choosing recognisable stimulus values is not cosmetic; it is the difference between a test that tells you something failed and a test that tells you what.
B10's kill message is the interesting one. Inverting the master's acknowledge produces did not release SDA for the acknowledge slot — not a payload error. Follow it through: the mutant treats the NACK as "send another", so after what should have been the final byte it re-enters ST_SEND and fetches again; the testbench's next action is the extra-byte check, and the block is in the wrong state for the slot assertion. The message is honest but indirect, and it is worth knowing that a state-machine mutation often surfaces as a protocol-timing failure rather than as a data failure — the first symptom is wherever the machine first disagrees with the testbench about what phase it is in.
9. Verification Connection — A Slave Is a Responder, Not a Driver
A master agent initiates. A slave agent responds, and that difference reshapes the whole component: there is no sequence deciding when to act, because the DUT's environment decides. In UVM this is the reactive-responder pattern, and a read-transmitter responder is its clearest example.
class i2c_slave_responder extends uvm_driver #(i2c_slave_rsp);
`uvm_component_utils(i2c_slave_responder)
// The model of the device: what a read SHOULD return from each register. It is
// the responder's own state, not a sequence's, because a slave is defined by
// what it contains rather than by what it does next.
bit [7:0] regs [int];
int ptr;
bit ptr_valid;
virtual i2c_if vif;
// A responder's run_phase waits on the BUS, never on a sequencer. Asking a
// sequencer for the next item would be asking "what should I do next", and a
// slave does not get to decide that -- the master's clock does.
task run_phase(uvm_phase phase);
forever begin
@(posedge vif.byte_request);
if (!ptr_valid) begin
`uvm_error("PTR", "a read was requested with no pointer established")
end
// Past the end: a slave-transmitter CANNOT refuse, so it must present
// something. The model must present the same fill the DUT does, or the
// scoreboard would flag the device's correct behaviour as a mismatch.
if (!regs.exists(ptr))
vif.tx_byte <= 8'hFF;
else begin
vif.tx_byte <= regs[ptr];
ptr++; // note 2: auto-increment is the DEVICE's
end
end
endtask
// A repeated START resets the transfer state -- note 4 -- but NOT the pointer,
// because note 1 requires the pointer written before the Sr to still apply.
// A responder that cleared it here would model a device that cannot perform a
// combined register read, which is most real devices.
function void on_repeated_start();
// deliberately empty of pointer handling; see note 1
endfunction
endclassAnd the coverage that a read responder makes necessary, because the interesting cases are all about where the pointer is rather than about data values:
covergroup i2c_read_ptr_cg with function sample(int ptr, int len, int reg_count);
// The bins are chosen from the BOUNDARY, not spread evenly. Everything
// interesting about a read's pointer happens within one register of the end of
// the file, because that is where the fill behaviour of section 3 starts.
start_ptr: coverpoint ptr {
bins first = {0};
bins middle = {[1:9]};
bins last_valid = {11}; // the last real register
bins past_end = {[12:15]}; // the pointer is already invalid
}
// A burst that STRADDLES the end is the case that distinguishes fill from wrap,
// and it cannot be reached by covering start position and length separately.
straddles_end: coverpoint (ptr + len > reg_count) {
bins entirely_valid = {0};
bins runs_past_end = {1};
}
len: coverpoint len {
bins probe = {0};
bins single = {1};
bins burst = {[2:16]};
}
// The cross is the point: a long burst from register 0 and a short one from the
// last register would fill both coverpoints while never producing the overrun.
ptr_x_straddle: cross start_ptr, straddles_end;
endgroup10. FPGA and ASIC Implications
The block is about twenty flops. Three states, a four-bit pointer, an eight-bit byte register and an eight-bit count, plus three status bits. The bound check is one comparator against a parameter.
The read port shape is the integration decision, and it is the mirror of the write's. A combinational read — flops, LUT RAM, distributed RAM — works with the design exactly as written. A registered read port, which is what a block RAM or an ASIC SRAM gives you, does not: reg_rdata arrives a cycle late and the byte captured would belong to the previous address. The fix is a fetch-ahead state, structurally identical to Chapter 8.1's WS_FETCH, and it is free in time because a byte lasts nine SCL periods — ninety microseconds at 100 kHz. What it is not is optional, and the failure if you skip it is a whole burst shifted by one register, which §8's B7 shows reads as perfectly plausible data.
The fill path costs nothing and should not be optimised away. past_end selects between reg_rdata and a constant. On an FPGA that is one LUT level on a path with a byte time to settle. The temptation is to let the pointer's width do the bounding — make REG_COUNT a power of two so the pointer wraps naturally and no comparator is needed. That is mutation B3, and §3 explains why the saving is not worth it: the registers between the real count and the rounded-up count do not exist, and reading them returns plausible wrong data.
Clock stretching is this block's only tool, and it is not in this block. A slave-transmitter that cannot produce the next byte in time — an ADC conversion not finished, a value behind an external memory, a microcontroller slave servicing an interrupt — has exactly one legal move: hold SCL low. It cannot NACK, cannot signal busy, and cannot slow the master any other way. That mechanism belongs in the byte-level layer that owns SCL, which is why this design has no timing in it at all; Module 12 builds it.
The reset state must be silent, and for a read that is a sharper requirement. transmitting and release_for_ack both reset to 0, so a slave coming out of reset drives nothing. Consider the alternative: a slave that reset into "transmitting" would drive SDA during whatever transfer happens to be in progress, corrupting another device's data with no indication of where the corruption came from. On a shared bus a device's reset must be invisible to every other device, and that is only achievable if the reset state drives nothing at all.
11. Debugging — The Slave That Kept Transmitting After Being Told to Stop
Pitfall — an ended transfer that restarts itself, because the addressing verdict outlives it
// The first version of the re-arm condition. It reads correctly: if we are
// addressed, and the direction is read, and we are idle, then begin transmitting.
//
// end else if (addressed && dir_is_read && state == ST_IDLE) begin
// state <= ST_SEND;
// end
//
// The bug is in what is NOT there. When the master NACKs the final byte, the block
// correctly sets state <= ST_IDLE and pulses ended. But addressed is a LEVEL
// from the address decoder of Chapter 6.5, and that decoder holds its verdict until
// the next addressing -- so addressed is STILL ASSERTED one cycle later.
//
// So the condition is true again immediately. The block re-arms into ST_SEND and
// waits for a byte request, which the byte engine will happily provide.The testbench's 3-byte read sent FOUR bytes. The fourth arrived after the master's NACK.
What made this expensive to find is that the first three bytes are perfect. Right registers, right order, right values, every slot released correctly, ended pulsed exactly once at the right moment. The state machine visibly went to IDLE. Every individual assertion about the transfer passed.
Worse, the obvious check did not catch it. The test looked at transmitting after the extra byte request and found it LOW -- because the re-arm consumed a cycle, so the stray byte_request arrived while the block was still in ST_IDLE and was missed; the re-arm and the request were one cycle apart. It was the byte COUNT that caught it, because the count is cumulative and does not care about phase alignment.
A trace showed the state going 2 (ST_SLOT) -> 0 (ST_IDLE) -> 1 (ST_SEND) across three consecutive cycles, with ended pulsing on the first transition. The block was ending the transfer and then starting a new one, correctly, from its own point of view. Nothing was wrong with any single decision it made.
addressed is a level that outlives the transfer, and the re-arm condition had no memory of the transfer having ENDED. "Addressed, reading, and idle" describes the state after a completed read just as accurately as it describes the state before a new one, so the condition cannot distinguish them.
The mental model that produced it is that reaching ST_IDLE means "done". It does not -- it means "not currently sending", which is also true at the start.
12. Common Misconceptions
"In a read, the slave drives the clock." The master drives SCL for the entire transfer, including every ninth pulse. The slave drives only SDA's data bits, and only for bytes after the address. The master clocks data it does not drive — which is the whole reason a slave-transmitter is reactive.
"A slave can NACK a read it cannot satisfy." It cannot. The ninth bit belongs to the master, because the master is the receiver. A slave-transmitter has no NACK, no error code and no field in the frame — §3's table is four rows of "nothing".
"Returning 0xFF past the end is an arbitrary convention." It is the physically correct default: an undriven open-drain line reads as all ones, so a silent slave transmits 0xFF whether it means to or not. Doing it deliberately converts an accident into a specification.
"Wrapping is gentler on a read than on a write." It is worse. A wrapping write corrupts register 0 and at least changes something you can notice. A wrapping read corrupts nothing and returns plausible wrong data — configuration registers presented as sensor samples, with every structural check passing.
"A repeated START resets everything in the slave." It resets the bus logic, which note 4 requires unconditionally — but the register pointer must survive it, because note 1 makes the pointer written before the Sr the basis of the read after it. That exception is the combined format.
"Once the state machine reaches idle, the transfer is over." Idle means "not currently sending", which is equally true before a transfer starts. Distinguishing "finished" from "not yet begun" needs its own state, and §11 is the bus hang that results from conflating them.
"The slave releases SDA for the ninth slot because the eighth bit has been sent." It releases because the slot arrived. A byte whose LSB is 1 leaves SDA high anyway, so a value-derived release looks correct for half of all bytes — and fails on the other half in a way that makes a NACK impossible to express.
13. Reason It Through
A device has 12 registers. The master sets the pointer to 10 and reads four bytes. What appears on the wire, and what does the master receive?
Registers 10 and 11 supply the first two bytes — 0xAA and 0xBB in this design's numbering. The pointer is then 12, past the end, so bytes three and four are the fill value 0xFF. The master receives 0xAA, 0xBB, 0xFF, 0xFF, acknowledges the first three and NACKs the fourth, and the transfer is completely well-formed. The slave could not have refused, and the only record that anything was unusual is the device's internal overread flag — which the master cannot see. Compare this with the write case: Chapter 8.2's slave-receiver would have NACKed the overrun and told the master exactly where acceptance stopped.
Why is a slave that wrongly transmits after the master's NACK worse than one that stops too early?
Stopping early produces a read that returns fill or stale bytes — wrong data, reported cleanly, in a well-formed frame. Transmitting after the NACK drives SDA during the window in which the master's STOP needs SDA to rise, so whenever that byte's MSB is a zero the STOP cannot be formed at all. The first is a data bug in one transfer; the second holds the bus for every device on it.
The master reads three bytes and gets the right values in the right order, but they start one register too high. Which of two bugs is it, and how do you tell?
Either the pointer was written one too high, or reg_addr presents the already-advanced pointer (§8's B7). They produce identical payloads, so the payload cannot distinguish them — but the pointer's own value can: after a three-byte read from a correctly-written pointer of 2, ptr reads 5. The B7 design also reads 5, because its increment is correct; only the data it fetched was shifted. So read back the pointer and compare against the register contents, and check whether the first byte matches the register the pointer was set to. This is why §7's register file holds distinct recognisable values.
Why must the frame_start branch come before the state machine rather than inside it?
Because note 4 requires a device to reset its bus logic on an S or Sr "even if these START conditions are not positioned according to the proper format" — mid-byte, mid-acknowledge-slot, anywhere. A handler inside the state machine's cases would only run in the states the author thought to cover, and note 4 is written precisely about the states nobody expects. The branch is unconditional and second only to frame_stop.
A slave needs 200 µs to fetch the next byte from an external memory. What are its options?
One: hold SCL low. That is the whole list. It cannot NACK — the ninth bit is the master's. It cannot signal busy — there is no such signal. It cannot transmit a placeholder and correct it later — the byte is gone once clocked. Clock stretching is not an optimisation for this device, it is the only legal behaviour, and a design that cannot stretch must guarantee its data is always ready within a bit time.
14. Understanding Check
15. Summary
Master/slave and transmitter/receiver are independent, and a read is where they disagree. The master owns SCL for the entire transfer and clocks data it does not drive. The slave owns SDA's data bits and is purely reactive: it cannot advance the transfer, cannot end it, and can slow it only by holding SCL low.
A slave-transmitter cannot refuse anything. The ninth bit belongs to the master, so there is no NACK available, no error code, and no field in the frame. Where Chapter 8.2's slave-receiver had two of the specification's five NACK conditions, this block has none — which is why what to transmit past the end of the register file is a design decision the protocol offers no help with.
0xFF is the physically honest fill. An undriven open-drain line reads as all ones, so a silent slave transmits 0xFF regardless. Choosing it deliberately turns an accident into a specification. Wrapping is the harmful option, and on a read it is harmful in the quietest possible way: plausible wrong data in a well-formed frame.
The register pointer is the one thing that survives a repeated START. Note 4 requires the bus logic to reset unconditionally on any S or Sr; note 1 requires the pointer to persist across exactly that event. Both are satisfied by three lines of deliberate exception.
A read port is the mirror of a write port, not a copy of it. A write registers the address alongside the data; a read presents the address so the data is already valid. Copying either style into the other produces an off-by-one, in whichever direction you copied.
An ended transfer must not restart itself. "Addressed, reading and idle" describes the state after a read as accurately as before one, so ending needs its own memory. Without it the slave transmits after the master's NACK and holds SDA low through the STOP window — the bus hang, produced by the slave.
16. What Comes Next
Chapter 9.3 takes both halves of the read across a burst and asks what the acknowledge pattern must look like. The answer is narrow enough to be checkable: a well-formed read of n payload bytes contains exactly n−1 master ACKs and one NACK, always in the final slot, with the address byte's acknowledge belonging to the slave and counted separately.
That narrowness is what makes the chapter's instrument possible. A passive monitor can verify the whole policy from the wire — and, more usefully, can predict the bus hang from the acknowledge pattern alone, before the STOP that cannot form has been attempted. It also settles the cost question for reads, which turns out to have the same closed forms as a write and one extra term worth knowing about.
Continue learning
Related tutorials
- 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
The START Condition
START is SDA falling while SCL is high, it is generated only by the controller, and it makes the bus busy. Derive what every device must do in response, then build a detector in three languages and find out why its two guard terms and its reset value are all load-bearing.
- Related topic
The STOP Condition and Releasing the Bus
STOP is SDA rising while SCL is high — the mirror edge of START, with obligations that are not mirrored at all. Releasing the bus is not the same as making it available, and the interval between the two is where a whole class of intermittent failure lives.
- Related topic
Repeated START — Holding the Bus Between Phases
A repeated START is not a new waveform. It is the START edge again, and what makes it a different event is that the bus was already busy. That single fact is why a classifier needs state and why a monitor that joins late cannot classify what it sees.
