From 0ca6ac1354ab6b0527ca1ccf5aa882d6d5ee7cec Mon Sep 17 00:00:00 2001 From: linuswck Date: Fri, 10 Jan 2025 12:38:02 +0800 Subject: [PATCH] gateware: use LTC2195 dco clk as PL only clock source --- fast-servo/linien-gateware/cores/adc.py | 129 ++---------------- fast-servo/linien-gateware/cores/dac.py | 32 ++--- .../linien-gateware/fast_servo_platform.py | 14 +- fast-servo/linien-gateware/fast_servo_soc.py | 81 +++++++---- fast-servo/pyfastservo/adc.py | 23 ---- fast-servo/pyfastservo/dac.py | 11 ++ 6 files changed, 98 insertions(+), 192 deletions(-) diff --git a/fast-servo/linien-gateware/cores/adc.py b/fast-servo/linien-gateware/cores/adc.py index bae6dff..7b3b6f8 100644 --- a/fast-servo/linien-gateware/cores/adc.py +++ b/fast-servo/linien-gateware/cores/adc.py @@ -22,93 +22,8 @@ from migen.genlib.cdc import MultiReg from misoc.interconnect.csr import AutoCSR, CSRStatus, CSRStorage from misoc.interconnect.stream import AsyncFIFO - -class CRG(Module): - def __init__(self, platform, dco_clk, dco_freq=200e6): - self.clock_domains.cd_dco = ClockDomain() - self.clock_domains.cd_dco2x = ClockDomain() - self.clock_domains.cd_dco2d = ClockDomain() - self.clock_domains.cd_dco2d_45_degree = ClockDomain() - dco_clk_p, dco_clk_n = dco_clk - - dco_clk_buf = Signal() - self.specials += Instance( - "IBUFGDS", i_I=dco_clk_p, i_IB=dco_clk_n, o_O=dco_clk_buf - ) - - # # # - clk_feedback = Signal() - clk_feedback_buf = Signal() - - clk_dco = Signal() - clk_dco2x = Signal() - clk_dco2d = Signal() - clk_dco2d_45_degree = Signal() - mmcm_ps_psdone = Signal() - - self.locked = Signal() - self.mmcm_rst = Signal() - self.ddr_clk_phase_shift_en = Signal() - self.ddr_clk_phase_incdec = Signal() - - platform.add_period_constraint(dco_clk_p, 1e9 / dco_freq) - self.specials += [ - Instance( - "MMCME2_ADV", - p_BANDWIDTH="OPTIMIZED", - p_DIVCLK_DIVIDE=1, - p_CLKFBOUT_PHASE=0.0, - p_CLKFBOUT_MULT_F=4, # VCO @ 800 MHz - p_CLKIN1_PERIOD=(1e9 / dco_freq), - p_REF_JITTER1=0.01, - p_STARTUP_WAIT="FALSE", - i_CLKIN1=dco_clk_buf, - i_PWRDWN=0, - i_RST=ResetSignal("sys") | self.mmcm_rst, - i_CLKFBIN=clk_feedback_buf, - o_CLKFBOUT=clk_feedback, - - p_CLKOUT0_USE_FINE_PS="TRUE", - p_CLKOUT0_DIVIDE_F=8, - p_CLKOUT0_PHASE=45.0, - p_CLKOUT0_DUTY_CYCLE=0.5, - o_CLKOUT0=clk_dco2d_45_degree, # 100 MHz <- dco_clk / 2 = 200 MHz / 2 - o_LOCKED=self.locked, - - p_CLKOUT1_DIVIDE=2, - p_CLKOUT1_PHASE=0.0, - p_CLKOUT1_DUTY_CYCLE=0.5, - o_CLKOUT1=clk_dco2x, # 400 MHZ <- 2 * dco_clk = 2*200 MHz - - p_CLKOUT2_DIVIDE=8, - p_CLKOUT2_PHASE=0.0, - p_CLKOUT2_DUTY_CYCLE=0.5, - o_CLKOUT2=clk_dco2d, # 100 MHz <- dco_clk / 2 = 200 MHz / 2 - - p_CLKOUT3_DIVIDE=4, - p_CLKOUT3_PHASE=0.0, - p_CLKOUT3_DUTY_CYCLE=0.5, - o_CLKOUT3=clk_dco, # 200 MHz <- dco_clk - - i_PSCLK=ClockSignal(), - i_PSEN=self.ddr_clk_phase_shift_en, - i_PSINCDEC=self.ddr_clk_phase_incdec, - o_PSDONE=mmcm_ps_psdone, - ) - ] - - self.specials += Instance("BUFG", i_I=clk_feedback, o_O=clk_feedback_buf) - self.specials += Instance("BUFG", i_I=clk_dco, o_O=self.cd_dco.clk) - self.specials += Instance("BUFG", i_I=clk_dco2d, o_O=self.cd_dco2d.clk) - self.specials += Instance("BUFG", i_I=clk_dco2d_45_degree, o_O=self.cd_dco2d_45_degree.clk) - self.specials += Instance("BUFG", i_I=clk_dco2x, o_O=self.cd_dco2x.clk) - - # Ignore dco2d to mmcm dco_clk path created by SoC's rst. - platform.add_false_path_constraints(self.cd_dco2d.clk, dco_clk_buf) - self.specials += Instance("FD", p_INIT=1, i_D=~self.locked, i_C=self.cd_dco2d.clk, o_Q=self.cd_dco2d.rst) - class ADC(Module, AutoCSR): - def __init__(self, platform, dco_freq=200e6): + def __init__(self, platform): adc_pads = platform.request("adc") afe_pads = platform.request("adc_afe") @@ -131,45 +46,27 @@ class ADC(Module, AutoCSR): ch2_shdn = Signal() self.data_out = [Signal(16, reset_less=True), Signal(16, reset_less=True)] - self.data_out_cdc = [Signal(16, reset_less=True), Signal(16, reset_less=True)] self.s_frame = Signal(4) - self.s_frame_cdc = Signal(4) - self.submodules.cdc_fifo = ClockDomainsRenamer({"write": "dco2d", "read": "sys"})(AsyncFIFO([("data", 36)], 4)) self.comb += [ - self.cdc_fifo.sink.data.eq(Cat(self.data_out_cdc[0], self.data_out_cdc[1], self.s_frame_cdc)), - self.cdc_fifo.sink.stb.eq(~ResetSignal("dco2d")), - Cat(self.data_out[0], self.data_out[1], self.s_frame).eq(self.cdc_fifo.source.data), - self.cdc_fifo.source.ack.eq(~ResetSignal("sys")), - ] - - ### - - # DCO clock coming from LTC2195 - # dco_clk = Record([("p", 1), ("n", 1)]) - dco_clk =(adc_pads.dco_p, adc_pads.dco_n) - self.comb += [ - # dco_clk.p.eq(adc_pads.dco_p), - # dco_clk.n.eq(adc_pads.dco_n), tap_delay_val.eq(self.tap_delay.storage), Cat(ch1_gain_x10, ch2_gain_x10, ch1_shdn, ch2_shdn).eq( self.afe_ctrl.storage[0:4] ), ] - self.submodules.crg = CRG(platform, dco_clk, dco_freq) - self.comb += self.afe_ctrl.storage[4].eq(self.crg.mmcm_rst) - self.comb += self.afe_ctrl.storage[5].eq(self.crg.ddr_clk_phase_shift_en) - self.comb += self.afe_ctrl.storage[6].eq(self.crg.ddr_clk_phase_incdec) + # self.comb += self.afe_ctrl.storage[4].eq(self.crg.mmcm_rst) + # self.comb += self.afe_ctrl.storage[5].eq(self.crg.ddr_clk_phase_shift_en) + # self.comb += self.afe_ctrl.storage[6].eq(self.crg.ddr_clk_phase_incdec) - self.specials += MultiReg(self.bitslip_csr.re, bitslip_re_dco_2d, "dco2d") - self.sync.dco2d += [ + self.specials += MultiReg(self.bitslip_csr.re, bitslip_re_dco_2d, "sys") + self.sync.sys += [ bitslip.eq(Mux(bitslip_re_dco_2d, self.bitslip_csr.storage, 0)) ] self.comb += [ self.frame_csr.status[0:4].eq(self.s_frame[0:4]), - self.frame_csr.status[4].eq(self.crg.locked), + # self.frame_csr.status[4].eq(self.crg.locked), self.data_ch0.status.eq(self.data_out[0]), self.data_ch1.status.eq(self.data_out[1]), ] @@ -186,10 +83,10 @@ class ADC(Module, AutoCSR): self.specials += Instance( "LTC2195", - i_rst_in=ResetSignal("dco2d"), + i_rst_in=ResetSignal("sys"), i_clk200=ClockSignal("idelay"), - i_DCO=ClockSignal("dco"), - i_DCO_2D=ClockSignal("dco2d"), + i_DCO=ClockSignal("sys_double"), + i_DCO_2D=ClockSignal("sys"), i_FR_in_p=adc_pads.frame_p, i_FR_in_n=adc_pads.frame_n, i_D0_in_p=adc_pads.data0_p, @@ -198,9 +95,9 @@ class ADC(Module, AutoCSR): i_D1_in_n=adc_pads.data1_n, i_bitslip=bitslip, i_delay_val=tap_delay_val, - o_ADC0_out=self.data_out_cdc[1], # LANES swapped on hardware - o_ADC1_out=self.data_out_cdc[0], - o_FR_out=self.s_frame_cdc, + o_ADC0_out=self.data_out[1], # LANES swapped on hardware + o_ADC1_out=self.data_out[0], + o_FR_out=self.s_frame, o_o_data_from_pins=dummy, o_idelay_rdy=dummy_idelay_rdy, ) diff --git a/fast-servo/linien-gateware/cores/dac.py b/fast-servo/linien-gateware/cores/dac.py index df4c3b8..c69606d 100644 --- a/fast-servo/linien-gateware/cores/dac.py +++ b/fast-servo/linien-gateware/cores/dac.py @@ -24,10 +24,13 @@ from misoc.interconnect.stream import AsyncFIFO class DAC(Module, AutoCSR): - def __init__(self, platform): + def __init__(self, platform, phase_shift_ctrl): dac_pads = platform.request("dac") dac_afe_pads = platform.request("dac_afe") - self.dac_ctrl = CSRStorage(3) + + phase_shift_en, phase_shift_dir = phase_shift_ctrl + + self.dac_ctrl = CSRStorage(5) self.output_value_ch0 = CSRStorage(14) self.output_value_ch1 = CSRStorage(14) @@ -40,46 +43,37 @@ class DAC(Module, AutoCSR): self.data_in = [Signal(14, reset_less=True), Signal(14, reset_less=True)] self.data_in_csr = [Signal(14, reset_less=True), Signal(14, reset_less=True)] - - self.data_in_cdc = [Signal(14, reset_less=True), Signal(14, reset_less=True)] - self.data_in_csr_cdc = [Signal(14, reset_less=True), Signal(14, reset_less=True)] - platform.add_period_constraint(dac_pads.dclkio, 10.0) - self.submodules.cdc_fifo = ClockDomainsRenamer({"write": "sys", "read": "dco2d"})(AsyncFIFO([("data", 56)], 4)) self.comb += [ self.data_in_csr[0].eq(self.output_value_ch0.storage), self.data_in_csr[1].eq(self.output_value_ch1.storage), - self.cdc_fifo.sink.data.eq(Cat(self.data_in[0], self.data_in[1], self.data_in_csr[0], self.data_in_csr[1])), - self.cdc_fifo.sink.stb.eq(~ResetSignal("sys")), - Cat(self.data_in_cdc[0], self.data_in_cdc[1], self.data_in_csr_cdc[0], self.data_in_csr_cdc[1]).eq(self.cdc_fifo.source.data), - self.cdc_fifo.source.ack.eq(~ResetSignal("dco2d")), ] self.comb += [ - Cat(manual_override, ch0_pd, ch1_pd).eq(self.dac_ctrl.storage), - dac_pads.rst.eq(ResetSignal("dco2d")), + Cat(manual_override, ch0_pd, ch1_pd, phase_shift_en, phase_shift_dir).eq(self.dac_ctrl.storage), + dac_pads.rst.eq(ResetSignal("sys")), dac_afe_pads.ch1_pd_n.eq(~ch0_pd), dac_afe_pads.ch2_pd_n.eq(~ch1_pd), output_data_ch0.eq( - Mux(manual_override, self.data_in_csr_cdc[0], self.data_in_cdc[0]) + Mux(manual_override, self.data_in_csr[0], self.data_in[0]) ), output_data_ch1.eq( - Mux(manual_override, self.data_in_csr_cdc[1], self.data_in_cdc[1]) + Mux(manual_override, self.data_in_csr[1], self.data_in[1]) ), ] self.specials += [ Instance("ODDR", - i_C=ClockSignal("dco2d"), - i_CE=~ResetSignal("dco2d"), + i_C=ClockSignal("sys"), + i_CE=~ResetSignal("sys"), i_D1=output_data_ch0[lane], # DDR CLK Rising Edge i_D2=output_data_ch1[lane], # DDR CLK Falling Edge o_Q=dac_pads.data[lane], p_DDR_CLK_EDGE="SAME_EDGE") for lane in range(14)] self.specials += Instance("ODDR", - i_C=ClockSignal("dco2d_45_degree"), - i_CE=~ResetSignal("dco2d"), + i_C=ClockSignal("sys_45_degree"), + i_CE=~ResetSignal("sys"), i_D1=0, i_D2=1, o_Q=dac_pads.dclkio, diff --git a/fast-servo/linien-gateware/fast_servo_platform.py b/fast-servo/linien-gateware/fast_servo_platform.py index b490040..0ffbe04 100644 --- a/fast-servo/linien-gateware/fast_servo_platform.py +++ b/fast-servo/linien-gateware/fast_servo_platform.py @@ -80,11 +80,13 @@ _io = [ Subsignal("data0_n", Pins("E7 B6 E3 C1"), IOStandard("LVDS_25")), Subsignal("data1_p", Pins("A2 D5 F2 D7"), IOStandard("LVDS_25")), Subsignal("data1_n", Pins("A1 C4 F1 D6"), IOStandard("LVDS_25")), - Subsignal("dco_p", Pins("B4"), IOStandard("LVDS_25")), - Subsignal("dco_n", Pins("B3"), IOStandard("LVDS_25")), Subsignal("frame_p", Pins("B2"), IOStandard("LVDS_25")), Subsignal("frame_n", Pins("B1"), IOStandard("LVDS_25")) ), + ("adc_dco_clk", 0 , + Subsignal("p", Pins("B4"), IOStandard("LVDS_25")), + Subsignal("n", Pins("B3"), IOStandard("LVDS_25")), + ), # ADC AFE ("adc_afe", 0, @@ -315,21 +317,23 @@ ps7_config_board_preset = { } class Platform(XilinxPlatform): - default_clk_name = "clk100" - default_clk_period = 10.0 + default_clk_name = "adc_dco_clk_p" + default_clk_period = 5.0 def __init__(self): XilinxPlatform.__init__(self, "xc7z015-clg485-1", _io, _connector_gpio + _connector_eem, toolchain="vivado") ps7_config = ps7_config_board_preset self.ps7_config = ps7_config + self.toolchain.with_phys_opt = True + verilog_sources = os.listdir(verilog_dir) self.add_sources(verilog_dir, *verilog_sources) def do_finalize(self, fragment): try: XilinxPlatform.do_finalize(self, fragment) - self.add_period_constraint(self.lookup_request(self.default_clk_name, loose=True), self.default_clk_period) + self.add_period_constraint(self.lookup_request(self.default_clk_name), self.default_clk_period) except ValueError: pass except ConstraintError: diff --git a/fast-servo/linien-gateware/fast_servo_soc.py b/fast-servo/linien-gateware/fast_servo_soc.py index 257fc8b..8af27bd 100644 --- a/fast-servo/linien-gateware/fast_servo_soc.py +++ b/fast-servo/linien-gateware/fast_servo_soc.py @@ -31,72 +31,91 @@ from fast_servo.gateware.cores.spi_phy import SpiInterface, SpiPhy class CRG(Module): - def __init__(self, platform): + def __init__(self, platform, dco_freq=200e6): self.ps_rst = Signal() self.locked = Signal() + + dco_clk = platform.request("adc_dco_clk") + dco_clk_buf = Signal() + self.specials += Instance( + "IBUFGDS", i_I=dco_clk.p, i_IB=dco_clk.n, o_O=dco_clk_buf + ) + self.clock_domains.cd_sys = ClockDomain() + self.clock_domains.cd_sys_45_degree = ClockDomain() self.clock_domains.cd_sys_double = ClockDomain() self.clock_domains.cd_idelay = ClockDomain() - # # # - - # Clk. - clk100 = platform.request("clk100") - platform.add_period_constraint(clk100, 10.0) - self.clkin = clk100 - clk100_buf = Signal() - self.specials += Instance("IBUFG", i_I=clk100, o_O=clk100_buf) - clk_feedback = Signal() clk_feedback_buf = Signal() clk_sys = Signal() + clk_sys_45_degree = Signal() clk_sys_double = Signal() clk_idelay = Signal() + self.ddr_clk_phase_shift_en = Signal() + self.ddr_clk_phase_incdec = Signal() + self.mmcm_ps_psdone = Signal() + si5340_nlol = platform.request("si5340_nlol") si5340_nlol_buf = Signal() self.specials += Instance("IBUF", i_I=si5340_nlol, o_O=si5340_nlol_buf) + platform.add_period_constraint(dco_clk.p, 1e9 / dco_freq) self.specials += [ Instance( - "PLLE2_BASE", + "MMCME2_ADV", p_BANDWIDTH="OPTIMIZED", p_DIVCLK_DIVIDE=1, p_CLKFBOUT_PHASE=0.0, - p_CLKFBOUT_MULT=10, - p_CLKIN1_PERIOD=10.0, - p_REF_JITTER1=0.01, + p_CLKFBOUT_MULT_F=4, # VCO @ 800 MHz + p_CLKIN1_PERIOD=(1e9 / dco_freq), + p_REF_JITTER1=0.06, # From LTC2195 Datasheet p_STARTUP_WAIT="FALSE", - i_CLKIN1=clk100_buf, + i_CLKIN1=dco_clk_buf, i_PWRDWN=0, i_RST=self.ps_rst | ~si5340_nlol_buf, i_CLKFBIN=clk_feedback_buf, o_CLKFBOUT=clk_feedback, - p_CLKOUT0_DIVIDE=10, - p_CLKOUT0_PHASE=0.0, + + p_CLKOUT0_USE_FINE_PS="True", + p_CLKOUT0_DIVIDE_F=8, + p_CLKOUT0_PHASE=45.0, p_CLKOUT0_DUTY_CYCLE=0.5, - o_CLKOUT0=clk_sys, # 100 MHz <- sys_clk - p_CLKOUT1_DIVIDE=5, + o_CLKOUT0=clk_sys_45_degree, # 800MHz / 8 -> 100MHz + o_LOCKED=self.locked, + + p_CLKOUT1_DIVIDE=8, p_CLKOUT1_PHASE=0.0, p_CLKOUT1_DUTY_CYCLE=0.5, - o_CLKOUT1=clk_idelay, # 200 MHZ <- 2 * sys_clk = 2*100 MHz - p_CLKOUT2_DIVIDE=5, + o_CLKOUT1=clk_sys, # 800MHz / 8 -> 100MHz + + p_CLKOUT2_DIVIDE=4, p_CLKOUT2_PHASE=0.0, p_CLKOUT2_DUTY_CYCLE=0.5, - o_CLKOUT2=clk_sys_double, # 200 MHZ <- 2 * sys_clk_double = 2*100 MHz - o_LOCKED=self.locked, + o_CLKOUT2=clk_sys_double, # 800MHz / 4 -> 200MHz + + p_CLKOUT3_DIVIDE=4, + p_CLKOUT3_PHASE=0.0, + p_CLKOUT3_DUTY_CYCLE=0.5, + o_CLKOUT3=clk_idelay, # 800MHz / 4 -> 200MHz + + i_PSCLK=ClockSignal(), + i_PSEN=self.ddr_clk_phase_shift_en, + i_PSINCDEC=self.ddr_clk_phase_incdec, + o_PSDONE=self.mmcm_ps_psdone, ) ] self.specials += Instance("BUFG", i_I=clk_feedback, o_O=clk_feedback_buf) self.specials += Instance("BUFG", i_I=clk_sys, o_O=self.cd_sys.clk) - self.specials += Instance("BUFG", i_I=clk_idelay, o_O=self.cd_idelay.clk) + self.specials += Instance("BUFG", i_I=clk_sys_45_degree, o_O=self.cd_sys_45_degree.clk) self.specials += Instance("BUFG", i_I=clk_sys_double, o_O=self.cd_sys_double.clk) - - + self.specials += Instance("BUFG", i_I=clk_idelay, o_O=self.cd_idelay.clk) + # Ignore sys_clk to pll clkin path created by SoC's rst. - platform.add_false_path_constraints(self.cd_sys.clk, self.clkin) + platform.add_false_path_constraints(self.cd_sys.clk, dco_clk) self.specials += Instance("FD", p_INIT=1, i_D=~self.locked, i_C=self.cd_sys.clk, o_Q=self.cd_sys.rst) @@ -126,6 +145,10 @@ class BaseSoC(PS7, AutoCSR): self.submodules.crg = CRG(platform) + # self.comb += self.afe_ctrl.storage[4].eq(self.crg.mmcm_rst) + # self.comb += self.afe_ctrl.storage[5].eq(self.crg.ddr_clk_phase_shift_en) + # self.comb += self.afe_ctrl.storage[6].eq(self.crg.ddr_clk_phase_incdec) + # # # AXI to system bus bridge self.submodules.axi2sys = Axi2Sys() self.submodules.sys2csr = Sys2CSR() @@ -156,10 +179,10 @@ class BaseSoC(PS7, AutoCSR): # self.add_main_adc(platform) self.submodules.adc = ADC(platform) self.csr_devices.append("adc") - platform.add_false_path_constraints(self.crg.cd_sys.clk, self.adc.crg.cd_dco2d.clk) + # platform.add_false_path_constraints(self.crg.cd_sys.clk, self.adc.crg.cd_dco2d.clk) # self.add_main_dac(platform) - self.submodules.dac = DAC(platform) + self.submodules.dac = DAC(platform, [self.crg.ddr_clk_phase_shift_en, self.crg.ddr_clk_phase_incdec,]) self.csr_devices.append("dac") # DEBUG diff --git a/fast-servo/pyfastservo/adc.py b/fast-servo/pyfastservo/adc.py index 7072cad..9f07024 100644 --- a/fast-servo/pyfastservo/adc.py +++ b/fast-servo/pyfastservo/adc.py @@ -85,26 +85,6 @@ def perform_bitslip(): print(f"No bitslip required; Current frame: 0x{current_frame:02x}") return -def mmcm_rst(): - curr_cfg = read_from_memory(ADC_AFE_CTRL_ADDR, 1)[0] & 0x0F - write_to_memory(ADC_AFE_CTRL_ADDR, 0x10 | curr_cfg) # Reset MMCM - write_to_memory(ADC_AFE_CTRL_ADDR, 0x00 | curr_cfg) # Release MMCM Reset - while not(read_frame() & 0x10): - print(f"Waiting for MMCM to lock") - time.sleep(0.001) - -def inc_ddr_clk_phase(): - curr_cfg = read_from_memory(ADC_AFE_CTRL_ADDR, 1)[0] & 0x1F - write_to_memory(ADC_AFE_CTRL_ADDR, 0x40 | curr_cfg) # Set MMCM Phase Shift to be INC - write_to_memory(ADC_AFE_CTRL_ADDR, 0x60 | curr_cfg) # Assert MMCM Phase Shift EN High - write_to_memory(ADC_AFE_CTRL_ADDR, curr_cfg) # Deassert MMCM Phase Shift EN High - -def dec_ddr_clk_phase(): - curr_cfg = read_from_memory(ADC_AFE_CTRL_ADDR, 1)[0] & 0x1F - write_to_memory(ADC_AFE_CTRL_ADDR, 0x00 | curr_cfg) # Set MMCM Phase Shift to be DEC - write_to_memory(ADC_AFE_CTRL_ADDR, 0x20 | curr_cfg) # Assert MMCM Phase Shift EN High - write_to_memory(ADC_AFE_CTRL_ADDR, curr_cfg) # Deassert MMCM Phase Shift EN High - def find_edge(): prev_frame = read_frame() for tap_delay in range(32): @@ -190,9 +170,6 @@ def configure_ltc2195(): 0x03: (test_pattern & 0xFF00) >> 8, 0x04: test_pattern & 0xFF }) - - # ADC software reset put its PLL to sleep momentarily. Thus, MMCM needs to be reset as well. - mmcm_rst() # Performing Word Align perform_bitslip() diff --git a/fast-servo/pyfastservo/dac.py b/fast-servo/pyfastservo/dac.py index 745781c..ff641ca 100644 --- a/fast-servo/pyfastservo/dac.py +++ b/fast-servo/pyfastservo/dac.py @@ -37,6 +37,17 @@ MAIN_DAC_BUS = 2 MAIN_DAC_DEVICE = 0 DAC_VERSION = 0x0A +def inc_ddr_clk_phase(): + curr_cfg = read_from_memory(CTRL_ADDR, 1)[0] & 0x07 + write_to_memory(CTRL_ADDR, 0x10 | curr_cfg) # Set MMCM Phase Shift to be INC + write_to_memory(CTRL_ADDR, 0x18 | curr_cfg) # Assert MMCM Phase Shift EN High + write_to_memory(CTRL_ADDR, curr_cfg) # Deassert MMCM Phase Shift EN High + +def dec_ddr_clk_phase(): + curr_cfg = read_from_memory(CTRL_ADDR, 1)[0] & 0x07 + write_to_memory(CTRL_ADDR, 0x00 | curr_cfg) # Set MMCM Phase Shift to be DEC + write_to_memory(CTRL_ADDR, 0x08 | curr_cfg) # Assert MMCM Phase Shift EN High + write_to_memory(CTRL_ADDR, curr_cfg) # Deassert MMCM Phase Shift EN High def spi_write(spi, address, value): spi.xfer2([address, value])