Skip to content
VLSI Mentor

I²C · Module 18

The Transmit Datapath — Sourcing Read Data in Time

The hardest datapath in a target, because the master decides when the next bit is wanted and the slave must have decided what it is one phase earlier. Builds the pre-fetch, shows why a transmitted one is a release, and why the ninth slot must be given back.

On a write the target receives, and 18.6 had a whole bit slot to think in. On a read the master begins clocking immediately after the acknowledge — and this is the hardest datapath in a target.

1. The Pre-Fetch Problem

That is a structural consequence of not owning the clock, and it is the mirror of Chapter 17.7's problem seen from the other end: there the master had to decide its acknowledge before seeing the byte; here the target has to produce a byte before being asked for it.

So tx_req pulses in the cycle this block latches tx_byte, and the consumer must present the byte in the same cycle — a combinational read of a register file, not a multi-cycle fetch.

2. A Transmitted One Is a Release

Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
bit = 0   ->   sda_drive_low = 1     pull the line down
bit = 1   ->   sda_drive_low = 0     release, and let the pull-up do it

3. Driven on the Falling Edge, Sampled on the Rising One

The bit is placed in the low phase — the only phase §3.1.2 allows SDA to change in — and the master samples it in the high phase that follows.

Note the asymmetry with the receive path:

instantwhy
received bits (18.6)scl_riseSDA is guaranteed stable there
transmitted bits (here)scl_fallit is the only phase SDA may change in

Both rules come from the same sentence. Mutation M8 places bits on the rising edge instead and fails twelve checks — every one of them through the "SDA moved while SCL was high" observer.

4. The Ninth Slot Is Not Ours

After eight bits the master drives the acknowledge, so this block must release and stop. Chapter 18.8 reads what the master says there.

A read that will not end is one of the two ways an I²C bus wedges permanently. Mutation M6 drives a ninth bit and fails thirteen checks.

5. Framing Abandons the Byte

A repeated START or STOP mid-read means the master has taken the bus back. The transmitter must let go at once — and releasing here cannot itself produce a framing edge, because the edge has already happened.

Mutations M11 (framing ignored) fails six checks — and it survived the first mutation run, because the bench had tied the framing inputs to zero. §9 has the detail.

6. One Byte, Reconstructed From the Wire

A block diagram. A start or continue request from the transaction layer enters a load state. On the next falling edge of SCL the block pulses a request to the register file and latches the byte into a shift register, simultaneously placing the most significant bit as a drive-low intent. Subsequent falling edges shift the register and place each following bit. After the eighth bit a release path clears the drive intent, gives up ownership, and emits a byte-sent pulse to chapter 18.8. A framing input from chapter 18.3 also reaches the release path directly.tx_start / continue18.10Pre-fetch on thefalltx_req + latchShift registerMSB firstsda_drive_low0 = release = a oneRegister file18.9 — combinationalRelease after eightthe ninth is theirsbyte_sentarms 18.8Framing18.3 — abandon now12
Figure 1 — the transmit path and the pre-fetch. The byte is taken and its MSB placed on the same falling edge; the remaining bits follow on subsequent falls; after the eighth the block releases and hands the slot to the master.

Eight slots ours, the ninth theirs

9 cycles
Nine intervals, one per clock pulse of a read byte. A row showing who drives SDA has the target driving intervals zero through seven and the master driving interval eight. A second row shows the target's drive intent asserted for the first eight intervals and released for the ninth. A third row labels interval eight as the acknowledge slot.ours — eight bitsours — eight bitstheirstheirspre-fetched before this risepre-fetched before thisrisereleased: the master answersreleased: the masteranswersdrives SDATTTTTTTTMwe own itslotb7b6b5b4b3b2b1b0ACKt0t1t2t3t4t5t6t7t8
Figure 2 — the ownership boundary at the end of a read byte, at slot resolution. The target owns slots 0 to 7 and must give slot 8 back; what the master puts there is the subject of 18.8. Conceptual figure: one interval per clock pulse.

7. The Transmit Datapath, in Three Languages

