Compare commits
5 Commits
79b53cf2ae
...
7e53be49f9
Author | SHA1 | Date | |
---|---|---|---|
7e53be49f9 | |||
77694a6741 | |||
589e9960c0 | |||
2707fa59a4 | |||
3797385a8c |
@ -0,0 +1,147 @@
|
|||||||
|
// See LICENSE.SiFive for license details.
|
||||||
|
|
||||||
|
package sifive.fpgashells.devices.xilinx.xilinxml507mig
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import chisel3.core.{Input, Output}
|
||||||
|
import freechips.rocketchip.config.Parameters
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import freechips.rocketchip.subsystem.{AsynchronousCrossing, HasCrossing}
|
||||||
|
import freechips.rocketchip.tilelink._
|
||||||
|
import freechips.rocketchip.util._
|
||||||
|
|
||||||
|
case class XilinxML507MIGParams(
|
||||||
|
address: Seq[AddressSet]
|
||||||
|
)
|
||||||
|
|
||||||
|
class MemoryController extends BlackBox {
|
||||||
|
val io = IO(new Bundle {
|
||||||
|
val sys = new MemorySysIO
|
||||||
|
val ddr2 = new MemoryDDR2IO
|
||||||
|
|
||||||
|
val request_addr = Input(UInt(28.W))
|
||||||
|
val request_type = 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())
|
||||||
|
|
||||||
|
val response_data = Output(UInt(256.W))
|
||||||
|
val response_valid = Output(Bool())
|
||||||
|
// no ready, as the mig does not wait
|
||||||
|
})
|
||||||
|
|
||||||
|
override def desiredName: String = "memory_controller"
|
||||||
|
}
|
||||||
|
|
||||||
|
class XilinxML507MIGToTL(c: XilinxML507MIGParams)(implicit p: Parameters) extends LazyModule with HasCrossing {
|
||||||
|
// 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)
|
||||||
|
val crossing = AsynchronousCrossing(8)
|
||||||
|
|
||||||
|
val device = new MemoryDevice
|
||||||
|
val node = TLManagerNode(
|
||||||
|
Seq(TLManagerPortParameters(
|
||||||
|
Seq(TLManagerParameters(
|
||||||
|
address = c.address,
|
||||||
|
resources = device.reg,
|
||||||
|
regionType = RegionType.UNCACHED,
|
||||||
|
executable = true,
|
||||||
|
supportsGet = TransferSizes(1, beatBytes),
|
||||||
|
supportsPutFull = TransferSizes(1, beatBytes),
|
||||||
|
fifoId = Some(0) // in-order
|
||||||
|
)),
|
||||||
|
beatBytes = beatBytes
|
||||||
|
))
|
||||||
|
)
|
||||||
|
// We could possibly also support supportsPutPartial, as we need support
|
||||||
|
// for masks anyway because of the possibility of transfers smaller that
|
||||||
|
// 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)
|
||||||
|
|
||||||
|
// Due to the Fragmenter defined above, all messages are 32 bytes or
|
||||||
|
// smaller. The data signal of the TL channels is also 32 bytes, so
|
||||||
|
// all messages will be transfered in a single beat.
|
||||||
|
// Also, TL guarantees (see TL$4.6) that the payload of a data message
|
||||||
|
// is always aligned to the width of the beat, e.g. in case of a 32
|
||||||
|
// byte data signal, data[7:0] will always have address 0x***00000 and
|
||||||
|
// data[255:247] address 0x***11111. It is also guaranteed that the
|
||||||
|
// mask bits always correctly reflect the active bytes inside the beat
|
||||||
|
// with respect to the size and address.
|
||||||
|
// So we can directly forward the mask, (relative) address and possibly
|
||||||
|
// data to the MIG interface.
|
||||||
|
// Put requests can be acknowledged as soon as they are latched into
|
||||||
|
// the write fifo of the MIG (possibly combinatorily).
|
||||||
|
// For read requests, we have to store the source id and size in a
|
||||||
|
// queue for later acknowledgment.
|
||||||
|
// We are ready if both the MIG and the response data queue are not
|
||||||
|
// full.
|
||||||
|
|
||||||
|
// Widths of the A channel:
|
||||||
|
// addressBits: 32
|
||||||
|
// dataBits: 256
|
||||||
|
// sourceBits: 6
|
||||||
|
// sinkBits: 1
|
||||||
|
// sizeBits: 3
|
||||||
|
|
||||||
|
// source (from): in.a.bits.source
|
||||||
|
// adresse (to): edgeIn.address(in.a.bits)
|
||||||
|
// size: edgeIn.size(in.a.bits)
|
||||||
|
// isPut: edgeIn.hasData(in.a.bits)
|
||||||
|
|
||||||
|
// bits kommt von Decoupled: ready, valid + bits
|
||||||
|
|
||||||
|
println("a parameters: " + in.a.bits.params)
|
||||||
|
|
||||||
|
in.a.ready := Bool(false)
|
||||||
|
in.d.valid := Bool(false)
|
||||||
|
|
||||||
|
// Tie off unused channels
|
||||||
|
in.b.valid := Bool(false)
|
||||||
|
in.c.ready := Bool(true)
|
||||||
|
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 := island.crossTLIn := 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
|
||||||
|
|
||||||
|
// The MIGToTL module lives in a separate clock domain together with
|
||||||
|
// the MIG, which is why it is called "island".
|
||||||
|
island.module.clock := io.port_sys.clk0
|
||||||
|
island.module.reset := io.port_sys.reset
|
||||||
|
}
|
||||||
|
}
|
@ -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
|
||||||
|
}
|
@ -114,6 +114,17 @@ class ml507_dvi_clock extends BlackBox {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ml507_ddr2_clock extends BlackBox {
|
||||||
|
val io = new Bundle {
|
||||||
|
val CLKIN_P_IN = Clock(INPUT)
|
||||||
|
val CLKIN_N_IN = Clock(INPUT)
|
||||||
|
val CLK0_OUT = Clock(OUTPUT)
|
||||||
|
val CLK90_OUT = Clock(OUTPUT)
|
||||||
|
val CLKDV_OUT = Clock(OUTPUT)
|
||||||
|
val LOCKED_OUT = Bool(OUTPUT)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// vc707_sys_clock_mmcm
|
// vc707_sys_clock_mmcm
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
|
@ -15,7 +15,8 @@ import sifive.blocks.devices.uart._
|
|||||||
import sifive.blocks.devices.chiplink._
|
import sifive.blocks.devices.chiplink._
|
||||||
import sifive.blocks.devices.terminal._
|
import sifive.blocks.devices.terminal._
|
||||||
|
|
||||||
import sifive.fpgashells.ip.xilinx.{PowerOnResetFPGAOnly, sdio_spi_bridge, ml507_dvi_clock, ml507_sys_clock, vc707reset}
|
import sifive.fpgashells.devices.xilinx.xilinxml507mig._
|
||||||
|
import sifive.fpgashells.ip.xilinx.{PowerOnResetFPGAOnly, sdio_spi_bridge, ml507_ddr2_clock, ml507_dvi_clock, ml507_sys_clock, vc707reset}
|
||||||
|
|
||||||
//-------------------------------------------------------------------------
|
//-------------------------------------------------------------------------
|
||||||
// ML507Shell
|
// ML507Shell
|
||||||
@ -56,6 +57,10 @@ abstract class ML507Shell(implicit val p: Parameters) extends RawModule {
|
|||||||
// 100Mhz sysclk
|
// 100Mhz sysclk
|
||||||
val sys_clock = IO(Input(Clock()))
|
val sys_clock = IO(Input(Clock()))
|
||||||
|
|
||||||
|
// 200MHz ddrclk
|
||||||
|
val ddr_clock_p = IO(Input(Clock()))
|
||||||
|
val ddr_clock_n = IO(Input(Clock()))
|
||||||
|
|
||||||
// active high async reset
|
// active high async reset
|
||||||
val reset = IO(Input(Bool()))
|
val reset = IO(Input(Bool()))
|
||||||
|
|
||||||
@ -79,6 +84,7 @@ abstract class ML507Shell(implicit val p: Parameters) extends RawModule {
|
|||||||
val reset_led = IO(Output(Bool()))
|
val reset_led = IO(Output(Bool()))
|
||||||
|
|
||||||
val dvi = IO(new TerminalDVIIO)
|
val dvi = IO(new TerminalDVIIO)
|
||||||
|
val ddr2 = IO(new MemoryDDR2IO)
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
// Wire declrations
|
// Wire declrations
|
||||||
@ -95,6 +101,12 @@ abstract class ML507Shell(implicit val p: Parameters) extends RawModule {
|
|||||||
val dvi_clock = Wire(Clock())
|
val dvi_clock = Wire(Clock())
|
||||||
val dvi_reset = Wire(Bool())
|
val dvi_reset = Wire(Bool())
|
||||||
|
|
||||||
|
val ddr_clk0 = Wire(Clock())
|
||||||
|
val ddr_clk90 = Wire(Clock())
|
||||||
|
val ddr_clkdiv0 = Wire(Clock())
|
||||||
|
val ddr_clk_locked = Wire(Bool())
|
||||||
|
val ddr_reset = Wire(Bool())
|
||||||
|
|
||||||
val sd_spi_sck = Wire(Bool())
|
val sd_spi_sck = Wire(Bool())
|
||||||
val sd_spi_cs = Wire(Bool())
|
val sd_spi_cs = Wire(Bool())
|
||||||
val sd_spi_dq_i = Wire(Vec(4, Bool()))
|
val sd_spi_dq_i = Wire(Vec(4, Bool()))
|
||||||
@ -124,9 +136,19 @@ abstract class ML507Shell(implicit val p: Parameters) extends RawModule {
|
|||||||
ml507_dvi_clock.io.CLKIN_IN := sys_clock
|
ml507_dvi_clock.io.CLKIN_IN := sys_clock
|
||||||
dvi_clock := ml507_dvi_clock.io.CLKFX_OUT
|
dvi_clock := ml507_dvi_clock.io.CLKFX_OUT
|
||||||
|
|
||||||
|
// 200 MHz (DDR2 and IDELAY clock)
|
||||||
|
val ml507_ddr2_clock = Module(new ml507_ddr2_clock)
|
||||||
|
ml507_ddr2_clock.io.CLKIN_P_IN := ddr_clock_p
|
||||||
|
ml507_ddr2_clock.io.CLKIN_N_IN := ddr_clock_n
|
||||||
|
ddr_clk0 := ml507_ddr2_clock.io.CLK0_OUT
|
||||||
|
ddr_clk90 := ml507_ddr2_clock.io.CLK90_OUT
|
||||||
|
ddr_clkdiv0 := ml507_ddr2_clock.io.CLKDV_OUT
|
||||||
|
ddr_clk_locked := ml507_ddr2_clock.io.LOCKED_OUT
|
||||||
|
|
||||||
// Clocks locked?
|
// Clocks locked?
|
||||||
clk_locked := ml507_sys_clock.io.LOCKED_OUT &
|
clk_locked := ml507_sys_clock.io.LOCKED_OUT &
|
||||||
ml507_dvi_clock.io.LOCKED_OUT
|
ml507_dvi_clock.io.LOCKED_OUT &
|
||||||
|
ddr_clk_locked
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
// System reset
|
// System reset
|
||||||
@ -138,7 +160,8 @@ abstract class ML507Shell(implicit val p: Parameters) extends RawModule {
|
|||||||
val safe_reset = Module(new vc707reset)
|
val safe_reset = Module(new vc707reset)
|
||||||
|
|
||||||
safe_reset.io.areset := do_reset
|
safe_reset.io.areset := do_reset
|
||||||
safe_reset.io.clock1 := dut_clock
|
safe_reset.io.clock1 := ddr_clk0
|
||||||
|
ddr_reset := safe_reset.io.reset1
|
||||||
safe_reset.io.clock2 := dut_clock
|
safe_reset.io.clock2 := dut_clock
|
||||||
safe_reset.io.clock3 := dvi_clock
|
safe_reset.io.clock3 := dvi_clock
|
||||||
dvi_reset := safe_reset.io.reset3
|
dvi_reset := safe_reset.io.reset3
|
||||||
@ -159,6 +182,21 @@ abstract class ML507Shell(implicit val p: Parameters) extends RawModule {
|
|||||||
dut.terminal.reset := dvi_reset
|
dut.terminal.reset := dvi_reset
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// Memory controller
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
def connectDDRMemory(dut: HasMemoryML507ModuleImp): Unit = {
|
||||||
|
ddr2 <> dut.ddr2
|
||||||
|
|
||||||
|
dut.ddr_sys.clk0 := ddr_clk0
|
||||||
|
dut.ddr_sys.clk90 := ddr_clk90
|
||||||
|
dut.ddr_sys.clkdiv0 := ddr_clkdiv0
|
||||||
|
dut.ddr_sys.clk_locked := ddr_clk_locked
|
||||||
|
dut.ddr_sys.clk_idelay := ddr_clk0
|
||||||
|
dut.ddr_sys.reset := ddr_reset
|
||||||
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
// UART
|
// UART
|
||||||
//-----------------------------------------------------------------------
|
//-----------------------------------------------------------------------
|
||||||
|
Loading…
Reference in New Issue
Block a user