forked from M-Labs/artiq-zynq
cxp downconn: use 40bits
This commit is contained in:
parent
17277504f1
commit
49d5cad5fd
|
@ -1,6 +1,5 @@
|
||||||
from migen import *
|
from migen import *
|
||||||
from migen.genlib.cdc import MultiReg, PulseSynchronizer
|
from migen.genlib.cdc import MultiReg, PulseSynchronizer
|
||||||
from migen.genlib.misc import WaitTimer
|
|
||||||
from migen.genlib.resetsync import AsyncResetSynchronizer
|
from migen.genlib.resetsync import AsyncResetSynchronizer
|
||||||
|
|
||||||
from misoc.cores.code_8b10b import Encoder, Decoder
|
from misoc.cores.code_8b10b import Encoder, Decoder
|
||||||
|
@ -155,43 +154,20 @@ class CXP_DownConn(Module, AutoCSR):
|
||||||
self.loopback_mode = CSRStorage(3)
|
self.loopback_mode = CSRStorage(3)
|
||||||
self.comb += gtx.loopback_mode.eq(self.loopback_mode.storage)
|
self.comb += gtx.loopback_mode.eq(self.loopback_mode.storage)
|
||||||
|
|
||||||
# DEBUG: RXDATA checking
|
|
||||||
aligned = Signal()
|
|
||||||
valid_data = Signal()
|
|
||||||
rx1cnt = Signal(max=11)
|
|
||||||
|
|
||||||
comma = 0b0101111100
|
|
||||||
comma_n = ~comma & 0b1111111111
|
|
||||||
|
|
||||||
self.sync.cxp_gtx_rx += [
|
|
||||||
If(self.gtx.comma_det.check_ps.o,
|
|
||||||
aligned.eq(0),
|
|
||||||
).Elif((gtx.comma_det.data[:10] == comma) | (gtx.comma_det.data[:10] == comma_n),
|
|
||||||
aligned.eq(1),
|
|
||||||
),
|
|
||||||
|
|
||||||
rx1cnt.eq(reduce(add, [gtx.comma_det.data[i] for i in range(10)])),
|
|
||||||
If(self.gtx.comma_det.check_ps.o,
|
|
||||||
valid_data.eq(0)
|
|
||||||
).Elif((rx1cnt == 4) | (rx1cnt == 5) | (rx1cnt == 6),
|
|
||||||
valid_data.eq(1)
|
|
||||||
),
|
|
||||||
]
|
|
||||||
|
|
||||||
# DEBUG: IO SMA & PMOD
|
# DEBUG: IO SMA & PMOD
|
||||||
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),
|
||||||
|
|
||||||
# pmod 0-7 pin
|
# pmod 0-7 pin
|
||||||
Instance("OBUF", i_I=gtx.comma_det.aligner_en_rxclk, o_O=pmod_pads[0]),
|
Instance("OBUF", i_I=gtx.comma_det.rxinit_done, o_O=pmod_pads[0]),
|
||||||
Instance("OBUF", i_I=gtx.comma_det.rxinit_done, o_O=pmod_pads[1]),
|
Instance("OBUF", i_I=gtx.comma_det.restart, o_O=pmod_pads[1]),
|
||||||
Instance("OBUF", i_I=gtx.comma_det.restart, o_O=pmod_pads[2]),
|
Instance("OBUF", i_I=gtx.comma_det.aligner_en_rxclk, o_O=pmod_pads[2]),
|
||||||
Instance("OBUF", i_I=aligned, o_O=pmod_pads[3]),
|
Instance("OBUF", i_I=gtx.comma_det.check_reset, o_O=pmod_pads[3]),
|
||||||
Instance("OBUF", i_I=gtx.comma_det.ready, o_O=pmod_pads[4]),
|
Instance("OBUF", i_I=gtx.comma_det.comma_aligned, o_O=pmod_pads[4]),
|
||||||
Instance("OBUF", i_I=gtx.comma_det.check_ps.o, o_O=pmod_pads[5]),
|
Instance("OBUF", i_I=gtx.comma_det.comma_seen, o_O=pmod_pads[5]),
|
||||||
Instance("OBUF", i_I=valid_data, o_O=pmod_pads[6]),
|
Instance("OBUF", i_I=gtx.comma_det.has_error, o_O=pmod_pads[6]),
|
||||||
# Instance("OBUF", i_I=, o_O=pmod_pads[7]),
|
Instance("OBUF", i_I=gtx.comma_det.ready, o_O=pmod_pads[7]),
|
||||||
|
|
||||||
# Instance("OBUF", i_I=gtx.dclk, o_O=pmod_pads[0]),
|
# Instance("OBUF", i_I=gtx.dclk, o_O=pmod_pads[0]),
|
||||||
# Instance("OBUF", i_I=gtx.den, o_O=pmod_pads[1]),
|
# Instance("OBUF", i_I=gtx.den, o_O=pmod_pads[1]),
|
||||||
|
@ -200,8 +176,6 @@ class CXP_DownConn(Module, AutoCSR):
|
||||||
]
|
]
|
||||||
|
|
||||||
# DEBUG: datain
|
# DEBUG: datain
|
||||||
counter_max = 2
|
|
||||||
counter = Signal(max=counter_max)
|
|
||||||
|
|
||||||
self.data_0 = CSRStorage(8)
|
self.data_0 = CSRStorage(8)
|
||||||
self.data_1 = CSRStorage(8)
|
self.data_1 = CSRStorage(8)
|
||||||
|
@ -222,24 +196,23 @@ class CXP_DownConn(Module, AutoCSR):
|
||||||
self.decoded_k_1 = CSRStatus()
|
self.decoded_k_1 = CSRStatus()
|
||||||
|
|
||||||
self.sync.cxp_gtx_tx += [
|
self.sync.cxp_gtx_tx += [
|
||||||
If(counter == 0,
|
self.gtx.encoder.d[0].eq(0xBC),
|
||||||
self.gtx.encoder.d[0].eq(self.data_0.storage),
|
self.gtx.encoder.k[0].eq(1),
|
||||||
self.gtx.encoder.k[0].eq(self.control_bit_0.storage),
|
self.gtx.encoder.d[1].eq(0x3C),
|
||||||
self.gtx.encoder.d[1].eq(self.data_1.storage),
|
self.gtx.encoder.k[1].eq(1),
|
||||||
self.gtx.encoder.k[1].eq(self.control_bit_1.storage),
|
self.gtx.encoder.d[2].eq(0x3C),
|
||||||
counter.eq(counter+1),
|
self.gtx.encoder.k[2].eq(1),
|
||||||
).Elif(counter == 1,
|
self.gtx.encoder.d[3].eq(0xB5),
|
||||||
self.gtx.encoder.d[0].eq(self.data_2.storage),
|
self.gtx.encoder.k[3].eq(0),
|
||||||
self.gtx.encoder.k[0].eq(self.control_bit_2.storage),
|
|
||||||
self.gtx.encoder.d[1].eq(self.data_3.storage),
|
|
||||||
self.gtx.encoder.k[1].eq(self.control_bit_3.storage),
|
|
||||||
counter.eq(0),
|
|
||||||
),
|
|
||||||
self.encoded_0.status.eq(self.gtx.encoder.output[0]),
|
self.encoded_0.status.eq(self.gtx.encoder.output[0]),
|
||||||
self.encoded_1.status.eq(self.gtx.encoder.output[1]),
|
self.encoded_1.status.eq(self.gtx.encoder.output[1]),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
# keep it odd, so it will show data[n] where n is odd
|
||||||
|
stb_timer = Signal(reset=10, max=11)
|
||||||
self.sync.cxp_gtx_rx += [
|
self.sync.cxp_gtx_rx += [
|
||||||
|
If(stb_timer == 0,
|
||||||
self.rxdata_0.status.eq(self.gtx.decoders[0].input),
|
self.rxdata_0.status.eq(self.gtx.decoders[0].input),
|
||||||
self.decoded_data_0.status.eq(self.gtx.decoders[0].d),
|
self.decoded_data_0.status.eq(self.gtx.decoders[0].d),
|
||||||
self.decoded_k_0.status.eq(self.gtx.decoders[0].k),
|
self.decoded_k_0.status.eq(self.gtx.decoders[0].k),
|
||||||
|
@ -247,6 +220,10 @@ class CXP_DownConn(Module, AutoCSR):
|
||||||
self.rxdata_1.status.eq(self.gtx.decoders[1].input),
|
self.rxdata_1.status.eq(self.gtx.decoders[1].input),
|
||||||
self.decoded_data_1.status.eq(self.gtx.decoders[1].d),
|
self.decoded_data_1.status.eq(self.gtx.decoders[1].d),
|
||||||
self.decoded_k_1.status.eq(self.gtx.decoders[1].k),
|
self.decoded_k_1.status.eq(self.gtx.decoders[1].k),
|
||||||
|
stb_timer.eq(stb_timer.reset),
|
||||||
|
).Else(
|
||||||
|
stb_timer.eq(stb_timer - 1),
|
||||||
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@ -295,7 +272,7 @@ class QPLL(Module):
|
||||||
# refclk_div = 2
|
# refclk_div = 2
|
||||||
# self.Xxout_div = 2
|
# self.Xxout_div = 2
|
||||||
|
|
||||||
self.tx_usrclk_freq = (sys_clk_freq*fbdiv_real/self.Xxout_div)/20
|
self.tx_usrclk_freq = (sys_clk_freq*fbdiv_real/self.Xxout_div)/40
|
||||||
|
|
||||||
self.specials += [
|
self.specials += [
|
||||||
Instance("GTXE2_COMMON",
|
Instance("GTXE2_COMMON",
|
||||||
|
@ -352,7 +329,7 @@ class QPLL(Module):
|
||||||
# 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 Comma_Detector(Module):
|
class Comma_Detector(Module):
|
||||||
def __init__(self, comma, check_period=150_000):
|
def __init__(self, comma, check_period=1_000_000):
|
||||||
self.data = Signal(20)
|
self.data = Signal(20)
|
||||||
self.rxinit_done = Signal()
|
self.rxinit_done = Signal()
|
||||||
|
|
||||||
|
@ -368,87 +345,207 @@ class Comma_Detector(Module):
|
||||||
# - UG476 (v1.12.1) p.228
|
# - UG476 (v1.12.1) p.228
|
||||||
|
|
||||||
# The validity of data & comma are checked externally
|
# The validity of data & comma are checked externally
|
||||||
aligned = Signal()
|
# aligned = Signal()
|
||||||
valid_data = Signal()
|
# valid_data = Signal()
|
||||||
aligned_rxclk = Signal()
|
# aligned_rxclk = Signal()
|
||||||
valid_data_rxclk = Signal()
|
# valid_data_rxclk = Signal()
|
||||||
rx1cnt = Signal(max=11)
|
# rx1cnt = Signal(max=11)
|
||||||
self.specials += [
|
# self.specials += [
|
||||||
MultiReg(aligned_rxclk, aligned),
|
# MultiReg(aligned_rxclk, aligned),
|
||||||
MultiReg(valid_data_rxclk, valid_data),
|
# MultiReg(valid_data_rxclk, valid_data),
|
||||||
]
|
# ]
|
||||||
self.submodules.check_ps = check_ps = PulseSynchronizer("sys", "cxp_gtx_rx")
|
# self.submodules.check_reset = check_reset = PulseSynchronizer("sys", "cxp_gtx_rx")
|
||||||
|
|
||||||
comma_n = ~comma & 0b1111111111
|
# comma_n = ~comma & 0b1111111111
|
||||||
self.sync.cxp_gtx_rx += [
|
# self.sync.cxp_gtx_rx += [
|
||||||
If(check_ps.o,
|
# If(check_reset.o,
|
||||||
aligned_rxclk.eq(0),
|
# aligned_rxclk.eq(0),
|
||||||
).Elif((self.data[:10] == comma) | (self.data[:10] == comma_n),
|
# ).Elif((self.data[:10] == comma) | (self.data[:10] == comma_n),
|
||||||
aligned_rxclk.eq(1),
|
# aligned_rxclk.eq(1),
|
||||||
),
|
# ),
|
||||||
|
|
||||||
rx1cnt.eq(reduce(add, [self.data[i] for i in range(10)])),
|
# rx1cnt.eq(reduce(add, [self.data[i] for i in range(10)])),
|
||||||
If(check_ps.o,
|
# If(check_reset.o,
|
||||||
valid_data_rxclk.eq(0),
|
# valid_data_rxclk.eq(0),
|
||||||
).Elif((rx1cnt == 4) | (rx1cnt == 5) | (rx1cnt == 6),
|
# ).Elif((rx1cnt == 4) | (rx1cnt == 5) | (rx1cnt == 6),
|
||||||
valid_data_rxclk.eq(1),
|
# valid_data_rxclk.eq(1),
|
||||||
),
|
# ),
|
||||||
]
|
# ]
|
||||||
|
|
||||||
|
# self.aligned = Signal()
|
||||||
|
# self.valid_data = Signal()
|
||||||
|
# self.comb +=[
|
||||||
|
# self.aligned.eq(aligned),
|
||||||
|
# self.valid_data.eq(valid_data)
|
||||||
|
# ]
|
||||||
|
|
||||||
|
|
||||||
check_counter = Signal(reset=check_period-1, max=check_period)
|
check_counter = Signal(reset=check_period-1, max=check_period)
|
||||||
check = Signal()
|
# check = Signal()
|
||||||
self.sync += [
|
self.sync += [
|
||||||
check.eq(0),
|
self.restart.eq(0),
|
||||||
|
# check.eq(0),
|
||||||
|
# check_reset.i.eq(0),
|
||||||
|
If(~self.ready,
|
||||||
If(check_counter == 0,
|
If(check_counter == 0,
|
||||||
check_counter.eq(check_counter.reset),
|
check_counter.eq(check_counter.reset),
|
||||||
check.eq(1),
|
# check.eq(1),
|
||||||
|
self.restart.eq(1),
|
||||||
|
# check_reset.i.eq(1),
|
||||||
).Else(
|
).Else(
|
||||||
check_counter.eq(check_counter - 1),
|
check_counter.eq(check_counter - 1),
|
||||||
)
|
)
|
||||||
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
self.submodules.fsm = fsm = FSM(reset_state="WAIT_COMMA_ALIGN")
|
# WIP:
|
||||||
|
|
||||||
aligner_en = Signal()
|
comma_n = ~comma & 0b1111111111
|
||||||
self.specials += MultiReg(aligner_en, self.aligner_en_rxclk, odomain="cxp_gtx_rx")
|
|
||||||
fsm.act("WAIT_COMMA_ALIGN",
|
has_error = Signal()
|
||||||
aligner_en.eq(1),
|
comma_aligned = Signal()
|
||||||
If(check,
|
comma_seen = Signal()
|
||||||
check_ps.i.eq(1),
|
error_seen = Signal()
|
||||||
If(aligned,
|
one_counts = Signal(max=11)
|
||||||
NextState("WAIT_VALID_DATA"),
|
|
||||||
|
counter_period = 5000
|
||||||
|
counter = Signal(reset=counter_period-1, max=counter_period)
|
||||||
|
check_reset = Signal()
|
||||||
|
check = Signal()
|
||||||
|
self.sync.cxp_gtx_rx += [
|
||||||
|
check.eq(0),
|
||||||
|
If(counter == 0,
|
||||||
|
counter.eq(counter.reset),
|
||||||
|
check.eq(1),
|
||||||
).Else(
|
).Else(
|
||||||
self.restart.eq(1),
|
counter.eq(counter - 1),
|
||||||
)
|
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
has_error.eq(0),
|
||||||
|
one_counts.eq(reduce(add, [self.data[i] for i in range(10, 20)])),
|
||||||
|
If((one_counts != 4) & (one_counts != 5) & (one_counts != 6),
|
||||||
|
has_error.eq(1)
|
||||||
|
),
|
||||||
|
|
||||||
|
comma_aligned.eq(0),
|
||||||
|
If((self.data[:10] == comma) | (self.data[:10] == comma_n),
|
||||||
|
comma_aligned.eq(1)
|
||||||
|
),
|
||||||
|
|
||||||
|
# signal that need to be manually cleared
|
||||||
|
If(check_reset,
|
||||||
|
comma_seen.eq(0),
|
||||||
|
).Elif((self.data[:10] == comma) | (self.data[:10] == comma_n),
|
||||||
|
comma_seen.eq(1)
|
||||||
|
),
|
||||||
|
|
||||||
|
one_counts.eq(reduce(add, [self.data[i] for i in range(10, 20)])),
|
||||||
|
If(check_reset,
|
||||||
|
error_seen.eq(0),
|
||||||
|
).Elif((one_counts != 4) & (one_counts != 5) & (one_counts != 6),
|
||||||
|
error_seen.eq(1),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
||||||
|
# DEBUG: expose signal
|
||||||
|
self.check_reset = Signal()
|
||||||
|
self.comma_aligned = Signal()
|
||||||
|
self.comma_seen = Signal()
|
||||||
|
self.has_error = Signal()
|
||||||
|
self.error_seen = Signal()
|
||||||
|
self.comb +=[
|
||||||
|
self.check_reset.eq(check_reset),
|
||||||
|
self.comma_aligned.eq(comma_aligned),
|
||||||
|
self.comma_seen.eq(comma_seen),
|
||||||
|
self.has_error.eq(has_error),
|
||||||
|
self.error_seen.eq(error_seen),
|
||||||
|
]
|
||||||
|
|
||||||
|
self.submodules.rxfsm = rxfsm = ClockDomainsRenamer("cxp_gtx_rx")(FSM(reset_state="ALIGNING"))
|
||||||
|
|
||||||
|
rxfsm.act("ALIGNING",
|
||||||
|
self.aligner_en_rxclk.eq(1),
|
||||||
|
If(comma_aligned & (~has_error),
|
||||||
|
check_reset.eq(1),
|
||||||
|
NextState("DOUBLE_CHECK"),
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
fsm.act("WAIT_VALID_DATA",
|
rxfsm.act("DOUBLE_CHECK",
|
||||||
aligner_en.eq(1),
|
|
||||||
If(check,
|
If(check,
|
||||||
check_ps.i.eq(1),
|
check_reset.eq(1),
|
||||||
If(aligned & valid_data,
|
If(~error_seen,
|
||||||
NextState("READY"),
|
NextState("READY"),
|
||||||
).Else(
|
).Else(
|
||||||
self.restart.eq(1),
|
NextState("ALIGNING")
|
||||||
NextState("WAIT_COMMA_ALIGN"),
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
fsm.act("READY",
|
ready = Signal()
|
||||||
self.ready.eq(1),
|
self.specials += MultiReg(ready, self.ready)
|
||||||
|
rxfsm.act("READY",
|
||||||
|
ready.eq(1),
|
||||||
If(check,
|
If(check,
|
||||||
check_ps.i.eq(1),
|
check_reset.eq(1),
|
||||||
If(~(aligned & valid_data),
|
If(~comma_seen,
|
||||||
self.restart.eq(1),
|
NextState("ALIGNING"),
|
||||||
NextState("WAIT_COMMA_ALIGN"),
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# self.submodules.fsm = fsm = FSM(reset_state="WAIT_RXINIT")
|
||||||
|
|
||||||
|
# aligner_en = Signal()
|
||||||
|
# self.specials += MultiReg(aligner_en, self.aligner_en_rxclk, odomain="cxp_gtx_rx")
|
||||||
|
|
||||||
|
# fsm.act("WAIT_RXINIT",
|
||||||
|
# If(self.rxinit_done,
|
||||||
|
# NextState("WAIT_COMMA_ALIGN"),
|
||||||
|
# )
|
||||||
|
# )
|
||||||
|
|
||||||
|
# fsm.act("WAIT_COMMA_ALIGN",
|
||||||
|
# aligner_en.eq(1),
|
||||||
|
# If(check,
|
||||||
|
# check_reset.i.eq(1),
|
||||||
|
# If(aligned,
|
||||||
|
# NextState("WAIT_VALID_DATA"),
|
||||||
|
# ).Else(
|
||||||
|
# self.restart.eq(1),
|
||||||
|
# NextState("WAIT_RXINIT")
|
||||||
|
# )
|
||||||
|
# )
|
||||||
|
# )
|
||||||
|
|
||||||
|
# fsm.act("WAIT_VALID_DATA",
|
||||||
|
# aligner_en.eq(1),
|
||||||
|
# If(check,
|
||||||
|
# check_reset.i.eq(1),
|
||||||
|
# If(aligned & valid_data,
|
||||||
|
# NextState("READY"),
|
||||||
|
# ).Else(
|
||||||
|
# self.restart.eq(1),
|
||||||
|
# NextState("WAIT_RXINIT"),
|
||||||
|
# )
|
||||||
|
# )
|
||||||
|
# )
|
||||||
|
|
||||||
|
# fsm.act("READY",
|
||||||
|
# self.ready.eq(1),
|
||||||
|
# If(check,
|
||||||
|
# check_reset.i.eq(1),
|
||||||
|
# If(~(aligned & valid_data),
|
||||||
|
# self.restart.eq(1),
|
||||||
|
# NextState("WAIT_RXINIT"),
|
||||||
|
# )
|
||||||
|
# )
|
||||||
|
# )
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class GTX(Module):
|
class GTX(Module):
|
||||||
# Settings:
|
# Settings:
|
||||||
|
@ -463,7 +560,7 @@ class GTX(Module):
|
||||||
|
|
||||||
# linerate = USRCLK * datawidth
|
# linerate = USRCLK * datawidth
|
||||||
pll_fbout_mult = 8
|
pll_fbout_mult = 8
|
||||||
txusr_pll_div = pll_fbout_mult*sys_clk_freq/qpll.tx_usrclk_freq # 20 is datawidth
|
txusr_pll_div = pll_fbout_mult*sys_clk_freq/qpll.tx_usrclk_freq
|
||||||
|
|
||||||
self.tx_restart = Signal()
|
self.tx_restart = Signal()
|
||||||
self.rx_restart = Signal()
|
self.rx_restart = Signal()
|
||||||
|
@ -484,9 +581,9 @@ class GTX(Module):
|
||||||
self.dout = Signal(16)
|
self.dout = Signal(16)
|
||||||
self.dready = Signal()
|
self.dready = Signal()
|
||||||
|
|
||||||
self.submodules.encoder = ClockDomainsRenamer("cxp_gtx_tx")(Encoder(2, True))
|
self.submodules.encoder = ClockDomainsRenamer("cxp_gtx_tx")(Encoder(4, True))
|
||||||
self.submodules.decoders = [ClockDomainsRenamer("cxp_gtx_rx")(
|
self.submodules.decoders = [ClockDomainsRenamer("cxp_gtx_rx")(
|
||||||
(Decoder(True))) for _ in range(2)]
|
(Decoder(True))) for _ in range(4)]
|
||||||
|
|
||||||
|
|
||||||
# transceiver direct clock outputs
|
# transceiver direct clock outputs
|
||||||
|
@ -509,8 +606,8 @@ class GTX(Module):
|
||||||
rx_init.cplllock.eq(qpll.lock)
|
rx_init.cplllock.eq(qpll.lock)
|
||||||
]
|
]
|
||||||
|
|
||||||
txdata = Signal(20)
|
txdata = Signal(40)
|
||||||
rxdata = Signal(20)
|
rxdata = Signal(40)
|
||||||
|
|
||||||
comma_aligner_en = Signal()
|
comma_aligner_en = Signal()
|
||||||
# Note: the following parameters were set after consulting AR45360
|
# Note: the following parameters were set after consulting AR45360
|
||||||
|
@ -570,11 +667,11 @@ class GTX(Module):
|
||||||
i_TXINHIBIT=~self.txenable,
|
i_TXINHIBIT=~self.txenable,
|
||||||
|
|
||||||
# TX data
|
# TX data
|
||||||
p_TX_DATA_WIDTH=20,
|
p_TX_DATA_WIDTH=40,
|
||||||
p_TX_INT_DATAWIDTH=0,
|
p_TX_INT_DATAWIDTH=1,
|
||||||
i_TXCHARDISPMODE=Cat(txdata[9], txdata[19]),
|
i_TXCHARDISPMODE=Cat(txdata[9], txdata[19], txdata[29], txdata[39]),
|
||||||
i_TXCHARDISPVAL=Cat(txdata[8], txdata[18]),
|
i_TXCHARDISPVAL=Cat(txdata[8], txdata[18], txdata[28], txdata[38]),
|
||||||
i_TXDATA=Cat(txdata[:8], txdata[10:18]),
|
i_TXDATA=Cat(txdata[:8], txdata[10:18], txdata[20:28], txdata[30:38]),
|
||||||
i_TXUSRCLK=ClockSignal("cxp_gtx_tx"),
|
i_TXUSRCLK=ClockSignal("cxp_gtx_tx"),
|
||||||
i_TXUSRCLK2=ClockSignal("cxp_gtx_tx"),
|
i_TXUSRCLK2=ClockSignal("cxp_gtx_tx"),
|
||||||
|
|
||||||
|
@ -633,27 +730,28 @@ class GTX(Module):
|
||||||
p_CLK_COR_SEQ_2_ENABLE=0b1111,
|
p_CLK_COR_SEQ_2_ENABLE=0b1111,
|
||||||
|
|
||||||
# RX data
|
# RX data
|
||||||
p_RX_DATA_WIDTH=20,
|
p_RX_DATA_WIDTH=40,
|
||||||
p_RX_INT_DATAWIDTH=0,
|
p_RX_INT_DATAWIDTH=1,
|
||||||
o_RXDISPERR=Cat(rxdata[9], rxdata[19]),
|
o_RXDISPERR=Cat(rxdata[9], rxdata[19], rxdata[29], rxdata[39]),
|
||||||
o_RXCHARISK=Cat(rxdata[8], rxdata[18]),
|
o_RXCHARISK=Cat(rxdata[8], rxdata[18], rxdata[28], rxdata[38]),
|
||||||
o_RXDATA=Cat(rxdata[:8], rxdata[10:18]),
|
o_RXDATA=Cat(rxdata[:8], rxdata[10:18], rxdata[20:28], rxdata[30:38]),
|
||||||
|
|
||||||
# RX Byte and Word Alignment Attributes
|
# RX Byte and Word Alignment Attributes
|
||||||
p_ALIGN_COMMA_DOUBLE="FALSE",
|
p_ALIGN_COMMA_DOUBLE="FALSE",
|
||||||
p_ALIGN_COMMA_ENABLE=0b1111111111,
|
p_ALIGN_COMMA_ENABLE=0b1111111111,
|
||||||
p_ALIGN_COMMA_WORD=2, # align comma to rxdata[:10] only
|
p_ALIGN_COMMA_WORD=4, # align comma to rxdata[:10] only
|
||||||
p_ALIGN_MCOMMA_DET="TRUE",
|
p_ALIGN_MCOMMA_DET="TRUE",
|
||||||
p_ALIGN_MCOMMA_VALUE=0b1010000011,
|
p_ALIGN_MCOMMA_VALUE=0b1010000011,
|
||||||
p_ALIGN_PCOMMA_DET="TRUE",
|
p_ALIGN_PCOMMA_DET="TRUE",
|
||||||
p_ALIGN_PCOMMA_VALUE=0b0101111100,
|
p_ALIGN_PCOMMA_VALUE=0b0101111100,
|
||||||
p_SHOW_REALIGN_COMMA="FALSE",
|
p_SHOW_REALIGN_COMMA="TRUE",
|
||||||
p_RXSLIDE_AUTO_WAIT=7,
|
p_RXSLIDE_AUTO_WAIT=7,
|
||||||
p_RXSLIDE_MODE="OFF",
|
p_RXSLIDE_MODE="OFF",
|
||||||
p_RX_SIG_VALID_DLY=10,
|
p_RX_SIG_VALID_DLY=10,
|
||||||
i_RXPCOMMAALIGNEN=comma_aligner_en,
|
i_RXPCOMMAALIGNEN=comma_aligner_en,
|
||||||
i_RXMCOMMAALIGNEN=comma_aligner_en,
|
i_RXMCOMMAALIGNEN=comma_aligner_en,
|
||||||
i_RXCOMMADETEN=1,
|
i_RXCOMMADETEN=1,
|
||||||
|
i_RXSLIDE=0,
|
||||||
|
|
||||||
# RX 8B/10B Decoder Attributes
|
# RX 8B/10B Decoder Attributes
|
||||||
p_RX_DISPERR_SEQ_MATCH="FALSE",
|
p_RX_DISPERR_SEQ_MATCH="FALSE",
|
||||||
|
@ -758,7 +856,7 @@ class GTX(Module):
|
||||||
p_CLKFBOUT_MULT=pll_fbout_mult, p_DIVCLK_DIVIDE=1,
|
p_CLKFBOUT_MULT=pll_fbout_mult, p_DIVCLK_DIVIDE=1,
|
||||||
i_CLKFBIN=txpll_fb_clk, o_CLKFBOUT=txpll_fb_clk,
|
i_CLKFBIN=txpll_fb_clk, o_CLKFBOUT=txpll_fb_clk,
|
||||||
|
|
||||||
# frequency = linerate/20
|
# frequency = linerate/40
|
||||||
p_CLKOUT0_DIVIDE=txusr_pll_div, p_CLKOUT0_PHASE=0.0, o_CLKOUT0=txpll_clkout,
|
p_CLKOUT0_DIVIDE=txusr_pll_div, p_CLKOUT0_PHASE=0.0, o_CLKOUT0=txpll_clkout,
|
||||||
|
|
||||||
# Dynamic Reconfiguration Ports
|
# Dynamic Reconfiguration Ports
|
||||||
|
@ -784,9 +882,11 @@ class GTX(Module):
|
||||||
]
|
]
|
||||||
|
|
||||||
self.comb += [
|
self.comb += [
|
||||||
txdata.eq(Cat(self.encoder.output[0], self.encoder.output[1])),
|
txdata.eq(Cat(self.encoder.output[0], self.encoder.output[1], self.encoder.output[2], self.encoder.output[3])),
|
||||||
self.decoders[0].input.eq(rxdata[:10]),
|
self.decoders[0].input.eq(rxdata[:10]),
|
||||||
self.decoders[1].input.eq(rxdata[10:])
|
self.decoders[1].input.eq(rxdata[10:20]),
|
||||||
|
self.decoders[2].input.eq(rxdata[20:30]),
|
||||||
|
self.decoders[3].input.eq(rxdata[30:]),
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue