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)) val topDesign = LazyModule(p(BuildTop)(dp))
// place all clocks in the shell // 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/Generate clocks ***/
// connect to the PLL that will generate multiple clocks // connect to the PLL that will generate multiple clocks
val harnessSysPLL = dp(PLLFactoryKey)() val harnessSysPLL = dp(PLLFactoryKey)()
sys_clock.get() match { harnessSysPLL := sys_clk_placed.overlayOutput.node
case Some(x : SysClockVCU118PlacedOverlay) => {
harnessSysPLL := x.node
}
}
// create and connect to the dutClock // create and connect to the dutClock
val dutClock = ClockSinkNode(freqMHz = dp(FPGAFrequencyKey)) val dutClock = ClockSinkNode(freqMHz = dp(FPGAFrequencyKey))
@@ -60,14 +57,6 @@ class VCU118FPGATestHarness(override implicit val p: Parameters) extends VCU118S
val dutGroup = ClockGroup() val dutGroup = ClockGroup()
dutClock := dutWrangler.node := dutGroup := harnessSysPLL 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 ***/ /*** UART ***/
// 1st UART goes to the VCU118 dedicated 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) val reset_ibuf = Module(new IBUF)
reset_ibuf.io.I := reset reset_ibuf.io.I := reset
val sysclk: Clock = _outer.sys_clock.get() match { val sysclk: Clock = _outer.sys_clk_placed.overlayOutput.node.out.head._1.clock
case Some(x: SysClockVCU118PlacedOverlay) => x.clock
}
val powerOnReset: Bool = PowerOnResetFPGAOnly(sysclk) val powerOnReset: Bool = PowerOnResetFPGAOnly(sysclk)
_outer.sdc.addAsyncPath(Seq(powerOnReset)) _outer.sdc.addAsyncPath(Seq(powerOnReset))

View File

@@ -5,7 +5,7 @@ import chisel3.experimental.{attach}
import freechips.rocketchip.diplomacy._ import freechips.rocketchip.diplomacy._
import freechips.rocketchip.config.{Parameters, Field} import freechips.rocketchip.config.{Parameters, Field}
import freechips.rocketchip.tilelink.{TLInwardNode} import freechips.rocketchip.tilelink.{TLInwardNode, TLAsyncCrossingSink}
import sifive.fpgashells.shell._ import sifive.fpgashells.shell._
import sifive.fpgashells.ip.xilinx._ 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 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) extends TSIHostPlacedOverlay[TSIHostWithDDRIO](name, designInput, shellInput)
{ {
val size = p(TSIHostVCU118DDRSize) val size = p(TSIHostVCU118DDRSize)
@@ -190,6 +190,14 @@ class TSIHostVCU118PlacedOverlay(val shell: VCU118ShellBasicOverlays, name: Stri
val areset = shell { ClockSinkNode(Seq(ClockSinkParameters())) } val areset = shell { ClockSinkNode(Seq(ClockSinkParameters())) }
areset := designInput.wrangler := ddrUI 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 // connect the TSI serial
val tlTsiSerialSink = di.node.makeSink() val tlTsiSerialSink = di.node.makeSink()
val tsiIoNode = BundleBridgeSource(() => new TSIHostWidgetIO(di.tsiHostParams.serialIfWidth)) val tsiIoNode = BundleBridgeSource(() => new TSIHostWidgetIO(di.tsiHostParams.serialIfWidth))
@@ -202,6 +210,10 @@ class TSIHostVCU118PlacedOverlay(val shell: VCU118ShellBasicOverlays, name: Stri
// connect MIG // connect MIG
ioNode.bundle <> mig.module.io ioNode.bundle <> mig.module.io
// setup async crossing
asyncSink.module.clock := migClkRstNode.bundle.clock
asyncSink.module.reset := migClkRstNode.bundle.reset
// connect TSI serial // connect TSI serial
val tsiSourcePort = tsiIoNode.bundle val tsiSourcePort = tsiIoNode.bundle
val tsiSinkPort = tlTsiSerialSink.bundle val tsiSinkPort = tlTsiSerialSink.bundle
@@ -216,10 +228,15 @@ class TSIHostVCU118PlacedOverlay(val shell: VCU118ShellBasicOverlays, name: Stri
// connect the DDR port // connect the DDR port
shell { InModuleBody { shell { InModuleBody {
require (shell.sys_clock.get.isDefined, "Use of DDRVCU118Overlay depends on SysClockVCU118Overlay") require (shell.sys_clock2.get.isDefined, "Use of TSIHostVCU118Overlay depends on SysClock2VCU118Overlay")
val (sys, _) = shell.sys_clock.get.get.overlayOutput.node.out(0) val (sys, _) = shell.sys_clock2.get.get.overlayOutput.node.out(0)
val (ui, _) = ddrUI.out(0) val (ui, _) = ddrUI.out(0)
val (ar, _) = areset.in(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 val ddrPort = topIONode.bundle.port
io.ddr <> ddrPort io.ddr <> ddrPort
ui.clock := ddrPort.c0_ddr4_ui_clk 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)) 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) extends TSIHostVCU118PlacedOverlay(shell, name, designInput, shellInput)
{ {
// connect the TSI port // 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) class BringupTSIHostVCU118ShellPlacer(shell: BringupVCU118FPGATestHarness, val shellInput: TSIHostShellInput)(implicit val valName: ValName)
extends TSIHostShellPlacer[VCU118ShellBasicOverlays] { extends TSIHostShellPlacer[BringupVCU118FPGATestHarness] {
def place(designInput: TSIHostDesignInput) = new BringupTSIHostVCU118PlacedOverlay(shell, valName.name, designInput, shellInput) 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 ***/ /*** TSI Host Widget ***/
require(dp(PeripheryTSIHostKey).size == 1) 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 tsi_host = Overlay(TSIHostOverlayKey, new BringupTSIHostVCU118ShellPlacer(this, TSIHostShellInput()))
val io_tsi_serial_bb = BundleBridgeSource(() => (new TSIHostWidgetIO(dp(PeripheryTSIHostKey).head.serialIfWidth))) 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 // connect 1 mem. channel to the FPGA DDR
val inTsiParams = topDesign match { case td: ChipTop => val inTsiParams = topDesign match { case td: ChipTop =>