From a6b1701de3cb28608941fe7a248fbcdda0d5a817 Mon Sep 17 00:00:00 2001 From: morgan Date: Wed, 14 Aug 2024 17:14:06 +0800 Subject: [PATCH] cxp downconn: fix aligner not work @ 5 & 6.25Gbps --- src/gateware/cxp_downconn.py | 114 +++++++---------------------------- 1 file changed, 23 insertions(+), 91 deletions(-) diff --git a/src/gateware/cxp_downconn.py b/src/gateware/cxp_downconn.py index e8cf1c3..b14982b 100644 --- a/src/gateware/cxp_downconn.py +++ b/src/gateware/cxp_downconn.py @@ -160,7 +160,7 @@ class CXP_DownConn(Module, AutoCSR): Instance("OBUF", i_I=gtx.cd_cxp_gtx_tx.clk, o_O=debug_sma.n_rx), # pmod 0-7 pin - Instance("OBUF", i_I=gtx.comma_det.rxinit_done, o_O=pmod_pads[0]), + Instance("OBUF", i_I=gtx.comma_det.word_aligned, o_O=pmod_pads[0]), Instance("OBUF", i_I=gtx.comma_det.restart, o_O=pmod_pads[1]), Instance("OBUF", i_I=gtx.comma_det.aligner_en_rxclk, o_O=pmod_pads[2]), Instance("OBUF", i_I=gtx.comma_det.check_reset, o_O=pmod_pads[3]), @@ -331,7 +331,7 @@ class QPLL(Module): class Comma_Detector(Module): def __init__(self, comma, check_period=1_000_000): self.data = Signal(20) - self.rxinit_done = Signal() + self.word_aligned = Signal() self.aligner_en_rxclk = Signal() self.ready = Signal() @@ -345,39 +345,6 @@ class Comma_Detector(Module): # - UG476 (v1.12.1) p.228 # The validity of data & comma are checked externally - # aligned = Signal() - # valid_data = Signal() - # aligned_rxclk = Signal() - # valid_data_rxclk = Signal() - # rx1cnt = Signal(max=11) - # self.specials += [ - # MultiReg(aligned_rxclk, aligned), - # MultiReg(valid_data_rxclk, valid_data), - # ] - # self.submodules.check_reset = check_reset = PulseSynchronizer("sys", "cxp_gtx_rx") - - # comma_n = ~comma & 0b1111111111 - # self.sync.cxp_gtx_rx += [ - # If(check_reset.o, - # aligned_rxclk.eq(0), - # ).Elif((self.data[:10] == comma) | (self.data[:10] == comma_n), - # aligned_rxclk.eq(1), - # ), - - # rx1cnt.eq(reduce(add, [self.data[i] for i in range(10)])), - # If(check_reset.o, - # valid_data_rxclk.eq(0), - # ).Elif((rx1cnt == 4) | (rx1cnt == 5) | (rx1cnt == 6), - # valid_data_rxclk.eq(1), - # ), - # ] - - # self.aligned = Signal() - # self.valid_data = Signal() - # self.comb +=[ - # self.aligned.eq(aligned), - # self.valid_data.eq(valid_data) - # ] check_counter = Signal(reset=check_period-1, max=check_period) @@ -465,18 +432,31 @@ class Comma_Detector(Module): self.submodules.rxfsm = rxfsm = ClockDomainsRenamer("cxp_gtx_rx")(FSM(reset_state="ALIGNING")) + # the data from gtxe2 is delayed and checking at the output may not reflect the alignment inside the aligner + # thus, failing to alignment on high linerate >5Gbps is common due to the aligner_en being asserted longer than necessary and lead to a lose of lock + # a timer is used to wait till the "aligned" data to arrive and do a system check like the datasheet suggested + self.submodules.timer = timer = ClockDomainsRenamer("cxp_gtx_rx")(WaitTimer(5000)) + rxfsm.act("ALIGNING", self.aligner_en_rxclk.eq(1), - If(comma_aligned & (~has_error), + If(self.word_aligned, check_reset.eq(1), - NextState("DOUBLE_CHECK"), + NextState("WAIT_ALIGNED_DATA"), ) ) - rxfsm.act("DOUBLE_CHECK", + rxfsm.act("WAIT_ALIGNED_DATA", + timer.wait.eq(1), + If(timer.done, + check_reset.eq(1), + NextState("CHECKING"), + ) + ) + + rxfsm.act("CHECKING", If(check, check_reset.eq(1), - If(~error_seen, + If(comma_seen & (~error_seen), NextState("READY"), ).Else( NextState("ALIGNING") @@ -490,62 +470,12 @@ class Comma_Detector(Module): ready.eq(1), If(check, check_reset.eq(1), - If(~comma_seen, + If(~(comma_seen & (~error_seen)), NextState("ALIGNING"), ) ) ) - - # self.submodules.fsm = fsm = FSM(reset_state="WAIT_RXINIT") - - # aligner_en = Signal() - # self.specials += MultiReg(aligner_en, self.aligner_en_rxclk, odomain="cxp_gtx_rx") - - # fsm.act("WAIT_RXINIT", - # If(self.rxinit_done, - # NextState("WAIT_COMMA_ALIGN"), - # ) - # ) - - # fsm.act("WAIT_COMMA_ALIGN", - # aligner_en.eq(1), - # If(check, - # check_reset.i.eq(1), - # If(aligned, - # NextState("WAIT_VALID_DATA"), - # ).Else( - # self.restart.eq(1), - # NextState("WAIT_RXINIT") - # ) - # ) - # ) - - # fsm.act("WAIT_VALID_DATA", - # aligner_en.eq(1), - # If(check, - # check_reset.i.eq(1), - # If(aligned & valid_data, - # NextState("READY"), - # ).Else( - # self.restart.eq(1), - # NextState("WAIT_RXINIT"), - # ) - # ) - # ) - - # fsm.act("READY", - # self.ready.eq(1), - # If(check, - # check_reset.i.eq(1), - # If(~(aligned & valid_data), - # self.restart.eq(1), - # NextState("WAIT_RXINIT"), - # ) - # ) - # ) - - class GTX(Module): # Settings: @@ -609,6 +539,7 @@ class GTX(Module): txdata = Signal(40) rxdata = Signal(40) + word_aligned = Signal() comma_aligner_en = Signal() # Note: the following parameters were set after consulting AR45360 self.specials += \ @@ -752,6 +683,7 @@ class GTX(Module): i_RXMCOMMAALIGNEN=comma_aligner_en, i_RXCOMMADETEN=1, i_RXSLIDE=0, + o_RXBYTEISALIGNED=word_aligned, # RX 8B/10B Decoder Attributes p_RX_DISPERR_SEQ_MATCH="FALSE", @@ -893,7 +825,7 @@ class GTX(Module): self.submodules.comma_det = comma_det = Comma_Detector(0b0101111100) self.comb += [ comma_det.data.eq(rxdata), - comma_det.rxinit_done.eq(rx_init.done), + comma_det.word_aligned.eq(word_aligned), comma_aligner_en.eq(comma_det.aligner_en_rxclk), self.rx_ready.eq(comma_det.ready),