lasmicon: remove limitations on the number of phases
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Mon, 26 Aug 2013 13:01:48 +0000 (15:01 +0200)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Mon, 26 Aug 2013 19:14:35 +0000 (21:14 +0200)
milkymist/lasmicon/__init__.py
milkymist/lasmicon/bankmachine.py
milkymist/lasmicon/multiplexer.py
milkymist/s6ddrphy/__init__.py
tb/lasmicon/common.py

index ffcb8e3a1447320839e0be659899c6072b4dae50..2e32d683d0327a7a54a04365a12c77735922b31b 100644 (file)
@@ -7,7 +7,7 @@ from milkymist.lasmicon.refresher import *
 from milkymist.lasmicon.bankmachine import *
 from milkymist.lasmicon.multiplexer import *
 
-PhySettings = namedtuple("PhySettings", "memtype dfi_d nphases rdphase wrphase cl read_latency write_latency")
+PhySettings = namedtuple("PhySettings", "memtype dfi_d nphases rdphase wrphase rdcmdphase wrcmdphase cl read_latency write_latency")
 
 class GeomSettings(namedtuple("_GeomSettings", "bank_a row_a col_a")):
        def __init__(self, *args, **kwargs):
@@ -18,7 +18,10 @@ TimingSettings = namedtuple("TimingSettings", "tRP tRCD tWR tWTR tREFI tRFC" \
 
 class LASMIcon(Module):
        def __init__(self, phy_settings, geom_settings, timing_settings):
-               burst_length = phy_settings.nphases*2 # command multiplication*DDR
+               if phy_settings.memtype in ["SDR"]:
+                       burst_length = phy_settings.nphases*1 # command multiplication*SDR
+               elif phy_settings.memtype in ["DDR", "LPDDR", "DDR2", "DDR3"]:
+                       burst_length = phy_settings.nphases*2 # command multiplication*DDR
                address_align = log2_int(burst_length)
 
                self.dfi = dfi.Interface(geom_settings.mux_a,
index 536e779270a036fc59058e6829b1d09846b5d4b8..6db44d196e6e740c5e1b00c14574434e29d1311e 100644 (file)
@@ -122,19 +122,22 @@ class BankMachine(Module):
                                self.cmd.stb.eq(1),
                                If(self.cmd.ack, NextState("TRP")),
                                self.cmd.ras_n.eq(0),
-                               self.cmd.we_n.eq(0)
+                               self.cmd.we_n.eq(0),
+                               self.cmd.is_cmd.eq(1)
                        )
                )
                fsm.act("ACTIVATE",
                        s_row_adr.eq(1),
                        track_open.eq(1),
                        self.cmd.stb.eq(1),
+                       self.cmd.is_cmd.eq(1),
                        If(self.cmd.ack, NextState("TRCD")),
                        self.cmd.ras_n.eq(0)
                )
                fsm.act("REFRESH",
                        self.refresh_gnt.eq(precharge_ok),
                        track_close.eq(1),
+                       self.cmd.is_cmd.eq(1),
                        If(~self.refresh_req, NextState("REGULAR"))
                )
                fsm.delayed_enter("TRP", "ACTIVATE", timing_settings.tRP-1)
index d0cfa48b12cfc1907aa8bd75ca244d535482412d..7ff2170b6c932b834bede5b0cf5342cc27e47c56 100644 (file)
@@ -19,6 +19,7 @@ class CommandRequestRW(CommandRequest):
                CommandRequest.__init__(self, a, ba)
                self.stb = Signal()
                self.ack = Signal()
+               self.is_cmd = Signal()
                self.is_read = Signal()
                self.is_write = Signal()
 
@@ -26,6 +27,7 @@ class _CommandChooser(Module):
        def __init__(self, requests):
                self.want_reads = Signal()
                self.want_writes = Signal()
+               self.want_cmds = Signal()
                # NB: cas_n/ras_n/we_n are 1 when stb is inactive
                self.cmd = CommandRequestRW(flen(requests[0].a), flen(requests[0].ba))
        
@@ -34,12 +36,12 @@ class _CommandChooser(Module):
                rr = RoundRobin(len(requests), SP_CE)
                self.submodules += rr
                
