Skip to content

Commit

Permalink
Merge pull request #2136 from doihead/intel-fpgas
Browse files Browse the repository at this point in the history
Add support for Intel/Altera FPGAs + Trenz Datastorm board
  • Loading branch information
jerryz123 authored Dec 3, 2024
2 parents 146f62f + 58b4ea6 commit d4ebf93
Show file tree
Hide file tree
Showing 5 changed files with 296 additions and 1 deletion.
26 changes: 26 additions & 0 deletions fpga/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,19 @@ ifeq ($(SUB_PROJECT),arty100t)
BOARD ?= arty_a7_100
FPGA_BRAND ?= xilinx
endif
ifeq ($(SUB_PROJECT),datastorm)
SBT_PROJECT ?= chipyard_fpga
MODEL ?= DatastormHarness
VLOG_MODEL ?= DatastormHarness
MODEL_PACKAGE ?= chipyard.fpga.datastorm
CONFIG ?= RocketDatastormConfig
CONFIG_PACKAGE ?= chipyard.fpga.datastorm
GENERATOR_PACKAGE ?= chipyard
TB ?= none # unused
TOP ?= ChipTop
BOARD ?= trenz_datastorm
FPGA_BRAND ?= altera
endif

export USE_CHISEL6=1

Expand Down Expand Up @@ -133,9 +146,11 @@ all_vsrcs := \
# combine all sources into single .f
synth_list_f := $(build_dir)/$(long_name).vsrcs.f
$(synth_list_f): $(sim_common_files) $(all_vsrcs)
rm -f $@
$(foreach file,$(all_vsrcs),echo "$(file)" >> $@;)
cat $(sim_common_files) >> $@

ifeq ($(FPGA_BRAND),xilinx)
BIT_FILE := $(build_dir)/obj/$(MODEL).bit
$(BIT_FILE): $(synth_list_f)
cd $(build_dir); vivado \
Expand All @@ -146,6 +161,17 @@ $(BIT_FILE): $(synth_list_f)
-F "$(synth_list_f)" \
-board "$(BOARD)" \
-ip-vivado-tcls "$(shell find '$(build_dir)' -name '*.vivado.tcl')"
endif
ifeq ($(FPGA_BRAND),altera)
BIT_FILE := $(build_dir)/output_files/$(MODEL).qsf
$(BIT_FILE): $(synth_list_f)
cd $(build_dir); quartus_sh \
-t $(fpga_common_script_dir)/quartus.tcl \
"$(MODEL)" \
"$(BOARD)" \
"$(long_name)" \
"$(shell find '$(build_dir)' -name '*.quartus.tcl')"
endif

.PHONY: bitstream
bitstream: $(BIT_FILE)
Expand Down
61 changes: 61 additions & 0 deletions fpga/src/main/scala/datastorm/Configs.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// See LICENSE for license details.
package chipyard.fpga.datastorm

import org.chipsalliance.cde.config._
import freechips.rocketchip.subsystem._
import freechips.rocketchip.devices.debug._
import freechips.rocketchip.devices.tilelink._
import org.chipsalliance.diplomacy._
import org.chipsalliance.diplomacy.lazymodule._
import freechips.rocketchip.system._
import freechips.rocketchip.tile._

import sifive.blocks.devices.uart._
import sifive.fpgashells.shell.{DesignKey}

import testchipip.serdes.{SerialTLKey}

import chipyard.{BuildSystem}
import testchipip.soc.WithNoScratchpads
import sifive.blocks.devices.spi.SPIProtocol.width
import chipyard.iobinders.WithGPIOPunchthrough

// don't use FPGAShell's DesignKey
class WithNoDesignKey extends Config((site, here, up) => {
case DesignKey => (p: Parameters) => new SimpleLazyRawModule()(p)
})

