ttl_serdes_ultrascale: configurable SERDES ratio. Also try X4 on Sayma

This commit is contained in:
Sebastien Bourdeauducq 2018-03-21 13:01:38 +08:00
parent 9c2d343052
commit f8c2d54e75
2 changed files with 39 additions and 38 deletions

View File

@ -6,10 +6,9 @@ from artiq.gateware.rtio.phy import ttl_serdes_generic
# SERDES clocks are in dedicated domains to make the implementation
# of the convoluted clocking schemes from AR#67885 less tedious.
class _OSERDESE2_8X(Module):
def __init__(self, pad, pad_n=None):
self.o = Signal(8)
class _OSERDESE3(Module):
def __init__(self, dw, pad, pad_n=None):
self.o = Signal(dw)
self.t_in = Signal()
self.t_out = Signal()
@ -17,12 +16,12 @@ class _OSERDESE2_8X(Module):
pad_o = Signal()
self.specials += Instance("OSERDESE3",
p_DATA_WIDTH=8, p_INIT=0,
p_DATA_WIDTH=dw, p_INIT=0,
p_IS_CLK_INVERTED=0, p_IS_CLKDIV_INVERTED=0, p_IS_RST_INVERTED=0,
o_OQ=pad_o, o_T_OUT=self.t_out,
i_RST=ResetSignal("rtio_serdes"),
i_CLK=ClockSignal("rtiox4_serdes"), i_CLKDIV=ClockSignal("rtio_serdes"),
i_CLK=ClockSignal("rtiox_serdes"), i_CLKDIV=ClockSignal("rtio_serdes"),
i_D=self.o, i_T=self.t_in)
if pad_n is None:
self.comb += pad.eq(pad_o)
@ -35,10 +34,10 @@ class _OSERDESE2_8X(Module):
io_IO=pad, io_IOB=pad_n)
class _ISERDESE2_8X(Module):
def __init__(self, pad, pad_n=None):
self.o = Signal(8)
self.i = Signal(8)
class _ISERDESE3(Module):
def __init__(self, dw, pad, pad_n=None):
self.o = Signal(dw)
self.i = Signal(dw)
self.oe = Signal()
# # #
@ -47,15 +46,15 @@ class _ISERDESE2_8X(Module):
self.specials += Instance("ISERDESE3",
p_IS_CLK_INVERTED=0,
p_IS_CLK_B_INVERTED=1,
p_DATA_WIDTH=8,
p_DATA_WIDTH=dw,
i_D=pad_i,
i_RST=ResetSignal("rtio_serdes"),
i_FIFO_RD_EN=0,
i_CLK=ClockSignal("rtiox4_serdes"),
i_CLK_B=ClockSignal("rtiox4_serdes"), # locally inverted
i_CLK=ClockSignal("rtiox_serdes"),
i_CLK_B=ClockSignal("rtiox_serdes"), # locally inverted
i_CLKDIV=ClockSignal("rtio_serdes"),
o_Q=Cat(*self.i[::-1]))
o_Q=Cat(*[self.i[i] for i in reversed(range(dw))]))
if pad_n is None:
self.comb += pad_i.eq(pad)
else:
@ -66,18 +65,18 @@ class _ISERDESE2_8X(Module):
io_I=pad, io_IB=pad_n)
class _IOSERDESE2_8X(Module):
def __init__(self, pad, pad_n=None):
self.o = Signal(8)
self.i = Signal(8)
class _IOSERDESE3(Module):
def __init__(self, dw, pad, pad_n=None):
self.o = Signal(dw)
self.i = Signal(dw)
self.oe = Signal()
# # #
pad_i = Signal()
pad_o = Signal()
iserdes = _ISERDESE2_8X(pad_i)
oserdes = _OSERDESE2_8X(pad_o)
iserdes = _ISERDESE3(dw, pad_i)
oserdes = _OSERDESE3(dw, pad_o)
self.submodules += iserdes, oserdes
if pad_n is None:
self.specials += Instance("IOBUF",
@ -96,22 +95,22 @@ class _IOSERDESE2_8X(Module):
]
class Output_8X(ttl_serdes_generic.Output):
def __init__(self, pad, pad_n=None):
serdes = _OSERDESE2_8X(pad, pad_n)
class Output(ttl_serdes_generic.Output):
def __init__(self, dw, pad, pad_n=None):
serdes = _OSERDESE3(dw, pad, pad_n)
self.submodules += serdes
ttl_serdes_generic.Output.__init__(self, serdes)
class InOut_8X(ttl_serdes_generic.InOut):
def __init__(self, pad, pad_n=None):
serdes = _IOSERDESE2_8X(pad, pad_n)
class InOut(ttl_serdes_generic.InOut):
def __init__(self, dw, pad, pad_n=None):
serdes = _IOSERDESE3(dw, pad, pad_n)
self.submodules += serdes
ttl_serdes_generic.InOut.__init__(self, serdes)
class Input_8X(ttl_serdes_generic.InOut):
class Input(ttl_serdes_generic.InOut):
def __init__(self, pad, pad_n=None):
serdes = _ISERDESE2_8X(pad, pad_n)
serdes = _ISERDESE3(dw, pad, pad_n)
self.submodules += serdes
ttl_serdes_generic.InOut.__init__(self, serdes)

