> I'm currently in the process of creating a synthesizable Verilog
> F/S I2C slave, but have little experience with I2C in the real
> I'm reading the specs, and I feel I'm getting a pretty good
> understanding. If I'm getting this right, the SDA line will only
> change when the SCL line is low - except when the master is
> indicating a START or STOP command.
> So the question I have for those who have really done this is -
> in the real world, could a master (or series of masters) issue
> a STOP command followed by a START command - all on the same
> SCL high period. The latest I2C spec doesn't explain whether
> or not this could happen.
> This is key to me, since I'm trying to create an I2C slave that
> runs solely off the SDA and SCL signals. Whether or not I have
> to deal with START and STOP on the same SCL high period will
> impact the design choice I make.
AFAIK, that's normal when the bus is idle in the meantime.
The idle bus has all drivers loose and both lines up. When the master ends a transmission, the last thing is the STOP condition: SCL up, then SDA up. When the next transmission starts, the first thing is the START condition: SCL still up, SDA down.
Hi, I have done this with a Lattice 1016 (64 registers) The start condition, SCL high and SDA falling is to put the device in lets call it "address compare mode", if the address (Bit 1-7) matches the device goes into "read or write mode" depending on bit0 , otherwise the "I'm not interested mode", i.e. the "not address compare mode" and "not read read or write mode"
This is determined at the rising edge of the 9th SCL pulse. So the start condition is a mode reset command. Note that controllers like the PCF8584 have slow rising and falling signals. Your FPGA will be ways too fast for this, so you will have to register the signals to determine the transitions.
Tip: in read/write mode where the 9th SCL pulse is used for ACK generation you can also use the rising edge to generate a read or write pulse to communicate with a device. With this you can have a continuous 8-bit data stream into or from the device. Ideal for a graphical LCD-display (and whenever there is a connection with a high frequency and a low frequency device)
Thanks for the answer. I actually re-read the spec, and noticed that a STOP following a START in the same SCL high period is illegal. I'm going to ignore an illegally applied STOP (i.e. illegal STOP ignored). I was also worried about the possibility of repeated STOP/ START/STOP/START sequences.
However - as a follow-up question, would it be possible to see SCL toggle after a STOP before the next START command "in the real world"? None of the timing diagrams in the spec seem to address this possibility; all diagrams show SDA and SCL staying high for the foreseeable future. I'd guess that the thing to do is simply put put the I2C slave in a wait state until a START condition is seen. I wouldn't see any reason to toggle SCL between a STOP and the next START, but I haven't seen any real-world designs.
I feel it is a bit futile forbidding illegal events because sooner or later they will happen either through bugs or malfunction.
Personally I would make my I2C slaves enter the idle state whenever they saw a stop condition (legal or not). Seems a fair and simple way of entering resetting slave state machines without sending any bytes, even if the spec forbids it.
If it happens to be an illegal transition then the I2C spec does not oblige me to do anything in particular, so I can keep my I2C slave logic simple. If I had to implement things like roll-back after malformed messages, I might need large n-byte roll-back buffers.
1) It seems that the preferred method is to have a STOP condition (SDA rising when SCL=1) on the same SCL high period as a START period (SDA falling when SCL=1). This would look like this: _________________________ SCL ___| |_____ _________________ SDA _______| |_________
2) As far as I can tell the spec says nothing about SCL changing between a STOP and START. I wouldn't see any advantage to it, but I couldn't sense it was illegal. I would suppose any clock toggling before a START should just be ignored until a START is detected.
3) I was worried about whether a master could "change its mind" after issuing a start if it was suddenly occupied with something considered more important. Fortunately, this doesn't seem to be a problem.
4) Most of what I'm planning is a straightforward FSM clocked on the negedge of SCL. The START and STOP logic I'm planning on using isn't as straightforward. This was the part that would have been messed up if I had to account for multiple START or STOP methods. I wanted to create a START detected signal, and use that to tell the FSM when to start monitoring SDA.
5) I could possibly use a high-speed internal clock. However - the goal is a low-power design, and I was told that just toggling the clock tree would create unnecessary power consumption.
Well that's what really matters (IHO), "the real world". And in the real world everything is possible. You can have a lousy implemented micro-controller software I2C or even if you are debugging the hardware you can accidentally toggle a line. I know applications where they misuse the spec and by driving the SCL low between STOP and START for a certain time, they signal other devices for example busmaster takeover. Everything is possible.
If you are designing this for a real application you have to deal with the real world and you must handle all the situations you can think off. It's very clumsy if your hardware is 'hanging'. Master controllers are build by spec's and slaves by sense.
I have not given this a lot of thought, but I believe you can use two FFs (with resets) to detect the start/stop conditions and maintain a state of disabled/enabled.
The start FF is clocked on the falling edge of SDA with SCL on the D input. This FF will be set on a start condition. The stop FF will be clocked on the rising edge of SDA with SCL on the D input. This FF will be set on the stop condition. The start FF being off will hold the stop FF in reset. The stop FF being set will reset the start FF. So the sequence will be;
1) both FFs clear
2) on start, the start FF is set and the rest of the circuit is enabled
3) on stop, the stop FF is set which clears the start FF
4) the start FF being cleared also clears the stop FF
The only issue I can see with this design is that the stop FF will generate a reset pulse determined by the time it takes to reset both FFs plus the routing. Some people would object to this saying it may violate the timing requirements of your logic. If so, you may want to use the LUT or the OR array with the FF to add some extra delay. In general this should work ok since it is basically self timed logic.
On the other hand, using a synchronous design should not consume much power. Unless you are going for power below 100 uA, a low power CPLD (like the coolrunner) should be able to run at 1 MHz (fast enough for most I2C chips at 400 kb/s) with power at that level.
Rick "rickman" Collins
In actual data transmission it's not allowed to change the data when the clock is high. The start and stop conditions are distinguished from normal data bits by breaking the data transfer protocol here.
Yes - the contention is taken care by the open-drain/collector nature of the bus. The master seeing its output clamped down by another master has to backoff.
There is a similar method to synchronise the clocks: any station feeling that the things are going too fast is allowed to extend the clock-down time by clamping it. The sending station has to honour the clock clamp and wait.
I had something a little different, but not far off from your suggestion. Think masking off one signal with the other.
I won't go into the proprietary details, but I'm doing this work for an SoC design that might be battery powered in some applications. My boss is keen on reducing power consumption during a standby mode.
I also apologize if I don't get into specifics about my planned design that might explain my problems. As with many in these NG's, I work at a large company that considers the product I produce confidential. If this works well, I (personally) wouldn't be averse to submitting this as an open source Verilog block. However - I'd have to make sure this is OK with my employer.