diff --git a/.gitignore b/.gitignore index c914cc5..7b684eb 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,7 @@ build/.../*.json # Log log* *.jou -*.log \ No newline at end of file +*.log + +# Env lds +firmware/fsbl/linker/board.lds \ No newline at end of file diff --git a/Makefile b/Makefile index 4ef0b17..46d6cbd 100644 --- a/Makefile +++ b/Makefile @@ -3,9 +3,12 @@ # Email: phantom@zju.edu.cn # This file is under MIT License, see https://www.phvntom.tech/LICENSE.txt +TARGET_FPGA ?= a7 +SUPPORTED_BOARDS := vc707 a7 + TOP := $(CURDIR) SRC := $(TOP)/repo -BUILD := $(TOP)/build +BUILD := $(TOP)/build/$(TARGET_FPGA) CONFIG := $(TOP)/conf SBT_BUILD := $(TOP)/target $(TOP)/project/target $(TOP)/project/project @@ -13,23 +16,44 @@ ifndef RISCV $(error $$RISCV is undefined, please set $$RISCV to your riscv-toolchain) endif +ifeq ($(filter $(TARGET_FPGA),$(SUPPORTED_BOARDS)),) +$(error $(TARGET_FPGA) is not supported yet. Choose one from $(SUPPORTED_BOARDS)) +endif + all: bitstream +####################################### +# +# Board Args Mapper +# +####################################### + +freq_a7 := 50 +freq_vc707 := 100 + +szmem_a7 := 128 +szmem_vc707 := 1024 + +board_a7 := nexys_a7 +board_vc707 := vc707 + ####################################### # # Verilog Generator # ####################################### +TARGET_FPGA_UP := $(shell echo $(TARGET_FPGA) | tr '[:lower:]' '[:upper:]') ROCKET_SRC := $(SRC)/rocket-chip ROCKET_BUILD := $(BUILD)/rocket-chip ROCKET_JVM_MEM ?= 2G ROCKET_JAVA := java -Xmx$(ROCKET_JVM_MEM) -Xss8M -jar $(ROCKET_SRC)/sbt-launch.jar ROCKET_TOP_PROJ ?= starship.fpga -ROCKET_TOP ?= TestHarness +ROCKET_TOP ?= TestHarness$(TARGET_FPGA_UP) ROCKET_CON_PROJ ?= starship.fpga ROCKET_CONFIG ?= StarshipFPGAConfig -ROCKET_FREQ ?= 100 +ROCKET_FREQ ?= $(freq_$(TARGET_FPGA)) +ROCKET_SZMEM ?= $(szmem_$(TARGET_FPGA)) ROCKET_OUTPUT := $(ROCKET_TOP_PROJ).$(ROCKET_TOP).$(ROCKET_CONFIG) ROCKET_VERILOG := $(ROCKET_BUILD)/$(ROCKET_OUTPUT).v ROCKET_FIRRTL := $(ROCKET_BUILD)/$(ROCKET_OUTPUT).fir @@ -38,7 +62,7 @@ $(ROCKET_FIRRTL): mkdir -p $(ROCKET_BUILD) $(ROCKET_JAVA) "runMain freechips.rocketchip.system.Generator \ -td $(ROCKET_BUILD) -T $(ROCKET_TOP_PROJ).$(ROCKET_TOP) \ - -C $(ROCKET_CON_PROJ).$(ROCKET_CONFIG),$(ROCKET_CON_PROJ).With$(ROCKET_FREQ)MHz \ + -C $(ROCKET_CON_PROJ).$(ROCKET_CONFIG),$(ROCKET_CON_PROJ).With$(ROCKET_FREQ)MHz,$(ROCKET_CON_PROJ).With$(ROCKET_SZMEM)MB,$(ROCKET_CON_PROJ).With$(TARGET_FPGA_UP) \ -n $(ROCKET_OUTPUT)" $(ROCKET_VERILOG): $(ROCKET_FIRRTL) @@ -64,7 +88,7 @@ FSBL_SRC := $(FIRMWARE_SRC)/fsbl FSBL_BUILD := $(FIRMWARE_BUILD)/fsbl STARSHIP_ROM_HEX := $(FSBL_BUILD)/sdboot.hex -BOARD := vc707 +BOARD_NAME := $(board_$(TARGET_FPGA)) SCRIPT_SRC := $(SRC)/fpga-shells VIVADO_SRC := $(SCRIPT_SRC)/xilinx VIVADO_BUILD := $(BUILD)/vivado @@ -77,8 +101,8 @@ VERILOG_SRC := $(VERILOG_SRAM) \ $(STARSHIP_ROM_HEX) \ $(ROCKET_BUILD)/$(ROCKET_OUTPUT).v \ $(ROCKET_BUILD)/plusarg_reader.v \ - $(VIVADO_SRC)/$(BOARD)/vsrc/sdio.v \ - $(VIVADO_SRC)/$(BOARD)/vsrc/vc707reset.v \ + $(VIVADO_SRC)/vc707/vsrc/sdio.v \ + $(VIVADO_SRC)/vc707/vsrc/vc707reset.v \ $(SCRIPT_SRC)/testbench/SimTestHarness.v $(VERILOG_INCLUDE): mkdir -p $(VIVADO_BUILD) @@ -88,7 +112,7 @@ $(VERILOG_SRAM): $(ROCKET_SRC)/scripts/vlsi_mem_gen $(ROCKET_BUILD)/$(ROCKET_OUTPUT).sram.conf >> $@ $(STARSHIP_ROM_HEX): - $(MAKE) -C $(FSBL_SRC) PBUS_CLK=$(ROCKET_FREQ)000000 ROOT_DIR=$(TOP) ROCKET_OUTPUT=$(ROCKET_OUTPUT) hex + $(MAKE) -C $(FSBL_SRC) TARGET_FPGA=$(TARGET_FPGA) PBUS_CLK=$(ROCKET_FREQ)000000 ROOT_DIR=$(TOP) ROCKET_OUTPUT=$(ROCKET_OUTPUT) hex $(VERILOG_ROM): $(STARSHIP_ROM_HEX) $(ROCKET_SRC)/scripts/vlsi_rom_gen $(ROCKET_BUILD)/$(ROCKET_OUTPUT).rom.conf $< > $@ @@ -100,7 +124,7 @@ $(VIVADO_BITSTREAM): $(ROCKET_VERILOG) $(VERILOG_INCLUDE) $(VERILOG_SRAM) $(VERI -tclargs -F "$(VERILOG_INCLUDE)" \ -top-module "$(ROCKET_TOP)" \ -ip-vivado-tcls "$(shell find '$(ROCKET_BUILD)' -name '*.vivado.tcl')" \ - -board "$(BOARD)" + -board "$(BOARD_NAME)" bitstream: $(VIVADO_BITSTREAM) @@ -111,4 +135,4 @@ bitstream: $(VIVADO_BITSTREAM) ####################################### clean: - rm -rf $(BUILD) $(SBT_BUILD) \ No newline at end of file + rm -rf $(TOP)/build $(SBT_BUILD) \ No newline at end of file diff --git a/README.md b/README.md index f56ab49..6cb620e 100644 --- a/README.md +++ b/README.md @@ -6,11 +6,12 @@ The `starship` is short for "**STA**rt **R**i**S**c-v on c**HIP**", hope this pr Current support boards: - Xilinx Virtex-7 VC707 +- Digilent Nexys A7 100T This project is simple enough compared to *chipyard*. We will only focus on how to run the rocket processor cores on FPGAs and does not provide any simulation environment. This project will provide great convenience for the following people who: -- ~~have Xilinx Virtex-7 VC707...~~ (I will try to support more boards!) +- ~~have Xilinx Virtex-7 VC707 or Digilent Nexys A7 100T...~~ (I will try to support more boards!) - want to test design on FPGA with modified rocket-chip - want to have a overview about FPGA development diff --git a/firmware/fsbl/Makefile b/firmware/fsbl/Makefile index 8925523..c5e1fc3 100644 --- a/firmware/fsbl/Makefile +++ b/firmware/fsbl/Makefile @@ -1,6 +1,7 @@ # RISCV environment variable must be set +TARGET_FPGA ?= a7 ROOT_DIR ?= $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) -BUILD_DIR := $(ROOT_DIR)/build/firmware/fsbl +BUILD_DIR := $(ROOT_DIR)/build/$(TARGET_FPGA)/firmware/fsbl CC = $(RISCV)/bin/riscv64-unknown-elf-gcc OBJCOPY = $(RISCV)/bin/riscv64-unknown-elf-objcopy @@ -12,11 +13,16 @@ LFLAGS = -static -nostdlib -L ./linker -T sdboot.elf.lds PBUS_CLK ?= 1000000 # default to 1MHz but really should be overridden +mem_sz_a7 := 0x8000000 +mem_oft_a7 := 0x7fff000 +mem_sz_vc707 := 0x40000000 +mem_oft_vc707 := 0xffff000 + default: elf bin dump dtb := $(BUILD_DIR)/$(ROCKET_OUTPUT).dtb dts := $(BUILD_DIR)/$(ROCKET_OUTPUT).dts -dts_org := $(ROOT_DIR)/build/rocket-chip/$(ROCKET_OUTPUT).dts +dts_org := $(ROOT_DIR)/build/$(TARGET_FPGA)/rocket-chip/$(ROCKET_OUTPUT).dts $(dtb): $(dts_org) mkdir -p $(BUILD_DIR) @@ -27,7 +33,8 @@ $(dtb): $(dts_org) elf := $(BUILD_DIR)/sdboot.elf $(elf): head.S kprintf.c sd.c $(dtb) mkdir -p $(BUILD_DIR) - $(CC) $(CFLAGS) -DTL_CLK="$(PBUS_CLK)UL" -DDEVICE_TREE='"$(dtb)"' $(LFLAGS) -o $@ head.S sd.c kprintf.c + $(shell echo DDR_LENGTH = $(mem_sz_$(TARGET_FPGA))\; > linker/board.lds) + $(CC) $(CFLAGS) -DBOARD_SPECIFIC_OFFSET="$(mem_oft_$(TARGET_FPGA))" -DTL_CLK="$(PBUS_CLK)UL" -DDEVICE_TREE='"$(dtb)"' $(LFLAGS) -o $@ head.S sd.c kprintf.c .PHONY: elf elf: $(elf) diff --git a/firmware/fsbl/common.h b/firmware/fsbl/common.h index ccb9cd3..f5a5dd4 100644 --- a/firmware/fsbl/common.h +++ b/firmware/fsbl/common.h @@ -6,5 +6,8 @@ #define PAYLOAD_DEST MEMORY_MEM_ADDR #endif +#ifndef BOARD_SPECIFIC_OFFSET + #define BOARD_SPECIFIC_OFFSET 0xffff000 +#endif #endif diff --git a/firmware/fsbl/head.S b/firmware/fsbl/head.S index e0e243c..e5f06be 100644 --- a/firmware/fsbl/head.S +++ b/firmware/fsbl/head.S @@ -8,7 +8,7 @@ .globl _prog_start _prog_start: smp_pause(s1, s2) - li sp, (PAYLOAD_DEST + 0xffff000) + li sp, (PAYLOAD_DEST + BOARD_SPECIFIC_OFFSET) call main smp_resume(s1, s2) csrr a0, mhartid // hartid for next level bootloader diff --git a/firmware/fsbl/linker/memory.lds b/firmware/fsbl/linker/memory.lds index 02b8ed1..d6edc69 100644 --- a/firmware/fsbl/linker/memory.lds +++ b/firmware/fsbl/linker/memory.lds @@ -1,5 +1,7 @@ +INCLUDE board.lds + MEMORY { bootrom_mem (rx) : ORIGIN = 0x20000, LENGTH = 0x2000 - memory_mem (rwx) : ORIGIN = 0x80000000, LENGTH = 0x40000000 + memory_mem (rwx) : ORIGIN = 0x80000000, LENGTH = DDR_LENGTH } diff --git a/firmware/fsbl/sd.c b/firmware/fsbl/sd.c index 21a9914..3a6f343 100644 --- a/firmware/fsbl/sd.c +++ b/firmware/fsbl/sd.c @@ -54,7 +54,7 @@ static uint8_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) spi_xfer(arg); spi_xfer(crc); - n = 1000; + n = 10000; do { r = sd_dummy(); if (!(r & 0x80)) { @@ -116,9 +116,11 @@ static void sd_cmd55(void) static int sd_acmd41(void) { uint8_t r; + long timeout = 1000000; dputs("ACMD41"); do { sd_cmd55(); + while(timeout--); r = sd_cmd(0x69, 0x40000000, 0x77); /* HCS = 1 */ } while (r == 0x01); return (r != 0x00); diff --git a/firmware/zsbl/Makefile b/firmware/zsbl/Makefile index 68853a9..99e7f93 100644 --- a/firmware/zsbl/Makefile +++ b/firmware/zsbl/Makefile @@ -1,5 +1,6 @@ +TARGET_FPGA ?= a7 ROOT_DIR ?= $(dir $(abspath $(lastword $(MAKEFILE_LIST)))) -BUILD_DIR := $(ROOT_DIR)/build/firmware/zsbl +BUILD_DIR := $(ROOT_DIR)/build/$(TARGET_FPGA)/firmware/zsbl CC = $(RISCV)/bin/riscv64-unknown-elf-gcc OBJCOPY = $(RISCV)/bin/riscv64-unknown-elf-objcopy diff --git a/repo/fpga-shells b/repo/fpga-shells index 1e5b708..1ab276b 160000 --- a/repo/fpga-shells +++ b/repo/fpga-shells @@ -1 +1 @@ -Subproject commit 1e5b70805f6d7ac24fcdbc3368685d66e12597c5 +Subproject commit 1ab276b67cb5bf7d55441c846c85530a94ac89ec diff --git a/src/main/scala/FPGA/A7.scala b/src/main/scala/FPGA/A7.scala new file mode 100644 index 0000000..1153360 --- /dev/null +++ b/src/main/scala/FPGA/A7.scala @@ -0,0 +1,72 @@ +package starship.fpga + +import starship._ +import chisel3._ +import firrtl.FirrtlProtos.Firrtl.BigInt +import freechips.rocketchip.tile._ +import freechips.rocketchip.util._ +import freechips.rocketchip.prci._ +import freechips.rocketchip.config._ +import freechips.rocketchip.system._ +import freechips.rocketchip.tilelink._ +import freechips.rocketchip.subsystem._ +import freechips.rocketchip.diplomacy._ +import freechips.rocketchip.devices.debug._ +import freechips.rocketchip.devices.tilelink._ +import sifive.fpgashells.shell._ +import sifive.fpgashells.clocks._ +import sifive.blocks.devices.spi._ +import sifive.blocks.devices.uart._ +import sifive.fpgashells.ip.xilinx._ +import sifive.fpgashells.shell.xilinx.nexysa7shell._ +import sifive.fpgashells.devices.xilinx.digilentnexysa7mig._ +import sifive.blocks.devices.uart._ + +class StarshipFPGATopA7(implicit p: Parameters) extends StarshipSystem + with HasPeripheryUART + with HasPeripherySPI + with HasMemoryDigilentNexysA7MIG +{ + + val chosen = new DeviceSnippet { + def describe() = Description("chosen", Map( + "bootargs" -> Seq(ResourceString("nokaslr")) + )) + } + + val mmc = new MMCDevice(tlSpiNodes.head.device) + ResourceBinding { + Resource(mmc, "reg").bind(ResourceAddress(0)) + } + + override lazy val module = new StarshipFPGATopModuleImpA7(this) +} + +class StarshipFPGATopModuleImpA7[+L <: StarshipFPGATopA7](_outer: L) extends StarshipSystemModuleImp(_outer) + with HasPeripheryUARTModuleImp + with HasPeripherySPIModuleImp + with HasMemoryDigilentNexysA7MIGModuleImp + with DontTouch + +// VC707 shell has SPI to SDIO +// Arty A7 100T has different memory interface with VC707 +class TestHarnessA7(override implicit val p: Parameters) extends NexysA7Shell + with HasDDR2 { + + + dut_clock := (p(FPGAFrequencyKey) match { + case 50 => clk50 + case 200 => clk200 + }) + + withClockAndReset(dut_clock, dut_reset) { + val dut = Module(LazyModule(new StarshipFPGATopA7).module) + + connectSPI (dut) + connectUART (dut) + connectMIG (dut) + + dut.tieOffInterrupts() + dut.dontTouchPorts() + } +} diff --git a/src/main/scala/FPGA/Configs.scala b/src/main/scala/FPGA/Configs.scala index d0d480e..2463f25 100644 --- a/src/main/scala/FPGA/Configs.scala +++ b/src/main/scala/FPGA/Configs.scala @@ -16,14 +16,16 @@ import sifive.fpgashells.clocks._ import sifive.fpgashells.ip.xilinx._ import sifive.fpgashells.shell.xilinx._ import sifive.fpgashells.devices.xilinx.xilinxvc707mig._ +import sifive.fpgashells.devices.xilinx.digilentnexysa7mig._ import sifive.blocks.devices.spi._ import sifive.blocks.devices.uart._ import sys.process._ -case object VCU707DDRSizeKey extends Field[BigInt](0x40000000L) // 1 GB +case object FPGAExtDDRSizeKey extends Field[BigInt](0x40000000L) // 1 GB case object FPGAFrequencyKey extends Field[Double](50) // 50 MHz +case object BoardNameKey extends Field[String]("vc707") // VC707 class WithPeripherals extends Config((site, here, up) => { case PeripheryUARTKey => List( @@ -39,35 +41,54 @@ class WithFrequency(MHz: Double) extends Config((site, here, up) => { case FPGAFrequencyKey => MHz }) +class WithExtDDRSize(MB: BigInt) extends Config((site, here, up) => { + case FPGAExtDDRSizeKey => BigInt(MB.toInt * 1024 * 1024) +}) + +class WithBoard(name: String) extends Config((site, here, up) => { + case BoardNameKey => name +}) + class With25MHz extends WithFrequency(25) +class With32MHz extends WithFrequency(32) class With50MHz extends WithFrequency(50) +class With60MHz extends WithFrequency(60) class With100MHz extends WithFrequency(100) class With150MHz extends WithFrequency(150) +class With128MB extends WithExtDDRSize(128) +class With1024MB extends WithExtDDRSize(1024) + +class WithVC707 extends WithBoard("vc707") +class WithA7 extends WithBoard("a7") + class StarshipFPGAConfig extends Config( new WithPeripherals ++ new WithNBigCores(1) ++ new StarshipBaseConfig().alter((site,here,up) => { case DebugModuleKey => None + /* cpu-frequency = 100 MHz by default */ case PeripheryBusKey => up(PeripheryBusKey, site).copy(dtsFrequency = Some(site(FPGAFrequencyKey).toInt * 1000000)) - /* timebase-frequency = 1 MHz */ + /* timebase-frequency = 1 MHz always */ case DTSTimebase => BigInt(1000000L) - /* memory-size = 1 GB */ - case MemoryXilinxDDRKey => XilinxVC707MIGParams(address = Seq(AddressSet(0x80000000L,site(VCU707DDRSizeKey)-1))) + /* memory-size = 1 GB by default */ + /* Different boards have different MIG Configs and are not unified yet */ + case MemoryDigilentDDRKey => DigilentNexysA7MIGParams(address = Seq(AddressSet(0x80000000L,site(FPGAExtDDRSizeKey)-1))) + case MemoryXilinxDDRKey => XilinxVC707MIGParams(address = Seq(AddressSet(0x80000000L,site(FPGAExtDDRSizeKey)-1))) case ExtMem => up(ExtMem, site).map(x => - x.copy(master = x.master.copy(size = site(VCU707DDRSizeKey)))) + x.copy(master = x.master.copy(size = site(FPGAExtDDRSizeKey)))) case BootROMLocated(x) => up(BootROMLocated(x), site).map { p => // invoke makefile for zero stage boot val freqMHz = site(FPGAFrequencyKey).toInt * 1000000 val path = System.getProperty("user.dir") - val make = s"make -C firmware/zsbl ROOT_DIR=${path} img" + val make = s"make -C firmware/zsbl TARGET_FPGA=" + site(BoardNameKey) + s" ROOT_DIR=${path} img" println("[Leaving Starship] " + make) require (make.! == 0, "Failed to build bootrom") - p.copy(hang = 0x10000, contentFileName = s"build/firmware/zsbl/bootrom.img") + p.copy(hang = 0x10000, contentFileName = s"build/" + site(BoardNameKey) + s"/firmware/zsbl/bootrom.img") } }) ) \ No newline at end of file diff --git a/src/main/scala/FPGA/VC707.scala b/src/main/scala/FPGA/VC707.scala index 838e55e..fa8556a 100644 --- a/src/main/scala/FPGA/VC707.scala +++ b/src/main/scala/FPGA/VC707.scala @@ -22,7 +22,7 @@ import sifive.fpgashells.shell.xilinx.vc707shell._ import sifive.fpgashells.devices.xilinx.xilinxvc707mig._ import sifive.blocks.devices.uart._ -class StarshipFPGATop(implicit p: Parameters) extends StarshipSystem +class StarshipFPGATopVC707(implicit p: Parameters) extends StarshipSystem with HasPeripheryUART with HasPeripherySPI with HasMemoryXilinxVC707MIG @@ -39,16 +39,16 @@ class StarshipFPGATop(implicit p: Parameters) extends StarshipSystem Resource(mmc, "reg").bind(ResourceAddress(0)) } - override lazy val module = new StarshipFPGATopModuleImp(this) + override lazy val module = new StarshipFPGATopModuleImpVC707(this) } -class StarshipFPGATopModuleImp[+L <: StarshipFPGATop](_outer: L) extends StarshipSystemModuleImp(_outer) +class StarshipFPGATopModuleImpVC707[+L <: StarshipFPGATopVC707](_outer: L) extends StarshipSystemModuleImp(_outer) with HasPeripheryUARTModuleImp with HasPeripherySPIModuleImp with HasMemoryXilinxVC707MIGModuleImp with DontTouch -class TestHarness(override implicit val p: Parameters) extends VC707Shell +class TestHarnessVC707(override implicit val p: Parameters) extends VC707Shell with HasDDR3 { @@ -60,7 +60,7 @@ class TestHarness(override implicit val p: Parameters) extends VC707Shell }) withClockAndReset(dut_clock, dut_reset) { - val dut = Module(LazyModule(new StarshipFPGATop).module) + val dut = Module(LazyModule(new StarshipFPGATopVC707).module) connectSPI (dut) connectUART (dut)