View File

@ -126,17 +126,18 @@ class AD9154NoSAWG(Module, AutoCSR):
for i in range(len(conv) // len(ramp))))
# Generates a X2 clock that can be used for 4:1 SERDES ratio.
class _RTIOClockMultiplier(Module):
def __init__(self, platform, rtio_clk_freq):
self.clock_domains.cd_rtio_serdes = ClockDomain()
self.clock_domains.cd_rtiox4_serdes = ClockDomain(reset_less=True)
self.clock_domains.cd_rtiox_serdes = ClockDomain(reset_less=True)
# See "Global Clock Network Deskew Using Two BUFGs" in ug572.
# See also AR#67885.
clkfbout = Signal()
clkfbin = Signal()
rtio_clk = Signal()
rtiox4_clk = Signal()
rtiox_clk = Signal()
self.specials += [
Instance("MMCME2_BASE",
p_CLKIN1_PERIOD=1e9/rtio_clk_freq,
@ -148,14 +149,14 @@ class _RTIOClockMultiplier(Module):
o_CLKFBOUT=clkfbout, i_CLKFBIN=clkfbin,
p_CLKOUT1_DIVIDE=8, o_CLKOUT1=rtio_clk,
p_CLKOUT2_DIVIDE=2, o_CLKOUT2=rtiox4_clk,
p_CLKOUT2_DIVIDE=4, o_CLKOUT2=rtiox_clk,
),
Instance("BUFG", name="rtioserdes_bufg_fb",
i_I=clkfbout, o_O=clkfbin),
Instance("BUFG", name="rtioserdes_bufg_div",
i_I=rtio_clk, o_O=self.cd_rtio_serdes.clk),
Instance("BUFG", name="rtioserdes_bufg",
i_I=rtiox4_clk, o_O=self.cd_rtiox4_serdes.clk)
i_I=rtiox_clk, o_O=self.cd_rtiox_serdes.clk)
]
self.comb += self.cd_rtio_serdes.rst.eq(ResetSignal("rio_phy"))
@ -238,6 +239,7 @@ class Standalone(MiniSoC, AMPSoC):
self.add_wb_slave(self.mem_map["serwb"], 8192, serwb_core.etherbone.wishbone.bus)
# RTIO
self.submodules.rtio_clkmul = _RTIOClockMultiplier(platform, 150e6)
rtio_channels = []
for i in range(4):
phy = ttl_simple.Output(platform.request("user_led", i))
@ -245,12 +247,12 @@ class Standalone(MiniSoC, AMPSoC):
rtio_channels.append(rtio.Channel.from_phy(phy))
sma_io = platform.request("sma_io", 0)
self.comb += sma_io.direction.eq(1)
phy = ttl_simple.Output(sma_io.level)
phy = ttl_serdes_ultrascale.Output(4, sma_io.level)
self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy))
sma_io = platform.request("sma_io", 1)
self.comb += sma_io.direction.eq(0)
phy = ttl_simple.InOut(sma_io.level)
phy = ttl_serdes_ultrascale.InOut(4, sma_io.level)
self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy))
@ -396,12 +398,12 @@ class Master(MiniSoC, AMPSoC):
rtio_channels.append(rtio.Channel.from_phy(phy))
sma_io = platform.request("sma_io", 0)
self.comb += sma_io.direction.eq(1)
phy = ttl_serdes_ultrascale.Output_8X(sma_io.level)
phy = ttl_serdes_ultrascale.Output(4, sma_io.level)
self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy))
sma_io = platform.request("sma_io", 1)
self.comb += sma_io.direction.eq(0)
phy = ttl_serdes_ultrascale.InOut_8X(sma_io.level)
phy = ttl_serdes_ultrascale.InOut(4, sma_io.level)
self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy))
@ -453,12 +455,12 @@ class Satellite(BaseSoC):
rtio_channels.append(rtio.Channel.from_phy(phy))
sma_io = platform.request("sma_io", 0)
self.comb += sma_io.direction.eq(1)
phy = ttl_serdes_ultrascale.Output_8X(sma_io.level)
phy = ttl_serdes_ultrascale.Output(4, sma_io.level)
self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy))
sma_io = platform.request("sma_io", 1)
self.comb += sma_io.direction.eq(0)
phy = ttl_serdes_ultrascale.InOut_8X(sma_io.level)
phy = ttl_serdes_ultrascale.InOut(4, sma_io.level)
self.submodules += phy
rtio_channels.append(rtio.Channel.from_phy(phy))