class WithDatastormTweaks(freqMHz: Double = 40) extends Config(
new WithDatastormPMODUART ++
new WithDatastormUARTTSI ++
new WithDatastormDDRTL ++
new WithDatastormJTAG ++
new WithNoDesignKey ++
new testchipip.tsi.WithUARTTSIClient(initBaudRate = BigInt(921600)) ++
new chipyard.harness.WithSerialTLTiedOff ++
new chipyard.harness.WithHarnessBinderClockFreqMHz(freqMHz) ++
new chipyard.config.WithUniformBusFrequencies(freqMHz) ++
new chipyard.harness.WithAllClocksFromHarnessClockInstantiator ++
new chipyard.clocking.WithPassthroughClockGenerator ++
new chipyard.config.WithTLBackingMemory ++ // FPGA-shells converts the AXI to TL for us
new freechips.rocketchip.subsystem.WithExtMemSize(BigInt(1) << 30) ++ // 1GB on Datastorm
new freechips.rocketchip.subsystem.WithoutTLMonitors)

class RocketDatastormConfig extends Config(
new WithDatastormTweaks ++
new WithNoScratchpads ++
new testchipip.serdes.WithNoSerialTL ++
new chipyard.config.WithBroadcastManager ++ // no l2
new freechips.rocketchip.rocket.WithNBigCores(1) ++ // Use bigrocket instead of huge due to space constraints
new chipyard.config.AbstractConfig)

class NoCoresDatastormConfig extends Config(
new WithDatastormTweaks ++
new chipyard.config.WithBroadcastManager ++ // no l2
new chipyard.NoCoresConfig)

class BringupDatastormConfig extends Config(
new WithDatastormSerialTLToFMC ++
new WithDatastormTweaks ++
new testchipip.serdes.WithSerialTLPHYParams(testchipip.serdes.InternalSyncSerialPhyParams(freqMHz=40)) ++
new chipyard.ChipBringupHostConfig)
83 changes: 83 additions & 0 deletions fpga/src/main/scala/datastorm/Harness.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package chipyard.fpga.datastorm

import chisel3._
import chisel3.util._
import freechips.rocketchip.diplomacy._
import org.chipsalliance.cde.config.{Parameters}
import freechips.rocketchip.tilelink._
import freechips.rocketchip.prci._
import freechips.rocketchip.subsystem.{SystemBusKey}

import sifive.fpgashells.shell.altera._
import sifive.fpgashells.shell._
import sifive.fpgashells.clocks._

import sifive.blocks.devices.uart._

import chipyard._
import chipyard.harness._

