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?
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
Two clk. signals
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.