├── .gitignore ├── .gitmodules ├── LICENSE.md ├── Makefile ├── README.md ├── config ├── config_busybox ├── config_linux ├── openocd_bscan.cfg └── openocd_pmod.cfg ├── constraints ├── DDR_Pin_Map.ucf ├── nexys4ddr.xdc └── nexysvideo.xdc ├── firmware ├── Makefile ├── driver │ ├── bits.h │ ├── diskio.c │ ├── diskio.h │ ├── elf.c │ ├── elf.h │ ├── ff.c │ ├── ff.h │ ├── ffconf.h │ ├── mem_map.h │ ├── memory.c │ ├── memory.h │ ├── myprintf.c │ ├── myprintf.h │ ├── spi.c │ ├── spi.h │ ├── uart.c │ └── uart.h ├── head.S ├── linker.ld └── sdload.c ├── linux_driver ├── README.md └── spi-xilinx.c ├── pics ├── bigmap.png ├── firmware.png ├── jtag_pmod.png ├── kernelconfig.png ├── minicom.png ├── pmod_pins.png └── sdcard.png ├── scripts ├── create_nexys4ddr_vivado_proj.tcl ├── create_nexysvideo_vivado_proj.tcl ├── nexys4ddr.mig.prj └── nexysvideo.mig.prj └── verilog ├── AXIMem.v ├── AXIMmio.v ├── chip_top.v ├── peri ├── DTModule.v ├── JtagTunnel.v ├── bram.v ├── bram_storage.v ├── spi.v └── uart.v ├── testbench └── dut_top_tb.v └── utils ├── AsyncResetReg.v ├── EICG_wrapper.v ├── narrower.v ├── nasti_lite_bridge ├── nasti_lite_bridge.sv ├── nasti_lite_reader.sv ├── nasti_lite_writer.sv └── nasti_request.vh ├── plusarg_reader.v ├── sram_modified.v └── xilinx_ips.txt /.gitignore: -------------------------------------------------------------------------------- 1 | firmware/firmware.bin 2 | firmware/firmware.elf 3 | firmware/firmware.hex 4 | nexysvideo/ 5 | nexys4ddr/ 6 | *.log 7 | *.jou 8 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "riscv-pk"] 2 | path = riscv-pk 3 | url = ../riscv-pk 4 | [submodule "rocket-chip"] 5 | path = rocket-chip 6 | url = ../rocket-chip 7 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright 2018-2020 Bangya Liu and Wei Song 2 | at the Institute of Information Engineering, Chinese Academy of Sciences. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # neutrino 2019 summer 2 | # IIE CAS 3 | # Please have a look at README.md first 4 | 5 | PROJ ?= nexys4ddr 6 | #PROJ ?= nexysvideo 7 | 8 | CONFIG ?= DefaultNexys4DDRConfig 9 | #CONFIG ?= DefaultNexysVideoConfig 10 | 11 | ### vivado source 12 | bootrom_img = rocket-chip/bootrom/bootrom.img 13 | defaultconfig_v = rocket-chip/vsim/generated-src/freechips.rocketchip.system.$(CONFIG).v 14 | firmware_hex = firmware/firmware.hex 15 | vivado_project = $(PROJ)/$(PROJ).xpr 16 | 17 | $(defaultconfig_v) : $(bootrom_img) 18 | CONFIG=$(CONFIG) $(MAKE) -C rocket-chip/vsim verilog 19 | @echo "#################################" 20 | @echo "##### DefaultConfig.v built #####" 21 | @echo "#################################" 22 | 23 | $(bootrom_img) : 24 | $(MAKE) -C rocket-chip/bootrom 25 | @echo "#################################" 26 | @echo "##### Bootrom.img built #####" 27 | @echo "#################################" 28 | 29 | $(firmware_hex) : 30 | $(MAKE) -C firmware all 31 | @echo "#################################" 32 | @echo "##### firmware.hex built #####" 33 | @echo "#################################" 34 | 35 | $(vivado_project): $(defaultconfig_v) $(firmware_hex) 36 | vivado -mode batch -source scripts/create_$(PROJ)_vivado_proj.tcl 37 | 38 | vivado: $(vivado_project) 39 | vivado $< & 40 | 41 | ### sd_image 42 | boot_elf = boot.elf 43 | 44 | sd_image : $(boot_elf) 45 | 46 | $(boot_elf) : $(VMLINUX) 47 | ifndef VMLINUX 48 | $(error Please set VMLINUX. Please take a look at README) 49 | endif 50 | VMLINUX=$(VMLINUX) $(MAKE) -C riscv-pk/build && cp riscv-pk/build/bbl ./boot.elf 51 | @echo "#################################" 52 | @echo "##### boot.elf built #####" 53 | @echo "#################################" 54 | 55 | ### clean 56 | clean: 57 | $(MAKE) -C rocket-chip/vsim clean 58 | $(MAKE) -C firmware clean 59 | $(MAKE) -C riscv-pk/build clean 60 | -rm $(defaultconfig_v) 61 | -rm $(bootrom_img) 62 | -rm $(firmware_hex) 63 | -rm $(boot_elf) 64 | 65 | cleanall: 66 | $(MAKE) clean 67 | -rm -r $(PROJ) 68 | -------------------------------------------------------------------------------- /config/openocd_bscan.cfg: -------------------------------------------------------------------------------- 1 | #bindto 0.0.0.0 2 | 3 | adapter speed 10000 4 | adapter driver ftdi 5 | ftdi vid_pid 0x0403 0x6010 6 | ftdi layout_init 0x0088 0x008b 7 | ftdi tdo_sample_edge falling 8 | ftdi channel 0 9 | 10 | #reset_config done 11 | 12 | set _CHIPNAME riscv 13 | jtag newtap $_CHIPNAME cpu -irlen 6 14 | 15 | set _TARGETNAME $_CHIPNAME.cpu 16 | 17 | target create $_TARGETNAME.0 riscv -chain-position $_TARGETNAME 18 | # $_TARGETNAME.0 configure -work-area-phys 0x80000000 -work-area-size 10000 -work-area-backup 1 19 | 20 | riscv use_bscan_tunnel 5 -------------------------------------------------------------------------------- /config/openocd_pmod.cfg: -------------------------------------------------------------------------------- 1 | # bindto 0.0.0.0 2 | 3 | adapter speed 10000 4 | adapter driver ftdi 5 | ftdi vid_pid 0x0403 0x6014 6 | ftdi layout_init 0x0088 0x008b 7 | ftdi tdo_sample_edge falling 8 | ftdi channel 0 9 | #reset_config done 10 | 11 | set _CHIPNAME riscv 12 | jtag newtap $_CHIPNAME cpu -irlen 5 13 | 14 | set _TARGETNAME $_CHIPNAME.cpu 15 | 16 | target create $_TARGETNAME.0 riscv -chain-position $_TARGETNAME 17 | # $_TARGETNAME.0 configure -work-area-phys 0x80000000 -work-area-size 10000 -work-area-backup 1 18 | -------------------------------------------------------------------------------- /constraints/DDR_Pin_Map.ucf: -------------------------------------------------------------------------------- 1 | NET "ddr2_dq[0]" LOC = "R7" | IOSTANDARD = SSTL18_II ; 2 | NET "ddr2_dq[1]" LOC = "V6" | IOSTANDARD = SSTL18_II ; 3 | NET "ddr2_dq[2]" LOC = "R8" | IOSTANDARD = SSTL18_II ; 4 | NET "ddr2_dq[3]" LOC = "U7" | IOSTANDARD = SSTL18_II ; 5 | NET "ddr2_dq[4]" LOC = "V7" | IOSTANDARD = SSTL18_II ; 6 | NET "ddr2_dq[5]" LOC = "R6" | IOSTANDARD = SSTL18_II ; 7 | NET "ddr2_dq[6]" LOC = "U6" | IOSTANDARD = SSTL18_II ; 8 | NET "ddr2_dq[7]" LOC = "R5" | IOSTANDARD = SSTL18_II ; 9 | NET "ddr2_dq[8]" LOC = "T5" | IOSTANDARD = SSTL18_II ; 10 | NET "ddr2_dq[9]" LOC = "U3" | IOSTANDARD = SSTL18_II ; 11 | NET "ddr2_dq[10]" LOC = "V5" | IOSTANDARD = SSTL18_II ; 12 | NET "ddr2_dq[11]" LOC = "U4" | IOSTANDARD = SSTL18_II ; 13 | NET "ddr2_dq[12]" LOC = "V4" | IOSTANDARD = SSTL18_II ; 14 | NET "ddr2_dq[13]" LOC = "T4" | IOSTANDARD = SSTL18_II ; 15 | NET "ddr2_dq[14]" LOC = "V1" | IOSTANDARD = SSTL18_II ; 16 | NET "ddr2_dq[15]" LOC = "T3" | IOSTANDARD = SSTL18_II ; 17 | NET "ddr2_dm[0]" LOC = "T6" | IOSTANDARD = SSTL18_II ; 18 | NET "ddr2_dm[1]" LOC = "U1" | IOSTANDARD = SSTL18_II ; 19 | NET "ddr2_dqs_p[0]" LOC = "U9" | IOSTANDARD = DIFF_SSTL18_II ; 20 | NET "ddr2_dqs_n[0]" LOC = "V9" | IOSTANDARD = DIFF_SSTL18_II ; 21 | NET "ddr2_dqs_p[1]" LOC = "U2" | IOSTANDARD = DIFF_SSTL18_II ; 22 | NET "ddr2_dqs_n[1]" LOC = "V2" | IOSTANDARD = DIFF_SSTL18_II ; 23 | NET "ddr2_addr[12]" LOC = "N6" | IOSTANDARD = SSTL18_II ; 24 | NET "ddr2_addr[11]" LOC = "K5" | IOSTANDARD = SSTL18_II ; 25 | NET "ddr2_addr[10]" LOC = "R2" | IOSTANDARD = SSTL18_II ; 26 | NET "ddr2_addr[9]" LOC = "N5" | IOSTANDARD = SSTL18_II ; 27 | NET "ddr2_addr[8]" LOC = "L4" | IOSTANDARD = SSTL18_II ; 28 | NET "ddr2_addr[7]" LOC = "N1" | IOSTANDARD = SSTL18_II ; 29 | NET "ddr2_addr[6]" LOC = "M2" | IOSTANDARD = SSTL18_II ; 30 | NET "ddr2_addr[5]" LOC = "P5" | IOSTANDARD = SSTL18_II ; 31 | NET "ddr2_addr[4]" LOC = "L3" | IOSTANDARD = SSTL18_II ; 32 | NET "ddr2_addr[3]" LOC = "T1" | IOSTANDARD = SSTL18_II ; 33 | NET "ddr2_addr[2]" LOC = "M6" | IOSTANDARD = SSTL18_II ; 34 | NET "ddr2_addr[1]" LOC = "P4" | IOSTANDARD = SSTL18_II ; 35 | NET "ddr2_addr[0]" LOC = "M4" | IOSTANDARD = SSTL18_II ; 36 | NET "ddr2_ba[2]" LOC = "R1" | IOSTANDARD = SSTL18_II ; 37 | NET "ddr2_ba[1]" LOC = "P3" | IOSTANDARD = SSTL18_II ; 38 | NET "ddr2_ba[0]" LOC = "P2" | IOSTANDARD = SSTL18_II ; 39 | NET "ddr2_ck_p[0]" LOC = "L6" | IOSTANDARD = DIFF_SSTL18_II ; 40 | NET "ddr2_ck_n[0]" LOC = "L5" | IOSTANDARD = DIFF_SSTL18_II ; 41 | NET "ddr2_ras_n" LOC = "N4" | IOSTANDARD = SSTL18_II ; 42 | NET "ddr2_cas_n" LOC = "L1" | IOSTANDARD = SSTL18_II ; 43 | NET "ddr2_we_n" LOC = "N2" | IOSTANDARD = SSTL18_II ; 44 | NET "ddr2_cke[0]" LOC = "M1" | IOSTANDARD = SSTL18_II ; 45 | NET "ddr2_odt[0]" LOC = "M3" | IOSTANDARD = SSTL18_II ; 46 | NET "ddr2_cs_n[0]" LOC = "K6" | IOSTANDARD = SSTL18_II ; 47 | -------------------------------------------------------------------------------- /constraints/nexys4ddr.xdc: -------------------------------------------------------------------------------- 1 | set_property -dict { PACKAGE_PIN E3 IOSTANDARD LVCMOS33 } [get_ports { clock100 }]; 2 | create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports {clock100}]; 3 | 4 | set_property -dict { PACKAGE_PIN C12 IOSTANDARD LVCMOS33 } [get_ports { buttonresetn }]; 5 | 6 | set_property -dict { PACKAGE_PIN D4 IOSTANDARD LVCMOS33 } [get_ports { uart_TX }]; 7 | set_property -dict { PACKAGE_PIN C4 IOSTANDARD LVCMOS33 } [get_ports { uart_RX }]; 8 | 9 | 10 | set_property -dict { PACKAGE_PIN H17 IOSTANDARD LVCMOS33 } [get_ports { LED[0] }]; 11 | set_property -dict { PACKAGE_PIN K15 IOSTANDARD LVCMOS33 } [get_ports { LED[1] }]; 12 | set_property -dict { PACKAGE_PIN J13 IOSTANDARD LVCMOS33 } [get_ports { LED[2] }]; 13 | set_property -dict { PACKAGE_PIN N14 IOSTANDARD LVCMOS33 } [get_ports { LED[3] }]; 14 | set_property -dict { PACKAGE_PIN R18 IOSTANDARD LVCMOS33 } [get_ports { LED[4] }]; 15 | set_property -dict { PACKAGE_PIN V17 IOSTANDARD LVCMOS33 } [get_ports { LED[5] }]; 16 | set_property -dict { PACKAGE_PIN U17 IOSTANDARD LVCMOS33 } [get_ports { LED[6] }]; 17 | set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports { LED[7] }]; 18 | 19 | set_property -dict { PACKAGE_PIN E2 IOSTANDARD LVCMOS33 } [get_ports { sd_poweroff }]; 20 | set_property -dict { PACKAGE_PIN B1 IOSTANDARD LVCMOS33 } [get_ports { spi_sclock }]; 21 | set_property -dict { PACKAGE_PIN C1 IOSTANDARD LVCMOS33 } [get_ports { spi_mosi }]; 22 | set_property -dict { PACKAGE_PIN C2 IOSTANDARD LVCMOS33 } [get_ports { spi_miso }]; 23 | set_property -dict { PACKAGE_PIN D2 IOSTANDARD LVCMOS33 } [get_ports { spi_cs }]; 24 | 25 | create_clock -period 200.000 -name pmod_jtag_tck [get_ports jtag_pmod_tck] 26 | set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets jtag_pmod_tck_IBUF] 27 | 28 | set_property -dict { PACKAGE_PIN K1 IOSTANDARD LVCMOS33 } [get_ports { jtag_pmod_tck }]; # JC1 29 | set_property -dict { PACKAGE_PIN F6 IOSTANDARD LVCMOS33 } [get_ports { jtag_pmod_tdi }]; # JC2 30 | set_property -dict { PACKAGE_PIN J2 IOSTANDARD LVCMOS33 } [get_ports { jtag_pmod_tdo }]; # JC3 31 | set_property -dict { PACKAGE_PIN G6 IOSTANDARD LVCMOS33 } [get_ports { jtag_pmod_tms }]; # JC4 32 | 33 | -------------------------------------------------------------------------------- /constraints/nexysvideo.xdc: -------------------------------------------------------------------------------- 1 | set_property -dict { PACKAGE_PIN R4 IOSTANDARD LVCMOS33 } [get_ports { clock100 }]; 2 | create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports {clock100}]; 3 | 4 | set_property -dict { PACKAGE_PIN G4 IOSTANDARD LVCMOS15 } [get_ports { buttonresetn }]; 5 | 6 | set_property -dict { PACKAGE_PIN AA19 IOSTANDARD LVCMOS33 } [get_ports { uart_TX }]; 7 | set_property -dict { PACKAGE_PIN V18 IOSTANDARD LVCMOS33 } [get_ports { uart_RX }]; 8 | 9 | 10 | set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { LED[0] }]; 11 | set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 } [get_ports { LED[1] }]; 12 | set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS33 } [get_ports { LED[2] }]; 13 | set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS33 } [get_ports { LED[3] }]; 14 | set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS33 } [get_ports { LED[4] }]; 15 | set_property -dict { PACKAGE_PIN W16 IOSTANDARD LVCMOS33 } [get_ports { LED[5] }]; 16 | set_property -dict { PACKAGE_PIN W15 IOSTANDARD LVCMOS33 } [get_ports { LED[6] }]; 17 | set_property -dict { PACKAGE_PIN Y13 IOSTANDARD LVCMOS33 } [get_ports { LED[7] }]; 18 | 19 | set_property -dict { PACKAGE_PIN V20 IOSTANDARD LVCMOS33 } [get_ports { sd_poweroff }]; 20 | set_property -dict { PACKAGE_PIN W19 IOSTANDARD LVCMOS33 } [get_ports { spi_sclock }]; 21 | set_property -dict { PACKAGE_PIN W20 IOSTANDARD LVCMOS33 } [get_ports { spi_mosi }]; 22 | set_property -dict { PACKAGE_PIN V19 IOSTANDARD LVCMOS33 } [get_ports { spi_miso }]; 23 | set_property -dict { PACKAGE_PIN U18 IOSTANDARD LVCMOS33 } [get_ports { spi_cs }]; 24 | 25 | create_clock -period 200.000 -name pmod_jtag_tck [get_ports jtag_pmod_tck] 26 | set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets jtag_pmod_tck_IBUF] 27 | 28 | set_property -dict { PACKAGE_PIN Y6 IOSTANDARD LVCMOS33 } [get_ports { jtag_pmod_tck }]; # JC1 29 | set_property -dict { PACKAGE_PIN AA6 IOSTANDARD LVCMOS33 } [get_ports { jtag_pmod_tdi }]; # JC2 30 | set_property -dict { PACKAGE_PIN AA8 IOSTANDARD LVCMOS33 } [get_ports { jtag_pmod_tdo }]; # JC3 31 | set_property -dict { PACKAGE_PIN AB8 IOSTANDARD LVCMOS33 } [get_ports { jtag_pmod_tms }]; # JC4 32 | 33 | -------------------------------------------------------------------------------- /firmware/Makefile: -------------------------------------------------------------------------------- 1 | all: firmware.hex #program.txt 2 | 3 | 4 | driver_dir = ./driver 5 | 6 | c_driver = \ 7 | $(driver_dir)/uart.c \ 8 | $(driver_dir)/myprintf.c \ 9 | $(driver_dir)/elf.c \ 10 | $(driver_dir)/spi.c \ 11 | $(driver_dir)/diskio.c \ 12 | $(driver_dir)/ff.c \ 13 | $(driver_dir)/memory.c 14 | 15 | 16 | # currently we put dtb into the boot.elf image (in SD card) for debug convinence. generally it should be put into firmware. 17 | # devicetree.dtb: devicetree.dts 18 | # dtc -I dts -O dtb -o $@ $< 19 | 20 | firmware.elf: linker.ld head.S sdload.c $(c_driver) # devicetree.dtb 21 | riscv64-unknown-elf-gcc -nostdlib -static -fno-builtin-printf -T linker.ld -I $(driver_dir) head.S sdload.c $(c_driver) -o $@ # -DDEVICE_TREE='"devicetree.dtb"' 22 | 23 | # program.txt is used to check the instructions 24 | # program.txt: firmware.elf 25 | # riscv64-unknown-elf-objdump -D $< > $@ 26 | 27 | firmware.bin: firmware.elf 28 | riscv64-unknown-elf-objcopy -O binary $< $@ 29 | 30 | firmware.hex: firmware.bin 31 | od -t x8 -An -w8 -v $< > $@ 32 | 33 | clean: 34 | -rm firmware.hex firmware.elf firmware.bin #program.txt devicetree.dtb 35 | 36 | refresh: 37 | make clean && make all -------------------------------------------------------------------------------- /firmware/driver/bits.h: -------------------------------------------------------------------------------- 1 | #ifndef _RISCV_BITS_H 2 | #define _RISCV_BITS_H 3 | 4 | #define likely(x) __builtin_expect((x), 1) 5 | #define unlikely(x) __builtin_expect((x), 0) 6 | 7 | #define ROUNDUP(a, b) ((((a)-1)/(b)+1)*(b)) 8 | #define ROUNDDOWN(a, b) ((a)/(b)*(b)) 9 | 10 | #define MAX(a, b) ((a) > (b) ? (a) : (b)) 11 | #define MIN(a, b) ((a) < (b) ? (a) : (b)) 12 | #define CLAMP(a, lo, hi) MIN(MAX(a, lo), hi) 13 | 14 | #define EXTRACT_FIELD(val, which) (((val) & (which)) / ((which) & ~((which)-1))) 15 | #define INSERT_FIELD(val, which, fieldval) (((val) & ~(which)) | ((fieldval) * ((which) & ~((which)-1)))) 16 | 17 | #define STR(x) XSTR(x) 18 | #define XSTR(x) #x 19 | 20 | #ifdef __riscv64 21 | # define SLL32 sllw 22 | # define STORE sd 23 | # define LOAD ld 24 | # define LWU lwu 25 | # define LOG_REGBYTES 3 26 | #else 27 | # define SLL32 sll 28 | # define STORE sw 29 | # define LOAD lw 30 | # define LWU lw 31 | # define LOG_REGBYTES 2 32 | #endif 33 | #define REGBYTES (1 << LOG_REGBYTES) 34 | 35 | #endif -------------------------------------------------------------------------------- /firmware/driver/diskio.h: -------------------------------------------------------------------------------- 1 | /*-----------------------------------------------------------------------*/ 2 | /* Low level disk interface modlue include file (C)ChaN, 2014 */ 3 | /*-----------------------------------------------------------------------*/ 4 | /* 5 | * Copyright (C) 2014, ChaN, all right reserved. 6 | * 7 | * * This software is a free software and there is NO WARRANTY. 8 | * * No restriction on use. You can use, modify and redistribute it for 9 | * personal, non-profit or commercial products UNDER YOUR RESPONSIBILITY. 10 | * * Redistributions of source code must retain the above copyright notice. 11 | * 12 | * Copyright (c) 2015, University of Cambridge. 13 | * All Rights Reserved. 14 | * 15 | * Redistribution and use in source and binary forms, with or without 16 | * modification, are permitted provided that the following conditions are met: 17 | * 1. Redistributions of source code must retain the above copyright 18 | * notice, this list of conditions and the following disclaimer. 19 | * 2. Redistributions in binary form must reproduce the above copyright 20 | * notice, this list of conditions and the following disclaimer in the 21 | * documentation and/or other materials provided with the distribution. 22 | * 3. Neither the name of the University of Cambridge nor the 23 | * names of its contributors may be used to endorse or promote products 24 | * derived from this software without specific prior written permission. 25 | * 26 | * IN NO EVENT SHALL UNIVERSITY OF CAMBRIDGE BE LIABLE TO ANY PARTY FOR DIRECT, 27 | * INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, 28 | * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS 29 | * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | * 31 | * UNIVERSITY OF CAMBRIDGE SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT 32 | * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 33 | * PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, 34 | * PROVIDED HEREUNDER IS PROVIDED "AS IS". UNIVERSITY OF CAMBRIDGE HAS NO 35 | * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR 36 | * MODIFICATIONS. 37 | */ 38 | /*------------------------------------------------------------------------*/ 39 | 40 | #ifndef _DISKIO_DEFINED 41 | #define _DISKIO_DEFINED 42 | 43 | #ifdef __cplusplus 44 | extern "C" { 45 | #endif 46 | 47 | #include 48 | 49 | #define _USE_WRITE 1 /* 1: Enable disk_write function */ 50 | #define _USE_IOCTL 1 /* 1: Enable disk_ioctl fucntion */ 51 | 52 | /* Status of Disk Functions */ 53 | typedef uint8_t DSTATUS; 54 | 55 | /* Results of Disk Functions */ 56 | typedef enum { 57 | RES_OK = 0, /* 0: Successful */ 58 | RES_ERROR, /* 1: R/W Error */ 59 | RES_WRPRT, /* 2: Write Protected */ 60 | RES_NOTRDY, /* 3: Not Ready */ 61 | RES_PARERR /* 4: Invalid Parameter */ 62 | } DRESULT; 63 | 64 | 65 | /*---------------------------------------*/ 66 | /* Prototypes for disk control functions */ 67 | 68 | 69 | DSTATUS disk_initialize (uint8_t pdrv); 70 | DSTATUS disk_status (uint8_t pdrv); 71 | DRESULT disk_read (uint8_t pdrv, uint8_t* buff, uint32_t sector, uint32_t count); 72 | #if _USE_WRITE 73 | DRESULT disk_write (uint8_t pdrv, const uint8_t* buff, uint32_t sector, uint32_t count); 74 | #endif 75 | #if _USE_IOCTL 76 | DRESULT disk_ioctl (uint8_t pdrv, uint8_t cmd, void* buff); 77 | #endif 78 | void disk_timerproc (void); 79 | 80 | 81 | /* Disk Status Bits (DSTATUS) */ 82 | #define STA_NOINIT 0x01 /* Drive not initialized */ 83 | #define STA_NODISK 0x02 /* No medium in the drive */ 84 | #define STA_PROTECT 0x04 /* Write protected */ 85 | 86 | 87 | /* Command code for disk_ioctrl fucntion */ 88 | 89 | /* Generic command (Used by FatFs) */ 90 | #define CTRL_SYNC 0 /* Complete pending write process (needed at _FS_READONLY == 0) */ 91 | #define GET_SECTOR_COUNT 1 /* Get media size (needed at _USE_MKFS == 1) */ 92 | #define GET_SECTOR_SIZE 2 /* Get sector size (needed at _MAX_SS != _MIN_SS) */ 93 | #define GET_BLOCK_SIZE 3 /* Get erase block size (needed at _USE_MKFS == 1) */ 94 | #define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */ 95 | 96 | /* Generic command (Not used by FatFs) */ 97 | #define CTRL_FORMAT 5 /* Create physical format on the media */ 98 | #define CTRL_POWER_IDLE 6 /* Put the device idle state */ 99 | #define CTRL_POWER_OFF 7 /* Put the device off state */ 100 | #define CTRL_LOCK 8 /* Lock media removal */ 101 | #define CTRL_UNLOCK 9 /* Unlock media removal */ 102 | #define CTRL_EJECT 10 /* Eject media */ 103 | 104 | /* MMC/SDC specific command (Not used by FatFs) */ 105 | #define MMC_GET_TYPE 50 /* Get card type */ 106 | #define MMC_GET_CSD 51 /* Get CSD */ 107 | #define MMC_GET_CID 52 /* Get CID */ 108 | #define MMC_GET_OCR 53 /* Get OCR */ 109 | #define MMC_GET_SDSTAT 54 /* Get SD status */ 110 | 111 | /* ATA/CF specific command (Not used by FatFs) */ 112 | #define ATA_GET_REV 60 /* Get F/W revision */ 113 | #define ATA_GET_MODEL 61 /* Get model name */ 114 | #define ATA_GET_SN 62 /* Get serial number */ 115 | 116 | 117 | /* MMC card type flags (MMC_GET_TYPE) */ 118 | #define CT_MMC 0x01 /* MMC ver 3 */ 119 | #define CT_SD1 0x02 /* SD ver 1 */ 120 | #define CT_SD2 0x04 /* SD ver 2 */ 121 | #define CT_SDC (CT_SD1|CT_SD2) /* SD */ 122 | #define CT_BLOCK 0x08 /* Block addressing */ 123 | 124 | 125 | #ifdef __cplusplus 126 | } 127 | #endif 128 | 129 | #endif 130 | -------------------------------------------------------------------------------- /firmware/driver/elf.c: -------------------------------------------------------------------------------- 1 | #include "elf.h" 2 | #include "myprintf.h" 3 | #include 4 | 5 | static void *memSet(void *s, int c, size_t n) 6 | { 7 | if (NULL == s || n < 0) 8 | return NULL; 9 | char * tmpS = (char *)s; 10 | while(n-- > 0) 11 | *tmpS++ = c; 12 | return s; 13 | } 14 | 15 | static void *memCpy(void *dest, const void *src, size_t n) 16 | { 17 | if (NULL == dest || NULL == src || n < 0) 18 | return NULL; 19 | char *tempDest = (char *)dest; 20 | char *tempSrc = (char *)src; 21 | 22 | while (n-- > 0) 23 | *tempDest++ = *tempSrc++; 24 | return dest; 25 | } 26 | 27 | 28 | int load_elf(const uint8_t *elf, const uint32_t elf_size) { 29 | // sanity checks 30 | if(elf_size <= sizeof(Elf64_Ehdr)) 31 | return 1; /* too small */ 32 | 33 | const Elf64_Ehdr *eh = (const Elf64_Ehdr *)elf; 34 | if(!IS_ELF64(*eh)) 35 | return 2; /* not a elf64 file */ 36 | 37 | const Elf64_Phdr *ph = (const Elf64_Phdr *)(elf + eh->e_phoff); 38 | if(elf_size < eh->e_phoff + eh->e_phnum*sizeof(*ph)) 39 | return 3; /* internal damaged */ 40 | 41 | uint32_t i; 42 | for(i=0; ie_phnum; i++) { 43 | if(ph[i].p_type == PT_LOAD && ph[i].p_memsz) { /* need to load this physical section */ 44 | printf("[load_elf]still alive ... writing %d bytes to ", ph[i].p_filesz); 45 | printf("%h \n\r", (uintptr_t)ph[i].p_paddr); 46 | 47 | if(ph[i].p_filesz) { /* has data */ 48 | if(elf_size < ph[i].p_offset + ph[i].p_filesz) 49 | return 3; /* internal damaged */ 50 | memCpy((uint8_t *)ph[i].p_paddr, elf + ph[i].p_offset, ph[i].p_filesz); 51 | } 52 | if(ph[i].p_memsz > ph[i].p_filesz) { /* zero padding */ 53 | memSet((uint8_t *)ph[i].p_paddr + ph[i].p_filesz, 0, ph[i].p_memsz - ph[i].p_filesz); 54 | } 55 | } 56 | } 57 | 58 | return 0; 59 | } -------------------------------------------------------------------------------- /firmware/driver/elf.h: -------------------------------------------------------------------------------- 1 | #ifndef _ELF_H 2 | #define _ELF_H 3 | 4 | #include 5 | 6 | #define IS_ELF(hdr) \ 7 | ((hdr).e_ident[0] == 0x7f && (hdr).e_ident[1] == 'E' && \ 8 | (hdr).e_ident[2] == 'L' && (hdr).e_ident[3] == 'F') 9 | 10 | #define IS_ELF32(hdr) (IS_ELF(hdr) && (hdr).e_ident[4] == 1) 11 | #define IS_ELF64(hdr) (IS_ELF(hdr) && (hdr).e_ident[4] == 2) 12 | 13 | #define PT_LOAD 1 14 | 15 | #define SHT_NOBITS 8 16 | 17 | typedef struct { 18 | uint8_t e_ident[16]; 19 | uint16_t e_type; 20 | uint16_t e_machine; 21 | uint32_t e_version; 22 | uint32_t e_entry; 23 | uint32_t e_phoff; 24 | uint32_t e_shoff; 25 | uint32_t e_flags; 26 | uint16_t e_ehsize; 27 | uint16_t e_phentsize; 28 | uint16_t e_phnum; 29 | uint16_t e_shentsize; 30 | uint16_t e_shnum; 31 | uint16_t e_shstrndx; 32 | } Elf32_Ehdr; 33 | 34 | typedef struct { 35 | uint32_t sh_name; 36 | uint32_t sh_type; 37 | uint32_t sh_flags; 38 | uint32_t sh_addr; 39 | uint32_t sh_offset; 40 | uint32_t sh_size; 41 | uint32_t sh_link; 42 | uint32_t sh_info; 43 | uint32_t sh_addralign; 44 | uint32_t sh_entsize; 45 | } Elf32_Shdr; 46 | 47 | typedef struct 48 | { 49 | uint32_t p_type; 50 | uint32_t p_offset; 51 | uint32_t p_vaddr; 52 | uint32_t p_paddr; 53 | uint32_t p_filesz; 54 | uint32_t p_memsz; 55 | uint32_t p_flags; 56 | uint32_t p_align; 57 | } Elf32_Phdr; 58 | 59 | typedef struct 60 | { 61 | uint32_t st_name; 62 | uint32_t st_value; 63 | uint32_t st_size; 64 | uint8_t st_info; 65 | uint8_t st_other; 66 | uint16_t st_shndx; 67 | } Elf32_Sym; 68 | 69 | typedef struct { 70 | uint8_t e_ident[16]; 71 | uint16_t e_type; 72 | uint16_t e_machine; 73 | uint32_t e_version; 74 | uint64_t e_entry; 75 | uint64_t e_phoff; 76 | uint64_t e_shoff; 77 | uint32_t e_flags; 78 | uint16_t e_ehsize; 79 | uint16_t e_phentsize; 80 | uint16_t e_phnum; 81 | uint16_t e_shentsize; 82 | uint16_t e_shnum; 83 | uint16_t e_shstrndx; 84 | } Elf64_Ehdr; 85 | 86 | typedef struct { 87 | uint32_t sh_name; 88 | uint32_t sh_type; 89 | uint64_t sh_flags; 90 | uint64_t sh_addr; 91 | uint64_t sh_offset; 92 | uint64_t sh_size; 93 | uint32_t sh_link; 94 | uint32_t sh_info; 95 | uint64_t sh_addralign; 96 | uint64_t sh_entsize; 97 | } Elf64_Shdr; 98 | 99 | typedef struct { 100 | uint32_t p_type; 101 | uint32_t p_flags; 102 | uint64_t p_offset; 103 | uint64_t p_vaddr; 104 | uint64_t p_paddr; 105 | uint64_t p_filesz; 106 | uint64_t p_memsz; 107 | uint64_t p_align; 108 | } Elf64_Phdr; 109 | 110 | typedef struct { 111 | uint32_t st_name; 112 | uint8_t st_info; 113 | uint8_t st_other; 114 | uint16_t st_shndx; 115 | uint64_t st_value; 116 | uint64_t st_size; 117 | } Elf64_Sym; 118 | 119 | extern int load_elf(const uint8_t *elf, const uint32_t elf_size); 120 | 121 | #endif -------------------------------------------------------------------------------- /firmware/driver/ffconf.h: -------------------------------------------------------------------------------- 1 | /*---------------------------------------------------------------------------/ 2 | / FatFs - FAT file system module configuration file R0.11a (C)ChaN, 2015 3 | /---------------------------------------------------------------------------*/ 4 | 5 | #define _FFCONF 64180 /* Revision ID */ 6 | 7 | /*---------------------------------------------------------------------------/ 8 | / Function Configurations 9 | /---------------------------------------------------------------------------*/ 10 | 11 | #define _FS_READONLY 0 12 | /* This option switches read-only configuration. (0:Read/Write or 1:Read-only) 13 | / Read-only configuration removes writing API functions, f_write(), f_sync(), 14 | / f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree() 15 | / and optional writing functions as well. */ 16 | 17 | 18 | #define _FS_MINIMIZE 0 19 | /* This option defines minimization level to remove some basic API functions. 20 | / 21 | / 0: All basic functions are enabled. 22 | / 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_chmod(), f_utime(), 23 | / f_truncate() and f_rename() function are removed. 24 | / 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1. 25 | / 3: f_lseek() function is removed in addition to 2. */ 26 | 27 | 28 | #define _USE_STRFUNC 0 29 | /* This option switches string functions, f_gets(), f_putc(), f_puts() and 30 | / f_printf(). 31 | / 32 | / 0: Disable string functions. 33 | / 1: Enable without LF-CRLF conversion. 34 | / 2: Enable with LF-CRLF conversion. */ 35 | 36 | 37 | #define _USE_FIND 0 38 | /* This option switches filtered directory read feature and related functions, 39 | / f_findfirst() and f_findnext(). (0:Disable or 1:Enable) */ 40 | 41 | 42 | #define _USE_MKFS 0 43 | /* This option switches f_mkfs() function. (0:Disable or 1:Enable) */ 44 | 45 | 46 | #define _USE_FASTSEEK 0 47 | /* This option switches fast seek feature. (0:Disable or 1:Enable) */ 48 | 49 | 50 | #define _USE_LABEL 1 51 | /* This option switches volume label functions, f_getlabel() and f_setlabel(). 52 | / (0:Disable or 1:Enable) */ 53 | 54 | 55 | #define _USE_FORWARD 0 56 | /* This option switches f_forward() function. (0:Disable or 1:Enable) 57 | / To enable it, also _FS_TINY need to be set to 1. */ 58 | 59 | 60 | /*---------------------------------------------------------------------------/ 61 | / Locale and Namespace Configurations 62 | /---------------------------------------------------------------------------*/ 63 | 64 | #define _CODE_PAGE 1 65 | /* This option specifies the OEM code page to be used on the target system. 66 | / Incorrect setting of the code page can cause a file open failure. 67 | / 68 | / 1 - ASCII (No extended character. Non-LFN cfg. only) 69 | / 437 - U.S. 70 | / 720 - Arabic 71 | / 737 - Greek 72 | / 771 - KBL 73 | / 775 - Baltic 74 | / 850 - Latin 1 75 | / 852 - Latin 2 76 | / 855 - Cyrillic 77 | / 857 - Turkish 78 | / 860 - Portuguese 79 | / 861 - Icelandic 80 | / 862 - Hebrew 81 | / 863 - Canadian French 82 | / 864 - Arabic 83 | / 865 - Nordic 84 | / 866 - Russian 85 | / 869 - Greek 2 86 | / 932 - Japanese (DBCS) 87 | / 936 - Simplified Chinese (DBCS) 88 | / 949 - Korean (DBCS) 89 | / 950 - Traditional Chinese (DBCS) 90 | */ 91 | 92 | 93 | #define _USE_LFN 0 94 | #define _MAX_LFN 255 95 | /* The _USE_LFN option switches the LFN feature. 96 | / 97 | / 0: Disable LFN feature. _MAX_LFN has no effect. 98 | / 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe. 99 | / 2: Enable LFN with dynamic working buffer on the STACK. 100 | / 3: Enable LFN with dynamic working buffer on the HEAP. 101 | / 102 | / When enable the LFN feature, Unicode handling functions (option/unicode.c) must 103 | / be added to the project. The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes. 104 | / When use stack for the working buffer, take care on stack overflow. When use heap 105 | / memory for the working buffer, memory management functions, ff_memalloc() and 106 | / ff_memfree(), must be added to the project. */ 107 | 108 | 109 | #define _LFN_UNICODE 0 110 | /* This option switches character encoding on the API. (0:ANSI/OEM or 1:Unicode) 111 | / To use Unicode string for the path name, enable LFN feature and set _LFN_UNICODE 112 | / to 1. This option also affects behavior of string I/O functions. */ 113 | 114 | 115 | #define _STRF_ENCODE 3 116 | /* When _LFN_UNICODE is 1, this option selects the character encoding on the file to 117 | / be read/written via string I/O functions, f_gets(), f_putc(), f_puts and f_printf(). 118 | / 119 | / 0: ANSI/OEM 120 | / 1: UTF-16LE 121 | / 2: UTF-16BE 122 | / 3: UTF-8 123 | / 124 | / When _LFN_UNICODE is 0, this option has no effect. */ 125 | 126 | 127 | #define _FS_RPATH 2 128 | /* This option configures relative path feature. 129 | / 130 | / 0: Disable relative path feature and remove related functions. 131 | / 1: Enable relative path feature. f_chdir() and f_chdrive() are available. 132 | / 2: f_getcwd() function is available in addition to 1. 133 | / 134 | / Note that directory items read via f_readdir() are affected by this option. */ 135 | 136 | 137 | /*---------------------------------------------------------------------------/ 138 | / Drive/Volume Configurations 139 | /---------------------------------------------------------------------------*/ 140 | 141 | #define _VOLUMES 2 142 | /* Number of volumes (logical drives) to be used. */ 143 | 144 | 145 | #define _STR_VOLUME_ID 0 146 | #define _VOLUME_STRS "CF","SD" 147 | /* _STR_VOLUME_ID option switches string volume ID feature. 148 | / When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive 149 | / number in the path name. _VOLUME_STRS defines the drive ID strings for each 150 | / logical drives. Number of items must be equal to _VOLUMES. Valid characters for 151 | / the drive ID strings are: A-Z and 0-9. */ 152 | 153 | 154 | #define _MULTI_PARTITION 0 155 | /* This option switches multi-partition feature. By default (0), each logical drive 156 | / number is bound to the same physical drive number and only an FAT volume found on 157 | / the physical drive will be mounted. When multi-partition feature is enabled (1), 158 | / each logical drive number is bound to arbitrary physical drive and partition 159 | / listed in the VolToPart[]. Also f_fdisk() funciton will be available. */ 160 | 161 | 162 | #define _MIN_SS 512 163 | #define _MAX_SS 512 164 | /* These options configure the range of sector size to be supported. (512, 1024, 165 | / 2048 or 4096) Always set both 512 for most systems, all type of memory cards and 166 | / harddisk. But a larger value may be required for on-board flash memory and some 167 | / type of optical media. When _MAX_SS is larger than _MIN_SS, FatFs is configured 168 | / to variable sector size and GET_SECTOR_SIZE command must be implemented to the 169 | / disk_ioctl() function. */ 170 | 171 | 172 | #define _USE_TRIM 0 173 | /* This option switches ATA-TRIM feature. (0:Disable or 1:Enable) 174 | / To enable Trim feature, also CTRL_TRIM command should be implemented to the 175 | / disk_ioctl() function. */ 176 | 177 | 178 | #define _FS_NOFSINFO 0 179 | /* If you need to know correct free space on the FAT32 volume, set bit 0 of this 180 | / option, and f_getfree() function at first time after volume mount will force 181 | / a full FAT scan. Bit 1 controls the use of last allocated cluster number. 182 | / 183 | / bit0=0: Use free cluster count in the FSINFO if available. 184 | / bit0=1: Do not trust free cluster count in the FSINFO. 185 | / bit1=0: Use last allocated cluster number in the FSINFO if available. 186 | / bit1=1: Do not trust last allocated cluster number in the FSINFO. 187 | */ 188 | 189 | 190 | 191 | /*---------------------------------------------------------------------------/ 192 | / System Configurations 193 | /---------------------------------------------------------------------------*/ 194 | 195 | #define _FS_TINY 0 196 | /* This option switches tiny buffer configuration. (0:Normal or 1:Tiny) 197 | / At the tiny configuration, size of the file object (FIL) is reduced _MAX_SS 198 | / bytes. Instead of private sector buffer eliminated from the file object, 199 | / common sector buffer in the file system object (FATFS) is used for the file 200 | / data transfer. */ 201 | 202 | 203 | #define _FS_NORTC 1 204 | #define _NORTC_MON 1 205 | #define _NORTC_MDAY 1 206 | #define _NORTC_YEAR 2015 207 | /* The _FS_NORTC option switches timestamp feature. If the system does not have 208 | / an RTC function or valid timestamp is not needed, set _FS_NORTC to 1 to disable 209 | / the timestamp feature. All objects modified by FatFs will have a fixed timestamp 210 | / defined by _NORTC_MON, _NORTC_MDAY and _NORTC_YEAR. 211 | / When timestamp feature is enabled (_FS_NORTC == 0), get_fattime() function need 212 | / to be added to the project to read current time form RTC. _NORTC_MON, 213 | / _NORTC_MDAY and _NORTC_YEAR have no effect. 214 | / These options have no effect at read-only configuration (_FS_READONLY == 1). */ 215 | 216 | 217 | #define _FS_LOCK 0 218 | /* The _FS_LOCK option switches file lock feature to control duplicated file open 219 | / and illegal operation to open objects. This option must be 0 when _FS_READONLY 220 | / is 1. 221 | / 222 | / 0: Disable file lock feature. To avoid volume corruption, application program 223 | / should avoid illegal open, remove and rename to the open objects. 224 | / >0: Enable file lock feature. The value defines how many files/sub-directories 225 | / can be opened simultaneously under file lock control. Note that the file 226 | / lock feature is independent of re-entrancy. */ 227 | 228 | 229 | #define _FS_REENTRANT 0 230 | #define _FS_TIMEOUT 1000 231 | #define _SYNC_t HANDLE 232 | /* The _FS_REENTRANT option switches the re-entrancy (thread safe) of the FatFs 233 | / module itself. Note that regardless of this option, file access to different 234 | / volume is always re-entrant and volume control functions, f_mount(), f_mkfs() 235 | / and f_fdisk() function, are always not re-entrant. Only file/directory access 236 | / to the same volume is under control of this feature. 237 | / 238 | / 0: Disable re-entrancy. _FS_TIMEOUT and _SYNC_t have no effect. 239 | / 1: Enable re-entrancy. Also user provided synchronization handlers, 240 | / ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj() 241 | / function, must be added to the project. Samples are available in 242 | / option/syscall.c. 243 | / 244 | / The _FS_TIMEOUT defines timeout period in unit of time tick. 245 | / The _SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*, 246 | / SemaphoreHandle_t and etc.. A header file for O/S definitions needs to be 247 | / included somewhere in the scope of ff.c. */ 248 | 249 | 250 | #define _WORD_ACCESS 0 251 | /* The _WORD_ACCESS option is an only platform dependent option. It defines 252 | / which access method is used to the word data on the FAT volume. 253 | / 254 | / 0: Byte-by-byte access. Always compatible with all platforms. 255 | / 1: Word access. Do not choose this unless under both the following conditions. 256 | / 257 | / * Address misaligned memory access is always allowed to ALL instructions. 258 | / * Byte order on the memory is little-endian. 259 | / 260 | / If it is the case, _WORD_ACCESS can also be set to 1 to reduce code size. 261 | / Following table shows allowable settings of some type of processors. 262 | / 263 | / ARM7TDMI 0 *2 ColdFire 0 *1 V850E 0 *2 264 | / Cortex-M3 0 *3 Z80 0/1 V850ES 0/1 265 | / Cortex-M0 0 *2 x86 0/1 TLCS-870 0/1 266 | / AVR 0/1 RX600(LE) 0/1 TLCS-900 0/1 267 | / AVR32 0 *1 RL78 0 *2 R32C 0 *2 268 | / PIC18 0/1 SH-2 0 *1 M16C 0/1 269 | / PIC24 0 *2 H8S 0 *1 MSP430 0 *2 270 | / PIC32 0 *1 H8/300H 0 *1 8051 0/1 271 | / 272 | / *1:Big-endian. 273 | / *2:Unaligned memory access is not supported. 274 | / *3:Some compilers generate LDM/STM for mem_cpy function. 275 | */ 276 | 277 | -------------------------------------------------------------------------------- /firmware/driver/mem_map.h: -------------------------------------------------------------------------------- 1 | #ifndef MEM_MAP_HEADER_H 2 | #define MEM_MAP_HEADER_H 3 | 4 | #define MEM_MAP_UART_BASE 0x60000000 5 | #define MEM_MAP_BRAM_BASE 0x60010000 6 | #define MEM_MAP_SPI_BASE 0x60020000 7 | #define MEM_MAP_DDR_BASE 0x80000000 8 | 9 | #endif -------------------------------------------------------------------------------- /firmware/driver/memory.c: -------------------------------------------------------------------------------- 1 | #include "memory.h" 2 | 3 | volatile uint64_t * get_bram_base() { 4 | #ifdef MEM_MAP_BRAM_BASE 5 | return (uint64_t *)(MEM_MAP_BRAM_BASE); 6 | #else 7 | return (uint64_t *)0; /* boot ROM, raise error */ 8 | #endif 9 | } 10 | 11 | volatile uint64_t * get_ddr_base() { 12 | return (uint64_t *)(MEM_MAP_DDR_BASE); 13 | } 14 | 15 | volatile uint64_t * get_flash_base() { 16 | #ifdef MEM_MAP_FLASH_BASE 17 | return (uint64_t *)(MEM_MAP_FLASH_BASE); 18 | #else 19 | return (uint64_t *)0; /* boot ROM, raise error */ 20 | #endif 21 | } -------------------------------------------------------------------------------- /firmware/driver/memory.h: -------------------------------------------------------------------------------- 1 | #ifndef MEMORY_HEADER_H 2 | #define MEMORY_HEADER_H 3 | 4 | #include 5 | #include "mem_map.h" 6 | 7 | extern volatile uint64_t * get_bram_base(); 8 | extern volatile uint64_t * get_ddr_base(); 9 | extern volatile uint64_t * get_flash_base(); 10 | 11 | #endif -------------------------------------------------------------------------------- /firmware/driver/myprintf.c: -------------------------------------------------------------------------------- 1 | 2 | #include "myprintf.h" 3 | 4 | void putch(uint8_t ch){ 5 | uart_send(ch); 6 | } 7 | 8 | // void printf(char *s, ...) 9 | void printf(uint8_t *s, uint64_t num) 10 | { 11 | int i = 0; 12 | // va_list va_ptr; 13 | // va_start(va_ptr, s); 14 | while (s[i] != '\0') 15 | { 16 | if (s[i] != '%') putch(s[i++]); 17 | else 18 | switch (s[++i]) 19 | { 20 | case 'd': { 21 | // printDeci(va_arg(va_ptr,int)); 22 | if (num == 0) putch('0'); 23 | else printNum(num, 10); 24 | i++; 25 | continue; 26 | } 27 | case 'h': { 28 | // printDeci(va_arg(va_ptr,int)); 29 | putch('0'); 30 | putch('x'); 31 | if (num == 0) putch('0'); 32 | else printNum(num, 16); 33 | i++; 34 | continue; 35 | } 36 | default : { 37 | i++; 38 | continue; 39 | } 40 | } 41 | 42 | } 43 | 44 | // va_end(va_ptr); 45 | } 46 | 47 | void printNum(uint64_t num, int base) 48 | { 49 | if (num == 0) return; 50 | printNum(num / base, base); 51 | putch("0123456789abcdef"[num % base]); 52 | } -------------------------------------------------------------------------------- /firmware/driver/myprintf.h: -------------------------------------------------------------------------------- 1 | #ifndef PRINTF_HEADER 2 | #define PRINTF_HEADER 3 | 4 | #include 5 | // #include 6 | #include "uart.h" 7 | 8 | // extern void printf(char*, ...); 9 | extern void printf(uint8_t *, uint64_t); 10 | void printNum(uint64_t, int); 11 | void putch(uint8_t); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /firmware/driver/spi.c: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | #include "spi.h" 4 | 5 | #define GetBit(r, p) (((r) & (1 <> p) 6 | 7 | volatile uint32_t *spi_base_ptr = (uint32_t *)(SPI_BASE); 8 | 9 | void spi_init() { 10 | uint32_t resp; 11 | 12 | // power off SD 13 | *(spi_base_ptr) = 0x1; 14 | 15 | // software reset? 16 | *(spi_base_ptr + SPI_SRR) = 0xa; 17 | 18 | // set control register 19 | // MSB first, master, reset FIFOs, SPI disabled, clock 00 mode 20 | *(spi_base_ptr + SPI_CR) = 0xE4; 21 | 22 | // disable interrupt, full polling mode 23 | *(spi_base_ptr + SPI_GIER) = 0x0; 24 | 25 | // read status register 26 | //resp = (*(spi_base_ptr + SPI_SR)) & 0x7FF; 27 | //if(resp != 0x25) 28 | // return SD_ERR_SPI; // SPI error! 29 | 30 | // enable spi 31 | *(spi_base_ptr + SPI_CR) = 0x86; 32 | 33 | // power on SD 34 | *(spi_base_ptr) = 0x0; 35 | 36 | } 37 | 38 | 39 | void spi_disable() { 40 | // power off SD 41 | *(spi_base_ptr) = 0x1; 42 | 43 | *(spi_base_ptr + SPI_CR) = 0xE4; 44 | } 45 | 46 | uint8_t spi_send(uint8_t dat) { 47 | *(spi_base_ptr + SPI_DTR) = dat; 48 | while(!GetBit(*(spi_base_ptr + SPI_SR), 2)); 49 | return *(spi_base_ptr + SPI_DRR); 50 | } 51 | 52 | void spi_send_multi(const uint8_t* dat, uint8_t n) { 53 | uint8_t i; 54 | for(i=0; i 7 | #include "mem_map.h" 8 | 9 | // Xilinx AXI_QUAD_SPI 10 | 11 | #ifdef MEM_MAP_SPI_BASE 12 | #define SPI_BASE ((uint32_t)MEM_MAP_SPI_BASE) 13 | #else 14 | #define SPI_BASE 0 15 | #endif 16 | 17 | // Global interrupt enable register [Write] 18 | #define SPI_GIER 0x07u 19 | 20 | // IP interrupt status register [Read/Toggle to write] 21 | #define SPI_ISR 0x08u 22 | 23 | // IP interrupt enable register [Read/Write] 24 | #define SPI_IER 0x0Au 25 | 26 | // Software reset register [Write] 27 | #define SPI_SRR 0x10u 28 | 29 | // SPI control register [Read/Write] 30 | #define SPI_CR 0x18u 31 | 32 | // SPI status register [Read] 33 | #define SPI_SR 0x19u 34 | 35 | // SPI data transmit register, FIFO-16 [Write] 36 | #define SPI_DTR 0x1Au 37 | 38 | // SPI data receive register, FIFO-16 [Read] 39 | #define SPI_DRR 0x1Bu 40 | 41 | // SPI Slave select register, [Read/Write] 42 | #define SPI_SSR 0x1Cu 43 | 44 | // Transmit FIFO occupancy register [Read] 45 | #define SPI_TFOR 0x1Du 46 | 47 | // Receive FIFO occupancy register [Read] 48 | #define SPI_RFROR 0x1Eu 49 | 50 | ///////////////////////////// 51 | // SPI APIs 52 | 53 | // start spi 54 | void spi_init(); 55 | 56 | // disable spi 57 | void spi_disable(); 58 | 59 | // send a byte 60 | uint8_t spi_send(uint8_t dat); 61 | 62 | // send multiple byte, n<=16 63 | void spi_send_multi(const uint8_t* dat, uint8_t n); 64 | 65 | // recv multiple byte, n<=16 66 | void spi_recv_multi(uint8_t* dat, uint8_t n); 67 | 68 | // select slave device 69 | void spi_select_slave(uint8_t id); 70 | 71 | // deselect slave device 72 | void spi_deselect_slave(uint8_t id); 73 | 74 | #endif 75 | -------------------------------------------------------------------------------- /firmware/driver/uart.c: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | #include "uart.h" 4 | 5 | volatile uint32_t *uart_base_ptr = (uint32_t *)(UART_BASE); 6 | 7 | void uart_init() { 8 | // set 0x0080 to UART.LCR to enable DLL and DLM write 9 | // configure baud rate 10 | *(uart_base_ptr + UART_LCR) = 0x0080; 11 | 12 | // System clock 50 MHz, 115200 baud rate 13 | // divisor = clk_freq / (16 * Baud) 14 | *(uart_base_ptr + UART_DLL) = 50*1000*1000u / (16u * 115200u) % 0x100u; 15 | *(uart_base_ptr + UART_DLM) = 50*1000*1000u / (16u * 115200u) >> 8; 16 | 17 | // 8-bit data, 1-bit odd parity 18 | *(uart_base_ptr + UART_LCR) = 0x000Bu; 19 | 20 | // Enable read IRQ 21 | *(uart_base_ptr + UART_IER) = 0x0001u; 22 | 23 | // print "uart is working ..." 24 | //uart_demo(); 25 | 26 | 27 | } 28 | 29 | void uart_send(uint8_t data) { 30 | // wait until THR empty 31 | while(! (*(uart_base_ptr + UART_LSR) & 0x40u)); 32 | *(uart_base_ptr + UART_THR) = data; 33 | } 34 | -------------------------------------------------------------------------------- /firmware/driver/uart.h: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | #ifndef UART_HEADER_H 4 | #define UART_HEADER_H 5 | 6 | #include 7 | #include "mem_map.h" 8 | 9 | #ifdef MEM_MAP_UART_BASE 10 | #define UART_BASE ((uint32_t)(MEM_MAP_UART_BASE | 0x1000)) 11 | #else 12 | #define UART_BASE 0 13 | #endif 14 | 15 | // RBR: Receiver buffer register [Read, LCR[7] == 0] 16 | #define UART_RBR 0x0u 17 | 18 | // THR: Transmitter Holding register [Write, LCR[7] == 0] 19 | #define UART_THR 0x0u 20 | 21 | // IER: Interrupt enable register [Read/Write, LCR[7] == 0] 22 | #define UART_IER 0x1u 23 | 24 | // IIR: Interrupt identification register [Read] 25 | #define UART_IIR 0x2u 26 | 27 | // FCR: FIFO control register [Write, Read only when LCR[7] == 1] 28 | #define UART_FCR 0x2u 29 | 30 | // LCR: Line control register [Read/Write] 31 | #define UART_LCR 0x3u 32 | 33 | // MCR: Modem control register [Read/Write] 34 | #define UART_MCR 0x4u 35 | 36 | // LSR: Line status register [Read/Write] 37 | #define UART_LSR 0x5u 38 | 39 | // MSR: Modem status register [Read/Write] 40 | #define UART_MSR 0x6u 41 | 42 | // SCR: Scratch register [Read/Write] 43 | #define UART_SCR 0x7u 44 | 45 | // DLL: Divisor latch (least significant byte) register [Read/Write, LCR[7] == 1] 46 | #define UART_DLL 0x0u 47 | 48 | // DLM: Divisor latch (most significant byte) register [Read/Write, LCR[7] == 1] 49 | #define UART_DLM 0x1u 50 | 51 | // UART APIs 52 | extern void uart_init(); 53 | extern void uart_send(uint8_t); 54 | 55 | 56 | #endif 57 | -------------------------------------------------------------------------------- /firmware/head.S: -------------------------------------------------------------------------------- 1 | #define DDR_BASE 0x80000000 2 | 3 | .text 4 | .globl _start 5 | _start: 6 | 7 | li x1, 0 8 | li x2, 0 9 | li x3, 0 10 | li x4, 0 11 | li x5, 0 12 | li x6, 0 13 | li x7, 0 14 | li x8, 0 15 | li x9, 0 16 | li x10,0 17 | li x11,0 18 | li x12,0 19 | li x13,0 20 | li x14,0 21 | li x15,0 22 | li x16,0 23 | li x17,0 24 | li x18,0 25 | li x19,0 26 | li x20,0 27 | li x21,0 28 | li x22,0 29 | li x23,0 30 | li x24,0 31 | li x25,0 32 | li x26,0 33 | li x27,0 34 | li x28,0 35 | li x29,0 36 | li x30,0 37 | li x31,0 38 | 39 | la sp, _stack 40 | 41 | jal main 42 | 43 | li s0, DDR_BASE 44 | csrr a0, mhartid 45 | # la a1, _dtb 46 | jr s0 47 | 48 | .section ".stack", "awx" 49 | .globl _stack 50 | _stack: 51 | 52 | # currently we put dtb into the boot.elf image for debug convinence. 53 | # generally it should be put into firmware, namely, here. 54 | # .section ".dtb", "ax" 55 | # .globl _dtb 56 | # _dtb: 57 | # .incbin DEVICE_TREE 58 | -------------------------------------------------------------------------------- /firmware/linker.ld: -------------------------------------------------------------------------------- 1 | SECTIONS 2 | { 3 | . = 0x60010000; 4 | .text : { *(.text) } 5 | 6 | . = ALIGN(0x1000); 7 | .rodata : { *(.rodata) } 8 | .bss : { *(.bss) } 9 | .sbss : { *(.sbss) } 10 | 11 | /* currently we put dtb into the boot.elf image for debug convinence */ 12 | /* so we do not need it here. generally it should be put into firmware */ 13 | /* . = ALIGN(0x1000); */ 14 | /* .dtb : { *(.dtb) } */ 15 | 16 | . = 0x6001f000; 17 | .stack : { *(.stack) } 18 | 19 | . = 0x6001ff00; 20 | .sdata : { *(.sdata) } 21 | } 22 | -------------------------------------------------------------------------------- /firmware/sdload.c: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include "myprintf.h" 5 | #include "bits.h" 6 | #include "diskio.h" 7 | #include "ff.h" 8 | #include "uart.h" 9 | #include "elf.h" 10 | #include "memory.h" 11 | #include "spi.h" 12 | 13 | FATFS FatFs; // Work area (file system object) for logical drive 14 | 15 | // max size of file image is 16M 16 | #define MAX_FILE_SIZE 0x1000000 17 | 18 | // size of DDR RAM (128M for NEXYS4-DDR) 19 | #define DDR_SIZE 0x8000000 20 | 21 | // 4K size read burst 22 | #define SD_READ_SIZE 4096 23 | 24 | int main (void) 25 | { 26 | FIL fil; // File object 27 | FRESULT fr; // FatFs return code 28 | uint8_t *boot_file_buf = (uint8_t *)(get_ddr_base()) + DDR_SIZE - MAX_FILE_SIZE; // at the end of DDR space 29 | uint8_t *memory_base = (uint8_t *)(get_ddr_base()); 30 | 31 | uart_init(); 32 | 33 | printf("=============== FSBL ===============\n\r", 0); 34 | 35 | // Register work area to the default drive 36 | if(f_mount(&FatFs, "", 1)) { 37 | printf("Fail to mount SD driver!\n\r", 0); 38 | return 1; 39 | } 40 | 41 | // Open a file 42 | printf("Loading boot.elf into memory...\n\r", 0); 43 | fr = f_open(&fil, "boot.elf", FA_READ); 44 | if (fr) { 45 | printf("Failed to open boot.elf!\n\r", 0); 46 | return (int)fr; 47 | } 48 | 49 | // Read file into memory 50 | uint8_t *buf = boot_file_buf; 51 | uint32_t fsize = 0; // file size count 52 | uint32_t br; // Read count 53 | do { 54 | fr = f_read(&fil, buf, SD_READ_SIZE, &br); // Read a chunk of source file 55 | buf += br; 56 | fsize += br; 57 | } while(!(fr || br == 0)); 58 | 59 | printf("Load %d bytes to memory address ", fsize); 60 | printf("%h from boot.elf \n\r", (uint64_t)boot_file_buf); 61 | 62 | // read elf 63 | if(br = load_elf(boot_file_buf, fil.fsize)) 64 | printf("elf read failed with code %d \n\r", br); 65 | 66 | // Close the file 67 | if(f_close(&fil)) { 68 | printf("fail to close file!\n\r", 0); 69 | return 1; 70 | } 71 | if(f_mount(NULL, "", 1)) { // unmount it 72 | printf("fail to umount disk!\n\r", 0); 73 | return 1; 74 | } 75 | 76 | spi_disable(); 77 | printf("=========== Jump to DDR ============\n\r", 0); 78 | } -------------------------------------------------------------------------------- /linux_driver/README.md: -------------------------------------------------------------------------------- 1 | ##### How to use these files: 2 | Just replace the origin linux drivers with its alternative provided below 3 | 4 | |NAME_OF_DRIVERS | PATH_IN_LINUX | 5 | |-|-| 6 | |spi-xilinx.c | /drivers/spi | 7 | 8 | 9 | 10 | // Bangya Liu 2019 summer, in IIE, CAS 11 | -------------------------------------------------------------------------------- /linux_driver/spi-xilinx.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Xilinx SPI controller driver (master mode only) 3 | * 4 | * Author: MontaVista Software, Inc. 5 | * source@mvista.com 6 | * 7 | * Copyright (c) 2010 Secret Lab Technologies, Ltd. 8 | * Copyright (c) 2009 Intel Corporation 9 | * 2002-2007 (c) MontaVista Software, Inc. 10 | 11 | * This program is free software; you can redistribute it and/or modify 12 | * it under the terms of the GNU General Public License version 2 as 13 | * published by the Free Software Foundation. 14 | */ 15 | 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | 26 | #define XILINX_SPI_MAX_CS 32 27 | 28 | #define XILINX_SPI_NAME "xilinx_spi" 29 | 30 | #define XSPI_dummy_power_ctrl 0x00 31 | 32 | /* Register definitions as per "OPB Serial Peripheral Interface (SPI) (v1.00e) 33 | * Product Specification", DS464 34 | */ 35 | #define XSPI_CR_OFFSET 0x60 /* Control Register */ 36 | #define XSPI_CR_LOOP 0x01 37 | #define XSPI_CR_ENABLE 0x02 38 | #define XSPI_CR_MASTER_MODE 0x04 39 | #define XSPI_CR_CPOL 0x08 40 | #define XSPI_CR_CPHA 0x10 41 | #define XSPI_CR_MODE_MASK (XSPI_CR_CPHA | XSPI_CR_CPOL | \ 42 | XSPI_CR_LSB_FIRST | XSPI_CR_LOOP) 43 | #define XSPI_CR_TXFIFO_RESET 0x20 44 | #define XSPI_CR_RXFIFO_RESET 0x40 45 | #define XSPI_CR_MANUAL_SSELECT 0x80 46 | #define XSPI_CR_TRANS_INHIBIT 0x100 47 | #define XSPI_CR_LSB_FIRST 0x200 48 | 49 | #define XSPI_SR_OFFSET 0x64 /* Status Register */ 50 | 51 | #define XSPI_SR_RX_EMPTY_MASK 0x01 /* Receive FIFO is empty */ 52 | #define XSPI_SR_RX_FULL_MASK 0x02 /* Receive FIFO is full */ 53 | #define XSPI_SR_TX_EMPTY_MASK 0x04 /* Transmit FIFO is empty */ 54 | #define XSPI_SR_TX_FULL_MASK 0x08 /* Transmit FIFO is full */ 55 | #define XSPI_SR_MODE_FAULT_MASK 0x10 /* Mode fault error */ 56 | 57 | #define XSPI_TXD_OFFSET 0x68 /* Data Transmit Register */ 58 | #define XSPI_RXD_OFFSET 0x6c /* Data Receive Register */ 59 | 60 | #define XSPI_SSR_OFFSET 0x70 /* 32-bit Slave Select Register */ 61 | 62 | /* Register definitions as per "OPB IPIF (v3.01c) Product Specification", DS414 63 | * IPIF registers are 32 bit 64 | */ 65 | #define XIPIF_V123B_DGIER_OFFSET 0x1c /* IPIF global int enable reg */ 66 | #define XIPIF_V123B_GINTR_ENABLE 0x80000000 67 | 68 | #define XIPIF_V123B_IISR_OFFSET 0x20 /* IPIF interrupt status reg */ 69 | #define XIPIF_V123B_IIER_OFFSET 0x28 /* IPIF interrupt enable reg */ 70 | 71 | #define XSPI_INTR_MODE_FAULT 0x01 /* Mode fault error */ 72 | #define XSPI_INTR_SLAVE_MODE_FAULT 0x02 /* Selected as slave while 73 | * disabled */ 74 | #define XSPI_INTR_TX_EMPTY 0x04 /* TxFIFO is empty */ 75 | #define XSPI_INTR_TX_UNDERRUN 0x08 /* TxFIFO was underrun */ 76 | #define XSPI_INTR_RX_FULL 0x10 /* RxFIFO is full */ 77 | #define XSPI_INTR_RX_OVERRUN 0x20 /* RxFIFO was overrun */ 78 | #define XSPI_INTR_TX_HALF_EMPTY 0x40 /* TxFIFO is half empty */ 79 | 80 | #define XIPIF_V123B_RESETR_OFFSET 0x40 /* IPIF reset register */ 81 | #define XIPIF_V123B_RESET_MASK 0x0a /* the value to write */ 82 | 83 | struct xilinx_spi { 84 | /* bitbang has to be first */ 85 | struct spi_bitbang bitbang; 86 | struct completion done; 87 | void __iomem *regs; /* virt. address of the control registers */ 88 | 89 | int irq; 90 | 91 | u8 *rx_ptr; /* pointer in the Tx buffer */ 92 | const u8 *tx_ptr; /* pointer in the Rx buffer */ 93 | u8 bytes_per_word; 94 | int buffer_size; /* buffer size in words */ 95 | u32 cs_inactive; /* Level of the CS pins when inactive*/ 96 | unsigned int (*read_fn)(void __iomem *); 97 | void (*write_fn)(u32, void __iomem *); 98 | }; 99 | 100 | static void xspi_write32(u32 val, void __iomem *addr) 101 | { 102 | iowrite32(val, addr); 103 | } 104 | 105 | static unsigned int xspi_read32(void __iomem *addr) 106 | { 107 | return ioread32(addr); 108 | } 109 | 110 | static void xspi_write32_be(u32 val, void __iomem *addr) 111 | { 112 | iowrite32be(val, addr); 113 | } 114 | 115 | static unsigned int xspi_read32_be(void __iomem *addr) 116 | { 117 | return ioread32be(addr); 118 | } 119 | 120 | static void xilinx_spi_tx(struct xilinx_spi *xspi) 121 | { 122 | u32 data = 0; 123 | 124 | if (!xspi->tx_ptr) { 125 | xspi->write_fn(0, xspi->regs + XSPI_TXD_OFFSET); 126 | return; 127 | } 128 | 129 | switch (xspi->bytes_per_word) { 130 | case 1: 131 | data = *(u8 *)(xspi->tx_ptr); 132 | break; 133 | case 2: 134 | data = *(u16 *)(xspi->tx_ptr); 135 | break; 136 | case 4: 137 | data = *(u32 *)(xspi->tx_ptr); 138 | break; 139 | } 140 | 141 | xspi->write_fn(data, xspi->regs + XSPI_TXD_OFFSET); 142 | xspi->tx_ptr += xspi->bytes_per_word; 143 | } 144 | 145 | static void xilinx_spi_rx(struct xilinx_spi *xspi) 146 | { 147 | u32 data = xspi->read_fn(xspi->regs + XSPI_RXD_OFFSET); 148 | 149 | if (!xspi->rx_ptr) 150 | return; 151 | 152 | switch (xspi->bytes_per_word) { 153 | case 1: 154 | *(u8 *)(xspi->rx_ptr) = data; 155 | break; 156 | case 2: 157 | *(u16 *)(xspi->rx_ptr) = data; 158 | break; 159 | case 4: 160 | *(u32 *)(xspi->rx_ptr) = data; 161 | break; 162 | } 163 | 164 | xspi->rx_ptr += xspi->bytes_per_word; 165 | } 166 | 167 | static void xspi_init_hw(struct xilinx_spi *xspi) 168 | { 169 | void __iomem *regs_base = xspi->regs; 170 | 171 | // neutrino 2019 summer, power off the sd card 172 | xspi->write_fn(1, regs_base + XSPI_dummy_power_ctrl); 173 | // 174 | 175 | /* Reset the SPI device */ 176 | xspi->write_fn(XIPIF_V123B_RESET_MASK, 177 | regs_base + XIPIF_V123B_RESETR_OFFSET); 178 | /* Enable the transmit empty interrupt, which we use to determine 179 | * progress on the transmission. 180 | */ 181 | xspi->write_fn(XSPI_INTR_TX_EMPTY, 182 | regs_base + XIPIF_V123B_IIER_OFFSET); 183 | /* Disable the global IPIF interrupt */ 184 | xspi->write_fn(0, regs_base + XIPIF_V123B_DGIER_OFFSET); 185 | /* Deselect the slave on the SPI bus */ 186 | xspi->write_fn(0xffff, regs_base + XSPI_SSR_OFFSET); 187 | /* Disable the transmitter, enable Manual Slave Select Assertion, 188 | * put SPI controller into master mode, and enable it */ 189 | xspi->write_fn(XSPI_CR_MANUAL_SSELECT | XSPI_CR_MASTER_MODE | 190 | XSPI_CR_ENABLE | XSPI_CR_TXFIFO_RESET | XSPI_CR_RXFIFO_RESET, 191 | regs_base + XSPI_CR_OFFSET); 192 | 193 | // neutrino 2019 summer, power on the sd card 194 | xspi->write_fn(0, regs_base + XSPI_dummy_power_ctrl); 195 | // 196 | } 197 | 198 | static void xilinx_spi_chipselect(struct spi_device *spi, int is_on) 199 | { 200 | struct xilinx_spi *xspi = spi_master_get_devdata(spi->master); 201 | u16 cr; 202 | u32 cs; 203 | 204 | if (is_on == BITBANG_CS_INACTIVE) { 205 | /* Deselect the slave on the SPI bus */ 206 | xspi->write_fn(xspi->cs_inactive, xspi->regs + XSPI_SSR_OFFSET); 207 | return; 208 | } 209 | 210 | /* Set the SPI clock phase and polarity */ 211 | cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET) & ~XSPI_CR_MODE_MASK; 212 | if (spi->mode & SPI_CPHA) 213 | cr |= XSPI_CR_CPHA; 214 | if (spi->mode & SPI_CPOL) 215 | cr |= XSPI_CR_CPOL; 216 | if (spi->mode & SPI_LSB_FIRST) 217 | cr |= XSPI_CR_LSB_FIRST; 218 | if (spi->mode & SPI_LOOP) 219 | cr |= XSPI_CR_LOOP; 220 | xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET); 221 | 222 | /* We do not check spi->max_speed_hz here as the SPI clock 223 | * frequency is not software programmable (the IP block design 224 | * parameter) 225 | */ 226 | 227 | cs = xspi->cs_inactive; 228 | cs ^= BIT(spi->chip_select); 229 | 230 | /* Activate the chip select */ 231 | xspi->write_fn(cs, xspi->regs + XSPI_SSR_OFFSET); 232 | } 233 | 234 | /* spi_bitbang requires custom setup_transfer() to be defined if there is a 235 | * custom txrx_bufs(). 236 | */ 237 | static int xilinx_spi_setup_transfer(struct spi_device *spi, 238 | struct spi_transfer *t) 239 | { 240 | struct xilinx_spi *xspi = spi_master_get_devdata(spi->master); 241 | 242 | if (spi->mode & SPI_CS_HIGH) 243 | xspi->cs_inactive &= ~BIT(spi->chip_select); 244 | else 245 | xspi->cs_inactive |= BIT(spi->chip_select); 246 | 247 | return 0; 248 | } 249 | 250 | static int xilinx_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t) 251 | { 252 | struct xilinx_spi *xspi = spi_master_get_devdata(spi->master); 253 | int remaining_words; /* the number of words left to transfer */ 254 | bool use_irq = false; 255 | u16 cr = 0; 256 | 257 | /* We get here with transmitter inhibited */ 258 | 259 | xspi->tx_ptr = t->tx_buf; 260 | xspi->rx_ptr = t->rx_buf; 261 | remaining_words = t->len / xspi->bytes_per_word; 262 | 263 | if (xspi->irq >= 0 && remaining_words > xspi->buffer_size) { 264 | u32 isr; 265 | use_irq = true; 266 | /* Inhibit irq to avoid spurious irqs on tx_empty*/ 267 | cr = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET); 268 | xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT, 269 | xspi->regs + XSPI_CR_OFFSET); 270 | /* ACK old irqs (if any) */ 271 | isr = xspi->read_fn(xspi->regs + XIPIF_V123B_IISR_OFFSET); 272 | if (isr) 273 | xspi->write_fn(isr, 274 | xspi->regs + XIPIF_V123B_IISR_OFFSET); 275 | /* Enable the global IPIF interrupt */ 276 | xspi->write_fn(XIPIF_V123B_GINTR_ENABLE, 277 | xspi->regs + XIPIF_V123B_DGIER_OFFSET); 278 | reinit_completion(&xspi->done); 279 | } 280 | 281 | while (remaining_words) { 282 | int n_words, tx_words, rx_words; 283 | u32 sr; 284 | int stalled; 285 | 286 | n_words = min(remaining_words, xspi->buffer_size); 287 | 288 | tx_words = n_words; 289 | while (tx_words--) 290 | xilinx_spi_tx(xspi); 291 | 292 | /* Start the transfer by not inhibiting the transmitter any 293 | * longer 294 | */ 295 | 296 | if (use_irq) { 297 | xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET); 298 | wait_for_completion(&xspi->done); 299 | /* A transmit has just completed. Process received data 300 | * and check for more data to transmit. Always inhibit 301 | * the transmitter while the Isr refills the transmit 302 | * register/FIFO, or make sure it is stopped if we're 303 | * done. 304 | */ 305 | xspi->write_fn(cr | XSPI_CR_TRANS_INHIBIT, 306 | xspi->regs + XSPI_CR_OFFSET); 307 | sr = XSPI_SR_TX_EMPTY_MASK; 308 | } else 309 | sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET); 310 | 311 | /* Read out all the data from the Rx FIFO */ 312 | rx_words = n_words; 313 | stalled = 10; 314 | while (rx_words) { 315 | if (rx_words == n_words && !(stalled--) && 316 | !(sr & XSPI_SR_TX_EMPTY_MASK) && 317 | (sr & XSPI_SR_RX_EMPTY_MASK)) { 318 | dev_err(&spi->dev, 319 | "Detected stall. Check C_SPI_MODE and C_SPI_MEMORY\n"); 320 | xspi_init_hw(xspi); 321 | return -EIO; 322 | } 323 | 324 | if ((sr & XSPI_SR_TX_EMPTY_MASK) && (rx_words > 1)) { 325 | xilinx_spi_rx(xspi); 326 | rx_words--; 327 | continue; 328 | } 329 | 330 | sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET); 331 | if (!(sr & XSPI_SR_RX_EMPTY_MASK)) { 332 | xilinx_spi_rx(xspi); 333 | rx_words--; 334 | } 335 | } 336 | 337 | remaining_words -= n_words; 338 | } 339 | 340 | if (use_irq) { 341 | xspi->write_fn(0, xspi->regs + XIPIF_V123B_DGIER_OFFSET); 342 | xspi->write_fn(cr, xspi->regs + XSPI_CR_OFFSET); 343 | } 344 | 345 | return t->len; 346 | } 347 | 348 | 349 | /* This driver supports single master mode only. Hence Tx FIFO Empty 350 | * is the only interrupt we care about. 351 | * Receive FIFO Overrun, Transmit FIFO Underrun, Mode Fault, and Slave Mode 352 | * Fault are not to happen. 353 | */ 354 | static irqreturn_t xilinx_spi_irq(int irq, void *dev_id) 355 | { 356 | struct xilinx_spi *xspi = dev_id; 357 | u32 ipif_isr; 358 | 359 | /* Get the IPIF interrupts, and clear them immediately */ 360 | ipif_isr = xspi->read_fn(xspi->regs + XIPIF_V123B_IISR_OFFSET); 361 | xspi->write_fn(ipif_isr, xspi->regs + XIPIF_V123B_IISR_OFFSET); 362 | 363 | if (ipif_isr & XSPI_INTR_TX_EMPTY) { /* Transmission completed */ 364 | complete(&xspi->done); 365 | return IRQ_HANDLED; 366 | } 367 | 368 | return IRQ_NONE; 369 | } 370 | 371 | static int xilinx_spi_find_buffer_size(struct xilinx_spi *xspi) 372 | { 373 | u8 sr; 374 | int n_words = 0; 375 | 376 | /* 377 | * Before the buffer_size detection we reset the core 378 | * to make sure we start with a clean state. 379 | */ 380 | xspi->write_fn(XIPIF_V123B_RESET_MASK, 381 | xspi->regs + XIPIF_V123B_RESETR_OFFSET); 382 | 383 | /* Fill the Tx FIFO with as many words as possible */ 384 | do { 385 | xspi->write_fn(0, xspi->regs + XSPI_TXD_OFFSET); 386 | sr = xspi->read_fn(xspi->regs + XSPI_SR_OFFSET); 387 | n_words++; 388 | } while (!(sr & XSPI_SR_TX_FULL_MASK)); 389 | 390 | return n_words; 391 | } 392 | 393 | static const struct of_device_id xilinx_spi_of_match[] = { 394 | { .compatible = "xlnx,axi-quad-spi-1.00.a", }, 395 | { .compatible = "xlnx,xps-spi-2.00.a", }, 396 | { .compatible = "xlnx,xps-spi-2.00.b", }, 397 | {} 398 | }; 399 | MODULE_DEVICE_TABLE(of, xilinx_spi_of_match); 400 | 401 | static int xilinx_spi_probe(struct platform_device *pdev) 402 | { 403 | struct xilinx_spi *xspi; 404 | struct xspi_platform_data *pdata; 405 | struct resource *res; 406 | int ret, num_cs = 0, bits_per_word = 8; 407 | struct spi_master *master; 408 | u32 tmp; 409 | u8 i; 410 | 411 | pdata = dev_get_platdata(&pdev->dev); 412 | if (pdata) { 413 | num_cs = pdata->num_chipselect; 414 | bits_per_word = pdata->bits_per_word; 415 | } else { 416 | of_property_read_u32(pdev->dev.of_node, "xlnx,num-ss-bits", 417 | &num_cs); 418 | } 419 | 420 | if (!num_cs) { 421 | dev_err(&pdev->dev, 422 | "Missing slave select configuration data\n"); 423 | return -EINVAL; 424 | } 425 | 426 | if (num_cs > XILINX_SPI_MAX_CS) { 427 | dev_err(&pdev->dev, "Invalid number of spi slaves\n"); 428 | return -EINVAL; 429 | } 430 | 431 | master = spi_alloc_master(&pdev->dev, sizeof(struct xilinx_spi)); 432 | if (!master) 433 | return -ENODEV; 434 | 435 | /* the spi->mode bits understood by this driver: */ 436 | master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_LSB_FIRST | SPI_LOOP | 437 | SPI_CS_HIGH; 438 | 439 | xspi = spi_master_get_devdata(master); 440 | xspi->cs_inactive = 0xffffffff; 441 | xspi->bitbang.master = master; 442 | xspi->bitbang.chipselect = xilinx_spi_chipselect; 443 | xspi->bitbang.setup_transfer = xilinx_spi_setup_transfer; 444 | xspi->bitbang.txrx_bufs = xilinx_spi_txrx_bufs; 445 | init_completion(&xspi->done); 446 | 447 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 448 | xspi->regs = devm_ioremap_resource(&pdev->dev, res); 449 | if (IS_ERR(xspi->regs)) { 450 | ret = PTR_ERR(xspi->regs); 451 | goto put_master; 452 | } 453 | 454 | master->bus_num = pdev->id; 455 | master->num_chipselect = num_cs; 456 | master->dev.of_node = pdev->dev.of_node; 457 | 458 | /* 459 | * Detect endianess on the IP via loop bit in CR. Detection 460 | * must be done before reset is sent because incorrect reset 461 | * value generates error interrupt. 462 | * Setup little endian helper functions first and try to use them 463 | * and check if bit was correctly setup or not. 464 | */ 465 | xspi->read_fn = xspi_read32; 466 | xspi->write_fn = xspi_write32; 467 | 468 | xspi->write_fn(XSPI_CR_LOOP, xspi->regs + XSPI_CR_OFFSET); 469 | tmp = xspi->read_fn(xspi->regs + XSPI_CR_OFFSET); 470 | tmp &= XSPI_CR_LOOP; 471 | if (tmp != XSPI_CR_LOOP) { 472 | xspi->read_fn = xspi_read32_be; 473 | xspi->write_fn = xspi_write32_be; 474 | } 475 | 476 | master->bits_per_word_mask = SPI_BPW_MASK(bits_per_word); 477 | xspi->bytes_per_word = bits_per_word / 8; 478 | xspi->buffer_size = xilinx_spi_find_buffer_size(xspi); 479 | 480 | xspi->irq = platform_get_irq(pdev, 0); 481 | if (xspi->irq < 0 && xspi->irq != -ENXIO) { 482 | ret = xspi->irq; 483 | goto put_master; 484 | } else if (xspi->irq >= 0) { 485 | /* Register for SPI Interrupt */ 486 | ret = devm_request_irq(&pdev->dev, xspi->irq, xilinx_spi_irq, 0, 487 | dev_name(&pdev->dev), xspi); 488 | if (ret) 489 | goto put_master; 490 | } 491 | 492 | /* SPI controller initializations */ 493 | xspi_init_hw(xspi); 494 | 495 | ret = spi_bitbang_start(&xspi->bitbang); 496 | if (ret) { 497 | dev_err(&pdev->dev, "spi_bitbang_start FAILED\n"); 498 | goto put_master; 499 | } 500 | 501 | dev_info(&pdev->dev, "at 0x%08llX mapped to 0x%p, irq=%d\n", 502 | (unsigned long long)res->start, xspi->regs, xspi->irq); 503 | 504 | if (pdata) { 505 | for (i = 0; i < pdata->num_devices; i++) 506 | spi_new_device(master, pdata->devices + i); 507 | } 508 | 509 | platform_set_drvdata(pdev, master); 510 | return 0; 511 | 512 | put_master: 513 | spi_master_put(master); 514 | 515 | return ret; 516 | } 517 | 518 | static int xilinx_spi_remove(struct platform_device *pdev) 519 | { 520 | struct spi_master *master = platform_get_drvdata(pdev); 521 | struct xilinx_spi *xspi = spi_master_get_devdata(master); 522 | void __iomem *regs_base = xspi->regs; 523 | 524 | spi_bitbang_stop(&xspi->bitbang); 525 | 526 | /* Disable all the interrupts just in case */ 527 | xspi->write_fn(0, regs_base + XIPIF_V123B_IIER_OFFSET); 528 | /* Disable the global IPIF interrupt */ 529 | xspi->write_fn(0, regs_base + XIPIF_V123B_DGIER_OFFSET); 530 | 531 | // neutrino 2019 summer, power off the sd card 532 | xspi->write_fn(1, regs_base + XSPI_dummy_power_ctrl); 533 | // 534 | spi_master_put(xspi->bitbang.master); 535 | 536 | return 0; 537 | } 538 | 539 | /* work with hotplug and coldplug */ 540 | MODULE_ALIAS("platform:" XILINX_SPI_NAME); 541 | 542 | static struct platform_driver xilinx_spi_driver = { 543 | .probe = xilinx_spi_probe, 544 | .remove = xilinx_spi_remove, 545 | .driver = { 546 | .name = XILINX_SPI_NAME, 547 | .of_match_table = xilinx_spi_of_match, 548 | }, 549 | }; 550 | module_platform_driver(xilinx_spi_driver); 551 | 552 | MODULE_AUTHOR("MontaVista Software, Inc. "); 553 | MODULE_DESCRIPTION("Xilinx SPI driver"); 554 | MODULE_LICENSE("GPL"); 555 | -------------------------------------------------------------------------------- /pics/bigmap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cnrv/fpga-rocket-chip/29f62bd985f7002662c28a31a130a057812a422c/pics/bigmap.png -------------------------------------------------------------------------------- /pics/firmware.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cnrv/fpga-rocket-chip/29f62bd985f7002662c28a31a130a057812a422c/pics/firmware.png -------------------------------------------------------------------------------- /pics/jtag_pmod.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cnrv/fpga-rocket-chip/29f62bd985f7002662c28a31a130a057812a422c/pics/jtag_pmod.png -------------------------------------------------------------------------------- /pics/kernelconfig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cnrv/fpga-rocket-chip/29f62bd985f7002662c28a31a130a057812a422c/pics/kernelconfig.png -------------------------------------------------------------------------------- /pics/minicom.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cnrv/fpga-rocket-chip/29f62bd985f7002662c28a31a130a057812a422c/pics/minicom.png -------------------------------------------------------------------------------- /pics/pmod_pins.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cnrv/fpga-rocket-chip/29f62bd985f7002662c28a31a130a057812a422c/pics/pmod_pins.png -------------------------------------------------------------------------------- /pics/sdcard.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cnrv/fpga-rocket-chip/29f62bd985f7002662c28a31a130a057812a422c/pics/sdcard.png -------------------------------------------------------------------------------- /scripts/create_nexys4ddr_vivado_proj.tcl: -------------------------------------------------------------------------------- 1 | set mem_data_width {64} 2 | set io_data_width {32} 3 | set axi_id_width {8} 4 | 5 | set base_dir "." 6 | 7 | set project_name nexys4ddr 8 | set CONFIG DefaultNexys4DDRConfig 9 | 10 | # Set the directory path for the original project from where this script was exported 11 | set orig_proj_dir [file normalize $base_dir/$project_name] 12 | 13 | # Create project 14 | create_project $project_name $base_dir/$project_name 15 | 16 | # Set the directory path for the new project 17 | set proj_dir [get_property directory [current_project]] 18 | 19 | # Set project properties 20 | set obj [get_projects $project_name] 21 | set_property "default_lib" "xil_defaultlib" $obj 22 | set_property "part" "xc7a100tcsg324-1" $obj 23 | 24 | # Create 'sources_1' fileset (if not found) 25 | if {[string equal [get_filesets -quiet sources_1] ""]} { 26 | create_fileset -srcset sources_1 27 | } 28 | 29 | # Set 'sources_1' fileset object 30 | set files [list \ 31 | [file normalize $base_dir/verilog/utils/nasti_lite_bridge/nasti_request.vh ] \ 32 | [file normalize $base_dir/verilog/utils/nasti_lite_bridge/nasti_lite_writer.sv ] \ 33 | [file normalize $base_dir/verilog/utils/nasti_lite_bridge/nasti_lite_reader.sv ] \ 34 | [file normalize $base_dir/verilog/utils/nasti_lite_bridge/nasti_lite_bridge.sv ] \ 35 | [file normalize $base_dir/verilog/utils/plusarg_reader.v ] \ 36 | [file normalize $base_dir/verilog/utils/EICG_wrapper.v ] \ 37 | [file normalize $base_dir/verilog/utils/AsyncResetReg.v ] \ 38 | [file normalize $base_dir/verilog/utils/sram_modified.v ] \ 39 | [file normalize $base_dir/verilog/utils/narrower.v ] \ 40 | [file normalize $base_dir/verilog/peri/bram_storage.v ] \ 41 | [file normalize $base_dir/verilog/peri/uart.v ] \ 42 | [file normalize $base_dir/verilog/peri/spi.v ] \ 43 | [file normalize $base_dir/verilog/peri/bram.v ] \ 44 | [file normalize $base_dir/verilog/peri/DTModule.v ] \ 45 | [file normalize $base_dir/verilog/peri/JtagTunnel.v ] \ 46 | [file normalize $base_dir/verilog/AXIMmio.v ] \ 47 | [file normalize $base_dir/verilog/AXIMem.v ] \ 48 | [file normalize $base_dir/firmware/firmware.hex ] \ 49 | [file normalize $base_dir/verilog/chip_top.v ] \ 50 | [file normalize $base_dir/rocket-chip/vsim/generated-src/freechips.rocketchip.system.$CONFIG.v ] 51 | ] 52 | add_files -norecurse -fileset [get_filesets sources_1] $files 53 | set_property file_type {Memory File} [get_files $base_dir/firmware/firmware.hex ] 54 | 55 | # Set 'sources_1' fileset properties 56 | set_property "top" "chip_top" [get_filesets sources_1] 57 | 58 | # Clock generators 59 | create_ip -name clk_wiz -vendor xilinx.com -library ip -module_name clk_wiz_0 60 | set_property -dict [list \ 61 | CONFIG.PRIMITIVE {PLL} \ 62 | CONFIG.RESET_TYPE {ACTIVE_LOW} \ 63 | CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {50.000} \ 64 | CONFIG.CLKOUT1_DRIVES {BUFG} \ 65 | CONFIG.CLKOUT2_REQUESTED_OUT_FREQ {200.000} \ 66 | CONFIG.CLKOUT2_DRIVES {BUFG} \ 67 | CONFIG.CLKOUT2_USED {1}] \ 68 | [get_ips clk_wiz_0] 69 | generate_target {instantiation_template} [get_files $proj_dir/$project_name.srcs/sources_1/ip/clk_wiz_0/clk_wiz_0.xci] 70 | 71 | # AXI crossbar 72 | create_ip -name axi_crossbar -vendor xilinx.com -library ip -module_name axi_crossbar_0 73 | set_property -dict [list \ 74 | CONFIG.NUM_MI {3} \ 75 | CONFIG.DATA_WIDTH {64} \ 76 | CONFIG.ADDR_WIDTH {31} \ 77 | CONFIG.ID_WIDTH {4} \ 78 | CONFIG.M00_A00_BASE_ADDR {0x0000000060000000} \ 79 | CONFIG.M01_A00_BASE_ADDR {0x0000000060010000} \ 80 | CONFIG.M02_A00_BASE_ADDR {0x0000000060020000} \ 81 | CONFIG.M00_A00_ADDR_WIDTH {13} \ 82 | CONFIG.M01_A00_ADDR_WIDTH {16} \ 83 | CONFIG.M02_A00_ADDR_WIDTH {12} ] \ 84 | [get_ips axi_crossbar_0] 85 | 86 | #UART 87 | create_ip -name axi_uart16550 -vendor xilinx.com -library ip -module_name axi_uart16550_0 88 | set_property -dict [list \ 89 | CONFIG.UART_BOARD_INTERFACE {Custom} \ 90 | CONFIG.C_S_AXI_ACLK_FREQ_HZ_d {50} \ 91 | ] [get_ips axi_uart16550_0] 92 | generate_target {instantiation_template} \ 93 | [get_files $proj_dir/$project_name.srcs/sources_1/ip/axi_uart16550_0/axi_uart16550_0.xci] 94 | 95 | #BRAM Controller 96 | create_ip -name axi_bram_ctrl -vendor xilinx.com -library ip -module_name axi_bram_ctrl_0 97 | set_property -dict [list \ 98 | CONFIG.DATA_WIDTH 64 \ 99 | CONFIG.ID_WIDTH 4 \ 100 | CONFIG.MEM_DEPTH {8192} \ 101 | CONFIG.PROTOCOL {AXI4} \ 102 | CONFIG.BMG_INSTANCE {EXTERNAL} \ 103 | CONFIG.SINGLE_PORT_BRAM {1} \ 104 | CONFIG.SUPPORTS_NARROW_BURST {1} \ 105 | ] [get_ips axi_bram_ctrl_0] 106 | generate_target {instantiation_template} \ 107 | [get_files $proj_dir/$project_name.srcs/sources_1/ip/axi_bram_ctrl_0/axi_bram_ctrl_0.xci] 108 | 109 | # SPI interface for R/W SD card 110 | create_ip -name axi_quad_spi -vendor xilinx.com -library ip -module_name axi_quad_spi_0 111 | set_property -dict [list \ 112 | CONFIG.C_USE_STARTUP {0} \ 113 | CONFIG.C_SCK_RATIO {2} \ 114 | CONFIG.C_USE_STARTUP_INT {0}] \ 115 | [get_ips axi_quad_spi_0] 116 | 117 | # AXI clock converter due to the clock difference 118 | create_ip -name axi_clock_converter -vendor xilinx.com -library ip -module_name axi_clock_converter_0 119 | set_property -dict [list \ 120 | CONFIG.ADDR_WIDTH {32} \ 121 | CONFIG.DATA_WIDTH 64 \ 122 | CONFIG.ID_WIDTH 4 \ 123 | CONFIG.ACLK_ASYNC {1}] \ 124 | [get_ips axi_clock_converter_0] 125 | generate_target {instantiation_template} [get_files $proj_dir/$project_name.srcs/sources_1/ip/axi_clock_converter_0/axi_clock_converter_0.xci] 126 | 127 | # Memory Controller 128 | create_ip -name mig_7series -vendor xilinx.com -library ip -module_name mig_7series_0 129 | set_property CONFIG.XML_INPUT_FILE [file normalize $base_dir/scripts/$project_name.mig.prj] [get_ips mig_7series_0] 130 | generate_target {instantiation_template} \ 131 | [get_files $proj_dir/$project_name.srcs/sources_1/ip/mig_7series_0/mig_7series_0.xci] 132 | 133 | # Create 'constrs_1' fileset (if not found) 134 | if {[string equal [get_filesets -quiet constrs_1] ""]} { 135 | create_fileset -constrset constrs_1 136 | } 137 | 138 | # Set 'constrs_1' fileset object 139 | set obj [get_filesets constrs_1] 140 | 141 | # Add/Import constrs file and set constrs file properties 142 | set files [list [file normalize "$base_dir/constraints/$project_name.xdc"]] 143 | set file_added [add_files -norecurse -fileset $obj $files] 144 | 145 | # generate all IP source code 146 | generate_target all [get_ips] 147 | 148 | #some tweaking of optimizations 149 | 150 | set_property STEPS.SYNTH_DESIGN.ARGS.FANOUT_LIMIT 128 [get_runs synth_1] 151 | set_property STEPS.SYNTH_DESIGN.ARGS.RETIMING true [get_runs synth_1] 152 | set_property STEPS.SYNTH_DESIGN.ARGS.KEEP_EQUIVALENT_REGISTERS true [get_runs synth_1] 153 | 154 | set_property STEPS.OPT_DESIGN.TCL.PRE {} [get_runs impl_1] 155 | set_property STEPS.OPT_DESIGN.ARGS.DIRECTIVE ExploreWithRemap [get_runs impl_1] 156 | set_property STEPS.PLACE_DESIGN.ARGS.DIRECTIVE ExtraPostPlacementOpt [get_runs impl_1] 157 | set_property STEPS.POST_ROUTE_PHYS_OPT_DESIGN.ARGS.DIRECTIVE AggressiveExplore [get_runs impl_1] 158 | 159 | # force create the synth_1 path (need to make soft link in Makefile) 160 | launch_runs -scripts_only synth_1 161 | -------------------------------------------------------------------------------- /scripts/create_nexysvideo_vivado_proj.tcl: -------------------------------------------------------------------------------- 1 | set mem_data_width {64} 2 | set io_data_width {32} 3 | set axi_id_width {8} 4 | 5 | set base_dir "." 6 | 7 | set project_name nexysvideo 8 | set CONFIG DefaultNexysVideoConfig 9 | 10 | # Set the directory path for the original project from where this script was exported 11 | set orig_proj_dir [file normalize $base_dir/$project_name] 12 | 13 | # Create project 14 | create_project $project_name $base_dir/$project_name 15 | 16 | # Set the directory path for the new project 17 | set proj_dir [get_property directory [current_project]] 18 | 19 | # Set project properties 20 | set obj [get_projects $project_name] 21 | set_property "default_lib" "xil_defaultlib" $obj 22 | set_property "part" "xc7a200tsbg484-1" $obj 23 | 24 | # Create 'sources_1' fileset (if not found) 25 | if {[string equal [get_filesets -quiet sources_1] ""]} { 26 | create_fileset -srcset sources_1 27 | } 28 | 29 | # Set 'sources_1' fileset object 30 | set files [list \ 31 | [file normalize $base_dir/verilog/utils/nasti_lite_bridge/nasti_request.vh ] \ 32 | [file normalize $base_dir/verilog/utils/nasti_lite_bridge/nasti_lite_writer.sv ] \ 33 | [file normalize $base_dir/verilog/utils/nasti_lite_bridge/nasti_lite_reader.sv ] \ 34 | [file normalize $base_dir/verilog/utils/nasti_lite_bridge/nasti_lite_bridge.sv ] \ 35 | [file normalize $base_dir/verilog/utils/plusarg_reader.v ] \ 36 | [file normalize $base_dir/verilog/utils/EICG_wrapper.v ] \ 37 | [file normalize $base_dir/verilog/utils/AsyncResetReg.v ] \ 38 | [file normalize $base_dir/verilog/utils/sram_modified.v ] \ 39 | [file normalize $base_dir/verilog/utils/narrower.v ] \ 40 | [file normalize $base_dir/verilog/peri/bram_storage.v ] \ 41 | [file normalize $base_dir/verilog/peri/uart.v ] \ 42 | [file normalize $base_dir/verilog/peri/spi.v ] \ 43 | [file normalize $base_dir/verilog/peri/bram.v ] \ 44 | [file normalize $base_dir/verilog/peri/DTModule.v ] \ 45 | [file normalize $base_dir/verilog/peri/JtagTunnel.v ] \ 46 | [file normalize $base_dir/verilog/AXIMmio.v ] \ 47 | [file normalize $base_dir/verilog/AXIMem.v ] \ 48 | [file normalize $base_dir/firmware/firmware.hex ] \ 49 | [file normalize $base_dir/verilog/chip_top.v ] \ 50 | [file normalize $base_dir/rocket-chip/vsim/generated-src/freechips.rocketchip.system.$CONFIG.v ] 51 | ] 52 | add_files -norecurse -fileset [get_filesets sources_1] $files 53 | set_property file_type {Memory File} [get_files $base_dir/firmware/firmware.hex ] 54 | 55 | set_property verilog_define [list BOARD_NEXYS_VIDEO] [get_filesets sources_1] 56 | 57 | # Set 'sources_1' fileset properties 58 | set_property "top" "chip_top" [get_filesets sources_1] 59 | 60 | # Clock generators 61 | create_ip -name clk_wiz -vendor xilinx.com -library ip -module_name clk_wiz_0 62 | set_property -dict [list \ 63 | CONFIG.PRIMITIVE {PLL} \ 64 | CONFIG.RESET_TYPE {ACTIVE_LOW} \ 65 | CONFIG.CLKOUT1_REQUESTED_OUT_FREQ {50.000} \ 66 | CONFIG.CLKOUT1_DRIVES {BUFG} \ 67 | CONFIG.CLKOUT2_REQUESTED_OUT_FREQ {200.000} \ 68 | CONFIG.CLKOUT2_DRIVES {BUFG} \ 69 | CONFIG.CLKOUT2_USED {1}] \ 70 | [get_ips clk_wiz_0] 71 | generate_target {instantiation_template} [get_files $proj_dir/$project_name.srcs/sources_1/ip/clk_wiz_0/clk_wiz_0.xci] 72 | 73 | # AXI crossbar 74 | create_ip -name axi_crossbar -vendor xilinx.com -library ip -module_name axi_crossbar_0 75 | set_property -dict [list \ 76 | CONFIG.NUM_MI {3} \ 77 | CONFIG.DATA_WIDTH {64} \ 78 | CONFIG.ADDR_WIDTH {31} \ 79 | CONFIG.ID_WIDTH {4} \ 80 | CONFIG.M00_A00_BASE_ADDR {0x0000000060000000} \ 81 | CONFIG.M01_A00_BASE_ADDR {0x0000000060010000} \ 82 | CONFIG.M02_A00_BASE_ADDR {0x0000000060020000} \ 83 | CONFIG.M00_A00_ADDR_WIDTH {13} \ 84 | CONFIG.M01_A00_ADDR_WIDTH {16} \ 85 | CONFIG.M02_A00_ADDR_WIDTH {12} ] \ 86 | [get_ips axi_crossbar_0] 87 | 88 | #UART 89 | create_ip -name axi_uart16550 -vendor xilinx.com -library ip -module_name axi_uart16550_0 90 | set_property -dict [list \ 91 | CONFIG.UART_BOARD_INTERFACE {Custom} \ 92 | CONFIG.C_S_AXI_ACLK_FREQ_HZ_d {50} \ 93 | ] [get_ips axi_uart16550_0] 94 | generate_target {instantiation_template} \ 95 | [get_files $proj_dir/$project_name.srcs/sources_1/ip/axi_uart16550_0/axi_uart16550_0.xci] 96 | 97 | #BRAM Controller 98 | create_ip -name axi_bram_ctrl -vendor xilinx.com -library ip -module_name axi_bram_ctrl_0 99 | set_property -dict [list \ 100 | CONFIG.DATA_WIDTH 64 \ 101 | CONFIG.ID_WIDTH 4 \ 102 | CONFIG.MEM_DEPTH {8192} \ 103 | CONFIG.PROTOCOL {AXI4} \ 104 | CONFIG.BMG_INSTANCE {EXTERNAL} \ 105 | CONFIG.SINGLE_PORT_BRAM {1} \ 106 | CONFIG.SUPPORTS_NARROW_BURST {1} \ 107 | ] [get_ips axi_bram_ctrl_0] 108 | generate_target {instantiation_template} \ 109 | [get_files $proj_dir/$project_name.srcs/sources_1/ip/axi_bram_ctrl_0/axi_bram_ctrl_0.xci] 110 | 111 | # SPI interface for R/W SD card 112 | create_ip -name axi_quad_spi -vendor xilinx.com -library ip -module_name axi_quad_spi_0 113 | set_property -dict [list \ 114 | CONFIG.C_USE_STARTUP {0} \ 115 | CONFIG.C_SCK_RATIO {2} \ 116 | CONFIG.C_USE_STARTUP_INT {0}] \ 117 | [get_ips axi_quad_spi_0] 118 | 119 | # AXI clock converter due to the clock difference 120 | create_ip -name axi_clock_converter -vendor xilinx.com -library ip -module_name axi_clock_converter_0 121 | set_property -dict [list \ 122 | CONFIG.ADDR_WIDTH {32} \ 123 | CONFIG.DATA_WIDTH 64 \ 124 | CONFIG.ID_WIDTH 4 \ 125 | CONFIG.ACLK_ASYNC {1}] \ 126 | [get_ips axi_clock_converter_0] 127 | generate_target {instantiation_template} [get_files $proj_dir/$project_name.srcs/sources_1/ip/axi_clock_converter_0/axi_clock_converter_0.xci] 128 | 129 | # Memory Controller 130 | create_ip -name mig_7series -vendor xilinx.com -library ip -module_name mig_7series_0 131 | set_property CONFIG.XML_INPUT_FILE [file normalize $base_dir/scripts/$project_name.mig.prj] [get_ips mig_7series_0] 132 | generate_target {instantiation_template} \ 133 | [get_files $proj_dir/$project_name.srcs/sources_1/ip/mig_7series_0/mig_7series_0.xci] 134 | 135 | # Create 'constrs_1' fileset (if not found) 136 | if {[string equal [get_filesets -quiet constrs_1] ""]} { 137 | create_fileset -constrset constrs_1 138 | } 139 | 140 | # Set 'constrs_1' fileset object 141 | set obj [get_filesets constrs_1] 142 | 143 | # Add/Import constrs file and set constrs file properties 144 | set files [list [file normalize "$base_dir/constraints/$project_name.xdc"]] 145 | set file_added [add_files -norecurse -fileset $obj $files] 146 | 147 | # generate all IP source code 148 | generate_target all [get_ips] 149 | 150 | #some tweaking of optimizations 151 | 152 | set_property STEPS.SYNTH_DESIGN.ARGS.FANOUT_LIMIT 128 [get_runs synth_1] 153 | set_property STEPS.SYNTH_DESIGN.ARGS.RETIMING true [get_runs synth_1] 154 | set_property STEPS.SYNTH_DESIGN.ARGS.KEEP_EQUIVALENT_REGISTERS true [get_runs synth_1] 155 | 156 | set_property STEPS.OPT_DESIGN.TCL.PRE {} [get_runs impl_1] 157 | set_property STEPS.OPT_DESIGN.ARGS.DIRECTIVE ExploreWithRemap [get_runs impl_1] 158 | set_property STEPS.PLACE_DESIGN.ARGS.DIRECTIVE ExtraPostPlacementOpt [get_runs impl_1] 159 | set_property STEPS.POST_ROUTE_PHYS_OPT_DESIGN.ARGS.DIRECTIVE AggressiveExplore [get_runs impl_1] 160 | 161 | # force create the synth_1 path (need to make soft link in Makefile) 162 | launch_runs -scripts_only synth_1 163 | -------------------------------------------------------------------------------- /scripts/nexys4ddr.mig.prj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | mig_7series_0 5 | 6 | 1 7 | 8 | 1 9 | 10 | OFF 11 | 12 | 1024 13 | 14 | OFF 15 | 16 | Disabled 17 | 18 | xc7a100t-csg324/-1 19 | 20 | 4.2 21 | 22 | No Buffer 23 | 24 | Use System Clock 25 | 26 | ACTIVE HIGH 27 | 28 | FALSE 29 | 30 | 1 31 | 32 | 50 Ohms 33 | 34 | 0 35 | 36 | 37 | 7a/xc7a100ti-csg324 38 | 39 | 40 | 41 | DDR2_SDRAM/Components/MT47H64M16HR-25E 42 | 5000 43 | 1.8V 44 | 4:1 45 | 200 46 | 0 47 | 1200 48 | 1.000 49 | 1 50 | 1 51 | 1 52 | 1 53 | 16 54 | 1 55 | 1 56 | Disabled 57 | Normal 58 | 4 59 | FALSE 60 | 61 | 13 62 | 10 63 | 3 64 | BANK_ROW_COLUMN 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 8 122 | Sequential 123 | 3 124 | Normal 125 | No 126 | Fast exit 127 | 3 128 | Enable-Normal 129 | Fullstrength 130 | Enable 131 | 1 132 | 50ohms 133 | 0 134 | OCD Exit 135 | Enable 136 | Disable 137 | Enable 138 | AXI 139 | 140 | RD_PRI_REG 141 | 27 142 | 64 143 | 4 144 | 0 145 | 146 | 147 | 148 | 149 | -------------------------------------------------------------------------------- /scripts/nexysvideo.mig.prj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | mig_7series_0 5 | 1 6 | 1 7 | OFF 8 | 1024 9 | OFF 10 | Enabled 11 | xc7a200t-sbg484/-1 12 | 4.0 13 | No Buffer 14 | Use System Clock 15 | ACTIVE HIGH 16 | FALSE 17 | 1 18 | 50 Ohms 19 | 0 20 | 21 | 7a/xc7a200ti-sbg484 22 | 23 | 24 | DDR3_SDRAM/Components/MT41K256M16XX-125 25 | 2500 26 | 1.8V 27 | 4:1 28 | 200 29 | 0 30 | 800 31 | 1.000 32 | 1 33 | 1 34 | 1 35 | 1 36 | 16 37 | 1 38 | 1 39 | Disabled 40 | Normal 41 | 4 42 | FALSE 43 | 44 | 15 45 | 10 46 | 3 47 | 1.5V 48 | BANK_ROW_COLUMN 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 8 - Fixed 108 | Sequential 109 | 6 110 | Normal 111 | No 112 | Slow Exit 113 | Enable 114 | RZQ/6 115 | Disable 116 | Disable 117 | RZQ/6 118 | 0 119 | Disabled 120 | Enabled 121 | Output Buffer Enabled 122 | Full Array 123 | 5 124 | Enabled 125 | Normal 126 | Dynamic ODT off 127 | AXI 128 | 129 | RD_PRI_REG 130 | 29 131 | 64 132 | 4 133 | 0 134 | 135 | 136 | 137 | 138 | -------------------------------------------------------------------------------- /verilog/AXIMem.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | `define DDR_MASK 32'h7fff_ffff 3 | 4 | module AXIMem ( 5 | input clock, 6 | input clock200, // 200m Hz to drive DDR ctrl 7 | input reset, 8 | 9 | output io_axi4_0_aw_ready, 10 | input io_axi4_0_aw_valid, 11 | input [3:0] io_axi4_0_aw_id, 12 | input [31:0] io_axi4_0_aw_addr, 13 | input [7:0] io_axi4_0_aw_len, 14 | input [2:0] io_axi4_0_aw_size, 15 | input [1:0] io_axi4_0_aw_burst, 16 | 17 | input io_axi4_0_aw_lock, 18 | input [3:0] io_axi4_0_aw_cache, 19 | input [2:0] io_axi4_0_aw_prot, 20 | input [3:0] io_axi4_0_aw_qos, 21 | 22 | output io_axi4_0_w_ready, 23 | input io_axi4_0_w_valid, 24 | input [63:0] io_axi4_0_w_data, 25 | input [7:0] io_axi4_0_w_strb, 26 | input io_axi4_0_w_last, 27 | input io_axi4_0_b_ready, 28 | output io_axi4_0_b_valid, 29 | output [3:0] io_axi4_0_b_id, 30 | output [1:0] io_axi4_0_b_resp, 31 | output io_axi4_0_ar_ready, 32 | input io_axi4_0_ar_valid, 33 | input [3:0] io_axi4_0_ar_id, 34 | input [31:0] io_axi4_0_ar_addr, 35 | input [7:0] io_axi4_0_ar_len, 36 | input [2:0] io_axi4_0_ar_size, 37 | input [1:0] io_axi4_0_ar_burst, 38 | 39 | input io_axi4_0_ar_lock, 40 | input [3:0] io_axi4_0_ar_cache, 41 | input [2:0] io_axi4_0_ar_prot, 42 | input [3:0] io_axi4_0_ar_qos, 43 | 44 | input io_axi4_0_r_ready, 45 | output io_axi4_0_r_valid, 46 | output [3:0] io_axi4_0_r_id, 47 | output [63:0] io_axi4_0_r_data, 48 | output [1:0] io_axi4_0_r_resp, 49 | output io_axi4_0_r_last, 50 | 51 | //----DDR pins 52 | inout [15:0] ddr_dq, 53 | inout [1:0] ddr_dqs_n, 54 | inout [1:0] ddr_dqs_p, 55 | output [14:0] ddr_addr, 56 | output [2:0] ddr_ba, 57 | output ddr_ras_n, 58 | output ddr_cas_n, 59 | output ddr_we_n, 60 | output ddr_reset_n, // nexys-video 61 | output ddr_ck_n, 62 | output ddr_ck_p, 63 | output ddr_cke, 64 | output ddr_cs_n, // nexys4-ddr 65 | output [1:0] ddr_dm, 66 | output ddr_odt 67 | 68 | // //for debug 69 | // output s_ar_ready, 70 | // output s_aw_ready, 71 | // output s_w_ready, 72 | // output s_b_valid, 73 | // output s_r_valid, 74 | // output init_fin 75 | ); 76 | 77 | wire resetn; 78 | assign resetn = ! reset; 79 | wire mig_ui_clk; 80 | wire mig_ui_rst; 81 | wire mig_ui_rstn; 82 | assign mig_ui_rstn = ! mig_ui_rst; 83 | 84 | wire [3:0] mig_axi4_aw_id; 85 | wire [31:0] mig_axi4_aw_addr; 86 | wire [7:0] mig_axi4_aw_len; 87 | wire [2:0] mig_axi4_aw_size; 88 | wire [1:0] mig_axi4_aw_burst; 89 | wire [0:0] mig_axi4_aw_lock; 90 | wire [3:0] mig_axi4_aw_cache; 91 | wire [2:0] mig_axi4_aw_prot; 92 | wire [3:0] mig_axi4_aw_qos; 93 | wire mig_axi4_aw_valid; 94 | wire mig_axi4_aw_ready; 95 | wire [63:0] mig_axi4_w_data; 96 | wire [7:0] mig_axi4_w_strb; 97 | wire mig_axi4_w_last; 98 | wire mig_axi4_w_valid; 99 | wire mig_axi4_w_ready; 100 | wire mig_axi4_b_ready; 101 | wire [3:0] mig_axi4_b_id; 102 | wire [1:0] mig_axi4_b_resp; 103 | wire mig_axi4_b_valid; 104 | wire [3:0] mig_axi4_ar_id; 105 | wire [31:0] mig_axi4_ar_addr; 106 | wire [7:0] mig_axi4_ar_len; 107 | wire [2:0] mig_axi4_ar_size; 108 | wire [1:0] mig_axi4_ar_burst; 109 | wire [0:0] mig_axi4_ar_lock; 110 | wire [3:0] mig_axi4_ar_cache; 111 | wire [2:0] mig_axi4_ar_prot; 112 | wire [3:0] mig_axi4_ar_qos; 113 | wire mig_axi4_ar_valid; 114 | wire mig_axi4_ar_ready; 115 | wire mig_axi4_r_ready; 116 | wire [3:0] mig_axi4_r_id; 117 | wire [63:0] mig_axi4_r_data; 118 | wire [1:0] mig_axi4_r_resp; 119 | wire mig_axi4_r_last; 120 | wire mig_axi4_r_valid; 121 | 122 | wire [31:0] io_axi4_0_aw_addr_shrink; 123 | wire [31:0] io_axi4_0_ar_addr_shrink; 124 | assign io_axi4_0_aw_addr_shrink = io_axi4_0_aw_addr[31:0] & `DDR_MASK; 125 | assign io_axi4_0_ar_addr_shrink = io_axi4_0_ar_addr[31:0] & `DDR_MASK; 126 | 127 | axi_clock_converter_0 clk_conv( 128 | 129 | .s_axi_aclk ( clock ), // rocket -> Freq converter -> DDR 130 | .s_axi_aresetn ( resetn ), 131 | 132 | .m_axi_aclk ( mig_ui_clk ), // the reference freq from DDR controller 133 | .m_axi_aresetn ( mig_ui_rstn ), 134 | 135 | .s_axi_awid ( io_axi4_0_aw_id ), 136 | .s_axi_awaddr ( io_axi4_0_aw_addr_shrink ), 137 | .s_axi_awlen ( io_axi4_0_aw_len ), 138 | .s_axi_awsize ( io_axi4_0_aw_size ), 139 | .s_axi_awburst ( io_axi4_0_aw_burst ), 140 | .s_axi_awlock ( io_axi4_0_aw_lock ), 141 | .s_axi_awcache ( io_axi4_0_aw_cache ), 142 | .s_axi_awprot ( io_axi4_0_aw_prot ), 143 | .s_axi_awqos ( io_axi4_0_aw_qos ), 144 | // .s_axi_awregion ( io_axi4_0_aw_region ), 145 | .s_axi_awvalid ( io_axi4_0_aw_valid ), 146 | .s_axi_awready ( io_axi4_0_aw_ready ), 147 | .s_axi_wdata ( io_axi4_0_w_data ), 148 | .s_axi_wstrb ( io_axi4_0_w_strb ), 149 | .s_axi_wlast ( io_axi4_0_w_last ), 150 | .s_axi_wvalid ( io_axi4_0_w_valid ), 151 | .s_axi_wready ( io_axi4_0_w_ready ), 152 | .s_axi_bid ( io_axi4_0_b_id ), 153 | .s_axi_bresp ( io_axi4_0_b_resp ), 154 | .s_axi_bvalid ( io_axi4_0_b_valid ), 155 | .s_axi_bready ( io_axi4_0_b_ready ), 156 | .s_axi_arid ( io_axi4_0_ar_id ), 157 | .s_axi_araddr ( io_axi4_0_ar_addr_shrink ), 158 | .s_axi_arlen ( io_axi4_0_ar_len ), 159 | .s_axi_arsize ( io_axi4_0_ar_size ), 160 | .s_axi_arburst ( io_axi4_0_ar_burst ), 161 | .s_axi_arlock ( io_axi4_0_ar_lock ), 162 | .s_axi_arcache ( io_axi4_0_ar_cache ), 163 | .s_axi_arprot ( io_axi4_0_ar_prot ), 164 | .s_axi_arqos ( io_axi4_0_ar_qos ), 165 | // .s_axi_arregion ( io_axi4_0_ar_region ), 166 | .s_axi_arvalid ( io_axi4_0_ar_valid ), 167 | .s_axi_arready ( io_axi4_0_ar_ready ), 168 | .s_axi_rid ( io_axi4_0_r_id ), 169 | .s_axi_rdata ( io_axi4_0_r_data ), 170 | .s_axi_rresp ( io_axi4_0_r_resp ), 171 | .s_axi_rlast ( io_axi4_0_r_last ), 172 | .s_axi_rvalid ( io_axi4_0_r_valid ), 173 | .s_axi_rready ( io_axi4_0_r_ready ), 174 | 175 | .m_axi_awid ( mig_axi4_aw_id ), 176 | .m_axi_awaddr ( mig_axi4_aw_addr ), 177 | .m_axi_awlen ( mig_axi4_aw_len ), 178 | .m_axi_awsize ( mig_axi4_aw_size ), 179 | .m_axi_awburst ( mig_axi4_aw_burst ), 180 | .m_axi_awlock ( mig_axi4_aw_lock ), 181 | .m_axi_awcache ( mig_axi4_aw_cache ), 182 | .m_axi_awprot ( mig_axi4_aw_prot ), 183 | .m_axi_awqos ( mig_axi4_aw_qos ), 184 | // .m_axi_awregion ( mig_axi4_aw_region ), 185 | .m_axi_awvalid ( mig_axi4_aw_valid ), 186 | .m_axi_awready ( mig_axi4_aw_ready ), 187 | .m_axi_wdata ( mig_axi4_w_data ), 188 | .m_axi_wstrb ( mig_axi4_w_strb ), 189 | .m_axi_wlast ( mig_axi4_w_last ), 190 | .m_axi_wvalid ( mig_axi4_w_valid ), 191 | .m_axi_wready ( mig_axi4_w_ready ), 192 | .m_axi_bid ( mig_axi4_b_id ), 193 | .m_axi_bresp ( mig_axi4_b_resp ), 194 | .m_axi_bvalid ( mig_axi4_b_valid ), 195 | .m_axi_bready ( mig_axi4_b_ready ), 196 | .m_axi_arid ( mig_axi4_ar_id ), 197 | .m_axi_araddr ( mig_axi4_ar_addr ), 198 | .m_axi_arlen ( mig_axi4_ar_len ), 199 | .m_axi_arsize ( mig_axi4_ar_size ), 200 | .m_axi_arburst ( mig_axi4_ar_burst ), 201 | .m_axi_arlock ( mig_axi4_ar_lock ), 202 | .m_axi_arcache ( mig_axi4_ar_cache ), 203 | .m_axi_arprot ( mig_axi4_ar_prot ), 204 | .m_axi_arqos ( mig_axi4_ar_qos ), 205 | // .m_axi_arregion ( mig_axi4_ar_region ), 206 | .m_axi_arvalid ( mig_axi4_ar_valid ), 207 | .m_axi_arready ( mig_axi4_ar_ready ), 208 | .m_axi_rid ( mig_axi4_r_id ), 209 | .m_axi_rdata ( mig_axi4_r_data ), 210 | .m_axi_rresp ( mig_axi4_r_resp ), 211 | .m_axi_rlast ( mig_axi4_r_last ), 212 | .m_axi_rvalid ( mig_axi4_r_valid ), 213 | .m_axi_rready ( mig_axi4_r_ready ) 214 | ); 215 | 216 | `ifdef BOARD_NEXYS_VIDEO 217 | mig_7series_0 DDR_ctrl( 218 | .ddr3_dq ( ddr_dq ), 219 | .ddr3_dqs_n ( ddr_dqs_n ), 220 | .ddr3_dqs_p ( ddr_dqs_p ), 221 | .ddr3_addr ( ddr_addr ), 222 | .ddr3_ba ( ddr_ba ), 223 | .ddr3_ras_n ( ddr_ras_n ), 224 | .ddr3_cas_n ( ddr_cas_n ), 225 | .ddr3_we_n ( ddr_we_n ), 226 | .ddr3_ck_p ( ddr_ck_p ), 227 | .ddr3_ck_n ( ddr_ck_n ), 228 | .ddr3_cke ( ddr_cke ), 229 | .ddr3_reset_n ( ddr_reset_n ), 230 | .ddr3_dm ( ddr_dm ), 231 | .ddr3_odt ( ddr_odt ), 232 | 233 | .sys_clk_i ( clock200 ), 234 | .sys_rst ( reset ), 235 | 236 | .app_sr_req ( 1'b0 ), // ddr control bits, all should be zero 237 | .app_ref_req ( 1'b0 ), // 238 | .app_zq_req ( 1'b0 ), 239 | 240 | .ui_clk ( mig_ui_clk ), // output clk - for clk converter 241 | .ui_clk_sync_rst( mig_ui_rst ), // output reset 242 | //.mmcm_locked ( mmcm_locked ), 243 | 244 | // axi interface with much higher freq 245 | .aresetn ( resetn ), // 246 | .s_axi_awid ( mig_axi4_aw_id ), 247 | .s_axi_awaddr ( mig_axi4_aw_addr ), 248 | .s_axi_awlen ( mig_axi4_aw_len ), 249 | .s_axi_awsize ( mig_axi4_aw_size ), 250 | .s_axi_awburst ( mig_axi4_aw_burst ), 251 | .s_axi_awlock ( mig_axi4_aw_lock ),//should be grounded 252 | .s_axi_awcache ( mig_axi4_aw_cache ), 253 | .s_axi_awprot ( mig_axi4_aw_prot ), 254 | .s_axi_awqos ( mig_axi4_aw_qos ), 255 | .s_axi_awvalid ( mig_axi4_aw_valid ), 256 | .s_axi_awready ( mig_axi4_aw_ready ), 257 | .s_axi_wdata ( mig_axi4_w_data ), 258 | .s_axi_wstrb ( mig_axi4_w_strb ), 259 | .s_axi_wlast ( mig_axi4_w_last ), 260 | .s_axi_wvalid ( mig_axi4_w_valid ), 261 | .s_axi_wready ( mig_axi4_w_ready ), 262 | .s_axi_bid ( mig_axi4_b_id ), 263 | .s_axi_bresp ( mig_axi4_b_resp ), 264 | .s_axi_bvalid ( mig_axi4_b_valid ), 265 | .s_axi_bready ( mig_axi4_b_ready ), 266 | .s_axi_arid ( mig_axi4_ar_id ), 267 | .s_axi_araddr ( mig_axi4_ar_addr ), 268 | .s_axi_arlen ( mig_axi4_ar_len ), 269 | .s_axi_arsize ( mig_axi4_ar_size ), 270 | .s_axi_arburst ( mig_axi4_ar_burst ), 271 | .s_axi_arlock ( mig_axi4_ar_lock ), 272 | .s_axi_arcache ( mig_axi4_ar_cache ), 273 | .s_axi_arprot ( mig_axi4_ar_prot ), 274 | .s_axi_arqos ( mig_axi4_ar_qos ), 275 | .s_axi_arvalid ( mig_axi4_ar_valid ), 276 | .s_axi_arready ( mig_axi4_ar_ready ), 277 | .s_axi_rid ( mig_axi4_r_id ), 278 | .s_axi_rdata ( mig_axi4_r_data ), 279 | .s_axi_rresp ( mig_axi4_r_resp ), 280 | .s_axi_rlast ( mig_axi4_r_last ), 281 | .s_axi_rvalid ( mig_axi4_r_valid ), 282 | .s_axi_rready ( mig_axi4_r_ready ), 283 | 284 | .init_calib_complete (init_fin) 285 | ); 286 | `else 287 | // DDR controller 288 | mig_7series_0 DDR_ctrl( 289 | 290 | // device pins 291 | .ddr2_dq ( ddr_dq ), 292 | .ddr2_dqs_n ( ddr_dqs_n ), 293 | .ddr2_dqs_p ( ddr_dqs_p ), 294 | .ddr2_addr ( ddr_addr ), 295 | .ddr2_ba ( ddr_ba ), 296 | .ddr2_ras_n ( ddr_ras_n ), 297 | .ddr2_cas_n ( ddr_cas_n ), 298 | .ddr2_we_n ( ddr_we_n ), 299 | .ddr2_ck_p ( ddr_ck_p ), 300 | .ddr2_ck_n ( ddr_ck_n ), 301 | .ddr2_cke ( ddr_cke ), 302 | .ddr2_cs_n ( ddr_cs_n ), 303 | .ddr2_dm ( ddr_dm ), 304 | .ddr2_odt ( ddr_odt ), 305 | 306 | .sys_clk_i ( clock200 ), 307 | .sys_rst ( reset ), 308 | 309 | .device_temp_i ( 0 ), // we do not need XADC just ground it 310 | .app_sr_req ( 1'b0 ), // ddr control bits, all should be zero 311 | .app_ref_req ( 1'b0 ), // 312 | .app_zq_req ( 1'b0 ), 313 | 314 | .ui_clk ( mig_ui_clk ), // output clk - for clk converter 315 | .ui_clk_sync_rst( mig_ui_rst ), // output reset 316 | //.mmcm_locked ( mmcm_locked ), 317 | 318 | // axi interface with much higher freq 319 | .aresetn ( resetn ), // 320 | .s_axi_awid ( mig_axi4_aw_id ), 321 | .s_axi_awaddr ( mig_axi4_aw_addr ), 322 | .s_axi_awlen ( mig_axi4_aw_len ), 323 | .s_axi_awsize ( mig_axi4_aw_size ), 324 | .s_axi_awburst ( mig_axi4_aw_burst ), 325 | .s_axi_awlock ( mig_axi4_aw_lock ),//should be grounded 326 | .s_axi_awcache ( mig_axi4_aw_cache ), 327 | .s_axi_awprot ( mig_axi4_aw_prot ), 328 | .s_axi_awqos ( mig_axi4_aw_qos ), 329 | .s_axi_awvalid ( mig_axi4_aw_valid ), 330 | .s_axi_awready ( mig_axi4_aw_ready ), 331 | .s_axi_wdata ( mig_axi4_w_data ), 332 | .s_axi_wstrb ( mig_axi4_w_strb ), 333 | .s_axi_wlast ( mig_axi4_w_last ), 334 | .s_axi_wvalid ( mig_axi4_w_valid ), 335 | .s_axi_wready ( mig_axi4_w_ready ), 336 | .s_axi_bid ( mig_axi4_b_id ), 337 | .s_axi_bresp ( mig_axi4_b_resp ), 338 | .s_axi_bvalid ( mig_axi4_b_valid ), 339 | .s_axi_bready ( mig_axi4_b_ready ), 340 | .s_axi_arid ( mig_axi4_ar_id ), 341 | .s_axi_araddr ( mig_axi4_ar_addr ), 342 | .s_axi_arlen ( mig_axi4_ar_len ), 343 | .s_axi_arsize ( mig_axi4_ar_size ), 344 | .s_axi_arburst ( mig_axi4_ar_burst ), 345 | .s_axi_arlock ( mig_axi4_ar_lock ), 346 | .s_axi_arcache ( mig_axi4_ar_cache ), 347 | .s_axi_arprot ( mig_axi4_ar_prot ), 348 | .s_axi_arqos ( mig_axi4_ar_qos ), 349 | .s_axi_arvalid ( mig_axi4_ar_valid ), 350 | .s_axi_arready ( mig_axi4_ar_ready ), 351 | .s_axi_rid ( mig_axi4_r_id ), 352 | .s_axi_rdata ( mig_axi4_r_data ), 353 | .s_axi_rresp ( mig_axi4_r_resp ), 354 | .s_axi_rlast ( mig_axi4_r_last ), 355 | .s_axi_rvalid ( mig_axi4_r_valid ), 356 | .s_axi_rready ( mig_axi4_r_ready ), 357 | 358 | .init_calib_complete (init_fin) 359 | ); 360 | `endif 361 | 362 | // for debug 363 | // assign s_aw_ready = mig_axi4_aw_ready; 364 | // assign s_ar_ready = mig_axi4_ar_ready; 365 | // assign s_w_ready = mig_axi4_w_ready; 366 | // assign s_b_valid = mig_axi4_b_valid; 367 | // assign s_r_valid = mig_axi4_r_valid; 368 | 369 | endmodule 370 | -------------------------------------------------------------------------------- /verilog/AXIMmio.v: -------------------------------------------------------------------------------- 1 | module AXIMmio ( 2 | input clock, 3 | input reset, 4 | 5 | input uart_RX, 6 | output uart_TX, 7 | 8 | inout spi_cs, 9 | inout spi_sclock, 10 | inout spi_mosi, 11 | inout spi_miso, 12 | output sd_poweroff, 13 | 14 | output io_axi4_0_aw_ready, 15 | input io_axi4_0_aw_valid, 16 | input [3:0] io_axi4_0_aw_id, 17 | input [30:0] io_axi4_0_aw_addr, 18 | input [7:0] io_axi4_0_aw_len, 19 | input [2:0] io_axi4_0_aw_size, 20 | input [1:0] io_axi4_0_aw_burst, 21 | output io_axi4_0_w_ready, 22 | input io_axi4_0_w_valid, 23 | input [63:0] io_axi4_0_w_data, 24 | input [7:0] io_axi4_0_w_strb, 25 | input io_axi4_0_w_last, 26 | input io_axi4_0_b_ready, 27 | output io_axi4_0_b_valid, 28 | output [3:0] io_axi4_0_b_id, 29 | output [1:0] io_axi4_0_b_resp, 30 | output io_axi4_0_ar_ready, 31 | input io_axi4_0_ar_valid, 32 | input [3:0] io_axi4_0_ar_id, 33 | input [30:0] io_axi4_0_ar_addr, 34 | input [7:0] io_axi4_0_ar_len, 35 | input [2:0] io_axi4_0_ar_size, 36 | input [1:0] io_axi4_0_ar_burst, 37 | input io_axi4_0_r_ready, 38 | output io_axi4_0_r_valid, 39 | output [3:0] io_axi4_0_r_id, 40 | output [63:0] io_axi4_0_r_data, 41 | output [1:0] io_axi4_0_r_resp, 42 | output io_axi4_0_r_last, 43 | 44 | output interrupt_uart, 45 | output interrupt_spi 46 | ); 47 | 48 | wire resetn; 49 | assign resetn = ~ reset; 50 | 51 | //crossbar IP Slave1-uart Slave2-BRAM Slave3-SPI, they have been merged into one bundle in the stupid IP 52 | wire [2:0] peribundle_axi4_aw_ready; 53 | wire [2:0] peribundle_axi4_aw_valid; 54 | wire [11:0] peribundle_axi4_aw_id; 55 | wire [92:0] peribundle_axi4_aw_addr; 56 | wire [23:0] peribundle_axi4_aw_len; 57 | wire [8:0] peribundle_axi4_aw_size; 58 | wire [5:0] peribundle_axi4_aw_burst; 59 | wire [2:0] peribundle_axi4_w_ready; 60 | wire [2:0] peribundle_axi4_w_valid; 61 | wire [191:0] peribundle_axi4_w_data; 62 | wire [23:0] peribundle_axi4_w_strb; 63 | wire [2:0] peribundle_axi4_w_last; 64 | wire [2:0] peribundle_axi4_b_ready; 65 | wire [2:0] peribundle_axi4_b_valid; 66 | wire [11:0] peribundle_axi4_b_id; 67 | wire [5:0] peribundle_axi4_b_resp; 68 | wire [2:0] peribundle_axi4_ar_ready; 69 | wire [2:0] peribundle_axi4_ar_valid; 70 | wire [11:0] peribundle_axi4_ar_id; 71 | wire [92:0] peribundle_axi4_ar_addr; 72 | wire [23:0] peribundle_axi4_ar_len; 73 | wire [8:0] peribundle_axi4_ar_size; 74 | wire [5:0] peribundle_axi4_ar_burst; 75 | wire [2:0] peribundle_axi4_r_ready; 76 | wire [2:0] peribundle_axi4_r_valid; 77 | wire [11:0] peribundle_axi4_r_id; 78 | wire [191:0] peribundle_axi4_r_data; 79 | wire [5:0] peribundle_axi4_r_resp; 80 | wire [2:0] peribundle_axi4_r_last; 81 | 82 | axi_crossbar_0 peri_Xbar( 83 | .aclk (clock), 84 | .aresetn (resetn), 85 | 86 | .s_axi_awid (io_axi4_0_aw_id), 87 | .s_axi_awaddr (io_axi4_0_aw_addr), 88 | .s_axi_awlen (io_axi4_0_aw_len), 89 | .s_axi_awsize (io_axi4_0_aw_size), 90 | .s_axi_awburst (io_axi4_0_aw_burst), 91 | .s_axi_awvalid (io_axi4_0_aw_valid), 92 | .s_axi_awready (io_axi4_0_aw_ready), 93 | .s_axi_wdata (io_axi4_0_w_data), 94 | .s_axi_wstrb (io_axi4_0_w_strb), 95 | .s_axi_wlast (io_axi4_0_w_last), 96 | .s_axi_wvalid (io_axi4_0_w_valid), 97 | .s_axi_wready (io_axi4_0_w_ready), 98 | .s_axi_bid (io_axi4_0_b_id), 99 | .s_axi_bresp (io_axi4_0_b_resp), 100 | .s_axi_bvalid (io_axi4_0_b_valid), 101 | .s_axi_bready (io_axi4_0_b_ready), 102 | .s_axi_arid (io_axi4_0_ar_id), 103 | .s_axi_araddr (io_axi4_0_ar_addr), 104 | .s_axi_arlen (io_axi4_0_ar_len), 105 | .s_axi_arsize (io_axi4_0_ar_size), 106 | .s_axi_arburst (io_axi4_0_ar_burst), 107 | .s_axi_arvalid (io_axi4_0_ar_valid), 108 | .s_axi_arready (io_axi4_0_ar_ready), 109 | .s_axi_rid (io_axi4_0_r_id), 110 | .s_axi_rdata (io_axi4_0_r_data), 111 | .s_axi_rresp (io_axi4_0_r_resp), 112 | .s_axi_rlast (io_axi4_0_r_last), 113 | .s_axi_rvalid (io_axi4_0_r_valid), 114 | .s_axi_rready (io_axi4_0_r_ready), 115 | 116 | .m_axi_awid (peribundle_axi4_aw_id), 117 | .m_axi_awaddr (peribundle_axi4_aw_addr), 118 | .m_axi_awlen (peribundle_axi4_aw_len), 119 | .m_axi_awsize (peribundle_axi4_aw_size), 120 | .m_axi_awburst (peribundle_axi4_aw_burst), 121 | .m_axi_awvalid (peribundle_axi4_aw_valid), 122 | .m_axi_awready (peribundle_axi4_aw_ready), 123 | .m_axi_wdata (peribundle_axi4_w_data), 124 | .m_axi_wstrb (peribundle_axi4_w_strb), 125 | .m_axi_wlast (peribundle_axi4_w_last), 126 | .m_axi_wvalid (peribundle_axi4_w_valid), 127 | .m_axi_wready (peribundle_axi4_w_ready), 128 | .m_axi_bid (peribundle_axi4_b_id), 129 | .m_axi_bresp (peribundle_axi4_b_resp), 130 | .m_axi_bvalid (peribundle_axi4_b_valid), 131 | .m_axi_bready (peribundle_axi4_b_ready), 132 | .m_axi_arid (peribundle_axi4_ar_id), 133 | .m_axi_araddr (peribundle_axi4_ar_addr), 134 | .m_axi_arlen (peribundle_axi4_ar_len), 135 | .m_axi_arsize (peribundle_axi4_ar_size), 136 | .m_axi_arburst (peribundle_axi4_ar_burst), 137 | .m_axi_arvalid (peribundle_axi4_ar_valid), 138 | .m_axi_arready (peribundle_axi4_ar_ready), 139 | .m_axi_rid (peribundle_axi4_r_id), 140 | .m_axi_rdata (peribundle_axi4_r_data), 141 | .m_axi_rresp (peribundle_axi4_r_resp), 142 | .m_axi_rlast (peribundle_axi4_r_last), 143 | .m_axi_rvalid (peribundle_axi4_r_valid), 144 | .m_axi_rready (peribundle_axi4_r_ready) 145 | ); 146 | 147 | //0x60000000 - 0x60001fff 148 | uart uart_inst( 149 | 150 | .uart_axi4_aw_ready (peribundle_axi4_aw_ready[0] ), 151 | .uart_axi4_aw_valid (peribundle_axi4_aw_valid[0] ), 152 | .uart_axi4_aw_id (peribundle_axi4_aw_id[3:0] ), 153 | .uart_axi4_aw_addr (peribundle_axi4_aw_addr[30:0] ), 154 | .uart_axi4_aw_len (peribundle_axi4_aw_len[7:0] ), 155 | .uart_axi4_aw_size (peribundle_axi4_aw_size[2:0] ), 156 | .uart_axi4_aw_burst (peribundle_axi4_aw_burst[1:0] ), 157 | .uart_axi4_w_ready (peribundle_axi4_w_ready[0] ), 158 | .uart_axi4_w_valid (peribundle_axi4_w_valid[0] ), 159 | .uart_axi4_w_data (peribundle_axi4_w_data[63:0] ), 160 | .uart_axi4_w_strb (peribundle_axi4_w_strb[7:0] ), 161 | .uart_axi4_w_last (peribundle_axi4_w_last[0] ), 162 | .uart_axi4_b_ready (peribundle_axi4_b_ready[0] ), 163 | .uart_axi4_b_valid (peribundle_axi4_b_valid[0] ), 164 | .uart_axi4_b_id (peribundle_axi4_b_id[3:0] ), 165 | .uart_axi4_b_resp (peribundle_axi4_b_resp[1:0] ), 166 | .uart_axi4_ar_ready (peribundle_axi4_ar_ready[0] ), 167 | .uart_axi4_ar_valid (peribundle_axi4_ar_valid[0] ), 168 | .uart_axi4_ar_id (peribundle_axi4_ar_id[3:0] ), 169 | .uart_axi4_ar_addr (peribundle_axi4_ar_addr[30:0] ), 170 | .uart_axi4_ar_len (peribundle_axi4_ar_len[7:0] ), 171 | .uart_axi4_ar_size (peribundle_axi4_ar_size[2:0] ), 172 | .uart_axi4_ar_burst (peribundle_axi4_ar_burst[1:0] ), 173 | .uart_axi4_r_ready (peribundle_axi4_r_ready[0] ), 174 | .uart_axi4_r_valid (peribundle_axi4_r_valid[0] ), 175 | .uart_axi4_r_id (peribundle_axi4_r_id[3:0] ), 176 | .uart_axi4_r_data (peribundle_axi4_r_data[63:0] ), 177 | .uart_axi4_r_resp (peribundle_axi4_r_resp[1:0] ), 178 | .uart_axi4_r_last (peribundle_axi4_r_last[0] ), 179 | 180 | .clock(clock), 181 | .resetn(resetn), 182 | .uart_TX(uart_TX), 183 | .uart_RX(uart_RX), 184 | 185 | .interrupt(interrupt_uart) 186 | 187 | ); 188 | 189 | //0x60010000 - 0x6001ffff , 64kB 190 | bram bram_inst( 191 | 192 | .bram_axi4_aw_ready (peribundle_axi4_aw_ready[1] ), 193 | .bram_axi4_aw_valid (peribundle_axi4_aw_valid[1] ), 194 | .bram_axi4_aw_id (peribundle_axi4_aw_id[7:4] ), 195 | .bram_axi4_aw_addr (peribundle_axi4_aw_addr[61:31] ), 196 | .bram_axi4_aw_len (peribundle_axi4_aw_len[15:8] ), 197 | .bram_axi4_aw_size (peribundle_axi4_aw_size[5:3] ), 198 | .bram_axi4_aw_burst (peribundle_axi4_aw_burst[3:2] ), 199 | .bram_axi4_w_ready (peribundle_axi4_w_ready[1] ), 200 | .bram_axi4_w_valid (peribundle_axi4_w_valid[1] ), 201 | .bram_axi4_w_data (peribundle_axi4_w_data[127:64] ), 202 | .bram_axi4_w_strb (peribundle_axi4_w_strb[15:8] ), 203 | .bram_axi4_w_last (peribundle_axi4_w_last[1] ), 204 | .bram_axi4_b_ready (peribundle_axi4_b_ready[1] ), 205 | .bram_axi4_b_valid (peribundle_axi4_b_valid[1] ), 206 | .bram_axi4_b_id (peribundle_axi4_b_id[7:4] ), 207 | .bram_axi4_b_resp (peribundle_axi4_b_resp[3:2] ), 208 | .bram_axi4_ar_ready (peribundle_axi4_ar_ready[1] ), 209 | .bram_axi4_ar_valid (peribundle_axi4_ar_valid[1] ), 210 | .bram_axi4_ar_id (peribundle_axi4_ar_id[7:4] ), 211 | .bram_axi4_ar_addr (peribundle_axi4_ar_addr[61:31] ), 212 | .bram_axi4_ar_len (peribundle_axi4_ar_len[15:8] ), 213 | .bram_axi4_ar_size (peribundle_axi4_ar_size[5:3] ), 214 | .bram_axi4_ar_burst (peribundle_axi4_ar_burst[3:2] ), 215 | .bram_axi4_r_ready (peribundle_axi4_r_ready[1] ), 216 | .bram_axi4_r_valid (peribundle_axi4_r_valid[1] ), 217 | .bram_axi4_r_id (peribundle_axi4_r_id[7:4] ), 218 | .bram_axi4_r_data (peribundle_axi4_r_data[127:64] ), 219 | .bram_axi4_r_resp (peribundle_axi4_r_resp[3:2] ), 220 | .bram_axi4_r_last (peribundle_axi4_r_last[1] ), 221 | 222 | .clock(clock), 223 | .resetn(resetn) 224 | 225 | ); 226 | 227 | //TBA for the SPI-SD based at 0x60020000, a lesson is "ground all your unused signals", or the stupid vivado simulator will go insane 228 | 229 | spi spi_inst( 230 | 231 | .spi_axi4_aw_ready (peribundle_axi4_aw_ready[2] ), 232 | .spi_axi4_aw_valid (peribundle_axi4_aw_valid[2] ), 233 | .spi_axi4_aw_id (peribundle_axi4_aw_id[11:8] ), 234 | .spi_axi4_aw_addr (peribundle_axi4_aw_addr[92:62] ), 235 | .spi_axi4_aw_len (peribundle_axi4_aw_len[23:16] ), 236 | .spi_axi4_aw_size (peribundle_axi4_aw_size[8:6] ), 237 | .spi_axi4_aw_burst (peribundle_axi4_aw_burst[5:4] ), 238 | .spi_axi4_w_ready (peribundle_axi4_w_ready[2] ), 239 | .spi_axi4_w_valid (peribundle_axi4_w_valid[2] ), 240 | .spi_axi4_w_data (peribundle_axi4_w_data[191:128] ), 241 | .spi_axi4_w_strb (peribundle_axi4_w_strb[23:16] ), 242 | .spi_axi4_w_last (peribundle_axi4_w_last[2] ), 243 | .spi_axi4_b_ready (peribundle_axi4_b_ready[2] ), 244 | .spi_axi4_b_valid (peribundle_axi4_b_valid[2] ), 245 | .spi_axi4_b_id (peribundle_axi4_b_id[11:8] ), 246 | .spi_axi4_b_resp (peribundle_axi4_b_resp[5:4] ), 247 | .spi_axi4_ar_ready (peribundle_axi4_ar_ready[2] ), 248 | .spi_axi4_ar_valid (peribundle_axi4_ar_valid[2] ), 249 | .spi_axi4_ar_id (peribundle_axi4_ar_id[11:8] ), 250 | .spi_axi4_ar_addr (peribundle_axi4_ar_addr[92:62] ), 251 | .spi_axi4_ar_len (peribundle_axi4_ar_len[23:16] ), 252 | .spi_axi4_ar_size (peribundle_axi4_ar_size[8:6] ), 253 | .spi_axi4_ar_burst (peribundle_axi4_ar_burst[5:4] ), 254 | .spi_axi4_r_ready (peribundle_axi4_r_ready[2] ), 255 | .spi_axi4_r_valid (peribundle_axi4_r_valid[2] ), 256 | .spi_axi4_r_id (peribundle_axi4_r_id[11:8] ), 257 | .spi_axi4_r_data (peribundle_axi4_r_data[191:128] ), 258 | .spi_axi4_r_resp (peribundle_axi4_r_resp[5:4] ), 259 | .spi_axi4_r_last (peribundle_axi4_r_last[2] ), 260 | 261 | .clock(clock), 262 | .resetn(resetn), 263 | 264 | .spi_mosi(spi_mosi), 265 | .spi_miso(spi_miso), 266 | .spi_sclock(spi_sclock), 267 | .spi_cs(spi_cs), 268 | .sd_poweroff(sd_poweroff), 269 | 270 | .interrupt(interrupt_spi) 271 | 272 | ); 273 | 274 | endmodule 275 | -------------------------------------------------------------------------------- /verilog/peri/DTModule.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | module DTModule ( // @[Peripheryscala 157:23:freechipsrocketchipsystemDefaultFPGAConfigfir@1947114] 4 | input reset, //(SimDTM_reset), 5 | input clk, //(SimDTM_clk) 6 | 7 | output [31:0] exit, //(SimDTM_exit), 8 | 9 | input debug_req_ready, //(SimDTM_debug_req_ready), 10 | output debug_req_valid, //(SimDTM_debug_req_valid), 11 | output [6:0] debug_req_addr, //(SimDTM_debug_req_addr), 12 | output [31:0] debug_req_data, //(SimDTM_debug_req_data), 13 | output [1:0] debug_req_op, //(SimDTM_debug_req_op), 14 | 15 | output debug_resp_ready, //(SimDTM_debug_resp_ready), 16 | input debug_resp_valid, //(SimDTM_debug_resp_valid), 17 | input [31:0] debug_resp_data, //(SimDTM_debug_resp_data), 18 | input [1:0] debug_resp_resp //(SimDTM_debug_resp_resp), 19 | ); 20 | 21 | assign exit = 0; 22 | 23 | assign debug_req_valid = 0; 24 | assign debug_req_addr = 0; 25 | assign debug_req_data = 0; 26 | assign debug_req_op = 0; 27 | 28 | assign debug_resp_ready = 0; 29 | 30 | endmodule -------------------------------------------------------------------------------- /verilog/peri/JtagTunnel.v: -------------------------------------------------------------------------------- 1 | module JTAGTUNNEL( 2 | output jtag_tck, 3 | output jtag_tms, 4 | output jtag_tdi, 5 | input jtag_tdo, 6 | input jtag_tdo_en 7 | ); 8 | 9 | parameter USER_CHAIN=4; 10 | wire CAPTURE; 11 | wire DRCK; 12 | wire RESET; 13 | wire SEL; 14 | wire SHIFT; 15 | wire UPDATE; 16 | wire RUNTEST; 17 | 18 | wire jtag_tck; 19 | reg jtag_tms; 20 | wire jtag_tdi; 21 | wire jtag_tdo; 22 | wire jtag_tdo_en; 23 | wire TDO; 24 | wire reset; 25 | wire start_tck; 26 | reg [6:0] shiftreg_cnt; 27 | reg [7:0] counter_neg; 28 | reg [7:0] counter_pos; 29 | reg TDI_REG; 30 | 31 | BSCANE2 #( 32 | .JTAG_CHAIN(USER_CHAIN) // Value for USER command. 33 | ) 34 | BSCANE2_inst ( 35 | .CAPTURE(CAPTURE), // 1-bit output: CAPTURE output from TAP controller. 36 | .DRCK(DRCK), // 1-bit output: Gated TCK output. When SEL is asserted, DRCK toggles when CAPTURE or 37 | // SHIFT are asserted. 38 | .RESET(RESET), // 1-bit output: Reset output for TAP controller. 39 | .RUNTEST(RUNTEST), // 1-bit output: Output asserted when TAP controller is in Run Test/Idle state. 40 | .SEL(SEL), // 1-bit output: USER instruction active output. 41 | .SHIFT(SHIFT), // 1-bit output: SHIFT output from TAP controller. 42 | .TCK(TCK), // 1-bit output: Test Clock output. Fabric connection to TAP Clock pin. 43 | .TDI(TDI), // 1-bit output: Test Data Input (TDI) output from TAP controller. 44 | .TMS(TMS), // 1-bit output: Test Mode Select output. Fabric connection to TAP. 45 | .UPDATE(UPDATE), // 1-bit output: UPDATE output from TAP controller 46 | .TDO(TDO) // 1-bit input: Test Data Output (TDO) input for USER function. 47 | ); 48 | // 49 | BUFGCE BUFGCE_JTAG ( 50 | .O(jtag_tck), // 1-bit output: Clock output 51 | .CE(start_tck), // 1-bit input: Clock enable input for I0 52 | .I(TCK) // 1-bit input: Primary clock 53 | ); 54 | 55 | 56 | assign start_tck = SEL; 57 | assign jtag_tdi = TDI; 58 | assign TDO = jtag_tdo_en ? jtag_tdo : 1'b1; 59 | 60 | always@(*) begin 61 | if (counter_neg == 8'h04) begin 62 | jtag_tms = TDI_REG; 63 | end else if (counter_neg == 8'h05) begin 64 | jtag_tms = 1'b1; 65 | end else if ((counter_neg == (8'h08 + shiftreg_cnt)) || (counter_neg == (8'h08 + shiftreg_cnt - 8'h01))) begin 66 | jtag_tms = 1'b1; 67 | end else begin 68 | jtag_tms = 1'b0; 69 | end 70 | end 71 | 72 | always@(posedge TCK) begin 73 | if (~SHIFT) begin 74 | shiftreg_cnt <= 7'b0000000; 75 | end else if ((counter_pos >= 8'h01) && (counter_pos <= 8'h07)) begin 76 | shiftreg_cnt <= {{TDI, shiftreg_cnt[6:1]}}; 77 | end else begin 78 | shiftreg_cnt <= shiftreg_cnt; 79 | end 80 | end 81 | 82 | always@(posedge TCK) begin 83 | if (~SHIFT) begin 84 | TDI_REG <= 1'b0; 85 | end else if (counter_pos == 8'h00) begin 86 | TDI_REG <= ~TDI; 87 | end else begin 88 | TDI_REG <= TDI_REG; 89 | end 90 | end 91 | 92 | always@(negedge TCK) begin 93 | if (~SHIFT) begin 94 | counter_neg <= 8'b00000000; 95 | end else begin 96 | counter_neg <= counter_neg + 1; 97 | end 98 | end 99 | 100 | always@(posedge TCK) begin 101 | if (~SHIFT) begin 102 | counter_pos <= 8'b00000000; 103 | end else begin 104 | counter_pos <= counter_pos + 1; 105 | end 106 | end 107 | endmodule 108 | -------------------------------------------------------------------------------- /verilog/peri/bram.v: -------------------------------------------------------------------------------- 1 | module bram( 2 | input clock, 3 | input resetn, 4 | //full axi4 port from crossbar 5 | output bram_axi4_aw_ready, 6 | input bram_axi4_aw_valid, 7 | input [3:0] bram_axi4_aw_id, 8 | input [30:0] bram_axi4_aw_addr, 9 | input [7:0] bram_axi4_aw_len, 10 | input [2:0] bram_axi4_aw_size, 11 | input [1:0] bram_axi4_aw_burst, 12 | output bram_axi4_w_ready, 13 | input bram_axi4_w_valid, 14 | input [63:0] bram_axi4_w_data, 15 | input [7:0] bram_axi4_w_strb, 16 | input bram_axi4_w_last, 17 | input bram_axi4_b_ready, 18 | output bram_axi4_b_valid, 19 | output [3:0] bram_axi4_b_id, 20 | output [1:0] bram_axi4_b_resp, 21 | output bram_axi4_ar_ready, 22 | input bram_axi4_ar_valid, 23 | input [3:0] bram_axi4_ar_id, 24 | input [30:0] bram_axi4_ar_addr, 25 | input [7:0] bram_axi4_ar_len, 26 | input [2:0] bram_axi4_ar_size, 27 | input [1:0] bram_axi4_ar_burst, 28 | input bram_axi4_r_ready, 29 | output bram_axi4_r_valid, 30 | output [3:0] bram_axi4_r_id, 31 | output [63:0] bram_axi4_r_data, 32 | output [1:0] bram_axi4_r_resp, 33 | output bram_axi4_r_last 34 | ); 35 | // BRAM & controller seperate design, 36 | wire [15:0] bram_addr; 37 | wire [63:0] bram_rdata; 38 | wire [63:0] bram_wdata; 39 | wire [7:0] bram_we_perbyte; 40 | wire bram_clk; 41 | wire bram_en; 42 | 43 | bram_storage bram_storage_inst( 44 | .clock(bram_clk), 45 | // address-width should be transformed form Byte/addr to 64bits/index, jsut omit the lower 3 bits. 46 | .addr(bram_addr[15:3]), 47 | .rdata(bram_rdata), 48 | .wdata(bram_wdata), 49 | .we_perbyte(bram_we_perbyte), 50 | .en(bram_en) 51 | ); 52 | 53 | //init bram with boot program 54 | 55 | axi_bram_ctrl_0 bram_ctrl_inst( 56 | .s_axi_aclk(clock), 57 | .s_axi_aresetn(resetn), 58 | 59 | .s_axi_awready(bram_axi4_aw_ready), 60 | .s_axi_awvalid(bram_axi4_aw_valid), 61 | .s_axi_awid(bram_axi4_aw_id), 62 | .s_axi_awaddr(bram_axi4_aw_addr[15:0]), 63 | .s_axi_awlen(bram_axi4_aw_len), 64 | .s_axi_awsize(bram_axi4_aw_size), 65 | .s_axi_awburst(bram_axi4_aw_burst), 66 | .s_axi_wready(bram_axi4_w_ready), 67 | .s_axi_wvalid(bram_axi4_w_valid), 68 | .s_axi_wdata(bram_axi4_w_data), 69 | .s_axi_wstrb(bram_axi4_w_strb), 70 | .s_axi_wlast(bram_axi4_w_last), 71 | .s_axi_bready(bram_axi4_b_ready), 72 | .s_axi_bvalid(bram_axi4_b_valid), 73 | .s_axi_bid(bram_axi4_b_id), 74 | .s_axi_bresp(bram_axi4_b_resp), 75 | .s_axi_arready(bram_axi4_ar_ready), 76 | .s_axi_arvalid(bram_axi4_ar_valid), 77 | .s_axi_arid(bram_axi4_ar_id), 78 | .s_axi_araddr(bram_axi4_ar_addr[15:0]), 79 | .s_axi_arlen(bram_axi4_ar_len), 80 | .s_axi_arsize(bram_axi4_ar_size), 81 | .s_axi_arburst(bram_axi4_ar_burst), 82 | .s_axi_rready(bram_axi4_r_ready), 83 | .s_axi_rvalid(bram_axi4_r_valid), 84 | .s_axi_rid(bram_axi4_r_id), 85 | .s_axi_rdata(bram_axi4_r_data), 86 | .s_axi_rresp(bram_axi4_r_resp), 87 | .s_axi_rlast(bram_axi4_r_last), 88 | 89 | // bram interface, use as ROM no need of ctrl signal 90 | .bram_addr_a(bram_addr), 91 | .bram_clk_a(bram_clk), 92 | .bram_rddata_a(bram_rdata), 93 | .bram_wrdata_a(bram_wdata), 94 | .bram_we_a(bram_we_perbyte), 95 | .bram_en_a(bram_en) 96 | 97 | ); 98 | 99 | endmodule -------------------------------------------------------------------------------- /verilog/peri/bram_storage.v: -------------------------------------------------------------------------------- 1 | module bram_storage( 2 | input en, 3 | input clock, 4 | input [12:0] addr, 5 | input [63:0] wdata, 6 | input [7:0] we_perbyte, 7 | output [63:0] rdata 8 | ); 9 | 10 | reg [63:0] bram [8191:0]; 11 | reg [63:0] outreg; 12 | wire[63:0] wmask; 13 | 14 | parameter BRAM_INIT_FILE = "firmware.hex"; 15 | initial begin 16 | if (BRAM_INIT_FILE != "") 17 | $readmemh(BRAM_INIT_FILE, bram); 18 | end 19 | 20 | // generate wmask according to we_perbyte 21 | assign wmask[7:0] = we_perbyte[0] ? 8'hff:8'h00; 22 | assign wmask[15:8] = we_perbyte[1] ? 8'hff:8'h00; 23 | assign wmask[23:16] = we_perbyte[2] ? 8'hff:8'h00; 24 | assign wmask[31:24] = we_perbyte[3] ? 8'hff:8'h00; 25 | assign wmask[39:32] = we_perbyte[4] ? 8'hff:8'h00; 26 | assign wmask[47:40] = we_perbyte[5] ? 8'hff:8'h00; 27 | assign wmask[55:48] = we_perbyte[6] ? 8'hff:8'h00; 28 | assign wmask[63:56] = we_perbyte[7] ? 8'hff:8'h00; 29 | 30 | always @(posedge clock) 31 | if (en) 32 | outreg <= (!we_perbyte) ? bram[addr]: 0; 33 | else 34 | outreg <= 0; 35 | 36 | always @(posedge clock) 37 | if (en) 38 | bram[addr] <= (~wmask & bram[addr]) | (wmask & wdata); 39 | else 40 | bram[addr] <= bram[addr]; 41 | 42 | assign rdata = outreg; 43 | endmodule 44 | 45 | 46 | -------------------------------------------------------------------------------- /verilog/peri/spi.v: -------------------------------------------------------------------------------- 1 | module spi( 2 | input clock, 3 | input resetn, 4 | //full axi4 port from crossbar 5 | output spi_axi4_aw_ready, 6 | input spi_axi4_aw_valid, 7 | input [3:0] spi_axi4_aw_id, 8 | input [30:0] spi_axi4_aw_addr, 9 | input [7:0] spi_axi4_aw_len, 10 | input [2:0] spi_axi4_aw_size, 11 | input [1:0] spi_axi4_aw_burst, 12 | output spi_axi4_w_ready, 13 | input spi_axi4_w_valid, 14 | input [63:0] spi_axi4_w_data, 15 | input [7:0] spi_axi4_w_strb, 16 | input spi_axi4_w_last, 17 | input spi_axi4_b_ready, 18 | output spi_axi4_b_valid, 19 | output [3:0] spi_axi4_b_id, 20 | output [1:0] spi_axi4_b_resp, 21 | output spi_axi4_ar_ready, 22 | input spi_axi4_ar_valid, 23 | input [3:0] spi_axi4_ar_id, 24 | input [30:0] spi_axi4_ar_addr, 25 | input [7:0] spi_axi4_ar_len, 26 | input [2:0] spi_axi4_ar_size, 27 | input [1:0] spi_axi4_ar_burst, 28 | input spi_axi4_r_ready, 29 | output spi_axi4_r_valid, 30 | output [3:0] spi_axi4_r_id, 31 | output [63:0] spi_axi4_r_data, 32 | output [1:0] spi_axi4_r_resp, 33 | output spi_axi4_r_last, 34 | // get axi4 and send out spi to sd card 35 | inout spi_miso, 36 | inout spi_mosi, 37 | inout spi_sclock, 38 | inout spi_cs, 39 | output reg sd_poweroff, 40 | 41 | output interrupt 42 | ); 43 | 44 | // always use a axi-lite to w/r the register configuree 45 | wire [3:0] spi_lite_ar_id; 46 | wire [6:0] spi_lite_ar_addr; 47 | wire spi_lite_ar_valid; 48 | wire spi_lite_ar_ready; 49 | wire [3:0] spi_lite_r_id; 50 | wire [31:0] spi_lite_r_data; 51 | wire [1:0] spi_lite_r_resp; 52 | wire spi_lite_r_valid; 53 | wire spi_lite_r_ready; 54 | wire [3:0] spi_lite_aw_id; 55 | wire [6:0] spi_lite_aw_addr; 56 | wire spi_lite_aw_valid; 57 | wire spi_lite_aw_ready; 58 | wire [31:0] spi_lite_w_data; 59 | wire [3:0] spi_lite_w_strb; 60 | wire spi_lite_w_valid; 61 | wire spi_lite_w_ready; 62 | wire [3:0] spi_lite_b_id; 63 | wire [1:0] spi_lite_b_resp; 64 | wire spi_lite_b_valid; 65 | wire spi_lite_b_ready; 66 | 67 | wire [3:0] spi_axi4_w_strb_half; 68 | wire [31:0] spi_axi4_w_data_half; 69 | wire [31:0] spi_axi4_r_data_half; 70 | 71 | narrower spi_narrower( 72 | .r_data_64 (spi_axi4_r_data), 73 | .w_data_64 (spi_axi4_w_data), 74 | .w_strb_8 (spi_axi4_w_strb), 75 | .r_data_32 (spi_axi4_r_data_half), 76 | .w_data_32 (spi_axi4_w_data_half), 77 | .w_strb_4 (spi_axi4_w_strb_half) 78 | ); 79 | 80 | 81 | nasti_lite_bridge #( 82 | .MAX_TRANSACTION(1), // maximal number of parallel write transactions 83 | .ID_WIDTH(4), // id width 84 | .ADDR_WIDTH(7), // address width 85 | .NASTI_DATA_WIDTH(32), // width of data on the nasti side 86 | .LITE_DATA_WIDTH(32), // width of data on the nasti-lite side 87 | .USER_WIDTH(1) 88 | ) 89 | bridge_inst_SPI 90 | ( 91 | .clk (clock), 92 | .rstn (resetn), 93 | .lite_slave_ar_id (spi_lite_ar_id ), 94 | .lite_slave_ar_addr (spi_lite_ar_addr ), 95 | .lite_slave_ar_valid (spi_lite_ar_valid ), 96 | .lite_slave_ar_ready (spi_lite_ar_ready ), 97 | .lite_slave_r_id (spi_lite_r_id ), 98 | .lite_slave_r_data (spi_lite_r_data ), 99 | .lite_slave_r_resp (spi_lite_r_resp ), 100 | .lite_slave_r_valid (spi_lite_r_valid ), 101 | .lite_slave_r_ready (spi_lite_r_ready ), 102 | .lite_slave_aw_id (spi_lite_aw_id ), 103 | .lite_slave_aw_addr (spi_lite_aw_addr ), 104 | .lite_slave_aw_valid (spi_lite_aw_valid ), 105 | .lite_slave_aw_ready (spi_lite_aw_ready ), 106 | .lite_slave_w_data (spi_lite_w_data ), 107 | .lite_slave_w_strb (spi_lite_w_strb ), 108 | .lite_slave_w_valid (spi_lite_w_valid ), 109 | .lite_slave_w_ready (spi_lite_w_ready ), 110 | .lite_slave_b_id (spi_lite_b_id ), 111 | .lite_slave_b_resp (spi_lite_b_resp ), 112 | .lite_slave_b_valid (spi_lite_b_valid ), 113 | .lite_slave_b_ready (spi_lite_b_ready ), 114 | //// ATTENTION this may cause problems 115 | .nasti_master_ar_id (spi_axi4_ar_id ), 116 | .nasti_master_ar_addr (spi_axi4_ar_addr[6:0] ), 117 | .nasti_master_ar_len (spi_axi4_ar_len ), 118 | .nasti_master_ar_size (spi_axi4_ar_size ), 119 | .nasti_master_ar_burst (spi_axi4_ar_burst ), 120 | .nasti_master_ar_valid (spi_axi4_ar_valid ), 121 | .nasti_master_ar_ready (spi_axi4_ar_ready ), 122 | .nasti_master_r_id (spi_axi4_r_id ), 123 | .nasti_master_r_data (spi_axi4_r_data_half ), 124 | .nasti_master_r_resp (spi_axi4_r_resp ), 125 | .nasti_master_r_last (spi_axi4_r_last ), 126 | .nasti_master_r_valid (spi_axi4_r_valid ), 127 | .nasti_master_r_ready (spi_axi4_r_ready ), 128 | .nasti_master_aw_id (spi_axi4_aw_id ), 129 | .nasti_master_aw_addr (spi_axi4_aw_addr[6:0] ), 130 | .nasti_master_aw_len (spi_axi4_aw_len ), 131 | .nasti_master_aw_size (spi_axi4_aw_size ), 132 | .nasti_master_aw_burst (spi_axi4_aw_burst ), 133 | .nasti_master_aw_valid (spi_axi4_aw_valid ), 134 | .nasti_master_aw_ready (spi_axi4_aw_ready ), 135 | .nasti_master_w_data (spi_axi4_w_data_half ), //// ATTENTION, this may cause problems, but it seems that AXI will copy the lower 32 bit data to the higher 32 ones, when send a 32bit data to 64bit bus 136 | .nasti_master_w_strb (spi_axi4_w_strb_half ), 137 | .nasti_master_w_last (spi_axi4_w_last ), 138 | .nasti_master_w_valid (spi_axi4_w_valid ), 139 | .nasti_master_w_ready (spi_axi4_w_ready ), 140 | .nasti_master_b_id (spi_axi4_b_id ), 141 | .nasti_master_b_resp (spi_axi4_b_resp ), 142 | .nasti_master_b_valid (spi_axi4_b_valid ), 143 | .nasti_master_b_ready (spi_axi4_b_ready ) 144 | ); 145 | 146 | // SD Power Control, the SPI IP cannot control the power on/off of the SD, so we add a logic tackling with it 147 | // NOTICE here we use 0x00 as the power controller register of SD card (not for SPI ip core 148 | parameter POWER_CTRL_REG = 7'b0000000; 149 | 150 | // the following part is in the reference of ************************the lowrisc v0.2********************** 151 | wire write_power_ctrl_cmd; 152 | wire read_power_ctrl_cmd; 153 | assign write_power_ctrl_cmd = (spi_lite_aw_addr == POWER_CTRL_REG) && spi_lite_aw_valid; 154 | assign read_power_ctrl_cmd = (spi_lite_ar_addr == POWER_CTRL_REG) && spi_lite_ar_valid; 155 | 156 | reg write_selected; // "hold-on" signal during the command period 157 | reg read_selected; 158 | always @(posedge clock or negedge resetn) begin 159 | if (!resetn) 160 | read_selected <= 0; 161 | else if (read_power_ctrl_cmd) 162 | read_selected <= 1; 163 | else if (spi_lite_r_valid && spi_lite_r_ready) 164 | read_selected <= 0; 165 | end 166 | 167 | always @(posedge clock or negedge resetn) begin 168 | if (!resetn) 169 | write_selected <= 0; 170 | else if (write_power_ctrl_cmd) 171 | write_selected <= 1; 172 | else if (spi_lite_b_valid && spi_lite_b_ready) 173 | write_selected <= 0; 174 | end 175 | 176 | always @(posedge clock or negedge resetn) begin 177 | if (!resetn) 178 | sd_poweroff <= 1; 179 | else if (write_selected && spi_lite_w_ready && spi_lite_w_valid) 180 | sd_poweroff <= spi_lite_w_strb & 1'b1 ? spi_lite_w_data & 8'hff : sd_poweroff; // to poweron when we write 0x00 into POWER_CTRL_REG 181 | end 182 | 183 | // the following are the exact axi-lite signal sent to the SPI IP 184 | wire [6:0] exact_spi_lite_ar_addr; //input to ip 185 | wire exact_spi_lite_ar_valid; //input to ip 186 | wire exact_spi_lite_ar_ready; //output from ip 187 | wire [31:0] exact_spi_lite_r_data; //output from ip 188 | wire [1:0] exact_spi_lite_r_resp; //output from ip 189 | wire exact_spi_lite_r_valid; //output from ip 190 | wire exact_spi_lite_r_ready; //input to ip 191 | wire [6:0] exact_spi_lite_aw_addr; //input to ip 192 | wire exact_spi_lite_aw_valid; //input to ip 193 | wire exact_spi_lite_aw_ready; //output from ip 194 | wire [31:0] exact_spi_lite_w_data; //input to ip 195 | wire [3:0] exact_spi_lite_w_strb; //input to ip 196 | wire exact_spi_lite_w_valid; //input to ip 197 | wire exact_spi_lite_w_ready; //output from ip 198 | wire [1:0] exact_spi_lite_b_resp; //output from ip 199 | wire exact_spi_lite_b_valid; //output from ip 200 | wire exact_spi_lite_b_ready; //input to ip 201 | 202 | assign exact_spi_lite_ar_addr = spi_lite_ar_addr; //input to ip 203 | assign exact_spi_lite_ar_valid = spi_lite_ar_valid && !read_power_ctrl_cmd; //input to ip 204 | 205 | assign exact_spi_lite_r_ready = read_selected ? 0 : spi_lite_r_ready; //input to ip 206 | 207 | assign exact_spi_lite_aw_addr = spi_lite_aw_addr; //input to ip 208 | assign exact_spi_lite_aw_valid = spi_lite_aw_valid && !write_power_ctrl_cmd; //input to ip 209 | 210 | assign exact_spi_lite_w_data = spi_lite_w_data; //input to ip 211 | assign exact_spi_lite_w_strb = spi_lite_w_strb; //input to ip 212 | assign exact_spi_lite_w_valid = spi_lite_w_valid && !write_selected; //input to ip 213 | 214 | assign exact_spi_lite_b_ready = write_selected ? 0 : spi_lite_b_ready; //input to ip 215 | // 216 | assign spi_lite_ar_ready = exact_spi_lite_ar_ready || read_power_ctrl_cmd; //output from ip 217 | 218 | assign spi_lite_r_data = read_selected ? sd_poweroff : exact_spi_lite_r_data; //output from ip 219 | assign spi_lite_r_resp = read_selected ? 0 : exact_spi_lite_r_resp; //output from ip 220 | assign spi_lite_r_valid = exact_spi_lite_r_valid || read_selected; //output from ip 221 | 222 | assign spi_lite_aw_ready = exact_spi_lite_aw_ready || write_power_ctrl_cmd; //output from ip 223 | 224 | assign spi_lite_w_ready = exact_spi_lite_w_ready || write_selected; //output from ip 225 | 226 | assign spi_lite_b_resp = write_selected ? 0 : exact_spi_lite_b_resp; //output from ip 227 | assign spi_lite_b_valid = exact_spi_lite_b_valid || write_selected; //output from ip 228 | 229 | 230 | // Instance the spi controller IP 231 | // connect tri-state gate to the pin IO 232 | wire spi_mosi_i, spi_mosi_o, spi_mosi_t; 233 | wire spi_miso_i, spi_miso_o, spi_miso_t; 234 | wire spi_sclock_i, spi_sclock_o, spi_sclock_t; 235 | wire spi_cs_i, spi_cs_o, spi_cs_t; 236 | 237 | axi_quad_spi_0 axi_spi_inst( 238 | .s_axi_aclk (clock), 239 | .s_axi_aresetn (resetn), 240 | 241 | .s_axi_awready (exact_spi_lite_aw_ready), 242 | .s_axi_awvalid (exact_spi_lite_aw_valid), 243 | .s_axi_awaddr (exact_spi_lite_aw_addr[6:0]), 244 | .s_axi_wready (exact_spi_lite_w_ready), 245 | .s_axi_wvalid (exact_spi_lite_w_valid), 246 | .s_axi_wdata (exact_spi_lite_w_data[31:0]), 247 | .s_axi_wstrb (exact_spi_lite_w_strb[3:0]), // need to be reconsidered 248 | .s_axi_bready (exact_spi_lite_b_ready), 249 | .s_axi_bvalid (exact_spi_lite_b_valid), 250 | .s_axi_bresp (exact_spi_lite_b_resp), 251 | .s_axi_arready (exact_spi_lite_ar_ready), 252 | .s_axi_arvalid (exact_spi_lite_ar_valid), 253 | .s_axi_araddr (exact_spi_lite_ar_addr[6:0]), 254 | .s_axi_rready (exact_spi_lite_r_ready), 255 | .s_axi_rvalid (exact_spi_lite_r_valid), 256 | .s_axi_rdata (exact_spi_lite_r_data[31:0]), 257 | .s_axi_rresp (exact_spi_lite_r_resp), 258 | 259 | .io0_i (spi_mosi_i ), 260 | .io0_o (spi_mosi_o ), 261 | .io0_t (spi_mosi_t ), 262 | .io1_i (spi_miso_i ), 263 | .io1_o (spi_miso_o ), 264 | .io1_t (spi_miso_t ), 265 | .sck_i (spi_sclock_i ), 266 | .sck_o (spi_sclock_o ), 267 | .sck_t (spi_sclock_t ), 268 | .ss_i (spi_cs_i ), 269 | .ss_o (spi_cs_o ), 270 | .ss_t (spi_cs_t ), 271 | .ext_spi_clk (clock ), 272 | .ip2intc_irpt (interrupt) 273 | 274 | ); 275 | 276 | assign spi_mosi = !spi_mosi_t ? spi_mosi_o : 1'bz; 277 | assign spi_mosi_i = 1'b1 ; // this pin is only for output 278 | 279 | assign spi_miso = !spi_miso_t ? spi_miso_o : 1'bz; 280 | assign spi_miso_i = spi_miso; // for both input and output, a tri-state gate 281 | 282 | assign spi_sclock = !spi_sclock_t ? spi_sclock_o : 1'bz; 283 | assign spi_sclock_i = 1'b1 ; // this pin is only for output 284 | 285 | assign spi_cs = !spi_cs_t ? spi_cs_o : 1'bz; 286 | assign spi_cs_i = 1'b1 ; // this pin is only for output 287 | 288 | 289 | endmodule -------------------------------------------------------------------------------- /verilog/peri/uart.v: -------------------------------------------------------------------------------- 1 | module uart( 2 | input clock, 3 | input resetn, 4 | //full axi4 port from crossbar 5 | output uart_axi4_aw_ready, 6 | input uart_axi4_aw_valid, 7 | input [3:0] uart_axi4_aw_id, 8 | input [30:0] uart_axi4_aw_addr, 9 | input [7:0] uart_axi4_aw_len, 10 | input [2:0] uart_axi4_aw_size, 11 | input [1:0] uart_axi4_aw_burst, 12 | output uart_axi4_w_ready, 13 | input uart_axi4_w_valid, 14 | input [63:0] uart_axi4_w_data, 15 | input [7:0] uart_axi4_w_strb, 16 | input uart_axi4_w_last, 17 | input uart_axi4_b_ready, 18 | output uart_axi4_b_valid, 19 | output [3:0] uart_axi4_b_id, 20 | output [1:0] uart_axi4_b_resp, 21 | output uart_axi4_ar_ready, 22 | input uart_axi4_ar_valid, 23 | input [3:0] uart_axi4_ar_id, 24 | input [30:0] uart_axi4_ar_addr, 25 | input [7:0] uart_axi4_ar_len, 26 | input [2:0] uart_axi4_ar_size, 27 | input [1:0] uart_axi4_ar_burst, 28 | input uart_axi4_r_ready, 29 | output uart_axi4_r_valid, 30 | output [3:0] uart_axi4_r_id, 31 | output [63:0] uart_axi4_r_data, 32 | output [1:0] uart_axi4_r_resp, 33 | output uart_axi4_r_last, 34 | 35 | output interrupt, 36 | 37 | input uart_RX, 38 | output uart_TX 39 | ); 40 | 41 | // provided ip is axilite, transform axi4 to axilite 42 | wire [3:0] lite_ar_id; // be driven 43 | wire [12:0] lite_ar_addr; 44 | wire lite_ar_valid; 45 | wire lite_ar_ready; 46 | wire [3:0] lite_r_id; // =0 47 | wire [31:0] lite_r_data; 48 | wire [1:0] lite_r_resp; 49 | wire lite_r_valid; 50 | wire lite_r_ready; 51 | wire [3:0] lite_aw_id; //be driven 52 | wire [12:0] lite_aw_addr; 53 | wire lite_aw_valid; 54 | wire lite_aw_ready; 55 | wire [31:0] lite_w_data; 56 | wire [3:0] lite_w_strb; 57 | wire lite_w_valid; 58 | wire lite_w_ready; 59 | wire [3:0] lite_b_id; // =0 60 | wire [1:0] lite_b_resp; 61 | wire lite_b_valid; 62 | wire lite_b_ready; 63 | 64 | wire [3:0] uart_axi4_w_strb_half; 65 | wire [31:0] uart_axi4_w_data_half; 66 | wire [31:0] uart_axi4_r_data_half; 67 | 68 | narrower uart_narrower( 69 | .r_data_64 (uart_axi4_r_data), 70 | .w_data_64 (uart_axi4_w_data), 71 | .w_strb_8 (uart_axi4_w_strb), 72 | .r_data_32 (uart_axi4_r_data_half), 73 | .w_data_32 (uart_axi4_w_data_half), 74 | .w_strb_4 (uart_axi4_w_strb_half) 75 | ); 76 | 77 | nasti_lite_bridge #( 78 | .MAX_TRANSACTION(1), // maximal number of parallel write transactions 79 | .ID_WIDTH(4), // id width 80 | .ADDR_WIDTH(13), // address width 81 | .NASTI_DATA_WIDTH(32), // width of data on the nasti side 82 | .LITE_DATA_WIDTH(32), // width of data on the nasti-lite side 83 | .USER_WIDTH(1) 84 | ) 85 | bridge_inst 86 | ( 87 | .clk (clock), 88 | .rstn (resetn), 89 | .lite_slave_ar_id (lite_ar_id ), 90 | .lite_slave_ar_addr (lite_ar_addr ), 91 | .lite_slave_ar_valid (lite_ar_valid ), 92 | .lite_slave_ar_ready (lite_ar_ready ), 93 | .lite_slave_r_id (lite_r_id ), 94 | .lite_slave_r_data (lite_r_data ), 95 | .lite_slave_r_resp (lite_r_resp ), 96 | .lite_slave_r_valid (lite_r_valid ), 97 | .lite_slave_r_ready (lite_r_ready ), 98 | .lite_slave_aw_id (lite_aw_id ), 99 | .lite_slave_aw_addr (lite_aw_addr ), 100 | .lite_slave_aw_valid (lite_aw_valid ), 101 | .lite_slave_aw_ready (lite_aw_ready ), 102 | .lite_slave_w_data (lite_w_data ), 103 | .lite_slave_w_strb (lite_w_strb ), 104 | .lite_slave_w_valid (lite_w_valid ), 105 | .lite_slave_w_ready (lite_w_ready ), 106 | .lite_slave_b_id (lite_b_id ), 107 | .lite_slave_b_resp (lite_b_resp ), 108 | .lite_slave_b_valid (lite_b_valid ), 109 | .lite_slave_b_ready (lite_b_ready ), 110 | 111 | .nasti_master_ar_id (uart_axi4_ar_id ), 112 | .nasti_master_ar_addr (uart_axi4_ar_addr[12:0] ), 113 | .nasti_master_ar_len (uart_axi4_ar_len ), 114 | .nasti_master_ar_size (uart_axi4_ar_size ), 115 | .nasti_master_ar_burst (uart_axi4_ar_burst ), 116 | .nasti_master_ar_valid (uart_axi4_ar_valid ), 117 | .nasti_master_ar_ready (uart_axi4_ar_ready ), 118 | .nasti_master_r_id (uart_axi4_r_id ), 119 | .nasti_master_r_data (uart_axi4_r_data_half ), 120 | .nasti_master_r_resp (uart_axi4_r_resp ), 121 | .nasti_master_r_last (uart_axi4_r_last ), 122 | .nasti_master_r_valid (uart_axi4_r_valid ), 123 | .nasti_master_r_ready (uart_axi4_r_ready ), 124 | .nasti_master_aw_id (uart_axi4_aw_id ), 125 | .nasti_master_aw_addr (uart_axi4_aw_addr[12:0] ), 126 | .nasti_master_aw_len (uart_axi4_aw_len ), 127 | .nasti_master_aw_size (uart_axi4_aw_size ), 128 | .nasti_master_aw_burst (uart_axi4_aw_burst ), 129 | .nasti_master_aw_valid (uart_axi4_aw_valid ), 130 | .nasti_master_aw_ready (uart_axi4_aw_ready ), 131 | .nasti_master_w_data (uart_axi4_w_data_half ), 132 | .nasti_master_w_strb (uart_axi4_w_strb_half ), 133 | .nasti_master_w_last (uart_axi4_w_last ), 134 | .nasti_master_w_valid (uart_axi4_w_valid ), 135 | .nasti_master_w_ready (uart_axi4_w_ready ), 136 | .nasti_master_b_id (uart_axi4_b_id ), 137 | .nasti_master_b_resp (uart_axi4_b_resp ), 138 | .nasti_master_b_valid (uart_axi4_b_valid ), 139 | .nasti_master_b_ready (uart_axi4_b_ready ) 140 | 141 | ); 142 | 143 | axi_uart16550_0 uart16550_inst( 144 | 145 | .s_axi_aclk (clock), 146 | .s_axi_aresetn (resetn), 147 | .s_axi_awaddr (lite_aw_addr), 148 | .s_axi_awvalid (lite_aw_valid), 149 | .s_axi_awready (lite_aw_ready), 150 | .s_axi_wdata (lite_w_data), 151 | .s_axi_wstrb (lite_w_strb), 152 | .s_axi_wvalid (lite_w_valid), 153 | .s_axi_wready (lite_w_ready), 154 | .s_axi_bresp (lite_b_resp), 155 | .s_axi_bvalid (lite_b_valid), 156 | .s_axi_bready (lite_b_ready), 157 | .s_axi_araddr (lite_ar_addr), 158 | .s_axi_arvalid (lite_ar_valid), 159 | .s_axi_arready (lite_ar_ready), 160 | .s_axi_rdata (lite_r_data), 161 | .s_axi_rresp (lite_r_resp), 162 | .s_axi_rvalid (lite_r_valid), 163 | .s_axi_rready (lite_r_ready), 164 | 165 | .sin (uart_RX), 166 | .sout (uart_TX), 167 | .ip2intc_irpt (interrupt), 168 | 169 | .freeze (1'b0), 170 | .rin (1'b1), 171 | .dcdn (1'b1), 172 | .dsrn (1'b1) 173 | 174 | ); 175 | endmodule 176 | -------------------------------------------------------------------------------- /verilog/testbench/dut_top_tb.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | `define RANDOMIZE_GARBAGE_ASSIGN 3 | `define RANDOMIZE_INVALID_ASSIGN 4 | `define RANDOMIZE_REG_INIT 5 | `define RANDOMIZE_MEM_INIT 6 | `define RANDOMIZE_DELAY 0.002 7 | `define INIT_RANDOM 8 | `define RANDOM 0 9 | 10 | module dut_top_tb ; 11 | 12 | reg clock; 13 | reg resetn; 14 | wire uartTX; 15 | wire uartRX; 16 | 17 | // wire [15:0] ddr_dq; 18 | // wire [1:0] ddr_dqs_n; 19 | // wire [1:0] ddr_dqs_p; 20 | // wire [12:0] ddr_addr; 21 | // wire [2:0] ddr_ba; 22 | // wire ddr_ras_n; 23 | // wire ddr_cas_n; 24 | // wire ddr_we_n; 25 | // wire ddr_ck_n; 26 | // wire ddr_ck_p; 27 | // wire ddr_cke; 28 | // wire ddr_cs_n; 29 | // wire [1:0] ddr_dm; 30 | // wire ddr_odt; 31 | 32 | // parameter SIM_BYPASS_INIT_CAL = "FAST"; 33 | 34 | chip_top chip_inst( 35 | 36 | .clock100(clock), 37 | .buttonresetn(resetn), 38 | 39 | .uart_TX(uartTX), 40 | .uart_RX(uartRX) 41 | 42 | // .ddr_dq(ddr_dq), 43 | // .ddr_dqs_n(ddr_dqs_n), 44 | // .ddr_dqs_p(ddr_dqs_p), 45 | // .ddr_addr(ddr_addr), 46 | // .ddr_ba(ddr_ba), 47 | // .ddr_ras_n(ddr_ras_n), 48 | // .ddr_cas_n(ddr_cas_n), 49 | // .ddr_we_n(ddr_we_n), 50 | // .ddr_ck_n(ddr_ck_n), 51 | // .ddr_ck_p(ddr_ck_p), 52 | // .ddr_cke(ddr_cke), 53 | // .ddr_cs_n(ddr_cs_n), 54 | // .ddr_dm(ddr_dm), 55 | // .ddr_odt(ddr_odt) 56 | 57 | ); 58 | // ddr2_model ddr2_model( 59 | // .ck(ddr_ck_p), 60 | // .ck_n(ddr_ck_n), 61 | // .cke(ddr_cke), 62 | // .cs_n(ddr_cs_n), 63 | // .ras_n(ddr_ras_n), 64 | // .cas_n(ddr_cas_n), 65 | // .we_n(ddr_we_n), 66 | // .dm_rdqs(ddr_dm), 67 | // .ba(ddr_ba), 68 | // .addr(ddr_addr), 69 | // .dq(ddr_dq), 70 | // .dqs(ddr_dqs_p), 71 | // .dqs_n(ddr_dqs_n), 72 | // .odt(ddr_odt) 73 | //); 74 | 75 | 76 | initial 77 | begin 78 | clock = 0 ; 79 | #17 resetn = 0 ; 80 | #56 resetn = 1 ; 81 | end 82 | 83 | always 84 | begin 85 | #5 clock=~clock; 86 | end 87 | 88 | endmodule 89 | -------------------------------------------------------------------------------- /verilog/utils/AsyncResetReg.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | `define RANDOMIZE_GARBAGE_ASSIGN 3 | `define RANDOMIZE_INVALID_ASSIGN 4 | `define RANDOMIZE_REG_INIT 5 | `define RANDOMIZE_MEM_INIT 6 | `define SYNTHESIS 7 | 8 | // See LICENSE.SiFive for license details. 9 | 10 | /** This black-boxes an Async Reset 11 | * Reg. 12 | * 13 | * Because Chisel doesn't support 14 | * parameterized black boxes, 15 | * we unfortunately have to 16 | * instantiate a number of these. 17 | * 18 | * We also have to hard-code the set/reset. 19 | * 20 | * Do not confuse an asynchronous 21 | * reset signal with an asynchronously 22 | * reset reg. You should still 23 | * properly synchronize your reset 24 | * deassertion. 25 | * 26 | * @param d Data input 27 | * @param q Data Output 28 | * @param clk Clock Input 29 | * @param rst Reset Input 30 | * @param en Write Enable Input 31 | * 32 | */ 33 | 34 | `ifdef RANDOMIZE_GARBAGE_ASSIGN 35 | `define RANDOMIZE 36 | `endif 37 | `ifdef RANDOMIZE_INVALID_ASSIGN 38 | `define RANDOMIZE 39 | `endif 40 | `ifdef RANDOMIZE_REG_INIT 41 | `define RANDOMIZE 42 | `endif 43 | `ifdef RANDOMIZE_MEM_INIT 44 | `define RANDOMIZE 45 | `endif 46 | 47 | module AsyncResetReg (d, q, en, clk, rst); 48 | parameter RESET_VALUE = 0; 49 | 50 | input wire d; 51 | output reg q; 52 | input wire en; 53 | input wire clk; 54 | input wire rst; 55 | 56 | // There is a lot of initialization 57 | // here you don't normally find in Verilog 58 | // async registers because of scenarios in which reset 59 | // is not actually asserted cleanly at time 0, 60 | // and we want to make sure to properly model 61 | // that, yet Chisel codebase is absolutely intolerant 62 | // of Xs. 63 | `ifndef SYNTHESIS 64 | initial begin 65 | `ifdef RANDOMIZE 66 | integer initvar; 67 | reg [31:0] _RAND; 68 | _RAND = {1{$random}}; 69 | q = _RAND[0]; 70 | `endif // RANDOMIZE 71 | if (rst) begin 72 | q = RESET_VALUE; 73 | end 74 | end 75 | `endif 76 | 77 | always @(posedge clk or posedge rst) begin 78 | 79 | if (rst) begin 80 | q <= RESET_VALUE; 81 | end else if (en) begin 82 | q <= d; 83 | end 84 | end 85 | 86 | endmodule // AsyncResetReg 87 | 88 | -------------------------------------------------------------------------------- /verilog/utils/EICG_wrapper.v: -------------------------------------------------------------------------------- 1 | /* verilator lint_off UNOPTFLAT */ 2 | `timescale 1ns / 1ps 3 | 4 | module EICG_wrapper( 5 | output out, 6 | input en, 7 | input in 8 | ); 9 | 10 | reg en_latched /*verilator clock_enable*/; 11 | 12 | always @(en or in) begin 13 | if (!in) begin 14 | en_latched = en; 15 | end 16 | end 17 | 18 | assign out = en_latched && in; 19 | 20 | endmodule 21 | -------------------------------------------------------------------------------- /verilog/utils/narrower.v: -------------------------------------------------------------------------------- 1 | // NARROWER is used to tackle with data transmit from 64bit m-axi to 32bit s-axi 2 | // neutrino 2019 3 | // but i suppose the "nasti_lite_bridge" IP can tackle with it independently, gonna elimit it in the future version 4 | 5 | module narrower( 6 | input [63:0] w_data_64, 7 | input [7:0] w_strb_8, 8 | output[63:0] r_data_64, 9 | 10 | output[31:0] w_data_32, 11 | output[3:0] w_strb_4, 12 | input [31:0] r_data_32 13 | ); 14 | 15 | wire which_side_valid; 16 | // generally the low 32 bits should be valid, but sometimes it changes 17 | // so here : 1 means highvalid; 0 means lowvalid 18 | assign which_side_valid = w_strb_8[7:4] ? 1:0 ; 19 | 20 | assign w_data_32 = which_side_valid ? w_data_64[63:32] : w_data_64[31:0] ; 21 | assign w_strb_4 = which_side_valid ? w_strb_8[7:4] : w_strb_8[3:0] ; 22 | assign r_data_64 = {r_data_32, r_data_32} ; 23 | endmodule -------------------------------------------------------------------------------- /verilog/utils/nasti_lite_bridge/nasti_lite_bridge.sv: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | // bridge for NASTI/NASTI-Lite conversion 4 | 5 | module nasti_lite_bridge 6 | #( 7 | MAX_TRANSACTION = 1, // maximal number of parallel write transactions 8 | ID_WIDTH = 4, // id width 9 | ADDR_WIDTH = 13, // address width 10 | NASTI_DATA_WIDTH = 32, // width of data on the nasti side 11 | LITE_DATA_WIDTH = 32, // width of data on the nasti-lite side 12 | USER_WIDTH = 1 // width of user field, must > 0, let synthesizer trim it if not in use 13 | ) 14 | ( 15 | input clk, rstn, 16 | 17 | input [ID_WIDTH-1:0] nasti_master_ar_id, 18 | input [ADDR_WIDTH-1:0] nasti_master_ar_addr, 19 | input [7:0] nasti_master_ar_len, 20 | input [2:0] nasti_master_ar_size, 21 | input [1:0] nasti_master_ar_burst, 22 | input nasti_master_ar_lock, 23 | input [3:0] nasti_master_ar_cache, 24 | input [2:0] nasti_master_ar_prot, 25 | input [3:0] nasti_master_ar_qos, 26 | input [3:0] nasti_master_ar_region, 27 | input [USER_WIDTH-1:0] nasti_master_ar_user, 28 | input nasti_master_ar_valid, 29 | output nasti_master_ar_ready, 30 | output [ID_WIDTH-1:0] nasti_master_r_id, 31 | output [NASTI_DATA_WIDTH-1:0] nasti_master_r_data, 32 | output [1:0] nasti_master_r_resp, 33 | output nasti_master_r_last, 34 | output [USER_WIDTH-1:0] nasti_master_r_user, 35 | output nasti_master_r_valid, 36 | input nasti_master_r_ready, 37 | input [ID_WIDTH-1:0] nasti_master_aw_id, 38 | input [ADDR_WIDTH-1:0] nasti_master_aw_addr, 39 | input [7:0] nasti_master_aw_len, 40 | input [2:0] nasti_master_aw_size, 41 | input [1:0] nasti_master_aw_burst, 42 | input nasti_master_aw_lock, 43 | input [3:0] nasti_master_aw_cache, 44 | input [2:0] nasti_master_aw_prot, 45 | input [3:0] nasti_master_aw_qos, 46 | input [3:0] nasti_master_aw_region, 47 | input [USER_WIDTH-1:0] nasti_master_aw_user, 48 | input nasti_master_aw_valid, 49 | output nasti_master_aw_ready, 50 | input [NASTI_DATA_WIDTH-1:0] nasti_master_w_data, 51 | input [NASTI_DATA_WIDTH/8-1:0] nasti_master_w_strb, 52 | input nasti_master_w_last, 53 | input [USER_WIDTH-1:0] nasti_master_w_user, 54 | input nasti_master_w_valid, 55 | output nasti_master_w_ready, 56 | output [ID_WIDTH-1:0] nasti_master_b_id, 57 | output [1:0] nasti_master_b_resp, 58 | output [USER_WIDTH-1:0] nasti_master_b_user, 59 | output nasti_master_b_valid, 60 | input nasti_master_b_ready, 61 | 62 | output [ID_WIDTH-1:0] lite_slave_ar_id, 63 | output [ADDR_WIDTH-1:0] lite_slave_ar_addr, 64 | output [2:0] lite_slave_ar_prot, 65 | output [3:0] lite_slave_ar_qos, 66 | output [3:0] lite_slave_ar_region, 67 | output [USER_WIDTH-1:0] lite_slave_ar_user, 68 | output lite_slave_ar_valid, 69 | input lite_slave_ar_ready, 70 | input [ID_WIDTH-1:0] lite_slave_r_id, 71 | input [LITE_DATA_WIDTH-1:0] lite_slave_r_data, 72 | input [1:0] lite_slave_r_resp, 73 | input [USER_WIDTH-1:0] lite_slave_r_user, 74 | input lite_slave_r_valid, 75 | output lite_slave_r_ready, 76 | output [ID_WIDTH-1:0] lite_slave_aw_id, 77 | output [ADDR_WIDTH-1:0] lite_slave_aw_addr, 78 | output [2:0] lite_slave_aw_prot, 79 | output [3:0] lite_slave_aw_qos, 80 | output [3:0] lite_slave_aw_region, 81 | output [USER_WIDTH-1:0] lite_slave_aw_user, 82 | output lite_slave_aw_valid, 83 | input lite_slave_aw_ready, 84 | output [LITE_DATA_WIDTH-1:0] lite_slave_w_data, 85 | output [LITE_DATA_WIDTH/8-1:0] lite_slave_w_strb, 86 | output [USER_WIDTH-1:0] lite_slave_w_user, 87 | output lite_slave_w_valid, 88 | input lite_slave_w_ready, 89 | input [ID_WIDTH-1:0] lite_slave_b_id, 90 | input [1:0] lite_slave_b_resp, 91 | input [USER_WIDTH-1:0] lite_slave_b_user, 92 | input lite_slave_b_valid, 93 | output lite_slave_b_ready 94 | 95 | ); 96 | 97 | nasti_lite_writer 98 | #( 99 | .MAX_TRANSACTION ( MAX_TRANSACTION ), 100 | .ID_WIDTH ( ID_WIDTH ), 101 | .ADDR_WIDTH ( ADDR_WIDTH ), 102 | .NASTI_DATA_WIDTH ( NASTI_DATA_WIDTH ), 103 | .LITE_DATA_WIDTH ( LITE_DATA_WIDTH ), 104 | .USER_WIDTH ( USER_WIDTH ) 105 | ) 106 | writer 107 | ( 108 | .*, 109 | .nasti_aw_id ( nasti_master_aw_id ), 110 | .nasti_aw_addr ( nasti_master_aw_addr ), 111 | .nasti_aw_len ( nasti_master_aw_len ), 112 | .nasti_aw_size ( nasti_master_aw_size ), 113 | .nasti_aw_burst ( nasti_master_aw_burst ), 114 | .nasti_aw_lock ( nasti_master_aw_lock ), 115 | .nasti_aw_cache ( nasti_master_aw_cache ), 116 | .nasti_aw_prot ( nasti_master_aw_prot ), 117 | .nasti_aw_qos ( nasti_master_aw_qos ), 118 | .nasti_aw_region ( nasti_master_aw_region ), 119 | .nasti_aw_user ( nasti_master_aw_user ), 120 | .nasti_aw_valid ( nasti_master_aw_valid ), 121 | .nasti_aw_ready ( nasti_master_aw_ready ), 122 | .nasti_w_data ( nasti_master_w_data ), 123 | .nasti_w_strb ( nasti_master_w_strb ), 124 | .nasti_w_last ( nasti_master_w_last ), 125 | .nasti_w_user ( nasti_master_w_user ), 126 | .nasti_w_valid ( nasti_master_w_valid ), 127 | .nasti_w_ready ( nasti_master_w_ready ), 128 | .nasti_b_id ( nasti_master_b_id ), 129 | .nasti_b_resp ( nasti_master_b_resp ), 130 | .nasti_b_user ( nasti_master_b_user ), 131 | .nasti_b_valid ( nasti_master_b_valid ), 132 | .nasti_b_ready ( nasti_master_b_ready ), 133 | .lite_aw_id ( lite_slave_aw_id ), 134 | .lite_aw_addr ( lite_slave_aw_addr ), 135 | .lite_aw_prot ( lite_slave_aw_prot ), 136 | .lite_aw_qos ( lite_slave_aw_qos ), 137 | .lite_aw_region ( lite_slave_aw_region ), 138 | .lite_aw_user ( lite_slave_aw_user ), 139 | .lite_aw_valid ( lite_slave_aw_valid ), 140 | .lite_aw_ready ( lite_slave_aw_ready ), 141 | .lite_w_data ( lite_slave_w_data ), 142 | .lite_w_strb ( lite_slave_w_strb ), 143 | .lite_w_user ( lite_slave_w_user ), 144 | .lite_w_valid ( lite_slave_w_valid ), 145 | .lite_w_ready ( lite_slave_w_ready ), 146 | .lite_b_id ( lite_slave_b_id ), 147 | .lite_b_resp ( lite_slave_b_resp ), 148 | .lite_b_user ( lite_slave_b_user ), 149 | .lite_b_valid ( lite_slave_b_valid ), 150 | .lite_b_ready ( lite_slave_b_ready ) 151 | ); 152 | 153 | nasti_lite_reader 154 | #( 155 | .MAX_TRANSACTION ( MAX_TRANSACTION ), 156 | .ID_WIDTH ( ID_WIDTH ), 157 | .ADDR_WIDTH ( ADDR_WIDTH ), 158 | .NASTI_DATA_WIDTH ( NASTI_DATA_WIDTH ), 159 | .LITE_DATA_WIDTH ( LITE_DATA_WIDTH ), 160 | .USER_WIDTH ( USER_WIDTH ) 161 | ) 162 | reader 163 | ( 164 | .*, 165 | .nasti_ar_id ( nasti_master_ar_id ), 166 | .nasti_ar_addr ( nasti_master_ar_addr ), 167 | .nasti_ar_len ( nasti_master_ar_len ), 168 | .nasti_ar_size ( nasti_master_ar_size ), 169 | .nasti_ar_burst ( nasti_master_ar_burst ), 170 | .nasti_ar_lock ( nasti_master_ar_lock ), 171 | .nasti_ar_cache ( nasti_master_ar_cache ), 172 | .nasti_ar_prot ( nasti_master_ar_prot ), 173 | .nasti_ar_qos ( nasti_master_ar_qos ), 174 | .nasti_ar_region ( nasti_master_ar_region ), 175 | .nasti_ar_user ( nasti_master_ar_user ), 176 | .nasti_ar_valid ( nasti_master_ar_valid ), 177 | .nasti_ar_ready ( nasti_master_ar_ready ), 178 | .nasti_r_id ( nasti_master_r_id ), 179 | .nasti_r_data ( nasti_master_r_data ), 180 | .nasti_r_resp ( nasti_master_r_resp ), 181 | .nasti_r_last ( nasti_master_r_last ), 182 | .nasti_r_user ( nasti_master_r_user ), 183 | .nasti_r_valid ( nasti_master_r_valid ), 184 | .nasti_r_ready ( nasti_master_r_ready ), 185 | .lite_ar_id ( lite_slave_ar_id ), 186 | .lite_ar_addr ( lite_slave_ar_addr ), 187 | .lite_ar_prot ( lite_slave_ar_prot ), 188 | .lite_ar_qos ( lite_slave_ar_qos ), 189 | .lite_ar_region ( lite_slave_ar_region ), 190 | .lite_ar_user ( lite_slave_ar_user ), 191 | .lite_ar_valid ( lite_slave_ar_valid ), 192 | .lite_ar_ready ( lite_slave_ar_ready ), 193 | .lite_r_id ( lite_slave_r_id ), 194 | .lite_r_data ( lite_slave_r_data ), 195 | .lite_r_resp ( lite_slave_r_resp ), 196 | .lite_r_user ( lite_slave_r_user ), 197 | .lite_r_valid ( lite_slave_r_valid ), 198 | .lite_r_ready ( lite_slave_r_ready ) 199 | ); 200 | 201 | endmodule // nasti_lite_bridge 202 | -------------------------------------------------------------------------------- /verilog/utils/nasti_lite_bridge/nasti_lite_reader.sv: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | // Feb21-2019 a change of xact_data_wp_offset's value is made 3 | 4 | module nasti_lite_reader 5 | #( 6 | MAX_TRANSACTION = 1, // the number of parallel transactions 7 | ID_WIDTH = 4, // id width 8 | ADDR_WIDTH = 13, // address width 9 | NASTI_DATA_WIDTH = 32, // width of data on the nasti side 10 | LITE_DATA_WIDTH = 32, // width of data on the nasti-lite side 11 | USER_WIDTH = 1 // width of user field, must > 0, let synthesizer trim it if not in use 12 | ) 13 | ( 14 | input clk, rstn, 15 | input [ID_WIDTH-1:0] nasti_ar_id, 16 | input [ADDR_WIDTH-1:0] nasti_ar_addr, 17 | input [7:0] nasti_ar_len, 18 | input [2:0] nasti_ar_size, 19 | input [1:0] nasti_ar_burst, 20 | input nasti_ar_lock, 21 | input [3:0] nasti_ar_cache, 22 | input [2:0] nasti_ar_prot, 23 | input [3:0] nasti_ar_qos, 24 | input [3:0] nasti_ar_region, 25 | input [USER_WIDTH-1:0] nasti_ar_user, 26 | input nasti_ar_valid, 27 | output nasti_ar_ready, 28 | 29 | output [ID_WIDTH-1:0] nasti_r_id, 30 | output [NASTI_DATA_WIDTH-1:0] nasti_r_data, 31 | output [1:0] nasti_r_resp, 32 | output nasti_r_last, 33 | output [USER_WIDTH-1:0] nasti_r_user, 34 | output nasti_r_valid, 35 | input nasti_r_ready, 36 | 37 | output [ID_WIDTH-1:0] lite_ar_id, 38 | output [ADDR_WIDTH-1:0] lite_ar_addr, 39 | output [2:0] lite_ar_prot, 40 | output [3:0] lite_ar_qos, 41 | output [3:0] lite_ar_region, 42 | output [USER_WIDTH-1:0] lite_ar_user, 43 | output lite_ar_valid, 44 | input lite_ar_ready, 45 | 46 | input [ID_WIDTH-1:0] lite_r_id, 47 | input [LITE_DATA_WIDTH-1:0] lite_r_data, 48 | input [1:0] lite_r_resp, 49 | input [USER_WIDTH-1:0] lite_r_user, 50 | input lite_r_valid, 51 | output lite_r_ready 52 | ); 53 | 54 | 55 | localparam BUF_LEN = NASTI_DATA_WIDTH > LITE_DATA_WIDTH ? NASTI_DATA_WIDTH/LITE_DATA_WIDTH : 1; 56 | localparam MAX_TRAN_BITS = $clog2(MAX_TRANSACTION); 57 | localparam BUF_LEN_BITS = $clog2(BUF_LEN); 58 | localparam NASTI_W_BITS = $clog2(NASTI_DATA_WIDTH/8); 59 | localparam LITE_W_BITS = $clog2(LITE_DATA_WIDTH/8); 60 | 61 | genvar i; 62 | 63 | initial begin 64 | assert(LITE_DATA_WIDTH == 32 || LITE_DATA_WIDTH == 64) 65 | else $fatal(1, "nasti-lite supports only 32/64-bit channels!"); 66 | assert(NASTI_DATA_WIDTH >= LITE_DATA_WIDTH) 67 | else $fatal(1, "nasti bus cannot be narrower than lite bus!"); 68 | end 69 | 70 | `include "nasti_request.vh" 71 | 72 | // nasti request buffer 73 | NastiReq [MAX_TRANSACTION-1:0] ar_buf; 74 | logic [MAX_TRAN_BITS-1:0] ar_buf_rp, ar_buf_wp; 75 | logic ar_buf_valid; 76 | logic ar_buf_full, ar_buf_empty; 77 | 78 | // transaction information 79 | NastiReq xact_req; 80 | logic xact_req_valid; 81 | logic [BUF_LEN_BITS+7:0] xact_ar_cnt; 82 | logic [BUF_LEN_BITS+7:0] xact_r_cnt; 83 | logic [BUF_LEN-1:0][LITE_DATA_WIDTH-1:0] xact_data_vec; 84 | logic [1:0] xact_resp; 85 | logic [BUF_LEN_BITS:0] xact_data_wp; 86 | logic xact_finish; 87 | 88 | logic [ADDR_WIDTH-1:0] lite_ar_addr_accum; 89 | logic [7:0] nasti_r_cnt; 90 | logic [ADDR_WIDTH-1:0] nasti_r_addr; 91 | logic [ADDR_WIDTH-1:0] nasti_r_addr_accum; 92 | 93 | function int unsigned nasti_step_size(input NastiReq req); 94 | return 8'd1 << req.size; 95 | endfunction // nasti_step_size 96 | 97 | function bit unsigned nasti_shrink(input NastiReq req); 98 | return nasti_step_size(req) > LITE_DATA_WIDTH/8; 99 | endfunction // nasti_shrink 100 | 101 | function int unsigned lite_step_size(input NastiReq req); 102 | return nasti_shrink(req) ? LITE_DATA_WIDTH/8 : nasti_step_size(req); 103 | endfunction // lite_step_size 104 | 105 | function int unsigned lite_packet_ratio(input NastiReq req); 106 | return nasti_shrink(req) ? 8'd1 << (req.size - LITE_W_BITS) : 1; 107 | endfunction // lite_packet_ratio 108 | 109 | function int unsigned lite_packet_size(input NastiReq req); 110 | return lite_packet_ratio(req) * (req.len + 1); 111 | endfunction // lite_packet_size 112 | 113 | function int unsigned incr(input int unsigned cnt, step, ub); 114 | return cnt >= ub - step ? 0 : cnt + step; 115 | endfunction // incr 116 | 117 | // buffer requests 118 | 119 | assign ar_buf_full = ar_buf_valid && ar_buf_wp == ar_buf_rp; 120 | assign ar_buf_empty = !ar_buf_valid && ar_buf_wp == ar_buf_rp; 121 | 122 | always_ff @(posedge clk or negedge rstn) 123 | if(!rstn) 124 | ar_buf_wp <= 0; 125 | else if(nasti_ar_valid && nasti_ar_ready) begin 126 | ar_buf[ar_buf_wp] <= NastiReq'{nasti_ar_id, nasti_ar_addr, nasti_ar_len, 127 | nasti_ar_size, nasti_ar_burst, nasti_ar_lock, 128 | nasti_ar_cache, nasti_ar_prot, nasti_ar_qos, 129 | nasti_ar_region, nasti_ar_user}; 130 | ar_buf_wp <= incr(ar_buf_wp, 1, MAX_TRANSACTION); 131 | 132 | // assert(nasti_ar_burst == 2'b01) 133 | // else $fatal(1, "nasti-lite support only INCR burst!"); 134 | end 135 | 136 | always_ff @(posedge clk or negedge rstn) 137 | if(!rstn) 138 | ar_buf_valid <= 1'b0; 139 | else if(nasti_ar_valid && nasti_ar_ready) 140 | ar_buf_valid <= 1'b1; 141 | else if((xact_finish || !xact_req_valid) && ar_buf_wp == incr(ar_buf_rp, 1, MAX_TRANSACTION)) 142 | ar_buf_valid <= 1'b0; 143 | 144 | always_ff @(posedge clk or negedge rstn) 145 | if(!rstn) 146 | ar_buf_rp <= 0; 147 | else if(ar_buf_valid && (xact_finish || !xact_req_valid)) 148 | ar_buf_rp <= incr(ar_buf_rp, 1, MAX_TRANSACTION); 149 | 150 | // current transaction 151 | 152 | always_ff @(posedge clk or negedge rstn) 153 | if(!rstn) 154 | lite_ar_addr_accum <= 0; 155 | else if(lite_ar_valid && lite_ar_ready) 156 | lite_ar_addr_accum <= lite_ar_addr_accum + lite_step_size(xact_req); 157 | else if(xact_finish) 158 | lite_ar_addr_accum <= 0; 159 | 160 | assign lite_ar_id = xact_req.id; 161 | assign lite_ar_addr = xact_req.addr + lite_ar_addr_accum; 162 | assign lite_ar_prot = xact_req.prot; 163 | assign lite_ar_qos = xact_req.qos; 164 | assign lite_ar_region = xact_req.region; 165 | assign lite_ar_user = xact_req.user; 166 | assign lite_ar_valid = xact_req_valid && xact_ar_cnt < lite_packet_size(xact_req); 167 | assign nasti_ar_ready = !ar_buf_full; 168 | 169 | always_ff @(posedge clk or negedge rstn) 170 | if(!rstn) begin 171 | xact_req_valid <= 1'b0; 172 | xact_ar_cnt <= 0; 173 | xact_r_cnt <= 0; 174 | end else begin 175 | if(lite_ar_valid && lite_ar_ready) 176 | xact_ar_cnt <= xact_ar_cnt + 1; 177 | else if(xact_finish) 178 | xact_ar_cnt <= 0; 179 | 180 | if(lite_r_valid && lite_r_ready) 181 | xact_r_cnt <= xact_r_cnt + 1; 182 | else if(xact_finish) 183 | xact_r_cnt <= 0; 184 | 185 | if(xact_finish || !xact_req_valid) begin 186 | if(ar_buf_valid) xact_req <= ar_buf[ar_buf_rp]; 187 | xact_req_valid <= ar_buf_valid; 188 | end 189 | end 190 | 191 | logic [BUF_LEN_BITS:0] xact_data_wp_offset; 192 | // assign xact_data_wp_offset = NASTI_DATA_WIDTH > LITE_DATA_WIDTH ? nasti_r_addr[NASTI_W_BITS-1:LITE_W_BITS] : 0; 193 | // syntax problem, here we have same bandwidth between nasti and lite, so rp=0; 194 | 195 | assign xact_data_wp_offset = 0; 196 | assign xact_finish = nasti_r_valid && nasti_r_ready && nasti_r_cnt == xact_req.len; 197 | 198 | always_ff @(posedge clk or negedge rstn) 199 | if(!rstn) 200 | xact_data_wp <= 0; 201 | else if(lite_r_valid && lite_r_ready) begin 202 | xact_data_vec[xact_data_wp+xact_data_wp_offset] <= lite_r_data; 203 | xact_resp <= lite_r_resp; 204 | xact_data_wp <= xact_data_wp + 1; 205 | end else if(nasti_r_valid && nasti_r_ready) 206 | xact_data_wp <= 0; 207 | 208 | assign nasti_r_valid = xact_req_valid && xact_data_wp == lite_packet_ratio(xact_req); 209 | assign nasti_r_id = xact_req.id; 210 | assign nasti_r_data = xact_data_vec; 211 | assign nasti_r_resp = xact_resp; 212 | assign nasti_r_last = nasti_r_cnt == xact_req.len; 213 | assign nasti_r_user = xact_req.user; 214 | assign nasti_r_addr = xact_req.addr + nasti_r_addr_accum; 215 | assign lite_r_ready = xact_req_valid && xact_r_cnt < lite_packet_size(xact_req) && 216 | xact_data_wp < lite_packet_ratio(xact_req); 217 | 218 | always_ff @(posedge clk or negedge rstn) 219 | if(!rstn) begin 220 | nasti_r_cnt <= 0; 221 | nasti_r_addr_accum <= 0; 222 | end else if(nasti_r_valid && nasti_r_ready) begin 223 | nasti_r_cnt <= nasti_r_cnt == xact_req.len ? 0 : nasti_r_cnt + 1; 224 | nasti_r_addr_accum <= xact_finish ? 0 : nasti_r_addr_accum + nasti_step_size(xact_req); 225 | end 226 | 227 | endmodule // nasti_lite_reader 228 | -------------------------------------------------------------------------------- /verilog/utils/nasti_lite_bridge/nasti_lite_writer.sv: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | // Feb21-2019 a change of rp's value is made 3 | 4 | module nasti_lite_writer 5 | #( 6 | MAX_TRANSACTION = 1, // the number of parallel transactions 7 | ID_WIDTH = 4, // id width 8 | ADDR_WIDTH = 13, // address width 9 | NASTI_DATA_WIDTH = 32, // width of data on the nasti side 10 | LITE_DATA_WIDTH = 32, // width of data on the nasti-lite side 11 | USER_WIDTH = 1 // width of user field, must > 0, let synthesizer trim it if not in use 12 | ) 13 | ( 14 | input clk, rstn, 15 | input [ID_WIDTH-1:0] nasti_aw_id, 16 | input [ADDR_WIDTH-1:0] nasti_aw_addr, 17 | input [7:0] nasti_aw_len, 18 | input [2:0] nasti_aw_size, 19 | input [1:0] nasti_aw_burst, 20 | input nasti_aw_lock, 21 | input [3:0] nasti_aw_cache, 22 | input [2:0] nasti_aw_prot, 23 | input [3:0] nasti_aw_qos, 24 | input [3:0] nasti_aw_region, 25 | input [USER_WIDTH-1:0] nasti_aw_user, 26 | input nasti_aw_valid, 27 | output nasti_aw_ready, 28 | 29 | input [NASTI_DATA_WIDTH-1:0] nasti_w_data, 30 | input [NASTI_DATA_WIDTH/8-1:0] nasti_w_strb, 31 | input nasti_w_last, 32 | input [USER_WIDTH-1:0] nasti_w_user, 33 | input nasti_w_valid, 34 | output nasti_w_ready, 35 | 36 | output [ID_WIDTH-1:0] nasti_b_id, 37 | output [1:0] nasti_b_resp, 38 | output [USER_WIDTH-1:0] nasti_b_user, 39 | output nasti_b_valid, 40 | input nasti_b_ready, 41 | 42 | output [ID_WIDTH-1:0] lite_aw_id, 43 | output [ADDR_WIDTH-1:0] lite_aw_addr, 44 | output [2:0] lite_aw_prot, 45 | output [3:0] lite_aw_qos, 46 | output [3:0] lite_aw_region, 47 | output [USER_WIDTH-1:0] lite_aw_user, 48 | output lite_aw_valid, 49 | input lite_aw_ready, 50 | 51 | output [LITE_DATA_WIDTH-1:0] lite_w_data, 52 | output [LITE_DATA_WIDTH/8-1:0] lite_w_strb, 53 | output [USER_WIDTH-1:0] lite_w_user, 54 | output lite_w_valid, 55 | input lite_w_ready, 56 | 57 | input [ID_WIDTH-1:0] lite_b_id, 58 | input [1:0] lite_b_resp, 59 | input [USER_WIDTH-1:0] lite_b_user, 60 | input lite_b_valid, 61 | output lite_b_ready 62 | ); 63 | 64 | localparam BUF_LEN = NASTI_DATA_WIDTH > LITE_DATA_WIDTH ? NASTI_DATA_WIDTH/LITE_DATA_WIDTH : 1; 65 | localparam MAX_TRAN_BITS = $clog2(MAX_TRANSACTION); 66 | localparam BUF_LEN_BITS = $clog2(BUF_LEN); 67 | localparam NASTI_W_BITS = $clog2(NASTI_DATA_WIDTH/8); 68 | localparam LITE_W_BITS = $clog2(LITE_DATA_WIDTH/8); 69 | 70 | genvar i; 71 | 72 | initial begin 73 | assert(LITE_DATA_WIDTH == 32 || LITE_DATA_WIDTH == 64) 74 | else $fatal(1, "nasti-lite supports only 32/64-bit channels!"); 75 | assert(NASTI_DATA_WIDTH >= LITE_DATA_WIDTH) 76 | else $fatal(1, "nasti bus cannot be narrower than lite bus!"); 77 | end 78 | 79 | `include "nasti_request.vh" 80 | 81 | // nasti request buffer 82 | NastiReq [MAX_TRANSACTION-1:0] aw_buf; 83 | logic [MAX_TRAN_BITS-1:0] aw_buf_rp, aw_buf_wp; 84 | logic aw_buf_valid; 85 | logic aw_buf_full, aw_buf_empty; 86 | 87 | // transaction information 88 | NastiReq xact_req; 89 | logic xact_req_valid; 90 | logic [BUF_LEN_BITS+8:0] xact_aw_cnt; 91 | logic [BUF_LEN_BITS+8:0] xact_b_cnt; 92 | logic [BUF_LEN-1:0][LITE_DATA_WIDTH-1:0] xact_data_vec; 93 | logic [BUF_LEN-1:0][LITE_DATA_WIDTH/8-1:0] xact_strb_vec; 94 | logic [USER_WIDTH-1:0] xact_user; 95 | logic [1:0] xact_resp; 96 | logic [8:0] nasti_w_cnt; 97 | logic [BUF_LEN_BITS:0] lite_aw_cnt; 98 | logic lite_aw_data_valid; 99 | logic [BUF_LEN_BITS:0] lite_w_rp; 100 | logic [BUF_LEN_BITS:0] lite_b_cnt; 101 | logic lite_b_data_valid; 102 | logic [LITE_DATA_WIDTH/8-1:0] lite_b_strb; 103 | logic [ADDR_WIDTH-1:0] lite_b_addr; 104 | logic [BUF_LEN_BITS:0] lite_b_rp; 105 | logic xact_finish; 106 | 107 | function int unsigned nasti_step_size(input NastiReq req); 108 | return 8'd1 << req.size; 109 | endfunction // nasti_step_size 110 | 111 | function bit unsigned nasti_shrink(input NastiReq req); 112 | return nasti_step_size(req) > LITE_DATA_WIDTH/8; 113 | endfunction // nasti_shrink 114 | 115 | function int unsigned lite_step_size(input NastiReq req); 116 | return nasti_shrink(req) ? LITE_DATA_WIDTH/8 : nasti_step_size(req); 117 | endfunction // lite_step_size 118 | 119 | function int unsigned lite_packet_ratio(input NastiReq req); 120 | return nasti_shrink(req) ? 8'd1 << (req.size - LITE_W_BITS) : 1; 121 | endfunction // lite_packet_ratio 122 | 123 | function int unsigned lite_packet_size(input NastiReq req); 124 | return lite_packet_ratio(req) * (req.len + 1); 125 | endfunction // lite_packet_size 126 | 127 | function int unsigned incr(input int unsigned cnt, step, ub); 128 | return cnt >= ub - step ? 0 : cnt + step; 129 | endfunction // incr 130 | 131 | // buffer requests 132 | 133 | assign aw_buf_full = aw_buf_valid && aw_buf_wp == aw_buf_rp; 134 | assign aw_buf_empty = !aw_buf_valid && aw_buf_wp == aw_buf_rp; 135 | 136 | always_ff @(posedge clk or negedge rstn) 137 | if(!rstn) 138 | aw_buf_wp <= 0; 139 | else if(nasti_aw_valid && nasti_aw_ready) begin 140 | aw_buf[aw_buf_wp] <= NastiReq'{nasti_aw_id, nasti_aw_addr, nasti_aw_len, 141 | nasti_aw_size, nasti_aw_burst, nasti_aw_lock, 142 | nasti_aw_cache, nasti_aw_prot, nasti_aw_qos, 143 | nasti_aw_region, nasti_aw_user}; 144 | aw_buf_wp <= incr(aw_buf_wp, 1, MAX_TRANSACTION); 145 | 146 | //assert(nasti_aw_burst == 2'b01) 147 | //else $fatal(1, "nasti-lite support only INCR burst!"); 148 | 149 | end 150 | 151 | always_ff @(posedge clk or negedge rstn) 152 | if(!rstn) 153 | aw_buf_valid <= 1'b0; 154 | else if(nasti_aw_valid && nasti_aw_ready) 155 | aw_buf_valid <= 1'b1; 156 | else if((xact_finish || !xact_req_valid) && aw_buf_wp == incr(aw_buf_rp, 1, MAX_TRANSACTION)) 157 | aw_buf_valid <= 1'b0; 158 | 159 | always_ff @(posedge clk or negedge rstn) 160 | if(!rstn) 161 | aw_buf_rp <= 0; 162 | else if(aw_buf_valid && (xact_finish || !xact_req_valid)) 163 | aw_buf_rp <= incr(aw_buf_rp, 1, MAX_TRANSACTION); 164 | 165 | assign nasti_aw_ready = !aw_buf_full; 166 | assign xact_finish = nasti_b_valid && nasti_b_ready; 167 | 168 | always_ff @(posedge clk or negedge rstn) 169 | if(!rstn) 170 | nasti_w_cnt <= 0; 171 | else if(nasti_w_valid && nasti_w_ready) 172 | nasti_w_cnt <= nasti_w_cnt + 1; 173 | else if(xact_finish) 174 | nasti_w_cnt <= 0; 175 | 176 | assign nasti_w_ready = xact_req_valid && !lite_b_data_valid && nasti_w_cnt < xact_req.len + 1; 177 | 178 | assign nasti_b_valid = xact_req_valid && xact_b_cnt == lite_packet_size(xact_req); 179 | assign nasti_b_id = xact_req.id; 180 | assign nasti_b_resp = xact_resp; 181 | assign nasti_b_user = xact_req.user; 182 | 183 | // current transaction 184 | logic lite_aw_bypass; 185 | logic lite_b_bypass; 186 | 187 | logic lite_aw_send, lite_w_send, lite_req_send; 188 | always_ff @(posedge clk or negedge rstn) 189 | if(!rstn) begin 190 | lite_aw_send <= 1'b0; 191 | lite_w_send <= 1'b0; 192 | end else begin 193 | lite_aw_send <= lite_req_send ? 1'b0 : lite_aw_send || (lite_aw_valid && lite_aw_ready); 194 | lite_w_send <= lite_req_send ? 1'b0 : lite_w_send || (lite_w_valid && lite_w_ready); 195 | end 196 | assign lite_req_send = (lite_aw_send || (lite_aw_valid && lite_aw_ready)) && 197 | (lite_w_send || (lite_w_valid && lite_w_ready)); 198 | assign lite_aw_bypass = lite_aw_data_valid && lite_w_strb == 0; 199 | assign lite_b_bypass = lite_b_data_valid && lite_b_strb == 0; 200 | 201 | always_ff @(posedge clk or negedge rstn) 202 | if(!rstn) begin 203 | xact_aw_cnt <= 0; 204 | lite_aw_cnt <= 0; 205 | end else if(lite_req_send || lite_aw_bypass) begin 206 | xact_aw_cnt <= xact_aw_cnt + 1; 207 | lite_aw_cnt <= lite_aw_cnt == lite_packet_ratio(xact_req)-1 ? 0 : lite_aw_cnt + 1; 208 | end else if(xact_finish) begin 209 | xact_aw_cnt <= 0; 210 | end 211 | 212 | always_ff @(posedge clk or negedge rstn) 213 | if(!rstn) begin 214 | xact_b_cnt <= 0; 215 | lite_b_cnt <= 0; 216 | end else if(lite_b_valid && lite_b_ready || lite_b_bypass) begin 217 | xact_b_cnt <= xact_b_cnt + 1; 218 | lite_b_cnt <= lite_b_cnt == lite_packet_ratio(xact_req)-1 ? 0 : lite_b_cnt + 1; 219 | end else if(xact_finish) 220 | xact_b_cnt <= 0; 221 | 222 | always_ff @(posedge clk or negedge rstn) 223 | if(!rstn) 224 | xact_req_valid <= 1'b0; 225 | else if(xact_finish || !xact_req_valid) begin 226 | if(aw_buf_valid) 227 | xact_req <= aw_buf[aw_buf_rp]; 228 | xact_req_valid <= aw_buf_valid; 229 | end 230 | 231 | always_ff @(posedge clk or negedge rstn) 232 | if(!rstn) begin 233 | lite_aw_data_valid <= 1'b0; 234 | lite_b_data_valid <= 1'b0; 235 | end else if(nasti_w_valid && nasti_w_ready) begin 236 | xact_data_vec <= nasti_w_data; 237 | xact_strb_vec <= nasti_w_strb; 238 | xact_user <= nasti_w_user; 239 | lite_aw_data_valid <= 1'b1; 240 | lite_b_data_valid <= 1'b1; 241 | end else begin 242 | if((lite_req_send || lite_aw_bypass) && lite_aw_cnt == lite_packet_ratio(xact_req)-1) 243 | lite_aw_data_valid <= 1'b0; 244 | 245 | if((lite_b_valid && lite_b_ready || lite_b_bypass) && lite_b_cnt == lite_packet_ratio(xact_req)-1) 246 | lite_b_data_valid <= 1'b0; 247 | end 248 | 249 | always_ff @(posedge clk) 250 | if(lite_b_valid && lite_b_ready) 251 | xact_resp <= lite_b_resp; 252 | 253 | assign lite_aw_id = xact_req.id; 254 | assign lite_aw_addr = xact_req.addr + xact_aw_cnt * lite_step_size(xact_req); 255 | assign lite_aw_prot = xact_req.prot; 256 | assign lite_aw_qos = xact_req.qos; 257 | assign lite_aw_region = xact_req.region; 258 | assign lite_aw_user = xact_req.user; 259 | assign lite_aw_valid = lite_aw_data_valid && !lite_aw_send && !lite_aw_bypass; 260 | 261 | // assign lite_w_rp = NASTI_DATA_WIDTH > LITE_DATA_WIDTH ? lite_aw_addr[NASTI_W_BITS-1:LITE_W_BITS] : 0; 262 | // syntax problem, here we have same bandwidth between nasti and lite, so rp=0; 263 | assign lite_w_rp = 0; 264 | assign lite_w_data = xact_data_vec[lite_w_rp]; 265 | assign lite_w_strb = xact_strb_vec[lite_w_rp]; 266 | assign lite_w_user = xact_user; 267 | assign lite_w_valid = lite_aw_data_valid && !lite_w_send && !lite_aw_bypass; 268 | 269 | assign lite_b_addr = xact_req.addr + xact_b_cnt * lite_step_size(xact_req); 270 | // assign lite_b_rp = NASTI_DATA_WIDTH > LITE_DATA_WIDTH ? lite_b_addr[NASTI_W_BITS-1:LITE_W_BITS] : 0; 271 | assign lite_b_rp = 0; 272 | assign lite_b_strb = xact_strb_vec[lite_b_rp]; 273 | assign lite_b_ready = lite_b_data_valid; 274 | 275 | 276 | endmodule // nasti_lite_write_buf 277 | -------------------------------------------------------------------------------- /verilog/utils/nasti_lite_bridge/nasti_request.vh: -------------------------------------------------------------------------------- 1 | // See LICENSE for license details. 2 | 3 | typedef struct packed unsigned { 4 | logic [ID_WIDTH-1:0] id; 5 | logic [ADDR_WIDTH-1:0] addr; 6 | logic [8:0] len; 7 | logic [2:0] size; 8 | logic [1:0] burst; 9 | logic lock; 10 | logic [3:0] cache; 11 | logic [2:0] prot; 12 | logic [3:0] qos; 13 | logic [3:0] region; 14 | logic [USER_WIDTH-1:0] user; 15 | } NastiReq; 16 | -------------------------------------------------------------------------------- /verilog/utils/plusarg_reader.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | 3 | // See LICENSE.SiFive for license details. 4 | 5 | //VCS coverage exclude_file 6 | 7 | // No default parameter values are intended, nor does IEEE 1800-2012 require them (clause A.2.4 param_assignment), 8 | // but Incisive demands them. These default values should never be used. 9 | module plusarg_reader #(parameter FORMAT="borked=%d", DEFAULT=0) ( 10 | output [31:0] out 11 | ); 12 | 13 | `ifdef SYNTHESIS 14 | assign out = DEFAULT; 15 | `else 16 | reg [31:0] myplus; 17 | assign out = myplus; 18 | 19 | initial begin 20 | if (!$value$plusargs(FORMAT, myplus)) myplus = DEFAULT; 21 | end 22 | `endif 23 | 24 | endmodule 25 | -------------------------------------------------------------------------------- /verilog/utils/sram_modified.v: -------------------------------------------------------------------------------- 1 | `timescale 1ns / 1ps 2 | `define RANDOMIZE_GARBAGE_ASSIGN 3 | `define RANDOMIZE_INVALID_ASSIGN 4 | `define RANDOMIZE_REG_INIT 5 | `define RANDOMIZE_MEM_INIT 6 | `define SYNTHESIS 7 | `define RANDOMIZE_DELAY 0.002 8 | 9 | 10 | /////////////////////////////////////////////////////////////////////////////////////////////////////////////////// 11 | module data_arrays_0_ext( 12 | input RW0_clk, 13 | input [8:0] RW0_addr, 14 | input RW0_en, 15 | input RW0_wmode, 16 | input [31:0] RW0_wmask, 17 | input [255:0] RW0_wdata, 18 | output [255:0] RW0_rdata 19 | ); 20 | 21 | reg reg_RW0_ren; 22 | reg [8:0] reg_RW0_addr; 23 | reg [255:0] ram [511:0]; 24 | `ifdef RANDOMIZE_MEM_INIT 25 | integer initvar; 26 | initial begin 27 | #`RANDOMIZE_DELAY begin end 28 | for (initvar = 0; initvar < 512; initvar = initvar+1) 29 | ram[initvar] = {8 {$random}}; 30 | reg_RW0_addr = {1 {$random}}; 31 | end 32 | `endif 33 | integer i; 34 | always @(posedge RW0_clk) 35 | reg_RW0_ren <= RW0_en && !RW0_wmode; 36 | always @(posedge RW0_clk) 37 | if (RW0_en && !RW0_wmode) reg_RW0_addr <= RW0_addr; 38 | 39 | integer j; 40 | integer width = 8; 41 | integer size = 32; 42 | always @(posedge RW0_clk) 43 | for (i=0; i 30MHz and 200MHz, resetn 5 | axi_crossbar interface-3 addr-31 width-64 id-4 6 | uart_16550 30MHz 7 | axi_bram_ctrl index-8k width-64 id-4 8 | memory interf #NOTICE sysrst-high activation 9 | clock_converter 10 | AXI to quad SPI 11 | --------------------------------------------------------------------------------