diff --git a/fpga/src/main/scala/vcu118/TestHarness.scala b/fpga/src/main/scala/vcu118/TestHarness.scala index d5a5481e..39f389f8 100644 --- a/fpga/src/main/scala/vcu118/TestHarness.scala +++ b/fpga/src/main/scala/vcu118/TestHarness.scala @@ -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)) diff --git a/fpga/src/main/scala/vcu118/bringup/CustomOverlays.scala b/fpga/src/main/scala/vcu118/bringup/CustomOverlays.scala index b138038d..23ed9f11 100644 --- a/fpga/src/main/scala/vcu118/bringup/CustomOverlays.scala +++ b/fpga/src/main/scala/vcu118/bringup/CustomOverlays.scala @@ -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) +} diff --git a/fpga/src/main/scala/vcu118/bringup/TestHarness.scala b/fpga/src/main/scala/vcu118/bringup/TestHarness.scala index e3b4c137..0fd51108 100644 --- a/fpga/src/main/scala/vcu118/bringup/TestHarness.scala +++ b/fpga/src/main/scala/vcu118/bringup/TestHarness.scala @@ -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 =>