From e055a11e1c0bf660f5729cb59f76a06023186ef0 Mon Sep 17 00:00:00 2001 From: morgan Date: Fri, 9 Aug 2024 16:52:13 +0800 Subject: [PATCH] cxp downconn: cleanup comma detector --- src/gateware/cxp_downconn.py | 92 ++++++++++++++++++++++-------------- 1 file changed, 56 insertions(+), 36 deletions(-) diff --git a/src/gateware/cxp_downconn.py b/src/gateware/cxp_downconn.py index 368271e..4b1a203 100644 --- a/src/gateware/cxp_downconn.py +++ b/src/gateware/cxp_downconn.py @@ -95,6 +95,29 @@ class CXP_DownConn(Module, AutoCSR): self.loopback_mode = CSRStorage(3) self.comb += gtx.loopback_mode.eq(self.loopback_mode.storage) + # DEBUG: RXDATA checking + aligned = Signal() + valid_data = Signal() + rx1cnt = Signal(max=11) + + comma = 0b0101111100 + comma_n = ~comma & 0b1111111111 + + self.sync.cxp_gtx_rx += [ + If(self.gtx.comma_det.check_ps.o, + aligned.eq(0), + ).Elif((gtx.comma_det.data[:10] == comma) | (gtx.comma_det.data[:10] == comma_n), + aligned.eq(1), + ), + + rx1cnt.eq(reduce(add, [gtx.comma_det.data[i] for i in range(10)])), + If(self.gtx.comma_det.check_ps.o, + valid_data.eq(0) + ).Elif((rx1cnt == 4) | (rx1cnt == 5) | (rx1cnt == 6), + valid_data.eq(1) + ), + ] + # DEBUG: IO SMA & PMOD self.specials += [ Instance("OBUF", i_I=gtx.rxoutclk, o_O=debug_sma.p_tx), @@ -104,9 +127,9 @@ class CXP_DownConn(Module, AutoCSR): Instance("OBUF", i_I=gtx.comma_det.aligner_en_rxclk, o_O=pmod_pads[0]), Instance("OBUF", i_I=gtx.comma_det.rxinit_done, o_O=pmod_pads[1]), Instance("OBUF", i_I=gtx.comma_det.restart, o_O=pmod_pads[2]), - Instance("OBUF", i_I=gtx.comma_det.comma_aligned, o_O=pmod_pads[3]), + Instance("OBUF", i_I=aligned, o_O=pmod_pads[3]), Instance("OBUF", i_I=gtx.comma_det.ready, o_O=pmod_pads[4]), - Instance("OBUF", i_I=gtx.comma_det.valid_data, o_O=pmod_pads[5]), + Instance("OBUF", i_I=valid_data, o_O=pmod_pads[5]), # Instance("OBUF", i_I=, o_O=pmod_pads[7]), ] @@ -261,8 +284,9 @@ class QPLL(Module): # Warning: Xilinx transceivers are LSB first, and comma needs to be flipped +# compared to the usual 8b10b binary representation. class Comma_Detector(Module): - def __init__(self, comma, check_period=50_000, width=20): + def __init__(self, comma, check_period=100_000, width=20): self.data = Signal(width) self.rxinit_done = Signal() @@ -272,34 +296,31 @@ class Comma_Detector(Module): # # # - - - 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) + 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_ps = check_ps = PulseSynchronizer("sys", "cxp_gtx_rx") comma_n = ~comma & 0b1111111111 - rx1cnt = Signal(max=11) self.sync.cxp_gtx_rx += [ - rx1cnt.eq(reduce(add, [self.data[i] for i in range(10)])), - If(recheck_ps.o, - self.comma_aligned.eq(0) + If(check_ps.o, + aligned_rxclk.eq(0), ).Elif((self.data[:10] == comma) | (self.data[:10] == comma_n), - self.comma_aligned.eq(1) + aligned_rxclk.eq(1), ), - If(recheck_ps.o, - self.valid_data.eq(0) + rx1cnt.eq(reduce(add, [self.data[i] for i in range(10)])), + If(check_ps.o, + valid_data_rxclk.eq(0), ).Elif((rx1cnt == 4) | (rx1cnt == 5) | (rx1cnt == 6), - self.valid_data.eq(1) + valid_data_rxclk.eq(1), ), ] @@ -307,9 +328,6 @@ class Comma_Detector(Module): 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, @@ -320,25 +338,27 @@ class Comma_Detector(Module): ) ] - self.submodules.fsm = fsm = FSM(reset_state="IDLE") + aligner_en = Signal() + self.specials += MultiReg(aligner_en, self.aligner_en_rxclk, odomain="cxp_gtx_rx") + fsm.act("IDLE", - aligner_en_sys.eq(1), + aligner_en.eq(1), If(check, - recheck_ps.i.eq(1), + check_ps.i.eq(1), If(aligned, - NextState("WAIT_NO_ERROR"), + NextState("WAIT_VALID_DATA"), ).Else( self.restart.eq(1), ) ) ) - fsm.act("WAIT_NO_ERROR", - aligner_en_sys.eq(1), + fsm.act("WAIT_VALID_DATA", + aligner_en.eq(1), If(check, - recheck_ps.i.eq(1), + check_ps.i.eq(1), If(aligned & valid_data, NextState("READY"), ).Else( @@ -351,7 +371,7 @@ class Comma_Detector(Module): fsm.act("READY", self.ready.eq(1), If(check, - recheck_ps.i.eq(1), + check_ps.i.eq(1), If(~(aligned & valid_data), self.restart.eq(1), NextState("IDLE"), @@ -414,7 +434,7 @@ class GTX(Module): txdata = Signal(20) rxdata = Signal(20) - comma_align_en = Signal() + comma_aligner_en = Signal() # Note: the following parameters were set after consulting AR45360 self.specials += \ Instance("GTXE2_CHANNEL", @@ -553,8 +573,8 @@ class GTX(Module): p_RXSLIDE_AUTO_WAIT=7, p_RXSLIDE_MODE="OFF", p_RX_SIG_VALID_DLY=10, - i_RXPCOMMAALIGNEN=comma_align_en, - i_RXMCOMMAALIGNEN=comma_align_en, + i_RXPCOMMAALIGNEN=comma_aligner_en, + i_RXMCOMMAALIGNEN=comma_aligner_en, i_RXCOMMADETEN=1, # enable auto word alignment # RX 8B/10B Decoder Attributes @@ -686,7 +706,7 @@ class GTX(Module): self.comb += [ comma_det.data.eq(rxdata), comma_det.rxinit_done.eq(rx_init.done), - comma_align_en.eq(comma_det.aligner_en_rxclk), + comma_aligner_en.eq(comma_det.aligner_en_rxclk), self.rx_ready.eq(comma_det.ready), rx_init.restart.eq(self.rx_restart | comma_det.restart),