Skip to content

Commit d4ebf93

Browse files
authored
Merge pull request #2136 from doihead/intel-fpgas
Add support for Intel/Altera FPGAs + Trenz Datastorm board
2 parents 146f62f + 58b4ea6 commit d4ebf93

File tree

5 files changed

+296
-1
lines changed

5 files changed

+296
-1
lines changed

fpga/Makefile

+26
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,19 @@ ifeq ($(SUB_PROJECT),arty100t)
8686
BOARD ?= arty_a7_100
8787
FPGA_BRAND ?= xilinx
8888
endif
89+
ifeq ($(SUB_PROJECT),datastorm)
90+
SBT_PROJECT ?= chipyard_fpga
91+
MODEL ?= DatastormHarness
92+
VLOG_MODEL ?= DatastormHarness
93+
MODEL_PACKAGE ?= chipyard.fpga.datastorm
94+
CONFIG ?= RocketDatastormConfig
95+
CONFIG_PACKAGE ?= chipyard.fpga.datastorm
96+
GENERATOR_PACKAGE ?= chipyard
97+
TB ?= none # unused
98+
TOP ?= ChipTop
99+
BOARD ?= trenz_datastorm
100+
FPGA_BRAND ?= altera
101+
endif
89102

90103
export USE_CHISEL6=1
91104

@@ -133,9 +146,11 @@ all_vsrcs := \
133146
# combine all sources into single .f
134147
synth_list_f := $(build_dir)/$(long_name).vsrcs.f
135148
$(synth_list_f): $(sim_common_files) $(all_vsrcs)
149+
rm -f $@
136150
$(foreach file,$(all_vsrcs),echo "$(file)" >> $@;)
137151
cat $(sim_common_files) >> $@
138152

153+
ifeq ($(FPGA_BRAND),xilinx)
139154
BIT_FILE := $(build_dir)/obj/$(MODEL).bit
140155
$(BIT_FILE): $(synth_list_f)
141156
cd $(build_dir); vivado \
@@ -146,6 +161,17 @@ $(BIT_FILE): $(synth_list_f)
146161
-F "$(synth_list_f)" \
147162
-board "$(BOARD)" \
148163
-ip-vivado-tcls "$(shell find '$(build_dir)' -name '*.vivado.tcl')"
164+
endif
165+
ifeq ($(FPGA_BRAND),altera)
166+
BIT_FILE := $(build_dir)/output_files/$(MODEL).qsf
167+
$(BIT_FILE): $(synth_list_f)
168+
cd $(build_dir); quartus_sh \
169+
-t $(fpga_common_script_dir)/quartus.tcl \
170+
"$(MODEL)" \
171+
"$(BOARD)" \
172+
"$(long_name)" \
173+
"$(shell find '$(build_dir)' -name '*.quartus.tcl')"
174+
endif
149175

