Modified I²C receiver from discrete logic

In this article, I will describe the operation of an I2C receiver built from discrete gates and components. The receiver has one register that can be read from and written to. Unlike other I2C devices, the contents of the register can be ORed or ANDed with another byte without reading and writing in separate transactions. The circuit described in this article is designed for slave devices that only accept data (for example, a motor driver) and do not return any data (for example, a temperature sensor).

Modified I2C protocol

Note: the protocol described in this section is not the same as the proper I2C protocol

Clock signal (SCL)

Unlike with true I2C, the clock signal SCL runs all the time. This provides all devices on the bus with a continuous clock signal. This allows other devices to transmit on the bus without having their own crystal or oscillator. Since the bitrate is 100kbps, but 200kHz is required for transmission, the two clock signals are mixed into one signal on one wire. On the master side, a positive-edge-triggered D-flip-flop is used to generate the 100kHz bit clock. Whenever the 200kHz signal is high, the clock wire is at -5V. Otherwise, it is equal to the complement of the 100kHz signal. An example is shown below:
Also, the clock wire (which is different from SCL), is not an open collector signal, but is is driven by a push-pull circuit on the master side.

Start, stop and data bits

The SDA wire is open-collector, meaning that there is a pull-up resistor on the SDA wire, and both the master and slave are only permitted to pull the wire to ground.
To begin a transaction, the master pulls the SDA line low while the 100kHz clock is high. On the following falling edge of the bit clock, the most significant bit of the first byte is presented on the SDA wire. The SDA wire is updated on the falling edge of the bit clock. After one byte has been transmitted, the receiver will pull the SDA pin low to acknowledge the previous byte. After the receiver has acknowledged the last byte, the transmitter lets the SDA pin go high while the bit clock is high.

Bit and byte structure

The first byte contains 7 address (device select) bits and one read/write bit. The second byte contains 7 register select bits and one register CLEAR bit. The third byte is the data byte. The R/W and CLEAR bit control the type of I2C transaction according to the table below:
R/W CLEAR Mode
0 0 In-place OR
0 1 Write
1 0 Read/in-place AND. Normally, the master does not drive the SDA line while the slave writes its data back, but if the master writes new data at the same time, the data on the bus will be the logical AND of the master and slave bytes. The slave reads this data back into the shift register, ANDing it with the byte from the master

Note on reference designators: Many logic chips contain multiple copies of the same circuit (for example, 74HC00 NAND chip). Each copy will be shown individually, but will have the same reference designator. To distinguish these copies, the lowest pin number belonging to that copy will be placed in brackets after the reference designator. For example, the gates a 74HC00 with reference designator U1 will be referred to as U1[1], U1[4], U1[8], and U1[11]

The schematic will be divided into four sections and each one will be explained separately. The schematic may be downloaded here

Part 1: Clock decoder

