bankmachine: some changes and first tests

This commit is contained in:
Florent Kermarrec 2015-09-27 22:12:30 +02:00
parent 7732ff27a6
commit 0ef987dab1
4 changed files with 123 additions and 90 deletions

View File

@ -73,15 +73,18 @@ class LiteDRAMPort:
self.write.connect(other)
self.read.connect(other)
def dram_bank_cmd_description(addressbits):
def dram_cmd_description(rowbits, colbits):
payload_layout = [("row", rowbits), ("col", colbits)]
return EndpointDescription(payload_layout)
def dram_bank_cmd_description(rowbits, colbits):
payload_layout = [
("adr", addressbits),
("cas_n", 1),
("ras_n", 1),
("we_n", 1),
("is_cmd", 1),
("is_read", 1),
("is_write", 1)
("write", 1),
("read", 1),
("precharge", 1),
("activate", 1),
("row", rowbits),
("col", colbits)
]
return EndpointDescription(payload_layout)

View File

@ -1,5 +1,4 @@
from migen.fhdl.std import *
from migen.genlib.roundrobin import *
from migen.genlib.fsm import FSM, NextState
from migen.genlib.misc import optree, WaitTimer
from migen.actorlib.fifo import SyncFIFO
@ -9,15 +8,15 @@ from litedram.common import *
class LiteDRAMRowTracker(Module):
def __init__(self, rw):
self.row = Signal(rw)
def __init__(self, rowbits):
self.row = Signal(rowbits)
self.open = Signal()
self.close = Signal()
# # #
self.hasopenrow = Signal()
self._openrow = Signal(rw)
self._openrow = Signal(rowbits)
self.sync += \
If(self.open,
self.hasopenrow.eq(1),
@ -31,13 +30,14 @@ class LiteDRAMRowTracker(Module):
class LiteDRAMBankMachine(Module):
def __init__(self, sdram_module, cmd_fifo_depth):
self.refresh = Sink(dram_refresh_description())
self.write_cmd = Sink(dram_cmd_description(sdram_module.geom_settings.rowbits,
sdram_module.geom_settings.colbits))
self.read_cmd = Sink(dram_cmd_description(sdram_module.geom_settings.rowbits,
sdram_module.geom_settings.colbits))
self.cmd = Source(dram_bank_cmd_description(32)) # XXX
def __init__(self, dram_module, cmd_fifo_depth):
rowbits = dram_module.geom_settings.rowbits
colbits = dram_module.geom_settings.colbits
self.refresh = refresh = Sink(dram_refresh_description())
self.write_cmd = write_cmd = Sink(dram_cmd_description(rowbits, colbits))
self.read_cmd = read_cmd = Sink(dram_cmd_description(rowbits, colbits))
self.cmd = cmd = Source(dram_bank_cmd_description(rowbits, colbits))
# # #
@ -46,16 +46,16 @@ class LiteDRAMBankMachine(Module):
self.submodules += read_write_n
# Cmd fifos
write_cmd_fifo = SyncFIFO(self.write_cmd.description, cmd_fifo_depth)
read_cmd_fifo = SyncFIFO(self.read_cmd.description, cmd_fifo_depth)
write_cmd_fifo = SyncFIFO(write_cmd.description, cmd_fifo_depth)
read_cmd_fifo = SyncFIFO(read_cmd.description, cmd_fifo_depth)
self.submodules += write_cmd_fifo, read_cmd_fifo
self.comb += [
Record.connect(self.write_cmd, write_cmd_fifo.sink),
Record.connect(self.read_cmd, read_cmd_fifo.sink)
Record.connect(write_cmd, write_cmd_fifo.sink),
Record.connect(read_cmd, read_cmd_fifo.sink)
]
# Cmd mux
mux = Multiplexer(self.write_cmd.description, 2) # XXX
mux = Multiplexer(write_cmd.description, 2) # XXX
self.submodules += mux
self.comb += [
mux.sel.eq(read_write_n.q),
@ -64,8 +64,9 @@ class LiteDRAMBankMachine(Module):
]
# Row tracking
tracker = LiteDRAMRowTracker(sdram_module.geom_settings.rowbits)
tracker = LiteDRAMRowTracker(dram_module.geom_settings.rowbits)
self.submodules += tracker
self.comb += tracker.row.eq(mux.source.row)
write_available = Signal()
write_hit = Signal()
@ -82,36 +83,34 @@ class LiteDRAMBankMachine(Module):
]
# Respect write-to-precharge specification
write2precharge_timer = WaitTimer(2 + sdram_module.timing_settings.tWR - 1)
write2precharge_timer = WaitTimer(2 + dram_module.timing_settings.tWR - 1)
self.submodules += write2precharge_timer
self.comb += write2precharge_timer.wait.eq(self.cmd.stb &
self.cmd.is_write &
self.cmd.ack)
self.comb += write2precharge_timer.wait.eq(~(cmd.stb & cmd.write & cmd.ack))
# Control and command generation FSM
self.submodules.fsm = fsm = FSM(reset_state="IDLE")
fsm.act("IDLE",
If(read_write_n.q,
NextState("WRITE")
).Else(
NextState("READ")
).Else(
NextState("WRITE")
)
)
fsm.act("WRITE",
read_write_n.reset.eq(1),
If(self.refresh.stb,
If(refresh.stb,
NextState("REFRESH")
).Else(
If(~write_available & read_available, # XXX add anti-starvation
NextState("READ")
If(~write_available,
If(read_available, # XXX add anti-starvation
NextState("READ")
)
).Else(
If(tracker.hasopenrow,
If(write_hit,
self.cmd.stb.eq(1),
self.cmd.is_write.eq(1),
self.cmd.cas_n.eq(0),
self.cmd.we_n.eq(0),
mux.source.ack.eq(self.cmd.ack)
cmd.stb.eq(1),
cmd.write.eq(1),
mux.source.ack.eq(cmd.ack)
).Else(
NextState("PRECHARGE")
)
@ -123,19 +122,19 @@ class LiteDRAMBankMachine(Module):
)
fsm.act("READ",
read_write_n.ce.eq(1),
If(self.refresh.stb,
If(refresh.stb,
NextState("REFRESH")
).Else(
If(~read_available & write_available, # XXX add anti starvation
NextState("READ")
If(~read_available,
If(write_available, # XXX add anti starvation
NextState("WRITE")
)
).Else(
If(tracker.hasopenrow,
If(read_hit,
self.cmd.stb.eq(1),
self.cmd.is_read.eq(1),
self.cmd.cas_n.eq(0),
self.cmd.we_n.eq(1),
mux.source.ack.eq(self.cmd.ack)
cmd.stb.eq(1),
cmd.read.eq(1),
mux.source.ack.eq(cmd.ack)
).Else(
NextState("PRECHARGE")
)
@ -146,32 +145,28 @@ class LiteDRAMBankMachine(Module):
)
)
fsm.act("PRECHARGE",
cmd.precharge.eq(1),
If(write2precharge_timer.done,
self.cmd.stb.eq(1),
self.cmd.is_cmd.eq(1),
self.cmd.ras_n.eq(0),
self.cmd.we_n.eq(0),
self.cmd.adr.eq(mux.source.col),
If(self.cmd.ack,
cmd.stb.eq(1),
If(cmd.ack,
NextState("TRP")
)
)
)
fsm.act("ACTIVATE",
tracker.open.eq(1),
self.cmd.stb.eq(1),
self.cmd.is_cmd.eq(1),
self.cmd.ras_n.eq(0),
self.cmd.adr.eq(mux.source.row),
If(self.cmd.ack, NextState("TRCD"))
cmd.stb.eq(1),
cmd.activate.eq(1),
If(cmd.ack,
NextState("TRCD")
)
)
fsm.act("REFRESH",
tracker.close.eq(1),
self.cmd.is_cmd.eq(1),
self.refresh.ack.eq(write2precharge_timer.done),
If(~self.refresh.stb,
refresh.ack.eq(write2precharge_timer.done),
If(~refresh.stb,
NextState("IDLE")
)
)
fsm.delayed_enter("TRP", "ACTIVATE", sdram_module.timing_settings.tRP-1)
fsm.delayed_enter("TRCD", "IDLE", sdram_module.timing_settings.tRCD-1)
fsm.delayed_enter("TRP", "ACTIVATE", dram_module.timing_settings.tRP-1)
fsm.delayed_enter("TRCD", "IDLE", dram_module.timing_settings.tRCD-1)

View File

@ -1,7 +1,7 @@
# SDRAM memory modules library
# DRAM memory modules library
#
# This library avoid duplications of memory modules definitions in targets and
# ease SDRAM usage. (User can only select an already existing module or create
# ease DRAM usage. (User can only select an already existing module or create
# one for its board and contribute to this library)
#
# TODO:
@ -20,7 +20,7 @@ from migen.fhdl.std import *
from misoclib.mem import sdram
class SDRAMModule:
class DRAMModule:
def __init__(self, clk_freq, memtype, geom_settings, timing_settings):
self.clk_freq = clk_freq
self.memtype = memtype
@ -46,7 +46,7 @@ class SDRAMModule:
# SDR
class IS42S16160(SDRAMModule):
class IS42S16160(DRAMModule):
geom_settings = {
"nbanks": 4,
"nrows": 8192,
@ -62,11 +62,11 @@ class IS42S16160(SDRAMModule):
"tRFC": 70
}
def __init__(self, clk_freq):
SDRAMModule.__init__(self, clk_freq, "SDR", self.geom_settings,
DRAMModule.__init__(self, clk_freq, "SDR", self.geom_settings,
self.timing_settings)
class MT48LC4M16(SDRAMModule):
class MT48LC4M16(DRAMModule):
geom_settings = {
"nbanks": 4,
"nrows": 4096,
@ -81,11 +81,11 @@ class MT48LC4M16(SDRAMModule):
"tRFC": 66
}
def __init__(self, clk_freq):
SDRAMModule.__init__(self, clk_freq, "SDR", self.geom_settings,
DRAMModule.__init__(self, clk_freq, "SDR", self.geom_settings,
self.timing_settings)
class AS4C16M16(SDRAMModule):
class AS4C16M16(DRAMModule):
geom_settings = {
"nbanks": 4,
"nrows": 8192,
@ -101,12 +101,12 @@ class AS4C16M16(SDRAMModule):
"tRFC": 60
}
def __init__(self, clk_freq):
SDRAMModule.__init__(self, clk_freq, "SDR", self.geom_settings,
DRAMModule.__init__(self, clk_freq, "SDR", self.geom_settings,
self.timing_settings)
# DDR
class MT46V32M16(SDRAMModule):
class MT46V32M16(DRAMModule):
geom_settings = {
"nbanks": 4,
"nrows": 8192,
@ -121,12 +121,12 @@ class MT46V32M16(SDRAMModule):
"tRFC": 70
}
def __init__(self, clk_freq):
SDRAMModule.__init__(self, clk_freq, "DDR", self.geom_settings,
DRAMModule.__init__(self, clk_freq, "DDR", self.geom_settings,
self.timing_settings)
# LPDDR
class MT46H32M16(SDRAMModule):
class MT46H32M16(DRAMModule):
geom_settings = {
"nbanks": 4,
"nrows": 8192,
@ -141,12 +141,12 @@ class MT46H32M16(SDRAMModule):
"tRFC": 72
}
def __init__(self, clk_freq):
SDRAMModule.__init__(self, clk_freq, "LPDDR", self.geom_settings,
DRAMModule.__init__(self, clk_freq, "LPDDR", self.geom_settings,
self.timing_settings)
# DDR2
class MT47H128M8(SDRAMModule):
class MT47H128M8(DRAMModule):
geom_settings = {
"nbanks": 8,
"nrows": 16384,
@ -161,11 +161,11 @@ class MT47H128M8(SDRAMModule):
"tRFC": 127.5
}
def __init__(self, clk_freq):
SDRAMModule.__init__(self, clk_freq, "DDR2", self.geom_settings,
DRAMModule.__init__(self, clk_freq, "DDR2", self.geom_settings,
self.timing_settings)
class P3R1GE4JGF(SDRAMModule):
class P3R1GE4JGF(DRAMModule):
geom_settings = {
"nbanks": 8,
"nrows": 8192,
@ -181,12 +181,12 @@ class P3R1GE4JGF(SDRAMModule):
}
def __init__(self, clk_freq):
SDRAMModule.__init__(self, clk_freq, "DDR2", self.geom_settings,
DRAMModule.__init__(self, clk_freq, "DDR2", self.geom_settings,
self.timing_settings)
# DDR3
class MT8JTF12864(SDRAMModule):
class MT8JTF12864(DRAMModule):
geom_settings = {
"nbanks": 8,
"nrows": 16384,
@ -201,11 +201,11 @@ class MT8JTF12864(SDRAMModule):
"tRFC": 70
}
def __init__(self, clk_freq):
SDRAMModule.__init__(self, clk_freq, "DDR3", self.geom_settings,
DRAMModule.__init__(self, clk_freq, "DDR3", self.geom_settings,
self.timing_settings)
class MT41J128M16(SDRAMModule):
class MT41J128M16(DRAMModule):
geom_settings = {
"nbanks": 8,
"nrows": 16384,
@ -221,5 +221,5 @@ class MT41J128M16(SDRAMModule):
}
def __init__(self, clk_freq):
SDRAMModule.__init__(self, clk_freq, "DDR3", self.geom_settings,
DRAMModule.__init__(self, clk_freq, "DDR3", self.geom_settings,
self.timing_settings)

View File

@ -2,19 +2,54 @@ from migen.fhdl.std import *
from migen.sim.generic import run_simulation
from litedram.common import *
from litedram.module import MT48LC4M16
from litedram.modules import MT48LC4M16
from litedram.core.bankmachine import LiteDRAMBankMachine
from test.common import *
class CmdGen(Module):
def __init__(self, dram_module):
self.rowbits = rowbits = dram_module.geom_settings.rowbits
self.colbits = colbits = dram_module.geom_settings.colbits
self.cmd = Source(dram_cmd_description(rowbits, colbits))
self.n = 0
def do_simulation(self, selfp):
if selfp.cmd.ack:
if self.n < 100:
selfp.cmd.stb = 1
selfp.cmd.row = randn(2**self.rowbits-1)
selfp.cmd.col = randn(2**self.colbits-1)
self.n += 1
else:
selfp.cmd.stb = 0
class TB(Module):
def __init__(self):
sdram_module = MT48LC4M16(100)
self.submodules.bankmachine = LiteDRAMBankMachine(sdram_module, 16)
dram_module = MT48LC4M16(100*1000000)
self.submodules.bankmachine = LiteDRAMBankMachine(dram_module, 16)
self.submodules.write_gen = CmdGen(dram_module)
self.submodules.read_gen = CmdGen(dram_module)
self.comb += [
Record.connect(self.write_gen.cmd, self.bankmachine.write_cmd),
Record.connect(self.read_gen.cmd, self.bankmachine.read_cmd),
self.bankmachine.cmd.ack.eq(1)
]
self.nreads = 0
self.nwrites = 0
def do_simulation(self, selfp):
if selfp.bankmachine.cmd.stb:
if selfp.bankmachine.cmd.write:
self.nwrites += 1
print("nwrites {}/ nreads {}".format(self.nwrites, self.nreads))
elif selfp.bankmachine.cmd.read:
self.nreads += 1
print("nwrites {}/ nreads {}".format(self.nwrites, self.nreads))
def gen_simulation(self, selfp):
for i in range(100):
yield
if __name__ == "__main__":
run_simulation(TB(), ncycles=2048, vcd_name="my.vcd", keep_files=True)