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
77
artiq/gateware/rtio/phy/ttl_serdes_nortio.py
Normal file
77
artiq/gateware/rtio/phy/ttl_serdes_nortio.py
Normal file
@ -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 artiq.gateware.rtio.phy import ttl_serdes_generic
|
||||
from artiq.gateware.rtio.phy import ttl_serdes_generic, ttl_serdes_nortio
|
||||
|
||||
|
||||
class _OSERDESE3(Module):
|
||||
@ -99,3 +99,23 @@ class InOut(ttl_serdes_generic.InOut):
|
||||
i_INTERMDISABLE=~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)
|
||||
|
||||
|
||||
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.
|
||||
"""
|
||||
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)
|
||||
|
||||
platform = self.platform
|
||||
@ -320,7 +320,13 @@ class Satellite(SatelliteBase):
|
||||
rtio_channels.append(rtio.Channel.from_phy(phy))
|
||||
for i in range(2):
|
||||
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)
|
||||
self.comb += mcx_io.direction.eq(1)
|
||||
else:
|
||||
@ -433,6 +439,8 @@ def main():
|
||||
"development and debugging.")
|
||||
parser.add_argument("--ttlout", default=False, action="store_true",
|
||||
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,
|
||||
help="Override ROM identifier")
|
||||
args = parser.parse_args()
|
||||
@ -443,6 +451,7 @@ def main():
|
||||
with_sfp=args.sfp,
|
||||
jdcg_type=args.jdcg_type,
|
||||
ttlout=args.ttlout,
|
||||
mcx_sqwave=args.mcx_sqwave,
|
||||
gateware_identifier_str=args.gateware_identifier_str,
|
||||
**soc_sayma_amc_argdict(args))
|
||||
elif variant == "simplesatellite":
|
||||
|
Loading…
Reference in New Issue
Block a user