The purpose of this section is to decode the bit clock SCL from the clock wire. This is necessary since the clock wire has negative voltages to indicate a different clock. The schematic is shown below:
To decode the SCL signal, the above circuit switches SCL low when the clock wire goes positive and keeps SCL low until the clock wire returns to zero.
  1. The clock wire is at 5V, and current flows through D1 and R5. The output of the XOR gate (which is wired as an inverter) goes low and SCL goes high.
  2. The clock wire goes negative, so Q2 switches on as current flows from ground, through the base-emitter junction of Q2, and through R4. This switches on Q1, which presents 5V at the emitter of Q3. Since SCL was previously low, Q3 switches on and applies 5V to thr input of the XOR gate. This keeps SCL low and SCL high while the clock wire is negative.
  3. Once the clock wire returns to zero, Q2, Q1, and Q3 switch off. Since the clock wire is at zero volts and the diode is not conducting, the input to the XOR gate (SCL is low and the output (SCL) is high.
  4. When the clock wire goes negative again, Q2 and Q1 switch on, but since SCL is high, Q3 does not switch on and SCL and SCL do not change.

Part 2: Start/stop detection

The purpose of this section is to detect the start and stop signals from the transmitter and detect when the transmitter is active. The schematic is down below:
This part consists of two D-flip-flops, U3 and U6, that detect the start and stop signals and a NOR-based SR-flip-flop to latch the state of the transmitter.
A start condition occurs when there is a falling edge on SDA while SCL is high. When there is a falling edge on SDA, there is a rising edge at the output of the XOR gate, and the D-flip-flop U6 stores the value on SCL at its output. If SCL was high during the falling edge, the output sets the SR-flip-flop and RECV goes high.
A stop condition occurs when there is a rising edge on SDA while SCL is high. When there is a rising edge on SDA, the U3 stores the value of SCL at is output. If SCL was high, the output of U3 is also high and the SR-flip-flop is reset and RECV goes low.
If either flip flop is set while SCL is high, both flip-flops are automatically cleared once SCL goes low to prepare the flip-flops to respond to another start or stop condition.
When Part 3 determines that the transaction is addressed to a different device (wrong address), it pulls the VALID wire low. This sets U3, which resets the SR-flip-flop and RECV goes low.

Part 3: Address decoder and bit/byte counter

The purpose of this section is to keep track of the current bit and byte. Additionally, this section determines whether a transaction is addressed to this receiver. The schematic is shown below:
This section contains a bit counter, a byte counter, an "address valid" latch, and an address comparator.
U3 is a D-flip-flop that latches RECV on the rising edge of SCL. The output of U3, RECVD, feeds the reset pins of the bit and byte counters. The purpose of this flip-flop is to prevent the bit counter from incrementing on the falling edge immediately following the start signal. The bit counter may only increment after at least one rising edge has occurred since the start signal. An image of the waveform is shown below:
0 1 2 3 4 5 6 7 8 0 0
bit counter enabled

U4: bit counter

U4 is decade ring counter that steps through its 10 outputs on the rising edge of its clock. Since its clock is connected to SCL, U4 counts on the falling edge of SCL. While RECV is low, the bit counter is reset. The details of this are explained in U1[1] and U2[1]: Reset circuit. The "0" output is connected to the wire b7 and is high while the most significant bit is being transmitted. The "7" output is connected to the wire b0 and is high while the least significant bit is being transmitted. The "8" output is connected to the wire DOACK and is high while the acknowledge bit is being transmitted. The "9" output feeds the reset circuit and causes the counter to reset itself after only 9 clock pulses, rather than 10.
Note: the outputs 0-7 will also be referred to as bits 7-0 or b7-b0 respectively. Note the inversion of the order, since I2C transmits most significant bit first.

U8 and U1[11]: Byte counter

U8 consists of 4 D-flip-flops with a common clock and reset pin. Its clock is connected to the 9th output of U4, so it triggers after the ACK bit has ended. Its reset pin is connected to RECVD, so it will be reset as long as no transaction is taking place. The wires B0, B1, and B2 will be high during the first, second, and third bytes of the transaction respectively.

Suppose the CLR pin just went high and U8 is no longer reset. Both the Q0 and Q1 pins are high, so the output of the AND gate U1[11], B0, is also high.

Suppose U8 receives one clock pulse. The value of B0 (high) is loaded onto B1, so B1 goes high while Q0 goes low. Thus, the output of U1[11] and B0 go low.

Suppose U8 received a second clock pulse. The value of B0 (low) is loaded onto B1 and the value of B1 (high) is loaded onto B2. Q0 goes high, but Q1 goes low, and the output of the AND gate stays low

Suppose U8 receives a third clock pulse. The value of B0 (low) is loaded onto B1 and rhe value of B1 (low) is loaded onto B2. Since B1 and B2 are now low, Q0 and Q1 are both high and so B0 goes high again.

Address comparator

The address consists of the diodes, Q5 and R8, R6, R7, U1[8], U1[4], U2[8], and U6[8]. The address is defined by the pattern of the diodes. The address bytes of the device shown above are 0b11110111 (device address) and 0b01101001 (register select). This will be explained later.

When the receiver is not receiving, the RECV pin is low and the Q pin of U6[8] is high. Suppose the master begins a transaction addressed to the current device. During the first byte, B0 will be high and B1 will be low. The wire A1 will be high since it is fed from B0 through R7 and nothing is connected to A1 to pull it down. The wire A0 will be pulled low through R6, but during certain bits (in this case, bit 3), current may flow through a diode and pull A0 high. When both A0 and A1 are high the output of U1[8] is also high. Thus, the pattern of bits on the output of U1[8] is 0b00001000. Note that this is the complement of the address I gave earlier.

During the second byte, B1 will be high and B0 will be low. This time, the A0 will always be high and A1 will be high only on bits connected to a diode. For example, during the most significant bit, current flows through D4 and pulls A1. The pattern of bits on the output of U1[8] will be 0b10010110. Similarly, this is the complement of the second address byte. In summary, the pattern of diodes is the complement of the corresponding address byte.

When the output of U1[8] is XOR'ed with SDA, one would expect a sequence of all ones, since a value XOR'ed with its complement is always one. On the rising edge of SCL, the output of the XOR gate, U2[8], is latched into the D-flip-flop U6[8]. If at any point an incorrect address bit is received, the output of the XOR gate will be low and the D-flip-flop will latch in a zero. If this happens, the corresponding wire VALID goes low as well. Remember that VALID connects to the stop bit detection D-flip-flop, so the effect of VALID going low is the same as the effect of receiving a stop signal. This will cause the entire receiver to shut down, and no data is read in from the bus.

If a byte is correct, the receiver must transmit an acknowledge bit. During bit 8 (the acknowledge bit), DOACK is high and will switch on Q7, pulling SDA low. Since a diode is present between DOACK and A0 as well as between DOACK and A1, the output of U1[8] will be high. Since SDA is low, the output of the XOR gate is high and the bit is latched in as "correct".

Additionally, transistor Q5 feeds the wire A0. Its emitter is connected to b7 via D10. Its base is connected via a resistor to SDA. Suppose b7 and B0 are high. Since B0 is high, A1 is high as well. If SDA is low, Q5 turns on and A0 goes high as well. The output of U1[8] goes high and the output of U2[8] is high as well. If SDA is high, Q5 is off and A0 is low. The output of U1[8] is low and the output of U2[8] is high (since SDA is high). Either way, the output of U2[8] is high and the bit is registered as correct. This behavior is needed when comparing the R/W bit, since either value is "correct" and should be responded to.

U1[1] and U2[1]: Reset circuit

If both address bytes were correct, then B2 will go high after the acknowledge bit for the second address byte is transmitted. Now, both B0 and B1 are low, so neither A0 nor A1 will be always high. The address comparator circuit will try to compare the incoming data with some random data from U1[8] and this will inevitable cause the receiver circuit to reset. However, since the U6[8] latches on the rising edge of SCL and B2 goes high on the preceding falling edge of SCL, there will be some time where B2 is high before U6[8] can cause the receiver to reset. When B2 goes high, Q2 of U8 (which is the same as B2) will go low and preset the D-flip-flop U3[8]. At this point, even if the CLR input of U3[8] goes low, the Q output will stay high, since according to the datasheet, if CLR and PRE are low, then both Q and Q will be high. Therefore, the Q output of U3[8] will stay high until another byte has occurred and the byte counter cycles back to byte 0 (B2 goes low and B0 goes high).

If Q of U3[8] were connected directly to U2[1] directly, this would cause the bit counter to be reset. However, this is not desireable, since it is needed to keep track of the acknowledge bit and drive DOACK accordingly. Thus, U1[1] was added so that if B2 has gone low, the reset pin of U4 is not driven. Note that in the absence of an OR gate, an XOR gate was used. This does not pose any risk since B2 changes after output 9 of U4 changes and output 9 and the output of the VALID flip-flop change at different times as well.

Part 4: Shift register, R/W latch, and clear circuitry

This section contains a shift register for storing the data byte, a latch for storing the read/write bit, and a circuit for clearing the register. The 74HC595 shift register has an internal shift register and an output latch. Only the last bit of the internal shift register is available. The circuit also contains a 4052 analog switch (multiplexer) as part of the latch and in-place OR circuits. The schematic is shown below:

U10[1] and U5[8]: Shift register clock generation

The shift register may only be clocked during the first 8 bits of the data byte. This is to make sure that the data on the shift register is the same as the data on the output latch, so that the data in the shift register may be used for the in-place OR and AND modes. The circuit formed by U10[1] and U5[8] is equivalent to SCL && B2 && !DOACK, which when rearranged, yields !(!(SCL && B2) || DOACK)

SRCLR generation

The CLEAR bit is the last bit in the second address byte. Thus the CLEAR bit must be read when B1, b0, and SCL are high. If B1 && b0 && SCL && SDA then the shift register is reset. However, since the shift register requires a low level to reset, the last gate is replaced with a NAND gate: SRCLR = !(((SCL && b0) && SDA) && B1)

R/W latch circuit

The wire LRW goes low when the R/W bit is on the SDA input. The R/W bit must be read when B0, b0, and SCL are high. Thus LRW = !((SCL && b0) && B0). The NOT gate has been replaced with a NOR gate wired as an inverter and the AND gate between SCL and b0 is shared between this and the previous sub-section (U9[8] in the diagram).

U10[4] and U10[8] form a NAND SR-flip-flop. Both the S and R inputs to the flip-flop are pulled up by R9 and R10. When LRW goes low, the X input of U11 goes low. If SDA is low, then X will be connected to either X0 or X2, depending on the value of the B input. However, since they are connected together, it does not matter which one X is connected to. Either way, the top input to U10[4] is pulled down through the analog switch, the output of U10[4] goes high, and the output of U10[8] (R/W) goes low. If SDA is high, the X will be connected to either X1 or X3, depending on the value of the B input. Either way, the bottom input of U10[8] is pulled doen through the analog switch, the output of U10[8] (R/W) goes high, and the output of U10[4] goes low. Thus, the value of R/W is latched in at the correct time.

In-place OR/AND circuit

The latched read/write bit is connected to select input B of U11, and the SDA pin is connected to select input A of U11.

If the transaction is a read transaction, R/W will be high and select input B will be high. Y will be connected to Y2 or Y3, but since they are wired together, it does not matter which one. The value on the QHs output of the shift register will be routed to the emitter of Q6. When B2 is high, Q6 will be on and will connect QHs to SDA, reading the data in the shift register back to the master. Additionally, the shift register reads the value on the bus via R13 into its SER input. If the master does not drive the bus while the receiver is responding, the data in the shift register do not change. However, if the master drives the bus, the data in the receiver's shift register will be ANDed with the data the master tries to write onto the bus.

Note that since the data returned are the data that were previously in the shift register, there is no way for the reciever to return data that have never been written to it. Thus, one couldn't use this circuit for something like a temperature sensor, where data is to be read back. I might show such circuits in future articles.

If the transaction is a write transaction, R/W will be low and select input B will be low. If SDA is high, Y will be connected to Y1 and Y0 will not be driven by U11 at all. Thus, SDA will drive the SER input via R13. If SDA is low, the analog switch will connect QHs to SER. Thus, the value in the register will be ORed with the data contained in the write transaction. If the clear bit is set in the second address byte, the shift register (which is now full of zeros) will be ORed with the incoming data, which is equivalent to writing the data to it.

Comments

Popular posts from this blog

Improving and calibrating the capacitive water sensor

Controlling a ceiling fan and light with an Arduino

Turn a buck converter module into a buck-boost converter with only two components