Skip to content
VLSI Mentor

I²C · Module 18

Address Shift Register, Address Match and Direction Decode

Three jobs that fail separately: receiving eight bits, deciding whether they name this device, and deciding whether to answer. A design with one state called address cannot tell you which of them broke — and the direction bit governs everything after the byte has left the wire.

A START has arrived (18.3), so a transfer is open. The target now has eight clock pulses to find out whether the transfer is its.

1. Three Jobs, Not One

They are separate because they happen at different times and fail separately:

What brokeSymptom
the shift registerwrong bit order, or sampled on the wrong edge
the comparisonright byte, wrong alignment, or wrong address
the acknowledgeboth of the above correct, driven in the wrong slot

A design with one state called ADDR cannot tell you which. That is not an abstract concern — it is the difference between a bug you find in an afternoon and one you find by replacing the part.

2. MSB First, and Where the Direction Lives

So the first bit observed is address bit 6, and the eighth is R/W̄:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
shreg[7:1] = the seven address bits
shreg[0]   = R/W   -- 1 means the master will READ

3. Where the Bits Are Sampled, and Why Nowhere Else

§3.1.2 makes SDA stable only while SCL is HIGH. So the one instant at which a received bit is guaranteed valid is the rising edge of SCL.

scl_rise from 18.2 is the sampling instant. This block contains no timing of its own and no notion of how long a phase lasts.

Mutation M11 samples on the falling edge instead and fails nineteen checks.

4. An Unselected Slave Must Go Quiet

If the address does not match, this device has no business on the bus until the next START:

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
must not acknowledge
must not drive
must not interpret the data bytes that follow as anything at all

selected is the gate for every later chapter, and the safe value is 0 — which is also its reset value, because an unselected slave is the only state that cannot disturb a bus mid-transfer. Mutation M12 resets selected and dies immediately.

5. What a START and a STOP Must Do to Selection

This is where 18.3's classification earns its keep.

A START of either kind restarts the address phase and drops selection. After a repeated START the master sends an address again, and it is entitled to be a different device's. So selection has to be re-earned, not assumed. Mutation M9 omits the drop, and a repeated START to another device then leaves this one selected — acknowledging bytes in a conversation it is not part of.

A STOP clears selection too. The next transfer opens with an address byte that may belong to somebody else, and a slave that stayed selected would acknowledge it. Mutation M8 omits this.

6. The Address Phase, and a Repeated START to Another Device

A block diagram in two rows. In the top row, a sampling instant and an SDA level feed a shift register, which feeds both a byte-complete output and a seven-bit comparator. The comparator takes the device address as a parameter and produces a match signal, which feeds a selected latch. Separately the shift register's lowest bit feeds a direction latch. In the bottom row, framing events from chapter 18.3 feed a control block that arms the shift register on a start and clears the selected latch on either a start or a stop. The selected and direction latches are shown as the two outputs every later chapter is gated on.scl_rise + sda_q18.2 — the sampleShift registerjob 1 — receive7-bit comparejob 2 — decideselected + dir_readjob 3 gates on theseFraming events18.3 — S, Sr, PArm / clearrenew the claim12
Figure 1 — the address path, drawn as the three separable jobs. The shift register, the comparator and the policy each have their own output, which is what makes a failure attributable.

Selected, then displaced by a repeated START to another address

7 cycles
Seven intervals at byte resolution. The first is a start condition. The second is this device's address with the write bit, and the device becomes selected. The third is the acknowledge slot which this device drives. The fourth is a repeated start condition, at which selection must drop. The fifth is a different device's address, so this device stays unselected. The sixth is that device's acknowledge slot, which this device must not drive. The seventh is a stop.oursoursnot ours — stay silentnot ours — staysilentour address: selectedour address: selectedrepeated START: claim invalidrepeated START: claiminvalidanother device's addressanother device's addresson the wireSADDR 0x50+WACKSrADDR 0x51+WACKPselectedwe drive00yesyesyesnonot0t1t2t3t4t5t6
Figure 2 — the case that catches a design which does not drop selection on a repeated START. This device is addressed, acknowledges, and is then displaced by a restart naming a different device. Conceptual figure at byte resolution: one interval per byte slot, not per clock.

Interval 5 is the one that matters. A design that kept selected through the repeated START would drive an acknowledge there, in the middle of another device's transfer — and both devices would answer the same address byte.

7. The Address Block, in Three Languages

