bankmachine: some changes and first tests
This commit is contained in:
parent
7732ff27a6
commit
0ef987dab1
|
@ -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)
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue