forked from M-Labs/artiq
1
0
Fork 0

gateware/serwb: move all clocking outside of serwb, use existing sys/sys4x clocks

This commit is contained in:
Florent Kermarrec 2018-04-03 18:48:08 +02:00
parent efbe915b24
commit 3248caa184
3 changed files with 59 additions and 135 deletions

View File

@ -7,7 +7,10 @@ from misoc.cores.code_8b10b import Encoder, Decoder
class KUSSerdes(Module): class KUSSerdes(Module):
def __init__(self, pll, pads, mode="master"): def __init__(self, pads, mode="master"):
if mode == "slave":
self.refclk = Signal()
self.tx_k = Signal(4) self.tx_k = Signal(4)
self.tx_d = Signal(32) self.tx_d = Signal(32)
self.rx_k = Signal(4) self.rx_k = Signal(4)
@ -26,29 +29,18 @@ class KUSSerdes(Module):
# # # # # #
self.submodules.encoder = ClockDomainsRenamer("serwb_serdes")( self.submodules.encoder = ClockDomainsRenamer("sys0p2x")(
Encoder(4, True)) Encoder(4, True))
self.decoders = [ClockDomainsRenamer("serwb_serdes")( self.decoders = [ClockDomainsRenamer("sys0p2x")(
Decoder(True)) for _ in range(4)] Decoder(True)) for _ in range(4)]
self.submodules += self.decoders self.submodules += self.decoders
# clocking: # clocking:
# In master mode: # In master mode:
# - linerate/10 pll refclk provided by user # - linerate/10 refclk generated on clk_pads
# - linerate/10 slave refclk generated on clk_pads
# In Slave mode: # In Slave mode:
# - linerate/10 pll refclk provided by clk_pads # - linerate/10 refclk provided by clk_pads
self.clock_domains.cd_serwb_serdes = ClockDomain()
self.clock_domains.cd_serwb_serdes_5x = ClockDomain()
self.clock_domains.cd_serwb_serdes_20x = ClockDomain(reset_less=True)
self.comb += [
self.cd_serwb_serdes.clk.eq(pll.serwb_serdes_clk),
self.cd_serwb_serdes_5x.clk.eq(pll.serwb_serdes_5x_clk),
self.cd_serwb_serdes_20x.clk.eq(pll.serwb_serdes_20x_clk)
]
self.specials += AsyncResetSynchronizer(self.cd_serwb_serdes, ~pll.lock)
self.comb += self.cd_serwb_serdes_5x.rst.eq(self.cd_serwb_serdes.rst)
# control/status cdc # control/status cdc
tx_idle = Signal() tx_idle = Signal()
@ -61,20 +53,20 @@ class KUSSerdes(Module):
rx_delay_en_vtc = Signal() rx_delay_en_vtc = Signal()
rx_delay_ce = Signal() rx_delay_ce = Signal()
self.specials += [ self.specials += [
MultiReg(self.tx_idle, tx_idle, "serwb_serdes"), MultiReg(self.tx_idle, tx_idle, "sys0p2x"),
MultiReg(self.tx_comma, tx_comma, "serwb_serdes"), MultiReg(self.tx_comma, tx_comma, "sys0p2x"),
MultiReg(rx_idle, self.rx_idle, "sys"), MultiReg(rx_idle, self.rx_idle, "sys"),
MultiReg(rx_comma, self.rx_comma, "sys"), MultiReg(rx_comma, self.rx_comma, "sys"),
MultiReg(self.rx_bitslip_value, rx_bitslip_value, "serwb_serdes"), MultiReg(self.rx_bitslip_value, rx_bitslip_value, "sys0p2x"),
MultiReg(self.rx_delay_inc, rx_delay_inc, "serwb_serdes_5x"), MultiReg(self.rx_delay_inc, rx_delay_inc, "sys"),
MultiReg(self.rx_delay_en_vtc, rx_delay_en_vtc, "serwb_serdes_5x") MultiReg(self.rx_delay_en_vtc, rx_delay_en_vtc, "sys")
] ]
self.submodules.do_rx_delay_rst = PulseSynchronizer("sys", "serwb_serdes_5x") self.submodules.do_rx_delay_rst = PulseSynchronizer("sys", "sys")
self.comb += [ self.comb += [
rx_delay_rst.eq(self.do_rx_delay_rst.o), rx_delay_rst.eq(self.do_rx_delay_rst.o),
self.do_rx_delay_rst.i.eq(self.rx_delay_rst) self.do_rx_delay_rst.i.eq(self.rx_delay_rst)
] ]
self.submodules.do_rx_delay_ce = PulseSynchronizer("sys", "serwb_serdes_5x") self.submodules.do_rx_delay_ce = PulseSynchronizer("sys", "sys")
self.comb += [ self.comb += [
rx_delay_ce.eq(self.do_rx_delay_ce.o), rx_delay_ce.eq(self.do_rx_delay_ce.o),
self.do_rx_delay_ce.i.eq(self.rx_delay_ce) self.do_rx_delay_ce.i.eq(self.rx_delay_ce)
@ -82,7 +74,7 @@ class KUSSerdes(Module):
# tx clock (linerate/10) # tx clock (linerate/10)
if mode == "master": if mode == "master":
self.submodules.tx_clk_gearbox = Gearbox(40, "serwb_serdes", 8, "serwb_serdes_5x") self.submodules.tx_clk_gearbox = Gearbox(40, "sys0p2x", 8, "sys")
self.comb += self.tx_clk_gearbox.i.eq((0b1111100000 << 30) | self.comb += self.tx_clk_gearbox.i.eq((0b1111100000 << 30) |
(0b1111100000 << 20) | (0b1111100000 << 20) |
(0b1111100000 << 10) | (0b1111100000 << 10) |
@ -94,8 +86,8 @@ class KUSSerdes(Module):
p_IS_CLK_INVERTED=0, p_IS_CLKDIV_INVERTED=0, p_IS_RST_INVERTED=0, p_IS_CLK_INVERTED=0, p_IS_CLKDIV_INVERTED=0, p_IS_RST_INVERTED=0,
o_OQ=clk_o, o_OQ=clk_o,
i_RST=ResetSignal("serwb_serdes"), i_RST=ResetSignal("sys"),
i_CLK=ClockSignal("serwb_serdes_20x"), i_CLKDIV=ClockSignal("serwb_serdes_5x"), i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal("sys"),
i_D=self.tx_clk_gearbox.o i_D=self.tx_clk_gearbox.o
), ),
Instance("OBUFDS", Instance("OBUFDS",
@ -107,7 +99,7 @@ class KUSSerdes(Module):
# tx datapath # tx datapath
# tx_data -> encoders -> gearbox -> serdes # tx_data -> encoders -> gearbox -> serdes
self.submodules.tx_gearbox = Gearbox(40, "serwb_serdes", 8, "serwb_serdes_5x") self.submodules.tx_gearbox = Gearbox(40, "sys0p2x", 8, "sys")
self.comb += [ self.comb += [
If(tx_comma, If(tx_comma,
self.encoder.k[0].eq(1), self.encoder.k[0].eq(1),
@ -123,7 +115,7 @@ class KUSSerdes(Module):
self.encoder.d[3].eq(self.tx_d[24:32]) self.encoder.d[3].eq(self.tx_d[24:32])
) )
] ]
self.sync.serwb_serdes += \ self.sync.sys0p2x += \
If(tx_idle, If(tx_idle,
self.tx_gearbox.i.eq(0) self.tx_gearbox.i.eq(0)
).Else( ).Else(
@ -137,8 +129,8 @@ class KUSSerdes(Module):
p_IS_CLK_INVERTED=0, p_IS_CLKDIV_INVERTED=0, p_IS_RST_INVERTED=0, p_IS_CLK_INVERTED=0, p_IS_CLKDIV_INVERTED=0, p_IS_RST_INVERTED=0,
o_OQ=serdes_o, o_OQ=serdes_o,
i_RST=ResetSignal("serwb_serdes"), i_RST=ResetSignal("sys"),
i_CLK=ClockSignal("serwb_serdes_20x"), i_CLKDIV=ClockSignal("serwb_serdes_5x"), i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal("sys"),
i_D=self.tx_gearbox.o i_D=self.tx_gearbox.o
), ),
Instance("OBUFDS", Instance("OBUFDS",
@ -168,12 +160,12 @@ class KUSSerdes(Module):
] ]
else: else:
self.specials += Instance("BUFG", i_I=clk_i, o_O=clk_i_bufg) self.specials += Instance("BUFG", i_I=clk_i, o_O=clk_i_bufg)
self.comb += pll.refclk.eq(clk_i_bufg) self.comb += self.refclk.eq(clk_i_bufg)
# rx datapath # rx datapath
# serdes -> gearbox -> bitslip -> decoders -> rx_data # serdes -> gearbox -> bitslip -> decoders -> rx_data
self.submodules.rx_gearbox = Gearbox(8, "serwb_serdes_5x", 40, "serwb_serdes") self.submodules.rx_gearbox = Gearbox(8, "sys", 40, "sys0p2x")
self.submodules.rx_bitslip = ClockDomainsRenamer("serwb_serdes")(BitSlip(40)) self.submodules.rx_bitslip = ClockDomainsRenamer("sys0p2x")(BitSlip(40))
serdes_i_nodelay = Signal() serdes_i_nodelay = Signal()
self.specials += [ self.specials += [
@ -193,7 +185,7 @@ class KUSSerdes(Module):
p_DELAY_FORMAT="COUNT", p_DELAY_SRC="IDATAIN", p_DELAY_FORMAT="COUNT", p_DELAY_SRC="IDATAIN",
p_DELAY_TYPE="VARIABLE", p_DELAY_VALUE=0, p_DELAY_TYPE="VARIABLE", p_DELAY_VALUE=0,
i_CLK=ClockSignal("serwb_serdes_5x"), i_CLK=ClockSignal("sys"),
i_RST=rx_delay_rst, i_LOAD=0, i_RST=rx_delay_rst, i_LOAD=0,
i_INC=rx_delay_inc, i_EN_VTC=rx_delay_en_vtc, i_INC=rx_delay_inc, i_EN_VTC=rx_delay_en_vtc,
i_CE=rx_delay_ce, i_CE=rx_delay_ce,
@ -206,11 +198,11 @@ class KUSSerdes(Module):
p_DATA_WIDTH=8, p_DATA_WIDTH=8,
i_D=serdes_i_delayed, i_D=serdes_i_delayed,
i_RST=ResetSignal("serwb_serdes"), i_RST=ResetSignal("sys"),
i_FIFO_RD_CLK=0, i_FIFO_RD_EN=0, i_FIFO_RD_CLK=0, i_FIFO_RD_EN=0,
i_CLK=ClockSignal("serwb_serdes_20x"), i_CLK=ClockSignal("sys4x"),
i_CLK_B=ClockSignal("serwb_serdes_20x"), # locally inverted i_CLK_B=ClockSignal("sys4x"), # locally inverted
i_CLKDIV=ClockSignal("serwb_serdes_5x"), i_CLKDIV=ClockSignal("sys"),
o_Q=serdes_q o_Q=serdes_q
) )
] ]

View File

@ -154,7 +154,6 @@ class _SerdesMasterInit(Module):
class _SerdesSlaveInit(Module, AutoCSR): class _SerdesSlaveInit(Module, AutoCSR):
def __init__(self, serdes, taps, timeout=4096): def __init__(self, serdes, taps, timeout=4096):
self.reset = Signal()
self.ready = Signal() self.ready = Signal()
self.error = Signal() self.error = Signal()
@ -170,11 +169,10 @@ class _SerdesSlaveInit(Module, AutoCSR):
timer = WaitTimer(timeout) timer = WaitTimer(timeout)
self.submodules += timer self.submodules += timer
self.comb += self.reset.eq(serdes.rx_idle)
self.comb += serdes.rx_delay_inc.eq(1) self.comb += serdes.rx_delay_inc.eq(1)
self.submodules.fsm = fsm = FSM(reset_state="IDLE") self.submodules.fsm = fsm = ResetInserter()(FSM(reset_state="IDLE"))
self.comb += fsm.reset.eq(serdes.rx_idle)
fsm.act("IDLE", fsm.act("IDLE",
NextValue(delay, 0), NextValue(delay, 0),
NextValue(delay_min, 0), NextValue(delay_min, 0),
@ -311,74 +309,16 @@ class _SerdesControl(Module, AutoCSR):
] ]
class SERWBPLL(Module):
def __init__(self, refclk_freq, linerate, vco_div=1):
assert refclk_freq in [62.5e6, 125e6]
assert linerate in [625e6, 1.25e9]
self.lock = Signal()
self.refclk = Signal()
self.serwb_serdes_clk = Signal()
self.serwb_serdes_20x_clk = Signal()
self.serwb_serdes_5x_clk = Signal()
# # #
self.linerate = linerate
refclk_mult = 125e6//refclk_freq
linerate_div = 1.25e9//linerate
pll_locked = Signal()
pll_fb = Signal()
pll_serwb_serdes_clk = Signal()
pll_serwb_serdes_20x_clk = Signal()
pll_serwb_serdes_5x_clk = Signal()
self.specials += [
Instance("PLLE2_BASE",
p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked,
# VCO @ 1.25GHz / vco_div
p_REF_JITTER1=0.01, p_CLKIN1_PERIOD=8.0*refclk_mult,
p_CLKFBOUT_MULT=10*refclk_mult, p_DIVCLK_DIVIDE=vco_div,
i_CLKIN1=self.refclk, i_CLKFBIN=pll_fb,
o_CLKFBOUT=pll_fb,
# serwb_serdes
p_CLKOUT0_DIVIDE=linerate_div*40//vco_div, p_CLKOUT0_PHASE=0.0,
o_CLKOUT0=pll_serwb_serdes_clk,
# serwb_serdes_20x
p_CLKOUT1_DIVIDE=linerate_div*2//vco_div, p_CLKOUT1_PHASE=0.0,
o_CLKOUT1=pll_serwb_serdes_20x_clk,
# serwb_serdes_5x
p_CLKOUT2_DIVIDE=linerate_div*8//vco_div, p_CLKOUT2_PHASE=0.0,
o_CLKOUT2=pll_serwb_serdes_5x_clk
),
Instance("BUFG",
i_I=pll_serwb_serdes_clk,
o_O=self.serwb_serdes_clk),
Instance("BUFG",
i_I=pll_serwb_serdes_20x_clk,
o_O=self.serwb_serdes_20x_clk),
Instance("BUFG",
i_I=pll_serwb_serdes_5x_clk,
o_O=self.serwb_serdes_5x_clk)
]
self.specials += MultiReg(pll_locked, self.lock)
class SERWBPHY(Module, AutoCSR): class SERWBPHY(Module, AutoCSR):
cd = "serwb_serdes" cd = "sys0p2x"
def __init__(self, device, pll, pads, mode="master"): def __init__(self, device, pads, mode="master"):
assert mode in ["master", "slave"] assert mode in ["master", "slave"]
if device[:4] == "xcku": if device[:4] == "xcku":
taps = 512 taps = 512
self.submodules.serdes = KUSSerdes(pll, pads, mode) self.submodules.serdes = KUSSerdes(pads, mode)
elif device[:4] == "xc7a": elif device[:4] == "xc7a":
taps = 32 taps = 32
self.submodules.serdes = S7Serdes(pll, pads, mode) self.submodules.serdes = S7Serdes(pads, mode)
else: else:
raise NotImplementedError raise NotImplementedError
if mode == "master": if mode == "master":

View File

@ -7,7 +7,10 @@ from misoc.cores.code_8b10b import Encoder, Decoder
class S7Serdes(Module): class S7Serdes(Module):
def __init__(self, pll, pads, mode="master"): def __init__(self, pads, mode="master"):
if mode == "slave":
self.refclk = Signal()
self.tx_k = Signal(4) self.tx_k = Signal(4)
self.tx_d = Signal(32) self.tx_d = Signal(32)
self.rx_k = Signal(4) self.rx_k = Signal(4)
@ -25,29 +28,18 @@ class S7Serdes(Module):
# # # # # #
self.submodules.encoder = ClockDomainsRenamer("serwb_serdes")( self.submodules.encoder = ClockDomainsRenamer("sys0p2x")(
Encoder(4, True)) Encoder(4, True))
self.decoders = [ClockDomainsRenamer("serwb_serdes")( self.decoders = [ClockDomainsRenamer("sys0p2x")(
Decoder(True)) for _ in range(4)] Decoder(True)) for _ in range(4)]
self.submodules += self.decoders self.submodules += self.decoders
# clocking: # clocking:
# In master mode: # In master mode:
# - linerate/10 pll refclk provided by user
# - linerate/10 slave refclk generated on clk_pads # - linerate/10 slave refclk generated on clk_pads
# In Slave mode: # In Slave mode:
# - linerate/10 pll refclk provided by clk_pads # - linerate/10 refclk provided by clk_pads
self.clock_domains.cd_serwb_serdes = ClockDomain()
self.clock_domains.cd_serwb_serdes_5x = ClockDomain()
self.clock_domains.cd_serwb_serdes_20x = ClockDomain(reset_less=True)
self.comb += [
self.cd_serwb_serdes.clk.eq(pll.serwb_serdes_clk),
self.cd_serwb_serdes_5x.clk.eq(pll.serwb_serdes_5x_clk),
self.cd_serwb_serdes_20x.clk.eq(pll.serwb_serdes_20x_clk)
]
self.specials += AsyncResetSynchronizer(self.cd_serwb_serdes, ~pll.lock)
self.comb += self.cd_serwb_serdes_5x.rst.eq(self.cd_serwb_serdes.rst)
# control/status cdc # control/status cdc
tx_idle = Signal() tx_idle = Signal()
@ -56,16 +48,16 @@ class S7Serdes(Module):
rx_comma = Signal() rx_comma = Signal()
rx_bitslip_value = Signal(6) rx_bitslip_value = Signal(6)
self.specials += [ self.specials += [
MultiReg(self.tx_idle, tx_idle, "serwb_serdes"), MultiReg(self.tx_idle, tx_idle, "sys0p2x"),
MultiReg(self.tx_comma, tx_comma, "serwb_serdes"), MultiReg(self.tx_comma, tx_comma, "sys0p2x"),
MultiReg(rx_idle, self.rx_idle, "sys"), MultiReg(rx_idle, self.rx_idle, "sys"),
MultiReg(rx_comma, self.rx_comma, "sys") MultiReg(rx_comma, self.rx_comma, "sys")
] ]
self.specials += MultiReg(self.rx_bitslip_value, rx_bitslip_value, "serwb_serdes"), self.specials += MultiReg(self.rx_bitslip_value, rx_bitslip_value, "sys0p2x"),
# tx clock (linerate/10) # tx clock (linerate/10)
if mode == "master": if mode == "master":
self.submodules.tx_clk_gearbox = Gearbox(40, "serwb_serdes", 8, "serwb_serdes_5x") self.submodules.tx_clk_gearbox = Gearbox(40, "sys0p2x", 8, "sys")
self.comb += self.tx_clk_gearbox.i.eq((0b1111100000 << 30) | self.comb += self.tx_clk_gearbox.i.eq((0b1111100000 << 30) |
(0b1111100000 << 20) | (0b1111100000 << 20) |
(0b1111100000 << 10) | (0b1111100000 << 10) |
@ -79,8 +71,8 @@ class S7Serdes(Module):
o_OQ=clk_o, o_OQ=clk_o,
i_OCE=1, i_OCE=1,
i_RST=ResetSignal("serwb_serdes"), i_RST=ResetSignal("sys"),
i_CLK=ClockSignal("serwb_serdes_20x"), i_CLKDIV=ClockSignal("serwb_serdes_5x"), i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal("sys"),
i_D1=self.tx_clk_gearbox.o[0], i_D2=self.tx_clk_gearbox.o[1], i_D1=self.tx_clk_gearbox.o[0], i_D2=self.tx_clk_gearbox.o[1],
i_D3=self.tx_clk_gearbox.o[2], i_D4=self.tx_clk_gearbox.o[3], i_D3=self.tx_clk_gearbox.o[2], i_D4=self.tx_clk_gearbox.o[3],
i_D5=self.tx_clk_gearbox.o[4], i_D6=self.tx_clk_gearbox.o[5], i_D5=self.tx_clk_gearbox.o[4], i_D6=self.tx_clk_gearbox.o[5],
@ -95,7 +87,7 @@ class S7Serdes(Module):
# tx datapath # tx datapath
# tx_data -> encoders -> gearbox -> serdes # tx_data -> encoders -> gearbox -> serdes
self.submodules.tx_gearbox = Gearbox(40, "serwb_serdes", 8, "serwb_serdes_5x") self.submodules.tx_gearbox = Gearbox(40, "sys0p2x", 8, "sys")
self.comb += [ self.comb += [
If(tx_comma, If(tx_comma,
self.encoder.k[0].eq(1), self.encoder.k[0].eq(1),
@ -111,7 +103,7 @@ class S7Serdes(Module):
self.encoder.d[3].eq(self.tx_d[24:32]) self.encoder.d[3].eq(self.tx_d[24:32])
) )
] ]
self.sync.serwb_serdes += \ self.sync.sys0p2x += \
If(tx_idle, If(tx_idle,
self.tx_gearbox.i.eq(0) self.tx_gearbox.i.eq(0)
).Else( ).Else(
@ -127,8 +119,8 @@ class S7Serdes(Module):
o_OQ=serdes_o, o_OQ=serdes_o,
i_OCE=1, i_OCE=1,
i_RST=ResetSignal("serwb_serdes"), i_RST=ResetSignal("sys"),
i_CLK=ClockSignal("serwb_serdes_20x"), i_CLKDIV=ClockSignal("serwb_serdes_5x"), i_CLK=ClockSignal("sys4x"), i_CLKDIV=ClockSignal("sys"),
i_D1=self.tx_gearbox.o[0], i_D2=self.tx_gearbox.o[1], i_D1=self.tx_gearbox.o[0], i_D2=self.tx_gearbox.o[1],
i_D3=self.tx_gearbox.o[2], i_D4=self.tx_gearbox.o[3], i_D3=self.tx_gearbox.o[2], i_D4=self.tx_gearbox.o[3],
i_D5=self.tx_gearbox.o[4], i_D6=self.tx_gearbox.o[5], i_D5=self.tx_gearbox.o[4], i_D6=self.tx_gearbox.o[5],
@ -161,12 +153,12 @@ class S7Serdes(Module):
] ]
else: else:
self.specials += Instance("BUFG", i_I=clk_i, o_O=clk_i_bufg) self.specials += Instance("BUFG", i_I=clk_i, o_O=clk_i_bufg)
self.comb += pll.refclk.eq(clk_i_bufg) self.comb += self.refclk.eq(clk_i_bufg)
# rx datapath # rx datapath
# serdes -> gearbox -> bitslip -> decoders -> rx_data # serdes -> gearbox -> bitslip -> decoders -> rx_data
self.submodules.rx_gearbox = Gearbox(8, "serwb_serdes_5x", 40, "serwb_serdes") self.submodules.rx_gearbox = Gearbox(8, "sys", 40, "sys0p2x")
self.submodules.rx_bitslip = ClockDomainsRenamer("serwb_serdes")(BitSlip(40)) self.submodules.rx_bitslip = ClockDomainsRenamer("sys0p2x")(BitSlip(40))
serdes_i_nodelay = Signal() serdes_i_nodelay = Signal()
self.specials += [ self.specials += [
@ -200,9 +192,9 @@ class S7Serdes(Module):
i_DDLY=serdes_i_delayed, i_DDLY=serdes_i_delayed,
i_CE1=1, i_CE1=1,
i_RST=ResetSignal("serwb_serdes"), i_RST=ResetSignal("sys"),
i_CLK=ClockSignal("serwb_serdes_20x"), i_CLKB=~ClockSignal("serwb_serdes_20x"), i_CLK=ClockSignal("sys4x"), i_CLKB=~ClockSignal("sys4x"),
i_CLKDIV=ClockSignal("serwb_serdes_5x"), i_CLKDIV=ClockSignal("sys"),
i_BITSLIP=0, i_BITSLIP=0,
o_Q8=serdes_q[0], o_Q7=serdes_q[1], o_Q8=serdes_q[0], o_Q7=serdes_q[1],
o_Q6=serdes_q[2], o_Q5=serdes_q[3], o_Q6=serdes_q[2], o_Q5=serdes_q[3],