diff --git a/src/gateware/cxp_downconn.py b/src/gateware/cxp_downconn.py index 5226f36..962560e 100644 --- a/src/gateware/cxp_downconn.py +++ b/src/gateware/cxp_downconn.py @@ -10,6 +10,113 @@ from artiq.gateware.drtio.transceiver.gtx_7series_init import * from operator import add from functools import reduce +class CXP_DownConn(Module, AutoCSR): + def __init__(self, refclk, pads, sys_clk_freq, debug_sma, pmod_pads): + self.rx_start_init = CSRStorage() + self.rx_restart = CSRStorage() + + self.tx_start_init = CSRStorage() + self.tx_restart = CSRStorage() + self.txenable = CSRStorage() + + + self.txinit_phaligndone = CSRStatus() + self.rxinit_phaligndone = CSRStatus() + self.rx_ready = CSRStatus() + + # # # + + # TODO: QPLL (GTXE2_COMMON) here + # CPLL too slow for 12.5Gbps :( + + # single & master tx_mode can lock with rx in loopback + self.submodules.gtx = CXP_GTX(refclk, pads, sys_clk_freq, tx_mode="single", rx_mode="single") + + self.comb += [ + self.txinit_phaligndone.status.eq(self.gtx.tx_init.Xxphaligndone), + # self.rxinit_phaligndone.status.eq(self.gtx.rx_init.Xxphaligndone), + self.rx_ready.status.eq(self.gtx.rx_ready), + + self.gtx.txenable.eq(self.txenable.storage[0]), + self.gtx.tx_restart.eq(self.tx_restart.storage), + self.gtx.rx_restart.eq(self.rx_restart.storage), + self.gtx.tx_init.clk_path_ready.eq(self.tx_start_init.storage), + self.gtx.rx_init.clk_path_ready.eq(self.rx_start_init.storage), + # self.gtx.rx_alignment_en.eq(self.rx_data_alignment.storage), + ] + + # DEBUG:loopback + self.loopback_mode = CSRStorage(3) + self.comb += self.gtx.loopback_mode.eq(self.loopback_mode.storage) + + # DEBUG:SMA + self.specials += [ + Instance("OBUF", i_I=self.gtx.rxoutclk, o_O=debug_sma.p_tx), + Instance("OBUF", i_I=self.gtx.cd_cxp_gtx_tx.clk, o_O=debug_sma.n_rx) + ] + + # DEBUG: datain + counter_max = 2 + counter = Signal(max=counter_max) + + self.data_0 = CSRStorage(8) + self.data_1 = CSRStorage(8) + self.data_2 = CSRStorage(8) + self.data_3 = CSRStorage(8) + self.control_bit_0 = CSRStorage() + self.control_bit_1 = CSRStorage() + self.control_bit_2 = CSRStorage() + self.control_bit_3 = CSRStorage() + self.encoded_0 = CSRStatus(10) + self.encoded_1 = CSRStatus(10) + + self.rxdata_0 = CSRStatus(10) + self.rxdata_1 = CSRStatus(10) + self.decoded_data_0 = CSRStatus(8) + self.decoded_data_1 = CSRStatus(8) + self.decoded_k_0 = CSRStatus() + self.decoded_k_1 = CSRStatus() + + + self.sync.cxp_gtx_tx += [ + If(counter == 0, + self.gtx.encoder.d[0].eq(self.data_0.storage), + self.gtx.encoder.k[0].eq(self.control_bit_0.storage), + self.gtx.encoder.d[1].eq(self.data_1.storage), + self.gtx.encoder.k[1].eq(self.control_bit_1.storage), + counter.eq(counter+1), + ).Elif(counter == 1, + self.gtx.encoder.d[0].eq(self.data_2.storage), + self.gtx.encoder.k[0].eq(self.control_bit_2.storage), + self.gtx.encoder.d[1].eq(self.data_3.storage), + self.gtx.encoder.k[1].eq(self.control_bit_3.storage), + counter.eq(0), + ), + self.encoded_0.status.eq(self.gtx.encoder.output[0]), + self.encoded_1.status.eq(self.gtx.encoder.output[1]), + ] + + self.sync.cxp_gtx_rx += [ + self.rxdata_0.status.eq(self.gtx.decoders[0].input), + self.decoded_data_0.status.eq(self.gtx.decoders[0].d), + self.decoded_k_0.status.eq(self.gtx.decoders[0].k), + + 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), + ] + + + # The TX phase alignment will fail with a wrong TXUSRCLK frequency + + + + # NOTE: No need to connect cxp_gtx_tx, we don't use tx anyway (just for loopback) + + # TODO: Connect slave cxp_gtx_rx clock tgt + # checkout channel interfaces & drtio_gtx + # checkout GTPTXPhaseAlignement for inspiration + # Changes the phase of the transceiver RX clock to align the comma to # the LSBs of RXDATA, fixing the latency. # @@ -117,7 +224,7 @@ class CXP_BruteforceClockAligner(Module): -class CXP_DownConn(Module): +class CXP_GTX(Module): # Settings: # * GTX reference clock @ 125MHz # * GTX data width = 20