From 30cc069a29565c6d869a35da9202cb1d55e38af1 Mon Sep 17 00:00:00 2001 From: morgan Date: Thu, 10 Oct 2024 13:06:46 +0800 Subject: [PATCH] cxp GW: fix read ptr not restarting with rx cxp GW: express size in bytes instead of bits --- src/gateware/cxp.py | 126 +++++++++++++++++++++----------------------- 1 file changed, 61 insertions(+), 65 deletions(-) diff --git a/src/gateware/cxp.py b/src/gateware/cxp.py index c0a4423..7dd9010 100644 --- a/src/gateware/cxp.py +++ b/src/gateware/cxp.py @@ -16,29 +16,32 @@ class CXP_PHYS(Module, AutoCSR): @FullMemoryWE() class CXP_Interface(Module, AutoCSR): def __init__(self, upconn_phy, downconn_phy, debug_sma, pmod_pads): - # TODO: move all transceiver csr into a transceiver interface submodule + # TODO: add rtio interface io self.submodules.upconn = UpConn_Interface(upconn_phy, debug_sma, pmod_pads) self.submodules.downconn = DownConn_Interface(downconn_phy, debug_sma, pmod_pads) def get_tx_port(self): - return self.upconn.command.mem.get_port(write_capable=True) + return self.upconn.bootstrap.mem.get_port(write_capable=True) def get_tx_mem_size(self): - return self.upconn.command.mem.depth*self.upconn.command.mem.width + # FIXME: if tx mem size is same as rx, for some reason when rx mem is writen, tx mem cannot be access anymore + # and each time tx mem is read, CPU will return rx mem instead + return self.upconn.bootstrap.mem.depth*self.upconn.bootstrap.mem.width // 8 + # return self.downconn.bootstrap.mem.depth*self.downconn.bootstrap.mem.width // 8 def get_rx_port(self): - return self.downconn.packet_decoder.mem.get_port(write_capable=False) + return self.downconn.bootstrap.mem.get_port(write_capable=False) def get_rx_mem_size(self): - return self.downconn.packet_decoder.mem.depth*self.downconn.packet_decoder.mem.width + return self.downconn.bootstrap.mem.depth*self.downconn.bootstrap.mem.width // 8 def get_loopback_tx_port(self): - return self.downconn.command.mem.get_port(write_capable=True) + return self.downconn.bootstrap_loopback.mem.get_port(write_capable=True) def get_loopback_tx_mem_size(self): - return self.downconn.command.mem.depth*self.downconn.command.mem.width + return self.downconn.bootstrap_loopback.mem.depth*self.downconn.bootstrap_loopback.mem.width // 8 class DownConn_Interface(Module, AutoCSR): def __init__(self, phy, debug_sma, pmod_pads): @@ -149,17 +152,17 @@ class DownConn_Interface(Module, AutoCSR): # DEBUG: Transmission Pipeline # - # test pak ----+ - # from gw | 32 32 - # |---/---> mux -----> packet -----> trigger ack ---/---> PHY - # | wrapper inserter - # data pak ----+ - # from fw + # rtio pak ----+ + # from gw | 32 32 + # mux---/---> packet -----> trigger ack ---/---> PHY + # | wrapper inserter + # data/test ----+ + # pak from fw + # # DEBUG: TX pipeline - self.submodules.command = command = TX_Command_Packet() - self.submodules.testseq = testseq = TX_Test_Packet() + self.submodules.bootstrap_loopback = bootstrap_loopback = TX_Bootstrap() self.submodules.mux = mux = stream.Multiplexer(word_layout, 2) self.submodules.pak_wrp = pak_wrp = Packet_Wrapper() self.submodules.trig_ack = trig_ack = Trigger_ACK_Inserter() @@ -169,8 +172,7 @@ class DownConn_Interface(Module, AutoCSR): self.sync += trig_ack.stb.eq(self.ack.re), self.comb += [ - command.source.connect(mux.sink0), - testseq.source.connect(mux.sink1), + bootstrap_loopback.source.connect(mux.sink0), mux.sel.eq(self.mux_sel.storage), ] @@ -207,36 +209,36 @@ class DownConn_Interface(Module, AutoCSR): ] # Priority level 2 packet - data, test packet - self.submodules.packet_decoder = packet_decoder = cdr(CXP_Data_Packet_Decode()) + self.submodules.bootstrap = bootstrap = cdr(RX_Bootstrap()) - self.decoder_error = CSR() - self.test_error = CSR() - self.buffer_error = CSR() + self.bootstrap_decoder_err = CSR() + self.bootstrap_test_err = CSR() + self.boostrap_buffer_err = CSR() decode_err_ps = PulseSynchronizer("cxp_gtx_rx", "sys") test_err_ps = PulseSynchronizer("cxp_gtx_rx", "sys") buffer_err_ps = PulseSynchronizer("cxp_gtx_rx", "sys") self.submodules += decode_err_ps, test_err_ps, buffer_err_ps self.comb += [ - decode_err_ps.i.eq(packet_decoder.decode_err), - test_err_ps.i.eq(packet_decoder.test_err), - buffer_err_ps.i.eq(packet_decoder.buffer_err), + decode_err_ps.i.eq(bootstrap.decode_err), + test_err_ps.i.eq(bootstrap.test_err), + buffer_err_ps.i.eq(bootstrap.buffer_err), ] self.sync += [ If(decode_err_ps.o, - self.decoder_error.w.eq(1), - ).Elif(self.decoder_error.re, - self.decoder_error.w.eq(0), + self.bootstrap_decoder_err.w.eq(1), + ).Elif(self.bootstrap_decoder_err.re, + self.bootstrap_decoder_err.w.eq(0), ), If(test_err_ps.o, - self.test_error.w.eq(1), - ).Elif(self.test_error.re, - self.test_error.w.eq(0), + self.bootstrap_test_err.w.eq(1), + ).Elif(self.bootstrap_test_err.re, + self.bootstrap_test_err.w.eq(0), ), If(buffer_err_ps.o, - self.buffer_error.w.eq(1), - ).Elif(self.test_error.re, - self.buffer_error.w.eq(0), + self.boostrap_buffer_err.w.eq(1), + ).Elif(self.bootstrap_test_err.re, + self.boostrap_buffer_err.w.eq(0), ), ] @@ -247,12 +249,14 @@ class DownConn_Interface(Module, AutoCSR): self.read_ptr = CSRStatus(log2_int(buffer_count)) self.specials += [ - MultiReg(packet_decoder.packet_type, self.packet_type.status), - MultiReg(self.read_ptr.status, packet_decoder.read_ptr_rx, odomain="cxp_gtx_rx"), + MultiReg(bootstrap.packet_type, self.packet_type.status), + MultiReg(self.read_ptr.status, bootstrap.read_ptr_rx, odomain="cxp_gtx_rx"), ] self.sync += [ - self.pending_packet.w.eq(self.read_ptr.status != packet_decoder.write_ptr_sys), - If(self.pending_packet.re & self.pending_packet.w, + self.pending_packet.w.eq(self.read_ptr.status != bootstrap.write_ptr_sys), + If(self.rx_restart.re, + self.read_ptr.status.eq(0), + ).Elif(self.pending_packet.re & self.pending_packet.w, self.read_ptr.status.eq(self.read_ptr.status + 1), ) ] @@ -263,8 +267,18 @@ class DownConn_Interface(Module, AutoCSR): self.submodules += ClockDomainsRenamer({"write": "cxp_gtx_rx", "read": "sys"})(cdc_fifo) self.submodules.debug_out = debug_out = RX_Debug_Buffer() + self.dmux_sel = CSRStorage() + self.submodules.dmux = dmux = stream.Demultiplexer(word_layout, 2) - rx_pipeline = [phy, trig_ack_checker, packet_decoder, cdc_fifo, debug_out] + + self.comb += [ + dmux.source0.connect(bootstrap.sink), + dmux.source1.connect(cdc_fifo.sink), + cdc_fifo.source.connect(debug_out.sink), + dmux.sel.eq(self.dmux_sel.storage), + ] + + rx_pipeline = [phy, trig_ack_checker, dmux] for s, d in zip(rx_pipeline, rx_pipeline[1:]): self.comb += s.source.connect(d.sink) @@ -278,14 +292,14 @@ class DownConn_Interface(Module, AutoCSR): pak_start = Signal() self.sync += [ - pak_start.eq(packet_decoder.sink.data == 0xFBFBFBFB), + pak_start.eq(bootstrap.sink.data == 0xFBFBFBFB), ] self.specials += [ Instance("OBUF", i_I=phy.gtx.cd_cxp_gtx_rx.clk, o_O=debug_sma.p_tx), # Instance("OBUF", i_I=, o_O=debug_sma.p_rx), # # pmod 0-7 pin - Instance("OBUF", i_I=packet_decoder.test_err, o_O=pmod_pads[0]), + Instance("OBUF", i_I=bootstrap.test_err, o_O=pmod_pads[0]), Instance("OBUF", i_I=pak_start, o_O=pmod_pads[1]), # Instance("OBUF", i_I=fifo_in.source.ack, o_O=pmod_pads[2]), # Instance("OBUF", i_I=gtx.comma_checker.aligner_en, o_O=pmod_pads[3]), @@ -301,11 +315,7 @@ class UpConn_Interface(Module, AutoCSR): self.clk_reset = CSRStorage(reset=1) self.bitrate2x_enable = CSRStorage() self.tx_enable = CSRStorage() - - # TODO: add busy condition - self.tx_busy = CSRStatus() - - self.tx_testmode_en = CSRStorage() + self.tx_mux = CSRStorage() # # # @@ -317,13 +327,10 @@ class UpConn_Interface(Module, AutoCSR): # Transmission Pipeline - # - # test pak ----+ - # from gw | 32 32 8 - # |---/---> mux -----> packet -----> idle word -----> trigger ack ---/--> conv ---/---> trigger -----> PHY - # | wrapper inserter inserter inserter - # data pak ----+ - # from fw + # + # 32 32 8 + # ctrl/test ---/---> packet -----> idle word -----> trigger ack ---/--> conv ---/---> trigger -----> PHY + # packet wrapper inserter inserter inserter # # Equivalent transmission priority: # trigger > trigger ack > idle > test/data packet @@ -362,20 +369,9 @@ class UpConn_Interface(Module, AutoCSR): # 2: All other packets (data & test packet) # Control is not timing dependent, all the data packets are handled in firmware - - self.submodules.command = command = TX_Command_Packet() - self.submodules.testseq = testseq = TX_Test_Packet() - self.submodules.mux = mux = stream.Multiplexer(word_layout, 2) - - self.comb += [ - command.source.connect(mux.sink0), - testseq.source.connect(mux.sink1), - mux.sel.eq(self.tx_testmode_en.storage), - ] + self.submodules.bootstrap = bootstrap = TX_Bootstrap() self.submodules.pak_wrp = pak_wrp = Packet_Wrapper() - - # IDLE Word self.submodules.idle = idle = Idle_Word_Inserter() # Section 9.2.5.1 (CXP-001-2021) @@ -394,6 +390,6 @@ class UpConn_Interface(Module, AutoCSR): self.submodules.converter = converter = stream.StrideConverter(word_layout, char_layout) - tx_pipeline = [mux, pak_wrp, idle, trig_ack, converter, trig, phy] + tx_pipeline = [bootstrap, pak_wrp, idle, trig_ack, converter, trig, phy] for s, d in zip(tx_pipeline, tx_pipeline[1:]): self.comb += s.source.connect(d.sink)