Skip to content
VLSI Mentor

I²C · Module 18

Detecting the Master's ACK or NACK on a Read

The ninth bit of a read belongs to the master, and the slave must read it rather than drive it. Builds the detector, shows why a NACK is the absence of a response, and why ignoring the answer is one of the two ways an I²C bus wedges permanently.

Chapter 18.5 built the slave's acknowledge: eight bits arrive, and in the ninth slot the slave pulls SDA down to say received. This chapter builds the same slot seen from the other side — because on a read the ninth bit is not the slave's to drive.

1. The Ownership Inversion

The ninth slot always belongs to whoever received the byte. On a write that is the slave. On a read the slave spent eight slots transmitting, so the receiver — and therefore the owner of the ninth slot — is the master.

who transmitted the bytewho owns the ninth slotwhich block
writemasterslave18.5 — it drives
readslave (18.7)masterthis one — it reads

This chapter is short because the block is small. It is here as its own chapter because the consequence of getting it wrong is not a corrupted byte — it is a bus that stops working for every device on it, and no amount of retrying by anyone recovers it.

2. A NACK Is the Absence of a Response

§3.1.4, read from the transmitting slave's end: the transmitter releases the SDA line during the acknowledge clock pulse so the receiver can pull the SDA line LOW. The slave is the transmitter here, so it released; the master is the receiver, so the master decides.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
master pulls SDA LOW    ->  ACK   ->  send me another byte
master leaves it HIGH   ->  NACK  ->  that was the last one

This is the same argument as 17.11 §2 made for the master's timeout defaults, and the same one 18.3 made for framing: the resting state of an open-drain bus should mean idle, so every absence of a signal reads as stop, not continue.

3. Sampled at the Rising Edge, Like Every Other Received Bit

The answer is a received bit, so it obeys the rule every received bit obeys — §3.1.2 makes SDA stable only while SCL is high, so it is sampled at scl_rise.

instantsource
received bits (18.6)scl_risemaster drives, slave samples
transmitted bits (18.7)scl_fallslave drives, master samples
the ninth bit of a read (here)scl_risemaster drives, slave samples

By the time SCL rises in the ninth slot, the slave released SDA on the fall that ended its eighth bit — that release is 18.7's last act, and it is what makes this sample meaningful. A transmitter that failed to release would have this detector reading the eighth data bit back as the answer, which is §4 of that chapter arriving here as a wrong conclusion rather than a wrong waveform.

Released on the fall, answered by the master, sampled on the rise

10 cycles
Ten cycles. SCL is low for cycles zero and one, high for two and three, low for four through six, then high for the last three. The slave's drive output is asserted for cycles zero and one, the last data bit, and released from cycle two onward. SDA carries the slave's last bit as a zero for cycles zero through three, rises to one at cycle four, then the master pulls it low from cycle six. An awaiting flag is high for cycles two through six. A sampled pulse appears at cycle seven, one cycle after SCL rises.slave transmittingslave transmittingthe master's slotthe master's sloteighth bit, still the slave'seighth bit, still theslave'sreleased — slot is the master'sreleased — slot is themaster'smaster pulls low: an ACKmaster pulls low: an ACKsampled at the risesampled at the risescl_busslave drivesda_busawaitingmack_validt0t1t2t3t4t5t6t7t8t9
Figure 1 — the ninth slot of a read. The slave's eight bits end with a release on the falling edge; the master's answer appears in the low phase that follows and is sampled at the rising edge. Conceptual figure: one interval per half-phase, not to scale.

Two details in that figure are load-bearing. The slave's release happens on the falling edge, one full phase before the answer is wanted — the detector never has to arbitrate for the line, because by the time it cares the line is already free. And awaiting covers the whole interval, including the high phase in which nothing is yet concluded: the block is waiting from the moment the byte ends, but it decides only once.

4. The Read That Will Not End

§3.1.10: after a NACK the master issues a STOP or a repeated START. So a slave that ignores the answer and sources another byte anyway is driving SDA at exactly the moment the master is trying to frame.

So keep_sourcing is not an optimisation. It is the gate that stands between an ignored NACK and a bus that needs a reset to recover, which is why a block this small gets a chapter.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
keep_sourcing = 1   the master acknowledged: 18.7 may fetch and send another byte
keep_sourcing = 0   anything else, including reset and every framing event

Every path that is not an explicit acknowledge clears it. That asymmetry is deliberate: the permission is granted by one specific observation and revoked by everything else.

5. Framing Ends the Read, Whatever the Ninth Bit Said

A repeated START or a STOP mid-read means the master has taken the bus back, and it can arrive at three different moments:

when framing arriveswhat must happen
after an ACK was sampledkeep_sourcing is cleared — the master changed its mind, and it is allowed to
while awaitingthe wait is abandoned, and no answer is taken
after a NACKnothing to do, but the state must stay cleared

The middle row is the one that is easy to miss. If framing cancels the transfer but leaves awaiting set, the next rising edge of the next transfer gets read as this transfer's answer — a slave that resumes sourcing data into an address phase, which corrupts the new transaction rather than the old one.

Framing takes priority over byte_sent and over the sampling instant, in that order. A STOP arriving in the same cycle the transmitter finishes its byte means the transfer is over, not that a ninth slot is beginning.

6. The Detector

A block diagram. A sampling instant and an SDA level from chapter 18.2 feed a sampler. A byte-sent pulse from chapter 18.7 arms a waiting flag which gates the sampler. The sampler produces a valid pulse and an acknowledge decision, which feed an acknowledge and NACK counter pair and a keep-sourcing permission. The permission goes back to chapter 18.7. Framing events from chapter 18.3 clear both the waiting flag and the permission. There is no output to the pad.scl_rise + sda_q18.2awaitingarmed by byte_sentSample onceLOW means ACKkeep_sourcingto 18.7byte_sent18.7 — eight bits donen_ack / n_nackdiagnosticsFraming18.3Clear bothwait and permission12
Figure 2 — the detector. It has no drive output at all: it consumes the sampling instant and the line level, and produces a permission the transmit path obeys.

The absence in that figure is the point: there is no path to the pad. A detector with a drive output is a design error before it is a coding error, and test T8 asserts the property directly rather than trusting the port list.

7. The Detector, in Three Languages

The design is ninety-odd lines in each language, and the whole of it is one clocked block with a four-way priority: reset, framing, arming, sampling.

