DFI injector (untested)

This commit is contained in:
Sebastien Bourdeauducq 2012-02-17 23:50:10 +01:00
parent c38de34a21
commit 5bc840b9c1
3 changed files with 173 additions and 4 deletions

112
milkymist/dfii/__init__.py Normal file
View File

@ -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()

View File

@ -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 */

19
top.py
View File

@ -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
])
#