Dealing with bidirectional communication over 1 pin

I am writing a Verilog driver for a simple temperature sensor connected to an FPGA. (The temperature sensor datasheet is available here.) Communications occur over one pin, the sda pin, where the slave or master sends a byte, which is then "acknowledged" by the other at the end of the byte (between the clock cycles 9 and 1).

I imagine that the best way to model this is making sda an inout wire, where both the master and the slave drive sda using an assign statement. It is unclear to me how collisions can be avoided.

What happens when the same inout wire is driven by both the source and the master? What is the best way to model send-acknowledge cycles over one pin in Verilog?

-

In I2C, when it's their turn to talk, either the master or slave will drives the data line low for a logic 0 or becomes a high impedance input for a logic 1.

When it becomes high impedance, it essentially floats the line and allows the pull-up resistor to pull the line high (logic one). When it is a high impedance input it can detect if the line is being driven low - if it tried to "write" a logic 1 in this clock cycle, then we know some kind of contention occurred. Note that this is the only case that we care about. If contention occurs but does not end up changing the resulting bit stream then we actually just go about our business without giving any error. If contention does occur, the party that concedes the bus is the one that detected a logic 0 when it was trying to put out a logic 1.

I don't know Verilog, but in VHDL, if we're using the STD_LOGIC type, we can assign it as "inout" and in a process, assign it the 'Z' value (high-impedance) and then sample the pin for a high or a low.

If you are writing an I2C master, it is your responsibility to detect if the I2C line is in use, specifically, looking for start and stop conditions to signal the start and end of usage by another possible master.

NOTE: it says two-wire interface in the datasheet, I'm pretty sure this means I2C so the above should still be relevant.

-
Watching for bus-in-use conditions is only necessary if a master is going to coexist with other master devices on the bus. In many applications that is not the case. On the other hand, on some I2C slave devices the SCK pin is bidirectional; devices which are not ready for a bit can hold SCK low until they are ready. To clock each bit when using any such devices, the master must release SCK, wait until all devices on the bus have also released it, and then reassert it. Incidentally, while "two-wire" generally means "non-licensed I2C-compatible", I've seen some "two-wire" devices which... – supercat Apr 10 '12 at 17:28
In addition to this, you also need to model the pullup resistor, in VHDL it would be sda <= 'H', and then read the signal using TO_X01(sda). Or implement a wire-and resolver function. – Ben Voigt Apr 10 '12 at 17:30
@supercat: Yeah, that's commonly known as "clock stretching", and it does create contention in even a single-master environment. – Ben Voigt Apr 10 '12 at 17:31
...borrow heavily from I2C but do some weird obnoxious things which I doubt Philips would go for, like a humidity sensor which requires that SCK be held low during a reading and asynchronously asserts SDA when it's ready. I've also seen a two-wire real-time clock chip which input and output data LSB-first. Bizarre. – supercat Apr 10 '12 at 17:34

Your temperature sensor doesn't use just 1 wire to communicate, it uses 2. The clock wire is equally important as the data wire in communicating correctly.

The I2C bus is fairly complex, especially if all its bells and whistles are implemented. Luckily most chips don't implement every capability, and that's why datasheet-level documentation is often inconsistent. For complete and definitive information, you can get the full specification from NXP.

It is unclear to me how collisions can be avoided.

If the temperature sensor is the only other device on the bus, your FPGA will always be the master in the communication protocol. That means you control the clock signal, and you will always know whether the slave is allowed to drive the bus at any given moment.

Typically, you would write a state machine in your FPGA that manages the data in and out of the slave device, and knows when to send data out and when to receive data in.

Note that some slave devices will also assert control of the clock signal at certain specific times in the transaction, as described by the standard. They will do this to "stretch" the low periods of the clock and give themselves time to complete a measurement or calculation before the master starts clocking out the actual data. If your master design doesn't account for this, it could cause a "collision".

What happens when the same inout wire is driven by both the source and the master?

Since I2C devices can only drive low, it generally won't damage either chip if there's a conflict. When you want to send a logic '1', you don't drive the line high, you put it in high-Z state and let an external resistor pull it up. If the slave drives a '0' at the same time, there won't be any damage to either device.

What is the best way to model send-acknowledge cycles over one pin in Verilog?

Your Verilog won't "model" a send-acknowledge cycle. It will describe logic that generates the correct signals from the master device.

If you want to simulate the protocol before committing to hardware, you would write a second module that has another state machine that responds to the master's signals and produces the correct signals for the slave device.

-