Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: GlasgowEmbedded/glasgow
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: d67503cf35ef
Choose a base ref
...
head repository: GlasgowEmbedded/glasgow
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 5d1fcd0c5cb7
Choose a head ref
  • 3 commits
  • 1 file changed
  • 1 contributor

Commits on Jan 13, 2020

  1. Copy the full SHA
    5665743 View commit details
  2. Copy the full SHA
    afa9211 View commit details
  3. Copy the full SHA
    5d1fcd0 View commit details
Showing with 61 additions and 13 deletions.
  1. +61 −13 software/glasgow/gateware/i2c.py
74 changes: 61 additions & 13 deletions software/glasgow/gateware/i2c.py
Original file line number Diff line number Diff line change
@@ -257,13 +257,22 @@ class I2CTarget(Module):
Clock stretching is not supported.
Builtin responses (identification, general call, etc.) are not provided.
Note that the start, stop, and restart strobes are transaction delimiters rather than direct
indicators of bus conditions. A transaction always starts with a start strobe and ends with
either a stop or a restart strobe. That is, a restart strobe, similarly to a stop strobe, may
be only followed by another start strobe (or no strobe at all if the device is not addressed
again).
:attr address:
The 7-bit address the target will respond to.
:attr start:
Start strobe. Active for one cycle immediately after acknowledging address.
:attr stop:
Stop stobe. Active for one cycle immediately after a stop condition that terminates
a transaction that addressed this device.
:attr restart:
Repeated start strobe. Active for one cycle immediately after a repeated start condition
that terminates a transaction that addressed this device.
:attr write:
Write strobe. Active for one cycle immediately after receiving a data octet.
:attr data_i:
@@ -280,8 +289,10 @@ class I2CTarget(Module):
"""
def __init__(self, pads):
self.address = Signal(7)
self.busy = Signal() # clock stretching request (experimental, undocumented)
self.start = Signal()
self.stop = Signal()
self.restart = Signal()
self.write = Signal()
self.data_i = Signal(8)
self.ack_o = Signal()
@@ -298,7 +309,6 @@ def __init__(self, pads):
shreg_o = Signal(8)

self.submodules.fsm = FSM(reset_state="IDLE")
self.comb += self.stop.eq(self.fsm.after_entering("IDLE"))
self.fsm.act("IDLE",
If(bus.start,
NextState("START"),
@@ -325,6 +335,7 @@ def __init__(self, pads):
NextValue(bitno, bitno + 1),
If(bitno == 7,
If(shreg_i[1:] == self.address,
self.start.eq(1),
NextValue(bus.sda_o, 0),
NextState("ADDR-ACK")
).Else(
@@ -335,27 +346,29 @@ def __init__(self, pads):
)
self.fsm.act("ADDR-ACK",
If(bus.stop,
self.stop.eq(1),
NextState("IDLE")
).Elif(bus.start,
self.restart.eq(1),
NextState("START")
).Elif(bus.setup,
If(~shreg_i[0],
self.start.eq(1),
NextValue(bus.sda_o, 1),
NextState("WRITE-SHIFT")
)
).Elif(bus.sample,
If(shreg_i[0],
self.start.eq(1),
NextValue(shreg_o, self.data_o),
NextState("READ-SHIFT")
NextState("READ-STRETCH")
)
)
)
self.fsm.act("WRITE-SHIFT",
If(bus.stop,
self.stop.eq(1),
NextState("IDLE")
).Elif(bus.start,
self.restart.eq(1),
NextState("START")
).Elif(bus.sample,
NextValue(shreg_i, (shreg_i << 1) | bus.sda_i),
@@ -370,21 +383,49 @@ def __init__(self, pads):
self.comb += self.write.eq(self.fsm.after_entering("WRITE-ACK"))
self.fsm.act("WRITE-ACK",
If(bus.stop,
self.stop.eq(1),
NextState("IDLE")
).Elif(bus.start,
self.restart.eq(1),
NextState("START")
).Elif(~bus.scl_i & self.ack_o,
NextValue(bus.sda_o, 0)
).Elif(bus.setup,
NextValue(bus.sda_o, 1),
NextState("WRITE-SHIFT")
).Elif(~bus.scl_i,
NextValue(bus.scl_o, ~self.busy),
If(self.ack_o,
NextValue(bus.sda_o, 0)
)
)
)
self.comb += self.read.eq(self.fsm.before_entering("READ-STRETCH"))
self.fsm.act("READ-STRETCH",
If(self.busy,
NextValue(shreg_o, self.data_o)
),
If(bus.stop,
self.stop.eq(1),
NextState("IDLE")
).Elif(bus.start,
NextState("START")
).Elif(self.busy,
If(~bus.scl_i,
NextValue(bus.scl_o, 0)
)
).Else(
If(~bus.scl_i,
NextValue(bus.sda_o, shreg_o[7])
),
NextValue(bus.scl_o, 1),
NextState("READ-SHIFT")
)
)
self.comb += self.read.eq(self.fsm.before_entering("READ-SHIFT"))
self.fsm.act("READ-SHIFT",
If(bus.stop,
self.stop.eq(1),
NextState("IDLE")
).Elif(bus.start,
self.restart.eq(1),
NextState("START")
).Elif(bus.setup,
NextValue(bus.sda_o, shreg_o[7]),
@@ -398,16 +439,19 @@ def __init__(self, pads):
)
self.fsm.act("READ-ACK",
If(bus.stop,
self.stop.eq(1),
NextState("IDLE")
).Elif(bus.start,
self.restart.eq(1),
NextState("START")
).Elif(bus.setup,
NextValue(bus.sda_o, 1),
).Elif(bus.sample,
If(~bus.sda_i,
NextValue(shreg_o, self.data_o),
NextState("READ-SHIFT")
NextState("READ-STRETCH")
).Else(
self.stop.eq(1),
NextState("IDLE")
)
)
@@ -741,23 +785,27 @@ def test_addr_r_ack(self, tb):
yield from tb.start()
yield from tb.write_octet(0b01010001)
yield tb.scl_o.eq(0)
yield from tb.half_period()
yield from self.assertCondition(tb, lambda: (yield tb.dut.start))
yield
yield from self.assertState(tb, "ADDR-ACK")
self.assertEqual((yield tb.sda_i), 0)
yield tb.scl_o.eq(1)
yield from self.assertCondition(tb, lambda: (yield tb.dut.start))
yield
yield from tb.half_period()
yield from self.assertState(tb, "READ-SHIFT")

@simulation_test
def test_addr_w_ack(self, tb):
yield from tb.start()
yield from tb.write_octet(0b01010000)
self.assertEqual((yield from tb.read_bit()), 0)
yield from self.assertState(tb, "ADDR-ACK")
yield tb.scl_o.eq(0)
yield from self.assertCondition(tb, lambda: (yield tb.dut.start))
yield
yield from self.assertState(tb, "ADDR-ACK")
self.assertEqual((yield tb.sda_i), 0)
yield tb.scl_o.eq(1)
yield from tb.half_period()
yield tb.scl_o.eq(0)
yield from tb.half_period()
yield from self.assertState(tb, "WRITE-SHIFT")

def start_addr(self, tb, read):