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: 257706517ee5
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: e6de4b1bf988
Choose a head ref
  • 2 commits
  • 3 files changed
  • 1 contributor

Commits on Mar 26, 2015

  1. software/bios/sdram: select the type of data we want to generate for …

    …memtest with TEST_RANDOM_DATA (debugging hardware is easier with a simple counter)
    enjoy-digital committed Mar 26, 2015
    2
    Copy the full SHA
    e79a716 View commit details
  2. 2
    Copy the full SHA
    e6de4b1 View commit details
Showing with 217 additions and 8 deletions.
  1. +199 −0 misoclib/mem/sdram/phy/simphy.py
  2. +17 −8 software/bios/sdram.c
  3. +1 −0 software/bios/sdram.h
199 changes: 199 additions & 0 deletions misoclib/mem/sdram/phy/simphy.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
# This file is Copyright (c) 2015 Florent Kermarrec <florent@enjoy-digital.fr>
# License: BSD

# SDRAM simulation PHY at DFI level
# Status:
# - tested against software memtest with SDR with Verilator.
# TODO:
# - expose phy_settings to user
# - test with DDR, LPDDR, DDR2 and DDR3
# - add $display support to Migen and manage timing violations?

from migen.fhdl.std import *
from migen.fhdl.specials import *
from misoclib.mem.sdram.phy.dfi import *
from misoclib.mem import sdram

class Bank(Module):
def __init__(self, data_width, nrows, ncols):
self.activate = Signal()
self.activate_row = Signal(max=nrows)
self.precharge = Signal()

