1
0
Fork 0

cxp downconn: use auto aligner

cxp downconn: fix autoaligner checking
This commit is contained in:
morgan 2024-08-09 10:42:57 +08:00
parent 0e69c5d5ba
commit 1f8ef6bf96
1 changed files with 85 additions and 138 deletions

View File

@ -8,8 +8,8 @@ from misoc.interconnect.csr import *
from artiq.gateware.drtio.transceiver.gtx_7series_init import * from artiq.gateware.drtio.transceiver.gtx_7series_init import *
from operator import add
from functools import reduce from functools import reduce
from operator import add
class CXP_DownConn(Module, AutoCSR): class CXP_DownConn(Module, AutoCSR):
def __init__(self, refclk, pads, sys_clk_freq, debug_sma, pmod_pads): def __init__(self, refclk, pads, sys_clk_freq, debug_sma, pmod_pads):
@ -101,13 +101,12 @@ class CXP_DownConn(Module, AutoCSR):
Instance("OBUF", i_I=gtx.cd_cxp_gtx_tx.clk, o_O=debug_sma.n_rx), Instance("OBUF", i_I=gtx.cd_cxp_gtx_tx.clk, o_O=debug_sma.n_rx),
# pmod 0-7 pin # pmod 0-7 pin
Instance("OBUF", i_I=gtx.clk_aligner.rxslide, o_O=pmod_pads[0]), Instance("OBUF", i_I=gtx.comma_det.aligner_en_rxclk, o_O=pmod_pads[0]),
Instance("OBUF", i_I=gtx.clk_aligner.rxinit_done, o_O=pmod_pads[1]), Instance("OBUF", i_I=gtx.comma_det.rxinit_done, o_O=pmod_pads[1]),
Instance("OBUF", i_I=gtx.clk_aligner.restart, o_O=pmod_pads[2]), Instance("OBUF", i_I=gtx.comma_det.restart, o_O=pmod_pads[2]),
Instance("OBUF", i_I=gtx.clk_aligner.comma_aligned, o_O=pmod_pads[3]), Instance("OBUF", i_I=gtx.comma_det.comma_aligned, o_O=pmod_pads[3]),
Instance("OBUF", i_I=gtx.clk_aligner.ready, o_O=pmod_pads[4]), Instance("OBUF", i_I=gtx.comma_det.ready, o_O=pmod_pads[4]),
Instance("OBUF", i_I=gtx.clk_aligner.comma_det_reset, o_O=pmod_pads[5]), Instance("OBUF", i_I=gtx.comma_det.valid_data, o_O=pmod_pads[5]),
# Instance("OBUF", i_I=gtx.clk_aligner.comma_det.detected, o_O=pmod_pads[6]),
# Instance("OBUF", i_I=, o_O=pmod_pads[7]), # Instance("OBUF", i_I=, o_O=pmod_pads[7]),
] ]
@ -260,157 +259,106 @@ class QPLL(Module):
) )
] ]
# detect if the comma is located at data[0:10]
class Comma_Detector(Module):
def __init__(self, comma, width):
self.reset = Signal()
self.data = Signal(width)
self.detected = Signal()
self.bitshift = Signal(max=width)
self.comma_aligned = Signal()
# # #
last_data = Signal(10)
data = Signal(width+10)
comma_n = ~comma & 0b1111111111
self.sync += [
last_data.eq(self.data[:10]),
data.eq(Cat(self.data, last_data)),
If(self.reset,
self.bitshift.eq(0),
self.detected.eq(0),
),
If(self.reset,
self.comma_aligned.eq(0)
).Elif((self.data[:10] == comma) | (self.data[:10] == comma_n),
self.comma_aligned.eq(1)
),
]
for n in range(width):
self.sync += \
If((data[n:n+10] == comma) | (data[n:n+10] == comma_n),
self.bitshift.eq(width-n),
self.detected.eq(1),
)
# Warning: Xilinx transceivers are LSB first, and comma needs to be flipped # Warning: Xilinx transceivers are LSB first, and comma needs to be flipped
# compared to the usual 8b10b binary representation. class Comma_Detector(Module):
# 50000 62.5MHz locks | 125MHz takes a lot time to locks | 250MHz many commas def __init__(self, comma, check_period=50_000, width=20):
# 30000 62.5MHz & 125MHz locks | 250MHz more commas but not lock
# 30000 62.5MHz & 125MHz locks | 250MHz nothing to see
# 27000 62.5MHz & 125MHz locks | 250MHz nothing to see
# 25000 62.5MHz takes long time to lock | 125MHz no lock | 250MHz locks
# 24700 62.5MHz lock | 125MHz sometimes locks | 250MHz locks
# 20000 250MHz nothing to see
# 10000 62.5MHz & 125MHz nothing to see | 250MHz many commas not much can survive the second check
class Manual_Aligner(Module):
def __init__(self, comma, check_period=24_700, width=20):
self.rxslide = Signal()
self.data = Signal(width) self.data = Signal(width)
self.rxinit_done = Signal() self.rxinit_done = Signal()
self.aligner_en_rxclk = Signal()
self.ready = Signal() self.ready = Signal()
self.restart = Signal() self.restart = Signal()
# # # # # #
timerout_period = 5_000_000
timerout = Signal(reset=timerout_period-1, max=timerout_period)
ready_rxclk = Signal()
self.specials += MultiReg(ready_rxclk, self.ready)
self.ready.attr.add("no_retiming")
restart_sys = Signal()
restart_rxclk = Signal()
self.specials += MultiReg(restart_rxclk, restart_sys)
restart_sys.attr.add("no_retiming")
# NOTE: be careful of all the timeout values!!! It should be much larger than the longest fsm
# TODO: fix comma fall too fast for 500MHz (10Gpbs) -> need to change CDR_CFG via DRP
# Restart rx periodically since rx need to be restart when connecting RXN/RXP
self.sync += [
self.restart.eq(0),
If(restart_sys,
timerout.eq(timerout.reset),
self.restart.eq(1),
).Elif(~self.ready,
If((timerout == 0),
timerout.eq(timerout.reset),
self.restart.eq(1),
).Else(
timerout.eq(timerout - 1),
)
)
]
self.comma_det_reset = Signal()
self.comma_aligned = Signal() self.comma_aligned = Signal()
self.valid_data = Signal()
self.submodules.recheck_ps = recheck_ps = PulseSynchronizer("sys", "cxp_gtx_rx")
aligned = Signal()
self.specials += MultiReg(self.comma_aligned, aligned)
valid_data = Signal()
self.specials += MultiReg(self.valid_data, valid_data)
comma_n = ~comma & 0b1111111111 comma_n = ~comma & 0b1111111111
rx1cnt = Signal(max=11)
self.sync.cxp_gtx_rx += [ self.sync.cxp_gtx_rx += [
If(self.comma_det_reset, rx1cnt.eq(reduce(add, [self.data[i] for i in range(10)])),
If(recheck_ps.o,
self.comma_aligned.eq(0) self.comma_aligned.eq(0)
).Elif((self.data[:10] == comma) | (self.data[:10] == comma_n), ).Elif((self.data[:10] == comma) | (self.data[:10] == comma_n),
self.comma_aligned.eq(1) self.comma_aligned.eq(1)
), ),
If(recheck_ps.o,
self.valid_data.eq(0)
).Elif((rx1cnt == 4) | (rx1cnt == 5) | (rx1cnt == 6),
self.valid_data.eq(1)
),
] ]
self.submodules.fsm = fsm = ClockDomainsRenamer("cxp_gtx_rx")(FSM(reset_state="IDLE"))
check_counter = Signal(reset=check_period-1, max=check_period)
check = Signal()
aligner_en_sys = Signal()
self.specials += MultiReg(aligner_en_sys, self.aligner_en_rxclk, odomain="cxp_gtx_rx")
self.sync += [
check.eq(0),
If(check_counter == 0,
check_counter.eq(check_counter.reset),
check.eq(1),
).Else(
check_counter.eq(check_counter - 1),
)
]
rxinit_done_rxclk = Signal() self.submodules.fsm = fsm = FSM(reset_state="IDLE")
self.specials += MultiReg(self.rxinit_done, rxinit_done_rxclk, odomain="cxp_gtx_rx")
check_timer = Signal(reset=check_period-1,max=check_period)
fsm.act("IDLE", fsm.act("IDLE",
self.comma_det_reset.eq(1), aligner_en_sys.eq(1),
If(rxinit_done_rxclk, If(check,
NextValue(check_timer, check_timer.reset), recheck_ps.i.eq(1),
NextState("WAIT_COMMA_DET"), If(aligned,
), NextState("WAIT_NO_ERROR"),
).Else(
self.restart.eq(1),
)
)
) )
fsm.act("WAIT_COMMA_DET", fsm.act("WAIT_NO_ERROR",
NextValue(check_timer, check_timer - 1), aligner_en_sys.eq(1),
If(check_timer == 0, If(check,
restart_rxclk.eq(1), recheck_ps.i.eq(1),
NextState("RESET"), If(aligned & valid_data,
# restart_ps.i.eq(1), NextState("READY"),
# NextState("IDLE"), ).Else(
).Elif(self.comma_aligned, self.restart.eq(1),
NextValue(check_timer, check_timer.reset), NextState("IDLE"),
self.comma_det_reset.eq(1), )
NextState("READY")
) )
) )
fsm.act("READY", fsm.act("READY",
ready_rxclk.eq(1), self.ready.eq(1),
If(check_timer == 0, If(check,
NextValue(check_timer, check_timer.reset), recheck_ps.i.eq(1),
self.comma_det_reset.eq(1), If(~(aligned & valid_data),
If(~self.comma_aligned, self.restart.eq(1),
restart_rxclk.eq(1), NextState("IDLE"),
NextState("RESET"),
# restart_ps.i.eq(1),
# NextState("IDLE"),
) )
).Else(
NextValue(check_timer, check_timer - 1),
) )
) )
fsm.act("RESET",
restart_rxclk.eq(1),
)
class GTX(Module): class GTX(Module):
@ -466,7 +414,7 @@ class GTX(Module):
txdata = Signal(20) txdata = Signal(20)
rxdata = Signal(20) rxdata = Signal(20)
rxslide = Signal() comma_align_en = Signal()
# Note: the following parameters were set after consulting AR45360 # Note: the following parameters were set after consulting AR45360
self.specials += \ self.specials += \
Instance("GTXE2_CHANNEL", Instance("GTXE2_CHANNEL",
@ -558,7 +506,7 @@ class GTX(Module):
i_RXDFEXYDEN=1, i_RXDFEXYDEN=1,
i_RXDFEXYDHOLD=0, i_RXDFEXYDHOLD=0,
i_RXDFEXYDOVRDEN=0, i_RXDFEXYDOVRDEN=0,
i_RXLPMEN=1, # RXLPMEN = 1: LPM mode is enabled for non scramble data i_RXLPMEN=0, # RXLPMEN = 0: DFE mode is enabled for non scramble data
p_RX_DFE_GAIN_CFG=0x0207EA, p_RX_DFE_GAIN_CFG=0x0207EA,
p_RX_DFE_VP_CFG=0b00011111100000011, p_RX_DFE_VP_CFG=0b00011111100000011,
p_RX_DFE_UT_CFG=0b10001000000000000, p_RX_DFE_UT_CFG=0b10001000000000000,
@ -597,18 +545,17 @@ class GTX(Module):
p_ALIGN_COMMA_DOUBLE="FALSE", p_ALIGN_COMMA_DOUBLE="FALSE",
p_ALIGN_COMMA_ENABLE=0b1111111111, p_ALIGN_COMMA_ENABLE=0b1111111111,
p_ALIGN_COMMA_WORD=2, # allow rxslide to shift 20 times p_ALIGN_COMMA_WORD=2, # allow rxslide to shift 20 times
p_ALIGN_MCOMMA_DET="FALSE", p_ALIGN_MCOMMA_DET="TRUE",
p_ALIGN_MCOMMA_VALUE=0b1010000011, p_ALIGN_MCOMMA_VALUE=0b1010000011,
p_ALIGN_PCOMMA_DET="FALSE", p_ALIGN_PCOMMA_DET="TRUE",
p_ALIGN_PCOMMA_VALUE=0b0101111100, p_ALIGN_PCOMMA_VALUE=0b0101111100,
p_SHOW_REALIGN_COMMA="FALSE", p_SHOW_REALIGN_COMMA="FALSE",
p_RXSLIDE_AUTO_WAIT=7, p_RXSLIDE_AUTO_WAIT=7,
p_RXSLIDE_MODE="PCS", p_RXSLIDE_MODE="OFF",
p_RX_SIG_VALID_DLY=10, p_RX_SIG_VALID_DLY=10,
i_RXPCOMMAALIGNEN=0, i_RXPCOMMAALIGNEN=comma_align_en,
i_RXMCOMMAALIGNEN=0, i_RXMCOMMAALIGNEN=comma_align_en,
i_RXCOMMADETEN=0, # enable manual word alignment i_RXCOMMADETEN=1, # enable auto word alignment
i_RXSLIDE=rxslide,
# RX 8B/10B Decoder Attributes # RX 8B/10B Decoder Attributes
p_RX_DISPERR_SEQ_MATCH="FALSE", p_RX_DISPERR_SEQ_MATCH="FALSE",
@ -735,13 +682,13 @@ class GTX(Module):
] ]
self.submodules.clk_aligner = clk_aligner = Manual_Aligner(0b0101111100) self.submodules.comma_det = comma_det = Comma_Detector(0b0101111100)
self.comb += [ self.comb += [
clk_aligner.data.eq(rxdata), comma_det.data.eq(rxdata),
clk_aligner.rxinit_done.eq(rx_init.done), comma_det.rxinit_done.eq(rx_init.done),
rxslide.eq(clk_aligner.rxslide), comma_align_en.eq(comma_det.aligner_en_rxclk),
self.rx_ready.eq(clk_aligner.ready), self.rx_ready.eq(comma_det.ready),
rx_init.restart.eq(self.rx_restart | clk_aligner.restart), rx_init.restart.eq(self.rx_restart | comma_det.restart),
tx_init.restart.eq(self.tx_restart), tx_init.restart.eq(self.tx_restart),
] ]