mirror of https://github.com/m-labs/artiq.git
Kasli JSON description for SPI over DIO cards (#1800)
This commit is contained in:
parent
2b918ac6f7
commit
c4292770f8
|
@ -33,6 +33,8 @@ Highlights:
|
||||||
warning is logged. The warning is additional to the one already printed in the core device log upon
|
warning is logged. The warning is additional to the one already printed in the core device log upon
|
||||||
detection of the error.
|
detection of the error.
|
||||||
* Removed worker DB warning for writing a dataset that is also in the archive
|
* Removed worker DB warning for writing a dataset that is also in the archive
|
||||||
|
* Extended Kasli gateware JSON description with configuration for SPI over DIO.
|
||||||
|
See: https://github.com/m-labs/artiq/pull/1800
|
||||||
|
|
||||||
Breaking changes:
|
Breaking changes:
|
||||||
|
|
||||||
|
|
|
@ -134,7 +134,7 @@
|
||||||
"properties": {
|
"properties": {
|
||||||
"type": {
|
"type": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": ["dio", "urukul", "novogorny", "sampler", "suservo", "zotino", "grabber", "mirny", "fastino", "phaser", "hvamp"]
|
"enum": ["dio", "dio_spi", "urukul", "novogorny", "sampler", "suservo", "zotino", "grabber", "mirny", "fastino", "phaser", "hvamp"]
|
||||||
},
|
},
|
||||||
"board": {
|
"board": {
|
||||||
"type": "string"
|
"type": "string"
|
||||||
|
@ -179,6 +179,89 @@
|
||||||
},
|
},
|
||||||
"required": ["ports", "bank_direction_low", "bank_direction_high"]
|
"required": ["ports", "bank_direction_low", "bank_direction_high"]
|
||||||
}
|
}
|
||||||
|
}, {
|
||||||
|
"title": "DIO_SPI",
|
||||||
|
"if": {
|
||||||
|
"properties": {
|
||||||
|
"type": {
|
||||||
|
"const": "dio_spi"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"then": {
|
||||||
|
"properties": {
|
||||||
|
"ports": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "integer"
|
||||||
|
},
|
||||||
|
"minItems": 1,
|
||||||
|
"maxItems": 1
|
||||||
|
},
|
||||||
|
"spi": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"clk": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 7
|
||||||
|
},
|
||||||
|
"mosi": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 7
|
||||||
|
},
|
||||||
|
"miso": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 7
|
||||||
|
},
|
||||||
|
"cs": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["clk"]
|
||||||
|
},
|
||||||
|
"minItems": 1
|
||||||
|
},
|
||||||
|
"ttl": {
|
||||||
|
"type": "array",
|
||||||
|
"items": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"name": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"pin": {
|
||||||
|
"type": "integer",
|
||||||
|
"minimum": 0,
|
||||||
|
"maximum": 7
|
||||||
|
},
|
||||||
|
"direction": {
|
||||||
|
"type": "string",
|
||||||
|
"enum": ["input", "output"]
|
||||||
|
},
|
||||||
|
"edge_counter": {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["pin", "direction"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["ports", "spi"]
|
||||||
|
}
|
||||||
}, {
|
}, {
|
||||||
"title": "Urukul",
|
"title": "Urukul",
|
||||||
"if": {
|
"if": {
|
||||||
|
|
|
@ -102,8 +102,7 @@ class PeripheralManager:
|
||||||
"module": "artiq.coredevice.ttl",
|
"module": "artiq.coredevice.ttl",
|
||||||
"class": "{class_name}",
|
"class": "{class_name}",
|
||||||
"arguments": {{"channel": 0x{channel:06x}}},
|
"arguments": {{"channel": 0x{channel:06x}}},
|
||||||
}}
|
}}""",
|
||||||
""",
|
|
||||||
name=name[i],
|
name=name[i],
|
||||||
class_name=classes[i // 4],
|
class_name=classes[i // 4],
|
||||||
channel=rtio_offset + next(channel))
|
channel=rtio_offset + next(channel))
|
||||||
|
@ -117,25 +116,64 @@ class PeripheralManager:
|
||||||
"module": "artiq.coredevice.edge_counter",
|
"module": "artiq.coredevice.edge_counter",
|
||||||
"class": "EdgeCounter",
|
"class": "EdgeCounter",
|
||||||
"arguments": {{"channel": 0x{channel:06x}}},
|
"arguments": {{"channel": 0x{channel:06x}}},
|
||||||
}}
|
}}""",
|
||||||
""",
|
|
||||||
name=name[i],
|
name=name[i],
|
||||||
channel=rtio_offset + next(channel))
|
channel=rtio_offset + next(channel))
|
||||||
return next(channel)
|
return next(channel)
|
||||||
|
|
||||||
|
def process_dio_spi(self, rtio_offset, peripheral):
|
||||||
|
channel = count(0)
|
||||||
|
for spi in peripheral["spi"]:
|
||||||
|
self.gen("""
|
||||||
|
device_db["{name}"] = {{
|
||||||
|
"type": "local",
|
||||||
|
"module": "artiq.coredevice.spi2",
|
||||||
|
"class": "SPIMaster",
|
||||||
|
"arguments": {{"channel": 0x{channel:06x}}}
|
||||||
|
}}""",
|
||||||
|
name=self.get_name(spi.get("name", "dio_spi")),
|
||||||
|
channel=rtio_offset + next(channel))
|
||||||
|
for ttl in peripheral.get("ttl", []):
|
||||||
|
ttl_class_names = {
|
||||||
|
"input": "TTLInOut",
|
||||||
|
"output": "TTLOut"
|
||||||
|
}
|
||||||
|
name = self.get_name(ttl.get("name", "ttl"))
|
||||||
|
self.gen("""
|
||||||
|
device_db["{name}"] = {{
|
||||||
|
"type": "local",
|
||||||
|
"module": "artiq.coredevice.ttl",
|
||||||
|
"class": "{class_name}",
|
||||||
|
"arguments": {{"channel": 0x{channel:06x}}},
|
||||||
|
}}""",
|
||||||
|
name=name,
|
||||||
|
class_name=ttl_class_names[ttl["direction"]],
|
||||||
|
channel=rtio_offset + next(channel))
|
||||||
|
if ttl.get("edge_counter", False):
|
||||||
|
self.gen("""
|
||||||
|
device_db["{name}_counter"] = {{
|
||||||
|
"type": "local",
|
||||||
|
"module": "artiq.coredevice.edge_counter",
|
||||||
|
"class": "EdgeCounter",
|
||||||
|
"arguments": {{"channel": 0x{channel:06x}}},
|
||||||
|
}}""",
|
||||||
|
name=name,
|
||||||
|
channel=rtio_offset + next(channel))
|
||||||
|
return next(channel)
|
||||||
|
|
||||||
def process_urukul(self, rtio_offset, peripheral):
|
def process_urukul(self, rtio_offset, peripheral):
|
||||||
urukul_name = self.get_name("urukul")
|
urukul_name = self.get_name("urukul")
|
||||||
synchronization = peripheral["synchronization"]
|
synchronization = peripheral["synchronization"]
|
||||||
channel = count(0)
|
channel = count(0)
|
||||||
self.gen("""
|
self.gen("""
|
||||||
device_db["eeprom_{name}"]={{
|
device_db["eeprom_{name}"] = {{
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"module": "artiq.coredevice.kasli_i2c",
|
"module": "artiq.coredevice.kasli_i2c",
|
||||||
"class": "KasliEEPROM",
|
"class": "KasliEEPROM",
|
||||||
"arguments": {{"port": "EEM{eem}"}}
|
"arguments": {{"port": "EEM{eem}"}}
|
||||||
}}
|
}}
|
||||||
|
|
||||||
device_db["spi_{name}"]={{
|
device_db["spi_{name}"] = {{
|
||||||
"type": "local",
|
"type": "local",
|
||||||
"module": "artiq.coredevice.spi2",
|
"module": "artiq.coredevice.spi2",
|
||||||
"class": "SPIMaster",
|
"class": "SPIMaster",
|
||||||
|
|
|
@ -70,6 +70,65 @@ class DIO(_EEM):
|
||||||
target.rtio_channels.append(rtio.Channel.from_phy(counter))
|
target.rtio_channels.append(rtio.Channel.from_phy(counter))
|
||||||
|
|
||||||
|
|
||||||
|
class DIO_SPI(_EEM):
|
||||||
|
@staticmethod
|
||||||
|
def io(eem, spi, ttl, iostandard):
|
||||||
|
def spi_subsignals(clk, mosi, miso, cs, pol):
|
||||||
|
signals = [Subsignal("clk", Pins(_eem_pin(eem, clk, pol)))]
|
||||||
|
if mosi is not None:
|
||||||
|
signals.append(Subsignal("mosi",
|
||||||
|
Pins(_eem_pin(eem, mosi, pol))))
|
||||||
|
if miso is not None:
|
||||||
|
signals.append(Subsignal("miso",
|
||||||
|
Pins(_eem_pin(eem, miso, pol))))
|
||||||
|
if cs:
|
||||||
|
signals.append(Subsignal("cs_n", Pins(
|
||||||
|
*(_eem_pin(eem, pin, pol) for pin in cs))))
|
||||||
|
return signals
|
||||||
|
|
||||||
|
spi = [
|
||||||
|
("dio{}_spi{}_{}".format(eem, i, pol), i,
|
||||||
|
*spi_subsignals(clk, mosi, miso, cs, pol),
|
||||||
|
iostandard(eem))
|
||||||
|
for i, (clk, mosi, miso, cs) in enumerate(spi) for pol in "pn"
|
||||||
|
]
|
||||||
|
ttl = [
|
||||||
|
("dio{}".format(eem), i,
|
||||||
|
Subsignal("p", Pins(_eem_pin(eem, pin, "p"))),
|
||||||
|
Subsignal("n", Pins(_eem_pin(eem, pin, "n"))),
|
||||||
|
iostandard(eem))
|
||||||
|
for i, (pin, _, _) in enumerate(ttl)
|
||||||
|
]
|
||||||
|
return spi + ttl
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def add_std(cls, target, eem, spi, ttl, iostandard=default_iostandard):
|
||||||
|
cls.add_extension(target, eem, spi, ttl, iostandard=iostandard)
|
||||||
|
|
||||||
|
for i in range(len(spi)):
|
||||||
|
phy = spi2.SPIMaster(
|
||||||
|
target.platform.request("dio{}_spi{}_p".format(eem, i)),
|
||||||
|
target.platform.request("dio{}_spi{}_n".format(eem, i))
|
||||||
|
)
|
||||||
|
target.submodules += phy
|
||||||
|
target.rtio_channels.append(
|
||||||
|
rtio.Channel.from_phy(phy, ififo_depth=4))
|
||||||
|
|
||||||
|
dci = iostandard(eem).name == "LVDS"
|
||||||
|
for i, (_, ttl_cls, edge_counter_cls) in enumerate(ttl):
|
||||||
|
pads = target.platform.request("dio{}".format(eem), i)
|
||||||
|
phy = ttl_cls(pads.p, pads.n, dci=dci)
|
||||||
|
target.submodules += phy
|
||||||
|
target.rtio_channels.append(rtio.Channel.from_phy(phy))
|
||||||
|
|
||||||
|
if edge_counter_cls is not None:
|
||||||
|
state = getattr(phy, "input_state", None)
|
||||||
|
if state is not None:
|
||||||
|
counter = edge_counter_cls(state)
|
||||||
|
target.submodules += counter
|
||||||
|
target.rtio_channels.append(rtio.Channel.from_phy(counter))
|
||||||
|
|
||||||
|
|
||||||
class Urukul(_EEM):
|
class Urukul(_EEM):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def io(eem, eem_aux, iostandard):
|
def io(eem, eem_aux, iostandard):
|
||||||
|
|
|
@ -19,6 +19,21 @@ def peripheral_dio(module, peripheral, **kwargs):
|
||||||
edge_counter_cls=edge_counter_cls, **kwargs)
|
edge_counter_cls=edge_counter_cls, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def peripheral_dio_spi(module, peripheral, **kwargs):
|
||||||
|
ttl_classes = {
|
||||||
|
"input": ttl_serdes_7series.InOut_8X,
|
||||||
|
"output": ttl_serdes_7series.Output_8X
|
||||||
|
}
|
||||||
|
if len(peripheral["ports"]) != 1:
|
||||||
|
raise ValueError("peripheral dio_spi must be assigned one port")
|
||||||
|
spi = [(s["clk"], s.get("mosi"), s.get("miso"), s.get("cs", []))
|
||||||
|
for s in peripheral["spi"]]
|
||||||
|
ttl = [(t["pin"], ttl_classes[t["direction"]],
|
||||||
|
edge_counter.SimpleEdgeCounter if t.get("edge_counter") else None)
|
||||||
|
for t in peripheral.get("ttl", [])]
|
||||||
|
eem.DIO_SPI.add_std(module, peripheral["ports"][0], spi, ttl, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
def peripheral_urukul(module, peripheral, **kwargs):
|
def peripheral_urukul(module, peripheral, **kwargs):
|
||||||
if len(peripheral["ports"]) == 1:
|
if len(peripheral["ports"]) == 1:
|
||||||
port, port_aux = peripheral["ports"][0], None
|
port, port_aux = peripheral["ports"][0], None
|
||||||
|
@ -119,6 +134,7 @@ def peripheral_hvamp(module, peripheral, **kwargs):
|
||||||
|
|
||||||
peripheral_processors = {
|
peripheral_processors = {
|
||||||
"dio": peripheral_dio,
|
"dio": peripheral_dio,
|
||||||
|
"dio_spi": peripheral_dio_spi,
|
||||||
"urukul": peripheral_urukul,
|
"urukul": peripheral_urukul,
|
||||||
"novogorny": peripheral_novogorny,
|
"novogorny": peripheral_novogorny,
|
||||||
"sampler": peripheral_sampler,
|
"sampler": peripheral_sampler,
|
||||||
|
|
Loading…
Reference in New Issue