In which clock edge does the I2C slave write?

I'm trying to implement an I2C master - slave example in an FPGA (Verilog).

As the I2C protocol specifies, the master must make sure that it writes the next bit enough time before the clock signal goes high (rising edge in SCL). Then, the slave can read this bit in the mentioned rising edge. To achieve this I generate 2 clock phase-shifted signals: one (whose rising edge comes before) is used as a clock signal to write each bit. The other, is directly connected to SDA.

However, the slave is not aware of the mentioned first signal, it just receives SCL. Then, how can the slave write bits before the SCL rising edge arrives? In which edge should it write?

Verilog code

Clock generator

module double_clk_gen
#(parameter CLK_DIV = 20,
parameter CLK0_HS = 1,
parameter CLK1_HS = 1'bz) (

output reg clkout0,
output reg clkout1,
input wire en,
input wire clk
);
localparam CS_START = 0, CS_RUN = 1;

parameter div = CLK_DIV / 2;

reg [15:0] cnt;

always @ (posedge clk) begin
if (en) begin
if (cnt < 1*div) begin
clkout0 <= CLK0_HS;
clkout1 <= 0;
end else if ((cnt >= 1*div) && (cnt < 2*div)) begin
clkout0 <= CLK0_HS;
clkout1 <= CLK1_HS;
end else if ((cnt >= 2*div) && (cnt < 3*div)) begin
clkout0 <= 0;
clkout1 <= CLK1_HS;
end else if ((cnt >= 3*div) && (cnt < 4*div)) begin
clkout0 <= 0;
clkout1 <= 0;
end else begin
clkout0 <= clkout0;
clkout1 <= clkout1;
end

if (cnt == 4*div - 1)
cnt <= 0;
else
cnt <= cnt + 1;
end else begin
clkout0 <= 0;
clkout1 <= CLK1_HS;
cnt <= 0;
end
end

endmodule


Timing diagrams

Two clk. signals SDA and SCL are the normal I2C signals. _sda_clk is the clock signal generated to write the bits, which is phase-shifted with regards to SCL to write them before the latter's rising edge.

3 Answers

During a transfer of bits then, for each bit, either the master or target will be a bit transmitter and the other will be a bit receiver. This will change during the transfer.

In I2C data communication^, the SDA line can only change while SCL is LOW.

The bit transmitter must drive each outgoing data bit onto SDA sometime between the SCL falling edge and the SCL rising edge.

The bit receiver will accept a bit while SCL is high.

So the transmitting of a bit is triggered by an SCL falling edge.

And the receiving of a bit is triggered by an SCL rising edge.

An I2C target (slave) design must be capable of responding to the SCL edges.

I have designed a successful and reliable I2C slaves in VHDL for FPGAs/CPLDs, as well as I2C masters. This information comes from the I2C spec', which is freely available on the internet. You should study this document and get all of the info' you need to sketch out some circuit block diagram before trying to write HDL for it. Keeping adding bits on to a design as you learn new fundamental I2C rules will make for a messy, hard-to-follow design.

(^ Note that I2C START and STOP conditions are not data communication.)

Both master and slave can (and should) change SDA as soon as SCL goes below VIL on the falling edge of clock.

According to the specs, for a data bit, it must be set before a rising edge and it must be updated after a falling edge. Data hold time after a falling edge is zero, but it still means after the clock has already fallen, and SCL fall time is allowed to be up to 300ns (depending on mode it might br less).

So the device can load in a data bit on rising clock edge, and must set the data state after falling edge.

It also mentioned in specs that a device must internally provide a data hold time of at least 300ns for SDA, which may mean that if properly implemented, data bit can be loaded in at falling edge too.