I2C Interfacing To XC3S400 FPGA

Download as pdf or txt
Download as pdf or txt
You are on page 1of 14

Interfacing I2C Device to

XC2Sxx D-Board

APPLIED DIGITAL MICROSYSTEMS PVT LTD


D-216, ANSA INDUSTRIAL ESTATE, SAKI VIHAR ROAD,
ANDHERI EAST, MUMBAI 400 072.
Tel: (91-22-)28520817, 56924483/4
Email: [email protected]
I2C Peripheral Interfacing

TKBase is a VLSI/µP design laboratory training board aimed at enabling


engineering students to learn complete µP to VLSI technology from startup single
chip microcontroller to a complex embedded FPGA platform.

The TKB2S daughter board and an ADM’s LG320/LGLite form a complete


integrated SOC - embedded design environment. It is built for real time
engineering inside a programmable physical hardware design space. You'll be
able to probe, analyze and debug your circuit just like an actual prototype. And
because the implementation is performed on a low cost Xilinx FPGA, you can
update your design quickly and many times over without incurring cost or time
penalties.

Introduction – I2C – Inter Integrated Circuits


The I2C bus was developed in the early 1980s by Philips for their consumer
products with multiple components like RTC, EEPROM, and ADC/DAC that
needed to be linked together. Controlling these functions with parallel bus
techniques would require multiple IO pins and lots of programming. Philips
solved the problem with a multi-master 2-wire bus system with transmission rates
of (up to) 400 KHz.

Challenge’s / Solution
With a parallel architecture each peripheral component will have address lines,
data lines, a clock line and various other control signals. Address or data values
sent over the bus are transferred at the same time over all the parallel lines. This
makes it relatively easy to generate chip selects and trigger on the event of
interest using logic analyzers.

With serial bus architecture all this information must be sent serially on the same
few signal lines. This means that a single signal may include address, control,
data, and clock information.

Wiring embedded processor with multiple I2C devices together is easy;


debugging them can be very difficult. Parallel peripheral devices can be
debugged with simple trigger logic using a logic analyzer. Today, however, more
and more of these parallel devices used in embedded system design are being
replaced with serial buses for the following reasons:

• Less board space/ signals to route, hence Lower cost.


• Lower power requirements.
• Fewer pins on packages.
• Differential signaling for better noise immunity.
• Wide availability of I2C serial devices.
I2C Serial busses are often hard to trigger on, and there is no time-reference to
the data because data bits are driven sequentially. The embedded designer has
to understand both sequential data and the sequential timing. Additionally, data
serializing/deserializing is required with programming logic overhead and in most
cases there's no guarantee that the interface will work properly.

This guide takes you through various steps in learning I2C features and how to
interface and debug these peripherals using capabilities of ADM’s new LGLite
Integrated Logic Analyzer/Pattern Generator. TKBase is equipped and fully
loaded with I2C based peripherals like ADC, DAC, EEPROM, RAM and RTC.

I2C – How does it work?

I2C’s architecture is a simple two-wire interface. It is comprised of bi-directional


serial clock (SCL) and data (SDA) lines. I2C supports multiple masters and
slaves on the bus, but only one master may be active at any one time. Any I2C
device can be attached to the bus allowing any master device to exchange
information with a slave device.

Each device is recognized by a unique address and can operate as either a


transmitter or receiver, depending on the function of the device. Initially, I2C only
used 7 bit addresses, but evolved over time to allow 10 bit addressing as well.
Three bit rates are supported; 100 kbps (standard mode), 400 kbps (fast mode),
and 3.4 Mbps (high speed mode). The maximum number of devices is
determined by a maximum capacitance of 400 pf or roughly 20-30 devices. The
I2C standard specifies the following format:
If the user wants to communicate with external I2C peripherals like EEPROM,
serial RAM, serial LCD etc, a complete knowledge of I2C protocol is a must. An
I2C peripheral communicates with only two Pins, SDA and SCL. While SCL is
driven by the master, the SDA is a bidirectional pin. Like any other protocol, an
I2C communication has a Start and Stop signature as shown below.

Format Description
Start Master is taking control and message will follow.
Address 8 or 10 bit number representing address of the device to
be read or written. The LSB bit defines the direction of
data flow (R/W bit)
R/W bit A one indicates that data will be read from else written to
the device.
ACK A bit from the slave device acknowledging the masters
action.
Data Data or message to be sent / received .
Stop Indicates the message is complete and master has
released the bus

CHARACTERISTICS OF THE I2C-BUS

The I2C-bus is for bidirectional, two-line communication between a master and a


slave device. The two signal lines are a serial data line (SDA) and a serial clock
line (SCL). Both lines must be connected to a positive supply via a pull-up
resistor as they can be tristated.

BIT transfer

One data bit is transferred during each clock pulse. The data on the SDA line
must remain stable during the HIGH period of the SCL clock pulse as changes in
the data line at this time will be interpreted as a control signal.
Start and stop conditions

