self.sys_clk_freq = sys_clk_freq
self.pod_bits = pod_bits
+ def do_2x_phase_clock_create(self, m, pll, name, freq):
+ """creates a domain that can be used with xdr=4 platform resources.
+
+ this requires creating a domain at *twice* the frequency,
+ then halving it. the doubled-frequency can then go to the
+ eclk parts of a 4-phase IOPad:
+ pads.a.o_clk.eq(ClockSignal("dramsync")),
+ pads.a.o_fclk.eq(ClockSignal("dramsync2x")),
+ """
+
+ # Generating sync2x from extclk
+ cd_2x = ClockDomain("%s2x" % name, local=False)
+ cd_2x_unbuf = ClockDomain("%s2x_unbuf" % name,
+ local=False, reset_less=True)
+ cd_ = ClockDomain("%s" % name, local=False)
+
+ # create PLL clocks
+ pll.create_clkout(ClockSignal("%s2x_unbuf" % name), 2*freq)
+ m.submodules += Instance("ECLKSYNCB",
+ i_ECLKI = ClockSignal("%s2x_unbuf" % name),
+ i_STOP = 0,
+ o_ECLKO = ClockSignal("%s2x" % name))
+ m.domains += cd_2x_unbuf
+ m.domains += cd_2x
+ m.domains += cd_
+
+ # # Generating sync from sync2x
+ m.submodules += Instance("CLKDIVF",
+ p_DIV="2.0",
+ i_ALIGNWD=0,
+ i_CLKI=ClockSignal("%s2x" % name),
+ i_RST=0,
+ o_CDIVX=ClockSignal("%s" % name))
+
def elaborate(self, platform):
m = Module()
m.d.rawclk += podcnt.eq(podcnt-1)
m.d.rawclk += pod_done.eq(podcnt == 0)
- # Generating sync2x (200Mhz) and init (25Mhz) from extclk
- cd_sync2x = ClockDomain("sync2x", local=False)
- cd_sync2x_unbuf = ClockDomain("sync2x_unbuf",
- local=False, reset_less=True)
- cd_init = ClockDomain("init", local=False)
- cd_sync = ClockDomain("sync", local=False)
- cd_dramsync = ClockDomain("dramsync", local=False)
+ # and reset which only drops when the PLL is done and pod completes
+ reset_ok = Signal(reset_less=True)
+ m.d.comb += reset_ok.eq(~pll.locked|~pod_done)
- # create PLL clocks
+ # create PLL input clock from platform default frequency
pll.set_clkin_freq(platform.default_clk_frequency)
- pll.create_clkout(ClockSignal("sync2x_unbuf"), 2*self.sys_clk_freq)
+
+ # create 25 mhz "init" clock, straight (no 2x phase stuff)
+ cd_init = ClockDomain("init", local=False)
pll.create_clkout(ClockSignal("init"), 25e6)
- m.submodules += Instance("ECLKSYNCB",
- i_ECLKI = ClockSignal("sync2x_unbuf"),
- i_STOP = 0,
- o_ECLKO = ClockSignal("sync2x"))
- m.domains += cd_sync2x_unbuf
- m.domains += cd_sync2x
m.domains += cd_init
- m.domains += cd_sync
- m.domains += cd_dramsync
- reset_ok = Signal(reset_less=True)
- m.d.comb += reset_ok.eq(~pll.locked|~pod_done)
m.d.comb += ResetSignal("init").eq(reset_ok)
- m.d.comb += ResetSignal("sync").eq(reset_ok)
- m.d.comb += ResetSignal("dramsync").eq(reset_ok)
- # # Generating sync (100Mhz) from sync2x
-
- m.submodules += Instance("CLKDIVF",
- p_DIV="2.0",
- i_ALIGNWD=0,
- i_CLKI=ClockSignal("sync2x"),
- i_RST=0,
- o_CDIVX=ClockSignal("sync"))
+ # Generating sync2x and sync from extclk, which is *only* how
+ # xdr=4 can be requested on the sync domain
+ self.do_2x_phase_clock_create(m, pll, "sync", self.sys_clk_freq)
+ m.d.comb += ResetSignal("sync").eq(reset_ok)
- # temporarily set dram sync clock exactly equal to main sync
+ # temporarily set dram sync clock exactly equal to main sync,
+ # which turns out to be a dog's dinner botch-job, because
+ # GRAM's ECP5PHY uses dramsync for the pads.o_clk but
+ # sync2x for the pads.o_fclk. sigh.
+ # TODO: this to be replaced with
+ # self.do_2x_phase_clock_create(m, pll, "dramsync", self.dram_clk_freq)
+ # and then a suitable DomainRenamer for *both* dramsync *and*
+ # dramsync2x applied
+ cd_dramsync = ClockDomain("dramsync", local=False)
+ m.domains += cd_dramsync
m.d.comb += ClockSignal("dramsync").eq(ClockSignal("sync"))
+ m.d.comb += ResetSignal("dramsync").eq(reset_ok)
return m