diff --git a/litedram/common.py b/litedram/common.py index e4abf28..d750790 100644 --- a/litedram/common.py +++ b/litedram/common.py @@ -84,20 +84,18 @@ class UserInterface(Record): Record.__init__(self, layout) -class CommandRequest: - def __init__(self, a, ba): - self.a = Signal(a) - self.ba = Signal(ba) - self.cas_n = Signal(reset=1) - self.ras_n = Signal(reset=1) - self.we_n = Signal(reset=1) +def cmd_request_layout(a, ba): + return [ + ("a", a), + ("ba", ba), + ("cas", 1), + ("ras", 1), + ("we", 1) + ] - -class CommandRequestRW(CommandRequest): - def __init__(self, a, ba): - CommandRequest.__init__(self, a, ba) - self.valid = Signal() - self.ready = Signal() - self.is_cmd = Signal() - self.is_read = Signal() - self.is_write = Signal() +def cmd_request_rw_layout(a, ba): + return cmd_request_layout(a, ba) + [ + ("is_cmd", 1), + ("is_read", 1), + ("is_write", 1) + ] diff --git a/litedram/core/bankmachine.py b/litedram/core/bankmachine.py index 590bc2c..2bf67eb 100644 --- a/litedram/core/bankmachine.py +++ b/litedram/core/bankmachine.py @@ -32,7 +32,8 @@ class BankMachine(Module): self.req = req = Record(cmd_layout(aw)) self.refresh_req = Signal() self.refresh_gnt = Signal() - self.cmd = CommandRequestRW(geom_settings.addressbits, geom_settings.bankbits) + self.cmd = cmd = stream.Endpoint(cmd_request_rw_layout(geom_settings.addressbits, + geom_settings.bankbits)) # # # @@ -68,19 +69,19 @@ class BankMachine(Module): # Address generation s_row_adr = Signal() self.comb += [ - self.cmd.ba.eq(n), + cmd.ba.eq(n), If(s_row_adr, - self.cmd.a.eq(slicer.row(fifo.source.adr)) + cmd.a.eq(slicer.row(fifo.source.adr)) ).Else( - self.cmd.a.eq(slicer.col(fifo.source.adr)) + cmd.a.eq(slicer.col(fifo.source.adr)) ) ] # Respect write-to-precharge specification self.submodules.precharge_timer = WaitTimer(2 + timing_settings.tWR - 1 + 1) - self.comb += self.precharge_timer.wait.eq(~(self.cmd.valid & - self.cmd.ready & - self.cmd.is_write)) + self.comb += self.precharge_timer.wait.eq(~(cmd.valid & + cmd.ready & + cmd.is_write)) # Control and command generation FSM self.submodules.fsm = fsm = FSM() @@ -91,16 +92,16 @@ class BankMachine(Module): If(has_openrow, If(hit, # NB: write-to-read specification is enforced by multiplexer - self.cmd.valid.eq(1), + cmd.valid.eq(1), If(fifo.source.we, - req.dat_w_ack.eq(self.cmd.ready), - self.cmd.is_write.eq(1) + req.dat_w_ack.eq(cmd.ready), + cmd.is_write.eq(1), + cmd.we.eq(1), ).Else( - req.dat_r_ack.eq(self.cmd.ready), - self.cmd.is_read.eq(1) + req.dat_r_ack.eq(cmd.ready), + cmd.is_read.eq(1) ), - self.cmd.cas_n.eq(0), - self.cmd.we_n.eq(~fifo.source.we) + cmd.cas.eq(1) ).Else( NextState("PRECHARGE") ) @@ -115,31 +116,31 @@ class BankMachine(Module): # 2. since we always go to the ACTIVATE state, we do not need # to assert track_close. If(self.precharge_timer.done, - self.cmd.valid.eq(1), - If(self.cmd.ready, + cmd.valid.eq(1), + If(cmd.ready, NextState("TRP") ), - self.cmd.ras_n.eq(0), - self.cmd.we_n.eq(0), - self.cmd.is_cmd.eq(1) + cmd.ras.eq(1), + cmd.we.eq(1), + cmd.is_cmd.eq(1) ) ) fsm.act("ACTIVATE", s_row_adr.eq(1), track_open.eq(1), - self.cmd.valid.eq(1), - self.cmd.is_cmd.eq(1), - If(self.cmd.ready, + cmd.valid.eq(1), + cmd.is_cmd.eq(1), + If(cmd.ready, NextState("TRCD") ), - self.cmd.ras_n.eq(0) + cmd.ras.eq(1) ) fsm.act("REFRESH", If(self.precharge_timer.done, self.refresh_gnt.eq(1), ), track_close.eq(1), - self.cmd.is_cmd.eq(1), + cmd.is_cmd.eq(1), If(~self.refresh_req, NextState("REGULAR") ) diff --git a/litedram/core/multiplexer.py b/litedram/core/multiplexer.py index bccb141..6feb55d 100644 --- a/litedram/core/multiplexer.py +++ b/litedram/core/multiplexer.py @@ -4,6 +4,7 @@ from operator import or_, and_ from litex.gen import * from litex.gen.genlib.roundrobin import * +from litex.soc.interconnect import stream from litex.soc.interconnect.csr import AutoCSR from litedram.common import * @@ -15,8 +16,9 @@ class _CommandChooser(Module): self.want_reads = Signal() self.want_writes = Signal() self.want_cmds = Signal() - # NB: cas_n/ras_n/we_n are 1 when valid is inactive - self.cmd = CommandRequestRW(len(requests[0].a), len(requests[0].ba)) + # NB: cas/ras/we are 0 when valid is inactive + self.cmd = cmd = stream.Endpoint(cmd_request_rw_layout(len(requests[0].a), + len(requests[0].ba))) # # # @@ -32,18 +34,18 @@ class _CommandChooser(Module): self.comb += valid.eq(Array(req.valid for req in requests)[rr.grant]) for name in ["a", "ba", "is_read", "is_write", "is_cmd"]: choices = Array(getattr(req, name) for req in requests) - self.comb += getattr(self.cmd, name).eq(choices[rr.grant]) - for name in ["cas_n", "ras_n", "we_n"]: + self.comb += getattr(cmd, name).eq(choices[rr.grant]) + for name in ["cas", "ras", "we"]: # we should only assert those signals when valid is 1 choices = Array(getattr(req, name) for req in requests) - self.comb += If(self.cmd.valid, getattr(self.cmd, name).eq(choices[rr.grant])) - self.comb += self.cmd.valid.eq(valid \ - & ((self.cmd.is_cmd & self.want_cmds) | ((self.cmd.is_read == self.want_reads) \ - & (self.cmd.is_write == self.want_writes)))) + self.comb += If(cmd.valid, getattr(cmd, name).eq(choices[rr.grant])) + self.comb += cmd.valid.eq(valid \ + & ((cmd.is_cmd & self.want_cmds) | ((cmd.is_read == self.want_reads) \ + & (cmd.is_write == self.want_writes)))) - self.comb += [If(self.cmd.valid & self.cmd.ready & (rr.grant == i), req.ready.eq(1)) + self.comb += [If(cmd.valid & cmd.ready & (rr.grant == i), req.ready.eq(1)) for i, req in enumerate(requests)] - self.comb += rr.ce.eq(self.cmd.ready) + self.comb += rr.ce.eq(cmd.ready) class _Steerer(Module): @@ -52,7 +54,7 @@ class _Steerer(Module): nph = len(dfi.phases) self.sel = [Signal(max=ncmd) for i in range(nph)] - ### + # # # def valid_and(cmd, attr): if not hasattr(cmd, "valid"): @@ -71,9 +73,9 @@ class _Steerer(Module): self.sync += [ phase.address.eq(Array(cmd.a for cmd in commands)[sel]), phase.bank.eq(Array(cmd.ba for cmd in commands)[sel]), - phase.cas_n.eq(Array(cmd.cas_n for cmd in commands)[sel]), - phase.ras_n.eq(Array(cmd.ras_n for cmd in commands)[sel]), - phase.we_n.eq(Array(cmd.we_n for cmd in commands)[sel]), + phase.cas_n.eq(~Array(cmd.cas for cmd in commands)[sel]), + phase.ras_n.eq(~Array(cmd.ras for cmd in commands)[sel]), + phase.we_n.eq(~Array(cmd.we for cmd in commands)[sel]), phase.rddata_en.eq(Array(valid_and(cmd, "is_read") for cmd in commands)[sel]), phase.wrdata_en.eq(Array(valid_and(cmd, "is_write") for cmd in commands)[sel]) ] @@ -100,7 +102,7 @@ class Multiplexer(Module, AutoCSR): ] # Command steering - nop = CommandRequest(geom_settings.addressbits, geom_settings.bankbits) + nop = Record(cmd_request_layout(geom_settings.addressbits, geom_settings.bankbits)) commands = [nop, choose_cmd.cmd, choose_req.cmd, refresher.cmd] # nop must be 1st (STEER_NOP, STEER_CMD, STEER_REQ, STEER_REFRESH) = range(4) steerer = _Steerer(commands, dfi) diff --git a/litedram/core/refresher.py b/litedram/core/refresher.py index 4979453..db4d0fa 100644 --- a/litedram/core/refresher.py +++ b/litedram/core/refresher.py @@ -8,7 +8,7 @@ class Refresher(Module): def __init__(self, a, ba, tRP, tREFI, tRFC, enable): self.req = Signal() self.ack = Signal() # 1st command 1 cycle after assertion of ack - self.cmd = cmd = CommandRequest(a, ba) + self.cmd = cmd = Record(cmd_request_layout(a, ba)) # # # @@ -19,19 +19,19 @@ class Refresher(Module): self.sync += [ cmd.a.eq(2**10), cmd.ba.eq(0), - cmd.cas_n.eq(1), - cmd.ras_n.eq(1), - cmd.we_n.eq(1), + cmd.cas.eq(0), + cmd.ras.eq(0), + cmd.we.eq(0), seq_done.eq(0) ] self.sync += timeline(seq_start, [ (1, [ - cmd.ras_n.eq(0), - cmd.we_n.eq(0) + cmd.ras.eq(1), + cmd.we.eq(1) ]), (1+tRP, [ - cmd.cas_n.eq(0), - cmd.ras_n.eq(0) + cmd.cas.eq(1), + cmd.ras.eq(1) ]), (1+tRP+tRFC, [ seq_done.eq(1) diff --git a/litedram/dfii.py b/litedram/dfii.py index 552c6a4..a1f8f8c 100644 --- a/litedram/dfii.py +++ b/litedram/dfii.py @@ -13,7 +13,7 @@ class PhaseInjector(Module, AutoCSR): self._wrdata = CSRStorage(len(phase.wrdata)) self._rddata = CSRStatus(len(phase.rddata)) - ### + # # # self.comb += [ If(self._command_issue.re, @@ -48,7 +48,7 @@ class DFIInjector(Module, AutoCSR): for n, phase in enumerate(inti.phases): setattr(self.submodules, "pi" + str(n), PhaseInjector(phase)) - ### + # # # self.comb += If(self._control.storage[0], self.slave.connect(self.master) diff --git a/litedram/phy/gensdrphy.py b/litedram/phy/gensdrphy.py index a455c9c..7f8389d 100644 --- a/litedram/phy/gensdrphy.py +++ b/litedram/phy/gensdrphy.py @@ -50,7 +50,7 @@ class GENSDRPHY(Module): self.dfi = Interface(addressbits, bankbits, databits) - ### + # # # # # Command/address diff --git a/litedram/phy/k7ddrphy.py b/litedram/phy/k7ddrphy.py index fa1e2e3..8456d45 100644 --- a/litedram/phy/k7ddrphy.py +++ b/litedram/phy/k7ddrphy.py @@ -43,7 +43,7 @@ class K7DDRPHY(Module, AutoCSR): self.dfi = Interface(addressbits, bankbits, 2*databits, nphases) - ### + # # # # Clock sd_clk_se = Signal() diff --git a/litedram/phy/s6ddrphy.py b/litedram/phy/s6ddrphy.py index 65e3146..515471e 100644 --- a/litedram/phy/s6ddrphy.py +++ b/litedram/phy/s6ddrphy.py @@ -68,7 +68,7 @@ class S6HalfRateDDRPHY(Module): self.clk4x_wr_strb = Signal() self.clk4x_rd_strb = Signal() - ### + # # # # sys_clk : system clk, used for dfi interface # sdram_half_clk : half rate sdram clk