gateware: use LTC2195 dco clk as PL only clock source
This commit is contained in:
parent
d9d44fa9e8
commit
0ca6ac1354
@ -22,93 +22,8 @@ from migen.genlib.cdc import MultiReg
|
|||||||
from misoc.interconnect.csr import AutoCSR, CSRStatus, CSRStorage
|
from misoc.interconnect.csr import AutoCSR, CSRStatus, CSRStorage
|
||||||
from misoc.interconnect.stream import AsyncFIFO
|
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):
|
class ADC(Module, AutoCSR):
|
||||||
def __init__(self, platform, dco_freq=200e6):
|
def __init__(self, platform):
|
||||||
adc_pads = platform.request("adc")
|
adc_pads = platform.request("adc")
|
||||||
afe_pads = platform.request("adc_afe")
|
afe_pads = platform.request("adc_afe")
|
||||||
|
|
||||||
@ -131,45 +46,27 @@ class ADC(Module, AutoCSR):
|
|||||||
ch2_shdn = Signal()
|
ch2_shdn = Signal()
|
||||||
|
|
||||||
self.data_out = [Signal(16, reset_less=True), Signal(16, reset_less=True)]
|
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 = Signal(4)
|
||||||
self.s_frame_cdc = Signal(4)
|
|
||||||
|
|
||||||
self.submodules.cdc_fifo = ClockDomainsRenamer({"write": "dco2d", "read": "sys"})(AsyncFIFO([("data", 36)], 4))
|
|
||||||
self.comb += [
|
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),
|
tap_delay_val.eq(self.tap_delay.storage),
|
||||||
Cat(ch1_gain_x10, ch2_gain_x10, ch1_shdn, ch2_shdn).eq(
|
Cat(ch1_gain_x10, ch2_gain_x10, ch1_shdn, ch2_shdn).eq(
|
||||||
self.afe_ctrl.storage[0:4]
|
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[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[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[6].eq(self.crg.ddr_clk_phase_incdec)
|
|
||||||
|
|
||||||
self.specials += MultiReg(self.bitslip_csr.re, bitslip_re_dco_2d, "dco2d")
|
self.specials += MultiReg(self.bitslip_csr.re, bitslip_re_dco_2d, "sys")
|
||||||
self.sync.dco2d += [
|
self.sync.sys += [
|
||||||
bitslip.eq(Mux(bitslip_re_dco_2d, self.bitslip_csr.storage, 0))
|
bitslip.eq(Mux(bitslip_re_dco_2d, self.bitslip_csr.storage, 0))
|
||||||
]
|
]
|
||||||
|
|
||||||
self.comb += [
|
self.comb += [
|
||||||
self.frame_csr.status[0:4].eq(self.s_frame[0:4]),
|
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_ch0.status.eq(self.data_out[0]),
|
||||||
self.data_ch1.status.eq(self.data_out[1]),
|
self.data_ch1.status.eq(self.data_out[1]),
|
||||||
]
|
]
|
||||||
@ -186,10 +83,10 @@ class ADC(Module, AutoCSR):
|
|||||||
|
|
||||||
self.specials += Instance(
|
self.specials += Instance(
|
||||||
"LTC2195",
|
"LTC2195",
|
||||||
i_rst_in=ResetSignal("dco2d"),
|
i_rst_in=ResetSignal("sys"),
|
||||||
i_clk200=ClockSignal("idelay"),
|
i_clk200=ClockSignal("idelay"),
|
||||||
i_DCO=ClockSignal("dco"),
|
i_DCO=ClockSignal("sys_double"),
|
||||||
i_DCO_2D=ClockSignal("dco2d"),
|
i_DCO_2D=ClockSignal("sys"),
|
||||||
i_FR_in_p=adc_pads.frame_p,
|
i_FR_in_p=adc_pads.frame_p,
|
||||||
i_FR_in_n=adc_pads.frame_n,
|
i_FR_in_n=adc_pads.frame_n,
|
||||||
i_D0_in_p=adc_pads.data0_p,
|
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_D1_in_n=adc_pads.data1_n,
|
||||||
i_bitslip=bitslip,
|
i_bitslip=bitslip,
|
||||||
i_delay_val=tap_delay_val,
|
i_delay_val=tap_delay_val,
|
||||||
o_ADC0_out=self.data_out_cdc[1], # LANES swapped on hardware
|
o_ADC0_out=self.data_out[1], # LANES swapped on hardware
|
||||||
o_ADC1_out=self.data_out_cdc[0],
|
o_ADC1_out=self.data_out[0],
|
||||||
o_FR_out=self.s_frame_cdc,
|
o_FR_out=self.s_frame,
|
||||||
o_o_data_from_pins=dummy,
|
o_o_data_from_pins=dummy,
|
||||||
o_idelay_rdy=dummy_idelay_rdy,
|
o_idelay_rdy=dummy_idelay_rdy,
|
||||||
)
|
)
|
||||||
|
@ -24,10 +24,13 @@ from misoc.interconnect.stream import AsyncFIFO
|
|||||||
|
|
||||||
|
|
||||||
class DAC(Module, AutoCSR):
|
class DAC(Module, AutoCSR):
|
||||||
def __init__(self, platform):
|
def __init__(self, platform, phase_shift_ctrl):
|
||||||
dac_pads = platform.request("dac")
|
dac_pads = platform.request("dac")
|
||||||
dac_afe_pads = platform.request("dac_afe")
|
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_ch0 = CSRStorage(14)
|
||||||
self.output_value_ch1 = CSRStorage(14)
|
self.output_value_ch1 = CSRStorage(14)
|
||||||
|
|
||||||
@ -41,45 +44,36 @@ class DAC(Module, AutoCSR):
|
|||||||
self.data_in = [Signal(14, reset_less=True), Signal(14, reset_less=True)]
|
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_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.comb += [
|
||||||
self.data_in_csr[0].eq(self.output_value_ch0.storage),
|
self.data_in_csr[0].eq(self.output_value_ch0.storage),
|
||||||
self.data_in_csr[1].eq(self.output_value_ch1.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 += [
|
self.comb += [
|
||||||
Cat(manual_override, ch0_pd, ch1_pd).eq(self.dac_ctrl.storage),
|
Cat(manual_override, ch0_pd, ch1_pd, phase_shift_en, phase_shift_dir).eq(self.dac_ctrl.storage),
|
||||||
dac_pads.rst.eq(ResetSignal("dco2d")),
|
dac_pads.rst.eq(ResetSignal("sys")),
|
||||||
dac_afe_pads.ch1_pd_n.eq(~ch0_pd),
|
dac_afe_pads.ch1_pd_n.eq(~ch0_pd),
|
||||||
dac_afe_pads.ch2_pd_n.eq(~ch1_pd),
|
dac_afe_pads.ch2_pd_n.eq(~ch1_pd),
|
||||||
output_data_ch0.eq(
|
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(
|
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 += [
|
self.specials += [
|
||||||
Instance("ODDR",
|
Instance("ODDR",
|
||||||
i_C=ClockSignal("dco2d"),
|
i_C=ClockSignal("sys"),
|
||||||
i_CE=~ResetSignal("dco2d"),
|
i_CE=~ResetSignal("sys"),
|
||||||
i_D1=output_data_ch0[lane], # DDR CLK Rising Edge
|
i_D1=output_data_ch0[lane], # DDR CLK Rising Edge
|
||||||
i_D2=output_data_ch1[lane], # DDR CLK Falling Edge
|
i_D2=output_data_ch1[lane], # DDR CLK Falling Edge
|
||||||
o_Q=dac_pads.data[lane],
|
o_Q=dac_pads.data[lane],
|
||||||
p_DDR_CLK_EDGE="SAME_EDGE")
|
p_DDR_CLK_EDGE="SAME_EDGE")
|
||||||
for lane in range(14)]
|
for lane in range(14)]
|
||||||
self.specials += Instance("ODDR",
|
self.specials += Instance("ODDR",
|
||||||
i_C=ClockSignal("dco2d_45_degree"),
|
i_C=ClockSignal("sys_45_degree"),
|
||||||
i_CE=~ResetSignal("dco2d"),
|
i_CE=~ResetSignal("sys"),
|
||||||
i_D1=0,
|
i_D1=0,
|
||||||
i_D2=1,
|
i_D2=1,
|
||||||
o_Q=dac_pads.dclkio,
|
o_Q=dac_pads.dclkio,
|
||||||
|
@ -80,11 +80,13 @@ _io = [
|
|||||||
Subsignal("data0_n", Pins("E7 B6 E3 C1"), IOStandard("LVDS_25")),
|
Subsignal("data0_n", Pins("E7 B6 E3 C1"), IOStandard("LVDS_25")),
|
||||||
Subsignal("data1_p", Pins("A2 D5 F2 D7"), 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("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_p", Pins("B2"), IOStandard("LVDS_25")),
|
||||||
Subsignal("frame_n", Pins("B1"), 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
|
||||||
("adc_afe", 0,
|
("adc_afe", 0,
|
||||||
@ -315,21 +317,23 @@ ps7_config_board_preset = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class Platform(XilinxPlatform):
|
class Platform(XilinxPlatform):
|
||||||
default_clk_name = "clk100"
|
default_clk_name = "adc_dco_clk_p"
|
||||||
default_clk_period = 10.0
|
default_clk_period = 5.0
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
XilinxPlatform.__init__(self, "xc7z015-clg485-1", _io, _connector_gpio + _connector_eem, toolchain="vivado")
|
XilinxPlatform.__init__(self, "xc7z015-clg485-1", _io, _connector_gpio + _connector_eem, toolchain="vivado")
|
||||||
ps7_config = ps7_config_board_preset
|
ps7_config = ps7_config_board_preset
|
||||||
self.ps7_config = ps7_config
|
self.ps7_config = ps7_config
|
||||||
|
|
||||||
|
self.toolchain.with_phys_opt = True
|
||||||
|
|
||||||
verilog_sources = os.listdir(verilog_dir)
|
verilog_sources = os.listdir(verilog_dir)
|
||||||
self.add_sources(verilog_dir, *verilog_sources)
|
self.add_sources(verilog_dir, *verilog_sources)
|
||||||
|
|
||||||
def do_finalize(self, fragment):
|
def do_finalize(self, fragment):
|
||||||
try:
|
try:
|
||||||
XilinxPlatform.do_finalize(self, fragment)
|
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:
|
except ValueError:
|
||||||
pass
|
pass
|
||||||
except ConstraintError:
|
except ConstraintError:
|
||||||
|
@ -31,72 +31,91 @@ from fast_servo.gateware.cores.spi_phy import SpiInterface, SpiPhy
|
|||||||
|
|
||||||
|
|
||||||
class CRG(Module):
|
class CRG(Module):
|
||||||
def __init__(self, platform):
|
def __init__(self, platform, dco_freq=200e6):
|
||||||
self.ps_rst = Signal()
|
self.ps_rst = Signal()
|
||||||
self.locked = 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 = ClockDomain()
|
||||||
|
self.clock_domains.cd_sys_45_degree = ClockDomain()
|
||||||
self.clock_domains.cd_sys_double = ClockDomain()
|
self.clock_domains.cd_sys_double = ClockDomain()
|
||||||
self.clock_domains.cd_idelay = 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 = Signal()
|
||||||
clk_feedback_buf = Signal()
|
clk_feedback_buf = Signal()
|
||||||
|
|
||||||
clk_sys = Signal()
|
clk_sys = Signal()
|
||||||
|
clk_sys_45_degree = Signal()
|
||||||
clk_sys_double = Signal()
|
clk_sys_double = Signal()
|
||||||
clk_idelay = 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 = platform.request("si5340_nlol")
|
||||||
si5340_nlol_buf = Signal()
|
si5340_nlol_buf = Signal()
|
||||||
self.specials += Instance("IBUF", i_I=si5340_nlol, o_O=si5340_nlol_buf)
|
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 += [
|
self.specials += [
|
||||||
Instance(
|
Instance(
|
||||||
"PLLE2_BASE",
|
"MMCME2_ADV",
|
||||||
p_BANDWIDTH="OPTIMIZED",
|
p_BANDWIDTH="OPTIMIZED",
|
||||||
p_DIVCLK_DIVIDE=1,
|
p_DIVCLK_DIVIDE=1,
|
||||||
p_CLKFBOUT_PHASE=0.0,
|
p_CLKFBOUT_PHASE=0.0,
|
||||||
p_CLKFBOUT_MULT=10,
|
p_CLKFBOUT_MULT_F=4, # VCO @ 800 MHz
|
||||||
p_CLKIN1_PERIOD=10.0,
|
p_CLKIN1_PERIOD=(1e9 / dco_freq),
|
||||||
p_REF_JITTER1=0.01,
|
p_REF_JITTER1=0.06, # From LTC2195 Datasheet
|
||||||
p_STARTUP_WAIT="FALSE",
|
p_STARTUP_WAIT="FALSE",
|
||||||
i_CLKIN1=clk100_buf,
|
i_CLKIN1=dco_clk_buf,
|
||||||
i_PWRDWN=0,
|
i_PWRDWN=0,
|
||||||
i_RST=self.ps_rst | ~si5340_nlol_buf,
|
i_RST=self.ps_rst | ~si5340_nlol_buf,
|
||||||
i_CLKFBIN=clk_feedback_buf,
|
i_CLKFBIN=clk_feedback_buf,
|
||||||
o_CLKFBOUT=clk_feedback,
|
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,
|
p_CLKOUT0_DUTY_CYCLE=0.5,
|
||||||
o_CLKOUT0=clk_sys, # 100 MHz <- sys_clk
|
o_CLKOUT0=clk_sys_45_degree, # 800MHz / 8 -> 100MHz
|
||||||
p_CLKOUT1_DIVIDE=5,
|
o_LOCKED=self.locked,
|
||||||
|
|
||||||
|
p_CLKOUT1_DIVIDE=8,
|
||||||
p_CLKOUT1_PHASE=0.0,
|
p_CLKOUT1_PHASE=0.0,
|
||||||
p_CLKOUT1_DUTY_CYCLE=0.5,
|
p_CLKOUT1_DUTY_CYCLE=0.5,
|
||||||
o_CLKOUT1=clk_idelay, # 200 MHZ <- 2 * sys_clk = 2*100 MHz
|
o_CLKOUT1=clk_sys, # 800MHz / 8 -> 100MHz
|
||||||
p_CLKOUT2_DIVIDE=5,
|
|
||||||
|
p_CLKOUT2_DIVIDE=4,
|
||||||
p_CLKOUT2_PHASE=0.0,
|
p_CLKOUT2_PHASE=0.0,
|
||||||
p_CLKOUT2_DUTY_CYCLE=0.5,
|
p_CLKOUT2_DUTY_CYCLE=0.5,
|
||||||
o_CLKOUT2=clk_sys_double, # 200 MHZ <- 2 * sys_clk_double = 2*100 MHz
|
o_CLKOUT2=clk_sys_double, # 800MHz / 4 -> 200MHz
|
||||||
o_LOCKED=self.locked,
|
|
||||||
|
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_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_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_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.
|
# 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)
|
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.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
|
# # # AXI to system bus bridge
|
||||||
self.submodules.axi2sys = Axi2Sys()
|
self.submodules.axi2sys = Axi2Sys()
|
||||||
self.submodules.sys2csr = Sys2CSR()
|
self.submodules.sys2csr = Sys2CSR()
|
||||||
@ -156,10 +179,10 @@ class BaseSoC(PS7, AutoCSR):
|
|||||||
# self.add_main_adc(platform)
|
# self.add_main_adc(platform)
|
||||||
self.submodules.adc = ADC(platform)
|
self.submodules.adc = ADC(platform)
|
||||||
self.csr_devices.append("adc")
|
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.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")
|
self.csr_devices.append("dac")
|
||||||
|
|
||||||
# DEBUG
|
# DEBUG
|
||||||
|
@ -85,26 +85,6 @@ def perform_bitslip():
|
|||||||
print(f"No bitslip required; Current frame: 0x{current_frame:02x}")
|
print(f"No bitslip required; Current frame: 0x{current_frame:02x}")
|
||||||
return
|
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():
|
def find_edge():
|
||||||
prev_frame = read_frame()
|
prev_frame = read_frame()
|
||||||
for tap_delay in range(32):
|
for tap_delay in range(32):
|
||||||
@ -191,9 +171,6 @@ def configure_ltc2195():
|
|||||||
0x04: test_pattern & 0xFF
|
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
|
# Performing Word Align
|
||||||
perform_bitslip()
|
perform_bitslip()
|
||||||
find_edge()
|
find_edge()
|
||||||
|
@ -37,6 +37,17 @@ MAIN_DAC_BUS = 2
|
|||||||
MAIN_DAC_DEVICE = 0
|
MAIN_DAC_DEVICE = 0
|
||||||
DAC_VERSION = 0x0A
|
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):
|
def spi_write(spi, address, value):
|
||||||
spi.xfer2([address, value])
|
spi.xfer2([address, value])
|
||||||
|
Loading…
Reference in New Issue
Block a user