diff --git a/artiq/gateware/wrpll/wrpll.py b/artiq/gateware/wrpll/wrpll.py index ef5a15290..992f41612 100644 --- a/artiq/gateware/wrpll/wrpll.py +++ b/artiq/gateware/wrpll/wrpll.py @@ -171,3 +171,66 @@ class WRPLL(Module, AutoCSR): ] self.submodules.ev = SharedIRQ(self.ref_tag_ev, self.main_tag_ev) + +class FrequencyMultiplier(Module, AutoCSR): + def __init__(self, clkin): + clkin_se = Signal() + mmcm_locked = Signal() + mmcm_fb_clk = Signal() + ref_clk = Signal() + self.clock_domains.cd_ref = ClockDomain() + self.refclk_reset = CSRStorage(reset=1) + + self.mmcm_bypass = CSRStorage() + self.mmcm_locked = CSRStatus() + self.mmcm_reset = CSRStorage(reset=1) + + self.mmcm_daddr = CSRStorage(7) + self.mmcm_din = CSRStorage(16) + self.mmcm_dwen = CSRStorage() + self.mmcm_den = CSRStorage() + self.mmcm_dclk = CSRStorage() + self.mmcm_dout = CSRStatus(16) + self.mmcm_dready = CSRStatus() + + # # # + + self.specials += [ + Instance("IBUFDS", + i_I=clkin.p, i_IB=clkin.n, + o_O=clkin_se), + # MMCME2 is capable to accept 10MHz input while PLLE2 only support down to 19MHz input (DS191) + # The MMCME2 can be reconfiged during runtime using the Dynamic Reconfiguration Ports + Instance("MMCME2_ADV", + p_BANDWIDTH="HIGH", # lower output jitter (see https://support.xilinx.com/s/question/0D52E00006iHqRqSAK) + o_LOCKED=self.mmcm_locked.status, + i_RST=self.mmcm_reset.storage, + + p_CLKIN1_PERIOD=8, # ns + i_CLKIN1=clkin_se, + i_CLKINSEL=1, # 1=CLKIN1 0=CLKIN2 + + # VCO @ 1.25GHz + p_CLKFBOUT_MULT_F=10, p_DIVCLK_DIVIDE=1, + i_CLKFBIN=mmcm_fb_clk, o_CLKFBOUT=mmcm_fb_clk, + + # 125MHz for WRPLL + p_CLKOUT0_DIVIDE_F=10, p_CLKOUT0_PHASE=0.0, o_CLKOUT0=ref_clk, + + # Dynamic Reconfiguration Ports + i_DADDR = self.mmcm_daddr.storage, + i_DI = self.mmcm_din.storage, + i_DWE = self.mmcm_dwen.storage, + i_DEN = self.mmcm_den.storage, + i_DCLK = self.mmcm_dclk.storage, + o_DO = self.mmcm_dout.status, + o_DRDY = self.mmcm_dready.status + ), + Instance("BUFGMUX", + i_I0=ref_clk, + i_I1=clkin_se, + i_S=self.mmcm_bypass.storage, + o_O=self.cd_ref.clk + ), + AsyncResetSynchronizer(self.cd_ref, self.refclk_reset.storage), + ]