1
0
Fork 0

Compare commits

..

35 Commits

Author SHA1 Message Date
morgan 6134ad5794 cxp upconn: refactor idle into its submodule 2024-06-28 17:24:13 +08:00
morgan dbf7ac1cb9 cxp upconn : fix idle word lag behind tx_wordcount 2024-06-28 15:46:13 +08:00
morgan 8ba7793b24 cxp upconn: fix word count issue 2024-06-28 12:46:35 +08:00
morgan 481162430c cxp upconn: add word & char boundary transmission 2024-06-28 12:02:15 +08:00
morgan 4eed5e99f4 cxp upconn: put encoder with tx_fifos 2024-06-27 16:50:15 +08:00
morgan 98f4d4cea4 cxp upconn: refactor fifo into submodule 2024-06-27 12:51:20 +08:00
morgan 14a9184fee cxp upcxp: add tx_enable & startup sequence 2024-06-25 15:29:18 +08:00
morgan ae4bfc40e5 cxp upconn: add priority packet 2024-06-24 14:59:49 +08:00
morgan cdc7294e99 cxp upconn: add sys_clk_freq parameter to set pll 2024-06-20 16:20:27 +08:00
morgan e6550c68cf cxp upconn: add sink to txphy & cleanup 2024-06-20 15:57:37 +08:00
morgan 00e5d32d45 cxp upconn: add priority lv1 fifo & refactor 2024-06-20 14:56:28 +08:00
morgan 779084d5dc cxp upconn: setup fifo 2024-06-20 10:57:05 +08:00
morgan f43c8b8bac cxp upconn: rename bits to tx_bitcount 2024-06-18 16:42:17 +08:00
morgan 6636339701 cxp upconn: refactor serial fsm as sync logic 2024-06-18 16:40:40 +08:00
morgan bd66659883 cxp upconn: write state fsm refactor 2024-06-18 15:58:53 +08:00
morgan 4de58e0d52 cxp upconn: use singlencoder & fix disparity bug 2024-06-18 14:40:58 +08:00
morgan 7c60fb5776 cxp upconn: init encoder 2024-06-18 12:26:10 +08:00
morgan bbf9e37867 cxp upconn: rename high speed upconn to bitrate2x 2024-06-18 12:24:31 +08:00
morgan d36afd6f7b CXP upconn: add sys reset signal to pll 2024-06-17 16:51:55 +08:00
morgan cb1ec7f62a CXP upconn: remove unused code 2024-06-17 14:46:49 +08:00
morgan 48d3a9cd4a CXP up connection gw: init 2024-06-17 13:19:37 +08:00
morgan 96a052513d zc706: use new CXP file name 2024-06-14 17:18:26 +08:00
morgan b2c6c20426 cxp: refactor to its separte module 2024-06-14 17:17:56 +08:00
morgan 5fcf5cb70f cxp gtx: rename to cxp_downconn 2024-06-14 17:17:16 +08:00
morgan 47e1a83519 cxp fmc: rename file 2024-06-14 17:16:51 +08:00
morgan d592825284 CXP gtx: rename to CXP DownConn 2024-06-14 17:07:58 +08:00
morgan b52589bd5f CXP CLK alignment: clock domain naming refactor 2024-06-13 16:56:36 +08:00
morgan 9c69167f7f CXP gtx: Clock domain naming refactor and remove cxp_gtx 2024-06-13 16:56:16 +08:00
morgan 8ac71b37a9 CXP GTX: init 2024-06-12 14:50:38 +08:00
morgan ce0e14879c Gateware: ZC706 CXP GTX setup 2024-06-05 13:02:52 +08:00
morgan df7feb3b17 Gateware: CXP_GTX init 2024-06-05 13:02:52 +08:00
morgan f5c604bbb5 zc706: add USER LED to allow compilation 2024-06-05 13:02:29 +08:00
morgan d61d7a5a95 zc706: add CXP FMC variant 2024-06-05 13:02:29 +08:00
morgan 681d7400c7 FMCIO: add cxp_4r adepter io 2024-06-05 13:02:29 +08:00
morgan 9f2f392728 flake: add CXP_FMC variant build options 2024-06-05 13:02:29 +08:00
8 changed files with 57 additions and 289 deletions

