From f8c2d54e75bb28f1c0f1ab885aaf3a9d2ee02617 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Wed, 21 Mar 2018 13:01:38 +0800 Subject: [PATCH] ttl_serdes_ultrascale: configurable SERDES ratio. Also try X4 on Sayma --- .../rtio/phy/ttl_serdes_ultrascale.py | 55 +++++++++---------- artiq/gateware/targets/sayma_amc.py | 22 ++++---- 2 files changed, 39 insertions(+), 38 deletions(-) diff --git a/artiq/gateware/rtio/phy/ttl_serdes_ultrascale.py b/artiq/gateware/rtio/phy/ttl_serdes_ultrascale.py index 33afb9afd..c9e47fcf8 100644 --- a/artiq/gateware/rtio/phy/ttl_serdes_ultrascale.py +++ b/artiq/gateware/rtio/phy/ttl_serdes_ultrascale.py @@ -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) diff --git a/artiq/gateware/targets/sayma_amc.py b/artiq/gateware/targets/sayma_amc.py index 2abd9786c..b5ca73c06 100755 --- a/artiq/gateware/targets/sayma_amc.py +++ b/artiq/gateware/targets/sayma_amc.py @@ -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))