I2C bus multiplexing inside CPLD

T

Thomas

Guest
Hi all,

I need to design (VHDL) a I2C bus multiplexer to control 4 clock I2C
slave devices that have the same slave address. My CPLD receives an on-
board I2C bus and needs to route it to 4 I2C devices thru an I2C mux
depending on the slave that i need to configure. No matter what I've
tryed, it doesn't work....

Any help/idea?

Thank you.

My design looklike:

entity I2c_Bus_Mux is
port( onboard_i2c_SCL : inout std_logic;
onboard_i2c_SDA : inout std_logic;
control_vector : in std_logic_vector(1 downto 0);
Slave0_SCL : inout std_logic;
Slave0_SDA : inout std_logic;
Slave1_SCL : inout std_logic;
Slave2_SDA : inout std_logic
---------------------etc-------------------);
end I2c_Bus_Mux;


process (----sensitivity list containing all involved signals)
begin
case control_vector is
when "00" =>
Slave0_SCL <= onboard_i2c_SCL ;
Slave0_SDA <= onboard_i2c_SDA;
onboard_i2c_SCL <= Slave0_SCL;
onboard_i2c_SDA <= Slave0_SDA;
when "01" =>
.......etc.....
 
On May 5, 12:01 am, "David Spencer" <davidmspen...@verizon.net> wrote:
"Thomas" <thomas....@gmail.com> wrote in message

news:5bde9bf2-ff64-4ca3-9d23-0fb2d85724e0@z72g2000hsb.googlegroups.com...



Hi all,

I need to design (VHDL) a I2C bus multiplexer to control 4 clock I2C
slave devices that have the same slave address. My CPLD receives an on-
board I2C bus and needs to route it to 4 I2C devices thru an I2C mux
depending on the slave that i need to configure. No matter what I've
tryed, it doesn't work....

Any help/idea?

Thank you.

My design looklike:

entity I2c_Bus_Mux is
port( onboard_i2c_SCL : inout std_logic;
onboard_i2c_SDA : inout std_logic;
control_vector : in std_logic_vector(1 downto 0);
Slave0_SCL : inout std_logic;
Slave0_SDA : inout std_logic;
Slave1_SCL : inout std_logic;
Slave2_SDA : inout std_logic
---------------------etc-------------------);
end I2c_Bus_Mux;

process (----sensitivity list containing all involved signals)
begin
case control_vector is
when "00" =
Slave0_SCL <= onboard_i2c_SCL ;
Slave0_SDA <= onboard_i2c_SDA;
onboard_i2c_SCL <= Slave0_SCL;
onboard_i2c_SDA <= Slave0_SDA;
when "01" =
.......etc.....

The problem is that I2C signals (SCL and SDA) are bidirectional, which makes
any form of I2C repeater/switch within an FPGA very hard to implement.
Assuming that you only have a single I2C master then you don't need to worry
about arbitration and you may be able to make it work with some careful
thinking, but it is non-trivial.

An easier solution is to implement an I2C device within your FPGA to act as
a control register for an external analog mux (Quickswitch type thing).
Alternative, just buy an I2C mux from NXP (Philips as was), which will do
the job for you.
Hi,
I agree with you but it's too late for us, the PCB is made and I have
to find a solution for that

Thanks

Thomas
 
On May 5, 12:27 pm, "Brad Smallridge" <bradsmallri...@dslextreme.com>
wrote:
You should be able switch your signals, if you can
get at the IOs before they are combined into inouts.
Can you do that? Or is there some sort of proprietary
code problem?

What tools are you using and what is your target CPLD?

Brad Smallridge
AiVision

Well to Brad,

Its Altear MAX II CPLD and I am using Quartus II 7.2sp3 tool.
I've discussed this morning with some senors at work and they seems to
say the same thing as David is saying here. But, giving the situation,
I am working on it trying to find some work around. It could be not
realy nice design but if it works we will be happy here.
So any other suggestions are more then welcome. I am sure that I am
not the first person that had this issue.

