From 5bc840b9c115936862a7f38ac11a25d13833f8d5 Mon Sep 17 00:00:00 2001 From: Sebastien Bourdeauducq Date: Fri, 17 Feb 2012 23:50:10 +0100 Subject: [PATCH] DFI injector (untested) --- milkymist/dfii/__init__.py | 112 +++++++++++++++++++++++++++++++++++++ software/include/hw/dfii.h | 46 +++++++++++++++ top.py | 19 +++++-- 3 files changed, 173 insertions(+), 4 deletions(-) create mode 100644 milkymist/dfii/__init__.py create mode 100644 software/include/hw/dfii.h diff --git a/milkymist/dfii/__init__.py b/milkymist/dfii/__init__.py new file mode 100644 index 000000000..429262006 --- /dev/null +++ b/milkymist/dfii/__init__.py @@ -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 index 000000000..9a58faac9 --- /dev/null +++ b/software/include/hw/dfii.h @@ -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 . + */ + +#ifndef __HW_DFII_H +#define __HW_DFII_H + +#include + +#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 9452f7a46..3e97119d8 100644 --- 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 ]) #