class DatastormHarness(override implicit val p: Parameters) extends DatastormShell {
def dp = designParameters

val clockOverlay = dp(ClockInputOverlayKey).map(_.place(ClockInputDesignInput())).head
val harnessSysPLL = dp(PLLFactoryKey)
val harnessSysPLLNode = harnessSysPLL()
val dutFreqMHz = (dp(SystemBusKey).dtsFrequency.get / (1000 * 1000)).toInt
val dutClock = ClockSinkNode(freqMHz = dutFreqMHz)
println(s"Datastorm FPGA Base Clock Freq: ${dutFreqMHz} MHz")
val dutWrangler = LazyModule(new ResetWrangler())
val dutGroup = ClockGroup()
dutClock := dutWrangler.node := dutGroup := harnessSysPLLNode

harnessSysPLLNode := clockOverlay.overlayOutput.node

val ddrOverlay = dp(DDROverlayKey).head.place(DDRDesignInput(dp(ExtTLMem).get.master.base, dutWrangler.node, harnessSysPLLNode)).asInstanceOf[DDRDatastormPlacedOverlay]
val ddrClient = TLClientNode(Seq(TLMasterPortParameters.v1(Seq(TLMasterParameters.v1(
name = "chip_ddr",
sourceId = IdRange(0, 1 << dp(ExtTLMem).get.master.idBits)
)))))
val ddrBlockDuringReset = LazyModule(new TLBlockDuringReset(4))
ddrOverlay.overlayOutput.ddr := ddrBlockDuringReset.node := ddrClient

val ledOverlays = dp(LEDOverlayKey).map(_.place(LEDDesignInput()))
val all_leds = ledOverlays.map(_.overlayOutput.led)

override lazy val module = new HarnessLikeImpl

class HarnessLikeImpl extends Impl with HasHarnessInstantiators {
clockOverlay.overlayOutput.node.out(0)._1.reset := ~resetPin

val clk_50mhz = clockOverlay.overlayOutput.node.out.head._1.clock

// Blink the status LEDs for sanity
withClockAndReset(clk_50mhz, dutClock.in.head._1.reset) {
val period = (BigInt(50) << 20)
val counter = RegInit(0.U(log2Ceil(period).W))
val on = RegInit(false.B)
all_leds(0) := on
counter := Mux(counter === (period-1).U, 0.U, counter + 1.U)
when (counter === 0.U) {
on := !on
}
}

harnessSysPLL.plls.foreach(_._1.getReset.get := pllReset)

def referenceClockFreqMHz = dutFreqMHz
def referenceClock = dutClock.in.head._1.clock
def referenceReset = dutClock.in.head._1.reset
def success = { require(false, "Unused"); false.B }

childClock := harnessBinderClock
childReset := harnessBinderReset

ddrOverlay.mig.module.clock := harnessBinderClock
ddrOverlay.mig.module.reset := harnessBinderReset
ddrBlockDuringReset.module.clock := harnessBinderClock
ddrBlockDuringReset.module.reset := harnessBinderReset.asBool || !ddrOverlay.mig.module.io.port.mem_status_local_cal_success

all_leds(1) := ddrOverlay.mig.module.io.port.mem_status_local_cal_success
instantiateChipTops()
}
}
125 changes: 125 additions & 0 deletions fpga/src/main/scala/datastorm/HarnessBinders.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package chipyard.fpga.datastorm

import chisel3._

import freechips.rocketchip.jtag.{JTAGIO}
import freechips.rocketchip.subsystem.{PeripheryBusKey}
import freechips.rocketchip.tilelink.{TLBundle}
import freechips.rocketchip.diplomacy.{LazyRawModuleImp}
import org.chipsalliance.diplomacy.nodes.{HeterogeneousBag}
import sifive.blocks.devices.uart.{UARTPortIO, UARTParams}
import sifive.blocks.devices.jtag.{JTAGPins, JTAGPinsFromPort}
import sifive.blocks.devices.pinctrl.{BasePin}
import sifive.fpgashells.shell._
import sifive.fpgashells.ip.altera._
import sifive.fpgashells.shell.altera._
import sifive.fpgashells.clocks._
import chipyard._
import chipyard.harness._
import chipyard.iobinders._
import testchipip.serdes._