View File

@ -341,7 +341,7 @@
{ {
inherit fastnumbers artiq-netboot ramda migen-axi binutils-arm; inherit fastnumbers artiq-netboot ramda migen-axi binutils-arm;
} // } //
(board-package-set { target = "zc706"; variant = "cxp_demo"; }) // (board-package-set { target = "zc706"; variant = "cxp_fmc"; }) //
(board-package-set { target = "zc706"; variant = "nist_clock"; }) // (board-package-set { target = "zc706"; variant = "nist_clock"; }) //
(board-package-set { target = "zc706"; variant = "nist_clock_master"; }) // (board-package-set { target = "zc706"; variant = "nist_clock_master"; }) //
(board-package-set { target = "zc706"; variant = "nist_clock_master_100mhz"; }) // (board-package-set { target = "zc706"; variant = "nist_clock_master_100mhz"; }) //

View File

@ -1,15 +1,14 @@
from migen import * 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 misoc.interconnect.csr import *
from artiq.gateware.drtio.core import TransceiverInterface, ChannelInterface
from cxp_downconn import CXP_DownConn from cxp_downconn import CXP_DownConn
from cxp_upconn import CXP_UpConn
class CXP(Module, AutoCSR): class CXP(Module, AutoCSR):
def __init__(self, refclk, pads, sys_clk_freq, debug_sma, pmod_pads): def __init__(self, refclk, pads, sys_clk_freq, debug_sma):
nchannels = len(pads) self.nchannels = nchannels = len(pads)
self.rx_start_init = CSRStorage() self.rx_start_init = CSRStorage()
self.rx_restart = CSRStatus() self.rx_restart = CSRStatus()
self.rx_bypass_clk_alignment = CSRStorage() self.rx_bypass_clk_alignment = CSRStorage()
@ -20,7 +19,6 @@ class CXP(Module, AutoCSR):
self.loopback_mode = CSRStorage(3) self.loopback_mode = CSRStorage(3)
self.txinit_phaligndone = CSRStatus() self.txinit_phaligndone = CSRStatus()
self.rxinit_phaligndone = CSRStatus()
self.rx_ready = CSRStatus() self.rx_ready = CSRStatus()
self.data_0 = CSRStorage(8) self.data_0 = CSRStorage(8)
@ -39,31 +37,20 @@ class CXP(Module, AutoCSR):
# # # # # #
self.submodules.crc = CXP_CRC(8) # single CXP
# 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") self.submodules.gtx = gtx = CXP_DownConn(refclk, pads, sys_clk_freq, tx_mode="single", rx_mode="single")
# DEBUG:loopback # ! loopback for debugging
self.sync += gtx.loopback_mode.eq(self.loopback_mode.storage) self.sync += gtx.loopback_mode.eq(self.loopback_mode.storage)
# # ! debug sma # ! debug sma
# self.specials += [ self.specials += [
# Instance("OBUF", i_I=gtx.rxoutclk, o_O=debug_sma.p_tx), 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) Instance("OBUF", i_I=gtx.cd_cxp_gtx_tx.clk, o_O=debug_sma.n_rx)
# ] ]
self.comb += [ self.comb += [
self.txinit_phaligndone.status.eq(self.gtx.tx_init.Xxphaligndone), 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.rx_ready.status.eq(self.gtx.rx_ready),
] ]
@ -128,58 +115,4 @@ class CXP(Module, AutoCSR):
getattr(self, "cd_cxp_gtx_rx" + str(0)).rst.eq(self.gtx.cd_cxp_gtx_rx.rst) getattr(self, "cd_cxp_gtx_rx" + str(0)).rst.eq(self.gtx.cd_cxp_gtx_rx.rst)
] ]
class CXP_CRC(Module, AutoCSR): # TODO: add low speed SERDES
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)),
]

View File

