diff --git a/litedram/common.py b/litedram/common.py index c9e4627..8028a89 100644 --- a/litedram/common.py +++ b/litedram/common.py @@ -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) diff --git a/litedram/core/bankmachine.py b/litedram/core/bankmachine.py index 24da839..ad0a654 100644 --- a/litedram/core/bankmachine.py +++ b/litedram/core/bankmachine.py @@ -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) diff --git a/litedram/module.py b/litedram/modules.py similarity index 82% rename from litedram/module.py rename to litedram/modules.py index ae26506..f1f29a1 100644 --- a/litedram/module.py +++ b/litedram/modules.py @@ -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) diff --git a/test/bankmachine_tb.py b/test/bankmachine_tb.py index 5b256f9..d969de4 100644 --- a/test/bankmachine_tb.py +++ b/test/bankmachine_tb.py @@ -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)