First draft of local FPGA support, targeting ARTY. Able to build verilog and bitfile for Rocket + Chipyard GCD example. To test, add GCD mixin to fpga/src/main/scala/arty/Config.scala, run make -f Makefile.e300artydevkit verilog and make -f Makefile.e300artydevkit mcs in fpga directory. Output will be in fpga/build.
This commit is contained in:
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -128,3 +128,6 @@
|
|||||||
[submodule "tools/dromajo/dromajo-src"]
|
[submodule "tools/dromajo/dromajo-src"]
|
||||||
path = tools/dromajo/dromajo-src
|
path = tools/dromajo/dromajo-src
|
||||||
url = https://github.com/riscv-boom/dromajo.git
|
url = https://github.com/riscv-boom/dromajo.git
|
||||||
|
[submodule "fpga/fpga-shells"]
|
||||||
|
path = fpga/fpga-shells
|
||||||
|
url = git@github.com:sifive/fpga-shells.git
|
||||||
|
|||||||
@@ -217,3 +217,10 @@ lazy val firechip = conditionalDependsOn(project in file("generators/firechip"))
|
|||||||
testGrouping in Test := isolateAllTests( (definedTests in Test).value ),
|
testGrouping in Test := isolateAllTests( (definedTests in Test).value ),
|
||||||
testOptions in Test += Tests.Argument("-oF")
|
testOptions in Test += Tests.Argument("-oF")
|
||||||
)
|
)
|
||||||
|
lazy val fpgaShells = (project in file("./fpga/fpga-shells"))
|
||||||
|
.dependsOn(rocketchip, sifive_blocks)
|
||||||
|
.settings(commonSettings)
|
||||||
|
|
||||||
|
lazy val freedomPlatforms = (project in file("./fpga"))
|
||||||
|
.dependsOn(chipyard, fpgaShells)
|
||||||
|
.settings(commonSettings)
|
||||||
|
|||||||
23
fpga/Makefile.e300artydevkit
Normal file
23
fpga/Makefile.e300artydevkit
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
# See LICENSE for license details.
|
||||||
|
base_dir=$(abspath ..)
|
||||||
|
BUILD_DIR := $(base_dir)/fpga/builds/e300artydevkit
|
||||||
|
FPGA_DIR := $(base_dir)/fpga/fpga-shells/xilinx
|
||||||
|
MODEL := E300ArtyDevKitFPGAChip
|
||||||
|
PROJECT := sifive.freedom.everywhere.e300artydevkit
|
||||||
|
export CONFIG_PROJECT := sifive.freedom.everywhere.e300artydevkit
|
||||||
|
export CONFIG := E300ArtyDevKitConfig
|
||||||
|
export BOARD := arty
|
||||||
|
export BOOTROM_DIR := $(base_dir)/fpga/bootrom/xip
|
||||||
|
|
||||||
|
rocketchip_dir := $(base_dir)/generators/rocket-chip
|
||||||
|
sifiveblocks_dir := $(base_dir)/generators/sifive-blocks
|
||||||
|
VSRCS := \
|
||||||
|
$(rocketchip_dir)/src/main/resources/vsrc/AsyncResetReg.v \
|
||||||
|
$(rocketchip_dir)/src/main/resources/vsrc/plusarg_reader.v \
|
||||||
|
$(rocketchip_dir)/src/main/resources/vsrc/EICG_wrapper.v \
|
||||||
|
$(sifiveblocks_dir)/vsrc/SRLatch.v \
|
||||||
|
$(FPGA_DIR)/common/vsrc/PowerOnResetFPGAOnly.v \
|
||||||
|
$(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).rom.v \
|
||||||
|
$(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).v
|
||||||
|
|
||||||
|
include common.mk
|
||||||
45
fpga/bootrom/xip/Makefile
Normal file
45
fpga/bootrom/xip/Makefile
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
# RISCV environment variable must be set
|
||||||
|
|
||||||
|
CC=$(RISCV)/bin/riscv64-unknown-elf-gcc
|
||||||
|
OBJCOPY=$(RISCV)/bin/riscv64-unknown-elf-objcopy
|
||||||
|
CFLAGS=-march=rv32imac -mabi=ilp32 -O2 -std=gnu11 -Wall -I. -nostartfiles -fno-common -g
|
||||||
|
LFLAGS=-static -nostdlib
|
||||||
|
|
||||||
|
dtb := $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).dtb
|
||||||
|
$(dtb): $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).dts
|
||||||
|
dtc -I dts -O dtb -o $@ $<
|
||||||
|
|
||||||
|
.PHONY: dtb
|
||||||
|
dtb: $(dtb)
|
||||||
|
|
||||||
|
elf := $(BUILD_DIR)/xip.elf
|
||||||
|
$(elf): xip.S $(dtb)
|
||||||
|
$(CC) $(CFLAGS) -DXIP_TARGET_ADDR=0x20400000 -DDEVICE_TREE='"$(dtb)"' $(LFLAGS) -o $@ $<
|
||||||
|
|
||||||
|
.PHONY: elf
|
||||||
|
elf: $(elf)
|
||||||
|
|
||||||
|
bin := $(BUILD_DIR)/xip.bin
|
||||||
|
$(bin): $(elf)
|
||||||
|
$(OBJCOPY) -O binary $< $@
|
||||||
|
|
||||||
|
.PHONY: bin
|
||||||
|
bin: $(bin)
|
||||||
|
|
||||||
|
hex := $(BUILD_DIR)/xip.hex
|
||||||
|
$(hex): $(bin)
|
||||||
|
od -t x4 -An -w4 -v $< > $@
|
||||||
|
|
||||||
|
.PHONY: hex
|
||||||
|
hex: $(hex)
|
||||||
|
|
||||||
|
romgen := $(BUILD_DIR)/rom.v
|
||||||
|
$(romgen): $(hex)
|
||||||
|
$(rocketchip_dir)/scripts/vlsi_rom_gen $(ROMCONF) $< > $@
|
||||||
|
|
||||||
|
.PHONY: romgen
|
||||||
|
romgen: $(romgen)
|
||||||
|
|
||||||
|
.PHONY: clean
|
||||||
|
clean::
|
||||||
|
rm -rf $(hex) $(elf)
|
||||||
16
fpga/bootrom/xip/xip.S
Normal file
16
fpga/bootrom/xip/xip.S
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
// Execute in place
|
||||||
|
// Jump directly to XIP_TARGET_ADDR
|
||||||
|
|
||||||
|
.section .text.init
|
||||||
|
.option norvc
|
||||||
|
.globl _start
|
||||||
|
_start:
|
||||||
|
csrr a0, mhartid
|
||||||
|
la a1, dtb
|
||||||
|
li t0, XIP_TARGET_ADDR
|
||||||
|
jr t0
|
||||||
|
|
||||||
|
.section .rodata
|
||||||
|
dtb:
|
||||||
|
.incbin DEVICE_TREE
|
||||||
119
fpga/common.mk
Normal file
119
fpga/common.mk
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
# See LICENSE for license details.
|
||||||
|
|
||||||
|
# Required variables:
|
||||||
|
# - MODEL
|
||||||
|
# - PROJECT
|
||||||
|
# - CONFIG_PROJECT
|
||||||
|
# - CONFIG
|
||||||
|
# - BUILD_DIR
|
||||||
|
# - FPGA_DIR
|
||||||
|
|
||||||
|
# Optional variables:
|
||||||
|
# - EXTRA_FPGA_VSRCS
|
||||||
|
|
||||||
|
# export to bootloader
|
||||||
|
export ROMCONF=$(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).rom.conf
|
||||||
|
|
||||||
|
# export to fpga-shells
|
||||||
|
export FPGA_TOP_SYSTEM=$(MODEL)
|
||||||
|
export FPGA_BUILD_DIR=$(BUILD_DIR)/$(FPGA_TOP_SYSTEM)
|
||||||
|
export fpga_common_script_dir=$(FPGA_DIR)/common/tcl
|
||||||
|
export fpga_board_script_dir=$(FPGA_DIR)/$(BOARD)/tcl
|
||||||
|
|
||||||
|
export BUILD_DIR
|
||||||
|
|
||||||
|
EXTRA_FPGA_VSRCS ?=
|
||||||
|
PATCHVERILOG ?= ""
|
||||||
|
BOOTROM_DIR ?= ""
|
||||||
|
|
||||||
|
base_dir=$(abspath ..)
|
||||||
|
export rocketchip_dir := $(base_dir)/generators/rocket-chip
|
||||||
|
SBT ?= java -jar $(rocketchip_dir)/sbt-launch.jar ++2.12.10
|
||||||
|
SBT_PROJECT ?= chipyard
|
||||||
|
firrtl_dir := $(base_dir)/tools/firrtl
|
||||||
|
|
||||||
|
# Build firrtl.jar and put it where chisel3 can find it.
|
||||||
|
FIRRTL_JAR := $(base_dir)/lib/firrtl.jar
|
||||||
|
FIRRTL ?= java -Xmx2G -Xss8M -XX:MaxPermSize=256M -cp $(FIRRTL_JAR) firrtl.Driver
|
||||||
|
|
||||||
|
$(FIRRTL_JAR): $(shell find $(firrtl_dir)/src/main/scala -iname "*.scala")
|
||||||
|
$(MAKE) -C $(firrtl_dir) SBT="$(SBT)" root_dir=$(firrtl_dir) build-scala
|
||||||
|
mkdir -p $(base_dir)/lib
|
||||||
|
cp $(firrtl_dir)/utils/bin/firrtl.jar $(FIRRTL_JAR)
|
||||||
|
|
||||||
|
# Build .fir
|
||||||
|
long_name := $(CONFIG_PROJECT).$(CONFIG)
|
||||||
|
firrtl := $(BUILD_DIR)/$(long_name).fir
|
||||||
|
$(firrtl): $(shell find $(base_dir) -name '*.scala') $(FIRRTL_JAR)
|
||||||
|
mkdir -p $(dir $@)
|
||||||
|
cd $(base_dir) && $(SBT) "project freedomPlatforms" \
|
||||||
|
"runMain chipyard.Generator \
|
||||||
|
--target-dir $(BUILD_DIR) \
|
||||||
|
--name $(long_name) \
|
||||||
|
--top-module $(PROJECT).$(MODEL) \
|
||||||
|
--legacy-configs $(CONFIG_PROJECT).$(CONFIG)"
|
||||||
|
|
||||||
|
.PHONY: firrtl
|
||||||
|
firrtl: $(firrtl)
|
||||||
|
|
||||||
|
# Build .v
|
||||||
|
verilog := $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).v
|
||||||
|
$(verilog): $(firrtl) $(FIRRTL_JAR)
|
||||||
|
$(FIRRTL) -i $(firrtl) -o $@ -X verilog
|
||||||
|
ifneq ($(PATCHVERILOG),"")
|
||||||
|
$(PATCHVERILOG)
|
||||||
|
endif
|
||||||
|
|
||||||
|
.PHONY: verilog
|
||||||
|
verilog: $(verilog)
|
||||||
|
|
||||||
|
romgen := $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).rom.v
|
||||||
|
$(romgen): $(verilog)
|
||||||
|
ifneq ($(BOOTROM_DIR),"")
|
||||||
|
$(MAKE) -C $(BOOTROM_DIR) romgen
|
||||||
|
mv $(BUILD_DIR)/rom.v $@
|
||||||
|
endif
|
||||||
|
|
||||||
|
.PHONY: romgen
|
||||||
|
romgen: $(romgen)
|
||||||
|
|
||||||
|
f := $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).vsrcs.F
|
||||||
|
$(f):
|
||||||
|
echo $(VSRCS) > $@
|
||||||
|
|
||||||
|
bit := $(BUILD_DIR)/obj/$(MODEL).bit
|
||||||
|
$(bit): $(romgen) $(f)
|
||||||
|
cd $(BUILD_DIR); vivado \
|
||||||
|
-nojournal -mode batch \
|
||||||
|
-source $(fpga_common_script_dir)/vivado.tcl \
|
||||||
|
-tclargs \
|
||||||
|
-top-module "$(MODEL)" \
|
||||||
|
-F "$(f)" \
|
||||||
|
-ip-vivado-tcls "$(shell find '$(BUILD_DIR)' -name '*.vivado.tcl')" \
|
||||||
|
-board "$(BOARD)"
|
||||||
|
|
||||||
|
|
||||||
|
# Build .mcs
|
||||||
|
mcs := $(BUILD_DIR)/obj/$(MODEL).mcs
|
||||||
|
$(mcs): $(bit)
|
||||||
|
cd $(BUILD_DIR); vivado -nojournal -mode batch -source $(fpga_common_script_dir)/write_cfgmem.tcl -tclargs $(BOARD) $@ $<
|
||||||
|
|
||||||
|
.PHONY: mcs
|
||||||
|
mcs: $(mcs)
|
||||||
|
|
||||||
|
# Build Libero project
|
||||||
|
prjx := $(BUILD_DIR)/libero/$(MODEL).prjx
|
||||||
|
$(prjx): $(verilog)
|
||||||
|
cd $(BUILD_DIR); libero SCRIPT:$(fpga_common_script_dir)/libero.tcl SCRIPT_ARGS:"$(BUILD_DIR) $(MODEL) $(PROJECT) $(CONFIG) $(BOARD)"
|
||||||
|
|
||||||
|
.PHONY: prjx
|
||||||
|
prjx: $(prjx)
|
||||||
|
|
||||||
|
# Clean
|
||||||
|
.PHONY: clean
|
||||||
|
clean:
|
||||||
|
ifneq ($(BOOTROM_DIR),"")
|
||||||
|
$(MAKE) -C $(BOOTROM_DIR) clean
|
||||||
|
endif
|
||||||
|
$(MAKE) -C $(FPGA_DIR) clean
|
||||||
|
rm -rf $(BUILD_DIR)
|
||||||
1
fpga/fpga-shells
Submodule
1
fpga/fpga-shells
Submodule
Submodule fpga/fpga-shells added at e8e7f8a321
65
fpga/src/main/scala/arty/Config.scala
Normal file
65
fpga/src/main/scala/arty/Config.scala
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
package sifive.freedom.everywhere.e300artydevkit
|
||||||
|
|
||||||
|
import freechips.rocketchip.config._
|
||||||
|
import freechips.rocketchip.subsystem._
|
||||||
|
import freechips.rocketchip.devices.debug._
|
||||||
|
import freechips.rocketchip.devices.tilelink._
|
||||||
|
import freechips.rocketchip.diplomacy.{DTSModel, DTSTimebase}
|
||||||
|
import freechips.rocketchip.system._
|
||||||
|
import freechips.rocketchip.tile._
|
||||||
|
|
||||||
|
import sifive.blocks.devices.mockaon._
|
||||||
|
import sifive.blocks.devices.gpio._
|
||||||
|
import sifive.blocks.devices.pwm._
|
||||||
|
import sifive.blocks.devices.spi._
|
||||||
|
import sifive.blocks.devices.uart._
|
||||||
|
import sifive.blocks.devices.i2c._
|
||||||
|
|
||||||
|
// Default FreedomEConfig
|
||||||
|
class DefaultFreedomEConfig extends Config (
|
||||||
|
new WithNBreakpoints(2) ++
|
||||||
|
new WithNExtTopInterrupts(0) ++
|
||||||
|
new WithJtagDTM ++
|
||||||
|
new TinyConfig
|
||||||
|
)
|
||||||
|
|
||||||
|
// Freedom E300 Arty Dev Kit Peripherals
|
||||||
|
class E300DevKitPeripherals extends Config((site, here, up) => {
|
||||||
|
case PeripheryGPIOKey => List(
|
||||||
|
GPIOParams(address = 0x10012000, width = 32, includeIOF = true))
|
||||||
|
case PeripheryPWMKey => List(
|
||||||
|
PWMParams(address = 0x10015000, cmpWidth = 8),
|
||||||
|
PWMParams(address = 0x10025000, cmpWidth = 16),
|
||||||
|
PWMParams(address = 0x10035000, cmpWidth = 16))
|
||||||
|
case PeripherySPIKey => List(
|
||||||
|
SPIParams(csWidth = 4, rAddress = 0x10024000, defaultSampleDel = 3),
|
||||||
|
SPIParams(csWidth = 1, rAddress = 0x10034000, defaultSampleDel = 3))
|
||||||
|
case PeripherySPIFlashKey => List(
|
||||||
|
SPIFlashParams(
|
||||||
|
fAddress = 0x20000000,
|
||||||
|
rAddress = 0x10014000,
|
||||||
|
defaultSampleDel = 3))
|
||||||
|
case PeripheryUARTKey => List(
|
||||||
|
UARTParams(address = 0x10013000),
|
||||||
|
UARTParams(address = 0x10023000))
|
||||||
|
case PeripheryI2CKey => List(
|
||||||
|
I2CParams(address = 0x10016000))
|
||||||
|
case PeripheryMockAONKey =>
|
||||||
|
MockAONParams(address = 0x10000000)
|
||||||
|
case PeripheryMaskROMKey => List(
|
||||||
|
MaskROMParams(address = 0x10000, name = "BootROM"))
|
||||||
|
})
|
||||||
|
|
||||||
|
// Freedom E300 Arty Dev Kit Peripherals
|
||||||
|
class E300ArtyDevKitConfig extends Config(
|
||||||
|
new E300DevKitPeripherals ++
|
||||||
|
new DefaultFreedomEConfig().alter((site,here,up) => {
|
||||||
|
case DTSTimebase => BigInt(32768)
|
||||||
|
case JtagDTMKey => new JtagDTMConfig (
|
||||||
|
idcodeVersion = 2,
|
||||||
|
idcodePartNum = 0x000,
|
||||||
|
idcodeManufId = 0x489,
|
||||||
|
debugIdleCycles = 5)
|
||||||
|
})
|
||||||
|
)
|
||||||
193
fpga/src/main/scala/arty/FPGAChip.scala
Normal file
193
fpga/src/main/scala/arty/FPGAChip.scala
Normal file
@@ -0,0 +1,193 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
package sifive.freedom.everywhere.e300artydevkit
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
import chisel3.core.{attach}
|
||||||
|
import chisel3.experimental.{withClockAndReset}
|
||||||
|
|
||||||
|
import freechips.rocketchip.config._
|
||||||
|
import freechips.rocketchip.diplomacy.{LazyModule}
|
||||||
|
|
||||||
|
import sifive.blocks.devices.gpio._
|
||||||
|
import sifive.blocks.devices.spi._
|
||||||
|
|
||||||
|
import sifive.fpgashells.shell.xilinx.artyshell.{ArtyShell}
|
||||||
|
import sifive.fpgashells.ip.xilinx.{IBUFG, IOBUF, PULLUP, PowerOnResetFPGAOnly}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// E300ArtyDevKitFPGAChip
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class E300ArtyDevKitFPGAChip(implicit override val p: Parameters) extends ArtyShell {
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// Clock divider
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
val slow_clock = Wire(Bool())
|
||||||
|
|
||||||
|
// Divide clock by 256, used to generate 32.768 kHz clock for AON block
|
||||||
|
withClockAndReset(clock_8MHz, ~mmcm_locked) {
|
||||||
|
val clockToggleReg = RegInit(false.B)
|
||||||
|
val (_, slowTick) = Counter(true.B, 256)
|
||||||
|
when (slowTick) {clockToggleReg := ~clockToggleReg}
|
||||||
|
slow_clock := clockToggleReg
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// DUT
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
withClockAndReset(clock_32MHz, ck_rst) {
|
||||||
|
val dut = Module(new E300ArtyDevKitPlatform)
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// SPI flash IOBUFs
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
|
IOBUF(qspi_sck, dut.io.pins.qspi.sck)
|
||||||
|
IOBUF(qspi_cs, dut.io.pins.qspi.cs(0))
|
||||||
|
|
||||||
|
IOBUF(qspi_dq(0), dut.io.pins.qspi.dq(0))
|
||||||
|
IOBUF(qspi_dq(1), dut.io.pins.qspi.dq(1))
|
||||||
|
IOBUF(qspi_dq(2), dut.io.pins.qspi.dq(2))
|
||||||
|
IOBUF(qspi_dq(3), dut.io.pins.qspi.dq(3))
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// JTAG IOBUFs
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
|
dut.io.pins.jtag.TCK.i.ival := IBUFG(IOBUF(jd_2).asClock).asUInt
|
||||||
|
|
||||||
|
IOBUF(jd_5, dut.io.pins.jtag.TMS)
|
||||||
|
PULLUP(jd_5)
|
||||||
|
|
||||||
|
IOBUF(jd_4, dut.io.pins.jtag.TDI)
|
||||||
|
PULLUP(jd_4)
|
||||||
|
|
||||||
|
IOBUF(jd_0, dut.io.pins.jtag.TDO)
|
||||||
|
|
||||||
|
// mimic putting a pullup on this line (part of reset vote)
|
||||||
|
SRST_n := IOBUF(jd_6)
|
||||||
|
PULLUP(jd_6)
|
||||||
|
|
||||||
|
// jtag reset
|
||||||
|
val jtag_power_on_reset = PowerOnResetFPGAOnly(clock_32MHz)
|
||||||
|
dut.io.jtag_reset := jtag_power_on_reset
|
||||||
|
|
||||||
|
// debug reset
|
||||||
|
dut_ndreset := dut.io.ndreset
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// Assignment to package pins
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// Pins IO0-IO13
|
||||||
|
//
|
||||||
|
// FTDI UART TX/RX are not connected to ck_io[0,1]
|
||||||
|
// the way they are on Arduino boards. We copy outgoing
|
||||||
|
// data to both places, switch 3 (sw[3]) determines whether
|
||||||
|
// input to UART comes from FTDI chip or gpio_16 (shield pin PD0)
|
||||||
|
|
||||||
|
val iobuf_ck0 = Module(new IOBUF())
|
||||||
|
iobuf_ck0.io.I := dut.io.pins.gpio.pins(16).o.oval
|
||||||
|
iobuf_ck0.io.T := ~dut.io.pins.gpio.pins(16).o.oe
|
||||||
|
attach(iobuf_ck0.io.IO, ck_io(0)) // UART0 RX
|
||||||
|
|
||||||
|
val iobuf_uart_txd = Module(new IOBUF())
|
||||||
|
iobuf_uart_txd.io.I := dut.io.pins.gpio.pins(16).o.oval
|
||||||
|
iobuf_uart_txd.io.T := ~dut.io.pins.gpio.pins(16).o.oe
|
||||||
|
attach(iobuf_uart_txd.io.IO, uart_txd_in)
|
||||||
|
|
||||||
|
// gpio(16) input is shared between FTDI TX pin and the Arduino shield pin using SW[3]
|
||||||
|
val sw_3_in = IOBUF(sw_3)
|
||||||
|
dut.io.pins.gpio.pins(16).i.ival := Mux(sw_3_in,
|
||||||
|
iobuf_ck0.io.O & dut.io.pins.gpio.pins(16).o.ie,
|
||||||
|
iobuf_uart_txd.io.O & dut.io.pins.gpio.pins(16).o.ie)
|
||||||
|
|
||||||
|
IOBUF(uart_rxd_out, dut.io.pins.gpio.pins(17))
|
||||||
|
|
||||||
|
// Shield header row 0: PD2-PD7
|
||||||
|
IOBUF(ck_io(2), dut.io.pins.gpio.pins(18))
|
||||||
|
IOBUF(ck_io(3), dut.io.pins.gpio.pins(19)) // PWM1(1)
|
||||||
|
IOBUF(ck_io(4), dut.io.pins.gpio.pins(20)) // PWM1(0)
|
||||||
|
IOBUF(ck_io(5), dut.io.pins.gpio.pins(21)) // PWM1(2)
|
||||||
|
IOBUF(ck_io(6), dut.io.pins.gpio.pins(22)) // PWM1(3)
|
||||||
|
IOBUF(ck_io(7), dut.io.pins.gpio.pins(23))
|
||||||
|
|
||||||
|
// Header row 1: PB0-PB5
|
||||||
|
IOBUF(ck_io(8), dut.io.pins.gpio.pins(0)) // PWM0(0)
|
||||||
|
IOBUF(ck_io(9), dut.io.pins.gpio.pins(1)) // PWM0(1)
|
||||||
|
IOBUF(ck_io(10), dut.io.pins.gpio.pins(2)) // SPI CS(0) / PWM0(2)
|
||||||
|
IOBUF(ck_io(11), dut.io.pins.gpio.pins(3)) // SPI MOSI / PWM0(3)
|
||||||
|
IOBUF(ck_io(12), dut.io.pins.gpio.pins(4)) // SPI MISO
|
||||||
|
IOBUF(ck_io(13), dut.io.pins.gpio.pins(5)) // SPI SCK
|
||||||
|
|
||||||
|
dut.io.pins.gpio.pins(6).i.ival := 0.U
|
||||||
|
dut.io.pins.gpio.pins(7).i.ival := 0.U
|
||||||
|
dut.io.pins.gpio.pins(8).i.ival := 0.U
|
||||||
|
|
||||||
|
// Header row 3: A0-A5 (we don't support using them as analog inputs)
|
||||||
|
// just treat them as regular digital GPIOs
|
||||||
|
IOBUF(ck_io(15), dut.io.pins.gpio.pins(9)) // A1 = CS(2)
|
||||||
|
IOBUF(ck_io(16), dut.io.pins.gpio.pins(10)) // A2 = CS(3) / PWM2(0)
|
||||||
|
IOBUF(ck_io(17), dut.io.pins.gpio.pins(11)) // A3 = PWM2(1)
|
||||||
|
IOBUF(ck_io(18), dut.io.pins.gpio.pins(12)) // A4 = PWM2(2) / SDA
|
||||||
|
IOBUF(ck_io(19), dut.io.pins.gpio.pins(13)) // A5 = PWM2(3) / SCL
|
||||||
|
|
||||||
|
// Mirror outputs of GPIOs with PWM peripherals to RGB LEDs on Arty
|
||||||
|
// assign RGB LED0 R,G,B inputs = PWM0(1,2,3) when iof_1 is active
|
||||||
|
IOBUF(led0_r, dut.io.pins.gpio.pins(1))
|
||||||
|
IOBUF(led0_g, dut.io.pins.gpio.pins(2))
|
||||||
|
IOBUF(led0_b, dut.io.pins.gpio.pins(3))
|
||||||
|
|
||||||
|
// Note that this is the one which is actually connected on the HiFive/Crazy88
|
||||||
|
// Board. Same with RGB LED1 R,G,B inputs = PWM1(1,2,3) when iof_1 is active
|
||||||
|
IOBUF(led1_r, dut.io.pins.gpio.pins(19))
|
||||||
|
IOBUF(led1_g, dut.io.pins.gpio.pins(21))
|
||||||
|
IOBUF(led1_b, dut.io.pins.gpio.pins(22))
|
||||||
|
|
||||||
|
// and RGB LED2 R,G,B inputs = PWM2(1,2,3) when iof_1 is active
|
||||||
|
IOBUF(led2_r, dut.io.pins.gpio.pins(11))
|
||||||
|
IOBUF(led2_g, dut.io.pins.gpio.pins(12))
|
||||||
|
IOBUF(led2_b, dut.io.pins.gpio.pins(13))
|
||||||
|
|
||||||
|
// Only 19 out of 20 shield pins connected to GPIO pins
|
||||||
|
// Shield pin A5 (pin 14) left unconnected
|
||||||
|
// The buttons are connected to some extra GPIO pins not connected on the
|
||||||
|
// HiFive1 board
|
||||||
|
IOBUF(btn_0, dut.io.pins.gpio.pins(15))
|
||||||
|
IOBUF(btn_1, dut.io.pins.gpio.pins(30))
|
||||||
|
IOBUF(btn_2, dut.io.pins.gpio.pins(31))
|
||||||
|
|
||||||
|
val iobuf_btn_3 = Module(new IOBUF())
|
||||||
|
iobuf_btn_3.io.I := ~dut.io.pins.aon.pmu.dwakeup_n.o.oval
|
||||||
|
iobuf_btn_3.io.T := ~dut.io.pins.aon.pmu.dwakeup_n.o.oe
|
||||||
|
attach(btn_3, iobuf_btn_3.io.IO)
|
||||||
|
dut.io.pins.aon.pmu.dwakeup_n.i.ival := ~iobuf_btn_3.io.O & dut.io.pins.aon.pmu.dwakeup_n.o.ie
|
||||||
|
|
||||||
|
// UART1 RX/TX pins are assigned to PMOD_D connector pins 0/1
|
||||||
|
IOBUF(ja_0, dut.io.pins.gpio.pins(25)) // UART1 TX
|
||||||
|
IOBUF(ja_1, dut.io.pins.gpio.pins(24)) // UART1 RX
|
||||||
|
|
||||||
|
// SPI2 pins mapped to 6 pin ICSP connector (standard on later
|
||||||
|
// arduinos) These are connected to some extra GPIO pins not connected
|
||||||
|
// on the HiFive1 board
|
||||||
|
IOBUF(ck_ss, dut.io.pins.gpio.pins(26))
|
||||||
|
IOBUF(ck_mosi, dut.io.pins.gpio.pins(27))
|
||||||
|
IOBUF(ck_miso, dut.io.pins.gpio.pins(28))
|
||||||
|
IOBUF(ck_sck, dut.io.pins.gpio.pins(29))
|
||||||
|
|
||||||
|
// Use the LEDs for some more useful debugging things
|
||||||
|
IOBUF(led_0, ck_rst)
|
||||||
|
IOBUF(led_1, SRST_n)
|
||||||
|
IOBUF(led_2, dut.io.pins.aon.pmu.dwakeup_n.i.ival)
|
||||||
|
IOBUF(led_3, dut.io.pins.gpio.pins(14))
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
// Unconnected inputs
|
||||||
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
|
dut.io.pins.aon.erst_n.i.ival := ~reset_periph
|
||||||
|
dut.io.pins.aon.lfextclk.i.ival := slow_clock
|
||||||
|
dut.io.pins.aon.pmu.vddpaden.i.ival := 1.U
|
||||||
|
}
|
||||||
|
}
|
||||||
178
fpga/src/main/scala/arty/Platform.scala
Normal file
178
fpga/src/main/scala/arty/Platform.scala
Normal file
@@ -0,0 +1,178 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
package sifive.freedom.everywhere.e300artydevkit
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
|
||||||
|
import freechips.rocketchip.config._
|
||||||
|
import freechips.rocketchip.subsystem._
|
||||||
|
import freechips.rocketchip.devices.debug._
|
||||||
|
import freechips.rocketchip.devices.tilelink._
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import freechips.rocketchip.util.ResetCatchAndSync
|
||||||
|
import freechips.rocketchip.system._
|
||||||
|
|
||||||
|
import sifive.blocks.devices.mockaon._
|
||||||
|
import sifive.blocks.devices.gpio._
|
||||||
|
import sifive.blocks.devices.jtag._
|
||||||
|
import sifive.blocks.devices.pwm._
|
||||||
|
import sifive.blocks.devices.spi._
|
||||||
|
import sifive.blocks.devices.uart._
|
||||||
|
import sifive.blocks.devices.i2c._
|
||||||
|
import sifive.blocks.devices.pinctrl._
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// PinGen
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
object PinGen {
|
||||||
|
def apply(): BasePin = {
|
||||||
|
val pin = new BasePin()
|
||||||
|
pin
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// E300ArtyDevKitPlatformIO
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class E300ArtyDevKitPlatformIO(implicit val p: Parameters) extends Bundle {
|
||||||
|
val pins = new Bundle {
|
||||||
|
val jtag = new JTAGPins(() => PinGen(), false)
|
||||||
|
val gpio = new GPIOPins(() => PinGen(), p(PeripheryGPIOKey)(0))
|
||||||
|
val qspi = new SPIPins(() => PinGen(), p(PeripherySPIFlashKey)(0))
|
||||||
|
val aon = new MockAONWrapperPins()
|
||||||
|
}
|
||||||
|
val jtag_reset = Bool(INPUT)
|
||||||
|
val ndreset = Bool(OUTPUT)
|
||||||
|
}
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// E300ArtyDevKitPlatform
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class E300ArtyDevKitPlatform(implicit val p: Parameters) extends Module {
|
||||||
|
val sys = Module(LazyModule(new E300ArtyDevKitSystem).module)
|
||||||
|
val io = new E300ArtyDevKitPlatformIO
|
||||||
|
|
||||||
|
// This needs to be de-asserted synchronously to the coreClk.
|
||||||
|
val async_corerst = sys.aon.rsts.corerst
|
||||||
|
// Add in debug-controlled reset.
|
||||||
|
sys.reset := ResetCatchAndSync(clock, async_corerst, 20)
|
||||||
|
Debug.connectDebugClockAndReset(sys.debug, clock)
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// Check for unsupported rocket-chip connections
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
require (p(NExtTopInterrupts) == 0, "No Top-level interrupts supported");
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// Build GPIO Pin Mux
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// Pin Mux for UART, SPI, PWM
|
||||||
|
// First convert the System outputs into "IOF" using the respective *GPIOPort
|
||||||
|
// converters.
|
||||||
|
|
||||||
|
val sys_uart = sys.uart
|
||||||
|
val sys_pwm = sys.pwm
|
||||||
|
val sys_spi = sys.spi
|
||||||
|
val sys_i2c = sys.i2c
|
||||||
|
|
||||||
|
val uart_pins = p(PeripheryUARTKey).map { c => Wire(new UARTPins(() => PinGen()))}
|
||||||
|
val pwm_pins = p(PeripheryPWMKey).map { c => Wire(new PWMPins(() => PinGen(), c))}
|
||||||
|
val spi_pins = p(PeripherySPIKey).map { c => Wire(new SPIPins(() => PinGen(), c))}
|
||||||
|
val i2c_pins = p(PeripheryI2CKey).map { c => Wire(new I2CPins(() => PinGen()))}
|
||||||
|
|
||||||
|
(uart_pins zip sys_uart) map {case (p, r) => UARTPinsFromPort(p, r, clock = clock, reset = reset, syncStages = 0)}
|
||||||
|
(pwm_pins zip sys_pwm) map {case (p, r) => PWMPinsFromPort(p, r) }
|
||||||
|
(spi_pins zip sys_spi) map {case (p, r) => SPIPinsFromPort(p, r, clock = clock, reset = reset, syncStages = 0)}
|
||||||
|
(i2c_pins zip sys_i2c) map {case (p, r) => I2CPinsFromPort(p, r, clock = clock, reset = reset, syncStages = 0)}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// Default Pin connections before attaching pinmux
|
||||||
|
|
||||||
|
for (iof_0 <- sys.gpio(0).iof_0.get) {
|
||||||
|
iof_0.default()
|
||||||
|
}
|
||||||
|
|
||||||
|
for (iof_1 <- sys.gpio(0).iof_1.get) {
|
||||||
|
iof_1.default()
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
val iof_0 = sys.gpio(0).iof_0.get
|
||||||
|
val iof_1 = sys.gpio(0).iof_1.get
|
||||||
|
|
||||||
|
// SPI1 (0 is the dedicated)
|
||||||
|
BasePinToIOF(spi_pins(0).cs(0), iof_0(2))
|
||||||
|
BasePinToIOF(spi_pins(0).dq(0), iof_0(3))
|
||||||
|
BasePinToIOF(spi_pins(0).dq(1), iof_0(4))
|
||||||
|
BasePinToIOF(spi_pins(0).sck, iof_0(5))
|
||||||
|
BasePinToIOF(spi_pins(0).dq(2), iof_0(6))
|
||||||
|
BasePinToIOF(spi_pins(0).dq(3), iof_0(7))
|
||||||
|
BasePinToIOF(spi_pins(0).cs(1), iof_0(8))
|
||||||
|
BasePinToIOF(spi_pins(0).cs(2), iof_0(9))
|
||||||
|
BasePinToIOF(spi_pins(0).cs(3), iof_0(10))
|
||||||
|
|
||||||
|
// SPI2
|
||||||
|
BasePinToIOF(spi_pins(1).cs(0), iof_0(26))
|
||||||
|
BasePinToIOF(spi_pins(1).dq(0), iof_0(27))
|
||||||
|
BasePinToIOF(spi_pins(1).dq(1), iof_0(28))
|
||||||
|
BasePinToIOF(spi_pins(1).sck, iof_0(29))
|
||||||
|
BasePinToIOF(spi_pins(1).dq(2), iof_0(30))
|
||||||
|
BasePinToIOF(spi_pins(1).dq(3), iof_0(31))
|
||||||
|
|
||||||
|
// I2C
|
||||||
|
if (p(PeripheryI2CKey).length == 1) {
|
||||||
|
BasePinToIOF(i2c_pins(0).sda, iof_0(12))
|
||||||
|
BasePinToIOF(i2c_pins(0).scl, iof_0(13))
|
||||||
|
}
|
||||||
|
|
||||||
|
// UART0
|
||||||
|
BasePinToIOF(uart_pins(0).rxd, iof_0(16))
|
||||||
|
BasePinToIOF(uart_pins(0).txd, iof_0(17))
|
||||||
|
|
||||||
|
// UART1
|
||||||
|
BasePinToIOF(uart_pins(1).rxd, iof_0(24))
|
||||||
|
BasePinToIOF(uart_pins(1).txd, iof_0(25))
|
||||||
|
|
||||||
|
//PWM
|
||||||
|
BasePinToIOF(pwm_pins(0).pwm(0), iof_1(0) )
|
||||||
|
BasePinToIOF(pwm_pins(0).pwm(1), iof_1(1) )
|
||||||
|
BasePinToIOF(pwm_pins(0).pwm(2), iof_1(2) )
|
||||||
|
BasePinToIOF(pwm_pins(0).pwm(3), iof_1(3) )
|
||||||
|
|
||||||
|
BasePinToIOF(pwm_pins(1).pwm(1), iof_1(19))
|
||||||
|
BasePinToIOF(pwm_pins(1).pwm(0), iof_1(20))
|
||||||
|
BasePinToIOF(pwm_pins(1).pwm(2), iof_1(21))
|
||||||
|
BasePinToIOF(pwm_pins(1).pwm(3), iof_1(22))
|
||||||
|
|
||||||
|
BasePinToIOF(pwm_pins(2).pwm(0), iof_1(10))
|
||||||
|
BasePinToIOF(pwm_pins(2).pwm(1), iof_1(11))
|
||||||
|
BasePinToIOF(pwm_pins(2).pwm(2), iof_1(12))
|
||||||
|
BasePinToIOF(pwm_pins(2).pwm(3), iof_1(13))
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
// Drive actual Pads
|
||||||
|
//-----------------------------------------------------------------------
|
||||||
|
|
||||||
|
// Result of Pin Mux
|
||||||
|
GPIOPinsFromPort(io.pins.gpio, sys.gpio(0))
|
||||||
|
|
||||||
|
// Dedicated SPI Pads
|
||||||
|
SPIPinsFromPort(io.pins.qspi, sys.qspi(0), clock = sys.clock, reset = sys.reset, syncStages = 3)
|
||||||
|
|
||||||
|
// JTAG Debug Interface
|
||||||
|
val sjtag = sys.debug.get.systemjtag.get
|
||||||
|
JTAGPinsFromPort(io.pins.jtag, sjtag.jtag)
|
||||||
|
sjtag.reset := io.jtag_reset
|
||||||
|
sjtag.mfr_id := p(JtagDTMKey).idcodeManufId.U(11.W)
|
||||||
|
|
||||||
|
io.ndreset := sys.debug.get.ndreset
|
||||||
|
|
||||||
|
// AON Pads -- direct connection is OK because
|
||||||
|
// EnhancedPin is hard-coded in MockAONPads
|
||||||
|
// and thus there is no .fromPort method.
|
||||||
|
io.pins.aon <> sys.aon.pins
|
||||||
|
}
|
||||||
51
fpga/src/main/scala/arty/System.scala
Normal file
51
fpga/src/main/scala/arty/System.scala
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
// See LICENSE for license details.
|
||||||
|
package sifive.freedom.everywhere.e300artydevkit
|
||||||
|
|
||||||
|
import Chisel._
|
||||||
|
|
||||||
|
import freechips.rocketchip.config._
|
||||||
|
import freechips.rocketchip.subsystem._
|
||||||
|
import freechips.rocketchip.devices.debug._
|
||||||
|
import freechips.rocketchip.devices.tilelink._
|
||||||
|
import freechips.rocketchip.diplomacy._
|
||||||
|
import freechips.rocketchip.system._
|
||||||
|
|
||||||
|
import sifive.blocks.devices.mockaon._
|
||||||
|
import sifive.blocks.devices.gpio._
|
||||||
|
import sifive.blocks.devices.pwm._
|
||||||
|
import sifive.blocks.devices.spi._
|
||||||
|
import sifive.blocks.devices.uart._
|
||||||
|
import sifive.blocks.devices.i2c._
|
||||||
|
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
// E300ArtyDevKitSystem
|
||||||
|
//-------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class E300ArtyDevKitSystem(implicit p: Parameters) extends RocketSubsystem
|
||||||
|
with HasPeripheryDebug
|
||||||
|
with HasPeripheryMockAON
|
||||||
|
with chipyard.example.CanHavePeripheryGCD
|
||||||
|
with HasPeripheryUART
|
||||||
|
with HasPeripherySPIFlash
|
||||||
|
with HasPeripherySPI
|
||||||
|
with HasPeripheryGPIO
|
||||||
|
with HasPeripheryPWM
|
||||||
|
with HasPeripheryI2C {
|
||||||
|
override lazy val module = new E300ArtyDevKitSystemModule(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
class E300ArtyDevKitSystemModule[+L <: E300ArtyDevKitSystem](_outer: L)
|
||||||
|
extends RocketSubsystemModuleImp(_outer)
|
||||||
|
with HasPeripheryDebugModuleImp
|
||||||
|
with chipyard.example.CanHavePeripheryGCDModuleImp
|
||||||
|
with HasPeripheryUARTModuleImp
|
||||||
|
with HasPeripherySPIModuleImp
|
||||||
|
with HasPeripheryGPIOModuleImp
|
||||||
|
with HasPeripherySPIFlashModuleImp
|
||||||
|
with HasPeripheryMockAONModuleImp
|
||||||
|
with HasPeripheryPWMModuleImp
|
||||||
|
with HasPeripheryI2CModuleImp {
|
||||||
|
// Reset vector is set to the location of the mask rom
|
||||||
|
val maskROMParams = p(PeripheryMaskROMKey)
|
||||||
|
global_reset_vector := maskROMParams(0).address.U
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user