Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: m-labs/misoc
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 4acab79987c6
Choose a base ref
...
head repository: m-labs/misoc
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: de87d65f6847
Choose a head ref
  • 5 commits
  • 6 files changed
  • 1 contributor

Commits on Aug 22, 2015

  1. README: small update

    enjoy-digital committed Aug 22, 2015
    Copy the full SHA
    b8f3fd5 View commit details
  2. sdram/phy/s6ddrphy: rename S6DDRPHY to S6HalfRateDDRPHY and use ORed …

    …wrdata_en/rddata_en (the controller already manages that)
    enjoy-digital committed Aug 22, 2015
    Copy the full SHA
    158fbe4 View commit details
  3. 3
    Copy the full SHA
    8bb30a8 View commit details
  4. sdram/phy/s6ddrphy: add S6QuarterRateDDRPHY to run DDR3 at higher fre…

    …quencies.
    
    Built on top of S6HalfRateDDRPHY, exposes a 4 phases DFI interface to the controller with a 2x slower clock.
    Validated on the Numato Lab opsis board (50MHz sys_clk/ DDR400), should also work on the Novena laptop (same DDR3 module).
    enjoy-digital committed Aug 22, 2015
    Copy the full SHA
    50e857e View commit details
  5. Copy the full SHA
    de87d65 View commit details
Showing with 167 additions and 22 deletions.
  1. +3 −1 README
  2. +1 −1 misoclib/com/liteeth/phy/__init__.py
  3. +40 −0 misoclib/mem/sdram/module.py
  4. +113 −10 misoclib/mem/sdram/phy/s6ddrphy.py
  5. +5 −5 targets/mlabs_video.py
  6. +5 −5 targets/pipistrello.py
4 changes: 3 additions & 1 deletion README
Original file line number Diff line number Diff line change
@@ -28,7 +28,8 @@
* Design new peripherals using Migen and benefit from automatic CSR maps
and logic, etc.
* Possibility to encapsulate legacy Verilog/VHDL code.
* Complex FPGA cores that can be used integrated in MiSoC or in standalone:
* Complex FPGA cores that can be used integrated in MiSoC or standalone:
- LitePcie: a small footprint and configuragle PCIe core
- LiteEth: a small footprint and configurable Ethernet core
- LiteSATA: a small footprint and configurable SATA core
- LiteScope: a small footprint and configurable logic analyzer core
@@ -40,6 +41,7 @@ MiSoC comes with built-in support for the following boards:
* Pipistrello, a simple board with USB and HDMI [XC6SLX45]
* De0 Nano, a simple and low-cost development board [CYCLONEIV]
* KC705, a Kintex-7 devboard from Xilinx [XC7K325T]
* Versa, a low-cost Lattice development board [ECP3-35]
MiSoC is portable and support for other boards can easily be added as external
modules.

2 changes: 1 addition & 1 deletion misoclib/com/liteeth/phy/__init__.py
Original file line number Diff line number Diff line change
@@ -2,7 +2,7 @@


def LiteEthPHY(clock_pads, pads, **kwargs):
clk_freq = kwargs.pop("clk_freq")
clk_freq = None if "clk_freq" not in kwargs else kwargs.pop("clk_freq")
# Autodetect PHY
if hasattr(pads, "source_stb"):
# This is a simulation PHY
40 changes: 40 additions & 0 deletions misoclib/mem/sdram/module.py
Original file line number Diff line number Diff line change
@@ -165,6 +165,26 @@ def __init__(self, clk_freq):
self.timing_settings)


class P3R1GE4JGF(SDRAMModule):
geom_settings = {
"nbanks": 8,
"nrows": 8192,
"ncols": 1024
}
timing_settings = {
"tRP": 12.5,
"tRCD": 12.5,
"tWR": 15,
"tWTR": 3,
"tREFI": 7800,
"tRFC": 127.5,
}

def __init__(self, clk_freq):
SDRAMModule.__init__(self, clk_freq, "DDR2", self.geom_settings,
self.timing_settings)


