Skip to content

Commit

Permalink
fpga/src/main/scala/zcu102: Support Testharness for zcu102, and suppo…
Browse files Browse the repository at this point in the history
…rt h-ext, memory interface generator.
  • Loading branch information
Jerryy959 committed Nov 6, 2024
1 parent 1fafdbb commit 45113e4
Show file tree
Hide file tree
Showing 6 changed files with 613 additions and 0 deletions.
96 changes: 96 additions & 0 deletions fpga/src/main/scala/zcu102/Configs.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package chipyard.fpga.zcu102

import sys.process._

import org.chipsalliance.cde.config.{Config, Parameters}
import freechips.rocketchip.subsystem.{SystemBusKey, PeripheryBusKey, ControlBusKey, ExtMem}
import freechips.rocketchip.devices.debug.{DebugModuleKey, ExportDebug, JTAG}
import freechips.rocketchip.devices.tilelink.{DevNullParams, BootROMLocated}
import freechips.rocketchip.diplomacy.{RegionType, AddressSet}
import freechips.rocketchip.resources.{DTSModel, DTSTimebase}


import sifive.blocks.devices.spi.{PeripherySPIKey, SPIParams}
import sifive.blocks.devices.uart.{PeripheryUARTKey, UARTParams}

import sifive.fpgashells.shell.{DesignKey}
import sifive.fpgashells.shell.xilinx.{ZCU102ShellPMOD, ZCU102DDRSize}

import testchipip.serdes.{SerialTLKey}

import chipyard._
import chipyard.harness._

class WithDefaultPeripherals extends Config((site, here, up) => {
case PeripheryUARTKey => List(UARTParams(address = BigInt(0x64000000L)))
case PeripherySPIKey => List(SPIParams(rAddress = BigInt(0x64001000L)))
case ZCU102ShellPMOD => "SDIO"
})

class WithSystemModifications extends Config((site, here, up) => {
case DTSTimebase => BigInt((1e6).toLong)
case BootROMLocated(x) => up(BootROMLocated(x), site).map { p =>
// invoke makefile for sdboot
val freqMHz = (site(SystemBusKey).dtsFrequency.get / (1000 * 1000)).toLong
val make = s"make -C fpga/src/main/resources/zcu102/sdboot PBUS_CLK=${freqMHz} bin"
require (make.! == 0, "Failed to build bootrom")
p.copy(hang = 0x10000, contentFileName = s"./fpga/src/main/resources/zcu102/sdboot/build/sdboot.bin")
}
case ExtMem => up(ExtMem, site).map(x => x.copy(master = x.master.copy(size = site(ZCU102DDRSize)))) // set extmem to DDR size
case SerialTLKey => Nil // remove serialized tl port
})

// DOC include start: AbstractZCU102 and Rocket
class WithZCU102Tweaks extends Config(
// clocking
new chipyard.harness.WithAllClocksFromHarnessClockInstantiator ++
new chipyard.clocking.WithPassthroughClockGenerator ++
new chipyard.config.WithUniformBusFrequencies(100) ++
new WithFPGAFrequency(100) ++ // default 100MHz freq
// harness binders
new WithUART ++
new WithSPISDCard ++
new WithDDRMem ++
new WithJTAG ++
// io binders
new chipyard.iobinders.WithUARTTSIPunchthrough ++ // Is it correctly?
new chipyard.iobinders.WithSPIIOPunchthrough ++ // Is it correctly?
// other configuration
new WithDefaultPeripherals ++
new chipyard.config.WithTLBackingMemory ++ // use TL backing memory
new WithSystemModifications ++ // setup busses, use sdboot bootrom, setup ext. mem. size
// new chipyard.config.WithNoDebug ++ // remove debug module
new freechips.rocketchip.subsystem.WithoutTLMonitors ++
new freechips.rocketchip.subsystem.WithNMemoryChannels(1)
)

class RocketZCU102Config extends Config(
new WithFPGAFrequency(25) ++
new WithZCU102Tweaks ++
new chipyard.RocketConfig)
// DOC include end: AbstractZCU102 and Rocket

class RocketZCU102ConfigWithHyp extends Config(
new freechips.rocketchip.system.HypervisorConfig ++ // Would like to support H-ext
new WithFPGAFrequency(25) ++
new WithZCU102Tweaks ++
new chipyard.RocketConfig)

