CPLD 1.8V to 3.3V bidirectional SDA

N

nobody

Guest
I have a small design flaw with a new sensor, ICM20948, into a PI device. I need to make the SDA bidirectional and level shift SCL, int, and fsync. Voltage level on the sensor board is 1.8V the PI is 3.3V. I have CPLD hardware that I would like to use to make the bidirectional level shifted SDA as well as level shift the other three.

The VHDL behavior is as simple as:

begin

enable <= '1' when DIR = '1' else '0';
I2C(0) <= SCL;
I2C(1) <= SDA when enable = '0' else 'Z';
SDA <= I2C(1) when enable = '1' else 'Z';

end Behavioral;

I have used this before in another I2C without failure. The hardware seems to be performing the bidirectional communication, but all logic is a ~3.3V level.

The CPLD is a Xilinx XC2CA64 with the 1.8V I2C pins on 11 and 13 and the 3.3V I2C and ancillary pins on 15, 16 and 17. The UCF is as follows:

NET "I2C(0)" LOC = "11" ; #SCL1V8
NET "I2C(0)" IOSTANDARD = "LVCMOS18" ;
NET "I2C(1)" LOC = "13" ;
NET "I2C(1)" IOSTANDARD = "LVCMOS18" ; #SDA1V8

NET "SCL" LOC = "17" ; #PI side
NET "SCL" IOSTANDARD = "LVCMOS33" ; #
NET "SDA" LOC = "15" ; #PI side
NET "SDA" IOSTANDARD = "LVCMOS33" ; #
NET "DIR" LOC = "16" ; #PI side
NET "DIR" IOSTANDARD = "LVCMOS33" ; #
 
Having taken a closer look at the XAPP785 I have a hardware issue on my board. Both the VCCIO1, pins 58 and 38, are driven by 3.3V as well as VCCIO2, pins 98, and 88.
 
nobody <cydrollinger@gmail.com> wrote:
Having taken a closer look at the XAPP785 I have a hardware issue on my
board. Both the VCCIO1, pins 58 and 38, are driven by 3.3V as well as
VCCIO2, pins 98, and 88.

As a general rule, while you can (have to) set IO voltages in the FPGA
software you still have to wire the bank VCC pins to the right voltage rail.
I'm not aware of any FPGAs which can dynamically switch bank voltages.

Theo
 
On Tuesday, May 8, 2018 at 10:59:21 AM UTC-4, nobody wrote:
I have a small design flaw with a new sensor, ICM20948, into a PI device. I need to make the SDA bidirectional and level shift SCL, int, and fsync. Voltage level on the sensor board is 1.8V the PI is 3.3V. I have CPLD hardware that I would like to use to make the bidirectional level shifted SDA as well as level shift the other three.

The VHDL behavior is as simple as:

begin

enable <= '1' when DIR = '1' else '0';
I2C(0) <= SCL;
I2C(1) <= SDA when enable = '0' else 'Z';
SDA <= I2C(1) when enable = '1' else 'Z';

end Behavioral;

I have used this before in another I2C without failure. The hardware seems to be performing the bidirectional communication, but all logic is a ~3.3V level.

This is not a problem really. The data line should be open collector which is what I2C is intended to use. I believe SDA is the 3.3 volt I2C data line and I2C(1) is the 1.8 volt I2C line. Your code should be written as below.

enable <= '1' when DIR = '1' else '0';
-- This is redundant, unless you expect DIR to be some invalid state like 'Z', 'U', etc., it should be sufficient alone.

I2C(0) <= '0' when SCL = '0' else 'Z';
I2C(1) <= '0' when enable = '0' and SDA = '0' else 'Z';
SDA <= '0' when enable = '1' and I2C(1) = '0' else 'Z';

Now your outputs will *not* be driven high by the FPGA at any time other than possibly for a brief moment at a transition which can be good for speed. This will be a race condition so may not happen. If you want to force a delay to enable a drive to '1' on transitions of the data or clock line you can set timing constraints to assign a max delay from clock to output for the data and a minimum delay from clock to output for the enable signal. You will also need to bracket it the other way to prevent the drive time from being too long, so min/max each delay to workable times. I've never tried doing this, so it may not be as easy as it sounds. Better might be a differential time delay... ?