class WithDatastormDDRTL extends HarnessBinder({
case (th: HasHarnessInstantiators, port: TLMemPort, chipId: Int) => {
val ath = th.asInstanceOf[LazyRawModuleImp].wrapper.asInstanceOf[DatastormHarness]
val bundles = ath.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 WithDatastormSerialTLToFMC extends HarnessBinder({
case (th: HasHarnessInstantiators, port: SerialTLPort, chipId: Int) => {
val ath = th.asInstanceOf[LazyRawModuleImp].wrapper.asInstanceOf[DatastormHarness]
val harnessIO = IO(chiselTypeOf(port.io)).suggestName("serial_tl")
harnessIO <> port.io

harnessIO match {
case io: DecoupledPhitIO => {
val clkIO = io match {
case io: InternalSyncPhitIO => IOPin(io.clock_out)
case io: ExternalSyncPhitIO => IOPin(io.clock_in)
}
val packagePinsWithPackageIOs = Seq(
("PIN_C13", clkIO),
("PIN_J12", IOPin(io.out.valid)),
("PIN_K12", IOPin(io.out.ready)),
("PIN_H12", IOPin(io.in.valid)),
("PIN_H13", IOPin(io.in.ready)),
("PIN_E9", IOPin(io.out.bits.phit, 0)),
("PIN_D9", IOPin(io.out.bits.phit, 1)),
("PIN_H14", IOPin(io.out.bits.phit, 2)),
("PIN_G13", IOPin(io.out.bits.phit, 3)),
("PIN_C12", IOPin(io.in.bits.phit, 0)),
("PIN_B11", IOPin(io.in.bits.phit, 1)),
("PIN_E8", IOPin(io.in.bits.phit, 2)),
("PIN_D7", IOPin(io.in.bits.phit, 3))
)
packagePinsWithPackageIOs foreach { case (pin, io) => {
ath.io_tcl.addPackagePin(io, pin)
ath.io_tcl.addIOStandard(io, "1.5 V")
}}

ath.sdc.addClock("ser_tl_clock", clkIO, 50)
ath.sdc.addGroup(clocks = Seq("ser_tl_clock"))
}
}
}
})

class WithDatastormUARTTSI extends HarnessBinder({
case (th: HasHarnessInstantiators, port: UARTTSIPort, chipId: Int) => {
val ath = th.asInstanceOf[LazyRawModuleImp].wrapper.asInstanceOf[DatastormHarness]
val harnessIO = IO(new UARTPortIO(port.io.uartParams)).suggestName("uart_tsi")
harnessIO <> port.io.uart
val packagePinsWithPackageIOs = Seq(
("PIN_AG10" , IOPin(harnessIO.rxd)),
("PIN_AH9", IOPin(harnessIO.txd)))
packagePinsWithPackageIOs foreach { case (pin, io) => {
ath.io_tcl.addPackagePin(io, pin)
ath.io_tcl.addIOStandard(io, "1.5 V")
} }
}
})

// Maps the UART device to the on-board USB-UART
class WithDatastormUART(rxdPin: String = "PIN_AG10", txdPin: String = "PIN_AH9") extends HarnessBinder({
case (th: HasHarnessInstantiators, port: UARTPort, chipId: Int) => {
val ath = th.asInstanceOf[LazyRawModuleImp].wrapper.asInstanceOf[DatastormHarness]
val harnessIO = IO(chiselTypeOf(port.io)).suggestName("uart")
harnessIO <> port.io
val packagePinsWithPackageIOs = Seq(
(rxdPin, IOPin(harnessIO.rxd)),
(txdPin, IOPin(harnessIO.txd)))
packagePinsWithPackageIOs foreach { case (pin, io) => {
ath.io_tcl.addPackagePin(io, pin)
ath.io_tcl.addIOStandard(io, "3.3-V LVTTL")
} }
}
})

// Maps the UART device to PMOD JD pins 3/7
class WithDatastormPMODUART extends WithDatastormUART("PIN_AB12", "PIN_AC12")

class WithDatastormJTAG extends HarnessBinder({
case (th: HasHarnessInstantiators, port: JTAGPort, chipId: Int) => {
val ath = th.asInstanceOf[LazyRawModuleImp].wrapper.asInstanceOf[DatastormHarness]
val harnessIO = IO(chiselTypeOf(port.io)).suggestName("jtag")
harnessIO <> port.io

ath.sdc.addClock("JTCK", IOPin(harnessIO.TCK), 10)
ath.sdc.addGroup(clocks = Seq("JTCK"))
val packagePinsWithPackageIOs = Seq(
("PIN_AD12", IOPin(harnessIO.TCK)),
("PIN_AD10", IOPin(harnessIO.TMS)),
("PIN_AC9", IOPin(harnessIO.TDI)),
("PIN_AD9", IOPin(harnessIO.TDO))
)
packagePinsWithPackageIOs foreach { case (pin, io) => {
ath.io_tcl.addPackagePin(io, pin)
ath.io_tcl.addIOStandard(io, "3.3-V LVTTL")
// TODO Check if Cyclone V devices have integrated pullups ath.io_tcl.addPullup(io)
} }
}
})

0 comments on commit d4ebf93

Please sign in to comment.