forked from M-Labs/artiq-zynq
Compare commits
35 Commits
6c53447808
...
6134ad5794
Author | SHA1 | Date |
---|---|---|
morgan | 6134ad5794 | |
morgan | dbf7ac1cb9 | |
morgan | 8ba7793b24 | |
morgan | 481162430c | |
morgan | 4eed5e99f4 | |
morgan | 98f4d4cea4 | |
morgan | 14a9184fee | |
morgan | ae4bfc40e5 | |
morgan | cdc7294e99 | |
morgan | e6550c68cf | |
morgan | 00e5d32d45 | |
morgan | 779084d5dc | |
morgan | f43c8b8bac | |
morgan | 6636339701 | |
morgan | bd66659883 | |
morgan | 4de58e0d52 | |
morgan | 7c60fb5776 | |
morgan | bbf9e37867 | |
morgan | d36afd6f7b | |
morgan | cb1ec7f62a | |
morgan | 48d3a9cd4a | |
morgan | 96a052513d | |
morgan | b2c6c20426 | |
morgan | 5fcf5cb70f | |
morgan | 47e1a83519 | |
morgan | d592825284 | |
morgan | b52589bd5f | |
morgan | 9c69167f7f | |
morgan | 8ac71b37a9 | |
morgan | ce0e14879c | |
morgan | df7feb3b17 | |
morgan | f5c604bbb5 | |
morgan | d61d7a5a95 | |
morgan | 681d7400c7 | |
morgan | 9f2f392728 |
|
@ -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"; }) //
|
||||||
|
|
|
@ -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)),
|
|
||||||
]
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
@ -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),
|
||||||
|
|
|
@ -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",
|
||||||
If(self.tx_enable.storage,
|
NextValue(self.tx_idle.disp_in, 0),
|
||||||
NextValue(self.tx_idle.word_idx, 0),
|
NextValue(self.tx_idle.word_idx, 0),
|
||||||
|
|
||||||
|
If(self.tx_enable.storage,
|
||||||
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
|
||||||
|
|
|
@ -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(
|
||||||
|
|
|
@ -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(),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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 }
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue