I'm trying to implement I2C on an FPGA, but I couldn't seem to figure out a way to detect clock stretching without external circuits. Is there any way that I can detect the wire (I'm using logic
not wire
, but I'm just calling it a wire for now) being held low by the slave from the master?
I heard about using tri-state or AND gates, but I couldn't figure out the logic behind this; do I hook both input clock and output clock to the buffer/gate or do I do something else?
I'm pretty sure the input clock (they're same wire, just port declaration here) will be low because it was driven low, so an AND gate will always not work?
If my understanding is correct, the signal should look something like this:
Slave
__ ___ ___ ___ ___ ___ ___ ___ ___ ______
sda \__/_7_X_6_X_5_X_4_X_3_X_2_X_1_X_0_/ !ACK
____ _ _ _ _ _ _ _ _ _ _
scl_in \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
____ _ _ _ _ _ _ _ _
scl_out \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_______
Master
__ ___ ___ ___ ___ ___ ___ ___ ___ ______
sda \__/_7_X_6_X_5_X_4_X_3_X_2_X_1_X_0_/ !ACK
____ _ _ _ _ _ _ _ _
scl_in \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_______
____ _ _ _ _ _ _ _ _ _ _
scl_out \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/ \_/
But the clock is driven by the Master only, so scl_in
is essentially scl_out
right? If I do any comparison scl_in
will just be the same value as the last scl_out
right? So how should I check if scl_in
is low when it could have just been the falling edge of the clock and nothing is pulling it up yet?
I could check if the ACK
is being sent but then I won't know if I need to resend the data because it's not receiving, or if it's just taking time processing. Maybe I just count ACK
for 2 cycles?
Does anyone know how I can use Verilog/SystemVerilog to detect a wire being driven both high and low at the same time or how to deal with clock stretching?