1
0
Fork 0

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:
morgan 2024-11-04 10:55:37 +08:00
parent 465609b3f3
commit 3fd7d3d905
1 changed files with 53 additions and 37 deletions

View File

@ -58,7 +58,7 @@ class Receiver(Module):
data_valid = Signal() data_valid = Signal()
self.sync.cxp_gtx_rx += [ 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), self.source.stb.eq(0),
If(data_valid & self.source.ack & ~((gtx.decoders[0].d == 0xBC) & (gtx.decoders[0].k == 1)), 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 # 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_Checker(Module): class Comma_Aligner(Module):
def __init__(self, comma, reset_period=10_000_000): def __init__(self, comma, reset_period=10_000_000):
self.data = Signal(20) self.data = Signal(20)
self.comma_aligned = Signal() self.comma_aligned = Signal()
@ -229,28 +253,9 @@ class Comma_Checker(Module):
self.aligner_en = Signal() self.aligner_en = Signal()
self.ready_sys = 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 # Data and comma checker
# From UG476 (v1.12.1) p.228 # From UG476 (v1.12.1) p.228
# The built-in RXBYTEISALIGNED can be falsely asserted at linerate higher than 5Gbps # 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), 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) AsyncResetSynchronizer(self.cd_cxp_gtx_tx, ~self.txpll_locked & ~tx_init.done)
] ]
self.comb += tx_init.restart.eq(self.tx_restart)
# RX clocking # RX clocking
# the CDR matches the required frequency for RXUSRCLK, no need for PLL # the CDR matches the required frequency for RXUSRCLK, no need for PLL
# 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.clock_domains.cd_cxp_gtx_rx = ClockDomain()
self.specials += [ self.specials += [
Instance("BUFG", i_I=self.rxoutclk, o_O=self.cd_cxp_gtx_rx.clk), Instance("BUFG", i_I=self.rxoutclk, o_O=self.cd_cxp_gtx_rx.clk),
AsyncResetSynchronizer(self.cd_cxp_gtx_rx, ~rx_init.done) 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 += [ self.comb += [
txdata.eq(Cat(self.encoder.output[0], self.encoder.output[1], self.encoder.output[2], self.encoder.output[3])), 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.decoders[3].input.eq(rxdata[30:]),
] ]
self.submodules.comma_aligner = comma_aligner = Comma_Aligner(0b0101111100)
self.submodules.comma_checker = comma_checker = Comma_Checker(0b0101111100)
self.comb += [ self.comb += [
comma_checker.data.eq(rxdata), comma_aligner.data.eq(rxdata),
comma_checker.comma_aligned.eq(comma_aligned), comma_aligner.comma_aligned.eq(comma_aligned),
comma_checker.comma_realigned.eq(comma_realigned), comma_aligner.comma_realigned.eq(comma_realigned),
comma_checker.comma_det.eq(comma_det), comma_aligner.comma_det.eq(comma_det),
comma_aligner_en.eq(comma_checker.aligner_en), comma_aligner_en.eq(comma_aligner.aligner_en),
self.rx_ready.eq(comma_checker.ready_sys), self.rx_ready.eq(comma_aligner.ready_sys),
rx_init.restart.eq(self.rx_restart | comma_checker.restart_sys),
tx_init.restart.eq(self.tx_restart),
] ]