From: Luke Kenneth Casson Leighton Date: Fri, 15 Apr 2022 15:48:43 +0000 (+0100) Subject: reorg of the ECP5 Clock-Reset to be able to add X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=51a16fc59b02e9902ea6d096d921091f1b190a3b;p=ls2.git reorg of the ECP5 Clock-Reset to be able to add a 2nd clock (DRAM) --- diff --git a/src/ecp5_crg.py b/src/ecp5_crg.py index 72c1af5..bd91df1 100644 --- a/src/ecp5_crg.py +++ b/src/ecp5_crg.py @@ -177,7 +177,7 @@ class ECP5CRG(Elaboratable): self.dram_clk_freq = dram_clk_freq self.pod_bits = pod_bits - def phase2_domain(self, m, pll, name, freq): + def phase2_domain(self, m, pll, name, freq, esyncb): """creates a domain that can be used with xdr=4 platform resources. this requires creating a domain at *twice* the frequency, @@ -187,29 +187,35 @@ class ECP5CRG(Elaboratable): pads.a.o_fclk.eq(ClockSignal("dramsync2x")), """ + # create names + cd2x = "%s2x" % name + cd2x_ub = cd2x+"_unbuf" + cd = name # Generating sync2x from extclk - cd_2x = ClockDomain("%s2x" % name, local=False) - cd_2x_unbuf = ClockDomain("%s2x_unbuf" % name, - local=False, reset_less=True) + cd_2x = ClockDomain(cd2x, local=False) + cd_2x_unbuf = ClockDomain(cd2x_ub, 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)) + pll.create_clkout(ClockSignal(cd2x_ub), 2*freq) + if esyncb: + m.submodules["%s_eclksyncb" % cd] = Instance("ECLKSYNCB", + i_ECLKI = ClockSignal(cd2x_ub), + i_STOP = 0, + o_ECLKO = ClockSignal(cd2x)) + else: + m.d.comb += ClockSignal(cd2x).eq(ClockSignal(cd2x_ub)) # no esyncb m.domains += cd_2x_unbuf m.domains += cd_2x m.domains += cd_ # # Generating sync from sync2x - m.submodules += Instance("CLKDIVF", + m.submodules["%s_clkdivf" % cd] = Instance("CLKDIVF", p_DIV="2.0", i_ALIGNWD=0, - i_CLKI=ClockSignal("%s2x" % name), + i_CLKI=ClockSignal(cd2x), i_RST=0, - o_CDIVX=ClockSignal("%s" % name)) + o_CDIVX=ClockSignal(cd)) def elaborate(self, platform): m = Module() @@ -229,18 +235,16 @@ class ECP5CRG(Elaboratable): gsr0 = Signal() gsr1 = Signal() - m.submodules += [ - Instance("FD1S3AX", p_GSR="DISABLED", + m.submodules.gsr0 = Instance("FD1S3AX", p_GSR="DISABLED", i_CK=ClockSignal("rawclk"), i_D=~reset, - o_Q=gsr0), - Instance("FD1S3AX", p_GSR="DISABLED", + o_Q=gsr0) + m.submodules.gsr1 = Instance("FD1S3AX", p_GSR="DISABLED", i_CK=ClockSignal("rawclk"), i_D=gsr0, - o_Q=gsr1), - Instance("SGSR", i_CLK=ClockSignal("rawclk"), - i_GSR=gsr1), - ] + o_Q=gsr1) + m.submodules.sgsr = Instance("SGSR", i_CLK=ClockSignal("rawclk"), + i_GSR=gsr1) # PLL m.submodules.pll = pll = PLL(ClockSignal("rawclk"), reset=~reset) @@ -259,19 +263,28 @@ class ECP5CRG(Elaboratable): # create PLL input clock from platform default frequency pll.set_clkin_freq(platform.default_clk_frequency) - # create 25 mhz "init" clock, straight (no 2x phase stuff) - cd_init = ClockDomain("init", local=False) - pll.create_clkout(ClockSignal("init"), 25e6) - m.domains += cd_init - m.d.comb += ResetSignal("init").eq(reset_ok) - - # Generating sync2x and sync from extclk, which is *only* how - # xdr=4 can be requested on the sync domain - self.phase2_domain(m, pll, "sync", self.sys_clk_freq) + # single or double main sync clock domain. double needs a 2nd PLL + # to match up with the CLKESYNCB, one per quadrant inside the ECP5 + if self.dram_clk_freq is not None: + m.domains += ClockDomain("sync_unbuf", local=False, reset_less=True) + m.domains += ClockDomain("sync", local=False) + pll.create_clkout(ClockSignal("sync_unbuf"), self.sys_clk_freq) + m.d.comb += ClockSignal("sync").eq(ClockSignal("sync_unbuf")) + else: + # Generating sync2x and sync from extclk, which is *only* how + # xdr=4 can be requested on the sync domain. also do not request + # an edge-clock-stop + self.phase2_domain(m, pll, "sync", self.sys_clk_freq, True) + m.d.comb += ResetSignal("sync2x").eq(reset_ok) m.d.comb += ResetSignal("sync").eq(reset_ok) + # DRAM clock: if not requested set to sync, otherwise create with + # a CLKESYNCB (which is set to no-stop at the moment) if self.dram_clk_freq is not None: - self.phase2_domain(m, pll, "dramsync", self.dram_clk_freq) + self.phase2_domain(m, pll, "dramsync", self.dram_clk_freq, True) + # resets for the dram domains + m.d.comb += ResetSignal("dramsync2x").eq(reset_ok) + m.d.comb += ResetSignal("dramsync").eq(reset_ok) else: # alias dramsync and dramsync2x to sync and sync2x cd_dramsync = ClockDomain("dramsync", local=False) @@ -282,9 +295,11 @@ class ECP5CRG(Elaboratable): 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) + # create 25 mhz "init" clock, straight (no 2x phase stuff) + cd_init = ClockDomain("init", local=False) + pll.create_clkout(ClockSignal("init"), 25e6) + m.domains += cd_init + m.d.comb += ResetSignal("init").eq(reset_ok) return m