From 99b52ed1cb0b3abe7c338634569a586ec450a7f2 Mon Sep 17 00:00:00 2001 From: Jie CHEN Date: Tue, 22 Oct 2019 11:09:35 +0200 Subject: [PATCH 01/46] Update for fpga --- .gitignore | 6 + fpga/.gitignore | 5 - fpga/Makefile | 48 ---- fpga/pulpissimo-genesys2/.gitignore | 22 -- fpga/pulpissimo-genesys2/Makefile | 44 ---- fpga/pulpissimo-genesys2/README.md | 56 ----- .../constraints/genesys2.xdc | 213 ------------------ fpga/pulpissimo-genesys2/elf_run.gdb | 4 - fpga/pulpissimo-genesys2/elf_run.sh | 17 -- fpga/pulpissimo-genesys2/fpga-settings.mk | 12 - .../ips/xilinx_clk_mngr/.gitignore | 21 -- .../ips/xilinx_clk_mngr/Makefile | 37 --- .../ips/xilinx_clk_mngr/tcl/run.tcl | 49 ---- .../ips/xilinx_interleaved_ram/.gitignore | 21 -- .../ips/xilinx_interleaved_ram/Makefile | 37 --- .../ips/xilinx_interleaved_ram/tcl/run.tcl | 38 ---- .../ips/xilinx_private_ram/.gitignore | 21 -- .../ips/xilinx_private_ram/Makefile | 37 --- .../ips/xilinx_private_ram/tcl/run.tcl | 38 ---- .../ips/xilinx_slow_clk_mngr/.gitignore | 21 -- .../ips/xilinx_slow_clk_mngr/Makefile | 37 --- .../ips/xilinx_slow_clk_mngr/tcl/run.tcl | 45 ---- fpga/pulpissimo-genesys2/openocd-genesys2.cfg | 46 ---- fpga/pulpissimo-genesys2/rtl/fpga_bootrom.sv | 36 --- fpga/pulpissimo-genesys2/rtl/fpga_clk_gen.sv | 74 ------ .../rtl/fpga_interleaved_ram.sv | 57 ----- .../rtl/fpga_private_ram.sv | 57 ----- .../rtl/fpga_slow_clk_gen.sv | 82 ------- .../rtl/pad_functional_xilinx.sv | 48 ---- .../rtl/pulp_clock_gating_xilinx.sv | 21 -- .../rtl/xilinx_pulpissimo.v | 148 ------------ fpga/pulpissimo-genesys2/tcl/.gitignore | 6 - fpga/pulpissimo-genesys2/tcl/messages.tcl | 13 -- fpga/pulpissimo-genesys2/tcl/run.tcl | 132 ----------- fpga/pulpissimo-nexys_video/.gitignore | 22 -- fpga/pulpissimo-nexys_video/Makefile | 44 ---- fpga/pulpissimo-nexys_video/README.md | 55 ----- .../constraints/nexys_video.xdc | 138 ------------ fpga/pulpissimo-nexys_video/elf_run.gdb | 4 - fpga/pulpissimo-nexys_video/elf_run.sh | 15 -- fpga/pulpissimo-nexys_video/fpga-settings.mk | 11 - .../ips/xilinx_clk_mngr/.gitignore | 21 -- .../ips/xilinx_clk_mngr/Makefile | 37 --- .../ips/xilinx_clk_mngr/tcl/run.tcl | 49 ---- .../ips/xilinx_interleaved_ram/.gitignore | 21 -- .../ips/xilinx_interleaved_ram/Makefile | 37 --- .../ips/xilinx_interleaved_ram/tcl/run.tcl | 38 ---- .../ips/xilinx_private_ram/.gitignore | 21 -- .../ips/xilinx_private_ram/Makefile | 37 --- .../ips/xilinx_private_ram/tcl/run.tcl | 38 ---- .../ips/xilinx_slow_clk_mngr/.gitignore | 21 -- .../ips/xilinx_slow_clk_mngr/Makefile | 37 --- .../ips/xilinx_slow_clk_mngr/tcl/run.tcl | 45 ---- .../openocd-nexys_video.cfg | 46 ---- .../rtl/fpga_bootrom.sv | 36 --- .../rtl/fpga_clk_gen.sv | 74 ------ .../rtl/fpga_interleaved_ram.sv | 57 ----- .../rtl/fpga_private_ram.sv | 57 ----- .../rtl/fpga_slow_clk_gen.sv | 82 ------- .../rtl/pad_functional_xilinx.sv | 48 ---- .../rtl/pulp_clock_gating_xilinx.sv | 21 -- .../rtl/xilinx_pulpissimo.v | 144 ------------ fpga/pulpissimo-nexys_video/tcl/.gitignore | 6 - fpga/pulpissimo-nexys_video/tcl/messages.tcl | 13 -- fpga/pulpissimo-nexys_video/tcl/run.tcl | 126 ----------- fpga/pulpissimo-zcu104/.gitignore | 22 -- fpga/pulpissimo-zcu104/Makefile | 44 ---- fpga/pulpissimo-zcu104/README.md | 52 ----- fpga/pulpissimo-zcu104/constraints/zcu104.xdc | 128 ----------- fpga/pulpissimo-zcu104/elf_run.gdb | 4 - fpga/pulpissimo-zcu104/elf_run.sh | 17 -- fpga/pulpissimo-zcu104/fpga-settings.mk | 12 - .../ips/xilinx_clk_mngr/.gitignore | 21 -- .../ips/xilinx_clk_mngr/Makefile | 37 --- .../ips/xilinx_clk_mngr/tcl/run.tcl | 49 ---- .../ips/xilinx_interleaved_ram/.gitignore | 21 -- .../ips/xilinx_interleaved_ram/Makefile | 37 --- .../ips/xilinx_interleaved_ram/tcl/run.tcl | 38 ---- .../ips/xilinx_private_ram/.gitignore | 21 -- .../ips/xilinx_private_ram/Makefile | 37 --- .../ips/xilinx_private_ram/tcl/run.tcl | 38 ---- .../ips/xilinx_slow_clk_mngr/.gitignore | 21 -- .../ips/xilinx_slow_clk_mngr/Makefile | 37 --- .../ips/xilinx_slow_clk_mngr/tcl/run.tcl | 45 ---- .../openocd-zcu104-digilent-jtag-hs1.cfg | 32 --- .../openocd-zcu104-olimex-arm-usb-ocd-h.cfg | 37 --- fpga/pulpissimo-zcu104/rtl/fpga_bootrom.sv | 36 --- fpga/pulpissimo-zcu104/rtl/fpga_clk_gen.sv | 74 ------ .../rtl/fpga_interleaved_ram.sv | 57 ----- .../pulpissimo-zcu104/rtl/fpga_private_ram.sv | 57 ----- .../rtl/fpga_slow_clk_gen.sv | 82 ------- .../rtl/pad_functional_xilinx.sv | 48 ---- .../rtl/pulp_clock_gating_xilinx.sv | 21 -- .../pulpissimo-zcu104/rtl/xilinx_pulpissimo.v | 143 ------------ fpga/pulpissimo-zcu104/tcl/.gitignore | 6 - fpga/pulpissimo-zcu104/tcl/messages.tcl | 13 -- fpga/pulpissimo-zcu104/tcl/run.tcl | 135 ----------- 97 files changed, 6 insertions(+), 4366 deletions(-) create mode 100644 .gitignore delete mode 100644 fpga/.gitignore delete mode 100644 fpga/Makefile delete mode 100644 fpga/pulpissimo-genesys2/.gitignore delete mode 100644 fpga/pulpissimo-genesys2/Makefile delete mode 100644 fpga/pulpissimo-genesys2/README.md delete mode 100644 fpga/pulpissimo-genesys2/constraints/genesys2.xdc delete mode 100644 fpga/pulpissimo-genesys2/elf_run.gdb delete mode 100755 fpga/pulpissimo-genesys2/elf_run.sh delete mode 100644 fpga/pulpissimo-genesys2/fpga-settings.mk delete mode 100644 fpga/pulpissimo-genesys2/ips/xilinx_clk_mngr/.gitignore delete mode 100644 fpga/pulpissimo-genesys2/ips/xilinx_clk_mngr/Makefile delete mode 100644 fpga/pulpissimo-genesys2/ips/xilinx_clk_mngr/tcl/run.tcl delete mode 100644 fpga/pulpissimo-genesys2/ips/xilinx_interleaved_ram/.gitignore delete mode 100644 fpga/pulpissimo-genesys2/ips/xilinx_interleaved_ram/Makefile delete mode 100644 fpga/pulpissimo-genesys2/ips/xilinx_interleaved_ram/tcl/run.tcl delete mode 100644 fpga/pulpissimo-genesys2/ips/xilinx_private_ram/.gitignore delete mode 100644 fpga/pulpissimo-genesys2/ips/xilinx_private_ram/Makefile delete mode 100644 fpga/pulpissimo-genesys2/ips/xilinx_private_ram/tcl/run.tcl delete mode 100644 fpga/pulpissimo-genesys2/ips/xilinx_slow_clk_mngr/.gitignore delete mode 100644 fpga/pulpissimo-genesys2/ips/xilinx_slow_clk_mngr/Makefile delete mode 100644 fpga/pulpissimo-genesys2/ips/xilinx_slow_clk_mngr/tcl/run.tcl delete mode 100644 fpga/pulpissimo-genesys2/openocd-genesys2.cfg delete mode 100644 fpga/pulpissimo-genesys2/rtl/fpga_bootrom.sv delete mode 100644 fpga/pulpissimo-genesys2/rtl/fpga_clk_gen.sv delete mode 100644 fpga/pulpissimo-genesys2/rtl/fpga_interleaved_ram.sv delete mode 100644 fpga/pulpissimo-genesys2/rtl/fpga_private_ram.sv delete mode 100644 fpga/pulpissimo-genesys2/rtl/fpga_slow_clk_gen.sv delete mode 100644 fpga/pulpissimo-genesys2/rtl/pad_functional_xilinx.sv delete mode 100644 fpga/pulpissimo-genesys2/rtl/pulp_clock_gating_xilinx.sv delete mode 100644 fpga/pulpissimo-genesys2/rtl/xilinx_pulpissimo.v delete mode 100644 fpga/pulpissimo-genesys2/tcl/.gitignore delete mode 100644 fpga/pulpissimo-genesys2/tcl/messages.tcl delete mode 100644 fpga/pulpissimo-genesys2/tcl/run.tcl delete mode 100644 fpga/pulpissimo-nexys_video/.gitignore delete mode 100644 fpga/pulpissimo-nexys_video/Makefile delete mode 100644 fpga/pulpissimo-nexys_video/README.md delete mode 100644 fpga/pulpissimo-nexys_video/constraints/nexys_video.xdc delete mode 100644 fpga/pulpissimo-nexys_video/elf_run.gdb delete mode 100755 fpga/pulpissimo-nexys_video/elf_run.sh delete mode 100644 fpga/pulpissimo-nexys_video/fpga-settings.mk delete mode 100644 fpga/pulpissimo-nexys_video/ips/xilinx_clk_mngr/.gitignore delete mode 100644 fpga/pulpissimo-nexys_video/ips/xilinx_clk_mngr/Makefile delete mode 100644 fpga/pulpissimo-nexys_video/ips/xilinx_clk_mngr/tcl/run.tcl delete mode 100644 fpga/pulpissimo-nexys_video/ips/xilinx_interleaved_ram/.gitignore delete mode 100644 fpga/pulpissimo-nexys_video/ips/xilinx_interleaved_ram/Makefile delete mode 100644 fpga/pulpissimo-nexys_video/ips/xilinx_interleaved_ram/tcl/run.tcl delete mode 100644 fpga/pulpissimo-nexys_video/ips/xilinx_private_ram/.gitignore delete mode 100644 fpga/pulpissimo-nexys_video/ips/xilinx_private_ram/Makefile delete mode 100644 fpga/pulpissimo-nexys_video/ips/xilinx_private_ram/tcl/run.tcl delete mode 100644 fpga/pulpissimo-nexys_video/ips/xilinx_slow_clk_mngr/.gitignore delete mode 100644 fpga/pulpissimo-nexys_video/ips/xilinx_slow_clk_mngr/Makefile delete mode 100644 fpga/pulpissimo-nexys_video/ips/xilinx_slow_clk_mngr/tcl/run.tcl delete mode 100644 fpga/pulpissimo-nexys_video/openocd-nexys_video.cfg delete mode 100644 fpga/pulpissimo-nexys_video/rtl/fpga_bootrom.sv delete mode 100644 fpga/pulpissimo-nexys_video/rtl/fpga_clk_gen.sv delete mode 100644 fpga/pulpissimo-nexys_video/rtl/fpga_interleaved_ram.sv delete mode 100644 fpga/pulpissimo-nexys_video/rtl/fpga_private_ram.sv delete mode 100644 fpga/pulpissimo-nexys_video/rtl/fpga_slow_clk_gen.sv delete mode 100644 fpga/pulpissimo-nexys_video/rtl/pad_functional_xilinx.sv delete mode 100644 fpga/pulpissimo-nexys_video/rtl/pulp_clock_gating_xilinx.sv delete mode 100644 fpga/pulpissimo-nexys_video/rtl/xilinx_pulpissimo.v delete mode 100644 fpga/pulpissimo-nexys_video/tcl/.gitignore delete mode 100644 fpga/pulpissimo-nexys_video/tcl/messages.tcl delete mode 100644 fpga/pulpissimo-nexys_video/tcl/run.tcl delete mode 100644 fpga/pulpissimo-zcu104/.gitignore delete mode 100644 fpga/pulpissimo-zcu104/Makefile delete mode 100644 fpga/pulpissimo-zcu104/README.md delete mode 100644 fpga/pulpissimo-zcu104/constraints/zcu104.xdc delete mode 100644 fpga/pulpissimo-zcu104/elf_run.gdb delete mode 100755 fpga/pulpissimo-zcu104/elf_run.sh delete mode 100644 fpga/pulpissimo-zcu104/fpga-settings.mk delete mode 100644 fpga/pulpissimo-zcu104/ips/xilinx_clk_mngr/.gitignore delete mode 100644 fpga/pulpissimo-zcu104/ips/xilinx_clk_mngr/Makefile delete mode 100644 fpga/pulpissimo-zcu104/ips/xilinx_clk_mngr/tcl/run.tcl delete mode 100644 fpga/pulpissimo-zcu104/ips/xilinx_interleaved_ram/.gitignore delete mode 100644 fpga/pulpissimo-zcu104/ips/xilinx_interleaved_ram/Makefile delete mode 100644 fpga/pulpissimo-zcu104/ips/xilinx_interleaved_ram/tcl/run.tcl delete mode 100644 fpga/pulpissimo-zcu104/ips/xilinx_private_ram/.gitignore delete mode 100644 fpga/pulpissimo-zcu104/ips/xilinx_private_ram/Makefile delete mode 100644 fpga/pulpissimo-zcu104/ips/xilinx_private_ram/tcl/run.tcl delete mode 100644 fpga/pulpissimo-zcu104/ips/xilinx_slow_clk_mngr/.gitignore delete mode 100644 fpga/pulpissimo-zcu104/ips/xilinx_slow_clk_mngr/Makefile delete mode 100644 fpga/pulpissimo-zcu104/ips/xilinx_slow_clk_mngr/tcl/run.tcl delete mode 100644 fpga/pulpissimo-zcu104/openocd-zcu104-digilent-jtag-hs1.cfg delete mode 100644 fpga/pulpissimo-zcu104/openocd-zcu104-olimex-arm-usb-ocd-h.cfg delete mode 100644 fpga/pulpissimo-zcu104/rtl/fpga_bootrom.sv delete mode 100644 fpga/pulpissimo-zcu104/rtl/fpga_clk_gen.sv delete mode 100644 fpga/pulpissimo-zcu104/rtl/fpga_interleaved_ram.sv delete mode 100644 fpga/pulpissimo-zcu104/rtl/fpga_private_ram.sv delete mode 100644 fpga/pulpissimo-zcu104/rtl/fpga_slow_clk_gen.sv delete mode 100644 fpga/pulpissimo-zcu104/rtl/pad_functional_xilinx.sv delete mode 100644 fpga/pulpissimo-zcu104/rtl/pulp_clock_gating_xilinx.sv delete mode 100644 fpga/pulpissimo-zcu104/rtl/xilinx_pulpissimo.v delete mode 100644 fpga/pulpissimo-zcu104/tcl/.gitignore delete mode 100644 fpga/pulpissimo-zcu104/tcl/messages.tcl delete mode 100644 fpga/pulpissimo-zcu104/tcl/run.tcl diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..960db112 --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +fpga +install +ips +ipstools +pulp-builder +pulp-rt-examples \ No newline at end of file diff --git a/fpga/.gitignore b/fpga/.gitignore deleted file mode 100644 index c764b3a0..00000000 --- a/fpga/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -pulpissimo/* -pulpissimo_genesys2.bin -pulpissimo_genesys2.bit -pulpissimo_zcu104.bin -pulpissimo_zcu104.bit diff --git a/fpga/Makefile b/fpga/Makefile deleted file mode 100644 index 3528176b..00000000 --- a/fpga/Makefile +++ /dev/null @@ -1,48 +0,0 @@ -.DEFAULT_GOAL:=help - -all: genesys2 zcu104 nexys_video ## Generates the bitstream for all supported boards board. - -clean_all: clean_genesys2 clean_zcu104 clean_nexys_video ## Removes synthesis output and bitstreams for all boards. - -genesys2: ## Generates the bistream for the genesys2 board - cd pulpissimo-genesys2; make all - cp pulpissimo-genesys2/pulpissimo_genesys2.runs/impl_1/xilinx_pulpissimo.bit pulpissimo_genesys2.bit - cp pulpissimo-genesys2/pulpissimo_genesys2.runs/impl_1/xilinx_pulpissimo.bin pulpissimo_genesys2.bin - @echo "Bitstream generation for genesys2 board finished. The bitstream Configuration Memory File was copied to ./pulpissimo_genesys2.bit and ./pulpissimo_genesys2.bin" - -clean_genesys2: ## Removes all bitstreams, *.log files and vivado related files (rm -rf vivado*) for the genesys2 board. - cd pulpissimo-genesys2; make clean - rm -f pulpissimo_genesys2.bit - rm -f pulpissimo_genesys2.bin - -zcu104: ## Generates the bistream for the zcu104 board - cd pulpissimo-zcu104; make all - cp pulpissimo-zcu104/pulpissimo_zcu104.runs/impl_1/xilinx_pulpissimo.bit pulpissimo_zcu104.bit - cp pulpissimo-zcu104/pulpissimo_zcu104.runs/impl_1/xilinx_pulpissimo.bin pulpissimo_zcu104.bin - @echo "Bitstream generation for zcu104 board finished. The bitstream Configuration Memory File was copied to ./pulpissimo_zcu104.bit and ./pulpissimo_zcu104.bin" - -clean_zcu104: ## Removes all bitstreams, *.log files and vivado related files (rm -rf vivado*) for the zcu104 board. - cd pulpissimo-zcu104; make clean - rm -f pulpissimo_zcu104.bit - rm -f pulpissimo_zcu104.bin - -nexys_video: ## Generates the bistream for the nexys_video board - cd pulpissimo-nexys_video; make all - cp pulpissimo-nexys_video/pulpissimo-nexys_video.runs/impl_1/xilinx_pulpissimo.bit pulpissimo_nexys_video.bit - cp pulpissimo-nexys_video/pulpissimo-nexys_video.runs/impl_1/xilinx_pulpissimo.bin pulpissimo_nexys_video.bin - @echo "Bitstream generation for nexys_video board finished. The bitstream Configuration Memory File was copied to ./pulpissimo_nexys_video.bit and ./pulpissimo_nexys_video.bin" - -clean_nexys_video: ## Removes all bitstreams, *.log files and vivado related files (rm -rf vivado*) for the nexys_video board. - cd pulpissimo-nexys_video; make clean - rm -f pulpissimo_nexys_video.bit - rm -f pulpissimo_nexys_video.bin - -help: ## Show this help message - @echo "PULPissimo on FPGA" - @echo "" - @echo "Call make with one of the supported FPGA boards as arguments to generate the bitstream in the corresponding folder. " - @echo "E.g. 'make genesys2' to generate the bitstream for the genesys2 board in pulpissimo-genesy2 subdirectory." - @echo "By default make invokes 'vivado' to start Xilinx Vivado. This behaviour can be overriden by setting the make variable 'VIVADO'" - @echo "e.g. make genesys2 VIVADO='vivado-2018.3 vivado' for ETH centos machines." - @echo "" - @grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' diff --git a/fpga/pulpissimo-genesys2/.gitignore b/fpga/pulpissimo-genesys2/.gitignore deleted file mode 100644 index 3f35710f..00000000 --- a/fpga/pulpissimo-genesys2/.gitignore +++ /dev/null @@ -1,22 +0,0 @@ -#Ignore vivado project files generated by the tcl script -**/.Xil/* -**/reports/* -**/*.cache/* -**/*.hw/* -**/*.ip_user_files/* -**/*.runs/* -**/*.sim/* -**/*.srcs/* -*.edf -*.xpr -*.jou -*.log - -.cxl.* - -*_stub.v -gmon.out - -/pulpissimo/**/pulpissimo.bit - -**/xdc/constraints.xdc diff --git a/fpga/pulpissimo-genesys2/Makefile b/fpga/pulpissimo-genesys2/Makefile deleted file mode 100644 index bd1a6083..00000000 --- a/fpga/pulpissimo-genesys2/Makefile +++ /dev/null @@ -1,44 +0,0 @@ -PROJECT:=pulpissimo_genesys2 -VIVADO ?= vivado -VIVADOFLAGS ?= -nojournal -mode batch -source scripts/prologue.tcl - -include fpga-settings.mk - -.DEFAULT_GOAL:=help - -.PHONY: help all gui ips clean-ips clk clean-clk ram clean-ram clean - -all: ips ## Generate the bitstream for pulpissimo with vivado in batch mode. The vivado invocation command may be overriden with the env variable VIVADO. - $(VIVADO) -mode batch -source tcl/run.tcl - -gui: ips ## Generates the bitstream for pulpissimo with vivado in GUI mode. The vivado invocation command may be overriden with the env variable VIVADO. - $(VIVADO) -mode gui -source tcl/run.tcl & - -ips: clk ram ## Synthesizes necessary xilinx IP - -clean-ips: clean-clk clean-ram ## Clean all IPs - -clk: ## Synthesizes the Xilinx Clocking Manager IPs - cd ips/xilinx_clk_mngr; make all - cd ips/xilinx_slow_clk_mngr; make all - -clean-clk: ## Removes all Clocking Wizard IP outputs - cd ips/xilinx_clk_mngr; make clean - cd ips/xilinx_slow_clk_mngr; make clean - -ram: ## Synthesizes the Xilinx Block Memory Generator IPs for PULPissimo's L2 Ram - cd ips/xilinx_interleaved_ram; make all - cd ips/xilinx_private_ram; make all - -clean-ram: ## Removes all Block Ram IP outputs related to l2 ram - cd ips/xilinx_interleaved_ram; make clean - cd ips/xilinx_private_ram; make clean - -clean: ## Removes all bitstreams, *.log files and vivado related files (rm -rf vivado*) - rm -rf ${PROJECT}.*[^'bit'] - rm -rf ${PROJECT}.*[^'bin'] - rm -rf *.log - rm -rf vivado* - -help: - @grep -E -h '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' diff --git a/fpga/pulpissimo-genesys2/README.md b/fpga/pulpissimo-genesys2/README.md deleted file mode 100644 index e8c7dc12..00000000 --- a/fpga/pulpissimo-genesys2/README.md +++ /dev/null @@ -1,56 +0,0 @@ -# PULPissimo on the Digilent Genesys2 Board -[\[Documentation\]](https://reference.digilentinc.com/reference/programmable-logic/genesys-2/start) - -## Bitstream Generation -In the fpga folder, run -```Shell -make genesys2 -``` -which will generate `pulpissimo_genesys2.bit`. -Use Vivado to load it into the FPGA. - -## Default SoC and Core Frequencies - -By default the clock generating IPs are synthesized to provide the following frequencies to PULPissimo: - -| Clock Domain | Default Frequency on Genesys2 board | -|----------------|-------------------------------------| -| Core Frequency | 20 MHz | -| SoC Frequency | 10 MHz | - - -## Peripherals -PULPissimo is connected to the following board peripherals: - - -| PULPissimo Pin | Mapped Board Peripheral | -|----------------|-----------------------------------------------------| -| `SPIM0` pins | QSPI Flash | -| `I2C0` pins | I2C Bus (connects to Board Current Measurement ICs) | -| `spim_csn1` | LED0 | -| `cam_pclk` | LED1 | -| `cam_hsync` | LED2 | -| `cam_data0` | LED3 | -| `cam_data1` | Switch 1 | -| `cam_data2` | Switch 2 | -| `cam_data3` | Button C | -| `cam_data4` | Button D | -| `cam_data5` | Button L | -| `cam_data6` | Button R | -| `cam_data7` | Button U | - -### Reset Button -The USER RESET button (BTN1) resets the RISC-V CPU. - -### UART -PULPissimo's UART port is mapped to the onboard FTDI FT232R USB-UART bridge and thus accessible through the UART micro-USB connector J15. - -### JTAG -PULPIssimo's JTAG plug is connected to Channel 0 of the onboard FTDI USB JTAG -programmer. Therefore we can attach OpenOCD withouth the need of an external -JTAG programmer. Just attach a micro-USB cable to the JTAG SW17 micro-USB connector and use the -provided OpenOCD configuration file: - -```Shell -$OPENOCD/bin/openocd -f pulpissimo/fpga/pulpissimo-genesys2/openocd-genesys2.cfg -``` diff --git a/fpga/pulpissimo-genesys2/constraints/genesys2.xdc b/fpga/pulpissimo-genesys2/constraints/genesys2.xdc deleted file mode 100644 index a165b732..00000000 --- a/fpga/pulpissimo-genesys2/constraints/genesys2.xdc +++ /dev/null @@ -1,213 +0,0 @@ -####################################### -# _______ _ _ # -# |__ __(_) (_) # -# | | _ _ __ ___ _ _ __ __ _ # -# | | | | '_ ` _ \| | '_ \ / _` | # -# | | | | | | | | | | | | | (_| | # -# |_| |_|_| |_| |_|_|_| |_|\__, | # -# __/ | # -# |___/ # -####################################### - - -#Create constraint for the clock input of the genesys2 board -create_clock -period 5.000 -name ref_clk [get_ports ref_clk_p] - -#I2S and CAM interface are not used in this FPGA port. Set constraints to -#disable the clock -set_case_analysis 0 i_pulpissimo/safe_domain_i/cam_pclk_o -set_case_analysis 0 i_pulpissimo/safe_domain_i/i2s_slave_sck_o -#set_input_jitter tck 1.000 - -## JTAG -create_clock -period 100.000 -name tck -waveform {0.000 50.000} [get_ports pad_jtag_tck] -set_input_jitter tck 1.000 - - -# minimize routing delay -set_input_delay -clock tck -clock_fall 5.000 [get_ports pad_jtag_tdi] -set_input_delay -clock tck -clock_fall 5.000 [get_ports pad_jtag_tms] -set_output_delay -clock tck 5.000 [get_ports pad_jtag_tdo] -set_false_path -from [get_ports pad_jtag_trst] - -set_max_delay -to [get_ports pad_jtag_tdo] 20.000 -set_max_delay -from [get_ports pad_jtag_tms] 20.000 -set_max_delay -from [get_ports pad_jtag_tdi] 20.000 -set_max_delay -from [get_ports pad_jtag_trst] 20.000 - -set_max_delay -datapath_only -from [get_pins i_pulpissimo/soc_domain_i/pulp_soc_i/i_dmi_jtag/i_dmi_cdc/i_cdc_resp/i_src/data_src_q_reg*/C] -to [get_pins i_pulpissimo/soc_domain_i/pulp_soc_i/i_dmi_jtag/i_dmi_cdc/i_cdc_resp/i_dst/data_dst_q_reg*/D] 20.000 -set_max_delay -datapath_only -from [get_pins i_pulpissimo/soc_domain_i/pulp_soc_i/i_dmi_jtag/i_dmi_cdc/i_cdc_resp/i_src/req_src_q_reg/C] -to [get_pins i_pulpissimo/soc_domain_i/pulp_soc_i/i_dmi_jtag/i_dmi_cdc/i_cdc_resp/i_dst/req_dst_q_reg/D] 20.000 -set_max_delay -datapath_only -from [get_pins i_pulpissimo/soc_domain_i/pulp_soc_i/i_dmi_jtag/i_dmi_cdc/i_cdc_req/i_dst/ack_dst_q_reg/C] -to [get_pins i_pulpissimo/soc_domain_i/pulp_soc_i/i_dmi_jtag/i_dmi_cdc/i_cdc_req/i_src/ack_src_q_reg/D] 20.000 - - -# reset signal -set_false_path -from [get_ports pad_reset_n] - -# Set ASYNC_REG attribute for ff synchronizers to place them closer together and -# increase MTBF -set_property ASYNC_REG true [get_cells i_pulpissimo/soc_domain_i/pulp_soc_i/soc_peripherals_i/apb_adv_timer_i/u_tim0/u_in_stage/r_ls_clk_sync_reg*] -set_property ASYNC_REG true [get_cells i_pulpissimo/soc_domain_i/pulp_soc_i/soc_peripherals_i/apb_adv_timer_i/u_tim1/u_in_stage/r_ls_clk_sync_reg*] -set_property ASYNC_REG true [get_cells i_pulpissimo/soc_domain_i/pulp_soc_i/soc_peripherals_i/apb_adv_timer_i/u_tim2/u_in_stage/r_ls_clk_sync_reg*] -set_property ASYNC_REG true [get_cells i_pulpissimo/soc_domain_i/pulp_soc_i/soc_peripherals_i/apb_adv_timer_i/u_tim3/u_in_stage/r_ls_clk_sync_reg*] -set_property ASYNC_REG true [get_cells i_pulpissimo/soc_domain_i/pulp_soc_i/soc_peripherals_i/i_apb_timer_unit/s_ref_clk*] -set_property ASYNC_REG true [get_cells i_pulpissimo/soc_domain_i/pulp_soc_i/soc_peripherals_i/i_ref_clk_sync/i_pulp_sync/r_reg_reg*] -set_property ASYNC_REG true [get_cells i_pulpissimo/soc_domain_i/pulp_soc_i/soc_peripherals_i/u_evnt_gen/r_ls_sync_reg*] - -# Create asynchronous clock group between slow-clk and SoC clock. Those clocks -# are considered asynchronously and proper synchronization regs are in place -set_clock_groups -asynchronous -group [get_clocks -of_objects [get_pins i_pulpissimo/safe_domain_i/i_slow_clk_gen/i_slow_clk_mngr/inst/mmcm_adv_inst/CLKOUT0]] -group [get_clocks -of_objects [get_pins i_pulpissimo/soc_domain_i/pulp_soc_i/i_clk_rst_gen/i_fpga_clk_gen/i_clk_manager/inst/mmcm_adv_inst/CLKOUT0]] - - -############################################################# -# _____ ____ _____ _ _ _ # -# |_ _/ __ \ / ____| | | | | (_) # -# | || | | |_____| (___ ___| |_| |_ _ _ __ __ _ ___ # -# | || | | |______\___ \ / _ \ __| __| | '_ \ / _` / __| # -# _| || |__| | ____) | __/ |_| |_| | | | | (_| \__ \ # -# |_____\____/ |_____/ \___|\__|\__|_|_| |_|\__, |___/ # -# __/ | # -# |___/ # -############################################################# - -## Sys clock -set_property -dict {PACKAGE_PIN AD11 IOSTANDARD LVDS} [get_ports ref_clk_n] -set_property -dict {PACKAGE_PIN AD12 IOSTANDARD LVDS} [get_ports ref_clk_p] - - -## Buttons -set_property -dict {PACKAGE_PIN R19 IOSTANDARD LVCMOS33} [get_ports pad_reset_n] -set_property -dict {PACKAGE_PIN E18 IOSTANDARD LVCMOS12} [get_ports btnc_i] -set_property -dict {PACKAGE_PIN M19 IOSTANDARD LVCMOS12} [get_ports btnd_i] -set_property -dict {PACKAGE_PIN M20 IOSTANDARD LVCMOS12} [get_ports btnl_i] -set_property -dict {PACKAGE_PIN C19 IOSTANDARD LVCMOS12} [get_ports btnr_i] -set_property -dict {PACKAGE_PIN B19 IOSTANDARD LVCMOS12} [get_ports btnu_i] - -## To use FTDI FT2232 JTAG -set_property -dict {PACKAGE_PIN Y29 IOSTANDARD LVCMOS33} [get_ports pad_jtag_trst] -set_property -dict {PACKAGE_PIN AD27 IOSTANDARD LVCMOS33} [get_ports pad_jtag_tck] -set_property -dict {PACKAGE_PIN W27 IOSTANDARD LVCMOS33} [get_ports pad_jtag_tdi] -set_property -dict {PACKAGE_PIN W28 IOSTANDARD LVCMOS33} [get_ports pad_jtag_tdo] -set_property -dict {PACKAGE_PIN W29 IOSTANDARD LVCMOS33} [get_ports pad_jtag_tms] - -## UART -set_property -dict {PACKAGE_PIN Y23 IOSTANDARD LVCMOS33} [get_ports pad_uart_tx] -set_property -dict {PACKAGE_PIN Y20 IOSTANDARD LVCMOS33} [get_ports pad_uart_rx] - -## LEDs -set_property -dict {PACKAGE_PIN T28 IOSTANDARD LVCMOS33} [get_ports led0_o] -set_property -dict {PACKAGE_PIN V19 IOSTANDARD LVCMOS33} [get_ports led1_o] -set_property -dict {PACKAGE_PIN U30 IOSTANDARD LVCMOS33} [get_ports led2_o] -set_property -dict {PACKAGE_PIN U29 IOSTANDARD LVCMOS33} [get_ports led3_o] -#set_property -dict {PACKAGE_PIN V20 IOSTANDARD LVCMOS33} [get_ports ] -#set_property -dict {PACKAGE_PIN V26 IOSTANDARD LVCMOS33} [get_ports ] -#set_property -dict {PACKAGE_PIN W24 IOSTANDARD LVCMOS33} [get_ports ] -#set_property -dict {PACKAGE_PIN W23 IOSTANDARD LVCMOS33} [get_ports ] - -## Switches -set_property -dict {PACKAGE_PIN G19 IOSTANDARD LVCMOS12} [get_ports switch0_i] -set_property -dict {PACKAGE_PIN G25 IOSTANDARD LVCMOS12} [get_ports switch1_i] -#set_property -dict {PACKAGE_PIN H24 IOSTANDARD LVCMOS12} [get_ports {}] -# set_property -dict {PACKAGE_PIN K19 IOSTANDARD LVCMOS12} [get_ports {}] -# set_property -dict {PACKAGE_PIN N19 IOSTANDARD LVCMOS12} [get_ports {}] -# set_property -dict {PACKAGE_PIN P19 IOSTANDARD LVCMOS12} [get_ports {}] -# set_property -dict {PACKAGE_PIN P26 IOSTANDARD LVCMOS33} [get_ports {}] -# set_property -dict {PACKAGE_PIN P27 IOSTANDARD LVCMOS33} [get_ports {}] - -## I2C Bus -set_property -dict {PACKAGE_PIN AE30 IOSTANDARD LVCMOS33} [get_ports pad_i2c0_scl] -set_property -dict {PACKAGE_PIN AF30 IOSTANDARD LVCMOS33} [get_ports pad_i2c0_sda] - -## QSPI Flash -set_property -dict {PACKAGE_PIN U19 IOSTANDARD LVCMOS33} [get_ports pad_spim_csn0] -#set_property -dict { PACKAGE_PIN P24 IOSTANDARD LVCMOS33 } [get_ports { pad_spim_sdio0 }]; #IO_L1P_T0_D00_MOSI_14 Sch=qspi_d[0] -set_property -dict {PACKAGE_PIN R25 IOSTANDARD LVCMOS33} [get_ports pad_spim_sdio1] -set_property -dict {PACKAGE_PIN R20 IOSTANDARD LVCMOS33} [get_ports pad_spim_sdio2] -set_property -dict {PACKAGE_PIN R21 IOSTANDARD LVCMOS33} [get_ports pad_spim_sdio3] - - -## OLED Display -set_property -dict {PACKAGE_PIN AC17 IOSTANDARD LVCMOS18} [get_ports oled_dc_o] -set_property -dict {PACKAGE_PIN AB17 IOSTANDARD LVCMOS18} [get_ports oled_rst_o] -set_property -dict {PACKAGE_PIN AF17 IOSTANDARD LVCMOS18} [get_ports oled_spim_sck_o] -set_property -dict {PACKAGE_PIN Y15 IOSTANDARD LVCMOS18} [get_ports oled_spim_mosi_o] -set_property -dict {PACKAGE_PIN AB22 IOSTANDARD LVCMOS33} [get_ports oled_vbat_o] -set_property -dict {PACKAGE_PIN AG17 IOSTANDARD LVCMOS18} [get_ports oled_vdd_o] - - -############################################# -## SD Card -############################################# -#set_property -dict { PACKAGE_PIN P28 IOSTANDARD LVCMOS33 } [get_ports { sd_cd }]; #IO_L8N_T1_D12_14 Sch=sd_cd -set_property -dict {PACKAGE_PIN R29 IOSTANDARD LVCMOS33} [get_ports pad_sdio_cmd] -set_property -dict {PACKAGE_PIN R26 IOSTANDARD LVCMOS33} [get_ports pad_sdio_data0] -set_property -dict {PACKAGE_PIN R30 IOSTANDARD LVCMOS33} [get_ports pad_sdio_data1] -set_property -dict {PACKAGE_PIN P29 IOSTANDARD LVCMOS33} [get_ports pad_sdio_data2] -set_property -dict {PACKAGE_PIN T30 IOSTANDARD LVCMOS33} [get_ports pad_sdio_data3] -set_property -dict {PACKAGE_PIN AE24 IOSTANDARD LVCMOS33} [get_ports sdio_reset_o] -set_property -dict {PACKAGE_PIN R28 IOSTANDARD LVCMOS33} [get_ports pad_sdio_clk] - - - -# set_property -dict {PACKAGE_PIN R28 IOSTANDARD LVCMOS33} [get_ports spi_clk_o] -# set_property -dict {PACKAGE_PIN T30 IOSTANDARD LVCMOS33} [get_ports spi_ss] -# set_property -dict {PACKAGE_PIN R26 IOSTANDARD LVCMOS33} [get_ports spi_miso] -# set_property -dict {PACKAGE_PIN R29 IOSTANDARD LVCMOS33} [get_ports spi_mosi] -# set_property -dict { PACKAGE_PIN P28 IOSTANDARD LVCMOS33 } [get_ports { sd_cd }]; #IO_L8N_T1_D12_14 Sch=sd_cd -# set_property -dict { PACKAGE_PIN R29 IOSTANDARD LVCMOS33 } [get_ports { sd_cmd }]; #IO_L7N_T1_D10_14 Sch=sd_cmd -# set_property -dict { PACKAGE_PIN R26 IOSTANDARD LVCMOS33 } [get_ports { sd_dat[0] }]; #IO_L10N_T1_D15_14 Sch=sd_dat[0] -# set_property -dict { PACKAGE_PIN R30 IOSTANDARD LVCMOS33 } [get_ports { sd_dat[1] }]; #IO_L9P_T1_DQS_14 Sch=sd_dat[1] -# set_property -dict { PACKAGE_PIN P29 IOSTANDARD LVCMOS33 } [get_ports { sd_dat[2] }]; #IO_L7P_T1_D09_14 Sch=sd_dat[2] -# set_property -dict { PACKAGE_PIN T30 IOSTANDARD LVCMOS33 } [get_ports { sd_dat[3] }]; #IO_L9N_T1_DQS_D13_14 Sch=sd_dat[3] -# set_property -dict { PACKAGE_PIN AE24 IOSTANDARD LVCMOS33 } [get_ports { sd_reset }]; #IO_L12N_T1_MRCC_12 Sch=sd_reset -# set_property -dict { PACKAGE_PIN R28 IOSTANDARD LVCMOS33 } [get_ports { sd_clk }]; #IO_L11P_T1_SRCC_14 Sch=sd_sclk - -# create_generated_clock -name sd_fast_clk -source [get_pins clk_mmcm/sd_sys_clk] -divide_by 2 [get_pins chipset_impl/piton_sd_top/sdc_controller/clock_divider0/fast_clk_reg/Q] -# create_generated_clock -name sd_slow_clk -source [get_pins clk_mmcm/sd_sys_clk] -divide_by 200 [get_pins chipset_impl/piton_sd_top/sdc_controller/clock_divider0/slow_clk_reg/Q] -# create_generated_clock -name sd_clk_out -source [get_pins sd_clk_oddr/C] -divide_by 1 -add -master_clock sd_fast_clk [get_ports sd_clk_out] -# create_generated_clock -name sd_clk_out_1 -source [get_pins sd_clk_oddr/C] -divide_by 1 -add -master_clock sd_slow_clk [get_ports sd_clk_out] - -# create_clock -period 40.000 -name VIRTUAL_sd_fast_clk -waveform {0.000 20.000} -# create_clock -period 4000.000 -name VIRTUAL_sd_slow_clk -waveform {0.000 2000.000} - -# set_output_delay -clock [get_clocks sd_clk_out] -min -add_delay 5.000 [get_ports {sd_dat[*]}] -# set_output_delay -clock [get_clocks sd_clk_out] -max -add_delay 15.000 [get_ports {sd_dat[*]}] -# set_output_delay -clock [get_clocks sd_clk_out_1] -min -add_delay 5.000 [get_ports {sd_dat[*]}] -# set_output_delay -clock [get_clocks sd_clk_out_1] -max -add_delay 1500.000 [get_ports {sd_dat[*]}] -# set_output_delay -clock [get_clocks sd_clk_out] -min -add_delay 5.000 [get_ports sd_cmd] -# set_output_delay -clock [get_clocks sd_clk_out] -max -add_delay 15.000 [get_ports sd_cmd] -# set_output_delay -clock [get_clocks sd_clk_out_1] -min -add_delay 5.000 [get_ports sd_cmd] -# set_output_delay -clock [get_clocks sd_clk_out_1] -max -add_delay 1500.000 [get_ports sd_cmd] -# set_input_delay -clock [get_clocks VIRTUAL_sd_fast_clk] -min -add_delay 20.000 [get_ports {sd_dat[*]}] -# set_input_delay -clock [get_clocks VIRTUAL_sd_fast_clk] -max -add_delay 35.000 [get_ports {sd_dat[*]}] -# set_input_delay -clock [get_clocks VIRTUAL_sd_slow_clk] -min -add_delay 2000.000 [get_ports {sd_dat[*]}] -# set_input_delay -clock [get_clocks VIRTUAL_sd_slow_clk] -max -add_delay 3500.000 [get_ports {sd_dat[*]}] -# set_input_delay -clock [get_clocks VIRTUAL_sd_fast_clk] -min -add_delay 20.000 [get_ports sd_cmd] -# set_input_delay -clock [get_clocks VIRTUAL_sd_fast_clk] -max -add_delay 35.000 [get_ports sd_cmd] -# set_input_delay -clock [get_clocks VIRTUAL_sd_slow_clk] -min -add_delay 2000.000 [get_ports sd_cmd] -# set_input_delay -clock [get_clocks VIRTUAL_sd_slow_clk] -max -add_delay 3500.000 [get_ports sd_cmd] -# set_clock_groups -physically_exclusive -group [get_clocks -include_generated_clocks sd_clk_out] -group [get_clocks -include_generated_clocks sd_clk_out_1] -# set_clock_groups -logically_exclusive -group [get_clocks -include_generated_clocks {VIRTUAL_sd_fast_clk sd_fast_clk}] -group [get_clocks -include_generated_clocks {sd_slow_clk VIRTUAL_sd_slow_clk}] -# set_clock_groups -asynchronous -group [get_clocks [list [get_clocks -of_objects [get_pins clk_mmcm/chipset_clk]]]] -group [get_clocks -filter { NAME =~ "*sd*" }] - -## PMOD Header JD -#set_property -dict {PACKAGE_PIN V27 IOSTANDARD LVCMOS33} [get_ports { jd[0]}] -#set_property -dict {PACKAGE_PIN Y30 IOSTANDARD LVCMOS33} [get_ports { jd[1]}] -#set_property -dict { PACKAGE_PIN V24 IOSTANDARD LVCMOS33 } [get_ports { jd[2] }]; #IO_L23N_T3_A02_D18_14 Sch=jd[3] -#set_property -dict { PACKAGE_PIN W22 IOSTANDARD LVCMOS33 } [get_ports { jd[3] }]; #IO_L24N_T3_A00_D16_14 Sch=jd[4] -#set_property -dict { PACKAGE_PIN U24 IOSTANDARD LVCMOS33 } [get_ports { jd[4] }]; #IO_L23P_T3_A03_D19_14 Sch=jd[7] -#set_property -dict { PACKAGE_PIN Y26 IOSTANDARD LVCMOS33 } [get_ports { jd[5] }]; #IO_L1P_T0_13 Sch=jd[8] -#set_property -dict { PACKAGE_PIN V22 IOSTANDARD LVCMOS33 } [get_ports { jd[6] }]; #IO_L22N_T3_A04_D20_14 Sch=jd[9] -#set_property -dict { PACKAGE_PIN W21 IOSTANDARD LVCMOS33 } [get_ports { jd[7] }]; #IO_L24P_T3_A01_D17_14 Sch=jd[10]## PMOD Header JD -#set_property -dict { PACKAGE_PIN V27 IOSTANDARD LVCMOS33 } [get_ports { jd[0] }]; #IO_L16N_T2_A15_D31_14 Sch=jd[1] -#set_property -dict { PACKAGE_PIN Y30 IOSTANDARD LVCMOS33 } [get_ports { jd[1] }]; #IO_L8P_T1_13 Sch=jd[2] -#set_property -dict { PACKAGE_PIN V24 IOSTANDARD LVCMOS33 } [get_ports { jd[2] }]; #IO_L23N_T3_A02_D18_14 Sch=jd[3] -#set_property -dict { PACKAGE_PIN W22 IOSTANDARD LVCMOS33 } [get_ports { jd[3] }]; #IO_L24N_T3_A00_D16_14 Sch=jd[4] -#set_property -dict { PACKAGE_PIN U24 IOSTANDARD LVCMOS33 } [get_ports { jd[4] }]; #IO_L23P_T3_A03_D19_14 Sch=jd[7] -#set_property -dict { PACKAGE_PIN Y26 IOSTANDARD LVCMOS33 } [get_ports { jd[5] }]; #IO_L1P_T0_13 Sch=jd[8] -#set_property -dict { PACKAGE_PIN V22 IOSTANDARD LVCMOS33 } [get_ports { jd[6] }]; #IO_L22N_T3_A04_D20_14 Sch=jd[9] -#set_property -dict { PACKAGE_PIN W21 IOSTANDARD LVCMOS33 } [get_ports { jd[7] }]; #IO_L24P_T3_A01_D17_14 Sch=jd[10] - - -# Genesys 2 has a quad SPI flash -set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design] - diff --git a/fpga/pulpissimo-genesys2/elf_run.gdb b/fpga/pulpissimo-genesys2/elf_run.gdb deleted file mode 100644 index cba53bd0..00000000 --- a/fpga/pulpissimo-genesys2/elf_run.gdb +++ /dev/null @@ -1,4 +0,0 @@ -target remote localhost:3333 -monitor reset halt -load -continue \ No newline at end of file diff --git a/fpga/pulpissimo-genesys2/elf_run.sh b/fpga/pulpissimo-genesys2/elf_run.sh deleted file mode 100755 index 06f2f60d..00000000 --- a/fpga/pulpissimo-genesys2/elf_run.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -trap "exit" INT TERM -trap "kill 0" EXIT - - -SCRIPTDIR=$(dirname $0) -UART_TTY=${PULP_GENESYS2_UART_TTY:=/dev/ttyUSB0} -UART_BAUDRATE=${PULP_GENESYS2_UART_BAUDRATE:=115200} - -#Execute gdb and connect to openocd via pipe -$OPENOCD/bin/openocd -f $SCRIPTDIR/openocd-genesys2.cfg & -$PULP_RISCV_GCC_TOOLCHAIN_CI/bin/riscv32-unknown-elf-gdb -x $SCRIPTDIR/elf_run.gdb $1 & -sleep 3 -minicom -D $UART_TTY -b $UART_BAUDRATE - - diff --git a/fpga/pulpissimo-genesys2/fpga-settings.mk b/fpga/pulpissimo-genesys2/fpga-settings.mk deleted file mode 100644 index 6d6495bb..00000000 --- a/fpga/pulpissimo-genesys2/fpga-settings.mk +++ /dev/null @@ -1,12 +0,0 @@ -export BOARD=genesys2 -export XILINX_PART=xc7k325tffg900-2 -export XILINX_BOARD=digilentinc.com:genesys2:part0:1.1 -export FC_CLK_PERIOD_NS=50 -export PER_CLK_PERIOD_NS=100 -export SLOW_CLK_PERIOD_NS=30517 -#Must also change the localparam 'L2_BANK_SIZE' in pulp_soc.sv accordingly -export INTERLEAVED_BANK_SIZE=28672 -#Must also change the localparam 'L2_BANK_SIZE_PRI' in pulp_soc.sv accordingly -export PRIVATE_BANK_SIZE=8192 -$(info Setting environment variables for $(BOARD) board) - diff --git a/fpga/pulpissimo-genesys2/ips/xilinx_clk_mngr/.gitignore b/fpga/pulpissimo-genesys2/ips/xilinx_clk_mngr/.gitignore deleted file mode 100644 index 5099fe9c..00000000 --- a/fpga/pulpissimo-genesys2/ips/xilinx_clk_mngr/.gitignore +++ /dev/null @@ -1,21 +0,0 @@ -#Ignore vivado project files generated by the tcl script -**/.Xil/* -**/reports/* -**/*.cache/* -**/*.hw/* -**/*.ip_user_files/* -**/*.runs/* -**/*.sim/* -**/*.srcs/* -*.edf -*.xpr -*.jou -*.log - -.cxl.* - -*ip - -*_stub.v -gmon.out - diff --git a/fpga/pulpissimo-genesys2/ips/xilinx_clk_mngr/Makefile b/fpga/pulpissimo-genesys2/ips/xilinx_clk_mngr/Makefile deleted file mode 100644 index 978b9cee..00000000 --- a/fpga/pulpissimo-genesys2/ips/xilinx_clk_mngr/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -PROJECT:=xilinx_clk_mngr -VIVADO ?= vivado -VIVADOFLAGS ?= -nojournal -mode batch -source scripts/prologue.tcl -MODE=batch - -include ../../fpga-settings.mk - -.DEFAULT_GOAL:=help - -.PHONY: help all gui clean - -all: MODE=batch ## Create and synthesize the IP in batch mode. - -gui: MODE=gui ## Create and synthesize the IP in GUI mode. - -all gui: $(PROJECT).xpr - -$(PROJECT).xpr: ../../fpga-settings.mk tcl/run.tcl - make clean - $(VIVADO) -mode $(MODE) -source tcl/run.tcl - mkdir -p ip - cp -r ${PROJECT}.srcs/sources_1/ip/${PROJECT}/* ip/. - cp ${PROJECT}.runs/${PROJECT}_synth_1/${PROJECT}.dcp ip/. - -clean: ## Remove all build products - rm -rf ip/* - mkdir -p ip - rm -rf ${PROJECT}.* - rm -rf component.xml - rm -rf vivado*.jou - rm -rf vivado*.log - rm -rf vivado*.str - rm -rf xgui - rm -rf .Xil - -help: ## Shows this help message - @grep -E -h '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' diff --git a/fpga/pulpissimo-genesys2/ips/xilinx_clk_mngr/tcl/run.tcl b/fpga/pulpissimo-genesys2/ips/xilinx_clk_mngr/tcl/run.tcl deleted file mode 100644 index 0ae49ff0..00000000 --- a/fpga/pulpissimo-genesys2/ips/xilinx_clk_mngr/tcl/run.tcl +++ /dev/null @@ -1,49 +0,0 @@ -set partNumber $::env(XILINX_PART) - -if [info exists ::env(BOARD)] { - set BOARD $::env(BOARD) -} else { - error "BOARD is not defined. Please source the sourceme.sh file." - exit -} -if [info exists ::env(XILINX_BOARD)] { - set boardName $::env(XILINX_BOARD) -} - -# detect target clock -if [info exists ::env(FC_CLK_PERIOD_NS)] { - set FC_CLK_PERIOD_NS $::env(FC_CLK_PERIOD_NS) -} else { - set FC_CLK_PERIOD_NS 10.000 -} -if [info exists ::env(PER_CLK_PERIOD_NS)] { - set PER_CLK_PERIOD_NS $::env(PER_CLK_PERIOD_NS) -} else { - set PER_CLK_PERIOD_NS 20.000 -} - - -set FC_CLK_FREQ_MHZ [expr 1000 / $FC_CLK_PERIOD_NS] -set PER_CLK_FREQ_MHZ [expr 1000 / $PER_CLK_PERIOD_NS] - -set ipName xilinx_clk_mngr - -create_project $ipName . -part $partNumber -set_property board_part $boardName [current_project] - -create_ip -name clk_wiz -vendor xilinx.com -library ip -module_name $ipName - -set_property -dict [eval list CONFIG.PRIM_IN_FREQ {200.000} \ - CONFIG.NUM_OUT_CLKS {2} \ - CONFIG.CLKOUT2_USED {true} \ - CONFIG.RESET_TYPE {ACTIVE_LOW} \ - CONFIG.RESET_PORT {resetn} \ - CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {$FC_CLK_FREQ_MHZ} \ - CONFIG.CLKOUT2_REQUESTED_OUT_FREQ {$PER_CLK_FREQ_MHZ} \ - CONFIG.CLKIN1_JITTER_PS {50.0} \ - ] [get_ips $ipName] - -generate_target all [get_files ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] -create_ip_run [get_files -of_objects [get_fileset sources_1] ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] -launch_run -jobs 8 ${ipName}_synth_1 -wait_on_run ${ipName}_synth_1 diff --git a/fpga/pulpissimo-genesys2/ips/xilinx_interleaved_ram/.gitignore b/fpga/pulpissimo-genesys2/ips/xilinx_interleaved_ram/.gitignore deleted file mode 100644 index 5099fe9c..00000000 --- a/fpga/pulpissimo-genesys2/ips/xilinx_interleaved_ram/.gitignore +++ /dev/null @@ -1,21 +0,0 @@ -#Ignore vivado project files generated by the tcl script -**/.Xil/* -**/reports/* -**/*.cache/* -**/*.hw/* -**/*.ip_user_files/* -**/*.runs/* -**/*.sim/* -**/*.srcs/* -*.edf -*.xpr -*.jou -*.log - -.cxl.* - -*ip - -*_stub.v -gmon.out - diff --git a/fpga/pulpissimo-genesys2/ips/xilinx_interleaved_ram/Makefile b/fpga/pulpissimo-genesys2/ips/xilinx_interleaved_ram/Makefile deleted file mode 100644 index 08752831..00000000 --- a/fpga/pulpissimo-genesys2/ips/xilinx_interleaved_ram/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -PROJECT:=xilinx_interleaved_ram -VIVADO ?= vivado -VIVADOFLAGS ?= -nojournal -mode batch -source scripts/prologue.tcl -MODE=batch - -include ../../fpga-settings.mk - -.DEFAULT_GOAL:=help - -.PHONY: help all gui clean - -all: MODE=batch ## Create and synthesize the IP in batch mode. - -gui: MODE=gui ## Create and synthesize the IP in GUI mode. - -all gui: $(PROJECT).xpr - -$(PROJECT).xpr: ../../fpga-settings.mk tcl/run.tcl - make clean - $(VIVADO) -mode $(MODE) -source tcl/run.tcl - mkdir -p ip - cp -r ${PROJECT}.srcs/sources_1/ip/${PROJECT}/* ip/. - cp ${PROJECT}.runs/${PROJECT}_synth_1/${PROJECT}.dcp ip/. - -clean: ## Remove all build products - rm -rf ip/* - mkdir -p ip - rm -rf ${PROJECT}.* - rm -rf component.xml - rm -rf vivado*.jou - rm -rf vivado*.log - rm -rf vivado*.str - rm -rf xgui - rm -rf .Xil - -help: ## Shows this help message - @grep -E -h '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' diff --git a/fpga/pulpissimo-genesys2/ips/xilinx_interleaved_ram/tcl/run.tcl b/fpga/pulpissimo-genesys2/ips/xilinx_interleaved_ram/tcl/run.tcl deleted file mode 100644 index a2e84f23..00000000 --- a/fpga/pulpissimo-genesys2/ips/xilinx_interleaved_ram/tcl/run.tcl +++ /dev/null @@ -1,38 +0,0 @@ -set partNumber $::env(XILINX_PART) - -if [info exists ::env(BOARD)] { - set BOARD $::env(BOARD) -} else { - error "BOARD is not defined. Please source the sourceme.sh file." - exit -} -if [info exists ::env(XILINX_BOARD)] { - set boardName $::env(XILINX_BOARD) -} - -# detect target ram size -if [info exists ::env(INTERLEAVED_BANK_SIZE)] { - set INTERLEAVED_BANK_SIZE $::env(INTERLEAVED_BANK_SIZE) -} else { - set INTERLEAVED_BANK_SIZE 4096 -} - -set ipName xilinx_interleaved_ram - -create_project $ipName . -part $partNumber -set_property board_part $boardName [current_project] - -create_ip -name blk_mem_gen -vendor xilinx.com -library ip -module_name $ipName - -set_property -dict [eval list CONFIG.Use_Byte_Write_Enable {true} \ - CONFIG.Byte_Size {8} \ - CONFIG.Write_Width_A {32} \ - CONFIG.Write_Depth_A {$INTERLEAVED_BANK_SIZE} \ - CONFIG.Read_Width_A {32} \ - CONFIG.Register_PortA_Output_of_Memory_Primitives {false} \ - ] [get_ips $ipName] - -generate_target all [get_files ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] -create_ip_run [get_files -of_objects [get_fileset sources_1] ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] -launch_run -jobs 8 ${ipName}_synth_1 -wait_on_run ${ipName}_synth_1 diff --git a/fpga/pulpissimo-genesys2/ips/xilinx_private_ram/.gitignore b/fpga/pulpissimo-genesys2/ips/xilinx_private_ram/.gitignore deleted file mode 100644 index 5099fe9c..00000000 --- a/fpga/pulpissimo-genesys2/ips/xilinx_private_ram/.gitignore +++ /dev/null @@ -1,21 +0,0 @@ -#Ignore vivado project files generated by the tcl script -**/.Xil/* -**/reports/* -**/*.cache/* -**/*.hw/* -**/*.ip_user_files/* -**/*.runs/* -**/*.sim/* -**/*.srcs/* -*.edf -*.xpr -*.jou -*.log - -.cxl.* - -*ip - -*_stub.v -gmon.out - diff --git a/fpga/pulpissimo-genesys2/ips/xilinx_private_ram/Makefile b/fpga/pulpissimo-genesys2/ips/xilinx_private_ram/Makefile deleted file mode 100644 index 4734e7ad..00000000 --- a/fpga/pulpissimo-genesys2/ips/xilinx_private_ram/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -PROJECT:=xilinx_private_ram -VIVADO ?= vivado -VIVADOFLAGS ?= -nojournal -mode batch -source scripts/prologue.tcl -MODE=batch - -include ../../fpga-settings.mk - -.DEFAULT_GOAL:=help - -.PHONY: help all gui clean - -all: MODE=batch ## Create and synthesize the IP in batch mode. - -gui: MODE=gui ## Create and synthesize the IP in GUI mode. - -all gui: $(PROJECT).xpr - -$(PROJECT).xpr: ../../fpga-settings.mk tcl/run.tcl - make clean - $(VIVADO) -mode $(MODE) -source tcl/run.tcl - mkdir -p ip - cp -r ${PROJECT}.srcs/sources_1/ip/${PROJECT}/* ip/. - cp ${PROJECT}.runs/${PROJECT}_synth_1/${PROJECT}.dcp ip/. - -clean: ## Remove all build products - rm -rf ip/* - mkdir -p ip - rm -rf ${PROJECT}.* - rm -rf component.xml - rm -rf vivado*.jou - rm -rf vivado*.log - rm -rf vivado*.str - rm -rf xgui - rm -rf .Xil - -help: ## Shows this help message - @grep -E -h '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' diff --git a/fpga/pulpissimo-genesys2/ips/xilinx_private_ram/tcl/run.tcl b/fpga/pulpissimo-genesys2/ips/xilinx_private_ram/tcl/run.tcl deleted file mode 100644 index 78493b37..00000000 --- a/fpga/pulpissimo-genesys2/ips/xilinx_private_ram/tcl/run.tcl +++ /dev/null @@ -1,38 +0,0 @@ -set partNumber $::env(XILINX_PART) - -if [info exists ::env(BOARD)] { - set BOARD $::env(BOARD) -} else { - error "BOARD is not defined. Please source the sourceme.sh file." - exit -} -if [info exists ::env(XILINX_BOARD)] { - set boardName $::env(XILINX_BOARD) -} - -# detect target ram size -if [info exists ::env(PRIVATE_BANK_SIZE)] { - set PRIVATE_BANK_SIZE $::env(PRIVATE_BANK_SIZE) -} else { - set PRIVATE_BANK_SIZE 4096 -} - -set ipName xilinx_private_ram - -create_project $ipName . -part $partNumber -set_property board_part $boardName [current_project] - -create_ip -name blk_mem_gen -vendor xilinx.com -library ip -module_name $ipName - -set_property -dict [eval list CONFIG.Use_Byte_Write_Enable {true} \ - CONFIG.Byte_Size {8} \ - CONFIG.Write_Width_A {32} \ - CONFIG.Write_Depth_A {$PRIVATE_BANK_SIZE} \ - CONFIG.Read_Width_A {32} \ - CONFIG.Register_PortA_Output_of_Memory_Primitives {false} \ - ] [get_ips $ipName] - -generate_target all [get_files ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] -create_ip_run [get_files -of_objects [get_fileset sources_1] ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] -launch_run -jobs 8 ${ipName}_synth_1 -wait_on_run ${ipName}_synth_1 diff --git a/fpga/pulpissimo-genesys2/ips/xilinx_slow_clk_mngr/.gitignore b/fpga/pulpissimo-genesys2/ips/xilinx_slow_clk_mngr/.gitignore deleted file mode 100644 index 5099fe9c..00000000 --- a/fpga/pulpissimo-genesys2/ips/xilinx_slow_clk_mngr/.gitignore +++ /dev/null @@ -1,21 +0,0 @@ -#Ignore vivado project files generated by the tcl script -**/.Xil/* -**/reports/* -**/*.cache/* -**/*.hw/* -**/*.ip_user_files/* -**/*.runs/* -**/*.sim/* -**/*.srcs/* -*.edf -*.xpr -*.jou -*.log - -.cxl.* - -*ip - -*_stub.v -gmon.out - diff --git a/fpga/pulpissimo-genesys2/ips/xilinx_slow_clk_mngr/Makefile b/fpga/pulpissimo-genesys2/ips/xilinx_slow_clk_mngr/Makefile deleted file mode 100644 index e3ba47bf..00000000 --- a/fpga/pulpissimo-genesys2/ips/xilinx_slow_clk_mngr/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -PROJECT:=xilinx_slow_clk_mngr -VIVADO ?= vivado -VIVADOFLAGS ?= -nojournal -mode batch -source scripts/prologue.tcl -MODE=batch - -include ../../fpga-settings.mk - -.DEFAULT_GOAL:=help - -.PHONY: help all gui clean - -all: MODE=batch ## Create and synthesize the IP in batch mode. - -gui: MODE=gui ## Create and synthesize the IP in GUI mode. - -all gui: $(PROJECT).xpr - -$(PROJECT).xpr: ../../fpga-settings.mk tcl/run.tcl - make clean - $(VIVADO) -mode $(MODE) -source tcl/run.tcl - mkdir -p ip - cp -r ${PROJECT}.srcs/sources_1/ip/${PROJECT}/* ip/. - cp ${PROJECT}.runs/${PROJECT}_synth_1/${PROJECT}.dcp ip/. - -clean: ## Remove all build products - rm -rf ip/* - mkdir -p ip - rm -rf ${PROJECT}.* - rm -rf component.xml - rm -rf vivado*.jou - rm -rf vivado*.log - rm -rf vivado*.str - rm -rf xgui - rm -rf .Xil - -help: ## Shows this help message - @grep -E -h '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' diff --git a/fpga/pulpissimo-genesys2/ips/xilinx_slow_clk_mngr/tcl/run.tcl b/fpga/pulpissimo-genesys2/ips/xilinx_slow_clk_mngr/tcl/run.tcl deleted file mode 100644 index a7cfbf0c..00000000 --- a/fpga/pulpissimo-genesys2/ips/xilinx_slow_clk_mngr/tcl/run.tcl +++ /dev/null @@ -1,45 +0,0 @@ -set partNumber $::env(XILINX_PART) - -if [info exists ::env(BOARD)] { - set BOARD $::env(BOARD) -} else { - error "BOARD is not defined. Please source the sourceme.sh file." - exit -} -if [info exists ::env(XILINX_BOARD)] { - set boardName $::env(XILINX_BOARD) -} - -# detect target clock -if [info exists ::env(SLOW_CLK_PERIOD_NS)] { - set SLOW_CLK_PERIOD_NS $::env(SLOW_CLK_PERIOD_NS) -} else { - set SLOW_CLK_PERIOD_NS 30517 -} - -# Multiply frequency by 250 as there is a clock divider (by 250) after the -# slow_clk_mngr since the MMCMs do not support clocks slower then 4.69 MHz. -set SLOW_CLK_FREQ_MHZ [expr 1000 * 256 / $SLOW_CLK_PERIOD_NS] - -set ipName xilinx_slow_clk_mngr - -create_project $ipName . -part $partNumber -set_property board_part $boardName [current_project] - -create_ip -name clk_wiz -vendor xilinx.com -library ip -module_name $ipName - -set_property -dict [eval list CONFIG.PRIM_IN_FREQ {200.000} \ - CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {$SLOW_CLK_FREQ_MHZ} \ - CONFIG.USE_SAFE_CLOCK_STARTUP {true} \ - CONFIG.USE_LOCKED {false} \ - CONFIG.RESET_TYPE {ACTIVE_LOW} \ - CONFIG.CLKIN1_JITTER_PS {50.0} \ - CONFIG.FEEDBACK_SOURCE {FDBK_AUTO} \ - CONFIG.RESET_PORT {resetn} \ - ] [get_ips $ipName] - - -generate_target all [get_files ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] -create_ip_run [get_files -of_objects [get_fileset sources_1] ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] -launch_run -jobs 8 ${ipName}_synth_1 -wait_on_run ${ipName}_synth_1 diff --git a/fpga/pulpissimo-genesys2/openocd-genesys2.cfg b/fpga/pulpissimo-genesys2/openocd-genesys2.cfg deleted file mode 100644 index b0de8583..00000000 --- a/fpga/pulpissimo-genesys2/openocd-genesys2.cfg +++ /dev/null @@ -1,46 +0,0 @@ -adapter_khz 1000 - -interface ftdi -ftdi_vid_pid 0x0403 0x6010 - -# Channel 1 is taken by Xilinx JTAG -ftdi_channel 0 - -# links: -# http://openocd.org/doc-release/html/Debug-Adapter-Configuration.html -# -# Bit MPSSE FT2232 JTAG Type Description -# Bit0 TCK ADBUS0 TCK Out Clock Signal Output -# Bit1 TDI ADBUS1 TDI Out Serial Data Out -# Bit2 TDO ADBUS2 TDO In Serial Data In -# Bit3 TMS ADBUS3 TMS Out Select Signal Out -# Bit4 GPIOL0 ADBUS4 nTRST In/Out General Purpose I/O -# this corresponds to the following in/out layout, with TMS initially set to 1 -ftdi_layout_init 0x0018 0x001b -# we only have to specify nTRST, the others are assigned correctly by default -ftdi_layout_signal nTRST -ndata 0x0010 - -set _CHIPNAME riscv - -jtag newtap $_CHIPNAME unknown0 -irlen 5 -expected-id 0x10102001 -jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x249511C3 - -set _TARGETNAME $_CHIPNAME.cpu -target create $_TARGETNAME riscv -chain-position $_TARGETNAME -coreid 0x3e0 - -gdb_report_data_abort enable -gdb_report_register_access_error enable - -riscv set_reset_timeout_sec 120 -riscv set_command_timeout_sec 120 - -# prefer to use sba for system bus access -riscv set_prefer_sba on - -# dump jtag chain -scan_chain - - -init -halt -echo "Ready for Remote Connections" diff --git a/fpga/pulpissimo-genesys2/rtl/fpga_bootrom.sv b/fpga/pulpissimo-genesys2/rtl/fpga_bootrom.sv deleted file mode 100644 index 79d78b3f..00000000 --- a/fpga/pulpissimo-genesys2/rtl/fpga_bootrom.sv +++ /dev/null @@ -1,36 +0,0 @@ -//----------------------------------------------------------------------------- -// Title : FPGA Bootrom for PULPissimo -//----------------------------------------------------------------------------- -// File : fpga_bootrom.sv -// Author : Manuel Eggimann -// Created : 29.05.2019 -//----------------------------------------------------------------------------- -// Description : -// Mockup bootrom that keeps returning jal x0,0 to trap the core in an infinite -// loop until the debug module takes over control. -//----------------------------------------------------------------------------- -// Copyright (C) 2013-2019 ETH Zurich, University of Bologna -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. -//----------------------------------------------------------------------------- - - -module fpga_bootrom - #( - parameter ADDR_WIDTH=32, - parameter DATA_WIDTH=32 - ) - ( - input logic CLK, - input logic CEN, - input logic [ADDR_WIDTH-1:0] A, - output logic [DATA_WIDTH-1:0] Q - ); - assign Q = 32'h0000006f; //jal x0,0 -endmodule : fpga_bootrom diff --git a/fpga/pulpissimo-genesys2/rtl/fpga_clk_gen.sv b/fpga/pulpissimo-genesys2/rtl/fpga_clk_gen.sv deleted file mode 100644 index 2ad9a8eb..00000000 --- a/fpga/pulpissimo-genesys2/rtl/fpga_clk_gen.sv +++ /dev/null @@ -1,74 +0,0 @@ -//----------------------------------------------------------------------------- -// Title : FPGA CLK Gen for PULPissimo -// ----------------------------------------------------------------------------- -// File : fpga_clk_gen.sv Author : Manuel Eggimann -// Created : 17.05.2019 -// ----------------------------------------------------------------------------- -// Description : Instantiates Xilinx clocking wizard IP to generate 2 output -// clocks. Currently, the clock is not dynamicly reconfigurable and all -// configuration requests are acknowledged without any effect. -// ----------------------------------------------------------------------------- -// Copyright (C) 2013-2019 ETH Zurich, University of Bologna Copyright and -// related rights are licensed under the Solderpad Hardware License, Version -// 0.51 (the "License"); you may not use this file except in compliance with the -// License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law or -// agreed to in writing, software, hardware and materials distributed under this -// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS -// OF ANY KIND, either express or implied. See the License for the specific -// language governing permissions and limitations under the License. -// ----------------------------------------------------------------------------- - - -module fpga_clk_gen ( - input logic ref_clk_i, - input logic rstn_glob_i, - input logic test_mode_i, - input logic shift_enable_i, - output logic soc_clk_o, - output logic per_clk_o, - output logic cluster_clk_o, - output logic soc_cfg_lock_o, - input logic soc_cfg_req_i, - output logic soc_cfg_ack_o, - input logic [1:0] soc_cfg_add_i, - input logic [31:0] soc_cfg_data_i, - output logic [31:0] soc_cfg_r_data_o, - input logic soc_cfg_wrn_i, - output logic per_cfg_lock_o, - input logic per_cfg_req_i, - output logic per_cfg_ack_o, - input logic [1:0] per_cfg_add_i, - input logic [31:0] per_cfg_data_i, - output logic [31:0] per_cfg_r_data_o, - input logic per_cfg_wrn_i, - output logic cluster_cfg_lock_o, - input logic cluster_cfg_req_i, - output logic cluster_cfg_ack_o, - input logic [1:0] cluster_cfg_add_i, - input logic [31:0] cluster_cfg_data_i, - output logic [31:0] cluster_cfg_r_data_o, - input logic cluster_cfg_wrn_i - ); - - logic s_locked; - - xilinx_clk_mngr i_clk_manager - ( - .resetn(rstn_glob_i), - .clk_in1(ref_clk_i), - .clk_out1(soc_clk_o), - .clk_out2(per_clk_o), - .locked(s_locked) - ); - - assign soc_cfg_lock_o = s_locked; - assign per_cfg_lock_o = s_locked; - - assign soc_cfg_ack_o = 1'b1; //Always acknowledge without doing anything for now - assign per_cfg_ack_o = 1'b1; - - assign soc_cfg_r_data_o = 32'hdeadda7a; - assign per_cfg_r_data_o = 32'hdeadda7a; - -endmodule : fpga_clk_gen diff --git a/fpga/pulpissimo-genesys2/rtl/fpga_interleaved_ram.sv b/fpga/pulpissimo-genesys2/rtl/fpga_interleaved_ram.sv deleted file mode 100644 index 7d52e5d8..00000000 --- a/fpga/pulpissimo-genesys2/rtl/fpga_interleaved_ram.sv +++ /dev/null @@ -1,57 +0,0 @@ -//----------------------------------------------------------------------------- -// Title : FPGA Interleaved RAM Bank for PULPissimo -// ----------------------------------------------------------------------------- -// File : fpga_interleaved_ram.sv Author : Manuel Eggimann -// Created : 20.05.2019 -// ----------------------------------------------------------------------------- -// Description : Instantiated block ram generator IP to replace the SRAM banks -// in the interleaved region of L2. Since Xilinx LogicoreIP are not customizable -// via parameters, the bank size selected in l2_ram_multibank must match the one -// used in the TCL script for IP generation. -// ----------------------------------------------------------------------------- -// Copyright (C) 2013-2019 ETH Zurich, University of Bologna Copyright and -// related rights are licensed under the Solderpad Hardware License, Version -// 0.51 (the "License"); you may not use this file except in compliance with the -// License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law or -// agreed to in writing, software, hardware and materials distributed under this -// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS -// OF ANY KIND, either express or implied. See the License for the specific -// language governing permissions and limitations under the License. -// ----------------------------------------------------------------------------- - -module fpga_interleaved_ram - #( - parameter ADDR_WIDTH=12 - ) ( - input logic clk_i, - input logic rst_ni, - input logic csn_i, - input logic wen_i, - input logic [3:0] be_i, - input logic [ADDR_WIDTH-1:0] addr_i, - input logic [31:0] wdata_i, - output logic [31:0] rdata_o - ); - - logic [3:0] wea; - - always_comb begin - if (wen_i == 1'b0) begin - wea = be_i; - end else begin - wea = '0; - end - end - - xilinx_interleaved_ram i_xilinx_interleaved_ram - ( - .clka(clk_i), - .ena(~csn_i), - .wea(wea), - .addra(addr_i), - .dina(wdata_i), - .douta(rdata_o) - ); - -endmodule : fpga_interleaved_ram diff --git a/fpga/pulpissimo-genesys2/rtl/fpga_private_ram.sv b/fpga/pulpissimo-genesys2/rtl/fpga_private_ram.sv deleted file mode 100644 index 05244931..00000000 --- a/fpga/pulpissimo-genesys2/rtl/fpga_private_ram.sv +++ /dev/null @@ -1,57 +0,0 @@ -//----------------------------------------------------------------------------- -// Title : FPGA Private RAM Bank for PULPissimo -// ----------------------------------------------------------------------------- -// File : fpga_private_ram.sv Author : Manuel Eggimann -// Created : 20.05.2019 -// ----------------------------------------------------------------------------- -// Description : Instantiated block ram generator IP to replace the SRAM banks -// in the private region of L2. Since Xilinx LogicoreIP are not customizable -// via parameters, the bank size selected in l2_ram_multibank must match the one -// used in the TCL script for IP generation. -// ----------------------------------------------------------------------------- -// Copyright (C) 2013-2019 ETH Zurich, University of Bologna Copyright and -// related rights are licensed under the Solderpad Hardware License, Version -// 0.51 (the "License"); you may not use this file except in compliance with the -// License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law or -// agreed to in writing, software, hardware and materials distributed under this -// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS -// OF ANY KIND, either express or implied. See the License for the specific -// language governing permissions and limitations under the License. -// ----------------------------------------------------------------------------- - -module fpga_private_ram - #( - parameter ADDR_WIDTH=12 - ) ( - input logic clk_i, - input logic rst_ni, - input logic csn_i, - input logic wen_i, - input logic [3:0] be_i, - input logic [ADDR_WIDTH-1:0] addr_i, - input logic [31:0] wdata_i, - output logic [31:0] rdata_o - ); - - logic [3:0] wea; - - always_comb begin - if (wen_i == 1'b0) begin - wea = be_i; - end else begin - wea = '0; - end - end - - xilinx_private_ram i_xilinx_private_ram - ( - .clka(clk_i), - .ena(~csn_i), - .wea(wea), - .addra(addr_i), - .dina(wdata_i), - .douta(rdata_o) - ); - -endmodule : fpga_private_ram diff --git a/fpga/pulpissimo-genesys2/rtl/fpga_slow_clk_gen.sv b/fpga/pulpissimo-genesys2/rtl/fpga_slow_clk_gen.sv deleted file mode 100644 index f3db58f4..00000000 --- a/fpga/pulpissimo-genesys2/rtl/fpga_slow_clk_gen.sv +++ /dev/null @@ -1,82 +0,0 @@ -//----------------------------------------------------------------------------- -// Title : FPGA slow clk generator for PULPissimo -//----------------------------------------------------------------------------- -// File : fpga_slow_clk_gen.sv -// Author : Manuel Eggimann -// Created : 20.05.2019 -//----------------------------------------------------------------------------- -// Description : Instantiates Xilinx Clocking Wizard IP to generate the slow_clk -// signal since for certain boards the available clock sources are to fast to -// use directly. -//----------------------------------------------------------------------------- -// Copyright (C) 2013-2019 ETH Zurich, University of Bologna -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. -//----------------------------------------------------------------------------- - - -module fpga_slow_clk_gen - #( - parameter CLK_DIV_VALUE = 256 //The xilinx_slow_clk_mngr is supposed to - //generate an 8.3886MHz clock. We need to divide it - //by 256 to arrive to a 32.768kHz clock - ) - (input logic ref_clk_i, - input logic rst_ni, - output logic slow_clk_o - ); - - - - localparam COUNTER_WIDTH = $clog2(CLK_DIV_VALUE); - - - //Create clock divider using BUFGCE cells as the PLL/MMCM cannot generate clocks - //slower than 4.69 MHz and we need 32.768kHz - - logic [COUNTER_WIDTH-1:0] clk_counter_d, clk_counter_q; - logic clock_gate_en; - - logic intermmediate_clock; - - xilinx_slow_clk_mngr i_slow_clk_mngr - ( - .resetn(rst_ni), - .clk_in1(ref_clk_i), - .clk_out1(intermmediate_clock) - ); - - - - always_comb begin - if (clk_counter_q == CLK_DIV_VALUE-1) begin - clk_counter_d = '0; - clock_gate_en = 1'b1; - end else begin - clk_counter_d = clk_counter_q + 1; - clock_gate_en = 1'b0; - end - end - - always_ff @(posedge intermmediate_clock, negedge rst_ni) begin - if (!rst_ni) begin - clk_counter_q <= '0; - end else begin - clk_counter_q <= clk_counter_d; - end - end - - BUFGCE i_clock_gate - ( - .I(intermmediate_clock), - .CE(clock_gate_en), - .O(slow_clk_o) - ); - -endmodule : fpga_slow_clk_gen diff --git a/fpga/pulpissimo-genesys2/rtl/pad_functional_xilinx.sv b/fpga/pulpissimo-genesys2/rtl/pad_functional_xilinx.sv deleted file mode 100644 index a3ca1cde..00000000 --- a/fpga/pulpissimo-genesys2/rtl/pad_functional_xilinx.sv +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2018 ETH Zurich and University of Bologna. -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - - -module pad_functional_pd -( - input logic OEN, - input logic I, - output logic O, - input logic PEN, - inout logic PAD -); - - (* PULLDOWN = "YES" *) - IOBUF iobuf_i ( - .T ( OEN ), - .I ( I ), - .O ( O ), - .IO( PAD ) - ); - -endmodule - -module pad_functional_pu -( - input logic OEN, - input logic I, - output logic O, - input logic PEN, - inout logic PAD -); - - (* PULLUP = "YES" *) - IOBUF iobuf_i ( - .T ( OEN ), - .I ( I ), - .O ( O ), - .IO( PAD ) - ); - -endmodule \ No newline at end of file diff --git a/fpga/pulpissimo-genesys2/rtl/pulp_clock_gating_xilinx.sv b/fpga/pulpissimo-genesys2/rtl/pulp_clock_gating_xilinx.sv deleted file mode 100644 index 1e2db2d1..00000000 --- a/fpga/pulpissimo-genesys2/rtl/pulp_clock_gating_xilinx.sv +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2018 ETH Zurich and University of Bologna. -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -module pulp_clock_gating - ( - input logic clk_i, - input logic en_i, - input logic test_en_i, - output logic clk_o - ); - - assign clk_o = clk_i; - -endmodule diff --git a/fpga/pulpissimo-genesys2/rtl/xilinx_pulpissimo.v b/fpga/pulpissimo-genesys2/rtl/xilinx_pulpissimo.v deleted file mode 100644 index b301a900..00000000 --- a/fpga/pulpissimo-genesys2/rtl/xilinx_pulpissimo.v +++ /dev/null @@ -1,148 +0,0 @@ -//----------------------------------------------------------------------------- -// Title : PULPissimo Verilog Wrapper -//----------------------------------------------------------------------------- -// File : xilinx_pulpissimo.v -// Author : Manuel Eggimann -// Created : 21.05.2019 -//----------------------------------------------------------------------------- -// Description : -// Verilog Wrapper of PULPissimo to use the module within Xilinx IP integrator. -//----------------------------------------------------------------------------- -// Copyright (C) 2013-2019 ETH Zurich, University of Bologna -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. -//----------------------------------------------------------------------------- - -module xilinx_pulpissimo - ( - input wire ref_clk_p, - input wire ref_clk_n, - -// inout wire pad_spim_sdio0, - inout wire pad_spim_sdio1, - inout wire pad_spim_sdio2, - inout wire pad_spim_sdio3, - inout wire pad_spim_csn0, - inout wire pad_spim_sck, - - inout wire pad_uart_rx, - inout wire pad_uart_tx, - - inout wire led0_o, //Mapped to spim_csn1 - inout wire led1_o, //Mapped to cam_pclk - inout wire led2_o, //Mapped to cam_hsync - inout wire led3_o, //Mapped to cam_data0 - - inout wire switch0_i, //Mapped to cam_data1 - inout wire switch1_i, //Mapped to cam_data2 - - inout wire btnc_i, //Mapped to cam_data3 - inout wire btnd_i, //Mapped to cam_data4 - inout wire btnl_i, //Mapped to cam_data5 - inout wire btnr_i, //Mapped to cam_data6 - inout wire btnu_i, //Mapped to cam_data7 - - inout wire oled_spim_sck_o, //Mapped to spim_sck - inout wire oled_spim_mosi_o, //Mapped to spim_sdio0 - inout wire oled_rst_o, //Mapped to i2s0_sck - inout wire oled_dc_o, //Mapped to i2s0_ws - inout wire oled_vbat_o, // Mapped to i2s0_sdi - inout wire oled_vdd_o, // Mapped to i2s1_sdi - - inout wire sdio_reset_o, //Reset signal for SD card need to be driven low to - //power the onboard sd-card. Mapped to cam_vsync. - inout wire pad_sdio_clk, - inout wire pad_sdio_cmd, - inout wire pad_sdio_data0, - inout wire pad_sdio_data1, - inout wire pad_sdio_data2, - inout wire pad_sdio_data3, - - inout wire pad_i2c0_sda, - inout wire pad_i2c0_scl, - - input wire pad_reset_n, - inout wire pad_bootsel, - - input wire pad_jtag_tck, - input wire pad_jtag_tdi, - output wire pad_jtag_tdo, - input wire pad_jtag_tms, - input wire pad_jtag_trst - ); - - localparam CORE_TYPE = 0; // 0 for RISCY, 1 for IBEX RV32IMC (formerly ZERORISCY), 2 for IBEX RV32EC (formerly MICRORISCY) - localparam USE_FPU = 1; - localparam USE_HWPE = 0; - - wire ref_clk; - - - //Differential to single ended clock conversion - IBUFGDS - #( - .IOSTANDARD("LVDS"), - .DIFF_TERM("FALSE"), - .IBUF_LOW_PWR("FALSE")) - i_sysclk_iobuf - ( - .I(ref_clk_p), - .IB(ref_clk_n), - .O(ref_clk) - ); - - pulpissimo - #(.CORE_TYPE(CORE_TYPE), - .USE_FPU(USE_FPU), - .USE_HWPE(USE_HWPE) - ) i_pulpissimo - ( - .pad_spim_sdio0(oled_spim_mosi_o), - .pad_spim_sdio1(pad_spim_sdio1), - .pad_spim_sdio2(pad_spim_sdio2), - .pad_spim_sdio3(pad_spim_sdio3), - .pad_spim_csn0(pad_spim_csn0), - .pad_spim_csn1(led0_o), - .pad_spim_sck(oled_spim_sck_o), - .pad_uart_rx(pad_uart_rx), - .pad_uart_tx(pad_uart_tx), - .pad_cam_pclk(led1_o), - .pad_cam_hsync(led2_o), - .pad_cam_data0(led3_o), - .pad_cam_data1(switch0_i), - .pad_cam_data2(switch1_i), - .pad_cam_data3(btnc_i), - .pad_cam_data4(btnd_i), - .pad_cam_data5(btnl_i), - .pad_cam_data6(btnr_i), - .pad_cam_data7(btnu_i), - .pad_cam_vsync(sdio_reset_o), - .pad_sdio_clk(pad_sdio_clk), - .pad_sdio_cmd(pad_sdio_cmd), - .pad_sdio_data0(pad_sdio_data0), - .pad_sdio_data1(pad_sdio_data1), - .pad_sdio_data2(pad_sdio_data2), - .pad_sdio_data3(pad_sdio_data3), - .pad_i2c0_sda(pad_i2c0_sda), - .pad_i2c0_scl(pad_i2c0_scl), - .pad_i2s0_sck(oled_rst_o), - .pad_i2s0_ws(oled_dc_o), - .pad_i2s0_sdi(oled_vbat_o), - .pad_i2s1_sdi(oled_vdd_o), - .pad_reset_n(pad_reset_n), - .pad_jtag_tck(pad_jtag_tck), - .pad_jtag_tdi(pad_jtag_tdi), - .pad_jtag_tdo(pad_jtag_tdo), - .pad_jtag_tms(pad_jtag_tms), - .pad_jtag_trst(pad_jtag_trst), - .pad_xtal_in(ref_clk), - .pad_bootsel() - ); - -endmodule diff --git a/fpga/pulpissimo-genesys2/tcl/.gitignore b/fpga/pulpissimo-genesys2/tcl/.gitignore deleted file mode 100644 index 587a0fa6..00000000 --- a/fpga/pulpissimo-genesys2/tcl/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -#Ignore tcl files generated by ipstools -ips_add_files.tcl -ips_inc_dirs.tcl -ips_src_files.tcl -rtl_add_files.tcl -rtl_src_files.tcl \ No newline at end of file diff --git a/fpga/pulpissimo-genesys2/tcl/messages.tcl b/fpga/pulpissimo-genesys2/tcl/messages.tcl deleted file mode 100644 index e8bfaf90..00000000 --- a/fpga/pulpissimo-genesys2/tcl/messages.tcl +++ /dev/null @@ -1,13 +0,0 @@ -# sets up Vivado messages in a more sensible way - -set_msg_config -id {[Synth 8-3352]} -new_severity "critical warning" -set_msg_config -id {[Synth 8-350]} -new_severity "critical warning" -set_msg_config -id {[Synth 8-2490]} -new_severity "warning" -set_msg_config -id {[Synth 8-2306]} -new_severity "info" -set_msg_config -id {[Synth 8-3331]} -new_severity "critical warning" -set_msg_config -id {[Synth 8-3332]} -new_severity "info" -set_msg_config -id {[Synth 8-2715]} -new_severity "error" -set_msg_config -id {[Opt 31-35]} -new_severity "info" -set_msg_config -id {[Opt 31-32]} -new_severity "info" -set_msg_config -id {[Shape Builder 18-119]} -new_severity "warning" -set_msg_config -id {[Filemgmt 20-742]} -new_severity "error" diff --git a/fpga/pulpissimo-genesys2/tcl/run.tcl b/fpga/pulpissimo-genesys2/tcl/run.tcl deleted file mode 100644 index b62025a7..00000000 --- a/fpga/pulpissimo-genesys2/tcl/run.tcl +++ /dev/null @@ -1,132 +0,0 @@ -set project pulpissimo_genesys2 -set RTL ../../../rtl -set IPS ../../../ips -set CONSTRS constraints - - -# detect board -if [info exists ::env(BOARD)] { - set BOARD $::env(BOARD) -} else { - puts "Please execute 'source ../sourceme.sh first before you start vivado in order to setup necessary environment variables." - exit -} -if [info exists ::env(XILINX_BOARD)] { - set XILINX_BOARD $::env(XILINX_BOARD) -} - -# create project -create_project $project . -force -part $::env(XILINX_PART) -set_property board_part $XILINX_BOARD [current_project] - -# set up meaningfull errors -source tcl/messages.tcl - -# set up includes -source ../pulpissimo/tcl/ips_inc_dirs.tcl -set_property include_dirs $INCLUDE_DIRS [current_fileset] -set_property include_dirs $INCLUDE_DIRS [current_fileset -simset] - -# setup and add IP source files -source ../pulpissimo/tcl/ips_src_files.tcl -source ../pulpissimo/tcl/ips_add_files.tcl - -# setup and add RTL source files -source ../pulpissimo/tcl/rtl_src_files.tcl -source ../pulpissimo/tcl/rtl_add_files.tcl - -# Override IPSApprox default variables -set FPGA_RTL rtl -set FPGA_IPS ips - -# remove duplicate incompatible modules -remove_files $IPS/pulp_soc/rtl/components/axi_slice_dc_slave_wrap.sv -remove_file $IPS/pulp_soc/rtl/components/axi_slice_dc_master_wrap.sv -remove_file $IPS/tech_cells_generic/pad_functional_xilinx.sv - -# Set Verilog Defines. -set DEFINES "FPGA_TARGET_XILINX=1 PULP_FPGA_EMUL=1 AXI4_XCHECK_OFF=1" -if { $BOARD == "genesys2" } { - set DEFINES "$DEFINES GENESYS2=1" -} -set_property verilog_define $DEFINES [current_fileset] - -# detect target clock -if [info exists ::env(FC_CLK_PERIOD_NS)] { - set FC_CLK_PERIOD_NS $::env(FC_CLK_PERIOD_NS) -} else { - set FC_CLK_PERIOD_NS 10.000 -} -set CLK_HALFPERIOD_NS [expr ${FC_CLK_PERIOD_NS} / 2.0] - -# Add toplevel wrapper -add_files -norecurse $FPGA_RTL/xilinx_pulpissimo.v - -# Add Xilinx IPs -read_ip $FPGA_IPS/xilinx_clk_mngr/ip/xilinx_clk_mngr.xci -read_ip $FPGA_IPS/xilinx_slow_clk_mngr/ip/xilinx_slow_clk_mngr.xci -read_ip $FPGA_IPS/xilinx_interleaved_ram/ip/xilinx_interleaved_ram.xci -read_ip $FPGA_IPS/xilinx_private_ram/ip/xilinx_private_ram.xci - -# Add wrappers and xilinx specific techcells -add_files -norecurse $FPGA_RTL/fpga_clk_gen.sv -add_files -norecurse $FPGA_RTL/fpga_slow_clk_gen.sv -add_files -norecurse $FPGA_RTL/fpga_interleaved_ram.sv -add_files -norecurse $FPGA_RTL/fpga_private_ram.sv -add_files -norecurse $FPGA_RTL/fpga_bootrom.sv -add_files -norecurse $FPGA_RTL/pad_functional_xilinx.sv -add_files -norecurse $FPGA_RTL/pulp_clock_gating_xilinx.sv - - -# set pulpissimo as top -set_property top xilinx_pulpissimo [current_fileset]; # - -# needed only if used in batch mode -update_compile_order -fileset sources_1 - -# Add constraints -add_files -fileset constrs_1 -norecurse $CONSTRS/genesys2.xdc - -# Elaborate design -synth_design -rtl -name rtl_1 -sfcu;# sfcu -> run synthesis in single file compilation unit mode - - - -# launch synthesis -set_property STEPS.SYNTH_DESIGN.ARGS.FLATTEN_HIERARCHY none [get_runs synth_1] -set_property -name {STEPS.SYNTH_DESIGN.ARGS.MORE OPTIONS} -value -sfcu -objects [get_runs synth_1] ;# Use single file compilation unit mode to prevent issues with import pkg::* statements in the codebase -launch_runs synth_1 -jobs 8 -wait_on_run synth_1 -open_run synth_1 -name netlist_1 -set_property needs_refresh false [get_runs synth_1] - -# Remove unused IOBUF cells in padframe (they are not optimized away since the -# pad driver also drives the input creating a datapath from pad_xy_o to pad_xy_i -# ) -remove_cell i_pulpissimo/pad_frame_i/padinst_bootsel - - -# Launch Implementation - -# set for RuntimeOptimized implementation -set_property "steps.opt_design.args.directive" "RuntimeOptimized" [get_runs impl_1] -set_property "steps.place_design.args.directive" "RuntimeOptimized" [get_runs impl_1] -set_property "steps.route_design.args.directive" "RuntimeOptimized" [get_runs impl_1] - -set_property STEPS.WRITE_BITSTREAM.ARGS.BIN_FILE true [get_runs impl_1] -set_property config_mode SPIx4 [current_design] - -launch_runs impl_1 -jobs 8 -wait_on_run impl_1 -launch_runs impl_1 -to_step write_bitstream -wait_on_run impl_1 - -open_run impl_1 - -# Generate reports -exec mkdir -p reports/ -exec rm -rf reports/* -check_timing -file reports/${project}.check_timing.rpt -report_timing -max_paths 100 -nworst 100 -delay_type max -sort_by slack -file reports/${project}.timing_WORST_100.rpt -report_timing -nworst 1 -delay_type max -sort_by group -file reports/${project}.timing.rpt -report_utilization -hierarchical -file reports/${project}.utilization.rpt diff --git a/fpga/pulpissimo-nexys_video/.gitignore b/fpga/pulpissimo-nexys_video/.gitignore deleted file mode 100644 index 58cd8944..00000000 --- a/fpga/pulpissimo-nexys_video/.gitignore +++ /dev/null @@ -1,22 +0,0 @@ -#Ignore vivado project files generated by the tcl script -**/.Xil/* -**/reports/* -**/*.cache/* -**/*.hw/* -**/*.ip_user_files/* -**/*.runs/* -**/*.sim/* -**/*.srcs/* -*.edf -*.xpr -*.jou -*.log - -.cxl.* - -*_stub.v -gmon.out - -/pulpissimo-nexys_video/**/pulpissimo.bit - -**/xdc/constraints.xdc diff --git a/fpga/pulpissimo-nexys_video/Makefile b/fpga/pulpissimo-nexys_video/Makefile deleted file mode 100644 index 5b436097..00000000 --- a/fpga/pulpissimo-nexys_video/Makefile +++ /dev/null @@ -1,44 +0,0 @@ -PROJECT:=pulpissimo-nexys_video -VIVADO ?= vivado -VIVADOFLAGS ?= -nojournal -mode batch -source scripts/prologue.tcl - -include fpga-settings.mk - -.DEFAULT_GOAL:=help - -.PHONY: help all gui ips clean-ips clk clean-clk ram clean-ram clean - -all: ips ## Generate the bitstream for pulpissimo with vivado in batch mode. The vivado invocation command may be overriden with the env variable VIVADO. - $(VIVADO) -mode batch -source tcl/run.tcl - -gui: ips ## Generates the bitstream for pulpissimo with vivado in GUI mode. The vivado invocation command may be overriden with the env variable VIVADO. - $(VIVADO) -mode gui -source tcl/run.tcl & - -ips: clk ram ## Synthesizes necessary xilinx IP - -clean-ips: clean-clk clean-ram ## Clean all IPs - -clk: ## Synthesizes the Xilinx Clocking Manager IPs - cd ips/xilinx_clk_mngr; make all - cd ips/xilinx_slow_clk_mngr; make all - -clean-clk: ## Removes all Clocking Wizard IP outputs - cd ips/xilinx_clk_mngr; make clean - cd ips/xilinx_slow_clk_mngr; make clean - -ram: ## Synthesizes the Xilinx Block Memory Generator IPs for PULPissimo's L2 Ram - cd ips/xilinx_interleaved_ram; make all - cd ips/xilinx_private_ram; make all - -clean-ram: ## Removes all Block Ram IP outputs related to l2 ram - cd ips/xilinx_interleaved_ram; make clean - cd ips/xilinx_private_ram; make clean - -clean: ## Removes all bitstreams, *.log files and vivado related files (rm -rf vivado*) - rm -rf ${PROJECT}.*[^'bit'] - rm -rf ${PROJECT}.*[^'bin'] - rm -rf *.log - rm -rf vivado* - -help: - @grep -E -h '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' diff --git a/fpga/pulpissimo-nexys_video/README.md b/fpga/pulpissimo-nexys_video/README.md deleted file mode 100644 index 354967f5..00000000 --- a/fpga/pulpissimo-nexys_video/README.md +++ /dev/null @@ -1,55 +0,0 @@ -# PULPissimo on the Digilent Nexys Video Board -[\[Documentation\]](https://reference.digilentinc.com/reference/programmable-logic/nexys-video/start) - -## Bitstream Generation -In the fpga folder, run -```Shell -make nexys_video -``` -which will generate `pulpissimo_nexys_video.bit`. -Use Vivado to load it into the FPGA. - -## Default SoC and Core Frequencies - -By default the clock generating IPs are synthesized to provide the following frequencies to PULPissimo: - -| Clock Domain | Default Frequency on Nexys Video board | -|----------------|----------------------------------------| -| Core Frequency | 10 MHz | -| SoC Frequency | 5 MHz | - - -## Peripherals -PULPissimo is connected to the following board peripherals: - - -| PULPissimo Pin | Mapped Board Peripheral | -|----------------|-----------------------------------------------------| -| `SPIM0` pins | QSPI Flash | -| `I2C0` pins | I2C Bus (connects to the ADAU1761 audio codec) | -| `spim_csn1` | LED0 | -| `cam_pclk` | LED1 | -| `cam_hsync` | LED2 | -| `cam_data0` | LED3 | -| `cam_data1` | Switch 0 | -| `cam_data2` | Switch 1 | -| `cam_data3` | Button C | -| `cam_data4` | Button D | -| `cam_data5` | Button L | -| `cam_data6` | Button R | -| `cam_data7` | Button U | - -### Reset Button -The CPU RESET button (G4) resets the RISC-V CPU. - -### UART -PULPissimo's UART port is mapped to the onboard FTDI FT232R USB-UART bridge and thus accessible through the UART micro-USB connector (J13). - -### JTAG -PULPIssimo's JTAG plug is connected to Channel 0 of the onboard FTDI USB JTAG programmer. -Therefore we can attach OpenOCD withouth the need of an external JTAG programmer. -Just attach a micro-USB cable to the PROG micro-USB connector (J12) and use the provided OpenOCD configuration file: - -```Shell -$OPENOCD/bin/openocd -f pulpissimo/fpga/pulpissimo-nexys_video/openocd-nexys_video.cfg -``` diff --git a/fpga/pulpissimo-nexys_video/constraints/nexys_video.xdc b/fpga/pulpissimo-nexys_video/constraints/nexys_video.xdc deleted file mode 100644 index b0e8e841..00000000 --- a/fpga/pulpissimo-nexys_video/constraints/nexys_video.xdc +++ /dev/null @@ -1,138 +0,0 @@ -####################################### -# _______ _ _ # -# |__ __(_) (_) # -# | | _ _ __ ___ _ _ __ __ _ # -# | | | | '_ ` _ \| | '_ \ / _` | # -# | | | | | | | | | | | | | (_| | # -# |_| |_|_| |_| |_|_|_| |_|\__, | # -# __/ | # -# |___/ # -####################################### - - -#Create constraint for the clock input of the nexys video board -create_clock -period 10.000 -name ref_clk [get_ports sys_clk] - -#I2S and CAM interface are not used in this FPGA port. Set constraints to -#disable the clock -set_case_analysis 0 i_pulpissimo/safe_domain_i/cam_pclk_o -set_case_analysis 0 i_pulpissimo/safe_domain_i/i2s_slave_sck_o -#set_input_jitter tck 1.000 - -## JTAG -create_clock -period 100.000 -name tck -waveform {0.000 50.000} [get_ports pad_jtag_tck] -set_input_jitter tck 1.000 - - -# minimize routing delay -set_input_delay -clock tck -clock_fall 5.000 [get_ports pad_jtag_tdi] -set_input_delay -clock tck -clock_fall 5.000 [get_ports pad_jtag_tms] -set_output_delay -clock tck 5.000 [get_ports pad_jtag_tdo] -set_false_path -from [get_ports pad_jtag_trst] - -set_max_delay -to [get_ports pad_jtag_tdo] 20.000 -set_max_delay -from [get_ports pad_jtag_tms] 20.000 -set_max_delay -from [get_ports pad_jtag_tdi] 20.000 -set_max_delay -from [get_ports pad_jtag_trst] 20.000 - -set_max_delay -datapath_only -from [get_pins i_pulpissimo/soc_domain_i/pulp_soc_i/i_dmi_jtag/i_dmi_cdc/i_cdc_resp/i_src/data_src_q_reg*/C] -to [get_pins i_pulpissimo/soc_domain_i/pulp_soc_i/i_dmi_jtag/i_dmi_cdc/i_cdc_resp/i_dst/data_dst_q_reg*/D] 20.000 -set_max_delay -datapath_only -from [get_pins i_pulpissimo/soc_domain_i/pulp_soc_i/i_dmi_jtag/i_dmi_cdc/i_cdc_resp/i_src/req_src_q_reg/C] -to [get_pins i_pulpissimo/soc_domain_i/pulp_soc_i/i_dmi_jtag/i_dmi_cdc/i_cdc_resp/i_dst/req_dst_q_reg/D] 20.000 -set_max_delay -datapath_only -from [get_pins i_pulpissimo/soc_domain_i/pulp_soc_i/i_dmi_jtag/i_dmi_cdc/i_cdc_req/i_dst/ack_dst_q_reg/C] -to [get_pins i_pulpissimo/soc_domain_i/pulp_soc_i/i_dmi_jtag/i_dmi_cdc/i_cdc_req/i_src/ack_src_q_reg/D] 20.000 - - -# reset signal -set_false_path -from [get_ports pad_reset_n] - -# Set ASYNC_REG attribute for ff synchronizers to place them closer together and -# increase MTBF -set_property ASYNC_REG true [get_cells i_pulpissimo/soc_domain_i/pulp_soc_i/soc_peripherals_i/apb_adv_timer_i/u_tim0/u_in_stage/r_ls_clk_sync_reg*] -set_property ASYNC_REG true [get_cells i_pulpissimo/soc_domain_i/pulp_soc_i/soc_peripherals_i/apb_adv_timer_i/u_tim1/u_in_stage/r_ls_clk_sync_reg*] -set_property ASYNC_REG true [get_cells i_pulpissimo/soc_domain_i/pulp_soc_i/soc_peripherals_i/apb_adv_timer_i/u_tim2/u_in_stage/r_ls_clk_sync_reg*] -set_property ASYNC_REG true [get_cells i_pulpissimo/soc_domain_i/pulp_soc_i/soc_peripherals_i/apb_adv_timer_i/u_tim3/u_in_stage/r_ls_clk_sync_reg*] -set_property ASYNC_REG true [get_cells i_pulpissimo/soc_domain_i/pulp_soc_i/soc_peripherals_i/i_apb_timer_unit/s_ref_clk*] -set_property ASYNC_REG true [get_cells i_pulpissimo/soc_domain_i/pulp_soc_i/soc_peripherals_i/i_ref_clk_sync/i_pulp_sync/r_reg_reg*] -set_property ASYNC_REG true [get_cells i_pulpissimo/soc_domain_i/pulp_soc_i/soc_peripherals_i/u_evnt_gen/r_ls_sync_reg*] - -# Create asynchronous clock group between slow-clk and SoC clock. Those clocks -# are considered asynchronously and proper synchronization regs are in place -set_clock_groups -asynchronous -group [get_clocks -of_objects [get_pins i_pulpissimo/safe_domain_i/i_slow_clk_gen/i_slow_clk_mngr/inst/mmcm_adv_inst/CLKOUT0]] -group [get_clocks -of_objects [get_pins i_pulpissimo/soc_domain_i/pulp_soc_i/i_clk_rst_gen/i_fpga_clk_gen/i_clk_manager/inst/mmcm_adv_inst/CLKOUT0]] - - -############################################################# -# _____ ____ _____ _ _ _ # -# |_ _/ __ \ / ____| | | | | (_) # -# | || | | |_____| (___ ___| |_| |_ _ _ __ __ _ ___ # -# | || | | |______\___ \ / _ \ __| __| | '_ \ / _` / __| # -# _| || |__| | ____) | __/ |_| |_| | | | | (_| \__ \ # -# |_____\____/ |_____/ \___|\__|\__|_|_| |_|\__, |___/ # -# __/ | # -# |___/ # -############################################################# - -## Sys clock -set_property -dict {PACKAGE_PIN R4 IOSTANDARD LVCMOS33} [get_ports sys_clk] - -## Buttons -set_property -dict {PACKAGE_PIN G4 IOSTANDARD LVCMOS15} [get_ports pad_reset_n] -set_property -dict {PACKAGE_PIN B22 IOSTANDARD LVCMOS12} [get_ports btnc_i] -set_property -dict {PACKAGE_PIN D22 IOSTANDARD LVCMOS12} [get_ports btnd_i] -set_property -dict {PACKAGE_PIN C22 IOSTANDARD LVCMOS12} [get_ports btnl_i] -set_property -dict {PACKAGE_PIN D14 IOSTANDARD LVCMOS12} [get_ports btnr_i] -set_property -dict {PACKAGE_PIN F15 IOSTANDARD LVCMOS12} [get_ports btnu_i] - -## To use FTDI FT2232 JTAG -set_property -dict {PACKAGE_PIN R17 IOSTANDARD LVCMOS33} [get_ports pad_jtag_trst] -set_property -dict {PACKAGE_PIN U20 IOSTANDARD LVCMOS33} [get_ports pad_jtag_tck] -set_property -dict {PACKAGE_PIN P14 IOSTANDARD LVCMOS33} [get_ports pad_jtag_tdi] -set_property -dict {PACKAGE_PIN P15 IOSTANDARD LVCMOS33} [get_ports pad_jtag_tdo] -set_property -dict {PACKAGE_PIN U17 IOSTANDARD LVCMOS33} [get_ports pad_jtag_tms] - -## UART -set_property -dict {PACKAGE_PIN AA19 IOSTANDARD LVCMOS33} [get_ports pad_uart_tx] -set_property -dict {PACKAGE_PIN V18 IOSTANDARD LVCMOS33} [get_ports pad_uart_rx] - -## LEDs -set_property -dict {PACKAGE_PIN T14 IOSTANDARD LVCMOS25} [get_ports led0_o] -set_property -dict {PACKAGE_PIN T15 IOSTANDARD LVCMOS25} [get_ports led1_o] -set_property -dict {PACKAGE_PIN T16 IOSTANDARD LVCMOS25} [get_ports led2_o] -set_property -dict {PACKAGE_PIN U16 IOSTANDARD LVCMOS25} [get_ports led3_o] - -## Switches -set_property -dict {PACKAGE_PIN E22 IOSTANDARD LVCMOS12} [get_ports switch0_i] -set_property -dict {PACKAGE_PIN F21 IOSTANDARD LVCMOS12} [get_ports switch1_i] - -## I2C Bus -set_property -dict {PACKAGE_PIN W5 IOSTANDARD LVCMOS33} [get_ports pad_i2c0_scl] -set_property -dict {PACKAGE_PIN V5 IOSTANDARD LVCMOS33} [get_ports pad_i2c0_sda] - -## QSPI Flash -set_property -dict {PACKAGE_PIN T19 IOSTANDARD LVCMOS33} [get_ports pad_spim_csn0] -#set_property -dict {PACKAGE_PIN P22 IOSTANDARD LVCMOS33} [get_ports { pad_spim_sdio0 }]; #IO_L1P_T0_D00_MOSI_14 Sch=qspi_dq[0] -set_property -dict {PACKAGE_PIN R22 IOSTANDARD LVCMOS33} [get_ports pad_spim_sdio1] -set_property -dict {PACKAGE_PIN P21 IOSTANDARD LVCMOS33} [get_ports pad_spim_sdio2] -set_property -dict {PACKAGE_PIN R21 IOSTANDARD LVCMOS33} [get_ports pad_spim_sdio3] - -## OLED Display -set_property -dict {PACKAGE_PIN W22 IOSTANDARD LVCMOS33} [get_ports oled_dc_o] -set_property -dict {PACKAGE_PIN U21 IOSTANDARD LVCMOS33} [get_ports oled_rst_o] -set_property -dict {PACKAGE_PIN W21 IOSTANDARD LVCMOS33} [get_ports oled_spim_sck_o] -set_property -dict {PACKAGE_PIN Y22 IOSTANDARD LVCMOS33} [get_ports oled_spim_mosi_o] -set_property -dict {PACKAGE_PIN P20 IOSTANDARD LVCMOS33} [get_ports oled_vbat_o] -set_property -dict {PACKAGE_PIN V22 IOSTANDARD LVCMOS33} [get_ports oled_vdd_o] - -## SD Card -set_property -dict {PACKAGE_PIN W19 IOSTANDARD LVCMOS33} [get_ports pad_sdio_clk] -#set_property -dict {PACKAGE_PIN T18 IOSTANDARD LVCMOS33} [get_ports { sd_cd }]; #IO_L20N_T3_A07_D23_14 Sch=sd_cd -set_property -dict {PACKAGE_PIN W20 IOSTANDARD LVCMOS33} [get_ports pad_sdio_cmd] -set_property -dict {PACKAGE_PIN V19 IOSTANDARD LVCMOS33} [get_ports pad_sdio_data0] -set_property -dict {PACKAGE_PIN T21 IOSTANDARD LVCMOS33} [get_ports pad_sdio_data1] -set_property -dict {PACKAGE_PIN T20 IOSTANDARD LVCMOS33} [get_ports pad_sdio_data2] -set_property -dict {PACKAGE_PIN U18 IOSTANDARD LVCMOS33} [get_ports pad_sdio_data3] -set_property -dict {PACKAGE_PIN V20 IOSTANDARD LVCMOS33} [get_ports sdio_reset_o] - -# Nexys Video has a quad SPI flash -set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design] - -# Configuration options, can be used for all designs -set_property CONFIG_VOLTAGE 3.3 [current_design] -set_property CFGBVS VCCO [current_design] diff --git a/fpga/pulpissimo-nexys_video/elf_run.gdb b/fpga/pulpissimo-nexys_video/elf_run.gdb deleted file mode 100644 index cba53bd0..00000000 --- a/fpga/pulpissimo-nexys_video/elf_run.gdb +++ /dev/null @@ -1,4 +0,0 @@ -target remote localhost:3333 -monitor reset halt -load -continue \ No newline at end of file diff --git a/fpga/pulpissimo-nexys_video/elf_run.sh b/fpga/pulpissimo-nexys_video/elf_run.sh deleted file mode 100755 index a17ade42..00000000 --- a/fpga/pulpissimo-nexys_video/elf_run.sh +++ /dev/null @@ -1,15 +0,0 @@ -#!/bin/bash - -trap "exit" INT TERM -trap "kill 0" EXIT - - -SCRIPTDIR=$(dirname $0) - -#Execute gdb and connect to openocd via pipe -$OPENOCD/bin/openocd -f $SCRIPTDIR/openocd-nexys_video.cfg & -$PULP_RISCV_GCC_TOOLCHAIN_CI/bin/riscv32-unknown-elf-gdb -x $SCRIPTDIR/elf_run.gdb $1 & -sleep 3 -minicom -D /dev/ttyUSB0 -b 115200 - - diff --git a/fpga/pulpissimo-nexys_video/fpga-settings.mk b/fpga/pulpissimo-nexys_video/fpga-settings.mk deleted file mode 100644 index 1b30bc93..00000000 --- a/fpga/pulpissimo-nexys_video/fpga-settings.mk +++ /dev/null @@ -1,11 +0,0 @@ -export BOARD=nexys_video -export XILINX_PART=xc7a200tsbg484-1 -export XILINX_BOARD=digilentinc.com:nexys_video:1.1 -export FC_CLK_PERIOD_NS=100 -export PER_CLK_PERIOD_NS=200 -export SLOW_CLK_PERIOD_NS=30517 -#Must also change the localparam 'L2_BANK_SIZE' in pulp_soc.sv accordingly -export INTERLEAVED_BANK_SIZE=28672 -#Must also change the localparam 'L2_BANK_SIZE_PRI' in pulp_soc.sv accordingly -export PRIVATE_BANK_SIZE=8192 -$(info Setting environment variables for $(BOARD) board) diff --git a/fpga/pulpissimo-nexys_video/ips/xilinx_clk_mngr/.gitignore b/fpga/pulpissimo-nexys_video/ips/xilinx_clk_mngr/.gitignore deleted file mode 100644 index 5099fe9c..00000000 --- a/fpga/pulpissimo-nexys_video/ips/xilinx_clk_mngr/.gitignore +++ /dev/null @@ -1,21 +0,0 @@ -#Ignore vivado project files generated by the tcl script -**/.Xil/* -**/reports/* -**/*.cache/* -**/*.hw/* -**/*.ip_user_files/* -**/*.runs/* -**/*.sim/* -**/*.srcs/* -*.edf -*.xpr -*.jou -*.log - -.cxl.* - -*ip - -*_stub.v -gmon.out - diff --git a/fpga/pulpissimo-nexys_video/ips/xilinx_clk_mngr/Makefile b/fpga/pulpissimo-nexys_video/ips/xilinx_clk_mngr/Makefile deleted file mode 100644 index 978b9cee..00000000 --- a/fpga/pulpissimo-nexys_video/ips/xilinx_clk_mngr/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -PROJECT:=xilinx_clk_mngr -VIVADO ?= vivado -VIVADOFLAGS ?= -nojournal -mode batch -source scripts/prologue.tcl -MODE=batch - -include ../../fpga-settings.mk - -.DEFAULT_GOAL:=help - -.PHONY: help all gui clean - -all: MODE=batch ## Create and synthesize the IP in batch mode. - -gui: MODE=gui ## Create and synthesize the IP in GUI mode. - -all gui: $(PROJECT).xpr - -$(PROJECT).xpr: ../../fpga-settings.mk tcl/run.tcl - make clean - $(VIVADO) -mode $(MODE) -source tcl/run.tcl - mkdir -p ip - cp -r ${PROJECT}.srcs/sources_1/ip/${PROJECT}/* ip/. - cp ${PROJECT}.runs/${PROJECT}_synth_1/${PROJECT}.dcp ip/. - -clean: ## Remove all build products - rm -rf ip/* - mkdir -p ip - rm -rf ${PROJECT}.* - rm -rf component.xml - rm -rf vivado*.jou - rm -rf vivado*.log - rm -rf vivado*.str - rm -rf xgui - rm -rf .Xil - -help: ## Shows this help message - @grep -E -h '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' diff --git a/fpga/pulpissimo-nexys_video/ips/xilinx_clk_mngr/tcl/run.tcl b/fpga/pulpissimo-nexys_video/ips/xilinx_clk_mngr/tcl/run.tcl deleted file mode 100644 index a6b3d9ea..00000000 --- a/fpga/pulpissimo-nexys_video/ips/xilinx_clk_mngr/tcl/run.tcl +++ /dev/null @@ -1,49 +0,0 @@ -set partNumber $::env(XILINX_PART) - -if [info exists ::env(BOARD)] { - set BOARD $::env(BOARD) -} else { - error "BOARD is not defined. Please source the sourceme.sh file." - exit -} -if [info exists ::env(XILINX_BOARD)] { - set boardName $::env(XILINX_BOARD) -} - -# detect target clock -if [info exists ::env(FC_CLK_PERIOD_NS)] { - set FC_CLK_PERIOD_NS $::env(FC_CLK_PERIOD_NS) -} else { - set FC_CLK_PERIOD_NS 10.000 -} -if [info exists ::env(PER_CLK_PERIOD_NS)] { - set PER_CLK_PERIOD_NS $::env(PER_CLK_PERIOD_NS) -} else { - set PER_CLK_PERIOD_NS 20.000 -} - - -set FC_CLK_FREQ_MHZ [expr 1000 / $FC_CLK_PERIOD_NS] -set PER_CLK_FREQ_MHZ [expr 1000 / $PER_CLK_PERIOD_NS] - -set ipName xilinx_clk_mngr - -create_project $ipName . -part $partNumber -set_property board_part $boardName [current_project] - -create_ip -name clk_wiz -vendor xilinx.com -library ip -module_name $ipName - -set_property -dict [eval list CONFIG.PRIM_IN_FREQ {100.000} \ - CONFIG.NUM_OUT_CLKS {2} \ - CONFIG.CLKOUT2_USED {true} \ - CONFIG.RESET_TYPE {ACTIVE_LOW} \ - CONFIG.RESET_PORT {resetn} \ - CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {$FC_CLK_FREQ_MHZ} \ - CONFIG.CLKOUT2_REQUESTED_OUT_FREQ {$PER_CLK_FREQ_MHZ} \ - CONFIG.CLKIN1_JITTER_PS {50.0} \ - ] [get_ips $ipName] - -generate_target all [get_files ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] -create_ip_run [get_files -of_objects [get_fileset sources_1] ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] -launch_run -jobs 8 ${ipName}_synth_1 -wait_on_run ${ipName}_synth_1 diff --git a/fpga/pulpissimo-nexys_video/ips/xilinx_interleaved_ram/.gitignore b/fpga/pulpissimo-nexys_video/ips/xilinx_interleaved_ram/.gitignore deleted file mode 100644 index 5099fe9c..00000000 --- a/fpga/pulpissimo-nexys_video/ips/xilinx_interleaved_ram/.gitignore +++ /dev/null @@ -1,21 +0,0 @@ -#Ignore vivado project files generated by the tcl script -**/.Xil/* -**/reports/* -**/*.cache/* -**/*.hw/* -**/*.ip_user_files/* -**/*.runs/* -**/*.sim/* -**/*.srcs/* -*.edf -*.xpr -*.jou -*.log - -.cxl.* - -*ip - -*_stub.v -gmon.out - diff --git a/fpga/pulpissimo-nexys_video/ips/xilinx_interleaved_ram/Makefile b/fpga/pulpissimo-nexys_video/ips/xilinx_interleaved_ram/Makefile deleted file mode 100644 index 08752831..00000000 --- a/fpga/pulpissimo-nexys_video/ips/xilinx_interleaved_ram/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -PROJECT:=xilinx_interleaved_ram -VIVADO ?= vivado -VIVADOFLAGS ?= -nojournal -mode batch -source scripts/prologue.tcl -MODE=batch - -include ../../fpga-settings.mk - -.DEFAULT_GOAL:=help - -.PHONY: help all gui clean - -all: MODE=batch ## Create and synthesize the IP in batch mode. - -gui: MODE=gui ## Create and synthesize the IP in GUI mode. - -all gui: $(PROJECT).xpr - -$(PROJECT).xpr: ../../fpga-settings.mk tcl/run.tcl - make clean - $(VIVADO) -mode $(MODE) -source tcl/run.tcl - mkdir -p ip - cp -r ${PROJECT}.srcs/sources_1/ip/${PROJECT}/* ip/. - cp ${PROJECT}.runs/${PROJECT}_synth_1/${PROJECT}.dcp ip/. - -clean: ## Remove all build products - rm -rf ip/* - mkdir -p ip - rm -rf ${PROJECT}.* - rm -rf component.xml - rm -rf vivado*.jou - rm -rf vivado*.log - rm -rf vivado*.str - rm -rf xgui - rm -rf .Xil - -help: ## Shows this help message - @grep -E -h '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' diff --git a/fpga/pulpissimo-nexys_video/ips/xilinx_interleaved_ram/tcl/run.tcl b/fpga/pulpissimo-nexys_video/ips/xilinx_interleaved_ram/tcl/run.tcl deleted file mode 100644 index a2e84f23..00000000 --- a/fpga/pulpissimo-nexys_video/ips/xilinx_interleaved_ram/tcl/run.tcl +++ /dev/null @@ -1,38 +0,0 @@ -set partNumber $::env(XILINX_PART) - -if [info exists ::env(BOARD)] { - set BOARD $::env(BOARD) -} else { - error "BOARD is not defined. Please source the sourceme.sh file." - exit -} -if [info exists ::env(XILINX_BOARD)] { - set boardName $::env(XILINX_BOARD) -} - -# detect target ram size -if [info exists ::env(INTERLEAVED_BANK_SIZE)] { - set INTERLEAVED_BANK_SIZE $::env(INTERLEAVED_BANK_SIZE) -} else { - set INTERLEAVED_BANK_SIZE 4096 -} - -set ipName xilinx_interleaved_ram - -create_project $ipName . -part $partNumber -set_property board_part $boardName [current_project] - -create_ip -name blk_mem_gen -vendor xilinx.com -library ip -module_name $ipName - -set_property -dict [eval list CONFIG.Use_Byte_Write_Enable {true} \ - CONFIG.Byte_Size {8} \ - CONFIG.Write_Width_A {32} \ - CONFIG.Write_Depth_A {$INTERLEAVED_BANK_SIZE} \ - CONFIG.Read_Width_A {32} \ - CONFIG.Register_PortA_Output_of_Memory_Primitives {false} \ - ] [get_ips $ipName] - -generate_target all [get_files ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] -create_ip_run [get_files -of_objects [get_fileset sources_1] ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] -launch_run -jobs 8 ${ipName}_synth_1 -wait_on_run ${ipName}_synth_1 diff --git a/fpga/pulpissimo-nexys_video/ips/xilinx_private_ram/.gitignore b/fpga/pulpissimo-nexys_video/ips/xilinx_private_ram/.gitignore deleted file mode 100644 index 5099fe9c..00000000 --- a/fpga/pulpissimo-nexys_video/ips/xilinx_private_ram/.gitignore +++ /dev/null @@ -1,21 +0,0 @@ -#Ignore vivado project files generated by the tcl script -**/.Xil/* -**/reports/* -**/*.cache/* -**/*.hw/* -**/*.ip_user_files/* -**/*.runs/* -**/*.sim/* -**/*.srcs/* -*.edf -*.xpr -*.jou -*.log - -.cxl.* - -*ip - -*_stub.v -gmon.out - diff --git a/fpga/pulpissimo-nexys_video/ips/xilinx_private_ram/Makefile b/fpga/pulpissimo-nexys_video/ips/xilinx_private_ram/Makefile deleted file mode 100644 index 4734e7ad..00000000 --- a/fpga/pulpissimo-nexys_video/ips/xilinx_private_ram/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -PROJECT:=xilinx_private_ram -VIVADO ?= vivado -VIVADOFLAGS ?= -nojournal -mode batch -source scripts/prologue.tcl -MODE=batch - -include ../../fpga-settings.mk - -.DEFAULT_GOAL:=help - -.PHONY: help all gui clean - -all: MODE=batch ## Create and synthesize the IP in batch mode. - -gui: MODE=gui ## Create and synthesize the IP in GUI mode. - -all gui: $(PROJECT).xpr - -$(PROJECT).xpr: ../../fpga-settings.mk tcl/run.tcl - make clean - $(VIVADO) -mode $(MODE) -source tcl/run.tcl - mkdir -p ip - cp -r ${PROJECT}.srcs/sources_1/ip/${PROJECT}/* ip/. - cp ${PROJECT}.runs/${PROJECT}_synth_1/${PROJECT}.dcp ip/. - -clean: ## Remove all build products - rm -rf ip/* - mkdir -p ip - rm -rf ${PROJECT}.* - rm -rf component.xml - rm -rf vivado*.jou - rm -rf vivado*.log - rm -rf vivado*.str - rm -rf xgui - rm -rf .Xil - -help: ## Shows this help message - @grep -E -h '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' diff --git a/fpga/pulpissimo-nexys_video/ips/xilinx_private_ram/tcl/run.tcl b/fpga/pulpissimo-nexys_video/ips/xilinx_private_ram/tcl/run.tcl deleted file mode 100644 index 78493b37..00000000 --- a/fpga/pulpissimo-nexys_video/ips/xilinx_private_ram/tcl/run.tcl +++ /dev/null @@ -1,38 +0,0 @@ -set partNumber $::env(XILINX_PART) - -if [info exists ::env(BOARD)] { - set BOARD $::env(BOARD) -} else { - error "BOARD is not defined. Please source the sourceme.sh file." - exit -} -if [info exists ::env(XILINX_BOARD)] { - set boardName $::env(XILINX_BOARD) -} - -# detect target ram size -if [info exists ::env(PRIVATE_BANK_SIZE)] { - set PRIVATE_BANK_SIZE $::env(PRIVATE_BANK_SIZE) -} else { - set PRIVATE_BANK_SIZE 4096 -} - -set ipName xilinx_private_ram - -create_project $ipName . -part $partNumber -set_property board_part $boardName [current_project] - -create_ip -name blk_mem_gen -vendor xilinx.com -library ip -module_name $ipName - -set_property -dict [eval list CONFIG.Use_Byte_Write_Enable {true} \ - CONFIG.Byte_Size {8} \ - CONFIG.Write_Width_A {32} \ - CONFIG.Write_Depth_A {$PRIVATE_BANK_SIZE} \ - CONFIG.Read_Width_A {32} \ - CONFIG.Register_PortA_Output_of_Memory_Primitives {false} \ - ] [get_ips $ipName] - -generate_target all [get_files ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] -create_ip_run [get_files -of_objects [get_fileset sources_1] ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] -launch_run -jobs 8 ${ipName}_synth_1 -wait_on_run ${ipName}_synth_1 diff --git a/fpga/pulpissimo-nexys_video/ips/xilinx_slow_clk_mngr/.gitignore b/fpga/pulpissimo-nexys_video/ips/xilinx_slow_clk_mngr/.gitignore deleted file mode 100644 index 5099fe9c..00000000 --- a/fpga/pulpissimo-nexys_video/ips/xilinx_slow_clk_mngr/.gitignore +++ /dev/null @@ -1,21 +0,0 @@ -#Ignore vivado project files generated by the tcl script -**/.Xil/* -**/reports/* -**/*.cache/* -**/*.hw/* -**/*.ip_user_files/* -**/*.runs/* -**/*.sim/* -**/*.srcs/* -*.edf -*.xpr -*.jou -*.log - -.cxl.* - -*ip - -*_stub.v -gmon.out - diff --git a/fpga/pulpissimo-nexys_video/ips/xilinx_slow_clk_mngr/Makefile b/fpga/pulpissimo-nexys_video/ips/xilinx_slow_clk_mngr/Makefile deleted file mode 100644 index e3ba47bf..00000000 --- a/fpga/pulpissimo-nexys_video/ips/xilinx_slow_clk_mngr/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -PROJECT:=xilinx_slow_clk_mngr -VIVADO ?= vivado -VIVADOFLAGS ?= -nojournal -mode batch -source scripts/prologue.tcl -MODE=batch - -include ../../fpga-settings.mk - -.DEFAULT_GOAL:=help - -.PHONY: help all gui clean - -all: MODE=batch ## Create and synthesize the IP in batch mode. - -gui: MODE=gui ## Create and synthesize the IP in GUI mode. - -all gui: $(PROJECT).xpr - -$(PROJECT).xpr: ../../fpga-settings.mk tcl/run.tcl - make clean - $(VIVADO) -mode $(MODE) -source tcl/run.tcl - mkdir -p ip - cp -r ${PROJECT}.srcs/sources_1/ip/${PROJECT}/* ip/. - cp ${PROJECT}.runs/${PROJECT}_synth_1/${PROJECT}.dcp ip/. - -clean: ## Remove all build products - rm -rf ip/* - mkdir -p ip - rm -rf ${PROJECT}.* - rm -rf component.xml - rm -rf vivado*.jou - rm -rf vivado*.log - rm -rf vivado*.str - rm -rf xgui - rm -rf .Xil - -help: ## Shows this help message - @grep -E -h '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' diff --git a/fpga/pulpissimo-nexys_video/ips/xilinx_slow_clk_mngr/tcl/run.tcl b/fpga/pulpissimo-nexys_video/ips/xilinx_slow_clk_mngr/tcl/run.tcl deleted file mode 100644 index 1f96dc03..00000000 --- a/fpga/pulpissimo-nexys_video/ips/xilinx_slow_clk_mngr/tcl/run.tcl +++ /dev/null @@ -1,45 +0,0 @@ -set partNumber $::env(XILINX_PART) - -if [info exists ::env(BOARD)] { - set BOARD $::env(BOARD) -} else { - error "BOARD is not defined. Please source the sourceme.sh file." - exit -} -if [info exists ::env(XILINX_BOARD)] { - set boardName $::env(XILINX_BOARD) -} - -# detect target clock -if [info exists ::env(SLOW_CLK_PERIOD_NS)] { - set SLOW_CLK_PERIOD_NS $::env(SLOW_CLK_PERIOD_NS) -} else { - set SLOW_CLK_PERIOD_NS 30517 -} - -# Multiply frequency by 250 as there is a clock divider (by 250) after the -# slow_clk_mngr since the MMCMs do not support clocks slower then 4.69 MHz. -set SLOW_CLK_FREQ_MHZ [expr 1000 * 256 / $SLOW_CLK_PERIOD_NS] - -set ipName xilinx_slow_clk_mngr - -create_project $ipName . -part $partNumber -set_property board_part $boardName [current_project] - -create_ip -name clk_wiz -vendor xilinx.com -library ip -module_name $ipName - -set_property -dict [eval list CONFIG.PRIM_IN_FREQ {100.000} \ - CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {$SLOW_CLK_FREQ_MHZ} \ - CONFIG.USE_SAFE_CLOCK_STARTUP {true} \ - CONFIG.USE_LOCKED {false} \ - CONFIG.RESET_TYPE {ACTIVE_LOW} \ - CONFIG.CLKIN1_JITTER_PS {50.0} \ - CONFIG.FEEDBACK_SOURCE {FDBK_AUTO} \ - CONFIG.RESET_PORT {resetn} \ - ] [get_ips $ipName] - - -generate_target all [get_files ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] -create_ip_run [get_files -of_objects [get_fileset sources_1] ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] -launch_run -jobs 8 ${ipName}_synth_1 -wait_on_run ${ipName}_synth_1 diff --git a/fpga/pulpissimo-nexys_video/openocd-nexys_video.cfg b/fpga/pulpissimo-nexys_video/openocd-nexys_video.cfg deleted file mode 100644 index b0de8583..00000000 --- a/fpga/pulpissimo-nexys_video/openocd-nexys_video.cfg +++ /dev/null @@ -1,46 +0,0 @@ -adapter_khz 1000 - -interface ftdi -ftdi_vid_pid 0x0403 0x6010 - -# Channel 1 is taken by Xilinx JTAG -ftdi_channel 0 - -# links: -# http://openocd.org/doc-release/html/Debug-Adapter-Configuration.html -# -# Bit MPSSE FT2232 JTAG Type Description -# Bit0 TCK ADBUS0 TCK Out Clock Signal Output -# Bit1 TDI ADBUS1 TDI Out Serial Data Out -# Bit2 TDO ADBUS2 TDO In Serial Data In -# Bit3 TMS ADBUS3 TMS Out Select Signal Out -# Bit4 GPIOL0 ADBUS4 nTRST In/Out General Purpose I/O -# this corresponds to the following in/out layout, with TMS initially set to 1 -ftdi_layout_init 0x0018 0x001b -# we only have to specify nTRST, the others are assigned correctly by default -ftdi_layout_signal nTRST -ndata 0x0010 - -set _CHIPNAME riscv - -jtag newtap $_CHIPNAME unknown0 -irlen 5 -expected-id 0x10102001 -jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x249511C3 - -set _TARGETNAME $_CHIPNAME.cpu -target create $_TARGETNAME riscv -chain-position $_TARGETNAME -coreid 0x3e0 - -gdb_report_data_abort enable -gdb_report_register_access_error enable - -riscv set_reset_timeout_sec 120 -riscv set_command_timeout_sec 120 - -# prefer to use sba for system bus access -riscv set_prefer_sba on - -# dump jtag chain -scan_chain - - -init -halt -echo "Ready for Remote Connections" diff --git a/fpga/pulpissimo-nexys_video/rtl/fpga_bootrom.sv b/fpga/pulpissimo-nexys_video/rtl/fpga_bootrom.sv deleted file mode 100644 index 79d78b3f..00000000 --- a/fpga/pulpissimo-nexys_video/rtl/fpga_bootrom.sv +++ /dev/null @@ -1,36 +0,0 @@ -//----------------------------------------------------------------------------- -// Title : FPGA Bootrom for PULPissimo -//----------------------------------------------------------------------------- -// File : fpga_bootrom.sv -// Author : Manuel Eggimann -// Created : 29.05.2019 -//----------------------------------------------------------------------------- -// Description : -// Mockup bootrom that keeps returning jal x0,0 to trap the core in an infinite -// loop until the debug module takes over control. -//----------------------------------------------------------------------------- -// Copyright (C) 2013-2019 ETH Zurich, University of Bologna -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. -//----------------------------------------------------------------------------- - - -module fpga_bootrom - #( - parameter ADDR_WIDTH=32, - parameter DATA_WIDTH=32 - ) - ( - input logic CLK, - input logic CEN, - input logic [ADDR_WIDTH-1:0] A, - output logic [DATA_WIDTH-1:0] Q - ); - assign Q = 32'h0000006f; //jal x0,0 -endmodule : fpga_bootrom diff --git a/fpga/pulpissimo-nexys_video/rtl/fpga_clk_gen.sv b/fpga/pulpissimo-nexys_video/rtl/fpga_clk_gen.sv deleted file mode 100644 index 2ad9a8eb..00000000 --- a/fpga/pulpissimo-nexys_video/rtl/fpga_clk_gen.sv +++ /dev/null @@ -1,74 +0,0 @@ -//----------------------------------------------------------------------------- -// Title : FPGA CLK Gen for PULPissimo -// ----------------------------------------------------------------------------- -// File : fpga_clk_gen.sv Author : Manuel Eggimann -// Created : 17.05.2019 -// ----------------------------------------------------------------------------- -// Description : Instantiates Xilinx clocking wizard IP to generate 2 output -// clocks. Currently, the clock is not dynamicly reconfigurable and all -// configuration requests are acknowledged without any effect. -// ----------------------------------------------------------------------------- -// Copyright (C) 2013-2019 ETH Zurich, University of Bologna Copyright and -// related rights are licensed under the Solderpad Hardware License, Version -// 0.51 (the "License"); you may not use this file except in compliance with the -// License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law or -// agreed to in writing, software, hardware and materials distributed under this -// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS -// OF ANY KIND, either express or implied. See the License for the specific -// language governing permissions and limitations under the License. -// ----------------------------------------------------------------------------- - - -module fpga_clk_gen ( - input logic ref_clk_i, - input logic rstn_glob_i, - input logic test_mode_i, - input logic shift_enable_i, - output logic soc_clk_o, - output logic per_clk_o, - output logic cluster_clk_o, - output logic soc_cfg_lock_o, - input logic soc_cfg_req_i, - output logic soc_cfg_ack_o, - input logic [1:0] soc_cfg_add_i, - input logic [31:0] soc_cfg_data_i, - output logic [31:0] soc_cfg_r_data_o, - input logic soc_cfg_wrn_i, - output logic per_cfg_lock_o, - input logic per_cfg_req_i, - output logic per_cfg_ack_o, - input logic [1:0] per_cfg_add_i, - input logic [31:0] per_cfg_data_i, - output logic [31:0] per_cfg_r_data_o, - input logic per_cfg_wrn_i, - output logic cluster_cfg_lock_o, - input logic cluster_cfg_req_i, - output logic cluster_cfg_ack_o, - input logic [1:0] cluster_cfg_add_i, - input logic [31:0] cluster_cfg_data_i, - output logic [31:0] cluster_cfg_r_data_o, - input logic cluster_cfg_wrn_i - ); - - logic s_locked; - - xilinx_clk_mngr i_clk_manager - ( - .resetn(rstn_glob_i), - .clk_in1(ref_clk_i), - .clk_out1(soc_clk_o), - .clk_out2(per_clk_o), - .locked(s_locked) - ); - - assign soc_cfg_lock_o = s_locked; - assign per_cfg_lock_o = s_locked; - - assign soc_cfg_ack_o = 1'b1; //Always acknowledge without doing anything for now - assign per_cfg_ack_o = 1'b1; - - assign soc_cfg_r_data_o = 32'hdeadda7a; - assign per_cfg_r_data_o = 32'hdeadda7a; - -endmodule : fpga_clk_gen diff --git a/fpga/pulpissimo-nexys_video/rtl/fpga_interleaved_ram.sv b/fpga/pulpissimo-nexys_video/rtl/fpga_interleaved_ram.sv deleted file mode 100644 index 7d52e5d8..00000000 --- a/fpga/pulpissimo-nexys_video/rtl/fpga_interleaved_ram.sv +++ /dev/null @@ -1,57 +0,0 @@ -//----------------------------------------------------------------------------- -// Title : FPGA Interleaved RAM Bank for PULPissimo -// ----------------------------------------------------------------------------- -// File : fpga_interleaved_ram.sv Author : Manuel Eggimann -// Created : 20.05.2019 -// ----------------------------------------------------------------------------- -// Description : Instantiated block ram generator IP to replace the SRAM banks -// in the interleaved region of L2. Since Xilinx LogicoreIP are not customizable -// via parameters, the bank size selected in l2_ram_multibank must match the one -// used in the TCL script for IP generation. -// ----------------------------------------------------------------------------- -// Copyright (C) 2013-2019 ETH Zurich, University of Bologna Copyright and -// related rights are licensed under the Solderpad Hardware License, Version -// 0.51 (the "License"); you may not use this file except in compliance with the -// License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law or -// agreed to in writing, software, hardware and materials distributed under this -// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS -// OF ANY KIND, either express or implied. See the License for the specific -// language governing permissions and limitations under the License. -// ----------------------------------------------------------------------------- - -module fpga_interleaved_ram - #( - parameter ADDR_WIDTH=12 - ) ( - input logic clk_i, - input logic rst_ni, - input logic csn_i, - input logic wen_i, - input logic [3:0] be_i, - input logic [ADDR_WIDTH-1:0] addr_i, - input logic [31:0] wdata_i, - output logic [31:0] rdata_o - ); - - logic [3:0] wea; - - always_comb begin - if (wen_i == 1'b0) begin - wea = be_i; - end else begin - wea = '0; - end - end - - xilinx_interleaved_ram i_xilinx_interleaved_ram - ( - .clka(clk_i), - .ena(~csn_i), - .wea(wea), - .addra(addr_i), - .dina(wdata_i), - .douta(rdata_o) - ); - -endmodule : fpga_interleaved_ram diff --git a/fpga/pulpissimo-nexys_video/rtl/fpga_private_ram.sv b/fpga/pulpissimo-nexys_video/rtl/fpga_private_ram.sv deleted file mode 100644 index 05244931..00000000 --- a/fpga/pulpissimo-nexys_video/rtl/fpga_private_ram.sv +++ /dev/null @@ -1,57 +0,0 @@ -//----------------------------------------------------------------------------- -// Title : FPGA Private RAM Bank for PULPissimo -// ----------------------------------------------------------------------------- -// File : fpga_private_ram.sv Author : Manuel Eggimann -// Created : 20.05.2019 -// ----------------------------------------------------------------------------- -// Description : Instantiated block ram generator IP to replace the SRAM banks -// in the private region of L2. Since Xilinx LogicoreIP are not customizable -// via parameters, the bank size selected in l2_ram_multibank must match the one -// used in the TCL script for IP generation. -// ----------------------------------------------------------------------------- -// Copyright (C) 2013-2019 ETH Zurich, University of Bologna Copyright and -// related rights are licensed under the Solderpad Hardware License, Version -// 0.51 (the "License"); you may not use this file except in compliance with the -// License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law or -// agreed to in writing, software, hardware and materials distributed under this -// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS -// OF ANY KIND, either express or implied. See the License for the specific -// language governing permissions and limitations under the License. -// ----------------------------------------------------------------------------- - -module fpga_private_ram - #( - parameter ADDR_WIDTH=12 - ) ( - input logic clk_i, - input logic rst_ni, - input logic csn_i, - input logic wen_i, - input logic [3:0] be_i, - input logic [ADDR_WIDTH-1:0] addr_i, - input logic [31:0] wdata_i, - output logic [31:0] rdata_o - ); - - logic [3:0] wea; - - always_comb begin - if (wen_i == 1'b0) begin - wea = be_i; - end else begin - wea = '0; - end - end - - xilinx_private_ram i_xilinx_private_ram - ( - .clka(clk_i), - .ena(~csn_i), - .wea(wea), - .addra(addr_i), - .dina(wdata_i), - .douta(rdata_o) - ); - -endmodule : fpga_private_ram diff --git a/fpga/pulpissimo-nexys_video/rtl/fpga_slow_clk_gen.sv b/fpga/pulpissimo-nexys_video/rtl/fpga_slow_clk_gen.sv deleted file mode 100644 index f3db58f4..00000000 --- a/fpga/pulpissimo-nexys_video/rtl/fpga_slow_clk_gen.sv +++ /dev/null @@ -1,82 +0,0 @@ -//----------------------------------------------------------------------------- -// Title : FPGA slow clk generator for PULPissimo -//----------------------------------------------------------------------------- -// File : fpga_slow_clk_gen.sv -// Author : Manuel Eggimann -// Created : 20.05.2019 -//----------------------------------------------------------------------------- -// Description : Instantiates Xilinx Clocking Wizard IP to generate the slow_clk -// signal since for certain boards the available clock sources are to fast to -// use directly. -//----------------------------------------------------------------------------- -// Copyright (C) 2013-2019 ETH Zurich, University of Bologna -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. -//----------------------------------------------------------------------------- - - -module fpga_slow_clk_gen - #( - parameter CLK_DIV_VALUE = 256 //The xilinx_slow_clk_mngr is supposed to - //generate an 8.3886MHz clock. We need to divide it - //by 256 to arrive to a 32.768kHz clock - ) - (input logic ref_clk_i, - input logic rst_ni, - output logic slow_clk_o - ); - - - - localparam COUNTER_WIDTH = $clog2(CLK_DIV_VALUE); - - - //Create clock divider using BUFGCE cells as the PLL/MMCM cannot generate clocks - //slower than 4.69 MHz and we need 32.768kHz - - logic [COUNTER_WIDTH-1:0] clk_counter_d, clk_counter_q; - logic clock_gate_en; - - logic intermmediate_clock; - - xilinx_slow_clk_mngr i_slow_clk_mngr - ( - .resetn(rst_ni), - .clk_in1(ref_clk_i), - .clk_out1(intermmediate_clock) - ); - - - - always_comb begin - if (clk_counter_q == CLK_DIV_VALUE-1) begin - clk_counter_d = '0; - clock_gate_en = 1'b1; - end else begin - clk_counter_d = clk_counter_q + 1; - clock_gate_en = 1'b0; - end - end - - always_ff @(posedge intermmediate_clock, negedge rst_ni) begin - if (!rst_ni) begin - clk_counter_q <= '0; - end else begin - clk_counter_q <= clk_counter_d; - end - end - - BUFGCE i_clock_gate - ( - .I(intermmediate_clock), - .CE(clock_gate_en), - .O(slow_clk_o) - ); - -endmodule : fpga_slow_clk_gen diff --git a/fpga/pulpissimo-nexys_video/rtl/pad_functional_xilinx.sv b/fpga/pulpissimo-nexys_video/rtl/pad_functional_xilinx.sv deleted file mode 100644 index a3ca1cde..00000000 --- a/fpga/pulpissimo-nexys_video/rtl/pad_functional_xilinx.sv +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2018 ETH Zurich and University of Bologna. -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - - -module pad_functional_pd -( - input logic OEN, - input logic I, - output logic O, - input logic PEN, - inout logic PAD -); - - (* PULLDOWN = "YES" *) - IOBUF iobuf_i ( - .T ( OEN ), - .I ( I ), - .O ( O ), - .IO( PAD ) - ); - -endmodule - -module pad_functional_pu -( - input logic OEN, - input logic I, - output logic O, - input logic PEN, - inout logic PAD -); - - (* PULLUP = "YES" *) - IOBUF iobuf_i ( - .T ( OEN ), - .I ( I ), - .O ( O ), - .IO( PAD ) - ); - -endmodule \ No newline at end of file diff --git a/fpga/pulpissimo-nexys_video/rtl/pulp_clock_gating_xilinx.sv b/fpga/pulpissimo-nexys_video/rtl/pulp_clock_gating_xilinx.sv deleted file mode 100644 index 1e2db2d1..00000000 --- a/fpga/pulpissimo-nexys_video/rtl/pulp_clock_gating_xilinx.sv +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2018 ETH Zurich and University of Bologna. -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -module pulp_clock_gating - ( - input logic clk_i, - input logic en_i, - input logic test_en_i, - output logic clk_o - ); - - assign clk_o = clk_i; - -endmodule diff --git a/fpga/pulpissimo-nexys_video/rtl/xilinx_pulpissimo.v b/fpga/pulpissimo-nexys_video/rtl/xilinx_pulpissimo.v deleted file mode 100644 index 8c9c4870..00000000 --- a/fpga/pulpissimo-nexys_video/rtl/xilinx_pulpissimo.v +++ /dev/null @@ -1,144 +0,0 @@ -//----------------------------------------------------------------------------- -// Title : PULPissimo Verilog Wrapper -//----------------------------------------------------------------------------- -// File : xilinx_pulpissimo.v -// Author : Manuel Eggimann -// Created : 21.05.2019 -//----------------------------------------------------------------------------- -// Description : -// Verilog Wrapper of PULPissimo to use the module within Xilinx IP integrator. -//----------------------------------------------------------------------------- -// Copyright (C) 2013-2019 ETH Zurich, University of Bologna -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. -//----------------------------------------------------------------------------- - -module xilinx_pulpissimo - ( - input wire sys_clk, - -// inout wire pad_spim_sdio0, - inout wire pad_spim_sdio1, - inout wire pad_spim_sdio2, - inout wire pad_spim_sdio3, - inout wire pad_spim_csn0, - inout wire pad_spim_sck, - - inout wire pad_uart_rx, - inout wire pad_uart_tx, - - inout wire led0_o, //Mapped to spim_csn1 - inout wire led1_o, //Mapped to cam_pclk - inout wire led2_o, //Mapped to cam_hsync - inout wire led3_o, //Mapped to cam_data0 - - inout wire switch0_i, //Mapped to cam_data1 - inout wire switch1_i, //Mapped to cam_data2 - - inout wire btnc_i, //Mapped to cam_data3 - inout wire btnd_i, //Mapped to cam_data4 - inout wire btnl_i, //Mapped to cam_data5 - inout wire btnr_i, //Mapped to cam_data6 - inout wire btnu_i, //Mapped to cam_data7 - - inout wire oled_spim_sck_o, //Mapped to spim_sck - inout wire oled_spim_mosi_o, //Mapped to spim_sdio0 - inout wire oled_rst_o, //Mapped to i2s0_sck - inout wire oled_dc_o, //Mapped to i2s0_ws - inout wire oled_vbat_o, // Mapped to i2s0_sdi - inout wire oled_vdd_o, // Mapped to i2s1_sdi - - inout wire sdio_reset_o, //Reset signal for SD card need to be driven low to - //power the onboard sd-card. Mapped to cam_vsync. - inout wire pad_sdio_clk, - inout wire pad_sdio_cmd, - inout wire pad_sdio_data0, - inout wire pad_sdio_data1, - inout wire pad_sdio_data2, - inout wire pad_sdio_data3, - - inout wire pad_i2c0_sda, - inout wire pad_i2c0_scl, - - input wire pad_reset_n, - inout wire pad_bootsel, - - input wire pad_jtag_tck, - input wire pad_jtag_tdi, - output wire pad_jtag_tdo, - input wire pad_jtag_tms, - input wire pad_jtag_trst - ); - - localparam CORE_TYPE = 0; // 0 for RISCY, 1 for IBEX RV32IMC (formerly ZERORISCY), 2 for IBEX RV32EC (formerly MICRORISCY) - localparam USE_FPU = 1; - localparam USE_HWPE = 0; - - wire ref_clk; - - // Input clock buffer - IBUFG - #( - .IOSTANDARD("LVCMOS33"), - .IBUF_LOW_PWR("FALSE")) - i_sysclk_iobuf - ( - .I(sys_clk), - .O(ref_clk) - ); - - pulpissimo - #(.CORE_TYPE(CORE_TYPE), - .USE_FPU(USE_FPU), - .USE_HWPE(USE_HWPE) - ) i_pulpissimo - ( - .pad_spim_sdio0(oled_spim_mosi_o), - .pad_spim_sdio1(pad_spim_sdio1), - .pad_spim_sdio2(pad_spim_sdio2), - .pad_spim_sdio3(pad_spim_sdio3), - .pad_spim_csn0(pad_spim_csn0), - .pad_spim_csn1(led0_o), - .pad_spim_sck(oled_spim_sck_o), - .pad_uart_rx(pad_uart_rx), - .pad_uart_tx(pad_uart_tx), - .pad_cam_pclk(led1_o), - .pad_cam_hsync(led2_o), - .pad_cam_data0(led3_o), - .pad_cam_data1(switch0_i), - .pad_cam_data2(switch1_i), - .pad_cam_data3(btnc_i), - .pad_cam_data4(btnd_i), - .pad_cam_data5(btnl_i), - .pad_cam_data6(btnr_i), - .pad_cam_data7(btnu_i), - .pad_cam_vsync(sdio_reset_o), - .pad_sdio_clk(pad_sdio_clk), - .pad_sdio_cmd(pad_sdio_cmd), - .pad_sdio_data0(pad_sdio_data0), - .pad_sdio_data1(pad_sdio_data1), - .pad_sdio_data2(pad_sdio_data2), - .pad_sdio_data3(pad_sdio_data3), - .pad_i2c0_sda(pad_i2c0_sda), - .pad_i2c0_scl(pad_i2c0_scl), - .pad_i2s0_sck(oled_rst_o), - .pad_i2s0_ws(oled_dc_o), - .pad_i2s0_sdi(oled_vbat_o), - .pad_i2s1_sdi(oled_vdd_o), - .pad_reset_n(pad_reset_n), - .pad_jtag_tck(pad_jtag_tck), - .pad_jtag_tdi(pad_jtag_tdi), - .pad_jtag_tdo(pad_jtag_tdo), - .pad_jtag_tms(pad_jtag_tms), - .pad_jtag_trst(pad_jtag_trst), - .pad_xtal_in(ref_clk), - .pad_bootsel() - ); - -endmodule diff --git a/fpga/pulpissimo-nexys_video/tcl/.gitignore b/fpga/pulpissimo-nexys_video/tcl/.gitignore deleted file mode 100644 index 587a0fa6..00000000 --- a/fpga/pulpissimo-nexys_video/tcl/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -#Ignore tcl files generated by ipstools -ips_add_files.tcl -ips_inc_dirs.tcl -ips_src_files.tcl -rtl_add_files.tcl -rtl_src_files.tcl \ No newline at end of file diff --git a/fpga/pulpissimo-nexys_video/tcl/messages.tcl b/fpga/pulpissimo-nexys_video/tcl/messages.tcl deleted file mode 100644 index e8bfaf90..00000000 --- a/fpga/pulpissimo-nexys_video/tcl/messages.tcl +++ /dev/null @@ -1,13 +0,0 @@ -# sets up Vivado messages in a more sensible way - -set_msg_config -id {[Synth 8-3352]} -new_severity "critical warning" -set_msg_config -id {[Synth 8-350]} -new_severity "critical warning" -set_msg_config -id {[Synth 8-2490]} -new_severity "warning" -set_msg_config -id {[Synth 8-2306]} -new_severity "info" -set_msg_config -id {[Synth 8-3331]} -new_severity "critical warning" -set_msg_config -id {[Synth 8-3332]} -new_severity "info" -set_msg_config -id {[Synth 8-2715]} -new_severity "error" -set_msg_config -id {[Opt 31-35]} -new_severity "info" -set_msg_config -id {[Opt 31-32]} -new_severity "info" -set_msg_config -id {[Shape Builder 18-119]} -new_severity "warning" -set_msg_config -id {[Filemgmt 20-742]} -new_severity "error" diff --git a/fpga/pulpissimo-nexys_video/tcl/run.tcl b/fpga/pulpissimo-nexys_video/tcl/run.tcl deleted file mode 100644 index 88b044ca..00000000 --- a/fpga/pulpissimo-nexys_video/tcl/run.tcl +++ /dev/null @@ -1,126 +0,0 @@ -# detect board -if [info exists ::env(BOARD)] { - set BOARD $::env(BOARD) -} else { - puts "Please include 'fpga-settings.mk' in your Makefile to setup necessary environment variables." - exit -} -if [info exists ::env(XILINX_BOARD)] { - set XILINX_BOARD $::env(XILINX_BOARD) -} - -set PROJECT pulpissimo-$BOARD -set RTL ../../../rtl -set IPS ../../../ips -set CONSTRS constraints - -# create project -create_project $PROJECT . -force -part $::env(XILINX_PART) -set_property board_part $XILINX_BOARD [current_project] - -# set up meaningfull errors -source tcl/messages.tcl - -# set up includes -source ../pulpissimo/tcl/ips_inc_dirs.tcl -set_property include_dirs $INCLUDE_DIRS [current_fileset] -set_property include_dirs $INCLUDE_DIRS [current_fileset -simset] - -# setup and add IP source files -source ../pulpissimo/tcl/ips_src_files.tcl -source ../pulpissimo/tcl/ips_add_files.tcl - -# setup and add RTL source files -source ../pulpissimo/tcl/rtl_src_files.tcl -source ../pulpissimo/tcl/rtl_add_files.tcl - -# Override IPSApprox default variables -set FPGA_RTL rtl -set FPGA_IPS ips - -# remove duplicate incompatible modules -remove_files $IPS/pulp_soc/rtl/components/axi_slice_dc_slave_wrap.sv -remove_file $IPS/pulp_soc/rtl/components/axi_slice_dc_master_wrap.sv -remove_file $IPS/tech_cells_generic/pad_functional_xilinx.sv - -# Set Verilog Defines. -set DEFINES "FPGA_TARGET_XILINX=1 PULP_FPGA_EMUL=1 AXI4_XCHECK_OFF=1" -set_property verilog_define $DEFINES [current_fileset] - -# detect target clock -if [info exists ::env(FC_CLK_PERIOD_NS)] { - set FC_CLK_PERIOD_NS $::env(FC_CLK_PERIOD_NS) -} else { - set FC_CLK_PERIOD_NS 10.000 -} -set CLK_HALFPERIOD_NS [expr ${FC_CLK_PERIOD_NS} / 2.0] - -# Add toplevel wrapper -add_files -norecurse $FPGA_RTL/xilinx_pulpissimo.v - -# Add Xilinx IPs -read_ip $FPGA_IPS/xilinx_clk_mngr/ip/xilinx_clk_mngr.xci -read_ip $FPGA_IPS/xilinx_slow_clk_mngr/ip/xilinx_slow_clk_mngr.xci -read_ip $FPGA_IPS/xilinx_interleaved_ram/ip/xilinx_interleaved_ram.xci -read_ip $FPGA_IPS/xilinx_private_ram/ip/xilinx_private_ram.xci - -# Add wrappers and xilinx specific techcells -add_files -norecurse $FPGA_RTL/fpga_clk_gen.sv -add_files -norecurse $FPGA_RTL/fpga_slow_clk_gen.sv -add_files -norecurse $FPGA_RTL/fpga_interleaved_ram.sv -add_files -norecurse $FPGA_RTL/fpga_private_ram.sv -add_files -norecurse $FPGA_RTL/fpga_bootrom.sv -add_files -norecurse $FPGA_RTL/pad_functional_xilinx.sv -add_files -norecurse $FPGA_RTL/pulp_clock_gating_xilinx.sv - - -# set pulpissimo as top -set_property top xilinx_pulpissimo [current_fileset]; # - -# needed only if used in batch mode -update_compile_order -fileset sources_1 - -# Add constraints -add_files -fileset constrs_1 -norecurse $CONSTRS/$BOARD.xdc - -# Elaborate design -synth_design -rtl -name rtl_1 -sfcu;# sfcu -> run synthesis in single file compilation unit mode - -# Launch synthesis -set_property STEPS.SYNTH_DESIGN.ARGS.FLATTEN_HIERARCHY none [get_runs synth_1] -set_property -name {STEPS.SYNTH_DESIGN.ARGS.MORE OPTIONS} -value -sfcu -objects [get_runs synth_1] ;# Use single file compilation unit mode to prevent issues with import pkg::* statements in the codebase -launch_runs synth_1 -jobs 8 -wait_on_run synth_1 -open_run synth_1 -name netlist_1 -set_property needs_refresh false [get_runs synth_1] - -# Remove unused IOBUF cells in padframe (they are not optimized away since the -# pad driver also drives the input creating a datapath from pad_xy_o to pad_xy_i -# ) -remove_cell i_pulpissimo/pad_frame_i/padinst_bootsel - - -# Launch Implementation - -# set for RuntimeOptimized implementation -set_property "steps.opt_design.args.directive" "RuntimeOptimized" [get_runs impl_1] -set_property "steps.place_design.args.directive" "RuntimeOptimized" [get_runs impl_1] -set_property "steps.route_design.args.directive" "RuntimeOptimized" [get_runs impl_1] - -set_property STEPS.WRITE_BITSTREAM.ARGS.BIN_FILE true [get_runs impl_1] -set_property config_mode SPIx4 [current_design] - -launch_runs impl_1 -jobs 8 -wait_on_run impl_1 -launch_runs impl_1 -to_step write_bitstream -wait_on_run impl_1 - -open_run impl_1 - -# Generate reports -exec mkdir -p reports/ -exec rm -rf reports/* -check_timing -file reports/$PROJECT.check_timing.rpt -report_timing -max_paths 100 -nworst 100 -delay_type max -sort_by slack -file reports/$PROJECT.timing_WORST_100.rpt -report_timing -nworst 1 -delay_type max -sort_by group -file reports/$PROJECT.timing.rpt -report_utilization -hierarchical -file reports/$PROJECT.utilization.rpt diff --git a/fpga/pulpissimo-zcu104/.gitignore b/fpga/pulpissimo-zcu104/.gitignore deleted file mode 100644 index 3f35710f..00000000 --- a/fpga/pulpissimo-zcu104/.gitignore +++ /dev/null @@ -1,22 +0,0 @@ -#Ignore vivado project files generated by the tcl script -**/.Xil/* -**/reports/* -**/*.cache/* -**/*.hw/* -**/*.ip_user_files/* -**/*.runs/* -**/*.sim/* -**/*.srcs/* -*.edf -*.xpr -*.jou -*.log - -.cxl.* - -*_stub.v -gmon.out - -/pulpissimo/**/pulpissimo.bit - -**/xdc/constraints.xdc diff --git a/fpga/pulpissimo-zcu104/Makefile b/fpga/pulpissimo-zcu104/Makefile deleted file mode 100644 index b18f05e8..00000000 --- a/fpga/pulpissimo-zcu104/Makefile +++ /dev/null @@ -1,44 +0,0 @@ -PROJECT:=pulpissimo_zcu104 -VIVADO ?= vivado -VIVADOFLAGS ?= -nojournal -mode batch -source scripts/prologue.tcl - -include fpga-settings.mk - -.DEFAULT_GOAL:=help - -.PHONY: help all gui ips clean-ips clk clean-clk ram clean-ram clean - -all: ips ## Generate the bitstream for pulpissimo with vivado in batch mode. The vivado invocation command may be overriden with the env variable VIVADO. - $(VIVADO) -mode batch -source tcl/run.tcl - -gui: ips ## Generates the bitstream for pulpissimo with vivado in GUI mode. The vivado invocation command may be overriden with the env variable VIVADO. - $(VIVADO) -mode gui -source tcl/run.tcl & - -ips: clk ram ## Synthesizes necessary xilinx IP - -clean-ips: clean-clk clean-ram ## Clean all IPs - -clk: ## Synthesizes the Xilinx Clocking Manager IPs - cd ips/xilinx_clk_mngr; make all - cd ips/xilinx_slow_clk_mngr; make all - -clean-clk: ## Removes all Clocking Wizard IP outputs - cd ips/xilinx_clk_mngr; make clean - cd ips/xilinx_slow_clk_mngr; make clean - -ram: ## Synthesizes the Xilinx Block Memory Generator IPs for PULPissimo's L2 Ram - cd ips/xilinx_interleaved_ram; make all - cd ips/xilinx_private_ram; make all - -clean-ram: ## Removes all Block Ram IP outputs related to l2 ram - cd ips/xilinx_interleaved_ram; make clean - cd ips/xilinx_private_ram; make clean - -clean: ## Removes all bitstreams, *.log files and vivado related files (rm -rf vivado*) - rm -rf ${PROJECT}.*[^'bit'] - rm -rf ${PROJECT}.*[^'bin'] - rm -rf *.log - rm -rf vivado* - -help: - @grep -E -h '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' diff --git a/fpga/pulpissimo-zcu104/README.md b/fpga/pulpissimo-zcu104/README.md deleted file mode 100644 index 02aa1fb0..00000000 --- a/fpga/pulpissimo-zcu104/README.md +++ /dev/null @@ -1,52 +0,0 @@ -# PULPissimo on the Xilinx ZCU104 Board -[\[Datasheet\]](https://www.xilinx.com/support/documentation/boards_and_kits/zcu104/ug1267-zcu104-eval-bd.pdf) - -## Bitstream Generation -In the fpga folder, run -```Shell -make zcu104 -``` -which will generate `pulpissimo_zcu104.bit`. -Use Vivado to load it into the FPGA. - -## Default SoC and Core Frequencies - -By default the clock generating IPs are synthesized to provide the following frequencies to PULPissimo: - -| Clock Domain | Default Frequency on ZCU104 board | -|----------------|------------------------------------| -| Core Frequency | 20 MHz | -| SoC Frequency | 10 MHz | - - -## Peripherals -Most peripherals of are connected to the ARM processing system domain of the SoC and cannot be used from the programmable logic domain. -The peripherals available to PULPissimo are thus very limited. - -### Reset Button -The CPU RESET button (SW20) resets the RISC-V CPU. - -### UART -PULPissimo's UART port is mapped to Channel D of the FT4232HL chip. -When connecting the board to a computer using the USB/JTAG/UART micro-USB connector (J164), it is the last of the four detected serial devices. - -### JTAG -Unfortunately, only one channel of the FT4232HL chip is connected to the programmable logic domain. -Since we are using that channel for UART, the micro-USB connector on the board cannot be used to communicate with the RISC-V debug module over JTAG. -Instead, you need to connect a separate JTAG adapter to the GPIO port (PMOD0 header) of the board: - -| JTAG Signal | FPGA Port | J55 Pin | -|-------------|-----------|----------| -| tms | PMOD0_0 | Pin 1 | -| tdi | PMOD0_1 | Pin 3 | -| tdo | PMOD0_2 | Pin 5 | -| tck | PMOD0_3 | Pin 7 | -| gnd | GND | Pin 9 | -| vdd | 3V3 | Pin 11 | - -An OpenOCD configuration file for the Digilent JTAG-HS1 adapter is included. -To use it, run - -```Shell -$OPENOCD/bin/openocd -f pulpissimo/home/meggiman/projects/pulp/pulpissimo/fpga/pulpissimo-zcu104/openocd-zcu104-digilent-jtag-hs1.cfg -``` diff --git a/fpga/pulpissimo-zcu104/constraints/zcu104.xdc b/fpga/pulpissimo-zcu104/constraints/zcu104.xdc deleted file mode 100644 index 7ce80166..00000000 --- a/fpga/pulpissimo-zcu104/constraints/zcu104.xdc +++ /dev/null @@ -1,128 +0,0 @@ -####################################### -# _______ _ _ # -# |__ __(_) (_) # -# | | _ _ __ ___ _ _ __ __ _ # -# | | | | '_ ` _ \| | '_ \ / _` | # -# | | | | | | | | | | | | | (_| | # -# |_| |_|_| |_| |_|_|_| |_|\__, | # -# __/ | # -# |___/ # -####################################### - - -#Create constraint for the clock input of the zcu104 board -create_clock -period 8.000 -name ref_clk [get_ports ref_clk_p] - -#I2S and CAM interface are not used in this FPGA port. Set constraints to -#disable the clock -set_case_analysis 0 i_pulpissimo/safe_domain_i/cam_pclk_o -set_case_analysis 0 i_pulpissimo/safe_domain_i/i2s_slave_sck_o -#set_input_jitter tck 1.000 - -## JTAG -create_clock -period 100.000 -name tck -waveform {0.000 50.000} [get_ports pad_jtag_tck] -set_input_jitter tck 1.000 -set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets pad_jtag_tck_IBUF_inst/O] - - -# minimize routing delay -set_input_delay -clock tck -clock_fall 5.000 [get_ports pad_jtag_tdi] -set_input_delay -clock tck -clock_fall 5.000 [get_ports pad_jtag_tms] -set_output_delay -clock tck 5.000 [get_ports pad_jtag_tdo] - -set_max_delay -to [get_ports pad_jtag_tdo] 20.000 -set_max_delay -from [get_ports pad_jtag_tms] 20.000 -set_max_delay -from [get_ports pad_jtag_tdi] 20.000 - -set_max_delay -datapath_only -from [get_pins i_pulpissimo/soc_domain_i/pulp_soc_i/i_dmi_jtag/i_dmi_cdc/i_cdc_resp/i_src/data_src_q_reg*/C] -to [get_pins i_pulpissimo/soc_domain_i/pulp_soc_i/i_dmi_jtag/i_dmi_cdc/i_cdc_resp/i_dst/data_dst_q_reg*/D] 20.000 -set_max_delay -datapath_only -from [get_pins i_pulpissimo/soc_domain_i/pulp_soc_i/i_dmi_jtag/i_dmi_cdc/i_cdc_resp/i_src/req_src_q_reg/C] -to [get_pins i_pulpissimo/soc_domain_i/pulp_soc_i/i_dmi_jtag/i_dmi_cdc/i_cdc_resp/i_dst/req_dst_q_reg/D] 20.000 -set_max_delay -datapath_only -from [get_pins i_pulpissimo/soc_domain_i/pulp_soc_i/i_dmi_jtag/i_dmi_cdc/i_cdc_req/i_dst/ack_dst_q_reg/C] -to [get_pins i_pulpissimo/soc_domain_i/pulp_soc_i/i_dmi_jtag/i_dmi_cdc/i_cdc_req/i_src/ack_src_q_reg/D] 20.000 - - -# reset signal -set_false_path -from [get_ports pad_reset] - -# Set ASYNC_REG attribute for ff synchronizers to place them closer together and -# increase MTBF -set_property ASYNC_REG true [get_cells i_pulpissimo/soc_domain_i/pulp_soc_i/soc_peripherals_i/apb_adv_timer_i/u_tim0/u_in_stage/r_ls_clk_sync_reg*] -set_property ASYNC_REG true [get_cells i_pulpissimo/soc_domain_i/pulp_soc_i/soc_peripherals_i/apb_adv_timer_i/u_tim1/u_in_stage/r_ls_clk_sync_reg*] -set_property ASYNC_REG true [get_cells i_pulpissimo/soc_domain_i/pulp_soc_i/soc_peripherals_i/apb_adv_timer_i/u_tim2/u_in_stage/r_ls_clk_sync_reg*] -set_property ASYNC_REG true [get_cells i_pulpissimo/soc_domain_i/pulp_soc_i/soc_peripherals_i/apb_adv_timer_i/u_tim3/u_in_stage/r_ls_clk_sync_reg*] -set_property ASYNC_REG true [get_cells i_pulpissimo/soc_domain_i/pulp_soc_i/soc_peripherals_i/i_apb_timer_unit/s_ref_clk*] -set_property ASYNC_REG true [get_cells i_pulpissimo/soc_domain_i/pulp_soc_i/soc_peripherals_i/i_ref_clk_sync/i_pulp_sync/r_reg_reg*] -set_property ASYNC_REG true [get_cells i_pulpissimo/soc_domain_i/pulp_soc_i/soc_peripherals_i/u_evnt_gen/r_ls_sync_reg*] - -# Create asynchronous clock group between slow-clk and SoC clock. Those clocks -# are considered asynchronously and proper synchronization regs are in place -set_clock_groups -asynchronous -group [get_clocks -of_objects [get_pins i_pulpissimo/safe_domain_i/i_slow_clk_gen/slow_clk_o]] -group [get_clocks -of_objects [get_pins i_pulpissimo/soc_domain_i/pulp_soc_i/i_clk_rst_gen/i_fpga_clk_gen/soc_clk_o]] - - -############################################################# -# _____ ____ _____ _ _ _ # -# |_ _/ __ \ / ____| | | | | (_) # -# | || | | |_____| (___ ___| |_| |_ _ _ __ __ _ ___ # -# | || | | |______\___ \ / _ \ __| __| | '_ \ / _` / __| # -# _| || |__| | ____) | __/ |_| |_| | | | | (_| \__ \ # -# |_____\____/ |_____/ \___|\__|\__|_|_| |_|\__, |___/ # -# __/ | # -# |___/ # -############################################################# - -## Sys clock -set_property -dict {PACKAGE_PIN E23 IOSTANDARD LVDS} [get_ports ref_clk_n] -set_property -dict {PACKAGE_PIN F23 IOSTANDARD LVDS} [get_ports ref_clk_p] - -## Reset -set_property -dict {PACKAGE_PIN M11 IOSTANDARD LVCMOS33} [get_ports pad_reset] - -## Buttons -set_property -dict {PACKAGE_PIN B4 IOSTANDARD LVCMOS33} [get_ports btn0_i] -set_property -dict {PACKAGE_PIN C4 IOSTANDARD LVCMOS33} [get_ports btn1_i] -set_property -dict {PACKAGE_PIN B3 IOSTANDARD LVCMOS33} [get_ports btn2_i] -set_property -dict {PACKAGE_PIN C3 IOSTANDARD LVCMOS33} [get_ports btn3_i] - -## PMOD 0 -set_property -dict {PACKAGE_PIN G8 IOSTANDARD LVCMOS33} [get_ports pad_jtag_tms] -set_property -dict {PACKAGE_PIN H8 IOSTANDARD LVCMOS33} [get_ports pad_jtag_tdi] -set_property -dict {PACKAGE_PIN G7 IOSTANDARD LVCMOS33} [get_ports pad_jtag_tdo] -set_property -dict {PACKAGE_PIN H7 IOSTANDARD LVCMOS33} [get_ports pad_jtag_tck] -set_property -dict {PACKAGE_PIN G6 IOSTANDARD LVCMOS33} [get_ports pad_pmod0_4] -set_property -dict {PACKAGE_PIN H6 IOSTANDARD LVCMOS33} [get_ports pad_pmod0_5] -set_property -dict {PACKAGE_PIN J6 IOSTANDARD LVCMOS33} [get_ports pad_pmod0_6] -set_property -dict {PACKAGE_PIN J7 IOSTANDARD LVCMOS33} [get_ports pad_pmod0_7] - -## PMOD 1 -set_property -dict {PACKAGE_PIN J9 IOSTANDARD LVCMOS33} [get_ports pad_pmod1_0] -set_property -dict {PACKAGE_PIN K9 IOSTANDARD LVCMOS33} [get_ports pad_pmod1_1] -set_property -dict {PACKAGE_PIN K8 IOSTANDARD LVCMOS33} [get_ports pad_pmod1_2] -set_property -dict {PACKAGE_PIN L8 IOSTANDARD LVCMOS33} [get_ports pad_pmod1_3] -set_property -dict {PACKAGE_PIN L10 IOSTANDARD LVCMOS33} [get_ports pad_pmod1_4] -set_property -dict {PACKAGE_PIN M10 IOSTANDARD LVCMOS33} [get_ports pad_pmod1_5] -set_property -dict {PACKAGE_PIN M8 IOSTANDARD LVCMOS33} [get_ports pad_pmod1_6] -set_property -dict {PACKAGE_PIN M9 IOSTANDARD LVCMOS33} [get_ports pad_pmod1_7] - -## UART -set_property -dict {PACKAGE_PIN A20 IOSTANDARD LVCMOS18} [get_ports pad_uart_rx] -set_property -dict {PACKAGE_PIN C19 IOSTANDARD LVCMOS18} [get_ports pad_uart_tx] -set_property -dict {PACKAGE_PIN C18 IOSTANDARD LVCMOS18} [get_ports pad_uart_rts] -set_property -dict {PACKAGE_PIN A19 IOSTANDARD LVCMOS18} [get_ports pad_uart_cts] - -## LEDs -set_property -dict {PACKAGE_PIN D5 IOSTANDARD LVCMOS33} [get_ports led0_o] -set_property -dict {PACKAGE_PIN D6 IOSTANDARD LVCMOS33} [get_ports led1_o] -set_property -dict {PACKAGE_PIN A5 IOSTANDARD LVCMOS33} [get_ports led2_o] -set_property -dict {PACKAGE_PIN B5 IOSTANDARD LVCMOS33} [get_ports led3_o] - -## Switches -set_property -dict {PACKAGE_PIN E4 IOSTANDARD LVCMOS33} [get_ports switch0_i] -set_property -dict {PACKAGE_PIN D4 IOSTANDARD LVCMOS33} [get_ports switch1_i] -set_property -dict {PACKAGE_PIN F5 IOSTANDARD LVCMOS33} [get_ports switch2_i] -set_property -dict {PACKAGE_PIN F4 IOSTANDARD LVCMOS33} [get_ports switch3_i] - -## I2C Bus -set_property -dict {PACKAGE_PIN N12 IOSTANDARD LVCMOS33} [get_ports pad_i2c0_scl] -set_property -dict {PACKAGE_PIN P12 IOSTANDARD LVCMOS33} [get_ports pad_i2c0_sda] - -## HDMI CTL -set_property -dict {PACKAGE_PIN D1 IOSTANDARD LVCMOS33} [get_ports pad_hdmi_scl] -set_property -dict {PACKAGE_PIN E1 IOSTANDARD LVCMOS33} [get_ports pad_hdmi_sda] diff --git a/fpga/pulpissimo-zcu104/elf_run.gdb b/fpga/pulpissimo-zcu104/elf_run.gdb deleted file mode 100644 index cba53bd0..00000000 --- a/fpga/pulpissimo-zcu104/elf_run.gdb +++ /dev/null @@ -1,4 +0,0 @@ -target remote localhost:3333 -monitor reset halt -load -continue \ No newline at end of file diff --git a/fpga/pulpissimo-zcu104/elf_run.sh b/fpga/pulpissimo-zcu104/elf_run.sh deleted file mode 100755 index 9bd74f6a..00000000 --- a/fpga/pulpissimo-zcu104/elf_run.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/bash - -trap "exit" INT TERM -trap "kill 0" EXIT - - -SCRIPTDIR=$(dirname $0) -UART_TTY=${PULP_ZCU104_UART_TTY:=/dev/ttyUSB0} -UART_BAUDRATE=${PULP_ZCU104_UART_BAUDRATE:=115200} - -#Execute gdb and connect to openocd via pipe -$OPENOCD/bin/openocd -f $SCRIPTDIR/openocd-zcu104.cfg & -$PULP_RISCV_GCC_TOOLCHAIN_CI/bin/riscv32-unknown-elf-gdb -x $SCRIPTDIR/elf_run.gdb $1 & -sleep 3 -minicom -D $UART_TTY -b $UART_BAUDRATE - - diff --git a/fpga/pulpissimo-zcu104/fpga-settings.mk b/fpga/pulpissimo-zcu104/fpga-settings.mk deleted file mode 100644 index 28d84697..00000000 --- a/fpga/pulpissimo-zcu104/fpga-settings.mk +++ /dev/null @@ -1,12 +0,0 @@ -export BOARD=zcu104 -export XILINX_PART=xczu7ev-ffvc1156-2-e -export XILINX_BOARD=xilinx.com:zcu104:part0:1.1 -export FC_CLK_PERIOD_NS=50 -export PER_CLK_PERIOD_NS=100 -export SLOW_CLK_PERIOD_NS=30517 -#Must also change the localparam 'L2_BANK_SIZE' in pulp_soc.sv accordingly -export INTERLEAVED_BANK_SIZE=28672 -#Must also change the localparam 'L2_BANK_SIZE_PRI' in pulp_soc.sv accordingly -export PRIVATE_BANK_SIZE=8192 -$(info Setting environment variables for $(BOARD) board) - diff --git a/fpga/pulpissimo-zcu104/ips/xilinx_clk_mngr/.gitignore b/fpga/pulpissimo-zcu104/ips/xilinx_clk_mngr/.gitignore deleted file mode 100644 index 5099fe9c..00000000 --- a/fpga/pulpissimo-zcu104/ips/xilinx_clk_mngr/.gitignore +++ /dev/null @@ -1,21 +0,0 @@ -#Ignore vivado project files generated by the tcl script -**/.Xil/* -**/reports/* -**/*.cache/* -**/*.hw/* -**/*.ip_user_files/* -**/*.runs/* -**/*.sim/* -**/*.srcs/* -*.edf -*.xpr -*.jou -*.log - -.cxl.* - -*ip - -*_stub.v -gmon.out - diff --git a/fpga/pulpissimo-zcu104/ips/xilinx_clk_mngr/Makefile b/fpga/pulpissimo-zcu104/ips/xilinx_clk_mngr/Makefile deleted file mode 100644 index 978b9cee..00000000 --- a/fpga/pulpissimo-zcu104/ips/xilinx_clk_mngr/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -PROJECT:=xilinx_clk_mngr -VIVADO ?= vivado -VIVADOFLAGS ?= -nojournal -mode batch -source scripts/prologue.tcl -MODE=batch - -include ../../fpga-settings.mk - -.DEFAULT_GOAL:=help - -.PHONY: help all gui clean - -all: MODE=batch ## Create and synthesize the IP in batch mode. - -gui: MODE=gui ## Create and synthesize the IP in GUI mode. - -all gui: $(PROJECT).xpr - -$(PROJECT).xpr: ../../fpga-settings.mk tcl/run.tcl - make clean - $(VIVADO) -mode $(MODE) -source tcl/run.tcl - mkdir -p ip - cp -r ${PROJECT}.srcs/sources_1/ip/${PROJECT}/* ip/. - cp ${PROJECT}.runs/${PROJECT}_synth_1/${PROJECT}.dcp ip/. - -clean: ## Remove all build products - rm -rf ip/* - mkdir -p ip - rm -rf ${PROJECT}.* - rm -rf component.xml - rm -rf vivado*.jou - rm -rf vivado*.log - rm -rf vivado*.str - rm -rf xgui - rm -rf .Xil - -help: ## Shows this help message - @grep -E -h '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' diff --git a/fpga/pulpissimo-zcu104/ips/xilinx_clk_mngr/tcl/run.tcl b/fpga/pulpissimo-zcu104/ips/xilinx_clk_mngr/tcl/run.tcl deleted file mode 100644 index 2310e43b..00000000 --- a/fpga/pulpissimo-zcu104/ips/xilinx_clk_mngr/tcl/run.tcl +++ /dev/null @@ -1,49 +0,0 @@ -set partNumber $::env(XILINX_PART) - -if [info exists ::env(BOARD)] { - set BOARD $::env(BOARD) -} else { - error "BOARD is not defined. Please source the sourceme.sh file." - exit -} -if [info exists ::env(XILINX_BOARD)] { - set boardName $::env(XILINX_BOARD) -} - -# detect target clock -if [info exists ::env(FC_CLK_PERIOD_NS)] { - set FC_CLK_PERIOD_NS $::env(FC_CLK_PERIOD_NS) -} else { - set FC_CLK_PERIOD_NS 10.000 -} -if [info exists ::env(PER_CLK_PERIOD_NS)] { - set PER_CLK_PERIOD_NS $::env(PER_CLK_PERIOD_NS) -} else { - set PER_CLK_PERIOD_NS 20.000 -} - - -set FC_CLK_FREQ_MHZ [expr 1000 / $FC_CLK_PERIOD_NS] -set PER_CLK_FREQ_MHZ [expr 1000 / $PER_CLK_PERIOD_NS] - -set ipName xilinx_clk_mngr - -create_project $ipName . -part $partNumber -set_property board_part $boardName [current_project] - -create_ip -name clk_wiz -vendor xilinx.com -library ip -module_name $ipName - -set_property -dict [eval list CONFIG.PRIM_IN_FREQ {125.000} \ - CONFIG.NUM_OUT_CLKS {2} \ - CONFIG.CLKOUT2_USED {true} \ - CONFIG.RESET_TYPE {ACTIVE_LOW} \ - CONFIG.RESET_PORT {resetn} \ - CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {$FC_CLK_FREQ_MHZ} \ - CONFIG.CLKOUT2_REQUESTED_OUT_FREQ {$PER_CLK_FREQ_MHZ} \ - CONFIG.CLKIN1_JITTER_PS {50.0} \ - ] [get_ips $ipName] - -generate_target all [get_files ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] -create_ip_run [get_files -of_objects [get_fileset sources_1] ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] -launch_run -jobs 8 ${ipName}_synth_1 -wait_on_run ${ipName}_synth_1 diff --git a/fpga/pulpissimo-zcu104/ips/xilinx_interleaved_ram/.gitignore b/fpga/pulpissimo-zcu104/ips/xilinx_interleaved_ram/.gitignore deleted file mode 100644 index 5099fe9c..00000000 --- a/fpga/pulpissimo-zcu104/ips/xilinx_interleaved_ram/.gitignore +++ /dev/null @@ -1,21 +0,0 @@ -#Ignore vivado project files generated by the tcl script -**/.Xil/* -**/reports/* -**/*.cache/* -**/*.hw/* -**/*.ip_user_files/* -**/*.runs/* -**/*.sim/* -**/*.srcs/* -*.edf -*.xpr -*.jou -*.log - -.cxl.* - -*ip - -*_stub.v -gmon.out - diff --git a/fpga/pulpissimo-zcu104/ips/xilinx_interleaved_ram/Makefile b/fpga/pulpissimo-zcu104/ips/xilinx_interleaved_ram/Makefile deleted file mode 100644 index 08752831..00000000 --- a/fpga/pulpissimo-zcu104/ips/xilinx_interleaved_ram/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -PROJECT:=xilinx_interleaved_ram -VIVADO ?= vivado -VIVADOFLAGS ?= -nojournal -mode batch -source scripts/prologue.tcl -MODE=batch - -include ../../fpga-settings.mk - -.DEFAULT_GOAL:=help - -.PHONY: help all gui clean - -all: MODE=batch ## Create and synthesize the IP in batch mode. - -gui: MODE=gui ## Create and synthesize the IP in GUI mode. - -all gui: $(PROJECT).xpr - -$(PROJECT).xpr: ../../fpga-settings.mk tcl/run.tcl - make clean - $(VIVADO) -mode $(MODE) -source tcl/run.tcl - mkdir -p ip - cp -r ${PROJECT}.srcs/sources_1/ip/${PROJECT}/* ip/. - cp ${PROJECT}.runs/${PROJECT}_synth_1/${PROJECT}.dcp ip/. - -clean: ## Remove all build products - rm -rf ip/* - mkdir -p ip - rm -rf ${PROJECT}.* - rm -rf component.xml - rm -rf vivado*.jou - rm -rf vivado*.log - rm -rf vivado*.str - rm -rf xgui - rm -rf .Xil - -help: ## Shows this help message - @grep -E -h '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' diff --git a/fpga/pulpissimo-zcu104/ips/xilinx_interleaved_ram/tcl/run.tcl b/fpga/pulpissimo-zcu104/ips/xilinx_interleaved_ram/tcl/run.tcl deleted file mode 100644 index a2e84f23..00000000 --- a/fpga/pulpissimo-zcu104/ips/xilinx_interleaved_ram/tcl/run.tcl +++ /dev/null @@ -1,38 +0,0 @@ -set partNumber $::env(XILINX_PART) - -if [info exists ::env(BOARD)] { - set BOARD $::env(BOARD) -} else { - error "BOARD is not defined. Please source the sourceme.sh file." - exit -} -if [info exists ::env(XILINX_BOARD)] { - set boardName $::env(XILINX_BOARD) -} - -# detect target ram size -if [info exists ::env(INTERLEAVED_BANK_SIZE)] { - set INTERLEAVED_BANK_SIZE $::env(INTERLEAVED_BANK_SIZE) -} else { - set INTERLEAVED_BANK_SIZE 4096 -} - -set ipName xilinx_interleaved_ram - -create_project $ipName . -part $partNumber -set_property board_part $boardName [current_project] - -create_ip -name blk_mem_gen -vendor xilinx.com -library ip -module_name $ipName - -set_property -dict [eval list CONFIG.Use_Byte_Write_Enable {true} \ - CONFIG.Byte_Size {8} \ - CONFIG.Write_Width_A {32} \ - CONFIG.Write_Depth_A {$INTERLEAVED_BANK_SIZE} \ - CONFIG.Read_Width_A {32} \ - CONFIG.Register_PortA_Output_of_Memory_Primitives {false} \ - ] [get_ips $ipName] - -generate_target all [get_files ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] -create_ip_run [get_files -of_objects [get_fileset sources_1] ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] -launch_run -jobs 8 ${ipName}_synth_1 -wait_on_run ${ipName}_synth_1 diff --git a/fpga/pulpissimo-zcu104/ips/xilinx_private_ram/.gitignore b/fpga/pulpissimo-zcu104/ips/xilinx_private_ram/.gitignore deleted file mode 100644 index 5099fe9c..00000000 --- a/fpga/pulpissimo-zcu104/ips/xilinx_private_ram/.gitignore +++ /dev/null @@ -1,21 +0,0 @@ -#Ignore vivado project files generated by the tcl script -**/.Xil/* -**/reports/* -**/*.cache/* -**/*.hw/* -**/*.ip_user_files/* -**/*.runs/* -**/*.sim/* -**/*.srcs/* -*.edf -*.xpr -*.jou -*.log - -.cxl.* - -*ip - -*_stub.v -gmon.out - diff --git a/fpga/pulpissimo-zcu104/ips/xilinx_private_ram/Makefile b/fpga/pulpissimo-zcu104/ips/xilinx_private_ram/Makefile deleted file mode 100644 index 4734e7ad..00000000 --- a/fpga/pulpissimo-zcu104/ips/xilinx_private_ram/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -PROJECT:=xilinx_private_ram -VIVADO ?= vivado -VIVADOFLAGS ?= -nojournal -mode batch -source scripts/prologue.tcl -MODE=batch - -include ../../fpga-settings.mk - -.DEFAULT_GOAL:=help - -.PHONY: help all gui clean - -all: MODE=batch ## Create and synthesize the IP in batch mode. - -gui: MODE=gui ## Create and synthesize the IP in GUI mode. - -all gui: $(PROJECT).xpr - -$(PROJECT).xpr: ../../fpga-settings.mk tcl/run.tcl - make clean - $(VIVADO) -mode $(MODE) -source tcl/run.tcl - mkdir -p ip - cp -r ${PROJECT}.srcs/sources_1/ip/${PROJECT}/* ip/. - cp ${PROJECT}.runs/${PROJECT}_synth_1/${PROJECT}.dcp ip/. - -clean: ## Remove all build products - rm -rf ip/* - mkdir -p ip - rm -rf ${PROJECT}.* - rm -rf component.xml - rm -rf vivado*.jou - rm -rf vivado*.log - rm -rf vivado*.str - rm -rf xgui - rm -rf .Xil - -help: ## Shows this help message - @grep -E -h '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' diff --git a/fpga/pulpissimo-zcu104/ips/xilinx_private_ram/tcl/run.tcl b/fpga/pulpissimo-zcu104/ips/xilinx_private_ram/tcl/run.tcl deleted file mode 100644 index 78493b37..00000000 --- a/fpga/pulpissimo-zcu104/ips/xilinx_private_ram/tcl/run.tcl +++ /dev/null @@ -1,38 +0,0 @@ -set partNumber $::env(XILINX_PART) - -if [info exists ::env(BOARD)] { - set BOARD $::env(BOARD) -} else { - error "BOARD is not defined. Please source the sourceme.sh file." - exit -} -if [info exists ::env(XILINX_BOARD)] { - set boardName $::env(XILINX_BOARD) -} - -# detect target ram size -if [info exists ::env(PRIVATE_BANK_SIZE)] { - set PRIVATE_BANK_SIZE $::env(PRIVATE_BANK_SIZE) -} else { - set PRIVATE_BANK_SIZE 4096 -} - -set ipName xilinx_private_ram - -create_project $ipName . -part $partNumber -set_property board_part $boardName [current_project] - -create_ip -name blk_mem_gen -vendor xilinx.com -library ip -module_name $ipName - -set_property -dict [eval list CONFIG.Use_Byte_Write_Enable {true} \ - CONFIG.Byte_Size {8} \ - CONFIG.Write_Width_A {32} \ - CONFIG.Write_Depth_A {$PRIVATE_BANK_SIZE} \ - CONFIG.Read_Width_A {32} \ - CONFIG.Register_PortA_Output_of_Memory_Primitives {false} \ - ] [get_ips $ipName] - -generate_target all [get_files ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] -create_ip_run [get_files -of_objects [get_fileset sources_1] ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] -launch_run -jobs 8 ${ipName}_synth_1 -wait_on_run ${ipName}_synth_1 diff --git a/fpga/pulpissimo-zcu104/ips/xilinx_slow_clk_mngr/.gitignore b/fpga/pulpissimo-zcu104/ips/xilinx_slow_clk_mngr/.gitignore deleted file mode 100644 index 5099fe9c..00000000 --- a/fpga/pulpissimo-zcu104/ips/xilinx_slow_clk_mngr/.gitignore +++ /dev/null @@ -1,21 +0,0 @@ -#Ignore vivado project files generated by the tcl script -**/.Xil/* -**/reports/* -**/*.cache/* -**/*.hw/* -**/*.ip_user_files/* -**/*.runs/* -**/*.sim/* -**/*.srcs/* -*.edf -*.xpr -*.jou -*.log - -.cxl.* - -*ip - -*_stub.v -gmon.out - diff --git a/fpga/pulpissimo-zcu104/ips/xilinx_slow_clk_mngr/Makefile b/fpga/pulpissimo-zcu104/ips/xilinx_slow_clk_mngr/Makefile deleted file mode 100644 index e3ba47bf..00000000 --- a/fpga/pulpissimo-zcu104/ips/xilinx_slow_clk_mngr/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -PROJECT:=xilinx_slow_clk_mngr -VIVADO ?= vivado -VIVADOFLAGS ?= -nojournal -mode batch -source scripts/prologue.tcl -MODE=batch - -include ../../fpga-settings.mk - -.DEFAULT_GOAL:=help - -.PHONY: help all gui clean - -all: MODE=batch ## Create and synthesize the IP in batch mode. - -gui: MODE=gui ## Create and synthesize the IP in GUI mode. - -all gui: $(PROJECT).xpr - -$(PROJECT).xpr: ../../fpga-settings.mk tcl/run.tcl - make clean - $(VIVADO) -mode $(MODE) -source tcl/run.tcl - mkdir -p ip - cp -r ${PROJECT}.srcs/sources_1/ip/${PROJECT}/* ip/. - cp ${PROJECT}.runs/${PROJECT}_synth_1/${PROJECT}.dcp ip/. - -clean: ## Remove all build products - rm -rf ip/* - mkdir -p ip - rm -rf ${PROJECT}.* - rm -rf component.xml - rm -rf vivado*.jou - rm -rf vivado*.log - rm -rf vivado*.str - rm -rf xgui - rm -rf .Xil - -help: ## Shows this help message - @grep -E -h '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' diff --git a/fpga/pulpissimo-zcu104/ips/xilinx_slow_clk_mngr/tcl/run.tcl b/fpga/pulpissimo-zcu104/ips/xilinx_slow_clk_mngr/tcl/run.tcl deleted file mode 100644 index a14c2958..00000000 --- a/fpga/pulpissimo-zcu104/ips/xilinx_slow_clk_mngr/tcl/run.tcl +++ /dev/null @@ -1,45 +0,0 @@ -set partNumber $::env(XILINX_PART) - -if [info exists ::env(BOARD)] { - set BOARD $::env(BOARD) -} else { - error "BOARD is not defined. Please source the sourceme.sh file." - exit -} -if [info exists ::env(XILINX_BOARD)] { - set boardName $::env(XILINX_BOARD) -} - -# detect target clock -if [info exists ::env(SLOW_CLK_PERIOD_NS)] { - set SLOW_CLK_PERIOD_NS $::env(SLOW_CLK_PERIOD_NS) -} else { - set SLOW_CLK_PERIOD_NS 30517 -} - -# Multiply frequency by 250 as there is a clock divider (by 250) after the -# slow_clk_mngr since the MMCMs do not support clocks slower then 4.69 MHz. -set SLOW_CLK_FREQ_MHZ [expr 1000 * 256 / $SLOW_CLK_PERIOD_NS] - -set ipName xilinx_slow_clk_mngr - -create_project $ipName . -part $partNumber -set_property board_part $boardName [current_project] - -create_ip -name clk_wiz -vendor xilinx.com -library ip -module_name $ipName - -set_property -dict [eval list CONFIG.PRIM_IN_FREQ {125.000} \ - CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {$SLOW_CLK_FREQ_MHZ} \ - CONFIG.USE_SAFE_CLOCK_STARTUP {true} \ - CONFIG.USE_LOCKED {false} \ - CONFIG.RESET_TYPE {ACTIVE_LOW} \ - CONFIG.CLKIN1_JITTER_PS {50.0} \ - CONFIG.FEEDBACK_SOURCE {FDBK_AUTO} \ - CONFIG.RESET_PORT {resetn} \ - ] [get_ips $ipName] - - -generate_target all [get_files ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] -create_ip_run [get_files -of_objects [get_fileset sources_1] ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] -launch_run -jobs 8 ${ipName}_synth_1 -wait_on_run ${ipName}_synth_1 diff --git a/fpga/pulpissimo-zcu104/openocd-zcu104-digilent-jtag-hs1.cfg b/fpga/pulpissimo-zcu104/openocd-zcu104-digilent-jtag-hs1.cfg deleted file mode 100644 index fc453400..00000000 --- a/fpga/pulpissimo-zcu104/openocd-zcu104-digilent-jtag-hs1.cfg +++ /dev/null @@ -1,32 +0,0 @@ -adapter_khz 1000 - -# Digilent JTAG-HS1 -interface ftdi -ftdi_vid_pid 0x0403 0x6010 -ftdi_channel 0 -ftdi_layout_init 0x0088 0x008b - -set _CHIPNAME riscv - -jtag newtap $_CHIPNAME unknown0 -irlen 5 -expected-id 0x10102001 -jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x249511C3 - -set _TARGETNAME $_CHIPNAME.cpu -target create $_TARGETNAME riscv -chain-position $_TARGETNAME -coreid 0x3e0 - -gdb_report_data_abort enable -gdb_report_register_access_error enable - -riscv set_reset_timeout_sec 120 -riscv set_command_timeout_sec 120 - -# prefer to use sba for system bus access -riscv set_prefer_sba on - -# dump jtag chain -scan_chain - - -init -halt -echo "Ready for Remote Connections" diff --git a/fpga/pulpissimo-zcu104/openocd-zcu104-olimex-arm-usb-ocd-h.cfg b/fpga/pulpissimo-zcu104/openocd-zcu104-olimex-arm-usb-ocd-h.cfg deleted file mode 100644 index ba6bda27..00000000 --- a/fpga/pulpissimo-zcu104/openocd-zcu104-olimex-arm-usb-ocd-h.cfg +++ /dev/null @@ -1,37 +0,0 @@ -adapter_khz 1000 - -# Olimex ARM-USB-OCD-H -interface ftdi -ftdi_device_desc "Olimex OpenOCD JTAG ARM-USB-OCD-H" -ftdi_vid_pid 0x15ba 0x002b - -ftdi_layout_init 0x0908 0x0b1b -ftdi_layout_signal nSRST -oe 0x0200 -ftdi_layout_signal nTRST -data 0x0100 -ftdi_layout_signal LED -data 0x0800 - - -set _CHIPNAME riscv - -jtag newtap $_CHIPNAME unknown0 -irlen 5 -expected-id 0x10102001 -jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x249511C3 - -set _TARGETNAME $_CHIPNAME.cpu -target create $_TARGETNAME riscv -chain-position $_TARGETNAME -coreid 0x3e0 - -gdb_report_data_abort enable -gdb_report_register_access_error enable - -riscv set_reset_timeout_sec 120 -riscv set_command_timeout_sec 120 - -# prefer to use sba for system bus access -riscv set_prefer_sba on - -# dump jtag chain -scan_chain - - -init -halt -echo "Ready for Remote Connections" diff --git a/fpga/pulpissimo-zcu104/rtl/fpga_bootrom.sv b/fpga/pulpissimo-zcu104/rtl/fpga_bootrom.sv deleted file mode 100644 index 79d78b3f..00000000 --- a/fpga/pulpissimo-zcu104/rtl/fpga_bootrom.sv +++ /dev/null @@ -1,36 +0,0 @@ -//----------------------------------------------------------------------------- -// Title : FPGA Bootrom for PULPissimo -//----------------------------------------------------------------------------- -// File : fpga_bootrom.sv -// Author : Manuel Eggimann -// Created : 29.05.2019 -//----------------------------------------------------------------------------- -// Description : -// Mockup bootrom that keeps returning jal x0,0 to trap the core in an infinite -// loop until the debug module takes over control. -//----------------------------------------------------------------------------- -// Copyright (C) 2013-2019 ETH Zurich, University of Bologna -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. -//----------------------------------------------------------------------------- - - -module fpga_bootrom - #( - parameter ADDR_WIDTH=32, - parameter DATA_WIDTH=32 - ) - ( - input logic CLK, - input logic CEN, - input logic [ADDR_WIDTH-1:0] A, - output logic [DATA_WIDTH-1:0] Q - ); - assign Q = 32'h0000006f; //jal x0,0 -endmodule : fpga_bootrom diff --git a/fpga/pulpissimo-zcu104/rtl/fpga_clk_gen.sv b/fpga/pulpissimo-zcu104/rtl/fpga_clk_gen.sv deleted file mode 100644 index 2ad9a8eb..00000000 --- a/fpga/pulpissimo-zcu104/rtl/fpga_clk_gen.sv +++ /dev/null @@ -1,74 +0,0 @@ -//----------------------------------------------------------------------------- -// Title : FPGA CLK Gen for PULPissimo -// ----------------------------------------------------------------------------- -// File : fpga_clk_gen.sv Author : Manuel Eggimann -// Created : 17.05.2019 -// ----------------------------------------------------------------------------- -// Description : Instantiates Xilinx clocking wizard IP to generate 2 output -// clocks. Currently, the clock is not dynamicly reconfigurable and all -// configuration requests are acknowledged without any effect. -// ----------------------------------------------------------------------------- -// Copyright (C) 2013-2019 ETH Zurich, University of Bologna Copyright and -// related rights are licensed under the Solderpad Hardware License, Version -// 0.51 (the "License"); you may not use this file except in compliance with the -// License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law or -// agreed to in writing, software, hardware and materials distributed under this -// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS -// OF ANY KIND, either express or implied. See the License for the specific -// language governing permissions and limitations under the License. -// ----------------------------------------------------------------------------- - - -module fpga_clk_gen ( - input logic ref_clk_i, - input logic rstn_glob_i, - input logic test_mode_i, - input logic shift_enable_i, - output logic soc_clk_o, - output logic per_clk_o, - output logic cluster_clk_o, - output logic soc_cfg_lock_o, - input logic soc_cfg_req_i, - output logic soc_cfg_ack_o, - input logic [1:0] soc_cfg_add_i, - input logic [31:0] soc_cfg_data_i, - output logic [31:0] soc_cfg_r_data_o, - input logic soc_cfg_wrn_i, - output logic per_cfg_lock_o, - input logic per_cfg_req_i, - output logic per_cfg_ack_o, - input logic [1:0] per_cfg_add_i, - input logic [31:0] per_cfg_data_i, - output logic [31:0] per_cfg_r_data_o, - input logic per_cfg_wrn_i, - output logic cluster_cfg_lock_o, - input logic cluster_cfg_req_i, - output logic cluster_cfg_ack_o, - input logic [1:0] cluster_cfg_add_i, - input logic [31:0] cluster_cfg_data_i, - output logic [31:0] cluster_cfg_r_data_o, - input logic cluster_cfg_wrn_i - ); - - logic s_locked; - - xilinx_clk_mngr i_clk_manager - ( - .resetn(rstn_glob_i), - .clk_in1(ref_clk_i), - .clk_out1(soc_clk_o), - .clk_out2(per_clk_o), - .locked(s_locked) - ); - - assign soc_cfg_lock_o = s_locked; - assign per_cfg_lock_o = s_locked; - - assign soc_cfg_ack_o = 1'b1; //Always acknowledge without doing anything for now - assign per_cfg_ack_o = 1'b1; - - assign soc_cfg_r_data_o = 32'hdeadda7a; - assign per_cfg_r_data_o = 32'hdeadda7a; - -endmodule : fpga_clk_gen diff --git a/fpga/pulpissimo-zcu104/rtl/fpga_interleaved_ram.sv b/fpga/pulpissimo-zcu104/rtl/fpga_interleaved_ram.sv deleted file mode 100644 index 7d52e5d8..00000000 --- a/fpga/pulpissimo-zcu104/rtl/fpga_interleaved_ram.sv +++ /dev/null @@ -1,57 +0,0 @@ -//----------------------------------------------------------------------------- -// Title : FPGA Interleaved RAM Bank for PULPissimo -// ----------------------------------------------------------------------------- -// File : fpga_interleaved_ram.sv Author : Manuel Eggimann -// Created : 20.05.2019 -// ----------------------------------------------------------------------------- -// Description : Instantiated block ram generator IP to replace the SRAM banks -// in the interleaved region of L2. Since Xilinx LogicoreIP are not customizable -// via parameters, the bank size selected in l2_ram_multibank must match the one -// used in the TCL script for IP generation. -// ----------------------------------------------------------------------------- -// Copyright (C) 2013-2019 ETH Zurich, University of Bologna Copyright and -// related rights are licensed under the Solderpad Hardware License, Version -// 0.51 (the "License"); you may not use this file except in compliance with the -// License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law or -// agreed to in writing, software, hardware and materials distributed under this -// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS -// OF ANY KIND, either express or implied. See the License for the specific -// language governing permissions and limitations under the License. -// ----------------------------------------------------------------------------- - -module fpga_interleaved_ram - #( - parameter ADDR_WIDTH=12 - ) ( - input logic clk_i, - input logic rst_ni, - input logic csn_i, - input logic wen_i, - input logic [3:0] be_i, - input logic [ADDR_WIDTH-1:0] addr_i, - input logic [31:0] wdata_i, - output logic [31:0] rdata_o - ); - - logic [3:0] wea; - - always_comb begin - if (wen_i == 1'b0) begin - wea = be_i; - end else begin - wea = '0; - end - end - - xilinx_interleaved_ram i_xilinx_interleaved_ram - ( - .clka(clk_i), - .ena(~csn_i), - .wea(wea), - .addra(addr_i), - .dina(wdata_i), - .douta(rdata_o) - ); - -endmodule : fpga_interleaved_ram diff --git a/fpga/pulpissimo-zcu104/rtl/fpga_private_ram.sv b/fpga/pulpissimo-zcu104/rtl/fpga_private_ram.sv deleted file mode 100644 index 05244931..00000000 --- a/fpga/pulpissimo-zcu104/rtl/fpga_private_ram.sv +++ /dev/null @@ -1,57 +0,0 @@ -//----------------------------------------------------------------------------- -// Title : FPGA Private RAM Bank for PULPissimo -// ----------------------------------------------------------------------------- -// File : fpga_private_ram.sv Author : Manuel Eggimann -// Created : 20.05.2019 -// ----------------------------------------------------------------------------- -// Description : Instantiated block ram generator IP to replace the SRAM banks -// in the private region of L2. Since Xilinx LogicoreIP are not customizable -// via parameters, the bank size selected in l2_ram_multibank must match the one -// used in the TCL script for IP generation. -// ----------------------------------------------------------------------------- -// Copyright (C) 2013-2019 ETH Zurich, University of Bologna Copyright and -// related rights are licensed under the Solderpad Hardware License, Version -// 0.51 (the "License"); you may not use this file except in compliance with the -// License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law or -// agreed to in writing, software, hardware and materials distributed under this -// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS -// OF ANY KIND, either express or implied. See the License for the specific -// language governing permissions and limitations under the License. -// ----------------------------------------------------------------------------- - -module fpga_private_ram - #( - parameter ADDR_WIDTH=12 - ) ( - input logic clk_i, - input logic rst_ni, - input logic csn_i, - input logic wen_i, - input logic [3:0] be_i, - input logic [ADDR_WIDTH-1:0] addr_i, - input logic [31:0] wdata_i, - output logic [31:0] rdata_o - ); - - logic [3:0] wea; - - always_comb begin - if (wen_i == 1'b0) begin - wea = be_i; - end else begin - wea = '0; - end - end - - xilinx_private_ram i_xilinx_private_ram - ( - .clka(clk_i), - .ena(~csn_i), - .wea(wea), - .addra(addr_i), - .dina(wdata_i), - .douta(rdata_o) - ); - -endmodule : fpga_private_ram diff --git a/fpga/pulpissimo-zcu104/rtl/fpga_slow_clk_gen.sv b/fpga/pulpissimo-zcu104/rtl/fpga_slow_clk_gen.sv deleted file mode 100644 index f3db58f4..00000000 --- a/fpga/pulpissimo-zcu104/rtl/fpga_slow_clk_gen.sv +++ /dev/null @@ -1,82 +0,0 @@ -//----------------------------------------------------------------------------- -// Title : FPGA slow clk generator for PULPissimo -//----------------------------------------------------------------------------- -// File : fpga_slow_clk_gen.sv -// Author : Manuel Eggimann -// Created : 20.05.2019 -//----------------------------------------------------------------------------- -// Description : Instantiates Xilinx Clocking Wizard IP to generate the slow_clk -// signal since for certain boards the available clock sources are to fast to -// use directly. -//----------------------------------------------------------------------------- -// Copyright (C) 2013-2019 ETH Zurich, University of Bologna -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. -//----------------------------------------------------------------------------- - - -module fpga_slow_clk_gen - #( - parameter CLK_DIV_VALUE = 256 //The xilinx_slow_clk_mngr is supposed to - //generate an 8.3886MHz clock. We need to divide it - //by 256 to arrive to a 32.768kHz clock - ) - (input logic ref_clk_i, - input logic rst_ni, - output logic slow_clk_o - ); - - - - localparam COUNTER_WIDTH = $clog2(CLK_DIV_VALUE); - - - //Create clock divider using BUFGCE cells as the PLL/MMCM cannot generate clocks - //slower than 4.69 MHz and we need 32.768kHz - - logic [COUNTER_WIDTH-1:0] clk_counter_d, clk_counter_q; - logic clock_gate_en; - - logic intermmediate_clock; - - xilinx_slow_clk_mngr i_slow_clk_mngr - ( - .resetn(rst_ni), - .clk_in1(ref_clk_i), - .clk_out1(intermmediate_clock) - ); - - - - always_comb begin - if (clk_counter_q == CLK_DIV_VALUE-1) begin - clk_counter_d = '0; - clock_gate_en = 1'b1; - end else begin - clk_counter_d = clk_counter_q + 1; - clock_gate_en = 1'b0; - end - end - - always_ff @(posedge intermmediate_clock, negedge rst_ni) begin - if (!rst_ni) begin - clk_counter_q <= '0; - end else begin - clk_counter_q <= clk_counter_d; - end - end - - BUFGCE i_clock_gate - ( - .I(intermmediate_clock), - .CE(clock_gate_en), - .O(slow_clk_o) - ); - -endmodule : fpga_slow_clk_gen diff --git a/fpga/pulpissimo-zcu104/rtl/pad_functional_xilinx.sv b/fpga/pulpissimo-zcu104/rtl/pad_functional_xilinx.sv deleted file mode 100644 index a3ca1cde..00000000 --- a/fpga/pulpissimo-zcu104/rtl/pad_functional_xilinx.sv +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2018 ETH Zurich and University of Bologna. -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - - -module pad_functional_pd -( - input logic OEN, - input logic I, - output logic O, - input logic PEN, - inout logic PAD -); - - (* PULLDOWN = "YES" *) - IOBUF iobuf_i ( - .T ( OEN ), - .I ( I ), - .O ( O ), - .IO( PAD ) - ); - -endmodule - -module pad_functional_pu -( - input logic OEN, - input logic I, - output logic O, - input logic PEN, - inout logic PAD -); - - (* PULLUP = "YES" *) - IOBUF iobuf_i ( - .T ( OEN ), - .I ( I ), - .O ( O ), - .IO( PAD ) - ); - -endmodule \ No newline at end of file diff --git a/fpga/pulpissimo-zcu104/rtl/pulp_clock_gating_xilinx.sv b/fpga/pulpissimo-zcu104/rtl/pulp_clock_gating_xilinx.sv deleted file mode 100644 index 1e2db2d1..00000000 --- a/fpga/pulpissimo-zcu104/rtl/pulp_clock_gating_xilinx.sv +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2018 ETH Zurich and University of Bologna. -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. - -module pulp_clock_gating - ( - input logic clk_i, - input logic en_i, - input logic test_en_i, - output logic clk_o - ); - - assign clk_o = clk_i; - -endmodule diff --git a/fpga/pulpissimo-zcu104/rtl/xilinx_pulpissimo.v b/fpga/pulpissimo-zcu104/rtl/xilinx_pulpissimo.v deleted file mode 100644 index 46d58c73..00000000 --- a/fpga/pulpissimo-zcu104/rtl/xilinx_pulpissimo.v +++ /dev/null @@ -1,143 +0,0 @@ -//----------------------------------------------------------------------------- -// Title : PULPissimo Verilog Wrapper -//----------------------------------------------------------------------------- -// File : xilinx_pulpissimo.v -// Author : Manuel Eggimann -// Created : 21.05.2019 -//----------------------------------------------------------------------------- -// Description : -// Verilog Wrapper of PULPissimo to use the module within Xilinx IP integrator. -//----------------------------------------------------------------------------- -// Copyright (C) 2013-2019 ETH Zurich, University of Bologna -// Copyright and related rights are licensed under the Solderpad Hardware -// License, Version 0.51 (the "License"); you may not use this file except in -// compliance with the License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law -// or agreed to in writing, software, hardware and materials distributed under -// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR -// CONDITIONS OF ANY KIND, either express or implied. See the License for the -// specific language governing permissions and limitations under the License. -//----------------------------------------------------------------------------- - -module xilinx_pulpissimo - ( - input wire ref_clk_p, - input wire ref_clk_n, - - inout wire pad_uart_rx, - inout wire pad_uart_tx, - inout wire pad_uart_rts, //Mapped to spim_csn0 - inout wire pad_uart_cts, //Mapped to spim_sck - - inout wire led0_o, //Mapped to spim_csn1 - inout wire led1_o, //Mapped to cam_pclk - inout wire led2_o, //Mapped to cam_hsync - inout wire led3_o, //Mapped to cam_data0 - - inout wire switch0_i, //Mapped to cam_data1 - inout wire switch1_i, //Mapped to cam_data2 - inout wire switch2_i, //Mapped to cam_data7 - inout wire switch3_i, //Mapped to cam_vsync - - inout wire btn0_i, //Mapped to cam_data3 - inout wire btn1_i, //Mapped to cam_data4 - inout wire btn2_i, //Mapped to cam_data5 - inout wire btn3_i, //Mapped to cam_data6 - - inout wire pad_i2c0_sda, - inout wire pad_i2c0_scl, - - inout wire pad_pmod0_4, //Mapped to spim_sdio0 - inout wire pad_pmod0_5, //Mapped to spim_sdio1 - inout wire pad_pmod0_6, //Mapped to spim_sdio2 - inout wire pad_pmod0_7, //Mapped to spim_sdio3 - - inout wire pad_pmod1_0, //Mapped to sdio_data0 - inout wire pad_pmod1_1, //Mapped to sdio_data1 - inout wire pad_pmod1_2, //Mapped to sdio_data2 - inout wire pad_pmod1_3, //Mapped to sdio_data3 - inout wire pad_pmod1_4, //Mapped to i2s0_sck - inout wire pad_pmod1_5, //Mapped to i2s0_ws - inout wire pad_pmod1_6, //Mapped to i2s0_sdi - inout wire pad_pmod1_7, //Mapped to i2s1_sdi - - inout wire pad_hdmi_scl, //Mapped to sdio_clk - inout wire pad_hdmi_sda, //Mapped to sdio_cmd - - input wire pad_reset, - - input wire pad_jtag_tck, - input wire pad_jtag_tdi, - output wire pad_jtag_tdo, - input wire pad_jtag_tms - ); - - localparam CORE_TYPE = 0; // 0 for RISCY, 1 for IBEX RV32IMC (formerly ZERORISCY), 2 for IBEX RV32EC (formerly MICRORISCY) - localparam USE_FPU = 1; - localparam USE_HWPE = 0; - - wire ref_clk; - - - //Differential to single ended clock conversion - IBUFGDS - #( - .IOSTANDARD("LVDS"), - .DIFF_TERM("FALSE"), - .IBUF_LOW_PWR("FALSE")) - i_sysclk_iobuf - ( - .I(ref_clk_p), - .IB(ref_clk_n), - .O(ref_clk) - ); - - pulpissimo - #(.CORE_TYPE(CORE_TYPE), - .USE_FPU(USE_FPU), - .USE_HWPE(USE_HWPE) - ) i_pulpissimo - ( - .pad_spim_sdio0(pad_pmod0_4), - .pad_spim_sdio1(pad_pmod0_5), - .pad_spim_sdio2(pad_pmod0_6), - .pad_spim_sdio3(pad_pmod0_7), - .pad_spim_csn0(pad_uart_rts), - .pad_spim_csn1(led0_o), - .pad_spim_sck(pad_uart_cts), - .pad_uart_rx(pad_uart_rx), - .pad_uart_tx(pad_uart_tx), - .pad_cam_pclk(led1_o), - .pad_cam_hsync(led2_o), - .pad_cam_data0(led3_o), - .pad_cam_data1(switch0_i), - .pad_cam_data2(switch1_i), - .pad_cam_data3(btn0_i), - .pad_cam_data4(btn1_i), - .pad_cam_data5(btn2_i), - .pad_cam_data6(btn3_i), - .pad_cam_data7(switch2_i), - .pad_cam_vsync(switch3_i), - .pad_sdio_clk(pad_hdmi_scl), - .pad_sdio_cmd(pad_hdmi_sda), - .pad_sdio_data0(pad_pmod1_0), - .pad_sdio_data1(pad_pmod1_1), - .pad_sdio_data2(pad_pmod1_2), - .pad_sdio_data3(pad_pmod1_3), - .pad_i2c0_sda(pad_i2c0_sda), - .pad_i2c0_scl(pad_i2c0_scl), - .pad_i2s0_sck(pad_pmod1_4), - .pad_i2s0_ws(pad_pmod1_5), - .pad_i2s0_sdi(pad_pmod1_6), - .pad_i2s1_sdi(pad_pmod1_7), - .pad_reset_n(~pad_reset), - .pad_jtag_tck(pad_jtag_tck), - .pad_jtag_tdi(pad_jtag_tdi), - .pad_jtag_tdo(pad_jtag_tdo), - .pad_jtag_tms(pad_jtag_tms), - .pad_jtag_trst(1'b1), - .pad_xtal_in(ref_clk), - .pad_bootsel() - ); - -endmodule diff --git a/fpga/pulpissimo-zcu104/tcl/.gitignore b/fpga/pulpissimo-zcu104/tcl/.gitignore deleted file mode 100644 index 587a0fa6..00000000 --- a/fpga/pulpissimo-zcu104/tcl/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -#Ignore tcl files generated by ipstools -ips_add_files.tcl -ips_inc_dirs.tcl -ips_src_files.tcl -rtl_add_files.tcl -rtl_src_files.tcl \ No newline at end of file diff --git a/fpga/pulpissimo-zcu104/tcl/messages.tcl b/fpga/pulpissimo-zcu104/tcl/messages.tcl deleted file mode 100644 index e8bfaf90..00000000 --- a/fpga/pulpissimo-zcu104/tcl/messages.tcl +++ /dev/null @@ -1,13 +0,0 @@ -# sets up Vivado messages in a more sensible way - -set_msg_config -id {[Synth 8-3352]} -new_severity "critical warning" -set_msg_config -id {[Synth 8-350]} -new_severity "critical warning" -set_msg_config -id {[Synth 8-2490]} -new_severity "warning" -set_msg_config -id {[Synth 8-2306]} -new_severity "info" -set_msg_config -id {[Synth 8-3331]} -new_severity "critical warning" -set_msg_config -id {[Synth 8-3332]} -new_severity "info" -set_msg_config -id {[Synth 8-2715]} -new_severity "error" -set_msg_config -id {[Opt 31-35]} -new_severity "info" -set_msg_config -id {[Opt 31-32]} -new_severity "info" -set_msg_config -id {[Shape Builder 18-119]} -new_severity "warning" -set_msg_config -id {[Filemgmt 20-742]} -new_severity "error" diff --git a/fpga/pulpissimo-zcu104/tcl/run.tcl b/fpga/pulpissimo-zcu104/tcl/run.tcl deleted file mode 100644 index 8d138a3b..00000000 --- a/fpga/pulpissimo-zcu104/tcl/run.tcl +++ /dev/null @@ -1,135 +0,0 @@ -set project pulpissimo_zcu104 -set RTL ../../../rtl -set IPS ../../../ips -set CONSTRS constraints - - -# detect board -if [info exists ::env(BOARD)] { - set BOARD $::env(BOARD) -} else { - puts "Please execute 'source ../sourceme.sh first before you start vivado in order to setup necessary environment variables." - exit -} -if [info exists ::env(XILINX_BOARD)] { - set XILINX_BOARD $::env(XILINX_BOARD) -} - -# create project -create_project $project . -force -part $::env(XILINX_PART) -set_property board_part $XILINX_BOARD [current_project] - -# set up meaningfull errors -source tcl/messages.tcl - -# set up includes -source ../pulpissimo/tcl/ips_inc_dirs.tcl -set_property include_dirs $INCLUDE_DIRS [current_fileset] -set_property include_dirs $INCLUDE_DIRS [current_fileset -simset] - -# setup and add IP source files -source ../pulpissimo/tcl/ips_src_files.tcl -source ../pulpissimo/tcl/ips_add_files.tcl - -# setup and add RTL source files -source ../pulpissimo/tcl/rtl_src_files.tcl -source ../pulpissimo/tcl/rtl_add_files.tcl - -# Override IPSApprox default variables -set FPGA_RTL rtl -set FPGA_IPS ips - -# remove duplicate incompatible modules -remove_files $IPS/pulp_soc/rtl/components/axi_slice_dc_slave_wrap.sv -remove_file $IPS/pulp_soc/rtl/components/axi_slice_dc_master_wrap.sv -remove_file $IPS/tech_cells_generic/pad_functional_xilinx.sv - -# Set Verilog Defines. -set DEFINES "FPGA_TARGET_XILINX=1 PULP_FPGA_EMUL=1 AXI4_XCHECK_OFF=1" -if { $BOARD == "zcu104" } { - set DEFINES "$DEFINES ZCU104=1" -} -set_property verilog_define $DEFINES [current_fileset] - -# detect target clock -if [info exists ::env(FC_CLK_PERIOD_NS)] { - set FC_CLK_PERIOD_NS $::env(FC_CLK_PERIOD_NS) -} else { - set FC_CLK_PERIOD_NS 10.000 -} -set CLK_HALFPERIOD_NS [expr ${FC_CLK_PERIOD_NS} / 2.0] - -# Add toplevel wrapper -add_files -norecurse $FPGA_RTL/xilinx_pulpissimo.v - -# Add Xilinx IPs -read_ip $FPGA_IPS/xilinx_clk_mngr/ip/xilinx_clk_mngr.xci -read_ip $FPGA_IPS/xilinx_slow_clk_mngr/ip/xilinx_slow_clk_mngr.xci -read_ip $FPGA_IPS/xilinx_interleaved_ram/ip/xilinx_interleaved_ram.xci -read_ip $FPGA_IPS/xilinx_private_ram/ip/xilinx_private_ram.xci - -# Add wrappers and xilinx specific techcells -add_files -norecurse $FPGA_RTL/fpga_clk_gen.sv -add_files -norecurse $FPGA_RTL/fpga_slow_clk_gen.sv -add_files -norecurse $FPGA_RTL/fpga_interleaved_ram.sv -add_files -norecurse $FPGA_RTL/fpga_private_ram.sv -add_files -norecurse $FPGA_RTL/fpga_bootrom.sv -add_files -norecurse $FPGA_RTL/pad_functional_xilinx.sv -add_files -norecurse $FPGA_RTL/pulp_clock_gating_xilinx.sv - - -# set pulpissimo as top -set_property top xilinx_pulpissimo [current_fileset]; # - -# needed only if used in batch mode -update_compile_order -fileset sources_1 - -# Add constraints -add_files -fileset constrs_1 -norecurse $CONSTRS/zcu104.xdc - -# Elaborate design -synth_design -rtl -name rtl_1 -sfcu;# sfcu -> run synthesis in single file compilation unit mode - - - -# launch synthesis -set_property STEPS.SYNTH_DESIGN.ARGS.FLATTEN_HIERARCHY none [get_runs synth_1] -set_property -name {STEPS.SYNTH_DESIGN.ARGS.MORE OPTIONS} -value -sfcu -objects [get_runs synth_1] ;# Use single file compilation unit mode to prevent issues with import pkg::* statements in the codebase -launch_runs synth_1 -jobs 8 -wait_on_run synth_1 -open_run synth_1 -name netlist_1 -set_property needs_refresh false [get_runs synth_1] - -# Remove unused IOBUF cells in padframe (they are not optimized away since the -# pad driver also drives the input creating a datapath from pad_xy_o to pad_xy_i -# ) -remove_cell i_pulpissimo/pad_frame_i/padinst_bootsel - - -# Launch Implementation - -# set for RuntimeOptimized implementation -set_property "steps.opt_design.args.directive" "RuntimeOptimized" [get_runs impl_1] -set_property "steps.place_design.args.directive" "RuntimeOptimized" [get_runs impl_1] -set_property "steps.route_design.args.directive" "RuntimeOptimized" [get_runs impl_1] -set_property "steps.phys_opt_design.args.is_enabled" true [get_runs impl_1] -set_property "steps.phys_opt_design.args.directive" "ExploreWithHoldFix" [get_runs impl_1] -set_property "steps.post_route_phys_opt_design.args.is_enabled" true [get_runs impl_1] -set_property "steps.post_route_phys_opt_design.args.directive" "ExploreWithAggressiveHoldFix" [get_runs impl_1] - -set_property STEPS.WRITE_BITSTREAM.ARGS.BIN_FILE true [get_runs impl_1] - -launch_runs impl_1 -jobs 8 -wait_on_run impl_1 -launch_runs impl_1 -to_step write_bitstream -wait_on_run impl_1 - -open_run impl_1 - -# Generate reports -exec mkdir -p reports/ -exec rm -rf reports/* -check_timing -file reports/${project}.check_timing.rpt -report_timing -max_paths 100 -nworst 100 -delay_type max -sort_by slack -file reports/${project}.timing_WORST_100.rpt -report_timing -nworst 1 -delay_type max -sort_by group -file reports/${project}.timing.rpt -report_utilization -hierarchical -file reports/${project}.utilization.rpt From 68f735eec8950126dc385931e5cb4ac74ca6eb8f Mon Sep 17 00:00:00 2001 From: Jie CHEN Date: Tue, 22 Oct 2019 11:17:14 +0200 Subject: [PATCH 02/46] Update for pulpissimo to PULP --- generate-scripts | 20 +++++++++----------- generate-scripts-fpga | 43 +++++++++++++++++++++++++++++++++++++++++++ ips_list.yml | 1 + 3 files changed, 53 insertions(+), 11 deletions(-) create mode 100755 generate-scripts-fpga diff --git a/generate-scripts b/generate-scripts index afb87880..79077f8c 100755 --- a/generate-scripts +++ b/generate-scripts @@ -35,8 +35,6 @@ execute("mkdir -p sim/vcompile/rtl") execute("rm -rf sim/vcompile/rtl/*") execute("mkdir -p sim/vcompile/tb") execute("rm -rf sim/vcompile/tb/*") -execute("mkdir -p fpga/pulpissimo/tcl") -execute("rm -rf fpga/pulpissimo/tcl/*") execute("mkdir -p sim/ncompile/ips") execute("rm -rf sim/ncompile/ips/*") @@ -94,16 +92,16 @@ for line in fileinput.input("sim/ncompile/src_ips_files.f", inplace=True): print(line) -# Generate FPGA scripts -# generate Vivado src_files.tcl -ipdb.export_vivado(script_path="fpga/pulpissimo/tcl/ips_src_files.tcl", domain='soc') -ipdb.export_vivado(script_path="fpga/pulpissimo/tcl/rtl_src_files.tcl", domain='soc', source='rtl') +# # Generate FPGA scripts +# # generate Vivado src_files.tcl +# ipdb.export_vivado(script_path="fpga/pulpissimo/tcl/ips_src_files.tcl", domain='soc') +# ipdb.export_vivado(script_path="fpga/pulpissimo/tcl/rtl_src_files.tcl", domain='soc', source='rtl') -# generate Vivado add_files.tcl -ipdb.generate_vivado_add_files("fpga/pulpissimo/tcl/ips_add_files.tcl", domain='soc') -ipdb.generate_vivado_add_files("fpga/pulpissimo/tcl/rtl_add_files.tcl", domain='soc', source='rtl') +# # generate Vivado add_files.tcl +# ipdb.generate_vivado_add_files("fpga/pulpissimo/tcl/ips_add_files.tcl", domain='soc') +# ipdb.generate_vivado_add_files("fpga/pulpissimo/tcl/rtl_add_files.tcl", domain='soc', source='rtl') -# generate Vivado inc_dirs.tcl -ipdb.generate_vivado_inc_dirs("fpga/pulpissimo/tcl/ips_inc_dirs.tcl", domain='soc') +# # generate Vivado inc_dirs.tcl +# ipdb.generate_vivado_inc_dirs("fpga/pulpissimo/tcl/ips_inc_dirs.tcl", domain='soc') print(tcolors.OK + "Generated new scripts for IPs!" + tcolors.ENDC) diff --git a/generate-scripts-fpga b/generate-scripts-fpga new file mode 100755 index 00000000..eb992fb5 --- /dev/null +++ b/generate-scripts-fpga @@ -0,0 +1,43 @@ +#!/usr/bin/env python +# Francesco Conti +# +# Copyright (C) 2016 ETH Zurich, University of Bologna. +# All rights reserved. + +from ipstools_cfg import * + +execute("mkdir -p fpga/sim/vcompile/ips") +execute("rm -rf fpga/sim/vcompile/ips/*") +execute("mkdir -p fpga/sim/vcompile/rtl") +execute("rm -rf fpga/sim/vcompile/rtl/*") + +# creates an IPApproX database +ipdb = ipstools.IPDatabase(rtl_dir='rtl', ips_dir='ips', vsim_dir='sim', load_cache=True) + + +# do the same for FPGA platform simulation +ipdb.export_make(script_path="fpga/sim/vcompile/ips", target_tech='xilinx') +ipdb.export_make(script_path="fpga/sim/vcompile/rtl", target_tech='xilinx', source='rtl') +ipdb.generate_vsim_tcl("fpga/sim/tcl_files/config/vsim_ips.tcl") +ipdb.generate_vsim_tcl("fpga/sim/tcl_files/config/vsim_rtl.tcl", source='rtl') +ipdb.generate_makefile("fpga/sim/vcompile/ips.mk", target_tech='xilinx') +ipdb.generate_makefile("fpga/sim/vcompile/rtl.mk", target_tech='xilinx', source='rtl') + +# generate Vivado compilation scripts +ipdb.export_vivado(script_path="fpga/ulpcluster/tcl/ips_src_files.tcl", domain='cluster') +ipdb.export_vivado(script_path="fpga/ulpcluster/tcl/rtl_src_files.tcl", domain='cluster', source='rtl') +ipdb.export_vivado(script_path="fpga/pulpemu/tcl/ips_src_files.tcl", domain='soc') +ipdb.export_vivado(script_path="fpga/pulpemu/tcl/rtl_src_files.tcl", domain='soc', source='rtl') +# generate Vivado add_files.tcl +ipdb.generate_vivado_add_files("fpga/ulpcluster/tcl/ips_add_files.tcl", domain='cluster') +ipdb.generate_vivado_add_files("fpga/ulpcluster/tcl/rtl_add_files.tcl", domain='cluster', source='rtl') +ipdb.generate_vivado_add_files("fpga/pulpemu/tcl/ips_add_files.tcl", domain='soc') +ipdb.generate_vivado_add_files("fpga/pulpemu/tcl/rtl_add_files.tcl", domain='soc', source='rtl') +# generate Vivado inc_dirs.tcl +ipdb.generate_vivado_inc_dirs("fpga/ulpcluster/tcl/ips_inc_dirs.tcl", domain='cluster') +ipdb.generate_vivado_inc_dirs("fpga/ulpcluster/tcl/rtl_inc_dirs.tcl", domain='cluster', source='rtl') +ipdb.generate_vivado_inc_dirs("fpga/pulpemu/tcl/ips_inc_dirs.tcl", domain='soc') +ipdb.generate_vivado_inc_dirs("fpga/pulpemu/tcl/rtl_inc_dirs.tcl", domain='soc', source='rtl') + +print tcolors.OK + "Generated sim scripts for IPs!" + tcolors.ENDC + diff --git a/ips_list.yml b/ips_list.yml index 0ebd3d14..af925a54 100644 --- a/ips_list.yml +++ b/ips_list.yml @@ -20,6 +20,7 @@ pulp_soc: commit: v1.1.0 + domain: [soc] server: https://github.com group: pulp-platform From 41e9c5d977a18a306215d6507493bb0aaa372ffb Mon Sep 17 00:00:00 2001 From: Jie CHEN Date: Tue, 22 Oct 2019 13:24:52 +0200 Subject: [PATCH 03/46] Update for seperating domain --- ips_list.yml | 2 ++ rtl_list.yml | 3 +++ 2 files changed, 5 insertions(+) diff --git a/ips_list.yml b/ips_list.yml index af925a54..0a80fb77 100644 --- a/ips_list.yml +++ b/ips_list.yml @@ -31,5 +31,7 @@ pulp_cluster: tbtools: commit: v0.1 + commit: master + domain: [soc] server: https://github.com group: pulp-platform diff --git a/rtl_list.yml b/rtl_list.yml index 6af3b2f2..1602196d 100644 --- a/rtl_list.yml +++ b/rtl_list.yml @@ -8,8 +8,11 @@ tb: path: tb + domain: [soc] vip: path: vip + domain: [soc] pulp: path: pulp + domain: [soc] From 2cf0e46b7b3508e0afb998757d58ef9afa2a0342 Mon Sep 17 00:00:00 2001 From: Jie CHEN Date: Tue, 22 Oct 2019 13:46:41 +0200 Subject: [PATCH 04/46] Update emu - TODO --- rtl/pulpemu/fpga_clk_gen.sv | 74 ++++++++ rtl/pulpemu/fpga_interleaved_ram.sv | 57 ++++++ rtl/pulpemu/fpga_private_ram.sv | 57 ++++++ rtl/pulpemu/pulpemu.sv | 284 ++++++++++++++++++++++++++++ rtl/pulpemu/pulpemu_ref_clk_div.sv | 37 ++++ rtl/pulpemu/src_files.yml | 15 ++ 6 files changed, 524 insertions(+) create mode 100644 rtl/pulpemu/fpga_clk_gen.sv create mode 100644 rtl/pulpemu/fpga_interleaved_ram.sv create mode 100644 rtl/pulpemu/fpga_private_ram.sv create mode 100644 rtl/pulpemu/pulpemu.sv create mode 100644 rtl/pulpemu/pulpemu_ref_clk_div.sv create mode 100644 rtl/pulpemu/src_files.yml diff --git a/rtl/pulpemu/fpga_clk_gen.sv b/rtl/pulpemu/fpga_clk_gen.sv new file mode 100644 index 00000000..2ad9a8eb --- /dev/null +++ b/rtl/pulpemu/fpga_clk_gen.sv @@ -0,0 +1,74 @@ +//----------------------------------------------------------------------------- +// Title : FPGA CLK Gen for PULPissimo +// ----------------------------------------------------------------------------- +// File : fpga_clk_gen.sv Author : Manuel Eggimann +// Created : 17.05.2019 +// ----------------------------------------------------------------------------- +// Description : Instantiates Xilinx clocking wizard IP to generate 2 output +// clocks. Currently, the clock is not dynamicly reconfigurable and all +// configuration requests are acknowledged without any effect. +// ----------------------------------------------------------------------------- +// Copyright (C) 2013-2019 ETH Zurich, University of Bologna Copyright and +// related rights are licensed under the Solderpad Hardware License, Version +// 0.51 (the "License"); you may not use this file except in compliance with the +// License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law or +// agreed to in writing, software, hardware and materials distributed under this +// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS +// OF ANY KIND, either express or implied. See the License for the specific +// language governing permissions and limitations under the License. +// ----------------------------------------------------------------------------- + + +module fpga_clk_gen ( + input logic ref_clk_i, + input logic rstn_glob_i, + input logic test_mode_i, + input logic shift_enable_i, + output logic soc_clk_o, + output logic per_clk_o, + output logic cluster_clk_o, + output logic soc_cfg_lock_o, + input logic soc_cfg_req_i, + output logic soc_cfg_ack_o, + input logic [1:0] soc_cfg_add_i, + input logic [31:0] soc_cfg_data_i, + output logic [31:0] soc_cfg_r_data_o, + input logic soc_cfg_wrn_i, + output logic per_cfg_lock_o, + input logic per_cfg_req_i, + output logic per_cfg_ack_o, + input logic [1:0] per_cfg_add_i, + input logic [31:0] per_cfg_data_i, + output logic [31:0] per_cfg_r_data_o, + input logic per_cfg_wrn_i, + output logic cluster_cfg_lock_o, + input logic cluster_cfg_req_i, + output logic cluster_cfg_ack_o, + input logic [1:0] cluster_cfg_add_i, + input logic [31:0] cluster_cfg_data_i, + output logic [31:0] cluster_cfg_r_data_o, + input logic cluster_cfg_wrn_i + ); + + logic s_locked; + + xilinx_clk_mngr i_clk_manager + ( + .resetn(rstn_glob_i), + .clk_in1(ref_clk_i), + .clk_out1(soc_clk_o), + .clk_out2(per_clk_o), + .locked(s_locked) + ); + + assign soc_cfg_lock_o = s_locked; + assign per_cfg_lock_o = s_locked; + + assign soc_cfg_ack_o = 1'b1; //Always acknowledge without doing anything for now + assign per_cfg_ack_o = 1'b1; + + assign soc_cfg_r_data_o = 32'hdeadda7a; + assign per_cfg_r_data_o = 32'hdeadda7a; + +endmodule : fpga_clk_gen diff --git a/rtl/pulpemu/fpga_interleaved_ram.sv b/rtl/pulpemu/fpga_interleaved_ram.sv new file mode 100644 index 00000000..7d52e5d8 --- /dev/null +++ b/rtl/pulpemu/fpga_interleaved_ram.sv @@ -0,0 +1,57 @@ +//----------------------------------------------------------------------------- +// Title : FPGA Interleaved RAM Bank for PULPissimo +// ----------------------------------------------------------------------------- +// File : fpga_interleaved_ram.sv Author : Manuel Eggimann +// Created : 20.05.2019 +// ----------------------------------------------------------------------------- +// Description : Instantiated block ram generator IP to replace the SRAM banks +// in the interleaved region of L2. Since Xilinx LogicoreIP are not customizable +// via parameters, the bank size selected in l2_ram_multibank must match the one +// used in the TCL script for IP generation. +// ----------------------------------------------------------------------------- +// Copyright (C) 2013-2019 ETH Zurich, University of Bologna Copyright and +// related rights are licensed under the Solderpad Hardware License, Version +// 0.51 (the "License"); you may not use this file except in compliance with the +// License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law or +// agreed to in writing, software, hardware and materials distributed under this +// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS +// OF ANY KIND, either express or implied. See the License for the specific +// language governing permissions and limitations under the License. +// ----------------------------------------------------------------------------- + +module fpga_interleaved_ram + #( + parameter ADDR_WIDTH=12 + ) ( + input logic clk_i, + input logic rst_ni, + input logic csn_i, + input logic wen_i, + input logic [3:0] be_i, + input logic [ADDR_WIDTH-1:0] addr_i, + input logic [31:0] wdata_i, + output logic [31:0] rdata_o + ); + + logic [3:0] wea; + + always_comb begin + if (wen_i == 1'b0) begin + wea = be_i; + end else begin + wea = '0; + end + end + + xilinx_interleaved_ram i_xilinx_interleaved_ram + ( + .clka(clk_i), + .ena(~csn_i), + .wea(wea), + .addra(addr_i), + .dina(wdata_i), + .douta(rdata_o) + ); + +endmodule : fpga_interleaved_ram diff --git a/rtl/pulpemu/fpga_private_ram.sv b/rtl/pulpemu/fpga_private_ram.sv new file mode 100644 index 00000000..05244931 --- /dev/null +++ b/rtl/pulpemu/fpga_private_ram.sv @@ -0,0 +1,57 @@ +//----------------------------------------------------------------------------- +// Title : FPGA Private RAM Bank for PULPissimo +// ----------------------------------------------------------------------------- +// File : fpga_private_ram.sv Author : Manuel Eggimann +// Created : 20.05.2019 +// ----------------------------------------------------------------------------- +// Description : Instantiated block ram generator IP to replace the SRAM banks +// in the private region of L2. Since Xilinx LogicoreIP are not customizable +// via parameters, the bank size selected in l2_ram_multibank must match the one +// used in the TCL script for IP generation. +// ----------------------------------------------------------------------------- +// Copyright (C) 2013-2019 ETH Zurich, University of Bologna Copyright and +// related rights are licensed under the Solderpad Hardware License, Version +// 0.51 (the "License"); you may not use this file except in compliance with the +// License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law or +// agreed to in writing, software, hardware and materials distributed under this +// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS +// OF ANY KIND, either express or implied. See the License for the specific +// language governing permissions and limitations under the License. +// ----------------------------------------------------------------------------- + +module fpga_private_ram + #( + parameter ADDR_WIDTH=12 + ) ( + input logic clk_i, + input logic rst_ni, + input logic csn_i, + input logic wen_i, + input logic [3:0] be_i, + input logic [ADDR_WIDTH-1:0] addr_i, + input logic [31:0] wdata_i, + output logic [31:0] rdata_o + ); + + logic [3:0] wea; + + always_comb begin + if (wen_i == 1'b0) begin + wea = be_i; + end else begin + wea = '0; + end + end + + xilinx_private_ram i_xilinx_private_ram + ( + .clka(clk_i), + .ena(~csn_i), + .wea(wea), + .addra(addr_i), + .dina(wdata_i), + .douta(rdata_o) + ); + +endmodule : fpga_private_ram diff --git a/rtl/pulpemu/pulpemu.sv b/rtl/pulpemu/pulpemu.sv new file mode 100644 index 00000000..a48bbef7 --- /dev/null +++ b/rtl/pulpemu/pulpemu.sv @@ -0,0 +1,284 @@ +/* + * Copyright (C) 2013-2017 ETH Zurich, University of Bologna + * All rights reserved. + * + * This code is under development and not yet released to the public. + * Until it is released, the code is under the copyright of ETH Zurich and + * the University of Bologna, and may contain confidential and/or unpublished + * work. Any reuse/redistribution is strictly forbidden without written + * permission from ETH Zurich. + * + * Bug fixes and contributions will eventually be released under the + * SolderPad open hardware license in the context of the PULP platform + * (http://www.pulp-platform.org), under the copyright of ETH Zurich and the + * University of Bologna. + */ + +`include "ulpsoc_defines.sv" + +`ifndef PULP_FPGA_SIM + `define PULP_FPGA_NETLIST +`endif + +module pulpemu + ( + // LED for VERIFY + output LED, + // FMC pins + inout FMC_csi2_clkp, + inout FMC_csi2_clkn, + inout FMC_csi2_datap0, + inout FMC_csi2_datan0, + inout FMC_csi2_datap1, + inout FMC_csi2_datan1, + inout FMC_pwm0, + inout FMC_pwm1, + inout FMC_pwm2, + inout FMC_pwm3, + inout FMC_qspi_sdio0, + inout FMC_qspi_sdio1, + inout FMC_qspi_sdio2, + inout FMC_qspi_sdio3, + inout FMC_qspi_cs0, + inout FMC_qspi_sck, + inout FMC_spim0_sck, + inout FMC_spim0_cs0, + inout FMC_spim0_miso, + inout FMC_spim0_mosi, + inout FMC_i3c0_sda, + inout FMC_i3c0_scl, + inout FMC_uart0_rx, + inout FMC_uart0_tx, + inout FMC_uart1_rx, + inout FMC_uart1_tx, + inout FMC_spim1_sck, + inout FMC_spim1_cs0, + inout FMC_spim1_miso, + inout FMC_spim1_mosi, + inout FMC_i3c1_sda, + inout FMC_i3c1_scl, + inout FMC_i2s_mst_sck, + inout FMC_i2s_mst_ws, + inout FMC_i2s_mst_sdo0, + inout FMC_i2s_mst_sdo1, + inout FMC_i2s_slv_sck, + inout FMC_i2s_slv_ws, + inout FMC_i2s_slv_sdi0, + inout FMC_i2s_slv_sdi1, + inout FMC_spim2_sck, + inout FMC_spim2_cs0, + inout FMC_spim2_miso, + inout FMC_spim2_mosi, + inout FMC_i3c2_sda, + inout FMC_i3c2_scl, + inout FMC_cam_pclk, + inout FMC_cam_hsync, + inout FMC_cam_data0, + inout FMC_cam_data1, + inout FMC_cam_data2, + inout FMC_cam_data3, + inout FMC_cam_data4, + inout FMC_cam_data5, + inout FMC_cam_data6, + inout FMC_cam_data7, + inout FMC_cam_vsync, + inout FMC_hyper_ckn, + inout FMC_hyper_ck, + inout FMC_hyper_dq0, + inout FMC_hyper_dq1, + inout FMC_hyper_dq2, + inout FMC_hyper_dq3, + inout FMC_hyper_dq4, + inout FMC_hyper_dq5, + inout FMC_hyper_dq6, + inout FMC_hyper_dq7, + inout FMC_hyper_csn0, + inout FMC_hyper_csn1, + inout FMC_hyper_rwds, + inout FMC_jtag_tck, + inout FMC_jtag_tdi, + inout FMC_jtag_tdo, + inout FMC_jtag_tms, + inout FMC_jtag_trst, + inout FMC_bootmode, + inout FMC_reset_n + ); + + // pulpemu top signals + logic zynq_clk; + logic zynq_rst_n; + logic pulp_soc_clk; + logic pulp_cluster_clk; + + // reference 32768 Hz clock + wire ref_clk; + + + pulpemu_ref_clk_div + #( + .DIVISOR ( 256 ) + ) + ref_clk_div ( + .clk_i ( zynq_clk ), // FPGA inner clock, 8.388608 MHz + .rstn_i ( zynq_rst_n ), // FPGA inner reset + .ref_clk_o ( ref_clk ) // REF clock out + ); + + // 1 socond blink LED + pulpemu_ref_clk_div + #( + .DIVISOR ( 32768 ) + ) + led_clk_div ( + .clk_i ( ref_clk ), + .rstn_i ( zynq_rst_n ), + .ref_clk_o ( LED ) + ); + + + // ██████╗ ██╗ ██╗██╗ ██████╗ ██████╗██╗ ██╗██╗██████╗ + // ██╔══██╗██║ ██║██║ ██╔══██╗ ██╔════╝██║ ██║██║██╔══██╗ + // ██████╔╝██║ ██║██║ ██████╔╝ ██║ ███████║██║██████╔╝ + // ██╔═══╝ ██║ ██║██║ ██╔═══╝ ██║ ██╔══██║██║██╔═══╝ + // ██║ ╚██████╔╝███████╗██║███████╗╚██████╗██║ ██║██║██║ + // ╚═╝ ╚═════╝ ╚══════╝╚═╝╚══════╝ ╚═════╝╚═╝ ╚═╝╚═╝╚═╝ + + pulpissimo + #(.CORE_TYPE(CORE_TYPE), + .USE_FPU(USE_FPU), + .USE_HWPE(USE_HWPE) + ) i_pulpissimo + ( + .pad_spim_sdio0(pad_pmod0_4), + .pad_spim_sdio1(pad_pmod0_5), + .pad_spim_sdio2(pad_pmod0_6), + .pad_spim_sdio3(pad_pmod0_7), + // .pad_spim_csn0(pad_uart_rts), + .pad_spim_csn1(led0_o), + // .pad_spim_sck(pad_uart_cts), + .pad_uart_rx(pad_uart_rx), + .pad_uart_tx(pad_uart_tx), + .pad_cam_pclk(led1_o), + .pad_cam_hsync(led2_o), + .pad_cam_data0(led3_o), + .pad_cam_data1(switch0_i), + .pad_cam_data2(switch1_i), + .pad_cam_data3(btn0_i), + .pad_cam_data4(btn1_i), + .pad_cam_data5(btn2_i), + .pad_cam_data6(btn3_i), + .pad_cam_data7(switch2_i), + .pad_cam_vsync(switch3_i), + // .pad_sdio_clk(pad_hdmi_scl), + // .pad_sdio_cmd(pad_hdmi_sda), + // .pad_sdio_data0(pad_pmod1_0), + // .pad_sdio_data1(pad_pmod1_1), + // .pad_sdio_data2(pad_pmod1_2), + // .pad_sdio_data3(pad_pmod1_3), + // .pad_i2c0_sda(pad_i2c0_sda), + // .pad_i2c0_scl(pad_i2c0_scl), + // .pad_i2s0_sck(pad_pmod1_4), + // .pad_i2s0_ws(pad_pmod1_5), + // .pad_i2s0_sdi(pad_pmod1_6), + // .pad_i2s1_sdi(pad_pmod1_7), + .pad_reset_n(~pad_reset), + .pad_jtag_tck(pad_jtag_tck), + .pad_jtag_tdi(pad_jtag_tdi), + .pad_jtag_tdo(pad_jtag_tdo), + .pad_jtag_tms(pad_jtag_tms), + .pad_jtag_trst(1'b1), + .pad_xtal_in(ref_clk), + .pad_bootsel() + ); + + pulp_chip pulp_chip_i ( + .zynq_clk_i ( ref_clk ), // FPGA inner clock, 50 MHz + .zynq_soc_clk_i ( pulp_soc_clk ), // FPGA inner clock, 50 MHz + .zynq_cluster_clk_i ( pulp_cluster_clk ), // FPGA inner clock, 50 MHz + .zynq_per_clk_i ( pulp_per_clk ), // FPGA inner clock, 50 MHz + + .pad_csi2_clkp ( FMC_csi2_clkp ), + .pad_csi2_clkn ( FMC_csi2_clkn ), + .pad_csi2_datap0 ( FMC_csi2_datap0 ), + .pad_csi2_datan0 ( FMC_csi2_datan0 ), + .pad_csi2_datap1 ( FMC_csi2_datap1 ), + .pad_csi2_datan1 ( FMC_csi2_datan1 ), + .pad_pwm0 ( FMC_pwm0 ), + .pad_pwm1 ( FMC_pwm1 ), + .pad_pwm2 ( FMC_pwm2 ), + .pad_pwm3 ( FMC_pwm3 ), + .pad_qspi_sdio0 ( FMC_qspi_sdio0 ), + .pad_qspi_sdio1 ( FMC_qspi_sdio1 ), + .pad_qspi_sdio2 ( FMC_qspi_sdio2 ), + .pad_qspi_sdio3 ( FMC_qspi_sdio3 ), + .pad_qspi_cs0 ( FMC_qspi_cs0 ), + .pad_qspi_sck ( FMC_qspi_sck ), + .pad_spim0_sck ( FMC_spim0_sck ), + .pad_spim0_cs0 ( FMC_spim0_cs0 ), + .pad_spim0_miso ( FMC_spim0_miso ), + .pad_spim0_mosi ( FMC_spim0_mosi ), + .pad_i3c0_sda ( FMC_i3c0_sda ), + .pad_i3c0_scl ( FMC_i3c0_scl ), + .pad_uart0_rx ( FMC_uart0_rx ), + .pad_uart0_tx ( FMC_uart0_tx ), + .pad_uart1_rx ( FMC_uart1_rx ), + .pad_uart1_tx ( FMC_uart1_tx ), + .pad_spim1_sck ( FMC_spim1_sck ), + .pad_spim1_cs0 ( FMC_spim1_cs0 ), + .pad_spim1_miso ( FMC_spim1_miso ), + .pad_spim1_mosi ( FMC_spim1_mosi ), + .pad_i3c1_sda ( FMC_i3c1_sda ), + .pad_i3c1_scl ( FMC_i3c1_scl ), + .pad_i2s_mst_sck ( FMC_i2s_mst_sck ), + .pad_i2s_mst_ws ( FMC_i2s_mst_ws ), + .pad_i2s_mst_sdo0 ( FMC_i2s_mst_sdo0 ), + .pad_i2s_mst_sdo1 ( FMC_i2s_mst_sdo1 ), + .pad_i2s_slv_sck ( FMC_i2s_slv_sck ), + .pad_i2s_slv_ws ( FMC_i2s_slv_ws ), + .pad_i2s_slv_sdi0 ( FMC_i2s_slv_sdi0 ), + .pad_i2s_slv_sdi1 ( FMC_i2s_slv_sdi1 ), + .pad_spim2_sck ( FMC_spim2_sck ), + .pad_spim2_cs0 ( FMC_spim2_cs0 ), + .pad_spim2_miso ( FMC_spim2_miso ), + .pad_spim2_mosi ( FMC_spim2_mosi ), + .pad_i3c2_sda ( FMC_i3c2_sda ), + .pad_i3c2_scl ( FMC_i3c2_scl ), + .pad_cam_pclk ( FMC_cam_pclk ), + .pad_cam_hsync ( FMC_cam_hsync ), + .pad_cam_data0 ( FMC_cam_data0 ), + .pad_cam_data1 ( FMC_cam_data1 ), + .pad_cam_data2 ( FMC_cam_data2 ), + .pad_cam_data3 ( FMC_cam_data3 ), + .pad_cam_data4 ( FMC_cam_data4 ), + .pad_cam_data5 ( FMC_cam_data5 ), + .pad_cam_data6 ( FMC_cam_data6 ), + .pad_cam_data7 ( FMC_cam_data7 ), + .pad_cam_vsync ( FMC_cam_vsync ), + .pad_hyper_ckn ( FMC_hyper_ckn ), + .pad_hyper_ck ( FMC_hyper_ck ), + .pad_hyper_dq0 ( FMC_hyper_dq0 ), + .pad_hyper_dq1 ( FMC_hyper_dq1 ), + .pad_hyper_dq2 ( FMC_hyper_dq2 ), + .pad_hyper_dq3 ( FMC_hyper_dq3 ), + .pad_hyper_dq4 ( FMC_hyper_dq4 ), + .pad_hyper_dq5 ( FMC_hyper_dq5 ), + .pad_hyper_dq6 ( FMC_hyper_dq6 ), + .pad_hyper_dq7 ( FMC_hyper_dq7 ), + + // Pay attention, the Chip select of Pulp FMC Sensor Board is inverted + .pad_hyper_csn0 ( FMC_hyper_csn0 ), + .pad_hyper_csn1 ( FMC_hyper_csn1 ), + + .pad_hyper_rwds ( FMC_hyper_rwds ), + .pad_jtag_tdi ( FMC_jtag_tdi ), // inout wire + .pad_jtag_tdo ( FMC_jtag_tdo ), // inout wire + .pad_jtag_tms ( FMC_jtag_tms ), // inout wire + .pad_jtag_trst ( FMC_jtag_trst ), // inout wire + .pad_jtag_tck ( FMC_jtag_tck ), // inout wire + .pad_bootmode ( FMC_bootmode ), // Boot mode = 0; boot from flash; Boot mode = 1; boot from jtag + .pad_reset_n ( FMC_reset_n ) // inout wire + + ); + + +endmodule // pulpemu diff --git a/rtl/pulpemu/pulpemu_ref_clk_div.sv b/rtl/pulpemu/pulpemu_ref_clk_div.sv new file mode 100644 index 00000000..49f627f9 --- /dev/null +++ b/rtl/pulpemu/pulpemu_ref_clk_div.sv @@ -0,0 +1,37 @@ + +module pulpemu_ref_clk_div + #( + parameter DIVISOR = 256 + ) + ( + input logic clk_i, + input logic rstn_i, + output logic ref_clk_o + ); + + logic [($clog2(DIVISOR) - 1):0] counter; + + always_ff @(posedge clk_i, negedge rstn_i) + begin + if(!rstn_i) + begin + counter <= '0; + end + else + begin + if(counter >= (DIVISOR-1)) + counter <= '0; + else + counter <= counter + 1; + end // else: !if(!rstn_i) + end + + // The frequency of the output clk_out + // = The frequency of the input clk_in divided by DIVISOR + // For example: clk_i = 8.388608 Mhz, if you want to get 32768 Hz signal to be reference clock + // You will modify the DIVISOR parameter value to 256 + // Then the frequency of the output clk_out = 8.388608 Mhz/ 256 = 32768 Hz + + assign ref_clk_o = (counter < DIVISOR / 2 ) ? 1'b0 : 1'b1; + +endmodule diff --git a/rtl/pulpemu/src_files.yml b/rtl/pulpemu/src_files.yml new file mode 100644 index 00000000..cd6a1be7 --- /dev/null +++ b/rtl/pulpemu/src_files.yml @@ -0,0 +1,15 @@ +pulpemu: + incdirs: [ + ../includes, + ., + ] + targets: [ + xilinx, + ] + files: [ + fpga_clk_gen.sv + fpga_interleaved_ram.sv, + fpga_private_ram.sv, + pulpemu.sv, + pulpemu_ref_clk_div.sv, + ] From 5ce4291bdd921e3f6419bc4d384da65d30137aa8 Mon Sep 17 00:00:00 2001 From: Jie CHEN Date: Tue, 22 Oct 2019 14:22:06 +0200 Subject: [PATCH 05/46] Update pulpemu rtl_list --- rtl_list.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/rtl_list.yml b/rtl_list.yml index 1602196d..2412f823 100644 --- a/rtl_list.yml +++ b/rtl_list.yml @@ -12,6 +12,9 @@ tb: vip: path: vip domain: [soc] +pulpemu: + path: pulpemu + domain: [soc] pulp: path: pulp domain: [soc] From 25918fe95618c2dacf5f0ae28368e4a89f894c8a Mon Sep 17 00:00:00 2001 From: Jie CHEN Date: Tue, 22 Oct 2019 16:13:23 +0200 Subject: [PATCH 06/46] Update for fpga --- generate-scripts-fpga | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/generate-scripts-fpga b/generate-scripts-fpga index eb992fb5..67792c4f 100755 --- a/generate-scripts-fpga +++ b/generate-scripts-fpga @@ -24,18 +24,18 @@ ipdb.generate_makefile("fpga/sim/vcompile/ips.mk", target_tech='xilinx') ipdb.generate_makefile("fpga/sim/vcompile/rtl.mk", target_tech='xilinx', source='rtl') # generate Vivado compilation scripts -ipdb.export_vivado(script_path="fpga/ulpcluster/tcl/ips_src_files.tcl", domain='cluster') -ipdb.export_vivado(script_path="fpga/ulpcluster/tcl/rtl_src_files.tcl", domain='cluster', source='rtl') +ipdb.export_vivado(script_path="fpga/pulp_cluster/tcl/ips_src_files.tcl", domain='cluster') +ipdb.export_vivado(script_path="fpga/pulp_cluster/tcl/rtl_src_files.tcl", domain='cluster', source='rtl') ipdb.export_vivado(script_path="fpga/pulpemu/tcl/ips_src_files.tcl", domain='soc') ipdb.export_vivado(script_path="fpga/pulpemu/tcl/rtl_src_files.tcl", domain='soc', source='rtl') # generate Vivado add_files.tcl -ipdb.generate_vivado_add_files("fpga/ulpcluster/tcl/ips_add_files.tcl", domain='cluster') -ipdb.generate_vivado_add_files("fpga/ulpcluster/tcl/rtl_add_files.tcl", domain='cluster', source='rtl') +ipdb.generate_vivado_add_files("fpga/pulp_cluster/tcl/ips_add_files.tcl", domain='cluster') +ipdb.generate_vivado_add_files("fpga/pulp_cluster/tcl/rtl_add_files.tcl", domain='cluster', source='rtl') ipdb.generate_vivado_add_files("fpga/pulpemu/tcl/ips_add_files.tcl", domain='soc') ipdb.generate_vivado_add_files("fpga/pulpemu/tcl/rtl_add_files.tcl", domain='soc', source='rtl') # generate Vivado inc_dirs.tcl -ipdb.generate_vivado_inc_dirs("fpga/ulpcluster/tcl/ips_inc_dirs.tcl", domain='cluster') -ipdb.generate_vivado_inc_dirs("fpga/ulpcluster/tcl/rtl_inc_dirs.tcl", domain='cluster', source='rtl') +ipdb.generate_vivado_inc_dirs("fpga/pulp_cluster/tcl/ips_inc_dirs.tcl", domain='cluster') +ipdb.generate_vivado_inc_dirs("fpga/pulp_cluster/tcl/rtl_inc_dirs.tcl", domain='cluster', source='rtl') ipdb.generate_vivado_inc_dirs("fpga/pulpemu/tcl/ips_inc_dirs.tcl", domain='soc') ipdb.generate_vivado_inc_dirs("fpga/pulpemu/tcl/rtl_inc_dirs.tcl", domain='soc', source='rtl') From d4b283122a8e9c23d262218f9161085130299928 Mon Sep 17 00:00:00 2001 From: Jie CHEN Date: Tue, 22 Oct 2019 18:04:28 +0200 Subject: [PATCH 07/46] Update fpga --- update-fpga | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100755 update-fpga diff --git a/update-fpga b/update-fpga new file mode 100755 index 00000000..bf43e8bb --- /dev/null +++ b/update-fpga @@ -0,0 +1,27 @@ +#!/bin/bash -e + +BLUE='\033[0;34m' +RED='\033[0;31m' +NC='\033[0m' # No Color +BOLD='\033[1m' +STD='\033[0m' + +if [ ! -e fpga ]; then + git clone git@iis-git.ee.ethz.ch:garofalo/jtag_fpga.git fpga + pushd fpga > /dev/null + echo -e "${BOLD}${BLUE}Cloning fpga${NC}${STD}" +else + pushd fpga > /dev/null + git checkout master + git pull + echo -e "${BOLD}${BLUE}Updating fpga${NC}${STD}" +fi + +ENV_COMMIT=pulp + +git checkout ${ENV_COMMIT} +echo -e "${BOLD}${BLUE}Moving to commit ${ENV_COMMIT}${NC}${STD}" + +popd > /dev/null + +./generate-scripts-fpga From 8a60506887e7f2cb772cc891f3da3f5650bedae3 Mon Sep 17 00:00:00 2001 From: Jie CHEN Date: Wed, 23 Oct 2019 10:43:55 +0200 Subject: [PATCH 08/46] Update pulpemu.sv --- rtl/pulpemu/fpga_clk_gen.sv | 74 ---------- rtl/pulpemu/pulpemu.sv | 274 ++++++++++++------------------------ rtl/pulpemu/src_files.yml | 1 - 3 files changed, 88 insertions(+), 261 deletions(-) delete mode 100644 rtl/pulpemu/fpga_clk_gen.sv diff --git a/rtl/pulpemu/fpga_clk_gen.sv b/rtl/pulpemu/fpga_clk_gen.sv deleted file mode 100644 index 2ad9a8eb..00000000 --- a/rtl/pulpemu/fpga_clk_gen.sv +++ /dev/null @@ -1,74 +0,0 @@ -//----------------------------------------------------------------------------- -// Title : FPGA CLK Gen for PULPissimo -// ----------------------------------------------------------------------------- -// File : fpga_clk_gen.sv Author : Manuel Eggimann -// Created : 17.05.2019 -// ----------------------------------------------------------------------------- -// Description : Instantiates Xilinx clocking wizard IP to generate 2 output -// clocks. Currently, the clock is not dynamicly reconfigurable and all -// configuration requests are acknowledged without any effect. -// ----------------------------------------------------------------------------- -// Copyright (C) 2013-2019 ETH Zurich, University of Bologna Copyright and -// related rights are licensed under the Solderpad Hardware License, Version -// 0.51 (the "License"); you may not use this file except in compliance with the -// License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law or -// agreed to in writing, software, hardware and materials distributed under this -// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS -// OF ANY KIND, either express or implied. See the License for the specific -// language governing permissions and limitations under the License. -// ----------------------------------------------------------------------------- - - -module fpga_clk_gen ( - input logic ref_clk_i, - input logic rstn_glob_i, - input logic test_mode_i, - input logic shift_enable_i, - output logic soc_clk_o, - output logic per_clk_o, - output logic cluster_clk_o, - output logic soc_cfg_lock_o, - input logic soc_cfg_req_i, - output logic soc_cfg_ack_o, - input logic [1:0] soc_cfg_add_i, - input logic [31:0] soc_cfg_data_i, - output logic [31:0] soc_cfg_r_data_o, - input logic soc_cfg_wrn_i, - output logic per_cfg_lock_o, - input logic per_cfg_req_i, - output logic per_cfg_ack_o, - input logic [1:0] per_cfg_add_i, - input logic [31:0] per_cfg_data_i, - output logic [31:0] per_cfg_r_data_o, - input logic per_cfg_wrn_i, - output logic cluster_cfg_lock_o, - input logic cluster_cfg_req_i, - output logic cluster_cfg_ack_o, - input logic [1:0] cluster_cfg_add_i, - input logic [31:0] cluster_cfg_data_i, - output logic [31:0] cluster_cfg_r_data_o, - input logic cluster_cfg_wrn_i - ); - - logic s_locked; - - xilinx_clk_mngr i_clk_manager - ( - .resetn(rstn_glob_i), - .clk_in1(ref_clk_i), - .clk_out1(soc_clk_o), - .clk_out2(per_clk_o), - .locked(s_locked) - ); - - assign soc_cfg_lock_o = s_locked; - assign per_cfg_lock_o = s_locked; - - assign soc_cfg_ack_o = 1'b1; //Always acknowledge without doing anything for now - assign per_cfg_ack_o = 1'b1; - - assign soc_cfg_r_data_o = 32'hdeadda7a; - assign per_cfg_r_data_o = 32'hdeadda7a; - -endmodule : fpga_clk_gen diff --git a/rtl/pulpemu/pulpemu.sv b/rtl/pulpemu/pulpemu.sv index a48bbef7..a85f5eaa 100644 --- a/rtl/pulpemu/pulpemu.sv +++ b/rtl/pulpemu/pulpemu.sv @@ -25,52 +25,27 @@ module pulpemu // LED for VERIFY output LED, // FMC pins - inout FMC_csi2_clkp, - inout FMC_csi2_clkn, - inout FMC_csi2_datap0, - inout FMC_csi2_datan0, - inout FMC_csi2_datap1, - inout FMC_csi2_datan1, - inout FMC_pwm0, - inout FMC_pwm1, - inout FMC_pwm2, - inout FMC_pwm3, inout FMC_qspi_sdio0, inout FMC_qspi_sdio1, inout FMC_qspi_sdio2, inout FMC_qspi_sdio3, - inout FMC_qspi_cs0, + inout FMC_qspi_csn0, + inout FMC_qspi_csn1, inout FMC_qspi_sck, - inout FMC_spim0_sck, - inout FMC_spim0_cs0, - inout FMC_spim0_miso, - inout FMC_spim0_mosi, - inout FMC_i3c0_sda, - inout FMC_i3c0_scl, - inout FMC_uart0_rx, - inout FMC_uart0_tx, - inout FMC_uart1_rx, - inout FMC_uart1_tx, - inout FMC_spim1_sck, - inout FMC_spim1_cs0, - inout FMC_spim1_miso, - inout FMC_spim1_mosi, - inout FMC_i3c1_sda, - inout FMC_i3c1_scl, - inout FMC_i2s_mst_sck, - inout FMC_i2s_mst_ws, - inout FMC_i2s_mst_sdo0, - inout FMC_i2s_mst_sdo1, - inout FMC_i2s_slv_sck, - inout FMC_i2s_slv_ws, - inout FMC_i2s_slv_sdi0, - inout FMC_i2s_slv_sdi1, - inout FMC_spim2_sck, - inout FMC_spim2_cs0, - inout FMC_spim2_miso, - inout FMC_spim2_mosi, - inout FMC_i3c2_sda, - inout FMC_i3c2_scl, + inout FMC_sdio_sdio0, + inout FMC_sdio_sdio1, + inout FMC_sdio_sdio2, + inout FMC_sdio_sdio3, + inout FMC_sdio_cs0, + inout FMC_sdio_sck, + inout FMC_i2c0_sda, + inout FMC_i2c0_scl, + inout FMC_uart_rx, + inout FMC_uart_tx, + inout FMC_i2s0_sck, + inout FMC_i2s0_ws, + inout FMC_i2s0_sdi, + inout FMC_i2s1_sdi, inout FMC_cam_pclk, inout FMC_cam_hsync, inout FMC_cam_data0, @@ -82,19 +57,6 @@ module pulpemu inout FMC_cam_data6, inout FMC_cam_data7, inout FMC_cam_vsync, - inout FMC_hyper_ckn, - inout FMC_hyper_ck, - inout FMC_hyper_dq0, - inout FMC_hyper_dq1, - inout FMC_hyper_dq2, - inout FMC_hyper_dq3, - inout FMC_hyper_dq4, - inout FMC_hyper_dq5, - inout FMC_hyper_dq6, - inout FMC_hyper_dq7, - inout FMC_hyper_csn0, - inout FMC_hyper_csn1, - inout FMC_hyper_rwds, inout FMC_jtag_tck, inout FMC_jtag_tdi, inout FMC_jtag_tdo, @@ -113,6 +75,24 @@ module pulpemu // reference 32768 Hz clock wire ref_clk; + // ███████╗██╗ ██╗███╗ ██╗ ██████╗ ██╗ ██╗██████╗ █████╗ ██████╗ ██████╗ ███████╗██████╗ + // ╚══███╔╝╚██╗ ██╔╝████╗ ██║██╔═══██╗ ██║ ██║██╔══██╗██╔══██╗██╔══██╗██╔══██╗██╔════╝██╔══██╗ + // ███╔╝ ╚████╔╝ ██╔██╗ ██║██║ ██║ ██║ █╗ ██║██████╔╝███████║██████╔╝██████╔╝█████╗ ██████╔╝ + // ███╔╝ ╚██╔╝ ██║╚██╗██║██║▄▄ ██║ ██║███╗██║██╔══██╗██╔══██║██╔═══╝ ██╔═══╝ ██╔══╝ ██╔══██╗ + // ███████╗ ██║ ██║ ╚████║╚██████╔╝███████╗╚███╔███╔╝██║ ██║██║ ██║██║ ██║ ███████╗██║ ██║ + // ╚══════╝ ╚═╝ ╚═╝ ╚═══╝ ╚══▀▀═╝ ╚══════╝ ╚══╝╚══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ + + zynq_wrapper zynq_wrapper_i ( + // pulp clocks (clk_wiz_clk_out1->cluster, clk_wiz_clk_out2->soc, clk_wiz_clk_out3->per) + .pulp_cluster_clk (pulp_cluster_clk ), + .pulp_soc_clk (pulp_soc_clk ), + .pulp_per_clk (pulp_per_clk ), + // zynq clock (FCLK0) + .zynq_clk (zynq_clk ), + .zynq_rst_n (zynq_rst_n ) + ); + + pulpemu_ref_clk_div #( @@ -143,142 +123,64 @@ module pulpemu // ██║ ╚██████╔╝███████╗██║███████╗╚██████╗██║ ██║██║██║ // ╚═╝ ╚═════╝ ╚══════╝╚═╝╚══════╝ ╚═════╝╚═╝ ╚═╝╚═╝╚═╝ - pulpissimo + pulp #(.CORE_TYPE(CORE_TYPE), .USE_FPU(USE_FPU), .USE_HWPE(USE_HWPE) - ) i_pulpissimo + ) i_pulp ( - .pad_spim_sdio0(pad_pmod0_4), - .pad_spim_sdio1(pad_pmod0_5), - .pad_spim_sdio2(pad_pmod0_6), - .pad_spim_sdio3(pad_pmod0_7), - // .pad_spim_csn0(pad_uart_rts), - .pad_spim_csn1(led0_o), - // .pad_spim_sck(pad_uart_cts), - .pad_uart_rx(pad_uart_rx), - .pad_uart_tx(pad_uart_tx), - .pad_cam_pclk(led1_o), - .pad_cam_hsync(led2_o), - .pad_cam_data0(led3_o), - .pad_cam_data1(switch0_i), - .pad_cam_data2(switch1_i), - .pad_cam_data3(btn0_i), - .pad_cam_data4(btn1_i), - .pad_cam_data5(btn2_i), - .pad_cam_data6(btn3_i), - .pad_cam_data7(switch2_i), - .pad_cam_vsync(switch3_i), - // .pad_sdio_clk(pad_hdmi_scl), - // .pad_sdio_cmd(pad_hdmi_sda), - // .pad_sdio_data0(pad_pmod1_0), - // .pad_sdio_data1(pad_pmod1_1), - // .pad_sdio_data2(pad_pmod1_2), - // .pad_sdio_data3(pad_pmod1_3), - // .pad_i2c0_sda(pad_i2c0_sda), - // .pad_i2c0_scl(pad_i2c0_scl), - // .pad_i2s0_sck(pad_pmod1_4), - // .pad_i2s0_ws(pad_pmod1_5), - // .pad_i2s0_sdi(pad_pmod1_6), - // .pad_i2s1_sdi(pad_pmod1_7), - .pad_reset_n(~pad_reset), - .pad_jtag_tck(pad_jtag_tck), - .pad_jtag_tdi(pad_jtag_tdi), - .pad_jtag_tdo(pad_jtag_tdo), - .pad_jtag_tms(pad_jtag_tms), - .pad_jtag_trst(1'b1), - .pad_xtal_in(ref_clk), - .pad_bootsel() + .zynq_clk_i ( ref_clk ), // FPGA inner clock, 32768 Hz + .zynq_soc_clk_i ( pulp_soc_clk ), // FPGA inner clock, 50 MHz + .zynq_cluster_clk_i ( pulp_cluster_clk ), // FPGA inner clock, 50 MHz + .zynq_per_clk_i ( pulp_per_clk ), // FPGA inner clock, 50 MHz + + .pad_spim_sdio0(FMC_qspi_sdio0), + .pad_spim_sdio1(FMC_qspi_sdio1), + .pad_spim_sdio2(FMC_qspi_sdio2), + .pad_spim_sdio3(FMC_qspi_sdio3), + .pad_spim_csn0(FMC_qspi_csn0), + .pad_spim_csn1(FMC_qspi_csn1), + .pad_spim_sck(FMC_qspi_sck), + + .pad_uart_rx(FMC_uart_rx), + .pad_uart_tx(FMC_uart_tx), + + .pad_cam_pclk(FMC_cam_pclk), + .pad_cam_hsync(FMC_cam_hsync), + .pad_cam_data0(FMC_cam_data0), + .pad_cam_data1(FMC_cam_data0), + .pad_cam_data2(FMC_cam_data0), + .pad_cam_data3(FMC_cam_data0), + .pad_cam_data4(FMC_cam_data0), + .pad_cam_data5(FMC_cam_data0), + .pad_cam_data6(FMC_cam_data0), + .pad_cam_data7(FMC_cam_data0), + .pad_cam_vsync(FMC_cam_data0), + + .pad_sdio_clk(FMC_sdio_clk), + .pad_sdio_cmd(FMC_sdio_cmd), + .pad_sdio_data0(FMC_sdio_data0), + .pad_sdio_data1(FMC_sdio_data1), + .pad_sdio_data2(FMC_sdio_data2), + .pad_sdio_data3(FMC_sdio_data3), + + .pad_i2c0_sda(FMC_i2c0_sda), + .pad_i2c0_scl(FMC_i2c0_scl), + + .pad_i2s0_sck(FMC_i2s0_sck), + .pad_i2s0_ws(FMC_i2s0_ws), + .pad_i2s0_sdi(FMC_i2s0_sdi), + .pad_i2s1_sdi(FMC_i2s1_sdi), + + .pad_jtag_tck(FMC_jtag_tck), + .pad_jtag_tdi(FMC_jtag_tdi), + .pad_jtag_tdo(FMC_jtag_tdo), + .pad_jtag_tms(FMC_jtag_tms), + .pad_jtag_trst(FMC_jtag_trst), + + .pad_xtal_in(), // USE zynq_clk_i as ref_clk + .pad_reset_n(FMC_reset_n), + .pad_bootmode(FMC_bootmode) // Boot mode = 0; boot from flash; Boot mode = 1; boot from jtag ); - pulp_chip pulp_chip_i ( - .zynq_clk_i ( ref_clk ), // FPGA inner clock, 50 MHz - .zynq_soc_clk_i ( pulp_soc_clk ), // FPGA inner clock, 50 MHz - .zynq_cluster_clk_i ( pulp_cluster_clk ), // FPGA inner clock, 50 MHz - .zynq_per_clk_i ( pulp_per_clk ), // FPGA inner clock, 50 MHz - - .pad_csi2_clkp ( FMC_csi2_clkp ), - .pad_csi2_clkn ( FMC_csi2_clkn ), - .pad_csi2_datap0 ( FMC_csi2_datap0 ), - .pad_csi2_datan0 ( FMC_csi2_datan0 ), - .pad_csi2_datap1 ( FMC_csi2_datap1 ), - .pad_csi2_datan1 ( FMC_csi2_datan1 ), - .pad_pwm0 ( FMC_pwm0 ), - .pad_pwm1 ( FMC_pwm1 ), - .pad_pwm2 ( FMC_pwm2 ), - .pad_pwm3 ( FMC_pwm3 ), - .pad_qspi_sdio0 ( FMC_qspi_sdio0 ), - .pad_qspi_sdio1 ( FMC_qspi_sdio1 ), - .pad_qspi_sdio2 ( FMC_qspi_sdio2 ), - .pad_qspi_sdio3 ( FMC_qspi_sdio3 ), - .pad_qspi_cs0 ( FMC_qspi_cs0 ), - .pad_qspi_sck ( FMC_qspi_sck ), - .pad_spim0_sck ( FMC_spim0_sck ), - .pad_spim0_cs0 ( FMC_spim0_cs0 ), - .pad_spim0_miso ( FMC_spim0_miso ), - .pad_spim0_mosi ( FMC_spim0_mosi ), - .pad_i3c0_sda ( FMC_i3c0_sda ), - .pad_i3c0_scl ( FMC_i3c0_scl ), - .pad_uart0_rx ( FMC_uart0_rx ), - .pad_uart0_tx ( FMC_uart0_tx ), - .pad_uart1_rx ( FMC_uart1_rx ), - .pad_uart1_tx ( FMC_uart1_tx ), - .pad_spim1_sck ( FMC_spim1_sck ), - .pad_spim1_cs0 ( FMC_spim1_cs0 ), - .pad_spim1_miso ( FMC_spim1_miso ), - .pad_spim1_mosi ( FMC_spim1_mosi ), - .pad_i3c1_sda ( FMC_i3c1_sda ), - .pad_i3c1_scl ( FMC_i3c1_scl ), - .pad_i2s_mst_sck ( FMC_i2s_mst_sck ), - .pad_i2s_mst_ws ( FMC_i2s_mst_ws ), - .pad_i2s_mst_sdo0 ( FMC_i2s_mst_sdo0 ), - .pad_i2s_mst_sdo1 ( FMC_i2s_mst_sdo1 ), - .pad_i2s_slv_sck ( FMC_i2s_slv_sck ), - .pad_i2s_slv_ws ( FMC_i2s_slv_ws ), - .pad_i2s_slv_sdi0 ( FMC_i2s_slv_sdi0 ), - .pad_i2s_slv_sdi1 ( FMC_i2s_slv_sdi1 ), - .pad_spim2_sck ( FMC_spim2_sck ), - .pad_spim2_cs0 ( FMC_spim2_cs0 ), - .pad_spim2_miso ( FMC_spim2_miso ), - .pad_spim2_mosi ( FMC_spim2_mosi ), - .pad_i3c2_sda ( FMC_i3c2_sda ), - .pad_i3c2_scl ( FMC_i3c2_scl ), - .pad_cam_pclk ( FMC_cam_pclk ), - .pad_cam_hsync ( FMC_cam_hsync ), - .pad_cam_data0 ( FMC_cam_data0 ), - .pad_cam_data1 ( FMC_cam_data1 ), - .pad_cam_data2 ( FMC_cam_data2 ), - .pad_cam_data3 ( FMC_cam_data3 ), - .pad_cam_data4 ( FMC_cam_data4 ), - .pad_cam_data5 ( FMC_cam_data5 ), - .pad_cam_data6 ( FMC_cam_data6 ), - .pad_cam_data7 ( FMC_cam_data7 ), - .pad_cam_vsync ( FMC_cam_vsync ), - .pad_hyper_ckn ( FMC_hyper_ckn ), - .pad_hyper_ck ( FMC_hyper_ck ), - .pad_hyper_dq0 ( FMC_hyper_dq0 ), - .pad_hyper_dq1 ( FMC_hyper_dq1 ), - .pad_hyper_dq2 ( FMC_hyper_dq2 ), - .pad_hyper_dq3 ( FMC_hyper_dq3 ), - .pad_hyper_dq4 ( FMC_hyper_dq4 ), - .pad_hyper_dq5 ( FMC_hyper_dq5 ), - .pad_hyper_dq6 ( FMC_hyper_dq6 ), - .pad_hyper_dq7 ( FMC_hyper_dq7 ), - - // Pay attention, the Chip select of Pulp FMC Sensor Board is inverted - .pad_hyper_csn0 ( FMC_hyper_csn0 ), - .pad_hyper_csn1 ( FMC_hyper_csn1 ), - - .pad_hyper_rwds ( FMC_hyper_rwds ), - .pad_jtag_tdi ( FMC_jtag_tdi ), // inout wire - .pad_jtag_tdo ( FMC_jtag_tdo ), // inout wire - .pad_jtag_tms ( FMC_jtag_tms ), // inout wire - .pad_jtag_trst ( FMC_jtag_trst ), // inout wire - .pad_jtag_tck ( FMC_jtag_tck ), // inout wire - .pad_bootmode ( FMC_bootmode ), // Boot mode = 0; boot from flash; Boot mode = 1; boot from jtag - .pad_reset_n ( FMC_reset_n ) // inout wire - - ); - - endmodule // pulpemu diff --git a/rtl/pulpemu/src_files.yml b/rtl/pulpemu/src_files.yml index cd6a1be7..e7008280 100644 --- a/rtl/pulpemu/src_files.yml +++ b/rtl/pulpemu/src_files.yml @@ -7,7 +7,6 @@ pulpemu: xilinx, ] files: [ - fpga_clk_gen.sv fpga_interleaved_ram.sv, fpga_private_ram.sv, pulpemu.sv, From a992a3c90cc834b12580a58c90a83d39b01dc903 Mon Sep 17 00:00:00 2001 From: Jie CHEN Date: Wed, 23 Oct 2019 11:22:02 +0200 Subject: [PATCH 09/46] Update for boot rom --- rtl/pulpemu/fpga_bootrom.sv | 52 +++++++++++++++++++++++++++++++++++++ rtl/pulpemu/src_files.yml | 1 + 2 files changed, 53 insertions(+) create mode 100644 rtl/pulpemu/fpga_bootrom.sv diff --git a/rtl/pulpemu/fpga_bootrom.sv b/rtl/pulpemu/fpga_bootrom.sv new file mode 100644 index 00000000..d7b9b0b3 --- /dev/null +++ b/rtl/pulpemu/fpga_bootrom.sv @@ -0,0 +1,52 @@ +//----------------------------------------------------------------------------- +// Title : FPGA Bootrom for PULP +//----------------------------------------------------------------------------- +// File : fpga_bootrom.sv +// Author : Jie Chen +// Created : 23.10.2019 +//----------------------------------------------------------------------------- +// Description : +// Real boot with jtag reaction. +//----------------------------------------------------------------------------- +// Copyright (C) 2013-2019 ETH Zurich, University of Bologna +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. +//----------------------------------------------------------------------------- + + +module fpga_bootrom + #( + parameter ADDR_WIDTH=32, + parameter DATA_WIDTH=32 + ) + ( + input logic CLK, + input logic RSTN, + input logic CEN, + input logic [ADDR_WIDTH-1:0] A, + output logic [DATA_WIDTH-1:0] Q + ); + + logic [3:0] wea; + logic [31:0] dina; + + assign wea = 4'b0000; + assign dina = 32'h0000_0000; + + xilinx_rom_bank_2048x32 rom_mem_i ( + .clka (CLK), + .rsta (~RSTN), + .ena (~CEN), + .wea (wea), + .addra (A), + .dina (dina), + .douta (Q) + ); + +endmodule : fpga_bootrom diff --git a/rtl/pulpemu/src_files.yml b/rtl/pulpemu/src_files.yml index e7008280..3d435539 100644 --- a/rtl/pulpemu/src_files.yml +++ b/rtl/pulpemu/src_files.yml @@ -7,6 +7,7 @@ pulpemu: xilinx, ] files: [ + fpga_bootrom.sv, fpga_interleaved_ram.sv, fpga_private_ram.sv, pulpemu.sv, From 9a0f491dd968a627ca2bb5a3565b7f96cd1a46d6 Mon Sep 17 00:00:00 2001 From: Jie CHEN Date: Wed, 23 Oct 2019 12:08:34 +0200 Subject: [PATCH 10/46] Update for fpga --- rtl/pulp/pad_frame.sv | 21 ++++++--------------- rtl/pulp/pulp.sv | 16 ++++++++++++++++ rtl/pulp/soc_domain.sv | 5 +++++ 3 files changed, 27 insertions(+), 15 deletions(-) diff --git a/rtl/pulp/pad_frame.sv b/rtl/pulp/pad_frame.sv index c606ca89..c5fae423 100644 --- a/rtl/pulp/pad_frame.sv +++ b/rtl/pulp/pad_frame.sv @@ -216,26 +216,17 @@ module pad_frame pad_functional_pu padinst_bootsel (.OEN(1'b1 ), .I( ), .O(bootsel_o ), .PAD(pad_bootsel ), .PEN(1'b1 ) ); + pad_functional_pu padinst_reset_n (.OEN(1'b1 ), .I( ), .O(rstn_o ), .PAD(pad_reset_n ), .PEN(1'b1 ) ); + pad_functional_pu padinst_jtag_tck (.OEN(1'b1 ), .I( ), .O(jtag_tck_o ), .PAD(pad_jtag_tck ), .PEN(1'b1 ) ); + pad_functional_pu padinst_jtag_tms (.OEN(1'b1 ), .I( ), .O(jtag_tms_o ), .PAD(pad_jtag_tms ), .PEN(1'b1 ) ); + pad_functional_pu padinst_jtag_tdi (.OEN(1'b1 ), .I( ), .O(jtag_tdi_o ), .PAD(pad_jtag_tdi ), .PEN(1'b1 ) ); + pad_functional_pu padinst_jtag_trstn (.OEN(1'b1 ), .I( ), .O(jtag_trst_o ), .PAD(pad_jtag_trst ), .PEN(1'b1 ) ); + pad_functional_pd padinst_jtag_tdo (.OEN(1'b0 ), .I(jtag_tdo_i ), .O( ), .PAD(pad_jtag_tdo ), .PEN(1'b1 ) ); `ifndef PULP_FPGA_EMUL pad_functional_pu padinst_ref_clk (.OEN(1'b1 ), .I( ), .O(ref_clk_o ), .PAD(pad_xtal_in ), .PEN(1'b1 ) ); - pad_functional_pu padinst_reset_n (.OEN(1'b1 ), .I( ), .O(rstn_o ), .PAD(pad_reset_n ), .PEN(1'b1 ) ); - pad_functional_pu padinst_jtag_tck (.OEN(1'b1 ), .I( ), .O(jtag_tck_o ), .PAD(pad_jtag_tck ), .PEN(1'b1 ) ); - pad_functional_pu padinst_jtag_tms (.OEN(1'b1 ), .I( ), .O(jtag_tms_o ), .PAD(pad_jtag_tms ), .PEN(1'b1 ) ); - pad_functional_pu padinst_jtag_tdi (.OEN(1'b1 ), .I( ), .O(jtag_tdi_o ), .PAD(pad_jtag_tdi ), .PEN(1'b1 ) ); - pad_functional_pu padinst_jtag_trstn (.OEN(1'b1 ), .I( ), .O(jtag_trst_o ), .PAD(pad_jtag_trst ), .PEN(1'b1 ) ); - pad_functional_pd padinst_jtag_tdo (.OEN(1'b0 ), .I(jtag_tdo_i ), .O( ), .PAD(pad_jtag_tdo ), .PEN(1'b1 ) ); - `else assign ref_clk_o = pad_xtal_in; - assign rstn_o = pad_reset_n; - - //JTAG signals - assign pad_jtag_tdo = jtag_tdo_i; - assign jtag_trst_o = pad_jtag_trst; - assign jtag_tms_o = pad_jtag_tms; - assign jtag_tck_o = pad_jtag_tck; - assign jtag_tdi_o = pad_jtag_tdi; `endif endmodule // pad_frame diff --git a/rtl/pulp/pulp.sv b/rtl/pulp/pulp.sv index 92a9f92c..94a234df 100644 --- a/rtl/pulp/pulp.sv +++ b/rtl/pulp/pulp.sv @@ -17,6 +17,12 @@ module pulp parameter USE_HWPE = 1 ) ( +`ifdef PULP_FPGA_EMUL + input logic zynq_clk_i, + input logic zynq_soc_clk_i, + input logic zynq_cluster_clk_i, + input logic zynq_per_clk_i, +`endif inout wire pad_spim_sdio0, inout wire pad_spim_sdio1, @@ -465,11 +471,16 @@ module pulp //*********************************************************** //********** PAD FRAME ************************************** //*********************************************************** +`ifdef PULP_FPGA_EMUL + assign s_ref_clk = zynq_clk_i; +`endif pad_frame pad_frame_i ( .pad_cfg_i ( s_pad_cfg ), +`ifndef PULP_FPGA_EMUL .ref_clk_o ( s_ref_clk ), +`endif .rstn_o ( s_rstn ), .jtag_tdo_i ( s_jtag_tdo ), .jtag_tck_o ( s_jtag_tck ), @@ -849,6 +860,11 @@ module pulp .test_clk_i ( s_test_clk ), .rstn_glob_i ( s_rstn_por ), + `ifdef PULP_FPGA_EMUL + .zynq_soc_clk_i ( zynq_soc_clk_i ), + .zynq_cluster_clk_i ( zynq_cluster_clk_i ), + .zynq_per_clk_i ( zynq_per_clk_i ), + `endif .mode_select_i ( s_mode_select ), .dft_cg_enable_i ( s_dft_cg_enable ), diff --git a/rtl/pulp/soc_domain.sv b/rtl/pulp/soc_domain.sv index 33d62721..7b8ea316 100644 --- a/rtl/pulp/soc_domain.sv +++ b/rtl/pulp/soc_domain.sv @@ -33,6 +33,11 @@ module soc_domain #( input logic test_clk_i, input logic rstn_glob_i, + `ifdef PULP_FPGA_EMUL + input logic zynq_soc_clk_i, + input logic zynq_cluster_clk_i, + input logic zynq_per_clk_i, + `endif input logic dft_test_mode_i, input logic dft_cg_enable_i, From 335b5d147c9bf8d4cdf53ad7b678da37cc3e09e9 Mon Sep 17 00:00:00 2001 From: agarofalo Date: Wed, 23 Oct 2019 03:33:36 -0700 Subject: [PATCH 11/46] fixed padframe --- rtl/pulpemu/pulpemu.sv | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/rtl/pulpemu/pulpemu.sv b/rtl/pulpemu/pulpemu.sv index a85f5eaa..b4467164 100644 --- a/rtl/pulpemu/pulpemu.sv +++ b/rtl/pulpemu/pulpemu.sv @@ -14,11 +14,7 @@ * University of Bologna. */ -`include "ulpsoc_defines.sv" - -`ifndef PULP_FPGA_SIM - `define PULP_FPGA_NETLIST -`endif +`include "pulp_ssoc_defines.sv" module pulpemu ( @@ -36,7 +32,7 @@ module pulpemu inout FMC_sdio_sdio1, inout FMC_sdio_sdio2, inout FMC_sdio_sdio3, - inout FMC_sdio_cs0, + inout FMC_sdio_cmd, inout FMC_sdio_sck, inout FMC_i2c0_sda, inout FMC_i2c0_scl, @@ -148,14 +144,14 @@ module pulpemu .pad_cam_pclk(FMC_cam_pclk), .pad_cam_hsync(FMC_cam_hsync), .pad_cam_data0(FMC_cam_data0), - .pad_cam_data1(FMC_cam_data0), - .pad_cam_data2(FMC_cam_data0), - .pad_cam_data3(FMC_cam_data0), - .pad_cam_data4(FMC_cam_data0), - .pad_cam_data5(FMC_cam_data0), - .pad_cam_data6(FMC_cam_data0), - .pad_cam_data7(FMC_cam_data0), - .pad_cam_vsync(FMC_cam_data0), + .pad_cam_data1(FMC_cam_data1), + .pad_cam_data2(FMC_cam_data2), + .pad_cam_data3(FMC_cam_data3), + .pad_cam_data4(FMC_cam_data4), + .pad_cam_data5(FMC_cam_data5), + .pad_cam_data6(FMC_cam_data6), + .pad_cam_data7(FMC_cam_data7), + .pad_cam_vsync(FMC_cam_vsync), .pad_sdio_clk(FMC_sdio_clk), .pad_sdio_cmd(FMC_sdio_cmd), From de938b15497dbac399dba8853e6230d0ac2a8fa2 Mon Sep 17 00:00:00 2001 From: agarofalo Date: Wed, 23 Oct 2019 07:05:52 -0700 Subject: [PATCH 12/46] added pad_functional --- rtl/pulp/pad_frame.sv | 21 ++++++++---- rtl/pulp/pulp.sv | 3 -- rtl/pulp/safe_domain.sv | 24 -------------- rtl/pulp/soc_domain.sv | 1 - rtl/pulpemu/pad_functional_xilinx.sv | 48 ++++++++++++++++++++++++++++ rtl/pulpemu/pulpemu.sv | 7 +++- rtl/pulpemu/src_files.yml | 1 + 7 files changed, 70 insertions(+), 35 deletions(-) create mode 100644 rtl/pulpemu/pad_functional_xilinx.sv diff --git a/rtl/pulp/pad_frame.sv b/rtl/pulp/pad_frame.sv index c5fae423..4446d9b1 100644 --- a/rtl/pulp/pad_frame.sv +++ b/rtl/pulp/pad_frame.sv @@ -216,17 +216,26 @@ module pad_frame pad_functional_pu padinst_bootsel (.OEN(1'b1 ), .I( ), .O(bootsel_o ), .PAD(pad_bootsel ), .PEN(1'b1 ) ); - pad_functional_pu padinst_reset_n (.OEN(1'b1 ), .I( ), .O(rstn_o ), .PAD(pad_reset_n ), .PEN(1'b1 ) ); - pad_functional_pu padinst_jtag_tck (.OEN(1'b1 ), .I( ), .O(jtag_tck_o ), .PAD(pad_jtag_tck ), .PEN(1'b1 ) ); - pad_functional_pu padinst_jtag_tms (.OEN(1'b1 ), .I( ), .O(jtag_tms_o ), .PAD(pad_jtag_tms ), .PEN(1'b1 ) ); - pad_functional_pu padinst_jtag_tdi (.OEN(1'b1 ), .I( ), .O(jtag_tdi_o ), .PAD(pad_jtag_tdi ), .PEN(1'b1 ) ); - pad_functional_pu padinst_jtag_trstn (.OEN(1'b1 ), .I( ), .O(jtag_trst_o ), .PAD(pad_jtag_trst ), .PEN(1'b1 ) ); - pad_functional_pd padinst_jtag_tdo (.OEN(1'b0 ), .I(jtag_tdo_i ), .O( ), .PAD(pad_jtag_tdo ), .PEN(1'b1 ) ); + `ifndef PULP_FPGA_EMUL pad_functional_pu padinst_ref_clk (.OEN(1'b1 ), .I( ), .O(ref_clk_o ), .PAD(pad_xtal_in ), .PEN(1'b1 ) ); + pad_functional_pu padinst_reset_n (.OEN(1'b1 ), .I( ), .O(rstn_o ), .PAD(pad_reset_n ), .PEN(1'b1 ) ); + pad_functional_pu padinst_jtag_tck (.OEN(1'b1 ), .I( ), .O(jtag_tck_o ), .PAD(pad_jtag_tck ), .PEN(1'b1 ) ); + pad_functional_pu padinst_jtag_tms (.OEN(1'b1 ), .I( ), .O(jtag_tms_o ), .PAD(pad_jtag_tms ), .PEN(1'b1 ) ); + pad_functional_pu padinst_jtag_tdi (.OEN(1'b1 ), .I( ), .O(jtag_tdi_o ), .PAD(pad_jtag_tdi ), .PEN(1'b1 ) ); + pad_functional_pu padinst_jtag_trstn (.OEN(1'b1 ), .I( ), .O(jtag_trst_o ), .PAD(pad_jtag_trst ), .PEN(1'b1 ) ); + pad_functional_pd padinst_jtag_tdo (.OEN(1'b0 ), .I(jtag_tdo_i ), .O( ), .PAD(pad_jtag_tdo ), .PEN(1'b1 ) ); `else assign ref_clk_o = pad_xtal_in; + assign rstn_o = pad_reset_n; + + //JTAG signals + assign pad_jtag_tdo = jtag_tdo_i; + assign jtag_trst_o = pad_jtag_trst; + assign jtag_tms_o = pad_jtag_tms; + assign jtag_tck_o = pad_jtag_tck; + assign jtag_tdi_o = pad_jtag_tdi; `endif endmodule // pad_frame diff --git a/rtl/pulp/pulp.sv b/rtl/pulp/pulp.sv index 94a234df..cb001ef2 100644 --- a/rtl/pulp/pulp.sv +++ b/rtl/pulp/pulp.sv @@ -213,7 +213,6 @@ module pulp //*********************************************************** logic s_test_clk; - logic s_slow_clk; logic s_sel_fll_clk; logic [11:0] s_pm_cfg_data; @@ -639,7 +638,6 @@ module pulp safe_domain safe_domain_i ( .ref_clk_i ( s_ref_clk ), - .slow_clk_o ( s_slow_clk ), .rst_ni ( s_rstn ), .rst_no ( s_rstn_por ), @@ -856,7 +854,6 @@ module pulp ) soc_domain_i ( .ref_clk_i ( s_ref_clk ), - .slow_clk_i ( s_slow_clk ), .test_clk_i ( s_test_clk ), .rstn_glob_i ( s_rstn_por ), diff --git a/rtl/pulp/safe_domain.sv b/rtl/pulp/safe_domain.sv index 8ed6537c..e9a51507 100644 --- a/rtl/pulp/safe_domain.sv +++ b/rtl/pulp/safe_domain.sv @@ -16,7 +16,6 @@ module safe_domain ) ( input logic ref_clk_i , - output logic slow_clk_o , input logic rst_ni , output logic rst_no , @@ -417,8 +416,6 @@ module safe_domain .* ); - -`ifndef PULP_FPGA_EMUL rstgen i_rstgen ( .clk_i ( ref_clk_i ), @@ -428,27 +425,6 @@ module safe_domain .init_no ( ) //not used ); - assign slow_clk_o = ref_clk_i; - -`else - assign s_rstn_sync = s_rstn; - //Don't use the supplied clock directly for the FPGA target. On some boards - //the reference clock is a very fast (e.g. 200MHz) clock that cannot be used - //directly as the "slow_clk". Therefore we slow it down if a FPGA/board - //dependent module fpga_slow_clk_gen. Dividing the fast reference clock - //internally instead of doing so in the toplevel prevents unecessary clock - //division just to generate a faster clock once again in the SoC and - //Peripheral clock PLLs in soc_domain.sv. Instead all PLL use directly the - //board reference clock as input. - - fpga_slow_clk_gen i_slow_clk_gen - ( - .rst_ni(s_rstn_sync), - .ref_clk_i(ref_clk_i), - .slow_clk_o(slow_clk_o) - ); -`endif - assign s_rstn = rst_ni; assign rst_no = s_rstn; diff --git a/rtl/pulp/soc_domain.sv b/rtl/pulp/soc_domain.sv index 7b8ea316..099f40ab 100644 --- a/rtl/pulp/soc_domain.sv +++ b/rtl/pulp/soc_domain.sv @@ -29,7 +29,6 @@ module soc_domain #( )( input logic ref_clk_i, - input logic slow_clk_i, input logic test_clk_i, input logic rstn_glob_i, diff --git a/rtl/pulpemu/pad_functional_xilinx.sv b/rtl/pulpemu/pad_functional_xilinx.sv new file mode 100644 index 00000000..a3ca1cde --- /dev/null +++ b/rtl/pulpemu/pad_functional_xilinx.sv @@ -0,0 +1,48 @@ +// Copyright 2018 ETH Zurich and University of Bologna. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + + +module pad_functional_pd +( + input logic OEN, + input logic I, + output logic O, + input logic PEN, + inout logic PAD +); + + (* PULLDOWN = "YES" *) + IOBUF iobuf_i ( + .T ( OEN ), + .I ( I ), + .O ( O ), + .IO( PAD ) + ); + +endmodule + +module pad_functional_pu +( + input logic OEN, + input logic I, + output logic O, + input logic PEN, + inout logic PAD +); + + (* PULLUP = "YES" *) + IOBUF iobuf_i ( + .T ( OEN ), + .I ( I ), + .O ( O ), + .IO( PAD ) + ); + +endmodule \ No newline at end of file diff --git a/rtl/pulpemu/pulpemu.sv b/rtl/pulpemu/pulpemu.sv index b4467164..9bb90c56 100644 --- a/rtl/pulpemu/pulpemu.sv +++ b/rtl/pulpemu/pulpemu.sv @@ -14,9 +14,14 @@ * University of Bologna. */ -`include "pulp_ssoc_defines.sv" +`include "pulp_soc_defines.sv" module pulpemu + #( + parameter CORE_TYPE = 0, // 0 for RISCY, 1 for IBEX RV32IMC (formerly ZERORISCY), 2 for IBEX RV32EC (formerly MICRORISCY) + parameter USE_FPU = 1, + parameter USE_HWPE = 0 +) ( // LED for VERIFY output LED, diff --git a/rtl/pulpemu/src_files.yml b/rtl/pulpemu/src_files.yml index 3d435539..797b5906 100644 --- a/rtl/pulpemu/src_files.yml +++ b/rtl/pulpemu/src_files.yml @@ -7,6 +7,7 @@ pulpemu: xilinx, ] files: [ + pad_functional_xilinx.sv, fpga_bootrom.sv, fpga_interleaved_ram.sv, fpga_private_ram.sv, From db6adc6858353aef5de70a947332260f4b362b57 Mon Sep 17 00:00:00 2001 From: agarofalo Date: Thu, 24 Oct 2019 03:19:20 -0700 Subject: [PATCH 13/46] modified pad frame --- rtl/pulp/pad_frame.sv | 23 ++++++++--------------- rtl/pulpemu/pulpemu.sv | 4 ++-- 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/rtl/pulp/pad_frame.sv b/rtl/pulp/pad_frame.sv index 4446d9b1..775dcf27 100644 --- a/rtl/pulp/pad_frame.sv +++ b/rtl/pulp/pad_frame.sv @@ -217,25 +217,18 @@ module pad_frame pad_functional_pu padinst_bootsel (.OEN(1'b1 ), .I( ), .O(bootsel_o ), .PAD(pad_bootsel ), .PEN(1'b1 ) ); + pad_functional_pu padinst_reset_n (.OEN(1'b1 ), .I( ), .O(rstn_o ), .PAD(pad_reset_n ), .PEN(1'b1 ) ); + pad_functional_pu padinst_jtag_tck (.OEN(1'b1 ), .I( ), .O(jtag_tck_o ), .PAD(pad_jtag_tck ), .PEN(1'b1 ) ); + pad_functional_pu padinst_jtag_tms (.OEN(1'b1 ), .I( ), .O(jtag_tms_o ), .PAD(pad_jtag_tms ), .PEN(1'b1 ) ); + pad_functional_pu padinst_jtag_tdi (.OEN(1'b1 ), .I( ), .O(jtag_tdi_o ), .PAD(pad_jtag_tdi ), .PEN(1'b1 ) ); + pad_functional_pu padinst_jtag_trstn (.OEN(1'b1 ), .I( ), .O(jtag_trst_o ), .PAD(pad_jtag_trst ), .PEN(1'b1 ) ); + pad_functional_pd padinst_jtag_tdo (.OEN(1'b0 ), .I(jtag_tdo_i ), .O( ), .PAD(pad_jtag_tdo ), .PEN(1'b1 ) ); `ifndef PULP_FPGA_EMUL - pad_functional_pu padinst_ref_clk (.OEN(1'b1 ), .I( ), .O(ref_clk_o ), .PAD(pad_xtal_in ), .PEN(1'b1 ) ); - pad_functional_pu padinst_reset_n (.OEN(1'b1 ), .I( ), .O(rstn_o ), .PAD(pad_reset_n ), .PEN(1'b1 ) ); - pad_functional_pu padinst_jtag_tck (.OEN(1'b1 ), .I( ), .O(jtag_tck_o ), .PAD(pad_jtag_tck ), .PEN(1'b1 ) ); - pad_functional_pu padinst_jtag_tms (.OEN(1'b1 ), .I( ), .O(jtag_tms_o ), .PAD(pad_jtag_tms ), .PEN(1'b1 ) ); - pad_functional_pu padinst_jtag_tdi (.OEN(1'b1 ), .I( ), .O(jtag_tdi_o ), .PAD(pad_jtag_tdi ), .PEN(1'b1 ) ); - pad_functional_pu padinst_jtag_trstn (.OEN(1'b1 ), .I( ), .O(jtag_trst_o ), .PAD(pad_jtag_trst ), .PEN(1'b1 ) ); - pad_functional_pd padinst_jtag_tdo (.OEN(1'b0 ), .I(jtag_tdo_i ), .O( ), .PAD(pad_jtag_tdo ), .PEN(1'b1 ) ); + pad_functional_pu padinst_ref_clk (.OEN(1'b1 ), .I( ), .O(ref_clk_o ), .PAD(pad_xtal_in ), .PEN(1'b1 ) ); + `else assign ref_clk_o = pad_xtal_in; - assign rstn_o = pad_reset_n; - - //JTAG signals - assign pad_jtag_tdo = jtag_tdo_i; - assign jtag_trst_o = pad_jtag_trst; - assign jtag_tms_o = pad_jtag_tms; - assign jtag_tck_o = pad_jtag_tck; - assign jtag_tdi_o = pad_jtag_tdi; `endif endmodule // pad_frame diff --git a/rtl/pulpemu/pulpemu.sv b/rtl/pulpemu/pulpemu.sv index 9bb90c56..ababf634 100644 --- a/rtl/pulpemu/pulpemu.sv +++ b/rtl/pulpemu/pulpemu.sv @@ -128,7 +128,7 @@ module pulpemu #(.CORE_TYPE(CORE_TYPE), .USE_FPU(USE_FPU), .USE_HWPE(USE_HWPE) - ) i_pulp + ) pulp_chip_i ( .zynq_clk_i ( ref_clk ), // FPGA inner clock, 32768 Hz .zynq_soc_clk_i ( pulp_soc_clk ), // FPGA inner clock, 50 MHz @@ -181,7 +181,7 @@ module pulpemu .pad_xtal_in(), // USE zynq_clk_i as ref_clk .pad_reset_n(FMC_reset_n), - .pad_bootmode(FMC_bootmode) // Boot mode = 0; boot from flash; Boot mode = 1; boot from jtag + .pad_bootsel(FMC_bootmode) // Boot mode = 0; boot from flash; Boot mode = 1; boot from jtag ); endmodule // pulpemu From 5b4a72b6dee840fe736565dd85b10aabb81ec550 Mon Sep 17 00:00:00 2001 From: Jie CHEN Date: Thu, 24 Oct 2019 15:46:21 +0200 Subject: [PATCH 14/46] Remove pull up down --- rtl/pulpemu/pad_functional_xilinx.sv | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/rtl/pulpemu/pad_functional_xilinx.sv b/rtl/pulpemu/pad_functional_xilinx.sv index a3ca1cde..cbf1b42c 100644 --- a/rtl/pulpemu/pad_functional_xilinx.sv +++ b/rtl/pulpemu/pad_functional_xilinx.sv @@ -18,7 +18,6 @@ module pad_functional_pd inout logic PAD ); - (* PULLDOWN = "YES" *) IOBUF iobuf_i ( .T ( OEN ), .I ( I ), @@ -37,7 +36,6 @@ module pad_functional_pu inout logic PAD ); - (* PULLUP = "YES" *) IOBUF iobuf_i ( .T ( OEN ), .I ( I ), @@ -45,4 +43,4 @@ module pad_functional_pu .IO( PAD ) ); -endmodule \ No newline at end of file +endmodule From 6c2e434390a93193b88e9df6ed6a1ff13319eb21 Mon Sep 17 00:00:00 2001 From: agarofalo Date: Thu, 24 Oct 2019 06:46:50 -0700 Subject: [PATCH 15/46] fixed pin names --- rtl/pulpemu/pulpemu.sv | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rtl/pulpemu/pulpemu.sv b/rtl/pulpemu/pulpemu.sv index ababf634..2ba32781 100644 --- a/rtl/pulpemu/pulpemu.sv +++ b/rtl/pulpemu/pulpemu.sv @@ -33,10 +33,10 @@ module pulpemu inout FMC_qspi_csn0, inout FMC_qspi_csn1, inout FMC_qspi_sck, - inout FMC_sdio_sdio0, - inout FMC_sdio_sdio1, - inout FMC_sdio_sdio2, - inout FMC_sdio_sdio3, + inout FMC_sdio_data0, + inout FMC_sdio_data1, + inout FMC_sdio_data2, + inout FMC_sdio_data3, inout FMC_sdio_cmd, inout FMC_sdio_sck, inout FMC_i2c0_sda, @@ -158,7 +158,7 @@ module pulpemu .pad_cam_data7(FMC_cam_data7), .pad_cam_vsync(FMC_cam_vsync), - .pad_sdio_clk(FMC_sdio_clk), + .pad_sdio_clk(FMC_sdio_sck), .pad_sdio_cmd(FMC_sdio_cmd), .pad_sdio_data0(FMC_sdio_data0), .pad_sdio_data1(FMC_sdio_data1), From 5553e166c0328a4e8e6c8613a074a7f876270f3b Mon Sep 17 00:00:00 2001 From: "jie.chen" Date: Thu, 24 Oct 2019 22:30:55 +0200 Subject: [PATCH 16/46] Add fpga clk gen --- rtl/pulpemu/fpga_clk_gen.sv | 74 +++++++++++++++++++++++++++++++++++++ rtl/pulpemu/src_files.yml | 1 + 2 files changed, 75 insertions(+) create mode 100644 rtl/pulpemu/fpga_clk_gen.sv diff --git a/rtl/pulpemu/fpga_clk_gen.sv b/rtl/pulpemu/fpga_clk_gen.sv new file mode 100644 index 00000000..2ad9a8eb --- /dev/null +++ b/rtl/pulpemu/fpga_clk_gen.sv @@ -0,0 +1,74 @@ +//----------------------------------------------------------------------------- +// Title : FPGA CLK Gen for PULPissimo +// ----------------------------------------------------------------------------- +// File : fpga_clk_gen.sv Author : Manuel Eggimann +// Created : 17.05.2019 +// ----------------------------------------------------------------------------- +// Description : Instantiates Xilinx clocking wizard IP to generate 2 output +// clocks. Currently, the clock is not dynamicly reconfigurable and all +// configuration requests are acknowledged without any effect. +// ----------------------------------------------------------------------------- +// Copyright (C) 2013-2019 ETH Zurich, University of Bologna Copyright and +// related rights are licensed under the Solderpad Hardware License, Version +// 0.51 (the "License"); you may not use this file except in compliance with the +// License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law or +// agreed to in writing, software, hardware and materials distributed under this +// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS +// OF ANY KIND, either express or implied. See the License for the specific +// language governing permissions and limitations under the License. +// ----------------------------------------------------------------------------- + + +module fpga_clk_gen ( + input logic ref_clk_i, + input logic rstn_glob_i, + input logic test_mode_i, + input logic shift_enable_i, + output logic soc_clk_o, + output logic per_clk_o, + output logic cluster_clk_o, + output logic soc_cfg_lock_o, + input logic soc_cfg_req_i, + output logic soc_cfg_ack_o, + input logic [1:0] soc_cfg_add_i, + input logic [31:0] soc_cfg_data_i, + output logic [31:0] soc_cfg_r_data_o, + input logic soc_cfg_wrn_i, + output logic per_cfg_lock_o, + input logic per_cfg_req_i, + output logic per_cfg_ack_o, + input logic [1:0] per_cfg_add_i, + input logic [31:0] per_cfg_data_i, + output logic [31:0] per_cfg_r_data_o, + input logic per_cfg_wrn_i, + output logic cluster_cfg_lock_o, + input logic cluster_cfg_req_i, + output logic cluster_cfg_ack_o, + input logic [1:0] cluster_cfg_add_i, + input logic [31:0] cluster_cfg_data_i, + output logic [31:0] cluster_cfg_r_data_o, + input logic cluster_cfg_wrn_i + ); + + logic s_locked; + + xilinx_clk_mngr i_clk_manager + ( + .resetn(rstn_glob_i), + .clk_in1(ref_clk_i), + .clk_out1(soc_clk_o), + .clk_out2(per_clk_o), + .locked(s_locked) + ); + + assign soc_cfg_lock_o = s_locked; + assign per_cfg_lock_o = s_locked; + + assign soc_cfg_ack_o = 1'b1; //Always acknowledge without doing anything for now + assign per_cfg_ack_o = 1'b1; + + assign soc_cfg_r_data_o = 32'hdeadda7a; + assign per_cfg_r_data_o = 32'hdeadda7a; + +endmodule : fpga_clk_gen diff --git a/rtl/pulpemu/src_files.yml b/rtl/pulpemu/src_files.yml index 797b5906..af696eea 100644 --- a/rtl/pulpemu/src_files.yml +++ b/rtl/pulpemu/src_files.yml @@ -11,6 +11,7 @@ pulpemu: fpga_bootrom.sv, fpga_interleaved_ram.sv, fpga_private_ram.sv, + fpga_clk_gen.sv pulpemu.sv, pulpemu_ref_clk_div.sv, ] From 28f39bdeffae1820bd9dede0df0771e38740c57b Mon Sep 17 00:00:00 2001 From: agarofalo Date: Fri, 25 Oct 2019 03:40:28 -0700 Subject: [PATCH 17/46] updated pulpemu for new clk srcs --- rtl/pulpemu/pulpemu.sv | 110 ++++++++++++++++++++++++++--------------- 1 file changed, 69 insertions(+), 41 deletions(-) diff --git a/rtl/pulpemu/pulpemu.sv b/rtl/pulpemu/pulpemu.sv index 2ba32781..655721e6 100644 --- a/rtl/pulpemu/pulpemu.sv +++ b/rtl/pulpemu/pulpemu.sv @@ -23,54 +23,57 @@ module pulpemu parameter USE_HWPE = 0 ) ( + input clk_125_n, + input clk_125_p, // LED for VERIFY - output LED, + output LED, // FMC pins - inout FMC_qspi_sdio0, - inout FMC_qspi_sdio1, - inout FMC_qspi_sdio2, - inout FMC_qspi_sdio3, - inout FMC_qspi_csn0, - inout FMC_qspi_csn1, - inout FMC_qspi_sck, - inout FMC_sdio_data0, - inout FMC_sdio_data1, - inout FMC_sdio_data2, - inout FMC_sdio_data3, - inout FMC_sdio_cmd, - inout FMC_sdio_sck, - inout FMC_i2c0_sda, - inout FMC_i2c0_scl, - inout FMC_uart_rx, - inout FMC_uart_tx, - inout FMC_i2s0_sck, - inout FMC_i2s0_ws, - inout FMC_i2s0_sdi, - inout FMC_i2s1_sdi, - inout FMC_cam_pclk, - inout FMC_cam_hsync, - inout FMC_cam_data0, - inout FMC_cam_data1, - inout FMC_cam_data2, - inout FMC_cam_data3, - inout FMC_cam_data4, - inout FMC_cam_data5, - inout FMC_cam_data6, - inout FMC_cam_data7, - inout FMC_cam_vsync, - inout FMC_jtag_tck, - inout FMC_jtag_tdi, - inout FMC_jtag_tdo, - inout FMC_jtag_tms, - inout FMC_jtag_trst, - inout FMC_bootmode, - inout FMC_reset_n + inout FMC_qspi_sdio0, + inout FMC_qspi_sdio1, + inout FMC_qspi_sdio2, + inout FMC_qspi_sdio3, + inout FMC_qspi_csn0, + inout FMC_qspi_csn1, + inout FMC_qspi_sck, + inout FMC_sdio_data0, + inout FMC_sdio_data1, + inout FMC_sdio_data2, + inout FMC_sdio_data3, + inout FMC_sdio_cmd, + inout FMC_sdio_sck, + inout FMC_i2c0_sda, + inout FMC_i2c0_scl, + inout FMC_uart_rx, + inout FMC_uart_tx, + inout FMC_i2s0_sck, + inout FMC_i2s0_ws, + inout FMC_i2s0_sdi, + inout FMC_i2s1_sdi, + inout FMC_cam_pclk, + inout FMC_cam_hsync, + inout FMC_cam_data0, + inout FMC_cam_data1, + inout FMC_cam_data2, + inout FMC_cam_data3, + inout FMC_cam_data4, + inout FMC_cam_data5, + inout FMC_cam_data6, + inout FMC_cam_data7, + inout FMC_cam_vsync, + inout FMC_jtag_tck, + inout FMC_jtag_tdi, + inout FMC_jtag_tdo, + inout FMC_jtag_tms, + inout FMC_jtag_trst, + inout FMC_bootmode, + inout FMC_reset_n ); // pulpemu top signals logic zynq_clk; logic zynq_rst_n; logic pulp_soc_clk; + logic pulp_per_clk; logic pulp_cluster_clk; // reference 32768 Hz clock @@ -82,6 +85,7 @@ module pulpemu // ███╔╝ ╚██╔╝ ██║╚██╗██║██║▄▄ ██║ ██║███╗██║██╔══██╗██╔══██║██╔═══╝ ██╔═══╝ ██╔══╝ ██╔══██╗ // ███████╗ ██║ ██║ ╚████║╚██████╔╝███████╗╚███╔███╔╝██║ ██║██║ ██║██║ ██║ ███████╗██║ ██║ // ╚══════╝ ╚═╝ ╚═╝ ╚═══╝ ╚══▀▀═╝ ╚══════╝ ╚══╝╚══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ +/* -----\/----- EXCLUDED -----\/----- zynq_wrapper zynq_wrapper_i ( // pulp clocks (clk_wiz_clk_out1->cluster, clk_wiz_clk_out2->soc, clk_wiz_clk_out3->per) @@ -92,8 +96,32 @@ module pulpemu .zynq_clk (zynq_clk ), .zynq_rst_n (zynq_rst_n ) ); + -----/\----- EXCLUDED -----/\----- */ - + //Differential to single ended clock conversion + IBUFGDS + #( + .IOSTANDARD("LVDS"), + .DIFF_TERM("FALSE"), + .IBUF_LOW_PWR("FALSE")) + i_sysclk_iobuf + ( + .I(clk_125_p), + .IB(clk_125_n), + .O(clk_125) // 125 MHz clock + ); + + // add clock generation for pulp chip, replaces zynq_wrapper + xilinx_clk_mngr_clk_wiz inst + ( + .clk_in1(clk_125), // 125 MHz + .clk_out1(ref_clk), // 8.something MHz + .clk_out2(pulp_soc_clk), // 50 Mhz + .clk_out3(pulp_per_clk), // 50MHz + .clk_out4(pulp_cluster_clk), //50MHz + .resetn(zynq_rst_n), + .locked( ), + ); pulpemu_ref_clk_div #( From 05b7bd12d5a873b0e3f234cf3c6244d4e0302082 Mon Sep 17 00:00:00 2001 From: "jie.chen" Date: Fri, 25 Oct 2019 14:13:17 +0200 Subject: [PATCH 18/46] Update pin --- rtl/pulpemu/pulpemu.sv | 35 ++++++++--------------------------- rtl/pulpemu/src_files.yml | 1 - 2 files changed, 8 insertions(+), 28 deletions(-) diff --git a/rtl/pulpemu/pulpemu.sv b/rtl/pulpemu/pulpemu.sv index 655721e6..7f615878 100644 --- a/rtl/pulpemu/pulpemu.sv +++ b/rtl/pulpemu/pulpemu.sv @@ -25,6 +25,7 @@ module pulpemu ( input clk_125_n, input clk_125_p, + input cpu_reset, // LED for VERIFY output LED, // FMC pins @@ -71,7 +72,6 @@ module pulpemu // pulpemu top signals logic zynq_clk; - logic zynq_rst_n; logic pulp_soc_clk; logic pulp_per_clk; logic pulp_cluster_clk; @@ -79,25 +79,6 @@ module pulpemu // reference 32768 Hz clock wire ref_clk; - // ███████╗██╗ ██╗███╗ ██╗ ██████╗ ██╗ ██╗██████╗ █████╗ ██████╗ ██████╗ ███████╗██████╗ - // ╚══███╔╝╚██╗ ██╔╝████╗ ██║██╔═══██╗ ██║ ██║██╔══██╗██╔══██╗██╔══██╗██╔══██╗██╔════╝██╔══██╗ - // ███╔╝ ╚████╔╝ ██╔██╗ ██║██║ ██║ ██║ █╗ ██║██████╔╝███████║██████╔╝██████╔╝█████╗ ██████╔╝ - // ███╔╝ ╚██╔╝ ██║╚██╗██║██║▄▄ ██║ ██║███╗██║██╔══██╗██╔══██║██╔═══╝ ██╔═══╝ ██╔══╝ ██╔══██╗ - // ███████╗ ██║ ██║ ╚████║╚██████╔╝███████╗╚███╔███╔╝██║ ██║██║ ██║██║ ██║ ███████╗██║ ██║ - // ╚══════╝ ╚═╝ ╚═╝ ╚═══╝ ╚══▀▀═╝ ╚══════╝ ╚══╝╚══╝ ╚═╝ ╚═╝╚═╝ ╚═╝╚═╝ ╚═╝ ╚══════╝╚═╝ ╚═╝ -/* -----\/----- EXCLUDED -----\/----- - - zynq_wrapper zynq_wrapper_i ( - // pulp clocks (clk_wiz_clk_out1->cluster, clk_wiz_clk_out2->soc, clk_wiz_clk_out3->per) - .pulp_cluster_clk (pulp_cluster_clk ), - .pulp_soc_clk (pulp_soc_clk ), - .pulp_per_clk (pulp_per_clk ), - // zynq clock (FCLK0) - .zynq_clk (zynq_clk ), - .zynq_rst_n (zynq_rst_n ) - ); - -----/\----- EXCLUDED -----/\----- */ - //Differential to single ended clock conversion IBUFGDS #( @@ -114,12 +95,12 @@ module pulpemu // add clock generation for pulp chip, replaces zynq_wrapper xilinx_clk_mngr_clk_wiz inst ( - .clk_in1(clk_125), // 125 MHz - .clk_out1(ref_clk), // 8.something MHz - .clk_out2(pulp_soc_clk), // 50 Mhz - .clk_out3(pulp_per_clk), // 50MHz + .clk_in1(clk_125), // 125 MHz + .clk_out1(zynq_clk), // 256*32768 = 8.3886 Hz + .clk_out2(pulp_soc_clk), // 50 Mhz + .clk_out3(pulp_per_clk), // 50MHz .clk_out4(pulp_cluster_clk), //50MHz - .resetn(zynq_rst_n), + .resetn(~cpu_reset), .locked( ), ); @@ -129,7 +110,7 @@ module pulpemu ) ref_clk_div ( .clk_i ( zynq_clk ), // FPGA inner clock, 8.388608 MHz - .rstn_i ( zynq_rst_n ), // FPGA inner reset + .rstn_i ( ~cpu_reset ), // FPGA inner reset .ref_clk_o ( ref_clk ) // REF clock out ); @@ -140,7 +121,7 @@ module pulpemu ) led_clk_div ( .clk_i ( ref_clk ), - .rstn_i ( zynq_rst_n ), + .rstn_i ( ~cpu_reset ), .ref_clk_o ( LED ) ); diff --git a/rtl/pulpemu/src_files.yml b/rtl/pulpemu/src_files.yml index af696eea..797b5906 100644 --- a/rtl/pulpemu/src_files.yml +++ b/rtl/pulpemu/src_files.yml @@ -11,7 +11,6 @@ pulpemu: fpga_bootrom.sv, fpga_interleaved_ram.sv, fpga_private_ram.sv, - fpga_clk_gen.sv pulpemu.sv, pulpemu_ref_clk_div.sv, ] From fa633b6c1613fdd7811530f36485e1bcf9525645 Mon Sep 17 00:00:00 2001 From: "jie.chen" Date: Fri, 25 Oct 2019 14:29:26 +0200 Subject: [PATCH 19/46] Fix clk wiz module syntax error --- rtl/pulpemu/pulpemu.sv | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/rtl/pulpemu/pulpemu.sv b/rtl/pulpemu/pulpemu.sv index 7f615878..d243d465 100644 --- a/rtl/pulpemu/pulpemu.sv +++ b/rtl/pulpemu/pulpemu.sv @@ -71,7 +71,7 @@ module pulpemu ); // pulpemu top signals - logic zynq_clk; + logic pulp_ref_clk; logic pulp_soc_clk; logic pulp_per_clk; logic pulp_cluster_clk; @@ -93,15 +93,15 @@ module pulpemu ); // add clock generation for pulp chip, replaces zynq_wrapper - xilinx_clk_mngr_clk_wiz inst + xilinx_clk_mngr clk_wiz_0 ( - .clk_in1(clk_125), // 125 MHz - .clk_out1(zynq_clk), // 256*32768 = 8.3886 Hz + .clk_out1(pulp_ref_clk), // 256*32768 = 8.3886 MHz .clk_out2(pulp_soc_clk), // 50 Mhz .clk_out3(pulp_per_clk), // 50MHz .clk_out4(pulp_cluster_clk), //50MHz .resetn(~cpu_reset), .locked( ), + .clk_in1(clk_125) // 125 MHz ); pulpemu_ref_clk_div @@ -109,7 +109,7 @@ module pulpemu .DIVISOR ( 256 ) ) ref_clk_div ( - .clk_i ( zynq_clk ), // FPGA inner clock, 8.388608 MHz + .clk_i ( pulp_ref_clk ), // FPGA inner clock, 8.388608 MHz .rstn_i ( ~cpu_reset ), // FPGA inner reset .ref_clk_o ( ref_clk ) // REF clock out ); @@ -188,7 +188,7 @@ module pulpemu .pad_jtag_tms(FMC_jtag_tms), .pad_jtag_trst(FMC_jtag_trst), - .pad_xtal_in(), // USE zynq_clk_i as ref_clk + .pad_xtal_in(), // USE generated ref_clk .pad_reset_n(FMC_reset_n), .pad_bootsel(FMC_bootmode) // Boot mode = 0; boot from flash; Boot mode = 1; boot from jtag ); From a6a90e5b2fe9cba864fd5b7c39dd9430419367d6 Mon Sep 17 00:00:00 2001 From: Jie CHEN Date: Fri, 25 Oct 2019 15:12:55 +0200 Subject: [PATCH 20/46] Delete useless file --- rtl/pulpemu/fpga_clk_gen.sv | 74 ------------------------------------- 1 file changed, 74 deletions(-) delete mode 100644 rtl/pulpemu/fpga_clk_gen.sv diff --git a/rtl/pulpemu/fpga_clk_gen.sv b/rtl/pulpemu/fpga_clk_gen.sv deleted file mode 100644 index 2ad9a8eb..00000000 --- a/rtl/pulpemu/fpga_clk_gen.sv +++ /dev/null @@ -1,74 +0,0 @@ -//----------------------------------------------------------------------------- -// Title : FPGA CLK Gen for PULPissimo -// ----------------------------------------------------------------------------- -// File : fpga_clk_gen.sv Author : Manuel Eggimann -// Created : 17.05.2019 -// ----------------------------------------------------------------------------- -// Description : Instantiates Xilinx clocking wizard IP to generate 2 output -// clocks. Currently, the clock is not dynamicly reconfigurable and all -// configuration requests are acknowledged without any effect. -// ----------------------------------------------------------------------------- -// Copyright (C) 2013-2019 ETH Zurich, University of Bologna Copyright and -// related rights are licensed under the Solderpad Hardware License, Version -// 0.51 (the "License"); you may not use this file except in compliance with the -// License. You may obtain a copy of the License at -// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law or -// agreed to in writing, software, hardware and materials distributed under this -// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS -// OF ANY KIND, either express or implied. See the License for the specific -// language governing permissions and limitations under the License. -// ----------------------------------------------------------------------------- - - -module fpga_clk_gen ( - input logic ref_clk_i, - input logic rstn_glob_i, - input logic test_mode_i, - input logic shift_enable_i, - output logic soc_clk_o, - output logic per_clk_o, - output logic cluster_clk_o, - output logic soc_cfg_lock_o, - input logic soc_cfg_req_i, - output logic soc_cfg_ack_o, - input logic [1:0] soc_cfg_add_i, - input logic [31:0] soc_cfg_data_i, - output logic [31:0] soc_cfg_r_data_o, - input logic soc_cfg_wrn_i, - output logic per_cfg_lock_o, - input logic per_cfg_req_i, - output logic per_cfg_ack_o, - input logic [1:0] per_cfg_add_i, - input logic [31:0] per_cfg_data_i, - output logic [31:0] per_cfg_r_data_o, - input logic per_cfg_wrn_i, - output logic cluster_cfg_lock_o, - input logic cluster_cfg_req_i, - output logic cluster_cfg_ack_o, - input logic [1:0] cluster_cfg_add_i, - input logic [31:0] cluster_cfg_data_i, - output logic [31:0] cluster_cfg_r_data_o, - input logic cluster_cfg_wrn_i - ); - - logic s_locked; - - xilinx_clk_mngr i_clk_manager - ( - .resetn(rstn_glob_i), - .clk_in1(ref_clk_i), - .clk_out1(soc_clk_o), - .clk_out2(per_clk_o), - .locked(s_locked) - ); - - assign soc_cfg_lock_o = s_locked; - assign per_cfg_lock_o = s_locked; - - assign soc_cfg_ack_o = 1'b1; //Always acknowledge without doing anything for now - assign per_cfg_ack_o = 1'b1; - - assign soc_cfg_r_data_o = 32'hdeadda7a; - assign per_cfg_r_data_o = 32'hdeadda7a; - -endmodule : fpga_clk_gen From 195a3764854ae8f73ab9f104144bcc57c61eb83c Mon Sep 17 00:00:00 2001 From: Jie CHEN Date: Fri, 25 Oct 2019 22:07:55 +0200 Subject: [PATCH 21/46] Update to add BUFGCE --- rtl/pulpemu/pulpemu.sv | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/rtl/pulpemu/pulpemu.sv b/rtl/pulpemu/pulpemu.sv index d243d465..0fe23e2c 100644 --- a/rtl/pulpemu/pulpemu.sv +++ b/rtl/pulpemu/pulpemu.sv @@ -92,16 +92,19 @@ module pulpemu .O(clk_125) // 125 MHz clock ); + logic clk_125_buf; + BUFGCE i_clk_buf (.I(clk_125), .CE(1'b1), .O(clk_125_buf)); + // add clock generation for pulp chip, replaces zynq_wrapper xilinx_clk_mngr clk_wiz_0 ( .clk_out1(pulp_ref_clk), // 256*32768 = 8.3886 MHz - .clk_out2(pulp_soc_clk), // 50 Mhz + .clk_out2(pulp_soc_clk), // 50 Mhz .clk_out3(pulp_per_clk), // 50MHz .clk_out4(pulp_cluster_clk), //50MHz - .resetn(~cpu_reset), + .resetn(~cpu_reset), .locked( ), - .clk_in1(clk_125) // 125 MHz + .clk_in1(clk_125_buf) // 125 MHz ); pulpemu_ref_clk_div From 1cf3471ad7175aa60d170faf0f6e9294c5ec32c8 Mon Sep 17 00:00:00 2001 From: "jie.chen" Date: Tue, 29 Oct 2019 18:14:33 +0100 Subject: [PATCH 22/46] Update for fpga sim --- rtl/tb/tb_pulp.sv | 99 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 86 insertions(+), 13 deletions(-) diff --git a/rtl/tb/tb_pulp.sv b/rtl/tb/tb_pulp.sv index 20ba68c6..20c9915d 100644 --- a/rtl/tb/tb_pulp.sv +++ b/rtl/tb/tb_pulp.sv @@ -45,6 +45,11 @@ module tb_pulp; // period of the external reference clock (32.769kHz) parameter REF_CLK_PERIOD = 30517ns; + + `ifdef PULP_FPGA_EMUL + parameter SYSTEM_CLK_PERIOD = 8ns; + `endif + // how L2 is loaded. valid values are "JTAG" or "STANDALONE", the latter works only when USE_S25FS256S_MODEL is 1 parameter LOAD_L2 = "JTAG"; @@ -534,6 +539,9 @@ module tb_pulp; // PULP chip (design under test) + `ifndef PULP_FPGA_EMUL + `define PULP_INST i_dut + pulp #( .CORE_TYPE ( CORE_TYPE ), .USE_FPU ( RISCY_FPU ) @@ -589,6 +597,72 @@ module tb_pulp; .pad_xtal_in ( w_clk_ref ) ); + `else // !`ifndef PULP_FPGA_EMU + + `define PULP_INST i_dut.pulp_chip_i + + logic s_clk_125; + tb_clk_gen #( .CLK_PERIOD(SYSTEM_CLK_PERIOD) ) i_system_clk_gen (.clk_o(s_clk_125) ); + + pulpemu #( + .CORE_TYPE ( 0 ), + .USE_FPU ( 1 ), + .USE_HWPE ( 0 ) + ) + i_dut ( + .clk_125_p ( s_clk_125 ), + .clk_125_n ( ~s_clk_125 ), + .cpu_reset ( s_rst_n ), + + .FMC_qspi_sdio0 ( w_spi_master_sdio0 ), + .FMC_qspi_sdio1 ( w_spi_master_sdio1 ), + .FMC_qspi_sdio2 ( w_spi_master_sdio2 ), + .FMC_qspi_sdio3 ( w_spi_master_sdio3 ), + .FMC_qspi_csn0 ( w_spi_master_csn0 ), + .FMC_qspi_csn1 ( w_spi_master_csn1 ), + .FMC_qspi_sck ( w_spi_master_sck ), + + .FMC_uart_rx ( w_uart_tx ), + .FMC_uart_tx ( w_uart_rx ), + + .FMC_cam_pclk ( w_cam_pclk ), + .FMC_cam_hsync ( w_cam_hsync ), + .FMC_cam_data0 ( w_cam_data[0] ), + .FMC_cam_data1 ( w_cam_data[1] ), + .FMC_cam_data2 ( w_cam_data[2] ), + .FMC_cam_data3 ( w_cam_data[3] ), + .FMC_cam_data4 ( w_cam_data[4] ), + .FMC_cam_data5 ( w_cam_data[5] ), + .FMC_cam_data6 ( w_cam_data[6] ), + .FMC_cam_data7 ( w_cam_data[7] ), + .FMC_cam_vsync ( w_cam_vsync ), + + .FMC_sdio_sck ( ), + .FMC_sdio_cmd ( ), + .FMC_sdio_data0 ( w_sdio_data0 ), + .FMC_sdio_data1 ( ), + .FMC_sdio_data2 ( ), + .FMC_sdio_data3 ( ), + + .FMC_i2c0_sda ( w_i2c0_sda ), + .FMC_i2c0_scl ( w_i2c0_scl ), + + .FMC_i2s0_sck ( w_i2s0_sck ), + .FMC_i2s0_ws ( w_i2s0_ws ), + .FMC_i2s0_sdi ( w_i2s0_sdi ), + .FMC_i2s1_sdi ( w_i2s1_sdi ), + + .FMC_reset_n ( w_rst_n ), + .FMC_bootmode ( w_bootsel ), + + .FMC_jtag_tck ( w_tck ), + .FMC_jtag_tdi ( w_tdi ), + .FMC_jtag_tdo ( w_tdo ), + .FMC_jtag_tms ( w_tms ), + .FMC_jtag_trst ( w_trstn ) + ); + `endif + tb_clk_gen #( .CLK_PERIOD(REF_CLK_PERIOD) ) i_ref_clk_gen (.clk_o(s_clk_ref) ); initial begin: timing_format @@ -807,8 +881,7 @@ module tb_pulp; end end - - + `ifndef USE_NETLIST /* File System access */ logic r_stdout_pready; @@ -822,26 +895,26 @@ module tb_pulp; logic [31:0] fs_wdata; logic [31:0] fs_rdata; - assign fs_clk = i_dut.soc_domain_i.pulp_soc_i.s_soc_clk; - assign fs_rst_n = i_dut.soc_domain_i.pulp_soc_i.s_soc_rstn; + assign fs_clk = `PULP_INST.soc_domain_i.pulp_soc_i.s_soc_clk; + assign fs_rst_n = `PULP_INST.soc_domain_i.pulp_soc_i.s_soc_rstn; - assign fs_csn = ~(i_dut.soc_domain_i.pulp_soc_i.soc_peripherals_i.s_stdout_bus.psel & - i_dut.soc_domain_i.pulp_soc_i.soc_peripherals_i.s_stdout_bus.penable & + assign fs_csn = ~(`PULP_INST.soc_domain_i.pulp_soc_i.soc_peripherals_i.s_stdout_bus.psel & + `PULP_INST.soc_domain_i.pulp_soc_i.soc_peripherals_i.s_stdout_bus.penable & r_stdout_pready); - assign fs_wen = ~i_dut.soc_domain_i.pulp_soc_i.soc_peripherals_i.s_stdout_bus.pwrite; - assign fs_add = i_dut.soc_domain_i.pulp_soc_i.soc_peripherals_i.s_stdout_bus.paddr; - assign fs_wdata = i_dut.soc_domain_i.pulp_soc_i.soc_peripherals_i.s_stdout_bus.pwdata; + assign fs_wen = ~`PULP_INST.soc_domain_i.pulp_soc_i.soc_peripherals_i.s_stdout_bus.pwrite; + assign fs_add = `PULP_INST.soc_domain_i.pulp_soc_i.soc_peripherals_i.s_stdout_bus.paddr; + assign fs_wdata = `PULP_INST.soc_domain_i.pulp_soc_i.soc_peripherals_i.s_stdout_bus.pwdata; assign fs_be = 4'hF; - assign i_dut.soc_domain_i.pulp_soc_i.soc_peripherals_i.s_stdout_bus.pready = r_stdout_pready; - assign i_dut.soc_domain_i.pulp_soc_i.soc_peripherals_i.s_stdout_bus.pslverr = 1'b0; - assign i_dut.soc_domain_i.pulp_soc_i.soc_peripherals_i.s_stdout_bus.prdata = fs_rdata; + assign `PULP_INST.soc_domain_i.pulp_soc_i.soc_peripherals_i.s_stdout_bus.pready = r_stdout_pready; + assign `PULP_INST.soc_domain_i.pulp_soc_i.soc_peripherals_i.s_stdout_bus.pslverr = 1'b0; + assign `PULP_INST.soc_domain_i.pulp_soc_i.soc_peripherals_i.s_stdout_bus.prdata = fs_rdata; always_ff @(posedge fs_clk or negedge fs_rst_n) begin if(~fs_rst_n) begin r_stdout_pready <= 0; end else begin - r_stdout_pready <= (i_dut.soc_domain_i.pulp_soc_i.soc_peripherals_i.s_stdout_bus.psel & i_dut.soc_domain_i.pulp_soc_i.soc_peripherals_i.s_stdout_bus.penable); + r_stdout_pready <= (`PULP_INST.soc_domain_i.pulp_soc_i.soc_peripherals_i.s_stdout_bus.psel & `PULP_INST.soc_domain_i.pulp_soc_i.soc_peripherals_i.s_stdout_bus.penable); end end From fe06cda33bfedb824cfc2e3c76c73ffb522e0a40 Mon Sep 17 00:00:00 2001 From: "jie.chen" Date: Tue, 29 Oct 2019 19:11:04 +0100 Subject: [PATCH 23/46] Update for netlist simu --- rtl/tb/src_files.yml | 1 + rtl/tb/tb_pulp.sv | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/rtl/tb/src_files.yml b/rtl/tb/src_files.yml index a1d66dcb..249bdf10 100644 --- a/rtl/tb/src_files.yml +++ b/rtl/tb/src_files.yml @@ -3,6 +3,7 @@ tb: rtl ] files: [ + ../../ips/riscv-dbg/src/dm_pkg.sv, riscv_pkg.sv, jtag_pkg.sv, pulp_tap_pkg.sv, diff --git a/rtl/tb/tb_pulp.sv b/rtl/tb/tb_pulp.sv index 20c9915d..38f4b5e7 100644 --- a/rtl/tb/tb_pulp.sv +++ b/rtl/tb/tb_pulp.sv @@ -604,11 +604,14 @@ module tb_pulp; logic s_clk_125; tb_clk_gen #( .CLK_PERIOD(SYSTEM_CLK_PERIOD) ) i_system_clk_gen (.clk_o(s_clk_125) ); - pulpemu #( + pulpemu + `ifndef USE_NETLIST + #( .CORE_TYPE ( 0 ), .USE_FPU ( 1 ), .USE_HWPE ( 0 ) ) + `endif i_dut ( .clk_125_p ( s_clk_125 ), .clk_125_n ( ~s_clk_125 ), From 465dc8cf9ae98b22f01f313e0879a0b62083c25c Mon Sep 17 00:00:00 2001 From: "jie.chen" Date: Wed, 30 Oct 2019 10:51:17 +0100 Subject: [PATCH 24/46] Fix cpu reset and fpga sim issue --- rtl/pulpemu/pulpemu.sv | 4 ++-- rtl/tb/tb_pulp.sv | 11 +++++++++-- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/rtl/pulpemu/pulpemu.sv b/rtl/pulpemu/pulpemu.sv index 0fe23e2c..f589f2f9 100644 --- a/rtl/pulpemu/pulpemu.sv +++ b/rtl/pulpemu/pulpemu.sv @@ -83,8 +83,8 @@ module pulpemu IBUFGDS #( .IOSTANDARD("LVDS"), - .DIFF_TERM("FALSE"), - .IBUF_LOW_PWR("FALSE")) + .DIFF_TERM(0), + .IBUF_LOW_PWR(0)) i_sysclk_iobuf ( .I(clk_125_p), diff --git a/rtl/tb/tb_pulp.sv b/rtl/tb/tb_pulp.sv index 38f4b5e7..2cf25fcd 100644 --- a/rtl/tb/tb_pulp.sv +++ b/rtl/tb/tb_pulp.sv @@ -125,6 +125,7 @@ module tb_pulp; /* system wires */ // the w_/s_ prefixes are used to mean wire/tri-type and logic-type (respectively) + logic s_cpu_rst = 1'b1; logic s_rst_n = 1'b0; logic s_rst_dpi_n; wire w_rst_n; @@ -615,7 +616,7 @@ module tb_pulp; i_dut ( .clk_125_p ( s_clk_125 ), .clk_125_n ( ~s_clk_125 ), - .cpu_reset ( s_rst_n ), + .cpu_reset ( s_cpu_rst ), .FMC_qspi_sdio0 ( w_spi_master_sdio0 ), .FMC_qspi_sdio1 ( w_spi_master_sdio1 ), @@ -698,7 +699,13 @@ module tb_pulp; $display("[TB] %t - Asserting hard reset", $realtime); s_rst_n = 1'b0; - + `ifdef PULP_FPGA_EMUL + $display("[TB] %t - Asserting CPU reset", $realtime); + s_cpu_rst = 1'b1; + #1us; + $display("[TB] %t - Releasing CPU reset", $realtime); + s_cpu_rst = 1'b0; + `endif #1ns uart_tb_rx_en = 1'b1; // enable uart rx in testbench From c70aa4d61c3afc19b06ebb807e93b72e877f0eee Mon Sep 17 00:00:00 2001 From: Angelo Garofalo Date: Thu, 14 Nov 2019 10:49:11 +0100 Subject: [PATCH 25/46] change clk prop strategy --- rtl/pulp/pad_frame.sv | 13 +- rtl/pulp/pulp.sv | 23 ++- rtl/pulp/safe_domain.sv | 359 +++++++++++++++++---------------- rtl/pulp/soc_domain.sv | 413 +++++++++++++++++++------------------- rtl/pulpemu/pulpemu.sv | 80 ++++---- rtl/pulpemu/src_files.yml | 2 + 6 files changed, 463 insertions(+), 427 deletions(-) diff --git a/rtl/pulp/pad_frame.sv b/rtl/pulp/pad_frame.sv index 775dcf27..9b677336 100644 --- a/rtl/pulp/pad_frame.sv +++ b/rtl/pulp/pad_frame.sv @@ -216,19 +216,26 @@ module pad_frame pad_functional_pu padinst_bootsel (.OEN(1'b1 ), .I( ), .O(bootsel_o ), .PAD(pad_bootsel ), .PEN(1'b1 ) ); - + +`ifndef PULP_FPGA_EMUL pad_functional_pu padinst_reset_n (.OEN(1'b1 ), .I( ), .O(rstn_o ), .PAD(pad_reset_n ), .PEN(1'b1 ) ); pad_functional_pu padinst_jtag_tck (.OEN(1'b1 ), .I( ), .O(jtag_tck_o ), .PAD(pad_jtag_tck ), .PEN(1'b1 ) ); pad_functional_pu padinst_jtag_tms (.OEN(1'b1 ), .I( ), .O(jtag_tms_o ), .PAD(pad_jtag_tms ), .PEN(1'b1 ) ); pad_functional_pu padinst_jtag_tdi (.OEN(1'b1 ), .I( ), .O(jtag_tdi_o ), .PAD(pad_jtag_tdi ), .PEN(1'b1 ) ); pad_functional_pu padinst_jtag_trstn (.OEN(1'b1 ), .I( ), .O(jtag_trst_o ), .PAD(pad_jtag_trst ), .PEN(1'b1 ) ); pad_functional_pd padinst_jtag_tdo (.OEN(1'b0 ), .I(jtag_tdo_i ), .O( ), .PAD(pad_jtag_tdo ), .PEN(1'b1 ) ); - -`ifndef PULP_FPGA_EMUL pad_functional_pu padinst_ref_clk (.OEN(1'b1 ), .I( ), .O(ref_clk_o ), .PAD(pad_xtal_in ), .PEN(1'b1 ) ); `else assign ref_clk_o = pad_xtal_in; + assign rstn_o = pad_reset_n; + + //JTAG signals + assign pad_jtag_tdo = jtag_tdo_i; + assign jtag_trst_o = pad_jtag_trst; + assign jtag_tms_o = pad_jtag_tms; + assign jtag_tck_o = pad_jtag_tck; + assign jtag_tdi_o = pad_jtag_tdi; `endif endmodule // pad_frame diff --git a/rtl/pulp/pulp.sv b/rtl/pulp/pulp.sv index cb001ef2..731b83f0 100644 --- a/rtl/pulp/pulp.sv +++ b/rtl/pulp/pulp.sv @@ -18,10 +18,10 @@ module pulp ) ( `ifdef PULP_FPGA_EMUL - input logic zynq_clk_i, - input logic zynq_soc_clk_i, - input logic zynq_cluster_clk_i, - input logic zynq_per_clk_i, + // input logic zynq_clk_i, + // input logic zynq_soc_clk_i, + // input logic zynq_cluster_clk_i, + // input logic zynq_per_clk_i, `endif inout wire pad_spim_sdio0, @@ -213,6 +213,7 @@ module pulp //*********************************************************** logic s_test_clk; + logic s_slow_clk; logic s_sel_fll_clk; logic [11:0] s_pm_cfg_data; @@ -471,15 +472,15 @@ module pulp //********** PAD FRAME ************************************** //*********************************************************** `ifdef PULP_FPGA_EMUL - assign s_ref_clk = zynq_clk_i; + //assign s_ref_clk = zynq_clk_i; `endif pad_frame pad_frame_i ( .pad_cfg_i ( s_pad_cfg ), -`ifndef PULP_FPGA_EMUL +//`ifndef PULP_FPGA_EMUL .ref_clk_o ( s_ref_clk ), -`endif +//`endif .rstn_o ( s_rstn ), .jtag_tdo_i ( s_jtag_tdo ), .jtag_tck_o ( s_jtag_tck ), @@ -638,6 +639,7 @@ module pulp safe_domain safe_domain_i ( .ref_clk_i ( s_ref_clk ), + .slow_clk_o ( s_slow_clk ), .rst_ni ( s_rstn ), .rst_no ( s_rstn_por ), @@ -854,13 +856,14 @@ module pulp ) soc_domain_i ( .ref_clk_i ( s_ref_clk ), + .slow_clk_i ( s_slow_clk ), .test_clk_i ( s_test_clk ), .rstn_glob_i ( s_rstn_por ), `ifdef PULP_FPGA_EMUL - .zynq_soc_clk_i ( zynq_soc_clk_i ), - .zynq_cluster_clk_i ( zynq_cluster_clk_i ), - .zynq_per_clk_i ( zynq_per_clk_i ), + //.zynq_soc_clk_i ( zynq_soc_clk_i ), + //.zynq_cluster_clk_i ( zynq_cluster_clk_i ), + //.zynq_per_clk_i ( zynq_per_clk_i ), `endif .mode_select_i ( s_mode_select ), diff --git a/rtl/pulp/safe_domain.sv b/rtl/pulp/safe_domain.sv index e9a51507..bb9ceb6e 100644 --- a/rtl/pulp/safe_domain.sv +++ b/rtl/pulp/safe_domain.sv @@ -15,211 +15,212 @@ module safe_domain parameter FLL_ADDR_WIDTH = 32 ) ( - input logic ref_clk_i , - input logic rst_ni , - output logic rst_no , + input logic ref_clk_i , + output logic slow_clk_o, + input logic rst_ni , + output logic rst_no , - output logic test_clk_o , - output logic test_mode_o , - output logic mode_select_o , - output logic dft_cg_enable_o , + output logic test_clk_o , + output logic test_mode_o , + output logic mode_select_o , + output logic dft_cg_enable_o , //********************************************************** //*** PERIPHERALS SIGNALS ********************************** //********************************************************** // PAD CONTROL REGISTER - input logic [127:0] pad_mux_i , - input logic [383:0] pad_cfg_i , + input logic [127:0] pad_mux_i , + input logic [383:0] pad_cfg_i , - output logic [47:0][5:0] pad_cfg_o , + output logic [47:0][5:0] pad_cfg_o , // GPIOS - input logic [31:0] gpio_out_i , - output logic [31:0] gpio_in_o , - input logic [31:0] gpio_dir_i , - input logic [191:0] gpio_cfg_i , + input logic [31:0] gpio_out_i , + output logic [31:0] gpio_in_o , + input logic [31:0] gpio_dir_i , + input logic [191:0] gpio_cfg_i , // UART - input logic uart_tx_i , - output logic uart_rx_o , + input logic uart_tx_i , + output logic uart_rx_o , // I2C0 - input logic i2c0_scl_out_i , - output logic i2c0_scl_in_o , - input logic i2c0_scl_oe_i , - input logic i2c0_sda_out_i , - output logic i2c0_sda_in_o , - input logic i2c0_sda_oe_i , + input logic i2c0_scl_out_i , + output logic i2c0_scl_in_o , + input logic i2c0_scl_oe_i , + input logic i2c0_sda_out_i , + output logic i2c0_sda_in_o , + input logic i2c0_sda_oe_i , // I2C1 - input logic i2c1_scl_out_i , - output logic i2c1_scl_in_o , - input logic i2c1_scl_oe_i , - input logic i2c1_sda_out_i , - output logic i2c1_sda_in_o , - input logic i2c1_sda_oe_i , + input logic i2c1_scl_out_i , + output logic i2c1_scl_in_o , + input logic i2c1_scl_oe_i , + input logic i2c1_sda_out_i , + output logic i2c1_sda_in_o , + input logic i2c1_sda_oe_i , // I2S - output logic i2s_slave_sd0_o , - output logic i2s_slave_sd1_o , - output logic i2s_slave_ws_o , - input logic i2s_slave_ws_i , - input logic i2s_slave_ws_oe , - output logic i2s_slave_sck_o , - input logic i2s_slave_sck_i , - input logic i2s_slave_sck_oe , + output logic i2s_slave_sd0_o , + output logic i2s_slave_sd1_o , + output logic i2s_slave_ws_o , + input logic i2s_slave_ws_i , + input logic i2s_slave_ws_oe , + output logic i2s_slave_sck_o , + input logic i2s_slave_sck_i , + input logic i2s_slave_sck_oe , // SPI MASTER - input logic spi_master0_csn0_i , - input logic spi_master0_csn1_i , - input logic spi_master0_sck_i , - output logic spi_master0_sdi0_o , - output logic spi_master0_sdi1_o , - output logic spi_master0_sdi2_o , - output logic spi_master0_sdi3_o , - input logic spi_master0_sdo0_i , - input logic spi_master0_sdo1_i , - input logic spi_master0_sdo2_i , - input logic spi_master0_sdo3_i , - input logic spi_master0_oen0_i , - input logic spi_master0_oen1_i , - input logic spi_master0_oen2_i , - input logic spi_master0_oen3_i , - - input logic spi_master1_csn0_i , - input logic spi_master1_csn1_i , - input logic spi_master1_sck_i , - output logic spi_master1_sdi_o , - input logic spi_master1_sdo_i , - input logic [1:0] spi_master1_mode_i, - - - input logic sdio_clk_i, - input logic sdio_cmd_i, + input logic spi_master0_csn0_i , + input logic spi_master0_csn1_i , + input logic spi_master0_sck_i , + output logic spi_master0_sdi0_o , + output logic spi_master0_sdi1_o , + output logic spi_master0_sdi2_o , + output logic spi_master0_sdi3_o , + input logic spi_master0_sdo0_i , + input logic spi_master0_sdo1_i , + input logic spi_master0_sdo2_i , + input logic spi_master0_sdo3_i , + input logic spi_master0_oen0_i , + input logic spi_master0_oen1_i , + input logic spi_master0_oen2_i , + input logic spi_master0_oen3_i , + + input logic spi_master1_csn0_i , + input logic spi_master1_csn1_i , + input logic spi_master1_sck_i , + output logic spi_master1_sdi_o , + input logic spi_master1_sdo_i , + input logic [1:0] spi_master1_mode_i, + + + input logic sdio_clk_i, + input logic sdio_cmd_i, output logic sdio_cmd_o, - input logic sdio_cmd_oen_i, - input logic [3:0] sdio_data_i, + input logic sdio_cmd_oen_i, + input logic [3:0] sdio_data_i, output logic [3:0] sdio_data_o, - input logic [3:0] sdio_data_oen_i, + input logic [3:0] sdio_data_oen_i, // CAMERA INTERFACE - output logic cam_pclk_o , - output logic [7:0] cam_data_o , - output logic cam_hsync_o , - output logic cam_vsync_o , + output logic cam_pclk_o , + output logic [7:0] cam_data_o , + output logic cam_hsync_o , + output logic cam_vsync_o , // TIMER - input logic [3:0] timer0_i , - input logic [3:0] timer1_i , - input logic [3:0] timer2_i , - input logic [3:0] timer3_i , + input logic [3:0] timer0_i , + input logic [3:0] timer1_i , + input logic [3:0] timer2_i , + input logic [3:0] timer3_i , //********************************************************** //*** PAD FRAME SIGNALS ************************************ //********************************************************** // PADS OUTPUTS - output logic out_spim_sdio0_o , - output logic out_spim_sdio1_o , - output logic out_spim_sdio2_o , - output logic out_spim_sdio3_o , - output logic out_spim_csn0_o , - output logic out_spim_csn1_o , - output logic out_spim_sck_o , - output logic out_sdio_clk_o , - output logic out_sdio_cmd_o , - output logic out_sdio_data0_o , - output logic out_sdio_data1_o , - output logic out_sdio_data2_o , - output logic out_sdio_data3_o , - output logic out_uart_rx_o , - output logic out_uart_tx_o , - output logic out_cam_pclk_o , - output logic out_cam_hsync_o , - output logic out_cam_data0_o , - output logic out_cam_data1_o , - output logic out_cam_data2_o , - output logic out_cam_data3_o , - output logic out_cam_data4_o , - output logic out_cam_data5_o , - output logic out_cam_data6_o , - output logic out_cam_data7_o , - output logic out_cam_vsync_o , - output logic out_i2c0_sda_o , - output logic out_i2c0_scl_o , - output logic out_i2s0_sck_o , - output logic out_i2s0_ws_o , - output logic out_i2s0_sdi_o , - output logic out_i2s1_sdi_o , + output logic out_spim_sdio0_o , + output logic out_spim_sdio1_o , + output logic out_spim_sdio2_o , + output logic out_spim_sdio3_o , + output logic out_spim_csn0_o , + output logic out_spim_csn1_o , + output logic out_spim_sck_o , + output logic out_sdio_clk_o , + output logic out_sdio_cmd_o , + output logic out_sdio_data0_o , + output logic out_sdio_data1_o , + output logic out_sdio_data2_o , + output logic out_sdio_data3_o , + output logic out_uart_rx_o , + output logic out_uart_tx_o , + output logic out_cam_pclk_o , + output logic out_cam_hsync_o , + output logic out_cam_data0_o , + output logic out_cam_data1_o , + output logic out_cam_data2_o , + output logic out_cam_data3_o , + output logic out_cam_data4_o , + output logic out_cam_data5_o , + output logic out_cam_data6_o , + output logic out_cam_data7_o , + output logic out_cam_vsync_o , + output logic out_i2c0_sda_o , + output logic out_i2c0_scl_o , + output logic out_i2s0_sck_o , + output logic out_i2s0_ws_o , + output logic out_i2s0_sdi_o , + output logic out_i2s1_sdi_o , // PAD INPUTS - input logic in_spim_sdio0_i , - input logic in_spim_sdio1_i , - input logic in_spim_sdio2_i , - input logic in_spim_sdio3_i , - input logic in_spim_csn0_i , - input logic in_spim_csn1_i , - input logic in_spim_sck_i , - input logic in_sdio_clk_i , - input logic in_sdio_cmd_i , - input logic in_sdio_data0_i , - input logic in_sdio_data1_i , - input logic in_sdio_data2_i , - input logic in_sdio_data3_i , - input logic in_uart_rx_i , - input logic in_uart_tx_i , - input logic in_cam_pclk_i , - input logic in_cam_hsync_i , - input logic in_cam_data0_i , - input logic in_cam_data1_i , - input logic in_cam_data2_i , - input logic in_cam_data3_i , - input logic in_cam_data4_i , - input logic in_cam_data5_i , - input logic in_cam_data6_i , - input logic in_cam_data7_i , - input logic in_cam_vsync_i , - input logic in_i2c0_sda_i , - input logic in_i2c0_scl_i , - input logic in_i2s0_sck_i , - input logic in_i2s0_ws_i , - input logic in_i2s0_sdi_i , - input logic in_i2s1_sdi_i , + input logic in_spim_sdio0_i , + input logic in_spim_sdio1_i , + input logic in_spim_sdio2_i , + input logic in_spim_sdio3_i , + input logic in_spim_csn0_i , + input logic in_spim_csn1_i , + input logic in_spim_sck_i , + input logic in_sdio_clk_i , + input logic in_sdio_cmd_i , + input logic in_sdio_data0_i , + input logic in_sdio_data1_i , + input logic in_sdio_data2_i , + input logic in_sdio_data3_i , + input logic in_uart_rx_i , + input logic in_uart_tx_i , + input logic in_cam_pclk_i , + input logic in_cam_hsync_i , + input logic in_cam_data0_i , + input logic in_cam_data1_i , + input logic in_cam_data2_i , + input logic in_cam_data3_i , + input logic in_cam_data4_i , + input logic in_cam_data5_i , + input logic in_cam_data6_i , + input logic in_cam_data7_i , + input logic in_cam_vsync_i , + input logic in_i2c0_sda_i , + input logic in_i2c0_scl_i , + input logic in_i2s0_sck_i , + input logic in_i2s0_ws_i , + input logic in_i2s0_sdi_i , + input logic in_i2s1_sdi_i , // OUTPUT ENABLE - output logic oe_spim_sdio0_o , - output logic oe_spim_sdio1_o , - output logic oe_spim_sdio2_o , - output logic oe_spim_sdio3_o , - output logic oe_spim_csn0_o , - output logic oe_spim_csn1_o , - output logic oe_spim_sck_o , - output logic oe_sdio_clk_o , - output logic oe_sdio_cmd_o , - output logic oe_sdio_data0_o , - output logic oe_sdio_data1_o , - output logic oe_sdio_data2_o , - output logic oe_sdio_data3_o , - output logic oe_uart_rx_o , - output logic oe_uart_tx_o , - output logic oe_cam_pclk_o , - output logic oe_cam_hsync_o , - output logic oe_cam_data0_o , - output logic oe_cam_data1_o , - output logic oe_cam_data2_o , - output logic oe_cam_data3_o , - output logic oe_cam_data4_o , - output logic oe_cam_data5_o , - output logic oe_cam_data6_o , - output logic oe_cam_data7_o , - output logic oe_cam_vsync_o , - output logic oe_i2c0_sda_o , - output logic oe_i2c0_scl_o , - output logic oe_i2s0_sck_o , - output logic oe_i2s0_ws_o , - output logic oe_i2s0_sdi_o , + output logic oe_spim_sdio0_o , + output logic oe_spim_sdio1_o , + output logic oe_spim_sdio2_o , + output logic oe_spim_sdio3_o , + output logic oe_spim_csn0_o , + output logic oe_spim_csn1_o , + output logic oe_spim_sck_o , + output logic oe_sdio_clk_o , + output logic oe_sdio_cmd_o , + output logic oe_sdio_data0_o , + output logic oe_sdio_data1_o , + output logic oe_sdio_data2_o , + output logic oe_sdio_data3_o , + output logic oe_uart_rx_o , + output logic oe_uart_tx_o , + output logic oe_cam_pclk_o , + output logic oe_cam_hsync_o , + output logic oe_cam_data0_o , + output logic oe_cam_data1_o , + output logic oe_cam_data2_o , + output logic oe_cam_data3_o , + output logic oe_cam_data4_o , + output logic oe_cam_data5_o , + output logic oe_cam_data6_o , + output logic oe_cam_data7_o , + output logic oe_cam_vsync_o , + output logic oe_i2c0_sda_o , + output logic oe_i2c0_scl_o , + output logic oe_i2s0_sck_o , + output logic oe_i2s0_ws_o , + output logic oe_i2s0_sdi_o , output logic oe_i2s1_sdi_o ); @@ -416,6 +417,7 @@ module safe_domain .* ); +`ifndef PULP_FPGA_EMUL rstgen i_rstgen ( .clk_i ( ref_clk_i ), @@ -425,7 +427,28 @@ module safe_domain .init_no ( ) //not used ); + assign slow_clk_o = ref_clk_i; +`else // !`ifndef PULP_FPGA_EMUL + assign s_rstn_sync = s_rstn; + //Don't use the supplied clock directly for the FPGA target. On some boards + //the reference clock is a very fast (e.g. 200MHz) clock that cannot be used + //directly as the "slow_clk". Therefore we slow it down if a FPGA/board + //dependent module fpga_slow_clk_gen. Dividing the fast reference clock + //internally instead of doing so in the toplevel prevents unecessary clock + //division just to generate a faster clock once again in the SoC and + //Peripheral clock PLLs in soc_domain.sv. Instead all PLL use directly the + //board reference clock as input. + + fpga_slow_clk_gen i_slow_clk_gen + ( + .rst_ni(s_rstn_sync), + .ref_clk_i(ref_clk_i), + .slow_clk_o(slow_clk_o) + ); +`endif // !`ifndef PULP_FPGA_EMUL + + assign s_rstn = rst_ni; assign rst_no = s_rstn; diff --git a/rtl/pulp/soc_domain.sv b/rtl/pulp/soc_domain.sv index 099f40ab..3c756425 100644 --- a/rtl/pulp/soc_domain.sv +++ b/rtl/pulp/soc_domain.sv @@ -28,226 +28,227 @@ module soc_domain #( parameter EVNT_WIDTH = 8 )( - input logic ref_clk_i, - input logic test_clk_i, + input logic ref_clk_i, + input logic test_clk_i, + input logic slow_clk_i, - input logic rstn_glob_i, + input logic rstn_glob_i, `ifdef PULP_FPGA_EMUL - input logic zynq_soc_clk_i, - input logic zynq_cluster_clk_i, - input logic zynq_per_clk_i, + //input logic zynq_soc_clk_i, + //input logic zynq_cluster_clk_i, + //input logic zynq_per_clk_i, `endif - input logic dft_test_mode_i, - input logic dft_cg_enable_i, - - input logic mode_select_i, - - input logic bootsel_i, - - input logic jtag_tck_i, - input logic jtag_trst_ni, - input logic jtag_tms_i, - input logic jtag_tdi_i, - output logic jtag_tdo_o, - - output logic [`NB_CORES-1:0] dbg_irq_valid_o, - - input logic [31:0] gpio_in_i, - output logic [31:0] gpio_out_o, - output logic [31:0] gpio_dir_o, - output logic [191:0] gpio_cfg_o, - - output logic [127:0] pad_mux_o, - output logic [383:0] pad_cfg_o, - - output logic uart_tx_o, - input logic uart_rx_i, - - input logic cam_clk_i, - input logic [7:0] cam_data_i, - input logic cam_hsync_i, - input logic cam_vsync_i, - - output logic [3:0] timer_ch0_o, - output logic [3:0] timer_ch1_o, - output logic [3:0] timer_ch2_o, - output logic [3:0] timer_ch3_o, - - input logic i2c0_scl_i, - output logic i2c0_scl_o, - output logic i2c0_scl_oe_o, - input logic i2c0_sda_i, - output logic i2c0_sda_o, - output logic i2c0_sda_oe_o, - - input logic i2c1_scl_i, - output logic i2c1_scl_o, - output logic i2c1_scl_oe_o, - input logic i2c1_sda_i, - output logic i2c1_sda_o, - output logic i2c1_sda_oe_o, - - input logic i2s_slave_sd0_i, - input logic i2s_slave_sd1_i, - input logic i2s_slave_ws_i, - output logic i2s_slave_ws_o, - output logic i2s_slave_ws_oe, - input logic i2s_slave_sck_i, - output logic i2s_slave_sck_o, - output logic i2s_slave_sck_oe, - - output logic spi_master0_clk_o, - output logic spi_master0_csn0_o, - output logic spi_master0_csn1_o, - output logic spi_master0_oen0_o, - output logic spi_master0_oen1_o, - output logic spi_master0_oen2_o, - output logic spi_master0_oen3_o, - output logic spi_master0_sdo0_o, - output logic spi_master0_sdo1_o, - output logic spi_master0_sdo2_o, - output logic spi_master0_sdo3_o, - input logic spi_master0_sdi0_i, - input logic spi_master0_sdi1_i, - input logic spi_master0_sdi2_i, - input logic spi_master0_sdi3_i, - - output logic sdio_clk_o, - output logic sdio_cmd_o, - input logic sdio_cmd_i, - output logic sdio_cmd_oen_o, - output logic [3:0] sdio_data_o, - input logic [3:0] sdio_data_i, - output logic [3:0] sdio_data_oen_o - - , + input logic dft_test_mode_i, + input logic dft_cg_enable_i, + + input logic mode_select_i, + + input logic bootsel_i, + + input logic jtag_tck_i, + input logic jtag_trst_ni, + input logic jtag_tms_i, + input logic jtag_tdi_i, + output logic jtag_tdo_o, + + output logic [`NB_CORES-1:0] dbg_irq_valid_o, + + input logic [31:0] gpio_in_i, + output logic [31:0] gpio_out_o, + output logic [31:0] gpio_dir_o, + output logic [191:0] gpio_cfg_o, + + output logic [127:0] pad_mux_o, + output logic [383:0] pad_cfg_o, + + output logic uart_tx_o, + input logic uart_rx_i, + + input logic cam_clk_i, + input logic [7:0] cam_data_i, + input logic cam_hsync_i, + input logic cam_vsync_i, + + output logic [3:0] timer_ch0_o, + output logic [3:0] timer_ch1_o, + output logic [3:0] timer_ch2_o, + output logic [3:0] timer_ch3_o, + + input logic i2c0_scl_i, + output logic i2c0_scl_o, + output logic i2c0_scl_oe_o, + input logic i2c0_sda_i, + output logic i2c0_sda_o, + output logic i2c0_sda_oe_o, + + input logic i2c1_scl_i, + output logic i2c1_scl_o, + output logic i2c1_scl_oe_o, + input logic i2c1_sda_i, + output logic i2c1_sda_o, + output logic i2c1_sda_oe_o, + + input logic i2s_slave_sd0_i, + input logic i2s_slave_sd1_i, + input logic i2s_slave_ws_i, + output logic i2s_slave_ws_o, + output logic i2s_slave_ws_oe, + input logic i2s_slave_sck_i, + output logic i2s_slave_sck_o, + output logic i2s_slave_sck_oe, + + output logic spi_master0_clk_o, + output logic spi_master0_csn0_o, + output logic spi_master0_csn1_o, + output logic spi_master0_oen0_o, + output logic spi_master0_oen1_o, + output logic spi_master0_oen2_o, + output logic spi_master0_oen3_o, + output logic spi_master0_sdo0_o, + output logic spi_master0_sdo1_o, + output logic spi_master0_sdo2_o, + output logic spi_master0_sdo3_o, + input logic spi_master0_sdi0_i, + input logic spi_master0_sdi1_i, + input logic spi_master0_sdi2_i, + input logic spi_master0_sdi3_i, + + output logic sdio_clk_o, + output logic sdio_cmd_o, + input logic sdio_cmd_i, + output logic sdio_cmd_oen_o, + output logic [3:0] sdio_data_o, + input logic [3:0] sdio_data_i, + output logic [3:0] sdio_data_oen_o + + , // CLUSTER - output logic cluster_clk_o, - output logic cluster_rstn_o, - input logic cluster_busy_i, - output logic cluster_irq_o, - - output logic cluster_rtc_o, - output logic cluster_fetch_enable_o, - output logic [63:0] cluster_boot_addr_o, - output logic cluster_test_en_o, - output logic cluster_pow_o, - output logic cluster_byp_o, + output logic cluster_clk_o, + output logic cluster_rstn_o, + input logic cluster_busy_i, + output logic cluster_irq_o, + + output logic cluster_rtc_o, + output logic cluster_fetch_enable_o, + output logic [63:0] cluster_boot_addr_o, + output logic cluster_test_en_o, + output logic cluster_pow_o, + output logic cluster_byp_o, // EVENT BUS - output logic [BUFFER_WIDTH-1:0] cluster_events_wt_o, - input logic [BUFFER_WIDTH-1:0] cluster_events_rp_i, - output logic [EVNT_WIDTH-1:0] cluster_events_da_o, + output logic [BUFFER_WIDTH-1:0] cluster_events_wt_o, + input logic [BUFFER_WIDTH-1:0] cluster_events_rp_i, + output logic [EVNT_WIDTH-1:0] cluster_events_da_o, - output logic dma_pe_evt_ack_o, - input logic dma_pe_evt_valid_i, + output logic dma_pe_evt_ack_o, + input logic dma_pe_evt_valid_i, - output logic dma_pe_irq_ack_o, - input logic dma_pe_irq_valid_i, + output logic dma_pe_irq_ack_o, + input logic dma_pe_irq_valid_i, - output logic pf_evt_ack_o, - input logic pf_evt_valid_i, + output logic pf_evt_ack_o, + input logic pf_evt_valid_i, // AXI4 SLAVE - input logic [7:0] data_slave_aw_writetoken_i, - input logic [AXI_ADDR_WIDTH-1:0] data_slave_aw_addr_i, - input logic [2:0] data_slave_aw_prot_i, - input logic [3:0] data_slave_aw_region_i, - input logic [7:0] data_slave_aw_len_i, - input logic [2:0] data_slave_aw_size_i, - input logic [1:0] data_slave_aw_burst_i, - input logic data_slave_aw_lock_i, - input logic [3:0] data_slave_aw_cache_i, - input logic [3:0] data_slave_aw_qos_i, - input logic [AXI_ID_IN_WIDTH-1:0] data_slave_aw_id_i, - input logic [AXI_USER_WIDTH-1:0] data_slave_aw_user_i, - output logic [7:0] data_slave_aw_readpointer_o, - - input logic [7:0] data_slave_ar_writetoken_i, - input logic [AXI_ADDR_WIDTH-1:0] data_slave_ar_addr_i, - input logic [2:0] data_slave_ar_prot_i, - input logic [3:0] data_slave_ar_region_i, - input logic [7:0] data_slave_ar_len_i, - input logic [2:0] data_slave_ar_size_i, - input logic [1:0] data_slave_ar_burst_i, - input logic data_slave_ar_lock_i, - input logic [3:0] data_slave_ar_cache_i, - input logic [3:0] data_slave_ar_qos_i, - input logic [AXI_ID_IN_WIDTH-1:0] data_slave_ar_id_i, - input logic [AXI_USER_WIDTH-1:0] data_slave_ar_user_i, - output logic [7:0] data_slave_ar_readpointer_o, - - input logic [7:0] data_slave_w_writetoken_i, - input logic [AXI_DATA_IN_WIDTH-1:0] data_slave_w_data_i, - input logic [AXI_STRB_IN_WIDTH-1:0] data_slave_w_strb_i, - input logic [AXI_USER_WIDTH-1:0] data_slave_w_user_i, - input logic data_slave_w_last_i, - output logic [7:0] data_slave_w_readpointer_o, - - output logic [7:0] data_slave_r_writetoken_o, - output logic [AXI_DATA_IN_WIDTH-1:0] data_slave_r_data_o, - output logic [1:0] data_slave_r_resp_o, - output logic data_slave_r_last_o, - output logic [AXI_ID_IN_WIDTH-1:0] data_slave_r_id_o, - output logic [AXI_USER_WIDTH-1:0] data_slave_r_user_o, - input logic [7:0] data_slave_r_readpointer_i, - - output logic [7:0] data_slave_b_writetoken_o, - output logic [1:0] data_slave_b_resp_o, - output logic [AXI_ID_IN_WIDTH-1:0] data_slave_b_id_o, - output logic [AXI_USER_WIDTH-1:0] data_slave_b_user_o, - input logic [7:0] data_slave_b_readpointer_i, + input logic [7:0] data_slave_aw_writetoken_i, + input logic [AXI_ADDR_WIDTH-1:0] data_slave_aw_addr_i, + input logic [2:0] data_slave_aw_prot_i, + input logic [3:0] data_slave_aw_region_i, + input logic [7:0] data_slave_aw_len_i, + input logic [2:0] data_slave_aw_size_i, + input logic [1:0] data_slave_aw_burst_i, + input logic data_slave_aw_lock_i, + input logic [3:0] data_slave_aw_cache_i, + input logic [3:0] data_slave_aw_qos_i, + input logic [AXI_ID_IN_WIDTH-1:0] data_slave_aw_id_i, + input logic [AXI_USER_WIDTH-1:0] data_slave_aw_user_i, + output logic [7:0] data_slave_aw_readpointer_o, + + input logic [7:0] data_slave_ar_writetoken_i, + input logic [AXI_ADDR_WIDTH-1:0] data_slave_ar_addr_i, + input logic [2:0] data_slave_ar_prot_i, + input logic [3:0] data_slave_ar_region_i, + input logic [7:0] data_slave_ar_len_i, + input logic [2:0] data_slave_ar_size_i, + input logic [1:0] data_slave_ar_burst_i, + input logic data_slave_ar_lock_i, + input logic [3:0] data_slave_ar_cache_i, + input logic [3:0] data_slave_ar_qos_i, + input logic [AXI_ID_IN_WIDTH-1:0] data_slave_ar_id_i, + input logic [AXI_USER_WIDTH-1:0] data_slave_ar_user_i, + output logic [7:0] data_slave_ar_readpointer_o, + + input logic [7:0] data_slave_w_writetoken_i, + input logic [AXI_DATA_IN_WIDTH-1:0] data_slave_w_data_i, + input logic [AXI_STRB_IN_WIDTH-1:0] data_slave_w_strb_i, + input logic [AXI_USER_WIDTH-1:0] data_slave_w_user_i, + input logic data_slave_w_last_i, + output logic [7:0] data_slave_w_readpointer_o, + + output logic [7:0] data_slave_r_writetoken_o, + output logic [AXI_DATA_IN_WIDTH-1:0] data_slave_r_data_o, + output logic [1:0] data_slave_r_resp_o, + output logic data_slave_r_last_o, + output logic [AXI_ID_IN_WIDTH-1:0] data_slave_r_id_o, + output logic [AXI_USER_WIDTH-1:0] data_slave_r_user_o, + input logic [7:0] data_slave_r_readpointer_i, + + output logic [7:0] data_slave_b_writetoken_o, + output logic [1:0] data_slave_b_resp_o, + output logic [AXI_ID_IN_WIDTH-1:0] data_slave_b_id_o, + output logic [AXI_USER_WIDTH-1:0] data_slave_b_user_o, + input logic [7:0] data_slave_b_readpointer_i, // AXI4 MASTER - output logic [7:0] data_master_aw_writetoken_o, - output logic [AXI_ADDR_WIDTH-1:0] data_master_aw_addr_o, - output logic [2:0] data_master_aw_prot_o, - output logic [3:0] data_master_aw_region_o, - output logic [7:0] data_master_aw_len_o, - output logic [2:0] data_master_aw_size_o, - output logic [1:0] data_master_aw_burst_o, - output logic data_master_aw_lock_o, - output logic [3:0] data_master_aw_cache_o, - output logic [3:0] data_master_aw_qos_o, - output logic [AXI_ID_OUT_WIDTH-1:0] data_master_aw_id_o, - output logic [AXI_USER_WIDTH-1:0] data_master_aw_user_o, - input logic [7:0] data_master_aw_readpointer_i, - - output logic [7:0] data_master_ar_writetoken_o, - output logic [AXI_ADDR_WIDTH-1:0] data_master_ar_addr_o, - output logic [2:0] data_master_ar_prot_o, - output logic [3:0] data_master_ar_region_o, - output logic [7:0] data_master_ar_len_o, - output logic [2:0] data_master_ar_size_o, - output logic [1:0] data_master_ar_burst_o, - output logic data_master_ar_lock_o, - output logic [3:0] data_master_ar_cache_o, - output logic [3:0] data_master_ar_qos_o, - output logic [AXI_ID_OUT_WIDTH-1:0] data_master_ar_id_o, - output logic [AXI_USER_WIDTH-1:0] data_master_ar_user_o, - input logic [7:0] data_master_ar_readpointer_i, - - output logic [7:0] data_master_w_writetoken_o, - output logic [AXI_DATA_OUT_WIDTH-1:0] data_master_w_data_o, - output logic [AXI_STRB_OUT_WIDTH-1:0] data_master_w_strb_o, - output logic [AXI_USER_WIDTH-1:0] data_master_w_user_o, - output logic data_master_w_last_o, - input logic [7:0] data_master_w_readpointer_i, - - input logic [7:0] data_master_r_writetoken_i, - input logic [AXI_DATA_OUT_WIDTH-1:0] data_master_r_data_i, - input logic [1:0] data_master_r_resp_i, - input logic data_master_r_last_i, - input logic [AXI_ID_OUT_WIDTH-1:0] data_master_r_id_i, - input logic [AXI_USER_WIDTH-1:0] data_master_r_user_i, - output logic [7:0] data_master_r_readpointer_o, - - input logic [7:0] data_master_b_writetoken_i, - input logic [1:0] data_master_b_resp_i, - input logic [AXI_ID_OUT_WIDTH-1:0] data_master_b_id_i, - input logic [AXI_USER_WIDTH-1:0] data_master_b_user_i, - output logic [7:0] data_master_b_readpointer_o + output logic [7:0] data_master_aw_writetoken_o, + output logic [AXI_ADDR_WIDTH-1:0] data_master_aw_addr_o, + output logic [2:0] data_master_aw_prot_o, + output logic [3:0] data_master_aw_region_o, + output logic [7:0] data_master_aw_len_o, + output logic [2:0] data_master_aw_size_o, + output logic [1:0] data_master_aw_burst_o, + output logic data_master_aw_lock_o, + output logic [3:0] data_master_aw_cache_o, + output logic [3:0] data_master_aw_qos_o, + output logic [AXI_ID_OUT_WIDTH-1:0] data_master_aw_id_o, + output logic [AXI_USER_WIDTH-1:0] data_master_aw_user_o, + input logic [7:0] data_master_aw_readpointer_i, + + output logic [7:0] data_master_ar_writetoken_o, + output logic [AXI_ADDR_WIDTH-1:0] data_master_ar_addr_o, + output logic [2:0] data_master_ar_prot_o, + output logic [3:0] data_master_ar_region_o, + output logic [7:0] data_master_ar_len_o, + output logic [2:0] data_master_ar_size_o, + output logic [1:0] data_master_ar_burst_o, + output logic data_master_ar_lock_o, + output logic [3:0] data_master_ar_cache_o, + output logic [3:0] data_master_ar_qos_o, + output logic [AXI_ID_OUT_WIDTH-1:0] data_master_ar_id_o, + output logic [AXI_USER_WIDTH-1:0] data_master_ar_user_o, + input logic [7:0] data_master_ar_readpointer_i, + + output logic [7:0] data_master_w_writetoken_o, + output logic [AXI_DATA_OUT_WIDTH-1:0] data_master_w_data_o, + output logic [AXI_STRB_OUT_WIDTH-1:0] data_master_w_strb_o, + output logic [AXI_USER_WIDTH-1:0] data_master_w_user_o, + output logic data_master_w_last_o, + input logic [7:0] data_master_w_readpointer_i, + + input logic [7:0] data_master_r_writetoken_i, + input logic [AXI_DATA_OUT_WIDTH-1:0] data_master_r_data_i, + input logic [1:0] data_master_r_resp_i, + input logic data_master_r_last_i, + input logic [AXI_ID_OUT_WIDTH-1:0] data_master_r_id_i, + input logic [AXI_USER_WIDTH-1:0] data_master_r_user_i, + output logic [7:0] data_master_r_readpointer_o, + + input logic [7:0] data_master_b_writetoken_i, + input logic [1:0] data_master_b_resp_i, + input logic [AXI_ID_OUT_WIDTH-1:0] data_master_b_id_i, + input logic [AXI_USER_WIDTH-1:0] data_master_b_user_i, + output logic [7:0] data_master_b_readpointer_o ); pulp_soc diff --git a/rtl/pulpemu/pulpemu.sv b/rtl/pulpemu/pulpemu.sv index f589f2f9..37e8bcf0 100644 --- a/rtl/pulpemu/pulpemu.sv +++ b/rtl/pulpemu/pulpemu.sv @@ -89,44 +89,44 @@ module pulpemu ( .I(clk_125_p), .IB(clk_125_n), - .O(clk_125) // 125 MHz clock + .O(ref_clk) // before clk_125 ); - logic clk_125_buf; - BUFGCE i_clk_buf (.I(clk_125), .CE(1'b1), .O(clk_125_buf)); + // logic clk_125_buf; + //BUFGCE i_clk_buf (.I(clk_125), .CE(1'b1), .O(clk_125_buf)); // add clock generation for pulp chip, replaces zynq_wrapper - xilinx_clk_mngr clk_wiz_0 - ( - .clk_out1(pulp_ref_clk), // 256*32768 = 8.3886 MHz - .clk_out2(pulp_soc_clk), // 50 Mhz - .clk_out3(pulp_per_clk), // 50MHz - .clk_out4(pulp_cluster_clk), //50MHz - .resetn(~cpu_reset), - .locked( ), - .clk_in1(clk_125_buf) // 125 MHz - ); - - pulpemu_ref_clk_div - #( - .DIVISOR ( 256 ) - ) - ref_clk_div ( - .clk_i ( pulp_ref_clk ), // FPGA inner clock, 8.388608 MHz - .rstn_i ( ~cpu_reset ), // FPGA inner reset - .ref_clk_o ( ref_clk ) // REF clock out - ); + // xilinx_clk_mngr clk_wiz_0 + //( + //.clk_out1(pulp_ref_clk), // 256*32768 = 8.3886 MHz + //.clk_out2(pulp_soc_clk), // 50 Mhz + //.clk_out3(pulp_per_clk), // 50MHz + //.clk_out4(pulp_cluster_clk), //50MHz + //.resetn(~cpu_reset), + //.locked( ), + //.clk_in1(clk_125_buf) // 125 MHz + //); + + //pulpemu_ref_clk_div + // #( + // .DIVISOR ( 256 ) + //) + //ref_clk_div ( + // .clk_i ( pulp_ref_clk ), // FPGA inner clock, 8.388608 MHz + // .rstn_i ( ~cpu_reset ), // FPGA inner reset + // .ref_clk_o ( ref_clk ) // REF clock out + // ); // 1 socond blink LED - pulpemu_ref_clk_div - #( - .DIVISOR ( 32768 ) - ) - led_clk_div ( - .clk_i ( ref_clk ), - .rstn_i ( ~cpu_reset ), - .ref_clk_o ( LED ) - ); +// pulpemu_ref_clk_div + // #( + // .DIVISOR ( 32768 ) + // ) + //led_clk_div ( + // .clk_i ( ref_clk ), + // .rstn_i ( ~cpu_reset ), + // .ref_clk_o ( LED ) + // ); // ██████╗ ██╗ ██╗██╗ ██████╗ ██████╗██╗ ██╗██╗██████╗ @@ -142,10 +142,10 @@ module pulpemu .USE_HWPE(USE_HWPE) ) pulp_chip_i ( - .zynq_clk_i ( ref_clk ), // FPGA inner clock, 32768 Hz - .zynq_soc_clk_i ( pulp_soc_clk ), // FPGA inner clock, 50 MHz - .zynq_cluster_clk_i ( pulp_cluster_clk ), // FPGA inner clock, 50 MHz - .zynq_per_clk_i ( pulp_per_clk ), // FPGA inner clock, 50 MHz + //.zynq_clk_i ( ref_clk ), // FPGA inner clock, 32768 Hz + //.zynq_soc_clk_i ( pulp_soc_clk ), // FPGA inner clock, 50 MHz + //.zynq_cluster_clk_i ( pulp_cluster_clk ), // FPGA inner clock, 50 MHz + //.zynq_per_clk_i ( pulp_per_clk ), // FPGA inner clock, 50 MHz .pad_spim_sdio0(FMC_qspi_sdio0), .pad_spim_sdio1(FMC_qspi_sdio1), @@ -189,11 +189,11 @@ module pulpemu .pad_jtag_tdi(FMC_jtag_tdi), .pad_jtag_tdo(FMC_jtag_tdo), .pad_jtag_tms(FMC_jtag_tms), - .pad_jtag_trst(FMC_jtag_trst), + .pad_jtag_trst(1'b1), //FMC_jtag_trst - .pad_xtal_in(), // USE generated ref_clk - .pad_reset_n(FMC_reset_n), - .pad_bootsel(FMC_bootmode) // Boot mode = 0; boot from flash; Boot mode = 1; boot from jtag + .pad_xtal_in(ref_clk), // USE generated ref_clk + .pad_reset_n(cpu_reset), //FMC_reset_n + .pad_bootsel(FMC_bootmode) // Boot mode = 0; boot from flash; Boot mode = 1; boot from jtag before FMC_bootmode ); endmodule // pulpemu diff --git a/rtl/pulpemu/src_files.yml b/rtl/pulpemu/src_files.yml index 797b5906..fc1254c4 100644 --- a/rtl/pulpemu/src_files.yml +++ b/rtl/pulpemu/src_files.yml @@ -7,6 +7,8 @@ pulpemu: xilinx, ] files: [ + fpga_clk_gen.sv, + fpga_slow_clk_gen.sv, pad_functional_xilinx.sv, fpga_bootrom.sv, fpga_interleaved_ram.sv, From fa5bcc4d570e0924dba0b72187556ddace3d579c Mon Sep 17 00:00:00 2001 From: Angelo Garofalo Date: Tue, 19 Nov 2019 14:32:27 +0100 Subject: [PATCH 26/46] add parameter for HPWE --- rtl/pulp/cluster_domain.sv | 2 ++ 1 file changed, 2 insertions(+) diff --git a/rtl/pulp/cluster_domain.sv b/rtl/pulp/cluster_domain.sv index 587152b4..f8e6d96c 100644 --- a/rtl/pulp/cluster_domain.sv +++ b/rtl/pulp/cluster_domain.sv @@ -26,6 +26,7 @@ module cluster_domain #( //CLUSTER PARAMETERS parameter NB_CORES = `NB_CORES, + parameter HWPE_PRESENT = 0, parameter NB_HWPE_PORTS = 4, parameter NB_DMAS = 4, @@ -253,6 +254,7 @@ module cluster_domain `ifndef USE_CLUSTER_NETLIST #( .NB_CORES ( NB_CORES ), + .HWPE_PRESENT ( HWPE_PRESENT ), .NB_HWPE_PORTS ( NB_HWPE_PORTS ), .NB_DMAS ( NB_DMAS ), .TCDM_SIZE ( TCDM_SIZE ), From 527f75d28065a48ce219b02ae78a7b2fc75a9e04 Mon Sep 17 00:00:00 2001 From: Angelo Garofalo Date: Tue, 19 Nov 2019 14:33:23 +0100 Subject: [PATCH 27/46] set HWPE and FPU in Soc to zero --- rtl/pulp/pulp.sv | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rtl/pulp/pulp.sv b/rtl/pulp/pulp.sv index 731b83f0..6ecb9874 100644 --- a/rtl/pulp/pulp.sv +++ b/rtl/pulp/pulp.sv @@ -13,8 +13,8 @@ module pulp #( parameter CORE_TYPE = 0, // 0 for RISCY, 1 for IBEX RV32IMC (formerly ZERORISCY), 2 for IBEX RV32EC (formerly MICRORISCY) - parameter USE_FPU = 1, - parameter USE_HWPE = 1 + parameter USE_FPU = 0, + parameter USE_HWPE = 0 ) ( `ifdef PULP_FPGA_EMUL From 486fd7acae72e9f4096c7315056be3512d89186c Mon Sep 17 00:00:00 2001 From: Angelo Garofalo Date: Tue, 19 Nov 2019 14:33:59 +0100 Subject: [PATCH 28/46] add PU and PD --- rtl/pulpemu/pad_functional_xilinx.sv | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rtl/pulpemu/pad_functional_xilinx.sv b/rtl/pulpemu/pad_functional_xilinx.sv index cbf1b42c..0d69b35f 100644 --- a/rtl/pulpemu/pad_functional_xilinx.sv +++ b/rtl/pulpemu/pad_functional_xilinx.sv @@ -17,7 +17,8 @@ module pad_functional_pd input logic PEN, inout logic PAD ); - + + (* PULLDOWN = "YES" *) IOBUF iobuf_i ( .T ( OEN ), .I ( I ), @@ -36,6 +37,7 @@ module pad_functional_pu inout logic PAD ); + (* PULLUP = "YES" *) IOBUF iobuf_i ( .T ( OEN ), .I ( I ), From b05a543a376559d3ec0376f13a3f404d465657f3 Mon Sep 17 00:00:00 2001 From: Angelo Garofalo Date: Tue, 19 Nov 2019 14:34:41 +0100 Subject: [PATCH 29/46] align top to pulpissimo --- rtl/pulpemu/pulpemu.sv | 327 ++++++++++++++++++----------------------- 1 file changed, 140 insertions(+), 187 deletions(-) diff --git a/rtl/pulpemu/pulpemu.sv b/rtl/pulpemu/pulpemu.sv index 37e8bcf0..a8917dcc 100644 --- a/rtl/pulpemu/pulpemu.sv +++ b/rtl/pulpemu/pulpemu.sv @@ -1,199 +1,152 @@ -/* - * Copyright (C) 2013-2017 ETH Zurich, University of Bologna - * All rights reserved. - * - * This code is under development and not yet released to the public. - * Until it is released, the code is under the copyright of ETH Zurich and - * the University of Bologna, and may contain confidential and/or unpublished - * work. Any reuse/redistribution is strictly forbidden without written - * permission from ETH Zurich. - * - * Bug fixes and contributions will eventually be released under the - * SolderPad open hardware license in the context of the PULP platform - * (http://www.pulp-platform.org), under the copyright of ETH Zurich and the - * University of Bologna. - */ - -`include "pulp_soc_defines.sv" +//----------------------------------------------------------------------------- +// Title : PULPissimo Verilog Wrapper +//----------------------------------------------------------------------------- +// File : xilinx_pulpissimo.v +// Author : Manuel Eggimann +// Created : 21.05.2019 +//----------------------------------------------------------------------------- +// Description : +// Verilog Wrapper of PULPissimo to use the module within Xilinx IP integrator. +//----------------------------------------------------------------------------- +// Copyright (C) 2013-2019 ETH Zurich, University of Bologna +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. +//----------------------------------------------------------------------------- module pulpemu - #( - parameter CORE_TYPE = 0, // 0 for RISCY, 1 for IBEX RV32IMC (formerly ZERORISCY), 2 for IBEX RV32EC (formerly MICRORISCY) - parameter USE_FPU = 1, - parameter USE_HWPE = 0 -) ( - input clk_125_n, - input clk_125_p, - input cpu_reset, - // LED for VERIFY - output LED, - // FMC pins - inout FMC_qspi_sdio0, - inout FMC_qspi_sdio1, - inout FMC_qspi_sdio2, - inout FMC_qspi_sdio3, - inout FMC_qspi_csn0, - inout FMC_qspi_csn1, - inout FMC_qspi_sck, - inout FMC_sdio_data0, - inout FMC_sdio_data1, - inout FMC_sdio_data2, - inout FMC_sdio_data3, - inout FMC_sdio_cmd, - inout FMC_sdio_sck, - inout FMC_i2c0_sda, - inout FMC_i2c0_scl, - inout FMC_uart_rx, - inout FMC_uart_tx, - inout FMC_i2s0_sck, - inout FMC_i2s0_ws, - inout FMC_i2s0_sdi, - inout FMC_i2s1_sdi, - inout FMC_cam_pclk, - inout FMC_cam_hsync, - inout FMC_cam_data0, - inout FMC_cam_data1, - inout FMC_cam_data2, - inout FMC_cam_data3, - inout FMC_cam_data4, - inout FMC_cam_data5, - inout FMC_cam_data6, - inout FMC_cam_data7, - inout FMC_cam_vsync, - inout FMC_jtag_tck, - inout FMC_jtag_tdi, - inout FMC_jtag_tdo, - inout FMC_jtag_tms, - inout FMC_jtag_trst, - inout FMC_bootmode, - inout FMC_reset_n - ); - - // pulpemu top signals - logic pulp_ref_clk; - logic pulp_soc_clk; - logic pulp_per_clk; - logic pulp_cluster_clk; - - // reference 32768 Hz clock - wire ref_clk; + input wire ref_clk_p, + input wire ref_clk_n, + + inout wire pad_uart_rx, + inout wire pad_uart_tx, + inout wire pad_uart_rts, //Mapped to spim_csn0 + inout wire pad_uart_cts, //Mapped to spim_sck + + inout wire led0_o, //Mapped to spim_csn1 + inout wire led1_o, //Mapped to cam_pclk + inout wire led2_o, //Mapped to cam_hsync + inout wire led3_o, //Mapped to cam_data0 + + inout wire switch0_i, //Mapped to cam_data1 + inout wire switch1_i, //Mapped to cam_data2 + inout wire switch2_i, //Mapped to cam_data7 + inout wire switch3_i, //Mapped to cam_vsync + + inout wire btn0_i, //Mapped to cam_data3 + inout wire btn1_i, //Mapped to cam_data4 + inout wire btn2_i, //Mapped to cam_data5 + inout wire btn3_i, //Mapped to cam_data6 + + inout wire pad_i2c0_sda, + inout wire pad_i2c0_scl, + + inout wire pad_pmod0_4, //Mapped to spim_sdio0 + inout wire pad_pmod0_5, //Mapped to spim_sdio1 + inout wire pad_pmod0_6, //Mapped to spim_sdio2 + inout wire pad_pmod0_7, //Mapped to spim_sdio3 + + inout wire pad_pmod1_0, //Mapped to sdio_data0 + inout wire pad_pmod1_1, //Mapped to sdio_data1 + inout wire pad_pmod1_2, //Mapped to sdio_data2 + inout wire pad_pmod1_3, //Mapped to sdio_data3 + inout wire pad_pmod1_4, //Mapped to i2s0_sck + inout wire pad_pmod1_5, //Mapped to i2s0_ws + inout wire pad_pmod1_6, //Mapped to i2s0_sdi + inout wire pad_pmod1_7, //Mapped to i2s1_sdi + + inout wire pad_hdmi_scl, //Mapped to sdio_clk + inout wire pad_hdmi_sda, //Mapped to sdio_cmd + + + input wire pad_reset, + + input wire pad_jtag_tck, + input wire pad_jtag_tdi, + output wire pad_jtag_tdo, + input wire pad_jtag_tms + ); + + localparam CORE_TYPE = 0; // 0 for RISCY, 1 for ZERORISCY, 2 for MICRORISCY + localparam USE_FPU = 0; + localparam USE_HWPE = 0; + + wire ref_clk; + //Differential to single ended clock conversion IBUFGDS #( .IOSTANDARD("LVDS"), - .DIFF_TERM(0), - .IBUF_LOW_PWR(0)) + .DIFF_TERM("FALSE"), + .IBUF_LOW_PWR("FALSE")) i_sysclk_iobuf ( - .I(clk_125_p), - .IB(clk_125_n), - .O(ref_clk) // before clk_125 + .I(ref_clk_p), + .IB(ref_clk_n), + .O(ref_clk) ); - // logic clk_125_buf; - //BUFGCE i_clk_buf (.I(clk_125), .CE(1'b1), .O(clk_125_buf)); - - // add clock generation for pulp chip, replaces zynq_wrapper - // xilinx_clk_mngr clk_wiz_0 - //( - //.clk_out1(pulp_ref_clk), // 256*32768 = 8.3886 MHz - //.clk_out2(pulp_soc_clk), // 50 Mhz - //.clk_out3(pulp_per_clk), // 50MHz - //.clk_out4(pulp_cluster_clk), //50MHz - //.resetn(~cpu_reset), - //.locked( ), - //.clk_in1(clk_125_buf) // 125 MHz - //); - - //pulpemu_ref_clk_div - // #( - // .DIVISOR ( 256 ) - //) - //ref_clk_div ( - // .clk_i ( pulp_ref_clk ), // FPGA inner clock, 8.388608 MHz - // .rstn_i ( ~cpu_reset ), // FPGA inner reset - // .ref_clk_o ( ref_clk ) // REF clock out - // ); - - // 1 socond blink LED -// pulpemu_ref_clk_div - // #( - // .DIVISOR ( 32768 ) - // ) - //led_clk_div ( - // .clk_i ( ref_clk ), - // .rstn_i ( ~cpu_reset ), - // .ref_clk_o ( LED ) - // ); - - - // ██████╗ ██╗ ██╗██╗ ██████╗ ██████╗██╗ ██╗██╗██████╗ - // ██╔══██╗██║ ██║██║ ██╔══██╗ ██╔════╝██║ ██║██║██╔══██╗ - // ██████╔╝██║ ██║██║ ██████╔╝ ██║ ███████║██║██████╔╝ - // ██╔═══╝ ██║ ██║██║ ██╔═══╝ ██║ ██╔══██║██║██╔═══╝ - // ██║ ╚██████╔╝███████╗██║███████╗╚██████╗██║ ██║██║██║ - // ╚═╝ ╚═════╝ ╚══════╝╚═╝╚══════╝ ╚═════╝╚═╝ ╚═╝╚═╝╚═╝ - - pulp - #(.CORE_TYPE(CORE_TYPE), - .USE_FPU(USE_FPU), - .USE_HWPE(USE_HWPE) - ) pulp_chip_i - ( - //.zynq_clk_i ( ref_clk ), // FPGA inner clock, 32768 Hz - //.zynq_soc_clk_i ( pulp_soc_clk ), // FPGA inner clock, 50 MHz - //.zynq_cluster_clk_i ( pulp_cluster_clk ), // FPGA inner clock, 50 MHz - //.zynq_per_clk_i ( pulp_per_clk ), // FPGA inner clock, 50 MHz - - .pad_spim_sdio0(FMC_qspi_sdio0), - .pad_spim_sdio1(FMC_qspi_sdio1), - .pad_spim_sdio2(FMC_qspi_sdio2), - .pad_spim_sdio3(FMC_qspi_sdio3), - .pad_spim_csn0(FMC_qspi_csn0), - .pad_spim_csn1(FMC_qspi_csn1), - .pad_spim_sck(FMC_qspi_sck), - - .pad_uart_rx(FMC_uart_rx), - .pad_uart_tx(FMC_uart_tx), - - .pad_cam_pclk(FMC_cam_pclk), - .pad_cam_hsync(FMC_cam_hsync), - .pad_cam_data0(FMC_cam_data0), - .pad_cam_data1(FMC_cam_data1), - .pad_cam_data2(FMC_cam_data2), - .pad_cam_data3(FMC_cam_data3), - .pad_cam_data4(FMC_cam_data4), - .pad_cam_data5(FMC_cam_data5), - .pad_cam_data6(FMC_cam_data6), - .pad_cam_data7(FMC_cam_data7), - .pad_cam_vsync(FMC_cam_vsync), - - .pad_sdio_clk(FMC_sdio_sck), - .pad_sdio_cmd(FMC_sdio_cmd), - .pad_sdio_data0(FMC_sdio_data0), - .pad_sdio_data1(FMC_sdio_data1), - .pad_sdio_data2(FMC_sdio_data2), - .pad_sdio_data3(FMC_sdio_data3), - - .pad_i2c0_sda(FMC_i2c0_sda), - .pad_i2c0_scl(FMC_i2c0_scl), - - .pad_i2s0_sck(FMC_i2s0_sck), - .pad_i2s0_ws(FMC_i2s0_ws), - .pad_i2s0_sdi(FMC_i2s0_sdi), - .pad_i2s1_sdi(FMC_i2s1_sdi), - - .pad_jtag_tck(FMC_jtag_tck), - .pad_jtag_tdi(FMC_jtag_tdi), - .pad_jtag_tdo(FMC_jtag_tdo), - .pad_jtag_tms(FMC_jtag_tms), - .pad_jtag_trst(1'b1), //FMC_jtag_trst - - .pad_xtal_in(ref_clk), // USE generated ref_clk - .pad_reset_n(cpu_reset), //FMC_reset_n - .pad_bootsel(FMC_bootmode) // Boot mode = 0; boot from flash; Boot mode = 1; boot from jtag before FMC_bootmode - ); - -endmodule // pulpemu + pulp + #(.CORE_TYPE(CORE_TYPE), + .USE_FPU(USE_FPU), + .USE_HWPE(USE_HWPE) + ) i_pulp + ( + .pad_spim_sdio0(pad_pmod0_4), + .pad_spim_sdio1(pad_pmod0_5), + .pad_spim_sdio2(pad_pmod0_6), + .pad_spim_sdio3(pad_pmod0_7), + .pad_spim_csn0(pad_uart_rts), + .pad_spim_csn1(led0_o), + .pad_spim_sck(pad_uart_cts), + + .pad_uart_rx(pad_uart_rx), + .pad_uart_tx(pad_uart_tx), + + .pad_cam_pclk(led1_o), + .pad_cam_hsync(led2_o), + .pad_cam_data0(led3_o), + .pad_cam_data1(switch0_i), + .pad_cam_data2(switch1_i), + .pad_cam_data3(btn0_i), + .pad_cam_data4(btn1_i), + .pad_cam_data5(btn2_i), + .pad_cam_data6(btn3_i), + .pad_cam_data7(switch2_i), + .pad_cam_vsync(switch3_i), + + .pad_sdio_clk(pad_hdmi_scl), + .pad_sdio_cmd(pad_hdmi_sda), + .pad_sdio_data0(pad_pmod1_0), + .pad_sdio_data1(pad_pmod1_1), + .pad_sdio_data2(pad_pmod1_2), + .pad_sdio_data3(pad_pmod1_3), + + .pad_i2c0_sda(pad_i2c0_sda), + .pad_i2c0_scl(pad_i2c0_scl), + + .pad_i2s0_sck(pad_pmod1_4), + .pad_i2s0_ws(pad_pmod1_5), + .pad_i2s0_sdi(pad_pmod1_6), + .pad_i2s1_sdi(pad_pmod1_7), + + .pad_reset_n(~pad_reset), + + .pad_jtag_tck(pad_jtag_tck), + .pad_jtag_tdi(pad_jtag_tdi), + .pad_jtag_tdo(pad_jtag_tdo), + .pad_jtag_tms(pad_jtag_tms), + .pad_jtag_trst(1'b1), + + .pad_xtal_in(ref_clk), + .pad_bootsel() + ); + +endmodule From c35c60535464ca52e08c094201287a830a3e3560 Mon Sep 17 00:00:00 2001 From: Angelo Garofalo Date: Tue, 19 Nov 2019 14:36:03 +0100 Subject: [PATCH 30/46] add xilinx clk gating to src --- rtl/pulpemu/src_files.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/rtl/pulpemu/src_files.yml b/rtl/pulpemu/src_files.yml index fc1254c4..8d435759 100644 --- a/rtl/pulpemu/src_files.yml +++ b/rtl/pulpemu/src_files.yml @@ -15,4 +15,5 @@ pulpemu: fpga_private_ram.sv, pulpemu.sv, pulpemu_ref_clk_div.sv, + pulp_clock_gating_xilinx.sv ] From 61e9ea8f785d52d163a91c24ef78e7943c5af609 Mon Sep 17 00:00:00 2001 From: Angelo Garofalo Date: Tue, 19 Nov 2019 14:38:13 +0100 Subject: [PATCH 31/46] checkout right branch for fpga flow --- update-fpga | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/update-fpga b/update-fpga index bf43e8bb..e039139c 100755 --- a/update-fpga +++ b/update-fpga @@ -12,7 +12,7 @@ if [ ! -e fpga ]; then echo -e "${BOLD}${BLUE}Cloning fpga${NC}${STD}" else pushd fpga > /dev/null - git checkout master + git checkout zcu102_align_pulpissimo git pull echo -e "${BOLD}${BLUE}Updating fpga${NC}${STD}" fi From 99ab3d71ddd3ae830938f537e8085e7d60e81fcc Mon Sep 17 00:00:00 2001 From: Angelo Garofalo Date: Thu, 5 Dec 2019 12:02:35 +0100 Subject: [PATCH 32/46] add xilinx clk and slow clk gen --- rtl/pulpemu/fpga_clk_gen.sv | 85 ++++++++++++++++++++++++++++++++ rtl/pulpemu/fpga_slow_clk_gen.sv | 82 ++++++++++++++++++++++++++++++ 2 files changed, 167 insertions(+) create mode 100644 rtl/pulpemu/fpga_clk_gen.sv create mode 100644 rtl/pulpemu/fpga_slow_clk_gen.sv diff --git a/rtl/pulpemu/fpga_clk_gen.sv b/rtl/pulpemu/fpga_clk_gen.sv new file mode 100644 index 00000000..1cca5b60 --- /dev/null +++ b/rtl/pulpemu/fpga_clk_gen.sv @@ -0,0 +1,85 @@ +//----------------------------------------------------------------------------- +// Title : FPGA CLK Gen for PULPissimo +// ----------------------------------------------------------------------------- +// File : fpga_clk_gen.sv Author : Manuel Eggimann +// Created : 17.05.2019 +// ----------------------------------------------------------------------------- +// Description : Instantiates Xilinx clocking wizard IP to generate 2 output +// clocks. Currently, the clock is not dynamicly reconfigurable and all +// configuration requests are acknowledged without any effect. +// ----------------------------------------------------------------------------- +// Copyright (C) 2013-2019 ETH Zurich, University of Bologna Copyright and +// related rights are licensed under the Solderpad Hardware License, Version +// 0.51 (the "License"); you may not use this file except in compliance with the +// License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law or +// agreed to in writing, software, hardware and materials distributed under this +// License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS +// OF ANY KIND, either express or implied. See the License for the specific +// language governing permissions and limitations under the License. +// ----------------------------------------------------------------------------- + + +module fpga_clk_gen ( + input logic ref_clk_i, + input logic rstn_glob_i, + input logic test_mode_i, + input logic shift_enable_i, + output logic soc_clk_o, + output logic per_clk_o, + output logic cluster_clk_o, + output logic soc_cfg_lock_o, + input logic soc_cfg_req_i, + output logic soc_cfg_ack_o, + input logic [1:0] soc_cfg_add_i, + input logic [31:0] soc_cfg_data_i, + output logic [31:0] soc_cfg_r_data_o, + input logic soc_cfg_wrn_i, + output logic per_cfg_lock_o, + input logic per_cfg_req_i, + output logic per_cfg_ack_o, + input logic [1:0] per_cfg_add_i, + input logic [31:0] per_cfg_data_i, + output logic [31:0] per_cfg_r_data_o, + input logic per_cfg_wrn_i, + output logic cluster_cfg_lock_o, + input logic cluster_cfg_req_i, + output logic cluster_cfg_ack_o, + input logic [1:0] cluster_cfg_add_i, + input logic [31:0] cluster_cfg_data_i, + output logic [31:0] cluster_cfg_r_data_o, + input logic cluster_cfg_wrn_i + ); + + logic s_locked; + logic s_clk; + + xilinx_clk_mngr i_clk_manager + ( + .resetn(rstn_glob_i), + .clk_in1(ref_clk_i), + .clk_out1(s_clk), + .clk_out2(per_clk_o), + //.clk_out3(cluster_clk_o), + .locked(s_locked) + ); + + assign soc_clk_o = s_clk; + assign cluster_clk_o = s_clk; + + assign soc_cfg_lock_o = s_locked; + assign per_cfg_lock_o = s_locked; + assign cluster_cfg_lock_o = s_locked; + + + assign soc_cfg_ack_o = 1'b1; //Always acknowledge without doing anything for now + assign per_cfg_ack_o = 1'b1; + assign cluster_cfg_ack_o = 1'b1; + + + assign soc_cfg_r_data_o = 32'hdeadda7a; + assign per_cfg_r_data_o = 32'hdeadda7a; + assign cluster_cfg_r_data_o = 32'hdeadda7a; + + +endmodule : fpga_clk_gen diff --git a/rtl/pulpemu/fpga_slow_clk_gen.sv b/rtl/pulpemu/fpga_slow_clk_gen.sv new file mode 100644 index 00000000..f3db58f4 --- /dev/null +++ b/rtl/pulpemu/fpga_slow_clk_gen.sv @@ -0,0 +1,82 @@ +//----------------------------------------------------------------------------- +// Title : FPGA slow clk generator for PULPissimo +//----------------------------------------------------------------------------- +// File : fpga_slow_clk_gen.sv +// Author : Manuel Eggimann +// Created : 20.05.2019 +//----------------------------------------------------------------------------- +// Description : Instantiates Xilinx Clocking Wizard IP to generate the slow_clk +// signal since for certain boards the available clock sources are to fast to +// use directly. +//----------------------------------------------------------------------------- +// Copyright (C) 2013-2019 ETH Zurich, University of Bologna +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. +//----------------------------------------------------------------------------- + + +module fpga_slow_clk_gen + #( + parameter CLK_DIV_VALUE = 256 //The xilinx_slow_clk_mngr is supposed to + //generate an 8.3886MHz clock. We need to divide it + //by 256 to arrive to a 32.768kHz clock + ) + (input logic ref_clk_i, + input logic rst_ni, + output logic slow_clk_o + ); + + + + localparam COUNTER_WIDTH = $clog2(CLK_DIV_VALUE); + + + //Create clock divider using BUFGCE cells as the PLL/MMCM cannot generate clocks + //slower than 4.69 MHz and we need 32.768kHz + + logic [COUNTER_WIDTH-1:0] clk_counter_d, clk_counter_q; + logic clock_gate_en; + + logic intermmediate_clock; + + xilinx_slow_clk_mngr i_slow_clk_mngr + ( + .resetn(rst_ni), + .clk_in1(ref_clk_i), + .clk_out1(intermmediate_clock) + ); + + + + always_comb begin + if (clk_counter_q == CLK_DIV_VALUE-1) begin + clk_counter_d = '0; + clock_gate_en = 1'b1; + end else begin + clk_counter_d = clk_counter_q + 1; + clock_gate_en = 1'b0; + end + end + + always_ff @(posedge intermmediate_clock, negedge rst_ni) begin + if (!rst_ni) begin + clk_counter_q <= '0; + end else begin + clk_counter_q <= clk_counter_d; + end + end + + BUFGCE i_clock_gate + ( + .I(intermmediate_clock), + .CE(clock_gate_en), + .O(slow_clk_o) + ); + +endmodule : fpga_slow_clk_gen From 2192e93426ef9df4fd147c25837e20cee16b4be3 Mon Sep 17 00:00:00 2001 From: Angelo Garofalo Date: Thu, 5 Dec 2019 12:03:25 +0100 Subject: [PATCH 33/46] add xilinx clk gating IP --- rtl/pulpemu/pulp_clock_gating_xilinx.sv | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 rtl/pulpemu/pulp_clock_gating_xilinx.sv diff --git a/rtl/pulpemu/pulp_clock_gating_xilinx.sv b/rtl/pulpemu/pulp_clock_gating_xilinx.sv new file mode 100644 index 00000000..1e2db2d1 --- /dev/null +++ b/rtl/pulpemu/pulp_clock_gating_xilinx.sv @@ -0,0 +1,21 @@ +// Copyright 2018 ETH Zurich and University of Bologna. +// Copyright and related rights are licensed under the Solderpad Hardware +// License, Version 0.51 (the "License"); you may not use this file except in +// compliance with the License. You may obtain a copy of the License at +// http://solderpad.org/licenses/SHL-0.51. Unless required by applicable law +// or agreed to in writing, software, hardware and materials distributed under +// this License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR +// CONDITIONS OF ANY KIND, either express or implied. See the License for the +// specific language governing permissions and limitations under the License. + +module pulp_clock_gating + ( + input logic clk_i, + input logic en_i, + input logic test_en_i, + output logic clk_o + ); + + assign clk_o = clk_i; + +endmodule From 7903fe3516e816728622228781ff5dc7114b3d07 Mon Sep 17 00:00:00 2001 From: Angelo Garofalo Date: Tue, 10 Dec 2019 10:57:13 +0100 Subject: [PATCH 34/46] update for FMC ext board. clean up needed --- rtl/pulpemu/pulpemu.sv | 182 ++++++++++++++++++++++++++++++----------- 1 file changed, 134 insertions(+), 48 deletions(-) diff --git a/rtl/pulpemu/pulpemu.sv b/rtl/pulpemu/pulpemu.sv index a8917dcc..d87191eb 100644 --- a/rtl/pulpemu/pulpemu.sv +++ b/rtl/pulpemu/pulpemu.sv @@ -26,43 +26,82 @@ module pulpemu inout wire pad_uart_rx, inout wire pad_uart_tx, - inout wire pad_uart_rts, //Mapped to spim_csn0 - inout wire pad_uart_cts, //Mapped to spim_sck - - inout wire led0_o, //Mapped to spim_csn1 - inout wire led1_o, //Mapped to cam_pclk - inout wire led2_o, //Mapped to cam_hsync - inout wire led3_o, //Mapped to cam_data0 - - inout wire switch0_i, //Mapped to cam_data1 - inout wire switch1_i, //Mapped to cam_data2 - inout wire switch2_i, //Mapped to cam_data7 - inout wire switch3_i, //Mapped to cam_vsync - - inout wire btn0_i, //Mapped to cam_data3 - inout wire btn1_i, //Mapped to cam_data4 - inout wire btn2_i, //Mapped to cam_data5 - inout wire btn3_i, //Mapped to cam_data6 - - inout wire pad_i2c0_sda, - inout wire pad_i2c0_scl, - - inout wire pad_pmod0_4, //Mapped to spim_sdio0 - inout wire pad_pmod0_5, //Mapped to spim_sdio1 - inout wire pad_pmod0_6, //Mapped to spim_sdio2 - inout wire pad_pmod0_7, //Mapped to spim_sdio3 - - inout wire pad_pmod1_0, //Mapped to sdio_data0 - inout wire pad_pmod1_1, //Mapped to sdio_data1 - inout wire pad_pmod1_2, //Mapped to sdio_data2 - inout wire pad_pmod1_3, //Mapped to sdio_data3 - inout wire pad_pmod1_4, //Mapped to i2s0_sck - inout wire pad_pmod1_5, //Mapped to i2s0_ws - inout wire pad_pmod1_6, //Mapped to i2s0_sdi - inout wire pad_pmod1_7, //Mapped to i2s1_sdi - - inout wire pad_hdmi_scl, //Mapped to sdio_clk - inout wire pad_hdmi_sda, //Mapped to sdio_cmd + //inout wire pad_uart_rts, //Mapped to spim_csn0 + //inout wire pad_uart_cts, //Mapped to spim_sck + + //inout wire led0_o, //Mapped to spim_csn1 + //inout wire led1_o, //Mapped to cam_pclk + //inout wire led2_o, //Mapped to cam_hsync + //inout wire led3_o, //Mapped to cam_data0 + + //inout wire switch0_i, //Mapped to cam_data1 + //inout wire switch1_i, //Mapped to cam_data2 + //inout wire switch2_i, //Mapped to cam_data7 + //inout wire switch3_i, //Mapped to cam_vsync + + //inout wire btn0_i, //Mapped to cam_data3 + //inout wire btn1_i, //Mapped to cam_data4 + //inout wire btn2_i, //Mapped to cam_data5 + //inout wire btn3_i, //Mapped to cam_data6 + + //inout wire pad_i2c0_sda, + //inout wire pad_i2c0_scl, + + //inout wire pad_pmod0_4, //Mapped to spim_sdio0 + //inout wire pad_pmod0_5, //Mapped to spim_sdio1 + //inout wire pad_pmod0_6, //Mapped to spim_sdio2 + // inout wire pad_pmod0_7, //Mapped to spim_sdio3 + + //inout wire pad_pmod1_0, //Mapped to sdio_data0 + //inout wire pad_pmod1_1, //Mapped to sdio_data1 + //inout wire pad_pmod1_2, //Mapped to sdio_data2 + //inout wire pad_pmod1_3, //Mapped to sdio_data3 + //inout wire pad_pmod1_4, //Mapped to i2s0_sck + //inout wire pad_pmod1_5, //Mapped to i2s0_ws + //inout wire pad_pmod1_6, //Mapped to i2s0_sdi + //inout wire pad_pmod1_7, //Mapped to i2s1_sdi + + inout FMC_sdio_data0, + inout FMC_sdio_data1, + inout FMC_sdio_data2, + inout FMC_sdio_data3, + inout FMC_sdio_cmd, + inout FMC_sdio_sck, + + + inout FMC_qspi_sdio0, + inout FMC_qspi_sdio1, + inout FMC_qspi_sdio2, + inout FMC_qspi_sdio3, + inout FMC_qspi_csn0, + inout FMC_qspi_csn1, + inout FMC_qspi_sck, + + inout FMC_i2c0_sda, + inout FMC_i2c0_scl, + + inout FMC_i2s0_sck, + inout FMC_i2s0_ws, + inout FMC_i2s0_sdi, + inout FMC_i2s1_sdi, + + + inout FMC_cam_pclk, + inout FMC_cam_hsync, + inout FMC_cam_data0, + inout FMC_cam_data1, + inout FMC_cam_data2, + inout FMC_cam_data3, + inout FMC_cam_data4, + inout FMC_cam_data5, + inout FMC_cam_data6, + inout FMC_cam_data7, + inout FMC_cam_vsync, + + + + //inout wire pad_hdmi_scl, //Mapped to sdio_clk + //inout wire pad_hdmi_sda, //Mapped to sdio_cmd input wire pad_reset, @@ -74,8 +113,8 @@ module pulpemu ); localparam CORE_TYPE = 0; // 0 for RISCY, 1 for ZERORISCY, 2 for MICRORISCY - localparam USE_FPU = 0; - localparam USE_HWPE = 0; + localparam USE_FPU = 1; + localparam USE_HWPE = 1; wire ref_clk; @@ -99,6 +138,7 @@ module pulpemu .USE_HWPE(USE_HWPE) ) i_pulp ( +/* -----\/----- EXCLUDED -----\/----- .pad_spim_sdio0(pad_pmod0_4), .pad_spim_sdio1(pad_pmod0_5), .pad_spim_sdio2(pad_pmod0_6), @@ -106,10 +146,20 @@ module pulpemu .pad_spim_csn0(pad_uart_rts), .pad_spim_csn1(led0_o), .pad_spim_sck(pad_uart_cts), + -----/\----- EXCLUDED -----/\----- */ + + .pad_spim_sdio0(FMC_qspi_sdio0), + .pad_spim_sdio1(FMC_qspi_sdio1), + .pad_spim_sdio2(FMC_qspi_sdio2), + .pad_spim_sdio3(FMC_qspi_sdio3), + .pad_spim_csn0(FMC_qspi_csn0), + .pad_spim_csn1(FMC_qspi_csn1), + .pad_spim_sck(FMC_qspi_sck), - .pad_uart_rx(pad_uart_rx), - .pad_uart_tx(pad_uart_tx), + .pad_uart_rx(pad_uart_rx), //keep + .pad_uart_tx(pad_uart_tx), //keep +/* -----\/----- EXCLUDED -----\/----- .pad_cam_pclk(led1_o), .pad_cam_hsync(led2_o), .pad_cam_data0(led3_o), @@ -121,32 +171,68 @@ module pulpemu .pad_cam_data6(btn3_i), .pad_cam_data7(switch2_i), .pad_cam_vsync(switch3_i), + -----/\----- EXCLUDED -----/\----- */ + + .pad_cam_pclk(FMC_cam_pclk), + .pad_cam_hsync(FMC_cam_hsync), + .pad_cam_data0(FMC_cam_data0), + .pad_cam_data1(FMC_cam_data1), + .pad_cam_data2(FMC_cam_data2), + .pad_cam_data3(FMC_cam_data3), + .pad_cam_data4(FMC_cam_data4), + .pad_cam_data5(FMC_cam_data5), + .pad_cam_data6(FMC_cam_data6), + .pad_cam_data7(FMC_cam_data7), + .pad_cam_vsync(FMC_cam_vsync), +/* -----\/----- EXCLUDED -----\/----- .pad_sdio_clk(pad_hdmi_scl), .pad_sdio_cmd(pad_hdmi_sda), .pad_sdio_data0(pad_pmod1_0), .pad_sdio_data1(pad_pmod1_1), .pad_sdio_data2(pad_pmod1_2), .pad_sdio_data3(pad_pmod1_3), + -----/\----- EXCLUDED -----/\----- */ + + + .pad_sdio_clk(FMC_sdio_sck), + .pad_sdio_cmd(FMC_sdio_cmd), + .pad_sdio_data0(FMC_sdio_data0), + .pad_sdio_data1(FMC_sdio_data1), + .pad_sdio_data2(FMC_sdio_data2), + .pad_sdio_data3(FMC_sdio_data3), + +/* -----\/----- EXCLUDED -----\/----- .pad_i2c0_sda(pad_i2c0_sda), .pad_i2c0_scl(pad_i2c0_scl), + -----/\----- EXCLUDED -----/\----- */ + + .pad_i2c0_sda(FMC_i2c0_sda), + .pad_i2c0_scl(FMC_i2c0_scl), +/* -----\/----- EXCLUDED -----\/----- .pad_i2s0_sck(pad_pmod1_4), .pad_i2s0_ws(pad_pmod1_5), .pad_i2s0_sdi(pad_pmod1_6), .pad_i2s1_sdi(pad_pmod1_7), + -----/\----- EXCLUDED -----/\----- */ + + .pad_i2s0_sck(FMC_i2s0_sck), + .pad_i2s0_ws(FMC_i2s0_ws), + .pad_i2s0_sdi(FMC_i2s0_sdi), + .pad_i2s1_sdi(FMC_i2s1_sdi), .pad_reset_n(~pad_reset), - .pad_jtag_tck(pad_jtag_tck), - .pad_jtag_tdi(pad_jtag_tdi), - .pad_jtag_tdo(pad_jtag_tdo), - .pad_jtag_tms(pad_jtag_tms), - .pad_jtag_trst(1'b1), + .pad_jtag_tck(pad_jtag_tck), //keep + .pad_jtag_tdi(pad_jtag_tdi), //keep + .pad_jtag_tdo(pad_jtag_tdo), //keep + .pad_jtag_tms(pad_jtag_tms), //keep + .pad_jtag_trst(1'b1), //keep - .pad_xtal_in(ref_clk), - .pad_bootsel() + .pad_xtal_in(ref_clk), //keep + .pad_bootsel() //keep ); endmodule From a02d9ad3011bfbb6e0073e12adfa3da84891fbb4 Mon Sep 17 00:00:00 2001 From: Angelo Garofalo Date: Wed, 22 Jan 2020 14:38:45 +0100 Subject: [PATCH 35/46] add fpga scripts --- fpga/.gitignore | 30 + fpga/Makefile | 45 ++ fpga/README.md | 17 + fpga/common/messages.tcl | 13 + fpga/docs/README.md | 12 + fpga/fpga-settings.mk | 13 + fpga/pulp_cluster/Makefile | 20 + fpga/pulp_cluster/postsynth_names.py | 28 + fpga/pulp_cluster/tcl/.gitignore | 3 + fpga/pulp_cluster/tcl/constraints.xdc | 11 + fpga/pulp_cluster/tcl/create_path_groups.xdc | 5 + fpga/pulp_cluster/tcl/run.tcl | 61 ++ fpga/pulpemu/.gitignore | 2 + fpga/pulpemu/Makefile | 86 +++ fpga/pulpemu/bitstream.bif | 5 + fpga/pulpemu/board/get-bitstream-name.sh | 11 + fpga/pulpemu/board/vcu118/bit_to_mcs.tcl | 2 + fpga/pulpemu/board/vcu118/guide.sh | 5 + fpga/pulpemu/board/vcu118/program_fpga.tcl | 13 + fpga/pulpemu/board/vcu118/program_spi.tcl | 30 + fpga/pulpemu/board/zc706/fsbl.elf | Bin 0 -> 397416 bytes fpga/pulpemu/board/zc706/output.bif | 6 + fpga/pulpemu/board/zcu102/fsbl.elf | Bin 0 -> 125384 bytes fpga/pulpemu/board/zcu102/output.bif | 7 + fpga/pulpemu/get-bitstream-name.sh | 11 + fpga/pulpemu/scripts/gen_probes_ltx.py | 37 ++ fpga/pulpemu/scripts/probes.yaml | 656 +++++++++++++++++++ fpga/pulpemu/tcl/.gitignore | 3 + fpga/pulpemu/tcl/constraints.xdc | 58 ++ fpga/pulpemu/tcl/debug.tcl | 96 +++ fpga/pulpemu/tcl/false_paths.tcl | 11 + fpga/pulpemu/tcl/floorplan.xdc | 6 + fpga/pulpemu/tcl/fmc_board.ucf | 73 +++ fpga/pulpemu/tcl/fmc_board_vcu118.xdc | 173 +++++ fpga/pulpemu/tcl/fmc_board_zc706.xdc | 229 +++++++ fpga/pulpemu/tcl/fmc_board_zcu102.xdc | 181 +++++ fpga/pulpemu/tcl/impl.tcl | 51 ++ fpga/pulpemu/tcl/run.tcl | 122 ++++ fpga/pulpemu/tcl/setup_impl.tcl | 58 ++ fpga/sim/.gitignore | 40 ++ fpga/sim/Makefile | 80 +++ fpga/sim/README.md | 38 ++ fpga/sim/boot | 1 + fpga/sim/compile_simlibs.sh | 3 + fpga/sim/compile_simlibs.tcl | 3 + fpga/sim/misc/glbl.v | 71 ++ fpga/sim/tcl_files/config/.gitignore | 2 + fpga/sim/tcl_files/config/export_all.tcl | 3 + fpga/sim/tcl_files/config/run_and_exit.tcl | 10 + fpga/sim/tcl_files/config/vsim.tcl | 155 +++++ fpga/sim/tcl_files/config/vsim_custom.tcl | 81 +++ fpga/sim/tcl_files/config/vsim_fpga.tcl | 15 + fpga/sim/tcl_files/config/vsim_sdvt.tcl | 98 +++ fpga/sim/tcl_files/export_run.tcl | 7 + fpga/sim/tcl_files/rtl_vopt.tcl | 41 ++ fpga/sim/tcl_files/run.tcl | 5 + fpga/sim/vcompile/.gitignore | 2 + fpga/sim/vcompile/build.mk | 63 ++ fpga/sim/vcompile/fpga.mk | 39 ++ fpga/sim/vcompile/ips.mk | 170 +++++ fpga/sim/vcompile/rtl.mk | 29 + fpga/sim/vcompile/tb.mk | 49 ++ fpga/sourceme.sh | 33 + fpga/tb | 1 + 64 files changed, 3229 insertions(+) create mode 100644 fpga/.gitignore create mode 100644 fpga/Makefile create mode 100644 fpga/README.md create mode 100644 fpga/common/messages.tcl create mode 100644 fpga/docs/README.md create mode 100644 fpga/fpga-settings.mk create mode 100644 fpga/pulp_cluster/Makefile create mode 100755 fpga/pulp_cluster/postsynth_names.py create mode 100644 fpga/pulp_cluster/tcl/.gitignore create mode 100644 fpga/pulp_cluster/tcl/constraints.xdc create mode 100644 fpga/pulp_cluster/tcl/create_path_groups.xdc create mode 100644 fpga/pulp_cluster/tcl/run.tcl create mode 100644 fpga/pulpemu/.gitignore create mode 100644 fpga/pulpemu/Makefile create mode 100644 fpga/pulpemu/bitstream.bif create mode 100755 fpga/pulpemu/board/get-bitstream-name.sh create mode 100644 fpga/pulpemu/board/vcu118/bit_to_mcs.tcl create mode 100644 fpga/pulpemu/board/vcu118/guide.sh create mode 100644 fpga/pulpemu/board/vcu118/program_fpga.tcl create mode 100644 fpga/pulpemu/board/vcu118/program_spi.tcl create mode 100755 fpga/pulpemu/board/zc706/fsbl.elf create mode 100644 fpga/pulpemu/board/zc706/output.bif create mode 100755 fpga/pulpemu/board/zcu102/fsbl.elf create mode 100644 fpga/pulpemu/board/zcu102/output.bif create mode 100755 fpga/pulpemu/get-bitstream-name.sh create mode 100644 fpga/pulpemu/scripts/gen_probes_ltx.py create mode 100644 fpga/pulpemu/scripts/probes.yaml create mode 100644 fpga/pulpemu/tcl/.gitignore create mode 100644 fpga/pulpemu/tcl/constraints.xdc create mode 100644 fpga/pulpemu/tcl/debug.tcl create mode 100644 fpga/pulpemu/tcl/false_paths.tcl create mode 100644 fpga/pulpemu/tcl/floorplan.xdc create mode 100644 fpga/pulpemu/tcl/fmc_board.ucf create mode 100644 fpga/pulpemu/tcl/fmc_board_vcu118.xdc create mode 100644 fpga/pulpemu/tcl/fmc_board_zc706.xdc create mode 100644 fpga/pulpemu/tcl/fmc_board_zcu102.xdc create mode 100644 fpga/pulpemu/tcl/impl.tcl create mode 100644 fpga/pulpemu/tcl/run.tcl create mode 100644 fpga/pulpemu/tcl/setup_impl.tcl create mode 100644 fpga/sim/.gitignore create mode 100644 fpga/sim/Makefile create mode 100644 fpga/sim/README.md create mode 120000 fpga/sim/boot create mode 100755 fpga/sim/compile_simlibs.sh create mode 100644 fpga/sim/compile_simlibs.tcl create mode 100644 fpga/sim/misc/glbl.v create mode 100644 fpga/sim/tcl_files/config/.gitignore create mode 100755 fpga/sim/tcl_files/config/export_all.tcl create mode 100644 fpga/sim/tcl_files/config/run_and_exit.tcl create mode 100644 fpga/sim/tcl_files/config/vsim.tcl create mode 100644 fpga/sim/tcl_files/config/vsim_custom.tcl create mode 100644 fpga/sim/tcl_files/config/vsim_fpga.tcl create mode 100644 fpga/sim/tcl_files/config/vsim_sdvt.tcl create mode 100755 fpga/sim/tcl_files/export_run.tcl create mode 100755 fpga/sim/tcl_files/rtl_vopt.tcl create mode 100755 fpga/sim/tcl_files/run.tcl create mode 100644 fpga/sim/vcompile/.gitignore create mode 100644 fpga/sim/vcompile/build.mk create mode 100644 fpga/sim/vcompile/fpga.mk create mode 100644 fpga/sim/vcompile/ips.mk create mode 100644 fpga/sim/vcompile/rtl.mk create mode 100644 fpga/sim/vcompile/tb.mk create mode 100644 fpga/sourceme.sh create mode 120000 fpga/tb diff --git a/fpga/.gitignore b/fpga/.gitignore new file mode 100644 index 00000000..f9fceac6 --- /dev/null +++ b/fpga/.gitignore @@ -0,0 +1,30 @@ +pulp_cluster/*.edf +pulp_cluster/*.v +pulpemu/pulpemu.* +ips/*/ip/ +*.jou +*.log +*.cache/ +*.hw/ +*.runs/ +*.srcs/ +*.xpr +*.xci +*.Xil +*.mif +*.swp +vivado_* +reports* +*bin +*bit + +sim/.cxl* +sim/ips_inputs +sim/vcompile/rtl/* +sim/vcompile/ips/* +sim/models +sim/modelsim.ini.bak +*sim.v +*sdf +*.mcs +*.prm \ No newline at end of file diff --git a/fpga/Makefile b/fpga/Makefile new file mode 100644 index 00000000..b32e9dd5 --- /dev/null +++ b/fpga/Makefile @@ -0,0 +1,45 @@ + +include fpga-settings.mk + +all: synth impl + +gui: + cd pulpemu; make clean-impl gui + +impl: + cd pulpemu; make clean-impl impl + +ips: mem clk + +mem: + cd ips/xilinx_interleaved_ram; make clean all + cd ips/xilinx_private_ram; make clean all + cd ips/xilinx_rom_bank_2048x32; make clean all + cd ips/xilinx_tcdm_bank_1024x32; make clean all + +clk: ## Synthesizes the Xilinx Clocking Manager IPs + cd ips/xilinx_clk_mngr; make clean all + cd ips/xilinx_slow_clk_mngr; make clean all + +synth: synth-ulpcluster synth-pulpemu + +synth-ulpcluster: + cd pulp_cluster; make clean all + +synth-pulpemu: + cd pulpemu; make clean all + +cleanall: clean-ips clean-ulpcluster clean-pulpemu + +clean-ulpcluster: + cd pulp_cluster; make clean + +clean-pulpemu: + cd pulpemu; make clean + +clean-ips: + cd ips/xilinx_interleaved_ram; make clean + cd ips/xilinx_private_ram; make clean + cd ips/xilinx_rom_bank_2048x32; make clean + cd ips/xilinx_tcdm_bank_1024x32; make clean + cd ips/xilinx_clk_mngr; make clean diff --git a/fpga/README.md b/fpga/README.md new file mode 100644 index 00000000..1f136aa9 --- /dev/null +++ b/fpga/README.md @@ -0,0 +1,17 @@ +1. Load environment variable according the fpga board, now support only zc706 and zcu102 +source sourceme.sh + +2. To make all fpga necessary IPs, for both FPGA RTL simulation and FPGA emulation +make ips + +3. For FPGA RTL simulation, go to ./sim + +4. For FPGA emulation + + - build cluster netlist + make synth-ulpcluster + + - build all SoC + make synth-pulpemu + + - If it is successful, you can find BOOT.bin in ./pulpemu/board \ No newline at end of file diff --git a/fpga/common/messages.tcl b/fpga/common/messages.tcl new file mode 100644 index 00000000..e8bfaf90 --- /dev/null +++ b/fpga/common/messages.tcl @@ -0,0 +1,13 @@ +# sets up Vivado messages in a more sensible way + +set_msg_config -id {[Synth 8-3352]} -new_severity "critical warning" +set_msg_config -id {[Synth 8-350]} -new_severity "critical warning" +set_msg_config -id {[Synth 8-2490]} -new_severity "warning" +set_msg_config -id {[Synth 8-2306]} -new_severity "info" +set_msg_config -id {[Synth 8-3331]} -new_severity "critical warning" +set_msg_config -id {[Synth 8-3332]} -new_severity "info" +set_msg_config -id {[Synth 8-2715]} -new_severity "error" +set_msg_config -id {[Opt 31-35]} -new_severity "info" +set_msg_config -id {[Opt 31-32]} -new_severity "info" +set_msg_config -id {[Shape Builder 18-119]} -new_severity "warning" +set_msg_config -id {[Filemgmt 20-742]} -new_severity "error" diff --git a/fpga/docs/README.md b/fpga/docs/README.md new file mode 100644 index 00000000..10a14ade --- /dev/null +++ b/fpga/docs/README.md @@ -0,0 +1,12 @@ +# Simple Guide + +## VEGA/GAP9 + +1. All the scripts are in master branch. +2. Document are for VEGA/GAP9 fpga implementation. + +## GAP8 + +1. All the scripts are in GAP8 branch. +2. Can also use for GAP8 fpga implementation. The only difference is that in GAP8, there is no pin. + diff --git a/fpga/fpga-settings.mk b/fpga/fpga-settings.mk new file mode 100644 index 00000000..ccaf0eb6 --- /dev/null +++ b/fpga/fpga-settings.mk @@ -0,0 +1,13 @@ +#export BOARD=zcu102 +#export XILINX_PART=xczu9eg-ffvb1156-2-e +#export XILINX_BOARD=xilinx.com:zcu102:part0:3.2 +export FC_CLK_PERIOD_NS=50 +export CL_CLK_PERIOD_NS=50 +export PER_CLK_PERIOD_NS=100 +export SLOW_CLK_PERIOD_NS=30517 +#Must also change the localparam 'L2_BANK_SIZE' in pulp_soc.sv accordingly +export INTERLEAVED_BANK_SIZE=28672 +#Must also change the localparam 'L2_BANK_SIZE_PRI' in pulp_soc.sv accordingly +export PRIVATE_BANK_SIZE=8192 +$(info Setting environment variables for $(BOARD) board) + diff --git a/fpga/pulp_cluster/Makefile b/fpga/pulp_cluster/Makefile new file mode 100644 index 00000000..bedd85dc --- /dev/null +++ b/fpga/pulp_cluster/Makefile @@ -0,0 +1,20 @@ +PROJECT:=pulp_cluster + +all: + vivado-2018.2 vivado -mode batch -source tcl/run.tcl + +gui: + vivado -mode gui -source tcl/run.tcl & + +clean: + rm -rf ${PROJECT}.xpr + rm -rf ${PROJECT}.data + rm -rf ${PROJECT}.runs + rm -rf ${PROJECT}.srcs + rm -rf ${PROJECT}.cache + rm -rf ${PROJECT}.hw + rm -rf component.xml + rm -rf vivado* + rm -rf .Xil + rm -rf xgui + diff --git a/fpga/pulp_cluster/postsynth_names.py b/fpga/pulp_cluster/postsynth_names.py new file mode 100755 index 00000000..17f8719d --- /dev/null +++ b/fpga/pulp_cluster/postsynth_names.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python +import sys + +with open("pulp_cluster_funcsim.v", "rb") as f: + f_s = f.readlines() + +with open("pulp_cluster_funcsim.v", "rb") as f: + f_str = f.read() + +module_list = [] + +for line in f_s: + lsplit = line.split() + try: + if lsplit[0] == "module" and lsplit[1] != "pulp_cluster": + module_list.append(lsplit[1]) + except IndexError: + continue + +print "Replacing postsynthesis names" +for mod in module_list: + # print " %s" % mod + f_str = f_str.replace("%s " % mod, "pulp_cluster_postsynth_%s " % mod) + f_str = f_str.replace("%s\n" % mod, "pulp_cluster_postsynth_%s\n" % mod) + +with open("pulp_cluster_postsynt.v", "wb") as f: + f.write(f_str) + diff --git a/fpga/pulp_cluster/tcl/.gitignore b/fpga/pulp_cluster/tcl/.gitignore new file mode 100644 index 00000000..fda3137b --- /dev/null +++ b/fpga/pulp_cluster/tcl/.gitignore @@ -0,0 +1,3 @@ +*_add_files.tcl +*_inc_dirs.tcl +*_src_files.tcl \ No newline at end of file diff --git a/fpga/pulp_cluster/tcl/constraints.xdc b/fpga/pulp_cluster/tcl/constraints.xdc new file mode 100644 index 00000000..7736ac9c --- /dev/null +++ b/fpga/pulp_cluster/tcl/constraints.xdc @@ -0,0 +1,11 @@ +## Boundary +set_input_delay 0.5 [all_inputs] +# set_load 0.1 [all_outputs] # only post-synthesis + +create_clock -period 10 -name clk_i [get_ports clk_i] + +set_false_path -from [all_inputs] +set_false_path -to [all_outputs] + +set_false_path -through [get_pins rstgen_i/s_rst_n_reg/Q] +set_false_path -from [get_clocks tck_i] -to [get_clocks clk_i] diff --git a/fpga/pulp_cluster/tcl/create_path_groups.xdc b/fpga/pulp_cluster/tcl/create_path_groups.xdc new file mode 100644 index 00000000..6daaa496 --- /dev/null +++ b/fpga/pulp_cluster/tcl/create_path_groups.xdc @@ -0,0 +1,5 @@ +group_path -name CORE_DATA_REQ -weight 2.000 -through [list [get_nets CORE*core_region_i/*_CORE/data_addr_o*] [get_nets CORE*core_region_i/*_CORE/data_wdata_o*] [get_nets CORE*core_region_i/*_CORE/data_we_o*] [get_nets CORE*core_region_i/*_CORE/data_req_o*] [get_nets CORE*core_region_i/*_CORE/data_be_o*] [get_nets CORE*core_region_i/*_CORE/data_gnt_i*]] +group_path -name CORE_DATA_RESP -weight 2.000 -through [list [get_nets CORE*core_region_i/*_CORE/data_rdata_i*] [get_nets CORE*core_region_i/*_CORE/data_rvalid_i*]] +group_path -name CORE_INSTR_REQ -weight 2.000 -through [list [get_nets CORE*core_region_i/*_CORE/instr_addr_o*] [get_nets CORE*core_region_i/*_CORE/instr_req_o*] [get_nets CORE*core_region_i/*_CORE/instr_gnt_i*]] +group_path -name CORE_INSTR_RESP -weight 2.000 -through [list [get_nets CORE*core_region_i/*_CORE/instr_rdata_i*] [get_nets CORE*core_region_i/*_CORE/instr_rvalid_i*]] +group_path -name CORE_R2R -weight 2.000 -from [filter [all_registers ] {name =~ CORE*core_region_i*}] -to [filter [all_registers ] {name =~ CORE*core_region_i*}] diff --git a/fpga/pulp_cluster/tcl/run.tcl b/fpga/pulp_cluster/tcl/run.tcl new file mode 100644 index 00000000..26264fd1 --- /dev/null +++ b/fpga/pulp_cluster/tcl/run.tcl @@ -0,0 +1,61 @@ +# create project +create_project pulp_cluster . -force -part $::env(XILINX_PART) +set_property board_part $::env(XILINX_BOARD) [current_project] + +# set up includes +source tcl/ips_inc_dirs.tcl +source tcl/rtl_inc_dirs.tcl +set_property include_dirs $INCLUDE_DIRS [current_fileset] + +# set up meaningful errors +source ../common/messages.tcl + +# setup source files +source tcl/ips_src_files.tcl +source tcl/rtl_src_files.tcl + +# add IPs +source tcl/ips_add_files.tcl +source tcl/rtl_add_files.tcl + +# add memory cuts + FPU IPs +read_ip $FPGA_IPS/xilinx_tcdm_bank_1024x32/ip/xilinx_tcdm_bank_1024x32.xci + +# set pulp_cluster as top +set_property top pulp_cluster [current_fileset] + +# needed only if used in batch mode +update_compile_order -fileset sources_1 +update_compile_order -fileset sim_1 + +# add constraints +add_files -fileset constrs_1 -norecurse tcl/constraints.xdc +set_property target_constrs_file tcl/constraints.xdc [current_fileset -constrset] +# create path groups +add_files -fileset constrs_1 -norecurse tcl/create_path_groups.xdc +set_property target_constrs_file tcl/create_path_groups.xdc [current_fileset -constrset] + +# run synthesis +# first try will fail +catch {synth_design -rtl -name rtl_1 -verilog_define PULP_FPGA_EMUL=1 -verilog_define PERF_COUNTERS=1 -verilog_define RISCV=1 -gated_clock_conversion on -constrset constrs_1} +update_compile_order -fileset sources_1 +synth_design -rtl -name rtl_1 -verilog_define PULP_FPGA_EMUL=1 -verilog_define PERF_COUNTERS=1 -verilog_define RISCV=1 -gated_clock_conversion on -constrset constrs_1 + +set_property STEPS.SYNTH_DESIGN.ARGS.FLATTEN_HIERARCHY none [get_runs synth_1] + +launch_runs synth_1 -jobs 28 +wait_on_run synth_1 +open_run synth_1 + +# save EDIF netlist +write_edif -force pulp_cluster.edf +write_verilog -force -mode synth_stub pulp_cluster_stub.v +write_verilog -force -mode funcsim pulp_cluster_funcsim.v + +# reports +exec mkdir -p reports/ +exec rm -rf reports/* +check_timing -file reports/pulp_cluster.check_timing.rpt +report_timing -max_paths 100 -nworst 100 -delay_type max -sort_by slack -file reports/pulp_cluster.timing_WORST_100.rpt +report_timing -nworst 1 -delay_type max -sort_by group -file reports/pulp_cluster.timing.rpt +report_utilization -hierarchical -file reports/pulp_cluster.utilization.rpt diff --git a/fpga/pulpemu/.gitignore b/fpga/pulpemu/.gitignore new file mode 100644 index 00000000..ab76b8ed --- /dev/null +++ b/fpga/pulpemu/.gitignore @@ -0,0 +1,2 @@ +!/gap-emu-*.bin +save \ No newline at end of file diff --git a/fpga/pulpemu/Makefile b/fpga/pulpemu/Makefile new file mode 100644 index 00000000..03908747 --- /dev/null +++ b/fpga/pulpemu/Makefile @@ -0,0 +1,86 @@ +PROJECT:=pulpemu +PROBES?=0 + +all: ${BOARD} + +vcu118: synth bootgen_vcu + +zcu102: synth bootgen_zynq_mp + +zc706: synth bootgen_zynq + +synth: + vivado-2018.2 vivado -mode batch -source tcl/run.tcl + +impl: + rm -rf .Xil + vivado-2018.2 vivado -mode batch -source tcl/impl.tcl + cp ${PROJECT}.runs/impl_1/${PROJECT}.bit . + cp ${PROJECT}.runs/impl_1/*.dcp . + +gui: + vivado-2018.2 vivado -mode gui -source tcl/setup_impl.tcl & + +gui-synth: + vivado-2018.2 vivado -mode gui -source tcl/run.tcl & + +gui-impl: + vivado-2018.2 vivado -mode gui -source tcl/impl.tcl & + +bootgen_zynq_mp: + cp ${PROJECT}.runs/impl_1/${PROJECT}.bit board/${BOARD}/${PROJECT}.bit + bootgen -image board/${BOARD}/output.bif -arch zynqmp -o board/${BOARD}/BOOT.bin -w on + cp board/${BOARD}/BOOT.bin "board/${BOARD}/`./board/get-bitstream-name.sh`" + +bootgen_zynq: + cp ${PROJECT}.runs/impl_1/${PROJECT}.bit board/${BOARD}/${PROJECT}.bit + bootgen -image board/${BOARD}/output.bif -arch zynq -o board/${BOARD}/BOOT.bin -w on + cp board/${BOARD}/BOOT.bin "board/${BOARD}/`./board/get-bitstream-name.sh`" + +bootgen_vcu: + cp ${PROJECT}.runs/impl_1/${PROJECT}.bit board/${BOARD}/${PROJECT}.bit + vivado-2018.2 vivado -mode tcl -source board/${BOARD}/bit_to_mcs.tcl + cp board/${BOARD}/${PROJECT}.mcs "board/${BOARD}/`./board/get-bitstream-name.sh`" + +program_fpga_vcu: + vivado-2018.2 vivado -mode tcl -source board/${BOARD}/program_fpga.tcl + +program_spi_vcu: + bash board/${BOARD}/guide.sh + vivado-2018.2 vivado -mode tcl -source board/${BOARD}/program_spi.tcl + +qspiflash: + program_flash -f board/BOOT.bin -offset 0 -flash_type \ + qspi_dual_parallel -fsbl board/${BOARD}/fsbl.elf \ + -cable type xilinx_tcf url TCP:127.0.0.1:3121 + +continue: + vivado-2018.2 vivado -mode gui ${PROJECT}.xpr + +clean-impl: + rm -rf ${PROJECT}.runs/impl_1 + +clean: + rm -rf ${PROJECT}.hw + rm -rf ${PROJECT}.xpr + rm -rf ${PROJECT}.data + rm -rf ${PROJECT}.runs + rm -rf ${PROJECT}.srcs + rm -rf ps7_* + rm -rf ${PROJECT}.sim + rm -rf ${PROJECT}.sdk + rm -rf ${PROJECT}.cache + rm -rf ${PROJECT}.ioplanning + rm -rf ${PROJECT}.hwdef + rm -rf *.log + rm -rf ulpsoc.txt + rm -rf pulp_cluster.txt + rm -rf component.xml + rm -rf vivado* + rm -rf xgui + rm -rf .Xil + rm -rf ps_clock* + rm -rf ${PROJECT}* + rm -rf ${PROJECT}.edf + rm -rf board/BOOT.bin + rm -rf board/${PROJECT}.bit diff --git a/fpga/pulpemu/bitstream.bif b/fpga/pulpemu/bitstream.bif new file mode 100644 index 00000000..56387e45 --- /dev/null +++ b/fpga/pulpemu/bitstream.bif @@ -0,0 +1,5 @@ +bitstream : { +[bootloader]../board/fsbl.elf +pulpemu.bit +../board/u-boot.elf +} diff --git a/fpga/pulpemu/board/get-bitstream-name.sh b/fpga/pulpemu/board/get-bitstream-name.sh new file mode 100755 index 00000000..596bf2b4 --- /dev/null +++ b/fpga/pulpemu/board/get-bitstream-name.sh @@ -0,0 +1,11 @@ +#!/bin/bash +tag=$(git describe --abbrev=0 --tags --exact-match 2> /dev/null) +if [ $? != 0 ]; then + commit_hash=`git rev-parse --short HEAD` + branch_name=`git rev-parse --abbrev-ref HEAD` + name=emu-${branch_name}-${commit_hash}.bit.bin +else + name=emu-${tag}.bit.bin +fi +echo $name + diff --git a/fpga/pulpemu/board/vcu118/bit_to_mcs.tcl b/fpga/pulpemu/board/vcu118/bit_to_mcs.tcl new file mode 100644 index 00000000..9a4d44e1 --- /dev/null +++ b/fpga/pulpemu/board/vcu118/bit_to_mcs.tcl @@ -0,0 +1,2 @@ +write_cfgmem -force -format mcs -size 256 -interface SPIx8 -loadbit {up 0x00000000 "./board/vcu118/pulpemu.bit" } -file "./board/vcu118/pulpemu.mcs" +exit diff --git a/fpga/pulpemu/board/vcu118/guide.sh b/fpga/pulpemu/board/vcu118/guide.sh new file mode 100644 index 00000000..f914ab68 --- /dev/null +++ b/fpga/pulpemu/board/vcu118/guide.sh @@ -0,0 +1,5 @@ +#!/bin/bash + +read -p "Before flashing QSPI : Set SW16 to <0101> (1 = on, Position 1 to Position 4). y / n ? " known +read -p "After flashed QSPI : Set SW16 to <0001> (1 = on, Position 1 to Position 4). y / n ? " known +read -p "If you have any questions, please see <../docs/xtp445-vcu118-restoring-flash-c-2018-2.pdf> for help. y / n ? " known diff --git a/fpga/pulpemu/board/vcu118/program_fpga.tcl b/fpga/pulpemu/board/vcu118/program_fpga.tcl new file mode 100644 index 00000000..2821140d --- /dev/null +++ b/fpga/pulpemu/board/vcu118/program_fpga.tcl @@ -0,0 +1,13 @@ +open_hw + +connect_hw_server -url localhost:3121 + +open_hw_target +current_hw_device [get_hw_devices xcvu9p_0] +set_property PROGRAM.FILE {./board/vcu118/pulpemu.bit} [get_hw_devices xcvu9p_0] +refresh_hw_device -update_hw_probes false [lindex [get_hw_devices xcvu9p_0] 0] +create_hw_cfgmem -hw_device [lindex [get_hw_devices] 0] -mem_dev [lindex [get_cfgmem_parts {mt25qu01g-spi-x1_x2_x4_x8}] 0] +set_property FULL_PROBES.FILE {} [get_hw_devices xcvu9p_0] +program_hw_devices [get_hw_devices xcvu9p_0] +refresh_hw_device [lindex [get_hw_devices xcvu9p_0] 0] +exit diff --git a/fpga/pulpemu/board/vcu118/program_spi.tcl b/fpga/pulpemu/board/vcu118/program_spi.tcl new file mode 100644 index 00000000..7400acf0 --- /dev/null +++ b/fpga/pulpemu/board/vcu118/program_spi.tcl @@ -0,0 +1,30 @@ +set_param xicom.use_bitstream_version_check false +open_hw +catch {disconnect_hw_server localhost:3121} +connect_hw_server -url localhost:3121 +current_hw_target [get_hw_targets */xilinx_tcf/Digilent/*] +set_property PARAM.FREQUENCY 15000000 [get_hw_targets */xilinx_tcf/Digilent/*] +open_hw_target +current_hw_device [lindex [get_hw_devices xcvu9p_0] 0] +refresh_hw_device -update_hw_probes false [lindex [get_hw_devices xcvu9p_0] 0] +create_hw_cfgmem -hw_device [lindex [get_hw_devices] 0] -mem_dev [lindex [get_cfgmem_parts {mt25qu01g-spi-x1_x2_x4_x8}] 0] +set_property PROGRAM.BLANK_CHECK 0 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices] 0 ]] +set_property PROGRAM.ERASE 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices] 0 ]] +set_property PROGRAM.CFG_PROGRAM 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices] 0 ]] +set_property PROGRAM.VERIFY 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices] 0 ]] +set_property PROGRAM.CHECKSUM 0 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices] 0 ]] +refresh_hw_device [lindex [get_hw_devices xcvu9p_0] 0] +set_property PROGRAM.ADDRESS_RANGE {use_file} [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices] 0 ]] +set_property PROGRAM.FILES [list "./board/vcu118/pulpemu_primary.mcs" "./board/vcu118/pulpemu_secondary.mcs" ] [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices] 0]] +set_property PROGRAM.PRM_FILES [list "./board/vcu118/pulpemu_primary.prm" "./board/vcu118/pulpemu_secondary.prm" ] [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices] 0]] +set_property PROGRAM.UNUSED_PIN_TERMINATION {pull-none} [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices] 0 ]] +set_property PROGRAM.BLANK_CHECK 0 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices] 0 ]] +set_property PROGRAM.ERASE 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices] 0 ]] +set_property PROGRAM.CFG_PROGRAM 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices] 0 ]] +set_property PROGRAM.VERIFY 1 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices] 0 ]] +set_property PROGRAM.CHECKSUM 0 [ get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices] 0 ]] +if {![string equal [get_property PROGRAM.HW_CFGMEM_TYPE [lindex [get_hw_devices] 0]] [get_property MEM_TYPE [get_property CFGMEM_PART [get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices] 0 ]]]]] } { create_hw_bitstream -hw_device [lindex [get_hw_devices] 0] [get_property PROGRAM.HW_CFGMEM_BITFILE [ lindex [get_hw_devices] 0]]; program_hw_devices [lindex [get_hw_devices] 0]; }; +program_hw_cfgmem -hw_cfgmem [get_property PROGRAM.HW_CFGMEM [lindex [get_hw_devices] 0 ]] +close_hw_target [current_hw_target [get_hw_targets */xilinx_tcf/Digilent/*]] +disconnect_hw_server localhost:3121 +close_hw diff --git a/fpga/pulpemu/board/zc706/fsbl.elf b/fpga/pulpemu/board/zc706/fsbl.elf new file mode 100755 index 0000000000000000000000000000000000000000..1a551adcb4f3954b043a164ab68bd4f6a3407b8a GIT binary patch literal 397416 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%0Dr5i9B(Y<~eI*-` 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 )hu>nE*r@$?2Lc6BX?0v^~ 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�-LHT(Pv3n#a1xyEVCob&5upFhW6eAD6; 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 literal 0 HcmV?d00001 diff --git a/fpga/pulpemu/board/zcu102/output.bif b/fpga/pulpemu/board/zcu102/output.bif new file mode 100644 index 00000000..51d45d80 --- /dev/null +++ b/fpga/pulpemu/board/zcu102/output.bif @@ -0,0 +1,7 @@ +//arch = zynqmp; split = false; format = BIN +the_ROM_image: +{ + [fsbl_config]a53_x64 + [bootloader]board/zcu102/fsbl.elf + [destination_device = pl]board/zcu102/pulpemu.bit +} \ No newline at end of file diff --git a/fpga/pulpemu/get-bitstream-name.sh b/fpga/pulpemu/get-bitstream-name.sh new file mode 100755 index 00000000..e48b60ce --- /dev/null +++ b/fpga/pulpemu/get-bitstream-name.sh @@ -0,0 +1,11 @@ +#!/bin/bash +tag=$(git describe --abbrev=0 --tags --exact-match 2> /dev/null) +if [ $? != 0 ]; then + commit_hash=`git rev-parse --short HEAD` + branch_name=`git rev-parse --abbrev-ref HEAD` + name=vega-emu-${branch_name}-${commit_hash}.bit.bin +else + name=vega-emu-${tag}.bit.bin +fi +echo $name + diff --git a/fpga/pulpemu/scripts/gen_probes_ltx.py b/fpga/pulpemu/scripts/gen_probes_ltx.py new file mode 100644 index 00000000..8327e2e6 --- /dev/null +++ b/fpga/pulpemu/scripts/gen_probes_ltx.py @@ -0,0 +1,37 @@ +import yaml + +yaml_file = "probes.yaml" +with open(yaml_file, "r") as f: + yaml_stream = f.read() +yaml_dic = {'dic' : yaml.load(yaml_stream), 'key' : 'yaml_dic'} +ilas = yaml_dic['dic']['ilas'] + +print """ + + +""" +for k,ila in enumerate(ilas): + for i,probe in enumerate(ila['probes']): + print """ + + + + """ % (ila['int_name'], probe['name'], probe['bits'], k, ila['name'], i, probe['bits']) + if probe['bits']==1: + print """ """ % (ila['int_name'], probe['name']) + else: + for j in xrange(probe['bits']-1,-1,-1): + print """ """ % (ila['int_name'], probe['name'], j) + print """ + +""" + +print """ + +""" diff --git a/fpga/pulpemu/scripts/probes.yaml b/fpga/pulpemu/scripts/probes.yaml new file mode 100644 index 00000000..89940433 --- /dev/null +++ b/fpga/pulpemu/scripts/probes.yaml @@ -0,0 +1,656 @@ +# +# Probes to generate probe LTX file +# +ilas: + - core: "1:0" + name: "ulpsoc_i/l2_ila_i" + int_name: "l2" + probes: + - name: int_csn + bits: 1 + - name: int_wen + bits: 1 + - name: int_ben + bits: 8 + - name: int_add + bits: 32 + - name: int_wdata + bits: 64 + - name: int_rdata + bits: 64 + - name: ext_en + bits: 1 + - name: ext_we + bits: 8 + - name: ext_addr + bits: 15 + - name: ext_din + bits: 64 + - name: ext_dout + bits: 64 + - name: spy_timer + bits: 16 + - core: "1:1" + name: "ulpsoc_i/cluster_i/ulpcluster_i/CORE[0].core_region_i/or1200_top_i/or1200_cpu/core_ila_i" + int_name: "core0" + probes: + - name: fetch_en_i + bits: 1 + - name: if_pc + bits: 32 + - name: if_insn + bits: 32 + - name: id_insn + bits: 32 + - name: ex_insn + bits: 32 + - name: wb_insn + bits: 32 + - name: except_flushpipe + bits: 1 + - name: except_start + bits: 1 + - name: except_started + bits: 1 + - name: except_align + bits: 1 + - name: except_dtlbmiss + bits: 1 + - name: except_dmmufault + bits: 1 + - name: except_illegal + bits: 1 + - name: except_itlbmiss + bits: 1 + - name: except_immufault + bits: 1 + - name: except_ibuserr + bits: 1 + - name: except_dbuserr + bits: 1 + - name: dcpu_adr_o + bits: 32 + - name: dcpu_dat_o + bits: 32 + - name: dcpu_dat_i + bits: 32 + - name: dcpu_ack_i + bits: 1 + - name: rf_dataw + bits: 32 + - name: rf_datawa + bits: 32 + - name: rf_datawb + bits: 32 + - name: rf_datawc + bits: 32 + - name: rf_dataa + bits: 32 + - name: rf_datab + bits: 32 + - name: spy_timer + bits: 16 + - core: "1:2" + name: "ulpsoc_i/cluster_i/ulpcluster_i/CORE[0].core_region_i/or1200_top_i/icache_ila_i" + int_name: "icache0" + probes: + - name: ic_en + bits: 1 + - name: icqmem_adr_qmem + bits: 32 + - name: icqmem_sel_qmem + bits: 4 + - name: icqmem_tag_qmem + bits: 4 + - name: icqmem_dat_ic + bits: 32 + - name: icqmem_ack_ic + bits: 1 + - name: icbiu_adr_ic + bits: 32 + - name: icbiu_dat_biu + bits: 64 + - name: icbiu_ack_biu + bits: 1 + - name: spy_timer + bits: 16 + - core: "1:3" + name: "ulpsoc_i/cluster_i/ulpcluster_i/CORE[1].core_region_i/or1200_top_i/or1200_cpu/core_ila_i" + int_name: "core1" + probes: + - name: fetch_en_i + bits: 1 + - name: if_pc + bits: 32 + - name: if_insn + bits: 32 + - name: id_insn + bits: 32 + - name: ex_insn + bits: 32 + - name: wb_insn + bits: 32 + - name: except_flushpipe + bits: 1 + - name: except_start + bits: 1 + - name: except_started + bits: 1 + - name: except_align + bits: 1 + - name: except_dtlbmiss + bits: 1 + - name: except_dmmufault + bits: 1 + - name: except_illegal + bits: 1 + - name: except_itlbmiss + bits: 1 + - name: except_immufault + bits: 1 + - name: except_ibuserr + bits: 1 + - name: except_dbuserr + bits: 1 + - name: dcpu_adr_o + bits: 32 + - name: dcpu_dat_o + bits: 32 + - name: dcpu_dat_i + bits: 32 + - name: dcpu_ack_i + bits: 1 + - name: rf_dataw + bits: 32 + - name: rf_datawa + bits: 32 + - name: rf_datawb + bits: 32 + - name: rf_datawc + bits: 32 + - name: rf_dataa + bits: 32 + - name: rf_datab + bits: 32 + - name: spy_timer + bits: 16 + - core: "1:4" + name: "ulpsoc_i/cluster_i/ulpcluster_i/CORE[1].core_region_i/or1200_top_i/icache_ila_i" + int_name: "icache1" + probes: + - name: ic_en + bits: 1 + - name: icqmem_adr_qmem + bits: 32 + - name: icqmem_sel_qmem + bits: 4 + - name: icqmem_tag_qmem + bits: 4 + - name: icqmem_dat_ic + bits: 32 + - name: icqmem_ack_ic + bits: 1 + - name: icbiu_adr_ic + bits: 32 + - name: icbiu_dat_biu + bits: 64 + - name: icbiu_ack_biu + bits: 1 + - name: spy_timer + bits: 16 + - core: "1:5" + name: "ulpsoc_i/cluster_i/ulpcluster_i/CORE[2].core_region_i/or1200_top_i/or1200_cpu/core_ila_i" + int_name: "core2" + probes: + - name: fetch_en_i + bits: 1 + - name: if_pc + bits: 32 + - name: if_insn + bits: 32 + - name: id_insn + bits: 32 + - name: ex_insn + bits: 32 + - name: wb_insn + bits: 32 + - name: except_flushpipe + bits: 1 + - name: except_start + bits: 1 + - name: except_started + bits: 1 + - name: except_align + bits: 1 + - name: except_dtlbmiss + bits: 1 + - name: except_dmmufault + bits: 1 + - name: except_illegal + bits: 1 + - name: except_itlbmiss + bits: 1 + - name: except_immufault + bits: 1 + - name: except_ibuserr + bits: 1 + - name: except_dbuserr + bits: 1 + - name: dcpu_adr_o + bits: 32 + - name: dcpu_dat_o + bits: 32 + - name: dcpu_dat_i + bits: 32 + - name: dcpu_ack_i + bits: 1 + - name: rf_dataw + bits: 32 + - name: rf_datawa + bits: 32 + - name: rf_datawb + bits: 32 + - name: rf_datawc + bits: 32 + - name: rf_dataa + bits: 32 + - name: rf_datab + bits: 32 + - name: spy_timer + bits: 16 + - core: "1:6" + name: "ulpsoc_i/cluster_i/ulpcluster_i/CORE[2].core_region_i/or1200_top_i/icache_ila_i" + int_name: "icache2" + probes: + - name: ic_en + bits: 1 + - name: icqmem_adr_qmem + bits: 32 + - name: icqmem_sel_qmem + bits: 4 + - name: icqmem_tag_qmem + bits: 4 + - name: icqmem_dat_ic + bits: 32 + - name: icqmem_ack_ic + bits: 1 + - name: icbiu_adr_ic + bits: 32 + - name: icbiu_dat_biu + bits: 64 + - name: icbiu_ack_biu + bits: 1 + - name: spy_timer + bits: 16 + - core: "1:7" + name: "ulpsoc_i/cluster_i/ulpcluster_i/CORE[3].core_region_i/or1200_top_i/or1200_cpu/core_ila_i" + int_name: "core3" + probes: + - name: fetch_en_i + bits: 1 + - name: if_pc + bits: 32 + - name: if_insn + bits: 32 + - name: id_insn + bits: 32 + - name: ex_insn + bits: 32 + - name: wb_insn + bits: 32 + - name: except_flushpipe + bits: 1 + - name: except_start + bits: 1 + - name: except_started + bits: 1 + - name: except_align + bits: 1 + - name: except_dtlbmiss + bits: 1 + - name: except_dmmufault + bits: 1 + - name: except_illegal + bits: 1 + - name: except_itlbmiss + bits: 1 + - name: except_immufault + bits: 1 + - name: except_ibuserr + bits: 1 + - name: except_dbuserr + bits: 1 + - name: dcpu_adr_o + bits: 32 + - name: dcpu_dat_o + bits: 32 + - name: dcpu_dat_i + bits: 32 + - name: dcpu_ack_i + bits: 1 + - name: rf_dataw + bits: 32 + - name: rf_datawa + bits: 32 + - name: rf_datawb + bits: 32 + - name: rf_datawc + bits: 32 + - name: rf_dataa + bits: 32 + - name: rf_datab + bits: 32 + - name: spy_timer + bits: 16 + - core: "1:8" + name: "ulpsoc_i/cluster_i/ulpcluster_i/CORE[3].core_region_i/or1200_top_i/icache_ila_i" + int_name: "icache3" + probes: + - name: ic_en + bits: 1 + - name: icqmem_adr_qmem + bits: 32 + - name: icqmem_sel_qmem + bits: 4 + - name: icqmem_tag_qmem + bits: 4 + - name: icqmem_dat_ic + bits: 32 + - name: icqmem_ack_ic + bits: 1 + - name: icbiu_adr_ic + bits: 32 + - name: icbiu_dat_biu + bits: 64 + - name: icbiu_ack_biu + bits: 1 + - name: spy_timer + bits: 16 + - core: "1:9" + name: "ulpsoc_i/cluster_i/ulpcluster_i/tcdm_sram_7_ila_i" + int_name: "sram7" + probes: + - name: csn + bits: 1 + - name: wen + bits: 1 + - name: wmn + bits: 32 + - name: add + bits: 8 + - name: wdata + bits: 32 + - name: rdata + bits: 32 + - name: spy_timer + bits: 16 + - core: "1:10" + name: "ulpsoc_i/cluster_i/ulpcluster_i/tcdm_sram_6_ila_i" + int_name: "sram6" + probes: + - name: csn + bits: 1 + - name: wen + bits: 1 + - name: wmn + bits: 32 + - name: add + bits: 8 + - name: wdata + bits: 32 + - name: rdata + bits: 32 + - name: spy_timer + bits: 16 + - core: "1:11" + name: "ulpsoc_i/cluster_i/ulpcluster_i/tcdm_sram_5_ila_i" + int_name: "sram5" + probes: + - name: csn + bits: 1 + - name: wen + bits: 1 + - name: wmn + bits: 32 + - name: add + bits: 8 + - name: wdata + bits: 32 + - name: rdata + bits: 32 + - name: spy_timer + bits: 16 + - core: "1:12" + name: "ulpsoc_i/cluster_i/ulpcluster_i/tcdm_sram_4_ila_i" + int_name: "sram4" + probes: + - name: csn + bits: 1 + - name: wen + bits: 1 + - name: wmn + bits: 32 + - name: add + bits: 8 + - name: wdata + bits: 32 + - name: rdata + bits: 32 + - name: spy_timer + bits: 16 + - core: "1:13" + name: "ulpsoc_i/cluster_i/ulpcluster_i/tcdm_sram_3_ila_i" + int_name: "sram3" + probes: + - name: csn + bits: 1 + - name: wen + bits: 1 + - name: wmn + bits: 32 + - name: add + bits: 8 + - name: wdata + bits: 32 + - name: rdata + bits: 32 + - name: spy_timer + bits: 16 + - core: "1:14" + name: "ulpsoc_i/cluster_i/ulpcluster_i/tcdm_sram_2_ila_i" + int_name: "sram2" + probes: + - name: csn + bits: 1 + - name: wen + bits: 1 + - name: wmn + bits: 32 + - name: add + bits: 8 + - name: wdata + bits: 32 + - name: rdata + bits: 32 + - name: spy_timer + bits: 16 + - core: "1:15" + name: "ulpsoc_i/cluster_i/ulpcluster_i/tcdm_sram_1_ila_i" + int_name: "sram1" + probes: + - name: csn + bits: 1 + - name: wen + bits: 1 + - name: wmn + bits: 32 + - name: add + bits: 8 + - name: wdata + bits: 32 + - name: rdata + bits: 32 + - name: spy_timer + bits: 16 + - core: "1:16" + name: "ulpsoc_i/cluster_i/ulpcluster_i/tcdm_sram_0_ila_i" + int_name: "sram0" + probes: + - name: csn + bits: 1 + - name: wen + bits: 1 + - name: wmn + bits: 32 + - name: add + bits: 8 + - name: wdata + bits: 32 + - name: rdata + bits: 32 + - name: spy_timer + bits: 16 + - core: "1:17" + name: "ulpsoc_i/cluster_i/ulpcluster_i/tcdm_scm_7_ila_i" + int_name: "scm7" + probes: + - name: ren + bits: 1 + - name: wen + bits: 1 + - name: ben + bits: 4 + - name: add + bits: 7 + - name: wdata + bits: 32 + - name: rdata + bits: 32 + - name: spy_timer + bits: 16 + - core: "1:18" + name: "ulpsoc_i/cluster_i/ulpcluster_i/tcdm_scm_6_ila_i" + int_name: "scm6" + probes: + - name: ren + bits: 1 + - name: wen + bits: 1 + - name: ben + bits: 4 + - name: add + bits: 7 + - name: wdata + bits: 32 + - name: rdata + bits: 32 + - name: spy_timer + bits: 16 + - core: "1:19" + name: "ulpsoc_i/cluster_i/ulpcluster_i/tcdm_scm_5_ila_i" + int_name: "scm5" + probes: + - name: ren + bits: 1 + - name: wen + bits: 1 + - name: ben + bits: 4 + - name: add + bits: 7 + - name: wdata + bits: 32 + - name: rdata + bits: 32 + - name: spy_timer + bits: 16 + - core: "1:20" + name: "ulpsoc_i/cluster_i/ulpcluster_i/tcdm_scm_4_ila_i" + int_name: "scm4" + probes: + - name: ren + bits: 1 + - name: wen + bits: 1 + - name: ben + bits: 4 + - name: add + bits: 7 + - name: wdata + bits: 32 + - name: rdata + bits: 32 + - name: spy_timer + bits: 16 + - core: "1:21" + name: "ulpsoc_i/cluster_i/ulpcluster_i/tcdm_scm_3_ila_i" + int_name: "scm3" + probes: + - name: ren + bits: 1 + - name: wen + bits: 1 + - name: ben + bits: 4 + - name: add + bits: 7 + - name: wdata + bits: 32 + - name: rdata + bits: 32 + - name: spy_timer + bits: 16 + - core: "1:22" + name: "ulpsoc_i/cluster_i/ulpcluster_i/tcdm_scm_2_ila_i" + int_name: "scm2" + probes: + - name: ren + bits: 1 + - name: wen + bits: 1 + - name: ben + bits: 4 + - name: add + bits: 7 + - name: wdata + bits: 32 + - name: rdata + bits: 32 + - name: spy_timer + bits: 16 + - core: "1:23" + name: "ulpsoc_i/cluster_i/ulpcluster_i/tcdm_scm_1_ila_i" + int_name: "scm1" + probes: + - name: ren + bits: 1 + - name: wen + bits: 1 + - name: ben + bits: 4 + - name: add + bits: 7 + - name: wdata + bits: 32 + - name: rdata + bits: 32 + - name: spy_timer + bits: 16 + - core: "1:24" + name: "ulpsoc_i/cluster_i/ulpcluster_i/tcdm_scm_0_ila_i" + int_name: "scm0" + probes: + - name: ren + bits: 1 + - name: wen + bits: 1 + - name: ben + bits: 4 + - name: add + bits: 7 + - name: wdata + bits: 32 + - name: rdata + bits: 32 + - name: spy_timer + bits: 16 diff --git a/fpga/pulpemu/tcl/.gitignore b/fpga/pulpemu/tcl/.gitignore new file mode 100644 index 00000000..fda3137b --- /dev/null +++ b/fpga/pulpemu/tcl/.gitignore @@ -0,0 +1,3 @@ +*_add_files.tcl +*_inc_dirs.tcl +*_src_files.tcl \ No newline at end of file diff --git a/fpga/pulpemu/tcl/constraints.xdc b/fpga/pulpemu/tcl/constraints.xdc new file mode 100644 index 00000000..0cc0518f --- /dev/null +++ b/fpga/pulpemu/tcl/constraints.xdc @@ -0,0 +1,58 @@ +####################################### +# _______ _ _ # +# |__ __(_) (_) # +# | | _ _ __ ___ _ _ __ __ _ # +# | | | | '_ ` _ \| | '_ \ / _` | # +# | | | | | | | | | | | | | (_| | # +# |_| |_|_| |_| |_|_|_| |_|\__, | # +# __/ | # +# |___/ # +####################################### + + +#Create constraint for the clock input of the zcu102 board +create_clock -period 8.000 -name ref_clk [get_ports ref_clk_p] +set_property CLOCK_DEDICATED_ROUTE ANY_CMT_COLUMN [get_nets ref_clk] + +#I2S and CAM interface are not used in this FPGA port. Set constraints to +#disable the clock +set_case_analysis 0 i_pulpissimo/safe_domain_i/cam_pclk_o +set_case_analysis 0 i_pulpissimo/safe_domain_i/i2s_slave_sck_o +#set_input_jitter tck 1.000 + +## JTAG +create_clock -period 100.000 -name tck -waveform {0.000 50.000} [get_ports pad_jtag_tck] +set_input_jitter tck 1.000 +set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets pad_jtag_tck_IBUF_inst/O] + + +# minimize routing delay +set_input_delay -clock tck -clock_fall 5.000 [get_ports pad_jtag_tdi] +set_input_delay -clock tck -clock_fall 5.000 [get_ports pad_jtag_tms] +set_output_delay -clock tck 5.000 [get_ports pad_jtag_tdo] + +set_max_delay -to [get_ports pad_jtag_tdo] 20.000 +set_max_delay -from [get_ports pad_jtag_tms] 20.000 +set_max_delay -from [get_ports pad_jtag_tdi] 20.000 + +set_max_delay -datapath_only -from [get_pins i_pulpissimo/soc_domain_i/pulp_soc_i/i_dmi_jtag/i_dmi_cdc/i_cdc_resp/i_src/data_src_q_reg*/C] -to [get_pins i_pulpissimo/soc_domain_i/pulp_soc_i/i_dmi_jtag/i_dmi_cdc/i_cdc_resp/i_dst/data_dst_q_reg*/D] 20.000 +set_max_delay -datapath_only -from [get_pins i_pulpissimo/soc_domain_i/pulp_soc_i/i_dmi_jtag/i_dmi_cdc/i_cdc_resp/i_src/req_src_q_reg/C] -to [get_pins i_pulpissimo/soc_domain_i/pulp_soc_i/i_dmi_jtag/i_dmi_cdc/i_cdc_resp/i_dst/req_dst_q_reg/D] 20.000 +set_max_delay -datapath_only -from [get_pins i_pulpissimo/soc_domain_i/pulp_soc_i/i_dmi_jtag/i_dmi_cdc/i_cdc_req/i_dst/ack_dst_q_reg/C] -to [get_pins i_pulpissimo/soc_domain_i/pulp_soc_i/i_dmi_jtag/i_dmi_cdc/i_cdc_req/i_src/ack_src_q_reg/D] 20.000 + + +# reset signal +set_false_path -from [get_ports pad_reset] + +# Set ASYNC_REG attribute for ff synchronizers to place them closer together and +# increase MTBF +set_property ASYNC_REG true [get_cells i_pulpissimo/soc_domain_i/pulp_soc_i/soc_peripherals_i/apb_adv_timer_i/u_tim0/u_in_stage/r_ls_clk_sync_reg*] +set_property ASYNC_REG true [get_cells i_pulpissimo/soc_domain_i/pulp_soc_i/soc_peripherals_i/apb_adv_timer_i/u_tim1/u_in_stage/r_ls_clk_sync_reg*] +set_property ASYNC_REG true [get_cells i_pulpissimo/soc_domain_i/pulp_soc_i/soc_peripherals_i/apb_adv_timer_i/u_tim2/u_in_stage/r_ls_clk_sync_reg*] +set_property ASYNC_REG true [get_cells i_pulpissimo/soc_domain_i/pulp_soc_i/soc_peripherals_i/apb_adv_timer_i/u_tim3/u_in_stage/r_ls_clk_sync_reg*] +set_property ASYNC_REG true [get_cells i_pulpissimo/soc_domain_i/pulp_soc_i/soc_peripherals_i/i_apb_timer_unit/s_ref_clk*] +set_property ASYNC_REG true [get_cells i_pulpissimo/soc_domain_i/pulp_soc_i/soc_peripherals_i/i_ref_clk_sync/i_pulp_sync/r_reg_reg*] +set_property ASYNC_REG true [get_cells i_pulpissimo/soc_domain_i/pulp_soc_i/soc_peripherals_i/u_evnt_gen/r_ls_sync_reg*] + +# Create asynchronous clock group between slow-clk and SoC clock. Those clocks +# are considered asynchronously and proper synchronization regs are in place +set_clock_groups -asynchronous -group [get_clocks -of_objects [get_pins i_pulpissimo/safe_domain_i/i_slow_clk_gen/slow_clk_o]] -group [get_clocks -of_objects [get_pins i_pulpissimo/soc_domain_i/pulp_soc_i/i_clk_rst_gen/i_fpga_clk_gen/soc_clk_o]] diff --git a/fpga/pulpemu/tcl/debug.tcl b/fpga/pulpemu/tcl/debug.tcl new file mode 100644 index 00000000..a033ae46 --- /dev/null +++ b/fpga/pulpemu/tcl/debug.tcl @@ -0,0 +1,96 @@ +set_property mark_debug true [get_nets [list {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[28]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[1]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[47]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[33]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[62]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[1]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[13]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[42]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[27]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[56]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[9]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[16]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[6]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[6]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[35]} ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_ready {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[21]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[50]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_ar_addr[15]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_aw_addr[9]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[5]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[30]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[15]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[44]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[4]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[23]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[23]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[52]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[0]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[39]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[18]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[48]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[32]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[61]} ulpsoc_i/soc_bus_wrap_i/soc_l2_master_ar_valid {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[11]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[21]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[40]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[27]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[56]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[11]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_ar_addr[7]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[7]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[36]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[4]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[20]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[0]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[29]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[29]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[58]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[15]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[44]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_aw_addr[15]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[24]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[53]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[38]} ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_valid {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[27]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[17]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[46]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[32]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[61]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[17]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[12]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[41]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[26]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[55]} ulpsoc_i/soc_bus_wrap_i/soc_l2_master_ar_ready {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[8]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[15]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[5]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[34]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[63]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[4]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[20]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_ar_addr[14]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_aw_addr[7]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[2]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[59]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[14]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[43]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[3]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[22]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[22]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[51]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[9]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[38]} ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_b_valid {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[1]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[47]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[31]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[60]} ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_ready {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[6]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[25]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[25]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[54]} ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_ready ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_b_ready {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[11]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[40]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_aw_addr[11]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[4]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[20]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[34]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[63]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[23]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[13]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[42]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[29]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[58]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[13]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[9]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[38]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[22]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[51]} ulpsoc_i/soc_bus_wrap_i/soc_l2_master_b_valid {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[11]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[30]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[5]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[30]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[17]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[46]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_ar_addr[10]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_aw_addr[4]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[26]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[55]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[3]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[10]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[29]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[18]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[48]} ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_valid {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[34]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[63]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[18]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[14]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[43]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[28]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[57]} ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_ready {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[17]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[7]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[7]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[36]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[22]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[51]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_ar_addr[3]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[31]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[60]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[16]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[45]} ulpsoc_i/soc_bus_wrap_i/soc_l2_master_b_ready {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[5]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[24]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[24]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[53]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[3]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[10]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_aw_addr[10]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[19]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[49]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[33]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[62]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[22]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[12]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[41]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[28]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[57]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[12]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_ar_addr[9]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[8]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[37]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[21]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[50]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[10]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[2]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[2]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[59]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[16]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[45]} ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_ready {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_aw_addr[3]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[25]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[54]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[0]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[39]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[13]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[3]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[32]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[61]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[18]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[48]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_ar_addr[12]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_aw_addr[8]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[28]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[57]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[12]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[41]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[30]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[20]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[4]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[20]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[7]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[36]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[16]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[45]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[2]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[59]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[18]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[9]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[9]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[38]} ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_valid {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[24]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[53]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_ar_addr[5]} ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_valid {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[33]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[62]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[1]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[47]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[7]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[26]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[26]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[55]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[12]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[41]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_aw_addr[12]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[21]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[50]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[35]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[24]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[14]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[43]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[2]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[59]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[14]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[0]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[39]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[23]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[52]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[12]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[31]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[31]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[60]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[1]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[47]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_ar_addr[11]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_aw_addr[5]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[27]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[56]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[11]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[40]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[2]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[19]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[19]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[49]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[6]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[35]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[15]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[44]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[29]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[58]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[1]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[8]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[8]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[37]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[23]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[52]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_ar_addr[4]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[32]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[61]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[17]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[46]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[20]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[10]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[3]} ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_ready {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[26]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[55]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[10]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_ar_addr[6]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[6]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[35]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[19]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[49]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[9]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[28]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[28]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[57]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[14]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[43]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_aw_addr[14]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[23]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[52]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[37]} ulpsoc_i/soc_bus_wrap_i/soc_l2_master_aw_valid {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[26]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[16]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[45]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[31]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[60]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[16]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[11]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[40]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[25]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[54]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[7]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[14]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[4]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[33]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[62]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[19]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[49]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_ar_addr[13]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_aw_addr[6]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[29]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[58]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[13]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[42]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[31]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[21]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[21]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[50]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[8]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[37]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[17]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[46]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[5]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[30]} ulpsoc_i/soc_bus_wrap_i/soc_l2_master_aw_ready {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[19]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[0]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[39]} ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_last {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[25]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[54]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[0]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_ar_addr[8]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[34]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[63]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[18]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[48]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[8]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[27]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[27]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[56]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[13]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[42]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_aw_addr[13]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[22]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[51]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[36]} ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_valid {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[15]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[25]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[44]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[5]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[30]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[15]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[3]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[10]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[24]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[53]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[6]}]] +create_debug_core u_ila_0 ila +set_property C_DATA_DEPTH 4096 [get_debug_cores u_ila_0] +set_property C_TRIGIN_EN false [get_debug_cores u_ila_0] +set_property C_TRIGOUT_EN false [get_debug_cores u_ila_0] +set_property C_ADV_TRIGGER false [get_debug_cores u_ila_0] +set_property C_INPUT_PIPE_STAGES 6 [get_debug_cores u_ila_0] +set_property C_EN_STRG_QUAL false [get_debug_cores u_ila_0] +set_property ALL_PROBE_SAME_MU true [get_debug_cores u_ila_0] +set_property ALL_PROBE_SAME_MU_CNT 1 [get_debug_cores u_ila_0] +set_property port_width 1 [get_debug_ports u_ila_0/clk] +connect_debug_port u_ila_0/clk [get_nets [list ps7_wrapper_i/ps7_i/ps7_clk ]] +set_property port_width 13 [get_debug_ports u_ila_0/probe0] +connect_debug_port u_ila_0/probe0 [get_nets [list {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_ar_addr[3]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_ar_addr[4]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_ar_addr[5]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_ar_addr[6]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_ar_addr[7]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_ar_addr[8]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_ar_addr[9]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_ar_addr[10]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_ar_addr[11]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_ar_addr[12]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_ar_addr[13]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_ar_addr[14]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_ar_addr[15]} ]] +create_debug_port u_ila_0 probe +set_property port_width 64 [get_debug_ports u_ila_0/probe1] +connect_debug_port u_ila_0/probe1 [get_nets [list {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[0]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[1]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[2]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[3]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[4]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[5]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[6]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[7]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[8]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[9]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[10]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[11]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[12]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[13]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[14]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[15]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[16]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[17]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[18]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[19]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[20]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[21]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[22]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[23]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[24]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[25]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[26]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[27]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[28]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[29]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[30]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[31]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[32]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[33]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[34]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[35]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[36]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[37]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[38]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[39]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[40]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[41]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[42]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[43]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[44]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[45]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[46]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[47]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[48]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[49]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[50]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[51]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[52]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[53]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[54]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[55]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[56]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[57]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[58]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[59]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[60]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[61]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[62]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_data[63]} ]] +create_debug_port u_ila_0 probe +set_property port_width 64 [get_debug_ports u_ila_0/probe2] +connect_debug_port u_ila_0/probe2 [get_nets [list {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[0]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[1]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[2]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[3]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[4]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[5]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[6]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[7]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[8]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[9]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[10]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[11]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[12]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[13]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[14]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[15]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[16]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[17]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[18]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[19]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[20]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[21]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[22]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[23]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[24]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[25]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[26]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[27]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[28]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[29]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[30]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[31]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[32]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[33]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[34]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[35]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[36]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[37]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[38]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[39]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[40]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[41]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[42]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[43]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[44]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[45]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[46]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[47]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[48]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[49]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[50]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[51]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[52]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[53]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[54]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[55]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[56]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[57]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[58]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[59]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[60]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[61]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[62]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_data[63]} ]] +create_debug_port u_ila_0 probe +set_property port_width 32 [get_debug_ports u_ila_0/probe3] +connect_debug_port u_ila_0/probe3 [get_nets [list {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[0]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[1]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[2]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[3]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[4]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[5]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[6]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[7]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[8]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[9]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[10]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[11]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[12]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[13]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[14]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[15]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[16]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[17]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[18]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[19]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[20]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[21]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[22]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[23]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[24]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[25]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[26]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[27]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[28]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[29]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[30]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_addr[31]} ]] +create_debug_port u_ila_0 probe +set_property port_width 32 [get_debug_ports u_ila_0/probe4] +connect_debug_port u_ila_0/probe4 [get_nets [list {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[0]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[1]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[2]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[3]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[4]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[5]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[6]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[7]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[8]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[9]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[10]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[11]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[12]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[13]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[14]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[15]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[16]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[17]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[18]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[19]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[20]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[21]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[22]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[23]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[24]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[25]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[26]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[27]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[28]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[29]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[30]} {ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_addr[31]} ]] +create_debug_port u_ila_0 probe +set_property port_width 64 [get_debug_ports u_ila_0/probe5] +connect_debug_port u_ila_0/probe5 [get_nets [list {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[0]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[1]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[2]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[3]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[4]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[5]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[6]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[7]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[8]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[9]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[10]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[11]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[12]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[13]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[14]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[15]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[16]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[17]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[18]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[19]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[20]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[21]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[22]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[23]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[24]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[25]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[26]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[27]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[28]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[29]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[30]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[31]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[32]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[33]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[34]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[35]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[36]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[37]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[38]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[39]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[40]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[41]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[42]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[43]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[44]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[45]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[46]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[47]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[48]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[49]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[50]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[51]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[52]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[53]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[54]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[55]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[56]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[57]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[58]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[59]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[60]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[61]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[62]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_data[63]} ]] +create_debug_port u_ila_0 probe +set_property port_width 64 [get_debug_ports u_ila_0/probe6] +connect_debug_port u_ila_0/probe6 [get_nets [list {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[0]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[1]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[2]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[3]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[4]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[5]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[6]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[7]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[8]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[9]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[10]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[11]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[12]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[13]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[14]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[15]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[16]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[17]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[18]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[19]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[20]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[21]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[22]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[23]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[24]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[25]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[26]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[27]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[28]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[29]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[30]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[31]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[32]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[33]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[34]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[35]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[36]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[37]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[38]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[39]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[40]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[41]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[42]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[43]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[44]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[45]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[46]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[47]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[48]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[49]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[50]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[51]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[52]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[53]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[54]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[55]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[56]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[57]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[58]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[59]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[60]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[61]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[62]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_data[63]} ]] +create_debug_port u_ila_0 probe +set_property port_width 13 [get_debug_ports u_ila_0/probe7] +connect_debug_port u_ila_0/probe7 [get_nets [list {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_aw_addr[3]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_aw_addr[4]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_aw_addr[5]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_aw_addr[6]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_aw_addr[7]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_aw_addr[8]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_aw_addr[9]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_aw_addr[10]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_aw_addr[11]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_aw_addr[12]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_aw_addr[13]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_aw_addr[14]} {ulpsoc_i/soc_bus_wrap_i/soc_l2_master_aw_addr[15]} ]] +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe8] +connect_debug_port u_ila_0/probe8 [get_nets [list ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_ready ]] +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe9] +connect_debug_port u_ila_0/probe9 [get_nets [list ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_ar_valid ]] +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe10] +connect_debug_port u_ila_0/probe10 [get_nets [list ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_ready ]] +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe11] +connect_debug_port u_ila_0/probe11 [get_nets [list ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_aw_valid ]] +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe12] +connect_debug_port u_ila_0/probe12 [get_nets [list ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_b_ready ]] +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe13] +connect_debug_port u_ila_0/probe13 [get_nets [list ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_b_valid ]] +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe14] +connect_debug_port u_ila_0/probe14 [get_nets [list ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_ready ]] +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe15] +connect_debug_port u_ila_0/probe15 [get_nets [list ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_r_valid ]] +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe16] +connect_debug_port u_ila_0/probe16 [get_nets [list ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_last ]] +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe17] +connect_debug_port u_ila_0/probe17 [get_nets [list ulpsoc_i/soc_bus_wrap_i/cluster_instr_slave_w_ready ]] +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe18] +connect_debug_port u_ila_0/probe18 [get_nets [list ulpsoc_i/soc_bus_wrap_i/soc_l2_master_ar_ready ]] +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe19] +connect_debug_port u_ila_0/probe19 [get_nets [list ulpsoc_i/soc_bus_wrap_i/soc_l2_master_ar_valid ]] +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe20] +connect_debug_port u_ila_0/probe20 [get_nets [list ulpsoc_i/soc_bus_wrap_i/soc_l2_master_aw_ready ]] +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe21] +connect_debug_port u_ila_0/probe21 [get_nets [list ulpsoc_i/soc_bus_wrap_i/soc_l2_master_aw_valid ]] +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe22] +connect_debug_port u_ila_0/probe22 [get_nets [list ulpsoc_i/soc_bus_wrap_i/soc_l2_master_b_ready ]] +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe23] +connect_debug_port u_ila_0/probe23 [get_nets [list ulpsoc_i/soc_bus_wrap_i/soc_l2_master_b_valid ]] +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe24] +connect_debug_port u_ila_0/probe24 [get_nets [list ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_ready ]] +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe25] +connect_debug_port u_ila_0/probe25 [get_nets [list ulpsoc_i/soc_bus_wrap_i/soc_l2_master_r_valid ]] +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe26] +connect_debug_port u_ila_0/probe26 [get_nets [list ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_ready ]] +create_debug_port u_ila_0 probe +set_property port_width 1 [get_debug_ports u_ila_0/probe27] +connect_debug_port u_ila_0/probe27 [get_nets [list ulpsoc_i/soc_bus_wrap_i/soc_l2_master_w_valid ]] + diff --git a/fpga/pulpemu/tcl/false_paths.tcl b/fpga/pulpemu/tcl/false_paths.tcl new file mode 100644 index 00000000..e483856d --- /dev/null +++ b/fpga/pulpemu/tcl/false_paths.tcl @@ -0,0 +1,11 @@ +set_false_path -from [get_pins {ulpsoc_i/cluster_i/ulpcluster_i/cluster_int_region_i/cluster_peripherals_i/cluster_control_unit_i/r_fetch_en_reg[*]/C}] +set_false_path -from [get_pins ulpsoc_i/cluster_i/ulpcluster_i/rstgen_i/s_rst_n_reg/C] +set_false_path -from [get_pins ulpsoc_i/i_clk_rst_gen/i_rst_gen_soc/s_rst_n_reg/C] +set_false_path -through [get_nets {ulpsoc_i/i_clk_rst_gen/rstn_cluster_sync_o}] +set_false_path -through [get_nets {ulpsoc_i/i_clk_rst_gen/rstn_sync_o}] +#set_false_path -from [get_clocks {ref_clk_i}] -to [get_clocks {ulpsoc_clk}] +#set_false_path -from [get_clocks {ulpsoc_clk}] -to [get_clocks {ref_clk_i}] +#set_false_path -from [get_clocks {spi_clk}] -to [get_clocks {ulpsoc_clk}] +#set_false_path -from [get_clocks {ulpsoc_clk}] -to [get_clocks {spi_clk}] +#set_false_path -from [get_clocks {ref_clk_i}] -to [get_clocks {spi_clk}] +#set_false_path -from [get_clocks {spi_clk}] -to [get_clocks {ref_clk_i}] diff --git a/fpga/pulpemu/tcl/floorplan.xdc b/fpga/pulpemu/tcl/floorplan.xdc new file mode 100644 index 00000000..124ba594 --- /dev/null +++ b/fpga/pulpemu/tcl/floorplan.xdc @@ -0,0 +1,6 @@ +create_pblock pblock_cluster_i +add_cells_to_pblock [get_pblocks pblock_cluster_i] [get_cells -quiet [list ulpsoc_i/cluster_i]] +resize_pblock [get_pblocks pblock_cluster_i] -add {SLICE_X32Y62:SLICE_X143Y274} +resize_pblock [get_pblocks pblock_cluster_i] -add {DSP48_X2Y26:DSP48_X5Y109} +resize_pblock [get_pblocks pblock_cluster_i] -add {RAMB18_X3Y26:RAMB18_X6Y109} +resize_pblock [get_pblocks pblock_cluster_i] -add {RAMB36_X3Y13:RAMB36_X6Y54} diff --git a/fpga/pulpemu/tcl/fmc_board.ucf b/fpga/pulpemu/tcl/fmc_board.ucf new file mode 100644 index 00000000..2a480718 --- /dev/null +++ b/fpga/pulpemu/tcl/fmc_board.ucf @@ -0,0 +1,73 @@ + +NET FMC_MSPI_SCK LOC = AD16 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L18P_T2_10 +NET FMC_MSPI_SDIO03 LOC = AJ16 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L4P_T0_10 +NET FMC_MSPI_SDIO02 LOC = AA15 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L20P_T3_10 +NET FMC_MSPI_SDIO01 LOC = AK16 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L4N_T0_10 +NET FMC_MSPI_SDIO00 LOC = AA14 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L20N_T3_10 +NET FMC_MSPI_NCS0 LOC = AH28 | IOSTANDARD=LVCMOS25; # Bank 12 VCCO - VADJ_FPGA - IO_L19P_T3_12 +NET FMC_MSPI_NCS1 LOC = AF30 | IOSTANDARD=LVCMOS25; # Bank 12 VCCO - VADJ_FPGA - IO_L16P_T2_12 +NET FMC_MSPI_NCS2 LOC = AG30 | IOSTANDARD=LVCMOS25; # Bank 12 VCCO - VADJ_FPGA - IO_L16N_T2_12 + +NET FMC_SSPI_SCK LOC = AE13 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L11P_T1_SRCC_10 +NET FMC_SSPI_NCS LOC = AF13 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L11N_T1_SRCC_10 +NET FMC_SSPI_SDIO03 LOC = AE12 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L7P_T1_10 +NET FMC_SSPI_SDIO02 LOC = AF12 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L7N_T1_10 +NET FMC_SSPI_SDIO01 LOC = AJ15 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L5P_T0_10 +NET FMC_SSPI_SDIO00 LOC = AK15 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L5N_T0_10 + +NET FMC_SENS_INT0 LOC = AB15 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L22P_T3_10 +NET FMC_SENS_INT1 LOC = AB14 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L22N_T3_10 +NET FMC_SENS_INT2 LOC = AH26 | IOSTANDARD=LVCMOS25; # Bank 12 VCCO - VADJ_FPGA - IO_L23P_T3_12 + +NET FMC_I2S_SCK0 LOC = AG29 | IOSTANDARD=LVCMOS25; # Bank 12 VCCO - VADJ_FPGA - IO_L15N_T2_DQS_12 +NET FMC_I2S_SDI0 LOC = AE25 | IOSTANDARD=LVCMOS25; # Bank 12 VCCO - VADJ_FPGA - IO_L18P_T2_12 +NET FMC_I2S_SDI1 LOC = AD25 | IOSTANDARD=LVCMOS25; # Bank 12 VCCO - VADJ_FPGA - IO_L10P_T1_12 +NET FMC_I2S_SDI2 LOC = AF25 | IOSTANDARD=LVCMOS25; # Bank 12 VCCO - VADJ_FPGA - IO_L18N_T2_12 +NET FMC_I2S_SDI3 LOC = AE26 | IOSTANDARD=LVCMOS25; # Bank 12 VCCO - VADJ_FPGA - IO_L10N_T1_12 + +NET FMC_I2C_SCL LOC = Y30 | IOSTANDARD=LVCMOS25; # Bank 12 VCCO - VADJ_FPGA - IO_L1P_T0_12 +NET FMC_I2C_SDA LOC = AA30 | IOSTANDARD=LVCMOS25; # Bank 12 VCCO - VADJ_FPGA - IO_L1N_T0_12 + +NET FMC_ADC_SDI0 LOC = AD29 | IOSTANDARD=LVCMOS25; # Bank 12 VCCO - VADJ_FPGA - IO_L9N_T1_DQS_12 +NET FMC_ADC_SDI1 LOC = AB29 | IOSTANDARD=LVCMOS25; # Bank 12 VCCO - VADJ_FPGA - IO_L2P_T0_12 +NET FMC_ADC_SDI2 LOC = AB30 | IOSTANDARD=LVCMOS25; # Bank 12 VCCO - VADJ_FPGA - IO_L2N_T0_12 +NET FMC_ADC_SDI3 LOC = Y26 | IOSTANDARD=LVCMOS25; # Bank 12 VCCO - VADJ_FPGA - IO_L3P_T0_DQS_12 +NET FMC_ADC_SCK LOC = Y27 | IOSTANDARD=LVCMOS25; # Bank 12 VCCO - VADJ_FPGA - IO_L3N_T0_DQS_12 +NET FMC_ADC_NCS LOC = AH27 | IOSTANDARD=LVCMOS25; # Bank 12 VCCO - VADJ_FPGA - IO_L23N_T3_12 + +NET FMC_GPIO0 LOC = AF15 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L14P_T2_SRCC_10 +NET FMC_GPIO1 LOC = AG15 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L14N_T2_SRCC_10 +NET FMC_GPIO2 LOC = AB12 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L21P_T3_DQS_10 +NET FMC_GPIO3 LOC = AC12 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L21N_T3_DQS_10 +NET FMC_GPIO4 LOC = AD13 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L9N_T1_DQS_10 +NET FMC_GPIO5 LOC = AD14 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L9P_T1_DQS_10 +NET FMC_GPIO6 LOC = AH12 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L10N_T1_10 +NET FMC_GPIO7 LOC = AG12 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L10P_T1_10 + +NET FMC_LOOP0_O LOC = AE18 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L17P_T2_10 +NET FMC_LOOP0_I LOC = AE17 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L17N_T2_10 +NET FMC_LOOP1_O LOC = AG26 | IOSTANDARD=LVCMOS25; # Bank 12 VCCO - VADJ_FPGA - IO_L17P_T2_12 +NET FMC_LOOP1_I LOC = AG27 | IOSTANDARD=LVCMOS25; # Bank 12 VCCO - VADJ_FPGA - IO_L17N_T2_12 +NET FMC_LOOP2_O LOC = AK27 | IOSTANDARD=LVCMOS25; # Bank 12 VCCO - VADJ_FPGA - IO_L22P_T3_12 +NET FMC_LOOP2_I LOC = AK28 | IOSTANDARD=LVCMOS25; # Bank 12 VCCO - VADJ_FPGA - IO_L22N_T3_12 +NET FMC_LOOP3_O LOC = AE16 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L16P_T2_10 +NET FMC_LOOP3_I LOC = AE15 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L16N_T2_10 +NET FMC_LOOP4_O LOC = AH14 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L8P_T1_10 +NET FMC_LOOP4_I LOC = AH13 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L8N_T1_10 + +NET FMC_CAM_PCLK LOC = AB27 | IOSTANDARD=LVCMOS25; # Bank 12 VCCO - VADJ_FPGA - IO_L11P_T1_SRCC_12 +NET FMC_CAM_HREF LOC = AC27 | IOSTANDARD=LVCMOS25; # Bank 12 VCCO - VADJ_FPGA - IO_L11N_T1_SRCC_12 +NET FMC_CAM_VSYNC LOC = AF17 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L15N_T2_DQS_10 +NET FMC_CAM_D0 LOC = AK26 | IOSTANDARD=LVCMOS25; # Bank 12 VCCO - VADJ_FPGA - IO_L24N_T3_12 +NET FMC_CAM_D1 LOC = AJ26 | IOSTANDARD=LVCMOS25; # Bank 12 VCCO - VADJ_FPGA - IO_L24P_T3_12 +NET FMC_CAM_D2 LOC = AE27 | IOSTANDARD=LVCMOS25; # Bank 12 VCCO - VADJ_FPGA - IO_L14P_T2_SRCC_12 +NET FMC_CAM_D3 LOC = AJ30 | IOSTANDARD=LVCMOS25; # Bank 12 VCCO - VADJ_FPGA - IO_L20P_T3_12 +NET FMC_CAM_D4 LOC = AF27 | IOSTANDARD=LVCMOS25; # Bank 12 VCCO - VADJ_FPGA - IO_L14N_T2_SRCC_12 +NET FMC_CAM_D5 LOC = AK30 | IOSTANDARD=LVCMOS25; # Bank 12 VCCO - VADJ_FPGA - IO_L20N_T3_12 +NET FMC_CAM_D6 LOC = AH16 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L6N_T0_VREF_10 +NET FMC_CAM_D7 LOC = AJ29 | IOSTANDARD=LVCMOS25; # Bank 12 VCCO - VADJ_FPGA - IO_L21N_T3_DQS_12 +NET FMC_CAM_SCK LOC = AC14 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L19P_T3_10 +NET FMC_CAM_MOSI LOC = AC13 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L19N_T3_VREF_10 +NET FMC_CAM_MISO LOC = AF18 | IOSTANDARD=LVCMOS25; # Bank 10 VCCO - VADJ_FPGA - IO_L15P_T2_DQS_10 +NET FMC_CAM_NCS LOC = AJ28 | IOSTANDARD=LVCMOS25; # Bank 12 VCCO - VADJ_FPGA - IO_L21P_T3_DQS_12 + diff --git a/fpga/pulpemu/tcl/fmc_board_vcu118.xdc b/fpga/pulpemu/tcl/fmc_board_vcu118.xdc new file mode 100644 index 00000000..efd23a4d --- /dev/null +++ b/fpga/pulpemu/tcl/fmc_board_vcu118.xdc @@ -0,0 +1,173 @@ +############################################################# +# _____ ____ _____ _ _ _ # +# |_ _/ __ \ / ____| | | | | (_) # +# | || | | |_____| (___ ___| |_| |_ _ _ __ __ _ ___ # +# | || | | |______\___ \ / _ \ __| __| | '_ \ / _` / __| # +# _| || |__| | ____) | __/ |_| |_| | | | | (_| \__ \ # +# |_____\____/ |_____/ \___|\__|\__|_|_| |_|\__, |___/ # +# __/ | # +# |___/ # +############################################################# + +## Sys clock (ok) +set_property -dict {PACKAGE_PIN AY23 IOSTANDARD LVDS} [get_ports ref_clk_n] +set_property -dict {PACKAGE_PIN AY24 IOSTANDARD LVDS} [get_ports ref_clk_p] + +## Reset (ok) +set_property -dict {PACKAGE_PIN L19 IOSTANDARD LVCMOS12} [get_ports pad_reset] + +## Buttons (ok) +#set_property -dict {PACKAGE_PIN BF22 IOSTANDARD LVCMOS18} [get_ports btn0_i] +#set_property -dict {PACKAGE_PIN BD23 IOSTANDARD LVCMOS18} [get_ports btn1_i] +#set_property -dict {PACKAGE_PIN BE23 IOSTANDARD LVCMOS18} [get_ports btn2_i] +#set_property -dict {PACKAGE_PIN BB24 IOSTANDARD LVCMOS18} [get_ports btn3_i] + +## PMOD 0 (J52 on Virtex) (ok) +## PMOD 0 --- JTAG +###################################################################### +# JTAG mapping (OK) +###################################################################### +set_property -dict {PACKAGE_PIN AY14 IOSTANDARD LVCMOS18} [get_ports pad_jtag_tms] +set_property -dict {PACKAGE_PIN AY15 IOSTANDARD LVCMOS18} [get_ports pad_jtag_tdi] +set_property -dict {PACKAGE_PIN AW15 IOSTANDARD LVCMOS18} [get_ports pad_jtag_tdo] +set_property -dict {PACKAGE_PIN AV15 IOSTANDARD LVCMOS18} [get_ports pad_jtag_tck] + + +#set_property -dict {PACKAGE_PIN AV16 IOSTANDARD LVCMOS18} [get_ports pad_pmod0_4] +#set_property -dict {PACKAGE_PIN AU16 IOSTANDARD LVCMOS18} [get_ports pad_pmod0_5] +#set_property -dict {PACKAGE_PIN AT15 IOSTANDARD LVCMOS18} [get_ports pad_pmod0_6] +#set_property -dict {PACKAGE_PIN AT16 IOSTANDARD LVCMOS18} [get_ports pad_pmod0_7] + +## PMOD 1 (ok) +#set_property -dict {PACKAGE_PIN N28 IOSTANDARD LVCMOS12} [get_ports pad_pmod1_0] +#set_property -dict {PACKAGE_PIN M30 IOSTANDARD LVCMOS12} [get_ports pad_pmod1_1] +#set_property -dict {PACKAGE_PIN N30 IOSTANDARD LVCMOS12} [get_ports pad_pmod1_2] +#set_property -dict {PACKAGE_PIN P30 IOSTANDARD LVCMOS12} [get_ports pad_pmod1_3] +#set_property -dict {PACKAGE_PIN P29 IOSTANDARD LVCMOS12} [get_ports pad_pmod1_4] +#set_property -dict {PACKAGE_PIN L31 IOSTANDARD LVCMOS12} [get_ports pad_pmod1_5] +#set_property -dict {PACKAGE_PIN M31 IOSTANDARD LVCMOS12} [get_ports pad_pmod1_6] +#set_property -dict {PACKAGE_PIN R29 IOSTANDARD LVCMOS12} [get_ports pad_pmod1_7] + +## UART (ok) +###################################################################### +# UART mapping +###################################################################### +set_property -dict {PACKAGE_PIN AW25 IOSTANDARD LVCMOS18} [get_ports pad_uart_rx] +set_property -dict {PACKAGE_PIN BB21 IOSTANDARD LVCMOS18} [get_ports pad_uart_tx] + +#set_property -dict {PACKAGE_PIN BB22 IOSTANDARD LVCMOS18} [get_ports pad_uart_rts] +#set_property -dict {PACKAGE_PIN AY25 IOSTANDARD LVCMOS18} [get_ports pad_uart_cts] + +## LEDs (ok) +#set_property -dict {PACKAGE_PIN AT32 IOSTANDARD LVCMOS12} [get_ports led0_o] +#set_property -dict {PACKAGE_PIN AV34 IOSTANDARD LVCMOS12} [get_ports led1_o] +#set_property -dict {PACKAGE_PIN AY30 IOSTANDARD LVCMOS12} [get_ports led2_o] +#set_property -dict {PACKAGE_PIN BB32 IOSTANDARD LVCMOS12} [get_ports led3_o] + +## Switches (ok) +#set_property -dict {PACKAGE_PIN B17 IOSTANDARD LVCMOS12} [get_ports switch0_i] +#set_property -dict {PACKAGE_PIN G16 IOSTANDARD LVCMOS12} [get_ports switch1_i] +#set_property -dict {PACKAGE_PIN J16 IOSTANDARD LVCMOS12} [get_ports switch2_i] +#set_property -dict {PACKAGE_PIN D21 IOSTANDARD LVCMOS12} [get_ports switch3_i] + +## I2C Bus +#set_property -dict {PACKAGE_PIN J10 IOSTANDARD LVCMOS33} [get_ports pad_i2c0_scl] +#set_property -dict {PACKAGE_PIN J11 IOSTANDARD LVCMOS33} [get_ports pad_i2c0_sda] + +## HDMI CTL +#set_property -dict {PACKAGE_PIN F15 IOSTANDARD LVCMOS33} [get_ports pad_hdmi_scl] +#set_property -dict {PACKAGE_PIN F16 IOSTANDARD LVCMOS33} [get_ports pad_hdmi_sda] + + +###################################################################### +# QSPI mapping (OK) +###################################################################### +# PULP pad_qspi_sdio0 - FPGA BD11 - FMC H8 +set_property -dict "PACKAGE_PIN BD11 IOSTANDARD LVCMOS18" [get_ports FMC_qspi_sdio0] +# PULP pad_qspi_sdio1 - FPGA BC13 - FMC G16 +set_property -dict "PACKAGE_PIN BC13 IOSTANDARD LVCMOS18" [get_ports FMC_qspi_sdio1] +# PULP pad_qspi_sdio2 - FPGA BF12 - FMC H10 +set_property -dict "PACKAGE_PIN BF12 IOSTANDARD LVCMOS18" [get_ports FMC_qspi_sdio2] +# PULP pad_qspi_sdio3 - FPGA AY9 - FMC G6 +set_property -dict "PACKAGE_PIN AY9 IOSTANDARD LVCMOS18" [get_ports FMC_qspi_sdio3] +# PULP pad_qspi_csn0 - FPGA BB16 - FMC H19 +set_property -dict "PACKAGE_PIN BB16 IOSTANDARD LVCMOS18" [get_ports FMC_qspi_csn0] +# PULP pad_qspi_sck - FPGA BC14 - FMC G15 +set_property -dict "PACKAGE_PIN BC14 IOSTANDARD LVCMOS18" [get_ports FMC_qspi_sck] +# GAP pad_spim0_sck - FPGA BC11 - FMC H7 +set_property -dict "PACKAGE_PIN BC11 IOSTANDARD LVCMOS18" [get_ports FMC_qspi_csn1] + +###################################################################### +# SDIO mapping (TO CHECK) +###################################################################### +# PULP pad_sdio_sdio0 - FPGA N28 - ZCU102 GPIO PMOD HEADER J53.1 +set_property -dict "PACKAGE_PIN N28 IOSTANDARD LVCMOS18" [get_ports FMC_sdio_data0] +# PULP pad_sdio_sdio1 - FPGA M30 - ZCU102 GPIO PMOD HEADER J53.3 +set_property -dict "PACKAGE_PIN M30 IOSTANDARD LVCMOS18" [get_ports FMC_sdio_data1] +# PULP pad_sdio_sdio2 - FPGA N30 - ZCU102 GPIO PMOD HEADER J53.5 +set_property -dict "PACKAGE_PIN N30 IOSTANDARD LVCMOS18" [get_ports FMC_sdio_data2] +# PULP pad_sdio_sdio3 - FPGA P30 - ZCU102 GPIO PMOD HEADER J53.7 +set_property -dict "PACKAGE_PIN P30 IOSTANDARD LVCMOS18" [get_ports FMC_sdio_data3] +# PULP pad_sdio_cmd - FPGA P29 - ZCU102 GPIO PMOD HEADER J53.2 +set_property -dict "PACKAGE_PIN P29 IOSTANDARD LVCMOS18" [get_ports FMC_sdio_cmd] +# PULP pad_sdio_sck - FPGA L31 - ZCU102 GPIO PMOD HEADER J53.4 +set_property -dict "PACKAGE_PIN L31 IOSTANDARD LVCMOS18" [get_ports FMC_sdio_sck] + +###################################################################### +# I2S master mapping (OK) +###################################################################### +# PULP pad_i2s_mst_sck - FPGA AR13 - FMC H29 +set_property -dict "PACKAGE_PIN AR13 IOSTANDARD LVCMOS18" [get_ports FMC_i2s0_sck] +# PULP pad_i2s_mst_ws - FPGA AW8 - FMC C18 +set_property -dict "PACKAGE_PIN AW8 IOSTANDARD LVCMOS18" [get_ports FMC_i2s0_ws] +# PULP pad_i2s_slv_sdi0 - FPGA BB7 - FMC D1 -- not mappable --mapped into H2 (dummy) +set_property -dict "PACKAGE_PIN BB7 IOSTANDARD LVCMOS18" [get_ports FMC_i2s0_sdi] +# PULP pad_i2s_slv_sdi1 - FPGA BD13 - FMC C10 +set_property -dict "PACKAGE_PIN BD13 IOSTANDARD LVCMOS18" [get_ports FMC_i2s1_sdi] + +###################################################################### +# I2C0 mapping (OK) +###################################################################### +# PULP pad_i3c2_scl - FPGA AJ12 - FMC H38 +set_property -dict "PACKAGE_PIN AJ12 IOSTANDARD LVCMOS18" [get_ports FMC_i2c0_scl] +# PULP pad_i3c2_sda - FPGA AJ13 - FMC H37 +set_property -dict "PACKAGE_PIN AJ13 IOSTANDARD LVCMOS18" [get_ports FMC_i2c0_sda] + +###################################################################### +# Camera mapping (OK) +###################################################################### +# PULP pad_cam_pclk - FPGA AR14 - FMC D20 +set_property -dict "PACKAGE_PIN AR14 IOSTANDARD LVCMOS18" [get_ports FMC_cam_pclk] +# PULP pad_cam_hsync - FPGA AT14 - FMC D21 +set_property -dict "PACKAGE_PIN AT14 IOSTANDARD LVCMOS18" [get_ports FMC_cam_hsync] +# PULP pad_cam_data0 - FPGA AP16 - FMC D24 +set_property -dict "PACKAGE_PIN AP16 IOSTANDARD LVCMOS18" [get_ports FMC_cam_data0] +# PULP pad_cam_data1 - FPGA AN16 - FMC D23 +set_property -dict "PACKAGE_PIN AN16 IOSTANDARD LVCMOS18" [get_ports FMC_cam_data1] +# PULP pad_cam_data2 - FPGA AP12 - FMC C22 +set_property -dict "PACKAGE_PIN AP12 IOSTANDARD LVCMOS18" [get_ports FMC_cam_data2] +# PULP pad_cam_data3 - FPGA AK15 - FMC D26 +set_property -dict "PACKAGE_PIN AK15 IOSTANDARD LVCMOS18" [get_ports FMC_cam_data3] +# PULP pad_cam_data4 - FPGA AR12 - FMC C23 +set_property -dict "PACKAGE_PIN AR12 IOSTANDARD LVCMOS18" [get_ports FMC_cam_data4] +# PULP pad_cam_data5 - FPGA AL15 - FMC D27 +set_property -dict "PACKAGE_PIN AL15 IOSTANDARD LVCMOS18" [get_ports FMC_cam_data5] +# PULP pad_cam_data6 - FPGA AY7 - FMC D18 +set_property -dict "PACKAGE_PIN AY7 IOSTANDARD LVCMOS18" [get_ports FMC_cam_data6] +# PULP pad_cam_data7 - FPGA AM14 - FMC C27 +set_property -dict "PACKAGE_PIN AM14 IOSTANDARD LVCMOS18" [get_ports FMC_cam_data7] +# PULP pad_cam_vsync - FPGA AW7 - FMC C19 +set_property -dict "PACKAGE_PIN AW7 IOSTANDARD LVCMOS18" [get_ports FMC_cam_vsync] + + +#LED +#set_property PACKAGE_PIN AG14 [get_ports LED] +#set_property IOSTANDARD LVCMOS33 [get_ports LED] + +set_property MARK_DEBUG true [get_nets pulp_chip_i/pad_jtag_tdi] +set_property MARK_DEBUG true [get_nets pulp_chip_i/pad_jtag_tdo] +set_property MARK_DEBUG true [get_nets pulp_chip_i/pad_jtag_tck] +set_property MARK_DEBUG true [get_nets pulp_chip_i/pad_jtag_tms] +set_property MARK_DEBUG true [get_nets pulp_chip_i/pad_reset_n] +set_property MARK_DEBUG true [get_nets pulp_chip_i/s_ref_clk] +set_property MARK_DEBUG true [get_nets pulp_chip_i/s_bootsel] diff --git a/fpga/pulpemu/tcl/fmc_board_zc706.xdc b/fpga/pulpemu/tcl/fmc_board_zc706.xdc new file mode 100644 index 00000000..8dfb4082 --- /dev/null +++ b/fpga/pulpemu/tcl/fmc_board_zc706.xdc @@ -0,0 +1,229 @@ +###################################################################### +# Sensorboard J5 HPC0 FMC mapping +###################################################################### + +###################################################################### +# PWM mapping +###################################################################### +# GAP pad_pwm0 - FPGA AK17 - FMC H7 +set_property -dict "PACKAGE_PIN AK17 IOSTANDARD LVCMOS25" [get_ports FMC_pwm0] +# GAP pad_pwm1 - FPGA AB14 - FMC H20 +set_property -dict "PACKAGE_PIN AB14 IOSTANDARD LVCMOS25" [get_ports FMC_pwm1] +# GAP pad_pwm2 - FPGA AH26 - FMC H22 +set_property -dict "PACKAGE_PIN AH26 IOSTANDARD LVCMOS25" [get_ports FMC_pwm2] +# GAP pad_pwm3 - FPGA AH27 - FMC H23 +set_property -dict "PACKAGE_PIN AH27 IOSTANDARD LVCMOS25" [get_ports FMC_pwm3] + +###################################################################### +# QSPI mapping +###################################################################### +# GAP pad_qspi_sdio0 - FPGA AK18 - FMC H8 +set_property -dict "PACKAGE_PIN AK18 IOSTANDARD LVCMOS25" [get_ports FMC_qspi_sdio0] +# GAP pad_qspi_sdio1 - FPGA AF24 - FMC G16 +set_property -dict "PACKAGE_PIN AF24 IOSTANDARD LVCMOS25" [get_ports FMC_qspi_sdio1] +# GAP pad_qspi_sdio2 - FPGA AJ20 - FMC H10 +set_property -dict "PACKAGE_PIN AJ20 IOSTANDARD LVCMOS25" [get_ports FMC_qspi_sdio2] +# GAP pad_qspi_sdio3 - FPGA AF20 - FMC G6 +set_property -dict "PACKAGE_PIN AF20 IOSTANDARD LVCMOS25" [get_ports FMC_qspi_sdio3] +# GAP pad_qspi_csn0 - FPGA Y22 - FMC H19 +set_property -dict "PACKAGE_PIN Y22 IOSTANDARD LVCMOS25" [get_ports FMC_qspi_cs0] +# GAP pad_qspi_sck - FPGA AF23 - FMC G15 +set_property -dict "PACKAGE_PIN AF23 IOSTANDARD LVCMOS25" [get_ports FMC_qspi_sck] + +###################################################################### +# SDIO mapping (If use SDIO) +###################################################################### +# GAP pad_sdio_sdio0 - FPGA D20 - ZC706 GPIO PMOD HEADER J57.1 +#set_property -dict "PACKAGE_PIN D20 IOSTANDARD LVCMOS25" [get_ports FMC_qspi_sdio0] +# GAP pad_sdio_sdio1 - FPGA E20 - ZC706 GPIO PMOD HEADER J57.3 +#set_property -dict "PACKAGE_PIN E20 IOSTANDARD LVCMOS25" [get_ports FMC_qspi_sdio1] +# GAP pad_sdio_sdio2 - FPGA D22 - ZC706 GPIO PMOD HEADER J57.5 +#set_property -dict "PACKAGE_PIN D22 IOSTANDARD LVCMOS25" [get_ports FMC_qspi_sdio2] +# GAP pad_sdio_sdio3 - FPGA E22 - ZC706 GPIO PMOD HEADER J57.7 +#set_property -dict "PACKAGE_PIN E22 IOSTANDARD LVCMOS25" [get_ports FMC_qspi_sdio3] +# GAP pad_sdio_cmd - FPGA F20 - ZC706 GPIO PMOD HEADER J57.2 +#set_property -dict "PACKAGE_PIN F20 IOSTANDARD LVCMOS25" [get_ports FMC_qspi_cs0] +# GAP pad_sdio_sck - FPGA G20 - ZC706 GPIO PMOD HEADER J57.4 +#set_property -dict "PACKAGE_PIN G20 IOSTANDARD LVCMOS25" [get_ports FMC_qspi_sck] + +###################################################################### +# SPIM0 mapping +###################################################################### +# GAP pad_spim0_sck - FPGA AF19 - FMC G12 +set_property -dict "PACKAGE_PIN AF19 IOSTANDARD LVCMOS25" [get_ports FMC_spim0_sck] +# GAP pad_spim0_csn - FPGA AG19 - FMC G13 +set_property -dict "PACKAGE_PIN AG19 IOSTANDARD LVCMOS25" [get_ports FMC_spim0_cs0] +# GAP pad_spim0_miso - FPGA N27 - FMC G37 +set_property -dict "PACKAGE_PIN N27 IOSTANDARD LVCMOS25" [get_ports FMC_spim0_miso] +# GAP pad_spim0_mosi - FPGA AJ24 - FMC H14 +set_property -dict "PACKAGE_PIN AJ24 IOSTANDARD LVCMOS25" [get_ports FMC_spim0_mosi] + +###################################################################### +# I3C0 mapping +###################################################################### +# GAP pad_i3c0_scl - FPGA AB29 - FMC H34 +set_property -dict "PACKAGE_PIN AB29 IOSTANDARD LVCMOS25" [get_ports FMC_i3c0_scl] +# GAP pad_i3c0_sda - FPGA AE26 - FMC H32 +set_property -dict "PACKAGE_PIN AE26 IOSTANDARD LVCMOS25" [get_ports FMC_i3c0_sda] + +###################################################################### +# UART0 mapping +###################################################################### +# GAP pad_uart0_rx - FPGA G2 - ZC706 GPIO LED DS9 +set_property -dict "PACKAGE_PIN G2 IOSTANDARD LVCMOS15" [get_ports FMC_uart0_rx] +# GAP pad_uart0_tx - FPGA W21 - ZC706 GPIO LED DS10 +set_property -dict "PACKAGE_PIN W21 IOSTANDARD LVCMOS25" [get_ports FMC_uart0_tx] + +###################################################################### +# UART1 mapping +###################################################################### +# GAP pad_uart1_rx - FPGA AE22 - FMC H4 +set_property -dict "PACKAGE_PIN AE22 IOSTANDARD LVCMOS25" [get_ports FMC_uart1_rx] +# GAP pad_uart1_tx - FPGA AF22 - FMC H5 +set_property -dict "PACKAGE_PIN AF22 IOSTANDARD LVCMOS25" [get_ports FMC_uart1_tx] + +###################################################################### +# SPIM1 mapping +###################################################################### +# GAP pad_spim1_sck - FPGA AD29 - FMC G34 +set_property -dict "PACKAGE_PIN AD29 IOSTANDARD LVCMOS25" [get_ports FMC_spim1_sck] +# GAP pad_spim1_cs0 - FPGA AF25 - FMC G31 +set_property -dict "PACKAGE_PIN AF25 IOSTANDARD LVCMOS25" [get_ports FMC_spim1_cs0] +# GAP pad_spim1_miso - FPGA N26 - FMC G36 +set_property -dict "PACKAGE_PIN N26 IOSTANDARD LVCMOS25" [get_ports FMC_spim1_miso] +# GAP pad_spim1_mosi - FPGA AC29 - FMC G33 +set_property -dict "PACKAGE_PIN AC29 IOSTANDARD LVCMOS25" [get_ports FMC_spim1_mosi] + +###################################################################### +# I3C1 mapping +###################################################################### +# GAP pad_i3c1_scl - FPGA AG25 - FMC C15 +set_property -dict "PACKAGE_PIN AG25 IOSTANDARD LVCMOS25" [get_ports FMC_i3c1_scl] +# GAP pad_i3c1_sda - FPGA AG24 - FMC C14 +set_property -dict "PACKAGE_PIN AG24 IOSTANDARD LVCMOS25" [get_ports FMC_i3c1_sda] + +###################################################################### +# I2S master mapping +###################################################################### +# GAP pad_i2s_mst_sck - FPGA U30 - FMC H29 +set_property -dict "PACKAGE_PIN U30 IOSTANDARD LVCMOS25" [get_ports FMC_i2s_mst_sck] +# GAP pad_i2s_mst_sdi0 - FPGA AB30 - FMC H35 +set_property -dict "PACKAGE_PIN AB30 IOSTANDARD LVCMOS25" [get_ports FMC_i2s_mst_sdo0] +# GAP pad_i2s_mst_sdi1 - FPGA AD25 - FMC H31 +set_property -dict "PACKAGE_PIN AD25 IOSTANDARD LVCMOS25" [get_ports FMC_i2s_mst_sdo1] +# GAP pad_i2s_mst_ws - FPGA AF30 - FMC H28 +set_property -dict "PACKAGE_PIN AF30 IOSTANDARD LVCMOS25" [get_ports FMC_i2s_mst_ws] + +###################################################################### +# I2S slave mapping +###################################################################### +# GAP pad_i2s_slv_sck - FPGA V28 - FMC C26 +set_property -dict "PACKAGE_PIN V28 IOSTANDARD LVCMOS25" [get_ports FMC_i2s_slv_sck] +# GAP pad_i2s_slv_sdi0 - FPGA AG22 - FMC C10 +set_property -dict "PACKAGE_PIN AG22 IOSTANDARD LVCMOS25" [get_ports FMC_i2s_slv_sdi0] +# GAP pad_i2s_slv_sdi1 - FPGA AC24 - FMC C18 +set_property -dict "PACKAGE_PIN AC24 IOSTANDARD LVCMOS25" [get_ports FMC_i2s_slv_sdi1] +# GAP pad_i2s_slv_ws - FPGA AH22 - FMC C11 +set_property -dict "PACKAGE_PIN AH22 IOSTANDARD LVCMOS25" [get_ports FMC_i2s_slv_ws] + +###################################################################### +# SPIM2 mapping +###################################################################### +# GAP pad_spim2_sck - FPGA AE25 - FMC G30 +set_property -dict "PACKAGE_PIN AE25 IOSTANDARD LVCMOS25" [get_ports FMC_spim2_sck] +# GAP pad_spim2_csn - FPGA AG29 - FMC G28 +set_property -dict "PACKAGE_PIN AG29 IOSTANDARD LVCMOS25" [get_ports FMC_spim2_cs0] +# GAP pad_spim2_miso - FPGA AF29 - FMC G27 +set_property -dict "PACKAGE_PIN AF29 IOSTANDARD LVCMOS25" [get_ports FMC_spim2_miso] +# GAP pad_spim2_mosi - FPGA AJ19 - FMC G10 +set_property -dict "PACKAGE_PIN AJ19 IOSTANDARD LVCMOS25" [get_ports FMC_spim2_mosi] + +###################################################################### +# I3C2/I2C0 mapping +###################################################################### +# GAP pad_i3c2_scl - FPGA R21 - FMC H38 +set_property -dict "PACKAGE_PIN R21 IOSTANDARD LVCMOS25" [get_ports FMC_i3c2_scl] +# GAP pad_i3c2_sda - FPGA P21 - FMC H37 +set_property -dict "PACKAGE_PIN P21 IOSTANDARD LVCMOS25" [get_ports FMC_i3c2_sda] + +###################################################################### +# Camera mapping +###################################################################### +# GAP pad_cam_pclk - FPGA V23 - FMC D20 +set_property -dict "PACKAGE_PIN V23 IOSTANDARD LVCMOS25" [get_ports FMC_cam_pclk] +# GAP pad_cam_hsync - FPGA W24 - FMC D21 +set_property -dict "PACKAGE_PIN W24 IOSTANDARD LVCMOS25" [get_ports FMC_cam_hsync] +# GAP pad_cam_data0 - FPGA P26 - FMC D24 +set_property -dict "PACKAGE_PIN P26 IOSTANDARD LVCMOS25" [get_ports FMC_cam_data0] +# GAP pad_cam_data1 - FPGA P25 - FMC D23 +set_property -dict "PACKAGE_PIN P25 IOSTANDARD LVCMOS25" [get_ports FMC_cam_data1] +# GAP pad_cam_data2 - FPGA W25 - FMC C22 +set_property -dict "PACKAGE_PIN W25 IOSTANDARD LVCMOS25" [get_ports FMC_cam_data2] +# GAP pad_cam_data3 - FPGA R28 - FMC D26 +set_property -dict "PACKAGE_PIN R28 IOSTANDARD LVCMOS25" [get_ports FMC_cam_data3] +# GAP pad_cam_data4 - FPGA W26 - FMC C23 +set_property -dict "PACKAGE_PIN W26 IOSTANDARD LVCMOS25" [get_ports FMC_cam_data4] +# GAP pad_cam_data5 - FPGA T28 - FMC D27 +set_property -dict "PACKAGE_PIN T28 IOSTANDARD LVCMOS25" [get_ports FMC_cam_data5] +# GAP pad_cam_data6 - FPGA AA23 - FMC D18 +set_property -dict "PACKAGE_PIN AA23 IOSTANDARD LVCMOS25" [get_ports FMC_cam_data6] +# GAP pad_cam_data7 - FPGA V29 - FMC C27 +set_property -dict "PACKAGE_PIN V29 IOSTANDARD LVCMOS25" [get_ports FMC_cam_data7] +# GAP pad_cam_vsync - FPGA AD24 - FMC C19 +set_property -dict "PACKAGE_PIN AD24 IOSTANDARD LVCMOS25" [get_ports FMC_cam_vsync] + +###################################################################### +# HYPERBUS mapping +###################################################################### +# GAP alt2 pad_hyper_ck - FPGA AG21 - FMC D8 +set_property -dict "PACKAGE_PIN AG21 IOSTANDARD LVCMOS25" [get_ports FMC_hyper_ck] +# GAP alt2 pad_hyper_ckn - FPGA AH21 - FMC D9 +set_property -dict "PACKAGE_PIN AH21 IOSTANDARD LVCMOS25" [get_ports FMC_hyper_ckn] +# GAP alt2 pad_hyper_rwds - FPGA AA22 - FMC D17 +set_property -dict "PACKAGE_PIN AA22 IOSTANDARD LVCMOS25" [get_ports FMC_hyper_rwds] +# GAP alt2 pad_hyper_csn0 - FPGA W28 - FMC G25 +set_property -dict "PACKAGE_PIN W28 IOSTANDARD LVCMOS25" [get_ports FMC_hyper_csn0] +# GAP alt2 pad_hyper_csn1 - FPGA V27 - FMC G24 +set_property -dict "PACKAGE_PIN V27 IOSTANDARD LVCMOS25" [get_ports FMC_hyper_csn1] +# GAP alt2 pad_hyper_dq0 - FPGA AH23 - FMC D11 +set_property -dict "PACKAGE_PIN AH23 IOSTANDARD LVCMOS25" [get_ports FMC_hyper_dq0] +# GAP alt2 pad_hyper_dq1 - FPGA AH24 - FMC D12 +set_property -dict "PACKAGE_PIN AH24 IOSTANDARD LVCMOS25" [get_ports FMC_hyper_dq1] +# GAP alt2 pad_hyper_dq2 - FPGA AD21 - FMC D14 +set_property -dict "PACKAGE_PIN AD21 IOSTANDARD LVCMOS25" [get_ports FMC_hyper_dq2] +# GAP alt2 pad_hyper_dq3 - FPGA AE21 - FMC D15 +set_property -dict "PACKAGE_PIN AE21 IOSTANDARD LVCMOS25" [get_ports FMC_hyper_dq3] +# GAP alt2 pad_hyper_dq4 - FPGA AA24 - FMC G18 +set_property -dict "PACKAGE_PIN AA24 IOSTANDARD LVCMOS25" [get_ports FMC_hyper_dq4] +# GAP alt2 pad_hyper_dq5 - FPGA AB24 - FMC G19 +set_property -dict "PACKAGE_PIN AB24 IOSTANDARD LVCMOS25" [get_ports FMC_hyper_dq5] +# GAP alt2 pad_hyper_dq6 - FPGA U25 - FMC G21 +set_property -dict "PACKAGE_PIN U25 IOSTANDARD LVCMOS25" [get_ports FMC_hyper_dq6] +# GAP alt2 pad_hyper_dq7 - FPGA V26 - FMC G22 +set_property -dict "PACKAGE_PIN V26 IOSTANDARD LVCMOS25" [get_ports FMC_hyper_dq7] + +###################################################################### +# Reset mapping +###################################################################### +# GAP pad_reset_n - FPGA AJ21 - ZC706 GPIO PMOD HEADER J58.1 +set_property -dict "PACKAGE_PIN AJ21 IOSTANDARD LVCMOS25" [get_ports FMC_reset_n] + +###################################################################### +# JTAG mapping +###################################################################### +# GAP pad_jtag_tdo - FPGA AB16 - ZC706 GPIO PMOD HEADER J58.7 +set_property -dict "PACKAGE_PIN AB16 IOSTANDARD LVCMOS25" [get_ports FMC_jtag_tdo] +# GAP pad_jtag_tck - FPGA Y20 - ZC706 GPIO PMOD HEADER J58.2 +set_property -dict "PACKAGE_PIN Y20 IOSTANDARD LVCMOS25" [get_ports FMC_jtag_tck] +# GAP pad_jtag_tms - FPGA AA20 - ZC706 GPIO PMOD HEADER J58.4 +set_property -dict "PACKAGE_PIN AA20 IOSTANDARD LVCMOS25" [get_ports FMC_jtag_tms] +# GAP pad_jtag_tdi - FPGA AC18 - ZC706 GPIO PMOD HEADER J58.6 +set_property -dict "PACKAGE_PIN AC18 IOSTANDARD LVCMOS25" [get_ports FMC_jtag_tdi] +# GAP pad_jtag_trst - FPGA AC19 - ZC706 GPIO PMOD HEADER J58.8 +set_property -dict "PACKAGE_PIN AC19 IOSTANDARD LVCMOS25" [get_ports FMC_jtag_trst] +# GAP pad_bootmode - FPGA AB21 - ZC706 GPIO PMOD HEADER J58.5 +set_property -dict "PACKAGE_PIN AB21 IOSTANDARD LVCMOS25" [get_ports FMC_bootmode] + +#LED +set_property PACKAGE_PIN Y21 [get_ports LED] +set_property IOSTANDARD LVCMOS25 [get_ports LED] diff --git a/fpga/pulpemu/tcl/fmc_board_zcu102.xdc b/fpga/pulpemu/tcl/fmc_board_zcu102.xdc new file mode 100644 index 00000000..4b162893 --- /dev/null +++ b/fpga/pulpemu/tcl/fmc_board_zcu102.xdc @@ -0,0 +1,181 @@ +############################################################# +# _____ ____ _____ _ _ _ # +# |_ _/ __ \ / ____| | | | | (_) # +# | || | | |_____| (___ ___| |_| |_ _ _ __ __ _ ___ # +# | || | | |______\___ \ / _ \ __| __| | '_ \ / _` / __| # +# _| || |__| | ____) | __/ |_| |_| | | | | (_| \__ \ # +# |_____\____/ |_____/ \___|\__|\__|_|_| |_|\__, |___/ # +# __/ | # +# |___/ # +############################################################# + +## Sys clock +set_property -dict {PACKAGE_PIN F21 IOSTANDARD LVDS_25} [get_ports ref_clk_n] +set_property -dict {PACKAGE_PIN G21 IOSTANDARD LVDS_25} [get_ports ref_clk_p] + +## Reset +###################################################################### +# Reset mapping +###################################################################### +set_property -dict {PACKAGE_PIN AM13 IOSTANDARD LVCMOS33} [get_ports pad_reset] + +## Buttons +#set_property -dict {PACKAGE_PIN AF15 IOSTANDARD LVCMOS33} [get_ports btn0_i] +#set_property -dict {PACKAGE_PIN AG13 IOSTANDARD LVCMOS33} [get_ports btn1_i] +#set_property -dict {PACKAGE_PIN AE14 IOSTANDARD LVCMOS33} [get_ports btn2_i] +#set_property -dict {PACKAGE_PIN AG15 IOSTANDARD LVCMOS33} [get_ports btn3_i] + +## PMOD 0 --- JTAG +###################################################################### +# JTAG mapping +###################################################################### +set_property -dict {PACKAGE_PIN A20 IOSTANDARD LVCMOS33} [get_ports pad_jtag_tms] +set_property -dict {PACKAGE_PIN B20 IOSTANDARD LVCMOS33} [get_ports pad_jtag_tdi] +set_property -dict {PACKAGE_PIN A22 IOSTANDARD LVCMOS33} [get_ports pad_jtag_tdo] +set_property -dict {PACKAGE_PIN A21 IOSTANDARD LVCMOS33} [get_ports pad_jtag_tck] + +#set_property -dict {PACKAGE_PIN B21 IOSTANDARD LVCMOS33} [get_ports pad_pmod0_4] +#set_property -dict {PACKAGE_PIN C21 IOSTANDARD LVCMOS33} [get_ports pad_pmod0_5] +#set_property -dict {PACKAGE_PIN C22 IOSTANDARD LVCMOS33} [get_ports pad_pmod0_6] +#set_property -dict {PACKAGE_PIN D21 IOSTANDARD LVCMOS33} [get_ports pad_pmod0_7] + +## PMOD 1 +#set_property -dict {PACKAGE_PIN D20 IOSTANDARD LVCMOS33} [get_ports pad_pmod1_0] +#set_property -dict {PACKAGE_PIN E20 IOSTANDARD LVCMOS33} [get_ports pad_pmod1_1] +#set_property -dict {PACKAGE_PIN D22 IOSTANDARD LVCMOS33} [get_ports pad_pmod1_2] +#set_property -dict {PACKAGE_PIN E22 IOSTANDARD LVCMOS33} [get_ports pad_pmod1_3] +#set_property -dict {PACKAGE_PIN F20 IOSTANDARD LVCMOS33} [get_ports pad_pmod1_4] +#set_property -dict {PACKAGE_PIN G20 IOSTANDARD LVCMOS33} [get_ports pad_pmod1_5] +#set_property -dict {PACKAGE_PIN J20 IOSTANDARD LVCMOS33} [get_ports pad_pmod1_6] +#set_property -dict {PACKAGE_PIN J19 IOSTANDARD LVCMOS33} [get_ports pad_pmod1_7] + +## UART +###################################################################### +# UART mapping +###################################################################### +set_property -dict {PACKAGE_PIN E13 IOSTANDARD LVCMOS33} [get_ports pad_uart_rx] +set_property -dict {PACKAGE_PIN F13 IOSTANDARD LVCMOS33} [get_ports pad_uart_tx] + + +#set_property -dict {PACKAGE_PIN D12 IOSTANDARD LVCMOS33} [get_ports pad_uart_rts] +#set_property -dict {PACKAGE_PIN E12 IOSTANDARD LVCMOS33} [get_ports pad_uart_cts] + +## LEDs +#set_property -dict {PACKAGE_PIN AG14 IOSTANDARD LVCMOS33} [get_ports led0_o] +#set_property -dict {PACKAGE_PIN AF13 IOSTANDARD LVCMOS33} [get_ports led1_o] +#set_property -dict {PACKAGE_PIN AE13 IOSTANDARD LVCMOS33} [get_ports led2_o] +#set_property -dict {PACKAGE_PIN AJ14 IOSTANDARD LVCMOS33} [get_ports led3_o] + +## Switches +#set_property -dict {PACKAGE_PIN AN14 IOSTANDARD LVCMOS33} [get_ports switch0_i] +#set_property -dict {PACKAGE_PIN AP14 IOSTANDARD LVCMOS33} [get_ports switch1_i] +#set_property -dict {PACKAGE_PIN AM14 IOSTANDARD LVCMOS33} [get_ports switch2_i] +#set_property -dict {PACKAGE_PIN AN13 IOSTANDARD LVCMOS33} [get_ports switch3_i] + +## I2C Bus +#set_property -dict {PACKAGE_PIN J10 IOSTANDARD LVCMOS33} [get_ports pad_i2c0_scl] +#set_property -dict {PACKAGE_PIN J11 IOSTANDARD LVCMOS33} [get_ports pad_i2c0_sda] + +## HDMI CTL +#set_property -dict {PACKAGE_PIN F15 IOSTANDARD LVCMOS33} [get_ports pad_hdmi_scl] +#set_property -dict {PACKAGE_PIN F16 IOSTANDARD LVCMOS33} [get_ports pad_hdmi_sda] + + +#LED +###################################################################### +# JTAG mapping +###################################################################### +#set_property PACKAGE_PIN AG14 [get_ports LED] +#set_property IOSTANDARD LVCMOS33 [get_ports LED] + +###################################################################### +# I2C0 mapping +###################################################################### +# PULP pad_i3c2_scl - FPGA T11 - FMC H38 +set_property -dict {PACKAGE_PIN T11 IOSTANDARD LVCMOS18} [get_ports FMC_i2c0_scl] +# PULP pad_i3c2_sda - FPGA U11 - FMC H37 +set_property -dict {PACKAGE_PIN U11 IOSTANDARD LVCMOS18} [get_ports FMC_i2c0_sda] + + +###################################################################### +# I2S master mapping +###################################################################### +# PULP pad_i2s_mst_sck - FPGA K12 - FMC H29 +set_property -dict {PACKAGE_PIN K12 IOSTANDARD LVCMOS18} [get_ports FMC_i2s0_sck] +# PULP pad_i2s_mst_ws - FPGA AC7 - FMC C18 +set_property -dict {PACKAGE_PIN AC7 IOSTANDARD LVCMOS18} [get_ports FMC_i2s0_ws] +# PULP pad_i2s_slv_sdi0 - FPGA AB4 - FMC D8 +set_property -dict {PACKAGE_PIN AB4 IOSTANDARD LVCMOS18} [get_ports FMC_i2s0_sdi] +# PULP pad_i2s_slv_sdi1 - FPGA AC2 - FMC C10 +set_property -dict {PACKAGE_PIN AC2 IOSTANDARD LVCMOS18} [get_ports FMC_i2s1_sdi] + + +###################################################################### +# SDIO mapping +###################################################################### +# PULP pad_sdio_sdio0 - FPGA D20 - ZCU102 GPIO PMOD HEADER J87.1 +set_property -dict {PACKAGE_PIN D20 IOSTANDARD LVCMOS33} [get_ports FMC_sdio_data0] +# PULP pad_sdio_sdio1 - FPGA E20 - ZCU102 GPIO PMOD HEADER J87.3 +set_property -dict {PACKAGE_PIN E20 IOSTANDARD LVCMOS33} [get_ports FMC_sdio_data1] +# PULP pad_sdio_sdio2 - FPGA D22 - ZCU102 GPIO PMOD HEADER J87.5 +set_property -dict {PACKAGE_PIN D22 IOSTANDARD LVCMOS33} [get_ports FMC_sdio_data2] +# PULP pad_sdio_sdio3 - FPGA E22 - ZCU102 GPIO PMOD HEADER J87.7 +set_property -dict {PACKAGE_PIN E22 IOSTANDARD LVCMOS33} [get_ports FMC_sdio_data3] +# PULP pad_sdio_cmd - FPGA F20 - ZCU102 GPIO PMOD HEADER J87.2 +set_property -dict {PACKAGE_PIN F20 IOSTANDARD LVCMOS33} [get_ports FMC_sdio_cmd] +# PULP pad_sdio_sck - FPGA G20 - ZCU102 GPIO PMOD HEADER J87.4 +set_property -dict {PACKAGE_PIN G20 IOSTANDARD LVCMOS33} [get_ports FMC_sdio_sck] + + +###################################################################### +# QSPI mapping +###################################################################### +# PULP pad_qspi_sdio0 - FPGA V1 - FMC H8 +set_property -dict {PACKAGE_PIN V1 IOSTANDARD LVCMOS18} [get_ports FMC_qspi_sdio0] +# PULP pad_qspi_sdio1 - FPGA W6 - FMC G16 +set_property -dict {PACKAGE_PIN W6 IOSTANDARD LVCMOS18} [get_ports FMC_qspi_sdio1] +# PULP pad_qspi_sdio2 - FPGA AA2 - FMC H10 +set_property -dict {PACKAGE_PIN AA2 IOSTANDARD LVCMOS18} [get_ports FMC_qspi_sdio2] +# PULP pad_qspi_sdio3 - FPGA Y4 - FMC G6 +set_property -dict {PACKAGE_PIN Y4 IOSTANDARD LVCMOS18} [get_ports FMC_qspi_sdio3] +# PULP pad_qspi_csn0 - FPGA Y10 - FMC H19 +set_property -dict {PACKAGE_PIN Y10 IOSTANDARD LVCMOS18} [get_ports FMC_qspi_csn0] +# PULP pad_qspi_sck - FPGA W7 - FMC G15 +set_property -dict {PACKAGE_PIN W7 IOSTANDARD LVCMOS18} [get_ports FMC_qspi_sck] +# GAP pad_spim0_sck - FPGA V2 - FMC H7 +set_property -dict {PACKAGE_PIN V2 IOSTANDARD LVCMOS18} [get_ports FMC_qspi_csn1] + + +###################################################################### +# Camera mapping +###################################################################### +# PULP pad_cam_pclk - FPGA P11 - FMC D20 +set_property -dict {PACKAGE_PIN P11 IOSTANDARD LVCMOS18} [get_ports FMC_cam_pclk] +# PULP pad_cam_hsync - FPGA N11 - FMC D21 +set_property -dict {PACKAGE_PIN N11 IOSTANDARD LVCMOS18} [get_ports FMC_cam_hsync] +# PULP pad_cam_data0 - FPGA K16 - FMC D24 +set_property -dict {PACKAGE_PIN K16 IOSTANDARD LVCMOS18} [get_ports FMC_cam_data0] +# PULP pad_cam_data1 - FPGA L16 - FMC D23 +set_property -dict {PACKAGE_PIN L16 IOSTANDARD LVCMOS18} [get_ports FMC_cam_data1] +# PULP pad_cam_data2 - FPGA N9 - FMC C22 +set_property -dict {PACKAGE_PIN N9 IOSTANDARD LVCMOS18} [get_ports FMC_cam_data2] +# PULP pad_cam_data3 - FPGA L15 - FMC D26 +set_property -dict {PACKAGE_PIN L15 IOSTANDARD LVCMOS18} [get_ports FMC_cam_data3] +# PULP pad_cam_data4 - FPGA N8 - FMC C23 +set_property -dict {PACKAGE_PIN N8 IOSTANDARD LVCMOS18} [get_ports FMC_cam_data4] +# PULP pad_cam_data5 - FPGA K15 - FMC D27 +set_property -dict {PACKAGE_PIN K15 IOSTANDARD LVCMOS18} [get_ports FMC_cam_data5] +# PULP pad_cam_data6 - FPGA AC8 - FMC D18 +set_property -dict {PACKAGE_PIN AC8 IOSTANDARD LVCMOS18} [get_ports FMC_cam_data6] +# PULP pad_cam_data7 - FPGA L10 - FMC C27 +set_property -dict {PACKAGE_PIN L10 IOSTANDARD LVCMOS18} [get_ports FMC_cam_data7] +# PULP pad_cam_vsync - FPGA AC6 - FMC C19 +set_property -dict {PACKAGE_PIN AC6 IOSTANDARD LVCMOS18} [get_ports FMC_cam_vsync] + +set_property MARK_DEBUG true [get_nets pulp_chip_i/pad_jtag_tdi] +set_property MARK_DEBUG true [get_nets pulp_chip_i/pad_jtag_tdo] +set_property MARK_DEBUG true [get_nets pulp_chip_i/pad_jtag_tck] +set_property MARK_DEBUG true [get_nets pulp_chip_i/pad_jtag_tms] +set_property MARK_DEBUG true [get_nets pulp_chip_i/pad_reset_n] +set_property MARK_DEBUG true [get_nets pulp_chip_i/s_ref_clk] +set_property MARK_DEBUG true [get_nets pulp_chip_i/s_bootsel] diff --git a/fpga/pulpemu/tcl/impl.tcl b/fpga/pulpemu/tcl/impl.tcl new file mode 100644 index 00000000..74b6ef18 --- /dev/null +++ b/fpga/pulpemu/tcl/impl.tcl @@ -0,0 +1,51 @@ +# set for RuntimeOptimized implementation +set_property "steps.opt_design.args.directive" "RuntimeOptimized" [get_runs impl_1] +set_property "steps.place_design.args.directive" "RuntimeOptimized" [get_runs impl_1] +set_property "steps.route_design.args.directive" "RuntimeOptimized" [get_runs impl_1] +set_property "steps.phys_opt_design.args.is_enabled" true [get_runs impl_1] +set_property "steps.phys_opt_design.args.directive" "ExploreWithHoldFix" [get_runs impl_1] +set_property "steps.post_route_phys_opt_design.args.is_enabled" true [get_runs impl_1] +set_property "steps.post_route_phys_opt_design.args.directive" "ExploreWithAggressiveHoldFix" [get_runs impl_1] + +launch_runs impl_1 -jobs 12 +wait_on_run impl_1 + +catch { +# Set only for VCU device to flash SPI flash fast +open_run impl_1 +set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 8 [get_designs impl_1] +set_property BITSTREAM.CONFIG.SPI_FALL_EDGE YES [get_designs impl_1] +reset_run impl_1 +} + +# reports +exec mkdir -p reports/ +exec rm -rf reports/* +check_timing -file reports/pulpemu.check_timing.rpt + +catch { +report_timing -max_paths 100 -nworst 100 -delay_type max -sort_by slack -file reports/pulpemu.timing_WORST_100.rpt +report_timing -group CLUSTER_CLK -max_paths 100 -nworst 100 -delay_type max -sort_by slack -file reports/pulpemu.timing_CLUSTER_WORST_100.rpt +report_timing -group SOC_CLK -max_paths 100 -nworst 100 -delay_type max -sort_by slack -file reports/pulpemu.timing_SOC_WORST_100.rpt +report_timing -nworst 1 -delay_type max -sort_by group -file reports/pulpemu.timing.rpt +report_utilization -hierarchical -file reports/pulpemu.utilization.rpt +report_utilization -hierarchical -hierarchical_depth 1 -file reports/pulpemu.area_top.rpt +report_utilization -hierarchical -hierarchical_depth 2 -cells pulp_chip_i -file reports/pulpemu.area_pulp_chip.rpt +report_utilization -hierarchical -hierarchical_depth 2 -cells pulp_chip_i/soc_domain_i/pulp_soc_i -file reports/pulpemu.area_soc.rpt +report_utilization -hierarchical -hierarchical_depth 2 -cells pulp_chip_i/cluster_domain_i/cluster_i -file reports/pulpemu.area_cluster.rpt +} + +launch_runs impl_1 -to_step write_bitstream -jobs 12 +wait_on_run impl_1 + + +# output Verilog netlist + SDC for timing simulation +write_verilog -force -mode funcsim pulpemu_funcsim.v +write_verilog -force -mode timesim pulpemu_timesim.v +write_sdf -force pulpemu_timesim.sdf + +# copy bitstream +exec cp pulpemu.runs/impl_1/pulpemu.bit . +if [info exists ::env(SDK_WORKSPACE)] { + exec cp pulpemu.bit $SDK_WORKSPACE/. +} diff --git a/fpga/pulpemu/tcl/run.tcl b/fpga/pulpemu/tcl/run.tcl new file mode 100644 index 00000000..2902b35b --- /dev/null +++ b/fpga/pulpemu/tcl/run.tcl @@ -0,0 +1,122 @@ +# setup +if [info exists ::env(SDK_WORKSPACE)] { + set SDK_WORKSPACE $::env(SDK_WORKSPACE) +} + + +# detect board +if [info exists ::env(BOARD)] { + set BOARD $::env(BOARD) +} else { + puts "Please execute 'source ../sourceme.sh first before you start vivado in order to setup necessary environment variables." + exit +} +if [info exists ::env(XILINX_BOARD)] { + set XILINX_BOARD $::env(XILINX_BOARD) +} + +# create project +create_project pulpemu . -force -part $::env(XILINX_PART) +set_property board_part $::env(XILINX_BOARD) [current_project] + +# set up meaningful errors +source ../common/messages.tcl + +#include ip inc dirs +source tcl/ips_inc_dirs.tcl +source tcl/rtl_inc_dirs.tcl +set_property include_dirs $INCLUDE_DIRS [current_fileset] + +# setup source files +source tcl/ips_src_files.tcl +source tcl/rtl_src_files.tcl + +# add IPs +source tcl/ips_add_files.tcl +source tcl/rtl_add_files.tcl + +# detect target clock +if [info exists ::env(FC_CLK_PERIOD_NS)] { + set FC_CLK_PERIOD_NS $::env(FC_CLK_PERIOD_NS) +} else { + set FC_CLK_PERIOD_NS 10.000 +} +set CLK_HALFPERIOD_NS [expr ${FC_CLK_PERIOD_NS} / 2.0] + +# add memory cuts + other FPGA IPs +read_ip $FPGA_IPS/xilinx_interleaved_ram/ip/xilinx_interleaved_ram.xci +read_ip $FPGA_IPS/xilinx_private_ram/ip/xilinx_private_ram.xci +read_ip $FPGA_IPS/xilinx_rom_bank_2048x32/ip/xilinx_rom_bank_2048x32.xci +read_ip $FPGA_IPS/xilinx_clk_mngr/ip/xilinx_clk_mngr.xci +read_ip $FPGA_IPS/xilinx_slow_clk_mngr/ip/xilinx_slow_clk_mngr.xci + + + +# add pulp_cluster +catch { +add_files -norecurse ../pulp_cluster/pulp_cluster.edf \ + ../pulp_cluster/pulp_cluster_stub.v +} + +# needed only if used in batch mode +update_compile_order -fileset sources_1 +update_compile_order -fileset sim_1 + +# add constraints +add_files -fileset constrs_1 -norecurse tcl/constraints.xdc +set_property target_constrs_file tcl/constraints.xdc [current_fileset -constrset] +add_files -fileset constrs_1 -norecurse "tcl/fmc_board_$::env(BOARD).xdc" +set_property target_constrs_file "tcl/fmc_board_$::env(BOARD).xdc" [current_fileset -constrset] + +# workaround for Maestro packages +set_property source_mgmt_mode DisplayOnly [current_project] + +# set pulpemu as top +set_property top pulpemu [current_fileset] + +# elaborate +set_msg_config -id {Synth 8-350} -new_severity {CRITICAL WARNING} + +catch { +synth_design -rtl -name rtl_1 -verilog_define PULP_FPGA_EMUL=1 -verilog_define USE_CLUSTER_NETLIST=1 -flatten_hierarchy none +} + +update_compile_order -fileset sources_1 + +synth_design -rtl -name rtl_1 -verilog_define PULP_FPGA_EMUL=1 -verilog_define USE_CLUSTER_NETLIST=1 -flatten_hierarchy none + +# set unconnected stuff as ERROR if not in block design +set_msg_config -id {[Synth 8-350]} -new_severity "critical warning" +set_msg_config -id {[Synth 8-3352]} -new_severity "critical warning" +set_property "steps.synth_design.args.flatten_hierarchy" "none" [get_runs synth_1] +set_property "steps.synth_design.args.directive" "RuntimeOptimized" [get_runs synth_1] + +# launch synthesis +launch_runs synth_1 -job 12 +wait_on_run synth_1 + +open_run synth_1 -name netlist_1 +set_property needs_refresh false [get_runs synth_1] + +# Remove unused IOBUF cells in padframe (they are not optimized away since the +# pad driver also drives the input creating a datapath from pad_xy_o to pad_xy_i +# ) +remove_cell i_pulp/pad_frame_i/padinst_bootsel + +# export synthesis netlist +catch { +exec mkdir -p ./save/synth +write_edif -force ./save/synth/pulpemu.edn +write_verilog -force -mode synth_stub ./save/synth/pulpemu_stub.v +write_verilog -force -mode funcsim ./save/synth/pulpemu_funcsim.v +} + +# export hardware design for sdk +if [info exists ::env(SDK_WORKSPACE)] { + write_hwdef -force -file $SDK_WORKSPACE/pulpemu.hdf +} else { + write_hwdef -force -file ./pulpemu.hdf +} + +# run implementation +source tcl/impl.tcl diff --git a/fpga/pulpemu/tcl/setup_impl.tcl b/fpga/pulpemu/tcl/setup_impl.tcl new file mode 100644 index 00000000..8b3e9909 --- /dev/null +++ b/fpga/pulpemu/tcl/setup_impl.tcl @@ -0,0 +1,58 @@ +set CLK_PERIOD 10.000 +set CLK_WAVEFORM { 0.000 5.000 } + +create_project pulpemu_top . -part xc7z045ffg900-2 +set_property board xilinx.com:zynq:zc706:1.1 [current_project] +set_property design_mode GateLvl [current_fileset] +add_files -norecurse ./pulpemu.edf +add_files -norecurse ../ulpcluster/ulpcluster.edf +add_files -norecurse ../ips/xilinx_tcdm_bank_512x32/ip/xilinx_tcdm_bank_512x32.dcp +add_files -norecurse ../ips/xilinx_l2_mem_8192x64/ip/xilinx_l2_mem_8192x64.dcp +add_files -norecurse ../ips/xilinx_tcdm_bank_256x32/ip/xilinx_tcdm_bank_256x32.dcp +add_files -norecurse ../ips/xilinx_ic_ram_128x32/ip/xilinx_ic_ram_128x32.dcp +add_files -norecurse ../ips/xilinx_core_ila/ip/xilinx_core_ila.dcp +add_files -norecurse ../ips/xilinx_icache_ila/ip/xilinx_icache_ila.dcp +add_files -norecurse ../ips/xilinx_tcdm_scm_ila/ip/xilinx_tcdm_scm_ila.dcp +add_files -norecurse ../ips/xilinx_tcdm_sram_ila/ip/xilinx_tcdm_sram_ila.dcp +set_property top pulpemu [current_fileset] +link_design -name netlist_1 + +# false paths +source tcl/false_paths.tcl + +# clocks +create_clock -period ${CLK_PERIOD} -name ref_clk_i -waveform ${CLK_WAVEFORM} [get_nets {ref_clk_i}] +create_clock -period ${CLK_PERIOD} -name ps7_clk -waveform ${CLK_WAVEFORM} [get_pins {ps7_wrapper_i/ps7_i/processing_system7_0/inst/PS7_i/FCLKCLK[0]}] +create_clock -period ${CLK_PERIOD} -name ulpsoc_clk -waveform ${CLK_WAVEFORM} [get_nets {ulpsoc_i/i_clk_rst_gen/clk_manager_i/clk_o}] +create_clock -period 100 -name spi_clk -waveform { 0.0 50.0 } [ get_nets {spi_slave_clk_r}] + +# pins +set_property package_pin AJ21 [get_ports PULP_SPI_clk] +set_property is_loc_fixed true [get_ports [list PULP_SPI_clk]] +set_property IOSTANDARD LVCMOS25 [get_ports PULP_SPI_clk] +set_property PULLTYPE NONE [get_ports PULP_SPI_clk] +set_property package_pin AK12 [get_ports PULP_SPI_cs] +set_property is_loc_fixed true [get_ports [list PULP_SPI_cs]] +set_property IOSTANDARD LVCMOS25 [get_ports PULP_SPI_cs] +set_property PULLTYPE PULLUP [get_ports PULP_SPI_cs] +set_property package_pin AA13 [get_ports PULP_SPI_sdo] +set_property is_loc_fixed true [get_ports [list PULP_SPI_sdo]] +set_property IOSTANDARD LVCMOS25 [get_ports PULP_SPI_sdo] +set_property PULLTYPE PULLUP [get_ports PULP_SPI_sdo] +set_property package_pin AH18 [get_ports PULP_SPI_sdi] +set_property is_loc_fixed true [get_ports [list PULP_SPI_sdi]] +set_property IOSTANDARD LVCMOS25 [get_ports PULP_SPI_sdi] +set_property PULLTYPE PULLUP [get_ports PULP_SPI_sdi] +set_property package_pin Y20 [get_ports PULP_SPI_mode_1] +set_property is_loc_fixed true [get_ports [list PULP_SPI_mode_1]] +set_property IOSTANDARD LVCMOS25 [get_ports PULP_SPI_mode_1] +set_property PULLTYPE PULLUP [get_ports PULP_SPI_mode_1] +set_property package_pin AA20 [get_ports PULP_SPI_mode_0] +set_property is_loc_fixed true [get_ports [list PULP_SPI_mode_0]] +set_property IOSTANDARD LVCMOS25 [get_ports PULP_SPI_mode_0] +set_property PULLTYPE PULLUP [get_ports PULP_SPI_mode_0] +#set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets PULP_SPI_clk_IBUF] + +save_constraints + +#source tcl/probes.tcl diff --git a/fpga/sim/.gitignore b/fpga/sim/.gitignore new file mode 100644 index 00000000..b37fa9c4 --- /dev/null +++ b/fpga/sim/.gitignore @@ -0,0 +1,40 @@ +# ignore modelsim libraries +modelsim_libs +work +xilinx_libs + +# ignore automatically generated stuff by modelsim +transcript +vsim.wlf +wlft* +vish_stacktrace.vstf +stdout/uart +CLUSTER_FLL.log +CORE*.txt +SOC_FLL.log +trace_core* +stim.txt +vsim_stacktrace.vstf + +CORE*_TCDM_DUMP.txt +stdout/stdout* +CORE* +FETCH_CORE_* +CLUSTER_FLL.log +SOC_FLL.log +core_state +i2s_buffer.hex +i2s_buffer_0.hex +i2s_buffer_1.hex +i2s_buffer_2.hex +i2s_buffer_3.hex + + + +# ignore modelsim.ini +modelsim.ini + +# ignore c build files +slm_files +simvectors +vectors diff --git a/fpga/sim/Makefile b/fpga/sim/Makefile new file mode 100644 index 00000000..ba02faec --- /dev/null +++ b/fpga/sim/Makefile @@ -0,0 +1,80 @@ +.PHONY: build lib clean sim simc + +mkfile_path := $(dir $(abspath $(firstword $(MAKEFILE_LIST)))) + +VSIM ?= vsim +VSIM_FLAGS = -gUSE_SDVT_SPI=0 -gUSE_SDVT_CPI=0 -gBAUDRATE=115200 \ + -gENABLE_DEV_DPI=0 -gLOAD_L2=JTAG -gUSE_SDVT_I2S=0 + +SVLIB = ../../rtl/tb/remote_bitbang/librbs + +PULP_CLUSTER_NETLIST = ../pulp_cluster/pulp_cluster_postsynt.v +PULPEMU_TIME_NETLIST = ../pulpemu/pulpemu_timesim.v +PULPEMU_FUNC_NETLIST = ../pulpemu/pulpemu_funcsim.v + +all: clean lib build opt + +sim: + $(VSIM) -64 -gui vopt_tb -L models_lib -L vip_lib \ + -suppress vsim-3009 -suppress vsim-8683 \ + +UVM_NO_RELNOTES -stats -t ps \ + -sv_lib $(SVLIB) $(VSIM_FLAGS) \ + -do "set StdArithNoWarnings 1; set NumericStdNoWarnings 1" + +simc: + $(VSIM) -64 -c vopt_tb -L models_lib -L vip_lib \ + -suppress vsim-3009 -suppress vsim-8683 \ + +UVM_NO_RELNOTES -stats -t ps \ + -sv_lib $(SVLIB) $(VSIM_FLAGS) \ + -do "set StdArithNoWarnings 1; set NumericStdNoWarnings 1" \ + -do "run -all" \ + -do "quit -code [examine -radix decimal sim:/tb_pulp/exit_status]" + +opt: + $(mkfile_path)/tcl_files/rtl_vopt.tcl + +build: + @make --no-print-directory -f $(mkfile_path)/vcompile/fpga.mk build + @make --no-print-directory -f $(mkfile_path)/vcompile/ips.mk build + @make --no-print-directory -f $(mkfile_path)/vcompile/rtl.mk build + +build_fpga_pulp_cluster: + @if [ ! -f $(PULP_CLUSTER_NETLIST) ]; then\ + echo "Can not find $(PULP_CLUSTER_NETLIST)! Please go to ../pulp_cluster and execute to get netlist!";\ + fi + @make --no-print-directory -f $(mkfile_path)/vcompile/fpga.mk build + @make --no-print-directory -f $(mkfile_path)/vcompile/ips.mk build + @make --no-print-directory -f $(mkfile_path)/vcompile/rtl.mk build + @vlog -quiet +define+PULP_FPGA_EMUL +define+PULP_FPGA_SIM -suppress 2583 -suppress 13314 -work modelsim_libs/pulp_cluster_lib $(PULP_CLUSTER_NETLIST) + @vlog -quiet -sv +incdir+../../rtl/includes +define+USE_CLUSTER_NETLIST \ + +define+PULP_FPGA_EMUL +define+PULP_FPGA_SIM -suppress 2583 -suppress 13314 \ + -work modelsim_libs/pulp_lib ../../rtl/pulp/cluster_domain.sv + +build_fpga_pulpemu_function: + @make --no-print-directory -f $(mkfile_path)/vcompile/rtl/vip.mk build + @make --no-print-directory -f $(mkfile_path)/vcompile/rtl/tb.mk USE_NETLIST=1 build + @vlog -quiet -work modelsim_libs/pulpemu_lib $(PULPEMU_FUNC_NETLIST) + +build_fpga_pulpemu_timing: + @make --no-print-directory -f $(mkfile_path)/vcompile/rtl/vip.mk build + @make --no-print-directory -f $(mkfile_path)/vcompile/tb.mk USE_NETLIST=1 build + @vlog -quiet -work modelsim_libs/pulpemu_lib $(PULPEMU_TIME_NETLIST) + +lib: + @make --no-print-directory -f $(mkfile_path)/vcompile/ips.mk lib + @make --no-print-directory -f $(mkfile_path)/vcompile/rtl.mk lib + +xilinx: + vmap secureip xilinx_libs/secureip + vmap simprims_ver xilinx_libs/simprims_ver + vmap unifast xilinx_libs/unifast + vmap unifast_ver xilinx_libs/unifast_ver + vmap unimacro_ver xilinx_libs/unimacro_ver + vmap unisim xilinx_libs/unisim + vmap unisims_ver xilinx_libs/unisims_ver + vmap unimacro xilinx_libs/unimacro + vmap work modelsim_libs/work + +clean: + @make --no-print-directory -f $(mkfile_path)/vcompile/ips.mk clean + @make --no-print-directory -f $(mkfile_path)/vcompile/rtl.mk clean diff --git a/fpga/sim/README.md b/fpga/sim/README.md new file mode 100644 index 00000000..f79be9f6 --- /dev/null +++ b/fpga/sim/README.md @@ -0,0 +1,38 @@ +To do the compilation of RTL, Make sure the fpga IPs are already compiled, must source sourceme.sh + + +1. Create xilinx_libs for modelsim simulation, please wait a few minutes. + bash compile_simlibs.sh + +2. Use following command to compile your FPGA RTL platform + make clean lib build opt + clean - clean all output including work + lib - create all modelsim_libs IP lib + build - build all rtl including testbench + build_fpga_pulp_cluster - build all rtl including testbench, replace pulp_cluster with netlist + build_fpga_pulpemu_function - build all rtl including testbench, replace pulpemu with functional netlist + build_fpga_pulpemu_timing - build all rtl including testbench, replace pulpemu with timing netlist + opt - modelsim optimization + +3. ! For any sdk, do as usual, only change your VSIM_PATH to /Your/pulp/project/fpga/sim + export VSIM_PATH=/Your/pulp/project/fpga/sim + +4. (Only for gap_sdk) go to your SDK, source sourceme.sh, then go to your test, add < load=-l JTAG_DEV > in Makefile + make clean all run/gui platform=fpga_rtl + + +RTL simualtion +Must do instruction 3. before continuing: + +a. FPGA RTL simulation +make clean lib build opt + +b. FPGA RTL pulp_cluster netlist simulation +make clean lib build_fpga_pulp_cluster opt + +c. FPGA RTL pulpemu functional netlist simulation +make clean lib build_fpga_pulpemu_function opt + +d. FPGA RTL pulpemu timing netlist simulation (need sdf) +make clean lib build_fpga_pulpemu_timing opt + diff --git a/fpga/sim/boot b/fpga/sim/boot new file mode 120000 index 00000000..6785301d --- /dev/null +++ b/fpga/sim/boot @@ -0,0 +1 @@ +../../sim/vsim/boot/ \ No newline at end of file diff --git a/fpga/sim/compile_simlibs.sh b/fpga/sim/compile_simlibs.sh new file mode 100755 index 00000000..a3689e5a --- /dev/null +++ b/fpga/sim/compile_simlibs.sh @@ -0,0 +1,3 @@ +#!/bin/bash +vivado -mode batch -source compile_simlibs.tcl + diff --git a/fpga/sim/compile_simlibs.tcl b/fpga/sim/compile_simlibs.tcl new file mode 100644 index 00000000..5c8901b8 --- /dev/null +++ b/fpga/sim/compile_simlibs.tcl @@ -0,0 +1,3 @@ +# to be wrapped by compile_simlibs.sh +compile_simlib -simulator questa -directory ./xilinx_libs + diff --git a/fpga/sim/misc/glbl.v b/fpga/sim/misc/glbl.v new file mode 100644 index 00000000..be642335 --- /dev/null +++ b/fpga/sim/misc/glbl.v @@ -0,0 +1,71 @@ +// $Header: /devl/xcs/repo/env/Databases/CAEInterfaces/verunilibs/data/glbl.v,v 1.14 2010/10/28 20:44:00 fphillip Exp $ +`ifndef GLBL +`define GLBL +`timescale 1 ps / 1 ps + +module glbl (); + + parameter ROC_WIDTH = 100000; + parameter TOC_WIDTH = 0; + +//-------- STARTUP Globals -------------- + wire GSR; + wire GTS; + wire GWE; + wire PRLD; + tri1 p_up_tmp; + tri (weak1, strong0) PLL_LOCKG = p_up_tmp; + + wire PROGB_GLBL; + wire CCLKO_GLBL; + wire FCSBO_GLBL; + wire [3:0] DO_GLBL; + wire [3:0] DI_GLBL; + + reg GSR_int; + reg GTS_int; + reg PRLD_int; + +//-------- JTAG Globals -------------- + wire JTAG_TDO_GLBL; + wire JTAG_TCK_GLBL; + wire JTAG_TDI_GLBL; + wire JTAG_TMS_GLBL; + wire JTAG_TRST_GLBL; + + reg JTAG_CAPTURE_GLBL; + reg JTAG_RESET_GLBL; + reg JTAG_SHIFT_GLBL; + reg JTAG_UPDATE_GLBL; + reg JTAG_RUNTEST_GLBL; + + reg JTAG_SEL1_GLBL = 0; + reg JTAG_SEL2_GLBL = 0 ; + reg JTAG_SEL3_GLBL = 0; + reg JTAG_SEL4_GLBL = 0; + + reg JTAG_USER_TDO1_GLBL = 1'bz; + reg JTAG_USER_TDO2_GLBL = 1'bz; + reg JTAG_USER_TDO3_GLBL = 1'bz; + reg JTAG_USER_TDO4_GLBL = 1'bz; + + assign (strong1, weak0) GSR = GSR_int; + assign (strong1, weak0) GTS = GTS_int; + assign (weak1, weak0) PRLD = PRLD_int; + + initial begin + GSR_int = 1'b1; + PRLD_int = 1'b1; + #(ROC_WIDTH) + GSR_int = 1'b0; + PRLD_int = 1'b0; + end + + initial begin + GTS_int = 1'b1; + #(TOC_WIDTH) + GTS_int = 1'b0; + end + +endmodule +`endif diff --git a/fpga/sim/tcl_files/config/.gitignore b/fpga/sim/tcl_files/config/.gitignore new file mode 100644 index 00000000..6b9d01e9 --- /dev/null +++ b/fpga/sim/tcl_files/config/.gitignore @@ -0,0 +1,2 @@ +vsim_ips.tcl +vsim_rtl.tcl diff --git a/fpga/sim/tcl_files/config/export_all.tcl b/fpga/sim/tcl_files/config/export_all.tcl new file mode 100755 index 00000000..dca8bede --- /dev/null +++ b/fpga/sim/tcl_files/config/export_all.tcl @@ -0,0 +1,3 @@ +vcd file -compress export.vcd.gz +vcd add -r -optcells -internal -ports {sim:/tb_pulp/i_dut/*} + diff --git a/fpga/sim/tcl_files/config/run_and_exit.tcl b/fpga/sim/tcl_files/config/run_and_exit.tcl new file mode 100644 index 00000000..d417d543 --- /dev/null +++ b/fpga/sim/tcl_files/config/run_and_exit.tcl @@ -0,0 +1,10 @@ +# check exit status in tb and quit the simulation accordingly +proc run_and_exit {} { + onElabError {quit -code 1} + onerror {quit -code 1} + if {[catch {run -all} ]} { + quit -code 1 + } + quit -code [examine -radix decimal sim:/tb/tb_test_i/sim_manager_i/exit_status] +} + diff --git a/fpga/sim/tcl_files/config/vsim.tcl b/fpga/sim/tcl_files/config/vsim.tcl new file mode 100644 index 00000000..15bc73ce --- /dev/null +++ b/fpga/sim/tcl_files/config/vsim.tcl @@ -0,0 +1,155 @@ +####################################### +# Define vsim path and custom variables passed via make +if {[info exists ::env(VSIM_PATH)]} { + quietly set VSIM_SCRIPTS_PATH $::env(VSIM_PATH) +} { + quietly set VSIM_SCRIPTS_PATH ./ +} + +if {[info exists ::env(TB_PATH)]} { + quietly set TB_PATH_TCL $::env(TB_PATH) +} { + quietly set TB_PATH_TCL "$VSIM_SCRIPTS_PATH/../../fe/tb/" +} + +if {[info exists ::env(VSIM_FLAGS)]} { + quietly set VSIM_FLAGS_TCL $::env(VSIM_FLAGS) +} { + quietly set VSIM_FLAGS_TCL "" +} + +if {[info exists ::env(VSIM_RUNNER_FLAGS)]} { + quietly set VSIM_FLAGS_TCL "$VSIM_FLAGS_TCL $::env(VSIM_RUNNER_FLAGS)" +} + +quietly set VSIM_TB_PATH $VSIM_SCRIPTS_PATH/../tb +####################################### +####################################### +quietly source $VSIM_SCRIPTS_PATH/tcl_files/config/vsim_ips.tcl + +quietly source $VSIM_SCRIPTS_PATH/tcl_files/config/vsim_sdvt.tcl +quietly source $VSIM_SCRIPTS_PATH/tcl_files/config/vsim_custom.tcl + +quietly set design_libs "\ + " + +set sdkLib "" + +if {[info exists ::env(PULP_SIMCHECKER)]} { + set sdkLib "-sv_lib $::env(PULP_SDK_HOME)/install/ws/lib/libri5cyv2sim $sdkLib" +} + +quietly set warning_args "\ + +nowarnTRAN \ + +nowarnTSCALE \ + +nowarnTFMPC \ + " + +quietly set define_args "\ + +TB_PATH=$TB_PATH_TCL \ + +UVM_NO_RELNOTES \ + " + +quietly set common_args "\ + $design_libs \ + $warning_args \ + $define_args \ + " + +quietly set custom_args "\ + $VSIM_FLAGS_TCL \ + $uart_drv_mon \ + $use_dev_dpi \ + $sdkLib \ + " + +quietly set common_sdvt_args "\ + $sdvt_debug_level \ + $use_sdvt_cpi \ + $sdvt_cpi_test \ + $sdvt_cpi_cmds \ + $sdvt_cpi_checker_ena \ + $sdvt_cpi_hres \ + $sdvt_cpi_vres \ + $use_sdvt_i2s \ + $sdvt_i2s_test \ + $sdvt_i2s_cmds \ + $use_sdvt_spi \ + $sdvt_spi_test \ + $sdvt_spi_cmds \ + " + +quietly set vsim_custom_args "\ + $vsim_record_wlf \ + $vsim_do_files \ + $use_sdvt \ + +VSIM_PATH=$::env(VSIM_PATH) \ + " + +quietly set vopt_args "" +if {$vopt_acc_ena == "YES"} { + #+ quietly append vopt_args $vopt_args "+acc=abflmnprstv" + quietly append vopt_args $vopt_args "+acc=mnprv \ + -assertdebug \ + -bitscalars \ + -fsmdebug \ + -linedebug" +} +if {[info exists vopt_cov]} { + quietly append vopt_args $vopt_args $vopt_cov +} +if {$vopt_args != ""} { + quietly set vsim_vopt_args "-voptargs=\"$vopt_args\"" +} { + quietly set vsim_vopt_args "" +} + +quietly set vopt_cmd "vopt -quiet tb \ + $common_args \ + $custom_args \ + $common_sdvt_args \ + $vopt_args \ + -o pulp_opt -work work" + +if {[info exists ::env(VOPT_FLOW)]} { + onElabError {quit -code 1} + onerror {quit -code 1} + quietly eval $vopt_cmd + quietly eval "quit" + + +} { + set vsim_cmd "vsim -c -quiet $TB \ + -t ps \ + $vsim_cov \ + $common_args \ + $custom_args \ + $common_sdvt_args \ + $vsim_custom_args \ + $vsim_vopt_args \ + " + + eval $vsim_cmd + eval $vsimcmd_test_path + eval $vsimcmd_testname + + # Added these variables to avoid dummy warnings in the FLL + set StdArithNoWarnings 1 + set NumericStdNoWarnings 1 + + # check exit status in tb and quit the simulation accordingly + proc run_and_exit {} { + run -all + if {[info exists ::env(VSIM_EXIT_SIGNAL)]} { + quit -code [examine -radix decimal sim:$::env(VSIM_EXIT_SIGNAL)] + } else { + quit -code [examine -radix decimal sim:/tb_pulp/exit_status] + } + } + + #+ set StdArithNoWarnings 1 + #+ set NumericStdNoWarnings 1 + #+ run 1ps + #+ set StdArithNoWarnings 0 + #+ set NumericStdNoWarnings 0 +} diff --git a/fpga/sim/tcl_files/config/vsim_custom.tcl b/fpga/sim/tcl_files/config/vsim_custom.tcl new file mode 100644 index 00000000..b78475a7 --- /dev/null +++ b/fpga/sim/tcl_files/config/vsim_custom.tcl @@ -0,0 +1,81 @@ + +####################################### +quietly set testname_uid "dummy_testname" + +quietly set vsim_testname "dummy_testname" +if {[info exists ::env(PLPTEST_NAME)]} { + quietly set vsim_testname $::env(PLPTEST_NAME) + quietly regsub -all {\.} $vsim_testname _ testname_uid +} { + if {[info exists ::env(TESTNAME)]} { + quietly set testname_uid "$::env(TESTNAME)" + } +} +quietly set vsimcmd_testname "coverage attribute -test $testname_uid -name TESTNAME_PLP -value $vsim_testname" + +# vsim UID testname +#+ if {[info exists ::env(PLPTEST_RUN_ID)]} { +#+ #+ quietly set testname_uid "$::env(PLPTEST_RUN_ID)" +#+ } { +#+ } +quietly set vsim_testname_uid "-testname $testname_uid" + +quietly set vsim_test_path "dummy_testpath" +if {[info exists ::env(PLPTEST_PATH)]} { + quietly set vsim_test_path $::env(PLPTEST_PATH) +} +quietly set vsimcmd_test_path "coverage attribute -test $testname_uid -name TESTPATH -value $vsim_test_path" + +# vsim coverage enable +quietly set vsim_cov "" +if {[info exists ::env(VSIM_COV)]} { + if {$::env(VSIM_COV) == "YES"} { + quietly set vsim_cov "-coverage -coverstore $GAP_PATH_TCL/fe/sim/cov $vsim_testname_uid" + quietly set vopt_cov "+cover+pulp_chip." + #+ quietly set vopt_cov "+cover+pulp_chip. -coveropt 1" + } +} +####################################### +####################################### +# enable access control in vopt when vsim gui mode activated +quietly set vopt_acc_ena "" +if {[info exists ::env(VOPT_ACC_ENA)]} { + if {$::env(VOPT_ACC_ENA) == "YES"} { + quietly set vopt_acc_ena "YES" + } +} + +####################################### +# Enable DPI use in tb +####################################### +quietly set use_dev_dpi "-gENABLE_DEV_DPI=0" +if {[info exists ::env(PLP_DEVICES)]} { + quietly set use_dev_dpi "-gENABLE_DEV_DPI=1" +} + +####################################### +# record wlf +quietly set vsim_record_wlf "" +if {[info exists ::env(RECORD_WLF)]} { + if {$::env(RECORD_WLF) == "YES"} { + # enable access control in vopt when recordwlf mode activated + quietly set vopt_acc_ena "YES" + quietly set vsim_record_wlf "-wlf \"gap.wlf\"" + } +} + +# select do file for waveform selection +quietly set vsim_do_files "" +if {[info exists ::env(DO_FILES)]} { + quietly set vsim_do_files $::env(DO_FILES) +} +####################################### +####################################### +# UART tb or VIP select +quietly set uart_drv_mon "" +if {[info exists ::env(UART_DRV_MON)]} { + if {$::env(UART_DRV_MON) == "VIP"} { + quietly set uart_drv_mon "+uart_drv_mon=$::env(UART_DRV_MON)" + } +} +####################################### diff --git a/fpga/sim/tcl_files/config/vsim_fpga.tcl b/fpga/sim/tcl_files/config/vsim_fpga.tcl new file mode 100644 index 00000000..a310ec6d --- /dev/null +++ b/fpga/sim/tcl_files/config/vsim_fpga.tcl @@ -0,0 +1,15 @@ +set VSIM_FPGA_LIBS " \ + -L fpga_lib \ + -L secureip \ + -L simprims_ver \ + -L unifast \ + -L unifast_ver \ + -L unimacro \ + -L unimacro_ver \ + -L unisim \ + -L unisims_ver \ + +nowarnTRAN \ + +nowarnTSCALE \ + +nowarnTFMPC \ + glbl \ +" diff --git a/fpga/sim/tcl_files/config/vsim_sdvt.tcl b/fpga/sim/tcl_files/config/vsim_sdvt.tcl new file mode 100644 index 00000000..8d749cae --- /dev/null +++ b/fpga/sim/tcl_files/config/vsim_sdvt.tcl @@ -0,0 +1,98 @@ + +####################################### +# SDVT support +if {[info exists ::env(SMARTDV_HOME)]} { + quietly set SMARTDV_HOME $::env(SMARTDV_HOME) +} { + quietly set SMARTDV_HOME ./ +} + +quietly set use_sdvt "" +if {[info exists ::env(USE_SDVT)]} { + if {$::env(USE_SDVT) == "YES"} { + quietly set use_sdvt "-pli $VSIM_TB_PATH/smartdv_vip_models/sdvt_license_fl_mti_64.so" + } +} + +# SMARTDV Debug level 1 - verbose, 2 - debug, 3 - info, 4 - warning, 5 - error +quietly set sdvt_debug_level "" +if {[info exists ::env(SDVT_DEBUG_LEVEL)]} { + quietly set sdvt_debug_level "+sdvt_debug=$::env(SDVT_DEBUG_LEVEL)" +} + +####################################### +#### SDVT CPI support +quietly set use_sdvt_cpi "-gUSE_SDVT_CPI=0" +if {[info exists ::env(SDVT_CPI)]} { + if {$::env(SDVT_CPI) == "YES"} { + quietly set use_sdvt_cpi "-gUSE_SDVT_CPI=1" + } +} + +quietly set sdvt_cpi_test "" +if {[info exists ::env(SDVT_CPI_TEST)]} { + quietly set sdvt_cpi_test "+sdvt_cpi_test=$::env(SDVT_CPI_TEST)" +} + +## camera number of images to be transmitted +quietly set sdvt_cpi_cmds "" +if {[info exists ::env(SDVT_CPI_CMDS)]} { + quietly set sdvt_cpi_cmds "+sdvt_cpi_cmds=$::env(SDVT_CPI_CMDS)" +} + +quietly set sdvt_cpi_checker_ena "" +if {[info exists ::env(SDVT_CPI_CHECKER_ENA)]} { + if {$::env(SDVT_CPI_CHECKER_ENA) == "YES"} { + quietly set sdvt_cpi_checker_ena "+SDVT_CPI_CHECKER_ENA" + } +} + +quietly set sdvt_cpi_hres "" +if {[info exists ::env(SDVT_CPI_H_RES)]} { + quietly set sdvt_cpi_hres "+sdvt_cpi_hres=$::env(SDVT_CPI_H_RES)" +} + +quietly set sdvt_cpi_vres "" +if {[info exists ::env(SDVT_CPI_V_RES)]} { + quietly set sdvt_cpi_vres "+sdvt_cpi_vres=$::env(SDVT_CPI_V_RES)" +} +####################################### +#### SDVT I2S support +quietly set use_sdvt_i2s "-gUSE_SDVT_I2S=0" +if {[info exists ::env(SDVT_I2S)]} { + if {$::env(SDVT_I2S) == "YES"} { + quietly set use_sdvt_i2s "-gUSE_SDVT_I2S=1" + } +} + +quietly set sdvt_i2s_test "" +if {[info exists ::env(SDVT_I2S_TEST)]} { + quietly set sdvt_i2s_test "+sdvt_i2s_test=$::env(SDVT_I2S_TEST)" +} + +## camera number of images to be transmitted +quietly set sdvt_i2s_cmds "" +if {[info exists ::env(SDVT_I2S_CMDS)]} { + quietly set sdvt_i2s_cmds "+sdvt_i2s_cmds=$::env(SDVT_I2S_CMDS)" +} + +####################################### +#### SDVT SPI support +quietly set use_sdvt_spi "-gUSE_SDVT_SPI=0" +if {[info exists ::env(SDVT_SPI)]} { + if {$::env(SDVT_SPI) == "YES"} { + quietly set use_sdvt_spi "-gUSE_SDVT_SPI=1" + } +} + +quietly set sdvt_spi_test "" +if {[info exists ::env(SDVT_SPI_TEST)]} { + quietly set sdvt_spi_test "+sdvt_spi_test=$::env(SDVT_SPI_TEST)" +} + +## camera number of images to be transmitted +quietly set sdvt_spi_cmds "" +if {[info exists ::env(SDVT_SPI_CMDS)]} { + quietly set sdvt_spi_cmds "+sdvt_spi_cmds=$::env(SDVT_SPI_CMDS)" +} + diff --git a/fpga/sim/tcl_files/export_run.tcl b/fpga/sim/tcl_files/export_run.tcl new file mode 100755 index 00000000..1fb87948 --- /dev/null +++ b/fpga/sim/tcl_files/export_run.tcl @@ -0,0 +1,7 @@ +#!/bin/bash + +set TB "vopt_tb -L models_lib -L vip_lib" + +source ./tcl_files/config/vsim.tcl +source ./tcl_files/config/export_all.tcl + diff --git a/fpga/sim/tcl_files/rtl_vopt.tcl b/fpga/sim/tcl_files/rtl_vopt.tcl new file mode 100755 index 00000000..feacb1f2 --- /dev/null +++ b/fpga/sim/tcl_files/rtl_vopt.tcl @@ -0,0 +1,41 @@ +#!/usr/bin/env tclsh + +source ./tcl_files/config/vsim_ips.tcl +source ./tcl_files/config/vsim_rtl.tcl +source ./tcl_files/config/vsim_fpga.tcl + + +proc color {foreground text} { + # tput is a little Unix utility that lets you use the termcap database + # *much* more easily... + return [exec tput setaf $foreground]$text[exec tput sgr0] +} + +if {[catch { + info exists $::env(VSIM_PATH) +}]} { + puts [concat [color 1 "ERROR"] ": VSIM_PATH should be defined before building the RTL platform."] + exit 1 +} +eval exec vlib $::env(VSIM_PATH)/modelsim_libs/tb_lib +eval exec vmap secureip xilinx_libs/secureip +eval exec vmap simprims_ver xilinx_libs/simprims_ver +eval exec vmap unifast xilinx_libs/unifast +eval exec vmap unifast_ver xilinx_libs/unifast_ver +eval exec vmap unimacro_ver xilinx_libs/unimacro_ver +eval exec vmap unisim xilinx_libs/unisim +eval exec vmap unisims_ver xilinx_libs/unisims_ver +eval exec vmap unimacro xilinx_libs/unimacro + +eval exec vmap work $::env(VSIM_PATH)/modelsim_libs/tb_lib + +set sub_str "-L ${::env(VSIM_PATH)}/modelsim_libs/" +set VSIM_IP_LIBS [regsub -all -- "-L " $VSIM_IP_LIBS $sub_str] +set VSIM_RTL_LIBS [regsub -all -- "-L " $VSIM_RTL_LIBS $sub_str] + +if {[info exists ::env(VSIM_PATH)]} { + eval exec >@stdout vopt +acc=mnpr -o vopt_tb tb_pulp -floatparameters+tb_pulp $VSIM_FPGA_LIBS $VSIM_RTL_LIBS $VSIM_IP_LIBS -work work +} else { + eval exec >@stdout vopt +acc=mnpr -o vopt_pulp_chip pulp_chip $VSIM_FPGA_LIBS $VSIM_RTL_LIBS $VSIM_IP_LIBS -work pulpissimo_lib +} + diff --git a/fpga/sim/tcl_files/run.tcl b/fpga/sim/tcl_files/run.tcl new file mode 100755 index 00000000..f32d35de --- /dev/null +++ b/fpga/sim/tcl_files/run.tcl @@ -0,0 +1,5 @@ +#!/bin/bash + +set TB "vopt_tb -L models_lib -L vip_lib" + +source ./tcl_files/config/vsim.tcl diff --git a/fpga/sim/vcompile/.gitignore b/fpga/sim/vcompile/.gitignore new file mode 100644 index 00000000..e6ddad4c --- /dev/null +++ b/fpga/sim/vcompile/.gitignore @@ -0,0 +1,2 @@ +vcompile_ips.csh +ips/ diff --git a/fpga/sim/vcompile/build.mk b/fpga/sim/vcompile/build.mk new file mode 100644 index 00000000..18576dab --- /dev/null +++ b/fpga/sim/vcompile/build.mk @@ -0,0 +1,63 @@ +# +# Copyright (C) 2015 ETH Zurich, University of Bologna +# All rights reserved. +# +# This software may be modified and distributed under the terms +# of the BSD license. See the LICENSE file for details. +# + +# fix for colors on Ubuntu +SHELL=/bin/bash + +# colors +Green=\e[0;92m +Yellow=\e[0;93m +Red=\e[0;91m +NC=\e[0;0m +Blue=\e[0;94m + +# paths +VSIM_PATH?=. +PULP_PATH?=../.. +MSIM_LIBS_PATH=$(VSIM_PATH)/modelsim_libs +IPS_PATH=../../ips +RTL_PATH=../../rtl +TB_PATH=../../tb +LIB_PATH=$(MSIM_LIBS_PATH)/$(LIB_NAME) + +# commands +ifndef VERBOSE + LIB_CREATE=@vlib + LIB_MAP=@vmap + SVLOG_CC=@vlog -quiet -sv + VLOG_CC=@vlog -quiet + VHDL_CC=@vcom -quiet + subip_echo=@echo -e " $(NC)Building $(Yellow)$(IP)$(NC)/$(Yellow)$(1)$(NC)" + ip_echo=@echo -e "$(Green)Built$(NC) $(Yellow)$(IP)$(NC)" +else + LIB_CREATE=vlib + LIB_MAP=vmap + SVLOG_CC=vlog -quiet -sv + VLOG_CC=vlog -quiet + VHDL_CC=vcom -quiet + subip_echo=@echo -e "\n$(NC)Building $(Yellow)$(IP)$(NC)/$(Yellow)$(1)$(NC)" + ip_echo=@echo -e "\n$(Green)Built$(NC) $(Yellow)$(IP)$(NC)" +endif + +# rules +.PHONY: build lib clean + +build: vcompile-$(IP) + @true + +lib: $(LIB_PATH) + +$(LIB_PATH): $(MSIM_LIBS_PATH) + $(LIB_CREATE) $(LIB_PATH) + $(LIB_MAP) $(LIB_NAME) $(LIB_PATH) + +$(MSIM_LIBS_PATH): + mkdir -p $(MSIM_LIBS_PATH) + +clean: + rm -rf $(LIB_PATH) diff --git a/fpga/sim/vcompile/fpga.mk b/fpga/sim/vcompile/fpga.mk new file mode 100644 index 00000000..85e0b1a8 --- /dev/null +++ b/fpga/sim/vcompile/fpga.mk @@ -0,0 +1,39 @@ +# +# Copyright (C) 2016 ETH Zurich, University of Bologna +# All rights reserved. +# +# This software may be modified and distributed under the terms +# of the BSD license. See the LICENSE file for details. +# + +IP=fpga +IP_PATH=../ips +LIB_NAME=fpga_lib + +include vcompile/build.mk + +vcompile-$(IP): $(LIB_PATH)/_vmake + +$(LIB_PATH)/_vmake : | $(LIB_PATH) + @make --no-print-directory -f vcompile/fpga.mk vcompile-subip-fpga-mem vcompile-subip-fpga-zynq + +vcompile-subip-dummy: + @touch $(LIB_PATH)/_vmake + +vcompile-subip-fpga-mem: $(LIB_PATH)/fpga_mem.vmake + +$(LIB_PATH)/fpga_mem.vmake: + $(call subip_echo,fpga_mem) + $(SVLOG_CC) -work $(LIB_PATH) ../ips/xilinx_clk_mngr/ip/xilinx_clk_mngr_sim_netlist.v + $(SVLOG_CC) -work $(LIB_PATH) ../ips/xilinx_interleaved_ram/ip/xilinx_interleaved_ram_sim_netlist.v + $(SVLOG_CC) -work $(LIB_PATH) ../ips/xilinx_private_ram/ip/xilinx_private_ram_sim_netlist.v + $(SVLOG_CC) -work $(LIB_PATH) ../ips/xilinx_rom_bank_2048x32/ip/xilinx_rom_bank_2048x32_sim_netlist.v + $(SVLOG_CC) -work $(LIB_PATH) ../ips/xilinx_tcdm_bank_1024x32/ip/xilinx_tcdm_bank_1024x32_sim_netlist.v + @touch $(LIB_PATH)/fpga_mem.vmake + +vcompile-subip-fpga-zynq: $(LIB_PATH)/fpga_zynq.vmake + +$(LIB_PATH)/fpga_zynq.vmake: + $(call subip_echo,fpga_zynq) + $(SVLOG_CC) -work $(LIB_PATH) +define+PULP_FPGA_EMUL +define+PULP_FPGA_SIM -suppress 2583 -suppress 13314 +incdir+$(RTL_PATH)/includes ./misc/glbl.v + @touch $(LIB_PATH)/fpga_zynq.vmake diff --git a/fpga/sim/vcompile/ips.mk b/fpga/sim/vcompile/ips.mk new file mode 100644 index 00000000..fa81faf9 --- /dev/null +++ b/fpga/sim/vcompile/ips.mk @@ -0,0 +1,170 @@ +# +# Copyright (C) 2016-2018 ETH Zurich, University of Bologna +# All rights reserved. +# +# This software may be modified and distributed under the terms +# of the BSD license. See the LICENSE file for details. +# + +mkfile_path := $(dir $(abspath $(firstword $(MAKEFILE_LIST)))) + +.PHONY: build clean lib + +build: + @make --no-print-directory -f $(mkfile_path)/ips/L2_tcdm_hybrid_interco.mk build + @make --no-print-directory -f $(mkfile_path)/ips/adv_dbg_if.mk build + @make --no-print-directory -f $(mkfile_path)/ips/apb2per.mk build + @make --no-print-directory -f $(mkfile_path)/ips/apb_adv_timer.mk build + @make --no-print-directory -f $(mkfile_path)/ips/apb_fll_if.mk build + @make --no-print-directory -f $(mkfile_path)/ips/apb_gpio.mk build + @make --no-print-directory -f $(mkfile_path)/ips/apb_node.mk build + @make --no-print-directory -f $(mkfile_path)/ips/apb_interrupt_cntrl.mk build + @make --no-print-directory -f $(mkfile_path)/ips/axi.mk build + @make --no-print-directory -f $(mkfile_path)/ips/common_cells.mk build + @make --no-print-directory -f $(mkfile_path)/ips/axi_node.mk build + @make --no-print-directory -f $(mkfile_path)/ips/axi_slice.mk build + @make --no-print-directory -f $(mkfile_path)/ips/axi_slice_dc.mk build + @make --no-print-directory -f $(mkfile_path)/ips/timer_unit.mk build + @make --no-print-directory -f $(mkfile_path)/ips/fpu_div_sqrt_mvp.mk build + @make --no-print-directory -f $(mkfile_path)/ips/fpnew.mk build + @make --no-print-directory -f $(mkfile_path)/ips/jtag_pulp.mk build + @make --no-print-directory -f $(mkfile_path)/ips/riscv.mk build + @make --no-print-directory -f $(mkfile_path)/ips/ibex.mk build + @make --no-print-directory -f $(mkfile_path)/ips/scm.mk build + @make --no-print-directory -f $(mkfile_path)/ips/generic_FLL.mk build + @make --no-print-directory -f $(mkfile_path)/ips/tech_cells_generic.mk build + @make --no-print-directory -f $(mkfile_path)/ips/udma_core.mk build + @make --no-print-directory -f $(mkfile_path)/ips/udma_uart.mk build + @make --no-print-directory -f $(mkfile_path)/ips/udma_i2c.mk build + @make --no-print-directory -f $(mkfile_path)/ips/udma_i2s.mk build + @make --no-print-directory -f $(mkfile_path)/ips/udma_qspi.mk build + @make --no-print-directory -f $(mkfile_path)/ips/udma_sdio.mk build + @make --no-print-directory -f $(mkfile_path)/ips/udma_camera.mk build + @make --no-print-directory -f $(mkfile_path)/ips/udma_filter.mk build + @make --no-print-directory -f $(mkfile_path)/ips/udma_external_per.mk build + @make --no-print-directory -f $(mkfile_path)/ips/hwpe-ctrl.mk build + @make --no-print-directory -f $(mkfile_path)/ips/hwpe-stream.mk build + @make --no-print-directory -f $(mkfile_path)/ips/hwpe-mac-engine.mk build + @make --no-print-directory -f $(mkfile_path)/ips/riscv-dbg.mk build + @make --no-print-directory -f $(mkfile_path)/ips/pulp_soc.mk build + @make --no-print-directory -f $(mkfile_path)/ips/axi2mem.mk build + @make --no-print-directory -f $(mkfile_path)/ips/axi2per.mk build + @make --no-print-directory -f $(mkfile_path)/ips/per2axi.mk build + @make --no-print-directory -f $(mkfile_path)/ips/axi_size_conv.mk build + @make --no-print-directory -f $(mkfile_path)/ips/cluster_interconnect.mk build + @make --no-print-directory -f $(mkfile_path)/ips/event_unit_flex.mk build + @make --no-print-directory -f $(mkfile_path)/ips/mchan.mk build + @make --no-print-directory -f $(mkfile_path)/ips/hier-icache.mk build + @make --no-print-directory -f $(mkfile_path)/ips/icache-intc.mk build + @make --no-print-directory -f $(mkfile_path)/ips/icache_mp_128_pf.mk build + @make --no-print-directory -f $(mkfile_path)/ips/icache_private.mk build + @make --no-print-directory -f $(mkfile_path)/ips/cluster_peripherals.mk build + @make --no-print-directory -f $(mkfile_path)/ips/fpu_interco.mk build + @make --no-print-directory -f $(mkfile_path)/ips/pulp_cluster.mk build + @make --no-print-directory -f $(mkfile_path)/ips/tbtools.mk build + +lib: + @make --no-print-directory -f $(mkfile_path)/ips/L2_tcdm_hybrid_interco.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/adv_dbg_if.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/apb2per.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/apb_adv_timer.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/apb_fll_if.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/apb_gpio.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/apb_node.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/apb_interrupt_cntrl.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/axi.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/common_cells.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/axi_node.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/axi_slice.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/axi_slice_dc.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/timer_unit.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/fpu_div_sqrt_mvp.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/fpnew.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/jtag_pulp.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/riscv.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/ibex.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/scm.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/generic_FLL.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/tech_cells_generic.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/udma_core.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/udma_uart.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/udma_i2c.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/udma_i2s.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/udma_qspi.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/udma_sdio.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/udma_camera.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/udma_filter.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/udma_external_per.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/hwpe-ctrl.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/hwpe-stream.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/hwpe-mac-engine.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/riscv-dbg.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/pulp_soc.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/axi2mem.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/axi2per.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/per2axi.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/axi_size_conv.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/cluster_interconnect.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/event_unit_flex.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/mchan.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/hier-icache.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/icache-intc.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/icache_mp_128_pf.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/icache_private.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/cluster_peripherals.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/fpu_interco.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/pulp_cluster.mk lib + @make --no-print-directory -f $(mkfile_path)/ips/tbtools.mk lib + +clean: + @make --no-print-directory -f $(mkfile_path)/ips/L2_tcdm_hybrid_interco.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/adv_dbg_if.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/apb2per.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/apb_adv_timer.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/apb_fll_if.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/apb_gpio.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/apb_node.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/apb_interrupt_cntrl.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/axi.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/common_cells.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/axi_node.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/axi_slice.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/axi_slice_dc.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/timer_unit.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/fpu_div_sqrt_mvp.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/fpnew.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/jtag_pulp.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/riscv.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/ibex.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/scm.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/generic_FLL.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/tech_cells_generic.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/udma_core.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/udma_uart.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/udma_i2c.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/udma_i2s.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/udma_qspi.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/udma_sdio.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/udma_camera.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/udma_filter.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/udma_external_per.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/hwpe-ctrl.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/hwpe-stream.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/hwpe-mac-engine.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/riscv-dbg.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/pulp_soc.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/axi2mem.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/axi2per.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/per2axi.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/axi_size_conv.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/cluster_interconnect.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/event_unit_flex.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/mchan.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/hier-icache.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/icache-intc.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/icache_mp_128_pf.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/icache_private.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/cluster_peripherals.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/fpu_interco.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/pulp_cluster.mk clean + @make --no-print-directory -f $(mkfile_path)/ips/tbtools.mk clean diff --git a/fpga/sim/vcompile/rtl.mk b/fpga/sim/vcompile/rtl.mk new file mode 100644 index 00000000..61417693 --- /dev/null +++ b/fpga/sim/vcompile/rtl.mk @@ -0,0 +1,29 @@ +# +# Copyright (C) 2016-2018 ETH Zurich, University of Bologna +# All rights reserved. +# +# This software may be modified and distributed under the terms +# of the BSD license. See the LICENSE file for details. +# + +mkfile_path := $(dir $(abspath $(firstword $(MAKEFILE_LIST)))) + +.PHONY: build clean lib + +build: + @make --no-print-directory -f $(mkfile_path)/rtl/tb.mk build + @make --no-print-directory -f $(mkfile_path)/rtl/vip.mk build + @make --no-print-directory -f $(mkfile_path)/rtl/pulpemu.mk build + @make --no-print-directory -f $(mkfile_path)/rtl/pulp.mk build + +lib: + @make --no-print-directory -f $(mkfile_path)/rtl/tb.mk lib + @make --no-print-directory -f $(mkfile_path)/rtl/vip.mk lib + @make --no-print-directory -f $(mkfile_path)/rtl/pulpemu.mk lib + @make --no-print-directory -f $(mkfile_path)/rtl/pulp.mk lib + +clean: + @make --no-print-directory -f $(mkfile_path)/rtl/tb.mk clean + @make --no-print-directory -f $(mkfile_path)/rtl/vip.mk clean + @make --no-print-directory -f $(mkfile_path)/rtl/pulpemu.mk clean + @make --no-print-directory -f $(mkfile_path)/rtl/pulp.mk clean diff --git a/fpga/sim/vcompile/tb.mk b/fpga/sim/vcompile/tb.mk new file mode 100644 index 00000000..b4adab0d --- /dev/null +++ b/fpga/sim/vcompile/tb.mk @@ -0,0 +1,49 @@ +# +# Copyright (C) 2016 ETH Zurich, University of Bologna +# All rights reserved. +# +# This software may be modified and distributed under the terms +# of the BSD license. See the LICENSE file for details. +# + +IP=tb +IP_PATH=$(RTL_PATH)/tb +LIB_NAME=$(IP)_lib + +include vcompile/build.mk + +.PHONY: vcompile-$(IP) vcompile-subip-tb + +vcompile-$(IP): $(LIB_PATH)/_vmake + +$(LIB_PATH)/_vmake : $(LIB_PATH)/tb.vmake + @touch $(LIB_PATH)/_vmake + +ifdef USE_NETLIST +$(info USE_NETLIST defined in tb) +DEF_MODEL_LEVEL=+define+USE_NETLIST +else +DEF_MODEL_LEVEL= +endif + +SRC_SVLOG_TB=\ + $(IP_PATH)/../../ips/riscv-dbg/src/dm_pkg.sv\ + $(IP_PATH)/riscv_pkg.sv\ + $(IP_PATH)/jtag_pkg.sv\ + $(IP_PATH)/pulp_tap_pkg.sv\ + $(IP_PATH)/tb_clk_gen.sv\ + $(IP_PATH)/tb_fs_handler.sv\ + $(IP_PATH)/dpi_models/dpi_models.sv\ + $(IP_PATH)/tb_driver/tb_driver.sv\ + $(IP_PATH)/tb_pulp.sv\ + $(IP_PATH)/SimJTAG.sv\ + $(IP_PATH)/SimDTM.sv +SRC_VHDL_TB= + +vcompile-subip-tb: $(LIB_PATH)/tb.vmake + +$(LIB_PATH)/tb.vmake: $(SRC_SVLOG_TB) $(SRC_VHDL_TB) + $(call subip_echo,tb) + $(SVLOG_CC) -work $(LIB_PATH) -L riscv_dbg_lib +define+PULP_FPGA_EMUL +define+PULP_FPGA_SIM -suppress 2583 $(INCDIR_TB) $(SRC_SVLOG_TB) ${DEF_MODEL_LEVEL} + @touch $(LIB_PATH)/tb.vmake + diff --git a/fpga/sourceme.sh b/fpga/sourceme.sh new file mode 100644 index 00000000..61821cd6 --- /dev/null +++ b/fpga/sourceme.sh @@ -0,0 +1,33 @@ +#!/bin/bash + +export VIVADO_HOME=/opt/xilinx/Vivado/2018.2 +source $VIVADO_HOME/settings64.sh + +# either "zedboard" or "zc706" or "vcu118" or "zcu102" +if [ -z "$BOARD" ]; then + read -p "Which board you want to use: 1-zedboard 2-zcu102 3-vcu118 4-zc706 [4]: " BOARD + + if [ "$BOARD" = "1" ]; then + export BOARD="zedboard" + export XILINX_PART="xc7z020clg484-1" + export XILINX_BOARD="em.avnet.com:zynq:zed:c" + elif [ "$BOARD" = "2" ]; then + export BOARD="zcu102" + export XILINX_PART="xczu9eg-ffvb1156-2-e" + export XILINX_BOARD="xilinx.com:zcu102:part0:3.2" + elif [ "$BOARD" = "3" ]; then + export BOARD="vcu118" + export XILINX_PART="xcvu9p-flga2104-2L-e" + export XILINX_BOARD="xilinx.com:vcu118:part0:2.0" + else + export BOARD="zc706" + export XILINX_PART="xc7z045ffg900-2" + export XILINX_BOARD="xilinx.com:zc706:part0:1.3" + fi +fi + +echo "$BOARD" +echo "XILINX_PART=$XILINX_PART" +echo "XILINX_BOARD=$XILINX_BOARD" + +export VSIM_PATH=$PWD/sim diff --git a/fpga/tb b/fpga/tb new file mode 120000 index 00000000..4145557e --- /dev/null +++ b/fpga/tb @@ -0,0 +1 @@ +../rtl/tb \ No newline at end of file From ad12589c613fb9f9e4a33077d5cfecc3f77954c6 Mon Sep 17 00:00:00 2001 From: Angelo Garofalo Date: Mon, 3 Feb 2020 15:21:34 +0100 Subject: [PATCH 36/46] clean up pulpemu --- rtl/pulpemu/pulpemu.sv | 196 ++++++++++++----------------------------- 1 file changed, 55 insertions(+), 141 deletions(-) diff --git a/rtl/pulpemu/pulpemu.sv b/rtl/pulpemu/pulpemu.sv index d87191eb..d58f4b31 100644 --- a/rtl/pulpemu/pulpemu.sv +++ b/rtl/pulpemu/pulpemu.sv @@ -26,48 +26,14 @@ module pulpemu inout wire pad_uart_rx, inout wire pad_uart_tx, - //inout wire pad_uart_rts, //Mapped to spim_csn0 - //inout wire pad_uart_cts, //Mapped to spim_sck - - //inout wire led0_o, //Mapped to spim_csn1 - //inout wire led1_o, //Mapped to cam_pclk - //inout wire led2_o, //Mapped to cam_hsync - //inout wire led3_o, //Mapped to cam_data0 - - //inout wire switch0_i, //Mapped to cam_data1 - //inout wire switch1_i, //Mapped to cam_data2 - //inout wire switch2_i, //Mapped to cam_data7 - //inout wire switch3_i, //Mapped to cam_vsync - - //inout wire btn0_i, //Mapped to cam_data3 - //inout wire btn1_i, //Mapped to cam_data4 - //inout wire btn2_i, //Mapped to cam_data5 - //inout wire btn3_i, //Mapped to cam_data6 - - //inout wire pad_i2c0_sda, - //inout wire pad_i2c0_scl, - - //inout wire pad_pmod0_4, //Mapped to spim_sdio0 - //inout wire pad_pmod0_5, //Mapped to spim_sdio1 - //inout wire pad_pmod0_6, //Mapped to spim_sdio2 - // inout wire pad_pmod0_7, //Mapped to spim_sdio3 - - //inout wire pad_pmod1_0, //Mapped to sdio_data0 - //inout wire pad_pmod1_1, //Mapped to sdio_data1 - //inout wire pad_pmod1_2, //Mapped to sdio_data2 - //inout wire pad_pmod1_3, //Mapped to sdio_data3 - //inout wire pad_pmod1_4, //Mapped to i2s0_sck - //inout wire pad_pmod1_5, //Mapped to i2s0_ws - //inout wire pad_pmod1_6, //Mapped to i2s0_sdi - //inout wire pad_pmod1_7, //Mapped to i2s1_sdi - + inout FMC_sdio_data0, inout FMC_sdio_data1, inout FMC_sdio_data2, inout FMC_sdio_data3, inout FMC_sdio_cmd, inout FMC_sdio_sck, - + inout FMC_qspi_sdio0, inout FMC_qspi_sdio1, @@ -84,8 +50,8 @@ module pulpemu inout FMC_i2s0_ws, inout FMC_i2s0_sdi, inout FMC_i2s1_sdi, - - + + inout FMC_cam_pclk, inout FMC_cam_hsync, inout FMC_cam_data0, @@ -98,12 +64,6 @@ module pulpemu inout FMC_cam_data7, inout FMC_cam_vsync, - - - //inout wire pad_hdmi_scl, //Mapped to sdio_clk - //inout wire pad_hdmi_sda, //Mapped to sdio_cmd - - input wire pad_reset, input wire pad_jtag_tck, @@ -112,68 +72,45 @@ module pulpemu input wire pad_jtag_tms ); - localparam CORE_TYPE = 0; // 0 for RISCY, 1 for ZERORISCY, 2 for MICRORISCY - localparam USE_FPU = 1; - localparam USE_HWPE = 1; - - wire ref_clk; - - - //Differential to single ended clock conversion - IBUFGDS - #( - .IOSTANDARD("LVDS"), - .DIFF_TERM("FALSE"), - .IBUF_LOW_PWR("FALSE")) - i_sysclk_iobuf - ( - .I(ref_clk_p), - .IB(ref_clk_n), - .O(ref_clk) - ); - - pulp - #(.CORE_TYPE(CORE_TYPE), - .USE_FPU(USE_FPU), - .USE_HWPE(USE_HWPE) - ) i_pulp - ( -/* -----\/----- EXCLUDED -----\/----- - .pad_spim_sdio0(pad_pmod0_4), - .pad_spim_sdio1(pad_pmod0_5), - .pad_spim_sdio2(pad_pmod0_6), - .pad_spim_sdio3(pad_pmod0_7), - .pad_spim_csn0(pad_uart_rts), - .pad_spim_csn1(led0_o), - .pad_spim_sck(pad_uart_cts), - -----/\----- EXCLUDED -----/\----- */ - - .pad_spim_sdio0(FMC_qspi_sdio0), + localparam CORE_TYPE = 0; // 0 for RISCY, 1 for ZERORISCY, 2 for MICRORISCY + localparam USE_FPU = 1; + localparam USE_HWPE = 1; + + wire ref_clk; + + + //Differential to single ended clock conversion + IBUFGDS + #( + .IOSTANDARD("LVDS"), + .DIFF_TERM("FALSE"), + .IBUF_LOW_PWR("FALSE")) + i_sysclk_iobuf + ( + .I(ref_clk_p), + .IB(ref_clk_n), + .O(ref_clk) + ); + + pulp + #(.CORE_TYPE(CORE_TYPE), + .USE_FPU(USE_FPU), + .USE_HWPE(USE_HWPE) + ) i_pulp + ( + + .pad_spim_sdio0(FMC_qspi_sdio0), .pad_spim_sdio1(FMC_qspi_sdio1), .pad_spim_sdio2(FMC_qspi_sdio2), .pad_spim_sdio3(FMC_qspi_sdio3), .pad_spim_csn0(FMC_qspi_csn0), .pad_spim_csn1(FMC_qspi_csn1), .pad_spim_sck(FMC_qspi_sck), - - .pad_uart_rx(pad_uart_rx), //keep - .pad_uart_tx(pad_uart_tx), //keep - -/* -----\/----- EXCLUDED -----\/----- - .pad_cam_pclk(led1_o), - .pad_cam_hsync(led2_o), - .pad_cam_data0(led3_o), - .pad_cam_data1(switch0_i), - .pad_cam_data2(switch1_i), - .pad_cam_data3(btn0_i), - .pad_cam_data4(btn1_i), - .pad_cam_data5(btn2_i), - .pad_cam_data6(btn3_i), - .pad_cam_data7(switch2_i), - .pad_cam_vsync(switch3_i), - -----/\----- EXCLUDED -----/\----- */ - - .pad_cam_pclk(FMC_cam_pclk), + + .pad_uart_rx(pad_uart_rx), //keep + .pad_uart_tx(pad_uart_tx), //keep + + .pad_cam_pclk(FMC_cam_pclk), .pad_cam_hsync(FMC_cam_hsync), .pad_cam_data0(FMC_cam_data0), .pad_cam_data1(FMC_cam_data1), @@ -184,55 +121,32 @@ module pulpemu .pad_cam_data6(FMC_cam_data6), .pad_cam_data7(FMC_cam_data7), .pad_cam_vsync(FMC_cam_vsync), - -/* -----\/----- EXCLUDED -----\/----- - .pad_sdio_clk(pad_hdmi_scl), - .pad_sdio_cmd(pad_hdmi_sda), - .pad_sdio_data0(pad_pmod1_0), - .pad_sdio_data1(pad_pmod1_1), - .pad_sdio_data2(pad_pmod1_2), - .pad_sdio_data3(pad_pmod1_3), - -----/\----- EXCLUDED -----/\----- */ - - + + .pad_sdio_clk(FMC_sdio_sck), .pad_sdio_cmd(FMC_sdio_cmd), .pad_sdio_data0(FMC_sdio_data0), .pad_sdio_data1(FMC_sdio_data1), .pad_sdio_data2(FMC_sdio_data2), .pad_sdio_data3(FMC_sdio_data3), - - -/* -----\/----- EXCLUDED -----\/----- - .pad_i2c0_sda(pad_i2c0_sda), - .pad_i2c0_scl(pad_i2c0_scl), - -----/\----- EXCLUDED -----/\----- */ - - .pad_i2c0_sda(FMC_i2c0_sda), - .pad_i2c0_scl(FMC_i2c0_scl), - -/* -----\/----- EXCLUDED -----\/----- - .pad_i2s0_sck(pad_pmod1_4), - .pad_i2s0_ws(pad_pmod1_5), - .pad_i2s0_sdi(pad_pmod1_6), - .pad_i2s1_sdi(pad_pmod1_7), - -----/\----- EXCLUDED -----/\----- */ - - .pad_i2s0_sck(FMC_i2s0_sck), + + .pad_i2c0_sda(FMC_i2c0_sda), + .pad_i2c0_scl(FMC_i2c0_scl), + .pad_i2s0_sck(FMC_i2s0_sck), .pad_i2s0_ws(FMC_i2s0_ws), .pad_i2s0_sdi(FMC_i2s0_sdi), .pad_i2s1_sdi(FMC_i2s1_sdi), - - .pad_reset_n(~pad_reset), - - .pad_jtag_tck(pad_jtag_tck), //keep - .pad_jtag_tdi(pad_jtag_tdi), //keep - .pad_jtag_tdo(pad_jtag_tdo), //keep - .pad_jtag_tms(pad_jtag_tms), //keep - .pad_jtag_trst(1'b1), //keep - - .pad_xtal_in(ref_clk), //keep - .pad_bootsel() //keep - ); + + .pad_reset_n(~pad_reset), + + .pad_jtag_tck(pad_jtag_tck), //keep + .pad_jtag_tdi(pad_jtag_tdi), //keep + .pad_jtag_tdo(pad_jtag_tdo), //keep + .pad_jtag_tms(pad_jtag_tms), //keep + .pad_jtag_trst(1'b1), //keep + + .pad_xtal_in(ref_clk), //keep + .pad_bootsel() //keep + ); endmodule From da1eb49ff6a1bc554188073393785770d10c2b26 Mon Sep 17 00:00:00 2001 From: Angelo Garofalo Date: Tue, 18 Feb 2020 18:41:43 +0100 Subject: [PATCH 37/46] add xilinx ips --- fpga/ips/xilinx_clk_mngr/.gitignore | 21 + fpga/ips/xilinx_clk_mngr/Makefile | 21 + fpga/ips/xilinx_clk_mngr/tcl/run.tcl | 59 + fpga/ips/xilinx_interleaved_ram/.gitignore | 21 + fpga/ips/xilinx_interleaved_ram/Makefile | 21 + fpga/ips/xilinx_interleaved_ram/tcl/run.tcl | 29 + fpga/ips/xilinx_private_ram/.gitignore | 21 + fpga/ips/xilinx_private_ram/Makefile | 21 + fpga/ips/xilinx_private_ram/tcl/run.tcl | 29 + fpga/ips/xilinx_rom_bank_2048x32/Makefile | 21 + .../ips/xilinx_rom_bank_2048x32/boot_code.coe | 2050 +++++++++++++++++ fpga/ips/xilinx_rom_bank_2048x32/tcl/run.tcl | 13 + fpga/ips/xilinx_slow_clk_mngr/.gitignore | 21 + fpga/ips/xilinx_slow_clk_mngr/Makefile | 30 + fpga/ips/xilinx_slow_clk_mngr/Makefile~ | 30 + fpga/ips/xilinx_slow_clk_mngr/tcl/run.tcl | 45 + fpga/ips/xilinx_tcdm_bank_1024x32/Makefile | 21 + fpga/ips/xilinx_tcdm_bank_1024x32/tcl/run.tcl | 11 + 18 files changed, 2485 insertions(+) create mode 100644 fpga/ips/xilinx_clk_mngr/.gitignore create mode 100644 fpga/ips/xilinx_clk_mngr/Makefile create mode 100644 fpga/ips/xilinx_clk_mngr/tcl/run.tcl create mode 100644 fpga/ips/xilinx_interleaved_ram/.gitignore create mode 100644 fpga/ips/xilinx_interleaved_ram/Makefile create mode 100644 fpga/ips/xilinx_interleaved_ram/tcl/run.tcl create mode 100644 fpga/ips/xilinx_private_ram/.gitignore create mode 100644 fpga/ips/xilinx_private_ram/Makefile create mode 100644 fpga/ips/xilinx_private_ram/tcl/run.tcl create mode 100644 fpga/ips/xilinx_rom_bank_2048x32/Makefile create mode 100644 fpga/ips/xilinx_rom_bank_2048x32/boot_code.coe create mode 100644 fpga/ips/xilinx_rom_bank_2048x32/tcl/run.tcl create mode 100644 fpga/ips/xilinx_slow_clk_mngr/.gitignore create mode 100644 fpga/ips/xilinx_slow_clk_mngr/Makefile create mode 100644 fpga/ips/xilinx_slow_clk_mngr/Makefile~ create mode 100644 fpga/ips/xilinx_slow_clk_mngr/tcl/run.tcl create mode 100644 fpga/ips/xilinx_tcdm_bank_1024x32/Makefile create mode 100644 fpga/ips/xilinx_tcdm_bank_1024x32/tcl/run.tcl diff --git a/fpga/ips/xilinx_clk_mngr/.gitignore b/fpga/ips/xilinx_clk_mngr/.gitignore new file mode 100644 index 00000000..5099fe9c --- /dev/null +++ b/fpga/ips/xilinx_clk_mngr/.gitignore @@ -0,0 +1,21 @@ +#Ignore vivado project files generated by the tcl script +**/.Xil/* +**/reports/* +**/*.cache/* +**/*.hw/* +**/*.ip_user_files/* +**/*.runs/* +**/*.sim/* +**/*.srcs/* +*.edf +*.xpr +*.jou +*.log + +.cxl.* + +*ip + +*_stub.v +gmon.out + diff --git a/fpga/ips/xilinx_clk_mngr/Makefile b/fpga/ips/xilinx_clk_mngr/Makefile new file mode 100644 index 00000000..3326b6c2 --- /dev/null +++ b/fpga/ips/xilinx_clk_mngr/Makefile @@ -0,0 +1,21 @@ +PROJECT:=xilinx_clk_mngr + +all: + vivado-2018.2 vivado -mode batch -source tcl/run.tcl + mkdir -p ip + cp -r ${PROJECT}.srcs/sources_1/ip/${PROJECT}/* ip/. + cp ${PROJECT}.runs/${PROJECT}_synth_1/${PROJECT}.dcp ip/. + +gui: + vivado -mode gui -source tcl/run.tcl & + +clean: + rm -rf ip/* + mkdir -p ip + rm -rf ${PROJECT}.* + rm -rf component.xml + rm -rf vivado*.jou + rm -rf vivado*.log + rm -rf vivado*.str + rm -rf xgui + rm -rf .Xil diff --git a/fpga/ips/xilinx_clk_mngr/tcl/run.tcl b/fpga/ips/xilinx_clk_mngr/tcl/run.tcl new file mode 100644 index 00000000..4a344bfd --- /dev/null +++ b/fpga/ips/xilinx_clk_mngr/tcl/run.tcl @@ -0,0 +1,59 @@ +set partNumber $::env(XILINX_PART) +set boardName $::env(XILINX_BOARD) + +if [info exists ::env(BOARD)] { + set BOARD $::env(BOARD) +} else { + error "BOARD is not defined. Please source the sourceme.sh file." + exit +} +if [info exists ::env(XILINX_BOARD)] { + set boardName $::env(XILINX_BOARD) +} + +# detect target clock +if [info exists ::env(FC_CLK_PERIOD_NS)] { + set FC_CLK_PERIOD_NS $::env(FC_CLK_PERIOD_NS) +} else { + set FC_CLK_PERIOD_NS 50.000 +} +if [info exists ::env(CL_CLK_PERIOD_NS)] { + set CL_CLK_PERIOD_NS $::env(CL_CLK_PERIOD_NS) +} else { + set CL_CLK_PERIOD_NS 50.000 +} +if [info exists ::env(PER_CLK_PERIOD_NS)] { + set PER_CLK_PERIOD_NS $::env(PER_CLK_PERIOD_NS) +} else { + set PER_CLK_PERIOD_NS 100.000 +} + + +set FC_CLK_FREQ_MHZ [expr 1000 / $FC_CLK_PERIOD_NS] +set PER_CLK_FREQ_MHZ [expr 1000 / $PER_CLK_PERIOD_NS] +set CL_CLK_FREQ_MHZ [expr 1000 / $CL_CLK_PERIOD_NS] + +set ipName xilinx_clk_mngr + +create_project $ipName . -part $partNumber +set_property board_part $boardName [current_project] + +create_ip -name clk_wiz -vendor xilinx.com -library ip -module_name $ipName + +#CONFIG.CLKOUT3_USED {true} +#CONFIG.CLKOUT3_REQUESTED_OUT_FREQ {$CL_CLK_FREQ_MHZ} \ + +set_property -dict [eval list CONFIG.PRIM_IN_FREQ {125.000} \ + CONFIG.NUM_OUT_CLKS {3} \ + CONFIG.CLKOUT2_USED {true} \ + CONFIG.RESET_TYPE {ACTIVE_LOW} \ + CONFIG.RESET_PORT {resetn} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {$FC_CLK_FREQ_MHZ} \ + CONFIG.CLKOUT2_REQUESTED_OUT_FREQ {$PER_CLK_FREQ_MHZ} \ + CONFIG.CLKIN1_JITTER_PS {50.0} \ + ] [get_ips $ipName] + +generate_target all [get_files ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] +create_ip_run [get_files -of_objects [get_fileset sources_1] ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] +launch_run -jobs 12 ${ipName}_synth_1 +wait_on_run ${ipName}_synth_1 diff --git a/fpga/ips/xilinx_interleaved_ram/.gitignore b/fpga/ips/xilinx_interleaved_ram/.gitignore new file mode 100644 index 00000000..5099fe9c --- /dev/null +++ b/fpga/ips/xilinx_interleaved_ram/.gitignore @@ -0,0 +1,21 @@ +#Ignore vivado project files generated by the tcl script +**/.Xil/* +**/reports/* +**/*.cache/* +**/*.hw/* +**/*.ip_user_files/* +**/*.runs/* +**/*.sim/* +**/*.srcs/* +*.edf +*.xpr +*.jou +*.log + +.cxl.* + +*ip + +*_stub.v +gmon.out + diff --git a/fpga/ips/xilinx_interleaved_ram/Makefile b/fpga/ips/xilinx_interleaved_ram/Makefile new file mode 100644 index 00000000..e06a8882 --- /dev/null +++ b/fpga/ips/xilinx_interleaved_ram/Makefile @@ -0,0 +1,21 @@ +PROJECT:=xilinx_interleaved_ram + +all: + vivado-2018.2 vivado -mode batch -source tcl/run.tcl + mkdir -p ip + cp -r ${PROJECT}.srcs/sources_1/ip/${PROJECT}/* ip/. + cp ${PROJECT}.runs/${PROJECT}_synth_1/${PROJECT}.dcp ip/. + +gui: + vivado -mode gui -source tcl/run.tcl & + +clean: + rm -rf ip/* + mkdir -p ip + rm -rf ${PROJECT}.* + rm -rf component.xml + rm -rf vivado*.jou + rm -rf vivado*.log + rm -rf vivado*.str + rm -rf xgui + rm -rf .Xil diff --git a/fpga/ips/xilinx_interleaved_ram/tcl/run.tcl b/fpga/ips/xilinx_interleaved_ram/tcl/run.tcl new file mode 100644 index 00000000..c46f21fb --- /dev/null +++ b/fpga/ips/xilinx_interleaved_ram/tcl/run.tcl @@ -0,0 +1,29 @@ +set partNumber $::env(XILINX_PART) +set boardName $::env(XILINX_BOARD) + +# detect target ram size +if [info exists ::env(INTERLEAVED_BANK_SIZE)] { + set INTERLEAVED_BANK_SIZE $::env(INTERLEAVED_BANK_SIZE) +} else { + set INTERLEAVED_BANK_SIZE 28672 +} + +set ipName xilinx_interleaved_ram + +create_project $ipName . -part $partNumber +set_property board_part $boardName [current_project] + +create_ip -name blk_mem_gen -vendor xilinx.com -library ip -module_name $ipName + +set_property -dict [eval list CONFIG.Use_Byte_Write_Enable {true} \ + CONFIG.Byte_Size {8} \ + CONFIG.Write_Width_A {32} \ + CONFIG.Write_Depth_A {$INTERLEAVED_BANK_SIZE} \ + CONFIG.Read_Width_A {32} \ + CONFIG.Register_PortA_Output_of_Memory_Primitives {false} \ + ] [get_ips $ipName] + +generate_target all [get_files ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] +create_ip_run [get_files -of_objects [get_fileset sources_1] ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] +launch_run -jobs 8 ${ipName}_synth_1 +wait_on_run ${ipName}_synth_1 diff --git a/fpga/ips/xilinx_private_ram/.gitignore b/fpga/ips/xilinx_private_ram/.gitignore new file mode 100644 index 00000000..5099fe9c --- /dev/null +++ b/fpga/ips/xilinx_private_ram/.gitignore @@ -0,0 +1,21 @@ +#Ignore vivado project files generated by the tcl script +**/.Xil/* +**/reports/* +**/*.cache/* +**/*.hw/* +**/*.ip_user_files/* +**/*.runs/* +**/*.sim/* +**/*.srcs/* +*.edf +*.xpr +*.jou +*.log + +.cxl.* + +*ip + +*_stub.v +gmon.out + diff --git a/fpga/ips/xilinx_private_ram/Makefile b/fpga/ips/xilinx_private_ram/Makefile new file mode 100644 index 00000000..bc81711f --- /dev/null +++ b/fpga/ips/xilinx_private_ram/Makefile @@ -0,0 +1,21 @@ +PROJECT:=xilinx_private_ram + +all: + vivado-2018.2 vivado -mode batch -source tcl/run.tcl + mkdir -p ip + cp -r ${PROJECT}.srcs/sources_1/ip/${PROJECT}/* ip/. + cp ${PROJECT}.runs/${PROJECT}_synth_1/${PROJECT}.dcp ip/. + +gui: + vivado -mode gui -source tcl/run.tcl & + +clean: + rm -rf ip/* + mkdir -p ip + rm -rf ${PROJECT}.* + rm -rf component.xml + rm -rf vivado*.jou + rm -rf vivado*.log + rm -rf vivado*.str + rm -rf xgui + rm -rf .Xil diff --git a/fpga/ips/xilinx_private_ram/tcl/run.tcl b/fpga/ips/xilinx_private_ram/tcl/run.tcl new file mode 100644 index 00000000..e2f21dee --- /dev/null +++ b/fpga/ips/xilinx_private_ram/tcl/run.tcl @@ -0,0 +1,29 @@ +set partNumber $::env(XILINX_PART) +set boardName $::env(XILINX_BOARD) + +# detect target ram size +if [info exists ::env(PRIVATE_BANK_SIZE)] { + set PRIVATE_BANK_SIZE $::env(PRIVATE_BANK_SIZE) +} else { + set PRIVATE_BANK_SIZE 8192 +} + +set ipName xilinx_private_ram + +create_project $ipName . -part $partNumber +set_property board_part $boardName [current_project] + +create_ip -name blk_mem_gen -vendor xilinx.com -library ip -module_name $ipName + +set_property -dict [eval list CONFIG.Use_Byte_Write_Enable {true} \ + CONFIG.Byte_Size {8} \ + CONFIG.Write_Width_A {32} \ + CONFIG.Write_Depth_A {$PRIVATE_BANK_SIZE} \ + CONFIG.Read_Width_A {32} \ + CONFIG.Register_PortA_Output_of_Memory_Primitives {false} \ + ] [get_ips $ipName] + +generate_target all [get_files ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] +create_ip_run [get_files -of_objects [get_fileset sources_1] ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] +launch_run -jobs 8 ${ipName}_synth_1 +wait_on_run ${ipName}_synth_1 diff --git a/fpga/ips/xilinx_rom_bank_2048x32/Makefile b/fpga/ips/xilinx_rom_bank_2048x32/Makefile new file mode 100644 index 00000000..5f14594e --- /dev/null +++ b/fpga/ips/xilinx_rom_bank_2048x32/Makefile @@ -0,0 +1,21 @@ +PROJECT:=xilinx_rom_bank_2048x32 + +all: + vivado-2018.2 vivado -mode batch -source tcl/run.tcl + mkdir -p ip + cp -r ${PROJECT}.srcs/sources_1/ip/${PROJECT}/* ip/. + cp ${PROJECT}.runs/${PROJECT}_synth_1/${PROJECT}.dcp ip/. + +gui: + vivado -mode gui -source tcl/run.tcl & + +clean: + rm -rf ip/* + mkdir -p ip + rm -rf ${PROJECT}.* + rm -rf component.xml + rm -rf vivado*.jou + rm -rf vivado*.log + rm -rf vivado*.str + rm -rf xgui + rm -rf .Xil diff --git a/fpga/ips/xilinx_rom_bank_2048x32/boot_code.coe b/fpga/ips/xilinx_rom_bank_2048x32/boot_code.coe new file mode 100644 index 00000000..5cbe3e78 --- /dev/null +++ b/fpga/ips/xilinx_rom_bank_2048x32/boot_code.coe @@ -0,0 +1,2050 @@ +memory_initialization_radix=2; +memory_initialization_vector= +00001000100000000000000001101111, +00001000010000000000000001101111, +00001000000000000000000001101111, +00000111110000000000000001101111, +00000111100000000000000001101111, +00000111010000000000000001101111, +00000111000000000000000001101111, +00000110110000000000000001101111, +00000110100000000000000001101111, +00000110010000000000000001101111, +00000110000000000000000001101111, +00000101110000000000000001101111, +00000101100000000000000001101111, +00000101010000000000000001101111, +00000101000000000000000001101111, +00000100110000000000000001101111, +00000100100000000000000001101111, +00000100010000000000000001101111, +00000100000000000000000001101111, +00000011110000000000000001101111, +00000011100000000000000001101111, +00000011010000000000000001101111, +00000011000000000000000001101111, +00000010110000000000000001101111, +00000010100000000000000001101111, +00000010010000000000000001101111, +00000010000000000000000001101111, +00000001110000000000000001101111, +00000001100000000000000001101111, +00000001010000000000000001101111, +00000001000000000000000001101111, +00000000110000000000000001101111, +00000000110000000000000001101111, +00000000000000000000000001101111, +00110000001000000000000001110011, +00000010000110001010000100010111, +01001101010000010000000100010011, +01011000010000000000000001101111, +10000101100000101000000100110010, +00011010000100001001011110110111, +00000000000001111010000000100011, +00010000010100000000000001110011, +10000111101101111011111111110101, +10000111100100110001110000011000, +10100000001000110000000000000111, +10000010001000110000000000000111, +10100100001000110000000000000111, +10010001001000110000001000000111, +10000010001000110000001000000111, +10000000100000100000001000000111, +00011100000110001000011110110111, +00000000000001111000011110010011, +10010101001111100000010100010010, +11001011000010010100010101111000, +00000010101101111100011110000011, +11111100000101111011011110110011, +00100011000000111100011110000001, +10000011000000100000010101000101, +10000000100000100100010100000001, +11001010001001100001000100000001, +00011100000110001000010010110111, +00000000000001001000011110010011, +00000000000101111100011110000011, +11001100001000101100111000000110, +11000110010011101100100001001010, +10001011101000011100010001010010, +10101001001101111100101111001001, +00100111100000110001110000011000, +10000100001010101001011111001001, +00011100000110001010010100110111, +00000000000001001000010010010011, +00001001000100111000100110101110, +00001010000100111001011111001001, +11000111100110011001100000000101, +10011000000001010000010100010011, +00000000000010010010000000100011, +00110111100000000001000011101111, +00111101010010010010100000000011, +10000111000100111000011111001110, +10000110100100110000000101010100, +10000110001000100000000001010100, +10000101010100101000010110100010, +00010100111000000001000011101111, +00000010101101001100011110000011, +00111100000010010010101000100011, +11000011101100011000101111000001, +11101101101110001000011010110111, +11111111110010011000010110010011, +01000111100000010101011101111101, +00110010000001101000011010010011, +00000000101101111110101001100011, +00100111100000111001010001001110, +01000111000100111111111111000100, +10000010011000111111111111110111, +00110111000011010000001011100111, +00000000111101000000011000110011, +00000000000001100100011000000011, +11010000111110111000111100110001, +01010101000100110000000010000011, +00000111001100110000000000010111, +10001111011101011100000000000111, +00000111100001011000111100101001, +01000000111100101011111111000001, +01000100110100100100010001100010, +01001001101100100100100101000010, +01100001000001010100101000100010, +01010111000100111000000010000010, +01100111101101110100000001010101, +00000111100100010001101000010000, +10010111001111100000011100001010, +01000111100001010100001100010100, +00000000101001111001010100110011, +11111111111101010100010100010011, +11000011000010001000110101110101, +10010111101101111000000010000010, +00000111001101110001101000010000, +11000011110110000000010000000000, +00000000110001111000011000010011, +10010101100100110100001000010100, +11011011011000110000000001010110, +10000110100100110000000000000101, +01000010100101000000001001000111, +00000001010001111000011010010011, +00000111101000011100001010011000, +10000000100000101100001110011000, +00010000010100000000000001110011, +01110001001110011011011111000101, +10000100001101111101110000100010, +11010100010100100001110000011000, +00000000000001000000010000010011, +00011010000100000010101000110111, +11010110010011101101101000100110, +11010000010110101101001001010110, +11001100011000101100111001011110, +10001001101010101100101001100110, +00001000000010100000110010010011, +11011000010010101101111000000110, +10000100101100101000010100101110, +00001011100100111000101010101110, +01011100000000010000100000000000, +00100100100001000000101100010011, +00001001000010100000101000010011, +01010100011000101110110010011001, +01010100110100100101000011110010, +01011001101100100101100101000010, +01011010100100100101101000100010, +01001011111100100101101100000010, +01001100110100100100110001100010, +01100001001000011000010110110010, +01010111100000111011110101100001, +00000100001000110000001101010100, +11010110100100110010010110000100, +11010111000100110000000010001001, +00000100101000110000000010000111, +11110111100100110010010011100100, +00000101001000110000111111110111, +01000111100000110010010011110100, +00000101101000110000001101110100, +00000111000100110010010000000100, +00000110001000111111100000000000, +00000110101000110010010011100100, +00000111001000110010010011110100, +11110110100100110010010011100100, +00000111101000110000111111110110, +00001000001000110010010011010100, +11110110100100110010010011100100, +00001000101000110000111111111001, +00001001001000110010010011010100, +00001001101000110010010000000100, +11000111101100110010010011100100, +00001010001000111100000000000111, +01000111100001010010010011110100, +00000101011101001100100100110011, +11010001011000110100011100110101, +00000111100100110000001010010111, +00001010101000111111110000000000, +00000111100100110010010011110100, +11110111100100111111111111111001, +00001011001000110000111111110111, +00000111100100110010010011110100, +00001011101000110000010000000000, +01000111010000010010010011110100, +00000110000000000000011110010011, +00000000111110110100011100100011, +00000010101101000100011110000011, +10011001110010100000011100000101, +11000000000101111001011110110011, +00000111100111100000011110011101, +00000001100101111000011010110011, +10100010001010111000010110110110, +10100000001000110000000101010101, +10010111110100100000000100100101, +00000110101000010100010111000001, +10000110101111101100001010001100, +00000001011001101010001000101011, +00000111101000011100001010011000, +11000110001010101100001110001100, +00111101010101011100010000110010, +10000100101100111001101011001010, +01000110001000100100000100100100, +10111111000110010100010100110010, +00011100000110001000011100110111, +00000000000001110000011100010011, +00000000010001110100011110000011, +11000010001101111001011110110011, +00100100111101110010010000100011, +00000010101001110100011110000011, +11111100000101111011011010110011, +11000001110001101100011010110011, +00100100110101110010011000100011, +00100000000001110000011010110111, +00000110101101111000110101010101, +00101000001000111001000000000000, +00000110100001010010010010100111, +00100100110101110010101000100011, +11000010000101111001011110110011, +00011010000100000010011100110111, +00001010000001110000011100010011, +10010111101110100000011110011110, +00011100000110001000011010110111, +10000110100100111000011100111110, +00100010001010110010010010000110, +01000110110000010000000011010111, +00000111101000011100001100010100, +11000011100110000100011101010001, +00010001000000011011010110011001, +10000100001010101100110000100010, +11000110001011100100010101100001, +11001110000001101100010000110010, +01000101101100100011101100010101, +00011110011000110100011000100010, +10000111101101110001000000000101, +10000111000100110001110000011000, +01000110100000110000000000000111, +10000111100100110000001010000111, +10110110101100110000000000000111, +11101110110110011111101000100110, +00000000010001110100011110000011, +00100000000001110000010100110111, +00100000000011110000100000110111, +11000010001101111001011110110011, +00100100111101110010010000100011, +00000010101001110100011110000011, +11111100000101111011011010110011, +11000001110001101100011010110011, +00100100110101110010011000100011, +00000000001101010000011010010011, +00100100110101110010100000100011, +11011110100001000001011010110011, +00000001000001101110011010110011, +11101110100001000011010000110011, +00100100110101110010101000100011, +00000110100100111000110001001001, +00000101001101111111111111110110, +00101100001000110111000001000111, +10001110110010010010010010000111, +00100100110101110010111000100011, +10010000000000000000011010110111, +00100000001000110000011010000101, +10010111101100110010011011010111, +00100110101101111100001000010111, +00000111100111100001101000010000, +00001000000001101000011100010011, +10000101001110101001011100111110, +00000000101101010010001000101011, +00001010000001101000011010010011, +10010111101101101100000100010000, +01000110010100010000011100100001, +00011100000110001000011010110111, +10000110100100111100001100010000, +10000111001111100010010010000110, +00000000110101110010001000101011, +11000011000101000100011011110001, +11000011100100000000011110100001, +01000000111100100100010001100010, +10111011101101010110000100000101, +00000100000101101011110101100011, +00000010101001111100011100000011, +11111100000101110011011010110011, +01110110100100111110001010110001, +00100111001101110000001000000111, +00000111000100110001101000010000, +11001010100001010100101000000111, +00000011000101111010011010000011, +11000011000000001000110001010101, +00000010101001111100011110000011, +00011010000100000010011100110111, +00001000000001110000011100010011, +11000010000101111001011110110011, +00000111100111100000011110100001, +10000111001111101001011110111010, +00000000101101110010001000101011, +00000111101000011100001100010000, +11000011100110000100011101010001, +01000100001100111011111101000101, +10111111110100011100000110000100, +00011010000100000010011100110111, +01001010100001110010000000100011, +10000101001000101011011111110001, +01000000111100100100010001100010, +00000000011011110110000100000101, +01000000111100100001010000010000, +01100001000001010100010001100010, +10000111001101111000000010000010, +00100111101101110001110000011000, +00000111000100110001101000010000, +00000101100001100000000000000111, +00100100101001110001010000100011, +01001010000001111000011010010011, +11000001100001011100010110110011, +00000111000100111100001010001100, +10000110100100110010010010000111, +11000010100110000100100100000111, +01001001010001111000011100010011, +11000011000101000100011010001001, +01001001100001111000011110010011, +11000011100110000100011101010001, +10010111101101111011100111011001, +10000111000100110001101000010000, +01100110100100010000000001000111, +00000111110100011100001100010100, +01000111011000110100011100000001, +10010111101101110000000010100111, +01100111000100010001101000010000, +10000000100000101100011110011000, +00010000010100000000000001110011, +00000111000001011100001110010100, +00010001000000011011011111101101, +01000100101101111100101000100110, +11000010010101100001101000010000, +11001110000001101100000001011010, +11001000010010101100110000100010, +11000100010100101100011001001110, +00000111010001001000010010010011, +01001011000010010100101010000101, +00110110011010010100010101101101, +10100000001000111110010101000001, +01000000100000000000000101010100, +00010000000001000111011110010011, +01000101000010011100101111001101, +11101001001111010011111010100101, +00111010001100111000000000100101, +00110100001100111111000001110100, +00100011011000111111100000110100, +01000110011000110000010000100100, +11011000011110010000000010001011, +00000010000101000010011101100011, +00100111011000110011111000000101, +00111101111000110000011001000100, +01000101000110011111111001010100, +11100001010000010011111010000001, +00000000000001001010000000100011, +00000000000001001010100100000011, +00000000100110010101100100010011, +11110000011110010011100100110011, +00000110010110010011011101100011, +00110111100101010100010100000101, +01000101011100011011011111110101, +11110101011000010011111000000101, +00011010000100000100011110110111, +10100000000000011101101111100000, +00011100000110001000011110110111, +00000000000001111000011110010011, +00000000000001111101011100000011, +01000000001110100101101000010011, +11001110001101000010011100110011, +00000000111001111001000000100011, +00000010100001111100011100000011, +11000010000010100010011100110011, +00000010111001111000010000100011, +01000100011000100100000011110010, +01001001010000100100010011010010, +01001010001000100100100110110010, +01001011000000100100101010010010, +10000000100000100110000100000101, +00110100111011010100010100010101, +10100000001000111110100100011001, +01000101000001010000000101010100, +10101001100000110011011100111001, +11011001100100110000000000000100, +10111001101100110000000010011001, +10000100010011101111000001111001, +10000100010010101011011110011101, +01000101000001011011011110001101, +10110111100100010011110111011101, +10010110001011101000011110101010, +00000000110001011001001101100011, +11000111000010111000000010000010, +10000000101010110000000000010101, +10111111110011010000000011100111, +01000111101101110111000100111001, +11011110000001100001101000010000, +11011010001001101101110000100010, +11010110010011101101100001001010, +11010010010101101101010001010010, +11001110010111101101000001011010, +11001010011001101100110001100010, +11000110011011101100100001101010, +00000111110001111010011110000011, +00011100000110001010010010110111, +11111000001101111011011110110011, +10010111110001001000011100010011, +00111100111101110010110000100011, +00000000001001111011011101100011, +00011100000000000000011110110111, +10010111100000100100001110011100, +01000111100001011010000000000001, +10010111110001001000010010010011, +00011100000110001000100110110111, +00111100111101001010101000100011, +10000111100100111100000010011100, +10000111100100110000000000001001, +10000100000100110000010111000111, +01010000111110110000000000001001, +10101000001010110000000111110010, +00000000000000010000000000000111, +00011010000100000110011110110111, +10000111000100110101100101111101, +00100000001000110000000001000111, +10000111000100110000000100100111, +00100000001000110000000010000111, +10000111000100110000000100100111, +00100000001000110000000011000111, +10000111000100110000000100100111, +00100000001000110000000100000111, +10000111000100110000000100100111, +00100000001000110000000101000111, +10000111000100110000000100100111, +00100000001000110000000110000111, +10000111000100110000000100100111, +00100000001000110000000111000111, +10000111100100110000000100100111, +10100000001000110000001000000111, +01000111101101110000000100100111, +10100111100000110001101000010000, +10011110011000110000110001000111, +00111010111000010001000000000111, +00000000000101000100011110000011, +00000010000001111111011110010011, +10010111101101111100011110001001, +10100000001000110001101000010000, +01000111100000111000000100100111, +01000111000001010000001010000100, +00100111101100110100011010001001, +01010111000000111100001000000111, +00000100001000110000000000000100, +10100111001100110000001011110100, +00010000001000111100111000110110, +00000111000000110000000011100100, +01001101011000110000001010110100, +10110111101100110000000000000111, +10010001011000111111101000100111, +01000111100000110000111000000111, +01000111000010010000000001000100, +11000010001101110010011110110011, +00000000111101000000001000100011, +00000010100001000100011110000011, +11111010001001111011011110110011, +00000000001001111011011001100011, +00000000000010011000010100010011, +01101111101000000000000011101111, +00000010101101000100011110000011, +00000010000001111111011110010011, +01000111100001011110011110000001, +00000010111101000001111000100011, +00000010101001000100011110000011, +00000100000001111111011100010011, +01000111000001011110011100000001, +00000010111001000000000010100011, +00010000000001111110011110110011, +00000000000001111100010101100011, +00001100101000110100011111000001, +01000111100000110000001011110100, +10110111101100110000001010000100, +11101111110010011111101000100111, +00000010101001000100010100000011, +00011010000100000010011100110111, +00010101001100110100001100010100, +01000111100001011100001000010101, +00000000101001111001011110110011, +11000011000111001000111111010101, +00110100000101010000010100001101, +00000010101101000100010100000011, +11111100000101010011011110110011, +00100111001101111100111110010001, +01000011000101000001101000010000, +11000000000101010001010100110011, +01000111100001010000010100011101, +00000000101001111001011110110011, +11000011000111001000111111010101, +00110100000000010000010100001010, +00000010101101000100011110000011, +11111100000101111011011110110011, +00001001000100111100011110011101, +00000110000100110000010010000100, +10000101110010100010000001000000, +00111100001001010100010100000001, +00001010100100110100101000000101, +00100101100000110000001000000000, +11000101100100010000000101001001, +00000001100010010010011000000011, +00000001000010010010010100000011, +00001010000001010011010000001101, +00010110111000110000100101000001, +01000101000001011111111101011010, +11001101000011010011000011010101, +00110000110000010011100001010101, +10111101111001010011101100001101, +00000000000101111011011101100011, +00000000010001000100011110000011, +11000010001100000010011110110011, +10110001111000111011011100000101, +10111111000000011111001000100111, +11111000000101111011001011100011, +00011010000100000010011100110111, +00000101000100110100001100011100, +11000111101100110000001000000000, +11000011000111001100000010000111, +00000101000100110011101001001001, +10110111101001010000001000010000, +00000000000001000101100100000011, +00011001001100110100010100001001, +00111000011110011100010000111001, +00100100000001010001001001100011, +00100010000010010000111101100011, +11111010001010010011101011100011, +00110000011110010100010100011101, +00100010000001010001101001100011, +00000010100001000100011110000011, +11111010001001111011011110110011, +00100010000101111011010101100011, +01000000000000000000011110010011, +10101110001000110100010101000101, +00111000100011010011110011110100, +00010100000001010001101101100011, +00000010100001000100011110000011, +11111010001001111011011110110011, +00100000000001111001100101100011, +11110000111011110100010101010101, +11100101010110011000010111111111, +00000010100001000100011110000011, +11000011110110011000101110010001, +00000010101001000100011110000011, +00000000010001000100010110000011, +00100000000001110000011010110111, +11111100000101111011011000110011, +11000010001101011001010110110011, +00100100101101000010010000100011, +11000001110001100100011000110011, +00100100110001000010011000100011, +00000110011001101000011100010011, +00100100111001000010100000100011, +10010000000000000000011100110111, +00100100111001000010101000100011, +00100100101101000010010000100011, +00100100110001000010011000100011, +00001001100101101000011010010011, +00100100110101000010100000100011, +00101010001000110000011100000101, +10010111101100110010010011100100, +00100111001101111100001000010111, +00000111000100110001101000010000, +00000111100111100000101000000111, +10000110101101111001011110111010, +10000111001111100001110000011000, +00100100100001101000011010010011, +00000000110101110010001000101011, +00000010000000000000011010010011, +00000111101000011100001100010100, +11000011100110000100011101010001, +01000111100000110011000011001101, +01000101010100010000001010000100, +00000100000001111111011110010011, +01000101000000111100001110011001, +00111110111101010000001110000100, +11110000111011110100010101011001, +11101101000000011111110010101111, +00111101100001001010011110000011, +00000000000101111011100101100011, +00000010100001000100011110000011, +11000111100000011000101111000001, +00001010101100000000010100010011, +01000101011101010011010000110001, +11111010110011111111000011101111, +01000111100000111110110100100101, +10110111001100110000001010010100, +11001011000100011111110000010111, +11000111100010011000101110001001, +00111101100001001010011110000011, +00000000000101111011010101100011, +00000010110001000100010100000011, +01000111100000110011001011100101, +11110111000100110000001010010100, +11001011000100010000000001000111, +11000111100010011000101110100001, +00111101100001001010011110000011, +00000000000101111011010101100011, +00000010110101000100010100000011, +01000111100000110011001011110001, +11110111000100110000001010010100, +11001011000110010000000100000111, +00000010000001111111011110010011, +10100111100000111100011110001001, +10110101011000110011110110000100, +01000101000000110000000000010111, +00110010011111010000001011100100, +00000010100101000100011110000011, +00000001000001111111011100010011, +11100111101100111100111100000001, +11010110011000110001000000000111, +10100111100000110000000000000111, +10110101011000110011110110000100, +01000101000000110000000000010111, +00110010011110010000001011110100, +11110000111011110100010101011101, +11101001000000011111001011101111, +00000010100001000100011110000011, +11000111100000011000101110100001, +00000011000001000100010100000011, +01000101001100010011011010101001, +11110001100011111111000011101111, +00001001000100111110110100000001, +10000101110010100110010011000100, +00010001100000000000011000010011, +00000101100100110011001011011001, +10000101010010100001000110000000, +11110010010011111111000011101111, +01000101001011010100011110000101, +00111100111101001010101000100011, +11101111010011111111000011101111, +11100000000001010001100011100011, +01100101110001000000100110010011, +00001100101101110100101100000001, +10001011101101110000000100000000, +00100111100000110001110000011000, +01100001011000110110010100000100, +01000101001111010010011011111011, +11101101010011111111000011101111, +00100110101101111110010100110001, +00000111101101110001101000010000, +10000111000100110000000001010000, +00000111100110010010101001000110, +01100111101101111100001100011100, +01010111011111010001101000010000, +00000000010001111000011000010011, +10000110000100111100001000011000, +11000010000110000000000010000111, +00000000110001111000011000010011, +10000110000100111100001000011000, +11000010000110000000000100000111, +00000001010001111000011000010011, +10000110000100111100001000011000, +11000010000110000000000110000111, +00000001110001111000011000010011, +10000111100100111100001000011000, +11000011100110000000001000000111, +00000000000001101010000000100011, +11110000111011110100010100110101, +00011111111000111110100000101111, +01000111100000111101100000000101, +11110111100100110000000000010100, +11000111100010010000001000000111, +00011010000100001001011110110111, +10000000000001111010000000100011, +01100101010001000010011110000011, +00011100000000000000011100110111, +10010111100000101100001100011100, +00111100010001011010000000000001, +01100111100001011010000000000001, +10111001011000111011101111110001, +01000101010010010001110000010111, +11100100110011111111000011101111, +11110000111011110100010101010001, +11100001001011011110010001101111, +00000000010001000100011100000011, +00011010000100000010011110110111, +01001000000001111000011110010011, +11000010001101110001011100110011, +00000100111001111010100000100011, +00000010101001000100011100000011, +11111100000101110011011100110011, +01000111000011011100001101011101, +00000010111001111010100000100011, +00000010000001111010010000100011, +00000010101001000100011100000011, +00000010000001110111011100010011, +00100111000000111100101101011001, +10100110001000110000001100010100, +01000110100000110000001011100111, +01000111100000110000001110010100, +00100111001101110000001000010100, +00000111000100110000101001100110, +10001111010101011000000000000111, +10001111110110010000011110111010, +00100111001101110000011010010110, +10001111110101010001101000010000, +01001000000001110000011100010011, +00000010111101110010001000100011, +11110000111011110100010101011001, +11100001001111011101110111101111, +00111101100001001010011110000011, +00000110000101111011000001100011, +00000010100001000100011110000011, +11001011101110011000101111000001, +01100100100001000000100100010011, +01010101010100000000010110010011, +00001010101000000000010100010011, +01100100000001000010010000100011, +00000101100100110011001001111101, +00000101000100110010101010100000, +00110010010101010000010101010000, +01010101010100000000010110010011, +00001001000000000000010100010011, +01000110000010010011101001101001, +01000101000000011000010111001010, +10000101101111111111000011101111, +00000101000100110100010110000001, +00110010011000010000111100000000, +01100100101001000101011100000011, +00000011110001000101011110000011, +00000000111101110000101001100011, +00111010010001010100010101010101, +01000111000101011011111101110101, +00000111001101111011111110110001, +10110111101101010000000100000000, +11110000111011110100010101010101, +11100001000101011101011100101111, +00000010100001000100011110000011, +11001111100100011000101110010001, +01010101010100000000010110010011, +00001111000000000000010100010011, +01000111100000110011101010001001, +11110111100100110000001010000100, +11000111100000010000010000000111, +00000011100001000100010100000011, +01000111100000110011101010101101, +11110111100100110000001010000100, +11000111100011010000001000000111, +01010101010100000000010110010011, +00001010101000000000010100010011, +00000101100100110011001000111101, +00000101000100110010101010100000, +00110010000101010000010101010000, +01010101010100000000010110010011, +00000011100000000000010100010011, +01100101001001010011101000101001, +00000101000100110100010110000001, +00111010000000011110000010110101, +11110000111011110100010101110101, +00010001111000111101000101101111, +01000111100000111101111000000101, +10110111001100110000001010010100, +11001111000000011111110000010111, +11000111100010011000101110001001, +00111101100001001010011110000011, +00000000000101111011011101100011, +00000010110001000100010100000011, +01010101010100000000010110010011, +01000111100000110011000011011101, +11110111000100110000001010010100, +11001111000000010000000001000111, +11000111100010011000101110100001, +00111101100001001010011110000011, +00000000000101111011011101100011, +00000010110101000100010100000011, +00101010101000000000010110010011, +01000111100000110011000011011001, +11110111000100110000001010010100, +11001111000010010000000100000111, +00000010000001111111011110010011, +10100111100000111100011110001001, +10110111011000110011110110000100, +01000101000000110000000000010111, +00000101100100110000001011100100, +00110000010101010101010101010000, +00000010100101000100011110000011, +00000100000001111111011100010011, +11010110000001110000101011100011, +00010000000001111110011110110011, +00000000000001111101100001100011, +00011100000110001010011110110111, +11010101010001111010011110000011, +11010110000101111011000011100011, +00000010111101000100010100000011, +01010101010100000000010110010011, +10111011100010010011100010101101, +00000000000010011000010100010011, +10110011100001010010100010110101, +11110000111011110100010100111001, +11100101000101011100011101101111, +00000000010010011010101000000011, +00000000000010011010110110000011, +00000000100010011010101010000011, +11100100000000000000011110110111, +00000000111110100000110100110011, +10100111000000110100110000000001, +01101011011000110000000011001001, +10100101100000110000000011101100, +10100101000000110000000010001001, +11110000111011110000000001001001, +00001011000001011100011011101111, +10110011100101010000100111000001, +00111101110001001010100100000011, +00000001001010101111011001100011, +00000000001110101000100100010011, +11000010000010010011100100110011, +01111100011000111000011001001010, +10000101110100100000000110011101, +11110000111011111000010101101110, +10011010010010101110111001001111, +10001010101100111001110111001010, +00001100000001010100000100101010, +10000101100100111011111101111101, +10000101011011100111011010001011, +11101100111011111111000011101111, +10000101100100111000011001001010, +10000101010100100111011010001011, +10110111110001010011001010000001, +00011010000100000110011110110111, +01000011100110000000011110100001, +11000110000001100001000101000001, +11000010001001101100010000100010, +11000001100001110011011100110011, +01000011100110001100001110011000, +11000001101001110011011100110011, +01000011100110001100001110011000, +11000001101101110011011100110011, +00100111001101111100001110011000, +01000011000111000001101000010000, +11000000111001111100011110110011, +01110111001101111100001100011100, +01000111110000010001101000010000, +00000000111101110010100000100011, +00100110001000110100011110011101, +10010111101101110000000011110111, +00000110101101110001101000010000, +11001011110101000000001000000000, +00000000000000100000011110110111, +00000100011101111000011110010011, +00000000111101110010000000100011, +00011010000100001001011110110111, +00000000110001111000100000010011, +00000010000000000000011100110111, +00000000010001111000010110010011, +00000000100001111000011000010011, +00110000000001000111011011110011, +00000000000010000010100010000011, +00000000011010001001001100010011, +00000000000000110100100101100011, +00000000011100111100000110011000, +11000010000110000001000001010000, +00110000000001101001000001110011, +00000111110100011011011111010101, +10010000011100111100001110011000, +00000111100000110011000000000110, +11011110011000110000001010110101, +01000111100000110000000000000111, +00100111001101110000000001000101, +00000111000100110001101000010000, +10010111101100110111100000000111, +11000111101100111100001000110111, +00101100001000111100000010000111, +00100100101101110000001011110111, +10000100000100110001101000010000, +01000111101111010111100000000100, +00000100111101000010001000100011, +00000010000001000010011000100011, +00001100000000000000011110010011, +00000010111101000010011000100011, +11110000111011110100010100001001, +00000111100100111111011000001111, +00100110001000110000111000000000, +10010111101101110000001011110100, +10000111100100110001110000011000, +00000111001101110111011010000111, +10100110001000110000000000000010, +00100111000000110001111011100111, +01000110100001010000001011000100, +11001110100001101010011100110011, +00000010111001000010011000100011, +00000011101000000000011100110111, +00000010111001000010000000100011, +01111001000001001000011100010011, +10000111100100111100001100011100, +00000111000100110111100101000100, +11000011100110000010000101000000, +01111001100001001000010010010011, +11000000100111000100011111000001, +10111110101011111111000011101111, +01000000101100100100010000100010, +01000101000010010100010010010010, +11110000011011110000000101000001, +00100111101101111111000010001111, +10000111000100110001101000010000, +00100110100000110111100000000111, +00001000000100110000001011000111, +00100110101100110000010000000000, +00100110001000111100111010001000, +00000110101101110000001011010111, +00100101010110110001110100000000, +00100010001000111000011011010101, +11000011000011000000001010100111, +01111000010001111000011100010011, +10000111100100111100001100010000, +01000111010000010111100010000111, +11110000011011111100001110011000, +01000111100000111011101001001111, +11110111100100110000001010110101, +11101011100100010000010000000111, +00011100000110001001011110110111, +01110110100001111000011110010011, +00001000010100100101000011111011, +00000000000001111000000010101011, +10000000100000100000000000000001, +00000010101101010100011110000011, +00000100000001111111011110010011, +11110111101101111100101110011101, +10100111100000110001101000010000, +10010110101101110010111000000111, +01000110001101110001110000011000, +10000111001111100000011010000100, +00000010111001010001111100100011, +00010000000001111101011110110011, +00100001010000000000011100010011, +00000100111001111101011110110011, +10000111100010010000011110001101, +01110110100001101000011010010011, +00000110000100110100011100000001, +10010011011000111100101110010110, +10000000100000100000000011100111, +00000000110001110000010110110011, +01000001100011000000010110001010, +10100010001010110000011100000101, +10110111111101010000000010110110, +01000101000000011000011110101010, +11111100000101011011011100110011, +10001101001111011100001100010001, +00010000000001111110011010110011, +00000000000101111001011100010011, +00001111111101110111011110010011, +00000000000001101101011001100011, +00000001101101110100011110010011, +00001111111101111111011110010011, +11111101111110011000000110000101, +00100111100000111000000010000010, +01000001100110000011000111100101, +11001110001000100001000100000001, +11000001100111001000111110111001, +00110010001001010010011100000011, +11001100001001100100000111011100, +10001111101110011100101001001010, +00100111000000111100000111011100, +01000101100111000011001001100101, +11000110010100101100100001001110, +11000101100111001000111110111001, +00110010101001010010011100000011, +11000100010101100100010111011100, +10001111101110011100001001011010, +11000101110111001100000001011110, +00110010111001010000001100010011, +01000000111110110100111000100101, +01000001100110000001010000011110, +01110111110101110000001101000001, +01110110110101111001000000000111, +10010111101010101001001000000111, +11000110000000111001011010101010, +11000111100000110010000000000111, +01110110110101110010000000000110, +01110111010101111001000000010111, +10010110101010101001001000010111, +11000110100000111001011100101010, +01000111000000110010000000000110, +10010110010101110010000000000111, +00010110010101111110000011000111, +01000001110110001101100011010111, +01110011110101111100000110010000, +01110111110101111001000000000110, +01110110110101111001000000000111, +10010111101010101001001000000111, +11001000000000111001011010101010, +11000111100000110010000000000111, +01110110110101110010000000000110, +01110111010101111001000000010111, +10010110101010101001001000010111, +11000110100000111001011100101010, +01000111000000110010000000000110, +10010111110101110010000000000111, +01110010110101111110000100000111, +00010111110101111001001000000110, +01000101100110001101100011010111, +01111111010101111100000111011100, +01110110110101111001000000010110, +10010110101010101001000000000111, +00100000000001101100100010000011, +10010010000001110111011011010111, +11001000000000111001011010101010, +01110110110101110010000000000110, +01110111010101111001000000010111, +10010110101010101001001000010111, +11000110100000111001011100101010, +01000111000000110010000000000110, +00011000010101110010000000000111, +01111110110101111110000100011000, +00011000010101111001001000010110, +01000101110110001101100011010111, +00000001000001011010010000100011, +11101000011110000111111111010111, +10010000000001110111011011010111, +11001001000000111001011010101010, +01110110110101110010000000000110, +10010110101010101001001000000111, +00100000000001101100100010000011, +10010000000101110111011011010111, +10010010000101110111011101010111, +10010111001010101001011010101010, +00100000000001101100011010000011, +00100000000001110100011100000011, +11100001001010001001100101010111, +00000001111101011010010000100011, +11011000110101110001100101010111, +11110010100110010111100111010111, +11000011110001111111011101010111, +10100110001000111100000111011000, +01110100100000110000000100110101, +01111000100000110000000001110101, +01110100000000110000000001010101, +01110110100000110000000111100101, +11111010010101110000000111010101, +10011000110101111001000000010111, +10011000110101111110000010011000, +11110100110101111101100010000110, +11110110110101111001001000010111, +00001010101100111001001000000111, +11001011100000110000000101000101, +00000100001100110001000000001010, +00001010101100110000000011010101, +11110111110101110000000010010101, +01000100000000111001000000000111, +11001011000000110001000000000100, +01111010000000110001000000001010, +01110110100000110000000101000101, +01110100100000110000000011010101, +00001010101100110000000010010101, +01110111100000110000000011110101, +11001010100000110000000011110101, +00010110110101110001000000001010, +10010110110101111110000011011010, +10010100010101111101100010010111, +01110111110101111110000010001011, +10010100010101111001001000011000, +01111010010101111101100101101010, +01110100110101111001000000001000, +00001010101100111001000000011000, +11001011100000110000000011110101, +11001000101100110001000000001010, +00001010101100110000000010001000, +01111000010101110000000101000101, +00000100001100111001001000001000, +11001011000000110000000010010101, +01000100000000110001000000001010, +00001010101100110001000000000100, +11001010100000110000000100000101, +10010100010101110001000000001010, +01110111100000111110000010001011, +01110100100000110000000011110101, +10010100010101110000000010010101, +01111000000000111101100101101010, +10001110101000010000000100000101, +00000001010001010111010000000011, +10010100110101111000111010110001, +11001000101100111110000010010111, +11000110101100110000000111111000, +00010100110101110000000100110110, +11001000101100111101100010001000, +01111010010101110000000100111000, +01111001110101111001000000001001, +01110100010101111001001000011001, +00001010101100111001001000001001, +01111001010101110000000010000101, +00000111101100111001000000011001, +00001000001100110000000100110101, +11000111100000110000000101000101, +11001011000000110001000000000111, +01001000000000110001000000001010, +00001010101100110001000000001000, +11001010100000110000000100100101, +00011000010101110001000000001010, +01000111101100111110000011111000, +10011000010101110000000011000111, +01110110000000111101100101101010, +10001111101001010000000100110101, +00000001010001010111010010000011, +00000000100001010111010000000011, +00000001000001111100011110110011, +00000001001001010111100000000011, +11100000110001001001011001010111, +10010010101010101001001110101010, +00010000000000101100001010000011, +11011000100010000001011001010111, +11001000000000111001111100101010, +10011110101010100001000000000011, +00010000000011110100111100000011, +00010000000011101100111010000011, +11100001000000101001100001010111, +00000001111101110100011100110011, +11011001111011101001100001010111, +01000111001100111000111100110001, +10100000001000110000000100000111, +11000001110101000000000100010101, +11000101110110001100010110011100, +11111111000000110010011000000011, +00000000110010001100100010110011, +00000001000101011010000000100011, +11111111010000110010111010000011, +11001110101100111000011001000110, +10100010001000110000000111010110, +00100110100000110000000111010101, +11001000101100111111111110000011, +10100100001000110000000011010111, +00100111100000110000000100010101, +10001111101110011111111111000011, +01110111010101111100010111011100, +10010111001010101001000000000110, +00100000000001110100100000000011, +10010010000001100111011101010111, +01000011000000111001011100101010, +01110111010101110010000000000111, +01110110010101111001000000010110, +10010111001010101001001000010110, +01000110100000111001011000101010, +01000111000000110010000000000111, +00010110010101110010000000000110, +01000100011100101110000100000011, +11011000110101110001011001010111, +10010000000011101111011101010111, +10010111001010101100000110010000, +00100000000001110100011000000011, +10010010000011101111011101010111, +01000110100000111001011100101010, +11110111010101110010000000000111, +10010111001010101001000000011110, +00100000000001110100100000000011, +10010010000111101111011101010111, +01000111000000111001011100101010, +10010110010101110010000000000111, +11110110110101111110000011000110, +00010110010101111001001000001000, +11000001110100001101100100000111, +11000011000000111001011010101010, +11110110110101110010000000000110, +11110111010101111001000000011000, +10010110101010101001000000001000, +00100000000001101100100000000011, +11110110110101111001011100101010, +01000111000000111001001000011000, +10010110101010100010000000000111, +00100000000001101100011010000011, +11100000111000110001011101010111, +11011001000001101001011101010111, +10010010000001111111100001010111, +11110110110101111100010110011000, +10011000001010101001000000000111, +00100000000010000100001100000011, +11111000010101111001011010101010, +11110111110101111001000000010111, +11000110100000111001001000010111, +10011000001010100010000000000110, +01001000100000111001011110101010, +11001000000000110010000000001000, +00010111110101110010000000000111, +01110111010101111110000011010011, +00010111110101111110100001110111, +01110110110101111101100100011000, +11110111110101111100001111000110, +11000001110101001111001010010111, +11000101110111001100010110011000, +00111011111001010010100000000011, +01000110001100110100000110010000, +11000001100100000000000100000110, +00111100001001010010011000000011, +11000001110101001000111010110001, +00111100011001010010011010000011, +11000101100110001000111100110101, +00111100101001010010011100000011, +11000101110111001000111110111001, +01001001010100100100010011100010, +01001010001100100100100111000010, +01001011000100100100101010100010, +01100001000001010100101110000010, +01110001010111011000000010000010, +11000010101001101100010010100010, +11011110010011101100000011001010, +11011100010100101100011010000110, +11011000010110101101101001010110, +10000100001010101101011001011110, +10001001001100101000010010101110, +00000110011000111000100110111110, +01000010100111000001001000001000, +00110000000101010000111000010011, +00101111001000110100001100101001, +01000010110111000011000011110101, +00110010111101010010000100100011, +00100011001000110100011010011100, +01000110110111000011001011110101, +00110010111101010010010100100011, +00110010111001010000011110010011, +00001000000100110100000011111011, +00000000011101101100111010000011, +00000000000001101100010110000011, +00000000101101101100111100000011, +00000001110101000000011000110011, +00100000000001100100011000000011, +00000000010001101100100010000011, +00000000100001101100100000000011, +10000000001000111000110110110001, +00000110001100110000000010110110, +01000110000000110000000111100100, +11001111100000110010000000000110, +00000111110000010000000000110110, +00000000110010001100100010110011, +00000000111101101100011000000011, +00000001000101101000001000100011, +00000001111101000000001010110011, +00000000110001000000010100110011, +00100000000001010100010100000011, +00000000101010000100100000110011, +00000001000001101000010000100011, +00100000000000101100001010000011, +00000000110001101100010100000011, +00000000010101010100010100110011, +00000000101001101000011000100011, +00000000000111100100001010001011, +00000000010101011100010110110011, +00000000000101101100001010000011, +00000000101101101000000000100011, +00000000010101011100010110110011, +00000000010101101100001010000011, +00000000101101101000000010100011, +00000000010110001100100010110011, +00000000100101101100001010000011, +00000001000101101000001010100011, +00000000010110000100100000110011, +00000000110101101100001010000011, +00000001000001101000010010100011, +00000000010101010100010100110011, +00000000001001101100001010000011, +00000000101001101000011010100011, +00000000010101011100010110110011, +00000000011001101100001010000011, +00000000101101101000000100100011, +00000000101111111100010110110011, +00000000010110001100100010110011, +00000000101001101100001010000011, +00000001000101101000001100100011, +00000001000111101100100010110011, +00000000010110000100100000110011, +00000001000001101000010100100011, +00000000111001101100001010000011, +00000000101101101000000110100011, +00000001000011110100100000110011, +00000000010101010100010100110011, +00000000101001101000011100100011, +01000010100100001000110100110001, +00000001000101101000001110100011, +00000001000001101000010110100011, +00000000101001101000011110100011, +11111110110001111010100000100011, +10101010001000110100001011010000, +01000110100100001111111011000111, +11111110110001111010110000100011, +10101110001000110100011011010000, +01001010010000011111111011000111, +00000011010010011100101000110011, +11001100000000100100001100011100, +11001000001111101000101011001010, +01001011000000010100001101011100, +00011011100100111100101000111110, +10000111110110100000000001001011, +01001001011000111001101110100110, +00001000000011000000011101001011, +00000100000010100110101000110011, +11001110010100101000010100100010, +01000110010000010011110001101101, +00000000000000000111011111010111, +11000010001111101100000000111110, +11000110001111101100010000111110, +10000101100010101000011010001010, +11000110000010011011011100110011, +00000010110010011110011000110011, +01000000110101011000011110110011, +00000110110001111100010101100011, +01000110010000100100011110000010, +10001111101100011001011101001010, +01000110000100101100000000111110, +10001111101100010100011111010010, +01000110011000101100001000111110, +10001111101100010100011110100010, +01000110011100101100010000111110, +10001111101100010100011110110010, +00000111101100111100011000111110, +11000110011000110100000100100111, +01000000101101100000010100110111, +01000100100101100100010000100110, +01011001111100100100100100000110, +01011010110100100101101001100010, +01011011101100100101101101000010, +10000000100000100110000101100001, +10000101001000100000100000001100, +00111100100000011100111000111110, +00001000000101000000101100000101, +00000001000010101000011000010011, +00000000010000111101000011111011, +00000000010010111010011100001011, +00000000010001101010010110001011, +10100010001010111000111100101101, +10001010101100100000000011101010, +10010111101001101011011110001101, +00000000111001111111011110000011, +00000000111101011000000010101011, +11000111100010111011011101100001, +00000000101010110000000000010110, +10110111011001010000000011110111, +11010010001001100111000101111001, +11001110010011101101000001001010, +11001010010101101100110001010010, +11000010011001101100010001100010, +11010100001000101101011000000110, +11000110010111101100100001011010, +00001001100100111000010010101010, +00001100000100110010000000000101, +00001001000100110001000000000101, +01001010000000010011000000000101, +00001100100100110100101011000001, +01110100000100110001000000000000, +10001011101100110000111111111010, +00001011001100110000000101000100, +01000101100010010000000101001100, +11110000111011111000010100100010, +10000000101010111001101100111111, +01000101100011010000000010101011, +11110000111011111000010100100010, +00000100000001011001101001111111, +00000000101010110000000010101011, +00001111111101000111010000010011, +11111110100010101001000111100011, +00001010010000010000101011000001, +00001111111110101111101010010011, +11111101100110100001010111100011, +01000111000001010100011010000101, +00010000000001110110011000110011, +10001111001100010000011100000110, +00010000000001110110011110110011, +01000111011011011000011001111101, +10001111001111011000111101110001, +00000000000101101001011110010011, +11100111101100111000111110110101, +11110110100100110001000000000111, +00000110100010100000111111110111, +11100111101100111000111110110101, +11110110100100110001000000000111, +00000110100100100000111111110111, +11100111101100111000111110110101, +11010110000100110001000000000111, +01000110101001010100000111110111, +10001111101101011000111011110001, +00001111111101111111011010010011, +00000000011101101101011000010011, +00000000000101101001011110010011, +11000110000100111000111111010001, +10001111101100010000011000110110, +00000000011001101101010110010011, +00000000001001101001011000010011, +10001111101100011000111001001101, +00000000010101101101010110010011, +00000000001101101001011000010011, +10001111101100011000111001001101, +00000000010001101101010110010011, +00000000010001101001011000010011, +01110111000100111000111001001101, +10001111101100010000111111110111, +00000000111110011100011100100011, +11111000000101110011000011100011, +00000110001100000000011110010011, +00100000111101001000000000100011, +01000100100000010100010100000001, +00000000101010110100100111111001, +00000100100001010000000010101001, +00000001001101001001111101100011, +01010100001000100101000010110010, +01011001000000100101010010010010, +01001010011000100100100111110010, +01001011010000100100101011010010, +01001100001000100100101110110010, +01100001010001010100110010010010, +11110100000100111000000010000010, +01000101000001010000111111110100, +11111100000101000010101111100011, +00010100011111010100010110001001, +10001100000111111111000011101111, +00001111111101000111010000010011, +00000000000000001011111111000101, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000, +00000000000000000000000000000000; diff --git a/fpga/ips/xilinx_rom_bank_2048x32/tcl/run.tcl b/fpga/ips/xilinx_rom_bank_2048x32/tcl/run.tcl new file mode 100644 index 00000000..97ac741a --- /dev/null +++ b/fpga/ips/xilinx_rom_bank_2048x32/tcl/run.tcl @@ -0,0 +1,13 @@ +set partNumber $::env(XILINX_PART) +set boardName $::env(XILINX_BOARD) + +create_project xilinx_rom_bank_2048x32 . -part $partNumber +set_property board_part $boardName [current_project] +create_ip -name blk_mem_gen -vendor xilinx.com -library ip -module_name xilinx_rom_bank_2048x32 +set_property -dict [list CONFIG.Memory_Type {Single_Port_RAM} CONFIG.Use_Byte_Write_Enable {true} CONFIG.Byte_Size {8} CONFIG.Write_Width_A {32} CONFIG.Write_Depth_A {2048} CONFIG.Register_PortA_Output_of_Memory_Primitives {false} CONFIG.Use_RSTA_Pin {true} ] [get_ips xilinx_rom_bank_2048x32] +exec cp boot_code.coe xilinx_rom_bank_2048x32.srcs/sources_1/ip/boot_code.coe +set_property -dict [list CONFIG.Load_Init_File {true} CONFIG.Coe_File {../boot_code.coe} CONFIG.Fill_Remaining_Memory_Locations {true}] [get_ips xilinx_rom_bank_2048x32] +generate_target all [get_files ./xilinx_rom_bank_2048x32.srcs/sources_1/ip/xilinx_rom_bank_2048x32/xilinx_rom_bank_2048x32.xci] +create_ip_run [get_files -of_objects [get_fileset sources_1] ./xilinx_rom_bank_2048x32.srcs/sources_1/ip/xilinx_rom_bank_2048x32/xilinx_rom_bank_2048x32.xci] +launch_run -jobs 8 xilinx_rom_bank_2048x32_synth_1 +wait_on_run xilinx_rom_bank_2048x32_synth_1 diff --git a/fpga/ips/xilinx_slow_clk_mngr/.gitignore b/fpga/ips/xilinx_slow_clk_mngr/.gitignore new file mode 100644 index 00000000..5099fe9c --- /dev/null +++ b/fpga/ips/xilinx_slow_clk_mngr/.gitignore @@ -0,0 +1,21 @@ +#Ignore vivado project files generated by the tcl script +**/.Xil/* +**/reports/* +**/*.cache/* +**/*.hw/* +**/*.ip_user_files/* +**/*.runs/* +**/*.sim/* +**/*.srcs/* +*.edf +*.xpr +*.jou +*.log + +.cxl.* + +*ip + +*_stub.v +gmon.out + diff --git a/fpga/ips/xilinx_slow_clk_mngr/Makefile b/fpga/ips/xilinx_slow_clk_mngr/Makefile new file mode 100644 index 00000000..80b82330 --- /dev/null +++ b/fpga/ips/xilinx_slow_clk_mngr/Makefile @@ -0,0 +1,30 @@ +PROJECT:=xilinx_slow_clk_mngr +VIVADO ?= vivado +VIVADOFLAGS ?= -nojournal -mode batch -source scripts/prologue.tcl + +.DEFAULT_GOAL:=help + +.PHONY: help + +all: ## Create and synthesize the IP in batch mode. + vivado-2018.2 vivado -mode batch -source tcl/run.tcl + mkdir -p ip + cp -r ${PROJECT}.srcs/sources_1/ip/${PROJECT}/* ip/. + cp ${PROJECT}.runs/${PROJECT}_synth_1/${PROJECT}.dcp ip/. + +gui: ## Create and synthesize the IP in GUI mode. + vivado-2018.2 vivado -mode gui -source tcl/run.tcl & + +clean: ## Remove all build products + rm -rf ip/* + mkdir -p ip + rm -rf ${PROJECT}.* + rm -rf component.xml + rm -rf vivado*.jou + rm -rf vivado*.log + rm -rf vivado*.str + rm -rf xgui + rm -rf .Xil + +help: ## Shows this help message + @grep -E -h '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' diff --git a/fpga/ips/xilinx_slow_clk_mngr/Makefile~ b/fpga/ips/xilinx_slow_clk_mngr/Makefile~ new file mode 100644 index 00000000..3709d058 --- /dev/null +++ b/fpga/ips/xilinx_slow_clk_mngr/Makefile~ @@ -0,0 +1,30 @@ +PROJECT:=xilinx_slow_clk_mngr +VIVADO ?= vivado +VIVADOFLAGS ?= -nojournal -mode batch -source scripts/prologue.tcl + +.DEFAULT_GOAL:=help + +.PHONY: help + +all: ## Create and synthesize the IP in batch mode. + $(VIVADO) -mode batch -source tcl/run.tcl + mkdir -p ip + cp -r ${PROJECT}.srcs/sources_1/ip/${PROJECT}/* ip/. + cp ${PROJECT}.runs/${PROJECT}_synth_1/${PROJECT}.dcp ip/. + +gui: ## Create and synthesize the IP in GUI mode. + $(VIVADO) -mode gui -source tcl/run.tcl & + +clean: ## Remove all build products + rm -rf ip/* + mkdir -p ip + rm -rf ${PROJECT}.* + rm -rf component.xml + rm -rf vivado*.jou + rm -rf vivado*.log + rm -rf vivado*.str + rm -rf xgui + rm -rf .Xil + +help: ## Shows this help message + @grep -E -h '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' diff --git a/fpga/ips/xilinx_slow_clk_mngr/tcl/run.tcl b/fpga/ips/xilinx_slow_clk_mngr/tcl/run.tcl new file mode 100644 index 00000000..891315bd --- /dev/null +++ b/fpga/ips/xilinx_slow_clk_mngr/tcl/run.tcl @@ -0,0 +1,45 @@ +set partNumber $::env(XILINX_PART) + +if [info exists ::env(BOARD)] { + set BOARD $::env(BOARD) +} else { + error "BOARD is not defined. Please source the sourceme.sh file." + exit +} +if [info exists ::env(XILINX_BOARD)] { + set boardName $::env(XILINX_BOARD) +} + +# detect target clock +if [info exists ::env(SLOW_CLK_PERIOD_NS)] { + set SLOW_CLK_PERIOD_NS $::env(SLOW_CLK_PERIOD_NS) +} else { + set SLOW_CLK_PERIOD_NS 30517 +} + +# Multiply frequency by 256 as there is a clock divider (by 256) after the +# slow_clk_mngr since the MMCMs do not support clocks slower then 4.69 MHz. +set SLOW_CLK_FREQ_MHZ [expr 1000 * 256 / $SLOW_CLK_PERIOD_NS] + +set ipName xilinx_slow_clk_mngr + +create_project $ipName . -part $partNumber +set_property board_part $boardName [current_project] + +create_ip -name clk_wiz -vendor xilinx.com -library ip -module_name $ipName + +set_property -dict [eval list CONFIG.PRIM_IN_FREQ {125.000} \ + CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {$SLOW_CLK_FREQ_MHZ} \ + CONFIG.USE_SAFE_CLOCK_STARTUP {true} \ + CONFIG.USE_LOCKED {false} \ + CONFIG.RESET_TYPE {ACTIVE_LOW} \ + CONFIG.CLKIN1_JITTER_PS {50.0} \ + CONFIG.FEEDBACK_SOURCE {FDBK_AUTO} \ + CONFIG.RESET_PORT {resetn} \ + ] [get_ips $ipName] + + +generate_target all [get_files ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] +create_ip_run [get_files -of_objects [get_fileset sources_1] ./$ipName.srcs/sources_1/ip/$ipName/$ipName.xci] +launch_run -jobs 8 ${ipName}_synth_1 +wait_on_run ${ipName}_synth_1 diff --git a/fpga/ips/xilinx_tcdm_bank_1024x32/Makefile b/fpga/ips/xilinx_tcdm_bank_1024x32/Makefile new file mode 100644 index 00000000..e9e93b49 --- /dev/null +++ b/fpga/ips/xilinx_tcdm_bank_1024x32/Makefile @@ -0,0 +1,21 @@ +PROJECT:=xilinx_tcdm_bank_1024x32 + +all: + vivado-2018.2 vivado -mode batch -source tcl/run.tcl + mkdir -p ip + cp -r ${PROJECT}.srcs/sources_1/ip/${PROJECT}/* ip/. + cp ${PROJECT}.runs/${PROJECT}_synth_1/${PROJECT}.dcp ip/. + +gui: + vivado-2018.2 vivado -mode gui -source tcl/run.tcl & + +clean: + rm -rf ip/* + mkdir -p ip + rm -rf ${PROJECT}.* + rm -rf component.xml + rm -rf vivado*.jou + rm -rf vivado*.log + rm -rf vivado*.str + rm -rf xgui + rm -rf .Xil diff --git a/fpga/ips/xilinx_tcdm_bank_1024x32/tcl/run.tcl b/fpga/ips/xilinx_tcdm_bank_1024x32/tcl/run.tcl new file mode 100644 index 00000000..f1195f60 --- /dev/null +++ b/fpga/ips/xilinx_tcdm_bank_1024x32/tcl/run.tcl @@ -0,0 +1,11 @@ +set partNumber $::env(XILINX_PART) +set boardName $::env(XILINX_BOARD) + +create_project xilinx_tcdm_bank_1024x32 . -part $partNumber +set_property board_part $boardName [current_project] +create_ip -name blk_mem_gen -vendor xilinx.com -library ip -module_name xilinx_tcdm_bank_1024x32 +set_property -dict [list CONFIG.Memory_Type {Single_Port_RAM} CONFIG.Use_Byte_Write_Enable {true} CONFIG.Byte_Size {8} CONFIG.Write_Width_A {32} CONFIG.Write_Depth_A {1024} CONFIG.Register_PortA_Output_of_Memory_Primitives {false} CONFIG.Use_RSTA_Pin {true}] [get_ips xilinx_tcdm_bank_1024x32] +generate_target all [get_files ./xilinx_tcdm_bank_1024x32.srcs/sources_1/ip/xilinx_tcdm_bank_1024x32/xilinx_tcdm_bank_1024x32.xci] +create_ip_run [get_files -of_objects [get_fileset sources_1] ./xilinx_tcdm_bank_1024x32.srcs/sources_1/ip/xilinx_tcdm_bank_1024x32/xilinx_tcdm_bank_1024x32.xci] +launch_run -jobs 8 xilinx_tcdm_bank_1024x32_synth_1 +wait_on_run xilinx_tcdm_bank_1024x32_synth_1 From 8c33fdd9a08a228d8b0b79bbb2a2e85b1a3b148c Mon Sep 17 00:00:00 2001 From: Angelo Garofalo Date: Wed, 11 Mar 2020 20:23:39 +0100 Subject: [PATCH 38/46] fix constraints --- fpga/ips/xilinx_clk_mngr/tcl/run.tcl | 2 +- fpga/pulpemu/tcl/constraints.xdc | 4 ++-- update-fpga | 27 --------------------------- 3 files changed, 3 insertions(+), 30 deletions(-) delete mode 100755 update-fpga diff --git a/fpga/ips/xilinx_clk_mngr/tcl/run.tcl b/fpga/ips/xilinx_clk_mngr/tcl/run.tcl index 4a344bfd..0b92652d 100644 --- a/fpga/ips/xilinx_clk_mngr/tcl/run.tcl +++ b/fpga/ips/xilinx_clk_mngr/tcl/run.tcl @@ -44,7 +44,7 @@ create_ip -name clk_wiz -vendor xilinx.com -library ip -module_name $ipName #CONFIG.CLKOUT3_REQUESTED_OUT_FREQ {$CL_CLK_FREQ_MHZ} \ set_property -dict [eval list CONFIG.PRIM_IN_FREQ {125.000} \ - CONFIG.NUM_OUT_CLKS {3} \ + CONFIG.NUM_OUT_CLKS {2} \ CONFIG.CLKOUT2_USED {true} \ CONFIG.RESET_TYPE {ACTIVE_LOW} \ CONFIG.RESET_PORT {resetn} \ diff --git a/fpga/pulpemu/tcl/constraints.xdc b/fpga/pulpemu/tcl/constraints.xdc index 0cc0518f..8a96160d 100644 --- a/fpga/pulpemu/tcl/constraints.xdc +++ b/fpga/pulpemu/tcl/constraints.xdc @@ -31,7 +31,7 @@ set_input_delay -clock tck -clock_fall 5.000 [get_ports pad_jtag_tdi] set_input_delay -clock tck -clock_fall 5.000 [get_ports pad_jtag_tms] set_output_delay -clock tck 5.000 [get_ports pad_jtag_tdo] -set_max_delay -to [get_ports pad_jtag_tdo] 20.000 +set_max_delay -to [get_ports pad_jtag_tdo] 20.000 set_max_delay -from [get_ports pad_jtag_tms] 20.000 set_max_delay -from [get_ports pad_jtag_tdi] 20.000 @@ -55,4 +55,4 @@ set_property ASYNC_REG true [get_cells i_pulpissimo/soc_domain_i/pulp_soc_i/soc_ # Create asynchronous clock group between slow-clk and SoC clock. Those clocks # are considered asynchronously and proper synchronization regs are in place -set_clock_groups -asynchronous -group [get_clocks -of_objects [get_pins i_pulpissimo/safe_domain_i/i_slow_clk_gen/slow_clk_o]] -group [get_clocks -of_objects [get_pins i_pulpissimo/soc_domain_i/pulp_soc_i/i_clk_rst_gen/i_fpga_clk_gen/soc_clk_o]] +set_clock_groups -asynchronous -group [get_clocks -of_objects [get_pins i_pulpissimo/safe_domain_i/i_slow_clk_gen/slow_clk_o]] -group [get_clocks -of_objects [get_pins i_pulpissimo/soc_domain_i/pulp_soc_i/i_clk_rst_gen/i_fpga_clk_gen/soc_clk_o]] -group [get_clocks -of_objects [get_pins i_pulpissimo/soc_domain_i/pulp_soc_i/i_clk_rst_gen/i_fpga_clk_gen/cluster_clk_o]] diff --git a/update-fpga b/update-fpga deleted file mode 100755 index e039139c..00000000 --- a/update-fpga +++ /dev/null @@ -1,27 +0,0 @@ -#!/bin/bash -e - -BLUE='\033[0;34m' -RED='\033[0;31m' -NC='\033[0m' # No Color -BOLD='\033[1m' -STD='\033[0m' - -if [ ! -e fpga ]; then - git clone git@iis-git.ee.ethz.ch:garofalo/jtag_fpga.git fpga - pushd fpga > /dev/null - echo -e "${BOLD}${BLUE}Cloning fpga${NC}${STD}" -else - pushd fpga > /dev/null - git checkout zcu102_align_pulpissimo - git pull - echo -e "${BOLD}${BLUE}Updating fpga${NC}${STD}" -fi - -ENV_COMMIT=pulp - -git checkout ${ENV_COMMIT} -echo -e "${BOLD}${BLUE}Moving to commit ${ENV_COMMIT}${NC}${STD}" - -popd > /dev/null - -./generate-scripts-fpga From 5810cdebb5ecc50ee2d8d0f411454a651f68fe51 Mon Sep 17 00:00:00 2001 From: Angelo Garofalo Date: Wed, 11 Mar 2020 20:29:12 +0100 Subject: [PATCH 39/46] add nex xilinx macro --- fpga/ips/xilinx_tcdm_bank_2048x32/Makefile | 21 +++++++++++++++++++ fpga/ips/xilinx_tcdm_bank_2048x32/tcl/run.tcl | 11 ++++++++++ 2 files changed, 32 insertions(+) create mode 100644 fpga/ips/xilinx_tcdm_bank_2048x32/Makefile create mode 100644 fpga/ips/xilinx_tcdm_bank_2048x32/tcl/run.tcl diff --git a/fpga/ips/xilinx_tcdm_bank_2048x32/Makefile b/fpga/ips/xilinx_tcdm_bank_2048x32/Makefile new file mode 100644 index 00000000..b0a08877 --- /dev/null +++ b/fpga/ips/xilinx_tcdm_bank_2048x32/Makefile @@ -0,0 +1,21 @@ +PROJECT:=xilinx_tcdm_bank_2048x32 + +all: + vivado-2018.2 vivado -mode batch -source tcl/run.tcl + mkdir -p ip + cp -r ${PROJECT}.srcs/sources_1/ip/${PROJECT}/* ip/. + cp ${PROJECT}.runs/${PROJECT}_synth_1/${PROJECT}.dcp ip/. + +gui: + vivado-2018.2 vivado -mode gui -source tcl/run.tcl & + +clean: + rm -rf ip/* + mkdir -p ip + rm -rf ${PROJECT}.* + rm -rf component.xml + rm -rf vivado*.jou + rm -rf vivado*.log + rm -rf vivado*.str + rm -rf xgui + rm -rf .Xil diff --git a/fpga/ips/xilinx_tcdm_bank_2048x32/tcl/run.tcl b/fpga/ips/xilinx_tcdm_bank_2048x32/tcl/run.tcl new file mode 100644 index 00000000..7f70ec0d --- /dev/null +++ b/fpga/ips/xilinx_tcdm_bank_2048x32/tcl/run.tcl @@ -0,0 +1,11 @@ +set partNumber $::env(XILINX_PART) +set boardName $::env(XILINX_BOARD) + +create_project xilinx_tcdm_bank_2048x32 . -part $partNumber +set_property board_part $boardName [current_project] +create_ip -name blk_mem_gen -vendor xilinx.com -library ip -module_name xilinx_tcdm_bank_2048x32 +set_property -dict [list CONFIG.Memory_Type {Single_Port_RAM} CONFIG.Use_Byte_Write_Enable {true} CONFIG.Byte_Size {8} CONFIG.Write_Width_A {32} CONFIG.Write_Depth_A {2048} CONFIG.Register_PortA_Output_of_Memory_Primitives {false} CONFIG.Use_RSTA_Pin {true}] [get_ips xilinx_tcdm_bank_2048x32] +generate_target all [get_files ./xilinx_tcdm_bank_2048x32.srcs/sources_1/ip/xilinx_tcdm_bank_2048x32/xilinx_tcdm_bank_2048x32.xci] +create_ip_run [get_files -of_objects [get_fileset sources_1] ./xilinx_tcdm_bank_2048x32.srcs/sources_1/ip/xilinx_tcdm_bank_2048x32/xilinx_tcdm_bank_2048x32.xci] +launch_run -jobs 8 xilinx_tcdm_bank_2048x32_synth_1 +wait_on_run xilinx_tcdm_bank_2048x32_synth_1 From ec83eb84e59d05f4cddc3f16cf054b031ad4fd02 Mon Sep 17 00:00:00 2001 From: Angelo Garofalo Date: Thu, 12 Mar 2020 11:30:21 +0100 Subject: [PATCH 40/46] add README for FPGA configuration --- fpga/README.md | 221 ++++++++++++++++++- fpga/openocd-zcu102-olimex-arm-usb-ocd-h.cfg | 37 ++++ 2 files changed, 248 insertions(+), 10 deletions(-) create mode 100644 fpga/openocd-zcu102-olimex-arm-usb-ocd-h.cfg diff --git a/fpga/README.md b/fpga/README.md index 1f136aa9..1f4ceb97 100644 --- a/fpga/README.md +++ b/fpga/README.md @@ -1,17 +1,218 @@ -1. Load environment variable according the fpga board, now support only zc706 and zcu102 +# FPGA + +PULP has been implemented on FPGA for various Xilinx FPGA boards + + +### CurrentlySupported Boards + +* Xilinx ZCU102 +* Xilinx VCU118 + +### Bitstream Generation +In order to generate the PULP bitstream for a supported target FPGA board +first generate the necessary synthesis include scripts by starting the +`update-ips` script in the pulpissimo root directory: + +```Shell +./update-ips +``` +This will parse the ips_list.yml using the PULP IPApproX IP management tool to +generate tcl scripts for all the IPs used in the PULP project. These files +are later on sourced by Vivado to generate the bitstream for PULP. + +Now switch to the fpga subdirectory and source the right board: + +```Shell +cd fpga source sourceme.sh +``` +Choose the platfom. + +### Bitstream Flashing +Start Vivado then: + +``` +Open Hardware Manager +Open Target +Program device +``` +Be sure you are loading ".bit" file to the fpga board. + +### Compiling Applications for the FPGA Target +To run or debug applications for the FPGA you need to use a recent version of +the PULP-SDK (tag 2019.11.05 is fully stable for FPGA). Configure the SDK for the FPGA +platform by running the following commands within the SDK's root directory: + +```Shell +source configs/pulp.sh +source configs/fpgas/pulp/genesys2.sh +``` + +In order for the SDK to be able to configure clock dividers (e.g. the ones for +the UART module) to the right values it needs to know which frequencies +PULP is running at. You can find the default frequencies in the above +mentioned board specific README files. + +In our application we need to override two weakly defined variables in our +source code to configure the SDK to use these frequencies: +```C +#include +#include + +int __rt_fpga_fc_frequency = // e.g. 20000000 for 20MHz; +int __rt_fpga_periph_frequency = // e.g. 10000000 for 10MHz; + +int main() +{ +... +} +``` + +By default, the baudrate of the UART is set to `115200`. + +Add the following global variable declaration to your application in case +you want to change it: + +```C +unsigned int __rt_iodev_uart_baudrate = your baudrate; +``` + +Compile your application with + +```Shell +make clean all io=uart +``` +This command builds the ELF binary with UART as the default io peripheral. +The binary will be stored at `build/pulp/[app_name]/[app_name]`. + +### GDB and OpenOCD +In order to execute our application on the FPGA we need to load the binary into +PULPissimo's L2 memory. To do so we can use OpenOCD in conjunction with GDB to +communicate with the internal RISC-V debug module. + +PULP uses JTAG as a communication channel between OpenOCD and the Core. +Have a look at the board specific README file on how to connect your PC with +PULP's JTAG port. + +Due to a long outstanding issue in the RISC-V OpenOCD project (issue #359) the +riscv/riscv-openocd does not work with PULPissimo. However there is a small +workaround that we incorporated in a patched version of openocd. If you have +access to the artifactory server, the patched openocd binary is installed by +default with the `make deps` command in the SDK. If you don't have access to the +precompiled binaries you can automatically download and compile the patched +OPENOCD from source. You will need to install the following dependencies on your +machine before you can compile OpenOCD: + +- `autoconf` >= 2.64 +- `automake` >= 1.14 +- `texinfo` +- `make` +- `libtool` +- `pkg-config` >= 0.23 (or compatible) +- `libusb-1.0` +- `libftdi` +- `libusb-0.1` or `libusb-compat-0.1` for some older drivers + +After installing those dependecies with you OS' package manager you can +download, apply the patch and compile OpenOCD with: + +```Shell +source sourceme.sh && ./pulp-tools/bin/plpbuild checkout build --p openocd --stdout +``` + +The SDK will automatically set the environment variable `OPENOCD` to the +installation path of this patched version. + +Launch openocd with one of the provided or your own configuration file for the +target board as an argument. + +E.g.: + +```Shell +$OPENOCD/bin/openocd -f pulp/fpga/openocd-zcu102-olimex-arm-usb-ocd-h.cfg +``` +In a seperate terminal launch gdb from your `pulp_riscv_gcc` installation passing +the ELF file as an argument with: + +`$PULP_RISCV_GCC_TOOLCHAIN_CI/bin/riscv32-unknown-elf-gdb PATH_TO_YOUR_ELF_FILE` + +In gdb, run: + +``` +(gdb) target remote localhost:3333 +``` + +to connect to the OpenOCD server. + +In a third terminal launch a serial port client (e.g. `screen` or `minicom`) on +Linux to riderect the UART output from PULPissimo with e.g.: + +```Shell +screen /dev/ttyUSB0 115200 +``` + +the ttyUSB0 target may change. + +Now you are ready to debug! + +In gdb, load the program into L2: + +``` +(gdb) load +``` +and run the programm: + +``` +(gdb) continue +``` +Of course you can also benefit from the debug capabilities that GDB provides. + +E.g. see the disasembled binary: +``` +(gdb) disas +``` +List the current C function, set a break point at line 25, continue and have fun! + +``` +(gdb) list +21 +22 int main() +23 { +24 while (1) { +25 printf("Hello World!\n\r"); +26 for (volatile int i=0; i<1000000; i++); +27 } +28 return 0; +29 } + +(gdb) b 25 +Breakpoint 1 at 0x1c0083d2: file test.c, line 25. +(gdb) c +Continuing. + +Breakpoint 1, main () at test.c:25 +25 printf("Hello World!\n\r"); -2. To make all fpga necessary IPs, for both FPGA RTL simulation and FPGA emulation -make ips -3. For FPGA RTL simulation, go to ./sim +(gdb) disas +Dump of assembler code for function main: + 0x1c0083d4 <+22>: li a1,1 + 0x1c0083d6 <+24>: blt s0,a5,0x1c0083e8 +=> 0x1c0083da <+28>: lw a5,12(sp) + 0x1c0083dc <+30>: slli a1,a1,0x1 + 0x1c0083de <+32>: addi a5,a5,1 + 0x1c0083e0 <+34>: sw a5,12(sp) -4. For FPGA emulation +(gdb) monitor reg a5 +a5 (/32): 0x000075B7 - - build cluster netlist - make synth-ulpcluster +``` +Not all gdb commands work as expected on the riscv-dbg target. +To get a list of available gdb commands execute: +``` +monitor help +``` - - build all SoC - make synth-pulpemu +Most notably the command `info registers` does not work. Use `monitor reg` +instead which has the same effect. - - If it is successful, you can find BOOT.bin in ./pulpemu/board \ No newline at end of file diff --git a/fpga/openocd-zcu102-olimex-arm-usb-ocd-h.cfg b/fpga/openocd-zcu102-olimex-arm-usb-ocd-h.cfg new file mode 100644 index 00000000..ba6bda27 --- /dev/null +++ b/fpga/openocd-zcu102-olimex-arm-usb-ocd-h.cfg @@ -0,0 +1,37 @@ +adapter_khz 1000 + +# Olimex ARM-USB-OCD-H +interface ftdi +ftdi_device_desc "Olimex OpenOCD JTAG ARM-USB-OCD-H" +ftdi_vid_pid 0x15ba 0x002b + +ftdi_layout_init 0x0908 0x0b1b +ftdi_layout_signal nSRST -oe 0x0200 +ftdi_layout_signal nTRST -data 0x0100 +ftdi_layout_signal LED -data 0x0800 + + +set _CHIPNAME riscv + +jtag newtap $_CHIPNAME unknown0 -irlen 5 -expected-id 0x10102001 +jtag newtap $_CHIPNAME cpu -irlen 5 -expected-id 0x249511C3 + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME riscv -chain-position $_TARGETNAME -coreid 0x3e0 + +gdb_report_data_abort enable +gdb_report_register_access_error enable + +riscv set_reset_timeout_sec 120 +riscv set_command_timeout_sec 120 + +# prefer to use sba for system bus access +riscv set_prefer_sba on + +# dump jtag chain +scan_chain + + +init +halt +echo "Ready for Remote Connections" From 03d001a236b4d3402ff57b29e49611e7c3290401 Mon Sep 17 00:00:00 2001 From: Angelo Garofalo Date: Thu, 9 Apr 2020 10:22:25 +0200 Subject: [PATCH 41/46] fix for new reset --- fpga/pulpemu/tcl/fmc_board_vcu118.xdc | 1 + rtl/pulp/cluster_domain.sv | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/fpga/pulpemu/tcl/fmc_board_vcu118.xdc b/fpga/pulpemu/tcl/fmc_board_vcu118.xdc index efd23a4d..895d79d7 100644 --- a/fpga/pulpemu/tcl/fmc_board_vcu118.xdc +++ b/fpga/pulpemu/tcl/fmc_board_vcu118.xdc @@ -31,6 +31,7 @@ set_property -dict {PACKAGE_PIN AY14 IOSTANDARD LVCMOS18} [get_ports pad_jtag_tm set_property -dict {PACKAGE_PIN AY15 IOSTANDARD LVCMOS18} [get_ports pad_jtag_tdi] set_property -dict {PACKAGE_PIN AW15 IOSTANDARD LVCMOS18} [get_ports pad_jtag_tdo] set_property -dict {PACKAGE_PIN AV15 IOSTANDARD LVCMOS18} [get_ports pad_jtag_tck] +set_property -dict {PACKAGE_PIN AV16 IOSTANDARD LVCMOS18} [get_ports pad_jtag_trst] #set_property -dict {PACKAGE_PIN AV16 IOSTANDARD LVCMOS18} [get_ports pad_pmod0_4] diff --git a/rtl/pulp/cluster_domain.sv b/rtl/pulp/cluster_domain.sv index f8e6d96c..e80dfca7 100644 --- a/rtl/pulp/cluster_domain.sv +++ b/rtl/pulp/cluster_domain.sv @@ -30,7 +30,7 @@ module cluster_domain parameter NB_HWPE_PORTS = 4, parameter NB_DMAS = 4, - parameter TCDM_SIZE = 64*1024, // in Byte, POWER of 2 + parameter TCDM_SIZE = 128*1024, // in Byte, POWER of 2 parameter NB_TCDM_BANKS = 16, // POWER of 2 parameter TCDM_BANK_SIZE = TCDM_SIZE/NB_TCDM_BANKS, // eg 4096 parameter TCDM_NUM_ROWS = TCDM_BANK_SIZE/4, // --> 4 byte, mem are 32 bit wide From 1e2900406720fc2e6276e35e92b73a45d4105d2a Mon Sep 17 00:00:00 2001 From: Angelo Garofalo Date: Thu, 9 Apr 2020 10:26:48 +0200 Subject: [PATCH 42/46] fix reset of pulp fpga --- rtl/pulpemu/pulpemu.sv | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/rtl/pulpemu/pulpemu.sv b/rtl/pulpemu/pulpemu.sv index d58f4b31..5a9f4cbc 100644 --- a/rtl/pulpemu/pulpemu.sv +++ b/rtl/pulpemu/pulpemu.sv @@ -78,6 +78,10 @@ module pulpemu wire ref_clk; + logic reset_n; + + assign reset_n = ~pad_reset & pad_jtag_trst; + //Differential to single ended clock conversion IBUFGDS @@ -137,7 +141,7 @@ module pulpemu .pad_i2s0_sdi(FMC_i2s0_sdi), .pad_i2s1_sdi(FMC_i2s1_sdi), - .pad_reset_n(~pad_reset), + .pad_reset_n(reset_n), .pad_jtag_tck(pad_jtag_tck), //keep .pad_jtag_tdi(pad_jtag_tdi), //keep From a93c472eb390be38cbec3d0513ce108e2cda64ad Mon Sep 17 00:00:00 2001 From: Jie Chen Date: Mon, 27 Jul 2020 18:06:55 +0800 Subject: [PATCH 43/46] Update for pulp master fpga --- .gitignore | 6 +++++- fpga/Makefile | 2 ++ fpga/pulp_cluster/tcl/run.tcl | 3 +++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 960db112..f20dda8c 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,8 @@ install ips ipstools pulp-builder -pulp-rt-examples \ No newline at end of file +pulp-rt-examples +*mk +*pyc +*.f +*.json \ No newline at end of file diff --git a/fpga/Makefile b/fpga/Makefile index b32e9dd5..0b5f85cf 100644 --- a/fpga/Makefile +++ b/fpga/Makefile @@ -16,6 +16,7 @@ mem: cd ips/xilinx_private_ram; make clean all cd ips/xilinx_rom_bank_2048x32; make clean all cd ips/xilinx_tcdm_bank_1024x32; make clean all + cd ips/xilinx_tcdm_bank_2048x32; make clean all clk: ## Synthesizes the Xilinx Clocking Manager IPs cd ips/xilinx_clk_mngr; make clean all @@ -42,4 +43,5 @@ clean-ips: cd ips/xilinx_private_ram; make clean cd ips/xilinx_rom_bank_2048x32; make clean cd ips/xilinx_tcdm_bank_1024x32; make clean + cd ips/xilinx_tcdm_bank_2048x32; make clean cd ips/xilinx_clk_mngr; make clean diff --git a/fpga/pulp_cluster/tcl/run.tcl b/fpga/pulp_cluster/tcl/run.tcl index 26264fd1..25f11113 100644 --- a/fpga/pulp_cluster/tcl/run.tcl +++ b/fpga/pulp_cluster/tcl/run.tcl @@ -18,8 +18,11 @@ source tcl/rtl_src_files.tcl source tcl/ips_add_files.tcl source tcl/rtl_add_files.tcl +add_files -norecurse -scan_for_includes $IPS/pulp_soc/rtl/components/pulp_interfaces.sv + # add memory cuts + FPU IPs read_ip $FPGA_IPS/xilinx_tcdm_bank_1024x32/ip/xilinx_tcdm_bank_1024x32.xci +read_ip $FPGA_IPS/xilinx_tcdm_bank_2048x32/ip/xilinx_tcdm_bank_2048x32.xci # set pulp_cluster as top set_property top pulp_cluster [current_fileset] From 80de6460129121f155d518d56f23807e1d4b2a2f Mon Sep 17 00:00:00 2001 From: Angelo Garofalo Date: Thu, 22 Oct 2020 11:35:59 +0200 Subject: [PATCH 44/46] fpga scripts: replace specific version of vivado with generic one --- fpga/ips/xilinx_clk_mngr/Makefile | 2 +- fpga/ips/xilinx_interleaved_ram/Makefile | 2 +- fpga/ips/xilinx_private_ram/Makefile | 2 +- fpga/ips/xilinx_rom_bank_2048x32/Makefile | 2 +- fpga/ips/xilinx_slow_clk_mngr/Makefile | 2 +- fpga/ips/xilinx_tcdm_bank_1024x32/Makefile | 2 +- fpga/ips/xilinx_tcdm_bank_2048x32/Makefile | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/fpga/ips/xilinx_clk_mngr/Makefile b/fpga/ips/xilinx_clk_mngr/Makefile index 3326b6c2..21698d87 100644 --- a/fpga/ips/xilinx_clk_mngr/Makefile +++ b/fpga/ips/xilinx_clk_mngr/Makefile @@ -1,7 +1,7 @@ PROJECT:=xilinx_clk_mngr all: - vivado-2018.2 vivado -mode batch -source tcl/run.tcl + vivado -mode batch -source tcl/run.tcl mkdir -p ip cp -r ${PROJECT}.srcs/sources_1/ip/${PROJECT}/* ip/. cp ${PROJECT}.runs/${PROJECT}_synth_1/${PROJECT}.dcp ip/. diff --git a/fpga/ips/xilinx_interleaved_ram/Makefile b/fpga/ips/xilinx_interleaved_ram/Makefile index e06a8882..85876b93 100644 --- a/fpga/ips/xilinx_interleaved_ram/Makefile +++ b/fpga/ips/xilinx_interleaved_ram/Makefile @@ -1,7 +1,7 @@ PROJECT:=xilinx_interleaved_ram all: - vivado-2018.2 vivado -mode batch -source tcl/run.tcl + vivado -mode batch -source tcl/run.tcl mkdir -p ip cp -r ${PROJECT}.srcs/sources_1/ip/${PROJECT}/* ip/. cp ${PROJECT}.runs/${PROJECT}_synth_1/${PROJECT}.dcp ip/. diff --git a/fpga/ips/xilinx_private_ram/Makefile b/fpga/ips/xilinx_private_ram/Makefile index bc81711f..7e81754f 100644 --- a/fpga/ips/xilinx_private_ram/Makefile +++ b/fpga/ips/xilinx_private_ram/Makefile @@ -1,7 +1,7 @@ PROJECT:=xilinx_private_ram all: - vivado-2018.2 vivado -mode batch -source tcl/run.tcl + vivado -mode batch -source tcl/run.tcl mkdir -p ip cp -r ${PROJECT}.srcs/sources_1/ip/${PROJECT}/* ip/. cp ${PROJECT}.runs/${PROJECT}_synth_1/${PROJECT}.dcp ip/. diff --git a/fpga/ips/xilinx_rom_bank_2048x32/Makefile b/fpga/ips/xilinx_rom_bank_2048x32/Makefile index 5f14594e..dd59873c 100644 --- a/fpga/ips/xilinx_rom_bank_2048x32/Makefile +++ b/fpga/ips/xilinx_rom_bank_2048x32/Makefile @@ -1,7 +1,7 @@ PROJECT:=xilinx_rom_bank_2048x32 all: - vivado-2018.2 vivado -mode batch -source tcl/run.tcl + vivado -mode batch -source tcl/run.tcl mkdir -p ip cp -r ${PROJECT}.srcs/sources_1/ip/${PROJECT}/* ip/. cp ${PROJECT}.runs/${PROJECT}_synth_1/${PROJECT}.dcp ip/. diff --git a/fpga/ips/xilinx_slow_clk_mngr/Makefile b/fpga/ips/xilinx_slow_clk_mngr/Makefile index 80b82330..d1c8d65c 100644 --- a/fpga/ips/xilinx_slow_clk_mngr/Makefile +++ b/fpga/ips/xilinx_slow_clk_mngr/Makefile @@ -7,7 +7,7 @@ VIVADOFLAGS ?= -nojournal -mode batch -source scripts/prologue.tcl .PHONY: help all: ## Create and synthesize the IP in batch mode. - vivado-2018.2 vivado -mode batch -source tcl/run.tcl + vivado -mode batch -source tcl/run.tcl mkdir -p ip cp -r ${PROJECT}.srcs/sources_1/ip/${PROJECT}/* ip/. cp ${PROJECT}.runs/${PROJECT}_synth_1/${PROJECT}.dcp ip/. diff --git a/fpga/ips/xilinx_tcdm_bank_1024x32/Makefile b/fpga/ips/xilinx_tcdm_bank_1024x32/Makefile index e9e93b49..af2eaed6 100644 --- a/fpga/ips/xilinx_tcdm_bank_1024x32/Makefile +++ b/fpga/ips/xilinx_tcdm_bank_1024x32/Makefile @@ -1,7 +1,7 @@ PROJECT:=xilinx_tcdm_bank_1024x32 all: - vivado-2018.2 vivado -mode batch -source tcl/run.tcl + vivado -mode batch -source tcl/run.tcl mkdir -p ip cp -r ${PROJECT}.srcs/sources_1/ip/${PROJECT}/* ip/. cp ${PROJECT}.runs/${PROJECT}_synth_1/${PROJECT}.dcp ip/. diff --git a/fpga/ips/xilinx_tcdm_bank_2048x32/Makefile b/fpga/ips/xilinx_tcdm_bank_2048x32/Makefile index b0a08877..f2eca5f6 100644 --- a/fpga/ips/xilinx_tcdm_bank_2048x32/Makefile +++ b/fpga/ips/xilinx_tcdm_bank_2048x32/Makefile @@ -1,7 +1,7 @@ PROJECT:=xilinx_tcdm_bank_2048x32 all: - vivado-2018.2 vivado -mode batch -source tcl/run.tcl + vivado -mode batch -source tcl/run.tcl mkdir -p ip cp -r ${PROJECT}.srcs/sources_1/ip/${PROJECT}/* ip/. cp ${PROJECT}.runs/${PROJECT}_synth_1/${PROJECT}.dcp ip/. From 5ed81fc3b33eb7b91d40a94aa20ffd93c7ede4a1 Mon Sep 17 00:00:00 2001 From: Angelo Garofalo Date: Thu, 22 Oct 2020 11:37:53 +0200 Subject: [PATCH 45/46] fpga scripts: clean-up files and update readme --- fpga/Makefile | 7 ++++--- fpga/README.md | 41 ++++++++++++++++++++++++++++++++++++++++- fpga/fpga-settings.mk | 3 --- fpga/sourceme.sh | 17 ++++++----------- 4 files changed, 50 insertions(+), 18 deletions(-) diff --git a/fpga/Makefile b/fpga/Makefile index 0b5f85cf..924cb4bb 100644 --- a/fpga/Makefile +++ b/fpga/Makefile @@ -1,4 +1,3 @@ - include fpga-settings.mk all: synth impl @@ -11,6 +10,8 @@ impl: ips: mem clk +generate_bitstream: ips synth-pulpcluster synth-pulpemu + mem: cd ips/xilinx_interleaved_ram; make clean all cd ips/xilinx_private_ram; make clean all @@ -22,9 +23,9 @@ clk: ## Synthesizes the Xilinx Clocking Manager IPs cd ips/xilinx_clk_mngr; make clean all cd ips/xilinx_slow_clk_mngr; make clean all -synth: synth-ulpcluster synth-pulpemu +synth: synth-pulpcluster synth-pulpemu -synth-ulpcluster: +synth-pulpcluster: cd pulp_cluster; make clean all synth-pulpemu: diff --git a/fpga/README.md b/fpga/README.md index 1f4ceb97..8e0e0d8b 100644 --- a/fpga/README.md +++ b/fpga/README.md @@ -11,10 +11,11 @@ PULP has been implemented on FPGA for various Xilinx FPGA boards ### Bitstream Generation In order to generate the PULP bitstream for a supported target FPGA board first generate the necessary synthesis include scripts by starting the -`update-ips` script in the pulpissimo root directory: +`update-ips` script in the PULP-open root directory: ```Shell ./update-ips +./generate-scripts-fpga ``` This will parse the ips_list.yml using the PULP IPApproX IP management tool to generate tcl scripts for all the IPs used in the PULP project. These files @@ -28,6 +29,44 @@ source sourceme.sh ``` Choose the platfom. + +### VIVADO IPs + +Before synthesizing the Design you should implement the Vivado-related ips. +To do this run the following Makefile command: + +```Shell +make ips +``` + +This will implement all the mem bram macros and the IPs needed by the design + + +### PULP CLUSTER SYNTHESIS + +First we need to synthesize the cluster +To do this run the following Makefile command: + +```Shell +make synth-pulpcluster +``` + + +### TOP LEVEL (PULP) SYNTHESIS AND IMPLEMENTATION + +If you already synthesized the cluster you can run the following command: + +```Shell +make synth-pulpemu +``` + +Otherwise you can run the following, which synthesizes the cluster, the top and then generates the bitstream + +```Shell +make synth +``` + + ### Bitstream Flashing Start Vivado then: diff --git a/fpga/fpga-settings.mk b/fpga/fpga-settings.mk index ccaf0eb6..2e13a04b 100644 --- a/fpga/fpga-settings.mk +++ b/fpga/fpga-settings.mk @@ -1,6 +1,3 @@ -#export BOARD=zcu102 -#export XILINX_PART=xczu9eg-ffvb1156-2-e -#export XILINX_BOARD=xilinx.com:zcu102:part0:3.2 export FC_CLK_PERIOD_NS=50 export CL_CLK_PERIOD_NS=50 export PER_CLK_PERIOD_NS=100 diff --git a/fpga/sourceme.sh b/fpga/sourceme.sh index 61821cd6..1f7fd130 100644 --- a/fpga/sourceme.sh +++ b/fpga/sourceme.sh @@ -3,26 +3,21 @@ export VIVADO_HOME=/opt/xilinx/Vivado/2018.2 source $VIVADO_HOME/settings64.sh -# either "zedboard" or "zc706" or "vcu118" or "zcu102" +#VIVADO SETTINGS +#Settings are board specific. Check FPGA board datasheet to add new target +# either "vcu118" or "zcu102" + if [ -z "$BOARD" ]; then - read -p "Which board you want to use: 1-zedboard 2-zcu102 3-vcu118 4-zc706 [4]: " BOARD + read -p "Which board you want to use: 1-zcu102 2-vcu118: " BOARD if [ "$BOARD" = "1" ]; then - export BOARD="zedboard" - export XILINX_PART="xc7z020clg484-1" - export XILINX_BOARD="em.avnet.com:zynq:zed:c" - elif [ "$BOARD" = "2" ]; then export BOARD="zcu102" export XILINX_PART="xczu9eg-ffvb1156-2-e" export XILINX_BOARD="xilinx.com:zcu102:part0:3.2" - elif [ "$BOARD" = "3" ]; then + elif [ "$BOARD" = "2" ]; then export BOARD="vcu118" export XILINX_PART="xcvu9p-flga2104-2L-e" export XILINX_BOARD="xilinx.com:vcu118:part0:2.0" - else - export BOARD="zc706" - export XILINX_PART="xc7z045ffg900-2" - export XILINX_BOARD="xilinx.com:zc706:part0:1.3" fi fi From 0ec6b940a7c69d7de6c4a3c07f65693cbde523b9 Mon Sep 17 00:00:00 2001 From: Angelo Garofalo Date: Thu, 22 Oct 2020 12:11:28 +0200 Subject: [PATCH 46/46] bump pulp cluster to newest tag --- ips_list.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ips_list.yml b/ips_list.yml index 0a80fb77..fd7cf805 100644 --- a/ips_list.yml +++ b/ips_list.yml @@ -25,7 +25,7 @@ pulp_soc: group: pulp-platform pulp_cluster: - commit: pulp_cluster_v1.2 + commit: pulp_cluster_v1.3 server: https://github.com group: pulp-platform