Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Xilinx zcu102 board rev1.1 #2117

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
13 changes: 13 additions & 0 deletions fpga/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,19 @@ ifeq ($(SUB_PROJECT),arty100t)
BOARD ?= arty_a7_100
FPGA_BRAND ?= xilinx
endif
ifeq ($(SUB_PROJECT),zcu102)
SBT_PROJECT ?= chipyard_fpga
MODEL ?= ZCU102FPGATestHarness
VLOG_MODEL ?= ZCU102FPGATestHarness
MODEL_PACKAGE ?= chipyard.fpga.zcu102
CONFIG ?= RocketZCU102Config
CONFIG_PACKAGE ?= chipyard.fpga.zcu102
GENERATOR_PACKAGE ?= chipyard
TB ?= none
TOP ?= ChipTop
BOARD ?= zcu102
FPGA_BRAND ?= xilinx
endif

export USE_CHISEL6=1

Expand Down
1 change: 1 addition & 0 deletions fpga/src/main/resources/zcu102
94 changes: 94 additions & 0 deletions fpga/src/main/scala/zcu102/Configs.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package chipyard.fpga.zcu102

import sys.process._

import org.chipsalliance.cde.config.{Config, Parameters}

import freechips.rocketchip.subsystem.{SystemBusKey, ExtMem}
import freechips.rocketchip.devices.debug.{JTAG}
import freechips.rocketchip.devices.tilelink.{BootROMLocated}
import freechips.rocketchip.resources.{DTSTimebase}


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

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 =>
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))))
case SerialTLKey => Nil
})

// 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 ++
new WithSystemModifications ++
// new chipyard.config.WithNoDebug ++
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)

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)
107 changes: 107 additions & 0 deletions fpga/src/main/scala/zcu102/CustomOverlays.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package chipyard.fpga.zcu102

import chisel3._

import freechips.rocketchip.diplomacy._
import org.chipsalliance.cde.config.{Parameters, Field}
import freechips.rocketchip.tilelink.{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)

// Fill from zcu102 manual.
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)
}

126 changes: 126 additions & 0 deletions fpga/src/main/scala/zcu102/FMCUtil.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
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
// 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)
}
Loading