├── .gitignore ├── bootrom ├── sdboot │ ├── common.h │ ├── include │ │ ├── devices │ │ │ ├── clint.h │ │ │ ├── gpio.h │ │ │ ├── uart.h │ │ │ ├── plic.h │ │ │ └── spi.h │ │ ├── sections.h │ │ ├── const.h │ │ ├── bits.h │ │ ├── riscv_test_defaults.h │ │ ├── platform.h │ │ └── smp.h │ ├── head.S │ ├── linker │ │ ├── memory.lds │ │ └── sdboot.elf.lds │ ├── kprintf.h │ ├── Makefile │ ├── kprintf.c │ └── sd.c └── xip │ ├── xip.S │ └── Makefile ├── .gitmodules ├── Makefile.veraiofpga ├── Makefile.u500vc707iofpga ├── Makefile.e300artydevkit ├── Makefile.u500vcu118devkit ├── Makefile.u500vc707devkit ├── Makefile.u500polarfireevalkit ├── src └── main │ └── scala │ ├── unleashed │ ├── u500vcu118devkit │ │ ├── System.scala │ │ ├── Config.scala │ │ └── FPGAChip.scala │ ├── u500vc707devkit │ │ ├── System.scala │ │ ├── Config.scala │ │ └── FPGAChip.scala │ ├── u500vera │ │ ├── System.scala │ │ ├── FPGAChip.scala │ │ └── Config.scala │ ├── u500polarfireevalkit │ │ ├── System.scala │ │ ├── FPGAChip.scala │ │ └── Config.scala │ ├── vc707 │ │ └── iofpga │ │ │ └── FPGAChip.scala │ └── vera │ │ └── iofpga │ │ └── FPGAChip.scala │ └── everywhere │ └── e300artydevkit │ ├── System.scala │ ├── Config.scala │ ├── Platform.scala │ └── FPGAChip.scala ├── common.mk ├── README.md └── LICENSE /.gitignore: -------------------------------------------------------------------------------- 1 | /builds 2 | 3 | # sbt directories 4 | /target 5 | /project/target 6 | -------------------------------------------------------------------------------- /bootrom/sdboot/common.h: -------------------------------------------------------------------------------- 1 | #ifndef _SDBOOT_COMMON_H 2 | #define _SDBOOT_COMMON_H 3 | 4 | #ifndef PAYLOAD_DEST 5 | #define PAYLOAD_DEST MEMORY_MEM_ADDR 6 | #endif 7 | 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "rocket-chip"] 2 | path = rocket-chip 3 | url = https://github.com/ucb-bar/rocket-chip.git 4 | [submodule "sifive-blocks"] 5 | path = sifive-blocks 6 | url = https://github.com/sifive/sifive-blocks.git 7 | [submodule "fpga-shells"] 8 | path = fpga-shells 9 | url = https://github.com/sifive/fpga-shells 10 | -------------------------------------------------------------------------------- /bootrom/xip/xip.S: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | // Execute in place 3 | // Jump directly to XIP_TARGET_ADDR 4 | 5 | .section .text.init 6 | .option norvc 7 | .globl _start 8 | _start: 9 | csrr a0, mhartid 10 | la a1, dtb 11 | li t0, XIP_TARGET_ADDR 12 | jr t0 13 | 14 | .section .rodata 15 | dtb: 16 | .incbin DEVICE_TREE 17 | -------------------------------------------------------------------------------- /bootrom/sdboot/include/devices/clint.h: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | #ifndef _SIFIVE_CLINT_H 4 | #define _SIFIVE_CLINT_H 5 | 6 | 7 | #define CLINT_MSIP 0x0000 8 | #define CLINT_MSIP_size 0x4 9 | #define CLINT_MTIMECMP 0x4000 10 | #define CLINT_MTIMECMP_size 0x8 11 | #define CLINT_MTIME 0xBFF8 12 | #define CLINT_MTIME_size 0x8 13 | 14 | #endif /* _SIFIVE_CLINT_H */ 15 | -------------------------------------------------------------------------------- /bootrom/sdboot/head.S: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | #include 3 | #include 4 | #include "common.h" 5 | 6 | .section .text.init 7 | .option norvc 8 | .globl _prog_start 9 | _prog_start: 10 | smp_pause(s1, s2) 11 | li sp, (PAYLOAD_DEST + 0x7fff000) 12 | call main 13 | smp_resume(s1, s2) 14 | csrr a0, mhartid 15 | la a1, dtb 16 | li s1, PAYLOAD_DEST 17 | jr s1 18 | 19 | .section .rodata 20 | dtb: 21 | .incbin DEVICE_TREE 22 | -------------------------------------------------------------------------------- /bootrom/sdboot/include/sections.h: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | #ifndef _SECTIONS_H 3 | #define _SECTIONS_H 4 | 5 | extern unsigned char _rom[]; 6 | extern unsigned char _rom_end[]; 7 | 8 | extern unsigned char _ram[]; 9 | extern unsigned char _ram_end[]; 10 | 11 | extern unsigned char _ftext[]; 12 | extern unsigned char _etext[]; 13 | extern unsigned char _fbss[]; 14 | extern unsigned char _ebss[]; 15 | extern unsigned char _end[]; 16 | 17 | #endif /* _SECTIONS_H */ 18 | -------------------------------------------------------------------------------- /bootrom/sdboot/include/const.h: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | /* Derived from */ 3 | 4 | #ifndef _SIFIVE_CONST_H 5 | #define _SIFIVE_CONST_H 6 | 7 | #ifdef __ASSEMBLER__ 8 | #define _AC(X,Y) X 9 | #define _AT(T,X) X 10 | #else 11 | #define _AC(X,Y) (X##Y) 12 | #define _AT(T,X) ((T)(X)) 13 | #endif /* !__ASSEMBLER__*/ 14 | 15 | #define _BITUL(x) (_AC(1,UL) << (x)) 16 | #define _BITULL(x) (_AC(1,ULL) << (x)) 17 | 18 | #endif /* _SIFIVE_CONST_H */ 19 | -------------------------------------------------------------------------------- /bootrom/sdboot/linker/memory.lds: -------------------------------------------------------------------------------- 1 | MEMORY 2 | { 3 | debug_ctrl (rwx) : ORIGIN = 0x0, LENGTH = 0x1000 4 | error_mem (rw) : ORIGIN = 0x3000, LENGTH = 0x1000 5 | test_ctrl (rw) : ORIGIN = 0x4000, LENGTH = 0x1000 6 | maskrom_mem (rx) : ORIGIN = 0x10000, LENGTH = 0x2000 7 | clint_ctrl (rw) : ORIGIN = 0x2000000, LENGTH = 0x10000 8 | plic_ctrl (rw) : ORIGIN = 0xc000000, LENGTH = 0x4000000 9 | axi_pcie_host_1_00_a_ctrl (rw) : ORIGIN = 0x50000000, LENGTH = 0x4000000 10 | uart_ctrl (rw) : ORIGIN = 0x54000000, LENGTH = 0x1000 11 | spi_ctrl (rw) : ORIGIN = 0x54001000, LENGTH = 0x1000 12 | gpio_ctrl (rw) : ORIGIN = 0x54002000, LENGTH = 0x1000 13 | memory_mem (rwx) : ORIGIN = 0x80000000, LENGTH = 0x40000000 14 | } 15 | -------------------------------------------------------------------------------- /bootrom/sdboot/include/devices/gpio.h: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | #ifndef _SIFIVE_GPIO_H 4 | #define _SIFIVE_GPIO_H 5 | 6 | #define GPIO_INPUT_VAL (0x00) 7 | #define GPIO_INPUT_EN (0x04) 8 | #define GPIO_OUTPUT_EN (0x08) 9 | #define GPIO_OUTPUT_VAL (0x0C) 10 | #define GPIO_PULLUP_EN (0x10) 11 | #define GPIO_DRIVE (0x14) 12 | #define GPIO_RISE_IE (0x18) 13 | #define GPIO_RISE_IP (0x1C) 14 | #define GPIO_FALL_IE (0x20) 15 | #define GPIO_FALL_IP (0x24) 16 | #define GPIO_HIGH_IE (0x28) 17 | #define GPIO_HIGH_IP (0x2C) 18 | #define GPIO_LOW_IE (0x30) 19 | #define GPIO_LOW_IP (0x34) 20 | #define GPIO_IOF_EN (0x38) 21 | #define GPIO_IOF_SEL (0x3C) 22 | #define GPIO_OUTPUT_XOR (0x40) 23 | 24 | #endif /* _SIFIVE_GPIO_H */ 25 | -------------------------------------------------------------------------------- /bootrom/sdboot/include/devices/uart.h: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | #ifndef _SIFIVE_UART_H 4 | #define _SIFIVE_UART_H 5 | 6 | /* Register offsets */ 7 | #define UART_REG_TXFIFO 0x00 8 | #define UART_REG_RXFIFO 0x04 9 | #define UART_REG_TXCTRL 0x08 10 | #define UART_REG_RXCTRL 0x0c 11 | #define UART_REG_IE 0x10 12 | #define UART_REG_IP 0x14 13 | #define UART_REG_DIV 0x18 14 | 15 | /* TXCTRL register */ 16 | #define UART_TXEN 0x1 17 | #define UART_TXNSTOP 0x2 18 | #define UART_TXWM(x) (((x) & 0xffff) << 16) 19 | 20 | /* RXCTRL register */ 21 | #define UART_RXEN 0x1 22 | #define UART_RXWM(x) (((x) & 0xffff) << 16) 23 | 24 | /* IP register */ 25 | #define UART_IP_TXWM 0x1 26 | #define UART_IP_RXWM 0x2 27 | 28 | #endif /* _SIFIVE_UART_H */ 29 | -------------------------------------------------------------------------------- /Makefile.veraiofpga: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | base_dir := $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST))))) 3 | BUILD_DIR := $(base_dir)/builds/vera-iofpga 4 | FPGA_DIR := $(base_dir)/fpga-shells/microsemi 5 | MODEL := IOFPGAChip 6 | PROJECT := sifive.freedom.unleashed.vera.iofpga 7 | export CONFIG_PROJECT := sifive.freedom.unleashed.vera.iofpga 8 | export CONFIG := IOFPGAConfig 9 | export BOARD := vera 10 | 11 | rocketchip_dir := $(base_dir)/rocket-chip 12 | sifiveblocks_dir := $(base_dir)/sifive-blocks 13 | VSRCS := \ 14 | $(rocketchip_dir)/src/main/resources/vsrc/AsyncResetReg.v \ 15 | $(rocketchip_dir)/src/main/resources/vsrc/plusarg_reader.v \ 16 | $(sifiveblocks_dir)/vsrc/SRLatch.v \ 17 | $(FPGA_DIR)/common/vsrc/PowerOnResetFPGAOnly.v \ 18 | $(FPGA_DIR)/$(BOARD)/vsrc/sdio.v \ 19 | $(FPGA_DIR)/$(BOARD)/vsrc/vc707reset.v \ 20 | $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).v 21 | 22 | include common.mk 23 | -------------------------------------------------------------------------------- /Makefile.u500vc707iofpga: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | base_dir := $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST))))) 3 | BUILD_DIR := $(base_dir)/builds/u500vc707iofpga 4 | FPGA_DIR := $(base_dir)/fpga-shells/xilinx 5 | MODEL := IOFPGAChip 6 | PROJECT := sifive.freedom.unleashed.vc707.iofpga 7 | export CONFIG_PROJECT := sifive.freedom.unleashed.vc707.iofpga 8 | export CONFIG := IOFPGAConfig 9 | export BOARD := vc707 10 | 11 | rocketchip_dir := $(base_dir)/rocket-chip 12 | sifiveblocks_dir := $(base_dir)/sifive-blocks 13 | VSRCS := \ 14 | $(rocketchip_dir)/src/main/resources/vsrc/AsyncResetReg.v \ 15 | $(rocketchip_dir)/src/main/resources/vsrc/plusarg_reader.v \ 16 | $(sifiveblocks_dir)/vsrc/SRLatch.v \ 17 | $(FPGA_DIR)/common/vsrc/PowerOnResetFPGAOnly.v \ 18 | $(FPGA_DIR)/$(BOARD)/vsrc/sdio.v \ 19 | $(FPGA_DIR)/$(BOARD)/vsrc/vc707reset.v \ 20 | $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).v 21 | 22 | include common.mk 23 | -------------------------------------------------------------------------------- /Makefile.e300artydevkit: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | base_dir := $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST))))) 3 | BUILD_DIR := $(base_dir)/builds/e300artydevkit 4 | FPGA_DIR := $(base_dir)/fpga-shells/xilinx 5 | MODEL := E300ArtyDevKitFPGAChip 6 | PROJECT := sifive.freedom.everywhere.e300artydevkit 7 | export CONFIG_PROJECT := sifive.freedom.everywhere.e300artydevkit 8 | export CONFIG := E300ArtyDevKitConfig 9 | export BOARD := arty 10 | export BOOTROM_DIR := $(base_dir)/bootrom/xip 11 | 12 | rocketchip_dir := $(base_dir)/rocket-chip 13 | sifiveblocks_dir := $(base_dir)/sifive-blocks 14 | VSRCS := \ 15 | $(rocketchip_dir)/src/main/resources/vsrc/AsyncResetReg.v \ 16 | $(rocketchip_dir)/src/main/resources/vsrc/plusarg_reader.v \ 17 | $(sifiveblocks_dir)/vsrc/SRLatch.v \ 18 | $(FPGA_DIR)/common/vsrc/PowerOnResetFPGAOnly.v \ 19 | $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).rom.v \ 20 | $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).v 21 | 22 | include common.mk 23 | -------------------------------------------------------------------------------- /bootrom/sdboot/include/devices/plic.h: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | #ifndef PLIC_H 4 | #define PLIC_H 5 | 6 | #include 7 | 8 | // 32 bits per source 9 | #define PLIC_PRIORITY_OFFSET _AC(0x0000,UL) 10 | #define PLIC_PRIORITY_SHIFT_PER_SOURCE 2 11 | // 1 bit per source (1 address) 12 | #define PLIC_PENDING_OFFSET _AC(0x1000,UL) 13 | #define PLIC_PENDING_SHIFT_PER_SOURCE 0 14 | 15 | //0x80 per target 16 | #define PLIC_ENABLE_OFFSET _AC(0x2000,UL) 17 | #define PLIC_ENABLE_SHIFT_PER_TARGET 7 18 | 19 | 20 | #define PLIC_THRESHOLD_OFFSET _AC(0x200000,UL) 21 | #define PLIC_CLAIM_OFFSET _AC(0x200004,UL) 22 | #define PLIC_THRESHOLD_SHIFT_PER_TARGET 12 23 | #define PLIC_CLAIM_SHIFT_PER_TARGET 12 24 | 25 | #define PLIC_MAX_SOURCE 1023 26 | #define PLIC_SOURCE_MASK 0x3FF 27 | 28 | #define PLIC_MAX_TARGET 15871 29 | #define PLIC_TARGET_MASK 0x3FFF 30 | 31 | #endif /* PLIC_H */ 32 | -------------------------------------------------------------------------------- /Makefile.u500vcu118devkit: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | base_dir := $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST))))) 3 | BUILD_DIR := $(base_dir)/builds/u500vcu118devkit 4 | FPGA_DIR := $(base_dir)/fpga-shells/xilinx 5 | MODEL := U500VCU118DevKitFPGAChip 6 | PROJECT := sifive.freedom.unleashed.u500vcu118devkit 7 | export CONFIG_PROJECT := sifive.freedom.unleashed.u500vcu118devkit 8 | export CONFIG := U500VCU118DevKitConfig 9 | export BOARD := vcu118 10 | export BOOTROM_DIR := $(base_dir)/bootrom/sdboot 11 | 12 | rocketchip_dir := $(base_dir)/rocket-chip 13 | sifiveblocks_dir := $(base_dir)/sifive-blocks 14 | VSRCS := \ 15 | $(rocketchip_dir)/vsrc/AsyncResetReg.v \ 16 | $(rocketchip_dir)/vsrc/plusarg_reader.v \ 17 | $(sifiveblocks_dir)/vsrc/SRLatch.v \ 18 | $(FPGA_DIR)/common/vsrc/PowerOnResetFPGAOnly.v \ 19 | $(FPGA_DIR)/$(BOARD)/vsrc/sdio.v \ 20 | $(FPGA_DIR)/$(BOARD)/vsrc/vcu118reset.v \ 21 | $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).rom.v \ 22 | $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).v 23 | 24 | include common.mk 25 | -------------------------------------------------------------------------------- /Makefile.u500vc707devkit: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | base_dir := $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST))))) 3 | BUILD_DIR := $(base_dir)/builds/u500vc707devkit 4 | FPGA_DIR := $(base_dir)/fpga-shells/xilinx 5 | MODEL := U500VC707DevKitFPGAChip 6 | PROJECT := sifive.freedom.unleashed.u500vc707devkit 7 | export CONFIG_PROJECT := sifive.freedom.unleashed.u500vc707devkit 8 | export CONFIG := U500VC707DevKitConfig 9 | export BOARD := vc707 10 | export BOOTROM_DIR := $(base_dir)/bootrom/sdboot 11 | 12 | rocketchip_dir := $(base_dir)/rocket-chip 13 | sifiveblocks_dir := $(base_dir)/sifive-blocks 14 | VSRCS := \ 15 | $(rocketchip_dir)/src/main/resources/vsrc/AsyncResetReg.v \ 16 | $(rocketchip_dir)/src/main/resources/vsrc/plusarg_reader.v \ 17 | $(sifiveblocks_dir)/vsrc/SRLatch.v \ 18 | $(FPGA_DIR)/common/vsrc/PowerOnResetFPGAOnly.v \ 19 | $(FPGA_DIR)/$(BOARD)/vsrc/sdio.v \ 20 | $(FPGA_DIR)/$(BOARD)/vsrc/vc707reset.v \ 21 | $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).rom.v \ 22 | $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).v 23 | 24 | include common.mk 25 | -------------------------------------------------------------------------------- /bootrom/sdboot/include/bits.h: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | #ifndef _RISCV_BITS_H 3 | #define _RISCV_BITS_H 4 | 5 | #define likely(x) __builtin_expect((x), 1) 6 | #define unlikely(x) __builtin_expect((x), 0) 7 | 8 | #define ROUNDUP(a, b) ((((a)-1)/(b)+1)*(b)) 9 | #define ROUNDDOWN(a, b) ((a)/(b)*(b)) 10 | 11 | #define MAX(a, b) ((a) > (b) ? (a) : (b)) 12 | #define MIN(a, b) ((a) < (b) ? (a) : (b)) 13 | #define CLAMP(a, lo, hi) MIN(MAX(a, lo), hi) 14 | 15 | #define EXTRACT_FIELD(val, which) (((val) & (which)) / ((which) & ~((which)-1))) 16 | #define INSERT_FIELD(val, which, fieldval) (((val) & ~(which)) | ((fieldval) * ((which) & ~((which)-1)))) 17 | 18 | #define STR(x) XSTR(x) 19 | #define XSTR(x) #x 20 | 21 | #if __riscv_xlen == 64 22 | # define SLL32 sllw 23 | # define STORE sd 24 | # define LOAD ld 25 | # define LWU lwu 26 | # define LOG_REGBYTES 3 27 | #else 28 | # define SLL32 sll 29 | # define STORE sw 30 | # define LOAD lw 31 | # define LWU lw 32 | # define LOG_REGBYTES 2 33 | #endif 34 | #define REGBYTES (1 << LOG_REGBYTES) 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /Makefile.u500polarfireevalkit: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | base_dir := $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST))))) 3 | BUILD_DIR := $(base_dir)/builds/u500polarfireevalkit 4 | FPGA_DIR := $(base_dir)/fpga-shells/microsemi 5 | MODEL := U500PolarFireEvalKitFPGAChip 6 | PROJECT := sifive.freedom.unleashed.u500polarfireevalkit 7 | CONFIG_PROJECT := sifive.freedom.unleashed.u500polarfireevalkit 8 | export CONFIG := U500PolarFireEvalKitConfig 9 | export BOARD := vc707 10 | export BOOTROM_DIR := $(base_dir)/bootrom/sdboot 11 | 12 | rocketchip_dir := $(base_dir)/rocket-chip 13 | sifiveblocks_dir := $(base_dir)/sifive-blocks 14 | VSRCS := \ 15 | $(rocketchip_dir)/src/main/resources/vsrc/AsyncResetReg.v \ 16 | $(rocketchip_dir)/src/main/resources/vsrc/plusarg_reader.v \ 17 | $(sifiveblocks_dir)/vsrc/SRLatch.v \ 18 | $(FPGA_DIR)/common/vsrc/PowerOnResetFPGAOnly.v \ 19 | $(FPGA_DIR)/$(BOARD)/vsrc/sdio.v \ 20 | $(FPGA_DIR)/$(BOARD)/vsrc/vc707reset.v \ 21 | $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).rom.v \ 22 | $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).v 23 | 24 | include common.mk 25 | -------------------------------------------------------------------------------- /bootrom/xip/Makefile: -------------------------------------------------------------------------------- 1 | # RISCV environment variable must be set 2 | 3 | CC=$(RISCV)/bin/riscv64-unknown-elf-gcc 4 | OBJCOPY=$(RISCV)/bin/riscv64-unknown-elf-objcopy 5 | CFLAGS=-march=rv32imac -mabi=ilp32 -O2 -std=gnu11 -Wall -I. -nostartfiles -fno-common -g 6 | LFLAGS=-static -nostdlib 7 | 8 | dtb := $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).dtb 9 | $(dtb): $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).dts 10 | dtc -I dts -O dtb -o $@ $< 11 | 12 | .PHONY: dtb 13 | dtb: $(dtb) 14 | 15 | elf := $(BUILD_DIR)/xip.elf 16 | $(elf): xip.S $(dtb) 17 | $(CC) $(CFLAGS) -DXIP_TARGET_ADDR=0x20400000 -DDEVICE_TREE='"$(dtb)"' $(LFLAGS) -o $@ $< 18 | 19 | .PHONY: elf 20 | elf: $(elf) 21 | 22 | bin := $(BUILD_DIR)/xip.bin 23 | $(bin): $(elf) 24 | $(OBJCOPY) -O binary $< $@ 25 | 26 | .PHONY: bin 27 | bin: $(bin) 28 | 29 | hex := $(BUILD_DIR)/xip.hex 30 | $(hex): $(bin) 31 | od -t x4 -An -w4 -v $< > $@ 32 | 33 | .PHONY: hex 34 | hex: $(hex) 35 | 36 | romgen := $(BUILD_DIR)/rom.v 37 | $(romgen): $(hex) 38 | $(rocketchip_dir)/scripts/vlsi_rom_gen $(ROMCONF) $< > $@ 39 | 40 | .PHONY: romgen 41 | romgen: $(romgen) 42 | 43 | .PHONY: clean 44 | clean:: 45 | rm -rf $(hex) $(elf) 46 | -------------------------------------------------------------------------------- /bootrom/sdboot/kprintf.h: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | #ifndef _SDBOOT_KPRINTF_H 3 | #define _SDBOOT_KPRINTF_H 4 | 5 | #include 6 | #include 7 | 8 | #define REG32(p, i) ((p)[(i) >> 2]) 9 | 10 | #ifndef UART_CTRL_ADDR 11 | #ifndef UART_NUM 12 | #define UART_NUM 0 13 | #endif 14 | 15 | #define _CONCAT3(A, B, C) A ## B ## C 16 | #define _UART_CTRL_ADDR(UART_NUM) _CONCAT3(UART, UART_NUM, _CTRL_ADDR) 17 | #define UART_CTRL_ADDR _UART_CTRL_ADDR(UART_NUM) 18 | #endif 19 | static volatile uint32_t * const uart = (void *)(UART_CTRL_ADDR); 20 | 21 | static inline void kputc(char c) 22 | { 23 | volatile uint32_t *tx = ®32(uart, UART_REG_TXFIFO); 24 | #ifdef __riscv_atomic 25 | int32_t r; 26 | do { 27 | __asm__ __volatile__ ( 28 | "amoor.w %0, %2, %1\n" 29 | : "=r" (r), "+A" (*tx) 30 | : "r" (c)); 31 | } while (r < 0); 32 | #else 33 | while ((int32_t)(*tx) < 0); 34 | *tx = c; 35 | #endif 36 | } 37 | 38 | extern void kputs(const char *); 39 | extern void kprintf(const char *, ...); 40 | 41 | #ifdef DEBUG 42 | #define dprintf(s, ...) kprintf((s), ##__VA_ARGS__) 43 | #define dputs(s) kputs((s)) 44 | #else 45 | #define dprintf(s, ...) do { } while (0) 46 | #define dputs(s) do { } while (0) 47 | #endif 48 | 49 | #endif /* _SDBOOT_KPRINTF_H */ 50 | -------------------------------------------------------------------------------- /bootrom/sdboot/Makefile: -------------------------------------------------------------------------------- 1 | # RISCV environment variable must be set 2 | 3 | CC=$(RISCV)/bin/riscv64-unknown-elf-gcc 4 | OBJCOPY=$(RISCV)/bin/riscv64-unknown-elf-objcopy 5 | CFLAGS=-march=rv64imac -mcmodel=medany -O2 -std=gnu11 -Wall -nostartfiles 6 | CFLAGS+= -fno-common -g -DENTROPY=0 -mabi=lp64 -DNONSMP_HART=0 7 | CFLAGS+= -I $(BOOTROM_DIR)/include -I. 8 | LFLAGS=-static -nostdlib -L $(BOOTROM_DIR)/linker -T sdboot.elf.lds 9 | 10 | dtb := $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).dtb 11 | $(dtb): $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).dts 12 | dtc -I dts -O dtb -o $@ $< 13 | 14 | .PHONY: dtb 15 | dtb: $(dtb) 16 | 17 | elf := $(BUILD_DIR)/sdboot.elf 18 | $(elf): $(dtb) head.S kprintf.c sd.c 19 | $(CC) $(CFLAGS) -DDEVICE_TREE='"$(dtb)"' $(LFLAGS) -o $@ head.S sd.c kprintf.c 20 | 21 | .PHONY: elf 22 | elf: $(elf) 23 | 24 | bin := $(BUILD_DIR)/sdboot.bin 25 | $(bin): $(elf) 26 | $(OBJCOPY) -O binary $< $@ 27 | 28 | .PHONY: bin 29 | bin: $(bin) 30 | 31 | hex := $(BUILD_DIR)/sdboot.hex 32 | $(hex): $(bin) 33 | od -t x4 -An -w4 -v $< > $@ 34 | 35 | .PHONY: hex 36 | hex: $(hex) 37 | 38 | romgen := $(BUILD_DIR)/rom.v 39 | $(romgen): $(hex) 40 | $(rocketchip_dir)/scripts/vlsi_rom_gen $(ROMCONF) $< > $@ 41 | 42 | .PHONY: romgen 43 | romgen: $(romgen) 44 | 45 | .PHONY: clean 46 | clean:: 47 | rm -rf $(hex) $(elf) 48 | -------------------------------------------------------------------------------- /bootrom/sdboot/kprintf.c: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | #include 3 | #include 4 | #include 5 | 6 | #include "kprintf.h" 7 | 8 | static inline void _kputs(const char *s) 9 | { 10 | char c; 11 | for (; (c = *s) != '\0'; s++) 12 | kputc(c); 13 | } 14 | 15 | void kputs(const char *s) 16 | { 17 | _kputs(s); 18 | kputc('\r'); 19 | kputc('\n'); 20 | } 21 | 22 | void kprintf(const char *fmt, ...) 23 | { 24 | va_list vl; 25 | bool is_format, is_long, is_char; 26 | char c; 27 | 28 | va_start(vl, fmt); 29 | is_format = false; 30 | is_long = false; 31 | is_char = false; 32 | while ((c = *fmt++) != '\0') { 33 | if (is_format) { 34 | switch (c) { 35 | case 'l': 36 | is_long = true; 37 | continue; 38 | case 'h': 39 | is_char = true; 40 | continue; 41 | case 'x': { 42 | unsigned long n; 43 | long i; 44 | if (is_long) { 45 | n = va_arg(vl, unsigned long); 46 | i = (sizeof(unsigned long) << 3) - 4; 47 | } else { 48 | n = va_arg(vl, unsigned int); 49 | i = is_char ? 4 : (sizeof(unsigned int) << 3) - 4; 50 | } 51 | for (; i >= 0; i -= 4) { 52 | long d; 53 | d = (n >> i) & 0xF; 54 | kputc(d < 10 ? '0' + d : 'a' + d - 10); 55 | } 56 | break; 57 | } 58 | case 's': 59 | _kputs(va_arg(vl, const char *)); 60 | break; 61 | case 'c': 62 | kputc(va_arg(vl, int)); 63 | break; 64 | } 65 | is_format = false; 66 | is_long = false; 67 | is_char = false; 68 | } else if (c == '%') { 69 | is_format = true; 70 | } else { 71 | kputc(c); 72 | } 73 | } 74 | va_end(vl); 75 | } 76 | -------------------------------------------------------------------------------- /src/main/scala/unleashed/u500vcu118devkit/System.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | package sifive.freedom.unleashed.u500vcu118devkit 3 | 4 | import Chisel._ 5 | 6 | import freechips.rocketchip.config._ 7 | import freechips.rocketchip.subsystem._ 8 | import freechips.rocketchip.devices.debug._ 9 | import freechips.rocketchip.devices.tilelink._ 10 | import freechips.rocketchip.diplomacy._ 11 | import freechips.rocketchip.system._ 12 | 13 | import sifive.blocks.devices.gpio._ 14 | import sifive.blocks.devices.spi._ 15 | import sifive.blocks.devices.uart._ 16 | 17 | import sifive.fpgashells.devices.xilinx.xilinxvcu118mig._ 18 | 19 | //------------------------------------------------------------------------- 20 | // U500VCU118DevKitSystem 21 | //------------------------------------------------------------------------- 22 | 23 | class U500VCU118DevKitSystem(implicit p: Parameters) extends RocketSubsystem 24 | with HasPeripheryMaskROMSlave 25 | with HasPeripheryDebug 26 | with HasSystemErrorSlave 27 | with HasPeripheryUART 28 | with HasPeripherySPI 29 | with HasPeripheryGPIO 30 | with HasMemoryXilinxVCU118MIG { 31 | override lazy val module = new U500VCU118DevKitSystemModule(this) 32 | } 33 | 34 | class U500VCU118DevKitSystemModule[+L <: U500VCU118DevKitSystem](_outer: L) 35 | extends RocketSubsystemModuleImp(_outer) 36 | with HasRTCModuleImp 37 | with HasPeripheryDebugModuleImp 38 | with HasPeripheryUARTModuleImp 39 | with HasPeripherySPIModuleImp 40 | with HasPeripheryGPIOModuleImp 41 | with HasMemoryXilinxVCU118MIGModuleImp { 42 | // Reset vector is set to the location of the mask rom 43 | val maskROMParams = p(PeripheryMaskROMKey) 44 | global_reset_vector := maskROMParams(0).address.U 45 | } 46 | -------------------------------------------------------------------------------- /bootrom/sdboot/include/riscv_test_defaults.h: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | #ifndef _RISCV_TEST_DEFAULTS_H 3 | #define _RISCV_TEST_DEFAULTS_H 4 | 5 | #define TESTNUM x28 6 | #define TESTBASE 0x4000 7 | 8 | #define RVTEST_RV32U \ 9 | .macro init; \ 10 | .endm 11 | 12 | #define RVTEST_RV64U \ 13 | .macro init; \ 14 | .endm 15 | 16 | #define RVTEST_RV32UF \ 17 | .macro init; \ 18 | /* If FPU exists, initialize FCSR. */ \ 19 | csrr t0, misa; \ 20 | andi t0, t0, 1 << ('F' - 'A'); \ 21 | beqz t0, 1f; \ 22 | /* Enable FPU if it exists. */ \ 23 | li t0, MSTATUS_FS; \ 24 | csrs mstatus, t0; \ 25 | fssr x0; \ 26 | 1: ; \ 27 | .endm 28 | 29 | #define RVTEST_RV64UF \ 30 | .macro init; \ 31 | /* If FPU exists, initialize FCSR. */ \ 32 | csrr t0, misa; \ 33 | andi t0, t0, 1 << ('F' - 'A'); \ 34 | beqz t0, 1f; \ 35 | /* Enable FPU if it exists. */ \ 36 | li t0, MSTATUS_FS; \ 37 | csrs mstatus, t0; \ 38 | fssr x0; \ 39 | 1: ; \ 40 | .endm 41 | 42 | #define RVTEST_CODE_BEGIN \ 43 | .section .text.init; \ 44 | .globl _prog_start; \ 45 | _prog_start: \ 46 | init; 47 | 48 | #define RVTEST_CODE_END \ 49 | unimp 50 | 51 | #define RVTEST_PASS \ 52 | fence; \ 53 | li t0, TESTBASE; \ 54 | li t1, 0x5555; \ 55 | sw t1, 0(t0); \ 56 | 1: \ 57 | j 1b; 58 | 59 | #define RVTEST_FAIL \ 60 | li t0, TESTBASE; \ 61 | li t1, 0x3333; \ 62 | slli a0, a0, 16; \ 63 | add a0, a0, t1; \ 64 | sw a0, 0(t0); \ 65 | 1: \ 66 | j 1b; 67 | 68 | #define EXTRA_DATA 69 | 70 | #define RVTEST_DATA_BEGIN \ 71 | EXTRA_DATA \ 72 | .align 4; .global begin_signature; begin_signature: 73 | 74 | #define RVTEST_DATA_END \ 75 | _msg_init: .asciz "RUN\r\n"; \ 76 | _msg_pass: .asciz "PASS"; \ 77 | _msg_fail: .asciz "FAIL "; \ 78 | _msg_end: .asciz "\r\n"; \ 79 | .align 4; .global end_signature; end_signature: 80 | 81 | #endif /* _RISCV_TEST_DEFAULTS_H */ 82 | -------------------------------------------------------------------------------- /src/main/scala/unleashed/u500vc707devkit/System.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | package sifive.freedom.unleashed.u500vc707devkit 3 | 4 | import Chisel._ 5 | 6 | import freechips.rocketchip.config._ 7 | import freechips.rocketchip.subsystem._ 8 | import freechips.rocketchip.devices.debug._ 9 | import freechips.rocketchip.devices.tilelink._ 10 | import freechips.rocketchip.diplomacy._ 11 | import freechips.rocketchip.system._ 12 | 13 | import sifive.blocks.devices.gpio._ 14 | import sifive.blocks.devices.spi._ 15 | import sifive.blocks.devices.uart._ 16 | 17 | import sifive.fpgashells.devices.xilinx.xilinxvc707mig._ 18 | import sifive.fpgashells.devices.xilinx.xilinxvc707pciex1._ 19 | 20 | //------------------------------------------------------------------------- 21 | // U500VC707DevKitSystem 22 | //------------------------------------------------------------------------- 23 | 24 | class U500VC707DevKitSystem(implicit p: Parameters) extends RocketSubsystem 25 | with HasPeripheryMaskROMSlave 26 | with HasPeripheryDebug 27 | with HasSystemErrorSlave 28 | with HasPeripheryUART 29 | with HasPeripherySPI 30 | with HasPeripheryGPIO 31 | with HasMemoryXilinxVC707MIG 32 | with HasSystemXilinxVC707PCIeX1 { 33 | override lazy val module = new U500VC707DevKitSystemModule(this) 34 | } 35 | 36 | class U500VC707DevKitSystemModule[+L <: U500VC707DevKitSystem](_outer: L) 37 | extends RocketSubsystemModuleImp(_outer) 38 | with HasRTCModuleImp 39 | with HasPeripheryDebugModuleImp 40 | with HasPeripheryUARTModuleImp 41 | with HasPeripherySPIModuleImp 42 | with HasPeripheryGPIOModuleImp 43 | with HasMemoryXilinxVC707MIGModuleImp 44 | with HasSystemXilinxVC707PCIeX1ModuleImp { 45 | // Reset vector is set to the location of the mask rom 46 | val maskROMParams = p(PeripheryMaskROMKey) 47 | global_reset_vector := maskROMParams(0).address.U 48 | } 49 | -------------------------------------------------------------------------------- /src/main/scala/everywhere/e300artydevkit/System.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | package sifive.freedom.everywhere.e300artydevkit 3 | 4 | import Chisel._ 5 | 6 | import freechips.rocketchip.config._ 7 | import freechips.rocketchip.subsystem._ 8 | import freechips.rocketchip.devices.debug._ 9 | import freechips.rocketchip.devices.tilelink._ 10 | import freechips.rocketchip.diplomacy._ 11 | import freechips.rocketchip.system._ 12 | 13 | import sifive.blocks.devices.mockaon._ 14 | import sifive.blocks.devices.gpio._ 15 | import sifive.blocks.devices.pwm._ 16 | import sifive.blocks.devices.spi._ 17 | import sifive.blocks.devices.uart._ 18 | import sifive.blocks.devices.i2c._ 19 | 20 | //------------------------------------------------------------------------- 21 | // E300ArtyDevKitSystem 22 | //------------------------------------------------------------------------- 23 | 24 | class E300ArtyDevKitSystem(implicit p: Parameters) extends RocketSubsystem 25 | with HasPeripheryMaskROMSlave 26 | with HasPeripheryDebug 27 | with HasPeripheryMockAON 28 | with HasPeripheryUART 29 | with HasPeripherySPIFlash 30 | with HasPeripherySPI 31 | with HasPeripheryGPIO 32 | with HasPeripheryPWM 33 | with HasPeripheryI2C { 34 | override lazy val module = new E300ArtyDevKitSystemModule(this) 35 | } 36 | 37 | class E300ArtyDevKitSystemModule[+L <: E300ArtyDevKitSystem](_outer: L) 38 | extends RocketSubsystemModuleImp(_outer) 39 | with HasPeripheryDebugModuleImp 40 | with HasPeripheryUARTModuleImp 41 | with HasPeripherySPIModuleImp 42 | with HasPeripheryGPIOModuleImp 43 | with HasPeripherySPIFlashModuleImp 44 | with HasPeripheryMockAONModuleImp 45 | with HasPeripheryPWMModuleImp 46 | with HasPeripheryI2CModuleImp { 47 | // Reset vector is set to the location of the mask rom 48 | val maskROMParams = p(PeripheryMaskROMKey) 49 | global_reset_vector := maskROMParams(0).address.U 50 | } 51 | -------------------------------------------------------------------------------- /src/main/scala/unleashed/u500vera/System.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | package sifive.freedom.unleashed.u500vera 3 | 4 | import Chisel._ 5 | 6 | import freechips.rocketchip.config._ 7 | import freechips.rocketchip.subsystem._ 8 | import freechips.rocketchip.devices.debug._ 9 | import freechips.rocketchip.devices.tilelink._ 10 | import freechips.rocketchip.diplomacy._ 11 | import freechips.rocketchip.system._ 12 | 13 | import sifive.blocks.devices.gpio._ 14 | import sifive.blocks.devices.spi._ 15 | import sifive.blocks.devices.uart._ 16 | 17 | import sifive.fpgashells.devices.microsemi.polarfireddr3._ 18 | import sifive.fpgashells.devices.microsemi.polarfireddr4._ 19 | import sifive.fpgashells.devices.microsemi.polarfireevalkitpciex4._ 20 | 21 | //------------------------------------------------------------------------- 22 | // U500VeraSystem 23 | //------------------------------------------------------------------------- 24 | 25 | class U500VeraSystem(implicit p: Parameters) extends RocketSubsystem 26 | with HasPeripheryMaskROMSlave 27 | with HasPeripheryDebug 28 | with HasSystemErrorSlave 29 | with HasPeripheryUART 30 | with HasPeripherySPI 31 | with HasPeripheryGPIO 32 | // with HasCoreJTAGDebug 33 | // with HasMemoryPolarFireEvalKitDDR4 34 | with HasMemoryPolarFireEvalKitDDR3 35 | with HasSystemPolarFireEvalKitPCIeX4 36 | { 37 | override lazy val module = new U500VeraSystemModule(this) 38 | } 39 | 40 | class U500VeraSystemModule[+L <: U500VeraSystem](_outer: L) 41 | extends RocketSubsystemModuleImp(_outer) 42 | // extends RocketCoreplexModule(_outer) 43 | with HasRTCModuleImp 44 | with HasPeripheryDebugModuleImp 45 | with HasPeripheryUARTModuleImp 46 | with HasPeripherySPIModuleImp 47 | with HasPeripheryGPIOModuleImp 48 | // with HasMemoryPolarFireEvalKitDDR4ModuleImp 49 | with HasMemoryPolarFireEvalKitDDR3ModuleImp 50 | with HasSystemPolarFireEvalKitPCIeX4ModuleImp 51 | { 52 | // Reset vector is set to the location of the mask rom 53 | val maskROMParams = p(PeripheryMaskROMKey) 54 | // global_reset_vector := maskROMParams(0).address.U 55 | global_reset_vector := BigInt(0x80000000L).U 56 | } 57 | -------------------------------------------------------------------------------- /src/main/scala/unleashed/u500polarfireevalkit/System.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | package sifive.freedom.unleashed.u500polarfireevalkit 3 | 4 | import Chisel._ 5 | 6 | import freechips.rocketchip.config._ 7 | //import freechips.rocketchip.coreplex._ 8 | import freechips.rocketchip.subsystem._ 9 | import freechips.rocketchip.devices.debug._ 10 | import freechips.rocketchip.devices.tilelink._ 11 | import freechips.rocketchip.diplomacy._ 12 | import freechips.rocketchip.system._ 13 | 14 | import sifive.blocks.devices.gpio._ 15 | import sifive.blocks.devices.spi._ 16 | import sifive.blocks.devices.uart._ 17 | 18 | import sifive.fpgashells.devices.microsemi.polarfireddr3._ 19 | import sifive.fpgashells.devices.microsemi.polarfireddr4._ 20 | import sifive.fpgashells.devices.microsemi.polarfireevalkitpciex4._ 21 | 22 | //------------------------------------------------------------------------- 23 | // U500PolarFireEvalKitSystem 24 | //------------------------------------------------------------------------- 25 | 26 | //class U500PolarFireEvalKitSystem(implicit p: Parameters) extends RocketCoreplex 27 | class U500PolarFireEvalKitSystem(implicit p: Parameters) extends RocketSubsystem 28 | with HasPeripheryMaskROMSlave 29 | with HasPeripheryDebug 30 | with HasSystemErrorSlave 31 | with HasPeripheryUART 32 | with HasPeripherySPI 33 | with HasPeripheryGPIO 34 | // with HasCoreJTAGDebug 35 | // with HasMemoryPolarFireEvalKitDDR4 36 | with HasMemoryPolarFireEvalKitDDR3 37 | with HasSystemPolarFireEvalKitPCIeX4 38 | { 39 | override lazy val module = new U500PolarFireEvalKitSystemModule(this) 40 | } 41 | 42 | class U500PolarFireEvalKitSystemModule[+L <: U500PolarFireEvalKitSystem](_outer: L) 43 | extends RocketSubsystemModuleImp(_outer) 44 | // extends RocketCoreplexModule(_outer) 45 | with HasRTCModuleImp 46 | with HasPeripheryDebugModuleImp 47 | with HasPeripheryUARTModuleImp 48 | with HasPeripherySPIModuleImp 49 | with HasPeripheryGPIOModuleImp 50 | // with HasMemoryPolarFireEvalKitDDR4ModuleImp 51 | with HasMemoryPolarFireEvalKitDDR3ModuleImp 52 | with HasSystemPolarFireEvalKitPCIeX4ModuleImp 53 | { 54 | // Reset vector is set to the location of the mask rom 55 | val maskROMParams = p(PeripheryMaskROMKey) 56 | // global_reset_vector := maskROMParams(0).address.U 57 | global_reset_vector := BigInt(0x80000000L).U 58 | } 59 | -------------------------------------------------------------------------------- /src/main/scala/unleashed/u500vc707devkit/Config.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | package sifive.freedom.unleashed.u500vc707devkit 3 | 4 | import freechips.rocketchip.config._ 5 | import freechips.rocketchip.subsystem._ 6 | import freechips.rocketchip.devices.debug._ 7 | import freechips.rocketchip.devices.tilelink._ 8 | import freechips.rocketchip.diplomacy._ 9 | import freechips.rocketchip.system._ 10 | import freechips.rocketchip.tile._ 11 | 12 | import sifive.blocks.devices.gpio._ 13 | import sifive.blocks.devices.spi._ 14 | import sifive.blocks.devices.uart._ 15 | 16 | import sifive.fpgashells.devices.xilinx.xilinxvc707mig.{MemoryXilinxDDRKey,XilinxVC707MIGParams} 17 | 18 | // Default FreedomUVC707Config 19 | class FreedomUVC707Config extends Config( 20 | new WithJtagDTM ++ 21 | new WithNMemoryChannels(1) ++ 22 | new WithNBigCores(4) ++ 23 | new BaseConfig 24 | ) 25 | 26 | // Freedom U500 VC707 Dev Kit Peripherals 27 | class U500VC707DevKitPeripherals extends Config((site, here, up) => { 28 | case PeripheryUARTKey => List( 29 | UARTParams(address = BigInt(0x64000000L))) 30 | case PeripherySPIKey => List( 31 | SPIParams(rAddress = BigInt(0x64001000L))) 32 | case PeripheryGPIOKey => List( 33 | GPIOParams(address = BigInt(0x64002000L), width = 4)) 34 | case PeripheryMaskROMKey => List( 35 | MaskROMParams(address = 0x10000, name = "BootROM")) 36 | }) 37 | 38 | // Freedom U500 VC707 Dev Kit 39 | class U500VC707DevKitConfig extends Config( 40 | new WithNExtTopInterrupts(0) ++ 41 | new U500VC707DevKitPeripherals ++ 42 | new FreedomUVC707Config().alter((site,here,up) => { 43 | case ErrorParams => ErrorParams(Seq(AddressSet(0x3000, 0xfff)), maxAtomic=site(XLen)/8, maxTransfer=128) 44 | case PeripheryBusKey => up(PeripheryBusKey, site).copy(frequency = 50000000) // 50 MHz hperiphery 45 | case MemoryXilinxDDRKey => XilinxVC707MIGParams(address = Seq(AddressSet(0x80000000L,0x40000000L-1))) //1GB 46 | case DTSTimebase => BigInt(1000000) 47 | case ExtMem => up(ExtMem).map(_.copy(size = 0x40000000L)) 48 | case JtagDTMKey => new JtagDTMConfig ( 49 | idcodeVersion = 2, // 1 was legacy (FE310-G000, Acai). 50 | idcodePartNum = 0x000, // Decided to simplify. 51 | idcodeManufId = 0x489, // As Assigned by JEDEC to SiFive. Only used in wrappers / test harnesses. 52 | debugIdleCycles = 5) // Reasonable guess for synchronization 53 | }) 54 | ) 55 | -------------------------------------------------------------------------------- /src/main/scala/unleashed/u500vcu118devkit/Config.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | package sifive.freedom.unleashed.u500vcu118devkit 3 | 4 | import freechips.rocketchip.config._ 5 | import freechips.rocketchip.subsystem._ 6 | import freechips.rocketchip.devices.debug._ 7 | import freechips.rocketchip.devices.tilelink._ 8 | import freechips.rocketchip.diplomacy._ 9 | import freechips.rocketchip.system._ 10 | import freechips.rocketchip.tile._ 11 | 12 | import sifive.blocks.devices.gpio._ 13 | import sifive.blocks.devices.spi._ 14 | import sifive.blocks.devices.uart._ 15 | 16 | import sifive.fpgashells.devices.xilinx.xilinxvcu118mig.{MemoryXilinxDDRKey,XilinxVCU118MIGParams} 17 | 18 | // Default FreedomUVCU118Config 19 | class FreedomUVCU118Config extends Config( 20 | new WithJtagDTM ++ 21 | new WithNMemoryChannels(1) ++ 22 | new WithNBigCores(4) ++ 23 | new BaseConfig 24 | ) 25 | 26 | // Freedom U500 VCU118 Dev Kit Peripherals 27 | class U500VCU118DevKitPeripherals extends Config((site, here, up) => { 28 | case PeripheryUARTKey => List( 29 | UARTParams(address = BigInt(0x64000000L))) 30 | case PeripherySPIKey => List( 31 | SPIParams(rAddress = BigInt(0x64001000L))) 32 | case PeripheryGPIOKey => List( 33 | GPIOParams(address = BigInt(0x64002000L), width = 4)) 34 | case PeripheryMaskROMKey => List( 35 | MaskROMParams(address = 0x10000, name = "BootROM")) 36 | }) 37 | 38 | // Freedom U500 VCU118 Dev Kit 39 | class U500VCU118DevKitConfig extends Config( 40 | new WithNExtTopInterrupts(0) ++ 41 | new U500VCU118DevKitPeripherals ++ 42 | new FreedomUVCU118Config().alter((site,here,up) => { 43 | case ErrorParams => ErrorParams(Seq(AddressSet(0x3000, 0xfff)), maxAtomic=site(XLen)/8, maxTransfer=128) 44 | case PeripheryBusKey => up(PeripheryBusKey, site).copy(frequency = 50000000) // 50 MHz hperiphery 45 | case MemoryXilinxDDRKey => XilinxVCU118MIGParams(address = Seq(AddressSet(0x80000000L,0x80000000L-1))) //2GB 46 | case DTSTimebase => BigInt(1000000) 47 | case ExtMem => up(ExtMem).map(_.copy(size = 0x80000000L)) 48 | case JtagDTMKey => new JtagDTMConfig ( 49 | idcodeVersion = 2, // 1 was legacy (FE310-G000, Acai). 50 | idcodePartNum = 0x000, // Decided to simplify. 51 | idcodeManufId = 0x489, // As Assigned by JEDEC to SiFive. Only used in wrappers / test harnesses. 52 | debugIdleCycles = 5) // Reasonable guess for synchronization 53 | }) 54 | ) 55 | -------------------------------------------------------------------------------- /src/main/scala/unleashed/u500vcu118devkit/FPGAChip.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | package sifive.freedom.unleashed.u500vcu118devkit 3 | 4 | import Chisel._ 5 | import chisel3.experimental.{withClockAndReset} 6 | 7 | import freechips.rocketchip.config._ 8 | import freechips.rocketchip.diplomacy._ 9 | 10 | import sifive.blocks.devices.gpio._ 11 | import sifive.blocks.devices.pinctrl.{BasePin} 12 | 13 | import sifive.fpgashells.shell.xilinx.vcu118shell._ 14 | import sifive.fpgashells.ip.xilinx.{IOBUF} 15 | 16 | //------------------------------------------------------------------------- 17 | // PinGen 18 | //------------------------------------------------------------------------- 19 | 20 | object PinGen { 21 | def apply(): BasePin = { 22 | new BasePin() 23 | } 24 | } 25 | 26 | //------------------------------------------------------------------------- 27 | // U500VCU118DevKitFPGAChip 28 | //------------------------------------------------------------------------- 29 | 30 | class U500VCU118DevKitFPGAChip(implicit override val p: Parameters) 31 | extends VCU118Shell 32 | with HasDDR3 { 33 | 34 | //----------------------------------------------------------------------- 35 | // DUT 36 | //----------------------------------------------------------------------- 37 | 38 | // Connect the clock to the 50 Mhz output from the PLL 39 | dut_clock := clk50 40 | withClockAndReset(dut_clock, dut_reset) { 41 | val dut = Module(LazyModule(new U500VCU118DevKitSystem).module) 42 | 43 | //--------------------------------------------------------------------- 44 | // Connect peripherals 45 | //--------------------------------------------------------------------- 46 | 47 | connectDebugJTAG(dut) 48 | connectSPI (dut) 49 | connectUART (dut) 50 | connectMIG (dut) 51 | 52 | //--------------------------------------------------------------------- 53 | // GPIO 54 | //--------------------------------------------------------------------- 55 | 56 | val gpioParams = p(PeripheryGPIOKey) 57 | val gpio_pins = Wire(new GPIOPins(() => PinGen(), gpioParams(0))) 58 | 59 | GPIOPinsFromPort(gpio_pins, dut.gpio(0)) 60 | 61 | gpio_pins.pins.foreach { _.i.ival := Bool(false) } 62 | //gpio_pins.pins.zipWithIndex.foreach { 63 | // case(pin, idx) => led(idx) := pin.o.oval 64 | //} 65 | 66 | // tie to zero 67 | //for( idx <- 7 to 4 ) { led(idx) := false.B } 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/scala/unleashed/u500vera/FPGAChip.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | package sifive.freedom.unleashed.u500vera 3 | 4 | import Chisel._ 5 | import chisel3.experimental.{withClockAndReset} 6 | 7 | import freechips.rocketchip.config._ 8 | import freechips.rocketchip.diplomacy._ 9 | 10 | import sifive.blocks.devices.gpio._ 11 | import sifive.blocks.devices.pinctrl.{BasePin} 12 | 13 | import sifive.fpgashells.devices.microsemi.polarfireddr4._ 14 | import sifive.fpgashells.shell.microsemi.polarfireevalkitshell._ 15 | 16 | //------------------------------------------------------------------------- 17 | // PinGen 18 | //------------------------------------------------------------------------- 19 | 20 | object PinGen { 21 | def apply(): BasePin = { 22 | new BasePin() 23 | } 24 | } 25 | 26 | //------------------------------------------------------------------------- 27 | // U500VeraFPGAChip 28 | //------------------------------------------------------------------------- 29 | 30 | 31 | class U500VeraFPGAChip(implicit override val p: Parameters) 32 | extends PolarFireEvalKitShell 33 | with HasPCIe 34 | with HasDDR3 { 35 | 36 | //----------------------------------------------------------------------- 37 | // DUT 38 | //----------------------------------------------------------------------- 39 | 40 | // Connect the clock to the 50 Mhz output from the PLL 41 | // dut_clock := clk50 42 | withClockAndReset(dut_clock, dut_reset) { 43 | val dut = Module(LazyModule(new U500VeraSystem).module) 44 | 45 | //--------------------------------------------------------------------- 46 | // Connect peripherals 47 | //--------------------------------------------------------------------- 48 | 49 | // connectDebugJTAG(dut) 50 | connectSPI (dut) 51 | connectUART (dut) 52 | connectPCIe (dut) 53 | connectMIG (dut) 54 | 55 | //--------------------------------------------------------------------- 56 | // GPIO 57 | //--------------------------------------------------------------------- 58 | 59 | val gpioParams = p(PeripheryGPIOKey) 60 | val gpio_pins = Wire(new GPIOPins(() => PinGen(), gpioParams(0))) 61 | 62 | GPIOPinsFromPort(gpio_pins, dut.gpio(0)) 63 | 64 | gpio_pins.pins.foreach { _.i.ival := Bool(false) } 65 | gpio_pins.pins.zipWithIndex.foreach { 66 | case(pin, idx) => led(idx) := pin.o.oval 67 | } 68 | 69 | // tie to zero 70 | for( idx <- 7 to 4 ) { led(idx) := false.B } 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /bootrom/sdboot/include/devices/spi.h: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | #ifndef _SIFIVE_SPI_H 4 | #define _SIFIVE_SPI_H 5 | 6 | /* Register offsets */ 7 | 8 | #define SPI_REG_SCKDIV 0x00 9 | #define SPI_REG_SCKMODE 0x04 10 | #define SPI_REG_CSID 0x10 11 | #define SPI_REG_CSDEF 0x14 12 | #define SPI_REG_CSMODE 0x18 13 | 14 | #define SPI_REG_DCSSCK 0x28 15 | #define SPI_REG_DSCKCS 0x2a 16 | #define SPI_REG_DINTERCS 0x2c 17 | #define SPI_REG_DINTERXFR 0x2e 18 | 19 | #define SPI_REG_FMT 0x40 20 | #define SPI_REG_TXFIFO 0x48 21 | #define SPI_REG_RXFIFO 0x4c 22 | #define SPI_REG_TXCTRL 0x50 23 | #define SPI_REG_RXCTRL 0x54 24 | 25 | #define SPI_REG_FCTRL 0x60 26 | #define SPI_REG_FFMT 0x64 27 | 28 | #define SPI_REG_IE 0x70 29 | #define SPI_REG_IP 0x74 30 | 31 | /* Fields */ 32 | 33 | #define SPI_SCK_POL 0x1 34 | #define SPI_SCK_PHA 0x2 35 | 36 | #define SPI_FMT_PROTO(x) ((x) & 0x3) 37 | #define SPI_FMT_ENDIAN(x) (((x) & 0x1) << 2) 38 | #define SPI_FMT_DIR(x) (((x) & 0x1) << 3) 39 | #define SPI_FMT_LEN(x) (((x) & 0xf) << 16) 40 | 41 | /* TXCTRL register */ 42 | #define SPI_TXWM(x) ((x) & 0xffff) 43 | /* RXCTRL register */ 44 | #define SPI_RXWM(x) ((x) & 0xffff) 45 | 46 | #define SPI_IP_TXWM 0x1 47 | #define SPI_IP_RXWM 0x2 48 | 49 | #define SPI_FCTRL_EN 0x1 50 | 51 | #define SPI_INSN_CMD_EN 0x1 52 | #define SPI_INSN_ADDR_LEN(x) (((x) & 0x7) << 1) 53 | #define SPI_INSN_PAD_CNT(x) (((x) & 0xf) << 4) 54 | #define SPI_INSN_CMD_PROTO(x) (((x) & 0x3) << 8) 55 | #define SPI_INSN_ADDR_PROTO(x) (((x) & 0x3) << 10) 56 | #define SPI_INSN_DATA_PROTO(x) (((x) & 0x3) << 12) 57 | #define SPI_INSN_CMD_CODE(x) (((x) & 0xff) << 16) 58 | #define SPI_INSN_PAD_CODE(x) (((x) & 0xff) << 24) 59 | 60 | #define SPI_TXFIFO_FULL (1 << 31) 61 | #define SPI_RXFIFO_EMPTY (1 << 31) 62 | 63 | /* Values */ 64 | 65 | #define SPI_CSMODE_AUTO 0 66 | #define SPI_CSMODE_HOLD 2 67 | #define SPI_CSMODE_OFF 3 68 | 69 | #define SPI_DIR_RX 0 70 | #define SPI_DIR_TX 1 71 | 72 | #define SPI_PROTO_S 0 73 | #define SPI_PROTO_D 1 74 | #define SPI_PROTO_Q 2 75 | 76 | #define SPI_ENDIAN_MSB 0 77 | #define SPI_ENDIAN_LSB 1 78 | 79 | #endif /* _SIFIVE_SPI_H */ 80 | -------------------------------------------------------------------------------- /src/main/scala/everywhere/e300artydevkit/Config.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | package sifive.freedom.everywhere.e300artydevkit 3 | 4 | import freechips.rocketchip.config._ 5 | import freechips.rocketchip.subsystem._ 6 | import freechips.rocketchip.devices.debug._ 7 | import freechips.rocketchip.devices.tilelink._ 8 | import freechips.rocketchip.diplomacy.{DTSModel, DTSTimebase} 9 | import freechips.rocketchip.system._ 10 | import freechips.rocketchip.tile._ 11 | 12 | import sifive.blocks.devices.mockaon._ 13 | import sifive.blocks.devices.gpio._ 14 | import sifive.blocks.devices.pwm._ 15 | import sifive.blocks.devices.spi._ 16 | import sifive.blocks.devices.uart._ 17 | import sifive.blocks.devices.i2c._ 18 | 19 | // Default FreedomEConfig 20 | class DefaultFreedomEConfig extends Config ( 21 | new WithNBreakpoints(2) ++ 22 | new WithNExtTopInterrupts(0) ++ 23 | new WithJtagDTM ++ 24 | new TinyConfig 25 | ) 26 | 27 | // Freedom E300 Arty Dev Kit Peripherals 28 | class E300DevKitPeripherals extends Config((site, here, up) => { 29 | case PeripheryGPIOKey => List( 30 | GPIOParams(address = 0x10012000, width = 32, includeIOF = true)) 31 | case PeripheryPWMKey => List( 32 | PWMParams(address = 0x10015000, cmpWidth = 8), 33 | PWMParams(address = 0x10025000, cmpWidth = 16), 34 | PWMParams(address = 0x10035000, cmpWidth = 16)) 35 | case PeripherySPIKey => List( 36 | SPIParams(csWidth = 4, rAddress = 0x10024000, sampleDelay = 3), 37 | SPIParams(csWidth = 1, rAddress = 0x10034000, sampleDelay = 3)) 38 | case PeripherySPIFlashKey => List( 39 | SPIFlashParams( 40 | fAddress = 0x20000000, 41 | rAddress = 0x10014000, 42 | sampleDelay = 3)) 43 | case PeripheryUARTKey => List( 44 | UARTParams(address = 0x10013000), 45 | UARTParams(address = 0x10023000)) 46 | case PeripheryI2CKey => List( 47 | I2CParams(address = 0x10016000)) 48 | case PeripheryMockAONKey => 49 | MockAONParams(address = 0x10000000) 50 | case PeripheryMaskROMKey => List( 51 | MaskROMParams(address = 0x10000, name = "BootROM")) 52 | }) 53 | 54 | // Freedom E300 Arty Dev Kit Peripherals 55 | class E300ArtyDevKitConfig extends Config( 56 | new E300DevKitPeripherals ++ 57 | new DefaultFreedomEConfig().alter((site,here,up) => { 58 | case DTSTimebase => BigInt(32768) 59 | case JtagDTMKey => new JtagDTMConfig ( 60 | idcodeVersion = 2, 61 | idcodePartNum = 0x000, 62 | idcodeManufId = 0x489, 63 | debugIdleCycles = 5) 64 | }) 65 | ) 66 | -------------------------------------------------------------------------------- /src/main/scala/unleashed/u500vc707devkit/FPGAChip.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | package sifive.freedom.unleashed.u500vc707devkit 3 | 4 | import Chisel._ 5 | import chisel3.experimental.{withClockAndReset} 6 | 7 | import freechips.rocketchip.config._ 8 | import freechips.rocketchip.diplomacy._ 9 | 10 | import sifive.blocks.devices.gpio._ 11 | import sifive.blocks.devices.pinctrl.{BasePin} 12 | 13 | import sifive.fpgashells.shell.xilinx.vc707shell._ 14 | import sifive.fpgashells.ip.xilinx.{IOBUF} 15 | 16 | //------------------------------------------------------------------------- 17 | // PinGen 18 | //------------------------------------------------------------------------- 19 | 20 | object PinGen { 21 | def apply(): BasePin = { 22 | new BasePin() 23 | } 24 | } 25 | 26 | //------------------------------------------------------------------------- 27 | // U500VC707DevKitFPGAChip 28 | //------------------------------------------------------------------------- 29 | 30 | class U500VC707DevKitFPGAChip(implicit override val p: Parameters) 31 | extends VC707Shell 32 | with HasPCIe 33 | with HasDDR3 34 | with HasDebugJTAG { 35 | 36 | //----------------------------------------------------------------------- 37 | // DUT 38 | //----------------------------------------------------------------------- 39 | 40 | // Connect the clock to the 50 Mhz output from the PLL 41 | dut_clock := clk50 42 | withClockAndReset(dut_clock, dut_reset) { 43 | val dut = Module(LazyModule(new U500VC707DevKitSystem).module) 44 | 45 | //--------------------------------------------------------------------- 46 | // Connect peripherals 47 | //--------------------------------------------------------------------- 48 | 49 | connectDebugJTAG(dut) 50 | connectSPI (dut) 51 | connectUART (dut) 52 | connectPCIe (dut) 53 | connectMIG (dut) 54 | 55 | //--------------------------------------------------------------------- 56 | // GPIO 57 | //--------------------------------------------------------------------- 58 | 59 | val gpioParams = p(PeripheryGPIOKey) 60 | val gpio_pins = Wire(new GPIOPins(() => PinGen(), gpioParams(0))) 61 | 62 | GPIOPinsFromPort(gpio_pins, dut.gpio(0)) 63 | 64 | gpio_pins.pins.foreach { _.i.ival := Bool(false) } 65 | gpio_pins.pins.zipWithIndex.foreach { 66 | case(pin, idx) => led(idx) := pin.o.oval 67 | } 68 | 69 | // tie to zero 70 | for( idx <- 7 to 4 ) { led(idx) := false.B } 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /src/main/scala/unleashed/u500polarfireevalkit/FPGAChip.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | package sifive.freedom.unleashed.u500polarfireevalkit 3 | 4 | import Chisel._ 5 | import chisel3.experimental.{withClockAndReset} 6 | 7 | import freechips.rocketchip.config._ 8 | import freechips.rocketchip.diplomacy._ 9 | 10 | import sifive.blocks.devices.gpio._ 11 | import sifive.blocks.devices.pinctrl.{BasePin} 12 | 13 | import sifive.fpgashells.devices.microsemi.polarfireddr4._ 14 | import sifive.fpgashells.shell.microsemi.polarfireevalkitshell._ 15 | 16 | //------------------------------------------------------------------------- 17 | // PinGen 18 | //------------------------------------------------------------------------- 19 | 20 | object PinGen { 21 | def apply(): BasePin = { 22 | new BasePin() 23 | } 24 | } 25 | 26 | //------------------------------------------------------------------------- 27 | // U500VC707DevKitFPGAChip 28 | //------------------------------------------------------------------------- 29 | 30 | 31 | class U500PolarFireEvalKitFPGAChip(implicit override val p: Parameters) 32 | extends PolarFireEvalKitShell 33 | with HasPCIe 34 | with HasDDR3 { 35 | 36 | //----------------------------------------------------------------------- 37 | // DUT 38 | //----------------------------------------------------------------------- 39 | 40 | // Connect the clock to the 50 Mhz output from the PLL 41 | // dut_clock := clk50 42 | withClockAndReset(dut_clock, dut_reset) { 43 | val dut = Module(LazyModule(new U500PolarFireEvalKitSystem).module) 44 | 45 | //--------------------------------------------------------------------- 46 | // Connect peripherals 47 | //--------------------------------------------------------------------- 48 | 49 | // connectDebugJTAG(dut) 50 | connectSPI (dut) 51 | connectUART (dut) 52 | connectPCIe (dut) 53 | connectMIG (dut) 54 | 55 | //--------------------------------------------------------------------- 56 | // GPIO 57 | //--------------------------------------------------------------------- 58 | 59 | val gpioParams = p(PeripheryGPIOKey) 60 | val gpio_pins = Wire(new GPIOPins(() => PinGen(), gpioParams(0))) 61 | 62 | GPIOPinsFromPort(gpio_pins, dut.gpio(0)) 63 | 64 | gpio_pins.pins.foreach { _.i.ival := Bool(false) } 65 | gpio_pins.pins.zipWithIndex.foreach { 66 | case(pin, idx) => led(idx) := pin.o.oval 67 | } 68 | 69 | // tie to zero 70 | for( idx <- 7 to 4 ) { led(idx) := false.B } 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /src/main/scala/unleashed/u500vera/Config.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | package sifive.freedom.unleashed.u500vera 3 | 4 | import freechips.rocketchip.config._ 5 | import freechips.rocketchip.subsystem._ 6 | import freechips.rocketchip.devices.debug._ 7 | import freechips.rocketchip.devices.tilelink._ 8 | import freechips.rocketchip.diplomacy._ 9 | import freechips.rocketchip.system._ 10 | import freechips.rocketchip.tile._ 11 | 12 | import sifive.blocks.devices.gpio._ 13 | import sifive.blocks.devices.spi._ 14 | import sifive.blocks.devices.uart._ 15 | 16 | import sifive.fpgashells.devices.microsemi.polarfireddr3.{MemoryMicrosemiDDR3Key, PolarFireEvalKitDDR3Params} 17 | import sifive.fpgashells.devices.microsemi.polarfireddr4.{MemoryMicrosemiDDR4Key, PolarFireEvalKitDDR4Params} 18 | 19 | // Default FreedomU PolarFire Eval Kit Config 20 | class FreedomVeraConfig extends Config( 21 | new WithJtagDTM ++ 22 | new WithNMemoryChannels(1) ++ 23 | new WithNBigCores(1) ++ 24 | new BaseConfig 25 | ) 26 | 27 | // Freedom U500 PolarFire Eval Kit Peripherals 28 | class U500VeraPeripherals extends Config((site, here, up) => { 29 | case PeripheryUARTKey => List( 30 | UARTParams(address = BigInt(0x54000000L))) 31 | case PeripherySPIKey => List( 32 | SPIParams(rAddress = BigInt(0x54001000L))) 33 | case PeripheryGPIOKey => List( 34 | GPIOParams(address = BigInt(0x54002000L), width = 4)) 35 | case PeripheryMaskROMKey => List( 36 | MaskROMParams(address = 0x10000, name = "BootROM")) 37 | }) 38 | 39 | // Freedom U500 PolarFire Eval Kit 40 | class U500VeraConfig extends Config( 41 | new WithNExtTopInterrupts(0) ++ 42 | new U500VeraPeripherals ++ 43 | new FreedomVeraConfig().alter((site,here,up) => { 44 | case ErrorParams => ErrorParams(Seq(AddressSet(0x3000, 0xfff)), maxAtomic=site(XLen)/8, maxTransfer=128) 45 | case PeripheryBusKey => up(PeripheryBusKey, site).copy(frequency = 50000000) // 50 MHz hperiphery 46 | case MemoryMicrosemiDDR3Key => PolarFireEvalKitDDR3Params(address = Seq(AddressSet(0x80000000L,0x40000000L-1))) //1GB 47 | // case MemoryMicrosemiDDR4Key => PolarFireEvalKitDDR4Params(address = Seq(AddressSet(0x80000000L,0x40000000L-1))) //1GB 48 | case DTSTimebase => BigInt(1000000) 49 | case ExtMem => up(ExtMem).map(_.copy(size = 0x40000000L)) 50 | case JtagDTMKey => new JtagDTMConfig ( 51 | idcodeVersion = 2, // 1 was legacy (FE310-G000, Acai). 52 | idcodePartNum = 0x000, // Decided to simplify. 53 | idcodeManufId = 0x489, // As Assigned by JEDEC to SiFive. Only used in wrappers / test harnesses. 54 | debugIdleCycles = 5) // Reasonable guess for synchronization 55 | }) 56 | ) 57 | 58 | -------------------------------------------------------------------------------- /src/main/scala/unleashed/u500polarfireevalkit/Config.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | package sifive.freedom.unleashed.u500polarfireevalkit 3 | 4 | import freechips.rocketchip.config._ 5 | //import freechips.rocketchip.coreplex._ 6 | import freechips.rocketchip.subsystem._ 7 | import freechips.rocketchip.devices.debug._ 8 | import freechips.rocketchip.devices.tilelink._ 9 | import freechips.rocketchip.diplomacy._ 10 | import freechips.rocketchip.system._ 11 | import freechips.rocketchip.tile._ 12 | 13 | import sifive.blocks.devices.gpio._ 14 | import sifive.blocks.devices.spi._ 15 | import sifive.blocks.devices.uart._ 16 | 17 | import sifive.fpgashells.devices.microsemi.polarfireddr3.{MemoryMicrosemiDDR3Key, PolarFireEvalKitDDR3Params} 18 | import sifive.fpgashells.devices.microsemi.polarfireddr4.{MemoryMicrosemiDDR4Key, PolarFireEvalKitDDR4Params} 19 | 20 | // Default FreedomU PolarFire Eval Kit Config 21 | class FreedomUPolarFireEvalKitConfig extends Config( 22 | new WithJtagDTM ++ 23 | new WithNMemoryChannels(1) ++ 24 | new WithNBigCores(1) ++ 25 | new BaseConfig 26 | ) 27 | 28 | // Freedom U500 PolarFire Eval Kit Peripherals 29 | class U500PolarFireEvalKitPeripherals extends Config((site, here, up) => { 30 | case PeripheryUARTKey => List( 31 | UARTParams(address = BigInt(0x64000000L))) 32 | case PeripherySPIKey => List( 33 | SPIParams(rAddress = BigInt(0x64001000L))) 34 | case PeripheryGPIOKey => List( 35 | GPIOParams(address = BigInt(0x64002000L), width = 4)) 36 | case PeripheryMaskROMKey => List( 37 | MaskROMParams(address = 0x10000, name = "BootROM")) 38 | }) 39 | 40 | // Freedom U500 PolarFire Eval Kit 41 | class U500PolarFireEvalKitConfig extends Config( 42 | new WithNExtTopInterrupts(0) ++ 43 | new U500PolarFireEvalKitPeripherals ++ 44 | new FreedomUPolarFireEvalKitConfig().alter((site,here,up) => { 45 | case ErrorParams => ErrorParams(Seq(AddressSet(0x3000, 0xfff)), maxAtomic=site(XLen)/8, maxTransfer=128) 46 | case PeripheryBusKey => up(PeripheryBusKey, site).copy(frequency = 50000000) // 50 MHz hperiphery 47 | case MemoryMicrosemiDDR3Key => PolarFireEvalKitDDR3Params(address = Seq(AddressSet(0x80000000L,0x40000000L-1))) //1GB 48 | // case MemoryMicrosemiDDR4Key => PolarFireEvalKitDDR4Params(address = Seq(AddressSet(0x80000000L,0x40000000L-1))) //1GB 49 | case DTSTimebase => BigInt(1000000) 50 | case ExtMem => up(ExtMem).map(_.copy(size = 0x40000000L)) 51 | case JtagDTMKey => new JtagDTMConfig ( 52 | idcodeVersion = 2, // 1 was legacy (FE310-G000, Acai). 53 | idcodePartNum = 0x000, // Decided to simplify. 54 | idcodeManufId = 0x489, // As Assigned by JEDEC to SiFive. Only used in wrappers / test harnesses. 55 | debugIdleCycles = 5) // Reasonable guess for synchronization 56 | }) 57 | ) 58 | 59 | -------------------------------------------------------------------------------- /bootrom/sdboot/linker/sdboot.elf.lds: -------------------------------------------------------------------------------- 1 | OUTPUT_ARCH("riscv") 2 | ENTRY(_prog_start) 3 | 4 | INCLUDE memory.lds 5 | 6 | PHDRS 7 | { 8 | text PT_LOAD; 9 | data PT_LOAD; 10 | bss PT_LOAD; 11 | } 12 | 13 | SECTIONS 14 | { 15 | PROVIDE(_ram = ORIGIN(memory_mem)); 16 | PROVIDE(_ram_end = _ram + LENGTH(memory_mem)); 17 | 18 | .text ALIGN((ORIGIN(maskrom_mem) + 0x0), 8) : AT(ALIGN((ORIGIN(maskrom_mem) + 0x0), 8)) { 19 | PROVIDE(_ftext = .); 20 | *(.text.init) 21 | *(.text.unlikely .text.unlikely.*) 22 | *(.text .text.* .gnu.linkonce.t.*) 23 | PROVIDE(_etext = .); 24 | . += 0x40; /* to create a gap between .text and .data b/c ifetch can fetch ahead from .data */ 25 | } >maskrom_mem :text 26 | 27 | .eh_frame ALIGN((ADDR(.text) + SIZEOF(.text)), 8) : AT(ALIGN((LOADADDR(.text) + SIZEOF(.text)), 8)) { 28 | *(.eh_frame) 29 | } >maskrom_mem :text 30 | 31 | .rodata ALIGN((ADDR(.eh_frame) + SIZEOF(.eh_frame)), 8) : AT(ALIGN((LOADADDR(.eh_frame) + SIZEOF(.eh_frame)), 8)) ALIGN_WITH_INPUT { 32 | *(.rodata .rodata.* .gnu.linkonce.r.*) 33 | } >maskrom_mem :data 34 | 35 | .srodata ALIGN((ADDR(.rodata) + SIZEOF(.rodata)), 8) : AT(ALIGN((LOADADDR(.rodata) + SIZEOF(.rodata)), 8)) ALIGN_WITH_INPUT { 36 | *(.srodata.cst16) 37 | *(.srodata.cst8) 38 | *(.srodata.cst4) 39 | *(.srodata.cst2) 40 | *(.srodata.*) 41 | } >maskrom_mem :data 42 | 43 | .data ALIGN((ADDR(.srodata) + SIZEOF(.srodata)), 8) : AT(ALIGN((LOADADDR(.srodata) + SIZEOF(.srodata)), 8)) ALIGN_WITH_INPUT { 44 | *(.data .data.* .gnu.linkonce.d.*) 45 | *(.tohost) /* TODO: Support sections that aren't explicitly listed in this linker script */ 46 | } >maskrom_mem :data 47 | 48 | .sdata ALIGN((ADDR(.data) + SIZEOF(.data)), 8) : AT(ALIGN((LOADADDR(.data) + SIZEOF(.data)), 8)) ALIGN_WITH_INPUT { 49 | *(.sdata .sdata.* .gnu.linkonce.s.*) 50 | } >maskrom_mem :data 51 | 52 | PROVIDE(_data = ADDR(.rodata)); 53 | PROVIDE(_data_lma = LOADADDR(.rodata)); 54 | PROVIDE(_edata = .); 55 | 56 | .bss ALIGN((ORIGIN(memory_mem) + 0x0), 8) : AT(ALIGN((ORIGIN(memory_mem) + 0x0), 8)) ALIGN(8) { 57 | PROVIDE(_fbss = .); 58 | PROVIDE(__global_pointer$ = . + 0x7C0); 59 | *(.sbss .sbss.* .gnu.linkonce.sb.*) 60 | *(.bss .bss.* .gnu.linkonce.b.*) 61 | . = ALIGN(8); 62 | PROVIDE(_ebss = .); 63 | } >memory_mem :bss 64 | 65 | PROVIDE(_end = .); 66 | 67 | /* 68 | * heap_stack_region_usable_end: (ORIGIN(memory_mem) + LENGTH(memory_mem)) 69 | * heap_stack_min_size: 4096 70 | * heap_stack_max_size: 1048576 71 | */ 72 | PROVIDE(_sp = ALIGN(MIN((ORIGIN(memory_mem) + LENGTH(memory_mem)), _ebss + 1048576) - 7, 8)); 73 | PROVIDE(_heap_end = _sp - 2048); 74 | 75 | /* This section is a noop and is only used for the ASSERT */ 76 | .stack : { 77 | ASSERT(_sp >= (_ebss + 4096), "Error: No room left for the heap and stack"); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /common.mk: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | # Required variables: 4 | # - MODEL 5 | # - PROJECT 6 | # - CONFIG_PROJECT 7 | # - CONFIG 8 | # - BUILD_DIR 9 | # - FPGA_DIR 10 | 11 | # Optional variables: 12 | # - EXTRA_FPGA_VSRCS 13 | 14 | # export to bootloader 15 | export ROMCONF=$(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).rom.conf 16 | 17 | # export to fpga-shells 18 | export FPGA_TOP_SYSTEM=$(MODEL) 19 | export FPGA_BUILD_DIR=$(BUILD_DIR)/$(FPGA_TOP_SYSTEM) 20 | export fpga_common_script_dir=$(FPGA_DIR)/common/tcl 21 | export fpga_board_script_dir=$(FPGA_DIR)/$(BOARD)/tcl 22 | 23 | export BUILD_DIR 24 | 25 | EXTRA_FPGA_VSRCS ?= 26 | PATCHVERILOG ?= "" 27 | BOOTROM_DIR ?= "" 28 | 29 | base_dir := $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST))))) 30 | export rocketchip_dir := $(base_dir)/rocket-chip 31 | SBT ?= java -jar $(rocketchip_dir)/sbt-launch.jar 32 | 33 | # Build firrtl.jar and put it where chisel3 can find it. 34 | FIRRTL_JAR ?= $(rocketchip_dir)/firrtl/utils/bin/firrtl.jar 35 | FIRRTL ?= java -Xmx2G -Xss8M -XX:MaxPermSize=256M -cp $(FIRRTL_JAR) firrtl.Driver 36 | 37 | $(FIRRTL_JAR): $(shell find $(rocketchip_dir)/firrtl/src/main/scala -iname "*.scala") 38 | $(MAKE) -C $(rocketchip_dir)/firrtl SBT="$(SBT)" root_dir=$(rocketchip_dir)/firrtl build-scala 39 | touch $(FIRRTL_JAR) 40 | mkdir -p $(rocketchip_dir)/lib 41 | cp -p $(FIRRTL_JAR) rocket-chip/lib 42 | mkdir -p $(rocketchip_dir)/chisel3/lib 43 | cp -p $(FIRRTL_JAR) $(rocketchip_dir)/chisel3/lib 44 | 45 | # Build .fir 46 | firrtl := $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).fir 47 | $(firrtl): $(shell find $(base_dir)/src/main/scala -name '*.scala') $(FIRRTL_JAR) 48 | mkdir -p $(dir $@) 49 | $(SBT) "runMain freechips.rocketchip.system.Generator $(BUILD_DIR) $(PROJECT) $(MODEL) $(CONFIG_PROJECT) $(CONFIG)" 50 | 51 | .PHONY: firrtl 52 | firrtl: $(firrtl) 53 | 54 | # Build .v 55 | verilog := $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).v 56 | $(verilog): $(firrtl) $(FIRRTL_JAR) 57 | $(FIRRTL) -i $(firrtl) -o $@ -X verilog 58 | ifneq ($(PATCHVERILOG),"") 59 | $(PATCHVERILOG) 60 | endif 61 | 62 | .PHONY: verilog 63 | verilog: $(verilog) 64 | 65 | romgen := $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).rom.v 66 | $(romgen): $(verilog) 67 | ifneq ($(BOOTROM_DIR),"") 68 | $(MAKE) -C $(BOOTROM_DIR) romgen 69 | mv $(BUILD_DIR)/rom.v $@ 70 | endif 71 | 72 | .PHONY: romgen 73 | romgen: $(romgen) 74 | 75 | f := $(BUILD_DIR)/$(CONFIG_PROJECT).$(CONFIG).vsrcs.F 76 | $(f): 77 | echo $(VSRCS) > $@ 78 | 79 | bit := $(BUILD_DIR)/obj/$(MODEL).bit 80 | $(bit): $(romgen) $(f) 81 | cd $(BUILD_DIR); vivado \ 82 | -nojournal -mode batch \ 83 | -source $(fpga_common_script_dir)/vivado.tcl \ 84 | -tclargs \ 85 | -top-module "$(MODEL)" \ 86 | -F "$(f)" \ 87 | -ip-vivado-tcls "$(shell find '$(BUILD_DIR)' -name '*.vivado.tcl')" \ 88 | -board "$(BOARD)" 89 | 90 | 91 | # Build .mcs 92 | mcs := $(BUILD_DIR)/obj/$(MODEL).mcs 93 | $(mcs): $(bit) 94 | cd $(BUILD_DIR); vivado -nojournal -mode batch -source $(fpga_common_script_dir)/write_cfgmem.tcl -tclargs $(BOARD) $@ $< 95 | 96 | .PHONY: mcs 97 | mcs: $(mcs) 98 | 99 | # Build Libero project 100 | prjx := $(BUILD_DIR)/libero/$(MODEL).prjx 101 | $(prjx): $(verilog) 102 | cd $(BUILD_DIR); libero SCRIPT:$(fpga_common_script_dir)/libero.tcl SCRIPT_ARGS:"$(BUILD_DIR) $(MODEL) $(PROJECT) $(CONFIG) $(BOARD)" 103 | 104 | .PHONY: prjx 105 | prjx: $(prjx) 106 | 107 | # Clean 108 | .PHONY: clean 109 | clean: 110 | ifneq ($(BOOTROM_DIR),"") 111 | $(MAKE) -C $(BOOTROM_DIR) clean 112 | endif 113 | $(MAKE) -C $(FPGA_DIR) clean 114 | rm -rf $(BUILD_DIR) 115 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Freedom 2 | ======= 3 | 4 | This repository contains the RTL created by SiFive for its Freedom E300 and U500 5 | platforms. The Freedom E310 Arty FPGA Dev Kit implements the Freedom E300 6 | Platform and is designed to be mapped onto an [Arty FPGA Evaluation 7 | Kit](https://www.xilinx.com/products/boards-and-kits/arty.html). The Freedom 8 | U500 VC707 FPGA Dev Kit implements the Freedom U500 Platform and is designed to 9 | be mapped onto a [VC707 FPGA Evaluation 10 | Kit](https://www.xilinx.com/products/boards-and-kits/ek-v7-vc707-g.html). 11 | Both systems boot autonomously and can be controlled via an external debugger. 12 | 13 | Please read the section corresponding to the kit you are interested in for 14 | instructions on how to use this repo. 15 | 16 | Software Requirement 17 | -------------------- 18 | 19 | To compile the bootloaders for both Freedom E300 Arty and U500 VC707 20 | FPGA dev kits, the RISC-V software toolchain must be installed locally and 21 | set the $(RISCV) environment variable to point to the location of where the 22 | RISC-V toolchains are installed. You can build the toolchain from scratch 23 | or download the tools here: https://www.sifive.com/products/tools/ 24 | 25 | 26 | Freedom E300 Arty FPGA Dev Kit 27 | ------------------------------ 28 | 29 | The Freedom E300 Arty FPGA Dev Kit implements a Freedom E300 chip. 30 | 31 | ### How to build 32 | 33 | The Makefile corresponding to the Freedom E300 Arty FPGA Dev Kit is 34 | `Makefile.e300artydevkit` and it consists of two main targets: 35 | 36 | - `verilog`: to compile the Chisel source files and generate the Verilog files. 37 | - `mcs`: to create a Configuration Memory File (.mcs) that can be programmed 38 | onto an Arty FPGA board. 39 | 40 | To execute these targets, you can run the following commands: 41 | 42 | ```sh 43 | $ make -f Makefile.e300artydevkit verilog 44 | $ make -f Makefile.e300artydevkit mcs 45 | ``` 46 | 47 | Note: This flow requires Vivado 2017.1. Old versions are known to fail. 48 | 49 | These will place the files under `builds/e300artydevkit/obj`. 50 | 51 | Note that in order to run the `mcs` target, you need to have the `vivado` 52 | executable on your `PATH`. 53 | 54 | ### Bootrom 55 | 56 | The default bootrom consists of a program that immediately jumps to address 57 | 0x20400000, which is 0x00400000 bytes into the SPI flash memory on the Arty 58 | board. 59 | 60 | ### Using the generated MCS Image 61 | 62 | 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/). 63 | 64 | Freedom U500 VC707 FPGA Dev Kit 65 | ------------------------------- 66 | 67 | The Freedom U500 VC707 FPGA Dev Kit implements the Freedom U500 platform. 68 | 69 | ### How to build 70 | 71 | The Makefile corresponding to the Freedom U500 VC707 FPGA Dev Kit is 72 | `Makefile.u500vc707devkit` and it consists of two main targets: 73 | 74 | - `verilog`: to compile the Chisel source files and generate the Verilog files. 75 | - `mcs`: to create a Configuration Memory File (.mcs) that can be programmed 76 | onto an VC707 FPGA board. 77 | 78 | To execute these targets, you can run the following commands: 79 | 80 | ```sh 81 | $ make -f Makefile.u500vc707devkit verilog 82 | $ make -f Makefile.u500vc707devkit mcs 83 | ``` 84 | 85 | Note: This flow requires Vivado 2016.4. Newer versions are known to fail. 86 | 87 | These will place the files under `builds/u500vc707devkit/obj`. 88 | 89 | Note that in order to run the `mcs` target, you need to have the `vivado` 90 | executable on your `PATH`. 91 | 92 | ### Bootrom 93 | 94 | The default bootrom consists of a bootloader that loads a program off the SD 95 | card slot on the VC707 board. 96 | -------------------------------------------------------------------------------- /bootrom/sdboot/include/platform.h: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | #ifndef _SIFIVE_PLATFORM_H 4 | #define _SIFIVE_PLATFORM_H 5 | 6 | #include "const.h" 7 | #include "riscv_test_defaults.h" 8 | #include "devices/clint.h" 9 | #include "devices/gpio.h" 10 | #include "devices/plic.h" 11 | #include "devices/spi.h" 12 | #include "devices/uart.h" 13 | 14 | // Some things missing from the official encoding.h 15 | #if __riscv_xlen == 32 16 | #define MCAUSE_INT 0x80000000UL 17 | #define MCAUSE_CAUSE 0x7FFFFFFFUL 18 | #else 19 | #define MCAUSE_INT 0x8000000000000000UL 20 | #define MCAUSE_CAUSE 0x7FFFFFFFFFFFFFFFUL 21 | #endif 22 | 23 | /**************************************************************************** 24 | * Platform definitions 25 | *****************************************************************************/ 26 | 27 | // CPU info 28 | #define NUM_CORES 1 29 | #define GLOBAL_INT_SIZE 15 30 | #define GLOBAL_INT_MAX_PRIORITY 7 31 | 32 | // Memory map 33 | #define AXI_PCIE_HOST_1_00_A_CTRL_ADDR _AC(0x50000000,UL) 34 | #define AXI_PCIE_HOST_1_00_A_CTRL_SIZE _AC(0x4000000,UL) 35 | #define CLINT_CTRL_ADDR _AC(0x2000000,UL) 36 | #define CLINT_CTRL_SIZE _AC(0x10000,UL) 37 | #define DEBUG_CTRL_ADDR _AC(0x0,UL) 38 | #define DEBUG_CTRL_SIZE _AC(0x1000,UL) 39 | #define ERROR_MEM_ADDR _AC(0x3000,UL) 40 | #define ERROR_MEM_SIZE _AC(0x1000,UL) 41 | #define GPIO_CTRL_ADDR _AC(0x64002000,UL) 42 | #define GPIO_CTRL_SIZE _AC(0x1000,UL) 43 | #define MASKROM_MEM_ADDR _AC(0x10000,UL) 44 | #define MASKROM_MEM_SIZE _AC(0x2000,UL) 45 | #define MEMORY_MEM_ADDR _AC(0x80000000,UL) 46 | #define MEMORY_MEM_SIZE _AC(0x40000000,UL) 47 | #define PLIC_CTRL_ADDR _AC(0xc000000,UL) 48 | #define PLIC_CTRL_SIZE _AC(0x4000000,UL) 49 | #define SPI_CTRL_ADDR _AC(0x64001000,UL) 50 | #define SPI_CTRL_SIZE _AC(0x1000,UL) 51 | #define TEST_CTRL_ADDR _AC(0x4000,UL) 52 | #define TEST_CTRL_SIZE _AC(0x1000,UL) 53 | #define UART_CTRL_ADDR _AC(0x64000000,UL) 54 | #define UART_CTRL_SIZE _AC(0x1000,UL) 55 | 56 | // IOF masks 57 | 58 | 59 | // Interrupt numbers 60 | #define UART_INT_BASE 1 61 | #define SPI_INT_BASE 2 62 | #define GPIO_INT_BASE 3 63 | #define AXI_PCIE_HOST_1_00_A_INT_BASE 7 64 | 65 | // Helper functions 66 | #define _REG64(p, i) (*(volatile uint64_t *)((p) + (i))) 67 | #define _REG32(p, i) (*(volatile uint32_t *)((p) + (i))) 68 | #define _REG16(p, i) (*(volatile uint16_t *)((p) + (i))) 69 | // Bulk set bits in `reg` to either 0 or 1. 70 | // E.g. SET_BITS(MY_REG, 0x00000007, 0) would generate MY_REG &= ~0x7 71 | // E.g. SET_BITS(MY_REG, 0x00000007, 1) would generate MY_REG |= 0x7 72 | #define SET_BITS(reg, mask, value) if ((value) == 0) { (reg) &= ~(mask); } else { (reg) |= (mask); } 73 | #define AXI_PCIE_HOST_1_00_A_REG(offset) _REG32(AXI_PCIE_HOST_1_00_A_CTRL_ADDR, offset) 74 | #define CLINT_REG(offset) _REG32(CLINT_CTRL_ADDR, offset) 75 | #define DEBUG_REG(offset) _REG32(DEBUG_CTRL_ADDR, offset) 76 | #define ERROR_REG(offset) _REG32(ERROR_CTRL_ADDR, offset) 77 | #define GPIO_REG(offset) _REG32(GPIO_CTRL_ADDR, offset) 78 | #define MASKROM_REG(offset) _REG32(MASKROM_CTRL_ADDR, offset) 79 | #define MEMORY_REG(offset) _REG32(MEMORY_CTRL_ADDR, offset) 80 | #define PLIC_REG(offset) _REG32(PLIC_CTRL_ADDR, offset) 81 | #define SPI_REG(offset) _REG32(SPI_CTRL_ADDR, offset) 82 | #define TEST_REG(offset) _REG32(TEST_CTRL_ADDR, offset) 83 | #define UART_REG(offset) _REG32(UART_CTRL_ADDR, offset) 84 | #define AXI_PCIE_HOST_1_00_A_REG64(offset) _REG64(AXI_PCIE_HOST_1_00_A_CTRL_ADDR, offset) 85 | #define CLINT_REG64(offset) _REG64(CLINT_CTRL_ADDR, offset) 86 | #define DEBUG_REG64(offset) _REG64(DEBUG_CTRL_ADDR, offset) 87 | #define ERROR_REG64(offset) _REG64(ERROR_CTRL_ADDR, offset) 88 | #define GPIO_REG64(offset) _REG64(GPIO_CTRL_ADDR, offset) 89 | #define MASKROM_REG64(offset) _REG64(MASKROM_CTRL_ADDR, offset) 90 | #define MEMORY_REG64(offset) _REG64(MEMORY_CTRL_ADDR, offset) 91 | #define PLIC_REG64(offset) _REG64(PLIC_CTRL_ADDR, offset) 92 | #define SPI_REG64(offset) _REG64(SPI_CTRL_ADDR, offset) 93 | #define TEST_REG64(offset) _REG64(TEST_CTRL_ADDR, offset) 94 | #define UART_REG64(offset) _REG64(UART_CTRL_ADDR, offset) 95 | 96 | // Misc 97 | 98 | 99 | #endif /* _SIFIVE_PLATFORM_H */ 100 | -------------------------------------------------------------------------------- /bootrom/sdboot/include/smp.h: -------------------------------------------------------------------------------- 1 | #ifndef SIFIVE_SMP 2 | #define SIFIVE_SMP 3 | #include "platform.h" 4 | 5 | // The maximum number of HARTs this code supports 6 | #ifndef MAX_HARTS 7 | #define MAX_HARTS 32 8 | #endif 9 | #define CLINT_END_HART_IPI CLINT_CTRL_ADDR + (MAX_HARTS*4) 10 | #define CLINT1_END_HART_IPI CLINT1_CTRL_ADDR + (MAX_HARTS*4) 11 | 12 | // The hart that non-SMP tests should run on 13 | #ifndef NONSMP_HART 14 | #define NONSMP_HART 0 15 | #endif 16 | 17 | /* If your test cannot handle multiple-threads, use this: 18 | * smp_disable(reg1) 19 | */ 20 | #define smp_disable(reg1, reg2) \ 21 | csrr reg1, mhartid ;\ 22 | li reg2, NONSMP_HART ;\ 23 | beq reg1, reg2, hart0_entry ;\ 24 | 42: ;\ 25 | wfi ;\ 26 | j 42b ;\ 27 | hart0_entry: 28 | 29 | /* If your test needs to temporarily block multiple-threads, do this: 30 | * smp_pause(reg1, reg2) 31 | * ... single-threaded work ... 32 | * smp_resume(reg1, reg2) 33 | * ... multi-threaded work ... 34 | */ 35 | 36 | #define smp_pause(reg1, reg2) \ 37 | li reg2, 0x8 ;\ 38 | csrw mie, reg2 ;\ 39 | li reg1, NONSMP_HART ;\ 40 | csrr reg2, mhartid ;\ 41 | bne reg1, reg2, 42f 42 | 43 | #ifdef CLINT1_CTRL_ADDR 44 | // If a second CLINT exists, then make sure we: 45 | // 1) Trigger a software interrupt on all harts of both CLINTs. 46 | // 2) Locate your own hart's software interrupt pending register and clear it. 47 | // 3) Wait for all harts on both CLINTs to clear their software interrupt 48 | // pending register. 49 | // WARNING: This code makes these assumptions, which are only true for Fadu as 50 | // of now: 51 | // 1) hart0 uses CLINT0 at offset 0 52 | // 2) hart2 uses CLINT1 at offset 0 53 | // 3) hart3 uses CLINT1 at offset 1 54 | // 4) There are no other harts or CLINTs in the system. 55 | #define smp_resume(reg1, reg2) \ 56 | /* Trigger software interrupt on CLINT0 */ \ 57 | li reg1, CLINT_CTRL_ADDR ;\ 58 | 41: ;\ 59 | li reg2, 1 ;\ 60 | sw reg2, 0(reg1) ;\ 61 | addi reg1, reg1, 4 ;\ 62 | li reg2, CLINT_END_HART_IPI ;\ 63 | blt reg1, reg2, 41b ;\ 64 | /* Trigger software interrupt on CLINT1 */ \ 65 | li reg1, CLINT1_CTRL_ADDR ;\ 66 | 41: ;\ 67 | li reg2, 1 ;\ 68 | sw reg2, 0(reg1) ;\ 69 | addi reg1, reg1, 4 ;\ 70 | li reg2, CLINT1_END_HART_IPI ;\ 71 | blt reg1, reg2, 41b ;\ 72 | /* Wait to receive software interrupt */ \ 73 | 42: ;\ 74 | wfi ;\ 75 | csrr reg2, mip ;\ 76 | andi reg2, reg2, 0x8 ;\ 77 | beqz reg2, 42b ;\ 78 | /* Clear own software interrupt bit */ \ 79 | csrr reg2, mhartid ;\ 80 | bnez reg2, 41f; \ 81 | /* hart0 case: Use CLINT0 */ \ 82 | li reg1, CLINT_CTRL_ADDR ;\ 83 | slli reg2, reg2, 2 ;\ 84 | add reg2, reg2, reg1 ;\ 85 | sw zero, 0(reg2) ;\ 86 | j 42f; \ 87 | 41: \ 88 | /* hart 2, 3 case: Use CLINT1 and remap hart IDs to 0 and 1 */ \ 89 | li reg1, CLINT1_CTRL_ADDR ;\ 90 | addi reg2, reg2, -2; \ 91 | slli reg2, reg2, 2 ;\ 92 | add reg2, reg2, reg1 ;\ 93 | sw zero, 0(reg2) ; \ 94 | 42: \ 95 | /* Wait for all software interrupt bits to be cleared on CLINT0 */ \ 96 | li reg1, CLINT_CTRL_ADDR ;\ 97 | 41: ;\ 98 | lw reg2, 0(reg1) ;\ 99 | bnez reg2, 41b ;\ 100 | addi reg1, reg1, 4 ;\ 101 | li reg2, CLINT_END_HART_IPI ;\ 102 | blt reg1, reg2, 41b; \ 103 | /* Wait for all software interrupt bits to be cleared on CLINT1 */ \ 104 | li reg1, CLINT1_CTRL_ADDR ;\ 105 | 41: ;\ 106 | lw reg2, 0(reg1) ;\ 107 | bnez reg2, 41b ;\ 108 | addi reg1, reg1, 4 ;\ 109 | li reg2, CLINT1_END_HART_IPI ;\ 110 | blt reg1, reg2, 41b; \ 111 | /* End smp_resume() */ 112 | 113 | #else 114 | 115 | #define smp_resume(reg1, reg2) \ 116 | li reg1, CLINT_CTRL_ADDR ;\ 117 | 41: ;\ 118 | li reg2, 1 ;\ 119 | sw reg2, 0(reg1) ;\ 120 | addi reg1, reg1, 4 ;\ 121 | li reg2, CLINT_END_HART_IPI ;\ 122 | blt reg1, reg2, 41b ;\ 123 | 42: ;\ 124 | wfi ;\ 125 | csrr reg2, mip ;\ 126 | andi reg2, reg2, 0x8 ;\ 127 | beqz reg2, 42b ;\ 128 | li reg1, CLINT_CTRL_ADDR ;\ 129 | csrr reg2, mhartid ;\ 130 | slli reg2, reg2, 2 ;\ 131 | add reg2, reg2, reg1 ;\ 132 | sw zero, 0(reg2) ;\ 133 | 41: ;\ 134 | lw reg2, 0(reg1) ;\ 135 | bnez reg2, 41b ;\ 136 | addi reg1, reg1, 4 ;\ 137 | li reg2, CLINT_END_HART_IPI ;\ 138 | blt reg1, reg2, 41b 139 | 140 | #endif /* ifdef CLINT1_CTRL_ADDR */ 141 | 142 | #endif 143 | -------------------------------------------------------------------------------- /bootrom/sdboot/sd.c: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | #include 3 | 4 | #include 5 | 6 | #include "common.h" 7 | 8 | #define DEBUG 9 | #include "kprintf.h" 10 | 11 | #define MAX_CORES 8 12 | 13 | #define PAYLOAD_SIZE (16 << 11) 14 | 15 | #define F_CLK 50000000UL 16 | 17 | static volatile uint32_t * const spi = (void *)(SPI_CTRL_ADDR); 18 | 19 | static inline uint8_t spi_xfer(uint8_t d) 20 | { 21 | int32_t r; 22 | 23 | REG32(spi, SPI_REG_TXFIFO) = d; 24 | do { 25 | r = REG32(spi, SPI_REG_RXFIFO); 26 | } while (r < 0); 27 | return r; 28 | } 29 | 30 | static inline uint8_t sd_dummy(void) 31 | { 32 | return spi_xfer(0xFF); 33 | } 34 | 35 | static uint8_t sd_cmd(uint8_t cmd, uint32_t arg, uint8_t crc) 36 | { 37 | unsigned long n; 38 | uint8_t r; 39 | 40 | REG32(spi, SPI_REG_CSMODE) = SPI_CSMODE_HOLD; 41 | sd_dummy(); 42 | spi_xfer(cmd); 43 | spi_xfer(arg >> 24); 44 | spi_xfer(arg >> 16); 45 | spi_xfer(arg >> 8); 46 | spi_xfer(arg); 47 | spi_xfer(crc); 48 | 49 | n = 1000; 50 | do { 51 | r = sd_dummy(); 52 | if (!(r & 0x80)) { 53 | // dprintf("sd:cmd: %hx\r\n", r); 54 | goto done; 55 | } 56 | } while (--n > 0); 57 | kputs("sd_cmd: timeout"); 58 | done: 59 | return r; 60 | } 61 | 62 | static inline void sd_cmd_end(void) 63 | { 64 | sd_dummy(); 65 | REG32(spi, SPI_REG_CSMODE) = SPI_CSMODE_AUTO; 66 | } 67 | 68 | 69 | static void sd_poweron(void) 70 | { 71 | long i; 72 | REG32(spi, SPI_REG_SCKDIV) = (F_CLK / 300000UL); 73 | REG32(spi, SPI_REG_CSMODE) = SPI_CSMODE_OFF; 74 | for (i = 10; i > 0; i--) { 75 | sd_dummy(); 76 | } 77 | REG32(spi, SPI_REG_CSMODE) = SPI_CSMODE_AUTO; 78 | } 79 | 80 | static int sd_cmd0(void) 81 | { 82 | int rc; 83 | dputs("CMD0"); 84 | rc = (sd_cmd(0x40, 0, 0x95) != 0x01); 85 | sd_cmd_end(); 86 | return rc; 87 | } 88 | 89 | static int sd_cmd8(void) 90 | { 91 | int rc; 92 | dputs("CMD8"); 93 | rc = (sd_cmd(0x48, 0x000001AA, 0x87) != 0x01); 94 | sd_dummy(); /* command version; reserved */ 95 | sd_dummy(); /* reserved */ 96 | rc |= ((sd_dummy() & 0xF) != 0x1); /* voltage */ 97 | rc |= (sd_dummy() != 0xAA); /* check pattern */ 98 | sd_cmd_end(); 99 | return rc; 100 | } 101 | 102 | static void sd_cmd55(void) 103 | { 104 | sd_cmd(0x77, 0, 0x65); 105 | sd_cmd_end(); 106 | } 107 | 108 | static int sd_acmd41(void) 109 | { 110 | uint8_t r; 111 | dputs("ACMD41"); 112 | do { 113 | sd_cmd55(); 114 | r = sd_cmd(0x69, 0x40000000, 0x77); /* HCS = 1 */ 115 | } while (r == 0x01); 116 | return (r != 0x00); 117 | } 118 | 119 | static int sd_cmd58(void) 120 | { 121 | int rc; 122 | dputs("CMD58"); 123 | rc = (sd_cmd(0x7A, 0, 0xFD) != 0x00); 124 | rc |= ((sd_dummy() & 0x80) != 0x80); /* Power up status */ 125 | sd_dummy(); 126 | sd_dummy(); 127 | sd_dummy(); 128 | sd_cmd_end(); 129 | return rc; 130 | } 131 | 132 | static int sd_cmd16(void) 133 | { 134 | int rc; 135 | dputs("CMD16"); 136 | rc = (sd_cmd(0x50, 0x200, 0x15) != 0x00); 137 | sd_cmd_end(); 138 | return rc; 139 | } 140 | 141 | static uint16_t crc16_round(uint16_t crc, uint8_t data) { 142 | crc = (uint8_t)(crc >> 8) | (crc << 8); 143 | crc ^= data; 144 | crc ^= (uint8_t)(crc >> 4) & 0xf; 145 | crc ^= crc << 12; 146 | crc ^= (crc & 0xff) << 5; 147 | return crc; 148 | } 149 | 150 | #define SPIN_SHIFT 6 151 | #define SPIN_UPDATE(i) (!((i) & ((1 << SPIN_SHIFT)-1))) 152 | #define SPIN_INDEX(i) (((i) >> SPIN_SHIFT) & 0x3) 153 | 154 | static const char spinner[] = { '-', '/', '|', '\\' }; 155 | 156 | static int copy(void) 157 | { 158 | volatile uint8_t *p = (void *)(PAYLOAD_DEST); 159 | long i = PAYLOAD_SIZE; 160 | int rc = 0; 161 | 162 | dputs("CMD18"); 163 | kprintf("LOADING "); 164 | 165 | REG32(spi, SPI_REG_SCKDIV) = (F_CLK / 16666666UL); 166 | if (sd_cmd(0x52, 0, 0xE1) != 0x00) { 167 | sd_cmd_end(); 168 | return 1; 169 | } 170 | do { 171 | uint16_t crc, crc_exp; 172 | long n; 173 | 174 | crc = 0; 175 | n = 512; 176 | while (sd_dummy() != 0xFE); 177 | do { 178 | uint8_t x = sd_dummy(); 179 | *p++ = x; 180 | crc = crc16_round(crc, x); 181 | } while (--n > 0); 182 | 183 | crc_exp = ((uint16_t)sd_dummy() << 8); 184 | crc_exp |= sd_dummy(); 185 | 186 | if (crc != crc_exp) { 187 | kputs("\b- CRC mismatch "); 188 | rc = 1; 189 | break; 190 | } 191 | 192 | if (SPIN_UPDATE(i)) { 193 | kputc('\b'); 194 | kputc(spinner[SPIN_INDEX(i)]); 195 | } 196 | } while (--i > 0); 197 | sd_cmd_end(); 198 | 199 | sd_cmd(0x4C, 0, 0x01); 200 | sd_cmd_end(); 201 | kputs("\b "); 202 | return rc; 203 | } 204 | 205 | int main(void) 206 | { 207 | REG32(uart, UART_REG_TXCTRL) = UART_TXEN; 208 | 209 | kputs("INIT"); 210 | sd_poweron(); 211 | if (sd_cmd0() || 212 | sd_cmd8() || 213 | sd_acmd41() || 214 | sd_cmd58() || 215 | sd_cmd16() || 216 | copy()) { 217 | kputs("ERROR"); 218 | return 1; 219 | } 220 | 221 | kputs("BOOT"); 222 | 223 | __asm__ __volatile__ ("fence.i" : : : "memory"); 224 | return 0; 225 | } 226 | -------------------------------------------------------------------------------- /src/main/scala/everywhere/e300artydevkit/Platform.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | package sifive.freedom.everywhere.e300artydevkit 3 | 4 | import Chisel._ 5 | 6 | import freechips.rocketchip.config._ 7 | import freechips.rocketchip.subsystem._ 8 | import freechips.rocketchip.devices.debug._ 9 | import freechips.rocketchip.devices.tilelink._ 10 | import freechips.rocketchip.diplomacy._ 11 | import freechips.rocketchip.util.ResetCatchAndSync 12 | import freechips.rocketchip.system._ 13 | 14 | import sifive.blocks.devices.mockaon._ 15 | import sifive.blocks.devices.gpio._ 16 | import sifive.blocks.devices.jtag._ 17 | import sifive.blocks.devices.pwm._ 18 | import sifive.blocks.devices.spi._ 19 | import sifive.blocks.devices.uart._ 20 | import sifive.blocks.devices.i2c._ 21 | import sifive.blocks.devices.pinctrl._ 22 | 23 | //------------------------------------------------------------------------- 24 | // PinGen 25 | //------------------------------------------------------------------------- 26 | 27 | object PinGen { 28 | def apply(): BasePin = { 29 | val pin = new BasePin() 30 | pin 31 | } 32 | } 33 | 34 | //------------------------------------------------------------------------- 35 | // E300ArtyDevKitPlatformIO 36 | //------------------------------------------------------------------------- 37 | 38 | class E300ArtyDevKitPlatformIO(implicit val p: Parameters) extends Bundle { 39 | val pins = new Bundle { 40 | val jtag = new JTAGPins(() => PinGen(), false) 41 | val gpio = new GPIOPins(() => PinGen(), p(PeripheryGPIOKey)(0)) 42 | val qspi = new SPIPins(() => PinGen(), p(PeripherySPIFlashKey)(0)) 43 | val aon = new MockAONWrapperPins() 44 | } 45 | val jtag_reset = Bool(INPUT) 46 | val ndreset = Bool(OUTPUT) 47 | } 48 | 49 | //------------------------------------------------------------------------- 50 | // E300ArtyDevKitPlatform 51 | //------------------------------------------------------------------------- 52 | 53 | class E300ArtyDevKitPlatform(implicit val p: Parameters) extends Module { 54 | val sys = Module(LazyModule(new E300ArtyDevKitSystem).module) 55 | val io = new E300ArtyDevKitPlatformIO 56 | 57 | // This needs to be de-asserted synchronously to the coreClk. 58 | val async_corerst = sys.aon.rsts.corerst 59 | // Add in debug-controlled reset. 60 | sys.reset := ResetCatchAndSync(clock, async_corerst, 20) 61 | 62 | //----------------------------------------------------------------------- 63 | // Check for unsupported rocket-chip connections 64 | //----------------------------------------------------------------------- 65 | 66 | require (p(NExtTopInterrupts) == 0, "No Top-level interrupts supported"); 67 | 68 | //----------------------------------------------------------------------- 69 | // Build GPIO Pin Mux 70 | //----------------------------------------------------------------------- 71 | // Pin Mux for UART, SPI, PWM 72 | // First convert the System outputs into "IOF" using the respective *GPIOPort 73 | // converters. 74 | 75 | val sys_uart = sys.uart 76 | val sys_pwm = sys.pwm 77 | val sys_spi = sys.spi 78 | val sys_i2c = sys.i2c 79 | 80 | val uart_pins = sys.outer.uartParams.map { c => Wire(new UARTPins(() => PinGen()))} 81 | val pwm_pins = sys.outer.pwmParams.map { c => Wire(new PWMPins(() => PinGen(), c))} 82 | val spi_pins = sys.outer.spiParams.map { c => Wire(new SPIPins(() => PinGen(), c))} 83 | val i2c_pins = sys.outer.i2cParams.map { c => Wire(new I2CPins(() => PinGen()))} 84 | 85 | (uart_pins zip sys_uart) map {case (p, r) => UARTPinsFromPort(p, r, clock = clock, reset = reset, syncStages = 0)} 86 | (pwm_pins zip sys_pwm) map {case (p, r) => PWMPinsFromPort(p, r) } 87 | (spi_pins zip sys_spi) map {case (p, r) => SPIPinsFromPort(p, r, clock = clock, reset = reset, syncStages = 0)} 88 | (i2c_pins zip sys_i2c) map {case (p, r) => I2CPinsFromPort(p, r, clock = clock, reset = reset, syncStages = 0)} 89 | 90 | //----------------------------------------------------------------------- 91 | // Default Pin connections before attaching pinmux 92 | 93 | for (iof_0 <- sys.gpio(0).iof_0.get) { 94 | iof_0.default() 95 | } 96 | 97 | for (iof_1 <- sys.gpio(0).iof_1.get) { 98 | iof_1.default() 99 | } 100 | 101 | //----------------------------------------------------------------------- 102 | 103 | val iof_0 = sys.gpio(0).iof_0.get 104 | val iof_1 = sys.gpio(0).iof_1.get 105 | 106 | // SPI1 (0 is the dedicated) 107 | BasePinToIOF(spi_pins(0).cs(0), iof_0(2)) 108 | BasePinToIOF(spi_pins(0).dq(0), iof_0(3)) 109 | BasePinToIOF(spi_pins(0).dq(1), iof_0(4)) 110 | BasePinToIOF(spi_pins(0).sck, iof_0(5)) 111 | BasePinToIOF(spi_pins(0).dq(2), iof_0(6)) 112 | BasePinToIOF(spi_pins(0).dq(3), iof_0(7)) 113 | BasePinToIOF(spi_pins(0).cs(1), iof_0(8)) 114 | BasePinToIOF(spi_pins(0).cs(2), iof_0(9)) 115 | BasePinToIOF(spi_pins(0).cs(3), iof_0(10)) 116 | 117 | // SPI2 118 | BasePinToIOF(spi_pins(1).cs(0), iof_0(26)) 119 | BasePinToIOF(spi_pins(1).dq(0), iof_0(27)) 120 | BasePinToIOF(spi_pins(1).dq(1), iof_0(28)) 121 | BasePinToIOF(spi_pins(1).sck, iof_0(29)) 122 | BasePinToIOF(spi_pins(1).dq(2), iof_0(30)) 123 | BasePinToIOF(spi_pins(1).dq(3), iof_0(31)) 124 | 125 | // I2C 126 | if (sys.outer.i2cParams.length == 1) { 127 | BasePinToIOF(i2c_pins(0).sda, iof_0(12)) 128 | BasePinToIOF(i2c_pins(0).scl, iof_0(13)) 129 | } 130 | 131 | // UART0 132 | BasePinToIOF(uart_pins(0).rxd, iof_0(16)) 133 | BasePinToIOF(uart_pins(0).txd, iof_0(17)) 134 | 135 | // UART1 136 | BasePinToIOF(uart_pins(1).rxd, iof_0(24)) 137 | BasePinToIOF(uart_pins(1).txd, iof_0(25)) 138 | 139 | //PWM 140 | BasePinToIOF(pwm_pins(0).pwm(0), iof_1(0) ) 141 | BasePinToIOF(pwm_pins(0).pwm(1), iof_1(1) ) 142 | BasePinToIOF(pwm_pins(0).pwm(2), iof_1(2) ) 143 | BasePinToIOF(pwm_pins(0).pwm(3), iof_1(3) ) 144 | 145 | BasePinToIOF(pwm_pins(1).pwm(1), iof_1(19)) 146 | BasePinToIOF(pwm_pins(1).pwm(0), iof_1(20)) 147 | BasePinToIOF(pwm_pins(1).pwm(2), iof_1(21)) 148 | BasePinToIOF(pwm_pins(1).pwm(3), iof_1(22)) 149 | 150 | BasePinToIOF(pwm_pins(2).pwm(0), iof_1(10)) 151 | BasePinToIOF(pwm_pins(2).pwm(1), iof_1(11)) 152 | BasePinToIOF(pwm_pins(2).pwm(2), iof_1(12)) 153 | BasePinToIOF(pwm_pins(2).pwm(3), iof_1(13)) 154 | 155 | //----------------------------------------------------------------------- 156 | // Drive actual Pads 157 | //----------------------------------------------------------------------- 158 | 159 | // Result of Pin Mux 160 | GPIOPinsFromPort(io.pins.gpio, sys.gpio(0)) 161 | 162 | // Dedicated SPI Pads 163 | SPIPinsFromPort(io.pins.qspi, sys.qspi(0), clock = sys.clock, reset = sys.reset, syncStages = 3) 164 | 165 | // JTAG Debug Interface 166 | val sjtag = sys.debug.systemjtag.get 167 | JTAGPinsFromPort(io.pins.jtag, sjtag.jtag) 168 | sjtag.reset := io.jtag_reset 169 | sjtag.mfr_id := p(JtagDTMKey).idcodeManufId.U(11.W) 170 | 171 | io.ndreset := sys.debug.ndreset 172 | 173 | // AON Pads -- direct connection is OK because 174 | // EnhancedPin is hard-coded in MockAONPads 175 | // and thus there is no .fromPort method. 176 | io.pins.aon <> sys.aon.pins 177 | } 178 | -------------------------------------------------------------------------------- /src/main/scala/everywhere/e300artydevkit/FPGAChip.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | package sifive.freedom.everywhere.e300artydevkit 3 | 4 | import Chisel._ 5 | import chisel3.core.{attach} 6 | import chisel3.experimental.{withClockAndReset} 7 | 8 | import freechips.rocketchip.config._ 9 | import freechips.rocketchip.diplomacy.{LazyModule} 10 | 11 | import sifive.blocks.devices.gpio._ 12 | import sifive.blocks.devices.spi._ 13 | 14 | import sifive.fpgashells.shell.xilinx.artyshell.{ArtyShell} 15 | import sifive.fpgashells.ip.xilinx.{IBUFG, IOBUF, PULLUP, PowerOnResetFPGAOnly} 16 | 17 | //------------------------------------------------------------------------- 18 | // E300ArtyDevKitFPGAChip 19 | //------------------------------------------------------------------------- 20 | 21 | class E300ArtyDevKitFPGAChip(implicit override val p: Parameters) extends ArtyShell { 22 | 23 | //----------------------------------------------------------------------- 24 | // Clock divider 25 | //----------------------------------------------------------------------- 26 | val slow_clock = Wire(Bool()) 27 | 28 | // Divide clock by 256, used to generate 32.768 kHz clock for AON block 29 | withClockAndReset(clock_8MHz, ~mmcm_locked) { 30 | val clockToggleReg = RegInit(false.B) 31 | val (_, slowTick) = Counter(true.B, 256) 32 | when (slowTick) {clockToggleReg := ~clockToggleReg} 33 | slow_clock := clockToggleReg 34 | } 35 | 36 | //----------------------------------------------------------------------- 37 | // DUT 38 | //----------------------------------------------------------------------- 39 | 40 | withClockAndReset(clock_32MHz, ck_rst) { 41 | val dut = Module(new E300ArtyDevKitPlatform) 42 | 43 | //--------------------------------------------------------------------- 44 | // SPI flash IOBUFs 45 | //--------------------------------------------------------------------- 46 | 47 | IOBUF(qspi_sck, dut.io.pins.qspi.sck) 48 | IOBUF(qspi_cs, dut.io.pins.qspi.cs(0)) 49 | 50 | IOBUF(qspi_dq(0), dut.io.pins.qspi.dq(0)) 51 | IOBUF(qspi_dq(1), dut.io.pins.qspi.dq(1)) 52 | IOBUF(qspi_dq(2), dut.io.pins.qspi.dq(2)) 53 | IOBUF(qspi_dq(3), dut.io.pins.qspi.dq(3)) 54 | 55 | //--------------------------------------------------------------------- 56 | // JTAG IOBUFs 57 | //--------------------------------------------------------------------- 58 | 59 | dut.io.pins.jtag.TCK.i.ival := IBUFG(IOBUF(jd_2).asClock).asUInt 60 | 61 | IOBUF(jd_5, dut.io.pins.jtag.TMS) 62 | PULLUP(jd_5) 63 | 64 | IOBUF(jd_4, dut.io.pins.jtag.TDI) 65 | PULLUP(jd_4) 66 | 67 | IOBUF(jd_0, dut.io.pins.jtag.TDO) 68 | 69 | // mimic putting a pullup on this line (part of reset vote) 70 | SRST_n := IOBUF(jd_6) 71 | PULLUP(jd_6) 72 | 73 | // jtag reset 74 | val jtag_power_on_reset = PowerOnResetFPGAOnly(clock_32MHz) 75 | dut.io.jtag_reset := jtag_power_on_reset 76 | 77 | // debug reset 78 | dut_ndreset := dut.io.ndreset 79 | 80 | //--------------------------------------------------------------------- 81 | // Assignment to package pins 82 | //--------------------------------------------------------------------- 83 | // Pins IO0-IO13 84 | // 85 | // FTDI UART TX/RX are not connected to ck_io[0,1] 86 | // the way they are on Arduino boards. We copy outgoing 87 | // data to both places, switch 3 (sw[3]) determines whether 88 | // input to UART comes from FTDI chip or gpio_16 (shield pin PD0) 89 | 90 | val iobuf_ck0 = Module(new IOBUF()) 91 | iobuf_ck0.io.I := dut.io.pins.gpio.pins(16).o.oval 92 | iobuf_ck0.io.T := ~dut.io.pins.gpio.pins(16).o.oe 93 | attach(iobuf_ck0.io.IO, ck_io(0)) // UART0 RX 94 | 95 | val iobuf_uart_txd = Module(new IOBUF()) 96 | iobuf_uart_txd.io.I := dut.io.pins.gpio.pins(16).o.oval 97 | iobuf_uart_txd.io.T := ~dut.io.pins.gpio.pins(16).o.oe 98 | attach(iobuf_uart_txd.io.IO, uart_txd_in) 99 | 100 | // gpio(16) input is shared between FTDI TX pin and the Arduino shield pin using SW[3] 101 | val sw_3_in = IOBUF(sw_3) 102 | dut.io.pins.gpio.pins(16).i.ival := Mux(sw_3_in, 103 | iobuf_ck0.io.O & dut.io.pins.gpio.pins(16).o.ie, 104 | iobuf_uart_txd.io.O & dut.io.pins.gpio.pins(16).o.ie) 105 | 106 | IOBUF(uart_rxd_out, dut.io.pins.gpio.pins(17)) 107 | 108 | // Shield header row 0: PD2-PD7 109 | IOBUF(ck_io(2), dut.io.pins.gpio.pins(18)) 110 | IOBUF(ck_io(3), dut.io.pins.gpio.pins(19)) // PWM1(1) 111 | IOBUF(ck_io(4), dut.io.pins.gpio.pins(20)) // PWM1(0) 112 | IOBUF(ck_io(5), dut.io.pins.gpio.pins(21)) // PWM1(2) 113 | IOBUF(ck_io(6), dut.io.pins.gpio.pins(22)) // PWM1(3) 114 | IOBUF(ck_io(7), dut.io.pins.gpio.pins(23)) 115 | 116 | // Header row 1: PB0-PB5 117 | IOBUF(ck_io(8), dut.io.pins.gpio.pins(0)) // PWM0(0) 118 | IOBUF(ck_io(9), dut.io.pins.gpio.pins(1)) // PWM0(1) 119 | IOBUF(ck_io(10), dut.io.pins.gpio.pins(2)) // SPI CS(0) / PWM0(2) 120 | IOBUF(ck_io(11), dut.io.pins.gpio.pins(3)) // SPI MOSI / PWM0(3) 121 | IOBUF(ck_io(12), dut.io.pins.gpio.pins(4)) // SPI MISO 122 | IOBUF(ck_io(13), dut.io.pins.gpio.pins(5)) // SPI SCK 123 | 124 | dut.io.pins.gpio.pins(6).i.ival := 0.U 125 | dut.io.pins.gpio.pins(7).i.ival := 0.U 126 | dut.io.pins.gpio.pins(8).i.ival := 0.U 127 | 128 | // Header row 3: A0-A5 (we don't support using them as analog inputs) 129 | // just treat them as regular digital GPIOs 130 | IOBUF(ck_io(15), dut.io.pins.gpio.pins(9)) // A1 = CS(2) 131 | IOBUF(ck_io(16), dut.io.pins.gpio.pins(10)) // A2 = CS(3) / PWM2(0) 132 | IOBUF(ck_io(17), dut.io.pins.gpio.pins(11)) // A3 = PWM2(1) 133 | IOBUF(ck_io(18), dut.io.pins.gpio.pins(12)) // A4 = PWM2(2) / SDA 134 | IOBUF(ck_io(19), dut.io.pins.gpio.pins(13)) // A5 = PWM2(3) / SCL 135 | 136 | // Mirror outputs of GPIOs with PWM peripherals to RGB LEDs on Arty 137 | // assign RGB LED0 R,G,B inputs = PWM0(1,2,3) when iof_1 is active 138 | IOBUF(led0_r, dut.io.pins.gpio.pins(1)) 139 | IOBUF(led0_g, dut.io.pins.gpio.pins(2)) 140 | IOBUF(led0_b, dut.io.pins.gpio.pins(3)) 141 | 142 | // Note that this is the one which is actually connected on the HiFive/Crazy88 143 | // Board. Same with RGB LED1 R,G,B inputs = PWM1(1,2,3) when iof_1 is active 144 | IOBUF(led1_r, dut.io.pins.gpio.pins(19)) 145 | IOBUF(led1_g, dut.io.pins.gpio.pins(21)) 146 | IOBUF(led1_b, dut.io.pins.gpio.pins(22)) 147 | 148 | // and RGB LED2 R,G,B inputs = PWM2(1,2,3) when iof_1 is active 149 | IOBUF(led2_r, dut.io.pins.gpio.pins(11)) 150 | IOBUF(led2_g, dut.io.pins.gpio.pins(12)) 151 | IOBUF(led2_b, dut.io.pins.gpio.pins(13)) 152 | 153 | // Only 19 out of 20 shield pins connected to GPIO pins 154 | // Shield pin A5 (pin 14) left unconnected 155 | // The buttons are connected to some extra GPIO pins not connected on the 156 | // HiFive1 board 157 | IOBUF(btn_0, dut.io.pins.gpio.pins(15)) 158 | IOBUF(btn_1, dut.io.pins.gpio.pins(30)) 159 | IOBUF(btn_2, dut.io.pins.gpio.pins(31)) 160 | 161 | val iobuf_btn_3 = Module(new IOBUF()) 162 | iobuf_btn_3.io.I := ~dut.io.pins.aon.pmu.dwakeup_n.o.oval 163 | iobuf_btn_3.io.T := ~dut.io.pins.aon.pmu.dwakeup_n.o.oe 164 | attach(btn_3, iobuf_btn_3.io.IO) 165 | dut.io.pins.aon.pmu.dwakeup_n.i.ival := ~iobuf_btn_3.io.O & dut.io.pins.aon.pmu.dwakeup_n.o.ie 166 | 167 | // UART1 RX/TX pins are assigned to PMOD_D connector pins 0/1 168 | IOBUF(ja_0, dut.io.pins.gpio.pins(25)) // UART1 TX 169 | IOBUF(ja_1, dut.io.pins.gpio.pins(24)) // UART1 RX 170 | 171 | // SPI2 pins mapped to 6 pin ICSP connector (standard on later 172 | // arduinos) These are connected to some extra GPIO pins not connected 173 | // on the HiFive1 board 174 | IOBUF(ck_ss, dut.io.pins.gpio.pins(26)) 175 | IOBUF(ck_mosi, dut.io.pins.gpio.pins(27)) 176 | IOBUF(ck_miso, dut.io.pins.gpio.pins(28)) 177 | IOBUF(ck_sck, dut.io.pins.gpio.pins(29)) 178 | 179 | // Use the LEDs for some more useful debugging things 180 | IOBUF(led_0, ck_rst) 181 | IOBUF(led_1, SRST_n) 182 | IOBUF(led_2, dut.io.pins.aon.pmu.dwakeup_n.i.ival) 183 | IOBUF(led_3, dut.io.pins.gpio.pins(14)) 184 | 185 | //--------------------------------------------------------------------- 186 | // Unconnected inputs 187 | //--------------------------------------------------------------------- 188 | 189 | dut.io.pins.aon.erst_n.i.ival := ~reset_periph 190 | dut.io.pins.aon.lfextclk.i.ival := slow_clock 191 | dut.io.pins.aon.pmu.vddpaden.i.ival := 1.U 192 | } 193 | } 194 | -------------------------------------------------------------------------------- /src/main/scala/unleashed/vc707/iofpga/FPGAChip.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package sifive.freedom.unleashed.vc707.iofpga 4 | 5 | import Chisel._ 6 | import chisel3.experimental.{withClockAndReset} 7 | 8 | import freechips.rocketchip.config._ 9 | import freechips.rocketchip.diplomacy._ 10 | import freechips.rocketchip.interrupts._ 11 | import freechips.rocketchip.tilelink._ 12 | import freechips.rocketchip.devices.tilelink._ 13 | import freechips.rocketchip.util.{ElaborationArtefacts,ResetCatchAndSync} 14 | 15 | import sifive.blocks.devices.gpio._ 16 | import sifive.blocks.devices.pinctrl.{BasePin} 17 | import sifive.blocks.devices.msi._ 18 | import sifive.blocks.devices.chiplink._ 19 | 20 | import sifive.fpgashells.shell.xilinx.vc707shell.{VC707Shell,HasPCIe,HasDDR3,HasVC707ChipLink} 21 | import sifive.fpgashells.ip.xilinx.{IOBUF,Series7MMCM} 22 | import sifive.fpgashells.devices.xilinx.xilinxvc707mig._ 23 | import sifive.fpgashells.devices.xilinx.xilinxvc707pciex1._ 24 | import sifive.fpgashells.clocks._ 25 | 26 | import sifive.freedom.unleashed.u500vc707devkit.FreedomUVC707Config 27 | 28 | 29 | //------------------------------------------------------------------------- 30 | // PinGen 31 | //------------------------------------------------------------------------- 32 | 33 | object PinGen { 34 | def apply(): BasePin = { 35 | new BasePin() 36 | } 37 | } 38 | 39 | //------------------------------------------------------------------------- 40 | // ShadowRAMHack -- shadow 512MiB of DDR at 0x6000_0000 from 0x30_0000_000 41 | // this makes it possible to boot linux using FPGA DDR 42 | //------------------------------------------------------------------------- 43 | 44 | class ShadowRAMHack(implicit p: Parameters) extends LazyModule 45 | { 46 | val from = AddressSet(0x60000000L, 0x1fffffffL) 47 | val to = AddressSet(0x3000000000L, 0x1fffffffL) 48 | 49 | val node = TLAdapterNode( 50 | clientFn = {cp => cp }, 51 | managerFn = { mp => 52 | require (mp.managers.size == 1) 53 | mp.copy(managers = mp.managers.map { m => 54 | m.copy(address = m.address ++ Seq(from)) 55 | }) 56 | }) 57 | 58 | lazy val module = new LazyModuleImp(this) { 59 | (node.in zip node.out) foreach { case ((in, _), (out, _)) => 60 | out <> in 61 | out.a.bits.address := Mux( 62 | from.contains(in.a.bits.address), 63 | in.a.bits.address + UInt(to.base - from.base), 64 | in.a.bits.address) 65 | } 66 | } 67 | } 68 | 69 | //------------------------------------------------------------------------- 70 | // IOFPGAChip 71 | //------------------------------------------------------------------------- 72 | 73 | class IOFPGA( 74 | localRoute: Seq[AddressSet], 75 | ddrparams: XilinxVC707MIGParams, 76 | chiplinkparams: ChipLinkParams, 77 | gpioparams: GPIOParams)(implicit p: Parameters) extends LazyModule 78 | { 79 | val link = LazyModule(new ChipLink(chiplinkparams)) 80 | val sbar = LazyModule(new TLXbar) 81 | val xbar = LazyModule(new TLXbar) 82 | val mbar = LazyModule(new TLXbar) 83 | val serr = LazyModule(new TLError(ErrorParams(Seq(AddressSet(0x2800000000L, 0xffffffffL)), 8, 128, true), beatBytes = 8)) 84 | val gpio = LazyModule(new TLGPIO(w = 8, c = gpioparams)) 85 | val xilinxvc707mig = LazyModule(new XilinxVC707MIG(ddrparams)) 86 | val xilinxvc707pcie = LazyModule(new XilinxVC707PCIeX1) 87 | val hack = LazyModule(new ShadowRAMHack) 88 | val msimaster = LazyModule(new MSIMaster(Seq(MSITarget(address=0x2020000, spacing=4, number=10)))) 89 | 90 | private def filter(m: TLManagerParameters) = // keep only managers that are locally routed 91 | if (m.address.exists(a => localRoute.exists(_.overlaps(a)))) Some(m) else None 92 | 93 | // local master Xbar 94 | mbar.node := msimaster.masterNode 95 | mbar.node := TLFIFOFixer() := xilinxvc707pcie.crossTLOut := xilinxvc707pcie.master 96 | 97 | // split local master traffic either to local routing or off-chip 98 | link.node := TLBuffer() := mbar.node 99 | xbar.node := TLFilter(filter) := TLBuffer() := mbar.node 100 | xbar.node := TLBuffer() := link.node 101 | 102 | // receive traffic either from local routing or from off-chip 103 | sbar.node := TLBuffer() := TLAtomicAutomata() := TLFIFOFixer() := TLHintHandler() := TLBuffer() := TLWidthWidget(4) := xbar.node 104 | 105 | // local slave Xbar 106 | serr.node := sbar.node 107 | gpio.node := TLFragmenter(8,64,true) := sbar.node 108 | xilinxvc707mig.node := hack.node := sbar.node 109 | xilinxvc707pcie.slave := xilinxvc707pcie.crossTLIn := TLWidthWidget(8) := sbar.node 110 | xilinxvc707pcie.control := xilinxvc707pcie.crossTLIn := TLWidthWidget(8) := sbar.node 111 | 112 | // interrupts are fed into chiplink via MSI 113 | msimaster.intNode := xilinxvc707pcie.crossIntOut := xilinxvc707pcie.intnode 114 | msimaster.intNode := gpio.intnode 115 | 116 | lazy val module = new LazyModuleImp(this) { 117 | val io = IO (new Bundle { 118 | val chiplink = new WideDataLayerPort(chiplinkparams) 119 | val gpio = new GPIOPortIO(gpioparams) 120 | val xilinxvc707mig = new XilinxVC707MIGIO(AddressRange.fromSets(ddrparams.address).head.size) 121 | val xilinxvc707pcie = new XilinxVC707PCIeX1IO 122 | val rxlocked = Bool(INPUT) 123 | }) 124 | 125 | io.xilinxvc707pcie <> xilinxvc707pcie.module.io.port 126 | xilinxvc707pcie.module.clock := xilinxvc707pcie.module.io.port.axi_aclk_out 127 | xilinxvc707pcie.module.reset := ~io.xilinxvc707pcie.axi_aresetn 128 | 129 | io.xilinxvc707mig <> xilinxvc707mig.module.io.port 130 | 131 | // Hold ChipLink in reset for a bit after power-on 132 | val timer = RegInit(UInt(255, width=8)) 133 | timer := timer - timer.orR 134 | 135 | io.chiplink <> link.module.io.port 136 | link.module.io.c2b_clk := clock 137 | link.module.io.c2b_rst := ResetCatchAndSync(clock, reset || timer.orR || !io.rxlocked) 138 | 139 | io.gpio <> gpio.module.io.port 140 | } 141 | } 142 | 143 | class IOFPGAChip(implicit override val p: Parameters) extends VC707Shell 144 | with HasVC707ChipLink { 145 | 146 | val ddrParams = XilinxVC707MIGParams(address = Seq(AddressSet(0x3000000000L, 0xFFFFFFFFL))) // 192GB - 196GB (behind L2); 147 | val chipLinkParams = ChipLinkParams( 148 | TLUH = AddressSet.misaligned(0, 0x40000000L), // Aloe MMIO [ 0GB, 1GB) 149 | TLC = AddressSet.misaligned(0x60000000L, 0x20000000L) ++ // local memory behind L2 [1.5GB, 2GB) 150 | AddressSet.misaligned(0x80000000L, 0x2000000000L - 0x80000000L) ++ // Aloe DDR [ 2GB, 128GB) 151 | AddressSet.misaligned(0x3000000000L, 0x1000000000L), // local memory behind L2 [192GB, 256GB) 152 | syncTX = true 153 | ) 154 | val localRoute = AddressSet.misaligned(0x40000000L, 0x20000000L) ++ // local MMIO [ 1GB, 1.5GB) 155 | AddressSet.misaligned(0x2000000000L, 0x1000000000L) // local MMIO [128GB, 192GB) 156 | val gpioParams = GPIOParams(address = BigInt(0x2400000000L), width = 4); 157 | 158 | // ChipLink skew RX clock 159 | val vc707_sys_clock_mmcm3 = Module(new Series7MMCM(PLLParameters( 160 | "vc707_sys_clock_mmcm3", 161 | InClockParameters(freqMHz=100), 162 | Seq(OutClockParameters(freqMHz=100, phaseDeg=180))))) 163 | 164 | //----------------------------------------------------------------------- 165 | // DUT 166 | //----------------------------------------------------------------------- 167 | 168 | // System runs at 100 MHz 169 | dut_clock := clk100 170 | dut_ndreset := !ereset_n // debug reset is external 171 | 172 | val ddr = IO(new XilinxVC707MIGPads(ddrParams)) 173 | val pcie = IO(new XilinxVC707PCIeX1Pads) 174 | 175 | withClockAndReset(dut_clock, dut_reset) { 176 | 177 | val iofpga = Module(LazyModule(new IOFPGA(localRoute,ddrParams,chipLinkParams,gpioParams)).module) 178 | 179 | //--------------------------------------------------------------------- 180 | // DDR 181 | //--------------------------------------------------------------------- 182 | iofpga.io.xilinxvc707mig.sys_clk_i := sys_clock.asUInt 183 | mig_clock := iofpga.io.xilinxvc707mig.ui_clk 184 | mig_sys_reset := iofpga.io.xilinxvc707mig.ui_clk_sync_rst 185 | mig_mmcm_locked := iofpga.io.xilinxvc707mig.mmcm_locked 186 | iofpga.io.xilinxvc707mig.aresetn := mig_resetn 187 | iofpga.io.xilinxvc707mig.sys_rst := sys_reset 188 | 189 | ddr <> iofpga.io.xilinxvc707mig 190 | 191 | //--------------------------------------------------------------------- 192 | // PCIe 193 | //--------------------------------------------------------------------- 194 | iofpga.io.xilinxvc707pcie.axi_aresetn := pcie_dat_resetn 195 | pcie_dat_clock := iofpga.io.xilinxvc707pcie.axi_aclk_out 196 | pcie_cfg_clock := iofpga.io.xilinxvc707pcie.axi_ctl_aclk_out 197 | mmcm_lock_pcie := iofpga.io.xilinxvc707pcie.mmcm_lock 198 | iofpga.io.xilinxvc707pcie.axi_ctl_aresetn := pcie_dat_resetn 199 | 200 | pcie <> iofpga.io.xilinxvc707pcie 201 | 202 | //--------------------------------------------------------------------- 203 | // ChipLink 204 | //--------------------------------------------------------------------- 205 | 206 | chiplink <> iofpga.io.chiplink 207 | constrainChipLink(iofpga=true) 208 | 209 | chiplink.c2b.clk := clk100_180 210 | 211 | vc707_sys_clock_mmcm3.io.reset := reset 212 | vc707_sys_clock_mmcm3.io.clk_in1 := chiplink.b2c.clk.asUInt.toBool 213 | iofpga.io.chiplink.b2c.clk := vc707_sys_clock_mmcm3.getClocks(0) 214 | 215 | 216 | 217 | iofpga.io.rxlocked := vc707_sys_clock_mmcm3.io.locked 218 | 219 | //--------------------------------------------------------------------- 220 | // GPIO 221 | //--------------------------------------------------------------------- 222 | val gpio_pins = Wire(new GPIOPins(() => PinGen(), gpioParams)) 223 | 224 | GPIOPinsFromPort(gpio_pins, iofpga.io.gpio) 225 | 226 | gpio_pins.pins.foreach { _.i.ival := Bool(false) } 227 | gpio_pins.pins.zipWithIndex.foreach { 228 | case(pin, idx) => led(idx) := pin.o.oval 229 | } 230 | 231 | // diagnostics 232 | led(4) := vc707_sys_clock_mmcm3.io.locked 233 | led(5) := ereset_n 234 | led(6) := iofpga.io.chiplink.b2c.send 235 | led(7) := iofpga.io.chiplink.c2b.send 236 | } 237 | 238 | } 239 | 240 | class IOFPGAConfig extends Config(new FreedomUVC707Config) 241 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2016 SiFive, Inc. 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /src/main/scala/unleashed/vera/iofpga/FPGAChip.scala: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | package sifive.freedom.unleashed.vera.iofpga 4 | 5 | import Chisel._ 6 | import chisel3.experimental.{withClockAndReset} 7 | 8 | import freechips.rocketchip.config._ 9 | import freechips.rocketchip.diplomacy._ 10 | import freechips.rocketchip.interrupts._ 11 | import freechips.rocketchip.tilelink._ 12 | import freechips.rocketchip.devices.tilelink._ 13 | import freechips.rocketchip.util.{ElaborationArtefacts,ResetCatchAndSync} 14 | 15 | import sifive.blocks.devices.gpio._ 16 | import sifive.blocks.devices.pinctrl.{BasePin} 17 | import sifive.blocks.devices.msi._ 18 | import sifive.blocks.devices.chiplink._ 19 | 20 | import sifive.fpgashells.shell.microsemi.verashell.{VeraShell,HasPCIe,HasDDR3,HasPFEvalKitChipLink} 21 | import sifive.fpgashells.devices.microsemi.polarfireevalkitpciex4._ 22 | import sifive.freedom.unleashed.u500vera.FreedomVeraConfig 23 | import sifive.fpgashells.ip.microsemi.CLKINT 24 | import sifive.fpgashells.ip.microsemi.polarfiredll._ 25 | import sifive.fpgashells.ip.microsemi.polarfireccc._ 26 | 27 | import sifive.fpgashells.devices.microsemi.polarfireddr4._ 28 | import sifive.fpgashells.clocks._ 29 | 30 | //------------------------------------------------------------------------- 31 | // PinGen 32 | //------------------------------------------------------------------------- 33 | 34 | object PinGen { 35 | def apply(): BasePin = { 36 | new BasePin() 37 | } 38 | } 39 | 40 | //------------------------------------------------------------------------- 41 | // ShadowRAMHack -- shadow 512MiB of DDR at 0x6000_0000 from 0x30_0000_000 42 | // this makes it possible to boot linux using FPGA DDR 43 | //------------------------------------------------------------------------- 44 | 45 | class ShadowRAMHack(implicit p: Parameters) extends LazyModule 46 | { 47 | val from = AddressSet(0x60000000L, 0x1fffffffL) 48 | val to = AddressSet(0x3000000000L, 0x1fffffffL) 49 | 50 | val node = TLAdapterNode( 51 | clientFn = {cp => cp }, 52 | managerFn = { mp => 53 | require (mp.managers.size == 1) 54 | mp.copy(managers = mp.managers.map { m => 55 | m.copy(address = m.address ++ Seq(from)) 56 | }) 57 | }) 58 | 59 | lazy val module = new LazyModuleImp(this) { 60 | (node.in zip node.out) foreach { case ((in, _), (out, _)) => 61 | out <> in 62 | out.a.bits.address := Mux( 63 | from.contains(in.a.bits.address), 64 | in.a.bits.address + UInt(to.base - from.base), 65 | in.a.bits.address) 66 | } 67 | } 68 | } 69 | 70 | //------------------------------------------------------------------------- 71 | // IOFPGAChip 72 | //------------------------------------------------------------------------- 73 | 74 | class IOFPGA( 75 | localRoute: Seq[AddressSet], 76 | ddrparams: PolarFireEvalKitDDR4Params, 77 | chiplinkparams: ChipLinkParams, 78 | gpioparams: GPIOParams)(implicit p: Parameters) extends LazyModule 79 | { 80 | val link = LazyModule(new ChipLink(chiplinkparams)) 81 | val sbar = LazyModule(new TLXbar) 82 | val xbar = LazyModule(new TLXbar) 83 | val mbar = LazyModule(new TLXbar) 84 | val serr = LazyModule(new TLError(ErrorParams(Seq(AddressSet(0x2800000000L, 0xffffffffL)), 8, 128, true), beatBytes = 8)) 85 | val gpio = LazyModule(new TLGPIO(w = 8, c = gpioparams)) 86 | val polarfirepcie = LazyModule(new PolarFireEvalKitPCIeX4) 87 | val msimaster = LazyModule(new MSIMaster(Seq(MSITarget(address=0x2020000, spacing=4, number=10)))) 88 | val test_ram = LazyModule(new TLRAM(AddressSet(0x2500000000L, 0x3fff), beatBytes = 8)) 89 | val pf_ddr4 = LazyModule(new PolarFireEvalKitDDR4(ddrparams)) 90 | 91 | private def filter(m: TLManagerParameters) = // keep only managers that are locally routed 92 | if (m.address.exists(a => localRoute.exists(_.overlaps(a)))) Some(m) else None 93 | 94 | // local master Xbar 95 | mbar.node := msimaster.masterNode 96 | mbar.node := TLFIFOFixer() := polarfirepcie.crossTLOut := polarfirepcie.master 97 | 98 | // split local master traffic either to local routing or off-chip 99 | link.node := TLBuffer() := mbar.node 100 | xbar.node := TLFilter(filter) := TLBuffer() := mbar.node 101 | xbar.node := TLBuffer() := link.node 102 | 103 | // receive traffic either from local routing or from off-chip 104 | sbar.node := TLBuffer() := TLAtomicAutomata() := TLFIFOFixer() := TLHintHandler() := TLBuffer() := TLWidthWidget(4) := xbar.node 105 | 106 | // local slave Xbar 107 | serr.node := sbar.node 108 | gpio.node := TLFragmenter(8,64,true) := sbar.node 109 | polarfirepcie.slave := polarfirepcie.crossTLIn := TLWidthWidget(8) := sbar.node 110 | polarfirepcie.control := polarfirepcie.crossTLIn := TLWidthWidget(8) := sbar.node 111 | test_ram.node := TLFragmenter(8, 64) := sbar.node 112 | pf_ddr4.node := sbar.node 113 | 114 | // interrupts are fed into chiplink via MSI 115 | msimaster.intNode := polarfirepcie.crossIntOut := polarfirepcie.intnode 116 | msimaster.intNode := gpio.intnode 117 | 118 | lazy val module = new LazyModuleImp(this) { 119 | val io = IO (new Bundle { 120 | val tx_clock = Clock(INPUT) 121 | val chiplink = new WideDataLayerPort(chiplinkparams) 122 | val gpio = new GPIOPortIO(gpioparams) 123 | val polarfirepcie = new PolarFireEvalKitPCIeX4IO 124 | val link_up = Bool(OUTPUT) 125 | val dll_up = Bool(OUTPUT) 126 | val pf_ddr4 = new PolarFireEvalKitDDR4IO(AddressRange.fromSets(ddrparams.address).head.size) 127 | }) 128 | 129 | io.polarfirepcie <> polarfirepcie.module.io.port 130 | io.pf_ddr4 <> pf_ddr4.module.io.port 131 | 132 | io.chiplink <> link.module.io.port 133 | 134 | // Take the b2c clock from an input pin 135 | val chiplink_rx_clkint = Module(new CLKINT) 136 | chiplink_rx_clkint.io.A := io.chiplink.b2c.clk 137 | 138 | // Skew the RX clock to sample in the data eye 139 | val chiplink_rx_pll = Module(new PolarFireCCC(PLLParameters( 140 | name = "chiplink_rx_pll", 141 | InClockParameters(125), 142 | Seq(OutClockParameters(freqMHz=125), 143 | OutClockParameters(freqMHz=125, phaseDeg = 240))))) 144 | 145 | val lock = chiplink_rx_pll.io.PLL_LOCK_0 146 | chiplink_rx_pll.io.REF_CLK_0 := chiplink_rx_clkint.io.Y 147 | link.module.io.port.b2c.clk := chiplink_rx_pll.io.OUT1_FABCLK_0.get 148 | 149 | // Use a phase-adjusted c2b_clk to meet timing constraints 150 | io.chiplink.c2b.clk := io.tx_clock 151 | 152 | // Hold ChipLink in reset for a bit after power-on 153 | val timer = RegInit(UInt(255, width=8)) 154 | timer := timer - (timer.orR && lock) 155 | 156 | link.module.io.c2b_clk := clock 157 | link.module.io.c2b_rst := ResetCatchAndSync(clock, reset || timer.orR) 158 | 159 | io.gpio <> gpio.module.io.port 160 | 161 | // Report link-up once RX is out of reset 162 | io.link_up := !io.chiplink.b2c.rst 163 | io.dll_up := lock 164 | } 165 | } 166 | 167 | class IOFPGAChip(implicit override val p: Parameters) extends VeraShell 168 | with HasPFEvalKitChipLink { 169 | 170 | val chipLinkParams = ChipLinkParams( 171 | TLUH = AddressSet.misaligned(0, 0x40000000L), // Aloe MMIO [ 0GB, 1GB) 172 | TLC = AddressSet.misaligned(0x60000000L, 0x20000000L) ++ // local memory behind L2 [1.5GB, 2GB) 173 | AddressSet.misaligned(0x80000000L, 0x2000000000L - 0x80000000L) ++ // Aloe DDR [ 2GB, 128GB) 174 | AddressSet.misaligned(0x3000000000L, 0x1000000000L), // local memory behind L2 [192GB, 256GB) 175 | syncTX = true 176 | ) 177 | val localRoute = AddressSet.misaligned(0x40000000L, 0x20000000L) ++ // local MMIO [ 1GB, 1.5GB) 178 | AddressSet.misaligned(0x2000000000L, 0x1000000000L) // local MMIO [128GB, 192GB) 179 | // val gpioParams = GPIOParams(address = BigInt(0x2400000000L), width = 4) 180 | val gpioParams = GPIOParams(address = BigInt(0x2400000000L), width = 8) 181 | val ddrParams = PolarFireEvalKitDDR4Params(address = Seq(AddressSet(0x2600000000L,0x40000000L-1))) 182 | 183 | //----------------------------------------------------------------------- 184 | // DUT 185 | //----------------------------------------------------------------------- 186 | 187 | // System runs at 125 MHz 188 | dut_clock := hart_clk_125 189 | dut_ext_reset_n := ereset_n 190 | 191 | val pcie = IO(new PolarFireEvalKitPCIeX4Pads) 192 | val ddr = IO(new PolarFireEvalKitDDR4Pads(ddrParams)) 193 | 194 | withClockAndReset(dut_clock, dut_reset) { 195 | 196 | // PCIe switch reset: 197 | val timer = RegInit(UInt(268435456, width=29)) 198 | // val timer = RegInit(UInt(16383, width=15)) 199 | timer := timer - timer.orR 200 | 201 | val pf_rstb_i = !ResetCatchAndSync(pcie_fab_ref_clk, !sys_reset_n || timer.orR) 202 | led3 := pf_rstb_i 203 | pf_rstb := pf_rstb_i 204 | 205 | // PCIe slots reset 206 | perst_x1_slot := pf_rstb_i 207 | perst_x16_slot := pf_rstb_i 208 | perst_m2_slot := pf_rstb_i 209 | perst_sata_slot := pf_rstb_i 210 | 211 | // val iofpga = Module(LazyModule(new IOFPGA(localRoute,ddrParams,chipLinkParams,gpioParams)).module) 212 | // val iofpga = Module(LazyModule(new IOFPGA(localRoute,chipLinkParams,gpioParams)).module) 213 | val iofpga = Module(LazyModule(new IOFPGA(localRoute,ddrParams,chipLinkParams,gpioParams)).module) 214 | 215 | //--------------------------------------------------------------------- 216 | // PCIe 217 | //--------------------------------------------------------------------- 218 | iofpga.io.polarfirepcie.APB_S_PCLK := dut_clock 219 | 220 | iofpga.io.polarfirepcie.APB_S_PRESET_N := sys_reset_n //!dut_reset //UInt("b1") 221 | 222 | iofpga.io.polarfirepcie.AXI_CLK := dut_clock 223 | iofpga.io.polarfirepcie.AXI_CLK_STABLE := hart_clk_lock 224 | 225 | iofpga.io.polarfirepcie.PCIE_1_TL_CLK_125MHz := pcie_tl_clk 226 | 227 | iofpga.io.polarfirepcie.PCIE_1_TX_PLL_REF_CLK := pf_tx_pll_refclk_to_lane 228 | 229 | iofpga.io.polarfirepcie.PCIE_1_TX_BIT_CLK := pf_tx_pll_bitclk 230 | 231 | iofpga.io.polarfirepcie.PCIESS_LANE0_CDR_REF_CLK_0 := pcie_refclk 232 | iofpga.io.polarfirepcie.PCIESS_LANE1_CDR_REF_CLK_0 := pcie_refclk 233 | iofpga.io.polarfirepcie.PCIESS_LANE2_CDR_REF_CLK_0 := pcie_refclk 234 | iofpga.io.polarfirepcie.PCIESS_LANE3_CDR_REF_CLK_0 := pcie_refclk 235 | 236 | iofpga.io.polarfirepcie.PCIE_1_TX_PLL_LOCK := pf_tx_pll_lock 237 | 238 | 239 | pcie <> iofpga.io.polarfirepcie 240 | 241 | // debug 242 | debug_io0 := iofpga.io.polarfirepcie.debug_pclk 243 | debug_io1 := iofpga.io.polarfirepcie.debug_preset 244 | debug_io2 := iofpga.io.polarfirepcie.debug_penable 245 | debug_io3 := iofpga.io.polarfirepcie.debug_psel 246 | debug_io4 := iofpga.io.polarfirepcie.debug_paddr2 247 | debug_io5 := iofpga.io.polarfirepcie.debug_paddr3 248 | 249 | //--------------------------------------------------------------------- 250 | // DDR 251 | //--------------------------------------------------------------------- 252 | iofpga.io.pf_ddr4.PLL_REF_CLK := ref_clk_int.io.Y 253 | iofpga.io.pf_ddr4.SYS_RESET_N := sys_reset_n 254 | 255 | // := iofpga.io.pf_ddr4.SYS_CLK 256 | ddr_pll_lock := iofpga.io.pf_ddr4.PLL_LOCK 257 | 258 | ddr_ready := iofpga.io.pf_ddr4.CTRLR_READY 259 | led5 := ddr_ready 260 | 261 | ddr <> iofpga.io.pf_ddr4 262 | 263 | 264 | //--------------------------------------------------------------------- 265 | // ChipLink 266 | //--------------------------------------------------------------------- 267 | iofpga.io.tx_clock := hart_clk_125_tx 268 | chiplink <> iofpga.io.chiplink 269 | 270 | constrainChipLink(iofpga=true) 271 | 272 | val counter = RegInit(UInt(255)) 273 | counter := counter - counter.orR 274 | 275 | led2 := iofpga.io.link_up 276 | led3 := iofpga.io.dll_up 277 | led4 := counter === UInt(0) 278 | // led5 := Bool(true) 279 | 280 | //--------------------------------------------------------------------- 281 | // GPIO 282 | //--------------------------------------------------------------------- 283 | val gpio_pins = Wire(new GPIOPins(() => PinGen(), gpioParams)) 284 | 285 | GPIOPinsFromPort(gpio_pins, iofpga.io.gpio) 286 | 287 | gpio_pins.pins(0).i.ival := Bool(false) 288 | gpio_pins.pins(1).i.ival := Bool(true) 289 | gpio_pins.pins(2).i.ival := Bool(false) 290 | gpio_pins.pins(3).i.ival := Bool(true) 291 | gpio_pins.pins(4).i.ival := Bool(false) 292 | gpio_pins.pins(5).i.ival := Bool(false) 293 | gpio_pins.pins(6).i.ival := Bool(true) 294 | gpio_pins.pins(7).i.ival := Bool(true) 295 | } 296 | 297 | } 298 | 299 | class IOFPGAConfig extends Config(new FreedomVeraConfig) 300 | --------------------------------------------------------------------------------