CPLD 1.8V to 3.3V bidirectional SDA

Started by nobody May 8, 2018
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 devic=
e. 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 har= dware that I would like to use to make the bidirectional level shifted SDA = as well as level shift the other three.
> >=20 > > The VHDL behavior is as simple as: > >=20 > > begin > >=20 > > enable <=3D '1' when DIR =3D '1' else '0'; > > I2C(0) <=3D SCL; > > I2C(1) <=3D SDA when enable =3D '0' else 'Z'; > > SDA <=3D I2C(1) when enable =3D '1' else 'Z'; > >=20 > > end Behavioral; > >=20 > > I have used this before in another I2C without failure. The hardware se=
ems to be performing the bidirectional communication, but all logic is a ~3= .3V level.
> >=20 > > The CPLD is a Xilinx XC2CA64 with the 1.8V I2C pins on 11 and 13 and th=
e 3.3V I2C and ancillary pins on 15, 16 and 17. The UCF is as follows:
> >=20 > > NET "I2C(0)" LOC =3D "11" ; #SCL1V8 > > NET "I2C(0)" IOSTANDARD =3D "LVCMOS18" ; > > NET "I2C(1)" LOC =3D "13" ; > > NET "I2C(1)" IOSTANDARD =3D "LVCMOS18" ; #SDA1V8 > >=20 > > NET "SCL" LOC =3D "17" ; #PI side > > NET "SCL" IOSTANDARD =3D "LVCMOS33" ; # > > NET "SDA" LOC =3D "15" ; #PI side > > NET "SDA" IOSTANDARD =3D "LVCMOS33" ; # > > NET "DIR" LOC =3D "16" ; #PI side > > NET "DIR" IOSTANDARD =3D "LVCMOS33" ; # >=20 > Level shifting bidirectional signals is not a trivial thing to do. >=20 > Agree with Rick's post where the output should either be pulled low of Hi=
-Z.
>=20 > What is wrong with the classic way of doing it as per: > https://www.nxp.com/docs/en/application-note/AN10441.pdf >=20 > The SCL may also need to be truly bidirectional if there is any device=20 > clock-stretching.
Your point is well taken. There isn't much chance of clock stretching bein= g 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. =20 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.=20 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.