Azvya Education Pvt. Ltd.VLSI Mentor
i2c_slave_mack.sv — read the ninth bit the master drives
   // -----------------------------------------------------------------------------
   // i2c_slave_mack.sv
   // The ninth bit of a READ, which the MASTER drives and the slave must read.
   //
   // THE OWNERSHIP INVERSION. On a write the slave owns the ninth slot and Chapter 18.5
   // drives it. On a read the slave has just spent eight slots driving and the ninth
   // belongs to the master -- so this block is the mirror image of 18.5, and the two must
   // never be active together.
   //
   // §3.1.4 again, read from the other end: "the transmitter releases the SDA line during
   // the acknowledge clock pulse so the receiver can pull the SDA line LOW". On a read the
   // slave is the transmitter and the master is the receiver, so:
   //
   //   master pulls SDA LOW  ->  ACK  ->  it wants another byte
   //   master leaves it HIGH ->  NACK ->  that was the last byte
   //
   // A NACK IS THE ABSENCE OF A RESPONSE, which makes it the default. If the master says
   // nothing at all -- or is not there -- the pull-up produces a one and the slave correctly
   // concludes the read is over. That is the right way round: the failure mode of a missing
   // master is a slave that stops, not a slave that keeps driving.
   //
   // SAMPLED AT THE RISING EDGE, like every other received bit, because §3.1.2 makes SDA
   // stable only while SCL is HIGH. The slave released SDA on the fall that ended its eighth
   // bit (Chapter 18.7), so by the time SCL rises again the line carries the master's answer
   // and nothing of the slave's.
   //
   // AND THE SLAVE MUST ACT ON IT. §3.1.10: after a NACK the master will issue a STOP or a
   // repeated START, and a slave that sourced another byte anyway would be driving SDA while
   // the master was trying to frame -- which means the slave's data bit fights the master's
   // STOP, and the STOP does not happen. A read that will not end is one of the two ways an
   // I²C bus wedges permanently, and this one AND gate is what prevents it.
   // -----------------------------------------------------------------------------

   module i2c_slave_mack #(
      parameter int CNT_W = 16
   ) (
      input  logic clk,
      input  logic rst_n,

      // From Chapter 18.2 -- the sampling instant and the value.
      input  logic scl_rise,
      input  logic sda_q,

      // From Chapter 18.3 -- framing ends the read whatever the ninth bit said.
      input  logic start_pulse,
      input  logic stop_pulse,

      // One cycle, from Chapter 18.7: eight bits are on the wire and SDA has been released.
      // The next rising edge is the master's answer.
      input  logic byte_sent,

      output logic awaiting,      // the ninth slot is in progress and is the master's
      output logic mack_valid,    // one cycle: the answer has been sampled
      output logic mack_ack,      // 1 = the master acknowledged and wants another byte
      output logic keep_sourcing, // level: continue only while this is set

      output logic [CNT_W-1:0] n_ack,
      output logic [CNT_W-1:0] n_nack
   );

      always @(posedge clk or negedge rst_n) begin
         if (!rst_n) begin
            awaiting      <= 1'b0;
            mack_valid    <= 1'b0;
            mack_ack      <= 1'b0;
            // The safe default is STOP SOURCING. A slave that came up believing a read was
            // in progress would drive a bus it has no claim on.
            keep_sourcing <= 1'b0;
            n_ack         <= {CNT_W{1'b0}};
            n_nack        <= {CNT_W{1'b0}};
         end else begin
            mack_valid <= 1'b0;

            if (start_pulse || stop_pulse) begin
               // Framing ends the read regardless. After a NACK the master frames, and this
               // is that framing arriving.
               awaiting      <= 1'b0;
               keep_sourcing <= 1'b0;
            end else if (byte_sent) begin
               // The slave has released. The ninth slot now belongs to the master.
               awaiting      <= 1'b1;
               keep_sourcing <= 1'b0;
            end else if (awaiting && scl_rise) begin
               // The one legal instant to read it: SDA is stable while SCL is high.
               awaiting      <= 1'b0;
               mack_valid    <= 1'b1;
               // LOW means acknowledged. The polarity is inverted relative to intuition for
               // the same reason as everywhere else in I²C: the responder pulls down.
               mack_ack      <= ~sda_q;
               keep_sourcing <= ~sda_q;
               if (~sda_q) n_ack  <= n_ack  + 1'b1;
               else        n_nack <= n_nack + 1'b1;
            end
         end
      end

   endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
i2c_slave_mack.v — the same design in Verilog-2001
   // -----------------------------------------------------------------------------
   // i2c_slave_mack.v
   // The ninth bit of a READ, which the MASTER drives and the slave must read.
   //
   // THE OWNERSHIP INVERSION. On a write the slave owns the ninth slot and Chapter 18.5
   // drives it. On a read the slave has just spent eight slots driving and the ninth
   // belongs to the master -- so this block is the mirror image of 18.5, and the two must
   // never be active together.
   //
   // §3.1.4 again, read from the other end: "the transmitter releases the SDA line during
   // the acknowledge clock pulse so the receiver can pull the SDA line LOW". On a read the
   // slave is the transmitter and the master is the receiver, so:
   //
   //   master pulls SDA LOW  ->  ACK  ->  it wants another byte
   //   master leaves it HIGH ->  NACK ->  that was the last byte
   //
   // A NACK IS THE ABSENCE OF A RESPONSE, which makes it the default. If the master says
   // nothing at all -- or is not there -- the pull-up produces a one and the slave correctly
   // concludes the read is over. That is the right way round: the failure mode of a missing
   // master is a slave that stops, not a slave that keeps driving.
   //
   // SAMPLED AT THE RISING EDGE, like every other received bit, because §3.1.2 makes SDA
   // stable only while SCL is HIGH. The slave released SDA on the fall that ended its eighth
   // bit (Chapter 18.7), so by the time SCL rises again the line carries the master's answer
   // and nothing of the slave's.
   //
   // AND THE SLAVE MUST ACT ON IT. §3.1.10: after a NACK the master will issue a STOP or a
   // repeated START, and a slave that sourced another byte anyway would be driving SDA while
   // the master was trying to frame -- which means the slave's data bit fights the master's
   // STOP, and the STOP does not happen. A read that will not end is one of the two ways an
   // I²C bus wedges permanently, and this one AND gate is what prevents it.
   // (Verilog-2001 -- structurally identical to the SystemVerilog above.)
   // -----------------------------------------------------------------------------

   module i2c_slave_mack #(
      parameter integer CNT_W = 16
   ) (
      input  wire  clk,
      input  wire  rst_n,

      // From Chapter 18.2 -- the sampling instant and the value.
      input  wire  scl_rise,
      input  wire  sda_q,

      // From Chapter 18.3 -- framing ends the read whatever the ninth bit said.
      input  wire  start_pulse,
      input  wire  stop_pulse,

      // One cycle, from Chapter 18.7: eight bits are on the wire and SDA has been released.
      // The next rising edge is the master's answer.
      input  wire  byte_sent,

      output reg   awaiting,      // the ninth slot is in progress and is the master's
      output reg   mack_valid,    // one cycle: the answer has been sampled
      output reg   mack_ack,      // 1 = the master acknowledged and wants another byte
      output reg   keep_sourcing, // level: continue only while this is set

      output reg   [CNT_W-1:0] n_ack,
      output reg   [CNT_W-1:0] n_nack
   );

      always @(posedge clk or negedge rst_n) begin
         if (!rst_n) begin
            awaiting      <= 1'b0;
            mack_valid    <= 1'b0;
            mack_ack      <= 1'b0;
            // The safe default is STOP SOURCING. A slave that came up believing a read was
            // in progress would drive a bus it has no claim on.
            keep_sourcing <= 1'b0;
            n_ack         <= {CNT_W{1'b0}};
            n_nack        <= {CNT_W{1'b0}};
         end else begin
            mack_valid <= 1'b0;

            if (start_pulse || stop_pulse) begin
               // Framing ends the read regardless. After a NACK the master frames, and this
               // is that framing arriving.
               awaiting      <= 1'b0;
               keep_sourcing <= 1'b0;
            end else if (byte_sent) begin
               // The slave has released. The ninth slot now belongs to the master.
               awaiting      <= 1'b1;
               keep_sourcing <= 1'b0;
            end else if (awaiting && scl_rise) begin
               // The one legal instant to read it: SDA is stable while SCL is high.
               awaiting      <= 1'b0;
               mack_valid    <= 1'b1;
               // LOW means acknowledged. The polarity is inverted relative to intuition for
               // the same reason as everywhere else in I²C: the responder pulls down.
               mack_ack      <= ~sda_q;
               keep_sourcing <= ~sda_q;
               if (~sda_q) n_ack  <= n_ack  + 1'b1;
               else        n_nack <= n_nack + 1'b1;
            end
         end
      end

   endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
i2c_slave_mack.vhd — the same design in VHDL
   -- -----------------------------------------------------------------------------
   -- i2c_slave_mack.vhd
   -- The ninth bit of a READ, which the MASTER drives and the slave must read. Same ports,
   -- generic, reset values and sampling instant as the SystemVerilog and Verilog versions.
   -- -----------------------------------------------------------------------------
   library ieee;
   use ieee.std_logic_1164.all;
   use ieee.numeric_std.all;

   entity i2c_slave_mack is
      generic (
         CNT_W : positive := 16
      );
      port (
         clk   : in  std_logic;
         rst_n : in  std_logic;

         -- From Chapter 18.2 -- the sampling instant and the value.
         scl_rise : in  std_logic;
         sda_q    : in  std_logic;

         -- From Chapter 18.3 -- framing ends the read whatever the ninth bit said.
         start_pulse : in  std_logic;
         stop_pulse  : in  std_logic;

         -- One cycle, from Chapter 18.7: eight bits are on the wire and SDA is released.
         byte_sent : in  std_logic;

         awaiting      : out std_logic;
         mack_valid    : out std_logic;
         mack_ack      : out std_logic;
         keep_sourcing : out std_logic;

         n_ack  : out unsigned(CNT_W-1 downto 0);
         n_nack : out unsigned(CNT_W-1 downto 0)
      );
   end entity i2c_slave_mack;

   architecture rtl of i2c_slave_mack is
      signal r_await, r_valid, r_ack, r_keep : std_logic := '0';
      signal c_a, c_n : unsigned(CNT_W-1 downto 0) := (others => '0');
   begin

      process (clk, rst_n)
      begin
         if rst_n = '0' then
            r_await <= '0';
            r_valid <= '0';
            r_ack   <= '0';
            -- The safe default is STOP SOURCING: a target that came up believing a read was
            -- in progress would drive a bus it has no claim on.
            r_keep  <= '0';
            c_a     <= (others => '0');
            c_n     <= (others => '0');
         elsif rising_edge(clk) then
            r_valid <= '0';

            if start_pulse = '1' or stop_pulse = '1' then
               -- Framing ends the read regardless. After a NACK the master frames, and this
               -- is that framing arriving.
               r_await <= '0';
               r_keep  <= '0';
            elsif byte_sent = '1' then
               -- The slave has released. The ninth slot now belongs to the master.
               r_await <= '1';
               r_keep  <= '0';
            elsif r_await = '1' and scl_rise = '1' then
               -- The one legal instant to read it: SDA is stable while SCL is high.
               r_await <= '0';
               r_valid <= '1';
               -- LOW means acknowledged. Inverted relative to intuition, for the same reason
               -- as everywhere else in I²C: the responder pulls down.
               r_ack   <= not sda_q;
               r_keep  <= not sda_q;
               if sda_q = '0' then
                  c_a <= c_a + 1;
               else
                  c_n <= c_n + 1;
               end if;
            end if;
         end if;
      end process;

      awaiting      <= r_await;
      mack_valid    <= r_valid;
      mack_ack      <= r_ack;
      keep_sourcing <= r_keep;
      n_ack         <= c_a;
      n_nack        <= c_n;

   end architecture rtl;

8. The Testbench

Twelve tests, and the bench instantiates 18.2's synchroniser rather than driving scl_rise directly — so the stimulus is a bus, not a convenient set of pulses, and the one-cycle events arrive with the latency the real front end has.

testwhat it establishes
T1a reset target is not awaiting an answer and will not source
T2clocking with no byte completed yields no answer at all
T3a LOW in the ninth slot is an acknowledge, and sourcing continues
T4a HIGH is a NACK, and it is the default
T5nothing is concluded while SCL is still low, even with the answer already present
T6exactly one answer per completed byte, whatever clocking follows
T7ACK then NACK across two bytes: the second overrides the first
T8the block never drives the line
T9a STOP ends the read after an ACK was already sampled
T10a repeated START does the same
T11framing while awaiting cancels the wait, so no false answer is taken
T12reset clears the permission and both counters

T5 is the test that separates "it reads SDA" from "it reads SDA at the right instant". It presents the low in the low phase, asserts that nothing has been concluded, and only then releases SCL:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
drive SCL low, then SDA low      -> assert no answer yet, still awaiting
release SCL                      -> assert exactly one answer, and it is an ACK

A block that sampled combinationally, or on any cycle while awaiting, passes every other test in the list and fails this one.

Azvya Education Pvt. Ltd.VLSI Mentor
i2c_slave_mack_tb.sv — the self-checking testbench
   // -----------------------------------------------------------------------------
   // i2c_slave_mack_tb.sv
   // Independent oracle for i2c_slave_mack: the ninth bit of a READ, which the MASTER drives.
   //
   // The bench is the master-receiver's other half: it releases SDA so the slave can source
   // bits, then DRIVES the ninth slot itself -- acknowledging or not -- and checks what the
   // slave concluded. The slave must not drive SDA at any point in this bench, because the
   // ninth slot is not its to own, so the bench asserts that too.
   // -----------------------------------------------------------------------------
   `timescale 1ns/1ps

   module i2c_slave_mack_tb;

      localparam integer HALF = 8;

      logic clk = 1'b0, rst_n = 1'b0;
      logic m_scl_low = 1'b0, m_sda_low = 1'b0;
      logic byte_sent = 1'b0;
      logic f_start = 1'b0, f_stop = 1'b0;

      // The bus. Only the master drives here; the slave's transmit path is not in this
      // bench, which is deliberate -- this block never drives anything.
      wire scl = ~m_scl_low;
      wire sda = ~m_sda_low;

      logic scl_q, sda_q, scl_rise, scl_fall, sda_rise, sda_fall;
      logic awaiting, mack_valid, mack_ack, keep_sourcing;
      logic [15:0] n_ack, n_nack;

      integer errors = 0;
      integer n, k;

      // ---- observers -------------------------------------------------------------
      integer n_valid_obs = 0, wide = 0;
      logic   last_ack = 1'b0;
      logic   v_d = 1'b0;
      always @(posedge clk) begin
         if (rst_n) begin
            if (mack_valid) begin n_valid_obs <= n_valid_obs + 1; last_ack <= mack_ack; end
            if (mack_valid & v_d) wide <= wide + 1;
         end
         v_d <= mack_valid;
      end

      i2c_slave_sync #(.SYNC_DEPTH(2)) u_sync (
         .clk(clk), .rst_n(rst_n), .scl_pin(scl), .sda_pin(sda),
         .scl_q(scl_q), .sda_q(sda_q), .scl_rise(scl_rise), .scl_fall(scl_fall),
         .sda_rise(sda_rise), .sda_fall(sda_fall));

      i2c_slave_mack #(.CNT_W(16)) dut (
         .clk(clk), .rst_n(rst_n), .scl_rise(scl_rise), .sda_q(sda_q),
         .start_pulse(f_start), .stop_pulse(f_stop), .byte_sent(byte_sent),
         .awaiting(awaiting), .mack_valid(mack_valid), .mack_ack(mack_ack),
         .keep_sourcing(keep_sourcing), .n_ack(n_ack), .n_nack(n_nack));

      always #5 clk = ~clk;
      task step;  begin @(posedge clk); @(negedge clk); end endtask
      task phase; begin for (n = 0; n < HALF; n = n + 1) step; end endtask

      task do_reset;
         begin
            @(negedge clk); rst_n = 1'b0;
            m_scl_low = 1'b0; m_sda_low = 1'b0; byte_sent = 1'b0;
            f_start = 1'b0; f_stop = 1'b0;
            n_valid_obs = 0; wide = 0; last_ack = 1'b0;
            step; step; @(negedge clk); rst_n = 1'b1; phase;
         end
      endtask

      // One clock pulse with the master driving SDA to `d` (active-low intent) through it.
      // The value is placed in the LOW phase, as §3.1.2 requires.
      task gen_pulse (input drive_low);
         begin
            @(negedge clk); m_scl_low = 1'b1; phase;
            @(negedge clk); m_sda_low = drive_low; phase;
            @(negedge clk); m_scl_low = 1'b0; phase;
            @(negedge clk); m_scl_low = 1'b1; phase;
         end
      endtask

      task pulse_byte_sent;
         begin @(negedge clk); byte_sent = 1'b1; step; @(negedge clk); byte_sent = 1'b0; end
      endtask

      task ck_bit (input [200*8:1] w, input g, input e);
         begin if (g !== e) begin
            $display("  FAIL %0s: got %0b expected %0b", w, g, e); errors = errors + 1; end end
      endtask
      task ck_int (input [200*8:1] w, input integer g, input integer e);
         begin if (g !== e) begin
            $display("  FAIL %0s: got %0d expected %0d", w, g, e); errors = errors + 1; end end
      endtask

      initial begin
         $display("=== i2c_slave_mack: the ninth bit of a read, which the master drives ===");

         // ----------------------------------------------------------------
         // T1. RESET DOES NOT ASSUME A READ IS IN PROGRESS. `keep_sourcing` low is the safe
         //     default: a target that came up believing a read was open would drive a bus it
         //     has no claim on.
         // ----------------------------------------------------------------
         do_reset;
         $display("T1  a reset target is not awaiting an answer and will not source");
         ck_bit("T1 not awaiting", awaiting, 1'b0);
         ck_bit("T1 and not sourcing", keep_sourcing, 1'b0);
         ck_int("T1 no answers seen", n_valid_obs, 0);

         // ----------------------------------------------------------------
         // T2. NOTHING WITHOUT A COMPLETED BYTE. Clocking alone must not be read as an
         //     answer -- the false-positive test. Without this gate the block would sample
         //     every data bit of every read as though it were the master's acknowledge.
         // ----------------------------------------------------------------
         do_reset;
         for (k = 0; k < 4; k = k + 1) gen_pulse(1'b0);
         $display("T2  clocking with no byte completed yields no answer");
         ck_int("T2 no answer", n_valid_obs, 0);
         ck_bit("T2 not awaiting", awaiting, 1'b0);

         // ----------------------------------------------------------------
         // T3. AN ACK: the master pulls SDA LOW in the ninth slot. LOW means acknowledged,
         //     which is inverted relative to intuition for the same reason as everywhere
         //     else in I²C -- the responder pulls down.
         // ----------------------------------------------------------------
         do_reset;
         pulse_byte_sent;
         ck_bit("T3 awaiting the answer", awaiting, 1'b1);
         gen_pulse(1'b1);                     // master drives LOW = ACK
         $display("T3  a LOW in the ninth slot is an acknowledge");
         ck_int("T3 one answer sampled", n_valid_obs, 1);
         ck_bit("T3 and it was an ACK", last_ack, 1'b1);
         ck_bit("T3 so the target keeps sourcing", keep_sourcing, 1'b1);
         ck_int("T3 the ACK counter moved", n_ack, 1);
         ck_bit("T3 and it is no longer awaiting", awaiting, 1'b0);

         // ----------------------------------------------------------------
         // T4. A NACK: the master leaves SDA released. A NACK is the ABSENCE of a response,
         //     which makes it the default -- and that is the right way round, because the
         //     failure mode of a missing master is a target that stops.
         // ----------------------------------------------------------------
         do_reset;
         pulse_byte_sent;
         gen_pulse(1'b0);                     // master leaves it HIGH = NACK
         $display("T4  a HIGH in the ninth slot is a NACK, and it is the default");
         ck_int("T4 one answer sampled", n_valid_obs, 1);
         ck_bit("T4 and it was a NACK", last_ack, 1'b0);
         ck_bit("T4 so the target stops sourcing", keep_sourcing, 1'b0);
         ck_int("T4 the NACK counter moved", n_nack, 1);

         // ----------------------------------------------------------------
         // T5. THE ANSWER IS SAMPLED AT THE RISING EDGE, not at the fall. §3.1.2 makes SDA
         //     stable only while SCL is HIGH, so the rise is the one instant the master's
         //     answer is guaranteed valid. Here the master presents a LOW in the low phase
         //     and the block must not conclude anything until SCL rises.
         // ----------------------------------------------------------------
         do_reset;
         pulse_byte_sent;
         @(negedge clk); m_scl_low = 1'b1; phase;      // SCL low
         @(negedge clk); m_sda_low = 1'b1; phase;      // the answer is presented
         ck_int("T5 nothing concluded while SCL is still low", n_valid_obs, 0);
         ck_bit("T5 still awaiting", awaiting, 1'b1);
         @(negedge clk); m_scl_low = 1'b0; phase;      // SCL rises
         $display("T5  the answer is sampled at the rising edge, not before");
         ck_int("T5 now it is sampled", n_valid_obs, 1);
         ck_bit("T5 and it read as an ACK", last_ack, 1'b1);

         // ----------------------------------------------------------------
         // T6. ONE ANSWER PER BYTE. The pulse is one cycle and fires once -- a block that
         //     kept sampling would take the NEXT byte's first data bit as a second answer.
         // ----------------------------------------------------------------
         do_reset;
         pulse_byte_sent;
         gen_pulse(1'b1);
         gen_pulse(1'b1); gen_pulse(1'b1);    // more clocking, more lows
         $display("T6  exactly one answer per completed byte, whatever follows");
         ck_int("T6 still one answer", n_valid_obs, 1);
         ck_int("T6 the pulse was one cycle", wide, 0);

         // ----------------------------------------------------------------
         // T7. TWO BYTES, TWO ANSWERS: ACK then NACK, which is how every multi-byte read
         //     ends. The second answer must override the first.
         // ----------------------------------------------------------------
         do_reset;
         pulse_byte_sent; gen_pulse(1'b1);    // ACK -> keep going
         ck_bit("T7 sourcing after the ACK", keep_sourcing, 1'b1);
         pulse_byte_sent; gen_pulse(1'b0);    // NACK -> stop
         $display("T7  ACK then NACK: the second answer overrides the first");
         ck_int("T7 two answers", n_valid_obs, 2);
         ck_bit("T7 the last was a NACK", last_ack, 1'b0);
         ck_bit("T7 and sourcing stopped", keep_sourcing, 1'b0);
         ck_int("T7 one of each was counted", n_ack + n_nack, 2);

         // ----------------------------------------------------------------
         // T8. THIS BLOCK NEVER DRIVES. It has no drive output at all, which is the point:
         //     the ninth slot of a read belongs to the master, and a target that drove there
         //     would fight the very answer it is trying to read. The bench proves it
         //     structurally -- the slave contributes nothing to the bus in this testbench,
         //     so the line is exactly what the master made it.
         // ----------------------------------------------------------------
         $display("T8  the block has no drive output: the ninth slot is not its to own");
         ck_bit("T8 the line is the master's alone", sda, ~m_sda_low);

         // ----------------------------------------------------------------
         // T9. FRAMING ENDS THE READ regardless of the ninth bit. After a NACK the master
         //     issues a STOP or a repeated START, and this is that framing arriving -- but
         //     framing must also end a read that was still expecting an answer.
         // ----------------------------------------------------------------
         do_reset;
         pulse_byte_sent; gen_pulse(1'b1);    // ACK: sourcing
         ck_bit("T9 sourcing before the framing", keep_sourcing, 1'b1);
         @(negedge clk); f_stop = 1'b1; step; @(negedge clk); f_stop = 1'b0; step;
         $display("T9  framing ends the read whatever the ninth bit said");
         ck_bit("T9 sourcing stopped", keep_sourcing, 1'b0);
         ck_bit("T9 and not awaiting", awaiting, 1'b0);

         // ----------------------------------------------------------------
         // T10. AND A REPEATED START DOES THE SAME -- the other half, and the likelier one:
         //      a master ending a read usually restarts rather than stopping.
         // ----------------------------------------------------------------
         do_reset;
         pulse_byte_sent; gen_pulse(1'b1);
         @(negedge clk); f_start = 1'b1; step; @(negedge clk); f_start = 1'b0; step;
         $display("T10 a repeated START ends it too");
         ck_bit("T10 sourcing stopped", keep_sourcing, 1'b0);
         ck_bit("T10 and not awaiting", awaiting, 1'b0);

         // ----------------------------------------------------------------
         // T11. FRAMING WHILE STILL AWAITING cancels the wait. A master that abandons a read
         //      mid-slot never supplies an answer, and a block left awaiting would take the
         //      NEXT transfer's first data bit as this read's acknowledge.
         // ----------------------------------------------------------------
         do_reset;
         pulse_byte_sent;
         ck_bit("T11 awaiting", awaiting, 1'b1);
         @(negedge clk); f_start = 1'b1; step; @(negedge clk); f_start = 1'b0; step;
         ck_bit("T11 the wait was cancelled", awaiting, 1'b0);
         gen_pulse(1'b1);                     // a low that is NOT an answer
         $display("T11 framing while awaiting cancels the wait, so no false answer");
         ck_int("T11 and nothing was taken as an answer", n_valid_obs, 0);

         // ----------------------------------------------------------------
         // T12. RESET CLEARS EVERYTHING, including the sourcing permission.
         // ----------------------------------------------------------------
         do_reset;
         pulse_byte_sent; gen_pulse(1'b1);
         ck_bit("T12 sourcing before reset", keep_sourcing, 1'b1);
         @(negedge clk); rst_n = 1'b0; step; step;
         $display("T12 reset clears the sourcing permission and the counters");
         ck_bit("T12 not sourcing", keep_sourcing, 1'b0);
         ck_int("T12 counters cleared", n_ack + n_nack, 0);

         if (errors == 0) $display("=== i2c_slave_mack: ALL CHECKS PASSED ===");
         else             $display("=== i2c_slave_mack: %0d CHECK(S) FAILED ===", errors);
         $finish;
      end

   endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
i2c_slave_mack_tb.v — the same tests in Verilog-2001
   // -----------------------------------------------------------------------------
   // i2c_slave_mack_tb.v
   // Independent oracle for i2c_slave_mack: the ninth bit of a READ, which the MASTER drives.
   //
   // The bench is the master-receiver's other half: it releases SDA so the slave can source
   // bits, then DRIVES the ninth slot itself -- acknowledging or not -- and checks what the
   // slave concluded. The slave must not drive SDA at any point in this bench, because the
   // ninth slot is not its to own, so the bench asserts that too.
   // -----------------------------------------------------------------------------
   `timescale 1ns/1ps

   module i2c_slave_mack_tb;

      localparam integer HALF = 8;

      reg clk = 1'b0, rst_n = 1'b0;
      reg m_scl_low = 1'b0, m_sda_low = 1'b0;
      reg byte_sent = 1'b0;
      reg f_start = 1'b0, f_stop = 1'b0;

      // The bus. Only the master drives here; the slave's transmit path is not in this
      // bench, which is deliberate -- this block never drives anything.
      wire scl = ~m_scl_low;
      wire sda = ~m_sda_low;

      wire scl_q, sda_q, scl_rise, scl_fall, sda_rise, sda_fall;
      wire awaiting, mack_valid, mack_ack, keep_sourcing;
      wire [15:0] n_ack, n_nack;

      integer errors = 0;
      integer n, k;

      // ---- observers -------------------------------------------------------------
      integer n_valid_obs = 0, wide = 0;
      reg last_ack = 1'b0;
      reg v_d = 1'b0;
      always @(posedge clk) begin
         if (rst_n) begin
            if (mack_valid) begin n_valid_obs <= n_valid_obs + 1; last_ack <= mack_ack; end
            if (mack_valid & v_d) wide <= wide + 1;
         end
         v_d <= mack_valid;
      end

      i2c_slave_sync #(.SYNC_DEPTH(2)) u_sync (
         .clk(clk), .rst_n(rst_n), .scl_pin(scl), .sda_pin(sda),
         .scl_q(scl_q), .sda_q(sda_q), .scl_rise(scl_rise), .scl_fall(scl_fall),
         .sda_rise(sda_rise), .sda_fall(sda_fall));

      i2c_slave_mack #(.CNT_W(16)) dut (
         .clk(clk), .rst_n(rst_n), .scl_rise(scl_rise), .sda_q(sda_q),
         .start_pulse(f_start), .stop_pulse(f_stop), .byte_sent(byte_sent),
         .awaiting(awaiting), .mack_valid(mack_valid), .mack_ack(mack_ack),
         .keep_sourcing(keep_sourcing), .n_ack(n_ack), .n_nack(n_nack));

      always #5 clk = ~clk;
      task step;  begin @(posedge clk); @(negedge clk); end endtask
      task phase; begin for (n = 0; n < HALF; n = n + 1) step; end endtask

      task do_reset;
         begin
            @(negedge clk); rst_n = 1'b0;
            m_scl_low = 1'b0; m_sda_low = 1'b0; byte_sent = 1'b0;
            f_start = 1'b0; f_stop = 1'b0;
            n_valid_obs = 0; wide = 0; last_ack = 1'b0;
            step; step; @(negedge clk); rst_n = 1'b1; phase;
         end
      endtask

      // One clock pulse with the master driving SDA to `d` (active-low intent) through it.
      // The value is placed in the LOW phase, as §3.1.2 requires.
      task gen_pulse (input drive_low);
         begin
            @(negedge clk); m_scl_low = 1'b1; phase;
            @(negedge clk); m_sda_low = drive_low; phase;
            @(negedge clk); m_scl_low = 1'b0; phase;
            @(negedge clk); m_scl_low = 1'b1; phase;
         end
      endtask

      task pulse_byte_sent;
         begin @(negedge clk); byte_sent = 1'b1; step; @(negedge clk); byte_sent = 1'b0; end
      endtask

      task ck_bit (input [200*8:1] w, input g, input e);
         begin if (g !== e) begin
            $display("  FAIL %0s: got %0b expected %0b", w, g, e); errors = errors + 1; end end
      endtask
      task ck_int (input [200*8:1] w, input integer g, input integer e);
         begin if (g !== e) begin
            $display("  FAIL %0s: got %0d expected %0d", w, g, e); errors = errors + 1; end end
      endtask

      initial begin
         $display("=== i2c_slave_mack: the ninth bit of a read, which the master drives ===");

         // ----------------------------------------------------------------
         // T1. RESET DOES NOT ASSUME A READ IS IN PROGRESS. `keep_sourcing` low is the safe
         //     default: a target that came up believing a read was open would drive a bus it
         //     has no claim on.
         // ----------------------------------------------------------------
         do_reset;
         $display("T1  a reset target is not awaiting an answer and will not source");
         ck_bit("T1 not awaiting", awaiting, 1'b0);
         ck_bit("T1 and not sourcing", keep_sourcing, 1'b0);
         ck_int("T1 no answers seen", n_valid_obs, 0);

         // ----------------------------------------------------------------
         // T2. NOTHING WITHOUT A COMPLETED BYTE. Clocking alone must not be read as an
         //     answer -- the false-positive test. Without this gate the block would sample
         //     every data bit of every read as though it were the master's acknowledge.
         // ----------------------------------------------------------------
         do_reset;
         for (k = 0; k < 4; k = k + 1) gen_pulse(1'b0);
         $display("T2  clocking with no byte completed yields no answer");
         ck_int("T2 no answer", n_valid_obs, 0);
         ck_bit("T2 not awaiting", awaiting, 1'b0);

         // ----------------------------------------------------------------
         // T3. AN ACK: the master pulls SDA LOW in the ninth slot. LOW means acknowledged,
         //     which is inverted relative to intuition for the same reason as everywhere
         //     else in I²C -- the responder pulls down.
         // ----------------------------------------------------------------
         do_reset;
         pulse_byte_sent;
         ck_bit("T3 awaiting the answer", awaiting, 1'b1);
         gen_pulse(1'b1);                     // master drives LOW = ACK
         $display("T3  a LOW in the ninth slot is an acknowledge");
         ck_int("T3 one answer sampled", n_valid_obs, 1);
         ck_bit("T3 and it was an ACK", last_ack, 1'b1);
         ck_bit("T3 so the target keeps sourcing", keep_sourcing, 1'b1);
         ck_int("T3 the ACK counter moved", n_ack, 1);
         ck_bit("T3 and it is no longer awaiting", awaiting, 1'b0);

         // ----------------------------------------------------------------
         // T4. A NACK: the master leaves SDA released. A NACK is the ABSENCE of a response,
         //     which makes it the default -- and that is the right way round, because the
         //     failure mode of a missing master is a target that stops.
         // ----------------------------------------------------------------
         do_reset;
         pulse_byte_sent;
         gen_pulse(1'b0);                     // master leaves it HIGH = NACK
         $display("T4  a HIGH in the ninth slot is a NACK, and it is the default");
         ck_int("T4 one answer sampled", n_valid_obs, 1);
         ck_bit("T4 and it was a NACK", last_ack, 1'b0);
         ck_bit("T4 so the target stops sourcing", keep_sourcing, 1'b0);
         ck_int("T4 the NACK counter moved", n_nack, 1);

         // ----------------------------------------------------------------
         // T5. THE ANSWER IS SAMPLED AT THE RISING EDGE, not at the fall. §3.1.2 makes SDA
         //     stable only while SCL is HIGH, so the rise is the one instant the master's
         //     answer is guaranteed valid. Here the master presents a LOW in the low phase
         //     and the block must not conclude anything until SCL rises.
         // ----------------------------------------------------------------
         do_reset;
         pulse_byte_sent;
         @(negedge clk); m_scl_low = 1'b1; phase;      // SCL low
         @(negedge clk); m_sda_low = 1'b1; phase;      // the answer is presented
         ck_int("T5 nothing concluded while SCL is still low", n_valid_obs, 0);
         ck_bit("T5 still awaiting", awaiting, 1'b1);
         @(negedge clk); m_scl_low = 1'b0; phase;      // SCL rises
         $display("T5  the answer is sampled at the rising edge, not before");
         ck_int("T5 now it is sampled", n_valid_obs, 1);
         ck_bit("T5 and it read as an ACK", last_ack, 1'b1);

         // ----------------------------------------------------------------
         // T6. ONE ANSWER PER BYTE. The pulse is one cycle and fires once -- a block that
         //     kept sampling would take the NEXT byte's first data bit as a second answer.
         // ----------------------------------------------------------------
         do_reset;
         pulse_byte_sent;
         gen_pulse(1'b1);
         gen_pulse(1'b1); gen_pulse(1'b1);    // more clocking, more lows
         $display("T6  exactly one answer per completed byte, whatever follows");
         ck_int("T6 still one answer", n_valid_obs, 1);
         ck_int("T6 the pulse was one cycle", wide, 0);

         // ----------------------------------------------------------------
         // T7. TWO BYTES, TWO ANSWERS: ACK then NACK, which is how every multi-byte read
         //     ends. The second answer must override the first.
         // ----------------------------------------------------------------
         do_reset;
         pulse_byte_sent; gen_pulse(1'b1);    // ACK -> keep going
         ck_bit("T7 sourcing after the ACK", keep_sourcing, 1'b1);
         pulse_byte_sent; gen_pulse(1'b0);    // NACK -> stop
         $display("T7  ACK then NACK: the second answer overrides the first");
         ck_int("T7 two answers", n_valid_obs, 2);
         ck_bit("T7 the last was a NACK", last_ack, 1'b0);
         ck_bit("T7 and sourcing stopped", keep_sourcing, 1'b0);
         ck_int("T7 one of each was counted", n_ack + n_nack, 2);

         // ----------------------------------------------------------------
         // T8. THIS BLOCK NEVER DRIVES. It has no drive output at all, which is the point:
         //     the ninth slot of a read belongs to the master, and a target that drove there
         //     would fight the very answer it is trying to read. The bench proves it
         //     structurally -- the slave contributes nothing to the bus in this testbench,
         //     so the line is exactly what the master made it.
         // ----------------------------------------------------------------
         $display("T8  the block has no drive output: the ninth slot is not its to own");
         ck_bit("T8 the line is the master's alone", sda, ~m_sda_low);

         // ----------------------------------------------------------------
         // T9. FRAMING ENDS THE READ regardless of the ninth bit. After a NACK the master
         //     issues a STOP or a repeated START, and this is that framing arriving -- but
         //     framing must also end a read that was still expecting an answer.
         // ----------------------------------------------------------------
         do_reset;
         pulse_byte_sent; gen_pulse(1'b1);    // ACK: sourcing
         ck_bit("T9 sourcing before the framing", keep_sourcing, 1'b1);
         @(negedge clk); f_stop = 1'b1; step; @(negedge clk); f_stop = 1'b0; step;
         $display("T9  framing ends the read whatever the ninth bit said");
         ck_bit("T9 sourcing stopped", keep_sourcing, 1'b0);
         ck_bit("T9 and not awaiting", awaiting, 1'b0);

         // ----------------------------------------------------------------
         // T10. AND A REPEATED START DOES THE SAME -- the other half, and the likelier one:
         //      a master ending a read usually restarts rather than stopping.
         // ----------------------------------------------------------------
         do_reset;
         pulse_byte_sent; gen_pulse(1'b1);
         @(negedge clk); f_start = 1'b1; step; @(negedge clk); f_start = 1'b0; step;
         $display("T10 a repeated START ends it too");
         ck_bit("T10 sourcing stopped", keep_sourcing, 1'b0);
         ck_bit("T10 and not awaiting", awaiting, 1'b0);

         // ----------------------------------------------------------------
         // T11. FRAMING WHILE STILL AWAITING cancels the wait. A master that abandons a read
         //      mid-slot never supplies an answer, and a block left awaiting would take the
         //      NEXT transfer's first data bit as this read's acknowledge.
         // ----------------------------------------------------------------
         do_reset;
         pulse_byte_sent;
         ck_bit("T11 awaiting", awaiting, 1'b1);
         @(negedge clk); f_start = 1'b1; step; @(negedge clk); f_start = 1'b0; step;
         ck_bit("T11 the wait was cancelled", awaiting, 1'b0);
         gen_pulse(1'b1);                     // a low that is NOT an answer
         $display("T11 framing while awaiting cancels the wait, so no false answer");
         ck_int("T11 and nothing was taken as an answer", n_valid_obs, 0);

         // ----------------------------------------------------------------
         // T12. RESET CLEARS EVERYTHING, including the sourcing permission.
         // ----------------------------------------------------------------
         do_reset;
         pulse_byte_sent; gen_pulse(1'b1);
         ck_bit("T12 sourcing before reset", keep_sourcing, 1'b1);
         @(negedge clk); rst_n = 1'b0; step; step;
         $display("T12 reset clears the sourcing permission and the counters");
         ck_bit("T12 not sourcing", keep_sourcing, 1'b0);
         ck_int("T12 counters cleared", n_ack + n_nack, 0);

         if (errors == 0) $display("=== i2c_slave_mack: ALL CHECKS PASSED ===");
         else             $display("=== i2c_slave_mack: %0d CHECK(S) FAILED ===", errors);
         $finish;
      end

   endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
i2c_slave_mack_tb.vhd — the same tests in VHDL
   -- -----------------------------------------------------------------------------
   -- i2c_slave_mack_tb.vhd
   -- Independent oracle for i2c_slave_mack. Behavioural twin of the SystemVerilog and
   -- Verilog benches: twelve tests, the same observers, the same finish time.
   -- -----------------------------------------------------------------------------
   library ieee;
   use ieee.std_logic_1164.all;
   use ieee.numeric_std.all;

   entity i2c_slave_mack_tb is
   end entity i2c_slave_mack_tb;

   architecture sim of i2c_slave_mack_tb is

      constant HALF : positive := 8;

      signal clk   : std_logic := '0';
      signal rst_n : std_logic := '0';
      signal m_scl_low, m_sda_low : std_logic := '0';
      signal byte_sent : std_logic := '0';
      signal f_start, f_stop : std_logic := '0';

      signal scl, sda : std_logic;
      signal scl_q, sda_q : std_logic;
      signal scl_rise, scl_fall, sda_rise, sda_fall : std_logic;
      signal awaiting, mack_valid, mack_ack, keep_sourcing : std_logic;
      signal n_ack, n_nack : unsigned(15 downto 0);

      signal halt : boolean := false;

      signal n_valid_obs, wide : integer := 0;
      signal last_ack : std_logic := '0';
      signal clr : boolean := false;

   begin

      scl <= not m_scl_low;
      sda <= not m_sda_low;

      u_sync : entity work.i2c_slave_sync
         generic map (SYNC_DEPTH => 2)
         port map (clk => clk, rst_n => rst_n, scl_pin => scl, sda_pin => sda,
            scl_q => scl_q, sda_q => sda_q, scl_rise => scl_rise, scl_fall => scl_fall,
            sda_rise => sda_rise, sda_fall => sda_fall);

      dut : entity work.i2c_slave_mack
         generic map (CNT_W => 16)
         port map (clk => clk, rst_n => rst_n, scl_rise => scl_rise, sda_q => sda_q,
            start_pulse => f_start, stop_pulse => f_stop, byte_sent => byte_sent,
            awaiting => awaiting, mack_valid => mack_valid, mack_ack => mack_ack,
            keep_sourcing => keep_sourcing, n_ack => n_ack, n_nack => n_nack);

      clkgen : process
      begin
         while not halt loop
            clk <= '0'; wait for 5 ns;
            clk <= '1'; wait for 5 ns;
         end loop;
         wait;
      end process;

      obs : process (clk, clr)
         variable v_d : std_logic := '0';
      begin
         if clr then
            n_valid_obs <= 0; wide <= 0; last_ack <= '0';
         elsif rising_edge(clk) then
            if rst_n = '1' then
               if mack_valid = '1' then
                  n_valid_obs <= n_valid_obs + 1;
                  last_ack <= mack_ack;
               end if;
               if mack_valid = '1' and v_d = '1' then wide <= wide + 1; end if;
            end if;
            v_d := mack_valid;
         end if;
      end process;

      stim : process
         variable err : integer := 0;
         variable k : integer;

         procedure step is
         begin
            wait until rising_edge(clk); wait until falling_edge(clk);
         end procedure;

         procedure phase is
         begin
            for i in 1 to HALF loop step; end loop;
         end procedure;

         procedure do_reset is
         begin
            wait until falling_edge(clk);
            rst_n <= '0'; m_scl_low <= '0'; m_sda_low <= '0'; byte_sent <= '0';
            f_start <= '0'; f_stop <= '0';
            clr <= true; wait for 1 ns; clr <= false;
            step; step;
            wait until falling_edge(clk); rst_n <= '1'; phase;
         end procedure;

         procedure gen_pulse (drive_low : std_logic) is
         begin
            wait until falling_edge(clk); m_scl_low <= '1'; phase;
            wait until falling_edge(clk); m_sda_low <= drive_low; phase;
            wait until falling_edge(clk); m_scl_low <= '0'; phase;
            wait until falling_edge(clk); m_scl_low <= '1'; phase;
         end procedure;

         procedure pulse_byte_sent is
         begin
            wait until falling_edge(clk); byte_sent <= '1';
            step;
            wait until falling_edge(clk); byte_sent <= '0';
         end procedure;

         procedure ck_bit (what : string; g : std_logic; e : std_logic) is
         begin
            if g /= e then
               report "  FAIL " & what severity note;
               err := err + 1;
            end if;
         end procedure;

         procedure ck_int (what : string; g : integer; e : integer) is
         begin
            if g /= e then
               report "  FAIL " & what & ": got " & integer'image(g)
                      & " expected " & integer'image(e) severity note;
               err := err + 1;
            end if;
         end procedure;

      begin
         report "=== i2c_slave_mack: the ninth bit of a read, which the master drives ==="
                severity note;

         -- T1. Reset does not assume a read is in progress.
         do_reset;
         report "T1  a reset target is not awaiting an answer and will not source"
                severity note;
         ck_bit("T1 not awaiting", awaiting, '0');
         ck_bit("T1 and not sourcing", keep_sourcing, '0');
         ck_int("T1 no answers seen", n_valid_obs, 0);

         -- T2. Nothing without a completed byte.
         do_reset;
         for k in 0 to 3 loop gen_pulse('0'); end loop;
         report "T2  clocking with no byte completed yields no answer" severity note;
         ck_int("T2 no answer", n_valid_obs, 0);
         ck_bit("T2 not awaiting", awaiting, '0');

         -- T3. An ACK: the master pulls SDA LOW.
         do_reset;
         pulse_byte_sent;
         ck_bit("T3 awaiting the answer", awaiting, '1');
         gen_pulse('1');
         report "T3  a LOW in the ninth slot is an acknowledge" severity note;
         ck_int("T3 one answer sampled", n_valid_obs, 1);
         ck_bit("T3 and it was an ACK", last_ack, '1');
         ck_bit("T3 so the target keeps sourcing", keep_sourcing, '1');
         ck_int("T3 the ACK counter moved", to_integer(n_ack), 1);
         ck_bit("T3 and it is no longer awaiting", awaiting, '0');

         -- T4. A NACK: the master leaves SDA released.
         do_reset;
         pulse_byte_sent;
         gen_pulse('0');
         report "T4  a HIGH in the ninth slot is a NACK, and it is the default"
                severity note;
         ck_int("T4 one answer sampled", n_valid_obs, 1);
         ck_bit("T4 and it was a NACK", last_ack, '0');
         ck_bit("T4 so the target stops sourcing", keep_sourcing, '0');
         ck_int("T4 the NACK counter moved", to_integer(n_nack), 1);

         -- T5. Sampled at the rising edge, not before.
         do_reset;
         pulse_byte_sent;
         wait until falling_edge(clk); m_scl_low <= '1'; phase;
         wait until falling_edge(clk); m_sda_low <= '1'; phase;
         ck_int("T5 nothing concluded while SCL is still low", n_valid_obs, 0);
         ck_bit("T5 still awaiting", awaiting, '1');
         wait until falling_edge(clk); m_scl_low <= '0'; phase;
         report "T5  the answer is sampled at the rising edge, not before" severity note;
         ck_int("T5 now it is sampled", n_valid_obs, 1);
         ck_bit("T5 and it read as an ACK", last_ack, '1');

         -- T6. One answer per byte.
         do_reset;
         pulse_byte_sent;
         gen_pulse('1');
         gen_pulse('1'); gen_pulse('1');
         report "T6  exactly one answer per completed byte, whatever follows" severity note;
         ck_int("T6 still one answer", n_valid_obs, 1);
         ck_int("T6 the pulse was one cycle", wide, 0);

         -- T7. Two bytes, ACK then NACK.
         do_reset;
         pulse_byte_sent; gen_pulse('1');
         ck_bit("T7 sourcing after the ACK", keep_sourcing, '1');
         pulse_byte_sent; gen_pulse('0');
         report "T7  ACK then NACK: the second answer overrides the first" severity note;
         ck_int("T7 two answers", n_valid_obs, 2);
         ck_bit("T7 the last was a NACK", last_ack, '0');
         ck_bit("T7 and sourcing stopped", keep_sourcing, '0');
         ck_int("T7 one of each was counted", to_integer(n_ack) + to_integer(n_nack), 2);

         -- T8. This block never drives.
         report "T8  the block has no drive output: the ninth slot is not its to own"
                severity note;
         ck_bit("T8 the line is the master's alone", sda, not m_sda_low);

         -- T9. Framing ends the read.
         do_reset;
         pulse_byte_sent; gen_pulse('1');
         ck_bit("T9 sourcing before the framing", keep_sourcing, '1');
         wait until falling_edge(clk); f_stop <= '1';
         step;
         wait until falling_edge(clk); f_stop <= '0';
         step;
         report "T9  framing ends the read whatever the ninth bit said" severity note;
         ck_bit("T9 sourcing stopped", keep_sourcing, '0');
         ck_bit("T9 and not awaiting", awaiting, '0');

         -- T10. And a repeated START does the same.
         do_reset;
         pulse_byte_sent; gen_pulse('1');
         wait until falling_edge(clk); f_start <= '1';
         step;
         wait until falling_edge(clk); f_start <= '0';
         step;
         report "T10 a repeated START ends it too" severity note;
         ck_bit("T10 sourcing stopped", keep_sourcing, '0');
         ck_bit("T10 and not awaiting", awaiting, '0');

         -- T11. Framing while awaiting cancels the wait.
         do_reset;
         pulse_byte_sent;
         ck_bit("T11 awaiting", awaiting, '1');
         wait until falling_edge(clk); f_start <= '1';
         step;
         wait until falling_edge(clk); f_start <= '0';
         step;
         ck_bit("T11 the wait was cancelled", awaiting, '0');
         gen_pulse('1');
         report "T11 framing while awaiting cancels the wait, so no false answer"
                severity note;
         ck_int("T11 and nothing was taken as an answer", n_valid_obs, 0);

         -- T12. Reset clears everything.
         do_reset;
         pulse_byte_sent; gen_pulse('1');
         ck_bit("T12 sourcing before reset", keep_sourcing, '1');
         wait until falling_edge(clk); rst_n <= '0'; step; step;
         report "T12 reset clears the sourcing permission and the counters" severity note;
         ck_bit("T12 not sourcing", keep_sourcing, '0');
         ck_int("T12 counters cleared", to_integer(n_ack) + to_integer(n_nack), 0);

         if err = 0 then
            report "=== i2c_slave_mack: ALL CHECKS PASSED ===" severity note;
         else
            report "=== i2c_slave_mack: " & integer'image(err) & " CHECK(S) FAILED ==="
                   severity note;
         end if;
         halt <= true;
         wait;
      end process;

   end architecture sim;

All three languages finish at the same instant:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
i2c_slave_mack_tb.sv    ALL CHECKS PASSED    $finish at 7440000
i2c_slave_mack_tb.v     ALL CHECKS PASSED    $finish at 7440000
i2c_slave_mack_tb.vhd   ALL CHECKS PASSED    stopped at 7440 ns

9. Mutation Testing

Ten defects, all ten killed on the first pass — the first block in this module for which that is true, and the reason is worth stating precisely rather than claiming as skill.

#Injected defectExpected detectionResult
M1inverted polarity — a HIGH is read as an acknowledgeT3, T4KILLED (11)
M2sampled on any cycle, not at the rising edgeT5KILLED (13)
M3the awaiting gate dropped: every data bit becomes an answerT2, T6KILLED (4)
M4a NACK is ignored: the target keeps sourcing regardlessT4KILLED (3)
M5an ACK never permits continuationT3, T7KILLED (5)
M6the ACK and NACK counters swappedT3, T4KILLED (3)
M7framing does not end the readT9, T10, T11KILLED (5)
M8byte_sent does not arm the waitT3 and afterKILLED (18)
M9the wait is not cleared, so the next bit is a second answerT6KILLED (3)
M10reset comes up permitting sourcingT1KILLED (3)
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
baseline: PASS   (verified before injecting anything)
valid mutants: 10   killed: 10   survived: 0   equivalent: 0   invalid: 0
restored: PASS

Why nothing survived here, when six mutants survived earlier in this module

Not because the block is simple — M7 and M9 are exactly the defects that survived in 18.5 and 18.6. They died here because the three survivor shapes this module has produced were applied as a checklist before running, not diagnosed afterwards:

shape first seen inthe check applied here
a framing input tied to a constant (18.5 M8)start_pulse and stop_pulse are driven, and T9–T11 use them
an output with no consumer (18.7)every output is read by an observer, n_ack and n_nack included
the untested half of a symmetric property (18.2, 18.3)T3 and T4 test both polarities; T7 tests the transition between them

The exception is worth being honest about: M8's eighteen failures are not a sign of a strong test, but of a mutant that disables the block entirely. A high failure count means the mutation was coarse, not that the bench is thorough — M4, M6, M9 and M10 each died on three checks, and those are the informative numbers.

10. Verification Connection — One Answer Per Byte

The property worth asserting is not the polarity, which any directed test catches. It is the cardinality: exactly one answer per completed byte, no more and no fewer.

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
// Not synthesisable. Icarus rejects SVA, so this documents the intent the
// bench's observer checks procedurally.
property one_answer_per_byte;
   @(posedge clk) disable iff (!rst_n)
      byte_sent |-> ##[1:$] (mack_valid || start_pulse || stop_pulse);
endproperty

property answer_needs_a_rise;
   @(posedge clk) disable iff (!rst_n)
      mack_valid |-> $past(scl_rise) && $past(awaiting);
endproperty

The second property is the one that would have found M2 and M3 without T5 existing: it says the valid pulse is only ever preceded by a rising edge inside a wait, which is the same claim as "sampled at the right instant" stated as an implication rather than a scenario.

The bench checks both procedurally instead, with a counting observer that also asserts the pulse is exactly one cycle wide — T6's wide check. A one-cycle pulse that stretches to two is a defect the polarity tests cannot see, because both cycles carry the same correct value.

11. FPGA and ASIC Implications

Nothing here is timing-critical. The block is a handful of flops with no arithmetic beyond two diagnostic counters, and it reads a signal that 18.2 has already synchronised — so there is no asynchronous input on this boundary at all.

Two implementation notes do matter:

The counters are diagnostics and should be parameterised out. CNT_W exists so a production build can shrink or remove them; they are there because an ACK/NACK ratio is the single most useful number when debugging a read that ends too early.

keep_sourcing is a level crossing into 18.7, in the same clock domain, so it needs no handshake — but it must be sampled by the transmitter at a defined instant, not used combinationally to gate a pad. That distinction is 18.11's to enforce.

12. Debugging — The Read That Delivers One Byte Too Many

Symptom. A master reads two bytes, NACKs the second, and issues a STOP. The bus works. But a logic analyser shows a third byte on the wire, overlapping the STOP, and occasionally the STOP is missing entirely and the next transaction fails to start.

What it is not. Not the register pointer, which is 18.9's: the extra byte's contents are correct for the next pointer value, which is why the pointer looks innocent. Not the transmit path either — it did exactly what it was told.

What it is. The NACK was sampled and the answer was ignored: mack_ack is produced but keep_sourcing is not derived from it, so 18.7 fetches another byte. That is mutant M4, and it is the single most plausible hand-written version of this block, because detecting the answer feels like the job and acting on it feels like somebody else's.

Why the intermittency. Whether the STOP survives depends on the extra byte's MSB. A one means the slave releases SDA and the master's STOP happens normally — the bug is invisible. A zero means the slave holds SDA low and the STOP does not occur at all. So the failure rate tracks the data, and a register map whose next value happens to have a high MSB hides the defect completely.

13. Common Misconceptions

"The slave acknowledges every byte, so it always drives the ninth bit." Only on writes. On a read the slave is the transmitter, and §3.1.4 requires the transmitter to release the acknowledge slot.

"A NACK from the master means something went wrong." It is the normal, mandatory way a master ends a read — §3.1.10. A read that ends with an ACK and a STOP is the abnormal case, and some slaves mis-handle it.

"The slave can ignore the answer, because the master will STOP anyway." It will try, and the slave's next data zero will prevent it. §4.

"The answer can be read whenever, since SDA is stable for a whole slot." It is stable while SCL is high. In the low phase of the ninth slot the master is still setting up its answer, and a block that samples there reads a value in transit — mutant M2, and it fails thirteen checks.

"A valid pulse two cycles wide is harmless because both cycles agree." The consumer counts pulses. Two pulses per byte is two answers per byte, and the second one is read after the wait was supposed to have ended — mutant M9.

14. Reason It Through

On a read, the slave drove an eighth data bit of zero and did not release. What does the detector conclude, and why is the conclusion worse than a wrong byte?

It samples its own pull-down and reads it as an ACK, so it keeps sourcing forever. A wrong byte is recoverable by a retry; this is not, because the retry needs a free SDA and the slave never frees it. §3, §4.

Why is a NACK the default rather than the exception?

Because it is the absence of a response, so a missing, reset, or silent master produces a slave that stops rather than a slave that keeps driving. §2.

Framing arrives in the same cycle as byte_sent. Which wins, and what would the other order do?

Framing wins. The other order would arm a wait inside a transfer that has already ended, and the next transfer's first rising edge would be consumed as this transfer's answer. §5.

Three chapters in this module have had the same class of bug. State the rule it produces.

Every flag meaning "I am waiting for a future edge" is state that framing must clear — an armed acknowledge slot (18.5), a partial byte (18.6), a pending answer (here). §5.

All ten mutants died here after six survived earlier in the module. What makes that evidence of method rather than luck?

The three survivor shapes were applied as a pre-run checklist, and M7 and M9 are exactly the defects that survived before. Two of the three checks are greps. §9.

15. Understanding Check

16. Summary

The ninth slot belongs to whoever received the byte. On a write that is the slave, and 18.5 drives it. On a read it is the master, and this block reads it — the two are mirror images and must never be active together.

A NACK is the absence of a response, which makes it the default and makes a missing master produce a slave that stops rather than a slave that keeps driving.

The answer is sampled at the rising edge, because SDA is stable only while SCL is high. The slave released a full phase earlier, on the fall that ended its eighth bit, so the detector never arbitrates for the line.

Ignoring the answer wedges the bus. A slave sourcing an unwanted byte holds SDA low for every zero in it, which prevents the master's STOP from occurring — and a retry cannot help, because a START needs a free SDA too.

So keep_sourcing is granted by one observation and revoked by everything else: reset, a NACK, and every framing event.

Framing must clear a pending wait, not only the permission — the third instance in this module of an armed flag surviving a transfer that ended, which is now a stated rule rather than three separate bugs.

Ten mutants, ten killed on the first pass — including the two shapes that survived in 18.5 and 18.6, because the module's survivor taxonomy was applied as a checklist before running rather than as a diagnosis afterwards.

And the informative mutants are the ones with low failure counts. M8's eighteen failures say the mutation was coarse; M4, M6, M9 and M10 died on three checks each, and those three are what the bench actually proves.

17. What Comes Next

The protocol engine is complete: the target can frame, match, receive, acknowledge, transmit, and now listen to the answer. What it still has nothing to talk to is an actual register file.

Chapter 18.9 builds it — the pointer, the auto-increment, the read-only bits, and the one requirement that this chapter and 18.7 have already imposed on it: the read must be combinational, because tx_req needs its byte in the same cycle. It is also where Module 16's design decisions stop being a specification and become flops.

Continue learning