Thoms
 
Thomas a écrit :

Its Altear MAX II CPLD and I am using Quartus II 7.2sp3 tool.
I've discussed this morning with some senors at work and they seems to
say the same thing as David is saying here. But, giving the situation,
I am working on it trying to find some work around. It could be not
realy nice design but if it works we will be happy here.
So any other suggestions are more then welcome. I am sure that I am
not the first person that had this issue.

Hello
I think I have found a way.
As David Spencer explained you need to know which side is driving the
bus low. Your mux must therefore never be able to drive both sides low
at the same time otherwise you're deadlocked.

The basic element is this :

entity i2c_mux_elem is
port (
pad : inout std_logic;
input : out std_logic;
output : in std_logic);
end i2c_mux_elem;

architecture rtl of i2c_mux_elem is
signal i_in : std_logic;

begin -- rtl

i_in <= to_x01(pad);
pad <= '0' when output = '0' else 'Z';
input <= i_in or not output; -- Mask i_in when driving the pad low

end rtl;

Now all you need to do is connect 5 of these elements together through a
standard mux
The tool will complain about combinatorial loops but that shouldn't be a
problem.

Anyone please comment if you see problems I have overlooked :)

Nicolas
 
On May 6, 3:51 pm, Nicolas Matringe <nicolas.matri...@fre.fre> wrote:
Thomas a écrit :

Its Altear MAX II CPLD and I am using Quartus II 7.2sp3 tool.
I've discussed this morning with some senors at work and they seems to
say the same thing as David is saying here. But, giving the situation,
I am working on it trying to find some work around. It could be not
realy nice design but if it works we will be happy here.
So any other suggestions are more then welcome. I am sure that I am
not the first person that had this issue.

Hello
I think I have found a way.
As David Spencer explained you need to know which side is driving the
bus low. Your mux must therefore never be able to drive both sides low
at the same time otherwise you're deadlocked.

The basic element is this :

entity i2c_mux_elem is
port (
pad : inout std_logic;
input : out std_logic;
output : in std_logic);
end i2c_mux_elem;

architecture rtl of i2c_mux_elem is
signal i_in : std_logic;

begin -- rtl

i_in <= to_x01(pad);
pad <= '0' when output = '0' else 'Z';
input <= i_in or not output; -- Mask i_in when driving the pad low

end rtl;

Now all you need to do is connect 5 of these elements together through a
standard mux
The tool will complain about combinatorial loops but that shouldn't be a
problem.

Anyone please comment if you see problems I have overlooked :)

Nicolas
Nicolas,

It's not easy as that. You risk to latch-up....

Finaly I've found a way around it by adding a slightly modified slave
that will listen on the same slave address that the reel one would but
it will not send a data, just listen to the bus. It will act as a sort
of controller/arbiter by controlling the tri-state buffers. The idea
is to have an I2C controller that listen to the bus, knows ho needs to
talk and gives it the access. It's tweaky but works fin for us.
Lesson learned here: never try to do this in FPGA/CPLD, instead add
external analog Mux.

Thank you all for participating in this post

Thomas.
 
Thomas a écrit :
On May 6, 3:51 pm, Nicolas Matringe <nicolas.matri...@fre.fre> wrote:

entity i2c_mux_elem is
port (
pad : inout std_logic;
input : out std_logic;
output : in std_logic);
end i2c_mux_elem;

architecture rtl of i2c_mux_elem is
signal i_in : std_logic;

begin -- rtl

i_in <= to_x01(pad);
pad <= '0' when output = '0' else 'Z';
input <= i_in or not output; -- Mask i_in when driving the pad low

end rtl;

It's not easy as that. You risk to latch-up....
I've looked at the problem in every posible direction I could think of
and still fail to see how this can latch-up.

Nicolas
 

Welcome to EDABoard.com

Sponsor

Back
Top