Both data and clock lines remain HIGH when the bus is not busy. A HIGH-to-
LOW transition of the data line, while the clock is HIGH, is defined as the start
condition (S). A LOW-to-HIGH transition of the data line while the clock is HIGH,
is defined as the stop condition (P).

Acknowledge
A slave receiver which is addressed must generate an acknowledge after the
reception of each byte. Also a master must generate an acknowledge after the
reception of each byte that has been clocked out of the slave transmitter. The
device that acknowledges has to pull down the SDA line during the acknowledge
clock pulse, so that the SDA line is stable LOW during the HIGH period of the
acknowledge related clock pulse. A master receiver must signal an end of data to
the transmitter by not generating an acknowledge on the last byte that has been
clocked out of the slave. In this event the transmitter must leave the data line
HIGH to enable the master to generate a stop condition.
PCF8591 – I2C ADC/DAC
GENERAL DESCRIPTION

The PCF8591 is a single-chip, single-supply low power 8-bit CMOS data


acquisition device with four analog inputs, one analog output and a serial I2C-bus
interface. Three address pins A0, A1 and A2 are used for programming the
hardware address, allowing the use of up to eight devices connected to the I2C-
bus without additional hardware. Address, control and data to and from the
device are transferred serially via the two-line bidirectional I2C-bus. The
functions of the device include analog input multiplexing, on-chip track and hold
function, 8-bit analog-to-digital conversion and an 8-bit digital-to-analog
conversion. The maximum conversion rate is given by the maximum speed of the
I2C-bus.
Pin Information

Functional Description

Addressing

Each PCF8591 device in an I2C-bus system is activated by sending a valid address to the
device. The address consists of a fixed part and a programmable part. The programmable
part must be set according to the address pins A0, A1 and A2. The address always has to
be sent as the first byte after the start condition in the I2C-bus protocol. The last bit of the
address byte is the read/write-bit which sets the direction of the following data transfer.
Control byte

The second byte sent to a PCF8591 device will be stored in its control register and is
required to control the device function. The upper nibble of the control register is used for
enabling the analog output, and for programming the analog inputs as single-ended or
differential inputs. The lower nibble selects one of the analog input channels defined by
the upper nibble (see Fig.4). If the auto-increment flag is set the channel number is
incremented automatically after each A/D conversion.

D/A conversion

The third byte sent to a PCF8591 device is stored in the DAC data register and is
converted to the corresponding analog voltage using the on-chip D/A converter.
A/D conversion
The A/D converter makes use of the successive approximation conversion technique. The
on-chip D/A converter and a high-gain comparator are used temporarily during an A/D
conversion cycle. An A/D conversion cycle is always started after sending a valid read
mode address to a PCF8591 device.

The Problem : - Interfacing FPGA to I2C device

We now understand what is I2C standard, and also know a little about
PCF8591 I2C device. The problem we face now is to use a standard Xilinx
Part like XC2S50 and interface the I2C device 8591, and demonstrate both
ADC and DAC working. To do this we need the following:

1. Xilinx WebPack VHDL compiler.


2. TKBase Evaluation board with XC2S50 daughter board
3. LG320/LGLite Logic Analyzer and Pattern Generator
VHDL – I2C Controller

Implementation of I2C Master

We start the vhdl design by defining the I2C master entity on the TKBASE evaluation
board as shown below.

entity I2C_ADC is
Port ( Header1 : out std_logic_vector(7 downto 0);
Header2 : out std_logic_vector(7 downto 0);
Header3 : out std_logic_vector(7 downto 0);
Header4 : out std_logic_vector(7 downto 0);
Header5 : out std_logic_vector(7 downto 0);
Header6 : out std_logic_vector(7 downto 0);
Header7 : out std_logic_vector(7 downto 0);
pfc_adc : inout std_logic;
clk100k : in std_logic);
end I2C_ADC;

The pin clk100k is the system clock and all other I2C bus clocking would be derived
using this clock. The pfc_adc is the SDA port on the I2C bus. The SCL is a derived clock
from the clk100k and is just an output on Header4. The VHDL code explaing the above
is given below.

P1:process (clk100k)
begin
if( rising_edge(clk100k)) then
clkdiv <= clkdiv + 1;
i2c_clk1 <= clkdiv(3); -- the base clock
i2c_clk2 <= clkdiv(4); -- base SCL clock
statedsp <= clkdiv(9 downto 8); -- 7seg mux
clkkey <= clkdiv(10); -- i2c r/w loop
end if;
end process P1;

The signal clkkey is used to generate I2C timing loops. We start the I2C cycle when
clkkey goes high. A state counter with 255 states is designed using i2c_clk1;

P4:process(i2c_clk2)
begin
if( falling_edge(i2c_clk2) ) then

if(clkkey = '1') then


i2c_count <= i2c_count + 1; -- the I2C state information
else
i2c_count <= X"00";
end if;
end if;
end process P4;
I2C ADC Protocol

Once the state counter is designed we now have to start coding for I2C-ADC protocol.
We should know the device address, and signals to generate and its timing.

I2C Start

We define the first state 00 as the initialization state, wherein we load all required I2C
device information register like device address and device control. The next state 01 is
used to generate the I2C Start condition. First, a start condition issued which is a high
to low-transition on SDA while SCL is high — and has to appear on the bus . To
isolate the bus and to trigger on this event, we generate a hardware bit i2c_start. The bit
i2c_start will be used by Logic Analyzer to trigger and view the I2C start condition.

P7:process(i2c_clk1)
begin

-- latch the data to read or write


if( falling_edge(i2c_clk1) ) then

case i2c_count is

when X"00" =>


--initialize the shift register
i2c_devaddr <= X"97";

when X"01" =>


-- the start cycle
i2c_start <= '1';
-- create the condition of falling SDA
if(i2c_clk2 = '0') then
i2c_sda <= '1';
i2c_dir <= '1';
end if;

if(i2c_clk2 = '1') then


i2c_sda <= '0';
i2c_dir <= '1';
end if;
I2C Device Addressing – the write cycle

The states from 02 thru 09 defines generation of device address. The next 8 bits are
clocked into the PCF8591. The first seven bits (7 to 1) are the 7-bit slave address defined
by the manufacturer of the device, in our case 0x97. Because bit 0 dictates whether it is a
read or write command, we first have to write the control word,"1," for ADC read cycle.
To acknowledge this data, PCF8591 has to pull the SDA line low. Hence during the
address write cycle, the direction of SDA is output and during the acknowledge cycle the
direction is input. This direction can be viewed using the i2c_dir hardware bit. Note the
9th bit identifies the acknowledge cycle.

when X"02" | X"03" | X"04" | X"05" |


X"06" | X"07" | X"08" | X"09" =>

-- the address cycle


-- the regular shift cycle
i2c_areg <= '1';
if(i2c_clk2 = '0') then
i2c_dir <= '1';
i2c_sda <= i2c_devaddr(7);
i2c_devaddr(7 downto 0) <= i2c_devaddr(6 downto 0) & '0';
end if;

Handling I2C – acknowledge

The first state is generation of Start , the next 8 are for transmitting device address and
the next 10th state is the acknowledge cycle, wherein the device informs the master that it
has received the information correctly by pulling SDA line low. Hence during this cycle
we have to make the SDA as input and monitor this input using the hardware bit
.i2c_ackreg going high.

when X"0A" | X"13" =>


-- the ack cycle
i2c_ackreg <= '1';-- the ack cycle
i2c_dir <= '0';
Reading ADC result

An A/D conversion cycle is always started after sending a valid read mode address to a
PCF8591 device. This is what we did in previous states. Hence the next 8 states would be
the PCF8591 sending ADC data. We now have to shift in this serial data by creating a
shift clock named as i2c_adc_clk. This shift clock would latch the serial data and we can
then display this information(i2c_rdata) on a simple multiplexed 7 segment display. To
trigger the logic analyzer we create a hardware bit i2c_dreg.

-- Generating the serial shift clock


when X"0B" | X"0C" | X"0D" | X"0E" |
X"0F" | X"10" | X"11" | X"12" =>
-- the adc read reg cycle
-- the regular shift read cycle
i2c_dreg <= '1';
if(i2c_clk2 = '1') then
i2c_dir <= '0';
i2c_adc_clk <= '1';
end if;

-- Capturing serial data using adc_clk


P5:process(i2c_adc_clk)
begin
if(rising_edge(i2c_adc_clk) ) then
if(i2c_scl = '1') then
i2c_rdata(7 downto 0) <= i2c_rdata(6 downto 0) & i2c_dack;
end if;
end if;
end process P5;
Conclusion

The complete cycle for reading the ADC data and displaying them onto the 7 segment
display (20 bytes to transfer) takes about 7 milli-seconds and hence best seen using a real
time Logic analyzer like LG320/LGLite. These VHDL hardware triggers bits allow you
to isolate the particular bus traffic you’re interested in, and enables you to instantly see
the content of every message transmitted over the bus in your acquisition.

While there are many benefits in transitioning from parallel to serial buses in embedded
systems design, there are also a number of challenges the design engineer faces. With
traditional test and measurement tools like scope’s, it’s much more difficult to trigger on
the event you’re looking for, it can be nearly impossible to tell what information is
present by just looking at the analog signal and it’s an extremely time consuming and
error prone process to have to manually decode a long period of bus activity to diagnose
problems. The LG320/LGLite changes everything. With its powerful trigger, clocking,
and search capabilities today’s design engineers can solve embedded system design
issues with exceptional efficiency.

You might also like