@ -5,6 +5,7 @@ from migen.genlib.cdc import MultiReg, PulseSynchronizer
from misoc.cores.code_8b10b import Encoder, Decoder from misoc.cores.code_8b10b import Encoder, Decoder
from misoc.interconnect.csr import * from misoc.interconnect.csr import *
from artiq.gateware.drtio.core import TransceiverInterface, ChannelInterface
from artiq.gateware.drtio.transceiver.gtx_7series_init import * from artiq.gateware.drtio.transceiver.gtx_7series_init import *
from operator import add from operator import add
@ -28,13 +29,13 @@ from functools import reduce
# Warning: Xilinx transceivers are LSB first, and comma needs to be flipped # Warning: Xilinx transceivers are LSB first, and comma needs to be flipped
# compared to the usual 8b10b binary representation. # compared to the usual 8b10b binary representation.
class CXP_BruteforceClockAligner(Module): class CXP_BruteforceClockAligner(Module):
def __init__(self, comma, sys_clk_freq, check_period): def __init__(self, comma, tx_clk_freq, check_period=6e-3):
self.rxdata = Signal(20) self.rxdata = Signal(20)
self.restart = Signal() self.restart = Signal()
self.ready = Signal() self.ready = Signal()
check_max_val = ceil(check_period*sys_clk_freq) check_max_val = ceil(check_period*tx_clk_freq)
check_counter = Signal(max=check_max_val+1) check_counter = Signal(max=check_max_val+1)
check = Signal() check = Signal()
reset_check_counter = Signal() reset_check_counter = Signal()
@ -134,6 +135,7 @@ class CXP_DownConn(Module):
pll_div = int(40/cpll_div) pll_div = int(40/cpll_div)
self.rx_restart = Signal() self.rx_restart = Signal()
self.rx_bypass_clk_alignment = Signal()
self.tx_restart = Signal() self.tx_restart = Signal()
self.loopback_mode = Signal(3) self.loopback_mode = Signal(3)
@ -339,7 +341,7 @@ class CXP_DownConn(Module):
# CDR Attributes # CDR Attributes
p_RXCDR_CFG=0x03_0000_23FF_1040_0020, # DFE @ <= 6.6Gb/s, 8B/10B encoded data, CDR setting < +/- 200ppm p_RXCDR_CFG=0x03_0000_23FF_1040_0020, # DFE @ <= 6.6Gb/s, 8B/10B encoded data, CDR setting < +/- 200ppm
# (See UG476 (v1.12.1), p.205) # (See UG476 (v1.12.1), p.205)
p_RXCDR_FR_RESET_ON_EIDLE=0b0, p_RXCDR_FR_RESET_ON_EIDLE=0b0,
p_RXCDR_HOLD_DURING_EIDLE=0b0, p_RXCDR_HOLD_DURING_EIDLE=0b0,
p_RXCDR_PH_RESET_ON_EIDLE=0b0, p_RXCDR_PH_RESET_ON_EIDLE=0b0,
@ -415,8 +417,7 @@ class CXP_DownConn(Module):
self.decoders[1].input.eq(rxdata[10:]) self.decoders[1].input.eq(rxdata[10:])
] ]
# 6e-3 is too slow for 3.25Gbps line rate clock_aligner = CXP_BruteforceClockAligner(0b0101111100, sys_clk_freq, check_period=1e-3)
clock_aligner = CXP_BruteforceClockAligner(0b0101111100, sys_clk_freq, check_period=1e-2)
self.submodules += clock_aligner self.submodules += clock_aligner
self.comb += [ self.comb += [
clock_aligner.rxdata.eq(rxdata), clock_aligner.rxdata.eq(rxdata),

View File

@ -8,8 +8,7 @@ from misoc.interconnect.csr import *
class CXP_UpConn(Module, AutoCSR): class CXP_UpConn(Module, AutoCSR):
nfifos = 3 def __init__(self, pads, sys_clk_freq, pmod, nfifos=3, fifo_depth=32):
def __init__(self, pads, sys_clk_freq, pmod, fifo_depth=32):
self.clock_domains.cd_cxp_upconn = ClockDomain() self.clock_domains.cd_cxp_upconn = ClockDomain()
self.clk_reset = CSRStorage(reset=1) self.clk_reset = CSRStorage(reset=1)
self.bitrate2x_enable = CSRStorage() self.bitrate2x_enable = CSRStorage()
@ -51,23 +50,26 @@ class CXP_UpConn(Module, AutoCSR):
] ]
self.submodules.fsm = ClockDomainsRenamer("cxp_upconn")(FSM(reset_state="WAIT_TX_ENABLE")) self.submodules.fsm = ClockDomainsRenamer("cxp_upconn")(FSM(reset_state="WAIT_TX_ENABLE"))
self.submodules.tx_fifos = TxFIFOs(self.nfifos, fifo_depth) self.submodules.tx_fifos = TxFIFOs(nfifos, fifo_depth)
self.submodules.tx_idle = TxIdle() self.submodules.tx_idle = TxIdle()
o = Signal() o = Signal()
tx_en = Signal() tx_en = Signal()
tx_bitcount = Signal(max=10) tx_bitcount = Signal(max=10)
tx_wordcount = Signal(max=4) tx_wordcount = Signal()
tx_reg = Signal(10) tx_reg = Signal(10)
disp = Signal() disp = Signal()
priorities = Signal(max=self.nfifos) tx_wordcount = Signal(max=4)
priority = Signal(max=nfifos)
idling = Signal() idling = Signal()
# startup sequence # startup sequence
self.fsm.act("WAIT_TX_ENABLE", self.fsm.act("WAIT_TX_ENABLE",
NextValue(self.tx_idle.disp_in, 0),
NextValue(self.tx_idle.word_idx, 0),
If(self.tx_enable.storage, If(self.tx_enable.storage,
NextValue(self.tx_idle.word_idx, 0),
NextValue(tx_wordcount, 0), NextValue(tx_wordcount, 0),
NextValue(tx_bitcount, 0), NextValue(tx_bitcount, 0),
NextState("LOAD_CHAR") NextState("LOAD_CHAR")
@ -89,6 +91,11 @@ class CXP_UpConn(Module, AutoCSR):
) )
) )
# CXP 2.1 section 9.2.4
# Higher priority packet can be inserted into a lower priority packet during transmission
# Priority lv 0 can be inserted in char boundary of the packet
# Priority lv 1-2 need to be inserted in word boundary of the packet
self.sync.cxp_upconn += [ self.sync.cxp_upconn += [
self.tx_fifos.disp_in.eq(disp), self.tx_fifos.disp_in.eq(disp),
self.tx_idle.disp_in.eq(disp), self.tx_idle.disp_in.eq(disp),
@ -103,33 +110,39 @@ class CXP_UpConn(Module, AutoCSR):
If(tx_bitcount == 9, If(tx_bitcount == 9,
tx_bitcount.eq(0), tx_bitcount.eq(0),
If((~self.tx_fifos.pe.n) & (self.tx_fifos.pe.o == 0), If((~self.tx_fifos.pe.n) & (self.tx_fifos.pe.o == 0),
# trigger packets are inserted at char boundary and don't contribute to word count # trigger packet can interrupt at char level
tx_reg.eq(self.tx_fifos.source_data[0]), tx_reg.eq(self.tx_fifos.source_data[0]),
self.tx_fifos.source_ack[0].eq(1), self.tx_fifos.source_ack[0].eq(1),
disp.eq(self.tx_fifos.disp_out[0]), disp.eq(self.tx_fifos.disp_out[0]),
).Else( ).Else(
# word boundary # priority zero doesn't contribute to word count
If(tx_wordcount == 3, If(tx_wordcount != 3,
tx_wordcount.eq(tx_wordcount + 1),
).Else(
tx_wordcount.eq(0), tx_wordcount.eq(0),
),
# new word boundary
If(tx_wordcount == 3,
If(~self.tx_fifos.pe.n, If(~self.tx_fifos.pe.n,
# priority lv 1 & 2 packets are inserted at word boundary
idling.eq(0), idling.eq(0),
priorities.eq(self.tx_fifos.pe.o), priority.eq(self.tx_fifos.pe.o),
self.tx_fifos.source_ack[self.tx_fifos.pe.o].eq(1), self.tx_fifos.source_ack[self.tx_fifos.pe.o].eq(1),
tx_reg.eq(self.tx_fifos.source_data[self.tx_fifos.pe.o]), tx_reg.eq(self.tx_fifos.source_data[self.tx_fifos.pe.o]),
disp.eq(self.tx_fifos.disp_out[self.tx_fifos.pe.o]), disp.eq(self.tx_fifos.disp_out[self.tx_fifos.pe.o]),
).Else( ).Else(
idling.eq(1), idling.eq(1),
self.tx_idle.source_ack.eq(1), self.tx_idle.source_ack.eq(1),
tx_reg.eq(self.tx_idle.source_data), tx_reg.eq(self.tx_idle.source_data),
disp.eq(self.tx_idle.disp_out), disp.eq(self.tx_idle.disp_out),
) )
).Else( ).Else(
tx_wordcount.eq(tx_wordcount + 1),
If(~idling, If(~idling,
self.tx_fifos.source_ack[priorities].eq(1), self.tx_fifos.source_ack[priority].eq(1),
tx_reg.eq(self.tx_fifos.source_data[priorities]), tx_reg.eq(self.tx_fifos.source_data[priority]),
disp.eq(self.tx_fifos.disp_out[priorities]), disp.eq(self.tx_fifos.disp_out[priority]),
).Else( ).Else(
self.tx_idle.source_ack.eq(1), self.tx_idle.source_ack.eq(1),
tx_reg.eq(self.tx_idle.source_data), tx_reg.eq(self.tx_idle.source_data),
@ -231,7 +244,6 @@ class TxFIFOs(Module):
# reset ack after asserted # reset ack after asserted
If(self.source_ack[i], self.source_ack[i].eq(0)), If(self.source_ack[i], self.source_ack[i].eq(0)),
] ]
# FIFOs transmission priority # FIFOs transmission priority
self.submodules.pe = PriorityEncoder(nfifos) self.submodules.pe = PriorityEncoder(nfifos)
self.comb += self.pe.i.eq(source_stb) self.comb += self.pe.i.eq(source_stb)
@ -249,7 +261,7 @@ class TxIdle(Module):
# CXP 2.1 section 9.2.5 # CXP 2.1 section 9.2.5
IDLE_CHARS = Array([ IDLE_CHARS = Array([
#[char, k] #[data, k]
[0b10111100, 1], #K28.5 [0b10111100, 1], #K28.5
[0b00111100, 1], #K28.1 [0b00111100, 1], #K28.1
[0b00111100, 1], #K28.1 [0b00111100, 1], #K28.1

View File

@ -649,7 +649,7 @@ class _NIST_QC2_RTIO:
self.add_rtio(rtio_channels) self.add_rtio(rtio_channels)
class CXP_FMC(): class _CXP_FMC_RTIO():
""" """
CoaXpress FMC with 4 CXP channel and 1 SMA trigger CoaXpress FMC with 4 CXP channel and 1 SMA trigger
""" """
@ -664,32 +664,17 @@ class CXP_FMC():
Subsignal("n_rx", Pins("AD19"), IOStandard("LVCMOS33")), Subsignal("n_rx", Pins("AD19"), IOStandard("LVCMOS33")),
), ),
] ]
pmod1_33 = [
("pmod1_33", 0, Pins("AJ21"), IOStandard("LVCMOS33")),
("pmod1_33", 1, Pins("AK21"), IOStandard("LVCMOS33")),
("pmod1_33", 2, Pins("AB21"), IOStandard("LVCMOS33")),
("pmod1_33", 3, Pins("AB16"), IOStandard("LVCMOS33")),
("pmod1_33", 4, Pins("Y20"), IOStandard("LVCMOS33")),
("pmod1_33", 5, Pins("AA20"), IOStandard("LVCMOS33")),
("pmod1_33", 6, Pins("AC18"), IOStandard("LVCMOS33")),
("pmod1_33", 7, Pins("AC19"), IOStandard("LVCMOS33")),
]
platform.add_extension(debug_sma) platform.add_extension(debug_sma)
platform.add_extension(pmod1_33)
pmod_pads = [platform.request("pmod1_33", i) for i in range(8)]
clk_freq = 125e6 clk_freq = 125e6
self.submodules.cxp = cxp.CXP( self.submodules.cxp_gtx = cxp.CXP(
refclk=self.cdr_clk, refclk=self.cdr_clk,
pads=platform.request("CXP_HS", 0), pads=platform.request("CXP_HS", 0),
sys_clk_freq=clk_freq, sys_clk_freq=clk_freq,
debug_sma=platform.request("user_sma_clock_33"), debug_sma=platform.request("user_sma_clock_33")
pmod_pads = pmod_pads
) )
self.csr_devices.append("cxp") self.csr_devices.append("cxp_gtx")
rtio_channels = [] rtio_channels = []
# FIXME remove this placeholder RTIO channel # FIXME remove this placeholder RTIO channel
@ -737,13 +722,14 @@ class NIST_QC2_Satellite(_SatelliteBase, _NIST_QC2_RTIO):
_SatelliteBase.__init__(self, acpki, drtio100mhz) _SatelliteBase.__init__(self, acpki, drtio100mhz)
_NIST_QC2_RTIO.__init__(self) _NIST_QC2_RTIO.__init__(self)
class CXP_Demo(ZC706, CXP_FMC): class CXP_FMC(ZC706, _CXP_FMC_RTIO):
def __init__(self, acpki, drtio100mhz): def __init__(self, acpki, drtio100mhz):
ZC706.__init__(self, acpki) ZC706.__init__(self, acpki)
CXP_FMC.__init__(self) # self.submodules += SMAClkinForward(self.platform)
_CXP_FMC_RTIO.__init__(self)
VARIANTS = {cls.__name__.lower(): cls for cls in [NIST_CLOCK, NIST_CLOCK_Master, NIST_CLOCK_Satellite, VARIANTS = {cls.__name__.lower(): cls for cls in [NIST_CLOCK, NIST_CLOCK_Master, NIST_CLOCK_Satellite,
NIST_QC2, NIST_QC2_Master, NIST_QC2_Satellite, CXP_Demo]} NIST_QC2, NIST_QC2_Master, NIST_QC2_Satellite, CXP_FMC]}
def main(): def main():
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(

View File

@ -1,71 +0,0 @@
use embedded_hal::prelude::_embedded_hal_blocking_delay_DelayUs;
use libboard_zynq::{println, timer::GlobalTimer};
use log::info;
use crate::pl::csr;
pub fn main(timer: &mut GlobalTimer) {
unsafe {
info!("turning on pmc loopback mode...");
csr::cxp::loopback_mode_write(0b010); // Near-End PMA Loopback
// enable cxp gtx clock domains
csr::cxp::tx_start_init_write(1);
csr::cxp::rx_start_init_write(1);
info!("waiting for QPLL/CPLL to lock...");
timer.delay_us(50_000);
info!("tx_phaligndone = {} ", csr::cxp::txinit_phaligndone_read(),);
// enable txdata tranmission thought MGTXTXP, required by PMA loopback
csr::cxp::txenable_write(1);
loopback_testing(timer, 0x00, 0);
}
fn loopback_testing(timer: &mut GlobalTimer, data: u8, control_bit: u8) {
unsafe {
// send K28_5 for CDR to align
const K28_5: u8 = 0xBC;
csr::cxp::data_0_write(K28_5);
csr::cxp::control_bit_0_write(1);
csr::cxp::data_1_write(K28_5);
csr::cxp::control_bit_1_write(1);
info!("waiting for rx to align...");
while csr::cxp::rx_ready_read() != 1 {}
info!("rx ready!");
csr::cxp::data_1_write(data);
csr::cxp::control_bit_1_write(control_bit);
println!(
"data[0] = {:#04x} control bit = {:#b} encoded = {:#012b}",
csr::cxp::data_0_read(),
csr::cxp::control_bit_0_read(),
csr::cxp::encoded_0_read(),
);
println!(
"data[1] = {:#04x} control bit = {:#b} encoded = {:#012b}",
csr::cxp::data_1_read(),
csr::cxp::control_bit_1_read(),
csr::cxp::encoded_1_read(),
);
for _ in 0..20 {
timer.delay_us(100);
// println!(
// "data[0] = {:#012b} data[1] = {:#012b}",
// csr::cxp::rxdata_0_read(),
// csr::cxp::rxdata_1_read(),
// );
println!(
"decoded_data[0] = {:#04x} decoded_k[0] = {:#b} decoded_data[1] = {:#04x} decoded_k[1] = {:#b}",
csr::cxp::decoded_data_0_read(),
csr::cxp::decoded_k_0_read(),
csr::cxp::decoded_data_1_read(),
csr::cxp::decoded_k_1_read(),
);
}
}
}
}

View File

@ -1,88 +0,0 @@
use embedded_hal::prelude::_embedded_hal_blocking_delay_DelayUs;
use libboard_zynq::{println, timer::GlobalTimer};
use crate::pl::csr;
pub fn crc_test() {
let arr = [
0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, // CXP CRC-32
0x56, 0x86, 0x5D, 0x6f,
];
let mut crc: u32; // seed = 0xFFFFFFFF
unsafe {
csr::cxp::crc_en_write(1);
for a in arr.iter() {
csr::cxp::crc_data_write(*a);
crc = csr::cxp::crc_value_read();
println!("input = {:#04x}", *a);
println!("CRC NOT(val.reverse) = {:#010x}", !crc.reverse_bits());
// since the input bit are reversed when entering the crc engine, the output char need to be reversed to cancel out on the receiver side
println!("CRC CXP = {:#010x}", crc);
}
}
}
pub fn tx_test(timer: &mut GlobalTimer) {
// the 8bit shift is k symbol
// const K28_1: u16 = 0x3C | (1 << 8);
// const K28_5: u16 = 0xBC | (1 << 8);
const D31_1: u16 = 0x3F;
const D01_1: u16 = 0x21;
const LEN: usize = 100;
let mut arr: [u16; LEN] = [0; LEN];
unsafe {
csr::cxp::upconn_clk_reset_write(1);
// csr::cxp::upconn_bitrate2x_enable_write(1);
csr::cxp::upconn_clk_reset_write(0);
loop {
// TODO: verify the char & word boundary thingy
for _ in 0..8 {
csr::cxp::upconn_symbol1_write(D01_1);
}
for _ in 0..4 {
csr::cxp::upconn_symbol2_write(D31_1);
}
timer.delay_us(1);
csr::cxp::upconn_tx_enable_write(1);
for i in 0..LEN {
arr[i] = get_encoded();
}
for i in 0..LEN {
match arr[i] {
0b1010111001 | 0b0101001001 => {
println!("encoded = {:#012b} D31.1", arr[i])
}
0b0111011001 | 0b1000101001 => {
println!("encoded = {:#012b} D01.1", arr[i])
}
0b0011111010 | 0b1100000101 => {
println!("encoded = {:#012b} K28.5 start idling....", arr[i])
}
0b0011111001 | 0b1100000110 => {
println!("encoded = {:#012b} K28.1 idling...", arr[i])
}
0b0011101010 => {
println!("encoded = {:#012b} D28.5 END idle", arr[i])
}
_ => {
println!("encoded = {:#012b}", arr[i])
}
}
}
println!("-------------------------------------");
csr::cxp::upconn_tx_enable_write(0);
timer.delay_us(2_000_000);
}
}
fn get_encoded() -> u16 {
unsafe { csr::cxp::upconn_encoded_data_read().reverse_bits() >> 6 }
}
}

View File

@ -42,11 +42,6 @@ pub mod si5324;
pub mod si549; pub mod si549;
use core::{cmp, str}; use core::{cmp, str};
#[cfg(has_cxp)]
pub mod cxp_downconn;
#[cfg(has_cxp)]
pub mod cxp_upconn;
pub fn identifier_read(buf: &mut [u8]) -> &str { pub fn identifier_read(buf: &mut [u8]) -> &str {
unsafe { unsafe {
pl::csr::identifier::address_write(0); pl::csr::identifier::address_write(0);