diff --git a/src/gateware/cxp.py b/src/gateware/cxp.py index 16dafa5..a67255d 100644 --- a/src/gateware/cxp.py +++ b/src/gateware/cxp.py @@ -295,7 +295,6 @@ class TX_Pipeline(Module, AutoCSR): class CXP_Frame_Pipeline(Module, AutoCSR): # optimal stream packet size is 2 KiB - Section 9.5.2 (CXP-001-2021) - # largest x/y pixel size supported by frame header are 24 bits def __init__(self, rx_pipelines, pmod_pads, roi_engine_count=1, res_width=16, count_width=31, packet_size=16384): n_downconn = len(rx_pipelines) assert n_downconn > 0 @@ -315,62 +314,63 @@ class CXP_Frame_Pipeline(Module, AutoCSR): # # # cdr = ClockDomainsRenamer("cxp_gtx_rx") + + debug_out = False - # self.submodules.pixel_pipeline = pixel_pipeline = cdr(Pixel_Pipeline(res_width, count_width)) + if not debug_out: + self.submodules.pixel_pipeline = pixel_pipeline = cdr(Pixel_Pipeline(res_width, count_width)) - # # RTIO interface + # RTIO interface - # n = 0 - # cfg = pixel_pipeline.roi.cfg - # for offset, target in enumerate([cfg.x0, cfg.y0, cfg.x1, cfg.y1]): - # roi_boundary = Signal.like(target) - # self.sync.rio += If(self.config.o.stb & (self.config.o.address == 4*n+offset), - # roi_boundary.eq(self.config.o.data)) - # self.specials += MultiReg(roi_boundary, target, "cxp_gtx_rx") + n = 0 + cfg = pixel_pipeline.roi.cfg + for offset, target in enumerate([cfg.x0, cfg.y0, cfg.x1, cfg.y1]): + roi_boundary = Signal.like(target) + self.sync.rio += If(self.config.o.stb & (self.config.o.address == 4*n+offset), + roi_boundary.eq(self.config.o.data)) + self.specials += MultiReg(roi_boundary, target, "cxp_gtx_rx") - # roi_out = pixel_pipeline.roi.out - # update = Signal() - # self.submodules.ps = ps = PulseSynchronizer("cxp_gtx_rx", "sys") - # self.sync.cxp_gtx_rx += ps.i.eq(roi_out.update) - # self.sync += update.eq(ps.o) + roi_out = pixel_pipeline.roi.out + update = Signal() + self.submodules.ps = ps = PulseSynchronizer("cxp_gtx_rx", "sys") + self.sync.cxp_gtx_rx += ps.i.eq(roi_out.update) + self.sync += update.eq(ps.o) - # sentinel = 2**count_width - # count_sys = Signal.like(roi_out.count) - # # count_rx = Signal.like(roi_out.count) - # # self.sync.cxp_gtx_rx += count_rx.eq(roi_out.count), - # # self.specials += MultiReg(count_rx, count_sys), + sentinel = 2**count_width + count_sys = Signal.like(roi_out.count) + # count_rx = Signal.like(roi_out.count) + # self.sync.cxp_gtx_rx += count_rx.eq(roi_out.count), + # self.specials += MultiReg(count_rx, count_sys), - # self.specials += MultiReg(roi_out.count, count_sys), - # self.sync.rio += [ - # self.gate_data.i.stb.eq(update), - # self.gate_data.i.data.eq(count_sys), - # ] - - # DEBUG: - crc_checker = cdr(CXPCRC32_Checker()) + self.specials += MultiReg(roi_out.count, count_sys), + self.sync.rio += [ + self.gate_data.i.stb.eq(update), + self.gate_data.i.data.eq(count_sys), + ] - # TODO: handle full buffer gracefully - # TODO: investigate why there is a heartbeat message in the middle of the frame with k27.7 code too??? - # NOTE: sometimes there are 0xFBFBFBFB K=0b1111 - # perhaps the buffer is full overflowing and doing strange stuff + else: + # DEBUG: + crc_checker = cdr(CXPCRC32_Checker()) - # it should be mem block not "cycle buffer" - # self.submodules.dropper = dropper = cdr(DChar_Dropper()) - buffer = cdr(Buffer(word_layout_dchar)) # crcchecker timinig is bad - buffer_cdc_fifo = cdr(Buffer(word_layout_dchar)) # to improve timing - cdc_fifo = stream.AsyncFIFO(word_layout_dchar, 2**log2_int(packet_size//word_width)) - self.submodules += buffer, crc_checker, buffer_cdc_fifo - self.submodules += ClockDomainsRenamer({"write": "cxp_gtx_rx", "read": "sys"})(cdc_fifo) + # TODO: handle full buffer gracefully + # TODO: investigate why there is a heartbeat message in the middle of the frame with k27.7 code too??? + # NOTE: sometimes there are 0xFBFBFBFB K=0b1111 + # perhaps the buffer is full overflowing and doing strange stuff - pipeline = [buffer, crc_checker, buffer_cdc_fifo, cdc_fifo] - for s, d in zip(pipeline, pipeline[1:]): - self.comb += s.source.connect(d.sink) - - # # DEBUG: - self.submodules.debug_out = debug_out = RX_Debug_Buffer(word_layout_dchar, 2**log2_int(packet_size//word_width)) - self.comb += pipeline[-1].source.connect(debug_out.sink) + # it should be mem block not "cycle buffer" + # self.submodules.dropper = dropper = cdr(DChar_Dropper()) + buffer = cdr(Buffer(word_layout_dchar)) # crcchecker timinig is bad + buffer_cdc_fifo = cdr(Buffer(word_layout_dchar)) # to improve timing + cdc_fifo = stream.AsyncFIFO(word_layout_dchar, 2**log2_int(packet_size//word_width)) + self.submodules += buffer, crc_checker, buffer_cdc_fifo + self.submodules += ClockDomainsRenamer({"write": "cxp_gtx_rx", "read": "sys"})(cdc_fifo) + self.submodules.debug_out = debug_out = RX_Debug_Buffer(word_layout_dchar, 2**log2_int(packet_size//word_width)) + + pipeline = [buffer, crc_checker, buffer_cdc_fifo, cdc_fifo, debug_out] + for s, d in zip(pipeline, pipeline[1:]): + self.comb += s.source.connect(d.sink) @@ -392,9 +392,11 @@ class CXP_Frame_Pipeline(Module, AutoCSR): self.comb += d.source.connect(arbiter.sinks[i]) self.comb += arbiter.source.connect(broadcaster.sink) - # self.comb += broadcaster.sources[0].connect(pixel_pipeline.sink), - # DEBUG - self.comb += broadcaster.sources[0].connect(pipeline[0].sink), + + if not debug_out: + self.comb += broadcaster.sources[0].connect(pixel_pipeline.sink), + else: + self.comb += broadcaster.sources[0].connect(pipeline[0].sink), # Control interface # only the simple topology MASTER:ch0, extension:ch1,2,3 is supported right now