Rick C.
 
On 08/05/2018 15:59, nobody wrote:
I have a small design flaw with a new sensor, ICM20948, into a PI device. I need to make the SDA bidirectional and level shift SCL, int, and fsync. Voltage level on the sensor board is 1.8V the PI is 3.3V. I have CPLD hardware that I would like to use to make the bidirectional level shifted SDA as well as level shift the other three.

The VHDL behavior is as simple as:

begin

enable <= '1' when DIR = '1' else '0';
I2C(0) <= SCL;
I2C(1) <= SDA when enable = '0' else 'Z';
SDA <= I2C(1) when enable = '1' else 'Z';

end Behavioral;

I have used this before in another I2C without failure. The hardware seems to be performing the bidirectional communication, but all logic is a ~3.3V level.

The CPLD is a Xilinx XC2CA64 with the 1.8V I2C pins on 11 and 13 and the 3.3V I2C and ancillary pins on 15, 16 and 17. The UCF is as follows:

NET "I2C(0)" LOC = "11" ; #SCL1V8
NET "I2C(0)" IOSTANDARD = "LVCMOS18" ;
NET "I2C(1)" LOC = "13" ;
NET "I2C(1)" IOSTANDARD = "LVCMOS18" ; #SDA1V8

NET "SCL" LOC = "17" ; #PI side
NET "SCL" IOSTANDARD = "LVCMOS33" ; #
NET "SDA" LOC = "15" ; #PI side
NET "SDA" IOSTANDARD = "LVCMOS33" ; #
NET "DIR" LOC = "16" ; #PI side
NET "DIR" IOSTANDARD = "LVCMOS33" ; #

Level shifting bidirectional signals is not a trivial thing to do.

Agree with Rick's post where the output should either be pulled low of Hi-Z.

What is wrong with the classic way of doing it as per:
https://www.nxp.com/docs/en/application-note/AN10441.pdf

The SCL may also need to be truly bidirectional if there is any device
clock-stretching.



--
Mike Perkins
Video Solutions Ltd
www.videosolutions.ltd.uk
 
On Sunday, May 20, 2018 at 12:21:28 PM UTC-4, Mike Perkins wrote:
On 08/05/2018 15:59, nobody wrote:
I have a small design flaw with a new sensor, ICM20948, into a PI device. I need to make the SDA bidirectional and level shift SCL, int, and fsync.. Voltage level on the sensor board is 1.8V the PI is 3.3V. I have CPLD hardware that I would like to use to make the bidirectional level shifted SDA as well as level shift the other three.

The VHDL behavior is as simple as:

begin

enable <= '1' when DIR = '1' else '0';
I2C(0) <= SCL;
I2C(1) <= SDA when enable = '0' else 'Z';
SDA <= I2C(1) when enable = '1' else 'Z';

end Behavioral;

I have used this before in another I2C without failure. The hardware seems to be performing the bidirectional communication, but all logic is a ~3..3V level.

The CPLD is a Xilinx XC2CA64 with the 1.8V I2C pins on 11 and 13 and the 3.3V I2C and ancillary pins on 15, 16 and 17. The UCF is as follows:

NET "I2C(0)" LOC = "11" ; #SCL1V8
NET "I2C(0)" IOSTANDARD = "LVCMOS18" ;
NET "I2C(1)" LOC = "13" ;
NET "I2C(1)" IOSTANDARD = "LVCMOS18" ; #SDA1V8

NET "SCL" LOC = "17" ; #PI side
NET "SCL" IOSTANDARD = "LVCMOS33" ; #
NET "SDA" LOC = "15" ; #PI side
NET "SDA" IOSTANDARD = "LVCMOS33" ; #
NET "DIR" LOC = "16" ; #PI side
NET "DIR" IOSTANDARD = "LVCMOS33" ; #

Level shifting bidirectional signals is not a trivial thing to do.

Agree with Rick's post where the output should either be pulled low of Hi-Z.

What is wrong with the classic way of doing it as per:
https://www.nxp.com/docs/en/application-note/AN10441.pdf

The SCL may also need to be truly bidirectional if there is any device
clock-stretching.

