diff --git a/src/gateware/cxp_downconn.py b/src/gateware/cxp_downconn.py index 95c1177..9f71685 100644 --- a/src/gateware/cxp_downconn.py +++ b/src/gateware/cxp_downconn.py @@ -20,14 +20,10 @@ class CXP_DownConn(Module, AutoCSR): self.tx_restart = CSR() self.txenable = CSRStorage() - self.txinit_phaligndone = CSRStatus() self.rxinit_phaligndone = CSRStatus() self.rx_ready = CSRStatus() - self.tx_div = CSRStorage(3) - self.rx_div = CSRStorage(3) - self.qpll_reset = CSR() self.qpll_locked = CSRStatus() @@ -47,7 +43,6 @@ class CXP_DownConn(Module, AutoCSR): # PLL qpll.reset.eq(self.qpll_reset.re), self.qpll_locked.status.eq(qpll.lock), - # GTX self.txinit_phaligndone.status.eq(gtx.tx_init.Xxphaligndone), self.rxinit_phaligndone.status.eq(gtx.rx_init.Xxphaligndone), @@ -58,13 +53,47 @@ class CXP_DownConn(Module, AutoCSR): gtx.rx_restart.eq(self.rx_restart.re), gtx.tx_init.clk_path_ready.eq(self.tx_start_init.storage), gtx.rx_init.clk_path_ready.eq(self.rx_start_init.storage), - # gtx.rx_alignment_en.eq(self.rx_data_alignment.storage), + ] - # GTX DRP + # GTX Channels DRP + self.tx_div = CSRStorage(3) + self.rx_div = CSRStorage(3) + + self.gtx_daddr = CSRStorage(9) + self.gtx_dread = CSR() + self.gtx_din_stb = CSR() + self.gtx_din = CSRStorage(16) + + self.gtx_dout = CSRStatus(16) + self.gtx_dready = CSR() + + self.comb += gtx.dclk.eq(ClockSignal("sys")), + self.sync += [ gtx.tx_rate.eq(self.tx_div.storage), gtx.rx_rate.eq(self.rx_div.storage), + + gtx.den.eq(0), + gtx.dwen.eq(0), + If(self.gtx_dread.re, + gtx.den.eq(1), + gtx.daddr.eq(self.gtx_daddr.storage), + ).Elif(self.gtx_din_stb.re, + gtx.den.eq(1), + gtx.dwen.eq(1), + gtx.daddr.eq(self.gtx_daddr.storage), + gtx.din.eq(self.gtx_din.storage), + ), + If(gtx.dready, + self.gtx_dready.w.eq(1), + self.gtx_dout.status.eq(gtx.dout), + ), + If(self.gtx_dready.re, + self.gtx_dready.w.eq(0), + ), ] + + # DEBUG: txusrclk PLL DRG self.txpll_reset = CSRStorage() @@ -130,7 +159,13 @@ class CXP_DownConn(Module, AutoCSR): 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=valid_data, o_O=pmod_pads[5]), + # Instance("OBUF", i_I=, o_O=pmod_pads[6]), # Instance("OBUF", i_I=, o_O=pmod_pads[7]), + + # Instance("OBUF", i_I=gtx.dclk, o_O=pmod_pads[0]), + # Instance("OBUF", i_I=gtx.den, o_O=pmod_pads[1]), + # Instance("OBUF", i_I=gtx.dwen, o_O=pmod_pads[2]), + # Instance("OBUF", i_I=gtx.dready, o_O=pmod_pads[3]), ] # DEBUG: datain @@ -282,7 +317,6 @@ 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): @@ -409,6 +443,15 @@ class GTX(Module): self.tx_rate = Signal(3) self.rx_rate = Signal(3) + # Dynamic Reconfiguration Ports + self.daddr = Signal(9) + self.dclk = Signal() + self.den = Signal() + self.dwen = Signal() + self.din = Signal(16) + self.dout = Signal(16) + self.dready = Signal() + self.submodules.encoder = ClockDomainsRenamer("cxp_gtx_tx")(Encoder(2, True)) self.submodules.decoders = [ClockDomainsRenamer("cxp_gtx_rx")( (Decoder(True))) for _ in range(2)] @@ -624,6 +667,16 @@ class GTX(Module): o_GTXTXP=pads.txp, o_GTXTXN=pads.txn, + # Dynamic Reconfiguration Ports + p_IS_DRPCLK_INVERTED=0b0, + i_DRPADDR=self.daddr, + i_DRPCLK=self.dclk, + i_DRPEN=self.den, + i_DRPWE=self.dwen, + i_DRPDI=self.din, + o_DRPDO=self.dout, + o_DRPRDY=self.dready, + # ! loopback for debugging i_LOOPBACK = self.loopback_mode, p_TX_LOOPBACK_DRIVE_HIZ = "FALSE",