self.write = Signal()
self.write_col = Signal(max=ncols)
self.write_data = Signal(data_width)
self.write_mask = Signal(data_width//8)

self.read = Signal()
self.read_col = Signal(max=ncols)
self.read_data = Signal(data_width)

###
active = Signal()
row = Signal(max=nrows)

self.sync += \
If(self.precharge,
active.eq(0),
).Elif(self.activate,
active.eq(1),
row.eq(self.activate_row)
)

self.specials.mem = mem = Memory(data_width, nrows*ncols)
self.specials.write_port = write_port = mem.get_port(write_capable=True, we_granularity=8)
self.specials.read_port = read_port = mem.get_port(async_read=True)
self.comb += [
If(active,
write_port.adr.eq(row*ncols | self.write_col),
write_port.dat_w.eq(self.write_data),
write_port.we.eq(Replicate(self.write, data_width//8) & ~self.write_mask),
If(self.read,
read_port.adr.eq(row*ncols | self.read_col),
self.read_data.eq(read_port.dat_r)
)
)
]

class DFIPhase(Module):
def __init__(self, dfi, n):
phase = getattr(dfi, "p"+str(n))

self.bank = phase.bank
self.address = phase.address

self.wrdata = phase.wrdata
self.wrdata_mask = phase.wrdata_mask

self.rddata = phase.rddata
self.rddata_valid = phase.rddata_valid

self.activate = Signal()
self.precharge = Signal()
self.write = Signal()
self.read = Signal()

###
self.comb += [
If(~phase.cs_n & ~phase.ras_n & phase.cas_n,
self.activate.eq(phase.we_n),
self.precharge.eq(~phase.we_n)
),
If(~phase.cs_n & phase.ras_n & ~phase.cas_n,
self.write.eq(~phase.we_n),
self.read.eq(phase.we_n)
)
]

class SDRAMPHYSim(Module):
def __init__(self, module, nmodules=1):
addressbits = module.geom_settings.addressbits
databits = module.geom_settings.databits
bankbits = module.geom_settings.bankbits
rowbits = module.geom_settings.rowbits
colbits = module.geom_settings.colbits

# XXX expose this to user
self.settings = sdram.PhySettings(
memtype=module.memtype,
dfi_databits=databits,
nphases=1,
rdphase=0,
wrphase=0,
rdcmdphase=0,
wrcmdphase=0,
cl=2,
read_latency=4,
write_latency=0
)
self.module = module

self.dfi = Interface(addressbits, bankbits, databits)

###
nbanks = 2**bankbits
nrows = 2**rowbits
ncols = 2**colbits
data_width = databits*nmodules

# DFI phases
phases = [DFIPhase(self.dfi, n) for n in range(self.settings.nphases)]
self.submodules += phases

# banks
banks = [Bank(data_width, nrows, ncols) for i in range(nbanks)]
self.submodules += banks

# connect DFI phases to banks (cmds, write datapath)
for nb, bank in enumerate(banks):
# bank activate
activates = Signal(len(phases))
cases = {}
for np, phase in enumerate(phases):
self.comb += activates[np].eq(phase.activate)
cases[2**np] = [
bank.activate.eq(phase.bank == nb),
bank.activate_row.eq(phase.address)
]
self.comb += Case(activates, cases)

# bank precharge
precharges = Signal(len(phases))
cases = {}
for np, phase in enumerate(phases):
self.comb += precharges[np].eq(phase.precharge)
cases[2**np] = [
bank.precharge.eq((phase.bank == nb) | phase.address[10])
]
self.comb += Case(precharges, cases)

# bank writes
writes = Signal(len(phases))
cases = {}
for np, phase in enumerate(phases):
self.comb += writes[np].eq(phase.write)
cases[2**np] = [
bank.write.eq(phase.bank == nb),
bank.write_col.eq(phase.address)
]
self.comb += Case(writes, cases)
self.comb += [
bank.write_data.eq(Cat(*[phase.wrdata for phase in phases])),
bank.write_mask.eq(Cat(*[phase.wrdata_mask for phase in phases]))
]

# bank reads
reads = Signal(len(phases))
read_data = Signal(data_width)
cases = {}
for np, phase in enumerate(phases):
self.comb += reads[np].eq(phase.read)
cases[2**np] = [
bank.read.eq(phase.bank == nb),
bank.read_col.eq(phase.address)
]
self.comb += Case(reads, cases)

# connect banks to DFI phases (cmds, read datapath)
banks_read = Signal()
banks_read_data = Signal(data_width)
self.comb += [
banks_read.eq(optree("|", [bank.read for bank in banks])),
banks_read_data.eq(optree("|", [bank.read_data for bank in banks]))
]
# simulate read latency
for i in range(self.settings.read_latency):
new_banks_read = Signal()
new_banks_read_data = Signal(data_width)
self.sync += [
new_banks_read.eq(banks_read),
new_banks_read_data.eq(banks_read_data)
]
banks_read = new_banks_read
banks_read_data = new_banks_read_data

self.comb += [
Cat(iter([phase.rddata_valid for phase in phases])).eq(banks_read),
Cat(iter([phase.rddata for phase in phases])).eq(banks_read_data)
]
25 changes: 17 additions & 8 deletions software/bios/sdram.c
Original file line number Diff line number Diff line change
@@ -423,15 +423,24 @@ int sdrlevel(void)
#endif /* CSR_DDRPHY_BASE */

#define TEST_SIZE (2*1024*1024)
#define TEST_RANDOM_DATA 1

#define ONEZERO 0xAAAAAAAA
#define ZEROONE 0x55555555

unsigned int seed_to_data(unsigned int seed, int random)
{
if (random)
return 1664525*seed + 1013904223;
else
return seed + 1;
}

int memtest_silent(void)
{
volatile unsigned int *array = (unsigned int *)MAIN_RAM_BASE;
int i;
unsigned int prv;
unsigned int seed;
unsigned int error_cnt;

/* test data bus */
@@ -453,18 +462,18 @@ int memtest_silent(void)
error_cnt++;
}

/* test random data */
prv = 0;
/* test counter or random data */
seed = 0;
for(i=0;i<TEST_SIZE/4;i++) {
prv = 1664525*prv + 1013904223;
array[i] = prv;
seed = seed_to_data(seed, TEST_RANDOM_DATA);
array[i] = seed;
}

prv = 0;
seed = 0;
error_cnt = 0;
for(i=0;i<TEST_SIZE/4;i++) {
prv = 1664525*prv + 1013904223;
if(array[i] != prv)
seed = seed_to_data(seed, TEST_RANDOM_DATA);
if(array[i] != seed)
error_cnt++;
}
return error_cnt;
1 change: 1 addition & 0 deletions software/bios/sdram.h
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@ void sdrwloff(void);
int sdrlevel(void);
#endif

unsigned int seed_to_data(unsigned int seed, int random);
int memtest_silent(void);
int memtest(void);
int sdrinit(void);