diff --git a/src/main/scala/devices/xilinx/xilinxml507mig/XilinxML507MIG.scala b/src/main/scala/devices/xilinx/xilinxml507mig/XilinxML507MIG.scala index 32d584a..7052b42 100644 --- a/src/main/scala/devices/xilinx/xilinxml507mig/XilinxML507MIG.scala +++ b/src/main/scala/devices/xilinx/xilinxml507mig/XilinxML507MIG.scala @@ -3,35 +3,37 @@ package sifive.fpgashells.devices.xilinx.xilinxml507mig import Chisel._ -import freechips.rocketchip.config.{Field, Parameters} +import chisel3.core.{Input, Output} +import freechips.rocketchip.config.Parameters import freechips.rocketchip.diplomacy._ -import freechips.rocketchip.subsystem.BaseSubsystem import freechips.rocketchip.tilelink._ import freechips.rocketchip.util._ -case class MemoryML507Params( +case class XilinxML507MIGParams( address: Seq[AddressSet] ) -case object MemoryML507Key extends Field[MemoryML507Params] +class MemoryController extends BlackBox { + val io = IO(new Bundle { + val sys = new MemorySysIO + val ddr2 = new MemoryDDR2IO -trait HasMemoryML507 { this: BaseSubsystem => - val memory = LazyModule(new TLMemoryML507(p(MemoryML507Key))) + val request_addr = Input(UInt(28.W)) + val request_read = Input(Bool()) + val request_data = Input(UInt(256.W)) + val request_mask = Input(UInt(32.W)) + val request_valid = Input(Bool()) + val request_ready = Output(Bool()) - // The Fragmenter will not fragment messages <= 32 bytes, so all - // slaves have to support this size. 64 byte specifies the maximum - // supported transfer size that the slave side of the fragmenter supports - // against the master (here the main memory bus). Specifying alwaysMin as - // true results in all messages being fragmented to the minimal size - // (32 byte). In TL1 terms, slaves - // correspond roughly to managers and masters to clients (confusingly…). - val fragmenter = TLFragmenter(32, 64, alwaysMin=true) + val response_data = Output(UInt(256.W)) + val response_valid = Output(Bool()) + // no ready, as the mig does not wait + }) - // TODO: right TL/memory node chain? - memory.node := fragmenter := memBuses.head.toDRAMController(Some("ml507mig"))() + override def desiredName: String = "memory_controller" } -class TLMemoryML507(c: MemoryML507Params)(implicit p: Parameters) extends LazyModule { +class XilinxML507MIGToTL(c: XilinxML507MIGParams)(implicit p: Parameters) extends LazyModule { // Corresponds to MIG interface with 64 bit width and a burst length of 4 val width = 256 val beatBytes = width/8 // 32 byte (half a cache-line, fragmented) @@ -56,6 +58,15 @@ class TLMemoryML507(c: MemoryML507Params)(implicit p: Parameters) extends LazyMo // the data width (size signal, see below). lazy val module = new LazyModuleImp(this) { + val io = IO(new Bundle { + val port_sys = new MemorySysIO + val port_ddr2 = new MemoryDDR2IO + }) + + val controller = Module(new MemoryController) + io.port_sys <> controller.io.sys + io.port_ddr2 <> controller.io.ddr2 + // in: TLBundle, edge: TLEdgeIn val (in, edge) = node.in(0) @@ -102,3 +113,28 @@ class TLMemoryML507(c: MemoryML507Params)(implicit p: Parameters) extends LazyMo in.e.ready := Bool(true) } } + +class XilinxML507MIG(c : XilinxML507MIGParams)(implicit p: Parameters) extends LazyModule { + // The Fragmenter will not fragment messages <= 32 bytes, so all + // slaves have to support this size. 64 byte specifies the maximum + // supported transfer size that the slave side of the fragmenter supports + // against the master (here the main memory bus). Specifying alwaysMin as + // true results in all messages being fragmented to the minimal size + // (32 byte). In TL1 terms, slaves correspond roughly to managers and + // masters to clients (confusingly…). + val fragmenter = LazyModule(new TLFragmenter(32, 64, alwaysMin=true)) + val island = LazyModule(new XilinxML507MIGToTL(c)) + + val node: TLInwardNode = + island.node := fragmenter.node + + lazy val module = new LazyModuleImp(this) { + val io = IO(new Bundle { + val port_sys = new MemorySysIO + val port_ddr2 = new MemoryDDR2IO + }) + + io.port_sys <> island.module.io.port_sys + io.port_ddr2 <> island.module.io.port_ddr2 + } +} diff --git a/src/main/scala/devices/xilinx/xilinxml507mig/XilinxML507MIGPeriphery.scala b/src/main/scala/devices/xilinx/xilinxml507mig/XilinxML507MIGPeriphery.scala new file mode 100644 index 0000000..fee53d1 --- /dev/null +++ b/src/main/scala/devices/xilinx/xilinxml507mig/XilinxML507MIGPeriphery.scala @@ -0,0 +1,58 @@ +// See LICENSE.SiFive for license details. + +package sifive.fpgashells.devices.xilinx.xilinxml507mig + +import Chisel._ +import chisel3.core.{Input, Output} +import chisel3.experimental.Analog +import freechips.rocketchip.config.Field +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.subsystem.BaseSubsystem + +case object MemoryML507Key extends Field[XilinxML507MIGParams] + +trait HasMemoryML507 { this: BaseSubsystem => + val memory = LazyModule(new XilinxML507MIG(p(MemoryML507Key))) + + memory.node := memBuses.head.toDRAMController(Some("xilinxml507mig"))() +} + +class MemorySysIO extends Bundle { + val clk0 = Input(Clock()) + val clk90 = Input(Clock()) + val clkdiv0 = Input(Clock()) + val clk_locked = Input(Bool()) + val clk_idelay = Input(Clock()) + val reset = Input(Bool()) +} + +class MemoryDDR2IO extends Bundle { + val dq = Analog(64.W) + val a = Output(Bits(13.W)) + val ba = Output(Bits(2.W)) + val ras_n = Output(Bits(1.W)) + val cas_n = Output(Bits(1.W)) + val we_n = Output(Bits(1.W)) + val cs_n = Output(Bits(1.W)) + val odt = Output(Bits(1.W)) + val cke = Output(Bits(1.W)) + val dm = Output(Bits(8.W)) + val dqs = Analog(8.W) + val dqs_n = Analog(8.W) + val ck = Output(Bits(2.W)) + val ck_n = Output(Bits(2.W)) +} + +trait HasMemoryML507Bundle { + val ddr_sys: MemorySysIO + val ddr2: MemoryDDR2IO +} + +trait HasMemoryML507ModuleImp extends LazyModuleImp with HasMemoryML507Bundle { + val outer: HasMemoryML507 + val ddr_sys = IO(new MemorySysIO) + val ddr2 = IO(new MemoryDDR2IO) + + ddr_sys <> outer.memory.module.io.port_sys + ddr2 <> outer.memory.module.io.port_ddr2 +} diff --git a/src/main/scala/shell/xilinx/ML507Shell.scala b/src/main/scala/shell/xilinx/ML507Shell.scala index ecb2116..fb798a9 100644 --- a/src/main/scala/shell/xilinx/ML507Shell.scala +++ b/src/main/scala/shell/xilinx/ML507Shell.scala @@ -15,6 +15,7 @@ import sifive.blocks.devices.uart._ import sifive.blocks.devices.chiplink._ import sifive.blocks.devices.terminal._ +import sifive.fpgashells.devices.xilinx.xilinxml507mig._ import sifive.fpgashells.ip.xilinx.{PowerOnResetFPGAOnly, sdio_spi_bridge, ml507_dvi_clock, ml507_sys_clock, vc707reset} //------------------------------------------------------------------------- @@ -79,6 +80,7 @@ abstract class ML507Shell(implicit val p: Parameters) extends RawModule { val reset_led = IO(Output(Bool())) val dvi = IO(new TerminalDVIIO) + val ddr2 = IO(new MemoryDDR2IO) //----------------------------------------------------------------------- // Wire declrations @@ -159,6 +161,14 @@ abstract class ML507Shell(implicit val p: Parameters) extends RawModule { dut.terminal.reset := dvi_reset } + //----------------------------------------------------------------------- + // Memory controller + //----------------------------------------------------------------------- + + def connectDDRMemory(dut: HasMemoryML507ModuleImp): Unit = { + ddr2 <> dut.ddr2 + } + //----------------------------------------------------------------------- // UART //-----------------------------------------------------------------------