# DDR3
class MT8JTF12864(SDRAMModule):
geom_settings = {
@@ -183,3 +203,23 @@ class MT8JTF12864(SDRAMModule):
def __init__(self, clk_freq):
SDRAMModule.__init__(self, clk_freq, "DDR3", self.geom_settings,
self.timing_settings)


class MT41J128M16(SDRAMModule):
geom_settings = {
"nbanks": 8,
"nrows": 16384,
"ncols": 1024,
}
timing_settings = {
"tRP": 15,
"tRCD": 15,
"tWR": 15,
"tWTR": 3,
"tREFI": 64*1000*1000/16384,
"tRFC": 260,
}

def __init__(self, clk_freq):
SDRAMModule.__init__(self, clk_freq, "DDR3", self.geom_settings,
self.timing_settings)
123 changes: 113 additions & 10 deletions misoclib/mem/sdram/phy/s6ddrphy.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# 1:2 frequency-ratio DDR / LPDDR / DDR2 PHY for Spartan-6
# 1:2 and 1:4 frequency-ratio DDR / LPDDR / DDR2 / DDR3 PHYs for Spartan-6
#
# Assert dfi_wrdata_en and present the data
# on dfi_wrdata_mask/dfi_wrdata in the same
@@ -23,10 +23,10 @@
from misoclib.mem import sdram


class S6DDRPHY(Module):
class S6HalfRateDDRPHY(Module):
def __init__(self, pads, module, rd_bitslip, wr_bitslip, dqs_ddr_alignment):
if module.memtype not in ["DDR", "LPDDR", "DDR2", "DDR3"]:
raise NotImplementedError("S6DDRPHY only supports DDR, LPDDR, DDR2 and DDR3")
raise NotImplementedError("S6HalfRateDDRPHY only supports DDR, LPDDR, DDR2 and DDR3")
addressbits = flen(pads.a)
bankbits = flen(pads.ba)
databits = flen(pads.dq)
@@ -358,30 +358,133 @@ def __init__(self, pads, module, rd_bitslip, wr_bitslip, dqs_ddr_alignment):
#
# DQ/DQS/DM control
#

# write
wrdata_en = Signal()
self.comb += wrdata_en.eq(optree("|", [d_dfi[p].wrdata_en for p in range(nphases)]))

if module.memtype == "DDR3":
r_drive_dq = Signal(self.settings.cwl-1)
sd_sdram_half += r_drive_dq.eq(Cat(d_dfi[self.settings.wrphase].wrdata_en, r_drive_dq))
sd_sdram_half += r_drive_dq.eq(Cat(wrdata_en, r_drive_dq))
self.comb += drive_dq.eq(r_drive_dq[self.settings.cwl-2])
else:
self.comb += drive_dq.eq(d_dfi[self.settings.wrphase].wrdata_en)
self.comb += drive_dq.eq(wrdata_en)

d_dfi_wrdata_en = Signal()
sd_sys += d_dfi_wrdata_en.eq(d_dfi[self.settings.wrphase].wrdata_en)
wrdata_en_d = Signal()
sd_sys += wrdata_en_d.eq(wrdata_en)

r_dfi_wrdata_en = Signal(max(self.settings.cwl, self.settings.cl))
sd_sdram_half += r_dfi_wrdata_en.eq(Cat(d_dfi_wrdata_en, r_dfi_wrdata_en))
sd_sdram_half += r_dfi_wrdata_en.eq(Cat(wrdata_en_d, r_dfi_wrdata_en))

if module.memtype == "DDR3":
self.comb += drive_dqs.eq(r_dfi_wrdata_en[self.settings.cwl-1])
else:
self.comb += drive_dqs.eq(r_dfi_wrdata_en[1])

# read
rddata_en = Signal()
self.comb += rddata_en.eq(optree("|", [d_dfi[p].rddata_en for p in range(nphases)]))

rddata_sr = Signal(self.settings.read_latency)
sd_sys += rddata_sr.eq(Cat(rddata_sr[1:self.settings.read_latency],
d_dfi[self.settings.rdphase].rddata_en))
sd_sys += rddata_sr.eq(Cat(rddata_sr[1:self.settings.read_latency], rddata_en))

for n, phase in enumerate(self.dfi.phases):
self.comb += [
phase.rddata.eq(d_dfi[n].rddata),
phase.rddata_valid.eq(rddata_sr[0]),
]


class S6QuarterRateDDRPHY(Module):
def __init__(self, pads, module, rd_bitslip, wr_bitslip, dqs_ddr_alignment):
if module.memtype not in ["DDR3"]:
raise NotImplementedError("S6QuarterRateDDRPHY only supports DDR3")
half_rate_phy = S6HalfRateDDRPHY(pads, module, rd_bitslip, wr_bitslip, dqs_ddr_alignment)
self.submodules += RenameClockDomains(half_rate_phy, {"sys" : "sys2x"})

addressbits = flen(pads.a)
bankbits = flen(pads.ba)
databits = flen(pads.dq)
nphases = 4

self.settings = sdram.PhySettings(
memtype="DDR3",
dfi_databits=2*databits,
nphases=nphases,
rdphase=0,
wrphase=1,
rdcmdphase=1,
wrcmdphase=0,
cl=5,
cwl=6,
read_latency=6//2+1,
write_latency=2//2
)

self.module = module

self.dfi = Interface(addressbits, bankbits, 2*databits, nphases)
self.clk8x_wr_strb = half_rate_phy.clk4x_wr_strb
self.clk8x_rd_strb = half_rate_phy.clk4x_rd_strb

# sys_clk : system clk, used for dfi interface
# sys2x_clk : half rate sys clk
sd_sys = getattr(self.sync, "sys")
sd_sys2x = getattr(self.sync, "sys2x")

# select active sys2x phase
# sys_clk ----____----____
# phase_sel 0 1 0 1
phase_sel = Signal()
phase_sys2x = Signal.like(phase_sel)
phase_sys = Signal.like(phase_sys2x)

sd_sys += phase_sys.eq(phase_sys2x)

sd_sys2x += [
If(phase_sys2x == phase_sys,
phase_sel.eq(0),
).Else(
phase_sel.eq(~phase_sel)
),
phase_sys2x.eq(~phase_sel)
]

# DFI adaptation

# Commands and writes
dfi_leave_out = set(["rddata", "rddata_valid", "wrdata_en"])
self.comb += [
If(~phase_sel,
Record.connect(self.dfi.phases[0], half_rate_phy.dfi.phases[0], leave_out=dfi_leave_out),
Record.connect(self.dfi.phases[1], half_rate_phy.dfi.phases[1], leave_out=dfi_leave_out),
).Else(
Record.connect(self.dfi.phases[2], half_rate_phy.dfi.phases[0], leave_out=dfi_leave_out),
Record.connect(self.dfi.phases[3], half_rate_phy.dfi.phases[1], leave_out=dfi_leave_out),
),
]
wr_data_en = self.dfi.phases[self.settings.wrphase].wrdata_en & ~phase_sel
wr_data_en_d = Signal()
sd_sys2x += wr_data_en_d.eq(wr_data_en)
self.comb += half_rate_phy.dfi.phases[half_rate_phy.settings.wrphase].wrdata_en.eq(wr_data_en | wr_data_en_d)

# Reads
rddata = Array(Signal(2*databits) for i in range(2))
rddata_valid = Signal(2)

for i in range(2):
sd_sys2x += [
rddata_valid[i].eq(half_rate_phy.dfi.phases[i].rddata_valid),
rddata[i].eq(half_rate_phy.dfi.phases[i].rddata)
]

sd_sys += [
self.dfi.phases[0].rddata.eq(rddata[0]),
self.dfi.phases[0].rddata_valid.eq(rddata_valid[0]),
self.dfi.phases[1].rddata.eq(rddata[1]),
self.dfi.phases[1].rddata_valid.eq(rddata_valid[1]),
self.dfi.phases[2].rddata.eq(half_rate_phy.dfi.phases[0].rddata),
self.dfi.phases[2].rddata_valid.eq(half_rate_phy.dfi.phases[0].rddata_valid),
self.dfi.phases[3].rddata.eq(half_rate_phy.dfi.phases[1].rddata),
self.dfi.phases[3].rddata_valid.eq(half_rate_phy.dfi.phases[1].rddata_valid)
]
10 changes: 5 additions & 5 deletions targets/mlabs_video.py
Original file line number Diff line number Diff line change
@@ -82,11 +82,11 @@ def __init__(self, platform, sdram_controller_settings=LASMIconSettings(), **kwa
self.submodules.crg = _MXCRG(_MXClockPads(platform), self.clk_freq)

if not self.integrated_main_ram_size:
self.submodules.ddrphy = s6ddrphy.S6DDRPHY(platform.request("ddram"),
MT46V32M16(self.clk_freq),
rd_bitslip=0,
wr_bitslip=3,
dqs_ddr_alignment="C1")
self.submodules.ddrphy = s6ddrphy.S6HalfRateDDRPHY(platform.request("ddram"),
MT46V32M16(self.clk_freq),
rd_bitslip=0,
wr_bitslip=3,
dqs_ddr_alignment="C1")
self.register_sdram_phy(self.ddrphy)
self.comb += [
self.ddrphy.clk4x_wr_strb.eq(self.crg.clk4x_wr_strb),
10 changes: 5 additions & 5 deletions targets/pipistrello.py
Original file line number Diff line number Diff line change
@@ -108,11 +108,11 @@ def __init__(self, platform, sdram_controller_settings=LASMIconSettings(),
self.submodules.crg = _CRG(platform, clk_freq)

if not self.integrated_main_ram_size:
self.submodules.ddrphy = s6ddrphy.S6DDRPHY(platform.request("ddram"),
MT46H32M16(self.clk_freq),
rd_bitslip=1,
wr_bitslip=3,
dqs_ddr_alignment="C1")
self.submodules.ddrphy = s6ddrphy.S6HalfRateDDRPHY(platform.request("ddram"),
MT46H32M16(self.clk_freq),
rd_bitslip=1,
wr_bitslip=3,
dqs_ddr_alignment="C1")
self.comb += [
self.ddrphy.clk4x_wr_strb.eq(self.crg.clk4x_wr_strb),
self.ddrphy.clk4x_rd_strb.eq(self.crg.clk4x_rd_strb),