diff --git a/litedram/core/bankmachine.py b/litedram/core/bankmachine.py index ef542ea..df6f99d 100644 --- a/litedram/core/bankmachine.py +++ b/litedram/core/bankmachine.py @@ -38,15 +38,18 @@ class BankMachine(Module): self.cmd = cmd = stream.Endpoint(cmd_request_rw_layout(a, ba)) # # # + auto_precharge = Signal() # Command buffer cmd_buffer_layout = [("we", 1), ("adr", len(req.adr))] - cmd_buffer = stream.SyncFIFO(cmd_buffer_layout, settings.cmd_buffer_depth) - self.submodules += cmd_buffer + cmd_bufferPre = stream.SyncFIFO(cmd_buffer_layout, settings.cmd_buffer_depth) + cmd_buffer = stream.Buffer(cmd_buffer_layout) # 1 depth buffer to detect row change + self.submodules += cmd_buffer, cmd_bufferPre self.comb += [ - req.connect(cmd_buffer.sink, omit=["wdata_valid", "wdata_ready", + req.connect(cmd_bufferPre.sink, omit=["wdata_valid", "wdata_ready", "rdata_valid", "rdata_ready", "lock"]), + cmd_bufferPre.source.connect(cmd_buffer.sink), cmd_buffer.source.ready.eq(req.wdata_ready | req.rdata_valid), req.lock.eq(cmd_buffer.source.valid), ] @@ -75,7 +78,7 @@ class BankMachine(Module): If(sel_row_adr, cmd.a.eq(slicer.row(cmd_buffer.source.adr)) ).Else( - cmd.a.eq(slicer.col(cmd_buffer.source.adr)) + cmd.a.eq((auto_precharge << 10) | slicer.col(cmd_buffer.source.adr)) ) ] @@ -86,6 +89,15 @@ class BankMachine(Module): cmd.ready & cmd.is_write)) + # Auto Precharge + self.comb += [ + If(cmd_bufferPre.source.valid & cmd_buffer.source.valid, + If(slicer.row(cmd_bufferPre.source.adr) != slicer.row(cmd_buffer.source.adr), + auto_precharge.eq(self.precharge_timer.done & (track_close == 0)) + ) + ) + ] + # Control and command generation FSM # Note: tRRD, tFAW, tCCD, tWTR timings are enforced by the multiplexer self.submodules.fsm = fsm = FSM() @@ -105,7 +117,10 @@ class BankMachine(Module): req.rdata_valid.eq(cmd.ready), cmd.is_read.eq(1) ), - cmd.cas.eq(1) + cmd.cas.eq(1), + If(cmd.ready & auto_precharge, + NextState("AUTOPRECHARGE") + ) ) ).Else( NextState("PRECHARGE") @@ -128,6 +143,12 @@ class BankMachine(Module): ), track_close.eq(1) ) + fsm.act("AUTOPRECHARGE", + If(self.precharge_timer.done, + NextState("TRP") + ), + track_close.eq(1) + ) fsm.act("ACTIVATE", sel_row_adr.eq(1), track_open.eq(1), diff --git a/litedram/core/multiplexer.py b/litedram/core/multiplexer.py index 70c3738..3b64b89 100644 --- a/litedram/core/multiplexer.py +++ b/litedram/core/multiplexer.py @@ -198,10 +198,12 @@ class Multiplexer(Module, AutoCSR): # tRRD timing (Row to Row delay) self.trrdcon = trrdcon = tXXDController(settings.timing.tRRD) + self.submodules += trrdcon self.comb += trrdcon.valid.eq(choose_cmd.accept() & choose_cmd.activate()) # tFAW timing (Four Activate Window) self.tfawcon = tfawcon = tFAWController(settings.timing.tFAW) + self.submodules += tfawcon self.comb += tfawcon.valid.eq(choose_cmd.accept() & choose_cmd.activate()) # RAS control @@ -210,7 +212,8 @@ class Multiplexer(Module, AutoCSR): # tCCD timing (Column to Column delay) self.tccdcon = tccdcon = tXXDController(settings.timing.tCCD) - self.comb += tccdcon.valid.eq(choose_cmd.accept() & (choose_cmd.write() | choose_cmd.read())) + self.submodules += tccdcon + self.comb += tccdcon.valid.eq(choose_req.accept() & (choose_req.write() | choose_req.read())) # CAS control self.comb += cas_allowed.eq(tccdcon.ready) @@ -221,6 +224,7 @@ class Multiplexer(Module, AutoCSR): settings.timing.tWTR + # tCCD must be added since tWTR begins after the transfer is complete settings.timing.tCCD if settings.timing.tCCD is not None else 0) + self.submodules += twtrcon self.comb += twtrcon.valid.eq(choose_req.accept() & choose_req.write()) # Read/write turnaround @@ -325,7 +329,7 @@ class Multiplexer(Module, AutoCSR): fsm.act("REFRESH", steerer.sel[0].eq(STEER_REFRESH), refresher.cmd.ready.eq(1), - If(~refresher.cmd.valid, + If(refresher.cmd.last, NextState("READ") ) ) diff --git a/litedram/core/refresher.py b/litedram/core/refresher.py index be58b2c..904d671 100644 --- a/litedram/core/refresher.py +++ b/litedram/core/refresher.py @@ -45,16 +45,14 @@ class Refresher(Module): self.comb += self.timer.wait.eq(settings.with_refresh & ~self.timer.done) # Control FSM - cmd_valid = Signal() self.submodules.fsm = fsm = FSM() fsm.act("IDLE", If(self.timer.done, - cmd_valid.eq(1), NextState("WAIT_GRANT") ) ) fsm.act("WAIT_GRANT", - cmd_valid.eq(1), + cmd.valid.eq(1), If(cmd.ready, seq_start.eq(1), NextState("WAIT_SEQ") @@ -62,8 +60,9 @@ class Refresher(Module): ) fsm.act("WAIT_SEQ", If(seq_done, - cmd_valid.eq(0), + cmd.last.eq(1), NextState("IDLE") + ).Else( + cmd.valid.eq(1) ) ) - self.sync += cmd.valid.eq(cmd_valid)