DFI injector (untested)
authorSebastien Bourdeauducq <sebastien@milkymist.org>
Fri, 17 Feb 2012 22:50:10 +0000 (23:50 +0100)
committerSebastien Bourdeauducq <sebastien@milkymist.org>
Fri, 17 Feb 2012 22:50:10 +0000 (23:50 +0100)
milkymist/dfii/__init__.py [new file with mode: 0644]
software/include/hw/dfii.h [new file with mode: 0644]
top.py

diff --git a/milkymist/dfii/__init__.py b/milkymist/dfii/__init__.py
new file mode 100644 (file)
index 0000000..4292620
--- /dev/null
@@ -0,0 +1,112 @@
+from migen.fhdl.structure import *
+from migen.bus import dfi
+from migen.bank.description import *
+from migen.bank import csrgen
+
+def _data_en(trigger, output, delay, duration):
+       dcounter = Signal(BV(4))
+       dce = Signal()
+       return [
+               If(trigger,
+                       dcounter.eq(delay),
+                       dce.eq(1)
+               ).Elif(dce,
+                       dcounter.eq(dcounter - 1),
+                       If(dcounter == 0,
+                               If(~output,
+                                       output.eq(1),
+                                       dcounter.eq(duration)
+                               ).Else(
+                                       output.eq(0),
+                                       dce.eq(0)
+                               )
+                       )
+               )
+       ]
+
+class DFIInjector:
+       def __init__(self, csr_address, a, ba, d, nphases=1):
+               self._int = dfi.Interface(a, ba, d, nphases)
+               self.slave = dfi.Interface(a, ba, d, nphases)
+               self.master = dfi.Interface(a, ba, d, nphases)
+               
+               self._sel = Field("sel")
+               self._cke = Field("cke")
+               self._control = RegisterFields("control", [self._sel, self._cke])
+               
+               self._cs = Field("cs", 1, WRITE_ONLY, READ_ONLY)
+               self._we = Field("we", 1, WRITE_ONLY, READ_ONLY)
+               self._cas = Field("cas", 1, WRITE_ONLY, READ_ONLY)
+               self._ras = Field("ras", 1, WRITE_ONLY, READ_ONLY)
+               self._rddata = Field("rddata", 1, WRITE_ONLY, READ_ONLY)
+               self._wrdata = Field("wrdata", 1, WRITE_ONLY, READ_ONLY)
+               self._command = RegisterFields("command",
+                       [self._cs, self._we, self._cas, self._ras, self._rddata, self._wrdata])
+               
+               self._address = RegisterField("address", a)
+               self._baddress = RegisterField("baddress", ba)
+               
+               self._rddelay = RegisterField("rddelay", 4, reset=5)
+               self._rdduration = RegisterField("rdduration", 3, reset=0)
+               self._wrdelay = RegisterField("wrdelay", 4, reset=3)
+               self._wrduration = RegisterField("wrduration", 3, reset=0)
+               
+               self.bank = csrgen.Bank([
+                               self._control, self._command,
+                               self._address, self._baddress,
+                               self._rddelay, self._rdduration,
+                               self._wrdelay, self._wrduration
+                       ], address=csr_address)
+       
+       def get_fragment(self):
+               comb = []
+               sync = []
+               
+               # mux
+               connect_int = dfi.interconnect_stmts(self._int, self.master)
+               connect_slave = dfi.interconnect_stmts(self.slave, self.master)
+               comb.append(If(self._sel.r, *connect_slave).Else(*connect_int))
+               
+               # phases
+               rddata_en = Signal()
+               wrdata_en = Signal()
+               for phase in self._int.phases:
+                       comb += [
+                               phase.cke.eq(self._cke.r),
+                               phase.rddata_en.eq(rddata_en),
+                               phase.wrdata_en.eq(wrdata_en)
+                       ]
+               cmdphase = self._int.phases[0]
+               for phase in self._int.phases[1:]:
+                       comb += [
+                               phase.cs_n.eq(1),
+                               phase.we_n.eq(1),
+                               phase.cas_n.eq(1),
+                               phase.ras_n.eq(1)
+                               
+                       ]
+               
+               # commands
+               comb += [
+                       If(self._command.re,
+                               cmdphase.cs_n.eq(~self._cs.r),
+                               cmdphase.we_n.eq(~self._we.r),
+                               cmdphase.cas_n.eq(~self._cas.r),
+                               cmdphase.ras_n.eq(~self._ras.r)
+                       ).Else(
+                               cmdphase.cs_n.eq(1),
+                               cmdphase.we_n.eq(1),
+                               cmdphase.cas_n.eq(1),
+                               cmdphase.ras_n.eq(1)
+                       )
+               ]
+               
+               # data enables
+               sync += _data_en(self._command.re & self._rddata.r,
+                       rddata_en,
+                       self._rddelay.field.r, self._rdduration.field.r)
+               sync += _data_en(self._command.re & self._wrdata.r,
+                       wrdata_en,
+                       self._wrdelay.field.r, self._wrduration.field.r)
+               
+               return Fragment(comb, sync) + self.bank.get_fragment()
diff --git a/software/include/hw/dfii.h b/software/include/hw/dfii.h
new file mode 100644 (file)
index 0000000..9a58faa
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Milkymist SoC (Software)
+ * Copyright (C) 2012 Sebastien Bourdeauducq
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __HW_DFII_H
+#define __HW_DFII_H
+
+#include <hw/common.h>
+
+#define CSR_DFII_CONTROL               MMPTR(0xe0001000)
+
+#define DFII_CONTROL_SEL               (0x01)
+#define DFII_CONTROL_CKE               (0x02)
+
+#define CSR_DFII_COMMAND               MMPTR(0xe0001004)
+
+#define DFII_COMMAND_CS                        (0x01)
+#define DFII_COMMAND_WE                        (0x02)
+#define DFII_COMMAND_CAS               (0x04)
+#define DFII_COMMAND_RAS               (0x08)
+#define DFII_COMMAND_RDDATA            (0x10)
+#define DFII_COMMAND_WRDATA            (0x20)
+
+#define CSR_DFII_AH                    MMPTR(0xe0001008)
+#define CSR_DFII_AL                    MMPTR(0xe000100C)
+#define CSR_DFII_BA                    MMPTR(0xe0001010)
+
+#define CSR_DFII_RDDELAY               MMPTR(0xe0001014)
+#define CSR_DFII_RDDURATION            MMPTR(0xe0001018)
+#define CSR_DFII_WRDELAY               MMPTR(0xe000101C)
+#define CSR_DFII_WRDURATION            MMPTR(0xe0001020)
+
+#endif /* __HW_DFII_H */
diff --git a/top.py b/top.py
index 9452f7a46e09562b7da6da20d503870599098128..3e97119d828fcedeffca952c38b9a45cacdd9817 100644 (file)
--- a/top.py
+++ b/top.py
@@ -2,9 +2,9 @@ from fractions import Fraction
 
 from migen.fhdl.structure import *
 from migen.fhdl import verilog, autofragment
