cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 
Visitor
Visitor
1,538 Views
Registered: ‎05-24-2017

Propagation of high impedance signals through I2C connexions

Jump to solution

Hello everyone,

 

I am working on a design implemented on a Nexys4ddr (Artix-7 XC7A100T), using Vivado 2015.4. This design includes a microprocessor and peripherals, both using a non-standard I2C interface with 4 unidirectional ports instead of 2 bidirectional ports. The interface of my top module allows the connexion of external I2C peripherals with standard interface (with bidirectional ports). The conversion between inout ports and input/outputs is realized using a "tri-state-like" design. The attached schematic shows what is done in the RTL description.

The I2C Ext periph is outside of the FPGA, the rest is inside. I have two such structures, one for an external slave, the other for an external slave. In the RTL code (System Verilog) I do something like this :

 

  assign io_scl_s = (w_scl_s == 1'b1) ? 1'bz : 1'b0;
  assign io_sda_s = (w_sda_s == 1'b1) ? 1'bz : 1'b0;
  assign io_scl_m = (w_scl_m == 1'b1) ? 1'bz : 1'b0;
  assign io_sda_m = (w_sda_m == 1'b1) ? 1'bz : 1'b0;

 

The instanciation of my microprocessor (which includes the i2C Master module) is like this :

 

 

mcu MCU (    
    ...
    // I2C Slave toward an external master
    .i_i2cs_scl         (io_scl_s),
    .i_i2cs_sda         (io_sda_s),
    .o_i2cs_scl         (w_scl_s),
    .o_i2cs_sda         (w_sda_s),
    // I2C Master toward an external slave
    .i_i2cm_scl         (io_scl_m),
    .i_i2cm_sda         (io_sda_m),
    .o_i2cm_scl         (w_scl_m),
    .o_i2cm_sda         (w_sda_m),
    ...
);

 

 

In simulation i realized i have a lot of signal being on 'hZ' value, which i don't like since it spawns 'hX' values on the outputs of logic gates. I tried to force a value on them in my testbench using a process like this one :

 

 

process_comb
begin
    if(rw_io_scl_m_w === 1'bz || rw_io_scl_m_w === 1'bx) begin
      rw_io_scl_m <= 1'b1;
    end

    if(rw_io_sda_m_w === 1'bz || rw_io_sda_m_w === 1'bx) begin
      rw_io_sda_m <= 1'b1;
    end

    if(rw_io_scl_s_w === 1'bz || rw_io_scl_s_w === 1'bx) begin
      rw_io_scl_s <= 1'b1;
    end

    if(rw_io_sda_s_w === 1'bz || rw_io_sda_s_w === 1'bx) begin
      rw_io_sda_s <= 1'b1;
    end
end 

assign rw_io_scl_s_w = rw_io_scl_s; 
assign rw_io_sda_s_w = rw_io_sda_s; 
assign rw_io_scl_m_w = rw_io_scl_m; 
assign rw_io_sda_m_w = rw_io_sda_m;

 

But this seems to only have half efficiency, since i do not have 'hZ' values anymore, but there are a lot of 'hX' on the 4 inout ports, as well as on the 'i_sda_m' port (which results from an AND operation with a 'hX' from 'io_sda_s').

Weird thing is that the rising edges of the signals are ok, but the rest is 'hX'. Thus i tried to clock the process with an high speed clock to be sure it is activated often enough, but this doesn't seem to help.

My theory is that when i read in my testbench an 'hX' or an 'hZ' from the design and that i force the '1'b1' value on it, since there is still 'hX' or 'hZ' on it  the simulation tool gives me an 'hX' cause it can't decide the value. If this is indeed the case, then i'm screwed.

 

So I would like to know if you have any advices that could help me solve this situation.

tristate.png
0 Kudos
Reply
1 Solution

Accepted Solutions
Professor
Professor
1,605 Views
Registered: ‎08-14-2007

The simple solution is to "pull up" the open-drain I/O signals.  In Verilog the built-in pullup function does this.  So for each I/O signal (bi-directional I2C pins of the FPGA) you implement a pullup in the test bench like

 

pullup (io_scl_s);

pullup (io_sda_s);

 

etc.

 

Then instead of Hi-Z, these pins take a weak '1' when not driven.  This emulates the actual board hardware which requires an actual resistor pulling up each of the I2C signals.

-- Gabor

View solution in original post

3 Replies
Professor
Professor
1,606 Views
Registered: ‎08-14-2007

The simple solution is to "pull up" the open-drain I/O signals.  In Verilog the built-in pullup function does this.  So for each I/O signal (bi-directional I2C pins of the FPGA) you implement a pullup in the test bench like

 

pullup (io_scl_s);

pullup (io_sda_s);

 

etc.

 

Then instead of Hi-Z, these pins take a weak '1' when not driven.  This emulates the actual board hardware which requires an actual resistor pulling up each of the I2C signals.

-- Gabor

View solution in original post

Scholar
Scholar
1,502 Views
Registered: ‎04-13-2015

@valten

 

I agree with @gszakacs and would like to add to not forget to also add external pull-ups on both lines.

All I2C devices are open drain.

0 Kudos
Reply
Visitor
Visitor
1,488 Views
Registered: ‎05-24-2017

@gszakacs, @ericv

 

Thank you a lot for your answers, it seems like this solved my problem. In Modelsim the values are displayed on dotted lines for the io on which i applied the pullup primitive, which means it is assigned to a weak '1' if i understood correctly.

Most important point is that there is no more 'X' or 'Z' in my design, since i guess the weak '1' got "absorbed" when it went through a logic gate (i have AND gates in which these signals go through).

I managed to have almost the same behaviour by doing this :

 

always_comb
begin
    if(rw_io_scl_m_w === 1'bz) begin
      rw_io_scl_m <= 1'b1;
    end
    else begin
      rw_io_scl_m <= 1'bz;
    end

    if(rw_io_sda_m_w === 1'bz) begin
      rw_io_sda_m <= 1'b1;
    end
    else begin
      rw_io_sda_m <= 1'bz;
    end

    if(rw_io_scl_s_w === 1'bz) begin
      rw_io_scl_s <= 1'b1;
    end
    else begin
      rw_io_scl_s <= 1'bz;
    end

    if(rw_io_sda_s_w === 1'bz) begin
      rw_io_sda_s <= 1'b1;
    end
    else begin
      rw_io_sda_s <= 1'bz;
    end    
end

In this case the 'X' and 'Z' values were still present in the design but only for infinitesimal periods of time and only on vertical edges (corresponding to the delay during which the triggering condition of the process is enabled and the moment where the assignment to '1' operates i suppose).

 

Thank you again for your help, and have a nice day !

0 Kudos
Reply