diff --git a/software/glasgow/applet/all.py b/software/glasgow/applet/all.py index 3597a56ac..c4152e8b7 100644 --- a/software/glasgow/applet/all.py +++ b/software/glasgow/applet/all.py @@ -3,7 +3,7 @@ from .interface.uart import UARTApplet from .interface.spi_master import SPIMasterApplet -from .interface.i2c_master import I2CMasterApplet +from .interface.i2c_initiator import I2CInitiatorApplet from .interface.jtag_pinout import JTAGPinoutApplet from .interface.jtag_probe import JTAGProbeApplet from .interface.jtag_openocd import JTAGOpenOCDApplet diff --git a/software/glasgow/applet/control/tps6598x/__init__.py b/software/glasgow/applet/control/tps6598x/__init__.py index 06ec18f74..cc331e624 100644 --- a/software/glasgow/applet/control/tps6598x/__init__.py +++ b/software/glasgow/applet/control/tps6598x/__init__.py @@ -1,7 +1,7 @@ import logging import asyncio -from ...interface.i2c_master import I2CMasterApplet +from ...interface.i2c_initiator import I2CInitiatorApplet from ... import * @@ -41,7 +41,7 @@ async def write_reg(self, address, data): self._check(await self.lower.write(self._i2c_addr, [address, len(data), *data], stop=True)) -class ControlTPS6598xApplet(I2CMasterApplet, name="control-tps6598x"): +class ControlTPS6598xApplet(I2CInitiatorApplet, name="control-tps6598x"): logger = logging.getLogger(__name__) help = "configure TPS6598x USB PD controllers" description = """ diff --git a/software/glasgow/applet/interface/i2c_master/__init__.py b/software/glasgow/applet/interface/i2c_initiator/__init__.py similarity index 89% rename from software/glasgow/applet/interface/i2c_master/__init__.py rename to software/glasgow/applet/interface/i2c_initiator/__init__.py index 1b959749f..a44269585 100644 --- a/software/glasgow/applet/interface/i2c_master/__init__.py +++ b/software/glasgow/applet/interface/i2c_initiator/__init__.py @@ -4,7 +4,7 @@ from nmigen.compat import * from ....gateware.pads import * -from ....gateware.i2c import I2CMaster +from ....gateware.i2c import I2CInitiator from ... import * @@ -15,9 +15,9 @@ CMD_READ = 0x05 -class I2CMasterSubtarget(Module): +class I2CInitiatorSubtarget(Module): def __init__(self, pads, out_fifo, in_fifo, period_cyc): - self.submodules.i2c_master = I2CMaster(pads, period_cyc) + self.submodules.i2c_initiator = I2CInitiator(pads, period_cyc) ### @@ -26,7 +26,7 @@ def __init__(self, pads, out_fifo, in_fifo, period_cyc): self.submodules.fsm = FSM(reset_state="IDLE") self.fsm.act("IDLE", - If(~self.i2c_master.busy & out_fifo.readable, + If(~self.i2c_initiator.busy & out_fifo.readable, out_fifo.re.eq(1), NextValue(cmd, out_fifo.dout), NextState("COMMAND") @@ -34,10 +34,10 @@ def __init__(self, pads, out_fifo, in_fifo, period_cyc): ) self.fsm.act("COMMAND", If(cmd == CMD_START, - self.i2c_master.start.eq(1), + self.i2c_initiator.start.eq(1), NextState("IDLE") ).Elif(cmd == CMD_STOP, - self.i2c_master.stop.eq(1), + self.i2c_initiator.stop.eq(1), NextState("IDLE") ).Elif(cmd == CMD_COUNT, NextState("COUNT-MSB") @@ -74,22 +74,22 @@ def __init__(self, pads, out_fifo, in_fifo, period_cyc): self.fsm.act("WRITE-FIRST", If(out_fifo.readable, out_fifo.re.eq(1), - self.i2c_master.data_i.eq(out_fifo.dout), - self.i2c_master.write.eq(1), + self.i2c_initiator.data_i.eq(out_fifo.dout), + self.i2c_initiator.write.eq(1), NextState("WRITE") ) ) self.fsm.act("WRITE", - If(~self.i2c_master.busy, - If(self.i2c_master.ack_o, + If(~self.i2c_initiator.busy, + If(self.i2c_initiator.ack_o, NextValue(count, count - 1) ), - If((count == 1) | ~self.i2c_master.ack_o, + If((count == 1) | ~self.i2c_initiator.ack_o, NextState("REPORT") ).Elif(out_fifo.readable, out_fifo.re.eq(1), - self.i2c_master.data_i.eq(out_fifo.dout), - self.i2c_master.write.eq(1), + self.i2c_initiator.data_i.eq(out_fifo.dout), + self.i2c_initiator.write.eq(1), ) ) ) @@ -102,21 +102,21 @@ def __init__(self, pads, out_fifo, in_fifo, period_cyc): ) ) self.fsm.act("READ-FIRST", - self.i2c_master.ack_i.eq(~(count == 1)), - self.i2c_master.read.eq(1), + self.i2c_initiator.ack_i.eq(~(count == 1)), + self.i2c_initiator.read.eq(1), NextValue(count, count - 1), NextState("READ") ) self.fsm.act("READ", - If(~self.i2c_master.busy, + If(~self.i2c_initiator.busy, If(in_fifo.writable, in_fifo.we.eq(1), - in_fifo.din.eq(self.i2c_master.data_o), + in_fifo.din.eq(self.i2c_initiator.data_o), If(count == 0, NextState("IDLE") ).Else( - self.i2c_master.ack_i.eq(~(count == 1)), - self.i2c_master.read.eq(1), + self.i2c_initiator.ack_i.eq(~(count == 1)), + self.i2c_initiator.read.eq(1), NextValue(count, count - 1) ) ) @@ -124,7 +124,7 @@ def __init__(self, pads, out_fifo, in_fifo, period_cyc): ) -class I2CMasterInterface: +class I2CInitiatorInterface: def __init__(self, interface, logger): self.lower = interface self._logger = logger @@ -257,7 +257,7 @@ async def scan(self, addresses=range(0b0001_000, 0b1111_000), *, read=True, writ return found -class I2CMasterApplet(GlasgowApplet, name="i2c-master"): +class I2CInitiatorApplet(GlasgowApplet, name="i2c-initiator"): logger = logging.getLogger(__name__) help = "initiate I2C transactions" description = """ @@ -282,7 +282,7 @@ def add_build_arguments(cls, parser, access): def build(self, target, args): self.mux_interface = iface = target.multiplexer.claim_interface(self, args) - iface.add_subtarget(I2CMasterSubtarget( + iface.add_subtarget(I2CInitiatorSubtarget( pads=iface.get_pads(args, pins=self.__pins), out_fifo=iface.get_out_fifo(), in_fifo=iface.get_in_fifo(), @@ -303,7 +303,7 @@ async def run(self, device, args): pulls = {args.pin_scl, args.pin_sda} iface = await device.demultiplexer.claim_interface(self, self.mux_interface, args, pull_high=pulls) - i2c_iface = I2CMasterInterface(iface, self.logger) + i2c_iface = I2CInitiatorInterface(iface, self.logger) return i2c_iface @classmethod @@ -351,7 +351,7 @@ async def interact(self, device, args, i2c_iface): # ------------------------------------------------------------------------------------------------- -class I2CMasterAppletTestCase(GlasgowAppletTestCase, applet=I2CMasterApplet): +class I2CInitiatorAppletTestCase(GlasgowAppletTestCase, applet=I2CInitiatorApplet): @synthesis_test def test_build(self): self.assertBuilds() diff --git a/software/glasgow/applet/memory/_24x/__init__.py b/software/glasgow/applet/memory/_24x/__init__.py index 1396e7e1c..7880cefa7 100644 --- a/software/glasgow/applet/memory/_24x/__init__.py +++ b/software/glasgow/applet/memory/_24x/__init__.py @@ -1,7 +1,7 @@ import logging import argparse -from ...interface.i2c_master import I2CMasterApplet +from ...interface.i2c_initiator import I2CInitiatorApplet from ... import * @@ -80,7 +80,7 @@ async def write(self, addr, data): return True -class Memory24xApplet(I2CMasterApplet, name="memory-24x"): +class Memory24xApplet(I2CInitiatorApplet, name="memory-24x"): logger = logging.getLogger(__name__) help = "read and write 24-series I²C EEPROM memories" default_page_size = 8 diff --git a/software/glasgow/applet/sensor/bmp280/__init__.py b/software/glasgow/applet/sensor/bmp280/__init__.py index 11a3a4724..3c72c8180 100644 --- a/software/glasgow/applet/sensor/bmp280/__init__.py +++ b/software/glasgow/applet/sensor/bmp280/__init__.py @@ -6,7 +6,7 @@ from ....support.data_logger import DataLogger from ... import * -from ...interface.i2c_master import I2CMasterApplet +from ...interface.i2c_initiator import I2CInitiatorApplet REG_CAL_T1 = 0x88 # 16-bit unsigned @@ -267,7 +267,7 @@ async def write(self, addr, data): .format(self._i2c_addr)) -class SensorBMP280Applet(I2CMasterApplet, name="sensor-bmp280"): +class SensorBMP280Applet(I2CInitiatorApplet, name="sensor-bmp280"): logger = logging.getLogger(__name__) help = "measure temperature and pressure with Bosch BMP280 sensors" description = """ diff --git a/software/glasgow/applet/sensor/ina260/__init__.py b/software/glasgow/applet/sensor/ina260/__init__.py index 4cffb23cc..bf36462a6 100644 --- a/software/glasgow/applet/sensor/ina260/__init__.py +++ b/software/glasgow/applet/sensor/ina260/__init__.py @@ -6,7 +6,7 @@ from ....support.data_logger import DataLogger from ... import * -from ...interface.i2c_master import I2CMasterApplet +from ...interface.i2c_initiator import I2CInitiatorApplet REG_CONFIG = 0x00 # 16-bit rw @@ -90,7 +90,7 @@ async def get_power(self): return watts -class SensorINA260Applet(I2CMasterApplet, name="sensor-ina260"): +class SensorINA260Applet(I2CInitiatorApplet, name="sensor-ina260"): logger = logging.getLogger(__name__) help = "measure voltage, current and power with TI INA260 sensors" description = """ diff --git a/software/glasgow/applet/sensor/scd30/__init__.py b/software/glasgow/applet/sensor/scd30/__init__.py index 987e9c782..d25a8e3da 100644 --- a/software/glasgow/applet/sensor/scd30/__init__.py +++ b/software/glasgow/applet/sensor/scd30/__init__.py @@ -12,7 +12,7 @@ from ....support.logging import dump_hex from ....support.data_logger import DataLogger -from ...interface.i2c_master import I2CMasterApplet +from ...interface.i2c_initiator import I2CInitiatorApplet from ... import * @@ -167,7 +167,7 @@ async def set_altitude_compensation(self, altitude_m): await self._write(CMD_ALTITUDE_COMP, ">H", altitude_m) -class SensorSCD30Applet(I2CMasterApplet, name="sensor-scd30"): +class SensorSCD30Applet(I2CInitiatorApplet, name="sensor-scd30"): logger = logging.getLogger(__name__) help = "measure CO₂, humidity, and temperature with Sensirion SCD30 sensors" description = """ diff --git a/software/glasgow/gateware/i2c.py b/software/glasgow/gateware/i2c.py index a33e8675d..4da6d7943 100644 --- a/software/glasgow/gateware/i2c.py +++ b/software/glasgow/gateware/i2c.py @@ -4,7 +4,7 @@ from nmigen.compat.genlib.cdc import MultiReg -__all__ = ['I2CSlave'] +__all__ = ["I2CInitiator", "I2CTarget"] class I2CBus(Module): @@ -53,9 +53,9 @@ def __init__(self, pads): ] -class I2CMaster(Module): +class I2CInitiator(Module): """ - Simple I2C master. + Simple I2C transaction initiator. Generates start and stop conditions, and transmits and receives octets. Clock stretching is supported. @@ -69,7 +69,7 @@ class I2CMaster(Module): :type clk_stretch: bool :attr busy: - Busy flag. Low if the master state machine is idle, high otherwise. + Busy flag. Low if the state machine is idle, high otherwise. :attr start: Start strobe. When ``busy`` is low, asserting ``start`` for one cycle generates a start or repeated start condition on the bus. Ignored when ``busy`` is high. @@ -250,15 +250,15 @@ def stb_x(state, next_state, *exprs): stb_x("READ-ACK-SDA-N", "IDLE") -class I2CSlave(Module): +class I2CTarget(Module): """ - Simple I2C slave. + Simple I2C target. Clock stretching is not supported. Builtin responses (identification, general call, etc.) are not provided. :attr address: - The 7-bit address the slave will respond to. + The 7-bit address the target will respond to. :attr start: Start strobe. Active for one cycle immediately after acknowledging address. :attr stop: @@ -267,7 +267,7 @@ class I2CSlave(Module): :attr write: Write strobe. Active for one cycle immediately after receiving a data octet. :attr data_i: - Data octet received from the master. Valid when ``write`` is high. + Data octet received from the initiator. Valid when ``write`` is high. :attr ack_o: Acknowledge strobe. If active for at least one cycle during the acknowledge bit setup period (one half-period after write strobe is asserted), acknowledge is asserted. @@ -275,7 +275,7 @@ class I2CSlave(Module): :attr read: Read strobe. Active for one cycle immediately before latching ``data_o``. :attr data_o: - Data octet to be transmitted to the master. Latched immedately after receiving + Data octet to be transmitted to the initiator. Latched immedately after receiving a read command. """ def __init__(self, pads): @@ -465,11 +465,11 @@ def assertCondition(self, tb, fn): self.assertTrue((yield from self.tb.wait_for(fn))) -class I2CMasterTestbench(I2CTestbench): +class I2CInitiatorTestbench(I2CTestbench): def __init__(self): super().__init__() - self.submodules.dut = I2CMaster(pads=self, period_cyc=self.period_cyc) + self.submodules.dut = I2CInitiator(pads=self, period_cyc=self.period_cyc) self.wait_cyc = self.period_cyc * 3 def strobe(self, signal): @@ -493,9 +493,9 @@ def write(self, data): yield from self.strobe(self.dut.write) -class I2CMasterTestCase(I2CTestCase): +class I2CInitiatorTestCase(I2CTestCase): def setUp(self): - self.tb = I2CMasterTestbench() + self.tb = I2CInitiatorTestbench() @simulation_test def test_start(self, tb): @@ -641,11 +641,11 @@ def test_read_tx(self, tb): self.assertEqual((yield tb.scl_i), 1) -class I2CSlaveTestbench(I2CTestbench): +class I2CTargetTestbench(I2CTestbench): def __init__(self): super().__init__() - self.submodules.dut = I2CSlave(pads=self) + self.submodules.dut = I2CTarget(pads=self) self.wait_cyc = self.period_cyc // 4 def start(self): @@ -704,9 +704,9 @@ def read_octet(self): return octet -class I2CSlaveTestCase(I2CTestCase): +class I2CTargetTestCase(I2CTestCase): def setUp(self): - self.tb = I2CSlaveTestbench() + self.tb = I2CTargetTestbench() def simulationSetUp(self, tb): yield tb.dut.address.eq(0b0101000) diff --git a/software/glasgow/gateware/registers.py b/software/glasgow/gateware/registers.py index c441eb0de..868d4c686 100644 --- a/software/glasgow/gateware/registers.py +++ b/software/glasgow/gateware/registers.py @@ -42,9 +42,9 @@ class I2CRegisters(Registers): Note that for multibyte registers, the register data is read in little endian, but written in big endian. This replaces a huge multiplexer with a shift register, but is a bit cursed. """ - def __init__(self, i2c_slave): + def __init__(self, i2c_target): super().__init__() - self.i2c_slave = i2c_slave + self.i2c_target = i2c_target def do_finalize(self): if self.reg_count == 0: @@ -54,32 +54,32 @@ def do_finalize(self): reg_addr = Signal(max=max(self.reg_count, 2)) reg_data = Signal(max(s.nbits for s in self.regs_r)) self.comb += [ - self.i2c_slave.data_o.eq(reg_data), - If(self.i2c_slave.write, + self.i2c_target.data_o.eq(reg_data), + If(self.i2c_target.write, If(latch_addr, - If(self.i2c_slave.data_i < self.reg_count, - self.i2c_slave.ack_o.eq(1) + If(self.i2c_target.data_i < self.reg_count, + self.i2c_target.ack_o.eq(1) ) ).Elif(~latch_addr, - self.i2c_slave.ack_o.eq(1), + self.i2c_target.ack_o.eq(1), ) ) ] self.sync += [ - If(self.i2c_slave.start, + If(self.i2c_target.start, latch_addr.eq(1) ), - If(self.i2c_slave.write, + If(self.i2c_target.write, latch_addr.eq(0), If(latch_addr, - reg_addr.eq(self.i2c_slave.data_i), - reg_data.eq(self.regs_r[self.i2c_slave.data_i]), + reg_addr.eq(self.i2c_target.data_i), + reg_data.eq(self.regs_r[self.i2c_target.data_i]), ).Else( - reg_data.eq(Cat(self.i2c_slave.data_i, reg_data)), - self.regs_w[reg_addr].eq(Cat(self.i2c_slave.data_i, reg_data)), + reg_data.eq(Cat(self.i2c_target.data_i, reg_data)), + self.regs_w[reg_addr].eq(Cat(self.i2c_target.data_i, reg_data)), ) ), - If(self.i2c_slave.read, + If(self.i2c_target.read, reg_data.eq(reg_data >> 8), ) ] @@ -89,12 +89,12 @@ def do_finalize(self): import unittest from . import simulation_test -from .i2c import I2CSlaveTestbench +from .i2c import I2CTargetTestbench class I2CRegistersTestbench(Module): def __init__(self): - self.submodules.i2c = I2CSlaveTestbench() + self.submodules.i2c = I2CTargetTestbench() self.submodules.dut = I2CRegisters(self.i2c.dut) self.reg_dummy, self.addr_dummy = self.dut.add_rw(8) self.reg_rw_8, self.addr_rw_8 = self.dut.add_rw(8) diff --git a/software/glasgow/target/hardware.py b/software/glasgow/target/hardware.py index db40f5138..8cd0a8844 100644 --- a/software/glasgow/target/hardware.py +++ b/software/glasgow/target/hardware.py @@ -8,7 +8,7 @@ from nmigen.build import ResourceError from ..gateware.pads import Pads -from ..gateware.i2c import I2CSlave +from ..gateware.i2c import I2CTarget from ..gateware.registers import I2CRegisters from ..gateware.fx2_crossbar import FX2Crossbar from ..platform.all import * @@ -40,9 +40,9 @@ def __init__(self, revision, multiplexer_cls=None, with_analyzer=False): except ResourceError: pass - self.submodules.i2c_slave = I2CSlave(self.platform.request("i2c")) - self.submodules.registers = I2CRegisters(self.i2c_slave) - self.comb += self.i2c_slave.address.eq(0b0001000) + self.submodules.i2c_target = I2CTarget(self.platform.request("i2c")) + self.submodules.registers = I2CRegisters(self.i2c_target) + self.comb += self.i2c_target.address.eq(0b0001000) self.submodules.fx2_crossbar = FX2Crossbar(self.platform.request("fx2", xdr={ "sloe": 1, "slrd": 1, "slwr": 1, "pktend": 1, "fifoadr": 1, "flag": 2, "fd": 2