diff --git a/.gitmodules b/.gitmodules index ac935dd9..aacd6c5c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -6,4 +6,4 @@ url = https://github.com/sifive/sifive-blocks.git [submodule "fpga-shells"] path = fpga-shells - url = https://github.com/sifive/fpga-shells + url = https://github.com/gongqingfeng/fpga-shells.git diff --git a/Makefile.e300zybodevkit b/Makefile.e300zybodevkit new file mode 100644 index 00000000..7abfd2e2 --- /dev/null +++ b/Makefile.e300zybodevkit @@ -0,0 +1,22 @@ +# See LICENSE for license details. +base_dir := $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST))))) +BUILD_DIR := $(base_dir)/builds/e300zybodevkit +FPGA_DIR := $(base_dir)/fpga-shells/xilinx +MODEL := E300ZyboDevKitFPGAChip +PROJECT := sifive.freedom.everywhere.e300zybodevkit +CONFIG_PROJECT := sifive.freedom.everywhere.e300zybodevkit +export CONFIG := E300ZyboDevKitConfig +export BOARD := zybo +export BOOTROM_DIR := $(base_dir)/bootrom/xip + +rocketchip_dir := $(base_dir)/rocket-chip +sifiveblocks_dir := $(base_dir)/sifive-blocks +VSRCS := \ + $(rocketchip_dir)/vsrc/AsyncResetReg.v \ + $(rocketchip_dir)/vsrc/plusarg_reader.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 diff --git a/README.md b/README.md index f1d22ac0..bf4c5770 100644 --- a/README.md +++ b/README.md @@ -1,95 +1,110 @@ -Freedom -======= +# Freedom Repository This repository contains the RTL created by SiFive for its Freedom E300 and U500 -platforms. The Freedom E310 Arty FPGA Dev Kit implements the Freedom E300 -Platform and is designed to be mapped onto an [Arty FPGA Evaluation -Kit](https://www.xilinx.com/products/boards-and-kits/arty.html). The Freedom -U500 VC707 FPGA Dev Kit implements the Freedom U500 Platform and is designed to -be mapped onto a [VC707 FPGA Evaluation -Kit](https://www.xilinx.com/products/boards-and-kits/ek-v7-vc707-g.html). -Both systems boot autonomously and can be controlled via an external debugger. +platforms. The Zybo Dev Kit +implement the Freedom E300 Platform. + +Note: The branch [freedom_zybo](https://github.com/gongqingfeng/freedom/tree/freedom_zybo) is for Zybo Dev Kit. If you use Ebaz4205 FPGA Board, please switch to the branch [ebaz4205](https://github.com/gongqingfeng/freedom/tree/ebaz4205). + Please read the section corresponding to the kit you are interested in for instructions on how to use this repo. -Software Requirement +## Software Requirement -------------------- - -To compile the bootloaders for both Freedom E300 Arty and U500 VC707 -FPGA dev kits, the RISC-V software toolchain must be installed locally and +To compile the bootloaders for Freedom E300 Zybo, the RISC-V software toolchain must be installed locally and set the $(RISCV) environment variable to point to the location of where the -RISC-V toolchains are installed. You can build the toolchain from scratch -or download the tools here: https://www.sifive.com/products/tools/ - - -Freedom E300 Arty FPGA Dev Kit ------------------------------- - -The Freedom E300 Arty FPGA Dev Kit implements a Freedom E300 chip. - -### How to build - -The Makefile corresponding to the Freedom E300 Arty FPGA Dev Kit is -`Makefile.e300artydevkit` and it consists of two main targets: - -- `verilog`: to compile the Chisel source files and generate the Verilog files. -- `mcs`: to create a Configuration Memory File (.mcs) that can be programmed -onto an Arty FPGA board. - -To execute these targets, you can run the following commands: +RISC-V toolchains are installed. You must pay attention to the version, or +you may meet much trouble. +First, you should download the repository(it may take much time. Maybe vpn need?): ```sh -$ make -f Makefile.e300artydevkit verilog -$ make -f Makefile.e300artydevkit mcs +$ git clone --recursive https://github.com/gongqingfeng/freedom.git +# you can also use gitee +$ git clone --recursive https://gitee.com/gongqingfeng/freedom.git ``` -Note: This flow requires vivado 2017.1. Old versions are known to fail. - -These will place the files under `builds/e300artydevkit/obj`. +Second, you should enter the work dir like this: +```sh +$ cd freedom +# check your branch +git branch +# if your branch is not freedom_zybo, you should switch to the branch freedom_zybo +git checkout freedom_zybo +``` -Note that in order to run the `mcs` target, you need to have the `vivado` -executable on your `PATH`. +Optionally, if you did not compile the toolchain and you do like this(it will take much time): +```sh +$ cd rocket-chip/riscv-tools +$ export RISCV=/yout/install/toolchain/location # eg: export RISCV=/home/xx/xxx/risc-v_dev/tools +$ export MAKEFLAGS="$MAKEFLAGS -jN" # Assuming you have N cores on your host system +$ ./build.sh +``` +Ubuntu packages needed: +```sh +$ sudo apt-get install autoconf automake autotools-dev curl libmpc-dev libmpfr-dev libgmp-dev libusb-1.0-0-dev gawk build-essentia +``` +OK! Let's go ahead! -### Bootrom +## Freedom E300 Zybo dev Kit -The default bootrom consists of a program that immediately jumps to address -0x20400000, which is 0x00400000 bytes into the SPI flash memory on the Arty -board. +The Freedom E300 Dev Kit implements a Freedom E300 chip. -### Using the generated MCS Image +### How to build +Noets: I use Ubuntu16.04 -For instructions for getting the generated image onto an FPGA and programming it with software using the [Freedom E SDK](https://github.com/sifive/freedom-e-sdk), please see the [Freedom E310 Arty FPGA Dev Kit Getting Started Guide](https://www.sifive.com/documentation/freedom-soc/freedom-e300-arty-fpga-dev-kit-getting-started-guide/). +Install java: +```sh +$ sudo apt install openjdk-8-jdk +``` -Freedom U500 VC707 FPGA Dev Kit -------------------------------- +Install sbt: +```sh +$ echo "deb https://repo.scala-sbt.org/scalasbt/debian all main" | sudo tee /etc/apt/sources.list.d/sbt.list +$ echo "deb https://repo.scala-sbt.org/scalasbt/debian /" | sudo tee /etc/apt/sources.list.d/sbt_old.list +$ curl -sL "https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x2EE0EA64E40A89B84B2DF73499E82A75642AC823" | sudo apt-key add +$ sudo apt-get update +$ sudo apt-get install sbt +``` -The Freedom U500 VC707 FPGA Dev Kit implements the Freedom U500 platform. +if you occur problem like this: +```sh +error: error while loading package, Missing dependency 'object java.lang.Object in compiler mirror', required by +``` +you should switch java version to 8: +```sh +$ sudo update-alternatives --config java +$ sudo update-alternatives --config javac +``` -### How to build +If you are not in freedom directory, please enter the dir like this: +```sh +$ cd freedom +``` -The Makefile corresponding to the Freedom U500 VC707 FPGA Dev Kit is -`Makefile.u500vc707devkit` and it consists of two main targets: +The Makefile corresponding to the Freedom E300 Zybo Dev Kit is +`Makefile.e300zybodevkit` and it consists of several targets: - `verilog`: to compile the Chisel source files and generate the Verilog files. -- `mcs`: to create a Configuration Memory File (.mcs) that can be programmed -onto an VC707 FPGA board. +- `project`: to compile the Chisel source files and generate the vivado project. +- `vivado`: to launch the vivado project with GUI mode. So you can systhesis, implement and generate bitstream by yourself. To execute these targets, you can run the following commands: ```sh -$ make -f Makefile.u500vc707devkit verilog -$ make -f Makefile.u500vc707devkit mcs +$ make -f Makefile.e300zybodevkit verilog +$ make -f Makefile.e300zybodevkit project +$ make -f Makefile.e300zybodevkit vivado ``` +Note1: This lab tested within vivado 2016.2. -Note: This flow requires vivado 2016.1. Newer versions are known to fail. +Note2: Before you generate bitstream, you are supposed to add the `freedom/fpga-shells/xilinx/zybo/tcl/no_connect.tcl` file to your Bitstream Settings's tcl.pre blank line. Otherwise, you will get errors. -These will place the files under `builds/u500vc707devkit/obj`. +The vivado project files place under `builds/e300zybodevkit` and the *.v files place under `builds/e300zybodevkit/obj`. -Note that in order to run the `mcs` target, you need to have the `vivado` +Note that in order to run the `projest` and `vivado`target, you need to have the `vivado` executable on your `PATH`. ### Bootrom -The default bootrom consists of a bootloader that loads a program off the SD -card slot on the VC707 board. +The default bootrom consists of a program that can blink three LED from address 0x0001FFFF on the Zybo Dev Kit. \ No newline at end of file diff --git a/bootrom/xip/xip.S b/bootrom/xip/xip.S index 7445f4c9..3968c6c8 100644 --- a/bootrom/xip/xip.S +++ b/bootrom/xip/xip.S @@ -8,8 +8,51 @@ _start: csrr a0, mhartid la a1, dtb - li t0, XIP_TARGET_ADDR - jr t0 +1: + li x1, 0x7 + li x2,0x10012008 // make GPIO0 GPIO1 GPIO2 out port + sw x1,0(x2) + + + li x3, 0 + li x5,1 + +2: + +// light Green LED2, then wait few seconds + li x1, 0x04 + li x2,0x1001200C + sw x1,0(x2) + + + li x4,0x1dfd240 +3: + sub x4,x4,x5 + bne x4,x3,3b + +// light Green LED1, then wait few seconds + li x1, 0x02 + li x2,0x1001200C + sw x1,0(x2) + + + li x4,0x1dfd240 +4: + sub x4,x4,x5 + bne x4,x3,4b + +// light Green LED0, then wait few seconds + li x1, 0x01 + li x2,0x1001200C + sw x1,0(x2) + + li x4,0x1dfd240 +5: + sub x4,x4,x5 + bne x4,x3,5b + + j 2b + nop .section .rodata dtb: diff --git a/common.mk b/common.mk index e23cbb7e..b990ab47 100644 --- a/common.mk +++ b/common.mk @@ -26,6 +26,8 @@ EXTRA_FPGA_VSRCS ?= PATCHVERILOG ?= "" BOOTROM_DIR ?= "" +proj_name = $(BOARD)_freedom_$(CONFIG) + base_dir := $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST))))) export rocketchip_dir := $(base_dir)/rocket-chip SBT ?= java -jar $(rocketchip_dir)/sbt-launch.jar @@ -76,6 +78,23 @@ f := $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).vsrcs.F $(f): echo $(VSRCS) > $@ +# Build .xpr +project := $(BUILD_DIR)/$(proj_name)/$(proj_name).xpr +$(project): $(romgen) $(f) + cd $(BUILD_DIR); vivado \ + -nojournal -mode batch \ + -source $(fpga_common_script_dir)/project.tcl \ + -tclargs \ + -top-module "$(MODEL)" \ + -F "$(f)" \ + -ip-vivado-tcls "$(shell find '$(BUILD_DIR)' -name '*.project.tcl')" \ + -board "$(BOARD)" \ + -config "$(CONFIG)" +project: $(project) + +vivado: $(project) + vivado -nojournal -nolog $(project) + bit := $(BUILD_DIR)/obj/$(MODEL).bit $(bit): $(romgen) $(f) cd $(BUILD_DIR); vivado \ diff --git a/fpga-shells b/fpga-shells index ba7beb67..e0795f84 160000 --- a/fpga-shells +++ b/fpga-shells @@ -1 +1 @@ -Subproject commit ba7beb676d55b73334bd4a85623e56c713a83773 +Subproject commit e0795f844c7c041434379c557abd41a2146c113b diff --git a/src/main/scala/everywhere/e300zybodevkit/Config.scala b/src/main/scala/everywhere/e300zybodevkit/Config.scala new file mode 100644 index 00000000..609259e2 --- /dev/null +++ b/src/main/scala/everywhere/e300zybodevkit/Config.scala @@ -0,0 +1,65 @@ +// See LICENSE for license details. +package sifive.freedom.everywhere.e300zybodevkit + +import freechips.rocketchip.config._ +import freechips.rocketchip.coreplex._ +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 Zybo 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, sampleDelay = 3), + SPIParams(csWidth = 1, rAddress = 0x10034000, sampleDelay = 3)) + case PeripherySPIFlashKey => List( + SPIFlashParams( + fAddress = 0x20000000, + rAddress = 0x10014000, + sampleDelay = 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 Zybo Dev Kit Peripherals +class E300ZyboDevKitConfig 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) + }) +) diff --git a/src/main/scala/everywhere/e300zybodevkit/FPGAChip.scala b/src/main/scala/everywhere/e300zybodevkit/FPGAChip.scala new file mode 100644 index 00000000..5aeffbf5 --- /dev/null +++ b/src/main/scala/everywhere/e300zybodevkit/FPGAChip.scala @@ -0,0 +1,195 @@ +// See LICENSE for license details. +package sifive.freedom.everywhere.e300zybodevkit + +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.zyboshell.{ZyboShell} +import sifive.fpgashells.ip.xilinx.{IBUFG, IOBUF, PULLUP, PowerOnResetFPGAOnly} + +//------------------------------------------------------------------------- +// E300ZyboDevKitFPGAChip +//------------------------------------------------------------------------- + +class E300ZyboDevKitFPGAChip(implicit override val p: Parameters) extends ZyboShell { + + //----------------------------------------------------------------------- + // 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 E300ZyboDevKitPlatform) + + //--------------------------------------------------------------------- + // 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_2, dut.io.pins.jtag.TCK) + PULLUP(jd_2) + + 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 Zybo + // 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 + } +} diff --git a/src/main/scala/everywhere/e300zybodevkit/Platform.scala b/src/main/scala/everywhere/e300zybodevkit/Platform.scala new file mode 100644 index 00000000..5b9325be --- /dev/null +++ b/src/main/scala/everywhere/e300zybodevkit/Platform.scala @@ -0,0 +1,177 @@ +// See LICENSE for license details. +package sifive.freedom.everywhere.e300zybodevkit + +import Chisel._ + +import freechips.rocketchip.config._ +import freechips.rocketchip.coreplex._ +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 + } +} + +//------------------------------------------------------------------------- +// E300ZyboDevKitPlatformIO +//------------------------------------------------------------------------- + +class E300ZyboDevKitPlatformIO(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) +} + +//------------------------------------------------------------------------- +// E300ZyboDevKitPlatform +//------------------------------------------------------------------------- + +class E300ZyboDevKitPlatform(implicit val p: Parameters) extends Module { + val sys = Module(LazyModule(new E300ZyboDevKitSystem).module) + val io = new E300ZyboDevKitPlatformIO + + // 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) + + //----------------------------------------------------------------------- + // 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 = sys.outer.uartParams.map { c => Wire(new UARTPins(() => PinGen()))} + val pwm_pins = sys.outer.pwmParams.map { c => Wire(new PWMPins(() => PinGen(), c))} + val spi_pins = sys.outer.spiParams.map { c => Wire(new SPIPins(() => PinGen(), c))} + val i2c_pins = sys.outer.i2cParams.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 (sys.outer.i2cParams.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.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.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 +} diff --git a/src/main/scala/everywhere/e300zybodevkit/System.scala b/src/main/scala/everywhere/e300zybodevkit/System.scala new file mode 100644 index 00000000..7fc6a93e --- /dev/null +++ b/src/main/scala/everywhere/e300zybodevkit/System.scala @@ -0,0 +1,50 @@ +// See LICENSE for license details. +package sifive.freedom.everywhere.e300zybodevkit + +import Chisel._ + +import freechips.rocketchip.config._ +import freechips.rocketchip.coreplex._ +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._ + +//------------------------------------------------------------------------- +// E300ZyboDevKitSystem +//------------------------------------------------------------------------- + +class E300ZyboDevKitSystem(implicit p: Parameters) extends RocketCoreplex + with HasPeripheryMaskROMSlave + with HasPeripheryDebug + with HasPeripheryMockAON + with HasPeripheryUART + with HasPeripherySPIFlash + with HasPeripherySPI + with HasPeripheryGPIO + with HasPeripheryPWM + with HasPeripheryI2C { + override lazy val module = new E300ZyboDevKitSystemModule(this) +} + +class E300ZyboDevKitSystemModule[+L <: E300ZyboDevKitSystem](_outer: L) + extends RocketCoreplexModule(_outer) + with HasPeripheryDebugModuleImp + 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 +}