class BoomZCU102Config extends Config(
new WithFPGAFrequency(50) ++
new WithZCU102Tweaks ++
new chipyard.MegaBoomV3Config) //Changed to Small from Mega

class WithFPGAFrequency(fMHz: Double) extends Config(
new chipyard.harness.WithHarnessBinderClockFreqMHz(fMHz) ++
new chipyard.config.WithSystemBusFrequency(fMHz) ++
new chipyard.config.WithPeripheryBusFrequency(fMHz) ++
new chipyard.config.WithControlBusFrequency(fMHz) ++
new chipyard.config.WithFrontBusFrequency(fMHz) ++
new chipyard.config.WithMemoryBusFrequency(fMHz)
)

class WithFPGAFreq25MHz extends WithFPGAFrequency(25)
class WithFPGAFreq50MHz extends WithFPGAFrequency(50)
class WithFPGAFreq75MHz extends WithFPGAFrequency(75)
class WithFPGAFreq100MHz extends WithFPGAFrequency(100)
109 changes: 109 additions & 0 deletions fpga/src/main/scala/zcu102/CustomOverlays.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package chipyard.fpga.zcu102

import chisel3._

import freechips.rocketchip.diplomacy._
import org.chipsalliance.cde.config.{Parameters, Field}
import freechips.rocketchip.tilelink.{TLInwardNode, TLAsyncCrossingSink}
import freechips.rocketchip.prci._
import sifive.fpgashells.shell._
import sifive.fpgashells.ip.xilinx._
import sifive.fpgashells.shell.xilinx._
import sifive.fpgashells.clocks._
import sifive.fpgashells.devices.xilinx.xilinxzcu102mig.{XilinxZCU102MIGPads, XilinxZCU102MIGParams, XilinxZCU102MIG}

class SysClock2ZCU102PlacedOverlay(val shell: ZCU102ShellBasicOverlays, name: String, val designInput: ClockInputDesignInput, val shellInput: ClockInputShellInput)
extends LVDSClockInputXilinxPlacedOverlay(name, designInput, shellInput)
{
val node = shell { ClockSourceNode(freqMHz = 300, jitterPS = 50)(ValName(name)) }

shell { InModuleBody {
shell.xdc.addPackagePin(io.p, "AL8")
shell.xdc.addPackagePin(io.n, "AL7")
shell.xdc.addIOStandard(io.p, "DIFF_SSTL12")
shell.xdc.addIOStandard(io.n, "DIFF_SSTL12")
} }
}
class SysClock2ZCU102ShellPlacer(shell: ZCU102ShellBasicOverlays, val shellInput: ClockInputShellInput)(implicit val valName: ValName)
extends ClockInputShellPlacer[ZCU102ShellBasicOverlays]
{
def place(designInput: ClockInputDesignInput) = new SysClock2ZCU102PlacedOverlay(shell, valName.name, designInput, shellInput)
}

