diff --git a/src/gateware/wrpll.py b/src/gateware/wrpll.py index e6f9ceb..e3b3f63 100644 --- a/src/gateware/wrpll.py +++ b/src/gateware/wrpll.py @@ -137,7 +137,7 @@ class SMA_PLL(Module, AutoCSR): self.clock_domains.cd_ref = ClockDomain() self.mmcm_locked = CSRStatus() - self.mmcm_reset = CSRStorage() #TODO for i_RST + self.mmcm_reset = CSRStorage() self.drp_addr = CSRStorage(7) self.drp_in = CSRStorage(16) @@ -154,10 +154,10 @@ class SMA_PLL(Module, AutoCSR): Instance("MMCME2_ADV", p_BANDWIDTH="LOW", # lower jitter o_LOCKED=self.mmcm_locked.status, + i_RST=self.mmcm_reset.storage, p_CLKIN1_PERIOD=period, i_CLKIN1=ClockSignal("sys"), - i_RST=ResetSignal("sys"), i_CLKINSEL=1, # 1=CLKIN1 0=CLKIN2 # VCO @ 1Ghz @@ -184,4 +184,3 @@ class SMA_PLL(Module, AutoCSR): # debug output Instance("OBUFDS", i_I=self.cd_ref.clk, o_O=sma_clkin.p, o_OB=sma_clkin.n) ] - diff --git a/src/libboard_artiq/src/si549.rs b/src/libboard_artiq/src/si549.rs index 1227ff9..5c64597 100644 --- a/src/libboard_artiq/src/si549.rs +++ b/src/libboard_artiq/src/si549.rs @@ -556,6 +556,20 @@ pub mod sma_pll { use super::*; + pub struct MmcmSetting { + pub clkout0_reg1: u16, //0x08 + pub clkout0_reg2: u16, //0x09 + pub clkfbout_reg1: u16, //0x14 + pub clkfbout_reg2: u16, //0x15 + pub div_reg: u16, //0x16 + pub lock_reg1: u16, //0x18 + pub lock_reg2: u16, //0x19 + pub lock_reg3: u16, //0x1A + pub power_reg: u16, //0x28 + pub filt_reg1: u16, //0x4E + pub filt_reg2: u16, //0x4F + } + fn one_clock_cycle(timer: &mut GlobalTimer) { unsafe { csr::sma_pll::drp_clk_write(1); @@ -600,7 +614,6 @@ pub mod sma_pll { } pub fn read(timer: &mut GlobalTimer, address: u8) -> u16 { - // Based on "DRP State Machine" from XAPP888 set_addr(address); set_enable(true); // Set DADDR on the MMCM and assert DEN for one clock cycle @@ -615,7 +628,6 @@ pub mod sma_pll { } pub fn write(timer: &mut GlobalTimer, address: u8, value: u16) { - // Based on "DRP State Machine" from XAPP888 set_addr(address); set_data(value); set_write_enable(true); @@ -630,6 +642,41 @@ pub mod sma_pll { one_clock_cycle(timer); } } + + pub fn reset(rst: bool) { + unsafe { + let val = if rst { 1 } else { 0 }; + csr::sma_pll::mmcm_reset_write(val) + } + } + + pub fn setup(timer: &mut GlobalTimer, settings: MmcmSetting) -> Result<(), &'static str> { + // Based on "DRP State Machine" from XAPP888 + + // hold reset HIGH during mmcm config + reset(true); + write(timer, 0x08, settings.clkout0_reg1); + write(timer, 0x09, settings.clkout0_reg2); + write(timer, 0x14, settings.clkfbout_reg1); + write(timer, 0x15, settings.clkfbout_reg2); + write(timer, 0x16, settings.div_reg); + write(timer, 0x18, settings.lock_reg1); + write(timer, 0x19, settings.lock_reg2); + write(timer, 0x1A, settings.lock_reg3); + write(timer, 0x28, settings.power_reg); + write(timer, 0x4E, settings.filt_reg1); + write(timer, 0x4F, settings.filt_reg2); + reset(false); + + // wait for the mmcm to lock + timer.delay_us(100); + + let locked = unsafe { csr::sma_pll::mmcm_locked_read() == 1 }; + if !locked { + return Err("failed to generate 125Mhz ref clock from SMA CLKIN"); + } + Ok(()) + } } pub fn setup(timer: &mut GlobalTimer) {