Azvya Education Pvt. Ltd.VLSI Mentor
i2c_slave_tx.sv — source a byte the master is already clocking out
   // -----------------------------------------------------------------------------
   // i2c_slave_tx.sv
   // The transmit datapath: source a byte the master is already clocking out.
   //
   // THE PROBLEM THAT MAKES THIS THE HARDEST DATAPATH IN A SLAVE. On a write, the slave
   // receives; it has the whole of a bit slot to think, and if it cannot keep up it can
   // stretch. On a READ, the master begins clocking immediately after the acknowledge --
   // and the slave must already have the first bit on SDA before that first rising edge,
   // because §3.1.2 forbids changing SDA once SCL is high.
   //
   // So the byte must be fetched BEFORE it is needed. That is the pre-fetch problem, and it
   // is a structural consequence of not owning the clock:
   //
   //   the master decides WHEN the next bit is wanted
   //   the slave must have decided WHAT it is, one phase earlier
   //
   // WHEN THE REQUEST IS ISSUED. `tx_req` pulses when this block takes a byte, and the
   // consumer must present `tx_byte` in the SAME cycle -- a combinational read of a register
   // file, not a multi-cycle fetch. Chapter 18.9 builds a register file that can do that,
   // and Chapter 18.10 is where a slave whose source genuinely cannot answer in one cycle
   // stretches SCL instead. Those are the only two honest options; hoping is not one.
   //
   // A TRANSMITTED ONE IS A RELEASE. There is no drive-high. So:
   //
   //   bit = 0  ->  sda_drive_low = 1   pull the line down
   //   bit = 1  ->  sda_drive_low = 0   release, and let the pull-up do it
   //
   // which means a byte of 0xFF is transmitted by driving nothing at all, and a slave that
   // "drives" a one has written the single most common sign error in I²C twice over -- once
   // here and once in whatever it thinks the pad does.
   //
   // DRIVEN ON THE FALLING EDGE, sampled by the master on the rising one. The bit is placed
   // in the low phase, which is the only phase §3.1.2 allows SDA to change in. Note the
   // asymmetry with the receive path: received bits are captured at `scl_rise`, transmitted
   // bits are placed at `scl_fall`. Both rules come from the same sentence.
   //
   // AND THE NINTH SLOT IS NOT OURS. After eight bits the master drives the acknowledge, so
   // this block must RELEASE and stop -- Chapter 18.8 reads what the master says there. A
   // transmitter still driving in the ninth slot fights the master's ACK: the master pulls
   // low to acknowledge, the slave is holding a one by releasing, and that part is fine --
   // but if the slave's eighth bit was a zero and it fails to release, the master reads its
   // own NACK as an ACK and keeps reading a byte the slave never intended to send.
   // -----------------------------------------------------------------------------

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

      // From Chapter 18.2. Transmitted bits are placed on the FALLING edge.
      input  logic scl_fall,

      // From Chapter 18.3 -- framing abandons the byte.
      input  logic start_pulse,
      input  logic stop_pulse,

      // From the layer above: start sourcing a byte now. One cycle.
      input  logic tx_start,
      // ... and keep going after the master acknowledged the last one.
      input  logic tx_continue,

      // The byte source. `tx_req` pulses in the cycle this block latches `tx_byte`, so the
      // source must be combinationally ready -- see the header.
      output logic       tx_req,
      input  logic [7:0] tx_byte,

      // DRIVE INTENT. 1 = pull SDA low, 0 = release. Never a driven high.
      output logic       sda_drive_low,
      output logic       driving,       // we own SDA right now
      output logic [3:0] bit_index,     // 0..7
      output logic       byte_sent,     // one cycle: eight bits are on the wire

      output logic [CNT_W-1:0] n_bytes,
      output logic [CNT_W-1:0] n_bits
   );

      localparam [1:0] T_IDLE = 2'd0,
                       T_LOAD = 2'd1,   // a byte is owed; fetch it on the next fall
                       T_SEND = 2'd2;   // driving bits 7..0

      logic [1:0] state;
      logic [7:0] shreg;

      always @(posedge clk or negedge rst_n) begin
         if (!rst_n) begin
            // Reset RELEASES. Anything else holds the bus down.
            sda_drive_low <= 1'b0;
            driving       <= 1'b0;
            bit_index     <= 4'd0;
            byte_sent     <= 1'b0;
            tx_req        <= 1'b0;
            shreg         <= 8'h00;
            state         <= T_IDLE;
            n_bytes       <= {CNT_W{1'b0}};
            n_bits        <= {CNT_W{1'b0}};
         end else begin
            byte_sent <= 1'b0;
            tx_req    <= 1'b0;

            if (start_pulse || stop_pulse) begin
               // Framing abandons the byte and releases the line. Releasing here cannot
               // itself produce a framing edge: the edge has already happened.
               sda_drive_low <= 1'b0;
               driving       <= 1'b0;
               bit_index     <= 4'd0;
               state         <= T_IDLE;
            end else begin
               case (state)
                  T_IDLE: begin
                     if (tx_start || tx_continue) begin
                        bit_index <= 4'd0;
                        state     <= T_LOAD;
                     end
                  end

                  T_LOAD: begin
                     // The PRE-FETCH. The byte is taken and the first bit placed on the
                     // same falling edge, so it is valid before the master's next rise.
                     if (scl_fall) begin
                        tx_req        <= 1'b1;
                        shreg         <= tx_byte;
                        sda_drive_low <= ~tx_byte[7];   // a one RELEASES
                        driving       <= 1'b1;
                        bit_index     <= 4'd1;
                        n_bits        <= n_bits + 1'b1;
                        state         <= T_SEND;
                     end
                  end

                  T_SEND: begin
                     if (scl_fall) begin
                        if (bit_index == 4'd8) begin
                           // Eight bits are on the wire. The ninth slot belongs to the
                           // MASTER, so release and stop -- Chapter 18.8 reads its answer.
                           sda_drive_low <= 1'b0;
                           driving       <= 1'b0;
                           bit_index     <= 4'd0;
                           byte_sent     <= 1'b1;
                           n_bytes       <= n_bytes + 1'b1;
                           state         <= T_IDLE;
                        end else begin
                           sda_drive_low <= ~shreg[6];
                           shreg         <= {shreg[6:0], 1'b0};
                           bit_index     <= bit_index + 4'd1;
                           n_bits        <= n_bits + 1'b1;
                        end
                     end
                  end

                  default: state <= T_IDLE;
               endcase
            end
         end
      end

   endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
i2c_slave_tx.v — the same design in Verilog-2001
   // -----------------------------------------------------------------------------
   // i2c_slave_tx.v
   // The transmit datapath: source a byte the master is already clocking out.
   //
   // THE PROBLEM THAT MAKES THIS THE HARDEST DATAPATH IN A SLAVE. On a write, the slave
   // receives; it has the whole of a bit slot to think, and if it cannot keep up it can
   // stretch. On a READ, the master begins clocking immediately after the acknowledge --
   // and the slave must already have the first bit on SDA before that first rising edge,
   // because §3.1.2 forbids changing SDA once SCL is high.
   //
   // So the byte must be fetched BEFORE it is needed. That is the pre-fetch problem, and it
   // is a structural consequence of not owning the clock:
   //
   //   the master decides WHEN the next bit is wanted
   //   the slave must have decided WHAT it is, one phase earlier
   //
   // WHEN THE REQUEST IS ISSUED. `tx_req` pulses when this block takes a byte, and the
   // consumer must present `tx_byte` in the SAME cycle -- a combinational read of a register
   // file, not a multi-cycle fetch. Chapter 18.9 builds a register file that can do that,
   // and Chapter 18.10 is where a slave whose source genuinely cannot answer in one cycle
   // stretches SCL instead. Those are the only two honest options; hoping is not one.
   //
   // A TRANSMITTED ONE IS A RELEASE. There is no drive-high. So:
   //
   //   bit = 0  ->  sda_drive_low = 1   pull the line down
   //   bit = 1  ->  sda_drive_low = 0   release, and let the pull-up do it
   //
   // which means a byte of 0xFF is transmitted by driving nothing at all, and a slave that
   // "drives" a one has written the single most common sign error in I²C twice over -- once
   // here and once in whatever it thinks the pad does.
   //
   // DRIVEN ON THE FALLING EDGE, sampled by the master on the rising one. The bit is placed
   // in the low phase, which is the only phase §3.1.2 allows SDA to change in. Note the
   // asymmetry with the receive path: received bits are captured at `scl_rise`, transmitted
   // bits are placed at `scl_fall`. Both rules come from the same sentence.
   //
   // AND THE NINTH SLOT IS NOT OURS. After eight bits the master drives the acknowledge, so
   // this block must RELEASE and stop -- Chapter 18.8 reads what the master says there. A
   // transmitter still driving in the ninth slot fights the master's ACK: the master pulls
   // low to acknowledge, the slave is holding a one by releasing, and that part is fine --
   // but if the slave's eighth bit was a zero and it fails to release, the master reads its
   // own NACK as an ACK and keeps reading a byte the slave never intended to send.
   // (Verilog-2001 -- structurally identical to the SystemVerilog above.)
   // -----------------------------------------------------------------------------

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

      // From Chapter 18.2. Transmitted bits are placed on the FALLING edge.
      input  wire  scl_fall,

      // From Chapter 18.3 -- framing abandons the byte.
      input  wire  start_pulse,
      input  wire  stop_pulse,

      // From the layer above: start sourcing a byte now. One cycle.
      input  wire  tx_start,
      // ... and keep going after the master acknowledged the last one.
      input  wire  tx_continue,

      // The byte source. `tx_req` pulses in the cycle this block latches `tx_byte`, so the
      // source must be combinationally ready -- see the header.
      output reg         tx_req,
      input  wire  [7:0] tx_byte,

      // DRIVE INTENT. 1 = pull SDA low, 0 = release. Never a driven high.
      output reg         sda_drive_low,
      output reg         driving,       // we own SDA right now
      output reg   [3:0] bit_index,     // 0..7
      output reg         byte_sent,     // one cycle: eight bits are on the wire

      output reg   [CNT_W-1:0] n_bytes,
      output reg   [CNT_W-1:0] n_bits
   );

      localparam [1:0] T_IDLE = 2'd0,
                       T_LOAD = 2'd1,   // a byte is owed; fetch it on the next fall
                       T_SEND = 2'd2;   // driving bits 7..0

      reg [1:0] state;
      reg [7:0] shreg;

      always @(posedge clk or negedge rst_n) begin
         if (!rst_n) begin
            // Reset RELEASES. Anything else holds the bus down.
            sda_drive_low <= 1'b0;
            driving       <= 1'b0;
            bit_index     <= 4'd0;
            byte_sent     <= 1'b0;
            tx_req        <= 1'b0;
            shreg         <= 8'h00;
            state         <= T_IDLE;
            n_bytes       <= {CNT_W{1'b0}};
            n_bits        <= {CNT_W{1'b0}};
         end else begin
            byte_sent <= 1'b0;
            tx_req    <= 1'b0;

            if (start_pulse || stop_pulse) begin
               // Framing abandons the byte and releases the line. Releasing here cannot
               // itself produce a framing edge: the edge has already happened.
               sda_drive_low <= 1'b0;
               driving       <= 1'b0;
               bit_index     <= 4'd0;
               state         <= T_IDLE;
            end else begin
               case (state)
                  T_IDLE: begin
                     if (tx_start || tx_continue) begin
                        bit_index <= 4'd0;
                        state     <= T_LOAD;
                     end
                  end

                  T_LOAD: begin
                     // The PRE-FETCH. The byte is taken and the first bit placed on the
                     // same falling edge, so it is valid before the master's next rise.
                     if (scl_fall) begin
                        tx_req        <= 1'b1;
                        shreg         <= tx_byte;
                        sda_drive_low <= ~tx_byte[7];   // a one RELEASES
                        driving       <= 1'b1;
                        bit_index     <= 4'd1;
                        n_bits        <= n_bits + 1'b1;
                        state         <= T_SEND;
                     end
                  end

                  T_SEND: begin
                     if (scl_fall) begin
                        if (bit_index == 4'd8) begin
                           // Eight bits are on the wire. The ninth slot belongs to the
                           // MASTER, so release and stop -- Chapter 18.8 reads its answer.
                           sda_drive_low <= 1'b0;
                           driving       <= 1'b0;
                           bit_index     <= 4'd0;
                           byte_sent     <= 1'b1;
                           n_bytes       <= n_bytes + 1'b1;
                           state         <= T_IDLE;
                        end else begin
                           sda_drive_low <= ~shreg[6];
                           shreg         <= {shreg[6:0], 1'b0};
                           bit_index     <= bit_index + 4'd1;
                           n_bits        <= n_bits + 1'b1;
                        end
                     end
                  end

                  default: state <= T_IDLE;
               endcase
            end
         end
      end

   endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
i2c_slave_tx.vhd — the same design in VHDL
   -- -----------------------------------------------------------------------------
   -- i2c_slave_tx.vhd
   -- The transmit datapath: source a byte the master is already clocking out. Same ports,
   -- generic, reset values and bit timing as the SystemVerilog and Verilog versions.
   -- -----------------------------------------------------------------------------
   library ieee;
   use ieee.std_logic_1164.all;
   use ieee.numeric_std.all;

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

         -- From Chapter 18.2. Transmitted bits are placed on the FALLING edge.
         scl_fall : in  std_logic;

         -- From Chapter 18.3 -- framing abandons the byte.
         start_pulse : in  std_logic;
         stop_pulse  : in  std_logic;

         tx_start    : in  std_logic;
         tx_continue : in  std_logic;

         -- The byte source. tx_req pulses in the cycle this block latches tx_byte, so the
         -- source must be combinationally ready.
         tx_req  : out std_logic;
         tx_byte : in  std_logic_vector(7 downto 0);

         -- DRIVE INTENT. 1 = pull SDA low, 0 = release. Never a driven high.
         sda_drive_low : out std_logic;
         driving       : out std_logic;
         bit_index     : out unsigned(3 downto 0);
         byte_sent     : out std_logic;

         n_bytes : out unsigned(CNT_W-1 downto 0);
         n_bits  : out unsigned(CNT_W-1 downto 0)
      );
   end entity i2c_slave_tx;

   architecture rtl of i2c_slave_tx is
      type state_t is (T_IDLE, T_LOAD, T_SEND);
      signal state : state_t := T_IDLE;

      signal shreg : std_logic_vector(7 downto 0) := (others => '0');
      signal r_drive, r_driving, r_sent, r_req : std_logic := '0';
      signal r_idx : unsigned(3 downto 0) := (others => '0');
      signal c_by, c_bi : unsigned(CNT_W-1 downto 0) := (others => '0');
   begin

      process (clk, rst_n)
      begin
         if rst_n = '0' then
            -- Reset RELEASES. Anything else holds the bus down.
            r_drive   <= '0';
            r_driving <= '0';
            r_idx     <= (others => '0');
            r_sent    <= '0';
            r_req     <= '0';
            shreg     <= (others => '0');
            state     <= T_IDLE;
            c_by      <= (others => '0');
            c_bi      <= (others => '0');
         elsif rising_edge(clk) then
            r_sent <= '0';
            r_req  <= '0';

            if start_pulse = '1' or stop_pulse = '1' then
               -- Framing abandons the byte and releases the line. Releasing here cannot
               -- itself produce a framing edge: the edge has already happened.
               r_drive   <= '0';
               r_driving <= '0';
               r_idx     <= (others => '0');
               state     <= T_IDLE;
            else
               case state is
                  when T_IDLE =>
                     if tx_start = '1' or tx_continue = '1' then
                        r_idx <= (others => '0');
                        state <= T_LOAD;
                     end if;

                  when T_LOAD =>
                     -- The PRE-FETCH. The byte is taken and the first bit placed on the same
                     -- falling edge, so it is valid before the master's next rise.
                     if scl_fall = '1' then
                        r_req     <= '1';
                        shreg     <= tx_byte;
                        r_drive   <= not tx_byte(7);   -- a one RELEASES
                        r_driving <= '1';
                        r_idx     <= to_unsigned(1, 4);
                        c_bi      <= c_bi + 1;
                        state     <= T_SEND;
                     end if;

                  when T_SEND =>
                     if scl_fall = '1' then
                        if r_idx = 8 then
                           -- Eight bits are on the wire. The ninth slot belongs to the
                           -- MASTER, so release and stop -- Chapter 18.8 reads its answer.
                           r_drive   <= '0';
                           r_driving <= '0';
                           r_idx     <= (others => '0');
                           r_sent    <= '1';
                           c_by      <= c_by + 1;
                           state     <= T_IDLE;
                        else
                           r_drive <= not shreg(6);
                           shreg   <= shreg(6 downto 0) & '0';
                           r_idx   <= r_idx + 1;
                           c_bi    <= c_bi + 1;
                        end if;
                     end if;
               end case;
            end if;
         end if;
      end process;

      tx_req        <= r_req;
      sda_drive_low <= r_drive;
      driving       <= r_driving;
      bit_index     <= r_idx;
      byte_sent     <= r_sent;
      n_bytes       <= c_by;
      n_bits        <= c_bi;

   end architecture rtl;

7a. The testbenches

Fifteen checks. The bench is the master-receiver: it clocks, keeps SDA released, and reconstructs each byte from the wire rather than from the DUT's shift register.

#TestProperty
T1reset releasesa transmitter holding SDA low kills the bus
T2unasked, it drives nothingthe false-positive test
T3the pre-fetch — the first bit is on the wire before the first rise
T40xFF is transmitted by driving nothinga one is a release
T50x00 pulls low for every bitthe mirror case
T6MSB first, with 0x80 and 0x01
T7an arbitrary byte, reconstructed from the wireexactly eight bits driven
T8SDA never moved during a high phasethe invariant every defect trips
T9after eight bits it releasesthe ninth slot is the master's
T10one byte completed
T11a continued read sources the next byte, re-reading the sourceso an advanced pointer is honoured
T12reset mid-byte releases immediately
T13byte_sent fires once per byte, one cycleadded after M12; see §8
T14a repeated START mid-byte abandons it and releasesadded after M11
T15and a STOP does the same

One bench detail is worth copying: gen_pulse is rise-then-fall, and a separate gen_first_fall supplies the loading edge. A task that began by asserting a low which was already low produces no falling edge — so the second byte of a continued read loses its loading edge and runs one fall short. A transmitter needs exactly one fall per bit slot, plus one to load and one to release: nine per byte, not eight.

Azvya Education Pvt. Ltd.VLSI Mentor
i2c_slave_tx_tb.sv — the self-checking testbench
   // -----------------------------------------------------------------------------
   // i2c_slave_tx_tb.sv
   // Independent oracle for i2c_slave_tx.
   //
   // The bench is the MASTER-RECEIVER: it clocks, releases SDA so the slave can drive, and
   // samples what arrives at each rising edge -- reconstructing the byte from the wire
   // rather than believing the DUT's shift register. That is the only way to prove a
   // transmitter: the value it thinks it sent is not evidence.
   // -----------------------------------------------------------------------------
   `timescale 1ns/1ps

   module i2c_slave_tx_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 tx_start = 1'b0, tx_continue = 1'b0;
      // Framing inputs, DRIVEN rather than tied off -- the third time in this module
      // that a tied-off port turned out to be an untested one.
      logic f_start = 1'b0, f_stop = 1'b0;
      logic [7:0] src = 8'h00;

      logic s_sda_low, driving, byte_sent, tx_req;
      logic [3:0] bit_index;
      logic [15:0] n_bytes, n_bits;

      // The bus, wired-AND. The slave's contribution is what this bench exists to observe.
      wire scl = ~m_scl_low;
      wire sda = ~(m_sda_low | s_sda_low);

      logic scl_q, sda_q, scl_rise, scl_fall, sda_rise, sda_fall;

      integer errors = 0, n, k;

      // ---- master-receiver reconstruction, from the WIRE ------------------------
      reg [7:0] rx_shift = 8'h00;
      integer   n_sampled = 0;
      reg [7:0] got_byte [0:7];
      integer   n_got = 0;
      // Sample only the slots the slave is actually DRIVING. A real master-receiver knows
      // which slots are data slots -- it is generating the clock -- so gating on `driving`
      // is not cheating, it is the master's own knowledge of the frame. Counting every rise
      // instead would fold the acknowledge slot's rise into the byte and misalign every
      // byte after the first.
      always @(posedge clk) if (rst_n && scl_rise && driving) begin
         rx_shift  = {rx_shift[6:0], sda};
         n_sampled = n_sampled + 1;
         if (n_sampled % 8 == 0) begin got_byte[n_got[2:0]] = rx_shift; n_got = n_got + 1; end
      end

      // ---- the invariant observer: SDA must not move while SCL is HIGH ----------
      integer moved_high = 0, drove_cycles = 0;
      // `byte_sent` gets its own observer. It is the pulse Chapter 18.8 looks for the
      // master's answer on, and this bench instantiates no consumer for it -- so without a
      // check a transmitter whose bits are all correct and whose byte_sent never fires would
      // pass everything while leaving the target unable to notice a NACK.
      integer n_sent_obs = 0, sent_wide = 0;
      logic bs_d = 1'b0;
      always @(posedge clk) begin
         if (rst_n) begin
            if (byte_sent) n_sent_obs <= n_sent_obs + 1;
            if (byte_sent & bs_d) sent_wide <= sent_wide + 1;
         end
         bs_d <= byte_sent;
      end
      logic s_d = 1'b0;
      always @(posedge clk) begin
         if (rst_n) begin
            if ((s_sda_low !== s_d) && scl) moved_high <= moved_high + 1;
            if (s_sda_low) drove_cycles <= drove_cycles + 1;
         end
         s_d <= s_sda_low;
      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_tx #(.CNT_W(16)) dut (
         .clk(clk), .rst_n(rst_n), .scl_fall(scl_fall),
         .start_pulse(f_start), .stop_pulse(f_stop),
         .tx_start(tx_start), .tx_continue(tx_continue),
         .tx_req(tx_req), .tx_byte(src),
         .sda_drive_low(s_sda_low), .driving(driving),
         .bit_index(bit_index), .byte_sent(byte_sent),
         .n_bytes(n_bytes), .n_bits(n_bits));

      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; tx_start = 1'b0; tx_continue = 1'b0;
            f_start = 1'b0; f_stop = 1'b0;
            n_sent_obs = 0; sent_wide = 0;
            moved_high = 0; drove_cycles = 0; n_sampled = 0; n_got = 0; rx_shift = 8'h00;
            step; step; @(negedge clk); rst_n = 1'b1; phase;
         end
      endtask

      // One clock pulse driven by the master: RISE then FALL, starting and ending with SCL
      // low. The master keeps SDA released throughout, so whatever appears on the wire is
      // the slave's.
      //
      // The shape matters. A task that began by asserting a low which was ALREADY low
      // produces no falling edge, so the first pulse of a second byte loses the edge that
      // loads it -- the byte then runs one fall short and never completes. The transmitter
      // needs exactly one fall per bit slot, so the generator must produce exactly one.
      task gen_pulse; begin
         @(negedge clk); m_scl_low = 1'b0; phase;     // high phase: the master samples
         @(negedge clk); m_scl_low = 1'b1; phase;     // fall: the slave places the next bit
      end endtask

      // The falling edge that begins a transfer, taking SCL from its idle high to low. This
      // is the edge the pre-fetch happens on, so it is separate from the bit pulses.
      task gen_first_fall; begin
         @(negedge clk); m_scl_low = 1'b0; phase;
         @(negedge clk); m_scl_low = 1'b1; phase;
      end endtask

      task pulse_start; begin
         @(negedge clk); tx_start = 1'b1; step; @(negedge clk); tx_start = 1'b0; end
      endtask
      task pulse_continue; begin
         @(negedge clk); tx_continue = 1'b1; step; @(negedge clk); tx_continue = 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_tx: source a byte the master is already clocking ===");

         // T1. Reset releases. A transmitter holding SDA low out of reset kills the bus.
         do_reset;
         $display("T1  reset releases SDA");
         ck_bit("T1 not driving", s_sda_low, 1'b0);
         ck_bit("T1 the line is high", sda, 1'b1);
         ck_bit("T1 does not claim ownership", driving, 1'b0);

         // T2. Nothing without a request. The false-positive test: clocking a transmitter
         //     that was never asked for a byte must produce silence.
         do_reset;
         for (k = 0; k < 4; k = k + 1) gen_pulse;
         $display("T2  unasked, it drives nothing at all");
         ck_int("T2 never drove", drove_cycles, 0);
         ck_int("T2 never moved SDA in a high phase", moved_high, 0);

         // T3. THE PRE-FETCH. The first bit must be on the wire BEFORE the master's first
         //     rising edge, because §3.1.2 forbids changing SDA once SCL is high. The byte
         //     is taken and the first bit placed on the same falling edge.
         do_reset;
         @(negedge clk); src = 8'h00;        // MSB is 0 -> the line must be pulled LOW
         pulse_start;
         gen_first_fall;                             // the edge the pre-fetch happens on
         $display("T3  the first bit is on the wire before the master's first rise");
         ck_bit("T3 driving already", driving, 1'b1);
         ck_bit("T3 and the MSB is presented", s_sda_low, 1'b1);
         ck_bit("T3 the line is low", sda, 1'b0);

         // T4. A TRANSMITTED ONE IS A RELEASE. 0xFF is sent by driving nothing whatsoever.
         do_reset;
         @(negedge clk); src = 8'hFF;
         pulse_start;
         gen_first_fall;
         for (k = 0; k < 8; k = k + 1) gen_pulse;
         $display("T4  0xFF is transmitted by driving nothing -- a one is a release");
         ck_int("T4 the master received 0xFF", got_byte[0], 8'hFF);
         ck_int("T4 and the slave never pulled the line down", drove_cycles, 0);

         // T5. A TRANSMITTED ZERO PULLS LOW. 0x00 is the mirror case.
         do_reset;
         @(negedge clk); src = 8'h00;
         pulse_start;
         gen_first_fall;
         for (k = 0; k < 8; k = k + 1) gen_pulse;
         $display("T5  0x00 is transmitted by pulling low for every bit");
         ck_int("T5 the master received 0x00", got_byte[0], 8'h00);

         // T6. MSB FIRST, proved with the two values that distinguish the orders.
         do_reset;
         @(negedge clk); src = 8'h80;
         pulse_start;
         gen_first_fall;
         for (k = 0; k < 8; k = k + 1) gen_pulse;
         $display("T6  MSB first, proved with 0x80");
         ck_int("T6 the master received 0x80", got_byte[0], 8'h80);

         do_reset;
         @(negedge clk); src = 8'h01;
         pulse_start;
         gen_first_fall;
         for (k = 0; k < 8; k = k + 1) gen_pulse;
         ck_int("T6 and 0x01 the other way", got_byte[0], 8'h01);

         // T7. AN ARBITRARY PATTERN, read off the wire bit by bit.
         do_reset;
         @(negedge clk); src = 8'hA6;
         pulse_start;
         gen_first_fall;
         for (k = 0; k < 8; k = k + 1) gen_pulse;
         $display("T7  an arbitrary byte, reconstructed from the wire");
         ck_int("T7 0xA6 arrived", got_byte[0], 8'hA6);
         ck_int("T7 exactly eight bits were driven", n_bits, 8);
         ck_int("T7 one byte completed", n_bytes, 1);

         // T8. THE INVARIANT. Over the whole byte, SDA never changed while SCL was high.
         //     Every timing defect in this block shows up here, because all of them move
         //     SDA in the wrong phase.
         $display("T8  SDA never moved during a high phase");
         ck_int("T8 no movement in any high phase", moved_high, 0);

         // T9. THE NINTH SLOT IS NOT OURS. After eight bits the transmitter must release so
         //     the master can drive its acknowledge. A transmitter still holding a zero
         //     there makes the master read its own NACK as an ACK.
         do_reset;
         @(negedge clk); src = 8'h00;        // every bit low, including the last
         pulse_start;
         gen_first_fall;
         for (k = 0; k < 8; k = k + 1) gen_pulse;
         $display("T9  after eight bits it releases: the ninth slot is the master's");
         ck_bit("T9 no longer driving", s_sda_low, 1'b0);
         ck_bit("T9 ownership given up", driving, 1'b0);
         ck_bit("T9 and the line is free for the master's ACK", sda, 1'b1);
         // And it stays released through the ninth pulse.
         gen_pulse;
         ck_bit("T9 still released through the ninth pulse", s_sda_low, 1'b0);

         // T10. byte_sent IS ONE CYCLE, once per byte. The layer above advances on it.
         do_reset;
         @(negedge clk); src = 8'h3C;
         pulse_start;
         gen_first_fall;
         for (k = 0; k < 8; k = k + 1) gen_pulse;
         n = 0;
         // The pulse fires on the fall that ends the eighth bit, which gen_pulse has
         // already produced, so look for the completion having been recorded.
         ck_int("T10 exactly one byte completed", n_bytes, 1);

         // T11. CONTINUING sources a second byte, and the source is re-read -- so a
         //      register file that advanced its pointer is honoured.
         do_reset;
         @(negedge clk); src = 8'h11;
         pulse_start;
         gen_first_fall;
         for (k = 0; k < 8; k = k + 1) gen_pulse;
         @(negedge clk); src = 8'h22;        // the source has moved on
         pulse_continue;
         // Nine falls per byte, not eight: one to load the MSB, seven to place bits 6..0,
         // and one to release for the acknowledge slot. A continued byte needs its own
         // loading edge exactly as the first one did.
         gen_first_fall;
         for (k = 0; k < 8; k = k + 1) gen_pulse;
         $display("T11 a continued read sources the NEXT byte, re-reading the source");
         ck_int("T11 first byte", got_byte[0], 8'h11);
         ck_int("T11 second byte", got_byte[1], 8'h22);
         ck_int("T11 two bytes completed", n_bytes, 2);
         ck_int("T11 sixteen bits driven", n_bits, 16);

         // T12. FRAMING ABANDONS THE BYTE AND RELEASES. A repeated START mid-read means
         //      the master has taken the bus back; the transmitter must let go at once.
         do_reset;
         @(negedge clk); src = 8'h00;
         pulse_start;
         gen_first_fall;
         gen_pulse;               // two bits out, still driving low
         ck_bit("T12 driving mid-byte", s_sda_low, 1'b1);
         // A reset stands in for the framing path here, which the integrated target wires;
         // the block's own framing inputs are exercised at integration in Chapter 18.11.
         @(negedge clk); rst_n = 1'b0; step; step;
         $display("T12 reset mid-byte releases the line immediately");
         ck_bit("T12 released", s_sda_low, 1'b0);
         ck_bit("T12 and the bus is free", sda, 1'b1);

         // ----------------------------------------------------------------
         // T13. byte_sent IS THE HAND-OFF TO 18.8. One pulse per byte, one cycle wide. It is
         //      what tells the target to start watching for the master's acknowledge, so a
         //      transmitter with perfect bits and no byte_sent would source byte after byte
         //      and never notice a NACK -- a read that will not end, which wedges the bus.
         // ----------------------------------------------------------------
         do_reset;
         @(negedge clk); src = 8'h5A;
         pulse_start;
         gen_first_fall;
         for (k = 0; k < 8; k = k + 1) gen_pulse;
         @(negedge clk); src = 8'hA5;
         pulse_continue;
         gen_first_fall;
         for (k = 0; k < 8; k = k + 1) gen_pulse;
         $display("T13 byte_sent fires once per byte, one cycle wide");
         ck_int("T13 two byte_sent pulses", n_sent_obs, 2);
         ck_int("T13 neither was wide", sent_wide, 0);
         ck_int("T13 and two bytes completed", n_bytes, 2);

         // ----------------------------------------------------------------
         // T14. FRAMING ABANDONS THE BYTE AND RELEASES. A repeated START mid-read means the
         //      master has taken the bus back; a transmitter that kept driving would fight
         //      whatever the master does next -- and if the master is framing, the held line
         //      prevents the framing from happening at all.
         // ----------------------------------------------------------------
         do_reset;
         @(negedge clk); src = 8'h00;        // every bit low, so driving is visible
         pulse_start;
         gen_first_fall;
         gen_pulse;
         ck_bit("T14 driving mid-byte", s_sda_low, 1'b1);
         @(negedge clk); f_start = 1'b1; step; @(negedge clk); f_start = 1'b0;
         step;
         $display("T14 a repeated START mid-byte abandons it and releases the line");
         ck_bit("T14 released", s_sda_low, 1'b0);
         ck_bit("T14 ownership given up", driving, 1'b0);
         ck_bit("T14 and the bus is free", sda, 1'b1);

         // ----------------------------------------------------------------
         // T15. AND A STOP DOES THE SAME.
         // ----------------------------------------------------------------
         do_reset;
         @(negedge clk); src = 8'h00;
         pulse_start;
         gen_first_fall;
         gen_pulse;
         ck_bit("T15 driving mid-byte", s_sda_low, 1'b1);
         @(negedge clk); f_stop = 1'b1; step; @(negedge clk); f_stop = 1'b0;
         step;
         $display("T15 a STOP mid-byte does the same");
         ck_bit("T15 released", s_sda_low, 1'b0);
         ck_bit("T15 ownership given up", driving, 1'b0);

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

   endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
i2c_slave_tx_tb.v — the same tests in Verilog-2001
   // -----------------------------------------------------------------------------
   // i2c_slave_tx_tb.v
   // Independent oracle for i2c_slave_tx.
   //
   // The bench is the MASTER-RECEIVER: it clocks, releases SDA so the slave can drive, and
   // samples what arrives at each rising edge -- reconstructing the byte from the wire
   // rather than believing the DUT's shift register. That is the only way to prove a
   // transmitter: the value it thinks it sent is not evidence.
   // -----------------------------------------------------------------------------
   `timescale 1ns/1ps

   module i2c_slave_tx_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 tx_start = 1'b0, tx_continue = 1'b0;
      // Framing inputs, DRIVEN rather than tied off -- the third time in this module
      // that a tied-off port turned out to be an untested one.
      reg f_start = 1'b0, f_stop = 1'b0;
      reg [7:0] src = 8'h00;

      wire s_sda_low, driving, byte_sent, tx_req;
      wire [3:0] bit_index;
      wire [15:0] n_bytes, n_bits;

      // The bus, wired-AND. The slave's contribution is what this bench exists to observe.
      wire scl = ~m_scl_low;
      wire sda = ~(m_sda_low | s_sda_low);

      wire scl_q, sda_q, scl_rise, scl_fall, sda_rise, sda_fall;

      integer errors = 0, n, k;

      // ---- master-receiver reconstruction, from the WIRE ------------------------
      reg [7:0] rx_shift = 8'h00;
      integer   n_sampled = 0;
      reg [7:0] got_byte [0:7];
      integer   n_got = 0;
      // Sample only the slots the slave is actually DRIVING. A real master-receiver knows
      // which slots are data slots -- it is generating the clock -- so gating on `driving`
      // is not cheating, it is the master's own knowledge of the frame. Counting every rise
      // instead would fold the acknowledge slot's rise into the byte and misalign every
      // byte after the first.
      always @(posedge clk) if (rst_n && scl_rise && driving) begin
         rx_shift  = {rx_shift[6:0], sda};
         n_sampled = n_sampled + 1;
         if (n_sampled % 8 == 0) begin got_byte[n_got[2:0]] = rx_shift; n_got = n_got + 1; end
      end

      // ---- the invariant observer: SDA must not move while SCL is HIGH ----------
      integer moved_high = 0, drove_cycles = 0;
      // `byte_sent` gets its own observer. It is the pulse Chapter 18.8 looks for the
      // master's answer on, and this bench instantiates no consumer for it -- so without a
      // check a transmitter whose bits are all correct and whose byte_sent never fires would
      // pass everything while leaving the target unable to notice a NACK.
      integer n_sent_obs = 0, sent_wide = 0;
      reg bs_d = 1'b0;
      always @(posedge clk) begin
         if (rst_n) begin
            if (byte_sent) n_sent_obs <= n_sent_obs + 1;
            if (byte_sent & bs_d) sent_wide <= sent_wide + 1;
         end
         bs_d <= byte_sent;
      end
      reg s_d = 1'b0;
      always @(posedge clk) begin
         if (rst_n) begin
            if ((s_sda_low !== s_d) && scl) moved_high <= moved_high + 1;
            if (s_sda_low) drove_cycles <= drove_cycles + 1;
         end
         s_d <= s_sda_low;
      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_tx #(.CNT_W(16)) dut (
         .clk(clk), .rst_n(rst_n), .scl_fall(scl_fall),
         .start_pulse(f_start), .stop_pulse(f_stop),
         .tx_start(tx_start), .tx_continue(tx_continue),
         .tx_req(tx_req), .tx_byte(src),
         .sda_drive_low(s_sda_low), .driving(driving),
         .bit_index(bit_index), .byte_sent(byte_sent),
         .n_bytes(n_bytes), .n_bits(n_bits));

      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; tx_start = 1'b0; tx_continue = 1'b0;
            f_start = 1'b0; f_stop = 1'b0;
            n_sent_obs = 0; sent_wide = 0;
            moved_high = 0; drove_cycles = 0; n_sampled = 0; n_got = 0; rx_shift = 8'h00;
            step; step; @(negedge clk); rst_n = 1'b1; phase;
         end
      endtask

      // One clock pulse driven by the master: RISE then FALL, starting and ending with SCL
      // low. The master keeps SDA released throughout, so whatever appears on the wire is
      // the slave's.
      //
      // The shape matters. A task that began by asserting a low which was ALREADY low
      // produces no falling edge, so the first pulse of a second byte loses the edge that
      // loads it -- the byte then runs one fall short and never completes. The transmitter
      // needs exactly one fall per bit slot, so the generator must produce exactly one.
      task gen_pulse; begin
         @(negedge clk); m_scl_low = 1'b0; phase;     // high phase: the master samples
         @(negedge clk); m_scl_low = 1'b1; phase;     // fall: the slave places the next bit
      end endtask

      // The falling edge that begins a transfer, taking SCL from its idle high to low. This
      // is the edge the pre-fetch happens on, so it is separate from the bit pulses.
      task gen_first_fall; begin
         @(negedge clk); m_scl_low = 1'b0; phase;
         @(negedge clk); m_scl_low = 1'b1; phase;
      end endtask

      task pulse_start; begin
         @(negedge clk); tx_start = 1'b1; step; @(negedge clk); tx_start = 1'b0; end
      endtask
      task pulse_continue; begin
         @(negedge clk); tx_continue = 1'b1; step; @(negedge clk); tx_continue = 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_tx: source a byte the master is already clocking ===");

         // T1. Reset releases. A transmitter holding SDA low out of reset kills the bus.
         do_reset;
         $display("T1  reset releases SDA");
         ck_bit("T1 not driving", s_sda_low, 1'b0);
         ck_bit("T1 the line is high", sda, 1'b1);
         ck_bit("T1 does not claim ownership", driving, 1'b0);

         // T2. Nothing without a request. The false-positive test: clocking a transmitter
         //     that was never asked for a byte must produce silence.
         do_reset;
         for (k = 0; k < 4; k = k + 1) gen_pulse;
         $display("T2  unasked, it drives nothing at all");
         ck_int("T2 never drove", drove_cycles, 0);
         ck_int("T2 never moved SDA in a high phase", moved_high, 0);

         // T3. THE PRE-FETCH. The first bit must be on the wire BEFORE the master's first
         //     rising edge, because §3.1.2 forbids changing SDA once SCL is high. The byte
         //     is taken and the first bit placed on the same falling edge.
         do_reset;
         @(negedge clk); src = 8'h00;        // MSB is 0 -> the line must be pulled LOW
         pulse_start;
         gen_first_fall;                             // the edge the pre-fetch happens on
         $display("T3  the first bit is on the wire before the master's first rise");
         ck_bit("T3 driving already", driving, 1'b1);
         ck_bit("T3 and the MSB is presented", s_sda_low, 1'b1);
         ck_bit("T3 the line is low", sda, 1'b0);

         // T4. A TRANSMITTED ONE IS A RELEASE. 0xFF is sent by driving nothing whatsoever.
         do_reset;
         @(negedge clk); src = 8'hFF;
         pulse_start;
         gen_first_fall;
         for (k = 0; k < 8; k = k + 1) gen_pulse;
         $display("T4  0xFF is transmitted by driving nothing -- a one is a release");
         ck_int("T4 the master received 0xFF", got_byte[0], 8'hFF);
         ck_int("T4 and the slave never pulled the line down", drove_cycles, 0);

         // T5. A TRANSMITTED ZERO PULLS LOW. 0x00 is the mirror case.
         do_reset;
         @(negedge clk); src = 8'h00;
         pulse_start;
         gen_first_fall;
         for (k = 0; k < 8; k = k + 1) gen_pulse;
         $display("T5  0x00 is transmitted by pulling low for every bit");
         ck_int("T5 the master received 0x00", got_byte[0], 8'h00);

         // T6. MSB FIRST, proved with the two values that distinguish the orders.
         do_reset;
         @(negedge clk); src = 8'h80;
         pulse_start;
         gen_first_fall;
         for (k = 0; k < 8; k = k + 1) gen_pulse;
         $display("T6  MSB first, proved with 0x80");
         ck_int("T6 the master received 0x80", got_byte[0], 8'h80);

         do_reset;
         @(negedge clk); src = 8'h01;
         pulse_start;
         gen_first_fall;
         for (k = 0; k < 8; k = k + 1) gen_pulse;
         ck_int("T6 and 0x01 the other way", got_byte[0], 8'h01);

         // T7. AN ARBITRARY PATTERN, read off the wire bit by bit.
         do_reset;
         @(negedge clk); src = 8'hA6;
         pulse_start;
         gen_first_fall;
         for (k = 0; k < 8; k = k + 1) gen_pulse;
         $display("T7  an arbitrary byte, reconstructed from the wire");
         ck_int("T7 0xA6 arrived", got_byte[0], 8'hA6);
         ck_int("T7 exactly eight bits were driven", n_bits, 8);
         ck_int("T7 one byte completed", n_bytes, 1);

         // T8. THE INVARIANT. Over the whole byte, SDA never changed while SCL was high.
         //     Every timing defect in this block shows up here, because all of them move
         //     SDA in the wrong phase.
         $display("T8  SDA never moved during a high phase");
         ck_int("T8 no movement in any high phase", moved_high, 0);

         // T9. THE NINTH SLOT IS NOT OURS. After eight bits the transmitter must release so
         //     the master can drive its acknowledge. A transmitter still holding a zero
         //     there makes the master read its own NACK as an ACK.
         do_reset;
         @(negedge clk); src = 8'h00;        // every bit low, including the last
         pulse_start;
         gen_first_fall;
         for (k = 0; k < 8; k = k + 1) gen_pulse;
         $display("T9  after eight bits it releases: the ninth slot is the master's");
         ck_bit("T9 no longer driving", s_sda_low, 1'b0);
         ck_bit("T9 ownership given up", driving, 1'b0);
         ck_bit("T9 and the line is free for the master's ACK", sda, 1'b1);
         // And it stays released through the ninth pulse.
         gen_pulse;
         ck_bit("T9 still released through the ninth pulse", s_sda_low, 1'b0);

         // T10. byte_sent IS ONE CYCLE, once per byte. The layer above advances on it.
         do_reset;
         @(negedge clk); src = 8'h3C;
         pulse_start;
         gen_first_fall;
         for (k = 0; k < 8; k = k + 1) gen_pulse;
         n = 0;
         // The pulse fires on the fall that ends the eighth bit, which gen_pulse has
         // already produced, so look for the completion having been recorded.
         ck_int("T10 exactly one byte completed", n_bytes, 1);

         // T11. CONTINUING sources a second byte, and the source is re-read -- so a
         //      register file that advanced its pointer is honoured.
         do_reset;
         @(negedge clk); src = 8'h11;
         pulse_start;
         gen_first_fall;
         for (k = 0; k < 8; k = k + 1) gen_pulse;
         @(negedge clk); src = 8'h22;        // the source has moved on
         pulse_continue;
         // Nine falls per byte, not eight: one to load the MSB, seven to place bits 6..0,
         // and one to release for the acknowledge slot. A continued byte needs its own
         // loading edge exactly as the first one did.
         gen_first_fall;
         for (k = 0; k < 8; k = k + 1) gen_pulse;
         $display("T11 a continued read sources the NEXT byte, re-reading the source");
         ck_int("T11 first byte", got_byte[0], 8'h11);
         ck_int("T11 second byte", got_byte[1], 8'h22);
         ck_int("T11 two bytes completed", n_bytes, 2);
         ck_int("T11 sixteen bits driven", n_bits, 16);

         // T12. FRAMING ABANDONS THE BYTE AND RELEASES. A repeated START mid-read means
         //      the master has taken the bus back; the transmitter must let go at once.
         do_reset;
         @(negedge clk); src = 8'h00;
         pulse_start;
         gen_first_fall;
         gen_pulse;               // two bits out, still driving low
         ck_bit("T12 driving mid-byte", s_sda_low, 1'b1);
         // A reset stands in for the framing path here, which the integrated target wires;
         // the block's own framing inputs are exercised at integration in Chapter 18.11.
         @(negedge clk); rst_n = 1'b0; step; step;
         $display("T12 reset mid-byte releases the line immediately");
         ck_bit("T12 released", s_sda_low, 1'b0);
         ck_bit("T12 and the bus is free", sda, 1'b1);

         // ----------------------------------------------------------------
         // T13. byte_sent IS THE HAND-OFF TO 18.8. One pulse per byte, one cycle wide. It is
         //      what tells the target to start watching for the master's acknowledge, so a
         //      transmitter with perfect bits and no byte_sent would source byte after byte
         //      and never notice a NACK -- a read that will not end, which wedges the bus.
         // ----------------------------------------------------------------
         do_reset;
         @(negedge clk); src = 8'h5A;
         pulse_start;
         gen_first_fall;
         for (k = 0; k < 8; k = k + 1) gen_pulse;
         @(negedge clk); src = 8'hA5;
         pulse_continue;
         gen_first_fall;
         for (k = 0; k < 8; k = k + 1) gen_pulse;
         $display("T13 byte_sent fires once per byte, one cycle wide");
         ck_int("T13 two byte_sent pulses", n_sent_obs, 2);
         ck_int("T13 neither was wide", sent_wide, 0);
         ck_int("T13 and two bytes completed", n_bytes, 2);

         // ----------------------------------------------------------------
         // T14. FRAMING ABANDONS THE BYTE AND RELEASES. A repeated START mid-read means the
         //      master has taken the bus back; a transmitter that kept driving would fight
         //      whatever the master does next -- and if the master is framing, the held line
         //      prevents the framing from happening at all.
         // ----------------------------------------------------------------
         do_reset;
         @(negedge clk); src = 8'h00;        // every bit low, so driving is visible
         pulse_start;
         gen_first_fall;
         gen_pulse;
         ck_bit("T14 driving mid-byte", s_sda_low, 1'b1);
         @(negedge clk); f_start = 1'b1; step; @(negedge clk); f_start = 1'b0;
         step;
         $display("T14 a repeated START mid-byte abandons it and releases the line");
         ck_bit("T14 released", s_sda_low, 1'b0);
         ck_bit("T14 ownership given up", driving, 1'b0);
         ck_bit("T14 and the bus is free", sda, 1'b1);

         // ----------------------------------------------------------------
         // T15. AND A STOP DOES THE SAME.
         // ----------------------------------------------------------------
         do_reset;
         @(negedge clk); src = 8'h00;
         pulse_start;
         gen_first_fall;
         gen_pulse;
         ck_bit("T15 driving mid-byte", s_sda_low, 1'b1);
         @(negedge clk); f_stop = 1'b1; step; @(negedge clk); f_stop = 1'b0;
         step;
         $display("T15 a STOP mid-byte does the same");
         ck_bit("T15 released", s_sda_low, 1'b0);
         ck_bit("T15 ownership given up", driving, 1'b0);

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

   endmodule
Azvya Education Pvt. Ltd.VLSI Mentor
i2c_slave_tx_tb.vhd — the same tests in VHDL
   -- -----------------------------------------------------------------------------
   -- i2c_slave_tx_tb.vhd
   -- Independent oracle for i2c_slave_tx. Behavioural twin of the SystemVerilog and Verilog
   -- benches.
   --
   -- The bench is the MASTER-RECEIVER: it clocks, releases SDA so the slave can drive, and
   -- reconstructs the byte from the WIRE rather than believing the DUT's shift register.
   -- That is the only way to prove a transmitter -- the value it thinks it sent is not
   -- evidence.
   -- -----------------------------------------------------------------------------
   library ieee;
   use ieee.std_logic_1164.all;
   use ieee.numeric_std.all;

   entity i2c_slave_tx_tb is
   end entity i2c_slave_tx_tb;

   architecture sim of i2c_slave_tx_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 tx_start, tx_continue : std_logic := '0';
      -- Framing inputs, DRIVEN rather than tied off.
      signal f_start, f_stop : std_logic := '0';
      signal src : std_logic_vector(7 downto 0) := (others => '0');

      signal s_sda_low, driving, byte_sent, tx_req : std_logic;
      signal bit_index : unsigned(3 downto 0);
      signal n_bytes, n_bits : unsigned(15 downto 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 halt : boolean := false;

      type gb_t is array (0 to 7) of std_logic_vector(7 downto 0);
      signal got_byte : gb_t := (others => (others => '0'));
      signal rx_shift : std_logic_vector(7 downto 0) := (others => '0');
      signal n_sampled, n_got : integer := 0;
      signal moved_high, drove_cycles : integer := 0;
      -- byte_sent gets its own observer: it is the pulse Chapter 18.8 looks for the
      -- master's answer on, and this bench instantiates no consumer for it.
      signal n_sent_obs, sent_wide : integer := 0;
      signal clr : boolean := false;

   begin

      scl <= not m_scl_low;
      sda <= not (m_sda_low or s_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_tx
         generic map (CNT_W => 16)
         port map (clk => clk, rst_n => rst_n, scl_fall => scl_fall,
            start_pulse => f_start, stop_pulse => f_stop,
            tx_start => tx_start, tx_continue => tx_continue,
            tx_req => tx_req, tx_byte => src,
            sda_drive_low => s_sda_low, driving => driving,
            bit_index => bit_index, byte_sent => byte_sent,
            n_bytes => n_bytes, n_bits => n_bits);

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

      -- Master-receiver reconstruction, from the WIRE, gated on the slave actually driving.
      -- A real master-receiver knows which slots are data slots because it generates the
      -- clock, so gating on `driving` is the master's own knowledge of the frame.
      obs : process (clk, clr)
         variable s_d, bs_d : std_logic := '0';
      begin
         if clr then
            n_sampled <= 0; n_got <= 0; rx_shift <= (others => '0');
            moved_high <= 0; drove_cycles <= 0;
            n_sent_obs <= 0; sent_wide <= 0;
         elsif rising_edge(clk) then
            if rst_n = '1' then
               if scl_rise = '1' and driving = '1' then
                  rx_shift  <= rx_shift(6 downto 0) & sda;
                  n_sampled <= n_sampled + 1;
                  if (n_sampled + 1) mod 8 = 0 then
                     got_byte(n_got mod 8) <= rx_shift(6 downto 0) & sda;
                     n_got <= n_got + 1;
                  end if;
               end if;
               if s_sda_low /= s_d and scl = '1' then moved_high <= moved_high + 1; end if;
               if s_sda_low = '1' then drove_cycles <= drove_cycles + 1; end if;
               if byte_sent = '1' then n_sent_obs <= n_sent_obs + 1; end if;
               if byte_sent = '1' and bs_d = '1' then sent_wide <= sent_wide + 1; end if;
            end if;
            s_d := s_sda_low; bs_d := byte_sent;
         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';
            tx_start <= '0'; tx_continue <= '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;

         -- RISE then FALL, starting and ending with SCL low: exactly one fall per bit slot.
         procedure gen_pulse is
         begin
            wait until falling_edge(clk); m_scl_low <= '0'; phase;
            wait until falling_edge(clk); m_scl_low <= '1'; phase;
         end procedure;

         -- The falling edge that begins a transfer. From the idle-high state this produces
         -- only a fall; from the low state it produces a rise then a fall.
         procedure gen_first_fall is
         begin
            wait until falling_edge(clk); m_scl_low <= '0'; phase;
            wait until falling_edge(clk); m_scl_low <= '1'; phase;
         end procedure;

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

         procedure pulse_continue is
         begin
            wait until falling_edge(clk); tx_continue <= '1';
            step;
            wait until falling_edge(clk); tx_continue <= '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_tx: source a byte the master is already clocking ==="
                severity note;

         -- T1. Reset releases.
         do_reset;
         report "T1  reset releases SDA" severity note;
         ck_bit("T1 not driving", s_sda_low, '0');
         ck_bit("T1 the line is high", sda, '1');
         ck_bit("T1 does not claim ownership", driving, '0');

         -- T2. Nothing without a request.
         do_reset;
         for k in 0 to 3 loop gen_pulse; end loop;
         report "T2  unasked, it drives nothing at all" severity note;
         ck_int("T2 never drove", drove_cycles, 0);
         ck_int("T2 never moved SDA in a high phase", moved_high, 0);

         -- T3. THE PRE-FETCH: the first bit is on the wire before the master's first rise.
         do_reset;
         wait until falling_edge(clk); src <= x"00";
         pulse_start;
         gen_first_fall;
         report "T3  the first bit is on the wire before the master's first rise"
                severity note;
         ck_bit("T3 driving already", driving, '1');
         ck_bit("T3 and the MSB is presented", s_sda_low, '1');
         ck_bit("T3 the line is low", sda, '0');

         -- T4. A transmitted one is a RELEASE: 0xFF drives nothing.
         do_reset;
         wait until falling_edge(clk); src <= x"FF";
         pulse_start;
         gen_first_fall;
         for k in 0 to 7 loop gen_pulse; end loop;
         report "T4  0xFF is transmitted by driving nothing -- a one is a release"
                severity note;
         ck_int("T4 the master received 0xFF", to_integer(unsigned(got_byte(0))), 255);
         ck_int("T4 and the slave never pulled the line down", drove_cycles, 0);

         -- T5. A transmitted zero pulls low.
         do_reset;
         wait until falling_edge(clk); src <= x"00";
         pulse_start;
         gen_first_fall;
         for k in 0 to 7 loop gen_pulse; end loop;
         report "T5  0x00 is transmitted by pulling low for every bit" severity note;
         ck_int("T5 the master received 0x00", to_integer(unsigned(got_byte(0))), 0);

         -- T6. MSB first, with the two distinguishing values.
         do_reset;
         wait until falling_edge(clk); src <= x"80";
         pulse_start;
         gen_first_fall;
         for k in 0 to 7 loop gen_pulse; end loop;
         report "T6  MSB first, proved with 0x80" severity note;
         ck_int("T6 the master received 0x80", to_integer(unsigned(got_byte(0))), 16#80#);

         do_reset;
         wait until falling_edge(clk); src <= x"01";
         pulse_start;
         gen_first_fall;
         for k in 0 to 7 loop gen_pulse; end loop;
         ck_int("T6 and 0x01 the other way", to_integer(unsigned(got_byte(0))), 1);

         -- T7. An arbitrary pattern, read off the wire.
         do_reset;
         wait until falling_edge(clk); src <= x"A6";
         pulse_start;
         gen_first_fall;
         for k in 0 to 7 loop gen_pulse; end loop;
         report "T7  an arbitrary byte, reconstructed from the wire" severity note;
         ck_int("T7 0xA6 arrived", to_integer(unsigned(got_byte(0))), 16#A6#);
         ck_int("T7 exactly eight bits were driven", to_integer(n_bits), 8);
         ck_int("T7 one byte completed", to_integer(n_bytes), 1);

         -- T8. The invariant.
         report "T8  SDA never moved during a high phase" severity note;
         ck_int("T8 no movement in any high phase", moved_high, 0);

         -- T9. The ninth slot is not ours.
         do_reset;
         wait until falling_edge(clk); src <= x"00";
         pulse_start;
         gen_first_fall;
         for k in 0 to 7 loop gen_pulse; end loop;
         report "T9  after eight bits it releases: the ninth slot is the master's"
                severity note;
         ck_bit("T9 no longer driving", s_sda_low, '0');
         ck_bit("T9 ownership given up", driving, '0');
         ck_bit("T9 and the line is free for the master's ACK", sda, '1');
         gen_pulse;
         ck_bit("T9 still released through the ninth pulse", s_sda_low, '0');

         -- T10. One byte completed.
         do_reset;
         wait until falling_edge(clk); src <= x"3C";
         pulse_start;
         gen_first_fall;
         for k in 0 to 7 loop gen_pulse; end loop;
         ck_int("T10 exactly one byte completed", to_integer(n_bytes), 1);

         -- T11. A continued read sources the NEXT byte, re-reading the source.
         do_reset;
         wait until falling_edge(clk); src <= x"11";
         pulse_start;
         gen_first_fall;
         for k in 0 to 7 loop gen_pulse; end loop;
         wait until falling_edge(clk); src <= x"22";
         pulse_continue;
         -- Nine falls per byte: one to load the MSB, seven to place bits 6..0, one to
         -- release for the acknowledge slot.
         gen_first_fall;
         for k in 0 to 7 loop gen_pulse; end loop;
         report "T11 a continued read sources the NEXT byte, re-reading the source"
                severity note;
         ck_int("T11 first byte", to_integer(unsigned(got_byte(0))), 16#11#);
         ck_int("T11 second byte", to_integer(unsigned(got_byte(1))), 16#22#);
         ck_int("T11 two bytes completed", to_integer(n_bytes), 2);
         ck_int("T11 sixteen bits driven", to_integer(n_bits), 16);

         -- T12. Reset mid-byte releases immediately.
         do_reset;
         wait until falling_edge(clk); src <= x"00";
         pulse_start;
         gen_first_fall;
         gen_pulse;
         ck_bit("T12 driving mid-byte", s_sda_low, '1');
         wait until falling_edge(clk); rst_n <= '0'; step; step;
         report "T12 reset mid-byte releases the line immediately" severity note;
         ck_bit("T12 released", s_sda_low, '0');
         ck_bit("T12 and the bus is free", sda, '1');

         -- T13. byte_sent is the hand-off to 18.8.
         do_reset;
         wait until falling_edge(clk); src <= x"5A";
         pulse_start; gen_first_fall;
         for k in 0 to 7 loop gen_pulse; end loop;
         wait until falling_edge(clk); src <= x"A5";
         pulse_continue; gen_first_fall;
         for k in 0 to 7 loop gen_pulse; end loop;
         report "T13 byte_sent fires once per byte, one cycle wide" severity note;
         ck_int("T13 two byte_sent pulses", n_sent_obs, 2);
         ck_int("T13 neither was wide", sent_wide, 0);
         ck_int("T13 and two bytes completed", to_integer(n_bytes), 2);

         -- T14. Framing abandons the byte and releases.
         do_reset;
         wait until falling_edge(clk); src <= x"00";
         pulse_start; gen_first_fall; gen_pulse;
         ck_bit("T14 driving mid-byte", s_sda_low, '1');
         wait until falling_edge(clk); f_start <= '1';
         step;
         wait until falling_edge(clk); f_start <= '0';
         step;
         report "T14 a repeated START mid-byte abandons it and releases the line"
                severity note;
         ck_bit("T14 released", s_sda_low, '0');
         ck_bit("T14 ownership given up", driving, '0');
         ck_bit("T14 and the bus is free", sda, '1');

         -- T15. And a STOP does the same.
         do_reset;
         wait until falling_edge(clk); src <= x"00";
         pulse_start; gen_first_fall; gen_pulse;
         ck_bit("T15 driving mid-byte", s_sda_low, '1');
         wait until falling_edge(clk); f_stop <= '1';
         step;
         wait until falling_edge(clk); f_stop <= '0';
         step;
         report "T15 a STOP mid-byte does the same" severity note;
         ck_bit("T15 released", s_sda_low, '0');
         ck_bit("T15 ownership given up", driving, '0');

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

   end architecture sim;

7b. Execution

DesignSystemVerilogVerilog-2001VHDLFinish
i2c_slave_txPASS 15/15PASS 15/15PASS 15/1522490 ns, all three

8. Mutation Testing

Twelve defects.

#Injected defectExpected detectionResult
M1the sign error — a transmitted one pulls lowT4KILLED (11)
M2the same sign error on the remaining seven bitsT4, T7KILLED (12)
M3LSB firstT6KILLED (5)
M4the shift register shifts the wrong wayT7KILLED (8)
M5the wrong shift-register bit is drivenT7KILLED (6)
M6nine bits driven — the ninth slot keptT9KILLED (13)
M7seven bits, released one slot earlyT7, T9KILLED (10)
M8bits placed on the rising edgeT8KILLED (12)
M9the pre-fetch does not latch the byteT3, T7KILLED (7)
M10reset leaves SDA drivenT1KILLED (7)
M11framing does not abandon the byteT14 newKILLED (6)
M12byte_sent never emittedT13 newKILLED (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

Both survivors were patterns this module has already produced

M11: the framing inputs were tied to zero in the bench — the same hole as 18.5 §9. A transmitter that keeps driving through a repeated START fights whatever the master does next, and if the master is framing, the held line prevents the framing from happening at all.

M12: byte_sent had no consumer — the same hole as 18.6 §8's byte_done. A transmitter with perfect bits and no byte_sent sources byte after byte and never notices a NACK, because 18.8 arms on that pulse and nothing else.

That is a checkable rule, and it is worth applying before trusting any mutation score.

9. Verification Connection — Proving a Transmitter

Azvya Education Pvt. Ltd.VLSI Mentor
slave_tx_sva.sv — the invariants, and why the value check cannot live here
   // 1. NEVER CHANGE SDA WHILE SCL IS HIGH. The property every timing defect in this
   //    block trips, stated on the drive INTENT rather than on the line.
   property p_no_change_while_high;
      @(posedge clk) disable iff (!rst_n)
         (scl_q && $past(scl_q)) |-> $stable(sda_drive_low);
   endproperty
   a_phase: assert property (p_no_change_while_high);

   // 2. A TRANSMITTED ONE NEVER PULLS DOWN. The sign error, as an assertion at this
   //    block's own boundary -- mutations M1 and M2.
   property p_one_never_drives;
      @(posedge clk) disable iff (!rst_n)
         (driving && shreg_msb) |-> !sda_drive_low;
   endproperty
   a_sign: assert property (p_one_never_drives);

   // 3. OWNERSHIP ENDS AT EIGHT. The drive may not be asserted once ownership is given
   //    up -- which is mutation M6's ninth bit.
   property p_no_drive_when_not_owning;
      @(posedge clk) disable iff (!rst_n) sda_drive_low |-> driving;
   endproperty
   a_own: assert property (p_no_drive_when_not_owning);

   // 4. FRAMING RELEASES WITHIN A CYCLE.
   property p_framing_releases;
      @(posedge clk) disable iff (!rst_n)
         (start_pulse || stop_pulse) |=> !sda_drive_low;
   endproperty
   a_abort: assert property (p_framing_releases);

   // WHAT CANNOT BE ASSERTED FROM INSIDE, and it is the whole reason the bench
   // reconstructs from the wire: "the master received the byte we intended".
   //
   // This block's shift register is not evidence about the bus. An assertion relating the
   // register to the pad can only restate the block's own arithmetic -- if the shift
   // direction is wrong, both sides of the assertion are wrong together and it passes.
   //
   // The only honest check samples the LINE at the master's rising edges and rebuilds the
   // byte, which is what test T7 does. That is a bench property, not an assertion, and it
   // is why a transmitter cannot be signed off on assertions alone.
   //
   // COVERAGE:
   //
   //   cover: a byte of all ones      (drives nothing -- the release path)
   //   cover: a byte of all zeros     (drives every slot)
   //   cover: 0x80 and 0x01           the order-distinguishing pair
   //   cover: two consecutive bytes   the continue path, and the re-read of the source
   //   cover: framing mid-byte        T14/T15 -- an aborted read
   //   illegal_bin: drive asserted while not owning

10. FPGA and ASIC Implications

On an FPGA the pre-fetch is the constraint that matters, and it is a combinational one: tx_byte must be valid in the same cycle tx_req pulses. That makes the register file's read path combinational from the pointer, which is exactly what Chapter 18.9 builds — and it is why a register file large enough to infer block RAM changes this interface rather than merely its area. Block RAM reads are registered, so a target with a block-RAM-backed map must either pre-fetch a cycle earlier or stretch.

Chapter 17.2 §9 made the same observation from the master's side, and the resolution is the same: the parameter that chooses the storage changes the interface timing, not just the size.

On an ASIC, this is the second block whose output reaches a pad, and the same three-signal rule applies: sda_drive_low drives the output enable, the data input is tied low, and the readback 18.2 consumes comes from the pad's input. There is no new pad here — it is the same SDA pad the acknowledge block drives, which means the two must be arbitrated. That arbitration is Chapter 18.11's, and it is a real integration decision rather than a formality: this block and 18.5 are the only two with SDA drive intent, and they must never assert together.

Reset releases, which is the same requirement as everywhere else and the same reason: a target holding SDA low during power-up prevents every device on the board from communicating.

11. Debugging — The Read That Returned 0x00 Instead of 0xFF

Symptom

A target's register map is read back over I2C. Registers holding small values read correctly. Registers holding 0xFF read as 0x00, and registers holding 0x80 read as 0x7F. A pattern emerges: every bit the target should have transmitted as a one arrives as a zero, and vice versa. Writes to the same registers are correct, and the register contents are confirmed correct by a separate debug port.

Root Cause

The sign error: the drive intent was the bit rather than its complement. I2C is open-drain, so a transmitted one is a RELEASE and a transmitted zero is a pull-down -- the drive enable is the INVERSE of the data bit. Reading the shift register proves nothing about this, because the inversion sits between the register and the pad. The register file, the pointer, the bit ordering and the slot count were all correct; every byte was inverted on the wire and nowhere else.

Fix
Take the complement: sda_drive_low = NOT bit, which is mutation M1 in reverse. The durable fix is the bench, and it is the reason this chapter's tests are built the way they are -- reconstruct the byte from the WIRE, at the master's sampling instants, rather than comparing against the DUT's shift register. Test T4 is the sharpest form of it: transmit 0xFF and assert the drive-low was never asserted for a single cycle. A byte of all ones is sent by driving nothing, so any inversion makes the target drive continuously and the check fails immediately.

Three generalisations.

The shift register is not evidence about the bus. Everything between the register and the pad — the inversion, the ownership gating, the release — is invisible to a check that reads the register. A transmitter must be verified from the line.

An inversion looks plausible on sparse data. Values with few set bits read as their complements and still look like "some value"; the pattern only becomes obvious on 0xFF and 0x80. That is why the extremes are tests rather than curiosities.

The sharpest test for a release-based one is a byte with no zeros. 0xFF must be transmitted by driving nothing, so the check is a count of drive cycles equal to zero — a negative assertion, and the kind that gets left out of a plan enumerating behaviours.

12. Common Misconceptions

"The target can fetch the byte when the master asks for it." By then SCL is about to rise and SDA may not change. The byte must be fetched one phase earlier. §1.

"A slow register file is a performance issue." It is a correctness issue: either the read is combinational or the target must stretch. §1.

"Transmitting a one means driving SDA high." It means releasing. 0xFF is sent by driving nothing at all. §2.

"Bits can be placed whenever the target is ready." Only on the falling edge, because that begins the only phase SDA may change in. §3.

"Received and transmitted bits use the same instant." Received at the rising edge, transmitted at the falling one — both rules from the same sentence. §3.

"Holding SDA through the ninth slot is harmless if the last bit was a one." If it was a zero, the master reads its own NACK as an ACK and the read never ends. §4.

"Framing can be handled by the same release path as end-of-byte." An end-of-byte release must wait for SCL to fall; a framing release must not. Two paths. §5.

"Comparing the shift register against the expected byte verifies a transmitter." The inversion, the gating and the release all sit after the register. §11.

"An output that is obviously correct needs no observer." byte_sent was correct in every test and silencing it passed the whole suite. §8.

13. Reason It Through

Why must the byte be fetched before the master asks for it?

Because the first bit must be on SDA before the master's first rising edge, and §3.1.2 forbids changing SDA once SCL is high. The fetch has to complete in the low phase. §1.

What are the only two ways to source a byte that a slow register file cannot deliver in one cycle?

Make the read combinational, or stretch the clock. Assuming the master will be slow enough is not one of them. §1.

Why is 0xFF the sharpest test of the open-drain contract?

Because it must be transmitted by driving nothing whatsoever, so any inversion makes the target drive continuously and a zero-drive-cycles check fails at once. §2, §11.

Received bits are sampled at the rising edge and transmitted bits placed at the falling one. Why is that not inconsistent?

Both follow from §3.1.2: SDA is stable while SCL is high, so that is when it may be read; it may only change while SCL is low, so that is when it may be written. §3.

A target keeps driving through the ninth slot and its eighth bit was a zero. What does the master conclude?

That it acknowledged — it reads its own NACK back as a low. The target then keeps sourcing and the read never ends, which wedges the bus. §4.

Why does a framing-driven release not need to wait for SCL to fall, when an end-of-byte release does?

Because the framing edge has already happened and the master controls the line, so the release cannot itself produce a framing condition. An end-of-byte release would make SDA rise, and a rise while SCL is high is a STOP. §5.

Six mutation survivors in this module fall into three shapes. Which, and what single check finds two of them?

The untested half of a symmetric property; a framing input tied off; an output with no consumer. A grep for constant port connections and for outputs appearing only in a port map finds the latter two. §8.

14. Understanding Check

15. Summary

The master decides when the next bit is wanted; the target must have decided what it is one phase earlier. That is the pre-fetch, and it is a structural consequence of not owning the clock.

So the byte source must be combinational — or the target must stretch. There is no third option.

A transmitted one is a release. 0xFF is sent by driving nothing, which makes it the sharpest test of the open-drain contract: zero drive cycles for a byte with no zeros.

Transmitted bits are placed on the falling edge, received bits sampled on the rising one — both rules from the same sentence of §3.1.2.

The ninth slot belongs to the master. A transmitter still driving there can make the master read its own NACK as an ACK, and a read that will not end wedges the bus.

Framing releases immediately, unlike an end-of-byte release which must wait for SCL to fall — two paths, and a block with one has a latent framing bug.

Twelve mutants, twelve killed — after two survived, both patterns this module had already produced: framing inputs tied to zero, and an output with no consumer instantiated.

Six survivors across the module, three shapes — an untested symmetric half, a tied-off input, an unobserved output. Two of the three are findable by grep, which makes them a checkable rule rather than a lesson.

And a transmitter cannot be verified from its shift register. The inversion, the gating and the release all sit after it, so the bench rebuilds each byte from the line at the master's sampling instants.

16. What Comes Next

The target can source bytes. Chapter 18.8 makes it listen to the answer — the ninth bit this chapter just handed back.

It is the mirror of 18.5: there the target owned the ninth slot and drove it; here the master owns it and the target reads it. The two must never be active together, and the consequence of ignoring the answer is the bus-wedging read of §4 — so the chapter is short, and one AND gate in it prevents a permanent failure.

Continue learning