case object ZCU102DDR2Size extends Field[BigInt](0x40000000L * 2) // 2GB
class DDR2ZCU102PlacedOverlay(val shell: ZCU102FPGATestHarness, name: String, val designInput: DDRDesignInput, val shellInput: DDRShellInput)
extends DDRPlacedOverlay[XilinxZCU102MIGPads](name, designInput, shellInput)
{
val size = p(ZCU102DDRSize)

val migParams = XilinxZCU102MIGParams(address = AddressSet.misaligned(di.baseAddress, size))
val mig = LazyModule(new XilinxZCU102MIG(migParams))
val ioNode = BundleBridgeSource(() => mig.module.io.cloneType)
val topIONode = shell { ioNode.makeSink() }
val ddrUI = shell { ClockSourceNode(freqMHz = 300) }
val areset = shell { ClockSinkNode(Seq(ClockSinkParameters())) }
areset := designInput.wrangler := ddrUI

// since this uses a separate clk/rst need to put an async crossing
val asyncSink = LazyModule(new TLAsyncCrossingSink())
val migClkRstNode = BundleBridgeSource(() => new Bundle {
val clock = Output(Clock())
val reset = Output(Bool())
})
val topMigClkRstIONode = shell { migClkRstNode.makeSink() }

def overlayOutput = DDROverlayOutput(ddr = mig.node)
def ioFactory = new XilinxZCU102MIGPads(size)

InModuleBody {
ioNode.bundle <> mig.module.io

// setup async crossing
asyncSink.module.clock := migClkRstNode.bundle.clock
asyncSink.module.reset := migClkRstNode.bundle.reset
}

shell { InModuleBody {
require (shell.sys_clock2.get.isDefined, "Use of DDRZCU102Overlay depends on SysClock2ZCU102Overlay")
val (sys, _) = shell.sys_clock2.get.get.overlayOutput.node.out(0)
val (ui, _) = ddrUI.out(0)
val (ar, _) = areset.in(0)

// connect the async fifo sync to sys_clock2
topMigClkRstIONode.bundle.clock := sys.clock
topMigClkRstIONode.bundle.reset := sys.reset

val port = topIONode.bundle.port
io <> port
ui.clock := port.c0_ddr4_ui_clk
ui.reset := /*!port.mmcm_locked ||*/ port.c0_ddr4_ui_clk_sync_rst
port.c0_sys_clk_i := sys.clock.asUInt
port.sys_rst := sys.reset // pllReset
port.c0_ddr4_aresetn := !(ar.reset.asBool)

// This was just copied from the SiFive example, but it's hard to follow.
// The pins are emitted in the following order:
// adr[0->13], we_n, cas_n, ras_n, bg, ba[0->1], reset_n, act_n, ck_c, ck_t, cke, cs_n, odt, dq[0->63], dqs_c[0->7], dqs_t[0->7], dm_dbi_n[0->7]
val allddrpins = Seq(

"AM8", "AM9", "AP8", "AN8", "AK10", "AJ10", "AP9", "AN9", "AP10", "AP11", "AM10", "AL10", "AM11", "AL11", // adr[0->13]
"AJ7", "AL5", "AJ9", "AK7", // we_n, cas_n, ras_n, bg
"AK12", "AJ12", // ba[0->1]
"AH9", "AK8", "AP7", "AN7", "AM3", "AP2", "AK9", // reset_n, act_n, ck_c, ck_t, cke, cs_n, odt

"AK4", "AK5", "AN4", "AM4", "AP4", "AP5", "AM5", "AM6", "AK2", "AK3", "AL1", "AK1", "AN1", "AM1", "AP3", "AN3", // dq[0->15]
"AP6", "AL2", // dqs_c[0->1]
"AN6", "AL3", // dqs_t[0->1]
"AL6", "AN2") // dm_dbi_n[0->1]

(IOPin.of(io) zip allddrpins) foreach { case (io, pin) => shell.xdc.addPackagePin(io, pin) }
} }

shell.sdc.addGroup(pins = Seq(mig.island.module.blackbox.io.c0_ddr4_ui_clk))
}

class DDR2ZCU102ShellPlacer(shell: ZCU102FPGATestHarness, val shellInput: DDRShellInput)(implicit val valName: ValName)
extends DDRShellPlacer[ZCU102FPGATestHarness] {
def place(designInput: DDRDesignInput) = new DDR2ZCU102PlacedOverlay(shell, valName.name, designInput, shellInput)
}

127 changes: 127 additions & 0 deletions fpga/src/main/scala/zcu102/FMCUtil.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package chipyard.fpga.zcu102

import scala.collection.immutable.HashMap

// TODO: was typed by hand, so this needs a once-over before it can be considered trustworthy

