1
0
Fork 0

cxp: add upconn, downconn & crc

cxp: add crc32 for cxp
cxp: add upconn & downconn
This commit is contained in:
morgan 2024-06-14 17:17:56 +08:00
parent 1f033d605c
commit 82af01350f
1 changed files with 185 additions and 0 deletions

185
src/gateware/cxp.py Normal file
View File

@ -0,0 +1,185 @@
from migen import *
from misoc.interconnect.csr import *
from misoc.cores.liteeth_mini.mac.crc import LiteEthMACCRCEngine
from artiq.gateware.drtio.core import ChannelInterface
from cxp_downconn import CXP_DownConn
from cxp_upconn import CXP_UpConn
class CXP(Module, AutoCSR):
def __init__(self, refclk, pads, sys_clk_freq, debug_sma, pmod_pads):
nchannels = len(pads)
self.rx_start_init = CSRStorage()
self.rx_restart = CSRStatus()
self.rx_bypass_clk_alignment = CSRStorage()
self.tx_start_init = CSRStorage()
self.tx_restart = CSRStorage()
self.loopback_mode = CSRStorage(3)
self.txinit_phaligndone = CSRStatus()
self.rxinit_phaligndone = CSRStatus()
self.rx_ready = CSRStatus()
self.data_0 = CSRStorage(8)
self.data_1 = CSRStorage(8)
self.control_bit_0 = CSRStorage()
self.control_bit_1 = 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.submodules.crc = CXP_CRC(8)
# FIFOs with transmission priority
# 0: Trigger packet
# 1: IO acknowledgment for trigger packet
# 2: All other packets
self.submodules.upconn = CXP_UpConn(debug_sma, sys_clk_freq, pmod_pads)
# single & master tx_mode can lock with rx in loopback
self.submodules.gtx = gtx = CXP_DownConn(refclk, pads, sys_clk_freq, tx_mode="single", rx_mode="single")
# DEBUG:loopback
self.sync += gtx.loopback_mode.eq(self.loopback_mode.storage)
# # ! debug sma
# self.specials += [
# Instance("OBUF", i_I=gtx.rxoutclk, o_O=debug_sma.p_tx),
# Instance("OBUF", i_I=gtx.cd_cxp_gtx_tx.clk, o_O=debug_sma.n_rx)
# ]
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.sync.cxp_gtx_tx += [
self.gtx.encoder.d[0].eq(self.data_0.storage),
self.gtx.encoder.k[0].eq(self.control_bit_0.storage),
self.encoded_0.status.eq(self.gtx.encoder.output[0]),
self.gtx.encoder.d[1].eq(self.data_1.storage),
self.gtx.encoder.k[1].eq(self.control_bit_1.storage),
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),
]
# TODO: rip encoder & rx clockalignment out of CXP_GTX
# TODO: use expose encoder & decoder from CXP
# encoder.k = 1 if sending control bit, different calculation
# encoder.d = data 8 bit
channel_interface = ChannelInterface(gtx.encoder, gtx.decoders)
self.comb += channel_interface.rx_ready.eq(gtx.rx_ready)
channel_interfaces = []
channel_interfaces.append(channel_interface)
# TransceiverInterface, just adding cxp_rx_<num>
self.stable_clkin = CSRStorage()
self.txenable = CSRStorage(len(channel_interfaces))
for i in range(len(channel_interfaces)):
name = "cxp_gtx_rx" + str(i)
setattr(self.clock_domains, "cd_"+name, ClockDomain(name=name))
self.channels = channel_interfaces
# TODO: add tx_phase_alignment for multi CXP
# The TX phase alignment will fail with a wrong TXUSRCLK frequency
self.comb += [
gtx.rx_init.clk_path_ready.eq(self.rx_start_init.storage),
gtx.tx_init.clk_path_ready.eq(self.tx_start_init.storage),
gtx.txenable.eq(self.txenable.storage[0]),
gtx.tx_restart.eq(self.tx_restart.storage),
]
# TODO: Connect multilane cxp_tx
# TODO: Connect slave i's `cxp_gtx_rx` clock to `cxp_gtx_rxi` clock
self.comb += [
getattr(self, "cd_cxp_gtx_rx" + str(0)).clk.eq(self.gtx.cd_cxp_gtx_rx.clk),
getattr(self, "cd_cxp_gtx_rx" + str(0)).rst.eq(self.gtx.cd_cxp_gtx_rx.rst)
]
class CXP_CRC(Module, AutoCSR):
width = 32
polynom = 0x04C11DB7
seed = 2**width-1
def __init__(self, data_width):
self.d = Signal(data_width)
self.stb = Signal()
self.reset = Signal()
self.val = Signal(self.width, reset=self.seed)
self.data = CSR(data_width)
self.en = CSR()
self.value = CSRStatus(self.width)
self.processed = CSRStatus(self.width)
# # #
self.submodules.engine = LiteEthMACCRCEngine(data_width, self.width, self.polynom)
self.sync += [
self.val.eq(self.engine.next),
If(self.stb,
self.engine.data.eq(self.d),
If(self.reset,
self.engine.last.eq(self.seed),
# clear reset bit
self.reset.eq(0),
).Else(
self.engine.last.eq(self.val),
)
),
]
# DEBUG: remove those csr
# TODO: do char bit reverse outside of this submodule
p0 = Signal(8)
p1 = Signal(8)
p2 = Signal(8)
p3 = Signal(8)
self.comb += [
p3.eq(self.engine.next[:8][::-1]),
p2.eq(self.engine.next[8:16][::-1]),
p1.eq(self.engine.next[16:24][::-1]),
p0.eq(self.engine.next[24:32][::-1]),
]
self.sync += [
self.d.eq(self.data.r),
self.stb.eq(self.data.re),
If(self.en.re, self.reset.eq(1)),
self.value.status.eq(self.engine.next),
self.processed.status.eq(Cat(p3, p2, p1, p0)),
]