Azvya Education Pvt. Ltd.VLSI Mentor
i2c_slave_addr.sv — acquire the first byte, compare it, latch the direction
   // -----------------------------------------------------------------------------
   // i2c_slave_addr.sv
   // The first byte: acquire it, compare it, and latch the direction.
   //
   // THREE JOBS THAT ARE NOT ONE JOB, and collapsing them is the commonest structural
   // mistake in a first slave:
   //
   //   1. RECEIVE eight bits        -- a shift register clocked by observed SCL rises
   //   2. DECIDE whether they match -- a comparison against this device's address
   //   3. DECIDE whether to answer  -- a policy, which is Chapter 18.5's to execute
   //
   // They are separate because they happen at different times and can fail separately. The
   // shift register is wrong if the bit order or the sampling edge is wrong; the comparison
   // is wrong if the address or its alignment is wrong; and the acknowledge is wrong if it
   // is driven in the wrong slot even when the first two are right. A design with one state
   // called "address" cannot tell you which of the three broke.
   //
   // MSB FIRST. §3.1.3: "Data is transferred with the Most Significant Bit (MSB) first."
   // So the first bit observed is address bit 6, and the EIGHTH is R/W. After eight bits:
   //
   //   shreg[7:1] = the seven address bits
   //   shreg[0]   = R/W -- 1 means the master will READ
   //
   // WHERE THE BITS ARE SAMPLED, and why it cannot be anywhere else. §3.1.2 makes SDA
   // stable only while SCL is HIGH, so the one instant at which a received bit is
   // guaranteed valid is the rising edge of SCL. `scl_rise` from Chapter 18.2 IS the
   // sampling instant; this block contains no timing of its own and no notion of how long
   // a phase lasts. That is the same division of labour Module 17.6 used, arrived at from
   // the opposite side: there the strobes came from a generator this device owned, here
   // they come from a bus this device merely watches.
   //
   // THE DIRECTION IS LATCHED, not re-read. Everything after the address phase depends on
   // it -- who drives SDA in each data byte, who drives the ninth bit, whether the slave
   // sources or sinks -- and the address byte will not be on the wire any more. A design
   // that recomputed direction later would have nothing to recompute it from.
   //
   // AND AN UNSELECTED SLAVE MUST GO QUIET. If the address does not match, this device has
   // no business on the bus until the next START: it must not acknowledge, must not drive,
   // and must not interpret the data bytes that follow as anything at all. `selected` is
   // the gate for every later chapter, and the safe value is 0.
   // -----------------------------------------------------------------------------

   module i2c_slave_addr #(
      // The device's own address. A parameter here; Chapter 18.9 discusses making it
      // software-programmable, and Chapter 18.11 wires whichever the integrator chose.
      parameter [6:0] MY_ADDR = 7'h50,
      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. A START of either kind restarts the address phase: after a
      // repeated START the master sends an address again, and it need not be this one.
      input  logic start_pulse,
      input  logic stop_pulse,

      // The acquisition state, exposed because Chapter 18.5 needs to know when the eighth
      // bit has landed and Chapter 18.11 needs to know whether a byte is in progress.
      output logic        acquiring,   // an address byte is being shifted in
      output logic [3:0]  bit_index,   // 0..7 within the address byte
      output logic        addr_done,   // one cycle: eight bits are in
      output logic [7:0]  addr_byte,   // what was received, for diagnosis

      // The decision, and the direction the rest of the transfer obeys.
      output logic        match,       // one cycle, with addr_done: it was our address
      output logic        selected,    // level: we are the addressed device
      output logic        dir_read,    // level: the master will READ from us

      output logic [CNT_W-1:0] n_match,
      output logic [CNT_W-1:0] n_miss
   );

      logic [7:0] shreg;

      // The byte AS IT WILL BE once this cycle's bit is shifted in. Named, because a
      // concatenation cannot be part-selected -- `{shreg[6:0], sda_q}[7:1]` is not legal --
      // and because the address comparison and the direction bit both need to read the
      // completed byte in the same cycle it completes.
      wire [7:0] shreg_next = {shreg[6:0], sda_q};

      always @(posedge clk or negedge rst_n) begin
         if (!rst_n) begin
            acquiring <= 1'b0;
            bit_index <= 4'd0;
            addr_done <= 1'b0;
            addr_byte <= 8'h00;
            match     <= 1'b0;
            // The safe reset value. An unselected slave drives nothing, so coming up
            // unselected is the only state that cannot disturb a bus mid-transfer.
            selected  <= 1'b0;
            dir_read  <= 1'b0;
            shreg     <= 8'h00;
            n_match   <= {CNT_W{1'b0}};
            n_miss    <= {CNT_W{1'b0}};
         end else begin
            addr_done <= 1'b0;
            match     <= 1'b0;

            if (start_pulse) begin
               // A START of EITHER kind restarts the address phase. After a repeated START
               // the master re-sends an address, and it is allowed to be a different
               // device's -- so selection must be dropped here and re-earned.
               acquiring <= 1'b1;
               bit_index <= 4'd0;
               shreg     <= 8'h00;
               selected  <= 1'b0;
               dir_read  <= 1'b0;
            end else if (stop_pulse) begin
               // A STOP ends everything. Selection must not survive it: the next transfer
               // begins with an address byte that may belong to somebody else, and a slave
               // that stayed selected would acknowledge it.
               acquiring <= 1'b0;
               bit_index <= 4'd0;
               selected  <= 1'b0;
               dir_read  <= 1'b0;
            end else if (acquiring && scl_rise) begin
               // The one legal sampling instant: SDA is stable while SCL is high (§3.1.2),
               // so the rising edge is where a received bit is guaranteed valid.
               shreg <= shreg_next;
               if (bit_index == 4'd7) begin
                  acquiring <= 1'b0;
                  bit_index <= 4'd0;
                  addr_done <= 1'b1;
                  addr_byte <= shreg_next;
                  // The comparison, and the direction, both taken from the byte that has
                  // just completed -- including the bit arriving in this very cycle, which
                  // is why the concatenation is repeated rather than read back from shreg.
                  if (shreg_next[7:1] == MY_ADDR) begin
                     match    <= 1'b1;
                     selected <= 1'b1;
                     dir_read <= shreg_next[0];
                     n_match  <= n_match + 1'b1;
                  end else begin
                     selected <= 1'b0;
                     dir_read <= 1'b0;
                     n_miss   <= n_miss + 1'b1;
                  end
               end else begin
                  bit_index <= bit_index + 4'd1;
               end
            end
         end
      end

   endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
i2c_slave_addr.v — the same design in Verilog-2001
   // -----------------------------------------------------------------------------
   // i2c_slave_addr.v
   // The first byte: acquire it, compare it, and latch the direction.
   //
   // THREE JOBS THAT ARE NOT ONE JOB, and collapsing them is the commonest structural
   // mistake in a first slave:
   //
   //   1. RECEIVE eight bits        -- a shift register clocked by observed SCL rises
   //   2. DECIDE whether they match -- a comparison against this device's address
   //   3. DECIDE whether to answer  -- a policy, which is Chapter 18.5's to execute
   //
   // They are separate because they happen at different times and can fail separately. The
   // shift register is wrong if the bit order or the sampling edge is wrong; the comparison
   // is wrong if the address or its alignment is wrong; and the acknowledge is wrong if it
   // is driven in the wrong slot even when the first two are right. A design with one state
   // called "address" cannot tell you which of the three broke.
   //
   // MSB FIRST. §3.1.3: "Data is transferred with the Most Significant Bit (MSB) first."
   // So the first bit observed is address bit 6, and the EIGHTH is R/W. After eight bits:
   //
   //   shreg[7:1] = the seven address bits
   //   shreg[0]   = R/W -- 1 means the master will READ
   //
   // WHERE THE BITS ARE SAMPLED, and why it cannot be anywhere else. §3.1.2 makes SDA
   // stable only while SCL is HIGH, so the one instant at which a received bit is
   // guaranteed valid is the rising edge of SCL. `scl_rise` from Chapter 18.2 IS the
   // sampling instant; this block contains no timing of its own and no notion of how long
   // a phase lasts. That is the same division of labour Module 17.6 used, arrived at from
   // the opposite side: there the strobes came from a generator this device owned, here
   // they come from a bus this device merely watches.
   //
   // THE DIRECTION IS LATCHED, not re-read. Everything after the address phase depends on
   // it -- who drives SDA in each data byte, who drives the ninth bit, whether the slave
   // sources or sinks -- and the address byte will not be on the wire any more. A design
   // that recomputed direction later would have nothing to recompute it from.
   //
   // AND AN UNSELECTED SLAVE MUST GO QUIET. If the address does not match, this device has
   // no business on the bus until the next START: it must not acknowledge, must not drive,
   // and must not interpret the data bytes that follow as anything at all. `selected` is
   // the gate for every later chapter, and the safe value is 0.
   // (Verilog-2001 -- structurally identical to the SystemVerilog above.)
   // -----------------------------------------------------------------------------

   module i2c_slave_addr #(
      // The device's own address. A parameter here; Chapter 18.9 discusses making it
      // software-programmable, and Chapter 18.11 wires whichever the integrator chose.
      parameter [6:0] MY_ADDR = 7'h50,
      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. A START of either kind restarts the address phase: after a
      // repeated START the master sends an address again, and it need not be this one.
      input  wire  start_pulse,
      input  wire  stop_pulse,

      // The acquisition state, exposed because Chapter 18.5 needs to know when the eighth
      // bit has landed and Chapter 18.11 needs to know whether a byte is in progress.
      output reg          acquiring,   // an address byte is being shifted in
      output reg   [3:0]  bit_index,   // 0..7 within the address byte
      output reg          addr_done,   // one cycle: eight bits are in
      output reg   [7:0]  addr_byte,   // what was received, for diagnosis

      // The decision, and the direction the rest of the transfer obeys.
      output reg          match,       // one cycle, with addr_done: it was our address
      output reg          selected,    // level: we are the addressed device
      output reg          dir_read,    // level: the master will READ from us

      output reg   [CNT_W-1:0] n_match,
      output reg   [CNT_W-1:0] n_miss
   );

      reg [7:0] shreg;

      // The byte AS IT WILL BE once this cycle's bit is shifted in. Named, because a
      // concatenation cannot be part-selected -- `{shreg[6:0], sda_q}[7:1]` is not legal --
      // and because the address comparison and the direction bit both need to read the
      // completed byte in the same cycle it completes.
      wire [7:0] shreg_next = {shreg[6:0], sda_q};

      always @(posedge clk or negedge rst_n) begin
         if (!rst_n) begin
            acquiring <= 1'b0;
            bit_index <= 4'd0;
            addr_done <= 1'b0;
            addr_byte <= 8'h00;
            match     <= 1'b0;
            // The safe reset value. An unselected slave drives nothing, so coming up
            // unselected is the only state that cannot disturb a bus mid-transfer.
            selected  <= 1'b0;
            dir_read  <= 1'b0;
            shreg     <= 8'h00;
            n_match   <= {CNT_W{1'b0}};
            n_miss    <= {CNT_W{1'b0}};
         end else begin
            addr_done <= 1'b0;
            match     <= 1'b0;

            if (start_pulse) begin
               // A START of EITHER kind restarts the address phase. After a repeated START
               // the master re-sends an address, and it is allowed to be a different
               // device's -- so selection must be dropped here and re-earned.
               acquiring <= 1'b1;
               bit_index <= 4'd0;
               shreg     <= 8'h00;
               selected  <= 1'b0;
               dir_read  <= 1'b0;
            end else if (stop_pulse) begin
               // A STOP ends everything. Selection must not survive it: the next transfer
               // begins with an address byte that may belong to somebody else, and a slave
               // that stayed selected would acknowledge it.
               acquiring <= 1'b0;
               bit_index <= 4'd0;
               selected  <= 1'b0;
               dir_read  <= 1'b0;
            end else if (acquiring && scl_rise) begin
               // The one legal sampling instant: SDA is stable while SCL is high (§3.1.2),
               // so the rising edge is where a received bit is guaranteed valid.
               shreg <= shreg_next;
               if (bit_index == 4'd7) begin
                  acquiring <= 1'b0;
                  bit_index <= 4'd0;
                  addr_done <= 1'b1;
                  addr_byte <= shreg_next;
                  // The comparison, and the direction, both taken from the byte that has
                  // just completed -- including the bit arriving in this very cycle, which
                  // is why the concatenation is repeated rather than read back from shreg.
                  if (shreg_next[7:1] == MY_ADDR) begin
                     match    <= 1'b1;
                     selected <= 1'b1;
                     dir_read <= shreg_next[0];
                     n_match  <= n_match + 1'b1;
                  end else begin
                     selected <= 1'b0;
                     dir_read <= 1'b0;
                     n_miss   <= n_miss + 1'b1;
                  end
               end else begin
                  bit_index <= bit_index + 4'd1;
               end
            end
         end
      end

   endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
i2c_slave_addr.vhd — the same design in VHDL
   -- -----------------------------------------------------------------------------
   -- i2c_slave_addr.vhd
   -- Acquire the first byte, compare it, latch the direction. Same ports, generics, reset
   -- values and event timing as the SystemVerilog and Verilog versions.
   -- -----------------------------------------------------------------------------
   library ieee;
   use ieee.std_logic_1164.all;
   use ieee.numeric_std.all;

   entity i2c_slave_addr is
      generic (
         -- The device's own address. Chapter 18.9 discusses making it programmable.
         MY_ADDR : std_logic_vector(6 downto 0) := "1010000";   -- 0x50
         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. A START of either kind restarts the address phase.
         start_pulse : in  std_logic;
         stop_pulse  : in  std_logic;

         acquiring : out std_logic;
         bit_index : out unsigned(3 downto 0);
         addr_done : out std_logic;
         addr_byte : out std_logic_vector(7 downto 0);

         match    : out std_logic;
         selected : out std_logic;
         dir_read : out std_logic;

         n_match : out unsigned(CNT_W-1 downto 0);
         n_miss  : out unsigned(CNT_W-1 downto 0)
      );
   end entity i2c_slave_addr;

   architecture rtl of i2c_slave_addr is
      signal shreg : std_logic_vector(7 downto 0) := (others => '0');

      -- The byte AS IT WILL BE once this cycle's bit is shifted in. Named, because the
      -- comparison and the direction bit both need the completed byte in the cycle it
      -- completes.
      signal shreg_next : std_logic_vector(7 downto 0);

      signal r_acq, r_done, r_match, r_sel, r_dir : std_logic := '0';
      signal r_idx  : unsigned(3 downto 0) := (others => '0');
      signal r_byte : std_logic_vector(7 downto 0) := (others => '0');
      signal c_m, c_x : unsigned(CNT_W-1 downto 0) := (others => '0');
   begin

      shreg_next <= shreg(6 downto 0) & sda_q;

      process (clk, rst_n)
      begin
         if rst_n = '0' then
            r_acq   <= '0';
            r_idx   <= (others => '0');
            r_done  <= '0';
            r_byte  <= (others => '0');
            r_match <= '0';
            -- The safe reset value: an unselected slave drives nothing.
            r_sel   <= '0';
            r_dir   <= '0';
            shreg   <= (others => '0');
            c_m     <= (others => '0');
            c_x     <= (others => '0');
         elsif rising_edge(clk) then
            r_done  <= '0';
            r_match <= '0';

            if start_pulse = '1' then
               -- A START of EITHER kind restarts the address phase: after a repeated START
               -- the master re-sends an address, possibly a different device's.
               r_acq <= '1';
               r_idx <= (others => '0');
               shreg <= (others => '0');
               r_sel <= '0';
               r_dir <= '0';
            elsif stop_pulse = '1' then
               -- Selection must not survive a STOP.
               r_acq <= '0';
               r_idx <= (others => '0');
               r_sel <= '0';
               r_dir <= '0';
            elsif r_acq = '1' and scl_rise = '1' then
               -- The one legal sampling instant (§3.1.2).
               shreg <= shreg_next;
               if r_idx = 7 then
                  r_acq  <= '0';
                  r_idx  <= (others => '0');
                  r_done <= '1';
                  r_byte <= shreg_next;
                  if shreg_next(7 downto 1) = MY_ADDR then
                     r_match <= '1';
                     r_sel   <= '1';
                     r_dir   <= shreg_next(0);
                     c_m     <= c_m + 1;
                  else
                     r_sel <= '0';
                     r_dir <= '0';
                     c_x   <= c_x + 1;
                  end if;
               else
                  r_idx <= r_idx + 1;
               end if;
            end if;
         end if;
      end process;

      acquiring <= r_acq;
      bit_index <= r_idx;
      addr_done <= r_done;
      addr_byte <= r_byte;
      match     <= r_match;
      selected  <= r_sel;
      dir_read  <= r_dir;
      n_match   <= c_m;
      n_miss    <= c_x;

   end architecture rtl;

7a. The testbenches

Twelve tests, behind the real front end and framing block, driven by a hand-written controller.

#TestProperty
T1reset is unselectedthe only state that cannot disturb a bus
T2a START arms acquisition — clocking without one does nothing
T3our address, write directionselected, direction latched
T4our address, read directionsame seven bits, eighth inverted
T5somebody else's addressunselected and silent
T6and data bytes after a mismatch change nothing
T7MSB first, proved with an asymmetric address
T8a repeated START drops selection and re-arms
T9... and a repeated START to our address re-selects with a new directionthe Module 16 turnaround from the device's side
T10a STOP clears selection
T11the bit index is exactly eight widea ninth shift eats the acknowledge slot
T12three addressings, two ours, counted exactlynothing accumulates

T7 uses 0x50 — 1010000 — deliberately. Sent LSB-first it would arrive as 0000101 and match nothing; an address whose bit pattern is symmetric could not distinguish the two orders.

Azvya Education Pvt. Ltd.VLSI Mentor
i2c_slave_addr_tb.sv — the self-checking testbench
   // -----------------------------------------------------------------------------
   // i2c_slave_addr_tb.sv
   // Independent oracle for i2c_slave_addr, behind the real front end and framing block.
   //
   // The bench is a controller: it frames transfers and clocks out address bytes MSB
   // first, changing SDA only while SCL is low. The DUT sees nothing but the two pins.
   // Every wait is bounded.
   // -----------------------------------------------------------------------------
   `timescale 1ns/1ps

   module i2c_slave_addr_tb;

      localparam integer HALF    = 8;
      localparam [6:0]   MY_ADDR = 7'h50;
      localparam [6:0]   OTHER   = 7'h51;

      logic clk = 1'b0, rst_n = 1'b0;
      logic m_scl = 1'b1, m_sda = 1'b1;
      wire  scl_pin = m_scl;
      wire  sda_pin = m_sda;

      logic scl_q, sda_q, scl_rise, scl_fall, sda_rise, sda_fall;
      logic start_pulse, restart_pulse, stop_pulse, bus_active, framing_midbyte;
      logic [15:0] n_sta, n_rs, n_sto;
      logic acquiring, addr_done, match, selected, dir_read;
      logic [3:0]  bit_index;
      logic [7:0]  addr_byte;
      logic [15:0] n_match, n_miss;

      integer errors = 0;
      integer n, k, bitpos;
      logic [6:0] cand;

      // ---- observers -------------------------------------------------------------
      integer n_done_obs = 0, n_match_obs = 0, wide = 0;
      logic ad_d = 1'b0, mt_d = 1'b0;
      always @(posedge clk) begin
         if (rst_n) begin
            if (addr_done) n_done_obs  <= n_done_obs + 1;
            if (match)     n_match_obs <= n_match_obs + 1;
            if ((addr_done & ad_d) | (match & mt_d)) wide <= wide + 1;
         end
         ad_d <= addr_done; mt_d <= match;
      end

      i2c_slave_sync #(.SYNC_DEPTH(2)) u_sync (
         .clk(clk), .rst_n(rst_n), .scl_pin(scl_pin), .sda_pin(sda_pin),
         .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_framing #(.CNT_W(16)) u_frm (
         .clk(clk), .rst_n(rst_n), .scl_q(scl_q),
         .sda_rise(sda_rise), .sda_fall(sda_fall),
         .start_pulse(start_pulse), .restart_pulse(restart_pulse), .stop_pulse(stop_pulse),
         .bus_active(bus_active), .mid_byte(acquiring), .framing_midbyte(framing_midbyte),
         .n_starts(n_sta), .n_restarts(n_rs), .n_stops(n_sto));

      i2c_slave_addr #(.MY_ADDR(MY_ADDR), .CNT_W(16)) dut (
         .clk(clk), .rst_n(rst_n), .scl_rise(scl_rise), .sda_q(sda_q),
         .start_pulse(start_pulse), .stop_pulse(stop_pulse),
         .acquiring(acquiring), .bit_index(bit_index), .addr_done(addr_done),
         .addr_byte(addr_byte), .match(match), .selected(selected), .dir_read(dir_read),
         .n_match(n_match), .n_miss(n_miss));

      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 = 1'b1; m_sda = 1'b1;
            n_done_obs = 0; n_match_obs = 0; wide = 0;
            step; step;
            @(negedge clk); rst_n = 1'b1; phase;
         end
      endtask

      task gen_start;
         begin
            @(negedge clk); m_sda = 1'b1; m_scl = 1'b1; phase;
            @(negedge clk); m_sda = 1'b0; phase;
            @(negedge clk); m_scl = 1'b0; phase;
         end
      endtask

      task gen_restart;
         begin
            @(negedge clk); m_scl = 1'b0; m_sda = 1'b1; phase;
            @(negedge clk); m_scl = 1'b1; phase;
            @(negedge clk); m_sda = 1'b0; phase;
            @(negedge clk); m_scl = 1'b0; phase;
         end
      endtask

      task gen_stop;
         begin
            @(negedge clk); m_scl = 1'b0; m_sda = 1'b0; phase;
            @(negedge clk); m_scl = 1'b1; phase;
            @(negedge clk); m_sda = 1'b1; phase;
         end
      endtask

      task gen_bit (input b);
         begin
            @(negedge clk); m_scl = 1'b0; phase;
            @(negedge clk); m_sda = b;    phase;
            @(negedge clk); m_scl = 1'b1; phase;
            @(negedge clk); m_scl = 1'b0; phase;
         end
      endtask

      // Eight bits, MSB first -- the order §3.1.3 requires.
      task gen_byte (input [7:0] d);
         begin
            for (k = 7; k >= 0; k = k - 1) gen_bit(d[k]);
         end
      endtask

      // The ninth slot, with SDA released so the bench does not fight a slave ACK.
      task gen_ack_slot;
         begin
            @(negedge clk); m_scl = 1'b0; phase;
            @(negedge clk); m_sda = 1'b1; phase;
            @(negedge clk); m_scl = 1'b1; phase;
            @(negedge clk); m_scl = 1'b0; phase;
         end
      endtask

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

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

      initial begin
         $display("=== i2c_slave_addr: receive eight bits, compare, latch the direction ===");

         // ----------------------------------------------------------------
         // T1. RESET IS UNSELECTED. The only state that cannot disturb a bus mid-transfer.
         // ----------------------------------------------------------------
         do_reset;
         $display("T1  a reset slave is unselected and has no direction");
         ck_bit("T1 not selected", selected, 1'b0);
         ck_bit("T1 no direction latched", dir_read, 1'b0);
         ck_bit("T1 not acquiring", acquiring, 1'b0);

         // ----------------------------------------------------------------
         // T2. A START ARMS THE ADDRESS PHASE. Before the START, clocking must do nothing:
         //     a slave that shifted bits on a bus it had not seen a START on would build an
         //     address out of the middle of somebody else's data.
         // ----------------------------------------------------------------
         do_reset;
         gen_bit(1'b0); gen_bit(1'b1);        // clocks with NO start
         ck_bit("T2 clocking without a START does not arm acquisition", acquiring, 1'b0);
         ck_int("T2 and no address completed", n_done_obs, 0);
         gen_start;
         ck_bit("T2 a START arms it", acquiring, 1'b1);

         // ----------------------------------------------------------------
         // T3. OUR ADDRESS, WRITE DIRECTION. Eight bits MSB first, then the decision.
         // ----------------------------------------------------------------
         do_reset;
         gen_start;
         gen_byte({MY_ADDR, 1'b0});
         $display("T3  our address with the write bit selects us, direction write");
         ck_int("T3 one address byte completed", n_done_obs, 1);
         ck_int("T3 and it matched", n_match_obs, 1);
         ck_bit("T3 we are selected", selected, 1'b1);
         ck_bit("T3 direction is write", dir_read, 1'b0);
         ck_int("T3 the received byte is exactly what was sent", addr_byte, {MY_ADDR, 1'b0});
         ck_int("T3 the match counter moved", n_match, 1);
         ck_int("T3 the pulses were one cycle", wide, 0);

         // ----------------------------------------------------------------
         // T4. OUR ADDRESS, READ DIRECTION. The same seven bits, the eighth inverted, and
         //     the direction the whole rest of the transfer obeys changes with it.
         // ----------------------------------------------------------------
         do_reset;
         gen_start;
         gen_byte({MY_ADDR, 1'b1});
         $display("T4  the same address with the read bit latches direction read");
         ck_bit("T4 selected", selected, 1'b1);
         ck_bit("T4 direction is read", dir_read, 1'b1);

         // ----------------------------------------------------------------
         // T5. SOMEBODY ELSE'S ADDRESS. We must go quiet: not selected, no direction, and
         //     nothing for the data bytes that follow to act on.
         // ----------------------------------------------------------------
         do_reset;
         gen_start;
         gen_byte({OTHER, 1'b0});
         $display("T5  another device's address leaves us unselected and silent");
         ck_int("T5 the byte still completed", n_done_obs, 1);
         ck_int("T5 but it did not match", n_match_obs, 0);
         ck_bit("T5 we are not selected", selected, 1'b0);
         ck_int("T5 the miss counter moved", n_miss, 1);

         // ----------------------------------------------------------------
         // T6. AND DATA BYTES AFTER A MISMATCH CHANGE NOTHING. An unselected slave has no
         //     business interpreting the transfer it is not part of.
         // ----------------------------------------------------------------
         gen_ack_slot;
         gen_byte(8'hA5);
         ck_bit("T6 still not selected after the data byte", selected, 1'b0);
         ck_int("T6 and no further address was decoded", n_done_obs, 1);

         // ----------------------------------------------------------------
         // T7. MSB FIRST, PROVED BY AN ASYMMETRIC ADDRESS. 0x50 is 1010000; sent LSB-first
         //     it would arrive as 0000101 and match nothing. An address whose bit pattern
         //     is symmetric could not tell the two orders apart.
         // ----------------------------------------------------------------
         do_reset;
         gen_start;
         gen_byte({MY_ADDR, 1'b0});
         $display("T7  MSB first, proved with an asymmetric address");
         ck_int("T7 the byte arrived in the right order", addr_byte, {MY_ADDR, 1'b0});
         ck_bit("T7 so it matched", selected, 1'b1);

         // ----------------------------------------------------------------
         // T8. A REPEATED START RE-ARMS THE ADDRESS PHASE AND DROPS SELECTION. After a
         //     repeated START the master sends an address again, and it is entitled to be
         //     a different device's -- so selection has to be re-earned, not assumed.
         // ----------------------------------------------------------------
         do_reset;
         gen_start;
         gen_byte({MY_ADDR, 1'b0});
         ck_bit("T8 selected after the first address", selected, 1'b1);
         gen_ack_slot;
         gen_restart;
         $display("T8  a repeated START drops selection and re-arms acquisition");
         ck_bit("T8 selection dropped at the repeated START", selected, 1'b0);
         ck_bit("T8 and acquisition is armed again", acquiring, 1'b1);
         gen_byte({OTHER, 1'b0});
         ck_bit("T8 the new address belongs to somebody else, so we stay unselected",
                selected, 1'b0);

         // ----------------------------------------------------------------
         // T9. ... AND THE OTHER WAY ROUND: a repeated START to OUR address selects us
         //     again, with a possibly different direction. This is the register-read
         //     turnaround of Module 16 seen from the device's side.
         // ----------------------------------------------------------------
         do_reset;
         gen_start;
         gen_byte({MY_ADDR, 1'b0});       // write phase: the pointer
         gen_ack_slot;
         gen_restart;
         gen_byte({MY_ADDR, 1'b1});       // read phase: same device, other direction
         $display("T9  a repeated START to our address re-selects us with a new direction");
         ck_bit("T9 selected again", selected, 1'b1);
         ck_bit("T9 and the direction is now read", dir_read, 1'b1);

         // ----------------------------------------------------------------
         // T10. A STOP CLEARS SELECTION. It must: the next transfer opens with an address
         //      byte that may be another device's, and a slave that stayed selected would
         //      acknowledge it and corrupt a transaction it is not part of.
         // ----------------------------------------------------------------
         do_reset;
         gen_start;
         gen_byte({MY_ADDR, 1'b1});
         ck_bit("T10 selected", selected, 1'b1);
         gen_stop;
         $display("T10 a STOP clears selection; it must not survive into the next transfer");
         ck_bit("T10 not selected after the STOP", selected, 1'b0);
         ck_bit("T10 and no direction is latched", dir_read, 1'b0);

         // ----------------------------------------------------------------
         // T11. THE BIT INDEX IS EXACTLY EIGHT WIDE. Seven intermediate values then done:
         //      a ninth shift would consume the acknowledge slot as data.
         // ----------------------------------------------------------------
         do_reset;
         gen_start;
         for (k = 7; k >= 1; k = k - 1) gen_bit(MY_ADDR[k-1]);   // seven bits
         ck_bit("T11 still acquiring after seven bits", acquiring, 1'b1);
         ck_int("T11 the index reached seven", bit_index, 7);
         gen_bit(1'b0);                                          // the eighth
         ck_bit("T11 acquisition ended after exactly eight", acquiring, 1'b0);
         ck_int("T11 and the byte completed once", n_done_obs, 1);

         // ----------------------------------------------------------------
         // T12. MANY TRANSFERS, NOTHING ACCUMULATES: ours, theirs, ours again.
         // ----------------------------------------------------------------
         do_reset;
         gen_start; gen_byte({MY_ADDR, 1'b0}); gen_ack_slot; gen_stop;
         gen_start; gen_byte({OTHER,   1'b0}); gen_ack_slot; gen_stop;
         gen_start; gen_byte({MY_ADDR, 1'b1}); gen_ack_slot; gen_stop;
         $display("T12 three addressings, two ours, counted exactly");
         ck_int("T12 three address bytes decoded", n_done_obs, 3);
         ck_int("T12 two of them matched", n_match_obs, 2);
         ck_int("T12 the miss counter saw one", n_miss, 1);
         ck_bit("T12 and we end unselected", selected, 1'b0);

         // ----------------------------------------------------------------
         // T13. ALL SEVEN ADDRESS BITS PARTICIPATE. T5 rejected one other address, which
         //      is a weaker result than it looks: 0x51 differs from 0x50 in bit 0 alone,
         //      so a comparator that had dropped any HIGHER bit would still reject it and
         //      still pass T5. A near-miss differing in SEVERAL bits hides a dropped bit
         //      for the same reason -- the bits still being compared reject it anyway.
         //
         //      The property worth asserting is therefore per-bit: flip each address bit
         //      in turn, one at a time, and the match must be lost every time. Seven
         //      vectors, each exactly one bit from ours, is the only shape of stimulus an
         //      ignored address bit cannot hide from. On a real bus a dropped address bit
         //      means two devices acknowledge the same byte.
         // ----------------------------------------------------------------
         do_reset;
         for (bitpos = 0; bitpos < 7; bitpos = bitpos + 1) begin
            cand = MY_ADDR ^ (7'b1 << bitpos);
            gen_start;
            gen_byte({cand, 1'b0});
            ck_bit("T13 a one-bit near-miss leaves us unselected", selected, 1'b0);
            ck_int("T13 and never matches", n_match_obs, 0);
            gen_ack_slot; gen_stop;
         end
         $display("T13 seven one-bit near-misses, every address bit discriminated");
         ck_int("T13 all seven were decoded", n_done_obs, 7);
         ck_int("T13 and the DUT counted seven misses", n_miss, 7);

         // The control. Without it T13 would pass just as well on a DUT that had stopped
         // matching ANYTHING -- the failure a negative-only test cannot see.
         gen_start;
         gen_byte({MY_ADDR, 1'b0});
         ck_bit("T13 the exact address still selects us", selected, 1'b1);
         ck_int("T13 and exactly one byte matched", n_match_obs, 1);

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

   endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
i2c_slave_addr_tb.v — the same tests in Verilog-2001
   // -----------------------------------------------------------------------------
   // i2c_slave_addr_tb.v
   // Independent oracle for i2c_slave_addr, behind the real front end and framing block.
   //
   // The bench is a controller: it frames transfers and clocks out address bytes MSB
   // first, changing SDA only while SCL is low. The DUT sees nothing but the two pins.
   // Every wait is bounded.
   // -----------------------------------------------------------------------------
   `timescale 1ns/1ps

   module i2c_slave_addr_tb;

      localparam integer HALF    = 8;
      localparam [6:0]   MY_ADDR = 7'h50;
      localparam [6:0]   OTHER   = 7'h51;

      reg clk = 1'b0, rst_n = 1'b0;
      reg m_scl = 1'b1, m_sda = 1'b1;
      wire  scl_pin = m_scl;
      wire  sda_pin = m_sda;

      wire scl_q, sda_q, scl_rise, scl_fall, sda_rise, sda_fall;
      wire start_pulse, restart_pulse, stop_pulse, bus_active, framing_midbyte;
      wire [15:0] n_sta, n_rs, n_sto;
      wire acquiring, addr_done, match, selected, dir_read;
      wire [3:0]  bit_index;
      wire [7:0]  addr_byte;
      wire [15:0] n_match, n_miss;

      integer errors = 0;
      integer n, k, bitpos;
      reg [6:0] cand;

      // ---- observers -------------------------------------------------------------
      integer n_done_obs = 0, n_match_obs = 0, wide = 0;
      reg ad_d = 1'b0, mt_d = 1'b0;
      always @(posedge clk) begin
         if (rst_n) begin
            if (addr_done) n_done_obs  <= n_done_obs + 1;
            if (match)     n_match_obs <= n_match_obs + 1;
            if ((addr_done & ad_d) | (match & mt_d)) wide <= wide + 1;
         end
         ad_d <= addr_done; mt_d <= match;
      end

      i2c_slave_sync #(.SYNC_DEPTH(2)) u_sync (
         .clk(clk), .rst_n(rst_n), .scl_pin(scl_pin), .sda_pin(sda_pin),
         .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_framing #(.CNT_W(16)) u_frm (
         .clk(clk), .rst_n(rst_n), .scl_q(scl_q),
         .sda_rise(sda_rise), .sda_fall(sda_fall),
         .start_pulse(start_pulse), .restart_pulse(restart_pulse), .stop_pulse(stop_pulse),
         .bus_active(bus_active), .mid_byte(acquiring), .framing_midbyte(framing_midbyte),
         .n_starts(n_sta), .n_restarts(n_rs), .n_stops(n_sto));

      i2c_slave_addr #(.MY_ADDR(MY_ADDR), .CNT_W(16)) dut (
         .clk(clk), .rst_n(rst_n), .scl_rise(scl_rise), .sda_q(sda_q),
         .start_pulse(start_pulse), .stop_pulse(stop_pulse),
         .acquiring(acquiring), .bit_index(bit_index), .addr_done(addr_done),
         .addr_byte(addr_byte), .match(match), .selected(selected), .dir_read(dir_read),
         .n_match(n_match), .n_miss(n_miss));

      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 = 1'b1; m_sda = 1'b1;
            n_done_obs = 0; n_match_obs = 0; wide = 0;
            step; step;
            @(negedge clk); rst_n = 1'b1; phase;
         end
      endtask

      task gen_start;
         begin
            @(negedge clk); m_sda = 1'b1; m_scl = 1'b1; phase;
            @(negedge clk); m_sda = 1'b0; phase;
            @(negedge clk); m_scl = 1'b0; phase;
         end
      endtask

      task gen_restart;
         begin
            @(negedge clk); m_scl = 1'b0; m_sda = 1'b1; phase;
            @(negedge clk); m_scl = 1'b1; phase;
            @(negedge clk); m_sda = 1'b0; phase;
            @(negedge clk); m_scl = 1'b0; phase;
         end
      endtask

      task gen_stop;
         begin
            @(negedge clk); m_scl = 1'b0; m_sda = 1'b0; phase;
            @(negedge clk); m_scl = 1'b1; phase;
            @(negedge clk); m_sda = 1'b1; phase;
         end
      endtask

      task gen_bit (input b);
         begin
            @(negedge clk); m_scl = 1'b0; phase;
            @(negedge clk); m_sda = b;    phase;
            @(negedge clk); m_scl = 1'b1; phase;
            @(negedge clk); m_scl = 1'b0; phase;
         end
      endtask

      // Eight bits, MSB first -- the order §3.1.3 requires.
      task gen_byte (input [7:0] d);
         begin
            for (k = 7; k >= 0; k = k - 1) gen_bit(d[k]);
         end
      endtask

      // The ninth slot, with SDA released so the bench does not fight a slave ACK.
      task gen_ack_slot;
         begin
            @(negedge clk); m_scl = 1'b0; phase;
            @(negedge clk); m_sda = 1'b1; phase;
            @(negedge clk); m_scl = 1'b1; phase;
            @(negedge clk); m_scl = 1'b0; phase;
         end
      endtask

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

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

      initial begin
         $display("=== i2c_slave_addr: receive eight bits, compare, latch the direction ===");

         // ----------------------------------------------------------------
         // T1. RESET IS UNSELECTED. The only state that cannot disturb a bus mid-transfer.
         // ----------------------------------------------------------------
         do_reset;
         $display("T1  a reset slave is unselected and has no direction");
         ck_bit("T1 not selected", selected, 1'b0);
         ck_bit("T1 no direction latched", dir_read, 1'b0);
         ck_bit("T1 not acquiring", acquiring, 1'b0);

         // ----------------------------------------------------------------
         // T2. A START ARMS THE ADDRESS PHASE. Before the START, clocking must do nothing:
         //     a slave that shifted bits on a bus it had not seen a START on would build an
         //     address out of the middle of somebody else's data.
         // ----------------------------------------------------------------
         do_reset;
         gen_bit(1'b0); gen_bit(1'b1);        // clocks with NO start
         ck_bit("T2 clocking without a START does not arm acquisition", acquiring, 1'b0);
         ck_int("T2 and no address completed", n_done_obs, 0);
         gen_start;
         ck_bit("T2 a START arms it", acquiring, 1'b1);

         // ----------------------------------------------------------------
         // T3. OUR ADDRESS, WRITE DIRECTION. Eight bits MSB first, then the decision.
         // ----------------------------------------------------------------
         do_reset;
         gen_start;
         gen_byte({MY_ADDR, 1'b0});
         $display("T3  our address with the write bit selects us, direction write");
         ck_int("T3 one address byte completed", n_done_obs, 1);
         ck_int("T3 and it matched", n_match_obs, 1);
         ck_bit("T3 we are selected", selected, 1'b1);
         ck_bit("T3 direction is write", dir_read, 1'b0);
         ck_int("T3 the received byte is exactly what was sent", addr_byte, {MY_ADDR, 1'b0});
         ck_int("T3 the match counter moved", n_match, 1);
         ck_int("T3 the pulses were one cycle", wide, 0);

         // ----------------------------------------------------------------
         // T4. OUR ADDRESS, READ DIRECTION. The same seven bits, the eighth inverted, and
         //     the direction the whole rest of the transfer obeys changes with it.
         // ----------------------------------------------------------------
         do_reset;
         gen_start;
         gen_byte({MY_ADDR, 1'b1});
         $display("T4  the same address with the read bit latches direction read");
         ck_bit("T4 selected", selected, 1'b1);
         ck_bit("T4 direction is read", dir_read, 1'b1);

         // ----------------------------------------------------------------
         // T5. SOMEBODY ELSE'S ADDRESS. We must go quiet: not selected, no direction, and
         //     nothing for the data bytes that follow to act on.
         // ----------------------------------------------------------------
         do_reset;
         gen_start;
         gen_byte({OTHER, 1'b0});
         $display("T5  another device's address leaves us unselected and silent");
         ck_int("T5 the byte still completed", n_done_obs, 1);
         ck_int("T5 but it did not match", n_match_obs, 0);
         ck_bit("T5 we are not selected", selected, 1'b0);
         ck_int("T5 the miss counter moved", n_miss, 1);

         // ----------------------------------------------------------------
         // T6. AND DATA BYTES AFTER A MISMATCH CHANGE NOTHING. An unselected slave has no
         //     business interpreting the transfer it is not part of.
         // ----------------------------------------------------------------
         gen_ack_slot;
         gen_byte(8'hA5);
         ck_bit("T6 still not selected after the data byte", selected, 1'b0);
         ck_int("T6 and no further address was decoded", n_done_obs, 1);

         // ----------------------------------------------------------------
         // T7. MSB FIRST, PROVED BY AN ASYMMETRIC ADDRESS. 0x50 is 1010000; sent LSB-first
         //     it would arrive as 0000101 and match nothing. An address whose bit pattern
         //     is symmetric could not tell the two orders apart.
         // ----------------------------------------------------------------
         do_reset;
         gen_start;
         gen_byte({MY_ADDR, 1'b0});
         $display("T7  MSB first, proved with an asymmetric address");
         ck_int("T7 the byte arrived in the right order", addr_byte, {MY_ADDR, 1'b0});
         ck_bit("T7 so it matched", selected, 1'b1);

         // ----------------------------------------------------------------
         // T8. A REPEATED START RE-ARMS THE ADDRESS PHASE AND DROPS SELECTION. After a
         //     repeated START the master sends an address again, and it is entitled to be
         //     a different device's -- so selection has to be re-earned, not assumed.
         // ----------------------------------------------------------------
         do_reset;
         gen_start;
         gen_byte({MY_ADDR, 1'b0});
         ck_bit("T8 selected after the first address", selected, 1'b1);
         gen_ack_slot;
         gen_restart;
         $display("T8  a repeated START drops selection and re-arms acquisition");
         ck_bit("T8 selection dropped at the repeated START", selected, 1'b0);
         ck_bit("T8 and acquisition is armed again", acquiring, 1'b1);
         gen_byte({OTHER, 1'b0});
         ck_bit("T8 the new address belongs to somebody else, so we stay unselected",
                selected, 1'b0);

         // ----------------------------------------------------------------
         // T9. ... AND THE OTHER WAY ROUND: a repeated START to OUR address selects us
         //     again, with a possibly different direction. This is the register-read
         //     turnaround of Module 16 seen from the device's side.
         // ----------------------------------------------------------------
         do_reset;
         gen_start;
         gen_byte({MY_ADDR, 1'b0});       // write phase: the pointer
         gen_ack_slot;
         gen_restart;
         gen_byte({MY_ADDR, 1'b1});       // read phase: same device, other direction
         $display("T9  a repeated START to our address re-selects us with a new direction");
         ck_bit("T9 selected again", selected, 1'b1);
         ck_bit("T9 and the direction is now read", dir_read, 1'b1);

         // ----------------------------------------------------------------
         // T10. A STOP CLEARS SELECTION. It must: the next transfer opens with an address
         //      byte that may be another device's, and a slave that stayed selected would
         //      acknowledge it and corrupt a transaction it is not part of.
         // ----------------------------------------------------------------
         do_reset;
         gen_start;
         gen_byte({MY_ADDR, 1'b1});
         ck_bit("T10 selected", selected, 1'b1);
         gen_stop;
         $display("T10 a STOP clears selection; it must not survive into the next transfer");
         ck_bit("T10 not selected after the STOP", selected, 1'b0);
         ck_bit("T10 and no direction is latched", dir_read, 1'b0);

         // ----------------------------------------------------------------
         // T11. THE BIT INDEX IS EXACTLY EIGHT WIDE. Seven intermediate values then done:
         //      a ninth shift would consume the acknowledge slot as data.
         // ----------------------------------------------------------------
         do_reset;
         gen_start;
         for (k = 7; k >= 1; k = k - 1) gen_bit(MY_ADDR[k-1]);   // seven bits
         ck_bit("T11 still acquiring after seven bits", acquiring, 1'b1);
         ck_int("T11 the index reached seven", bit_index, 7);
         gen_bit(1'b0);                                          // the eighth
         ck_bit("T11 acquisition ended after exactly eight", acquiring, 1'b0);
         ck_int("T11 and the byte completed once", n_done_obs, 1);

         // ----------------------------------------------------------------
         // T12. MANY TRANSFERS, NOTHING ACCUMULATES: ours, theirs, ours again.
         // ----------------------------------------------------------------
         do_reset;
         gen_start; gen_byte({MY_ADDR, 1'b0}); gen_ack_slot; gen_stop;
         gen_start; gen_byte({OTHER,   1'b0}); gen_ack_slot; gen_stop;
         gen_start; gen_byte({MY_ADDR, 1'b1}); gen_ack_slot; gen_stop;
         $display("T12 three addressings, two ours, counted exactly");
         ck_int("T12 three address bytes decoded", n_done_obs, 3);
         ck_int("T12 two of them matched", n_match_obs, 2);
         ck_int("T12 the miss counter saw one", n_miss, 1);
         ck_bit("T12 and we end unselected", selected, 1'b0);

         // ----------------------------------------------------------------
         // T13. ALL SEVEN ADDRESS BITS PARTICIPATE. T5 rejected one other address, which
         //      is a weaker result than it looks: 0x51 differs from 0x50 in bit 0 alone,
         //      so a comparator that had dropped any HIGHER bit would still reject it and
         //      still pass T5. A near-miss differing in SEVERAL bits hides a dropped bit
         //      for the same reason -- the bits still being compared reject it anyway.
         //
         //      The property worth asserting is therefore per-bit: flip each address bit
         //      in turn, one at a time, and the match must be lost every time. Seven
         //      vectors, each exactly one bit from ours, is the only shape of stimulus an
         //      ignored address bit cannot hide from. On a real bus a dropped address bit
         //      means two devices acknowledge the same byte.
         // ----------------------------------------------------------------
         do_reset;
         for (bitpos = 0; bitpos < 7; bitpos = bitpos + 1) begin
            cand = MY_ADDR ^ (7'b1 << bitpos);
            gen_start;
            gen_byte({cand, 1'b0});
            ck_bit("T13 a one-bit near-miss leaves us unselected", selected, 1'b0);
            ck_int("T13 and never matches", n_match_obs, 0);
            gen_ack_slot; gen_stop;
         end
         $display("T13 seven one-bit near-misses, every address bit discriminated");
         ck_int("T13 all seven were decoded", n_done_obs, 7);
         ck_int("T13 and the DUT counted seven misses", n_miss, 7);

         // The control. Without it T13 would pass just as well on a DUT that had stopped
         // matching ANYTHING -- the failure a negative-only test cannot see.
         gen_start;
         gen_byte({MY_ADDR, 1'b0});
         ck_bit("T13 the exact address still selects us", selected, 1'b1);
         ck_int("T13 and exactly one byte matched", n_match_obs, 1);

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

   endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
i2c_slave_addr_tb.vhd — the same tests in VHDL
   -- -----------------------------------------------------------------------------
   -- i2c_slave_addr_tb.vhd
   -- Independent oracle for i2c_slave_addr, behind the real front end and framing block.
   -- Behavioural twin of the SystemVerilog and Verilog benches.
   --
   -- The bench is a controller: it frames transfers and clocks address bytes MSB first,
   -- changing SDA only while SCL is low. The DUT sees nothing but the two pins.
   -- -----------------------------------------------------------------------------
   library ieee;
   use ieee.std_logic_1164.all;
   use ieee.numeric_std.all;

   entity i2c_slave_addr_tb is
   end entity i2c_slave_addr_tb;

   architecture sim of i2c_slave_addr_tb is

      constant HALF    : positive := 8;
      constant MY_ADDR : std_logic_vector(6 downto 0) := "1010000";   -- 0x50
      constant OTHER   : std_logic_vector(6 downto 0) := "1010001";   -- 0x51

      signal clk   : std_logic := '0';
      signal rst_n : std_logic := '0';
      signal m_scl : std_logic := '1';
      signal m_sda : std_logic := '1';

      signal scl_q, sda_q : std_logic;
      signal scl_rise, scl_fall, sda_rise, sda_fall : std_logic;
      signal start_pulse, restart_pulse, stop_pulse, bus_active, framing_midbyte : std_logic;
      signal n_sta, n_rs, n_sto : unsigned(15 downto 0);
      signal acquiring, addr_done, match, selected, dir_read : std_logic;
      signal bit_index : unsigned(3 downto 0);
      signal addr_byte : std_logic_vector(7 downto 0);
      signal n_match, n_miss : unsigned(15 downto 0);

      signal halt : boolean := false;

      signal n_done_obs, n_match_obs : integer := 0;
      signal wide : integer := 0;
      signal clr  : boolean := false;

   begin

      u_sync : entity work.i2c_slave_sync
         generic map (SYNC_DEPTH => 2)
         port map (clk => clk, rst_n => rst_n, scl_pin => m_scl, sda_pin => m_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);

      u_frm : entity work.i2c_slave_framing
         generic map (CNT_W => 16)
         port map (clk => clk, rst_n => rst_n, scl_q => scl_q,
            sda_rise => sda_rise, sda_fall => sda_fall,
            start_pulse => start_pulse, restart_pulse => restart_pulse,
            stop_pulse => stop_pulse, bus_active => bus_active,
            mid_byte => acquiring, framing_midbyte => framing_midbyte,
            n_starts => n_sta, n_restarts => n_rs, n_stops => n_sto);

      dut : entity work.i2c_slave_addr
         generic map (MY_ADDR => MY_ADDR, CNT_W => 16)
         port map (clk => clk, rst_n => rst_n, scl_rise => scl_rise, sda_q => sda_q,
            start_pulse => start_pulse, stop_pulse => stop_pulse,
            acquiring => acquiring, bit_index => bit_index, addr_done => addr_done,
            addr_byte => addr_byte, match => match, selected => selected,
            dir_read => dir_read, n_match => n_match, n_miss => n_miss);

      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 ad_d, mt_d : std_logic := '0';
      begin
         if clr then
            n_done_obs <= 0; n_match_obs <= 0; wide <= 0;
         elsif rising_edge(clk) then
            if rst_n = '1' then
               if addr_done = '1' then n_done_obs  <= n_done_obs + 1;  end if;
               if match = '1'     then n_match_obs <= n_match_obs + 1; end if;
               if (addr_done = '1' and ad_d = '1') or (match = '1' and mt_d = '1') then
                  wide <= wide + 1;
               end if;
            end if;
            ad_d := addr_done; mt_d := match;
         end if;
      end process;

      stim : process
         variable err : integer := 0;
         variable n, k : integer;
         variable cand : std_logic_vector(6 downto 0);

         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 <= '1'; m_sda <= '1';
            clr <= true; wait for 1 ns; clr <= false;
            step; step;
            wait until falling_edge(clk); rst_n <= '1';
            phase;
         end procedure;

         procedure gen_start is
         begin
            wait until falling_edge(clk); m_sda <= '1'; m_scl <= '1'; phase;
            wait until falling_edge(clk); m_sda <= '0'; phase;
            wait until falling_edge(clk); m_scl <= '0'; phase;
         end procedure;

         procedure gen_restart is
         begin
            wait until falling_edge(clk); m_scl <= '0'; m_sda <= '1'; phase;
            wait until falling_edge(clk); m_scl <= '1'; phase;
            wait until falling_edge(clk); m_sda <= '0'; phase;
            wait until falling_edge(clk); m_scl <= '0'; phase;
         end procedure;

         procedure gen_stop is
         begin
            wait until falling_edge(clk); m_scl <= '0'; m_sda <= '0'; phase;
            wait until falling_edge(clk); m_scl <= '1'; phase;
            wait until falling_edge(clk); m_sda <= '1'; phase;
         end procedure;

         procedure gen_bit (b : std_logic) is
         begin
            wait until falling_edge(clk); m_scl <= '0'; phase;
            wait until falling_edge(clk); m_sda <= b;   phase;
            wait until falling_edge(clk); m_scl <= '1'; phase;
            wait until falling_edge(clk); m_scl <= '0'; phase;
         end procedure;

         -- Eight bits, MSB first -- the order §3.1.3 requires.
         procedure gen_byte (d : std_logic_vector(7 downto 0)) is
         begin
            for i in 7 downto 0 loop gen_bit(d(i)); end loop;
         end procedure;

         -- The ninth slot, with SDA released so the bench does not fight a slave ACK.
         procedure gen_ack_slot is
         begin
            wait until falling_edge(clk); m_scl <= '0'; phase;
            wait until falling_edge(clk); m_sda <= '1'; phase;
            wait until falling_edge(clk); m_scl <= '1'; phase;
            wait until falling_edge(clk); m_scl <= '0'; phase;
         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_addr: receive eight bits, compare, latch the direction ==="
                severity note;

         -- T1. Reset is unselected.
         do_reset;
         report "T1  a reset slave is unselected and has no direction" severity note;
         ck_bit("T1 not selected", selected, '0');
         ck_bit("T1 no direction latched", dir_read, '0');
         ck_bit("T1 not acquiring", acquiring, '0');

         -- T2. A START arms the address phase; clocking without one does nothing.
         do_reset;
         gen_bit('0'); gen_bit('1');
         ck_bit("T2 clocking without a START does not arm acquisition", acquiring, '0');
         ck_int("T2 and no address completed", n_done_obs, 0);
         gen_start;
         ck_bit("T2 a START arms it", acquiring, '1');

         -- T3. Our address, write direction.
         do_reset;
         gen_start;
         gen_byte(MY_ADDR & '0');
         report "T3  our address with the write bit selects us, direction write" severity note;
         ck_int("T3 one address byte completed", n_done_obs, 1);
         ck_int("T3 and it matched", n_match_obs, 1);
         ck_bit("T3 we are selected", selected, '1');
         ck_bit("T3 direction is write", dir_read, '0');
         ck_int("T3 the received byte is exactly what was sent",
                to_integer(unsigned(addr_byte)), to_integer(unsigned(MY_ADDR & '0')));
         ck_int("T3 the match counter moved", to_integer(n_match), 1);
         ck_int("T3 the pulses were one cycle", wide, 0);

         -- T4. Our address, read direction.
         do_reset;
         gen_start;
         gen_byte(MY_ADDR & '1');
         report "T4  the same address with the read bit latches direction read" severity note;
         ck_bit("T4 selected", selected, '1');
         ck_bit("T4 direction is read", dir_read, '1');

         -- T5. Somebody else's address.
         do_reset;
         gen_start;
         gen_byte(OTHER & '0');
         report "T5  another device's address leaves us unselected and silent" severity note;
         ck_int("T5 the byte still completed", n_done_obs, 1);
         ck_int("T5 but it did not match", n_match_obs, 0);
         ck_bit("T5 we are not selected", selected, '0');
         ck_int("T5 the miss counter moved", to_integer(n_miss), 1);

         -- T6. Data after a mismatch changes nothing.
         gen_ack_slot;
         gen_byte(x"A5");
         ck_bit("T6 still not selected after the data byte", selected, '0');
         ck_int("T6 and no further address was decoded", n_done_obs, 1);

         -- T7. MSB first, proved with an asymmetric address.
         do_reset;
         gen_start;
         gen_byte(MY_ADDR & '0');
         report "T7  MSB first, proved with an asymmetric address" severity note;
         ck_int("T7 the byte arrived in the right order",
                to_integer(unsigned(addr_byte)), to_integer(unsigned(MY_ADDR & '0')));
         ck_bit("T7 so it matched", selected, '1');

         -- T8. A repeated START re-arms and drops selection.
         do_reset;
         gen_start;
         gen_byte(MY_ADDR & '0');
         ck_bit("T8 selected after the first address", selected, '1');
         gen_ack_slot;
         gen_restart;
         report "T8  a repeated START drops selection and re-arms acquisition" severity note;
         ck_bit("T8 selection dropped at the repeated START", selected, '0');
         ck_bit("T8 and acquisition is armed again", acquiring, '1');
         gen_byte(OTHER & '0');
         ck_bit("T8 the new address belongs to somebody else, so we stay unselected",
                selected, '0');

         -- T9. ... and the other way round.
         do_reset;
         gen_start;
         gen_byte(MY_ADDR & '0');
         gen_ack_slot;
         gen_restart;
         gen_byte(MY_ADDR & '1');
         report "T9  a repeated START to our address re-selects us with a new direction"
                severity note;
         ck_bit("T9 selected again", selected, '1');
         ck_bit("T9 and the direction is now read", dir_read, '1');

         -- T10. A STOP clears selection.
         do_reset;
         gen_start;
         gen_byte(MY_ADDR & '1');
         ck_bit("T10 selected", selected, '1');
         gen_stop;
         report "T10 a STOP clears selection; it must not survive into the next transfer"
                severity note;
         ck_bit("T10 not selected after the STOP", selected, '0');
         ck_bit("T10 and no direction is latched", dir_read, '0');

         -- T11. The bit index is exactly eight wide.
         do_reset;
         gen_start;
         for k in 7 downto 1 loop gen_bit(MY_ADDR(k-1)); end loop;
         ck_bit("T11 still acquiring after seven bits", acquiring, '1');
         ck_int("T11 the index reached seven", to_integer(bit_index), 7);
         gen_bit('0');
         ck_bit("T11 acquisition ended after exactly eight", acquiring, '0');
         ck_int("T11 and the byte completed once", n_done_obs, 1);

         -- T12. Many transfers, nothing accumulates.
         do_reset;
         gen_start; gen_byte(MY_ADDR & '0'); gen_ack_slot; gen_stop;
         gen_start; gen_byte(OTHER   & '0'); gen_ack_slot; gen_stop;
         gen_start; gen_byte(MY_ADDR & '1'); gen_ack_slot; gen_stop;
         report "T12 three addressings, two ours, counted exactly" severity note;
         ck_int("T12 three address bytes decoded", n_done_obs, 3);
         ck_int("T12 two of them matched", n_match_obs, 2);
         ck_int("T12 the miss counter saw one", to_integer(n_miss), 1);
         ck_bit("T12 and we end unselected", selected, '0');

         -- T13. All seven address bits participate. T5 rejected one other address, which
         --      is a weaker result than it looks: 0x51 differs from 0x50 in bit 0 alone,
         --      so a comparator that had dropped any HIGHER bit would still reject it and
         --      still pass T5. A near-miss differing in SEVERAL bits hides a dropped bit
         --      for the same reason -- the bits still being compared reject it anyway.
         --
         --      The property worth asserting is therefore per-bit: flip each address bit
         --      in turn, one at a time, and the match must be lost every time. Seven
         --      vectors, each exactly one bit from ours, is the only shape of stimulus an
         --      ignored address bit cannot hide from. On a real bus a dropped address bit
         --      means two devices acknowledge the same byte.
         do_reset;
         for bitpos in 0 to 6 loop
            cand := MY_ADDR;
            cand(bitpos) := not MY_ADDR(bitpos);
            gen_start;
            gen_byte(cand & '0');
            ck_bit("T13 a one-bit near-miss leaves us unselected", selected, '0');
            ck_int("T13 and never matches", n_match_obs, 0);
            gen_ack_slot; gen_stop;
         end loop;
         report "T13 seven one-bit near-misses, every address bit discriminated"
                severity note;
         ck_int("T13 all seven were decoded", n_done_obs, 7);
         ck_int("T13 and the DUT counted seven misses", to_integer(n_miss), 7);

         -- The control. Without it T13 would pass just as well on a DUT that had stopped
         -- matching ANYTHING -- the failure a negative-only test cannot see.
         gen_start;
         gen_byte(MY_ADDR & '0');
         ck_bit("T13 the exact address still selects us", selected, '1');
         ck_int("T13 and exactly one byte matched", n_match_obs, 1);

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

   end architecture sim;

7b. Execution

DesignSystemVerilogVerilog-2001VHDLFinish
i2c_slave_addrPASS 12/12PASS 12/12PASS 12/1249560 ns, all three

8. Mutation Testing

Twelve defects, spread across the three jobs so that a survivor would point at which job is unverified.

#Injected defectJobResult
M1LSB first — shift the wrong wayreceiveKILLED (15)
M2the comparison is disabled: every address matchesdecideKILLED (8)
M3the comparison is misaligned by one bit, so R/W is compared as addressdecideKILLED (13)
M4the direction bit taken from the wrong enddecideKILLED (2)
M5the direction inverteddecideKILLED (4)
M6seven bits instead of eightreceiveKILLED (17)
M7nine bits — the acknowledge slot consumed as addressreceiveKILLED (20)
M8a STOP does not clear selectionpolicyKILLED (4)
M9a START does not drop selectionpolicyKILLED (2)
M10acquisition is self-starting — shifts without a STARTreceiveKILLED (2)
M11bits sampled on the falling edgereceiveKILLED (19)
M12reset comes up selectedpolicyKILLED (2)
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
baseline: PASS   (verified before injecting anything)
valid mutants: 12   killed: 12   survived: 0   equivalent: 0   invalid: 0
restored: PASS

The spread is the useful part

M3 is the one worth dwelling on. Comparing shreg_next[6:0] instead of [7:1] is a one-character change that shifts the comparison window by a bit — so the target compares six address bits plus the R/W̄ bit against its address. It matches on a different address depending on direction, which on a real board presents as a device that responds to reads and not writes, or to one neighbouring address. Thirteen failing checks, because T3, T4, T5 and T9 all disagree with it in different ways.

M9 and M12 each fail exactly two checks, and both are policy defects rather than datapath ones. Two failing checks means one test is protecting each — T8 for the repeated-START drop, T1 for the reset value — which is worth knowing before anyone trims the suite.

M4 also fails only two. The direction bit is read in exactly one place, so only the two direction tests see it. Given that direction governs every later chapter, that thinness is itself an argument for 18.11's integration tests.

9. Verification Connection — Address Coverage and the Predictor's First Job

Azvya Education Pvt. Ltd.VLSI Mentor
addr_coverage.sv — the bins that matter, and the one that must be illegal
   // The address phase is where a target environment first needs a PREDICTOR rather than
   // just a monitor, because "should this device have answered?" is a question about the
   // device's configuration, not about the bus.
   //
   //   monitor    : an address byte 0xA0 was seen, and it was acknowledged
   //   predictor  : MY_ADDR is 0x50 and 0xA0>>1 is 0x50, so it SHOULD have been
   //   scoreboard : agreement
   //
   // Note the predictor needs the DUT's parameter. That is legitimate -- it is
   // configuration, not internal state -- and it is different in kind from reading the
   // DUT's `selected` output, which would be reading its mind.
   //
   // COVERAGE, and the reason each bin exists:
   //
   //   cover: our address, WRITE direction        the ordinary case
   //   cover: our address, READ direction         the other ordinary case
   //   cover: a NEIGHBOURING address (±1)         catches M3's misaligned window
   //   cover: an address differing only in bit 6  catches a comparator wired short
   //   cover: a repeated START to our address     the combined transfer
   //   cover: a repeated START to ANOTHER address the displacement case of §6
   //
   //   illegal_bin: selected while the last address byte did not match
   //
   // THE NEIGHBOURING-ADDRESS BIN IS THE ONE PEOPLE OMIT. A suite that tests "our
   // address" and "a completely different address" cannot distinguish a correct
   // comparator from one whose window is off by a bit -- because 0x51 differs from 0x50
   // in the bit that a misaligned window happens to ignore. The bin has to be chosen
   // adversarially against the comparator, not chosen for coverage of the address space.
   //
   // AND THE ILLEGAL BIN IS NOT DECORATION. It is the property that an unselected target
   // stays unselected, which is what §4 exists for and what mutations M9 and M12 break.

10. FPGA and ASIC Implications

On an FPGA the comparator is seven XNORs and an AND — nothing. The interesting question is where MY_ADDR comes from. As a parameter it becomes constants and the comparator collapses to a handful of LUTs; as a register it stays a real comparator and the address becomes writable, which is Chapter 18.9's topic. Either way the address must be stable before the first START the device sees, because a device whose address changes mid-transfer can acknowledge the first half of a transaction and not the second.

selected fans out to every later block, so it has the same broad-load, slow-signal character as 18.3's bus_active. Neither is a timing risk at any I²C rate.

On an ASIC, address configuration is usually pins — strap resistors read at reset, which is how several devices of the same type share a bus. That has a consequence this chapter's architecture already accommodates: the straps are sampled once, into the register that feeds the comparator, rather than being read continuously. A comparator wired straight to pads would make a floating strap an intermittently-addressed device.

The reserved-address policy belongs elsewhere. Module 15 owns which addresses a device may not claim, and a production target would refuse to match them; this educational block compares against one parameter and says so.

11. Debugging — The Device That Answered to Two Addresses

Symptom

A board carries two identical sensors, strapped to 0x50 and 0x51. Reads from 0x50 return correct data. Reads from 0x51 also return data -- from the sensor at 0x50. Writes to 0x51 are NACKed. Both parts are the same silicon revision and both straps measure correctly at the pins.

Root Cause

The address comparison window was off by one bit -- shreg[6:0] instead of shreg[7:1] -- so the device compared six of its seven address bits plus the direction bit. The result is a comparator that matches a direction-dependent address: it answered reads at one address and writes at none, and a second device strapped to the neighbouring address matched nothing at all. Nothing was wrong with the shift register, the sampling edge, the acknowledge generator or the straps. The bug is a single index and it is invisible in any test whose addresses differ in the bits the shifted window still happens to compare.

Fix
Compare shreg_next[7:1] against the device address and take the direction from shreg_next[0], which is mutation M3 in reverse. Then fix the coverage, because that is what let it through: a suite that tests only our address and one clearly different address cannot see a window shifted by a bit. Add a NEIGHBOURING address -- differing in the least significant address bit -- and an address differing only in the most significant, both chosen adversarially against the comparator rather than for spread across the address space. Test T5 with 0x51 against MY_ADDR 0x50 is exactly that neighbour, and it is why M3 now fails thirteen checks rather than none.

Three generalisations.

Direction-dependent addressing is the fingerprint of a misaligned window. A device that answers reads and not writes at the same address has a comparator that includes the R/W̄ bit. Nothing else produces that symptom, and recognising it goes straight to the index.

The second device failing silently was a consequence, not a second bug. Its own shifted window matched nothing the master sent, so it looked dead. Two symptoms, one defect, and the loud one pointed away from the cause.

Coverage chosen for spread misses comparator bugs. "Our address and a very different one" feels thorough and is the weakest possible pair, because a shifted window still compares the bits those two differ in. The useful neighbour differs by one bit.

12. Common Misconceptions

"Address matching is an equality operator." It is a windowed equality plus a direction extraction plus a policy — three things that fail separately. §1.

"The direction can be read when it is needed." By then the address byte is gone. It must be latched during the address phase. §2.

"Bits can be sampled whenever the target's clock is convenient." Only at the SCL rising edge, because §3.1.2 makes SDA stable only while SCL is high. §3.

"An unselected target can just ignore what follows." It must actively not acknowledge, not drive, and not interpret. selected gating every later block is what implements that. §4.

"Only a STOP ends selection." A START of either kind does too: after a repeated START the master may name a different device. §5.

"A repeated START to our own address is the same as staying selected." It re-selects with a possibly different direction, which is the whole mechanism behind a register read. §5, T9.

"Reset value doesn't matter, the first START will set it." A target that resets selected can acknowledge a byte in a transfer that was already in progress when it came out of reset. §4.

"If the address decodes, the comparator is right." A window shifted by one bit still decodes some addresses correctly — direction-dependently. §11.

"Coverage should spread across the address space." It should be chosen adversarially against the comparator. The decisive case is a neighbouring address, differing by one bit. §9, §11.

13. Reason It Through

Why separate receiving, comparing and answering when one state machine could do all three?

Because they fail separately and produce different symptoms — wrong bit order, wrong alignment, wrong slot — and a single ADDR state cannot attribute a failure to any of them. §1.

Why must the direction be latched rather than decoded later?

Because everything after the address phase depends on it and the address byte is no longer on the wire. There would be nothing left to decode. §2.

A device answers reads at 0x51 but NACKs writes there, and it is physically strapped to 0x50. What is wrong?

Its comparison window is shifted one bit toward the LSB, so it compares six address bits plus the direction bit — making the match direction-dependent. §11.

Why does a repeated START have to drop selection even when it names the same device?

Because the block cannot know it names the same device until the new address byte completes. Selection is a claim renewed on evidence, and the previous evidence is invalidated by the framing event. §5.

Why is 0x51 a better test address against 0x50 than something far away?

Because it differs in the least significant address bit — the bit a shifted comparison window is most likely to mishandle. A distant address differs in bits that a misaligned window still compares correctly. §9, §11.

Mutations M4, M9 and M12 each failed only two checks. What does that tell you?

That exactly one test protects each — the direction reads, the repeated-START drop, the reset value. Low failure counts mark single points of failure in the suite. §8.

Why is it legitimate for a predictor to know MY_ADDR but not to read selected?

Because the address is configuration, which the environment sets, while selected is the DUT's internal conclusion. Reading the latter would let a DUT that agrees with itself pass. §9.

14. Understanding Check

15. Summary

Three jobs, not one: receive eight bits, decide whether they match, decide whether to answer. They fail separately and a single ADDR state cannot attribute a failure to any of them.

MSB first, so the eighth bit is R/W̄ — and the direction is latched, because everything afterwards depends on it and the address byte will be gone.

Bits are sampled at the SCL rising edge, the only instant §3.1.2 guarantees SDA is valid. This block has no timing of its own, exactly as 17.6 had none — the same structure reached from the opposite side.

An unselected target goes quiet, and selected resets low because that is the only state which cannot disturb a bus mid-transfer.

A START of either kind drops selection, and so does a STOP. Selection is a claim renewed on evidence, and any framing event invalidates the previous evidence.

Twelve mutants, twelve killed, no survivors — the first block in this module with a clean first pass, which is what the three-way separation buys.

A comparison window off by one bit produces direction-dependent addressing: the device answers reads at a neighbouring address and writes at none, and a second device strapped there matches nothing.

And coverage chosen for spread cannot find it. "Our address and a very different one" is the weakest possible pair; the decisive case differs by a single bit.

16. What Comes Next

The target knows it is being addressed, and in which direction. Chapter 18.5 makes it answer — and that is where most slave designs first fail, because the acknowledge has three parts and getting the first one right while missing either of the others produces something that looks like data corruption.

The window is bounded at both ends by falling edges, and asserting early is not merely early: SDA falling while SCL is high is a START, so a premature acknowledge does not acknowledge a byte — it restarts the transaction.

Continue learning