diff --git a/src/gateware/cxp.py b/src/gateware/cxp.py index f0cd545..fe8f1e1 100644 --- a/src/gateware/cxp.py +++ b/src/gateware/cxp.py @@ -6,6 +6,9 @@ from cxp_downconn import CXP_DownConn_PHY from cxp_upconn import CXP_UpConn_PHY from cxp_pipeline import * +buffer_depth = 128 + +@FullMemoryWE() class CXP(Module, AutoCSR): def __init__(self, refclk, downconn_pads, upconn_pads, sys_clk_freq, debug_sma, pmod_pads): self.submodules.upconn = UpConn_Interface(upconn_pads, sys_clk_freq, debug_sma, pmod_pads) @@ -13,11 +16,76 @@ class CXP(Module, AutoCSR): self.submodules.downconn = DownConn_Interface(refclk, downconn_pads, sys_clk_freq, debug_sma, pmod_pads) # TODO: support the option high speed upconn + self.submodules.transmitter = Transmitter() + # TODO: add link layer + def get_tx_port(self): + return self.transmitter.mem.get_port(write_capable=True) + + def get_mem_size(self): + return buffer_depth*downconn_dw + +@FullMemoryWE() +class Transmitter(Module, AutoCSR): + def __init__(self): + self.cxp_tx_word_len = CSRStorage(bits_for(buffer_depth)) + self.cxp_tx = CSR() + + # # # + + self.specials.mem = mem = Memory(downconn_dw, buffer_depth) + self.specials.mem_port = mem_port = mem.get_port() + self.source = stream.Endpoint(downconn_layout) + + + tx_done = Signal() + addr_next = Signal(bits_for(buffer_depth)) + addr = Signal.like(addr_next) + addr_rst = Signal() + addr_inc = Signal() + + # increment addr in the same cycle the moment addr_inc is rise + # since memory takes one cycle to shift to the correct addr + self.sync += [ + addr.eq(addr_next), + If(self.cxp_tx.re, self.cxp_tx.w.eq(1)), + If(tx_done, self.cxp_tx.w.eq(0)), + ] + + self.comb += [ + addr_next.eq(addr), + If(addr_rst, + addr_next.eq(addr_next.reset), + ).Elif(addr_inc, + addr_next.eq(addr + 1), + ), + mem_port.adr.eq(addr_next), + self.source.data.eq(mem_port.dat_r) + ] + + self.submodules.fsm = fsm = FSM(reset_state="IDLE") + + fsm.act("IDLE", + addr_rst.eq(1), + If(self.cxp_tx.re, NextState("TRANSMIT")) + ) + fsm.act("TRANSMIT", + self.source.stb.eq(1), + If(self.source.ack, + addr_inc.eq(1), + ), + If(addr_next == self.cxp_tx_word_len.storage, + tx_done.eq(1), + NextState("IDLE") + ) + ) + + self.submodules.debug_out = debug_out = RX_Debug_Buffer() + self.comb += self.source.connect(debug_out.sink) + class DownConn_Interface(Module, AutoCSR): def __init__(self, refclk, downconn_pads, sys_clk_freq, debug_sma, pmod_pads): - # # # self.submodules.phy = phy = CXP_DownConn_PHY(refclk, downconn_pads, sys_clk_freq, debug_sma, pmod_pads) @@ -111,6 +179,15 @@ class UpConn_Interface(Module, AutoCSR): ] + # TODO: rewrite the transmite path into pipeline + # + # test pak ----+ + # from gw | 32 32 8 + # |---/---> mux -----> trig ack -----> idle word ---/--> conv ---/---> trig -----> PHY + # | inserter inserter inserter + # data pak ----+ + # from fw + # Packet FIFOs with transmission priority # 0: Trigger packet self.submodules.trig = trig = TX_Trigger()