mirror of
https://github.com/enjoy-digital/litedram.git
synced 2025-01-04 09:52:25 -05:00
commit
db4ec67741
3 changed files with 36 additions and 12 deletions
|
@ -38,15 +38,18 @@ class BankMachine(Module):
|
||||||
self.cmd = cmd = stream.Endpoint(cmd_request_rw_layout(a, ba))
|
self.cmd = cmd = stream.Endpoint(cmd_request_rw_layout(a, ba))
|
||||||
|
|
||||||
# # #
|
# # #
|
||||||
|
auto_precharge = Signal()
|
||||||
|
|
||||||
# Command buffer
|
# Command buffer
|
||||||
cmd_buffer_layout = [("we", 1), ("adr", len(req.adr))]
|
cmd_buffer_layout = [("we", 1), ("adr", len(req.adr))]
|
||||||
cmd_buffer = stream.SyncFIFO(cmd_buffer_layout, settings.cmd_buffer_depth)
|
cmd_bufferPre = stream.SyncFIFO(cmd_buffer_layout, settings.cmd_buffer_depth)
|
||||||
self.submodules += cmd_buffer
|
cmd_buffer = stream.Buffer(cmd_buffer_layout) # 1 depth buffer to detect row change
|
||||||
|
self.submodules += cmd_buffer, cmd_bufferPre
|
||||||
self.comb += [
|
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",
|
"rdata_valid", "rdata_ready",
|
||||||
"lock"]),
|
"lock"]),
|
||||||
|
cmd_bufferPre.source.connect(cmd_buffer.sink),
|
||||||
cmd_buffer.source.ready.eq(req.wdata_ready | req.rdata_valid),
|
cmd_buffer.source.ready.eq(req.wdata_ready | req.rdata_valid),
|
||||||
req.lock.eq(cmd_buffer.source.valid),
|
req.lock.eq(cmd_buffer.source.valid),
|
||||||
]
|
]
|
||||||
|
@ -75,7 +78,7 @@ class BankMachine(Module):
|
||||||
If(sel_row_adr,
|
If(sel_row_adr,
|
||||||
cmd.a.eq(slicer.row(cmd_buffer.source.adr))
|
cmd.a.eq(slicer.row(cmd_buffer.source.adr))
|
||||||
).Else(
|
).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.ready &
|
||||||
cmd.is_write))
|
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
|
# Control and command generation FSM
|
||||||
# Note: tRRD, tFAW, tCCD, tWTR timings are enforced by the multiplexer
|
# Note: tRRD, tFAW, tCCD, tWTR timings are enforced by the multiplexer
|
||||||
self.submodules.fsm = fsm = FSM()
|
self.submodules.fsm = fsm = FSM()
|
||||||
|
@ -105,7 +117,10 @@ class BankMachine(Module):
|
||||||
req.rdata_valid.eq(cmd.ready),
|
req.rdata_valid.eq(cmd.ready),
|
||||||
cmd.is_read.eq(1)
|
cmd.is_read.eq(1)
|
||||||
),
|
),
|
||||||
cmd.cas.eq(1)
|
cmd.cas.eq(1),
|
||||||
|
If(cmd.ready & auto_precharge,
|
||||||
|
NextState("AUTOPRECHARGE")
|
||||||
|
)
|
||||||
)
|
)
|
||||||
).Else(
|
).Else(
|
||||||
NextState("PRECHARGE")
|
NextState("PRECHARGE")
|
||||||
|
@ -128,6 +143,12 @@ class BankMachine(Module):
|
||||||
),
|
),
|
||||||
track_close.eq(1)
|
track_close.eq(1)
|
||||||
)
|
)
|
||||||
|
fsm.act("AUTOPRECHARGE",
|
||||||
|
If(self.precharge_timer.done,
|
||||||
|
NextState("TRP")
|
||||||
|
),
|
||||||
|
track_close.eq(1)
|
||||||
|
)
|
||||||
fsm.act("ACTIVATE",
|
fsm.act("ACTIVATE",
|
||||||
sel_row_adr.eq(1),
|
sel_row_adr.eq(1),
|
||||||
track_open.eq(1),
|
track_open.eq(1),
|
||||||
|
|
|
@ -198,10 +198,12 @@ class Multiplexer(Module, AutoCSR):
|
||||||
|
|
||||||
# tRRD timing (Row to Row delay)
|
# tRRD timing (Row to Row delay)
|
||||||
self.trrdcon = trrdcon = tXXDController(settings.timing.tRRD)
|
self.trrdcon = trrdcon = tXXDController(settings.timing.tRRD)
|
||||||
|
self.submodules += trrdcon
|
||||||
self.comb += trrdcon.valid.eq(choose_cmd.accept() & choose_cmd.activate())
|
self.comb += trrdcon.valid.eq(choose_cmd.accept() & choose_cmd.activate())
|
||||||
|
|
||||||
# tFAW timing (Four Activate Window)
|
# tFAW timing (Four Activate Window)
|
||||||
self.tfawcon = tfawcon = tFAWController(settings.timing.tFAW)
|
self.tfawcon = tfawcon = tFAWController(settings.timing.tFAW)
|
||||||
|
self.submodules += tfawcon
|
||||||
self.comb += tfawcon.valid.eq(choose_cmd.accept() & choose_cmd.activate())
|
self.comb += tfawcon.valid.eq(choose_cmd.accept() & choose_cmd.activate())
|
||||||
|
|
||||||
# RAS control
|
# RAS control
|
||||||
|
@ -210,7 +212,8 @@ class Multiplexer(Module, AutoCSR):
|
||||||
|
|
||||||
# tCCD timing (Column to Column delay)
|
# tCCD timing (Column to Column delay)
|
||||||
self.tccdcon = tccdcon = tXXDController(settings.timing.tCCD)
|
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
|
# CAS control
|
||||||
self.comb += cas_allowed.eq(tccdcon.ready)
|
self.comb += cas_allowed.eq(tccdcon.ready)
|
||||||
|
@ -221,6 +224,7 @@ class Multiplexer(Module, AutoCSR):
|
||||||
settings.timing.tWTR +
|
settings.timing.tWTR +
|
||||||
# tCCD must be added since tWTR begins after the transfer is complete
|
# tCCD must be added since tWTR begins after the transfer is complete
|
||||||
settings.timing.tCCD if settings.timing.tCCD is not None else 0)
|
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())
|
self.comb += twtrcon.valid.eq(choose_req.accept() & choose_req.write())
|
||||||
|
|
||||||
# Read/write turnaround
|
# Read/write turnaround
|
||||||
|
@ -325,7 +329,7 @@ class Multiplexer(Module, AutoCSR):
|
||||||
fsm.act("REFRESH",
|
fsm.act("REFRESH",
|
||||||
steerer.sel[0].eq(STEER_REFRESH),
|
steerer.sel[0].eq(STEER_REFRESH),
|
||||||
refresher.cmd.ready.eq(1),
|
refresher.cmd.ready.eq(1),
|
||||||
If(~refresher.cmd.valid,
|
If(refresher.cmd.last,
|
||||||
NextState("READ")
|
NextState("READ")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
@ -45,16 +45,14 @@ class Refresher(Module):
|
||||||
self.comb += self.timer.wait.eq(settings.with_refresh & ~self.timer.done)
|
self.comb += self.timer.wait.eq(settings.with_refresh & ~self.timer.done)
|
||||||
|
|
||||||
# Control FSM
|
# Control FSM
|
||||||
cmd_valid = Signal()
|
|
||||||
self.submodules.fsm = fsm = FSM()
|
self.submodules.fsm = fsm = FSM()
|
||||||
fsm.act("IDLE",
|
fsm.act("IDLE",
|
||||||
If(self.timer.done,
|
If(self.timer.done,
|
||||||
cmd_valid.eq(1),
|
|
||||||
NextState("WAIT_GRANT")
|
NextState("WAIT_GRANT")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
fsm.act("WAIT_GRANT",
|
fsm.act("WAIT_GRANT",
|
||||||
cmd_valid.eq(1),
|
cmd.valid.eq(1),
|
||||||
If(cmd.ready,
|
If(cmd.ready,
|
||||||
seq_start.eq(1),
|
seq_start.eq(1),
|
||||||
NextState("WAIT_SEQ")
|
NextState("WAIT_SEQ")
|
||||||
|
@ -62,8 +60,9 @@ class Refresher(Module):
|
||||||
)
|
)
|
||||||
fsm.act("WAIT_SEQ",
|
fsm.act("WAIT_SEQ",
|
||||||
If(seq_done,
|
If(seq_done,
|
||||||
cmd_valid.eq(0),
|
cmd.last.eq(1),
|
||||||
NextState("IDLE")
|
NextState("IDLE")
|
||||||
|
).Else(
|
||||||
|
cmd.valid.eq(1)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
self.sync += cmd.valid.eq(cmd_valid)
|
|
||||||
|
|
Loading…
Reference in a new issue