2015-11-04 00:35:03 +08:00
|
|
|
from migen import *
|
2015-04-14 19:44:45 +08:00
|
|
|
from migen.genlib.cdc import MultiReg
|
2018-03-06 03:12:49 +08:00
|
|
|
from migen.genlib.io import DifferentialInput, DifferentialOutput
|
2015-04-14 19:44:45 +08:00
|
|
|
|
|
|
|
from artiq.gateware.rtio import rtlink
|
|
|
|
|
|
|
|
|
|
|
|
class Output(Module):
|
2018-03-06 03:12:49 +08:00
|
|
|
def __init__(self, pad, pad_n=None):
|
2015-04-14 19:44:45 +08:00
|
|
|
self.rtlink = rtlink.Interface(rtlink.OInterface(1))
|
2018-03-06 03:12:49 +08:00
|
|
|
pad_o = Signal(reset_less=True)
|
|
|
|
self.probes = [pad_o]
|
2015-06-09 19:51:02 +08:00
|
|
|
override_en = Signal()
|
|
|
|
override_o = Signal()
|
|
|
|
self.overrides = [override_en, override_o]
|
2015-04-14 19:44:45 +08:00
|
|
|
|
|
|
|
# # #
|
|
|
|
|
2015-06-09 19:51:02 +08:00
|
|
|
pad_k = Signal()
|
|
|
|
self.sync.rio_phy += [
|
|
|
|
If(self.rtlink.o.stb,
|
|
|
|
pad_k.eq(self.rtlink.o.data)
|
|
|
|
),
|
|
|
|
If(override_en,
|
2018-03-06 03:12:49 +08:00
|
|
|
pad_o.eq(override_o)
|
2015-06-09 19:51:02 +08:00
|
|
|
).Else(
|
2018-03-06 03:12:49 +08:00
|
|
|
pad_o.eq(pad_k)
|
2015-06-09 19:51:02 +08:00
|
|
|
)
|
|
|
|
]
|
2018-03-06 03:12:49 +08:00
|
|
|
if pad_n is None:
|
|
|
|
self.comb += pad.eq(pad_o)
|
|
|
|
else:
|
|
|
|
self.specials += DifferentialOutput(pad_o, pad, pad_n)
|
2015-04-14 19:44:45 +08:00
|
|
|
|
|
|
|
|
2016-10-10 22:12:28 +08:00
|
|
|
class Input(Module):
|
2018-03-06 03:12:49 +08:00
|
|
|
def __init__(self, pad, pad_n=None):
|
2016-10-10 22:12:28 +08:00
|
|
|
self.rtlink = rtlink.Interface(
|
|
|
|
rtlink.OInterface(2, 2),
|
|
|
|
rtlink.IInterface(1))
|
|
|
|
self.overrides = []
|
|
|
|
self.probes = []
|
|
|
|
|
2018-12-11 06:21:26 +08:00
|
|
|
#: Registered copy of the input state, in the rio_phy clock domain.
|
|
|
|
self.input_state = Signal()
|
|
|
|
|
2016-10-10 22:12:28 +08:00
|
|
|
# # #
|
|
|
|
|
|
|
|
sensitivity = Signal(2)
|
|
|
|
|
|
|
|
sample = Signal()
|
|
|
|
self.sync.rio += [
|
|
|
|
sample.eq(0),
|
|
|
|
If(self.rtlink.o.stb & self.rtlink.o.address[1],
|
|
|
|
sensitivity.eq(self.rtlink.o.data),
|
|
|
|
If(self.rtlink.o.address[0], sample.eq(1))
|
|
|
|
)
|
|
|
|
]
|
|
|
|
|
|
|
|
i = Signal()
|
2018-03-06 03:12:49 +08:00
|
|
|
i_d = Signal(reset_less=True)
|
|
|
|
pad_i = Signal()
|
|
|
|
if pad_n is None:
|
|
|
|
self.comb += pad_i.eq(pad)
|
|
|
|
else:
|
|
|
|
self.specials += DifferentialInput(pad, pad_n, pad_i)
|
|
|
|
self.specials += MultiReg(pad_i, i, "rio_phy")
|
2016-10-10 22:12:28 +08:00
|
|
|
self.sync.rio_phy += i_d.eq(i)
|
|
|
|
self.comb += [
|
|
|
|
self.rtlink.i.stb.eq(
|
|
|
|
sample |
|
|
|
|
(sensitivity[0] & ( i & ~i_d)) |
|
|
|
|
(sensitivity[1] & (~i & i_d))
|
|
|
|
),
|
2018-12-11 06:21:26 +08:00
|
|
|
self.rtlink.i.data.eq(i),
|
|
|
|
self.input_state.eq(i)
|
2016-10-10 22:12:28 +08:00
|
|
|
]
|
|
|
|
|
|
|
|
self.probes += [i]
|
|
|
|
|
|
|
|
|
2017-03-14 14:18:55 +08:00
|
|
|
class InOut(Module):
|
2015-04-14 19:44:45 +08:00
|
|
|
def __init__(self, pad):
|
|
|
|
self.rtlink = rtlink.Interface(
|
|
|
|
rtlink.OInterface(2, 2),
|
|
|
|
rtlink.IInterface(1))
|
2015-06-09 19:51:02 +08:00
|
|
|
override_en = Signal()
|
|
|
|
override_o = Signal()
|
|
|
|
override_oe = Signal()
|
|
|
|
self.overrides = [override_en, override_o, override_oe]
|
2015-06-02 17:41:40 +08:00
|
|
|
self.probes = []
|
2015-04-14 19:44:45 +08:00
|
|
|
|
2019-10-16 18:48:20 +08:00
|
|
|
# Output enable, for interfacing to external buffers.
|
|
|
|
self.oe = Signal()
|
2018-12-11 06:21:26 +08:00
|
|
|
# Registered copy of the input state, in the rio_phy clock domain.
|
|
|
|
self.input_state = Signal()
|
|
|
|
|
2015-04-14 19:44:45 +08:00
|
|
|
# # #
|
|
|
|
|
|
|
|
ts = TSTriple()
|
|
|
|
self.specials += ts.get_tristate(pad)
|
|
|
|
sensitivity = Signal(2)
|
|
|
|
|
2015-06-09 19:51:02 +08:00
|
|
|
o_k = Signal()
|
|
|
|
oe_k = Signal()
|
2019-10-16 18:48:20 +08:00
|
|
|
self.oe.attr.add("no_retiming")
|
2015-06-09 19:51:02 +08:00
|
|
|
self.sync.rio_phy += [
|
|
|
|
If(self.rtlink.o.stb,
|
|
|
|
If(self.rtlink.o.address == 0, o_k.eq(self.rtlink.o.data[0])),
|
|
|
|
If(self.rtlink.o.address == 1, oe_k.eq(self.rtlink.o.data[0])),
|
|
|
|
),
|
|
|
|
If(override_en,
|
|
|
|
ts.o.eq(override_o),
|
2019-10-16 18:48:20 +08:00
|
|
|
self.oe.eq(override_oe)
|
2015-06-09 19:51:02 +08:00
|
|
|
).Else(
|
|
|
|
ts.o.eq(o_k),
|
2019-10-16 18:48:20 +08:00
|
|
|
self.oe.eq(oe_k)
|
2015-05-02 16:17:31 +08:00
|
|
|
)
|
2015-06-09 19:51:02 +08:00
|
|
|
]
|
2019-10-16 18:48:20 +08:00
|
|
|
self.comb += ts.oe.eq(self.oe)
|
2016-09-07 15:42:09 +08:00
|
|
|
sample = Signal()
|
|
|
|
self.sync.rio += [
|
|
|
|
sample.eq(0),
|
|
|
|
If(self.rtlink.o.stb & self.rtlink.o.address[1],
|
|
|
|
sensitivity.eq(self.rtlink.o.data),
|
|
|
|
If(self.rtlink.o.address[0], sample.eq(1))
|
|
|
|
)
|
|
|
|
]
|
2015-04-14 19:44:45 +08:00
|
|
|
|
|
|
|
i = Signal()
|
|
|
|
i_d = Signal()
|
2015-05-02 11:47:11 +08:00
|
|
|
self.specials += MultiReg(ts.i, i, "rio_phy")
|
|
|
|
self.sync.rio_phy += i_d.eq(i)
|
2015-04-14 19:44:45 +08:00
|
|
|
self.comb += [
|
|
|
|
self.rtlink.i.stb.eq(
|
2016-09-07 15:42:09 +08:00
|
|
|
sample |
|
2015-04-14 19:44:45 +08:00
|
|
|
(sensitivity[0] & ( i & ~i_d)) |
|
|
|
|
(sensitivity[1] & (~i & i_d))
|
|
|
|
),
|
2018-12-11 06:21:26 +08:00
|
|
|
self.rtlink.i.data.eq(i),
|
|
|
|
self.input_state.eq(i)
|
2015-04-14 19:44:45 +08:00
|
|
|
]
|
2015-06-02 17:41:40 +08:00
|
|
|
|
|
|
|
self.probes += [i, ts.oe]
|
2015-07-03 00:20:26 +08:00
|
|
|
|
|
|
|
|
|
|
|
class ClockGen(Module):
|
2022-05-06 13:33:42 +08:00
|
|
|
def __init__(self, pad, pad_n=None, ftw_width=24, dci=False):
|
2016-03-10 09:47:29 +08:00
|
|
|
self.rtlink = rtlink.Interface(rtlink.OInterface(ftw_width))
|
2015-07-03 00:20:26 +08:00
|
|
|
|
|
|
|
# # #
|
|
|
|
|
2022-05-06 13:33:42 +08:00
|
|
|
pad_o = Signal()
|
|
|
|
if pad_n is None:
|
|
|
|
self.comb += pad.eq(pad_o)
|
|
|
|
else:
|
|
|
|
self.specials += DifferentialOutput(pad_o, pad, pad_n)
|
2015-07-03 00:20:26 +08:00
|
|
|
ftw = Signal(ftw_width)
|
|
|
|
acc = Signal(ftw_width)
|
|
|
|
self.sync.rio += If(self.rtlink.o.stb, ftw.eq(self.rtlink.o.data))
|
|
|
|
self.sync.rio_phy += [
|
|
|
|
acc.eq(acc + ftw),
|
2015-07-06 01:07:13 +08:00
|
|
|
# rtlink takes precedence over regular acc increments
|
2015-07-05 00:36:01 +08:00
|
|
|
If(self.rtlink.o.stb,
|
|
|
|
If(self.rtlink.o.data != 0,
|
|
|
|
# known phase on frequency write: at rising edge
|
|
|
|
acc.eq(2**(ftw_width - 1))
|
|
|
|
).Else(
|
|
|
|
# set output to 0 on stop
|
|
|
|
acc.eq(0)
|
|
|
|
)
|
|
|
|
),
|
2022-05-06 13:33:42 +08:00
|
|
|
pad_o.eq(acc[-1])
|
2015-07-03 00:20:26 +08:00
|
|
|
]
|