Your point is well taken. There isn't much chance of clock stretching being used though as some number of I2C masters don't implement it. I would be more concerned with proper management of the direction control signal.

In the app note you point to they don't seem to compensate for the loss in voltage across the source to gate. So while there are pullups on both side, the active drive from either side won't drive the full range and in fact may be very cramped by the 1.8 volt power supply. If this bus isn't using the fast bit rate I guess that won't be a problem.

Rick C.
 
On 5/21/18 10:19 AM, gnuarm.deletethisbit@gmail.com wrote:
On Sunday, May 20, 2018 at 12:21:28 PM UTC-4, Mike Perkins wrote:
On 08/05/2018 15:59, nobody wrote:
I have a small design flaw with a new sensor, ICM20948, into a PI device. I need to make the SDA bidirectional and level shift SCL, int, and fsync. Voltage level on the sensor board is 1.8V the PI is 3.3V. I have CPLD hardware that I would like to use to make the bidirectional level shifted SDA as well as level shift the other three.

The VHDL behavior is as simple as:

begin

enable <= '1' when DIR = '1' else '0';
I2C(0) <= SCL;
I2C(1) <= SDA when enable = '0' else 'Z';
SDA <= I2C(1) when enable = '1' else 'Z';

end Behavioral;

I have used this before in another I2C without failure. The hardware seems to be performing the bidirectional communication, but all logic is a ~3.3V level.

The CPLD is a Xilinx XC2CA64 with the 1.8V I2C pins on 11 and 13 and the 3.3V I2C and ancillary pins on 15, 16 and 17. The UCF is as follows:

NET "I2C(0)" LOC = "11" ; #SCL1V8
NET "I2C(0)" IOSTANDARD = "LVCMOS18" ;
NET "I2C(1)" LOC = "13" ;
NET "I2C(1)" IOSTANDARD = "LVCMOS18" ; #SDA1V8

NET "SCL" LOC = "17" ; #PI side
NET "SCL" IOSTANDARD = "LVCMOS33" ; #
NET "SDA" LOC = "15" ; #PI side
NET "SDA" IOSTANDARD = "LVCMOS33" ; #
NET "DIR" LOC = "16" ; #PI side
NET "DIR" IOSTANDARD = "LVCMOS33" ; #

Level shifting bidirectional signals is not a trivial thing to do.

Agree with Rick's post where the output should either be pulled low of Hi-Z.

What is wrong with the classic way of doing it as per:
https://www.nxp.com/docs/en/application-note/AN10441.pdf

The SCL may also need to be truly bidirectional if there is any device
clock-stretching.

Your point is well taken. There isn't much chance of clock stretching being used though as some number of I2C masters don't implement it. I would be more concerned with proper management of the direction control signal.

In the app note you point to they don't seem to compensate for the loss in voltage across the source to gate. So while there are pullups on both side, the active drive from either side won't drive the full range and in fact may be very cramped by the 1.8 volt power supply. If this bus isn't using the fast bit rate I guess that won't be a problem.

Rick C.

'active drive'? I2C (at least at base speeds) is a purely pull up
protocal. The only time logic is supposed to actually drive signal high
is if you transition into 'High Speed' (above the 400KHz fast mode)
mode. The App note specifically says it is for full / fast ((not High
Speed), so the bus is designed to be just restive pulled up.
 
On Monday, May 21, 2018 at 10:21:21 PM UTC-4, Richard Damon wrote:
On 5/21/18 10:19 AM, gnuarm.deletethisbit@gmail.com wrote:
On Sunday, May 20, 2018 at 12:21:28 PM UTC-4, Mike Perkins wrote:
On 08/05/2018 15:59, nobody wrote:
I have a small design flaw with a new sensor, ICM20948, into a PI device. I need to make the SDA bidirectional and level shift SCL, int, and fsync. Voltage level on the sensor board is 1.8V the PI is 3.3V. I have CPLD hardware that I would like to use to make the bidirectional level shifted SDA as well as level shift the other three.

The VHDL behavior is as simple as:

begin

enable <= '1' when DIR = '1' else '0';
I2C(0) <= SCL;
I2C(1) <= SDA when enable = '0' else 'Z';
SDA <= I2C(1) when enable = '1' else 'Z';

end Behavioral;

I have used this before in another I2C without failure. The hardware seems to be performing the bidirectional communication, but all logic is a ~3.3V level.

The CPLD is a Xilinx XC2CA64 with the 1.8V I2C pins on 11 and 13 and the 3.3V I2C and ancillary pins on 15, 16 and 17. The UCF is as follows:

NET "I2C(0)" LOC = "11" ; #SCL1V8
NET "I2C(0)" IOSTANDARD = "LVCMOS18" ;
NET "I2C(1)" LOC = "13" ;
NET "I2C(1)" IOSTANDARD = "LVCMOS18" ; #SDA1V8

NET "SCL" LOC = "17" ; #PI side
NET "SCL" IOSTANDARD = "LVCMOS33" ; #
NET "SDA" LOC = "15" ; #PI side
NET "SDA" IOSTANDARD = "LVCMOS33" ; #
NET "DIR" LOC = "16" ; #PI side
NET "DIR" IOSTANDARD = "LVCMOS33" ; #

Level shifting bidirectional signals is not a trivial thing to do.

Agree with Rick's post where the output should either be pulled low of Hi-Z.

What is wrong with the classic way of doing it as per:
https://www.nxp.com/docs/en/application-note/AN10441.pdf

The SCL may also need to be truly bidirectional if there is any device
clock-stretching.

Your point is well taken. There isn't much chance of clock stretching being used though as some number of I2C masters don't implement it. I would be more concerned with proper management of the direction control signal.

In the app note you point to they don't seem to compensate for the loss in voltage across the source to gate. So while there are pullups on both side, the active drive from either side won't drive the full range and in fact may be very cramped by the 1.8 volt power supply. If this bus isn't using the fast bit rate I guess that won't be a problem.

Rick C.


'active drive'? I2C (at least at base speeds) is a purely pull up
protocal. The only time logic is supposed to actually drive signal high
is if you transition into 'High Speed' (above the 400KHz fast mode)
mode. The App note specifically says it is for full / fast ((not High
Speed), so the bus is designed to be just restive pulled up.

That's why I said if they weren't running fast it won't matter. I didn't memorize the names they use for the various modes, so "fast" was descriptive rather than nominal.

The real issue is using a device that will actually be turned on with only a 1.8 volt gate drive which will potentially be even less since the driving signal may not pull fully to ground.

I don't recall the details of the I2C interface timing, but it might be more realistic to implement a repeater that receives and retransmits the I2C signals rather than just level shifts. The devil is in the details so it is hard to say without at least simulating this circuit.

Rick Collins
 
On 21/05/2018 15:19, gnuarm.deletethisbit@gmail.com wrote:
On Sunday, May 20, 2018 at 12:21:28 PM UTC-4, Mike Perkins wrote:
On 08/05/2018 15:59, nobody wrote:
I have a small design flaw with a new sensor, ICM20948, into a PI
device. I need to make the SDA bidirectional and level shift SCL,
int, and fsync. Voltage level on the sensor board is 1.8V the PI
is 3.3V. I have CPLD hardware that I would like to use to make
the bidirectional level shifted SDA as well as level shift the
other three.

The VHDL behavior is as simple as:

begin

enable <= '1' when DIR = '1' else '0'; I2C(0) <= SCL; I2C(1) <=
SDA when enable = '0' else 'Z'; SDA <= I2C(1) when enable = '1'
else 'Z';

end Behavioral;

I have used this before in another I2C without failure. The
hardware seems to be performing the bidirectional communication,
but all logic is a ~3.3V level.

The CPLD is a Xilinx XC2CA64 with the 1.8V I2C pins on 11 and 13
and the 3.3V I2C and ancillary pins on 15, 16 and 17. The UCF is
as follows:

NET "I2C(0)" LOC = "11" ; #SCL1V8 NET "I2C(0)" IOSTANDARD =
"LVCMOS18" ; NET "I2C(1)" LOC = "13" ; NET "I2C(1)" IOSTANDARD =
"LVCMOS18" ; #SDA1V8

NET "SCL" LOC = "17" ; #PI side NET "SCL" IOSTANDARD =
"LVCMOS33" ; # NET "SDA" LOC = "15" ; #PI side NET "SDA"
IOSTANDARD = "LVCMOS33" ; # NET "DIR" LOC = "16" ; #PI
side NET "DIR" IOSTANDARD = "LVCMOS33" ; #

Level shifting bidirectional signals is not a trivial thing to do.

Agree with Rick's post where the output should either be pulled low
of Hi-Z.

What is wrong with the classic way of doing it as per:
https://www.nxp.com/docs/en/application-note/AN10441.pdf

The SCL may also need to be truly bidirectional if there is any
device clock-stretching.

Your point is well taken. There isn't much chance of clock
stretching being used though as some number of I2C masters don't
implement it.

Is it not the slave that holds the clock low, not the master?
https://www.i2c-bus.org/clock-stretching/

Not all devices do this.

--
Mike Perkins
Video Solutions Ltd
www.videosolutions.ltd.uk
 
On 5/22/18 3:48 AM, gnuarm.deletethisbit@gmail.com wrote:
On Monday, May 21, 2018 at 10:21:21 PM UTC-4, Richard Damon wrote:
On 5/21/18 10:19 AM, gnuarm.deletethisbit@gmail.com wrote:
On Sunday, May 20, 2018 at 12:21:28 PM UTC-4, Mike Perkins wrote:
On 08/05/2018 15:59, nobody wrote:
I have a small design flaw with a new sensor, ICM20948, into a PI device. I need to make the SDA bidirectional and level shift SCL, int, and fsync. Voltage level on the sensor board is 1.8V the PI is 3.3V. I have CPLD hardware that I would like to use to make the bidirectional level shifted SDA as well as level shift the other three.

The VHDL behavior is as simple as:

begin

enable <= '1' when DIR = '1' else '0';
I2C(0) <= SCL;
I2C(1) <= SDA when enable = '0' else 'Z';
SDA <= I2C(1) when enable = '1' else 'Z';

end Behavioral;

I have used this before in another I2C without failure. The hardware seems to be performing the bidirectional communication, but all logic is a ~3.3V level.

The CPLD is a Xilinx XC2CA64 with the 1.8V I2C pins on 11 and 13 and the 3.3V I2C and ancillary pins on 15, 16 and 17. The UCF is as follows:

NET "I2C(0)" LOC = "11" ; #SCL1V8
NET "I2C(0)" IOSTANDARD = "LVCMOS18" ;
NET "I2C(1)" LOC = "13" ;
NET "I2C(1)" IOSTANDARD = "LVCMOS18" ; #SDA1V8

NET "SCL" LOC = "17" ; #PI side
NET "SCL" IOSTANDARD = "LVCMOS33" ; #
NET "SDA" LOC = "15" ; #PI side
NET "SDA" IOSTANDARD = "LVCMOS33" ; #
NET "DIR" LOC = "16" ; #PI side
NET "DIR" IOSTANDARD = "LVCMOS33" ; #

Level shifting bidirectional signals is not a trivial thing to do.

Agree with Rick's post where the output should either be pulled low of Hi-Z.

What is wrong with the classic way of doing it as per:
https://www.nxp.com/docs/en/application-note/AN10441.pdf

The SCL may also need to be truly bidirectional if there is any device
clock-stretching.

Your point is well taken. There isn't much chance of clock stretching being used though as some number of I2C masters don't implement it. I would be more concerned with proper management of the direction control signal.

In the app note you point to they don't seem to compensate for the loss in voltage across the source to gate. So while there are pullups on both side, the active drive from either side won't drive the full range and in fact may be very cramped by the 1.8 volt power supply. If this bus isn't using the fast bit rate I guess that won't be a problem.

Rick C.


'active drive'? I2C (at least at base speeds) is a purely pull up
protocal. The only time logic is supposed to actually drive signal high
is if you transition into 'High Speed' (above the 400KHz fast mode)
mode. The App note specifically says it is for full / fast ((not High
Speed), so the bus is designed to be just restive pulled up.

That's why I said if they weren't running fast it won't matter. I didn't memorize the names they use for the various modes, so "fast" was descriptive rather than nominal.

The real issue is using a device that will actually be turned on with only a 1.8 volt gate drive which will potentially be even less since the driving signal may not pull fully to ground.

I don't recall the details of the I2C interface timing, but it might be more realistic to implement a repeater that receives and retransmits the I2C signals rather than just level shifts. The devil is in the details so it is hard to say without at least simulating this circuit.

Rick Collins

The big point is that the High Speed I2C bus is very much a different
beast than the Full / Fast speed bus, with very different requirements.
The notes on implementing High Speed mode often talk about the need to
isolate High Speed devices from 'Normal' speed devices because they
might not tolerate the bus suddenly running faster than they were
designed for, even if they aren't being talked to.

As I mentioned, the App Note specifically limited its applicability to
the modes with the passive pull ups.

Also, High Speed I2C devices are fairly rare.

Geting Fets that turn on at 1-1.2 volts isn't that hard (and the current
needed isn't that high which makes the lower threshold easier to implement).

If by an I2C Repeater, you mean something that receives an I2C message
on one side and then send it to the other, this is basically impossible
if you want it to be transparent due to acks and reads. You basically
need to be re transmitting bit by bit.

There are devices that are a bit more complicated that can do this task,
and even handle High Speed, which operate by assuming that the signal
driving to them drive low with better than required margins, and then
the repeater drives a weaker low so it can detect which sides are being
driven (something like if Ain < 0.3V then pull Bout to 0.5V) with the
disadvantage that you can't repeat a repeated signal.
 
On Tuesday, May 22, 2018 at 10:26:26 PM UTC-4, Mike Perkins wrote:
On 21/05/2018 15:19, gnuarm.deletethisbit@gmail.com wrote:
On Sunday, May 20, 2018 at 12:21:28 PM UTC-4, Mike Perkins wrote:
On 08/05/2018 15:59, nobody wrote:
I have a small design flaw with a new sensor, ICM20948, into a PI
device. I need to make the SDA bidirectional and level shift SCL,
int, and fsync. Voltage level on the sensor board is 1.8V the PI
is 3.3V. I have CPLD hardware that I would like to use to make
the bidirectional level shifted SDA as well as level shift the
other three.

The VHDL behavior is as simple as:

begin

enable <= '1' when DIR = '1' else '0'; I2C(0) <= SCL; I2C(1) <=
SDA when enable = '0' else 'Z'; SDA <= I2C(1) when enable = '1'
else 'Z';

end Behavioral;

I have used this before in another I2C without failure. The
hardware seems to be performing the bidirectional communication,
but all logic is a ~3.3V level.

The CPLD is a Xilinx XC2CA64 with the 1.8V I2C pins on 11 and 13
and the 3.3V I2C and ancillary pins on 15, 16 and 17. The UCF is
as follows:

NET "I2C(0)" LOC = "11" ; #SCL1V8 NET "I2C(0)" IOSTANDARD =
"LVCMOS18" ; NET "I2C(1)" LOC = "13" ; NET "I2C(1)" IOSTANDARD =
"LVCMOS18" ; #SDA1V8

NET "SCL" LOC = "17" ; #PI side NET "SCL" IOSTANDARD =
"LVCMOS33" ; # NET "SDA" LOC = "15" ; #PI side NET "SDA"
IOSTANDARD = "LVCMOS33" ; # NET "DIR" LOC = "16" ; #PI
side NET "DIR" IOSTANDARD = "LVCMOS33" ; #

Level shifting bidirectional signals is not a trivial thing to do.

Agree with Rick's post where the output should either be pulled low
of Hi-Z.

What is wrong with the classic way of doing it as per:
https://www.nxp.com/docs/en/application-note/AN10441.pdf

The SCL may also need to be truly bidirectional if there is any
device clock-stretching.

Your point is well taken. There isn't much chance of clock
stretching being used though as some number of I2C masters don't
implement it.

Is it not the slave that holds the clock low, not the master?
https://www.i2c-bus.org/clock-stretching/

Not all devices do this.

Yes, the slave holds the clock low, but the master has to be paying attention. If not the network screws up.

Rick C.
 

Welcome to EDABoard.com

Sponsor

Back
Top