forked from M-Labs/artiq-zynq
downconn GW: update to add none for tx/rxmode
This commit is contained in:
parent
edb7c62d4a
commit
635c62b8e6
@ -36,7 +36,7 @@ class CXP_RXPHYs(Module, AutoCSR):
|
||||
rx_mode = "single"
|
||||
else:
|
||||
rx_mode = "master" if i == master else "slave"
|
||||
rx = Receiver(qpll, pad, sys_clk_freq, "single", rx_mode, debug_sma, pmod_pads)
|
||||
rx = Receiver(qpll, pad, sys_clk_freq, rx_mode)
|
||||
self.phys.append(rx)
|
||||
setattr(self.submodules, "rx"+str(i), rx)
|
||||
|
||||
@ -52,8 +52,8 @@ class CXP_RXPHYs(Module, AutoCSR):
|
||||
self.submodules.rx_phase_alignment = GTXInitPhaseAlignment([rx_phy.gtx.rx_init for rx_phy in self.phys])
|
||||
|
||||
class Receiver(Module):
|
||||
def __init__(self, qpll, pad, sys_clk_freq, tx_mode, rx_mode, debug_sma, pmod_pads):
|
||||
self.submodules.gtx = gtx = GTX(qpll, pad, sys_clk_freq, tx_mode, rx_mode)
|
||||
def __init__(self, qpll, pad, sys_clk_freq, rx_mode):
|
||||
self.submodules.gtx = gtx = GTX(qpll, pad, sys_clk_freq, None, rx_mode)
|
||||
|
||||
self.source = stream.Endpoint(word_layout)
|
||||
|
||||
@ -294,13 +294,21 @@ class Comma_Aligner(Module):
|
||||
|
||||
|
||||
class GTX(Module):
|
||||
def __init__(self, qpll, pads, sys_clk_freq, tx_mode="single", rx_mode="single"):
|
||||
assert tx_mode in ["single", "master", "slave"]
|
||||
assert rx_mode in ["single", "master", "slave"]
|
||||
"""
|
||||
A reconfigurable linerate GTX with QPLL
|
||||
Designed for 12.5, 10, 6.25, 5, 3.125, 2.5, 1.25Gpbs
|
||||
|
||||
To change the linerate:
|
||||
1) Change the VCO frequency
|
||||
- 12.5, 6.25, 3.125Gbps: QPLL VCO @ 12.5GHz,
|
||||
- 10, 6.25, 5, 2.5, 1.25Gbps: QPLL VCO @ 10GHz
|
||||
2) Update the xXOUT_DIV and TXUSRCLK frequency if using tx
|
||||
3) Reset the entire rx and tx
|
||||
"""
|
||||
def __init__(self, qpll, pads, sys_clk_freq, tx_mode="single", rx_mode="single"):
|
||||
assert tx_mode in ["single", "master", "slave", None]
|
||||
assert rx_mode in ["single", "master", "slave", None]
|
||||
|
||||
# linerate = USRCLK * datawidth
|
||||
pll_fbout_mult = 8
|
||||
txusr_pll_div = pll_fbout_mult*sys_clk_freq/qpll.tx_usrclk_freq
|
||||
|
||||
self.tx_restart = Signal()
|
||||
self.rx_manual_restart = Signal()
|
||||
@ -318,9 +326,6 @@ class GTX(Module):
|
||||
self.dout = Signal(16)
|
||||
self.dready = Signal()
|
||||
|
||||
self.submodules.encoder = ClockDomainsRenamer("cxp_gtx_tx")(Encoder(4, True))
|
||||
self.submodules.decoders = [ClockDomainsRenamer("cxp_gtx_rx")(
|
||||
(Decoder(True))) for _ in range(4)]
|
||||
|
||||
|
||||
# transceiver direct clock outputs
|
||||
@ -330,18 +335,29 @@ class GTX(Module):
|
||||
|
||||
# # #
|
||||
|
||||
# TX generates cxp_tx clock, init must be in system domain
|
||||
self.submodules.tx_init = tx_init = GTXInit(sys_clk_freq, False, mode=tx_mode)
|
||||
self.submodules.rx_init = rx_init = GTXInit(sys_clk_freq, True, mode=rx_mode)
|
||||
|
||||
self.comb += [
|
||||
tx_init.cplllock.eq(qpll.lock),
|
||||
rx_init.cplllock.eq(qpll.lock)
|
||||
]
|
||||
|
||||
txdata = Signal(40)
|
||||
rxdata = Signal(40)
|
||||
|
||||
if tx_mode:
|
||||
self.submodules.tx_init = tx_init = GTXInit(sys_clk_freq, False, mode=tx_mode)
|
||||
self.comb += tx_init.cplllock.eq(qpll.lock),
|
||||
|
||||
self.submodules.encoder = ClockDomainsRenamer("cxp_gtx_tx")(Encoder(4, True))
|
||||
self.comb += txdata.eq(Cat(self.encoder.output[0], self.encoder.output[1], self.encoder.output[2], self.encoder.output[3])),
|
||||
|
||||
if rx_mode:
|
||||
self.submodules.rx_init = rx_init = GTXInit(sys_clk_freq, True, mode=rx_mode)
|
||||
self.comb += rx_init.cplllock.eq(qpll.lock)
|
||||
|
||||
self.submodules.decoders = [ClockDomainsRenamer("cxp_gtx_rx")(
|
||||
(Decoder(True))) for _ in range(4)]
|
||||
self.comb += [
|
||||
self.decoders[0].input.eq(rxdata[:10]),
|
||||
self.decoders[1].input.eq(rxdata[10:20]),
|
||||
self.decoders[2].input.eq(rxdata[20:30]),
|
||||
self.decoders[3].input.eq(rxdata[30:]),
|
||||
]
|
||||
|
||||
comma_aligned = Signal()
|
||||
comma_realigned = Signal()
|
||||
comma_det = Signal()
|
||||
@ -383,17 +399,17 @@ class GTX(Module):
|
||||
# TX Startup/Reset
|
||||
i_TXPHDLYRESET=0,
|
||||
i_TXDLYBYPASS=0,
|
||||
i_TXPHALIGNEN=1 if tx_mode != "single" else 0,
|
||||
i_GTTXRESET=tx_init.gtXxreset,
|
||||
o_TXRESETDONE=tx_init.Xxresetdone,
|
||||
i_TXDLYSRESET=tx_init.Xxdlysreset,
|
||||
o_TXDLYSRESETDONE=tx_init.Xxdlysresetdone,
|
||||
i_TXPHINIT=tx_init.txphinit if tx_mode != "single" else 0,
|
||||
o_TXPHINITDONE=tx_init.txphinitdone if tx_mode != "single" else Signal(),
|
||||
i_TXPHALIGN=tx_init.Xxphalign if tx_mode != "single" else 0,
|
||||
i_TXDLYEN=tx_init.Xxdlyen if tx_mode != "single" else 0,
|
||||
o_TXPHALIGNDONE=tx_init.Xxphaligndone,
|
||||
i_TXUSERRDY=tx_init.Xxuserrdy,
|
||||
i_TXPHALIGNEN=1 if tx_mode in ["master", "slave"] else 0,
|
||||
i_GTTXRESET=tx_init.gtXxreset if tx_mode else 0,
|
||||
o_TXRESETDONE=tx_init.Xxresetdone if tx_mode else 0,
|
||||
i_TXDLYSRESET=tx_init.Xxdlysreset if tx_mode else 0,
|
||||
o_TXDLYSRESETDONE=tx_init.Xxdlysresetdone if tx_mode else 0,
|
||||
i_TXPHINIT=tx_init.txphinit if tx_mode in ["master", "slave"] else 0,
|
||||
o_TXPHINITDONE=tx_init.txphinitdone if tx_mode in ["master", "slave"] else Signal(),
|
||||
i_TXPHALIGN=tx_init.Xxphalign if tx_mode in ["master", "slave"] else 0,
|
||||
i_TXDLYEN=tx_init.Xxdlyen if tx_mode in ["master", "slave"] else 0,
|
||||
o_TXPHALIGNDONE=tx_init.Xxphaligndone if tx_mode else 0,
|
||||
i_TXUSERRDY=tx_init.Xxuserrdy if tx_mode else 0,
|
||||
p_TXPMARESET_TIME=1,
|
||||
p_TXPCSRESET_TIME=1,
|
||||
i_TXINHIBIT=~self.txenable,
|
||||
@ -404,8 +420,8 @@ class GTX(Module):
|
||||
i_TXCHARDISPMODE=Cat(txdata[9], txdata[19], txdata[29], txdata[39]),
|
||||
i_TXCHARDISPVAL=Cat(txdata[8], txdata[18], txdata[28], txdata[38]),
|
||||
i_TXDATA=Cat(txdata[:8], txdata[10:18], txdata[20:28], txdata[30:38]),
|
||||
i_TXUSRCLK=ClockSignal("cxp_gtx_tx"),
|
||||
i_TXUSRCLK2=ClockSignal("cxp_gtx_tx"),
|
||||
i_TXUSRCLK=ClockSignal("cxp_gtx_tx") if tx_mode else 0,
|
||||
i_TXUSRCLK2=ClockSignal("cxp_gtx_tx") if tx_mode else 0,
|
||||
|
||||
# TX electrical
|
||||
i_TXBUFDIFFCTRL=0b100,
|
||||
@ -414,15 +430,15 @@ class GTX(Module):
|
||||
# RX Startup/Reset
|
||||
i_RXPHDLYRESET=0,
|
||||
i_RXDLYBYPASS=0,
|
||||
i_RXPHALIGNEN=1 if rx_mode != "single" else 0,
|
||||
i_GTRXRESET=rx_init.gtXxreset,
|
||||
o_RXRESETDONE=rx_init.Xxresetdone,
|
||||
i_RXDLYSRESET=rx_init.Xxdlysreset,
|
||||
o_RXDLYSRESETDONE=rx_init.Xxdlysresetdone,
|
||||
i_RXPHALIGN=rx_init.Xxphalign if rx_mode != "single" else 0,
|
||||
i_RXDLYEN=rx_init.Xxdlyen if rx_mode != "single" else 0,
|
||||
o_RXPHALIGNDONE=rx_init.Xxphaligndone,
|
||||
i_RXUSERRDY=rx_init.Xxuserrdy,
|
||||
i_RXPHALIGNEN=1 if rx_mode in ["master", "slave"] else 0,
|
||||
i_GTRXRESET=rx_init.gtXxreset if rx_mode else 0,
|
||||
o_RXRESETDONE=rx_init.Xxresetdone if rx_mode else 0,
|
||||
i_RXDLYSRESET=rx_init.Xxdlysreset if rx_mode else 0,
|
||||
o_RXDLYSRESETDONE=rx_init.Xxdlysresetdone if rx_mode else 0,
|
||||
i_RXPHALIGN=rx_init.Xxphalign if rx_mode in ["master", "slave"] else 0,
|
||||
i_RXDLYEN=rx_init.Xxdlyen if rx_mode in ["master", "slave"] else 0,
|
||||
o_RXPHALIGNDONE=rx_init.Xxphaligndone if rx_mode else 0,
|
||||
i_RXUSERRDY=rx_init.Xxuserrdy if rx_mode else 0,
|
||||
p_RXPMARESET_TIME=1,
|
||||
p_RXPCSRESET_TIME=1,
|
||||
|
||||
@ -454,8 +470,8 @@ class GTX(Module):
|
||||
# i_RXSYSCLKSEL=0b00,
|
||||
i_RXOUTCLKSEL=0b010,
|
||||
o_RXOUTCLK=self.rxoutclk,
|
||||
i_RXUSRCLK=ClockSignal("cxp_gtx_rx"),
|
||||
i_RXUSRCLK2=ClockSignal("cxp_gtx_rx"),
|
||||
i_RXUSRCLK=ClockSignal("cxp_gtx_rx") if rx_mode else 0,
|
||||
i_RXUSRCLK2=ClockSignal("cxp_gtx_rx") if rx_mode else 0,
|
||||
|
||||
# RX Clock Correction Attributes
|
||||
p_CLK_CORRECT_USE="FALSE",
|
||||
@ -545,7 +561,7 @@ class GTX(Module):
|
||||
o_DRPDO=self.dout,
|
||||
o_DRPRDY=self.dready,
|
||||
|
||||
# ! loopback for debugging
|
||||
# Nearend Loopback
|
||||
i_LOOPBACK = self.loopback_mode,
|
||||
p_TX_LOOPBACK_DRIVE_HIZ = "FALSE",
|
||||
p_RXPRBS_ERR_LOOPBACK = 0b0,
|
||||
@ -565,52 +581,58 @@ class GTX(Module):
|
||||
|
||||
|
||||
# TX clocking
|
||||
# A PLL is used to generate the correct frequency for TXUSRCLK (UG476 Equation 3-1)
|
||||
self.clock_domains.cd_cxp_gtx_tx = ClockDomain()
|
||||
txpll_fb_clk = Signal()
|
||||
txoutclk_buf = Signal()
|
||||
txpll_clkout = Signal()
|
||||
# As TX buffer is bypass, freq txoutclk_buf == refclk
|
||||
# To match the require frequency TXUSRCLK = linerate/datewidth (UG476 Equation 3-1)
|
||||
# A PLL need to be used to generate the correct frequency for TXUSRCLK
|
||||
if tx_mode:
|
||||
self.clock_domains.cd_cxp_gtx_tx = ClockDomain()
|
||||
txpll_fb_clk = Signal()
|
||||
txoutclk_buf = Signal()
|
||||
txpll_clkout = Signal()
|
||||
|
||||
self.txpll_reset = Signal()
|
||||
self.pll_daddr = Signal(7)
|
||||
self.pll_dclk = Signal()
|
||||
self.pll_den = Signal()
|
||||
self.pll_din = Signal(16)
|
||||
self.pll_dwen = Signal()
|
||||
self.txpll_reset = Signal()
|
||||
self.pll_daddr = Signal(7)
|
||||
self.pll_dclk = Signal()
|
||||
self.pll_den = Signal()
|
||||
self.pll_din = Signal(16)
|
||||
self.pll_dwen = Signal()
|
||||
|
||||
self.txpll_locked = Signal()
|
||||
self.pll_dout = Signal(16)
|
||||
self.pll_dready = Signal()
|
||||
self.specials += [
|
||||
Instance("PLLE2_ADV",
|
||||
p_BANDWIDTH="HIGH",
|
||||
o_LOCKED=self.txpll_locked,
|
||||
i_RST=self.txpll_reset,
|
||||
self.txpll_locked = Signal()
|
||||
self.pll_dout = Signal(16)
|
||||
self.pll_dready = Signal()
|
||||
|
||||
pll_fbout_mult = 8
|
||||
txusr_pll_div = pll_fbout_mult*sys_clk_freq/qpll.tx_usrclk_freq
|
||||
self.specials += [
|
||||
Instance("PLLE2_ADV",
|
||||
p_BANDWIDTH="HIGH",
|
||||
o_LOCKED=self.txpll_locked,
|
||||
i_RST=self.txpll_reset,
|
||||
|
||||
p_CLKIN1_PERIOD=1e9/sys_clk_freq, # ns
|
||||
i_CLKIN1=txoutclk_buf,
|
||||
p_CLKIN1_PERIOD=1e9/sys_clk_freq, # ns
|
||||
i_CLKIN1=txoutclk_buf,
|
||||
|
||||
# VCO @ 1.25GHz
|
||||
p_CLKFBOUT_MULT=pll_fbout_mult, p_DIVCLK_DIVIDE=1,
|
||||
i_CLKFBIN=txpll_fb_clk, o_CLKFBOUT=txpll_fb_clk,
|
||||
# VCO @ 1.25GHz
|
||||
p_CLKFBOUT_MULT=pll_fbout_mult, p_DIVCLK_DIVIDE=1,
|
||||
i_CLKFBIN=txpll_fb_clk, o_CLKFBOUT=txpll_fb_clk,
|
||||
|
||||
# frequency = linerate/40
|
||||
p_CLKOUT0_DIVIDE=txusr_pll_div, p_CLKOUT0_PHASE=0.0, o_CLKOUT0=txpll_clkout,
|
||||
# frequency = linerate/40
|
||||
p_CLKOUT0_DIVIDE=txusr_pll_div, p_CLKOUT0_PHASE=0.0, o_CLKOUT0=txpll_clkout,
|
||||
|
||||
# Dynamic Reconfiguration Ports
|
||||
i_DADDR = self.pll_daddr,
|
||||
i_DCLK = self.pll_dclk,
|
||||
i_DEN = self.pll_den,
|
||||
i_DI = self.pll_din,
|
||||
i_DWE = self.pll_dwen,
|
||||
o_DO = self.pll_dout,
|
||||
o_DRDY = self.pll_dready,
|
||||
),
|
||||
Instance("BUFG", i_I=self.txoutclk, o_O=txoutclk_buf),
|
||||
Instance("BUFG", i_I=txpll_clkout, o_O=self.cd_cxp_gtx_tx.clk),
|
||||
AsyncResetSynchronizer(self.cd_cxp_gtx_tx, ~self.txpll_locked & ~tx_init.done)
|
||||
]
|
||||
self.comb += tx_init.restart.eq(self.tx_restart)
|
||||
# Dynamic Reconfiguration Ports
|
||||
i_DADDR = self.pll_daddr,
|
||||
i_DCLK = self.pll_dclk,
|
||||
i_DEN = self.pll_den,
|
||||
i_DI = self.pll_din,
|
||||
i_DWE = self.pll_dwen,
|
||||
o_DO = self.pll_dout,
|
||||
o_DRDY = self.pll_dready,
|
||||
),
|
||||
Instance("BUFG", i_I=self.txoutclk, o_O=txoutclk_buf),
|
||||
Instance("BUFG", i_I=txpll_clkout, o_O=self.cd_cxp_gtx_tx.clk),
|
||||
AsyncResetSynchronizer(self.cd_cxp_gtx_tx, ~self.txpll_locked & ~tx_init.done)
|
||||
]
|
||||
self.comb += tx_init.restart.eq(self.tx_restart)
|
||||
|
||||
# RX clocking
|
||||
# the CDR matches the required frequency for RXUSRCLK, no need for PLL
|
||||
@ -624,15 +646,6 @@ class GTX(Module):
|
||||
|
||||
self.comb += rx_init.restart.eq(self.rx_manual_restart)
|
||||
|
||||
# 8b10b Encoder/Decoder
|
||||
self.comb += [
|
||||
txdata.eq(Cat(self.encoder.output[0], self.encoder.output[1], self.encoder.output[2], self.encoder.output[3])),
|
||||
self.decoders[0].input.eq(rxdata[:10]),
|
||||
self.decoders[1].input.eq(rxdata[10:20]),
|
||||
self.decoders[2].input.eq(rxdata[20:30]),
|
||||
self.decoders[3].input.eq(rxdata[30:]),
|
||||
]
|
||||
|
||||
self.submodules.comma_aligner = comma_aligner = Comma_Aligner(0b0101111100)
|
||||
self.comb += [
|
||||
comma_aligner.data.eq(rxdata),
|
||||
|
Loading…
Reference in New Issue
Block a user