10.2. Running a Design on VCU118¶
10.2.1. Basic VCU118 Design¶
The default Xilinx VCU118 harness is setup to have UART, a SPI SDCard, and DDR backing memory.
This allows it to run RISC-V Linux from an SDCard while piping the terminal over UART to the host machine (the machine connected to the VCU118).
To extend this design, you can create your own Chipyard configuration and add the WithVCU118Tweaks
located in fpga/src/main/scala/vcu118/Configs.scala
.
Adding this config fragment will enable and connect the UART, SPI SDCard, and DDR backing memory to your Chipyard design/config.
class WithVCU118Tweaks extends Config(
new WithUART ++
new WithSPISDCard ++
new WithDDRMem ++
new WithUARTIOPassthrough ++
new WithSPIIOPassthrough ++
new WithTLIOPassthrough ++
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 RocketVCU118Config extends Config(
new WithVCU118Tweaks ++
new chipyard.RocketConfig)
10.2.2. Brief Implementation Description + More Complicated Designs¶
The basis for a VCU118 design revolves around creating a special test harness to connect the external IOs to your Chipyard design.
This is done with the VCU118TestHarness
in the basic default VCU118 FPGA target.
The VCU118TestHarness
(located in fpga/src/main/scala/vcu118/TestHarness.scala
) uses Overlays
that connect to the VCU118 external IOs.
Generally, the Overlays
take an IO from the ChipTop
(labeled as topDesign
in the file) when “placed” and connect it to the external IO and generate necessary Vivado collateral.
For example, the following shows a UART Overlay
being “placed” into the design with a IO input called io_uart_bb
.
// 1st UART goes to the VCU118 dedicated UART
val io_uart_bb = BundleBridgeSource(() => (new UARTPortIO(dp(PeripheryUARTKey).head)))
dp(UARTOverlayKey).head.place(UARTDesignInput(io_uart_bb))
Here the UARTOverlayKey
is referenced and used to “place” the necessary connections (and collateral) to connect to the UART.
The UARTDesignInput
is used to pass in the UART IO from the ChipTop
/topDesign
to the Overlay
.
Note that the BundleBridgeSource
can be viewed as a glorified wire (that is defined in the LazyModule
scope).
This pattern is similar for all other Overlays
in the test harness.
They must be “placed” and given a set of inputs (IOs, parameters).
The main exception to this pattern is the Overlay
used to generate the clock(s) for the FPGA.
// place all clocks in the shell
require(dp(ClockInputOverlayKey).size >= 1)
val sysClkNode = dp(ClockInputOverlayKey)(0).place(ClockInputDesignInput()).overlayOutput.node
/*** Connect/Generate clocks ***/
// connect to the PLL that will generate multiple clocks
val harnessSysPLL = dp(PLLFactoryKey)()
harnessSysPLL := sysClkNode
// create and connect to the dutClock
val dutClock = ClockSinkNode(freqMHz = dp(FPGAFrequencyKey))
val dutWrangler = LazyModule(new ResetWrangler)
val dutGroup = ClockGroup()
dutClock := dutWrangler.node := dutGroup := harnessSysPLL
Without going into too much detail, the clocks overlay is placed in the harness and a PLL node (harnessSysPLL
) generates the necessary clocks specified by ClockSinkNodes
.
For ease of use, you can change the FPGAFrequencyKey
to change the default clock frequency of the FPGA design.
After the harness is created, the BundleBridgeSource
’s must be connected to the ChipTop
IOs.
This is done with harness binders and io binders (see fpga/src/main/scala/vcu118/HarnessBinders.scala
and fpga/src/main/scala/vcu118/IOBinders.scala
).
For more information on harness binders and io binders, refer to IOBinders and HarnessBinders.
10.2.3. Introduction to the Bringup Platform¶
An example of a more complicated design used for Chipyard test chips can be viewed in fpga/src/main/scala/vcu118/bringup/
.
This example extends the default test harness and creates new Overlays
to connect to a DUT (connected to the FMC port).
Extensions include another UART (connected over FMC), I2C (connected over FMC), miscellaneous GPIOS (can be connected to anything), and a TSI Host Widget.
The TSI Host Widget is used to interact with the DUT from the prototype over a SerDes link (sometimes called the Low BandWidth InterFace - LBWIF) and provide access to a channel of the FPGA’s DRAM.
Note
Remember that since whenever a new test harness is created (or the config changes, or the config packages changes, or…), you need to modify the make invocation.
For example, make SUB_PROJECT=vcu118 CONFIG=MyNewVCU118Config CONFIG_PACKAGE=this.is.my.scala.package bitstream
.
See Generating a Bitstream for information on the various make variables.