-
Notifications
You must be signed in to change notification settings - Fork 652
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fpga/src/main/scala/zcu102: Support Testharness for zcu102, and suppo…
…rt h-ext, memory interface generator.
- Loading branch information
Showing
6 changed files
with
613 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | ||
|
||
} | ||
}) |
Oops, something went wrong.