forked from M-Labs/artiq
sayma_amc: add option to generate a 9MHz sq wave on the MCXs
This commit is contained in:
parent
86fcd97416
commit
f49f1fcbfc
|
@ -0,0 +1,77 @@
|
||||||
|
from migen import *
|
||||||
|
from migen.genlib.coding import PriorityEncoder
|
||||||
|
|
||||||
|
from artiq.gateware.rtio import rtlink
|
||||||
|
|
||||||
|
|
||||||
|
def _mk_edges(w, direction):
|
||||||
|
l = [(1 << i) - 1 for i in range(w)]
|
||||||
|
if direction == "rising":
|
||||||
|
l = [((1 << w) - 1) ^ x for x in l]
|
||||||
|
elif direction == "falling":
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
raise ValueError
|
||||||
|
return l
|
||||||
|
|
||||||
|
|
||||||
|
class _SerdesSquareWaveDriver(Module):
|
||||||
|
def __init__(self, serdes_o, rtio_freq, wave_freq):
|
||||||
|
assert wave_freq <= rtio_freq
|
||||||
|
serdes_width = len(serdes_o)
|
||||||
|
assert serdes_width & (serdes_width-1) == 0 # serdes_width must be 2**n
|
||||||
|
|
||||||
|
edges = Array(_mk_edges(serdes_width, "rising"))
|
||||||
|
edges_n = Array(_mk_edges(serdes_width, "falling"))
|
||||||
|
|
||||||
|
phase_accumulator = Signal(32)
|
||||||
|
tuning_word = int((wave_freq/rtio_freq) * 2**32)
|
||||||
|
|
||||||
|
fine_ts = Signal() # indicates which rtiox period within the
|
||||||
|
# current rtio period should the edge be changed
|
||||||
|
logic_level = Signal(reset=1)
|
||||||
|
logic_level_d = Signal(reset=1)
|
||||||
|
self.comb += [
|
||||||
|
fine_ts.eq(phase_accumulator[-log2_int(serdes_width):]),
|
||||||
|
logic_level.eq(~phase_accumulator[-1]),
|
||||||
|
]
|
||||||
|
# Using CD rio such that RtioInitRequest
|
||||||
|
# resets the phase accumulator and logic level registers
|
||||||
|
# (Refer to :class:`artiq.gateware.rtio.core.Core`)
|
||||||
|
self.sync.rio += [
|
||||||
|
logic_level_d.eq(logic_level),
|
||||||
|
If(~logic_level_d & logic_level,
|
||||||
|
serdes_o.eq(edges[fine_ts]),
|
||||||
|
).Elif(logic_level_d & ~logic_level,
|
||||||
|
serdes_o.eq(edges_n[fine_ts]),
|
||||||
|
).Else(
|
||||||
|
serdes_o.eq(Replicate(logic_level_d, serdes_width)),
|
||||||
|
),
|
||||||
|
phase_accumulator.eq(phase_accumulator + tuning_word),
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
SEDRES_DRIVER_TYPES = {
|
||||||
|
"square_wave": _SerdesSquareWaveDriver,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class Output(Module):
|
||||||
|
def __init__(self, serdes, driver_type, **kwargs):
|
||||||
|
assert driver_type in SEDRES_DRIVER_TYPES.keys()
|
||||||
|
|
||||||
|
# Include an unused, dummy rtlink interface just to consume an RTIO channel
|
||||||
|
self.rtlink = rtlink.Interface(
|
||||||
|
rtlink.OInterface(1, fine_ts_width=log2_int(len(serdes.o))))
|
||||||
|
self.probes = [Signal()]
|
||||||
|
self.overrides = [Signal(), Signal()]
|
||||||
|
|
||||||
|
# # #
|
||||||
|
|
||||||
|
self.submodules += SEDRES_DRIVER_TYPES[driver_type](
|
||||||
|
serdes.o, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class InOut(Module):
|
||||||
|
def __init__(self, serdes):
|
||||||
|
raise NotImplementedError()
|
|
@ -1,6 +1,6 @@
|
||||||
from migen import *
|
from migen import *
|
||||||
|
|
||||||
from artiq.gateware.rtio.phy import ttl_serdes_generic
|
from artiq.gateware.rtio.phy import ttl_serdes_generic, ttl_serdes_nortio
|
||||||
|
|
||||||
|
|
||||||
class _OSERDESE3(Module):
|
class _OSERDESE3(Module):
|
||||||
|
@ -99,3 +99,23 @@ class InOut(ttl_serdes_generic.InOut):
|
||||||
i_INTERMDISABLE=~serdes.t_out,
|
i_INTERMDISABLE=~serdes.t_out,
|
||||||
i_I=serdes.ser_out, o_O=serdes.ser_in, i_T=serdes.t_out,
|
i_I=serdes.ser_out, o_O=serdes.ser_in, i_T=serdes.t_out,
|
||||||
io_IO=pad, io_IOB=pad_n)
|
io_IO=pad, io_IOB=pad_n)
|
||||||
|
|
||||||
|
|
||||||
|
class CustomOutput(ttl_serdes_nortio.Output):
|
||||||
|
def __init__(self, dw, pad, pad_n=None, dci=False, **kwargs):
|
||||||
|
serdes = _OSERDESE3(dw)
|
||||||
|
self.submodules += serdes
|
||||||
|
ttl_serdes_nortio.Output.__init__(self, serdes, **kwargs)
|
||||||
|
|
||||||
|
if pad_n is None:
|
||||||
|
self.comb += pad.eq(serdes.ser_out)
|
||||||
|
else:
|
||||||
|
self.specials += Instance("IOBUFDS",
|
||||||
|
i_I=serdes.ser_out,
|
||||||
|
i_T=serdes.t_out,
|
||||||
|
io_IO=pad, io_IOB=pad_n)
|
||||||
|
|
||||||
|
|
||||||
|
class CustomInOut(ttl_serdes_nortio.InOut):
|
||||||
|
def __init__(self, dw, pad, pad_n=None, dci=False, **kwargs):
|
||||||
|
raise NotImplementedError()
|
||||||
|
|
|
@ -294,7 +294,7 @@ class Satellite(SatelliteBase):
|
||||||
"""
|
"""
|
||||||
DRTIO satellite with local DAC/SAWG channels, as well as TTL channels via FMC and VHDCI carrier.
|
DRTIO satellite with local DAC/SAWG channels, as well as TTL channels via FMC and VHDCI carrier.
|
||||||
"""
|
"""
|
||||||
def __init__(self, jdcg_type, ttlout=False, **kwargs):
|
def __init__(self, jdcg_type, ttlout=False, mcx_sqwave=False, **kwargs):
|
||||||
SatelliteBase.__init__(self, identifier_suffix="." + jdcg_type, **kwargs)
|
SatelliteBase.__init__(self, identifier_suffix="." + jdcg_type, **kwargs)
|
||||||
|
|
||||||
platform = self.platform
|
platform = self.platform
|
||||||
|
@ -320,7 +320,13 @@ class Satellite(SatelliteBase):
|
||||||
rtio_channels.append(rtio.Channel.from_phy(phy))
|
rtio_channels.append(rtio.Channel.from_phy(phy))
|
||||||
for i in range(2):
|
for i in range(2):
|
||||||
mcx_io = platform.request("mcx_io", i)
|
mcx_io = platform.request("mcx_io", i)
|
||||||
if ttlout:
|
if mcx_sqwave:
|
||||||
|
phy = ttl_serdes_ultrascale.CustomOutput(4, mcx_io.level,
|
||||||
|
driver_type="square_wave",
|
||||||
|
rtio_freq=self.rtio_clk_freq,
|
||||||
|
wave_freq=9e6)
|
||||||
|
self.comb += mcx_io.direction.eq(1)
|
||||||
|
elif ttlout:
|
||||||
phy = ttl_serdes_ultrascale.Output(4, mcx_io.level)
|
phy = ttl_serdes_ultrascale.Output(4, mcx_io.level)
|
||||||
self.comb += mcx_io.direction.eq(1)
|
self.comb += mcx_io.direction.eq(1)
|
||||||
else:
|
else:
|
||||||
|
@ -433,6 +439,8 @@ def main():
|
||||||
"development and debugging.")
|
"development and debugging.")
|
||||||
parser.add_argument("--ttlout", default=False, action="store_true",
|
parser.add_argument("--ttlout", default=False, action="store_true",
|
||||||
help="force only outputs on the MCX TTL IOs")
|
help="force only outputs on the MCX TTL IOs")
|
||||||
|
parser.add_argument("--mcx-sqwave", default=False, action="store_true",
|
||||||
|
help="generate a square wave on the MCX TTL IOs")
|
||||||
parser.add_argument("--gateware-identifier-str", default=None,
|
parser.add_argument("--gateware-identifier-str", default=None,
|
||||||
help="Override ROM identifier")
|
help="Override ROM identifier")
|
||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
|
@ -443,6 +451,7 @@ def main():
|
||||||
with_sfp=args.sfp,
|
with_sfp=args.sfp,
|
||||||
jdcg_type=args.jdcg_type,
|
jdcg_type=args.jdcg_type,
|
||||||
ttlout=args.ttlout,
|
ttlout=args.ttlout,
|
||||||
|
mcx_sqwave=args.mcx_sqwave,
|
||||||
gateware_identifier_str=args.gateware_identifier_str,
|
gateware_identifier_str=args.gateware_identifier_str,
|
||||||
**soc_sayma_amc_argdict(args))
|
**soc_sayma_amc_argdict(args))
|
||||||
elif variant == "simplesatellite":
|
elif variant == "simplesatellite":
|
||||||
|
|
Loading…
Reference in New Issue