From 1adceb8276b9e425623f11c436eb388849a25775 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Thu, 17 Apr 2014 19:38:13 +0200 Subject: [PATCH] sdramphy: move and clean up s6ddrphy, add generic SDRAM PHY --- make.py | 9 +- misoclib/sdramphy/gensdrphy.py | 97 +++++++++++++++++++ .../{s6ddrphy => sdramphy}/initsequence.py | 0 .../__init__.py => sdramphy/s6ddrphy.py} | 14 +-- targets/mlabs_video.py | 3 +- 5 files changed, 108 insertions(+), 15 deletions(-) create mode 100644 misoclib/sdramphy/gensdrphy.py rename misoclib/{s6ddrphy => sdramphy}/initsequence.py (100%) rename misoclib/{s6ddrphy/__init__.py => sdramphy/s6ddrphy.py} (96%) diff --git a/make.py b/make.py index c245e0c8..c8ef3db3 100755 --- a/make.py +++ b/make.py @@ -7,7 +7,7 @@ from migen.util.misc import autotype from migen.fhdl import simplify from misoclib.gensoc import cpuif -from misoclib.s6ddrphy import initsequence +from misoclib.sdramphy import initsequence import programmer def _get_args(): @@ -151,9 +151,10 @@ Subtarget: {} write_to_file("software/include/generated/mem.h", boilerplate + mem_header) csr_header = cpuif.get_csr_header(soc.csr_base, soc.csrbankarray, soc.interrupt_map) write_to_file("software/include/generated/csr.h", boilerplate + csr_header) - if hasattr(soc, "ddrphy"): - sdram_phy_header = initsequence.get_sdram_phy_header(soc.ddrphy) - write_to_file("software/include/generated/sdram_phy.h", boilerplate + sdram_phy_header) + for sdram_phy in ["sdrphy", "ddrphy"]: + if hasattr(soc, sdram_phy): + sdram_phy_header = initsequence.get_sdram_phy_header(getattr(soc, sdram_phy)) + write_to_file("software/include/generated/sdram_phy.h", boilerplate + sdram_phy_header) if actions["build-csr-csv"]: csr_csv = cpuif.get_csr_csv(soc.csr_base, soc.csrbankarray) diff --git a/misoclib/sdramphy/gensdrphy.py b/misoclib/sdramphy/gensdrphy.py new file mode 100644 index 00000000..01ccc195 --- /dev/null +++ b/misoclib/sdramphy/gensdrphy.py @@ -0,0 +1,97 @@ +# +# 1:1 frequency-ratio Generic SDR PHY +# +# The GENSDRPHY is validated on CycloneIV (Altera) but since it does +# not use vendor-dependent code, it can also be used on other architectures. +# +# The PHY needs 2 Clock domains: +# - sys_clk : The System Clock domain +# - sys_clk_ps : The System Clock domain with its phase shifted +# (-0.75ns on C4@100MHz) +# +# Assert dfi_wrdata_en and present the data +# on dfi_wrdata_mask/dfi_wrdata in the same +# cycle as the write command. +# +# Assert dfi_rddata_en in the same cycle as the read +# command. The data will come back on dfi_rddata +# 4 cycles later, along with the assertion of +# dfi_rddata_valid. +# +# This PHY only supports CAS Latency 2. +# + +from migen.fhdl.std import * +from migen.bus.dfi import * +from migen.genlib.record import * +from migen.fhdl.specials import * + +from misoclib import lasmicon + +class GENSDRPHY(Module): + def __init__(self, pads, memtype, nphases, cl): + if memtype not in ["SDR"]: + raise NotImplementedError("GENSDRPHY only supports SDR") + if cl != 2: + raise NotImplementedError("GENSDRPHY only supports CAS LATENCY 2") + if nphases > 1: + raise NotImplementedError("GENSDRPHY only supports Full Rate (nphases=1)") + + a = flen(pads.a) + ba = flen(pads.ba) + d = flen(pads.dq) + + self.phy_settings = lasmicon.PhySettings( + memtype=memtype, + dfi_d=d, + nphases=nphases, + rdphase=0, + wrphase=0, + rdcmdphase=0, + wrcmdphase=0, + cl=cl, + read_latency=4, + write_latency=0 + ) + + self.dfi = Interface(a, ba, nphases*d, nphases) + + ### + + # + # Command/address + # + self.sync += [ + pads.a.eq(self.dfi.p0.address), + pads.ba.eq(self.dfi.p0.bank), + pads.cs_n.eq(self.dfi.p0.cs_n), + pads.cke.eq(self.dfi.p0.cke), + pads.cas_n.eq(self.dfi.p0.cas_n), + pads.ras_n.eq(self.dfi.p0.ras_n), + pads.we_n.eq(self.dfi.p0.we_n) + ] + if hasattr(pads, "cs_n"): + self.sync += pads.cs_n.eq(self.dfi.p0.cs_n), + + # + # DQ/DQS/DM data + # + sd_dq_out = Signal(d) + drive_dq = Signal() + self.sync += sd_dq_out.eq(self.dfi.p0.wrdata), + self.specials += Tristate(pads.dq, sd_dq_out, drive_dq) + self.comb += pads.dqm.eq(0) + sd_dq_in_ps = Signal(d) + self.sync.sys_ps += sd_dq_in_ps.eq(pads.dq) + self.sync += self.dfi.p0.rddata.eq(sd_dq_in_ps) + + # + # DQ/DM control + # + d_dfi_wrdata_en = Signal() + self.sync += d_dfi_wrdata_en.eq(self.dfi.p0.wrdata_en) + self.comb += drive_dq.eq(d_dfi_wrdata_en) + + rddata_sr = Signal(4) + self.comb += self.dfi.p0.rddata_valid.eq(rddata_sr[0]) + self.sync += rddata_sr.eq(Cat(self.dfi.p0.rddata_en, rddata_sr[1:])) diff --git a/misoclib/s6ddrphy/initsequence.py b/misoclib/sdramphy/initsequence.py similarity index 100% rename from misoclib/s6ddrphy/initsequence.py rename to misoclib/sdramphy/initsequence.py diff --git a/misoclib/s6ddrphy/__init__.py b/misoclib/sdramphy/s6ddrphy.py similarity index 96% rename from misoclib/s6ddrphy/__init__.py rename to misoclib/sdramphy/s6ddrphy.py index 044c0afc..7211ca00 100644 --- a/misoclib/s6ddrphy/__init__.py +++ b/misoclib/sdramphy/s6ddrphy.py @@ -1,5 +1,4 @@ -# 1:2 frequency-ratio DDR / LPDDR / DDR2 PHY for -# Spartan-6 +# 1:2 frequency-ratio DDR / LPDDR / DDR2 PHY for Spartan-6 # # Assert dfi_wrdata_en and present the data # on dfi_wrdata_mask/dfi_wrdata in the same @@ -15,11 +14,6 @@ # Write commands must be sent on phase 1. # -# Todo: -# - use CSR for bitslip? -# - add configurable CAS Latency -# - automatically determines wrphase / rdphase / latencies - from migen.fhdl.std import * from migen.bus.dfi import * from migen.genlib.record import * @@ -32,6 +26,8 @@ class S6DDRPHY(Module): raise NotImplementedError("S6DDRPHY only supports DDR, LPDDR and DDR2") if cl != 3: raise NotImplementedError("S6DDRPHY only supports CAS LATENCY 3") + if nphases != 2: + raise NotImplementedError("S6DDRPHY only supports Half Rate (nphases=2)") a = flen(pads.a) ba = flen(pads.ba) d = flen(pads.dq) @@ -73,9 +69,7 @@ class S6DDRPHY(Module): # select active phase # sys_clk ----____----____ - # phase_sel(nphases=1) 0 0 - # phase_sel(nphases=2) 0 1 0 1 - # phase_sel(nphases=4) 0 1 2 3 0 1 2 3 + # phase_sel(nphases=2) 0 1 0 1 Half Rate phase_sel = Signal(log2_int(nphases)) sys_clk_d = Signal() diff --git a/targets/mlabs_video.py b/targets/mlabs_video.py index 06b9f4c9..3c179c26 100644 --- a/targets/mlabs_video.py +++ b/targets/mlabs_video.py @@ -4,7 +4,8 @@ from fractions import Fraction from migen.fhdl.std import * from mibuild.generic_platform import ConstraintError -from misoclib import lasmicon, mxcrg, norflash16, s6ddrphy, minimac3, framebuffer, dvisampler, gpio +from misoclib import lasmicon, mxcrg, norflash16, minimac3, framebuffer, dvisampler, gpio +from misoclib.sdramphy import s6ddrphy from misoclib.gensoc import SDRAMSoC class _MXClockPads: -- 2.30.2