I2C bus multiplexing inside CPLD

Discussion in 'VHDL' started by Thomas, May 4, 2008.

  1. Thomas

    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.....
     
    Thomas, May 4, 2008
    #1
    1. Advertisements

  2. 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.
     
    David Spencer, May 5, 2008
    #2
    1. Advertisements

  3. Thomas

    Thomas Guest

    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
     
    Thomas, May 5, 2008
    #3
  4. 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
     
    Brad Smallridge, May 5, 2008
    #4
  5. The problem is that I2C signals are open-drain and inherently bidirectional.
    Any sort of I2C buffering or switching requires a low-level on either side
    to be propagated to the other side. This is virtually impossible to do in a
    100% digital device since either or both sides can pull the signal low at
    any time.
     
    David Spencer, May 5, 2008
    #5
  6. Thomas

    Thomas Guest


    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, May 5, 2008
    #6
  7. The fundamental problem with bridging I2C is its inherent bidirectional
    nature. Essentially, you are connecting side A to side B and if either side
    pulls the signal low you need to repeat that low on the other side. However,
    you then need to make sure you don't try to repeat the destination low (that
    you are driving) on the source side otherwise you just latch up. Custom I2C
    repeaters and muxes tend to use a low value series resistor and measure the
    voltage drop across that to determine which side is the driving side. Of
    course, you can't do this in an FPGA.

    One way that may work is to have a state machine for each signal that keeps
    track of which side is driving the signal low. In other words, when you
    detect one side driving low, you remember which side it is and enter a state
    that drives the other side low. When the source side stops driving you
    release the other side. You will almost certainly need some form of delay to
    allow the signal time to go high again otherwise you might detect a low on
    the destination side immediately after you stop driving it.
     
    David Spencer, May 6, 2008
    #7
  8. Its Altear MAX II CPLD and I am using Quartus II 7.2sp3 tool.
    So, you don't have the code to the I2C module?
     
    Brad Smallridge, May 6, 2008
    #8
  9. Thomas a écrit :

    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 Matringe, May 6, 2008
    #9
  10. Thomas

    Thomas Guest

    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, May 6, 2008
    #10
  11. Thomas a écrit :
    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
     
    Nicolas Matringe, May 7, 2008
    #11
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.