-from migen.bus import wishbone, asmibus, wishbone2asmi, csr, wishbone2csr
+from migen.bus import wishbone, asmibus, wishbone2asmi, csr, wishbone2csr, dfi
 
-from milkymist import m1crg, lm32, norflash, uart, sram, s6ddrphy
+from milkymist import m1crg, lm32, norflash, uart, sram, s6ddrphy, dfii
 import constraints
 
 MHz = 1000000
@@ -12,6 +12,10 @@ clk_freq = (83 + Fraction(1, 3))*MHz
 sram_size = 4096 # in bytes
 l2_size = 8192 # in bytes
 
+dfi_a = 13
+dfi_ba = 2
+dfi_d = 128 # TODO -> 64
+
 def ddrphy_clocking(crg, phy):
        names = [
                "clk2x_90",
@@ -31,11 +35,17 @@ def get():
        #
        # ASMI
        #
-       ddrphy0 = s6ddrphy.S6DDRPHY(1, 13, 2, 128)
        asmihub0 = asmibus.Hub(23, 128, 12) # TODO: get hub from memory controller
        asmiport_wb = asmihub0.get_port()
        asmihub0.finalize()
        
+       #
+       # DFI
+       #
+       ddrphy0 = s6ddrphy.S6DDRPHY(1, dfi_a, dfi_ba, dfi_d)
+       dfii0 = dfii.DFIInjector(2, dfi_a, dfi_ba, dfi_d, 2)
+       dficon0 = dfi.Interconnect(dfii0.master, ddrphy0.dfi)
+
        #
        # WISHBONE
        #
@@ -70,7 +80,8 @@ def get():
        uart0 = uart.UART(0, clk_freq, baud=115200)
        csrcon0 = csr.Interconnect(wishbone2csr0.csr, [
                uart0.bank.interface,
-               ddrphy0.bank.interface
+               ddrphy0.bank.interface,
+               dfii0.bank.interface
        ])
        
        #