class ECP5CRG(Elaboratable):
- def __init__(self, sys_clk_freq=100e6, pod_bits=25):
+ def __init__(self, sys_clk_freq=100e6, dram_clk_freq=None, pod_bits=25):
+ """when dram_clk_freq=None, a dramsync domain is still created
+ but it is an alias of sync domain. likewise the 2x
+ """
self.sys_clk_freq = sys_clk_freq
+ self.dram_clk_freq = dram_clk_freq
self.pod_bits = pod_bits
- def do_2x_phase_clock_create(self, m, pll, name, freq):
+ def phase2_domain(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,
# 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)
+ self.phase2_domain(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,
- # 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)
-
- # and a dram 2x sigh
- cd_dramsync2x = ClockDomain("dramsync2x", local=False)
- m.domains += cd_dramsync2x
- m.d.comb += ClockSignal("dramsync2x").eq(ClockSignal("sync2x"))
+ if self.dram_clk_freq is not None:
+ self.phase2_domain(m, pll, "dramsync", self.dram_clk_freq)
+ else:
+ # alias dramsync and dramsync2x to sync and sync2x
+ cd_dramsync = ClockDomain("dramsync", local=False)
+ m.domains += cd_dramsync
+ m.d.comb += ClockSignal("dramsync").eq(ClockSignal("sync"))
+ # and a dram 2x sigh
+ cd_dramsync2x = ClockDomain("dramsync2x", local=False)
+ m.domains += cd_dramsync2x
+ m.d.comb += ClockSignal("dramsync2x").eq(ClockSignal("sync2x"))
+
+ # resets for the dram domains
m.d.comb += ResetSignal("dramsync2x").eq(reset_ok)
+ m.d.comb += ResetSignal("dramsync").eq(reset_ok)
return m
if ddr_pins is not None: # or fpga == 'sim':
ddrmodule = dram_cls(clk_freq, "1:2") # match DDR3 ASIC P/N
- #drs = lambda x: x
# remap both the sync domain (wherever it occurs) and
# the sync2x domain. technically this should NOT be done.
# it's a bit of a mess. ok: this should be done only
drs = DomainRenamer({"sync": "dramsync",
"sync2x": "dramsync2x"})
+ # HOWEVER, when the ASyncBridge is deployed, the two domains
+ # must NOT be renamed, instead this used:
+ #drs = lambda x: x
+ # and then the ASyncBridge takes care of it.
+ # but, back in ecp5_crg.py,
+
if fpga == 'sim':
self.ddrphy = FakePHY(module=ddrmodule,
settings=sim_ddr3_settings(clk_freq),