From ae472bbe5208b6e1d37e4f66b6d72a65dd72ce21 Mon Sep 17 00:00:00 2001 From: Jean THOMAS Date: Mon, 8 Jun 2020 11:17:46 +0200 Subject: [PATCH] Rework DFI interface code --- gram/phy/dfi.py | 103 +++++++++-------------------------------- gram/phy/ecp5ddrphy.py | 24 ++++++---- 2 files changed, 37 insertions(+), 90 deletions(-) diff --git a/gram/phy/dfi.py b/gram/phy/dfi.py index f78bb80..867c6f1 100644 --- a/gram/phy/dfi.py +++ b/gram/phy/dfi.py @@ -1,11 +1,14 @@ # This file is Copyright (c) 2015 Sebastien Bourdeauducq -# Copyright (c) 2020 LambdaConcept +# This file is Copyright (c) 2020 LambdaConcept from nmigen import * from nmigen.hdl.rec import * -def phase_cmd_description(addressbits, bankbits, nranks): +__ALL__ = ["Interface"] + +def phase_description(addressbits, bankbits, nranks, databits): return [ + # cmd description ("address", addressbits, DIR_FANOUT), ("bank", bankbits, DIR_FANOUT), ("cas_n", 1, DIR_FANOUT), @@ -15,97 +18,37 @@ def phase_cmd_description(addressbits, bankbits, nranks): ("cke", nranks, DIR_FANOUT), ("odt", nranks, DIR_FANOUT), ("reset_n", 1, DIR_FANOUT), - ("act_n", 1, DIR_FANOUT) - ] - - -def phase_wrdata_description(databits): - return [ + ("act_n", 1, DIR_FANOUT), + # wrdata description ("wrdata", databits, DIR_FANOUT), ("wrdata_en", 1, DIR_FANOUT), - ("wrdata_mask", databits//8, DIR_FANOUT) - ] - - -def phase_rddata_description(databits): - return [ + ("wrdata_mask", databits//8, DIR_FANOUT), + # rddata description ("rddata_en", 1, DIR_FANOUT), ("rddata", databits, DIR_FANIN), - ("rddata_valid", 1, DIR_FANIN) + ("rddata_valid", 1, DIR_FANIN), ] -def phase_description(addressbits, bankbits, nranks, databits): - r = phase_cmd_description(addressbits, bankbits, nranks) - r += phase_wrdata_description(databits) - r += phase_rddata_description(databits) - return r - - -class Interface(Record): +class Interface: def __init__(self, addressbits, bankbits, nranks, databits, nphases=1): - layout = [("p"+str(i), phase_description(addressbits, bankbits, nranks, databits)) for i in range(nphases)] - Record.__init__(self, layout) - self.phases = [getattr(self, "p"+str(i)) for i in range(nphases)] - for p in self.phases: + self.phases = [] + for p in range(nphases): + p = Record(phase_description(addressbits, bankbits, nranks, databits)) + self.phases += [p] p.cas_n.reset = 1 p.cs_n.reset = (2**nranks-1) p.ras_n.reset = 1 p.we_n.reset = 1 p.act_n.reset = 1 - # Returns pairs (DFI-mandated signal name, Migen signal object) - def get_standard_names(self, m2s=True, s2m=True): - r = [] - add_suffix = len(self.phases) > 1 - for n, phase in enumerate(self.phases): - for field, size, direction in phase.layout: - if (m2s and direction == DIR_FANOUT) or (s2m and direction == DIR_FANIN): - if add_suffix: - if direction == DIR_FANOUT: - suffix = "_p" + str(n) - else: - suffix = "_w" + str(n) - else: - suffix = "" - r.append(("dfi_" + field + suffix, getattr(phase, field))) - return r - - -class Interconnect(Elaboratable): - def __init__(self, master, slave): - self._master = master - self._slave = slave - - def elaborate(self, platform): - m = Module() - m.d.comb += self._master.connect(self._slave) - return m - - -class DDR4DFIMux(Elaboratable): - def __init__(self, dfi_i, dfi_o): - self.dfi_i = dfi_i - self.dfi_o = dfi_o - - def elaborate(self, platform): - m = Module() - - dfi_i = self.dfi_i - dfi_o = self.dfi_o + def connect(self, target): + if not isinstance(target, Interface): + raise TypeError("Target must be an instance of Interface, not {!r}" + .format(target)) - for i in range(len(dfi_i.phases)): - p_i = dfi_i.phases[i] - p_o = dfi_o.phases[i] - m.d.comb += p_i.connect(p_o) - with m.If(~p_i.ras_n & p_i.cas_n & p_i.we_n): - m.d.comb += [ - p_o.act_n.eq(0), - p_o.we_n.eq(p_i.address[14]), - p_o.cas_n.eq(p_i.address[15]), - p_o.ras_n.eq(p_i.address[16]), - ] - with m.Else(): - m.d.comb += p_o.act_n.eq(1) + ret = [] + for i in range(min(len(self.phases), len(target.phases))): + ret += [self.phases[i].connect(target.phases[i])] - return m + return ret diff --git a/gram/phy/ecp5ddrphy.py b/gram/phy/ecp5ddrphy.py index b9a9576..e228f4d 100644 --- a/gram/phy/ecp5ddrphy.py +++ b/gram/phy/ecp5ddrphy.py @@ -1,5 +1,6 @@ # This file is Copyright (c) 2019 David Shah # This file is Copyright (c) 2019-2020 Florent Kermarrec +# This file is Copyright (c) 2020 LambdaConcept # License: BSD # 1:2 frequency-ratio DDR3 PHY for Lattice's ECP5 @@ -7,8 +8,6 @@ import math -# from litex.soc.interconnect.csr import * - from nmigen import * from nmigen.lib.cdc import FFSynchronizer from nmigen.utils import log2_int @@ -17,7 +16,7 @@ from lambdasoc.periph import Peripheral import gram.stream as stream from gram.common import * -from gram.phy.dfi import * +from gram.phy.dfi import Interface from gram.compat import Timeline # Lattice ECP5 DDR PHY Initialization -------------------------------------------------------------- @@ -116,22 +115,27 @@ class ECP5DDRPHY(Peripheral, Elaboratable): self.bus = self._bridge.bus self.irq = self._bridge.irq + addressbits = len(self.pads.a.o) + bankbits = len(self.pads.ba.o) + nranks = 1 if not hasattr(self.pads, "cs_n") else len(self.pads.cs_n) + databits = len(self.pads.dq.oe) + self.dfi = Interface(addressbits, bankbits, nranks, 4*databits, 4) + def elaborate(self, platform): m = Module() - memtype = "DDR3" tck = 2/(2*2*self._sys_clk_freq) + nphases = 2 + databits = len(self.pads.dq.oe) + nranks = 1 if not hasattr(self.pads, "cs_n") else len(self.pads.cs_n) addressbits = len(self.pads.a.o) bankbits = len(self.pads.ba.o) - nranks = 1 if not hasattr(self.pads, "cs_n") else len(self.pads.cs_n) - databits = len(self.pads.dq.oe) - nphases = 2 # Init ------------------------------------------------------------------------------------- m.submodules.init = DomainRenamer("init")(ECP5DDRPHYInit("sys2x")) # Parameters ------------------------------------------------------------------------------- - cl, cwl = get_cl_cw(memtype, tck) + cl, cwl = get_cl_cw("DDR3", tck) cl_sys_latency = get_sys_latency(nphases, cl) cwl_sys_latency = get_sys_latency(nphases, cwl) @@ -143,7 +147,7 @@ class ECP5DDRPHY(Peripheral, Elaboratable): wrcmdphase, wrphase = get_sys_phases(nphases, cwl_sys_latency, cwl) self.settings = PhySettings( phytype = "ECP5DDRPHY", - memtype = memtype, + memtype = "DDR3", databits = databits, dfi_databits = 4*databits, nranks = nranks, @@ -159,7 +163,7 @@ class ECP5DDRPHY(Peripheral, Elaboratable): ) # DFI Interface ---------------------------------------------------------------------------- - self.dfi = dfi = Interface(addressbits, bankbits, nranks, 4*databits, 4) + dfi = self.dfi # # # -- 2.30.2