forked from M-Labs/artiq-zynq
downconn GW: move rx reset out of comma checker
rx reset: only active for singe/master rx comma checker: rename to aligner & active on all rx config
This commit is contained in:
parent
465609b3f3
commit
3fd7d3d905
|
@ -58,7 +58,7 @@ class Receiver(Module):
|
|||
|
||||
data_valid = Signal()
|
||||
self.sync.cxp_gtx_rx += [
|
||||
data_valid.eq(gtx.comma_checker.rxfsm.ongoing("READY")),
|
||||
data_valid.eq(gtx.comma_aligner.rxfsm.ongoing("READY")),
|
||||
|
||||
self.source.stb.eq(0),
|
||||
If(data_valid & self.source.ack & ~((gtx.decoders[0].d == 0xBC) & (gtx.decoders[0].k == 1)),
|
||||
|
@ -218,9 +218,33 @@ class QPLL(Module, AutoCSR):
|
|||
),
|
||||
]
|
||||
|
||||
|
||||
class RX_Resetter(Module):
|
||||
def __init__(self, reset_period=10_000_000):
|
||||
self.rx_ready = Signal()
|
||||
self.rx_reset = Signal()
|
||||
|
||||
# # #
|
||||
|
||||
# periodically reset rx until rx is connected and receiving valid data
|
||||
# as after connecting RXP/RXN, the whole RX need to be reset
|
||||
|
||||
reset_counter = Signal(reset=reset_period-1, max=reset_period)
|
||||
self.sync += [
|
||||
self.rx_reset.eq(0),
|
||||
If(~self.rx_ready,
|
||||
If(reset_counter == 0,
|
||||
reset_counter.eq(reset_counter.reset),
|
||||
self.rx_reset.eq(1),
|
||||
).Else(
|
||||
reset_counter.eq(reset_counter - 1),
|
||||
)
|
||||
)
|
||||
]
|
||||
|
||||
# Warning: Xilinx transceivers are LSB first, and comma needs to be flipped
|
||||
# compared to the usual 8b10b binary representation.
|
||||
class Comma_Checker(Module):
|
||||
class Comma_Aligner(Module):
|
||||
def __init__(self, comma, reset_period=10_000_000):
|
||||
self.data = Signal(20)
|
||||
self.comma_aligned = Signal()
|
||||
|
@ -229,28 +253,9 @@ class Comma_Checker(Module):
|
|||
|
||||
self.aligner_en = Signal()
|
||||
self.ready_sys = Signal()
|
||||
self.restart_sys = Signal()
|
||||
|
||||
# # #
|
||||
|
||||
|
||||
# periodically reset rx until rx is connected and receiving valid data
|
||||
# as after connecting RXP/RXN, the whole RX need to be reset
|
||||
|
||||
reset_counter = Signal(reset=reset_period-1, max=reset_period)
|
||||
self.sync += [
|
||||
self.restart_sys.eq(0),
|
||||
If(~self.ready_sys,
|
||||
If(reset_counter == 0,
|
||||
reset_counter.eq(reset_counter.reset),
|
||||
self.restart_sys.eq(1),
|
||||
).Else(
|
||||
reset_counter.eq(reset_counter - 1),
|
||||
)
|
||||
)
|
||||
]
|
||||
|
||||
|
||||
# Data and comma checker
|
||||
# From UG476 (v1.12.1) p.228
|
||||
# The built-in RXBYTEISALIGNED can be falsely asserted at linerate higher than 5Gbps
|
||||
|
@ -694,14 +699,29 @@ class GTX(Module):
|
|||
Instance("BUFG", i_I=txpll_clkout, o_O=self.cd_cxp_gtx_tx.clk),
|
||||
AsyncResetSynchronizer(self.cd_cxp_gtx_tx, ~self.txpll_locked & ~tx_init.done)
|
||||
]
|
||||
self.comb += tx_init.restart.eq(self.tx_restart)
|
||||
|
||||
# RX clocking
|
||||
# the CDR matches the required frequency for RXUSRCLK, no need for PLL
|
||||
self.clock_domains.cd_cxp_gtx_rx = ClockDomain()
|
||||
self.specials += [
|
||||
Instance("BUFG", i_I=self.rxoutclk, o_O=self.cd_cxp_gtx_rx.clk),
|
||||
AsyncResetSynchronizer(self.cd_cxp_gtx_rx, ~rx_init.done)
|
||||
]
|
||||
|
||||
# Slave Rx will use cxp_gtx_rx instead
|
||||
if rx_mode == "single" or rx_mode == "master":
|
||||
self.clock_domains.cd_cxp_gtx_rx = ClockDomain()
|
||||
self.specials += [
|
||||
Instance("BUFG", i_I=self.rxoutclk, o_O=self.cd_cxp_gtx_rx.clk),
|
||||
AsyncResetSynchronizer(self.cd_cxp_gtx_rx, ~rx_init.done)
|
||||
]
|
||||
self.submodules.rx_resetter = rx_resetter = RX_Resetter()
|
||||
self.comb += [
|
||||
rx_resetter.rx_ready.eq(self.rx_ready),
|
||||
rx_init.restart.eq(self.rx_restart | rx_resetter.rx_reset),
|
||||
]
|
||||
else:
|
||||
self.comb += rx_init.restart.eq(self.rx_restart),
|
||||
|
||||
|
||||
|
||||
# 8b10b Encoder/Decoder
|
||||
|
||||
self.comb += [
|
||||
txdata.eq(Cat(self.encoder.output[0], self.encoder.output[1], self.encoder.output[2], self.encoder.output[3])),
|
||||
|
@ -711,16 +731,12 @@ class GTX(Module):
|
|||
self.decoders[3].input.eq(rxdata[30:]),
|
||||
]
|
||||
|
||||
|
||||
self.submodules.comma_checker = comma_checker = Comma_Checker(0b0101111100)
|
||||
self.submodules.comma_aligner = comma_aligner = Comma_Aligner(0b0101111100)
|
||||
self.comb += [
|
||||
comma_checker.data.eq(rxdata),
|
||||
comma_checker.comma_aligned.eq(comma_aligned),
|
||||
comma_checker.comma_realigned.eq(comma_realigned),
|
||||
comma_checker.comma_det.eq(comma_det),
|
||||
comma_aligner_en.eq(comma_checker.aligner_en),
|
||||
self.rx_ready.eq(comma_checker.ready_sys),
|
||||
|
||||
rx_init.restart.eq(self.rx_restart | comma_checker.restart_sys),
|
||||
tx_init.restart.eq(self.tx_restart),
|
||||
comma_aligner.data.eq(rxdata),
|
||||
comma_aligner.comma_aligned.eq(comma_aligned),
|
||||
comma_aligner.comma_realigned.eq(comma_realigned),
|
||||
comma_aligner.comma_det.eq(comma_det),
|
||||
comma_aligner_en.eq(comma_aligner.aligner_en),
|
||||
self.rx_ready.eq(comma_aligner.ready_sys),
|
||||
]
|
||||
|
|
Loading…
Reference in New Issue