From: Brad Smallridge on

Well, I have a requirement for I2C or IIC communications to some video
decoder chips on a new board I am designing. I would rather had not use
this bus, but it seems that the Philips people have started a defacto
standard in the video decoder world.

So my questions are, what IO standard is best to use on a Virtex4, and what
pullups should I use? The TI part I picked, the TVP5150AM1PBSR, has 3V3 volt
digital connections. There are also two 1.8V requirements.

And are there any free examples of VHDL that will drive slave devices. I
have found an ap note Xapp172 Design of Video Capture but I can't find the
source code downloads.

I see on the Xilinx's Video Daughter Board (not V4) for the ML40x boards
(are V4), that the SCL and SDA seem to be driven by a 3.3V bank7 and are
pulled up with what I think are 4K. Weird BOM.

Then I will have the issue of running multiple devices, more than are
addressable by the hardwire addresing options. My first thought is to run
multiple IOs from the V4. Is this the best solution?

TMA Thanks Much in Advance,

Brad Smallridge
Ai Vision dot com








From: Falk Brunner on
Brad Smallridge schrieb:

> Well, I have a requirement for I2C or IIC communications to some video
> decoder chips on a new board I am designing. I would rather had not use
> this bus, but it seems that the Philips people have started a defacto
> standard in the video decoder world.
>
> So my questions are, what IO standard is best to use on a Virtex4, and what
> pullups should I use? The TI part I picked, the TVP5150AM1PBSR, has 3V3 volt

3.3 V LVCMOS or LVTTL is fine.
Pull up of 4.7k to 10k is fine.

> digital connections. There are also two 1.8V requirements.

What kind of 1.8V requirements? For I2C communication?

> And are there any free examples of VHDL that will drive slave devices. I

There are some app notes that describe a I2C master/slave block,
including VHDL source. I dont have the number handy.

> I see on the Xilinx's Video Daughter Board (not V4) for the ML40x boards
> (are V4), that the SCL and SDA seem to be driven by a 3.3V bank7 and are
> pulled up with what I think are 4K. Weird BOM.

Just fine.

> Then I will have the issue of running multiple devices, more than are
> addressable by the hardwire addresing options. My first thought is to run
> multiple IOs from the V4. Is this the best solution?

This is one solution. In similar situation were multiple devices with
the same I2C address had to be connected to a I2C bus, we used I2C
switches/MUXes. Philips offers them.

Regards
Falk
From: Antti on
the easiest way may be adding a picoblaze to handle the i2
initialization

http://www.dulseelectronics.com/download/download_index.html

there are some examples,

I am using this approuch to initialize chrontel DVI chips and Agilent
smart cameras
on an Virtex-4 board

the DVI application (a pong demo) will soon be added to reference
designs available
online http://hydraxc.xilant.com

basically you use the picoblaze as black box and connect to i2c

the code that initializes ch7301 then is coded as picoblaze assembler,
like her

; Enable DVI power
LOAD sA, 49
LOAD sB, C0
CALL I2C_DVI_WRITE

Antti Lukats

From: Felix Bertram on
Hi Brad,

> And are there any free examples of VHDL that will drive slave devices. I
> have found an ap note Xapp172 Design of Video Capture but I can't find the
> source code downloads.

I have pasted some code below, hope this helps. We have used this code
to control audio volumes of Crystal DACs. The module takes volume data
from the outside world and sends them to the DAC via I2C. Should be easy
to adapt.

I believe this is way easier than using PicoBlaze for the task.

In case you need the file (due to line break problems, whatever), drop
me a line.


Best regards, Felix

--
Dipl.-Ing. Felix Bertram
http://www.bertram-family.com/felix


--------------------------------------------------------------------------------
-- File: i2c.vhd
-- Description: Simple I2C controller.
-- History: Felix Bertram, 2002jan11, Created.
--------------------------------------------------------------------------------

library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity ValI2C is
port (
-- clocks & reset
clk24: in std_logic;
reset: in std_logic;
-- dynamic data from external units (token wrd)
val: in std_logic_vector(7 downto 0); -- value
idx: out std_logic_vector(7 downto 0); -- index
-- i2c bus
sda: out std_logic;
scl: out std_logic
);
end ValI2C;

--------------------------------------------------------------------------------
architecture bhv of ValI2C is
------------------------------------
-- basic structure
-- note: data field is used for constants or value-indices
type i2cE is (start, stop, const, wrd);
type i2cT is record
tag: i2cE;
data: std_logic_vector(7 downto 0);
end record;

------------------------------------
-- Crystal CS43L43 control sequence
-- i2c start condition
-- i2c address= 001000, R/nW= 0
-- memory address pointer
-- volume data
-- i2c stop condition
type seqT is array(0 to 9) of i2cT;
constant seq: seqT:= (
(start, x"00"),
(const, "0010000" & '0'),
(const, x"04"), -- 04h Channel A Digital Volume Control
(wrd, x"00"),
(stop, x"00"),
--
(start, x"00"),
(const, "0010000" & '0'),
(const, x"05"), -- 05h Channel B Digital Volume Control
(wrd, x"00"),
(stop, x"00")
);

------------------------------------
-- clock divider and sequencing
signal idxSeq: integer range seqT'low to seqT'high;
signal idxBit: unsigned(3 downto 0);
signal idxCyc: unsigned(1 downto 0);
signal clkdiv: unsigned(8 downto 0);
signal clkp1a, clkp1b: std_logic;
signal clken: std_logic;
------------------------------------
-- transmit data
signal txd: std_logic_vector(8 downto 0);
constant txdstart: std_logic_vector(8 downto 0):= "111000000"; -- I2C
start pattern
constant txdstop: std_logic_vector(8 downto 0):= "000000111"; -- I2C
stop pattern
begin

-- ic2 clock divider, approx 100kHz
process(clk24, reset)
begin
if reset= '1' then
clkdiv<= (others=> '0');
clkp1b<= '0';
elsif rising_edge(clk24) then
clkdiv<= clkdiv + 1;
clkp1b<= clkp1a;
end if;
end process;
clkp1a<= clkdiv(clkdiv'left);
clken <= clkp1a and not clkp1b;

----------------------------------------------------------------------------
-- create i2c timing
----------------------------------------------------------------------------

-- i2c clock cycle counter: 4 cycles per bit
-- |___ _______________ ________
-- sda |___X_______________X________
-- | _______ ____
-- scl |_______/ \_______/
-- |
-- phase | 0 / 1 / 2 / 3 / 0 / 1 / 2 / ...
process(clk24, reset)
begin
if reset= '1' then
idxCyc<= "00";
elsif rising_edge(clk24) then
if clken= '1' then
if idxCyc/= "11" then idxCyc<= idxCyc + 1;
else idxCyc<= "00"; end if;
end if;
end if;
end process;

-- i2c bit counter: 9 bits per token (8 data + 1 ack)
process(clk24, reset)
begin
if reset= '1' then
idxBit<= x"8";
elsif rising_edge(clk24) then
if clken= '1' and idxCyc= 3 then
if idxBit/= x"8" then idxBit<= idxBit + 1;
else idxBit<= x"0"; end if;
end if;
end if;
end process;

-- i2c sequence counter: see seqT definition
process(clk24, reset)
begin
if reset= '1' then
idxSeq<= seqT'high;
elsif rising_edge(clk24) then
if clken= '1' and idxCyc= 3 and idxBit= 8 then
if idxSeq/= seqT'high then idxSeq<= idxSeq + 1;
else idxSeq<= 0; end if;
end if;
end if;
end process;

----------------------------------------------------------------------------
-- create i2c clock and data
----------------------------------------------------------------------------

-- create data address
idx<= seq(idxSeq).data;

-- select byte to transfer, send out bits msb first
process(clk24, reset)
begin
if reset= '1' then
txd<= (others=> '1');
elsif rising_edge(clk24) then
if clken= '1' and idxCyc= 0 then
if idxBit= 0 then
case seq(idxSeq).tag is
when start => txd<= txdstart;
when stop => txd<= txdstop;
when const => txd<= seq(idxSeq).data & '1'; -- const + ack
when wrd => txd<= val & '1'; -- value + ack
end case;
else
txd<= txd(7 downto 0) & '-';
end if;
end if;
end if;
end process;
sda<= txd(8);

-- select clock to transfer, send out clock
process(clk24, reset)
begin
if reset= '1' then
scl<= '1';
elsif rising_edge(clk24) then
if clken= '1' then
case seq(idxSeq).tag is
when const | wrd=> scl<= idxCyc(0) xor idxCyc(1);
when start=> scl<= not(idxBit(3) or idxBit(2));
when stop=> scl<= idxBit(3) or idxBit(2);
end case;
end if;
end if;
end process;

end bhv;

--------------------------------------------------------------------------------
-- end of file
From: Ray Andraka on

The I2C interface is pretty simple for just talking to a slave. I
personally find it much easier to just infer a shift register and small
state machine rather than putting in pico or microblaze and all the
baggage that goes with it.