forked from M-Labs/artiq-zynq
cxp downconn: refactor bruteforce aligner
This commit is contained in:
parent
dbce74d831
commit
0e69c5d5ba
|
@ -104,10 +104,10 @@ class CXP_DownConn(Module, AutoCSR):
|
||||||
Instance("OBUF", i_I=gtx.clk_aligner.rxslide, o_O=pmod_pads[0]),
|
Instance("OBUF", i_I=gtx.clk_aligner.rxslide, o_O=pmod_pads[0]),
|
||||||
Instance("OBUF", i_I=gtx.clk_aligner.rxinit_done, o_O=pmod_pads[1]),
|
Instance("OBUF", i_I=gtx.clk_aligner.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.clk_aligner.restart, o_O=pmod_pads[2]),
|
||||||
Instance("OBUF", i_I=gtx.clk_aligner.comma_det.comma_aligned, o_O=pmod_pads[3]),
|
Instance("OBUF", i_I=gtx.clk_aligner.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.clk_aligner.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.clk_aligner.comma_det_reset, o_O=pmod_pads[5]),
|
||||||
Instance("OBUF", i_I=gtx.clk_aligner.comma_det.detected, o_O=pmod_pads[6]),
|
# 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]),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -162,9 +162,9 @@ class CXP_DownConn(Module, AutoCSR):
|
||||||
self.rxdata_1.status.eq(self.gtx.decoders[1].input),
|
self.rxdata_1.status.eq(self.gtx.decoders[1].input),
|
||||||
self.decoded_data_1.status.eq(self.gtx.decoders[1].d),
|
self.decoded_data_1.status.eq(self.gtx.decoders[1].d),
|
||||||
self.decoded_k_1.status.eq(self.gtx.decoders[1].k),
|
self.decoded_k_1.status.eq(self.gtx.decoders[1].k),
|
||||||
If(self.gtx.clk_aligner.comma_det.detected,
|
# If(self.gtx.clk_aligner.comma_det.detected,
|
||||||
self.shifted.status.eq(self.gtx.clk_aligner.comma_det.bitshift),
|
# self.shifted.status.eq(self.gtx.clk_aligner.comma_det.bitshift),
|
||||||
)
|
# )
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -299,8 +299,16 @@ class Comma_Detector(Module):
|
||||||
|
|
||||||
# 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.
|
# compared to the usual 8b10b binary representation.
|
||||||
|
# 50000 62.5MHz locks | 125MHz takes a lot time to locks | 250MHz many commas
|
||||||
|
# 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):
|
class Manual_Aligner(Module):
|
||||||
def __init__(self, comma, check_period=50_000, width=20):
|
def __init__(self, comma, check_period=24_700, width=20):
|
||||||
self.rxslide = Signal()
|
self.rxslide = Signal()
|
||||||
self.data = Signal(width)
|
self.data = Signal(width)
|
||||||
self.rxinit_done = Signal()
|
self.rxinit_done = Signal()
|
||||||
|
@ -310,24 +318,29 @@ class Manual_Aligner(Module):
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
|
||||||
self.submodules.restart_ps = restart_ps = PulseSynchronizer("cxp_gtx_rx", "sys")
|
|
||||||
|
|
||||||
timerout_period = 5_000_000
|
timerout_period = 5_000_000
|
||||||
timerout = Signal(reset=timerout_period-1, max=timerout_period)
|
timerout = Signal(reset=timerout_period-1, max=timerout_period)
|
||||||
|
|
||||||
ready_sys = Signal()
|
ready_rxclk = Signal()
|
||||||
self.specials += MultiReg(self.ready, ready_sys)
|
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
|
# 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
|
# 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
|
# Restart rx periodically since rx need to be restart when connecting RXN/RXP
|
||||||
self.sync += [
|
self.sync += [
|
||||||
self.restart.eq(0),
|
self.restart.eq(0),
|
||||||
If(restart_ps.o,
|
If(restart_sys,
|
||||||
timerout.eq(timerout.reset),
|
timerout.eq(timerout.reset),
|
||||||
self.restart.eq(1),
|
self.restart.eq(1),
|
||||||
),
|
).Elif(~self.ready,
|
||||||
If(~ready_sys,
|
|
||||||
If((timerout == 0),
|
If((timerout == 0),
|
||||||
timerout.eq(timerout.reset),
|
timerout.eq(timerout.reset),
|
||||||
self.restart.eq(1),
|
self.restart.eq(1),
|
||||||
|
@ -337,115 +350,67 @@ class Manual_Aligner(Module):
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
self.comma_det_reset = Signal()
|
||||||
|
self.comma_aligned = Signal()
|
||||||
|
|
||||||
self.submodules.comma_det = comma_det = ClockDomainsRenamer("cxp_gtx_rx")(Comma_Detector(comma, width))
|
comma_n = ~comma & 0b1111111111
|
||||||
self.comb += comma_det.data.eq(self.data)
|
self.sync.cxp_gtx_rx += [
|
||||||
|
If(self.comma_det_reset,
|
||||||
|
self.comma_aligned.eq(0)
|
||||||
|
).Elif((self.data[:10] == comma) | (self.data[:10] == comma_n),
|
||||||
|
self.comma_aligned.eq(1)
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
# minimum of 32 RXUSRCLK2 cycles are required between two RXSLIDE pulses
|
|
||||||
# There is latency between the slide and the slide result at RXDATA
|
|
||||||
# Max = 967.5 UI
|
|
||||||
# see 42662 - 7 Series GTX Transceivers - TX and RX Latency Values
|
|
||||||
# https://support.xilinx.com/s/article/42662?language=en_US
|
|
||||||
self.submodules.timer = timer = ClockDomainsRenamer("cxp_gtx_rx")(WaitTimer(64))
|
|
||||||
|
|
||||||
# DS191 (v1.18.1) Table 95
|
|
||||||
# Tlock = 50000 UI
|
|
||||||
self.submodules.cdr_stable_timer = cdr_stable_timer = ClockDomainsRenamer("cxp_gtx_rx")(WaitTimer(check_period))
|
|
||||||
self.submodules.fsm = fsm = ClockDomainsRenamer("cxp_gtx_rx")(FSM(reset_state="IDLE"))
|
self.submodules.fsm = fsm = ClockDomainsRenamer("cxp_gtx_rx")(FSM(reset_state="IDLE"))
|
||||||
|
|
||||||
|
|
||||||
# NOTE: if this is connected to PMOD it will work on 250MHz
|
|
||||||
# BUG: somehow the comma det doesn't work after the cdr_stable_timer :( thus, waiting for the timeout to happen
|
|
||||||
# (which I know from bruteforcealigner, doesn't work well :( )
|
|
||||||
rxinit_done_rxclk = Signal()
|
rxinit_done_rxclk = Signal()
|
||||||
self.specials += MultiReg(self.rxinit_done, rxinit_done_rxclk, odomain="cxp_gtx_rx")
|
self.specials += MultiReg(self.rxinit_done, rxinit_done_rxclk, odomain="cxp_gtx_rx")
|
||||||
|
|
||||||
check_timer = Signal(reset=check_period-1,max=check_period)
|
check_timer = Signal(reset=check_period-1,max=check_period)
|
||||||
slide_counter = Signal(max=width)
|
|
||||||
|
|
||||||
fsm.act("IDLE",
|
fsm.act("IDLE",
|
||||||
comma_det.reset.eq(1),
|
self.comma_det_reset.eq(1),
|
||||||
If(rxinit_done_rxclk,
|
If(rxinit_done_rxclk,
|
||||||
|
NextValue(check_timer, check_timer.reset),
|
||||||
NextState("WAIT_COMMA_DET"),
|
NextState("WAIT_COMMA_DET"),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
fsm.act("WAIT_COMMA_DET",
|
fsm.act("WAIT_COMMA_DET",
|
||||||
cdr_stable_timer.wait.eq(1),
|
NextValue(check_timer, check_timer - 1),
|
||||||
If(cdr_stable_timer.done,
|
If(check_timer == 0,
|
||||||
If(comma_det.comma_aligned,
|
restart_rxclk.eq(1),
|
||||||
NextState("READY")
|
NextState("RESET"),
|
||||||
).Else(
|
# restart_ps.i.eq(1),
|
||||||
restart_ps.i.eq(1),
|
# NextState("IDLE"),
|
||||||
NextState("IDLE"),
|
).Elif(self.comma_aligned,
|
||||||
)
|
NextValue(check_timer, check_timer.reset),
|
||||||
),
|
self.comma_det_reset.eq(1),
|
||||||
|
NextState("READY")
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
fsm.act("READY",
|
fsm.act("READY",
|
||||||
self.ready.eq(1),
|
ready_rxclk.eq(1),
|
||||||
If(check_timer == 0,
|
If(check_timer == 0,
|
||||||
NextValue(check_timer, check_timer.reset),
|
NextValue(check_timer, check_timer.reset),
|
||||||
comma_det.reset.eq(1),
|
self.comma_det_reset.eq(1),
|
||||||
If(~comma_det.comma_aligned,
|
If(~self.comma_aligned,
|
||||||
restart_ps.i.eq(1),
|
restart_rxclk.eq(1),
|
||||||
NextState("IDLE"),
|
NextState("RESET"),
|
||||||
|
# restart_ps.i.eq(1),
|
||||||
|
# NextState("IDLE"),
|
||||||
)
|
)
|
||||||
).Else(
|
).Else(
|
||||||
NextValue(check_timer, check_timer - 1),
|
NextValue(check_timer, check_timer - 1),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# fsm.act("IDLE",
|
fsm.act("RESET",
|
||||||
# comma_det.reset.eq(1),
|
restart_rxclk.eq(1),
|
||||||
# If(rxinit_done_rxclk,
|
)
|
||||||
# cdr_stable_timer.wait.eq(1),
|
|
||||||
# If(cdr_stable_timer.done,
|
|
||||||
# NextState("WAIT_COMMA_DET"),
|
|
||||||
# ),
|
|
||||||
# ),
|
|
||||||
# )
|
|
||||||
|
|
||||||
# fsm.act("WAIT_COMMA_DET",
|
|
||||||
# If(comma_det.detected,
|
|
||||||
# NextValue(slide_counter, comma_det.bitshift),
|
|
||||||
# NextState("SLIDING")
|
|
||||||
# )
|
|
||||||
# )
|
|
||||||
|
|
||||||
# fsm.act("SLIDING",
|
|
||||||
# comma_det.reset.eq(1),
|
|
||||||
# If(slide_counter == 0,
|
|
||||||
# NextValue(check_timer, check_timer.reset),
|
|
||||||
# NextState("READY")
|
|
||||||
# ).Else(
|
|
||||||
# NextValue(slide_counter, slide_counter - 1),
|
|
||||||
# self.rxslide.eq(1),
|
|
||||||
# NextState("WAIT_DATA_SLIDE"),
|
|
||||||
# )
|
|
||||||
# )
|
|
||||||
|
|
||||||
# fsm.act("WAIT_DATA_SLIDE",
|
|
||||||
# comma_det.reset.eq(1),
|
|
||||||
# timer.wait.eq(1),
|
|
||||||
# If(timer.done,
|
|
||||||
# NextState("SLIDING"),
|
|
||||||
# )
|
|
||||||
# )
|
|
||||||
|
|
||||||
# fsm.act("READY",
|
|
||||||
# self.ready.eq(1),
|
|
||||||
# If(check_timer == 0,
|
|
||||||
# NextValue(check_timer, check_timer.reset),
|
|
||||||
# comma_det.reset.eq(1),
|
|
||||||
# If(~comma_det.comma_aligned,
|
|
||||||
# restart_ps.i.eq(1),
|
|
||||||
# NextState("IDLE"),
|
|
||||||
# )
|
|
||||||
# ).Else(
|
|
||||||
# NextValue(check_timer, check_timer - 1),
|
|
||||||
# )
|
|
||||||
# )
|
|
||||||
|
|
||||||
|
|
||||||
class GTX(Module):
|
class GTX(Module):
|
||||||
|
@ -593,7 +558,7 @@ class GTX(Module):
|
||||||
i_RXDFEXYDEN=1,
|
i_RXDFEXYDEN=1,
|
||||||
i_RXDFEXYDHOLD=0,
|
i_RXDFEXYDHOLD=0,
|
||||||
i_RXDFEXYDOVRDEN=0,
|
i_RXDFEXYDOVRDEN=0,
|
||||||
i_RXLPMEN=0, # RXLPMEN = 0: DFE mode is enabled
|
i_RXLPMEN=1, # RXLPMEN = 1: LPM 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,
|
||||||
|
|
Loading…
Reference in New Issue