Use 2nd system clock for TSI DDR | Small cleanups

This commit is contained in:
abejgonzalez
2020-11-06 16:34:45 -08:00
parent 6aae66c54f
commit 7baa1341ee
3 changed files with 59 additions and 25 deletions

View File

@@ -42,17 +42,14 @@ class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118S
val topDesign = LazyModule(p(BuildTop)(dp))
// place all clocks in the shell
dp(ClockInputOverlayKey).foreach { _.place(ClockInputDesignInput()) }
require(dp(ClockInputOverlayKey).size >= 1)
val sys_clk_placed = dp(ClockInputOverlayKey)(0).place(ClockInputDesignInput())
/*** Connect/Generate clocks ***/
// connect to the PLL that will generate multiple clocks
val harnessSysPLL = dp(PLLFactoryKey)()
sys_clock.get() match {
case Some(x : SysClockVCU118PlacedOverlay) => {
harnessSysPLL := x.node
}
}
harnessSysPLL := sys_clk_placed.overlayOutput.node
// create and connect to the dutClock
val dutClock = ClockSinkNode(freqMHz = dp(FPGAFrequencyKey))
@@ -60,14 +57,6 @@ class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118S
val dutGroup = ClockGroup()
dutClock := dutWrangler.node := dutGroup := harnessSysPLL
// connect ref clock to dummy sink node
ref_clock.get() match {
case Some(x : RefClockVCU118PlacedOverlay) => {
val sink = ClockSinkNode(Seq(ClockSinkParameters()))
sink := x.node
}
}
/*** UART ***/
// 1st UART goes to the VCU118 dedicated UART
@@ -110,9 +99,7 @@ class VCU118FPGATestHarnessImp(_outer: VCU118FPGATestHarness) extends LazyRawMod
val reset_ibuf = Module(new IBUF)
reset_ibuf.io.I := reset
val sysclk: Clock = _outer.sys_clock.get() match {
case Some(x: SysClockVCU118PlacedOverlay) => x.clock
}
val sysclk: Clock = _outer.sys_clk_placed.overlayOutput.node.out.head._1.clock
val powerOnReset: Bool = PowerOnResetFPGAOnly(sysclk)
_outer.sdc.addAsyncPath(Seq(powerOnReset))

View File