-               self.comb += [rr.request[i].eq(req.stb & ((req.is_read == self.want_reads) | (req.is_write == self.want_writes)))
+               self.comb += [rr.request[i].eq(req.stb & ((req.is_cmd & self.want_cmds) | ((req.is_read == self.want_reads) | (req.is_write == self.want_writes))))
                        for i, req in enumerate(requests)]
                
                stb = Signal()
                self.comb += stb.eq(Array(req.stb for req in requests)[rr.grant])
-               for name in ["a", "ba", "is_read", "is_write"]:
+               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"]:
@@ -47,8 +49,8 @@ class _CommandChooser(Module):
                        choices = Array(getattr(req, name) for req in requests)
                        self.comb += If(self.cmd.stb, getattr(self.cmd, name).eq(choices[rr.grant]))
                self.comb += self.cmd.stb.eq(stb \
-                       & (self.cmd.is_read == self.want_reads) \
-                       & (self.cmd.is_write == self.want_writes))
+                       & ((self.cmd.is_cmd & self.want_cmds) | ((self.cmd.is_read == self.want_reads) \
+                       & (self.cmd.is_write == self.want_writes))))
                
                self.comb += [If(self.cmd.stb & self.cmd.ack & (rr.grant == i), req.ack.eq(1))
                        for i, req in enumerate(requests)]
@@ -85,8 +87,6 @@ class _Steerer(Module):
 class Multiplexer(Module, AutoCSR):
        def __init__(self, phy_settings, geom_settings, timing_settings, bank_machines, refresher, dfi, lasmic):
                assert(phy_settings.nphases == len(dfi.phases))
-               if phy_settings.nphases != 2:
-                       raise NotImplementedError("TODO: multiplexer only supports 2 phases")
        
                # Command choosing
                requests = [bm.cmd for bm in bank_machines]
@@ -96,6 +96,11 @@ class Multiplexer(Module, AutoCSR):
                        choose_cmd.want_reads.eq(0),
                        choose_cmd.want_writes.eq(0)
                ]
+               if phy_settings.nphases == 1:
+                       self.comb += [
+                               choose_cmd.want_cmds.eq(1),
+                               choose_req.want_cmds.eq(1)
+                       ]       
                self.submodules += choose_cmd, choose_req
                
                # Command steering
@@ -148,14 +153,32 @@ class Multiplexer(Module, AutoCSR):
                
                # Control FSM
                fsm = FSM()
+               (STEER_WRITE, STEER_READ) = range(2)
+               
+               def steerer_sel(steerer, phy_settings, r_w_n):
+                       r = []
+                       for i in range(phy_settings.nphases):
+                               s = steerer.sel[i].eq(STEER_NOP)
+                               if r_w_n:
+                                       if i == phy_settings.rdphase:
+                                               s = steerer.sel[i].eq(STEER_REQ)
+                                       elif i == phy_settings.wrcmdphase:
+                                               s = steerer.sel[i].eq(STEER_CMD)
+                               else:
+                                       if i == phy_settings.wrphase:
+                                               s = steerer.sel[i].eq(STEER_REQ)
+                                       elif i == phy_settings.rdcmdphase:
+                                               s = steerer.sel[i].eq(STEER_CMD)
+                               r.append(s)
+                       return r
+
                self.submodules += fsm
                fsm.act("READ",
                        read_time_en.eq(1),
                        choose_req.want_reads.eq(1),
                        choose_cmd.cmd.ack.eq(1),
                        choose_req.cmd.ack.eq(1),
-                       steerer.sel[1-phy_settings.rdphase].eq(STEER_CMD),
-                       steerer.sel[phy_settings.rdphase].eq(STEER_REQ),
+                       steerer_sel(steerer, phy_settings, STEER_READ),
                        If(write_available,
                                # TODO: switch only after several cycles of ~read_available?
                                If(~read_available | max_read_time, NextState("RTW"))
@@ -167,8 +190,7 @@ class Multiplexer(Module, AutoCSR):
                        choose_req.want_writes.eq(1),
                        choose_cmd.cmd.ack.eq(1),
                        choose_req.cmd.ack.eq(1),
-                       steerer.sel[1-phy_settings.wrphase].eq(STEER_CMD),
-                       steerer.sel[phy_settings.wrphase].eq(STEER_REQ),
+                       steerer_sel(steerer, phy_settings, STEER_WRITE),
                        If(read_available,
                                If(~write_available | max_write_time, NextState("WTR"))
                        ),
index e079987d2180e836da679c0621aef5c35456f719..a1491f5a060af1dd828c695c5a957af482627aae 100644 (file)
@@ -43,6 +43,8 @@ class S6DDRPHY(Module):
                        nphases=nphases,
                        rdphase=0,
                        wrphase=1,
+                       rdcmdphase=1,
+                       wrcmdphase=0,
                        cl=cl,
                        read_latency=5,
                        write_latency=0
index f145ef56f3e3df47fb7ad9e447b77358761f1f87..d7acd5c1eeb9f8e27772d288c249b8be87064076 100644 (file)
@@ -21,6 +21,8 @@ sdram_phy = lasmicon.PhySettings(
        nphases=2,
        rdphase=0,
        wrphase=1,
+       rdcmdphase=1,
+       wrcmdphase=0,
        cl=3,
        read_latency=5,
        write_latency=0