diff --git a/src/gateware/cxp_downconn.py b/src/gateware/cxp_downconn.py index bdf6443..be342f4 100644 --- a/src/gateware/cxp_downconn.py +++ b/src/gateware/cxp_downconn.py @@ -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.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.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.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_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=, 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.decoded_data_1.status.eq(self.gtx.decoders[1].d), self.decoded_k_1.status.eq(self.gtx.decoders[1].k), - If(self.gtx.clk_aligner.comma_det.detected, - self.shifted.status.eq(self.gtx.clk_aligner.comma_det.bitshift), - ) + # If(self.gtx.clk_aligner.comma_det.detected, + # 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 # 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): - def __init__(self, comma, check_period=50_000, width=20): + def __init__(self, comma, check_period=24_700, width=20): self.rxslide = Signal() self.data = Signal(width) 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 = Signal(reset=timerout_period-1, max=timerout_period) - ready_sys = Signal() - self.specials += MultiReg(self.ready, ready_sys) + 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_ps.o, + If(restart_sys, timerout.eq(timerout.reset), self.restart.eq(1), - ), - If(~ready_sys, + ).Elif(~self.ready, If((timerout == 0), timerout.eq(timerout.reset), 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)) - self.comb += comma_det.data.eq(self.data) + comma_n = ~comma & 0b1111111111 + 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")) - # 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() self.specials += MultiReg(self.rxinit_done, rxinit_done_rxclk, odomain="cxp_gtx_rx") check_timer = Signal(reset=check_period-1,max=check_period) - slide_counter = Signal(max=width) fsm.act("IDLE", - comma_det.reset.eq(1), + self.comma_det_reset.eq(1), If(rxinit_done_rxclk, + NextValue(check_timer, check_timer.reset), NextState("WAIT_COMMA_DET"), ), ) fsm.act("WAIT_COMMA_DET", - cdr_stable_timer.wait.eq(1), - If(cdr_stable_timer.done, - If(comma_det.comma_aligned, - NextState("READY") - ).Else( - restart_ps.i.eq(1), - NextState("IDLE"), - ) - ), + NextValue(check_timer, check_timer - 1), + If(check_timer == 0, + restart_rxclk.eq(1), + NextState("RESET"), + # restart_ps.i.eq(1), + # NextState("IDLE"), + ).Elif(self.comma_aligned, + NextValue(check_timer, check_timer.reset), + self.comma_det_reset.eq(1), + NextState("READY") + ) ) fsm.act("READY", - self.ready.eq(1), + ready_rxclk.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"), + self.comma_det_reset.eq(1), + If(~self.comma_aligned, + restart_rxclk.eq(1), + NextState("RESET"), + # restart_ps.i.eq(1), + # NextState("IDLE"), ) ).Else( NextValue(check_timer, check_timer - 1), ) ) - # fsm.act("IDLE", - # comma_det.reset.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), - # ) - # ) + fsm.act("RESET", + restart_rxclk.eq(1), + ) class GTX(Module): @@ -593,7 +558,7 @@ class GTX(Module): i_RXDFEXYDEN=1, i_RXDFEXYDHOLD=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_VP_CFG=0b00011111100000011, p_RX_DFE_UT_CFG=0b10001000000000000,