from migen import * from migen.genlib.cdc import MultiReg, AsyncResetSynchronizer, PulseSynchronizer from misoc.interconnect.csr import * from misoc.interconnect.csr_eventmanager import * from ddmtd import DDMTDSamplerGTX, DDMTD class FrequencyCounter(Module, AutoCSR): def __init__(self, counter_width=24, domains=["gtx0_rtio_rx", "sys", "helper"]): for domain in domains: name = "counter_" + domain counter = CSRStatus(counter_width, name=name) setattr(self, name, counter) self.update_en = CSRStorage() timer = Signal(counter_width) timer_tick = Signal() self.sync += Cat(timer, timer_tick).eq(timer + 1) for domain in domains: sync_domain = getattr(self.sync, domain) divider = Signal(2) sync_domain += divider.eq(divider + 1) divided = Signal() divided.attr.add("no_retiming") sync_domain += divided.eq(divider[-1]) divided_sys = Signal() self.specials += MultiReg(divided, divided_sys) divided_sys_r = Signal() divided_tick = Signal() self.sync += divided_sys_r.eq(divided_sys) self.comb += divided_tick.eq(divided_sys & ~divided_sys_r) counter = Signal(counter_width) counter_csr = getattr(self, "counter_" + domain) self.sync += [ If(timer_tick, If(self.update_en.storage, counter_csr.status.eq(counter)), counter.eq(0), ).Else( If(divided_tick, counter.eq(counter + 1)) ) ] class WRPLL(Module, AutoCSR): def __init__(self, gtx, main_dcxo_pads, helper_dcxo_pads, COUNTER_BIT=32): self.gtx_tag = CSRStatus(COUNTER_BIT) self.main_tag = CSRStatus(COUNTER_BIT) ddmtd_counter = Signal(COUNTER_BIT) gtx_tag_sys = Signal(COUNTER_BIT) main_tag_sys = Signal(COUNTER_BIT) gtx_tag_stb_sys = Signal() main_tag_stb_sys = Signal() # # # self.helper_reset = CSRStorage(reset=1) self.clock_domains.cd_helper = ClockDomain() self.helper_reset.storage.attr.add("no_retiming") self.specials += [ Instance("IBUFGDS", i_I=helper_dcxo_pads.p, i_IB=helper_dcxo_pads.n, o_O=self.cd_helper.clk), AsyncResetSynchronizer(self.cd_helper, self.helper_reset.storage) ] self.submodules.frequency_counter = FrequencyCounter() self.submodules.ddmtd_sampler = DDMTDSamplerGTX(gtx, main_dcxo_pads) self.sync.helper += ddmtd_counter.eq(ddmtd_counter + 1) self.submodules.ddmtd_gtx = DDMTD(ddmtd_counter, self.ddmtd_sampler.gtx_beating) self.submodules.ddmtd_main = DDMTD(ddmtd_counter, self.ddmtd_sampler.main_beating) # DDMTD tags collection self.specials += [ MultiReg(self.ddmtd_gtx.h_tag, gtx_tag_sys), MultiReg(self.ddmtd_main.h_tag, main_tag_sys) ] gtx_tag_stb_ps = PulseSynchronizer("helper", "sys") main_tag_stb_ps = PulseSynchronizer("helper", "sys") self.submodules += [ gtx_tag_stb_ps, main_tag_stb_ps ] self.sync.helper += [ gtx_tag_stb_ps.i.eq(self.ddmtd_gtx.h_tag_update), main_tag_stb_ps.i.eq(self.ddmtd_main.h_tag_update) ] self.sync += [ gtx_tag_stb_sys.eq(gtx_tag_stb_ps.o), main_tag_stb_sys.eq(main_tag_stb_ps.o) ] self.sync += [ If(gtx_tag_stb_sys, self.gtx_tag.status.eq(gtx_tag_sys), ), If(main_tag_stb_sys, self.main_tag.status.eq(main_tag_sys) ) ] # PL-PS shared peripheral interrupt (SPI) self.submodules.gtx_tag_ev = EventManager() self.gtx_tag_ev.stb = EventSourcePulse() self.gtx_tag_ev.finalize() self.submodules.main_tag_ev = EventManager() self.main_tag_ev.stb = EventSourcePulse() self.main_tag_ev.finalize() self.sync += [ self.gtx_tag_ev.stb.trigger.eq(gtx_tag_stb_sys), self.main_tag_ev.stb.trigger.eq(main_tag_stb_sys) ]