@@ -5,7 +5,7 @@ import chisel3.experimental.{attach}
import freechips.rocketchip.diplomacy._
import freechips.rocketchip.config.{Parameters, Field}
import freechips.rocketchip.tilelink.{TLInwardNode}
import freechips.rocketchip.tilelink.{TLInwardNode, TLAsyncCrossingSink}
import sifive.fpgashells.shell._
import sifive.fpgashells.ip.xilinx._
@@ -176,7 +176,7 @@ abstract class TSIHostPlacedOverlay[IO <: Data](val name: String, val di: TSIHos
}
case object TSIHostVCU118DDRSize extends Field[BigInt](0x40000000L * 2) // 2GB
class TSIHostVCU118PlacedOverlay(val shell: VCU118ShellBasicOverlays, name: String, val designInput: TSIHostDesignInput, val shellInput: TSIHostShellInput)
class TSIHostVCU118PlacedOverlay(val shell: BringupVCU118FPGATestHarness, name: String, val designInput: TSIHostDesignInput, val shellInput: TSIHostShellInput)
extends TSIHostPlacedOverlay[TSIHostWithDDRIO](name, designInput, shellInput)
{
val size = p(TSIHostVCU118DDRSize)
@@ -190,6 +190,14 @@ class TSIHostVCU118PlacedOverlay(val shell: VCU118ShellBasicOverlays, name: Stri
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() }
// connect the TSI serial
val tlTsiSerialSink = di.node.makeSink()
val tsiIoNode = BundleBridgeSource(() => new TSIHostWidgetIO(di.tsiHostParams.serialIfWidth))
@@ -202,6 +210,10 @@ class TSIHostVCU118PlacedOverlay(val shell: VCU118ShellBasicOverlays, name: Stri
// connect MIG
ioNode.bundle <> mig.module.io
// setup async crossing
asyncSink.module.clock := migClkRstNode.bundle.clock
asyncSink.module.reset := migClkRstNode.bundle.reset
// connect TSI serial
val tsiSourcePort = tsiIoNode.bundle
val tsiSinkPort = tlTsiSerialSink.bundle
@@ -216,10 +228,15 @@ class TSIHostVCU118PlacedOverlay(val shell: VCU118ShellBasicOverlays, name: Stri
// connect the DDR port
shell { InModuleBody {
require (shell.sys_clock.get.isDefined, "Use of DDRVCU118Overlay depends on SysClockVCU118Overlay")
val (sys, _) = shell.sys_clock.get.get.overlayOutput.node.out(0)
require (shell.sys_clock2.get.isDefined, "Use of TSIHostVCU118Overlay depends on SysClock2VCU118Overlay")
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 sink to sys_clock2
topMigClkRstIONode.bundle.clock := sys.clock
topMigClkRstIONode.bundle.reset := sys.reset
val ddrPort = topIONode.bundle.port
io.ddr <> ddrPort
ui.clock := ddrPort.c0_ddr4_ui_clk
@@ -250,7 +267,7 @@ class TSIHostVCU118PlacedOverlay(val shell: VCU118ShellBasicOverlays, name: Stri
shell.sdc.addGroup(pins = Seq(mig.island.module.blackbox.io.c0_ddr4_ui_clk))
}
class BringupTSIHostVCU118PlacedOverlay(override val shell: VCU118ShellBasicOverlays, override val name: String, override val designInput: TSIHostDesignInput, override val shellInput: TSIHostShellInput)
class BringupTSIHostVCU118PlacedOverlay(override val shell: BringupVCU118FPGATestHarness, override val name: String, override val designInput: TSIHostDesignInput, override val shellInput: TSIHostShellInput)
extends TSIHostVCU118PlacedOverlay(shell, name, designInput, shellInput)
{
// connect the TSI port
@@ -293,7 +310,25 @@ class BringupTSIHostVCU118PlacedOverlay(override val shell: VCU118ShellBasicOver
} }
}
class BringupTSIHostVCU118ShellPlacer(shell: VCU118ShellBasicOverlays, val shellInput: TSIHostShellInput)(implicit val valName: ValName)
extends TSIHostShellPlacer[VCU118ShellBasicOverlays] {
class BringupTSIHostVCU118ShellPlacer(shell: BringupVCU118FPGATestHarness, val shellInput: TSIHostShellInput)(implicit val valName: ValName)
extends TSIHostShellPlacer[BringupVCU118FPGATestHarness] {
def place(designInput: TSIHostDesignInput) = new BringupTSIHostVCU118PlacedOverlay(shell, valName.name, designInput, shellInput)
}
class SysClock2VCU118PlacedOverlay(val shell: VCU118ShellBasicOverlays, name: String, val designInput: ClockInputDesignInput, val shellInput: ClockInputShellInput)
extends LVDSClockInputXilinxPlacedOverlay(name, designInput, shellInput)
{
val node = shell { ClockSourceNode(freqMHz = 250, jitterPS = 50)(ValName(name)) }
shell { InModuleBody {
shell.xdc.addPackagePin(io.p, "AW26")
shell.xdc.addPackagePin(io.n, "AW27")
shell.xdc.addIOStandard(io.p, "DIFF_SSTL12")
shell.xdc.addIOStandard(io.n, "DIFF_SSTL12")
} }
}
class SysClock2VCU118ShellPlacer(shell: VCU118ShellBasicOverlays, val shellInput: ClockInputShellInput)(implicit val valName: ValName)
extends ClockInputShellPlacer[VCU118ShellBasicOverlays]
{
def place(designInput: ClockInputDesignInput) = new SysClock2VCU118PlacedOverlay(shell, valName.name, designInput, shellInput)
}

View File

@@ -70,10 +70,22 @@ class BringupVCU118FPGATestHarness(override implicit val p: Parameters) extends
/*** TSI Host Widget ***/
require(dp(PeripheryTSIHostKey).size == 1)
// use the 2nd system clock for the 2nd DDR
val sys_clock2 = Overlay(ClockInputOverlayKey, new SysClock2VCU118ShellPlacer(this, ClockInputShellInput()))
val sys_clk2_placed = dp(ClockInputOverlayKey).last.place(ClockInputDesignInput())
val ddr2PLL = dp(PLLFactoryKey)()
ddr2PLL := sys_clk2_placed.overlayOutput.node
val ddrClock = ClockSinkNode(freqMHz = dp(FPGAFrequencyKey))
val ddrWrangler = LazyModule(new ResetWrangler)
val ddrGroup = ClockGroup()
ddrClock := ddrWrangler.node := ddrGroup := ddr2PLL
val tsi_host = Overlay(TSIHostOverlayKey, new BringupTSIHostVCU118ShellPlacer(this, TSIHostShellInput()))
val io_tsi_serial_bb = BundleBridgeSource(() => (new TSIHostWidgetIO(dp(PeripheryTSIHostKey).head.serialIfWidth)))
val tsiDdrPlaced = dp(TSIHostOverlayKey).head.place(TSIHostDesignInput(dutWrangler.node, harnessSysPLL, dp(PeripheryTSIHostKey).head, io_tsi_serial_bb))
val tsiDdrPlaced = dp(TSIHostOverlayKey).head.place(TSIHostDesignInput(ddrWrangler.node, ddr2PLL, dp(PeripheryTSIHostKey).head, io_tsi_serial_bb))
// connect 1 mem. channel to the FPGA DDR
val inTsiParams = topDesign match { case td: ChipTop =>