From 367231322da02105203e5a46cdb977cf7f1eed0d Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Fri, 13 Aug 2021 14:42:34 +0800 Subject: [PATCH 1/3] litedram_gen: Add pll_locked to ECP5 Signed-off-by: Matt Johnston --- litedram/gen.py | 1 + 1 file changed, 1 insertion(+) diff --git a/litedram/gen.py b/litedram/gen.py index dc0225e..372a9aa 100755 --- a/litedram/gen.py +++ b/litedram/gen.py @@ -336,6 +336,7 @@ class LiteDRAMECP5DDRPHYCRG(Module): AsyncResetSynchronizer(self.cd_sys, ~pll.locked | self.reset), AsyncResetSynchronizer(self.cd_sys2x, ~pll.locked | self.reset), ] + self.comb += platform.request("pll_locked").eq(pll.locked) class LiteDRAMS7DDRPHYCRG(Module): def __init__(self, platform, core_config): From 06ca898c698548ba17117ee6b5701e4ac2121bc8 Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Fri, 20 Aug 2021 11:24:49 +0800 Subject: [PATCH 2/3] litedram_gen: Add ECLKBRIDGECS for ECP5 clock Signed-off-by: Matt Johnston --- litedram/gen.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/litedram/gen.py b/litedram/gen.py index 372a9aa..06fb4da 100755 --- a/litedram/gen.py +++ b/litedram/gen.py @@ -317,14 +317,19 @@ class LiteDRAMECP5DDRPHYCRG(Module): self.sync.por += If(~por_done, por_count.eq(por_count - 1)) # PLL. + sys2x_clk_ecsout = Signal() self.submodules.pll = pll = ECP5PLL() self.comb += pll.reset.eq(~por_done | rst | self.rst) pll.register_clkin(clk, core_config["input_clk_freq"]) pll.create_clkout(self.cd_sys2x_i, 2*core_config["sys_clk_freq"]) pll.create_clkout(self.cd_init, core_config["init_clk_freq"]) self.specials += [ + Instance("ECLKBRIDGECS", + i_CLK0 = self.cd_sys2x_i.clk, + i_SEL = 0, + o_ECSOUT = sys2x_clk_ecsout), Instance("ECLKSYNCB", - i_ECLKI = self.cd_sys2x_i.clk, + i_ECLKI = sys2x_clk_ecsout, i_STOP = self.stop, o_ECLKO = self.cd_sys2x.clk), Instance("CLKDIVF", From 7560435d078327ba9e56e6469ed7bf6aeaf85a31 Mon Sep 17 00:00:00 2001 From: Matt Johnston Date: Wed, 17 Nov 2021 15:01:36 +0800 Subject: [PATCH 3/3] phy/ecp5ddrphy: Bring back dm_remapping This allows swapping UDM/LDM pins. Was removed in https://github.com/enjoy-digital/litedram/commit/af9abd6ec9bef7182ec00fa9d21c32c9faba9f87 phy/ecp5ddrphy: remove dm_remapping introduce for VexRiscv-SMP on OrangeCrab... But is still useful for native port uses of litedram Add dm_swap parameter to gen.py Signed-off-by: Matt Johnston --- litedram/gen.py | 7 ++++++- litedram/phy/ecp5ddrphy.py | 7 +++++-- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/litedram/gen.py b/litedram/gen.py index 06fb4da..d1fa927 100755 --- a/litedram/gen.py +++ b/litedram/gen.py @@ -582,10 +582,15 @@ class LiteDRAMCore(SoCCore): # ECP5DDRPHY. elif core_config["sdram_phy"] in [litedram_phys.ECP5DDRPHY]: assert core_config["memtype"] in ["DDR3"] + kwargs = {} + if core_config.get("dm_swap", False): + kwargs['dm_remapping'] = {0:1, 1:0} + self.submodules.ddrphy = sdram_phy = core_config["sdram_phy"]( pads = platform.request("ddram"), sys_clk_freq = sys_clk_freq, - cmd_delay = core_config.get("cmd_delay", 0)) + cmd_delay = core_config.get("cmd_delay", 0), + **kwargs) self.ddrphy.settings.add_electrical_settings(**electrical_settings_kwargs) self.comb += crg.stop.eq(self.ddrphy.init.stop) self.comb += crg.reset.eq(self.ddrphy.init.reset) diff --git a/litedram/phy/ecp5ddrphy.py b/litedram/phy/ecp5ddrphy.py index 4f1010e..2aa49ca 100644 --- a/litedram/phy/ecp5ddrphy.py +++ b/litedram/phy/ecp5ddrphy.py @@ -117,7 +117,8 @@ class ECP5DDRPHY(Module, AutoCSR): cl = None, cwl = None, cmd_delay = 0, - clk_polarity = 0): + clk_polarity = 0, + dm_remapping = None): assert isinstance(cmd_delay, int) and cmd_delay < 128 pads = PHYPadsCombiner(pads) memtype = "DDR3" @@ -127,6 +128,8 @@ class ECP5DDRPHY(Module, AutoCSR): nranks = 1 if not hasattr(pads, "cs_n") else len(pads.cs_n) databits = len(pads.dq) nphases = 2 + if not dm_remapping: + dm_remapping = {} assert databits%8 == 0 # Init ------------------------------------------------------------------------------------- @@ -327,7 +330,7 @@ class ECP5DDRPHY(Module, AutoCSR): dm_o_data_d = Signal(8) dm_o_data_muxed = Signal(4) for n in range(8): - self.comb += dm_o_data[n].eq(dfi.phases[n//4].wrdata_mask[n%4*databits//8 + i]) + self.comb += dm_o_data[n].eq(dfi.phases[n//4].wrdata_mask[n%4*databits//8+dm_remapping.get(i, i)]) self.sync += dm_o_data_d.eq(dm_o_data) dm_bl8_cases = {} dm_bl8_cases[0] = dm_o_data_muxed.eq(dm_o_data[:4])