Kasli JSON description for SPI over DIO cards (#1800)

This commit is contained in:
Leon Riesebos 2022-02-25 18:36:00 -05:00 committed by GitHub
parent 2b918ac6f7
commit c4292770f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 206 additions and 8 deletions

View File

@ -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:

View File

@ -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": {

View File

@ -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,12 +116,51 @@ 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"]

View File

@ -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):

View File

@ -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,