150176
.PHONY: bitstream
151177
bitstream: $(BIT_FILE)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
// See LICENSE for license details.
2+
package chipyard.fpga.datastorm
3+
4+
import org.chipsalliance.cde.config._
5+
import freechips.rocketchip.subsystem._
6+
import freechips.rocketchip.devices.debug._
7+
import freechips.rocketchip.devices.tilelink._
8+
import org.chipsalliance.diplomacy._
9+
import org.chipsalliance.diplomacy.lazymodule._
10+
import freechips.rocketchip.system._
11+
import freechips.rocketchip.tile._
12+
13+
import sifive.blocks.devices.uart._
14+
import sifive.fpgashells.shell.{DesignKey}
15+
16+
import testchipip.serdes.{SerialTLKey}
17+
18+
import chipyard.{BuildSystem}
19+
import testchipip.soc.WithNoScratchpads
20+
import sifive.blocks.devices.spi.SPIProtocol.width
21+
import chipyard.iobinders.WithGPIOPunchthrough
22+
23+
// don't use FPGAShell's DesignKey
24+
class WithNoDesignKey extends Config((site, here, up) => {
25+
case DesignKey => (p: Parameters) => new SimpleLazyRawModule()(p)
26+
})
27+
28+
class WithDatastormTweaks(freqMHz: Double = 40) extends Config(
29+
new WithDatastormPMODUART ++
30+
new WithDatastormUARTTSI ++
31+
new WithDatastormDDRTL ++
32+
new WithDatastormJTAG ++
33+
new WithNoDesignKey ++
34+
new testchipip.tsi.WithUARTTSIClient(initBaudRate = BigInt(921600)) ++
35+
new chipyard.harness.WithSerialTLTiedOff ++
36+
new chipyard.harness.WithHarnessBinderClockFreqMHz(freqMHz) ++
37+
new chipyard.config.WithUniformBusFrequencies(freqMHz) ++
38+
new chipyard.harness.WithAllClocksFromHarnessClockInstantiator ++
39+
new chipyard.clocking.WithPassthroughClockGenerator ++
40+
new chipyard.config.WithTLBackingMemory ++ // FPGA-shells converts the AXI to TL for us
41+
new freechips.rocketchip.subsystem.WithExtMemSize(BigInt(1) << 30) ++ // 1GB on Datastorm
42+
new freechips.rocketchip.subsystem.WithoutTLMonitors)
43+
44+
class RocketDatastormConfig extends Config(
45+
new WithDatastormTweaks ++
46+
new WithNoScratchpads ++
47+
new testchipip.serdes.WithNoSerialTL ++
48+
new chipyard.config.WithBroadcastManager ++ // no l2
49+
new freechips.rocketchip.rocket.WithNBigCores(1) ++ // Use bigrocket instead of huge due to space constraints
50+
new chipyard.config.AbstractConfig)
51+
52+
class NoCoresDatastormConfig extends Config(
53+
new WithDatastormTweaks ++
54+
new chipyard.config.WithBroadcastManager ++ // no l2
55+
new chipyard.NoCoresConfig)
56+
57+
class BringupDatastormConfig extends Config(
58+
new WithDatastormSerialTLToFMC ++
59+
new WithDatastormTweaks ++
60+
new testchipip.serdes.WithSerialTLPHYParams(testchipip.serdes.InternalSyncSerialPhyParams(freqMHz=40)) ++
61+
new chipyard.ChipBringupHostConfig)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package chipyard.fpga.datastorm
2+
3+
import chisel3._
4+
import chisel3.util._
5+
import freechips.rocketchip.diplomacy._
6+
import org.chipsalliance.cde.config.{Parameters}
7+
import freechips.rocketchip.tilelink._
8+
import freechips.rocketchip.prci._
9+
import freechips.rocketchip.subsystem.{SystemBusKey}
10+
11+
import sifive.fpgashells.shell.altera._
12+
import sifive.fpgashells.shell._
13+
import sifive.fpgashells.clocks._
14+
15+
import sifive.blocks.devices.uart._
16+
17+
import chipyard._
18+
import chipyard.harness._
19+
20+
class DatastormHarness(override implicit val p: Parameters) extends DatastormShell {
21+
def dp = designParameters
22+
23+
val clockOverlay = dp(ClockInputOverlayKey).map(_.place(ClockInputDesignInput())).head
24+
val harnessSysPLL = dp(PLLFactoryKey)
25+
val harnessSysPLLNode = harnessSysPLL()
26+
val dutFreqMHz = (dp(SystemBusKey).dtsFrequency.get / (1000 * 1000)).toInt
27+
val dutClock = ClockSinkNode(freqMHz = dutFreqMHz)
28+
println(s"Datastorm FPGA Base Clock Freq: ${dutFreqMHz} MHz")
29+
val dutWrangler = LazyModule(new ResetWrangler())
30+
val dutGroup = ClockGroup()
31+
dutClock := dutWrangler.node := dutGroup := harnessSysPLLNode
32+
33+
harnessSysPLLNode := clockOverlay.overlayOutput.node
34+
35+
val ddrOverlay = dp(DDROverlayKey).head.place(DDRDesignInput(dp(ExtTLMem).get.master.base, dutWrangler.node, harnessSysPLLNode)).asInstanceOf[DDRDatastormPlacedOverlay]
36+
val ddrClient = TLClientNode(Seq(TLMasterPortParameters.v1(Seq(TLMasterParameters.v1(
37+
name = "chip_ddr",
38+
sourceId = IdRange(0, 1 << dp(ExtTLMem).get.master.idBits)
39+
)))))
40+
val ddrBlockDuringReset = LazyModule(new TLBlockDuringReset(4))
41+
ddrOverlay.overlayOutput.ddr := ddrBlockDuringReset.node := ddrClient
42+
43+
val ledOverlays = dp(LEDOverlayKey).map(_.place(LEDDesignInput()))
44+
val all_leds = ledOverlays.map(_.overlayOutput.led)
45+
46+
override lazy val module = new HarnessLikeImpl
47+
48+
class HarnessLikeImpl extends Impl with HasHarnessInstantiators {
49+
clockOverlay.overlayOutput.node.out(0)._1.reset := ~resetPin
50+
51+
val clk_50mhz = clockOverlay.overlayOutput.node.out.head._1.clock
52+
53+
// Blink the status LEDs for sanity
54+
withClockAndReset(clk_50mhz, dutClock.in.head._1.reset) {
55+
val period = (BigInt(50) << 20)
56+
val counter = RegInit(0.U(log2Ceil(period).W))
57+
val on = RegInit(false.B)
58+
all_leds(0) := on
59+
counter := Mux(counter === (period-1).U, 0.U, counter + 1.U)
60+
when (counter === 0.U) {
61+
on := !on
62+
}
63+
}
64+
65+
harnessSysPLL.plls.foreach(_._1.getReset.get := pllReset)
66+
67+
def referenceClockFreqMHz = dutFreqMHz
68+
def referenceClock = dutClock.in.head._1.clock
69+
def referenceReset = dutClock.in.head._1.reset
70+
def success = { require(false, "Unused"); false.B }
71+
72+
childClock := harnessBinderClock
73+
childReset := harnessBinderReset
74+
75+
ddrOverlay.mig.module.clock := harnessBinderClock
76+
ddrOverlay.mig.module.reset := harnessBinderReset
77+
ddrBlockDuringReset.module.clock := harnessBinderClock
78+
ddrBlockDuringReset.module.reset := harnessBinderReset.asBool || !ddrOverlay.mig.module.io.port.mem_status_local_cal_success
79+
80+
all_leds(1) := ddrOverlay.mig.module.io.port.mem_status_local_cal_success
81+
instantiateChipTops()
82+
}
83+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
package chipyard.fpga.datastorm
2+
3+
import chisel3._
4+
5+
import freechips.rocketchip.jtag.{JTAGIO}
6+
import freechips.rocketchip.subsystem.{PeripheryBusKey}
7+
import freechips.rocketchip.tilelink.{TLBundle}
8+
import freechips.rocketchip.diplomacy.{LazyRawModuleImp}
9+
import org.chipsalliance.diplomacy.nodes.{HeterogeneousBag}
10+
import sifive.blocks.devices.uart.{UARTPortIO, UARTParams}
11+
import sifive.blocks.devices.jtag.{JTAGPins, JTAGPinsFromPort}
12+
import sifive.blocks.devices.pinctrl.{BasePin}
13+
import sifive.fpgashells.shell._
14+
import sifive.fpgashells.ip.altera._
15+
import sifive.fpgashells.shell.altera._
16+
import sifive.fpgashells.clocks._
17+
import chipyard._
18+
import chipyard.harness._
19+
import chipyard.iobinders._
20+
import testchipip.serdes._
21+
22+
class WithDatastormDDRTL extends HarnessBinder({
23+
case (th: HasHarnessInstantiators, port: TLMemPort, chipId: Int) => {
24+
val ath = th.asInstanceOf[LazyRawModuleImp].wrapper.asInstanceOf[DatastormHarness]
25+
val bundles = ath.ddrClient.out.map(_._1)
26+
val ddrClientBundle = Wire(new HeterogeneousBag(bundles.map(_.cloneType)))
27+
bundles.zip(ddrClientBundle).foreach { case (bundle, io) => bundle <> io }
28+
ddrClientBundle <> port.io
29+
}
30+
})
31+
32+
class WithDatastormSerialTLToFMC extends HarnessBinder({
33+
case (th: HasHarnessInstantiators, port: SerialTLPort, chipId: Int) => {
34+
val ath = th.asInstanceOf[LazyRawModuleImp].wrapper.asInstanceOf[DatastormHarness]
35+
val harnessIO = IO(chiselTypeOf(port.io)).suggestName("serial_tl")
36+
harnessIO <> port.io
37+
38+
harnessIO match {
39+
case io: DecoupledPhitIO => {
40+
val clkIO = io match {
41+
case io: InternalSyncPhitIO => IOPin(io.clock_out)
42+
case io: ExternalSyncPhitIO => IOPin(io.clock_in)
43+
}
44+
val packagePinsWithPackageIOs = Seq(
45+
("PIN_C13", clkIO),
46+
("PIN_J12", IOPin(io.out.valid)),
47+
("PIN_K12", IOPin(io.out.ready)),
48+
("PIN_H12", IOPin(io.in.valid)),
49+
("PIN_H13", IOPin(io.in.ready)),
50+
("PIN_E9", IOPin(io.out.bits.phit, 0)),
51+
("PIN_D9", IOPin(io.out.bits.phit, 1)),
52+
("PIN_H14", IOPin(io.out.bits.phit, 2)),
53+
("PIN_G13", IOPin(io.out.bits.phit, 3)),
54+
("PIN_C12", IOPin(io.in.bits.phit, 0)),
55+
("PIN_B11", IOPin(io.in.bits.phit, 1)),
56+
("PIN_E8", IOPin(io.in.bits.phit, 2)),
57+
("PIN_D7", IOPin(io.in.bits.phit, 3))
58+
)
59+
packagePinsWithPackageIOs foreach { case (pin, io) => {
60+
ath.io_tcl.addPackagePin(io, pin)
61+
ath.io_tcl.addIOStandard(io, "1.5 V")
62+
}}
63+
64+
ath.sdc.addClock("ser_tl_clock", clkIO, 50)
65+
ath.sdc.addGroup(clocks = Seq("ser_tl_clock"))
66+
}
67+
}
68+
}
69+
})
70+
71+
class WithDatastormUARTTSI extends HarnessBinder({
72+
case (th: HasHarnessInstantiators, port: UARTTSIPort, chipId: Int) => {
73+
val ath = th.asInstanceOf[LazyRawModuleImp].wrapper.asInstanceOf[DatastormHarness]
74+
val harnessIO = IO(new UARTPortIO(port.io.uartParams)).suggestName("uart_tsi")
75+
harnessIO <> port.io.uart
76+
val packagePinsWithPackageIOs = Seq(
77+
("PIN_AG10" , IOPin(harnessIO.rxd)),
78+
("PIN_AH9", IOPin(harnessIO.txd)))
79+
packagePinsWithPackageIOs foreach { case (pin, io) => {
80+
ath.io_tcl.addPackagePin(io, pin)
81+
ath.io_tcl.addIOStandard(io, "1.5 V")
82+
} }
83+
}
84+
})
85+
86+
// Maps the UART device to the on-board USB-UART
87+
class WithDatastormUART(rxdPin: String = "PIN_AG10", txdPin: String = "PIN_AH9") extends HarnessBinder({
88+
case (th: HasHarnessInstantiators, port: UARTPort, chipId: Int) => {
89+
val ath = th.asInstanceOf[LazyRawModuleImp].wrapper.asInstanceOf[DatastormHarness]
90+
val harnessIO = IO(chiselTypeOf(port.io)).suggestName("uart")
91+
harnessIO <> port.io
92+
val packagePinsWithPackageIOs = Seq(
93+
(rxdPin, IOPin(harnessIO.rxd)),
94+
(txdPin, IOPin(harnessIO.txd)))
95+
packagePinsWithPackageIOs foreach { case (pin, io) => {
96+
ath.io_tcl.addPackagePin(io, pin)
97+
ath.io_tcl.addIOStandard(io, "3.3-V LVTTL")
98+
} }
99+
}
100+
})
101+
102+
// Maps the UART device to PMOD JD pins 3/7
103+
class WithDatastormPMODUART extends WithDatastormUART("PIN_AB12", "PIN_AC12")
104+
105+
class WithDatastormJTAG extends HarnessBinder({
106+
case (th: HasHarnessInstantiators, port: JTAGPort, chipId: Int) => {
107+
val ath = th.asInstanceOf[LazyRawModuleImp].wrapper.asInstanceOf[DatastormHarness]
108+
val harnessIO = IO(chiselTypeOf(port.io)).suggestName("jtag")
109+
harnessIO <> port.io
110+
111+
ath.sdc.addClock("JTCK", IOPin(harnessIO.TCK), 10)
112+
ath.sdc.addGroup(clocks = Seq("JTCK"))
113+
val packagePinsWithPackageIOs = Seq(
114+
("PIN_AD12", IOPin(harnessIO.TCK)),
115+
("PIN_AD10", IOPin(harnessIO.TMS)),
116+
("PIN_AC9", IOPin(harnessIO.TDI)),
117+
("PIN_AD9", IOPin(harnessIO.TDO))
118+
)
119+
packagePinsWithPackageIOs foreach { case (pin, io) => {
120+
ath.io_tcl.addPackagePin(io, pin)
121+
ath.io_tcl.addIOStandard(io, "3.3-V LVTTL")
122+
// TODO Check if Cyclone V devices have integrated pullups ath.io_tcl.addPullup(io)
123+
} }
124+
}
125+
})

0 commit comments

Comments
 (0)