artiq-zynq/src/gateware/ddmtd.py

73 lines
2.2 KiB
Python

from migen import *
from migen.genlib.cdc import PulseSynchronizer, MultiReg
from migen.genlib.fsm import FSM
from misoc.interconnect.csr import *
class DDMTDSamplerGTX(Module):
def __init__(self, gtx, main_xo_pads):
self.gtx_beating = Signal()
self.main_beating = Signal()
# # #
main_clk_se = Signal()
gtx_beating_FF = Signal()
main_beating_FF = Signal()
self.specials += [
Instance("IBUFDS",
i_I=main_xo_pads.p, i_IB=main_xo_pads.n,
o_O=main_clk_se),
# Two back to back FFs are used to prevent metastability
Instance("FD", i_C=ClockSignal("helper"),
i_D=gtx.cd_rtio_rx0.clk, o_Q=gtx_beating_FF),
Instance("FD", i_C=ClockSignal("helper"),
i_D=gtx_beating_FF, o_Q=self.gtx_beating),
Instance("FD", i_C=ClockSignal("helper"),
i_D=main_clk_se, o_Q=main_beating_FF,),
Instance("FD", i_C=ClockSignal("helper"),
i_D=main_beating_FF, o_Q=self.main_beating,)
]
class DDMTDDeglitcherFirstEdge(Module):
def __init__(self, input_signal, blind_period=200):
self.detect = Signal()
rising = Signal()
input_signal_r = Signal()
# # #
self.sync.helper += [
input_signal_r.eq(input_signal),
rising.eq(input_signal & ~input_signal_r)
]
blind_counter = Signal(max=blind_period)
self.sync.helper += [
If(blind_counter != 0, blind_counter.eq(blind_counter - 1)),
If(input_signal_r, blind_counter.eq(blind_period - 1)),
self.detect.eq(rising & (blind_counter == 0))
]
class DDMTD(Module):
def __init__(self, counter, input_signal):
# in helper clock domain
self.h_tag = Signal(len(counter))
self.h_tag_update = Signal()
# # #
deglitcher = DDMTDDeglitcherFirstEdge(input_signal)
self.submodules += deglitcher
self.sync.helper += [
self.h_tag_update.eq(0),
If(deglitcher.detect,
self.h_tag_update.eq(1),
self.h_tag.eq(counter)
)
]