soc/cores/bitbang/I2C: use Tristate on SDL/SDA and only drive low (rely on I2C Pull-Ups for high).

This commit is contained in:
Florent Kermarrec 2020-11-10 09:46:43 +01:00
parent 221ea4c31a
commit ce9f24748f
1 changed files with 16 additions and 13 deletions

View File

@ -16,8 +16,11 @@ class I2CMaster(Module, AutoCSR):
Provides the minimal hardware to do software I2C Master bit banging. Provides the minimal hardware to do software I2C Master bit banging.
On the same write CSRStorage (_w), software can control SCL (I2C_SCL), SDA direction and value On the same write CSRStorage (_w), software can control:
(I2C_OE, I2C_W). Software get back SDA value with the read CSRStatus (_r). - SCL (I2C_SCL).
- SDA direction and value (I2C_OE, I2C_W).
Software get back SDA value with the read CSRStatus (_r).
""" """
pads_layout = [("scl", 1), ("sda", 1)] pads_layout = [("scl", 1), ("sda", 1)]
def __init__(self, pads=None): def __init__(self, pads=None):
@ -36,17 +39,17 @@ class I2CMaster(Module, AutoCSR):
self.connect(pads) self.connect(pads)
def connect(self, pads): def connect(self, pads):
_sda_w = Signal() # SCL
_sda_oe = Signal() self.specials += Tristate(pads.scl,
_sda_r = Signal() o = 0, # I2C uses Pull-ups, only drive low.
self.comb += [ oe = ~self._w.fields.scl # Drive when scl is low.
pads.scl.eq(self._w.fields.scl), )
_sda_oe.eq( self._w.fields.oe), # SDA
_sda_w.eq( self._w.fields.sda), self.specials += Tristate(pads.sda,
self._r.fields.sda.eq(_sda_r), o = 0, # I2C uses Pull-ups, only drive low.
] oe = self._w.fields.oe & ~self._w.fields.sda, # Drive when oe and sda is low.
self.specials += Tristate(pads.sda, _sda_w, _sda_oe, _sda_r) i = self._r.fields.sda
)
class I2CMasterSim(I2CMaster): class I2CMasterSim(I2CMaster):
"""I2C Master Bit-Banging for Verilator simulation """I2C Master Bit-Banging for Verilator simulation