object FMCMap {
// Take an FMC pin name and return the VCU118 package pin
// See https://www.xilinx.com/support/documentation/boards_and_kits/vcu118/ug1224-vcu118-eval-bd.pdf
// Pages 97-98
// Omitted pins are not connected to a GPIO
// ZCU106 Updates: https://docs.xilinx.com/v/u/en-US/ug1244-zcu106-eval-bd
// Pages 105-109
def apply(fmcPin: String): String = HashMap(
//pg 105
"A2" -> "J4",
"A3" -> "J3",
"A6" -> "F2",
"A7" -> "F1",
"A10" -> "K2",
"A11" -> "K1",
"A14" -> "L4",
"A15" -> "L3",
"A18" -> "P2",
"A19" -> "P1",
"A22" -> "H6",
"A23" -> "H5",
"A26" -> "F6",
"A27" -> "F5",
"A30" -> "K6",
"A31" -> "K5",
"A34" -> "M6",
"A35" -> "M5",
"A38" -> "P6",
"A39" -> "P5",
"B12" -> "M2",
"B13" -> "M1",
"B16" -> "T2",
"B17" -> "T1",
"B20" -> "L8",
"B21" -> "L7",
"B32" -> "N4",
"B33" -> "N3",
"B36" -> "R4",
"B37" -> "R3",
//pg 106
"C2" -> "G4",
"C3" -> "G3",
"C6" -> "H2",
"C7" -> "H1",
"C10" -> "AC2",
"C11" -> "AC1",
"C14" -> "W5",
"C15" -> "W4",
"C18" -> "AC7",
"C19" -> "AC6",
"C22" -> "N9",
"C23" -> "N8",
"C26" -> "M10",
"C27" -> "L10",
"D4" -> "G8",
"D5" -> "G7",
"D8" -> "AB4",
"D9" -> "AC4",
"D11" -> "AB3",
"D12" -> "AC3",
"D14" -> "W2",
"D15" -> "W1",
"D17" -> "AB8",
"D18" -> "AC8",
"D20" -> "P11",
"D21" -> "N11",
"D23" -> "L16",
"D24" -> "K16",
"D26" -> "L15",
"D27" -> "K15",
//pg 108
"G2" -> "T8",
"G3" -> "R8",
"G6" -> "Y4",
"G7" -> "Y3",
"G9" -> "Y2",
"G10" -> "Y1",
"G12" -> "V4",
"G13" -> "V3",
"G15" -> "W7",
"G16" -> "W6",
"G18" -> "Y12",
"G19" -> "AA12",
"G21" -> "N13",
"G22" -> "M13",
"G24" -> "M15",
"G25" -> "M14",
"G27" -> "M11",
"G28" -> "L11",
"G30" -> "U9",
"G31" -> "U8",
"G33" -> "V8",
"G34" -> "V7",
"G36" -> "V12",
"G37" -> "V11",
"H4" -> "AA7",
"H5" -> "AA6",
"H7" -> "V2",
"H8" -> "V1",
"H10" -> "AA2",
"H11" -> "AA1",
"H13" -> "U5",
"H14" -> "U4",
"H16" -> "AB6",
"H17" -> "AB5",
"H19" -> "Y10",
"H20" -> "Y9",
"H22" -> "L13",
"H23" -> "K13",
"H25" -> "P12",
"H26" -> "N12",
"H28" -> "L12",
"H29" -> "K12",
"H31" -> "T7",
"H32" -> "T6",
"H34" -> "V6",
"H35" -> "U6",
"H37" -> "U11",
"H38" -> "T11"
)(fmcPin)
}
52 changes: 52 additions & 0 deletions fpga/src/main/scala/zcu102/HarnessBinders.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package chipyard.fpga.zcu102

import chisel3._
import chisel3.experimental.{BaseModule}

import org.chipsalliance.diplomacy.nodes.{HeterogeneousBag}
import freechips.rocketchip.tilelink.{TLBundle}

import sifive.blocks.devices.uart.{UARTPortIO}
import sifive.blocks.devices.spi.{HasPeripherySPI, SPIPortIO}

import chipyard._
import chipyard.harness._
import chipyard.iobinders._

/*** UART ***/
class WithUART extends HarnessBinder({
case (th: ZCU102FPGATestHarnessImp, port: UARTPort, chipId: Int) => {
th.zcu102Outer.io_uart_bb.bundle <> port.io
}
})

/*** SPI ***/
class WithSPISDCard extends HarnessBinder({
case (th: ZCU102FPGATestHarnessImp, port: SPIPort, chipId: Int) => {
th.zcu102Outer.io_spi_bb.bundle <> port.io
}
})

/*** Experimental DDR ***/
class WithDDRMem extends HarnessBinder({
case (th: ZCU102FPGATestHarnessImp, port: TLMemPort, chipId: Int) => {
val bundles = th.zcu102Outer.ddrClient.out.map(_._1)
val ddrClientBundle = Wire(new HeterogeneousBag(bundles.map(_.cloneType)))
bundles.zip(ddrClientBundle).foreach { case (bundle, io) => bundle <> io }
ddrClientBundle <> port.io
}
})

class WithJTAG extends HarnessBinder({
case (th: ZCU102FPGATestHarnessImp, port: JTAGPort, chipId: Int) => {
val jtag_io = th.zcu102Outer.jtagPlacedOverlay.overlayOutput.jtag.getWrappedValue
port.io.TCK := jtag_io.TCK
port.io.TMS := jtag_io.TMS
port.io.TDI := jtag_io.TDI
jtag_io.TDO.data := port.io.TDO
jtag_io.TDO.driven := true.B
// ignore srst_n
jtag_io.srst_n := DontCare

}
})
Loading

0 comments on commit 45113e4

Please sign in to comment.