artiq/artiq/gateware/rtio/phy/ttl_serdes_generic.py

118 lines
3.6 KiB
Python
Raw Normal View History

2015-11-04 00:35:03 +08:00
from migen import *
2015-07-26 17:40:18 +08:00
from migen.genlib.coding import PriorityEncoder
2015-07-27 00:01:41 +08:00
from artiq.gateware.rtio import rtlink
2015-07-26 17:40:18 +08:00
2015-07-27 00:01:41 +08:00
def _mk_edges(w, direction):
l = [(1 << i) - 1 for i in range(w)]
if direction == "rising":
l = [2**w - 1 ^ x for x in l]
elif direction == "falling":
pass
else:
raise ValueError
return l
2015-07-26 17:40:18 +08:00
2015-07-27 00:01:41 +08:00
class _SerdesDriver(Module):
def __init__(self, serdes_o, stb, data, fine_ts, override_en, override_o):
previous_data = Signal()
2015-11-04 00:35:03 +08:00
serdes_width = len(serdes_o)
2015-07-27 00:01:41 +08:00
edges = Array(_mk_edges(serdes_width, "rising"))
edges_n = Array(_mk_edges(serdes_width, "falling"))
self.sync.rio_phy += [
If(stb, previous_data.eq(data)),
If(override_en,
serdes_o.eq(Replicate(override_o, serdes_width))
).Else(
If(stb & ~previous_data & data,
serdes_o.eq(edges[fine_ts]),
).Elif(stb & previous_data & ~data,
serdes_o.eq(edges_n[fine_ts]),
2015-07-26 17:40:18 +08:00
).Else(
2015-07-27 00:01:41 +08:00
serdes_o.eq(Replicate(previous_data, serdes_width)),
2015-07-26 17:40:18 +08:00
)
2015-07-27 00:01:41 +08:00
)
2015-07-26 17:40:18 +08:00
]
2015-07-27 00:01:41 +08:00
class Output(Module):
def __init__(self, serdes):
self.rtlink = rtlink.Interface(
2015-11-04 00:35:03 +08:00
rtlink.OInterface(1, fine_ts_width=log2_int(len(serdes.o))))
2015-07-27 00:01:41 +08:00
self.probes = [serdes.o[-1]]
override_en = Signal()
override_o = Signal()
self.overrides = [override_en, override_o]
# # #
self.submodules += _SerdesDriver(
serdes.o,
self.rtlink.o.stb, self.rtlink.o.data, self.rtlink.o.fine_ts,
override_en, override_o)
2015-07-26 17:40:18 +08:00
2017-03-14 14:18:55 +08:00
class InOut(Module):
2015-07-27 00:01:41 +08:00
def __init__(self, serdes):
2015-11-04 00:35:03 +08:00
serdes_width = len(serdes.o)
assert len(serdes.i) == serdes_width
2015-07-26 17:40:18 +08:00
self.rtlink = rtlink.Interface(
2015-07-27 00:01:41 +08:00
rtlink.OInterface(2, 2, fine_ts_width=log2_int(serdes_width)),
rtlink.IInterface(1, fine_ts_width=log2_int(serdes_width)))
self.probes = [serdes.i[-1], serdes.oe]
2015-07-26 17:40:18 +08:00
override_en = Signal()
override_o = Signal()
override_oe = Signal()
self.overrides = [override_en, override_o, override_oe]
2015-07-27 00:01:41 +08:00
# # #
# Output
self.submodules += _SerdesDriver(
serdes_o=serdes.o,
stb=self.rtlink.o.stb & (self.rtlink.o.address == 0),
data=self.rtlink.o.data[0],
fine_ts=self.rtlink.o.fine_ts,
override_en=override_en, override_o=override_o)
oe_k = Signal()
2015-07-26 17:40:18 +08:00
self.sync.rio_phy += [
2015-07-27 00:01:41 +08:00
If(self.rtlink.o.stb & (self.rtlink.o.address == 1),
oe_k.eq(self.rtlink.o.data[0])),
2015-07-26 17:40:18 +08:00
If(override_en,
2015-07-27 00:01:41 +08:00
serdes.oe.eq(override_oe)
).Else(
serdes.oe.eq(oe_k)
)
2015-07-26 17:40:18 +08:00
]
2015-07-27 00:01:41 +08:00
# Input
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))
)
]
2015-07-27 00:01:41 +08:00
i = serdes.i[-1]
i_d = Signal()
self.sync.rio_phy += [
i_d.eq(i),
self.rtlink.i.stb.eq(
sample |
2015-07-27 00:01:41 +08:00
(sensitivity[0] & ( i & ~i_d)) |
(sensitivity[1] & (~i & i_d))
),
self.rtlink.i.data.eq(i),
2015-07-26 17:40:18 +08:00
]
2015-07-27 00:01:41 +08:00
pe = PriorityEncoder(serdes_width)
self.submodules += pe
self.comb += pe.i.eq(serdes.i ^ Replicate(i_d, serdes_width))
self.sync.rio_phy += self.rtlink.i.fine_ts.eq(pe.o)