diff --git a/artiq/build_soc.py b/artiq/build_soc.py index 7c1f49e8d..483860d62 100644 --- a/artiq/build_soc.py +++ b/artiq/build_soc.py @@ -1,7 +1,8 @@ import os import subprocess -from misoc.cores import identifier +from migen import * +from misoc.interconnect.csr import * from misoc.integration.builder import * from artiq.gateware.amp import AMPSoC @@ -22,11 +23,39 @@ def get_identifier_string(soc, suffix="", add_class_name=True): return r +class ReprogrammableIdentifier(Module, AutoCSR): + def __init__(self, ident): + self.address = CSRStorage(8) + self.data = CSRStatus(8) + + contents = list(ident.encode()) + l = len(contents) + if l > 255: + raise ValueError("Identifier string must be 255 characters or less") + contents.insert(0, l) + + init_params = {i: 0 for i in range(0x40)} + for i, c in enumerate(contents): + # 0x38 was determined empirically. Another Xilinx mystery. + row = 0x38 + i//32 + col = 8*(i % 32) + init_params[row] |= c << col + init_params = {"p_INIT_{:02X}".format(k): v for k, v in init_params.items()} + + self.specials += Instance("RAMB18E1", name="identifier_str", + i_ADDRARDADDR=Cat(C(0, 3), self.address.storage), + i_CLKARDCLK=ClockSignal(), + o_DOADO=self.data.status, + i_ENARDEN=1, + p_READ_WIDTH_A=9, + **init_params) + + def add_identifier(soc, *args, **kwargs): if hasattr(soc, "identifier"): raise ValueError identifier_str = get_identifier_string(soc, *args, **kwargs) - soc.submodules.identifier = identifier.Identifier(identifier_str) + soc.submodules.identifier = ReprogrammableIdentifier(identifier_str) soc.config["IDENTIFIER_STR"] = identifier_str