├── empty_dmem.hex ├── libsoc ├── libsoc.txt ├── gpio.h ├── icerror.h └── timer.h ├── docs ├── riscv.png ├── datasheet.pdf ├── diagram.png ├── example.png ├── opencores.png └── Doxyfile ├── src ├── ry_constants.vhd ├── dsaf │ ├── ry_constants.vhd │ ├── ry_counter.vhd │ ├── ry_csr_alu.vhd │ ├── ry_comparator.vhd │ ├── ry_imm_decoder.vhd │ ├── ry_alu_mux.vhd │ ├── ry_register_file.vhd │ ├── ry_writeback.vhd │ ├── ry_alu.vhd │ ├── ry_utilities.vhd │ ├── ry_fetch.vhd │ ├── ry_wb_arbiter.vhd │ ├── ry_wb_adapter.vhd │ └── ry_types.vhd ├── ry_counter.vhd ├── ry_csr_alu.vhd ├── ry_comparator.vhd ├── ry_imm_decoder.vhd ├── ry_alu_mux.vhd ├── ry_register_file.vhd ├── ry_writeback.vhd ├── ry_alu.vhd ├── ry_utilities.vhd ├── ry_fetch.vhd ├── ry_wb_arbiter.vhd ├── ry_wb_adapter.vhd └── ry_types.vhd ├── software ├── bootloader │ ├── README.md │ ├── Makefile │ ├── bootloader.ld │ └── main.c ├── hello │ ├── main.c │ └── Makefile ├── sha256 │ ├── sha256.h │ └── Makefile ├── riscy.ld ├── common.mk └── start.S ├── riscv-tests ├── simple.S ├── auipc.S ├── lui.S ├── fence_i.S ├── jal.S ├── LICENSE ├── jalr.S ├── andi.S ├── ori.S ├── xori.S ├── bne.S ├── beq.S ├── blt.S ├── bge.S ├── slti.S ├── sltiu.S ├── addi.S ├── bltu.S ├── lb.S ├── lh.S ├── lbu.S ├── lhu.S ├── lw.S ├── bgeu.S ├── srai.S ├── or.S ├── and.S ├── xor.S ├── sb.S ├── sh.S ├── sw.S ├── sltu.S ├── slt.S ├── sub.S ├── add.S └── srl.S ├── tests.ld ├── tests └── csr_hazard.S ├── scripts └── extract_hex.sh ├── platform.h ├── example ├── tb_toplevel.vhd ├── aee_rom_wrapper.vhd └── arty.xdc ├── riscy-test.h ├── soc ├── ry_soc_reset.vhd ├── ry_fifo.vhd ├── ry_soc_memory.vhd ├── ry_soc_timer.vhd └── ry_soc_gpio.vhd ├── testbenches ├── tb_soc_gpio.vhd ├── tb_soc_memory.vhd ├── tb_soc_timer.vhd ├── tb_soc_uart.vhd └── tb_soc_intercon.vhd ├── riscy.h ├── README.md └── Makefile /empty_dmem.hex: -------------------------------------------------------------------------------- 1 | 00000000 2 | -------------------------------------------------------------------------------- /libsoc/libsoc.txt: -------------------------------------------------------------------------------- 1 | libsoc 2 | -------------------------------------------------------------------------------- /docs/riscv.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mongrelgem/RISCY/HEAD/docs/riscv.png -------------------------------------------------------------------------------- /docs/datasheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mongrelgem/RISCY/HEAD/docs/datasheet.pdf -------------------------------------------------------------------------------- /docs/diagram.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mongrelgem/RISCY/HEAD/docs/diagram.png -------------------------------------------------------------------------------- /docs/example.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mongrelgem/RISCY/HEAD/docs/example.png -------------------------------------------------------------------------------- /docs/opencores.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mongrelgem/RISCY/HEAD/docs/opencores.png -------------------------------------------------------------------------------- /src/ry_constants.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | library ieee; 4 | use ieee.std_logic_1164.all; 5 | 6 | use work.ry_types.all; 7 | 8 | package ry_constants is 9 | 10 | --! No-operation instruction, addi x0, x0, 0. 11 | constant RISCV_NOP : std_logic_vector(31 downto 0) := (31 downto 5 => '0') & b"10011"; --! ADDI x0, x0, 0. 12 | 13 | end package ry_constants; 14 | -------------------------------------------------------------------------------- /src/dsaf/ry_constants.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | library ieee; 4 | use ieee.std_logic_1164.all; 5 | 6 | use work.ry_types.all; 7 | 8 | package ry_constants is 9 | 10 | --! No-operation instruction, addi x0, x0, 0. 11 | constant RISCV_NOP : std_logic_vector(31 downto 0) := (31 downto 5 => '0') & b"10011"; --! ADDI x0, x0, 0. 12 | 13 | end package ry_constants; 14 | -------------------------------------------------------------------------------- /software/bootloader/README.md: -------------------------------------------------------------------------------- 1 | # Bootloader 2 | 3 | A trivial bootloader has been created so to ease software development and testing. 4 | The bootloader emits a welcome message over the UART (115200 baud, 8N1) and waits 5 | for a 128 kB binary image to be received. 6 | 7 | Once the image has been received, the booloader jumps to address 0x00000000 to begin 8 | executing the new application. 9 | 10 | To use the bootloader, build an application and upload it to the board with the following 11 | command: 12 | 13 | ``` 14 | cat image.bin /dev/zero | head -c128k | pv -s 128k -L 14400 > /dev/ttyUSB1 15 | ``` 16 | 17 | -------------------------------------------------------------------------------- /riscv-tests/simple.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # simple.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # This is the most basic self checking test. If your simulator does not 8 | # pass thiss then there is little chance that it will pass any of the 9 | # more complicated self checking tests. 10 | # 11 | 12 | #include "riscv_test.h" 13 | #include "test_macros.h" 14 | 15 | RVTEST_RV32M 16 | RVTEST_CODE_BEGIN 17 | 18 | RVTEST_PASS 19 | 20 | RVTEST_CODE_END 21 | 22 | .data 23 | RVTEST_DATA_BEGIN 24 | 25 | TEST_DATA 26 | 27 | RVTEST_DATA_END 28 | -------------------------------------------------------------------------------- /software/hello/main.c: -------------------------------------------------------------------------------- 1 | /* The RISCY Processor Benchmark Applications 2 | The RISCY Processor - A simple RISC-V based processor for FPGAs 3 | (c) Krishna Subramanian 4 | */ 5 | 6 | #include 7 | 8 | #include "platform.h" 9 | #include "uart.h" 10 | 11 | static struct uart uart0; 12 | 13 | void exception_handler(uint32_t cause, void * epc, void * regbase) 14 | { 15 | // Not used in this application 16 | } 17 | 18 | int main(void) 19 | { 20 | uart_initialize(&uart0, (volatile void *) PLATFORM_UART0_BASE); 21 | uart_set_divisor(&uart0, uart_baud2divisor(115200, PLATFORM_SYSCLK_FREQ)); 22 | uart_tx_string(&uart0, "Hello world. I am the RISCY Processor\n\r"); 23 | 24 | return 0; 25 | } 26 | 27 | -------------------------------------------------------------------------------- /tests.ld: -------------------------------------------------------------------------------- 1 | /* 2 | * Linker Script for the RISCY Processor test applications. 3 | * The RISCY Processor - A simple RISC-V based processor for FPGAs 4 | * (c) Krishna Subramanian 5 | */ 6 | 7 | /* 8 | * The linker script assumes that default testbench settings are used, that is, 9 | * 2048 bytes (each) of separate instruction and data memory. 10 | */ 11 | 12 | OUTPUT_ARCH(riscv); 13 | ENTRY(_start); 14 | 15 | SECTIONS 16 | { 17 | .text 0x100 : 18 | { 19 | *(.text.init) 20 | *(.text) 21 | } 22 | 23 | .data 0x1000 : 24 | { 25 | __data_begin = .; 26 | *(.data*) 27 | } 28 | 29 | .bss : 30 | { 31 | __bss_begin = .; 32 | *(.bss*) 33 | __bss_end = .; 34 | } 35 | __data_end = .; 36 | 37 | __stack_top = 0x2000; 38 | } 39 | 40 | -------------------------------------------------------------------------------- /software/hello/Makefile: -------------------------------------------------------------------------------- 1 | # The RISCY Processor Software Components 2 | # The RISCY Processor - A simple RISC-V based processor for FPGAs 3 | # (c) Krishna Subramanian 4 | 5 | 6 | .PHONY: all clean 7 | include ../common.mk 8 | 9 | TARGET_LDFLAGS += -Wl,-T../riscy.ld -Wl,--Map,hello.map 10 | 11 | OBJECTS := main.o start.o 12 | 13 | all: hello.elf hello.bin hello.coe 14 | 15 | hello.elf: $(OBJECTS) 16 | $(TARGET_LD) -o hello.elf $(TARGET_LDFLAGS) $(OBJECTS) 17 | $(TARGET_SIZE) hello.elf 18 | 19 | clean: 20 | -$(RM) $(OBJECTS) 21 | -$(RM) hello.elf hello.bin hello.coe 22 | 23 | # Object file rules: 24 | 25 | main.o: main.c ../../riscy.h 26 | $(TARGET_CC) -c -o $@ $(TARGET_CFLAGS) $< 27 | 28 | start.o: ../start.S 29 | $(TARGET_CC) -c -o $@ $(TARGET_CFLAGS) $< 30 | 31 | -------------------------------------------------------------------------------- /riscv-tests/auipc.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # auipc.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test auipc instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | TEST_CASE(2, a0, 10000, \ 17 | .align 3; \ 18 | lla a0, 1f + 10000; \ 19 | jal a1, 1f; \ 20 | 1: sub a0, a0, a1; \ 21 | ) 22 | 23 | TEST_CASE(3, a0, -10000, \ 24 | .align 3; \ 25 | lla a0, 1f - 10000; \ 26 | jal a1, 1f; \ 27 | 1: sub a0, a0, a1; \ 28 | ) 29 | 30 | TEST_PASSFAIL 31 | 32 | RVTEST_CODE_END 33 | 34 | .data 35 | RVTEST_DATA_BEGIN 36 | 37 | TEST_DATA 38 | 39 | RVTEST_DATA_END 40 | -------------------------------------------------------------------------------- /tests/csr_hazard.S: -------------------------------------------------------------------------------- 1 | # The RISCY Processor Benchmark Applications 2 | # The RISCY Processor - A simple RISC-V based processor for FPGAs 3 | # (c) Krishna Subramanian 4 | 5 | 6 | #include "riscv_test.h" 7 | #include "test_macros.h" 8 | 9 | RVTEST_RV32M 10 | RVTEST_CODE_BEGIN 11 | 12 | li TESTNUM, 1 13 | li x1, 4 14 | li x2, 5 15 | li x3, 6 16 | csrw mscratch, x1 17 | csrr x4, mscratch 18 | bne x4, x1, fail 19 | 20 | li TESTNUM, 2 21 | csrw mscratch, x1 22 | csrw mscratch, x2 23 | csrr x4, mscratch 24 | bne x4, x2, fail 25 | 26 | li TESTNUM, 3 27 | csrw mscratch, x1 28 | csrw mscratch, x2 29 | csrw mscratch, x3 30 | csrr x4, mscratch 31 | bne x4, x3, fail 32 | 33 | TEST_PASSFAIL 34 | 35 | RVTEST_CODE_END 36 | 37 | .data 38 | RVTEST_DATA_BEGIN 39 | 40 | TEST_DATA 41 | 42 | RVTEST_DATA_END 43 | 44 | 45 | -------------------------------------------------------------------------------- /software/bootloader/Makefile: -------------------------------------------------------------------------------- 1 | # The RISCY Processor Software Components 2 | # The RISCY Processor - A simple RISC-V based processor for FPGAs 3 | # (c) Krishna Subramanian 4 | 5 | .PHONY: all clean 6 | include ../common.mk 7 | 8 | TARGET_LDFLAGS += -Wl,-Tbootloader.ld -Wl,--Map,bootloader.map 9 | 10 | OBJECTS := main.o start.o 11 | 12 | all: bootloader.elf bootloader.bin bootloader.coe 13 | 14 | bootloader.elf: $(OBJECTS) 15 | $(TARGET_LD) -o bootloader.elf $(TARGET_LDFLAGS) $(OBJECTS) 16 | $(TARGET_SIZE) bootloader.elf 17 | 18 | clean: 19 | -$(RM) $(OBJECTS) 20 | -$(RM) bootloader.elf bootloader.bin bootloader.coe 21 | 22 | # Object file rules: 23 | 24 | main.o: main.c ../../riscy.h 25 | $(TARGET_CC) -c -o $@ $(TARGET_CFLAGS) $< 26 | 27 | start.o: ../start.S 28 | $(TARGET_CC) -DCOPY_DATA_TO_RAM -c -o $@ $(TARGET_CFLAGS) $< 29 | 30 | -------------------------------------------------------------------------------- /software/sha256/sha256.h: -------------------------------------------------------------------------------- 1 | /* The RISCY Processor Benchmark Applications 2 | The RISCY Processor - A simple RISC-V based processor for FPGAs 3 | (c) Krishna Subramanian 4 | */ 5 | 6 | #ifndef SHA256_H 7 | #define SHA256_H 8 | 9 | #include 10 | 11 | struct sha256_context 12 | { 13 | uint32_t intermediate[8]; 14 | }; 15 | 16 | // Resets a SHA256 context: 17 | void sha256_reset(struct sha256_context * ctx); 18 | 19 | // Hash a block of data: 20 | void sha256_hash_block(struct sha256_context * ctx, const uint32_t * data); 21 | 22 | // Pad a block of data to hash: 23 | void sha256_pad_le_block(uint8_t * block, int block_length, uint64_t total_length); 24 | 25 | // Get the hash from a SHA256 context: 26 | void sha256_get_hash(const struct sha256_context * ctx, uint8_t * hash); 27 | 28 | // Formats a hash for printing: 29 | void sha256_format_hash(const uint8_t * hash, char * output); 30 | 31 | #endif 32 | 33 | -------------------------------------------------------------------------------- /scripts/extract_hex.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # The RISCY Processor - A simple processor for FPGA Prototyping 3 | # The RISCY Processor - A simple RISC-V based processor for FPGAs 4 | #(c) Krishna Subramanian 5 | 6 | 7 | # This script extracts the code and data sections from executables and 8 | # produces hex files that can be used to initialize the instruction and 9 | # data memories in the testbench. 10 | 11 | if [ -z "$1" -o -z "$2" -o -z "$3" ]; then 12 | echo "exctract_hex " 13 | exit 1 14 | fi 15 | 16 | if [ -z "$TOOLCHAIN_PREFIX" ]; then 17 | TOOLCHAIN_PREFIX=riscv32-unknown-elf 18 | fi; 19 | 20 | $TOOLCHAIN_PREFIX-objdump -d -w $1 | sed '1,5d' | awk '!/:$/ { print $2; }' | sed '/^$/d' > $2; \ 21 | test -z "$($TOOLCHAIN_PREFIX-readelf -l $1 | grep .data)" || \ 22 | $TOOLCHAIN_PREFIX-objdump -s -j .data $1 | sed '1,4d' | \ 23 | awk '!/:$/ { for (i = 2; i < 6; i++) print $i; }' | sed '/^$/d' > $3; 24 | 25 | exit 0 26 | 27 | -------------------------------------------------------------------------------- /riscv-tests/lui.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # lui.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test lui instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Basic tests 18 | #------------------------------------------------------------- 19 | 20 | TEST_CASE( 2, x1, 0x0000000000000000, lui x1, 0x00000 ); 21 | TEST_CASE( 3, x1, 0xfffffffffffff800, lui x1, 0xfffff;sra x1,x1,1); 22 | TEST_CASE( 4, x1, 0x00000000000007ff, lui x1, 0x7ffff;sra x1,x1,20); 23 | TEST_CASE( 5, x1, 0xfffffffffffff800, lui x1, 0x80000;sra x1,x1,20); 24 | 25 | TEST_CASE( 6, x0, 0, lui x0, 0x80000 ); 26 | 27 | TEST_PASSFAIL 28 | 29 | RVTEST_CODE_END 30 | 31 | .data 32 | RVTEST_DATA_BEGIN 33 | 34 | TEST_DATA 35 | 36 | RVTEST_DATA_END 37 | -------------------------------------------------------------------------------- /riscv-tests/fence_i.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # fence_i.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test self-modifying code and the fence.i instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | li a3, 111 17 | lh a0, insn 18 | lh a1, insn+2 19 | 20 | # test I$ hit 21 | .align 6 22 | sh a0, 1f, t0 23 | sh a1, 1f+2, t0 24 | fence.i 25 | 26 | 1: addi a3, a3, 222 27 | TEST_CASE( 2, a3, 444, nop ) 28 | 29 | # test prefetcher hit 30 | li a4, 100 31 | 1: addi a4, a4, -1 32 | bnez a4, 1b 33 | 34 | sh a0, 1f, t0 35 | sh a1, 1f+2, t0 36 | fence.i 37 | 38 | .align 6 39 | 1: addi a3, a3, 555 40 | TEST_CASE( 3, a3, 777, nop ) 41 | 42 | TEST_PASSFAIL 43 | 44 | RVTEST_CODE_END 45 | 46 | .data 47 | RVTEST_DATA_BEGIN 48 | 49 | TEST_DATA 50 | 51 | insn: 52 | addi a3, a3, 333 53 | 54 | RVTEST_DATA_END 55 | -------------------------------------------------------------------------------- /software/bootloader/bootloader.ld: -------------------------------------------------------------------------------- 1 | /* Linker script for standalone test applications for the RISCY SoC 2 | The RISCY Processor - A simple RISC-V based processor for FPGAs 3 | (c) Krishna Subramanian 4 | */ 5 | 6 | ENTRY(_start) 7 | 8 | MEMORY 9 | { 10 | RAM (rwx) : ORIGIN = 0x00000000, LENGTH = 0x00020000 11 | AEE_ROM (rx) : ORIGIN = 0xffff8000, LENGTH = 0x00004000 12 | AEE_RAM (rw) : ORIGIN = 0xffffc000, LENGTH = 0x00004000 13 | } 14 | 15 | SECTIONS 16 | { 17 | .text : 18 | { 19 | *(.init) 20 | *(.text*) 21 | __text_end = .; 22 | *(.rodata*) 23 | } > AEE_ROM 24 | 25 | .data : AT(ADDR(.text) + SIZEOF(.text)) 26 | { 27 | __data_begin = .; 28 | *(.data*) 29 | *(.eh_frame*) 30 | __data_end = ALIGN(4); 31 | } > AEE_RAM 32 | 33 | .bss ALIGN(4) : 34 | { 35 | __bss_begin = .; 36 | *(.bss*) 37 | *(.sbss) 38 | __bss_end = ALIGN(4); 39 | } > AEE_RAM 40 | 41 | /* Use the top of RAM and downwards for the stack: */ 42 | __stack_top = 0x00000000; 43 | 44 | /DISCARD/ : 45 | { 46 | *(.comment) 47 | } 48 | } 49 | 50 | -------------------------------------------------------------------------------- /software/riscy.ld: -------------------------------------------------------------------------------- 1 | /* Linker script for standalone test applications for the RISCY SoC 2 | The RISCY Processor - A simple processor for FPGA Prototyping 3 | The RISCY Processor - A simple RISC-V based processor for FPGAs 4 | (c) Krishna Subramanian 5 | */ 6 | ENTRY(_start) 7 | 8 | MEMORY 9 | { 10 | RAM (rwx) : ORIGIN = 0x00000000, LENGTH = 0x00020000 11 | } 12 | 13 | SECTIONS 14 | { 15 | .text : 16 | { 17 | *(.init) 18 | 19 | __text_begin = .; 20 | *(.text*) 21 | __text_end = .; 22 | } > RAM 23 | 24 | .rodata : 25 | { 26 | __rodata_begin = .; 27 | *(.rodata*) 28 | __rodata_end = .; 29 | } > RAM 30 | 31 | .data : 32 | { 33 | __data_begin = .; 34 | *(.data*) 35 | *(.eh_frame*) 36 | __data_end = .; 37 | } > RAM 38 | 39 | .bss ALIGN(4) : 40 | { 41 | __bss_begin = .; 42 | *(.bss*) 43 | *(.sbss*) 44 | __bss_end = ALIGN(4); 45 | } > RAM 46 | 47 | /* Set the start of the stack to the top of RAM: */ 48 | __stack_top = 0x00020000; 49 | 50 | /DISCARD/ : 51 | { 52 | *(.comment) 53 | } 54 | } 55 | 56 | -------------------------------------------------------------------------------- /software/sha256/Makefile: -------------------------------------------------------------------------------- 1 | # The RISCY Processor Software Components 2 | # The RISCY Processor - A simple RISC-V based processor for FPGAs 3 | # (c) Krishna Subramanian 4 | 5 | 6 | .PHONY: all clean 7 | include ../common.mk 8 | 9 | TARGET_LDFLAGS += -Wl,-T../riscy.ld -Wl,--Map,sha256.map 10 | 11 | OBJECTS := main.o sha256.o start.o 12 | LINKER_SCRIPT := ../riscy.ld 13 | 14 | all: sha256.elf sha256.bin sha256.coe 15 | 16 | sha256.elf: $(OBJECTS) $(LINKER_SCRIPT) 17 | $(TARGET_LD) -o sha256.elf $(TARGET_LDFLAGS) $(OBJECTS) 18 | $(TARGET_SIZE) sha256.elf 19 | 20 | clean: 21 | -$(RM) $(OBJECTS) 22 | -$(RM) sha256.elf sha256.bin sha256.coe sha256.map 23 | 24 | # Object file rules: 25 | 26 | main.o: main.c sha256.h ../../platform.h ../../riscy.h ../../libsoc/timer.h ../../libsoc/uart.h ../../libsoc/icerror.h ../../libsoc/gpio.h 27 | $(TARGET_CC) -c -o $@ $(TARGET_CFLAGS) $< 28 | 29 | sha256.o: sha256.c sha256.h 30 | $(TARGET_CC) -c -o $@ $(TARGET_CFLAGS) $< 31 | 32 | start.o: ../start.S ../../platform.h 33 | $(TARGET_CC) -c -o $@ $(TARGET_CFLAGS) $< 34 | 35 | -------------------------------------------------------------------------------- /src/ry_counter.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | use ieee.numeric_std.all; 7 | 8 | entity ry_counter is 9 | generic( 10 | COUNTER_WIDTH : natural := 64; 11 | COUNTER_STEP : natural := 1 12 | ); 13 | port( 14 | clk : in std_logic; 15 | reset : in std_logic; 16 | 17 | count : out std_logic_vector(COUNTER_WIDTH - 1 downto 0); 18 | increment : in std_logic 19 | ); 20 | end entity ry_counter; 21 | 22 | architecture behaviour of ry_counter is 23 | signal current_count : std_logic_vector(COUNTER_WIDTH - 1 downto 0); 24 | begin 25 | 26 | count <= current_count; 27 | 28 | counter: process(clk) 29 | begin 30 | if rising_edge(clk) then 31 | if reset = '1' then 32 | current_count <= (others => '0'); 33 | elsif increment = '1' then 34 | current_count <= std_logic_vector(unsigned(current_count) + COUNTER_STEP); 35 | end if; 36 | end if; 37 | end process counter; 38 | 39 | end architecture behaviour; 40 | -------------------------------------------------------------------------------- /platform.h: -------------------------------------------------------------------------------- 1 | /* The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | (c) Krishna Subramanian 3 | */ 4 | 5 | #ifndef PAEE_PLATFORM_H 6 | #define PAEE_PLATFORM_H 7 | 8 | // This file contains information about the platform that the PAEE is running 9 | // on. The current version of the file contains information about the Arty- 10 | // based "official" RISCY SoC. 11 | 12 | // System clock frequency: 13 | #define PLATFORM_SYSCLK_FREQ 50000000U 14 | 15 | // Base addresses for peripherals: 16 | #define PLATFORM_TIMER0_BASE 0xc0000000 17 | #define PLATFORM_TIMER1_BASE 0xc0001000 18 | #define PLATFORM_UART0_BASE 0xc0002000 19 | #define PLATFORM_UART1_BASE 0xc0003000 20 | #define PLATFORM_GPIO_BASE 0xc0004000 21 | #define PLATFORM_ICERROR_BASE 0xc0005000 22 | #define PLATFORM_PAEE_ROM_BASE 0xffff8000 23 | #define PLATFORM_PAEE_RAM_BASE 0xffffc000 24 | 25 | // Interrupts: 26 | #define PLATFORM_IRQ_TIMER0 0 27 | #define PLATFORM_IRQ_TIMER1 1 28 | #define PLATFORM_IRQ_UART0 2 29 | #define PLATFORM_IRQ_UART1 3 30 | #define PLATFORM_IRQ_BUS_ERROR 4 31 | 32 | #endif 33 | 34 | -------------------------------------------------------------------------------- /src/dsaf/ry_counter.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | use ieee.numeric_std.all; 7 | 8 | entity ry_counter is 9 | generic( 10 | COUNTER_WIDTH : natural := 64; 11 | COUNTER_STEP : natural := 1 12 | ); 13 | port( 14 | clk : in std_logic; 15 | reset : in std_logic; 16 | 17 | count : out std_logic_vector(COUNTER_WIDTH - 1 downto 0); 18 | increment : in std_logic 19 | ); 20 | end entity ry_counter; 21 | 22 | architecture behaviour of ry_counter is 23 | signal current_count : std_logic_vector(COUNTER_WIDTH - 1 downto 0); 24 | begin 25 | 26 | count <= current_count; 27 | 28 | counter: process(clk) 29 | begin 30 | if rising_edge(clk) then 31 | if reset = '1' then 32 | current_count <= (others => '0'); 33 | elsif increment = '1' then 34 | current_count <= std_logic_vector(unsigned(current_count) + COUNTER_STEP); 35 | end if; 36 | end if; 37 | end process counter; 38 | 39 | end architecture behaviour; 40 | -------------------------------------------------------------------------------- /software/common.mk: -------------------------------------------------------------------------------- 1 | # The RISCY Processor - Applications 2 | # The RISCY Processor - A simple RISC-V based processor for FPGAs 3 | # (c) Krishna Subramanian 4 | 5 | # Tools used to build applications: 6 | TARGET_PREFIX ?= riscv32-unknown-elf 7 | TARGET_CC := $(TARGET_PREFIX)-gcc 8 | TARGET_LD := $(TARGET_PREFIX)-gcc 9 | TARGET_SIZE := $(TARGET_PREFIX)-size 10 | TARGET_OBJCOPY := $(TARGET_PREFIX)-objcopy 11 | HEXDUMP ?= hexdump 12 | 13 | TARGET_CFLAGS += -march=rv32i -Wall -Os -fomit-frame-pointer \ 14 | -ffreestanding -fno-builtin -I../.. -I../../libsoc -std=gnu99 \ 15 | -Wall -Werror=implicit-function-declaration -ffunction-sections -fdata-sections 16 | TARGET_LDFLAGS += -march=rv32i -nostartfiles -L../libsoc \ 17 | -Wl,-m,elf32lriscv --specs=nosys.specs -Wl,--no-relax -Wl,--gc-sections 18 | 19 | # Rule for converting an ELF file to a binary file: 20 | %.bin: %.elf 21 | $(TARGET_OBJCOPY) -j .text -j .data -j .rodata -O binary $< $@ 22 | 23 | # Rule for generating coefficient files for initializing block RAM resources 24 | # from binary files: 25 | %.coe: %.bin 26 | echo "memory_initialization_radix=16;" > $@ 27 | echo "memory_initialization_vector=" >> $@ 28 | $(HEXDUMP) -v -e '1/4 "%08x\n"' $< >> $@ 29 | echo ";" >> $@ 30 | 31 | -------------------------------------------------------------------------------- /src/ry_csr_alu.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | use ieee.numeric_std.all; 7 | 8 | use work.ry_csr.all; 9 | 10 | --! @brief ALU used for calculating new values of control and status registers. 11 | entity ry_csr_alu is 12 | port( 13 | x, y : in std_logic_vector(31 downto 0); 14 | result : out std_logic_vector(31 downto 0); 15 | immediate : in std_logic_vector(4 downto 0); 16 | use_immediate : in std_logic; 17 | write_mode : in csr_write_mode 18 | ); 19 | end entity ry_csr_alu; 20 | 21 | architecture behaviour of ry_csr_alu is 22 | signal a, b : std_logic_vector(31 downto 0); 23 | begin 24 | 25 | a <= x; 26 | b <= y when use_immediate = '0' else std_logic_vector(resize(unsigned(immediate), b'length)); 27 | 28 | calculate: process(a, b, write_mode) 29 | begin 30 | case write_mode is 31 | when CSR_WRITE_NONE => 32 | result <= a; 33 | when CSR_WRITE_SET => 34 | result <= a or b; 35 | when CSR_WRITE_CLEAR => 36 | result <= a and (not b); 37 | when CSR_WRITE_REPLACE => 38 | result <= b; 39 | end case; 40 | end process calculate; 41 | 42 | end architecture behaviour; 43 | -------------------------------------------------------------------------------- /src/dsaf/ry_csr_alu.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | use ieee.numeric_std.all; 7 | 8 | use work.ry_csr.all; 9 | 10 | --! @brief ALU used for calculating new values of control and status registers. 11 | entity ry_csr_alu is 12 | port( 13 | x, y : in std_logic_vector(31 downto 0); 14 | result : out std_logic_vector(31 downto 0); 15 | immediate : in std_logic_vector(4 downto 0); 16 | use_immediate : in std_logic; 17 | write_mode : in csr_write_mode 18 | ); 19 | end entity ry_csr_alu; 20 | 21 | architecture behaviour of ry_csr_alu is 22 | signal a, b : std_logic_vector(31 downto 0); 23 | begin 24 | 25 | a <= x; 26 | b <= y when use_immediate = '0' else std_logic_vector(resize(unsigned(immediate), b'length)); 27 | 28 | calculate: process(a, b, write_mode) 29 | begin 30 | case write_mode is 31 | when CSR_WRITE_NONE => 32 | result <= a; 33 | when CSR_WRITE_SET => 34 | result <= a or b; 35 | when CSR_WRITE_CLEAR => 36 | result <= a and (not b); 37 | when CSR_WRITE_REPLACE => 38 | result <= b; 39 | end case; 40 | end process calculate; 41 | 42 | end architecture behaviour; 43 | -------------------------------------------------------------------------------- /example/tb_toplevel.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | 7 | entity tb_toplevel is 8 | end entity tb_toplevel; 9 | 10 | architecture testbench of tb_toplevel is 11 | 12 | signal clk : std_logic := '0'; 13 | constant clk_period : time := 10 ns; 14 | 15 | signal reset_n : std_logic := '0'; 16 | 17 | signal gpio_pins : std_logic_vector(11 downto 0); 18 | 19 | signal uart0_txd : std_logic; 20 | signal uart0_rxd : std_logic := '1'; 21 | 22 | signal uart1_txd : std_logic; 23 | signal uart1_rxd : std_logic := '1'; 24 | 25 | begin 26 | 27 | uut: entity work.toplevel 28 | port map( 29 | clk => clk, 30 | reset_n => reset_n, 31 | gpio_pins => gpio_pins, 32 | uart0_txd => uart0_txd, 33 | uart0_rxd => uart0_rxd, 34 | uart1_txd => uart1_txd, 35 | uart1_rxd => uart1_rxd 36 | ); 37 | 38 | clock: process 39 | begin 40 | clk <= '0'; 41 | wait for clk_period / 2; 42 | clk <= '1'; 43 | wait for clk_period / 2; 44 | end process clock; 45 | 46 | stimulus: process 47 | begin 48 | reset_n <= '0'; 49 | wait for clk_period * 4; 50 | reset_n <= '1'; 51 | 52 | wait; 53 | end process stimulus; 54 | 55 | end architecture testbench; 56 | -------------------------------------------------------------------------------- /riscv-tests/jal.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # jal.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test jal instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Test 2: Basic test 18 | #------------------------------------------------------------- 19 | 20 | test_2: 21 | li TESTNUM, 2 22 | li ra, 0 23 | 24 | jal x4, target_2 25 | linkaddr_2: 26 | nop 27 | nop 28 | 29 | j fail 30 | 31 | target_2: 32 | la x2, linkaddr_2 33 | bne x2, x4, fail 34 | 35 | #------------------------------------------------------------- 36 | # Test delay slot instructions not executed nor bypassed 37 | #------------------------------------------------------------- 38 | 39 | TEST_CASE( 3, ra, 3, \ 40 | li ra, 1; \ 41 | jal x0, 1f; \ 42 | addi ra, ra, 1; \ 43 | addi ra, ra, 1; \ 44 | addi ra, ra, 1; \ 45 | addi ra, ra, 1; \ 46 | 1: addi ra, ra, 1; \ 47 | addi ra, ra, 1; \ 48 | ) 49 | 50 | TEST_PASSFAIL 51 | 52 | RVTEST_CODE_END 53 | 54 | .data 55 | RVTEST_DATA_BEGIN 56 | 57 | TEST_DATA 58 | 59 | RVTEST_DATA_END 60 | -------------------------------------------------------------------------------- /src/ry_comparator.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | use ieee.numeric_std.all; 7 | 8 | use work.ry_utilities.all; 9 | 10 | --! @brief Component for comparing two registers in the ID stage whens branching. 11 | entity ry_comparator is 12 | port( 13 | funct3 : in std_logic_vector(14 downto 12); 14 | rs1, rs2 : in std_logic_vector(31 downto 0); 15 | result : out std_logic --! Result of the comparison. 16 | ); 17 | end entity ry_comparator; 18 | 19 | architecture behaviour of ry_comparator is 20 | begin 21 | 22 | compare: process(funct3, rs1, rs2) 23 | begin 24 | case funct3 is 25 | when b"000" => -- EQ 26 | result <= to_std_logic(rs1 = rs2); 27 | when b"001" => -- NE 28 | result <= to_std_logic(rs1 /= rs2); 29 | when b"100" => -- LT 30 | result <= to_std_logic(signed(rs1) < signed(rs2)); 31 | when b"101" => -- GE 32 | result <= to_std_logic(signed(rs1) >= signed(rs2)); 33 | when b"110" => -- LTU 34 | result <= to_std_logic(unsigned(rs1) < unsigned(rs2)); 35 | when b"111" => -- GEU 36 | result <= to_std_logic(unsigned(rs1) >= unsigned(rs2)); 37 | when others => 38 | result <= '0'; 39 | end case; 40 | end process compare; 41 | 42 | end architecture behaviour; 43 | -------------------------------------------------------------------------------- /src/dsaf/ry_comparator.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | use ieee.numeric_std.all; 7 | 8 | use work.ry_utilities.all; 9 | 10 | --! @brief Component for comparing two registers in the ID stage whens branching. 11 | entity ry_comparator is 12 | port( 13 | funct3 : in std_logic_vector(14 downto 12); 14 | rs1, rs2 : in std_logic_vector(31 downto 0); 15 | result : out std_logic --! Result of the comparison. 16 | ); 17 | end entity ry_comparator; 18 | 19 | architecture behaviour of ry_comparator is 20 | begin 21 | 22 | compare: process(funct3, rs1, rs2) 23 | begin 24 | case funct3 is 25 | when b"000" => -- EQ 26 | result <= to_std_logic(rs1 = rs2); 27 | when b"001" => -- NE 28 | result <= to_std_logic(rs1 /= rs2); 29 | when b"100" => -- LT 30 | result <= to_std_logic(signed(rs1) < signed(rs2)); 31 | when b"101" => -- GE 32 | result <= to_std_logic(signed(rs1) >= signed(rs2)); 33 | when b"110" => -- LTU 34 | result <= to_std_logic(unsigned(rs1) < unsigned(rs2)); 35 | when b"111" => -- GEU 36 | result <= to_std_logic(unsigned(rs1) >= unsigned(rs2)); 37 | when others => 38 | result <= '0'; 39 | end case; 40 | end process compare; 41 | 42 | end architecture behaviour; 43 | -------------------------------------------------------------------------------- /software/bootloader/main.c: -------------------------------------------------------------------------------- 1 | /* The RISCY Processor Benchmark Applications 2 | The RISCY Processor - A simple RISC-V based processor for FPGAs 3 | (c) Krishna Subramanian 4 | */ 5 | 6 | #include 7 | 8 | #include "platform.h" 9 | #include "uart.h" 10 | 11 | #define APP_START (0x00000000) 12 | #define APP_LEN (0x20000) 13 | #define APP_ENTRY (0x00000000) 14 | 15 | static struct uart uart0; 16 | 17 | void exception_handler(uint32_t cause, void * epc, void * regbase) 18 | { 19 | while(uart_tx_fifo_full(&uart0)); 20 | uart_tx(&uart0, 'E'); 21 | } 22 | 23 | int main(void) 24 | { 25 | uart_initialize(&uart0, (volatile void *) PLATFORM_UART0_BASE); 26 | uart_set_divisor(&uart0, uart_baud2divisor(115200, PLATFORM_SYSCLK_FREQ)); 27 | 28 | /* Print welcome message */ 29 | uart_tx_string(&uart0, "\n\r** RISCY Bootloader - waiting for application image **\n\r"); 30 | 31 | /* Read application from UART and store it in RAM */ 32 | for(int i = 0; i < APP_LEN; i++){ 33 | while(uart_rx_fifo_empty(&uart0)); 34 | *((volatile uint8_t*)(APP_START + i)) = uart_rx(&uart0); 35 | 36 | /* Print some dots */ 37 | if(((i & 0x7ff) == 0) && !uart_tx_fifo_full(&uart0)) 38 | uart_tx(&uart0, '.'); 39 | } 40 | 41 | /* Print booting message */ 42 | uart_tx_string(&uart0, "\n\rBooting\n\r"); 43 | 44 | /* Jump in RAM */ 45 | goto *APP_ENTRY; 46 | 47 | return 0; 48 | } 49 | 50 | -------------------------------------------------------------------------------- /docs/Doxyfile: -------------------------------------------------------------------------------- 1 | # The RISCY Project 2 | # (c) Krishna Subramanian 3 | # Report bugs and issues on 4 | 5 | DOXYFILE_ENCODING = UTF-8 6 | INPUT_ENCODING = UTF-8 7 | 8 | TAB_SIZE = 8 9 | OPTIMIZE_OUTPUT_VHDL = YES 10 | 11 | PROJECT_NAME = "The RISCY Processor" 12 | PROJECT_BRIEF = "A 32-bit RISC-V implementation" 13 | 14 | OUTPUT_DIRECTORY = "manual/" 15 | 16 | BRIEF_MEMBER_DESC = YES 17 | REPEAT_BRIEF = YES 18 | 19 | JAVADOC_AUTOBRIEF = YES 20 | QT_AUTOBRIEF = NO 21 | MULTILINE_CPP_IS_BRIEF = NO 22 | 23 | ALIASES = 24 | 25 | MARKDOWN_SUPPORT = YES 26 | AUTOLINK_SUPPORT = YES 27 | 28 | EXTRACT_ALL = NO 29 | HIDE_UNDOC_MEMBERS = NO 30 | HIDE_SCOPE_NAMES = YES 31 | SHOW_INCLUDE_FILES = NO 32 | SORT_MEMBER_DOCS = YES 33 | 34 | GENERATE_TODOLIST = YES 35 | GENERATE_BUGLIST = YES 36 | 37 | SHOW_FILES = NO 38 | 39 | WARN_IF_UNDOCUMENTED = YES 40 | WARN_IF_DOC_ERROR = YES 41 | WARN_NO_PARAMDOC = YES 42 | 43 | INPUT = ../src/ 44 | FILE_PATTERNS = *.vhd 45 | USE_MDFILE_AS_MAINPAGE = ../README.md 46 | 47 | ALPHABETICAL_INDEX = YES 48 | 49 | GENERATE_HTML = YES 50 | HTML_OUTPUT = . 51 | HTML_FILE_EXTENSION = .html 52 | GENERATE_TREEVIEW = YES 53 | 54 | GENERATE_LATEX = NO 55 | 56 | -------------------------------------------------------------------------------- /riscv-tests/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2015, The Regents of the University of California (Regents). 2 | All Rights Reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 1. Redistributions of source code must retain the above copyright 7 | notice, this list of conditions and the following disclaimer. 8 | 2. Redistributions in binary form must reproduce the above copyright 9 | notice, this list of conditions and the following disclaimer in the 10 | documentation and/or other materials provided with the distribution. 11 | 3. Neither the name of the Regents nor the 12 | names of its contributors may be used to endorse or promote products 13 | derived from this software without specific prior written permission. 14 | 15 | IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, 16 | SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST PROFITS, ARISING 17 | OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF REGENTS HAS 18 | BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 19 | 20 | REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 21 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 | PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION, IF ANY, PROVIDED 23 | HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO OBLIGATION TO PROVIDE 24 | MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 25 | -------------------------------------------------------------------------------- /src/ry_imm_decoder.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | 7 | --! @brief Module decoding immediate values from instruction words. 8 | entity ry_imm_decoder is 9 | port( 10 | instruction : in std_logic_vector(31 downto 2); 11 | immediate : out std_logic_vector(31 downto 0) 12 | ); 13 | end entity ry_imm_decoder; 14 | 15 | architecture behaviour of ry_imm_decoder is 16 | begin 17 | decode: process(instruction) 18 | begin 19 | case instruction(6 downto 2) is 20 | when b"01101" | b"00101" => -- U type 21 | immediate <= instruction(31 downto 12) & (11 downto 0 => '0'); 22 | when b"11011" => -- J type 23 | immediate <= (31 downto 20 => instruction(31)) & instruction(19 downto 12) & instruction(20) & instruction(30 downto 21) & '0'; 24 | when b"11001" | b"00000" | b"00100" | b"11100"=> -- I type 25 | immediate <= (31 downto 11 => instruction(31)) & instruction(30 downto 20); 26 | when b"11000" => -- B type 27 | immediate <= (31 downto 12 => instruction(31)) & instruction(7) & instruction(30 downto 25) & instruction(11 downto 8) & '0'; 28 | when b"01000" => -- S type 29 | immediate <= (31 downto 11 => instruction(31)) & instruction(30 downto 25) & instruction(11 downto 7); 30 | when others => 31 | immediate <= (others => '0'); 32 | end case; 33 | end process decode; 34 | end architecture behaviour; 35 | -------------------------------------------------------------------------------- /src/dsaf/ry_imm_decoder.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | 7 | --! @brief Module decoding immediate values from instruction words. 8 | entity ry_imm_decoder is 9 | port( 10 | instruction : in std_logic_vector(31 downto 2); 11 | immediate : out std_logic_vector(31 downto 0) 12 | ); 13 | end entity ry_imm_decoder; 14 | 15 | architecture behaviour of ry_imm_decoder is 16 | begin 17 | decode: process(instruction) 18 | begin 19 | case instruction(6 downto 2) is 20 | when b"01101" | b"00101" => -- U type 21 | immediate <= instruction(31 downto 12) & (11 downto 0 => '0'); 22 | when b"11011" => -- J type 23 | immediate <= (31 downto 20 => instruction(31)) & instruction(19 downto 12) & instruction(20) & instruction(30 downto 21) & '0'; 24 | when b"11001" | b"00000" | b"00100" | b"11100"=> -- I type 25 | immediate <= (31 downto 11 => instruction(31)) & instruction(30 downto 20); 26 | when b"11000" => -- B type 27 | immediate <= (31 downto 12 => instruction(31)) & instruction(7) & instruction(30 downto 25) & instruction(11 downto 8) & '0'; 28 | when b"01000" => -- S type 29 | immediate <= (31 downto 11 => instruction(31)) & instruction(30 downto 25) & instruction(11 downto 7); 30 | when others => 31 | immediate <= (others => '0'); 32 | end case; 33 | end process decode; 34 | end architecture behaviour; 35 | -------------------------------------------------------------------------------- /src/ry_alu_mux.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | library ieee; 4 | use ieee.std_logic_1164.all; 5 | use ieee.numeric_std.all; 6 | 7 | use work.ry_types.all; 8 | 9 | --! @brief Multiplexer used to choose between ALU inputs. 10 | entity ry_alu_mux is 11 | port( 12 | source : in alu_operand_source; 13 | 14 | register_value : in std_logic_vector(31 downto 0); 15 | immediate_value : in std_logic_vector(31 downto 0); 16 | shamt_value : in std_logic_vector( 4 downto 0); 17 | pc_value : in std_logic_vector(31 downto 0); 18 | csr_value : in std_logic_vector(31 downto 0); 19 | 20 | output : out std_logic_vector(31 downto 0) 21 | ); 22 | end entity ry_alu_mux; 23 | 24 | architecture behaviour of ry_alu_mux is 25 | begin 26 | 27 | mux: process(source, register_value, immediate_value, shamt_value, pc_value, csr_value) 28 | begin 29 | case source is 30 | when ALU_SRC_REG => 31 | output <= register_value; 32 | when ALU_SRC_IMM => 33 | output <= immediate_value; 34 | when ALU_SRC_PC => 35 | output <= pc_value; 36 | when ALU_SRC_PC_NEXT => 37 | output <= std_logic_vector(unsigned(pc_value) + 4); 38 | when ALU_SRC_CSR => 39 | output <= csr_value; 40 | when ALU_SRC_SHAMT => 41 | output <= (31 downto 5 => '0') & shamt_value; 42 | when ALU_SRC_NULL => 43 | output <= (others => '0'); 44 | end case; 45 | end process mux; 46 | 47 | end architecture behaviour; 48 | -------------------------------------------------------------------------------- /src/ry_register_file.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | use ieee.numeric_std.all; 7 | 8 | use work.ry_types.all; 9 | use work.ry_utilities.all; 10 | 11 | --! @brief 32-bit RISC-V register file. 12 | entity ry_register_file is 13 | port( 14 | clk : in std_logic; 15 | 16 | -- Read port 1: 17 | rs1_addr : in register_address; 18 | rs1_data : out std_logic_vector(31 downto 0); 19 | 20 | -- Read port 2: 21 | rs2_addr : in register_address; 22 | rs2_data : out std_logic_vector(31 downto 0); 23 | 24 | -- Write port: 25 | rd_addr : in register_address; 26 | rd_data : in std_logic_vector(31 downto 0); 27 | rd_write : in std_logic 28 | ); 29 | end entity ry_register_file; 30 | 31 | architecture behaviour of ry_register_file is 32 | 33 | --! Register array type. 34 | type regfile_array is array(0 to 31) of std_logic_vector(31 downto 0); 35 | 36 | begin 37 | 38 | regfile: process(clk) 39 | variable registers : regfile_array := (others => (others => '0')); 40 | begin 41 | if rising_edge(clk) then 42 | if rd_write = '1' and rd_addr /= b"00000" then 43 | registers(to_integer(unsigned(rd_addr))) := rd_data; 44 | end if; 45 | 46 | rs1_data <= registers(to_integer(unsigned(rs1_addr))); 47 | rs2_data <= registers(to_integer(unsigned(rs2_addr))); 48 | end if; 49 | end process regfile; 50 | 51 | end architecture behaviour; 52 | -------------------------------------------------------------------------------- /src/dsaf/ry_alu_mux.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | library ieee; 4 | use ieee.std_logic_1164.all; 5 | use ieee.numeric_std.all; 6 | 7 | use work.ry_types.all; 8 | 9 | --! @brief Multiplexer used to choose between ALU inputs. 10 | entity ry_alu_mux is 11 | port( 12 | source : in alu_operand_source; 13 | 14 | register_value : in std_logic_vector(31 downto 0); 15 | immediate_value : in std_logic_vector(31 downto 0); 16 | shamt_value : in std_logic_vector( 4 downto 0); 17 | pc_value : in std_logic_vector(31 downto 0); 18 | csr_value : in std_logic_vector(31 downto 0); 19 | 20 | output : out std_logic_vector(31 downto 0) 21 | ); 22 | end entity ry_alu_mux; 23 | 24 | architecture behaviour of ry_alu_mux is 25 | begin 26 | 27 | mux: process(source, register_value, immediate_value, shamt_value, pc_value, csr_value) 28 | begin 29 | case source is 30 | when ALU_SRC_REG => 31 | output <= register_value; 32 | when ALU_SRC_IMM => 33 | output <= immediate_value; 34 | when ALU_SRC_PC => 35 | output <= pc_value; 36 | when ALU_SRC_PC_NEXT => 37 | output <= std_logic_vector(unsigned(pc_value) + 4); 38 | when ALU_SRC_CSR => 39 | output <= csr_value; 40 | when ALU_SRC_SHAMT => 41 | output <= (31 downto 5 => '0') & shamt_value; 42 | when ALU_SRC_NULL => 43 | output <= (others => '0'); 44 | end case; 45 | end process mux; 46 | 47 | end architecture behaviour; 48 | -------------------------------------------------------------------------------- /src/dsaf/ry_register_file.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | use ieee.numeric_std.all; 7 | 8 | use work.ry_types.all; 9 | use work.ry_utilities.all; 10 | 11 | --! @brief 32-bit RISC-V register file. 12 | entity ry_register_file is 13 | port( 14 | clk : in std_logic; 15 | 16 | -- Read port 1: 17 | rs1_addr : in register_address; 18 | rs1_data : out std_logic_vector(31 downto 0); 19 | 20 | -- Read port 2: 21 | rs2_addr : in register_address; 22 | rs2_data : out std_logic_vector(31 downto 0); 23 | 24 | -- Write port: 25 | rd_addr : in register_address; 26 | rd_data : in std_logic_vector(31 downto 0); 27 | rd_write : in std_logic 28 | ); 29 | end entity ry_register_file; 30 | 31 | architecture behaviour of ry_register_file is 32 | 33 | --! Register array type. 34 | type regfile_array is array(0 to 31) of std_logic_vector(31 downto 0); 35 | 36 | begin 37 | 38 | regfile: process(clk) 39 | variable registers : regfile_array := (others => (others => '0')); 40 | begin 41 | if rising_edge(clk) then 42 | if rd_write = '1' and rd_addr /= b"00000" then 43 | registers(to_integer(unsigned(rd_addr))) := rd_data; 44 | end if; 45 | 46 | rs1_data <= registers(to_integer(unsigned(rs1_addr))); 47 | rs2_data <= registers(to_integer(unsigned(rs2_addr))); 48 | end if; 49 | end process regfile; 50 | 51 | end architecture behaviour; 52 | -------------------------------------------------------------------------------- /riscv-tests/jalr.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # jalr.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test jalr instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Test 2: Basic test 18 | #------------------------------------------------------------- 19 | 20 | test_2: 21 | li TESTNUM, 2 22 | li t0, 0 23 | la t1, target_2 24 | 25 | jalr t0, t1, 0 26 | linkaddr_2: 27 | j fail 28 | 29 | target_2: 30 | la t1, linkaddr_2 31 | bne t0, t1, fail 32 | 33 | #------------------------------------------------------------- 34 | # Bypassing tests 35 | #------------------------------------------------------------- 36 | 37 | TEST_JALR_SRC1_BYPASS( 4, 0, jalr ); 38 | TEST_JALR_SRC1_BYPASS( 5, 1, jalr ); 39 | TEST_JALR_SRC1_BYPASS( 6, 2, jalr ); 40 | 41 | #------------------------------------------------------------- 42 | # Test delay slot instructions not executed nor bypassed 43 | #------------------------------------------------------------- 44 | 45 | .option push 46 | .option norvc 47 | TEST_CASE( 7, t0, 4, \ 48 | li t0, 1; \ 49 | la t1, 1f; \ 50 | jr t1, -4; \ 51 | addi t0, t0, 1; \ 52 | addi t0, t0, 1; \ 53 | addi t0, t0, 1; \ 54 | addi t0, t0, 1; \ 55 | 1: addi t0, t0, 1; \ 56 | addi t0, t0, 1; \ 57 | ) 58 | .option pop 59 | 60 | TEST_PASSFAIL 61 | 62 | RVTEST_CODE_END 63 | 64 | .data 65 | RVTEST_DATA_BEGIN 66 | 67 | TEST_DATA 68 | 69 | RVTEST_DATA_END 70 | -------------------------------------------------------------------------------- /example/aee_rom_wrapper.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | use ieee.numeric_std.all; 7 | 8 | use work.pp_utilities.all; 9 | 10 | entity aee_rom_wrapper is 11 | generic( 12 | MEMORY_SIZE : natural := 4096 --! Memory size in bytes. 13 | ); 14 | port( 15 | clk : in std_logic; 16 | reset : in std_logic; 17 | 18 | -- Wishbone interface: 19 | wb_adr_in : in std_logic_vector(log2(MEMORY_SIZE) - 1 downto 0); 20 | wb_dat_out : out std_logic_vector(31 downto 0); 21 | wb_cyc_in : in std_logic; 22 | wb_stb_in : in std_logic; 23 | wb_sel_in : in std_logic_vector(3 downto 0); 24 | wb_ack_out : out std_logic 25 | ); 26 | end entity aee_rom_wrapper; 27 | 28 | architecture behaviour of aee_rom_wrapper is 29 | signal ack : std_logic; 30 | 31 | signal read_data : std_logic_vector(31 downto 0); 32 | signal data_mask : std_logic_vector(31 downto 0); 33 | 34 | begin 35 | 36 | rom: entity work.aee_rom 37 | port map( 38 | clka => clk, 39 | addra => wb_adr_in(log2(MEMORY_SIZE) - 1 downto 2), 40 | douta => read_data 41 | ); 42 | 43 | data_mask <= (31 downto 24 => wb_sel_in(3), 23 downto 16 => wb_sel_in(2), 44 | 15 downto 8 => wb_sel_in(1), 7 downto 0 => wb_sel_in(0)); 45 | 46 | wb_dat_out <= read_data and data_mask; 47 | 48 | wb_ack_out <= ack and wb_cyc_in and wb_stb_in; 49 | 50 | wishbone: process(clk) 51 | begin 52 | if rising_edge(clk) then 53 | if reset = '1' then 54 | ack <= '0'; 55 | else 56 | if wb_cyc_in = '1' and wb_stb_in = '1' then 57 | ack <= '1'; 58 | else 59 | ack <= '0'; 60 | end if; 61 | end if; 62 | end if; 63 | end process wishbone; 64 | 65 | end architecture behaviour; 66 | -------------------------------------------------------------------------------- /riscv-tests/andi.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # andi.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test andi instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Logical tests 18 | #------------------------------------------------------------- 19 | 20 | TEST_IMM_OP( 2, andi, 0xff00ff00, 0xff00ff00, 0xf0f ); 21 | TEST_IMM_OP( 3, andi, 0x000000f0, 0x0ff00ff0, 0x0f0 ); 22 | TEST_IMM_OP( 4, andi, 0x0000000f, 0x00ff00ff, 0x70f ); 23 | TEST_IMM_OP( 5, andi, 0x00000000, 0xf00ff00f, 0x0f0 ); 24 | 25 | #------------------------------------------------------------- 26 | # Source/Destination tests 27 | #------------------------------------------------------------- 28 | 29 | TEST_IMM_SRC1_EQ_DEST( 6, andi, 0x00000000, 0xff00ff00, 0x0f0 ); 30 | 31 | #------------------------------------------------------------- 32 | # Bypassing tests 33 | #------------------------------------------------------------- 34 | 35 | TEST_IMM_DEST_BYPASS( 7, 0, andi, 0x00000700, 0x0ff00ff0, 0x70f ); 36 | TEST_IMM_DEST_BYPASS( 8, 1, andi, 0x000000f0, 0x00ff00ff, 0x0f0 ); 37 | TEST_IMM_DEST_BYPASS( 9, 2, andi, 0xf00ff00f, 0xf00ff00f, 0xf0f ); 38 | 39 | TEST_IMM_SRC1_BYPASS( 10, 0, andi, 0x00000700, 0x0ff00ff0, 0x70f ); 40 | TEST_IMM_SRC1_BYPASS( 11, 1, andi, 0x000000f0, 0x00ff00ff, 0x0f0 ); 41 | TEST_IMM_SRC1_BYPASS( 12, 2, andi, 0x0000000f, 0xf00ff00f, 0x70f ); 42 | 43 | TEST_IMM_ZEROSRC1( 13, andi, 0, 0x0f0 ); 44 | TEST_IMM_ZERODEST( 14, andi, 0x00ff00ff, 0x70f ); 45 | 46 | TEST_PASSFAIL 47 | 48 | RVTEST_CODE_END 49 | 50 | .data 51 | RVTEST_DATA_BEGIN 52 | 53 | TEST_DATA 54 | 55 | RVTEST_DATA_END 56 | -------------------------------------------------------------------------------- /riscy-test.h: -------------------------------------------------------------------------------- 1 | /* The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | (c) Krishna Subramanian 3 | */ 4 | 5 | #ifndef RISCY_TEST_H 6 | #define RISCY_TEST_H 7 | 8 | // Ensure that the following define is set to use this header in assembly code: 9 | // #define RISCY_TEST_ASSEMBLY 10 | 11 | // Address of the test and debug CSR: 12 | #define RISCY_TEST_CSR 0xbf0 13 | 14 | // Value of the test state field when no test is running: 15 | #define RISCY_TEST_STATE_IDLE 0x0 16 | // Value of the test state field when a test is running: 17 | #define RISCY_TEST_STATE_RUNNING 0x1 18 | // Value of the test state field when a test has failed: 19 | #define RISCY_TEST_STATE_FAILED 0x2 20 | // Value of the test state field when a test has passed: 21 | #define RISCY_TEST_STATE_PASSED 0x3 22 | 23 | #ifdef RISCY_TEST_ASSEMBLY 24 | 25 | #define RISCY_TEST_START(testnum, tempreg) \ 26 | li tempreg, testnum; \ 27 | slli tempreg, tempreg, 2; \ 28 | ori tempreg, tempreg, RISCY_TEST_STATE_RUNNING; \ 29 | csrw RISCY_TEST_CSR, tempreg; 30 | 31 | #define RISCY_TEST_FAIL() \ 32 | csrci RISCY_TEST_CSR, 3; \ 33 | csrsi RISCY_TEST_CSR, RISCY_TEST_STATE_FAILED; 34 | 35 | #define RISCY_TEST_PASS() \ 36 | csrci RISCY_TEST_CSR, 3; \ 37 | csrsi RISCY_TEST_CSR, RISCY_TEST_STATE_PASSED; 38 | #else 39 | 40 | #define RISCY_TEST_START(testnum) \ 41 | do { \ 42 | uint32_t temp = testnum << 3 | RISCY_TEST_STATE_RUNNING; \ 43 | asm volatile("csrw %[regname], %[regval]\n\t" :: [regname] "i" (RISCY_TEST_CSR), [regval] "r" (temp)); \ 44 | } while(0) 45 | 46 | #define RISCY_TEST_FAIL() \ 47 | asm volatile("csrrci x0, %[regname], 3\n\tcsrrsi x0, %[regname], %[state]\n\t" \ 48 | :: [regname] "i" (RISCY_TEST_CSR), [state] "i" (RISCY_TEST_STATE_FAILED)) 49 | #define RISCY_TEST_PASS() \ 50 | asm volatile("csrrci x0, %[regname], 3\n\tcsrrsi x0, %[regname], %[state]\n\t" \ 51 | :: [regname] "i" (RISCY_TEST_CSR), [state] "i" (RISCY_TEST_STATE_PASSED)) 52 | #endif 53 | 54 | #endif 55 | 56 | -------------------------------------------------------------------------------- /soc/ry_soc_reset.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple processor for FPGA Prototyping 2 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 3 | -- (c) Krishna Subramanian 4 | 5 | library ieee; 6 | use ieee.std_logic_1164.all; 7 | use work.ry_utilities.all; 8 | 9 | --! @brief System reset unit. 10 | --! Because most resets in the processor core are synchronous, at least one 11 | --! clock pulse has to be given to the processor while the reset signal is 12 | --! asserted. However, if the clock generator is being reset at the same time, 13 | --! the system clock might not run during reset, preventing the processor from 14 | --! properly resetting. 15 | entity ry_soc_reset is 16 | generic( 17 | RESET_CYCLE_COUNT : natural := 1 18 | ); 19 | port( 20 | clk : in std_logic; 21 | 22 | reset_n : in std_logic; 23 | reset_out : out std_logic; 24 | 25 | system_clk : in std_logic; 26 | system_clk_locked : in std_logic 27 | ); 28 | end entity ry_soc_reset; 29 | 30 | architecture behaviour of ry_soc_reset is 31 | 32 | subtype counter_type is natural range 0 to RESET_CYCLE_COUNT; 33 | signal counter : counter_type; 34 | 35 | signal fast_reset : std_logic := '0'; 36 | signal slow_reset : std_logic := '1'; 37 | begin 38 | 39 | reset_out <= fast_reset or slow_reset; 40 | 41 | process(clk) 42 | begin 43 | if rising_edge(clk) then 44 | if reset_n = '0' then 45 | fast_reset <= '1'; 46 | elsif system_clk_locked = '1' then 47 | if fast_reset = '1' and slow_reset = '1' then 48 | fast_reset <= '0'; 49 | end if; 50 | end if; 51 | end if; 52 | end process; 53 | 54 | process(system_clk) 55 | begin 56 | if rising_edge(system_clk) then 57 | if fast_reset = '1' then 58 | slow_reset <= '1'; 59 | counter <= RESET_CYCLE_COUNT; 60 | else 61 | if counter = 0 then 62 | slow_reset <= '0'; 63 | else 64 | counter <= counter - 1; 65 | end if; 66 | end if; 67 | end if; 68 | end process; 69 | 70 | end architecture behaviour; 71 | -------------------------------------------------------------------------------- /riscv-tests/ori.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # ori.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test ori instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Logical tests 18 | #------------------------------------------------------------- 19 | 20 | TEST_IMM_OP( 2, ori, 0xffffffffffffff0f, 0xffffffffff00ff00, 0xf0f ); 21 | TEST_IMM_OP( 3, ori, 0x000000000ff00ff0, 0x000000000ff00ff0, 0x0f0 ); 22 | TEST_IMM_OP( 4, ori, 0x0000000000ff07ff, 0x0000000000ff00ff, 0x70f ); 23 | TEST_IMM_OP( 5, ori, 0xfffffffff00ff0ff, 0xfffffffff00ff00f, 0x0f0 ); 24 | 25 | #------------------------------------------------------------- 26 | # Source/Destination tests 27 | #------------------------------------------------------------- 28 | 29 | TEST_IMM_SRC1_EQ_DEST( 6, ori, 0xff00fff0, 0xff00ff00, 0x0f0 ); 30 | 31 | #------------------------------------------------------------- 32 | # Bypassing tests 33 | #------------------------------------------------------------- 34 | 35 | TEST_IMM_DEST_BYPASS( 7, 0, ori, 0x000000000ff00ff0, 0x000000000ff00ff0, 0x0f0 ); 36 | TEST_IMM_DEST_BYPASS( 8, 1, ori, 0x0000000000ff07ff, 0x0000000000ff00ff, 0x70f ); 37 | TEST_IMM_DEST_BYPASS( 9, 2, ori, 0xfffffffff00ff0ff, 0xfffffffff00ff00f, 0x0f0 ); 38 | 39 | TEST_IMM_SRC1_BYPASS( 10, 0, ori, 0x000000000ff00ff0, 0x000000000ff00ff0, 0x0f0 ); 40 | TEST_IMM_SRC1_BYPASS( 11, 1, ori, 0xffffffffffffffff, 0x0000000000ff00ff, 0xf0f ); 41 | TEST_IMM_SRC1_BYPASS( 12, 2, ori, 0xfffffffff00ff0ff, 0xfffffffff00ff00f, 0x0f0 ); 42 | 43 | TEST_IMM_ZEROSRC1( 13, ori, 0x0f0, 0x0f0 ); 44 | TEST_IMM_ZERODEST( 14, ori, 0x00ff00ff, 0x70f ); 45 | 46 | TEST_PASSFAIL 47 | 48 | RVTEST_CODE_END 49 | 50 | .data 51 | RVTEST_DATA_BEGIN 52 | 53 | TEST_DATA 54 | 55 | RVTEST_DATA_END 56 | -------------------------------------------------------------------------------- /riscv-tests/xori.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # xori.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test xori instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Logical tests 18 | #------------------------------------------------------------- 19 | 20 | TEST_IMM_OP( 2, xori, 0xffffffffff00f00f, 0x0000000000ff0f00, 0xf0f ); 21 | TEST_IMM_OP( 3, xori, 0x000000000ff00f00, 0x000000000ff00ff0, 0x0f0 ); 22 | TEST_IMM_OP( 4, xori, 0x0000000000ff0ff0, 0x0000000000ff08ff, 0x70f ); 23 | TEST_IMM_OP( 5, xori, 0xfffffffff00ff0ff, 0xfffffffff00ff00f, 0x0f0 ); 24 | 25 | #------------------------------------------------------------- 26 | # Source/Destination tests 27 | #------------------------------------------------------------- 28 | 29 | TEST_IMM_SRC1_EQ_DEST( 6, xori, 0xffffffffff00f00f, 0xffffffffff00f700, 0x70f ); 30 | 31 | #------------------------------------------------------------- 32 | # Bypassing tests 33 | #------------------------------------------------------------- 34 | 35 | TEST_IMM_DEST_BYPASS( 7, 0, xori, 0x000000000ff00f00, 0x000000000ff00ff0, 0x0f0 ); 36 | TEST_IMM_DEST_BYPASS( 8, 1, xori, 0x0000000000ff0ff0, 0x0000000000ff08ff, 0x70f ); 37 | TEST_IMM_DEST_BYPASS( 9, 2, xori, 0xfffffffff00ff0ff, 0xfffffffff00ff00f, 0x0f0 ); 38 | 39 | TEST_IMM_SRC1_BYPASS( 10, 0, xori, 0x000000000ff00f00, 0x000000000ff00ff0, 0x0f0 ); 40 | TEST_IMM_SRC1_BYPASS( 11, 1, xori, 0x0000000000ff0ff0, 0x0000000000ff0fff, 0x00f ); 41 | TEST_IMM_SRC1_BYPASS( 12, 2, xori, 0xfffffffff00ff0ff, 0xfffffffff00ff00f, 0x0f0 ); 42 | 43 | TEST_IMM_ZEROSRC1( 13, xori, 0x0f0, 0x0f0 ); 44 | TEST_IMM_ZERODEST( 14, xori, 0x00ff00ff, 0x70f ); 45 | 46 | TEST_PASSFAIL 47 | 48 | RVTEST_CODE_END 49 | 50 | .data 51 | RVTEST_DATA_BEGIN 52 | 53 | TEST_DATA 54 | 55 | RVTEST_DATA_END 56 | -------------------------------------------------------------------------------- /src/ry_writeback.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | use ieee.numeric_std.all; 7 | 8 | use work.ry_types.all; 9 | use work.ry_csr.all; 10 | 11 | entity ry_writeback is 12 | port( 13 | clk : in std_logic; 14 | reset : in std_logic; 15 | 16 | -- Count instruction: 17 | count_instr_in : in std_logic; 18 | count_instr_out : out std_logic; 19 | 20 | -- Exception signals: 21 | exception_ctx_in : in csr_exception_context; 22 | exception_in : in std_logic; 23 | exception_ctx_out : out csr_exception_context; 24 | exception_out : out std_logic; 25 | 26 | -- CSR signals: 27 | csr_write_in : in csr_write_mode; 28 | csr_write_out : out csr_write_mode; 29 | csr_data_in : in std_logic_vector(31 downto 0); 30 | csr_data_out : out std_logic_vector(31 downto 0); 31 | csr_addr_in : in csr_address; 32 | csr_addr_out : out csr_address; 33 | 34 | -- Destination register interface: 35 | rd_addr_in : in register_address; 36 | rd_addr_out : out register_address; 37 | rd_write_in : in std_logic; 38 | rd_write_out : out std_logic; 39 | rd_data_in : in std_logic_vector(31 downto 0); 40 | rd_data_out : out std_logic_vector(31 downto 0) 41 | ); 42 | end entity ry_writeback; 43 | 44 | architecture behaviour of ry_writeback is 45 | begin 46 | 47 | pipeline_register: process(clk) 48 | begin 49 | if rising_edge(clk) then 50 | if reset = '1' then 51 | rd_write_out <= '0'; 52 | exception_out <= '0'; 53 | count_instr_out <= '0'; 54 | else 55 | count_instr_out <= count_instr_in; 56 | rd_data_out <= rd_data_in; 57 | rd_write_out <= rd_write_in; 58 | rd_addr_out <= rd_addr_in; 59 | 60 | exception_out <= exception_in; 61 | exception_ctx_out <= exception_ctx_in; 62 | 63 | csr_write_out <= csr_write_in; 64 | csr_data_out <= csr_data_in; 65 | csr_addr_out <= csr_addr_in; 66 | end if; 67 | end if; 68 | end process pipeline_register; 69 | 70 | end architecture behaviour; 71 | -------------------------------------------------------------------------------- /src/dsaf/ry_writeback.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | use ieee.numeric_std.all; 7 | 8 | use work.ry_types.all; 9 | use work.ry_csr.all; 10 | 11 | entity ry_writeback is 12 | port( 13 | clk : in std_logic; 14 | reset : in std_logic; 15 | 16 | -- Count instruction: 17 | count_instr_in : in std_logic; 18 | count_instr_out : out std_logic; 19 | 20 | -- Exception signals: 21 | exception_ctx_in : in csr_exception_context; 22 | exception_in : in std_logic; 23 | exception_ctx_out : out csr_exception_context; 24 | exception_out : out std_logic; 25 | 26 | -- CSR signals: 27 | csr_write_in : in csr_write_mode; 28 | csr_write_out : out csr_write_mode; 29 | csr_data_in : in std_logic_vector(31 downto 0); 30 | csr_data_out : out std_logic_vector(31 downto 0); 31 | csr_addr_in : in csr_address; 32 | csr_addr_out : out csr_address; 33 | 34 | -- Destination register interface: 35 | rd_addr_in : in register_address; 36 | rd_addr_out : out register_address; 37 | rd_write_in : in std_logic; 38 | rd_write_out : out std_logic; 39 | rd_data_in : in std_logic_vector(31 downto 0); 40 | rd_data_out : out std_logic_vector(31 downto 0) 41 | ); 42 | end entity ry_writeback; 43 | 44 | architecture behaviour of ry_writeback is 45 | begin 46 | 47 | pipeline_register: process(clk) 48 | begin 49 | if rising_edge(clk) then 50 | if reset = '1' then 51 | rd_write_out <= '0'; 52 | exception_out <= '0'; 53 | count_instr_out <= '0'; 54 | else 55 | count_instr_out <= count_instr_in; 56 | rd_data_out <= rd_data_in; 57 | rd_write_out <= rd_write_in; 58 | rd_addr_out <= rd_addr_in; 59 | 60 | exception_out <= exception_in; 61 | exception_ctx_out <= exception_ctx_in; 62 | 63 | csr_write_out <= csr_write_in; 64 | csr_data_out <= csr_data_in; 65 | csr_addr_out <= csr_addr_in; 66 | end if; 67 | end if; 68 | end process pipeline_register; 69 | 70 | end architecture behaviour; 71 | -------------------------------------------------------------------------------- /example/arty.xdc: -------------------------------------------------------------------------------- 1 | # The RISCY Processor - A simple processor for FPGA Prototyping 2 | # (c) Krishna Subramanian 3 | 4 | # Set operating conditions to improve temperature estimation: 5 | set_operating_conditions -airflow 0 6 | set_operating_conditions -heatsink low 7 | 8 | # Clock signal: 9 | set_property -dict {PACKAGE_PIN E3 IOSTANDARD LVCMOS33} [get_ports {clk}]; 10 | create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports {clk}]; 11 | 12 | # Reset button: 13 | set_property -dict {PACKAGE_PIN C2 IOSTANDARD LVCMOS33} [get_ports {reset_n}]; 14 | 15 | # GPIOs (Buttons): 16 | set_property -dict {PACKAGE_PIN D9 IOSTANDARD LVCMOS33} [get_ports {gpio_pins[0]}]; 17 | set_property -dict {PACKAGE_PIN C9 IOSTANDARD LVCMOS33} [get_ports {gpio_pins[1]}]; 18 | set_property -dict {PACKAGE_PIN B9 IOSTANDARD LVCMOS33} [get_ports {gpio_pins[2]}]; 19 | set_property -dict {PACKAGE_PIN B8 IOSTANDARD LVCMOS33} [get_ports {gpio_pins[3]}]; 20 | 21 | # GPIO (Switches): 22 | set_property -dict {PACKAGE_PIN A8 IOSTANDARD LVCMOS33} [get_ports {gpio_pins[4]}]; 23 | set_property -dict {PACKAGE_PIN C11 IOSTANDARD LVCMOS33} [get_ports {gpio_pins[5]}]; 24 | set_property -dict {PACKAGE_PIN C10 IOSTANDARD LVCMOS33} [get_ports {gpio_pins[6]}]; 25 | set_property -dict {PACKAGE_PIN A10 IOSTANDARD LVCMOS33} [get_ports {gpio_pins[7]}]; 26 | 27 | # GPIOs (LEDs): 28 | set_property -dict {PACKAGE_PIN H5 IOSTANDARD LVCMOS33} [get_ports {gpio_pins[8]}]; 29 | set_property -dict {PACKAGE_PIN J5 IOSTANDARD LVCMOS33} [get_ports {gpio_pins[9]}]; 30 | set_property -dict {PACKAGE_PIN T9 IOSTANDARD LVCMOS33} [get_ports {gpio_pins[10]}]; 31 | set_property -dict {PACKAGE_PIN T10 IOSTANDARD LVCMOS33} [get_ports {gpio_pins[11]}]; 32 | 33 | # UART0: 34 | set_property -dict {PACKAGE_PIN D10 IOSTANDARD LVCMOS33} [get_ports {uart0_txd}]; 35 | set_property -dict {PACKAGE_PIN A9 IOSTANDARD LVCMOS33} [get_ports {uart0_rxd}]; 36 | 37 | # UART1 (pin 5 and 6 on JA, to match the pins on the PMOD-GPS): 38 | set_property -dict {PACKAGE_PIN B18 IOSTANDARD LVCMOS33} [get_ports {uart1_txd}]; 39 | set_property -dict {PACKAGE_PIN A18 IOSTANDARD LVCMOS33} [get_ports {uart1_rxd}]; 40 | -------------------------------------------------------------------------------- /src/ry_alu.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | use ieee.numeric_std.all; 7 | 8 | use work.ry_types.all; 9 | 10 | --! @brief 11 | --! Arithmetic Logic Unit (ALU). 12 | --! 13 | --! @details 14 | --! Performs logic and arithmetic calculations. The operation to perform 15 | --! is specified by the user of the module. 16 | entity ry_alu is 17 | port( 18 | x, y : in std_logic_vector(31 downto 0); --! Input operand. 19 | result : out std_logic_vector(31 downto 0); --! Operation result. 20 | operation : in alu_operation --! Operation type. 21 | ); 22 | end entity ry_alu; 23 | 24 | --! @brief Behavioural description of the ALU. 25 | architecture behaviour of ry_alu is 26 | begin 27 | 28 | --! Performs the ALU calculation. 29 | calculate: process(operation, x, y) 30 | begin 31 | case operation is 32 | when ALU_AND => 33 | result <= x and y; 34 | when ALU_OR => 35 | result <= x or y; 36 | when ALU_XOR => 37 | result <= x xor y; 38 | when ALU_SLT => 39 | if signed(x) < signed(y) then 40 | result <= (0 => '1', others => '0'); 41 | else 42 | result <= (others => '0'); 43 | end if; 44 | when ALU_SLTU => 45 | if unsigned(x) < unsigned(y) then 46 | result <= (0 => '1', others => '0'); 47 | else 48 | result <= (others => '0'); 49 | end if; 50 | when ALU_ADD => 51 | result <= std_logic_vector(unsigned(x) + unsigned(y)); 52 | when ALU_SUB => 53 | result <= std_logic_vector(unsigned(x) - unsigned(y)); 54 | when ALU_SRL => 55 | result <= std_logic_vector(shift_right(unsigned(x), to_integer(unsigned(y(4 downto 0))))); 56 | when ALU_SLL => 57 | result <= std_logic_vector(shift_left(unsigned(x), to_integer(unsigned(y(4 downto 0))))); 58 | when ALU_SRA => 59 | result <= std_logic_vector(shift_right(signed(x), to_integer(unsigned(y(4 downto 0))))); 60 | when others => 61 | result <= (others => '0'); 62 | end case; 63 | end process calculate; 64 | 65 | end architecture behaviour; 66 | -------------------------------------------------------------------------------- /src/dsaf/ry_alu.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | use ieee.numeric_std.all; 7 | 8 | use work.ry_types.all; 9 | 10 | --! @brief 11 | --! Arithmetic Logic Unit (ALU). 12 | --! 13 | --! @details 14 | --! Performs logic and arithmetic calculations. The operation to perform 15 | --! is specified by the user of the module. 16 | entity ry_alu is 17 | port( 18 | x, y : in std_logic_vector(31 downto 0); --! Input operand. 19 | result : out std_logic_vector(31 downto 0); --! Operation result. 20 | operation : in alu_operation --! Operation type. 21 | ); 22 | end entity ry_alu; 23 | 24 | --! @brief Behavioural description of the ALU. 25 | architecture behaviour of ry_alu is 26 | begin 27 | 28 | --! Performs the ALU calculation. 29 | calculate: process(operation, x, y) 30 | begin 31 | case operation is 32 | when ALU_AND => 33 | result <= x and y; 34 | when ALU_OR => 35 | result <= x or y; 36 | when ALU_XOR => 37 | result <= x xor y; 38 | when ALU_SLT => 39 | if signed(x) < signed(y) then 40 | result <= (0 => '1', others => '0'); 41 | else 42 | result <= (others => '0'); 43 | end if; 44 | when ALU_SLTU => 45 | if unsigned(x) < unsigned(y) then 46 | result <= (0 => '1', others => '0'); 47 | else 48 | result <= (others => '0'); 49 | end if; 50 | when ALU_ADD => 51 | result <= std_logic_vector(unsigned(x) + unsigned(y)); 52 | when ALU_SUB => 53 | result <= std_logic_vector(unsigned(x) - unsigned(y)); 54 | when ALU_SRL => 55 | result <= std_logic_vector(shift_right(unsigned(x), to_integer(unsigned(y(4 downto 0))))); 56 | when ALU_SLL => 57 | result <= std_logic_vector(shift_left(unsigned(x), to_integer(unsigned(y(4 downto 0))))); 58 | when ALU_SRA => 59 | result <= std_logic_vector(shift_right(signed(x), to_integer(unsigned(y(4 downto 0))))); 60 | when others => 61 | result <= (others => '0'); 62 | end case; 63 | end process calculate; 64 | 65 | end architecture behaviour; 66 | -------------------------------------------------------------------------------- /libsoc/gpio.h: -------------------------------------------------------------------------------- 1 | // The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | // (c) Krishna Subramanian 3 | 4 | #ifndef PAEE_GPIO_H 5 | #define PAEE_GPIO_H 6 | 7 | #include 8 | #include 9 | 10 | #define PAEE_GPIO_REG_INPUT 0 11 | #define PAEE_GPIO_REG_OUTPUT 4 12 | #define PAEE_GPIO_REG_DIRECTION 8 13 | 14 | struct gpio 15 | { 16 | volatile uint32_t * registers; 17 | }; 18 | 19 | /** 20 | * Initializes a GPIO instance. 21 | * @param module Pointer to a GPIO instance structure. 22 | * @param base Pointer to the base address of the GPIO hardware instance. 23 | */ 24 | static inline void gpio_initialize(struct gpio * module, volatile void * base) 25 | { 26 | module->registers = base; 27 | } 28 | 29 | /** 30 | * Sets the GPIO direction register. 31 | * 32 | * A value of 1 in the direction bitmask indicates that the pin is an output, 33 | * while a value of 0 indicates that the pin is an input. 34 | * 35 | * @param module Pointer to a GPIO instance structure. 36 | * @param dir Direction bitmask for the GPIO direction register. 37 | */ 38 | static inline void gpio_set_direction(struct gpio * module, uint32_t dir) 39 | { 40 | module->registers[PAEE_GPIO_REG_DIRECTION >> 2] = dir; 41 | } 42 | 43 | static inline uint32_t gpio_get_input(struct gpio * module) 44 | { 45 | return module->registers[PAEE_GPIO_REG_INPUT >> 2]; 46 | } 47 | 48 | static inline void gpio_set_output(struct gpio * module, uint32_t output) 49 | { 50 | module->registers[PAEE_GPIO_REG_OUTPUT >> 2] = output; 51 | } 52 | 53 | /** 54 | * Sets (turns on) the specified GPIO pin. 55 | * @param module Pointer to the GPIO instance structure. 56 | * @param pin Pin number for the pin to turn on. 57 | */ 58 | static inline void gpio_set_pin(struct gpio * module, uint8_t pin) 59 | { 60 | module->registers[PAEE_GPIO_REG_OUTPUT >> 2] |= (1 << pin); 61 | } 62 | 63 | /** 64 | * Clears (turns off) the specified GPIO pin. 65 | * @param module Pointer to the PGIO instance structure. 66 | * @param pin Pin number for the pin to turn off. 67 | */ 68 | static inline void gpio_clear_pin(struct gpio * module, uint8_t pin) 69 | { 70 | module->registers[PAEE_GPIO_REG_OUTPUT >> 2] &= ~(1 << pin); 71 | } 72 | 73 | #endif 74 | 75 | -------------------------------------------------------------------------------- /riscv-tests/bne.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # bne.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test bne instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Branch tests 18 | #------------------------------------------------------------- 19 | 20 | # Each test checks both forward and backward branches 21 | 22 | TEST_BR2_OP_TAKEN( 2, bne, 0, 1 ); 23 | TEST_BR2_OP_TAKEN( 3, bne, 1, 0 ); 24 | TEST_BR2_OP_TAKEN( 4, bne, -1, 1 ); 25 | TEST_BR2_OP_TAKEN( 5, bne, 1, -1 ); 26 | 27 | TEST_BR2_OP_NOTTAKEN( 6, bne, 0, 0 ); 28 | TEST_BR2_OP_NOTTAKEN( 7, bne, 1, 1 ); 29 | TEST_BR2_OP_NOTTAKEN( 8, bne, -1, -1 ); 30 | 31 | #------------------------------------------------------------- 32 | # Bypassing tests 33 | #------------------------------------------------------------- 34 | 35 | TEST_BR2_SRC12_BYPASS( 9, 0, 0, bne, 0, 0 ); 36 | TEST_BR2_SRC12_BYPASS( 10, 0, 1, bne, 0, 0 ); 37 | TEST_BR2_SRC12_BYPASS( 11, 0, 2, bne, 0, 0 ); 38 | TEST_BR2_SRC12_BYPASS( 12, 1, 0, bne, 0, 0 ); 39 | TEST_BR2_SRC12_BYPASS( 13, 1, 1, bne, 0, 0 ); 40 | TEST_BR2_SRC12_BYPASS( 14, 2, 0, bne, 0, 0 ); 41 | 42 | TEST_BR2_SRC12_BYPASS( 15, 0, 0, bne, 0, 0 ); 43 | TEST_BR2_SRC12_BYPASS( 16, 0, 1, bne, 0, 0 ); 44 | TEST_BR2_SRC12_BYPASS( 17, 0, 2, bne, 0, 0 ); 45 | TEST_BR2_SRC12_BYPASS( 18, 1, 0, bne, 0, 0 ); 46 | TEST_BR2_SRC12_BYPASS( 19, 1, 1, bne, 0, 0 ); 47 | TEST_BR2_SRC12_BYPASS( 20, 2, 0, bne, 0, 0 ); 48 | 49 | #------------------------------------------------------------- 50 | # Test delay slot instructions not executed nor bypassed 51 | #------------------------------------------------------------- 52 | 53 | TEST_CASE( 21, x1, 3, \ 54 | li x1, 1; \ 55 | bne x1, x0, 1f; \ 56 | addi x1, x1, 1; \ 57 | addi x1, x1, 1; \ 58 | addi x1, x1, 1; \ 59 | addi x1, x1, 1; \ 60 | 1: addi x1, x1, 1; \ 61 | addi x1, x1, 1; \ 62 | ) 63 | 64 | TEST_PASSFAIL 65 | 66 | RVTEST_CODE_END 67 | 68 | .data 69 | RVTEST_DATA_BEGIN 70 | 71 | TEST_DATA 72 | 73 | RVTEST_DATA_END 74 | -------------------------------------------------------------------------------- /riscv-tests/beq.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # beq.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test beq instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Branch tests 18 | #------------------------------------------------------------- 19 | 20 | # Each test checks both forward and backward branches 21 | 22 | TEST_BR2_OP_TAKEN( 2, beq, 0, 0 ); 23 | TEST_BR2_OP_TAKEN( 3, beq, 1, 1 ); 24 | TEST_BR2_OP_TAKEN( 4, beq, -1, -1 ); 25 | 26 | TEST_BR2_OP_NOTTAKEN( 5, beq, 0, 1 ); 27 | TEST_BR2_OP_NOTTAKEN( 6, beq, 1, 0 ); 28 | TEST_BR2_OP_NOTTAKEN( 7, beq, -1, 1 ); 29 | TEST_BR2_OP_NOTTAKEN( 8, beq, 1, -1 ); 30 | 31 | #------------------------------------------------------------- 32 | # Bypassing tests 33 | #------------------------------------------------------------- 34 | 35 | TEST_BR2_SRC12_BYPASS( 9, 0, 0, beq, 0, -1 ); 36 | TEST_BR2_SRC12_BYPASS( 10, 0, 1, beq, 0, -1 ); 37 | TEST_BR2_SRC12_BYPASS( 11, 0, 2, beq, 0, -1 ); 38 | TEST_BR2_SRC12_BYPASS( 12, 1, 0, beq, 0, -1 ); 39 | TEST_BR2_SRC12_BYPASS( 13, 1, 1, beq, 0, -1 ); 40 | TEST_BR2_SRC12_BYPASS( 14, 2, 0, beq, 0, -1 ); 41 | 42 | TEST_BR2_SRC12_BYPASS( 15, 0, 0, beq, 0, -1 ); 43 | TEST_BR2_SRC12_BYPASS( 16, 0, 1, beq, 0, -1 ); 44 | TEST_BR2_SRC12_BYPASS( 17, 0, 2, beq, 0, -1 ); 45 | TEST_BR2_SRC12_BYPASS( 18, 1, 0, beq, 0, -1 ); 46 | TEST_BR2_SRC12_BYPASS( 19, 1, 1, beq, 0, -1 ); 47 | TEST_BR2_SRC12_BYPASS( 20, 2, 0, beq, 0, -1 ); 48 | 49 | #------------------------------------------------------------- 50 | # Test delay slot instructions not executed nor bypassed 51 | #------------------------------------------------------------- 52 | 53 | TEST_CASE( 21, x1, 3, \ 54 | li x1, 1; \ 55 | beq x0, x0, 1f; \ 56 | addi x1, x1, 1; \ 57 | addi x1, x1, 1; \ 58 | addi x1, x1, 1; \ 59 | addi x1, x1, 1; \ 60 | 1: addi x1, x1, 1; \ 61 | addi x1, x1, 1; \ 62 | ) 63 | 64 | TEST_PASSFAIL 65 | 66 | RVTEST_CODE_END 67 | 68 | .data 69 | RVTEST_DATA_BEGIN 70 | 71 | TEST_DATA 72 | 73 | RVTEST_DATA_END 74 | -------------------------------------------------------------------------------- /riscv-tests/blt.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # blt.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test blt instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Branch tests 18 | #------------------------------------------------------------- 19 | 20 | # Each test checks both forward and backward branches 21 | 22 | TEST_BR2_OP_TAKEN( 2, blt, 0, 1 ); 23 | TEST_BR2_OP_TAKEN( 3, blt, -1, 1 ); 24 | TEST_BR2_OP_TAKEN( 4, blt, -2, -1 ); 25 | 26 | TEST_BR2_OP_NOTTAKEN( 5, blt, 1, 0 ); 27 | TEST_BR2_OP_NOTTAKEN( 6, blt, 1, -1 ); 28 | TEST_BR2_OP_NOTTAKEN( 7, blt, -1, -2 ); 29 | TEST_BR2_OP_NOTTAKEN( 8, blt, 1, -2 ); 30 | 31 | #------------------------------------------------------------- 32 | # Bypassing tests 33 | #------------------------------------------------------------- 34 | 35 | TEST_BR2_SRC12_BYPASS( 9, 0, 0, blt, 0, -1 ); 36 | TEST_BR2_SRC12_BYPASS( 10, 0, 1, blt, 0, -1 ); 37 | TEST_BR2_SRC12_BYPASS( 11, 0, 2, blt, 0, -1 ); 38 | TEST_BR2_SRC12_BYPASS( 12, 1, 0, blt, 0, -1 ); 39 | TEST_BR2_SRC12_BYPASS( 13, 1, 1, blt, 0, -1 ); 40 | TEST_BR2_SRC12_BYPASS( 14, 2, 0, blt, 0, -1 ); 41 | 42 | TEST_BR2_SRC12_BYPASS( 15, 0, 0, blt, 0, -1 ); 43 | TEST_BR2_SRC12_BYPASS( 16, 0, 1, blt, 0, -1 ); 44 | TEST_BR2_SRC12_BYPASS( 17, 0, 2, blt, 0, -1 ); 45 | TEST_BR2_SRC12_BYPASS( 18, 1, 0, blt, 0, -1 ); 46 | TEST_BR2_SRC12_BYPASS( 19, 1, 1, blt, 0, -1 ); 47 | TEST_BR2_SRC12_BYPASS( 20, 2, 0, blt, 0, -1 ); 48 | 49 | #------------------------------------------------------------- 50 | # Test delay slot instructions not executed nor bypassed 51 | #------------------------------------------------------------- 52 | 53 | TEST_CASE( 21, x1, 3, \ 54 | li x1, 1; \ 55 | blt x0, x1, 1f; \ 56 | addi x1, x1, 1; \ 57 | addi x1, x1, 1; \ 58 | addi x1, x1, 1; \ 59 | addi x1, x1, 1; \ 60 | 1: addi x1, x1, 1; \ 61 | addi x1, x1, 1; \ 62 | ) 63 | 64 | TEST_PASSFAIL 65 | 66 | RVTEST_CODE_END 67 | 68 | .data 69 | RVTEST_DATA_BEGIN 70 | 71 | TEST_DATA 72 | 73 | RVTEST_DATA_END 74 | -------------------------------------------------------------------------------- /testbenches/tb_soc_gpio.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | 7 | entity tb_soc_gpio is 8 | end entity tb_soc_gpio; 9 | 10 | architecture testbench of tb_soc_gpio is 11 | 12 | -- Clock signal: 13 | signal clk : std_logic := '0'; 14 | constant clk_period : time := 10 ns; 15 | 16 | -- Reset signal: 17 | signal reset : std_logic := '1'; 18 | 19 | -- GPIOs: 20 | signal gpio : std_logic_vector(31 downto 0); 21 | 22 | -- Wishbone bus: 23 | signal wb_adr_in : std_logic_vector(11 downto 0) := (others => '0'); 24 | signal wb_dat_in : std_logic_vector(31 downto 0) := (others => '0'); 25 | signal wb_dat_out : std_logic_vector(31 downto 0); 26 | signal wb_cyc_in : std_logic := '0'; 27 | signal wb_stb_in : std_logic := '0'; 28 | signal wb_we_in : std_logic := '0'; 29 | signal wb_ack_out : std_logic; 30 | begin 31 | 32 | uut: entity work.ry_soc_gpio 33 | generic map( 34 | NUM_GPIOS => 32 35 | ) port map( 36 | clk => clk, 37 | reset => reset, 38 | gpio => gpio, 39 | wb_adr_in => wb_adr_in, 40 | wb_dat_in => wb_dat_in, 41 | wb_dat_out => wb_dat_out, 42 | wb_cyc_in => wb_cyc_in, 43 | wb_stb_in => wb_stb_in, 44 | wb_we_in => wb_we_in, 45 | wb_ack_out => wb_ack_out 46 | ); 47 | 48 | clock: process 49 | begin 50 | clk <= '1'; 51 | wait for clk_period / 2; 52 | clk <= '0'; 53 | wait for clk_period / 2; 54 | end process clock; 55 | 56 | stimulus: process 57 | begin 58 | wait for clk_period * 2; 59 | reset <= '0'; 60 | 61 | -- Set the upper half of the GPIOs as inputs, the rest as outputs: 62 | wb_dat_in <= x"0000ffff"; 63 | wb_adr_in <= x"008"; 64 | wb_we_in <= '1'; 65 | wb_cyc_in <= '1'; 66 | wb_stb_in <= '1'; 67 | wait until wb_ack_out = '1'; 68 | wait for clk_period; 69 | wb_stb_in <= '0'; 70 | wb_cyc_in <= '0'; 71 | wb_we_in <= '0'; 72 | wait for clk_period; 73 | 74 | -- Set the outputs to aa, see if the upper half gets ignored correctly: 75 | wb_dat_in <= x"aaaaaaaa"; 76 | wb_adr_in <= x"004"; 77 | wb_we_in <= '1'; 78 | wb_cyc_in <= '1'; 79 | wb_stb_in <= '1'; 80 | wait until wb_ack_out = '1'; 81 | wait for clk_period; 82 | wb_stb_in <= '0'; 83 | wb_cyc_in <= '0'; 84 | wb_we_in <= '0'; 85 | wait for clk_period; 86 | 87 | wait; 88 | end process stimulus; 89 | 90 | end architecture testbench; 91 | -------------------------------------------------------------------------------- /riscv-tests/bge.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # bge.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test bge instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Branch tests 18 | #------------------------------------------------------------- 19 | 20 | # Each test checks both forward and backward branches 21 | 22 | TEST_BR2_OP_TAKEN( 2, bge, 0, 0 ); 23 | TEST_BR2_OP_TAKEN( 3, bge, 1, 1 ); 24 | TEST_BR2_OP_TAKEN( 4, bge, -1, -1 ); 25 | TEST_BR2_OP_TAKEN( 5, bge, 1, 0 ); 26 | TEST_BR2_OP_TAKEN( 6, bge, 1, -1 ); 27 | TEST_BR2_OP_TAKEN( 7, bge, -1, -2 ); 28 | 29 | TEST_BR2_OP_NOTTAKEN( 8, bge, 0, 1 ); 30 | TEST_BR2_OP_NOTTAKEN( 9, bge, -1, 1 ); 31 | TEST_BR2_OP_NOTTAKEN( 10, bge, -2, -1 ); 32 | TEST_BR2_OP_NOTTAKEN( 11, bge, -2, 1 ); 33 | 34 | #------------------------------------------------------------- 35 | # Bypassing tests 36 | #------------------------------------------------------------- 37 | 38 | TEST_BR2_SRC12_BYPASS( 12, 0, 0, bge, -1, 0 ); 39 | TEST_BR2_SRC12_BYPASS( 13, 0, 1, bge, -1, 0 ); 40 | TEST_BR2_SRC12_BYPASS( 14, 0, 2, bge, -1, 0 ); 41 | TEST_BR2_SRC12_BYPASS( 15, 1, 0, bge, -1, 0 ); 42 | TEST_BR2_SRC12_BYPASS( 16, 1, 1, bge, -1, 0 ); 43 | TEST_BR2_SRC12_BYPASS( 17, 2, 0, bge, -1, 0 ); 44 | 45 | TEST_BR2_SRC12_BYPASS( 18, 0, 0, bge, -1, 0 ); 46 | TEST_BR2_SRC12_BYPASS( 19, 0, 1, bge, -1, 0 ); 47 | TEST_BR2_SRC12_BYPASS( 20, 0, 2, bge, -1, 0 ); 48 | TEST_BR2_SRC12_BYPASS( 21, 1, 0, bge, -1, 0 ); 49 | TEST_BR2_SRC12_BYPASS( 22, 1, 1, bge, -1, 0 ); 50 | TEST_BR2_SRC12_BYPASS( 23, 2, 0, bge, -1, 0 ); 51 | 52 | #------------------------------------------------------------- 53 | # Test delay slot instructions not executed nor bypassed 54 | #------------------------------------------------------------- 55 | 56 | TEST_CASE( 24, x1, 3, \ 57 | li x1, 1; \ 58 | bge x1, x0, 1f; \ 59 | addi x1, x1, 1; \ 60 | addi x1, x1, 1; \ 61 | addi x1, x1, 1; \ 62 | addi x1, x1, 1; \ 63 | 1: addi x1, x1, 1; \ 64 | addi x1, x1, 1; \ 65 | ) 66 | 67 | TEST_PASSFAIL 68 | 69 | RVTEST_CODE_END 70 | 71 | .data 72 | RVTEST_DATA_BEGIN 73 | 74 | TEST_DATA 75 | 76 | RVTEST_DATA_END 77 | -------------------------------------------------------------------------------- /riscv-tests/slti.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # slti.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test slti instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Arithmetic tests 18 | #------------------------------------------------------------- 19 | 20 | TEST_IMM_OP( 2, slti, 0, 0x0000000000000000, 0x000 ); 21 | TEST_IMM_OP( 3, slti, 0, 0x0000000000000001, 0x001 ); 22 | TEST_IMM_OP( 4, slti, 1, 0x0000000000000003, 0x007 ); 23 | TEST_IMM_OP( 5, slti, 0, 0x0000000000000007, 0x003 ); 24 | 25 | TEST_IMM_OP( 6, slti, 0, 0x0000000000000000, 0x800 ); 26 | TEST_IMM_OP( 7, slti, 1, 0xffffffff80000000, 0x000 ); 27 | TEST_IMM_OP( 8, slti, 1, 0xffffffff80000000, 0x800 ); 28 | 29 | TEST_IMM_OP( 9, slti, 1, 0x0000000000000000, 0x7ff ); 30 | TEST_IMM_OP( 10, slti, 0, 0x000000007fffffff, 0x000 ); 31 | TEST_IMM_OP( 11, slti, 0, 0x000000007fffffff, 0x7ff ); 32 | 33 | TEST_IMM_OP( 12, slti, 1, 0xffffffff80000000, 0x7ff ); 34 | TEST_IMM_OP( 13, slti, 0, 0x000000007fffffff, 0x800 ); 35 | 36 | TEST_IMM_OP( 14, slti, 0, 0x0000000000000000, 0xfff ); 37 | TEST_IMM_OP( 15, slti, 1, 0xffffffffffffffff, 0x001 ); 38 | TEST_IMM_OP( 16, slti, 0, 0xffffffffffffffff, 0xfff ); 39 | 40 | #------------------------------------------------------------- 41 | # Source/Destination tests 42 | #------------------------------------------------------------- 43 | 44 | TEST_IMM_SRC1_EQ_DEST( 17, slti, 1, 11, 13 ); 45 | 46 | #------------------------------------------------------------- 47 | # Bypassing tests 48 | #------------------------------------------------------------- 49 | 50 | TEST_IMM_DEST_BYPASS( 18, 0, slti, 0, 15, 10 ); 51 | TEST_IMM_DEST_BYPASS( 19, 1, slti, 1, 10, 16 ); 52 | TEST_IMM_DEST_BYPASS( 20, 2, slti, 0, 16, 9 ); 53 | 54 | TEST_IMM_SRC1_BYPASS( 21, 0, slti, 1, 11, 15 ); 55 | TEST_IMM_SRC1_BYPASS( 22, 1, slti, 0, 17, 8 ); 56 | TEST_IMM_SRC1_BYPASS( 23, 2, slti, 1, 12, 14 ); 57 | 58 | TEST_IMM_ZEROSRC1( 24, slti, 0, 0xfff ); 59 | TEST_IMM_ZERODEST( 25, slti, 0x00ff00ff, 0xfff ); 60 | 61 | TEST_PASSFAIL 62 | 63 | RVTEST_CODE_END 64 | 65 | .data 66 | RVTEST_DATA_BEGIN 67 | 68 | TEST_DATA 69 | 70 | RVTEST_DATA_END 71 | -------------------------------------------------------------------------------- /riscv-tests/sltiu.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # sltiu.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test sltiu instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Arithmetic tests 18 | #------------------------------------------------------------- 19 | 20 | TEST_IMM_OP( 2, sltiu, 0, 0x0000000000000000, 0x000 ); 21 | TEST_IMM_OP( 3, sltiu, 0, 0x0000000000000001, 0x001 ); 22 | TEST_IMM_OP( 4, sltiu, 1, 0x0000000000000003, 0x007 ); 23 | TEST_IMM_OP( 5, sltiu, 0, 0x0000000000000007, 0x003 ); 24 | 25 | TEST_IMM_OP( 6, sltiu, 1, 0x0000000000000000, 0x800 ); 26 | TEST_IMM_OP( 7, sltiu, 0, 0xffffffff80000000, 0x000 ); 27 | TEST_IMM_OP( 8, sltiu, 1, 0xffffffff80000000, 0x800 ); 28 | 29 | TEST_IMM_OP( 9, sltiu, 1, 0x0000000000000000, 0x7ff ); 30 | TEST_IMM_OP( 10, sltiu, 0, 0x000000007fffffff, 0x000 ); 31 | TEST_IMM_OP( 11, sltiu, 0, 0x000000007fffffff, 0x7ff ); 32 | 33 | TEST_IMM_OP( 12, sltiu, 0, 0xffffffff80000000, 0x7ff ); 34 | TEST_IMM_OP( 13, sltiu, 1, 0x000000007fffffff, 0x800 ); 35 | 36 | TEST_IMM_OP( 14, sltiu, 1, 0x0000000000000000, 0xfff ); 37 | TEST_IMM_OP( 15, sltiu, 0, 0xffffffffffffffff, 0x001 ); 38 | TEST_IMM_OP( 16, sltiu, 0, 0xffffffffffffffff, 0xfff ); 39 | 40 | #------------------------------------------------------------- 41 | # Source/Destination tests 42 | #------------------------------------------------------------- 43 | 44 | TEST_IMM_SRC1_EQ_DEST( 17, sltiu, 1, 11, 13 ); 45 | 46 | #------------------------------------------------------------- 47 | # Bypassing tests 48 | #------------------------------------------------------------- 49 | 50 | TEST_IMM_DEST_BYPASS( 18, 0, sltiu, 0, 15, 10 ); 51 | TEST_IMM_DEST_BYPASS( 19, 1, sltiu, 1, 10, 16 ); 52 | TEST_IMM_DEST_BYPASS( 20, 2, sltiu, 0, 16, 9 ); 53 | 54 | TEST_IMM_SRC1_BYPASS( 21, 0, sltiu, 1, 11, 15 ); 55 | TEST_IMM_SRC1_BYPASS( 22, 1, sltiu, 0, 17, 8 ); 56 | TEST_IMM_SRC1_BYPASS( 23, 2, sltiu, 1, 12, 14 ); 57 | 58 | TEST_IMM_ZEROSRC1( 24, sltiu, 1, 0xfff ); 59 | TEST_IMM_ZERODEST( 25, sltiu, 0x00ff00ff, 0xfff ); 60 | 61 | TEST_PASSFAIL 62 | 63 | RVTEST_CODE_END 64 | 65 | .data 66 | RVTEST_DATA_BEGIN 67 | 68 | TEST_DATA 69 | 70 | RVTEST_DATA_END 71 | -------------------------------------------------------------------------------- /src/ry_utilities.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | 7 | use work.ry_types.all; 8 | use work.ry_constants.all; 9 | 10 | package ry_utilities is 11 | 12 | --! Converts a boolean to an std_logic. 13 | function to_std_logic(input : in boolean) return std_logic; 14 | 15 | -- Checks if a number is 2^n: 16 | function is_pow2(input : in natural) return boolean; 17 | 18 | --! Calculates log2 with integers. 19 | function log2(input : in natural) return natural; 20 | 21 | -- Gets the value of the sel signals to the wishbone interconnect for the specified 22 | -- operand size and address. 23 | function wb_get_data_sel(size : in std_logic_vector(1 downto 0); address : in std_logic_vector) 24 | return std_logic_vector; 25 | 26 | end package ry_utilities; 27 | 28 | package body ry_utilities is 29 | 30 | function to_std_logic(input : in boolean) return std_logic is 31 | begin 32 | if input then 33 | return '1'; 34 | else 35 | return '0'; 36 | end if; 37 | end function to_std_logic; 38 | 39 | function is_pow2(input : in natural) return boolean is 40 | variable c : natural := 1; 41 | begin 42 | for i in 0 to 31 loop 43 | if input = c then 44 | return true; 45 | end if; 46 | 47 | c := c * 2; 48 | end loop; 49 | 50 | return false; 51 | end function is_pow2; 52 | 53 | function log2(input : in natural) return natural is 54 | variable retval : natural := 0; 55 | variable temp : natural := input; 56 | begin 57 | while temp > 1 loop 58 | retval := retval + 1; 59 | temp := temp / 2; 60 | end loop; 61 | 62 | return retval; 63 | end function log2; 64 | 65 | function wb_get_data_sel(size : in std_logic_vector(1 downto 0); address : in std_logic_vector) 66 | return std_logic_vector is 67 | begin 68 | case size is 69 | when b"01" => 70 | case address(1 downto 0) is 71 | when b"00" => 72 | return b"0001"; 73 | when b"01" => 74 | return b"0010"; 75 | when b"10" => 76 | return b"0100"; 77 | when b"11" => 78 | return b"1000"; 79 | when others => 80 | return b"0001"; 81 | end case; 82 | when b"10" => 83 | if address(1) = '0' then 84 | return b"0011"; 85 | else 86 | return b"1100"; 87 | end if; 88 | when others => 89 | return b"1111"; 90 | end case; 91 | end function wb_get_data_sel; 92 | 93 | end package body ry_utilities; 94 | -------------------------------------------------------------------------------- /soc/ry_fifo.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple processor for FPGA Prototyping 2 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 3 | -- (c) Krishna Subramanian 4 | 5 | 6 | library ieee; 7 | use ieee.std_logic_1164.all; 8 | 9 | --! @brief A generic FIFO module. 10 | --! Adopted from the FIFO module in . 11 | entity ry_fifo is 12 | generic( 13 | DEPTH : natural := 64; 14 | WIDTH : natural := 32 15 | ); 16 | port( 17 | -- Control lines: 18 | clk : in std_logic; 19 | reset : in std_logic; 20 | 21 | -- Status lines: 22 | full : out std_logic; 23 | empty : out std_logic; 24 | 25 | -- Data in: 26 | data_in : in std_logic_vector(WIDTH - 1 downto 0); 27 | data_out : out std_logic_vector(WIDTH - 1 downto 0); 28 | push, pop : in std_logic 29 | ); 30 | end entity ry_fifo; 31 | 32 | architecture behaviour of ry_fifo is 33 | 34 | type memory_array is array(0 to DEPTH - 1) of std_logic_vector(WIDTH - 1 downto 0); 35 | shared variable memory : memory_array := (others => (others => '0')); 36 | 37 | subtype index_type is integer range 0 to DEPTH - 1; 38 | signal top, bottom : index_type; 39 | 40 | type fifo_op is (FIFO_POP, FIFO_PUSH); 41 | signal prev_op : fifo_op := FIFO_POP; 42 | 43 | begin 44 | 45 | empty <= '1' when top = bottom and prev_op = FIFO_POP else '0'; 46 | full <= '1' when top = bottom and prev_op = FIFO_PUSH else '0'; 47 | 48 | read: process(clk) 49 | begin 50 | if rising_edge(clk) then 51 | if reset = '1' then 52 | bottom <= 0; 53 | else 54 | if pop = '1' then 55 | data_out <= memory(bottom); 56 | bottom <= (bottom + 1) mod DEPTH; 57 | end if; 58 | end if; 59 | end if; 60 | end process read; 61 | 62 | write: process(clk) 63 | begin 64 | if rising_edge(clk) then 65 | if reset = '1' then 66 | top <= 0; 67 | else 68 | if push = '1' then 69 | memory(top) := data_in; 70 | top <= (top + 1) mod DEPTH; 71 | end if; 72 | end if; 73 | end if; 74 | end process write; 75 | 76 | set_prev_op: process(clk) 77 | begin 78 | if rising_edge(clk) then 79 | if reset = '1' then 80 | prev_op <= FIFO_POP; 81 | else 82 | if push = '1' and pop = '1' then 83 | prev_op <= FIFO_POP; 84 | elsif push = '1' then 85 | prev_op <= FIFO_PUSH; 86 | elsif pop = '1' then 87 | prev_op <= FIFO_POP; 88 | end if; 89 | end if; 90 | end if; 91 | end process set_prev_op; 92 | 93 | end architecture behaviour; 94 | -------------------------------------------------------------------------------- /src/dsaf/ry_utilities.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | 7 | use work.ry_types.all; 8 | use work.ry_constants.all; 9 | 10 | package ry_utilities is 11 | 12 | --! Converts a boolean to an std_logic. 13 | function to_std_logic(input : in boolean) return std_logic; 14 | 15 | -- Checks if a number is 2^n: 16 | function is_pow2(input : in natural) return boolean; 17 | 18 | --! Calculates log2 with integers. 19 | function log2(input : in natural) return natural; 20 | 21 | -- Gets the value of the sel signals to the wishbone interconnect for the specified 22 | -- operand size and address. 23 | function wb_get_data_sel(size : in std_logic_vector(1 downto 0); address : in std_logic_vector) 24 | return std_logic_vector; 25 | 26 | end package ry_utilities; 27 | 28 | package body ry_utilities is 29 | 30 | function to_std_logic(input : in boolean) return std_logic is 31 | begin 32 | if input then 33 | return '1'; 34 | else 35 | return '0'; 36 | end if; 37 | end function to_std_logic; 38 | 39 | function is_pow2(input : in natural) return boolean is 40 | variable c : natural := 1; 41 | begin 42 | for i in 0 to 31 loop 43 | if input = c then 44 | return true; 45 | end if; 46 | 47 | c := c * 2; 48 | end loop; 49 | 50 | return false; 51 | end function is_pow2; 52 | 53 | function log2(input : in natural) return natural is 54 | variable retval : natural := 0; 55 | variable temp : natural := input; 56 | begin 57 | while temp > 1 loop 58 | retval := retval + 1; 59 | temp := temp / 2; 60 | end loop; 61 | 62 | return retval; 63 | end function log2; 64 | 65 | function wb_get_data_sel(size : in std_logic_vector(1 downto 0); address : in std_logic_vector) 66 | return std_logic_vector is 67 | begin 68 | case size is 69 | when b"01" => 70 | case address(1 downto 0) is 71 | when b"00" => 72 | return b"0001"; 73 | when b"01" => 74 | return b"0010"; 75 | when b"10" => 76 | return b"0100"; 77 | when b"11" => 78 | return b"1000"; 79 | when others => 80 | return b"0001"; 81 | end case; 82 | when b"10" => 83 | if address(1) = '0' then 84 | return b"0011"; 85 | else 86 | return b"1100"; 87 | end if; 88 | when others => 89 | return b"1111"; 90 | end case; 91 | end function wb_get_data_sel; 92 | 93 | end package body ry_utilities; 94 | -------------------------------------------------------------------------------- /testbenches/tb_soc_memory.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | use ieee.numeric_std.all; 7 | 8 | entity tb_soc_memory is 9 | end entity tb_soc_memory; 10 | 11 | architecture testbench of tb_soc_memory is 12 | 13 | -- Clock signal: 14 | signal clk : std_logic; 15 | constant clk_period : time := 10 ns; 16 | 17 | -- Reset signal: 18 | signal reset : std_logic := '1'; 19 | 20 | -- Wishbone signals: 21 | signal wb_adr_in : std_logic_vector(31 downto 0); 22 | signal wb_dat_in : std_logic_vector(31 downto 0); 23 | signal wb_dat_out : std_logic_vector(31 downto 0); 24 | signal wb_cyc_in : std_logic := '0'; 25 | signal wb_stb_in : std_logic := '0'; 26 | signal wb_sel_in : std_logic_vector(3 downto 0) := (others => '1'); 27 | signal wb_we_in : std_logic := '0'; 28 | signal wb_ack_out : std_logic; 29 | 30 | begin 31 | 32 | uut: entity work.ry_soc_memory 33 | port map( 34 | clk => clk, 35 | reset => reset, 36 | wb_adr_in => wb_adr_in, 37 | wb_dat_in => wb_dat_in, 38 | wb_dat_out => wb_dat_out, 39 | wb_cyc_in => wb_cyc_in, 40 | wb_stb_in => wb_stb_in, 41 | wb_sel_in => wb_sel_in, 42 | wb_we_in => wb_we_in, 43 | wb_ack_out => wb_ack_out 44 | ); 45 | 46 | clock: process 47 | begin 48 | clk <= '1'; 49 | wait for clk_period / 2; 50 | clk <= '0'; 51 | wait for clk_period / 2; 52 | end process clock; 53 | 54 | stimulus: process 55 | begin 56 | wait for clk_period; 57 | reset <= '0'; 58 | 59 | -- Write 32 bit of data to address 0: 60 | wb_adr_in <= x"00000000"; 61 | wb_dat_in <= x"deadbeef"; 62 | wb_cyc_in <= '1'; 63 | wb_stb_in <= '1'; 64 | wb_we_in <= '1'; 65 | wait for clk_period; 66 | wb_stb_in <= '0'; 67 | wb_cyc_in <= '0'; 68 | wait for clk_period; 69 | 70 | -- Write a block write of two 32-bit words at address 0 and 1: 71 | wb_adr_in <= x"00000000"; 72 | wb_dat_in <= x"feedbeef"; 73 | wb_cyc_in <= '1'; 74 | wb_stb_in <= '1'; 75 | wait for clk_period; 76 | wb_stb_in <= '0'; 77 | wb_adr_in <= x"00000004"; 78 | wb_dat_in <= x"f00dd00d"; 79 | wait for clk_period; 80 | wb_stb_in <= '1'; 81 | wait for clk_period; 82 | wb_stb_in <= '0'; 83 | wb_cyc_in <= '0'; 84 | 85 | -- Read address 4: 86 | wait for clk_period; 87 | wb_we_in <= '0'; 88 | wb_adr_in <= x"00000000"; 89 | wb_cyc_in <= '1'; 90 | wb_stb_in <= '1'; 91 | wait for clk_period; 92 | 93 | -- TODO: Make this testbench automatic. 94 | 95 | wait; 96 | end process stimulus; 97 | 98 | end architecture testbench; 99 | -------------------------------------------------------------------------------- /riscv-tests/addi.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # addi.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test addi instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Arithmetic tests 18 | #------------------------------------------------------------- 19 | 20 | TEST_IMM_OP( 2, addi, 0x00000000, 0x00000000, 0x000 ); 21 | TEST_IMM_OP( 3, addi, 0x00000002, 0x00000001, 0x001 ); 22 | TEST_IMM_OP( 4, addi, 0x0000000a, 0x00000003, 0x007 ); 23 | 24 | TEST_IMM_OP( 5, addi, 0xfffffffffffff800, 0x0000000000000000, 0x800 ); 25 | TEST_IMM_OP( 6, addi, 0xffffffff80000000, 0xffffffff80000000, 0x000 ); 26 | TEST_IMM_OP( 7, addi, 0xffffffff7ffff800, 0xffffffff80000000, 0x800 ); 27 | 28 | TEST_IMM_OP( 8, addi, 0x00000000000007ff, 0x00000000, 0x7ff ); 29 | TEST_IMM_OP( 9, addi, 0x000000007fffffff, 0x7fffffff, 0x000 ); 30 | TEST_IMM_OP( 10, addi, 0x00000000800007fe, 0x7fffffff, 0x7ff ); 31 | 32 | TEST_IMM_OP( 11, addi, 0xffffffff800007ff, 0xffffffff80000000, 0x7ff ); 33 | TEST_IMM_OP( 12, addi, 0x000000007ffff7ff, 0x000000007fffffff, 0x800 ); 34 | 35 | TEST_IMM_OP( 13, addi, 0xffffffffffffffff, 0x0000000000000000, 0xfff ); 36 | TEST_IMM_OP( 14, addi, 0x0000000000000000, 0xffffffffffffffff, 0x001 ); 37 | TEST_IMM_OP( 15, addi, 0xfffffffffffffffe, 0xffffffffffffffff, 0xfff ); 38 | 39 | TEST_IMM_OP( 16, addi, 0x0000000080000000, 0x7fffffff, 0x001 ); 40 | 41 | #------------------------------------------------------------- 42 | # Source/Destination tests 43 | #------------------------------------------------------------- 44 | 45 | TEST_IMM_SRC1_EQ_DEST( 17, addi, 24, 13, 11 ); 46 | 47 | #------------------------------------------------------------- 48 | # Bypassing tests 49 | #------------------------------------------------------------- 50 | 51 | TEST_IMM_DEST_BYPASS( 18, 0, addi, 24, 13, 11 ); 52 | TEST_IMM_DEST_BYPASS( 19, 1, addi, 23, 13, 10 ); 53 | TEST_IMM_DEST_BYPASS( 20, 2, addi, 22, 13, 9 ); 54 | 55 | TEST_IMM_SRC1_BYPASS( 21, 0, addi, 24, 13, 11 ); 56 | TEST_IMM_SRC1_BYPASS( 22, 1, addi, 23, 13, 10 ); 57 | TEST_IMM_SRC1_BYPASS( 23, 2, addi, 22, 13, 9 ); 58 | 59 | TEST_IMM_ZEROSRC1( 24, addi, 32, 32 ); 60 | TEST_IMM_ZERODEST( 25, addi, 33, 50 ); 61 | 62 | TEST_PASSFAIL 63 | 64 | RVTEST_CODE_END 65 | 66 | .data 67 | RVTEST_DATA_BEGIN 68 | 69 | TEST_DATA 70 | 71 | RVTEST_DATA_END 72 | -------------------------------------------------------------------------------- /riscv-tests/bltu.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # bltu.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test bltu instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Branch tests 18 | #------------------------------------------------------------- 19 | 20 | # Each test checks both forward and backward branches 21 | 22 | TEST_BR2_OP_TAKEN( 2, bltu, 0x00000000, 0x00000001 ); 23 | TEST_BR2_OP_TAKEN( 3, bltu, 0xfffffffe, 0xffffffff ); 24 | TEST_BR2_OP_TAKEN( 4, bltu, 0x00000000, 0xffffffff ); 25 | 26 | TEST_BR2_OP_NOTTAKEN( 5, bltu, 0x00000001, 0x00000000 ); 27 | TEST_BR2_OP_NOTTAKEN( 6, bltu, 0xffffffff, 0xfffffffe ); 28 | TEST_BR2_OP_NOTTAKEN( 7, bltu, 0xffffffff, 0x00000000 ); 29 | TEST_BR2_OP_NOTTAKEN( 8, bltu, 0x80000000, 0x7fffffff ); 30 | 31 | #------------------------------------------------------------- 32 | # Bypassing tests 33 | #------------------------------------------------------------- 34 | 35 | TEST_BR2_SRC12_BYPASS( 9, 0, 0, bltu, 0xf0000000, 0xefffffff ); 36 | TEST_BR2_SRC12_BYPASS( 10, 0, 1, bltu, 0xf0000000, 0xefffffff ); 37 | TEST_BR2_SRC12_BYPASS( 11, 0, 2, bltu, 0xf0000000, 0xefffffff ); 38 | TEST_BR2_SRC12_BYPASS( 12, 1, 0, bltu, 0xf0000000, 0xefffffff ); 39 | TEST_BR2_SRC12_BYPASS( 13, 1, 1, bltu, 0xf0000000, 0xefffffff ); 40 | TEST_BR2_SRC12_BYPASS( 14, 2, 0, bltu, 0xf0000000, 0xefffffff ); 41 | 42 | TEST_BR2_SRC12_BYPASS( 15, 0, 0, bltu, 0xf0000000, 0xefffffff ); 43 | TEST_BR2_SRC12_BYPASS( 16, 0, 1, bltu, 0xf0000000, 0xefffffff ); 44 | TEST_BR2_SRC12_BYPASS( 17, 0, 2, bltu, 0xf0000000, 0xefffffff ); 45 | TEST_BR2_SRC12_BYPASS( 18, 1, 0, bltu, 0xf0000000, 0xefffffff ); 46 | TEST_BR2_SRC12_BYPASS( 19, 1, 1, bltu, 0xf0000000, 0xefffffff ); 47 | TEST_BR2_SRC12_BYPASS( 20, 2, 0, bltu, 0xf0000000, 0xefffffff ); 48 | 49 | #------------------------------------------------------------- 50 | # Test delay slot instructions not executed nor bypassed 51 | #------------------------------------------------------------- 52 | 53 | TEST_CASE( 21, x1, 3, \ 54 | li x1, 1; \ 55 | bltu x0, x1, 1f; \ 56 | addi x1, x1, 1; \ 57 | addi x1, x1, 1; \ 58 | addi x1, x1, 1; \ 59 | addi x1, x1, 1; \ 60 | 1: addi x1, x1, 1; \ 61 | addi x1, x1, 1; \ 62 | ) 63 | 64 | TEST_PASSFAIL 65 | 66 | RVTEST_CODE_END 67 | 68 | .data 69 | RVTEST_DATA_BEGIN 70 | 71 | TEST_DATA 72 | 73 | RVTEST_DATA_END 74 | -------------------------------------------------------------------------------- /riscv-tests/lb.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # lb.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test lb instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Basic tests 18 | #------------------------------------------------------------- 19 | 20 | TEST_LD_OP( 2, lb, 0xffffffffffffffff, 0, tdat ); 21 | TEST_LD_OP( 3, lb, 0x0000000000000000, 1, tdat ); 22 | TEST_LD_OP( 4, lb, 0xfffffffffffffff0, 2, tdat ); 23 | TEST_LD_OP( 5, lb, 0x000000000000000f, 3, tdat ); 24 | 25 | # Test with negative offset 26 | 27 | TEST_LD_OP( 6, lb, 0xffffffffffffffff, -3, tdat4 ); 28 | TEST_LD_OP( 7, lb, 0x0000000000000000, -2, tdat4 ); 29 | TEST_LD_OP( 8, lb, 0xfffffffffffffff0, -1, tdat4 ); 30 | TEST_LD_OP( 9, lb, 0x000000000000000f, 0, tdat4 ); 31 | 32 | # Test with a negative base 33 | 34 | TEST_CASE( 10, x5, 0xffffffffffffffff, \ 35 | la x1, tdat; \ 36 | addi x1, x1, -32; \ 37 | lb x5, 32(x1); \ 38 | ) 39 | 40 | # Test with unaligned base 41 | 42 | TEST_CASE( 11, x5, 0x0000000000000000, \ 43 | la x1, tdat; \ 44 | addi x1, x1, -6; \ 45 | lb x5, 7(x1); \ 46 | ) 47 | 48 | #------------------------------------------------------------- 49 | # Bypassing tests 50 | #------------------------------------------------------------- 51 | 52 | TEST_LD_DEST_BYPASS( 12, 0, lb, 0xfffffffffffffff0, 1, tdat2 ); 53 | TEST_LD_DEST_BYPASS( 13, 1, lb, 0x000000000000000f, 1, tdat3 ); 54 | TEST_LD_DEST_BYPASS( 14, 2, lb, 0x0000000000000000, 1, tdat1 ); 55 | 56 | TEST_LD_SRC1_BYPASS( 15, 0, lb, 0xfffffffffffffff0, 1, tdat2 ); 57 | TEST_LD_SRC1_BYPASS( 16, 1, lb, 0x000000000000000f, 1, tdat3 ); 58 | TEST_LD_SRC1_BYPASS( 17, 2, lb, 0x0000000000000000, 1, tdat1 ); 59 | 60 | #------------------------------------------------------------- 61 | # Test write-after-write hazard 62 | #------------------------------------------------------------- 63 | 64 | TEST_CASE( 18, x2, 2, \ 65 | la x5, tdat; \ 66 | lb x2, 0(x5); \ 67 | li x2, 2; \ 68 | ) 69 | 70 | TEST_CASE( 19, x2, 2, \ 71 | la x5, tdat; \ 72 | lb x2, 0(x5); \ 73 | nop; \ 74 | li x2, 2; \ 75 | ) 76 | 77 | TEST_PASSFAIL 78 | 79 | RVTEST_CODE_END 80 | 81 | .data 82 | RVTEST_DATA_BEGIN 83 | 84 | TEST_DATA 85 | 86 | tdat: 87 | tdat1: .byte 0xff 88 | tdat2: .byte 0x00 89 | tdat3: .byte 0xf0 90 | tdat4: .byte 0x0f 91 | 92 | RVTEST_DATA_END 93 | -------------------------------------------------------------------------------- /src/ry_fetch.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | use ieee.numeric_std.all; 7 | 8 | use work.ry_constants.all; 9 | 10 | --! @brief Instruction fetch unit. 11 | entity ry_fetch is 12 | generic( 13 | RESET_ADDRESS : std_logic_vector(31 downto 0) 14 | ); 15 | port( 16 | clk : in std_logic; 17 | reset : in std_logic; 18 | 19 | -- Instruction memory connections: 20 | imem_address : out std_logic_vector(31 downto 0); 21 | imem_data_in : in std_logic_vector(31 downto 0); 22 | imem_req : out std_logic; 23 | imem_ack : in std_logic; 24 | 25 | -- Control inputs: 26 | stall : in std_logic; 27 | flush : in std_logic; 28 | branch : in std_logic; 29 | exception : in std_logic; 30 | 31 | branch_target : in std_logic_vector(31 downto 0); 32 | evec : in std_logic_vector(31 downto 0); 33 | 34 | -- Outputs to the instruction decode unit: 35 | instruction_data : out std_logic_vector(31 downto 0); 36 | instruction_address : out std_logic_vector(31 downto 0); 37 | instruction_ready : out std_logic 38 | ); 39 | end entity ry_fetch; 40 | 41 | architecture behaviour of ry_fetch is 42 | signal pc : std_logic_vector(31 downto 0); 43 | signal pc_next : std_logic_vector(31 downto 0); 44 | signal cancel_fetch : std_logic; 45 | begin 46 | 47 | imem_address <= pc_next when cancel_fetch = '0' else pc; 48 | 49 | instruction_data <= imem_data_in; 50 | instruction_ready <= imem_ack and (not stall) and (not cancel_fetch); 51 | instruction_address <= pc; 52 | 53 | imem_req <= not reset; 54 | 55 | set_pc: process(clk) 56 | begin 57 | if rising_edge(clk) then 58 | if reset = '1' then 59 | pc <= RESET_ADDRESS; 60 | cancel_fetch <= '0'; 61 | else 62 | if (exception = '1' or branch = '1') and imem_ack = '0' then 63 | cancel_fetch <= '1'; 64 | pc <= pc_next; 65 | elsif cancel_fetch = '1' and imem_ack = '1' then 66 | cancel_fetch <= '0'; 67 | else 68 | pc <= pc_next; 69 | end if; 70 | end if; 71 | end if; 72 | end process set_pc; 73 | 74 | calc_next_pc: process(reset, stall, branch, exception, imem_ack, branch_target, evec, pc, cancel_fetch) 75 | begin 76 | if exception = '1' then 77 | pc_next <= evec; 78 | elsif branch = '1' then 79 | pc_next <= branch_target; 80 | elsif imem_ack = '1' and stall = '0' and cancel_fetch = '0' then 81 | pc_next <= std_logic_vector(unsigned(pc) + 4); 82 | else 83 | pc_next <= pc; 84 | end if; 85 | end process calc_next_pc; 86 | 87 | end architecture behaviour; 88 | -------------------------------------------------------------------------------- /riscv-tests/lh.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # lh.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test lh instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Basic tests 18 | #------------------------------------------------------------- 19 | 20 | TEST_LD_OP( 2, lh, 0x00000000000000ff, 0, tdat ); 21 | TEST_LD_OP( 3, lh, 0xffffffffffffff00, 2, tdat ); 22 | TEST_LD_OP( 4, lh, 0x0000000000000ff0, 4, tdat ); 23 | TEST_LD_OP( 5, lh, 0xfffffffffffff00f, 6, tdat ); 24 | 25 | # Test with negative offset 26 | 27 | TEST_LD_OP( 6, lh, 0x00000000000000ff, -6, tdat4 ); 28 | TEST_LD_OP( 7, lh, 0xffffffffffffff00, -4, tdat4 ); 29 | TEST_LD_OP( 8, lh, 0x0000000000000ff0, -2, tdat4 ); 30 | TEST_LD_OP( 9, lh, 0xfffffffffffff00f, 0, tdat4 ); 31 | 32 | # Test with a negative base 33 | 34 | TEST_CASE( 10, x5, 0x00000000000000ff, \ 35 | la x1, tdat; \ 36 | addi x1, x1, -32; \ 37 | lh x5, 32(x1); \ 38 | ) 39 | 40 | # Test with unaligned base 41 | 42 | TEST_CASE( 11, x5, 0xffffffffffffff00, \ 43 | la x1, tdat; \ 44 | addi x1, x1, -5; \ 45 | lh x5, 7(x1); \ 46 | ) 47 | 48 | #------------------------------------------------------------- 49 | # Bypassing tests 50 | #------------------------------------------------------------- 51 | 52 | TEST_LD_DEST_BYPASS( 12, 0, lh, 0x0000000000000ff0, 2, tdat2 ); 53 | TEST_LD_DEST_BYPASS( 13, 1, lh, 0xfffffffffffff00f, 2, tdat3 ); 54 | TEST_LD_DEST_BYPASS( 14, 2, lh, 0xffffffffffffff00, 2, tdat1 ); 55 | 56 | TEST_LD_SRC1_BYPASS( 15, 0, lh, 0x0000000000000ff0, 2, tdat2 ); 57 | TEST_LD_SRC1_BYPASS( 16, 1, lh, 0xfffffffffffff00f, 2, tdat3 ); 58 | TEST_LD_SRC1_BYPASS( 17, 2, lh, 0xffffffffffffff00, 2, tdat1 ); 59 | 60 | #------------------------------------------------------------- 61 | # Test write-after-write hazard 62 | #------------------------------------------------------------- 63 | 64 | TEST_CASE( 18, x2, 2, \ 65 | la x5, tdat; \ 66 | lh x2, 0(x5); \ 67 | li x2, 2; \ 68 | ) 69 | 70 | TEST_CASE( 19, x2, 2, \ 71 | la x5, tdat; \ 72 | lh x2, 0(x5); \ 73 | nop; \ 74 | li x2, 2; \ 75 | ) 76 | 77 | TEST_PASSFAIL 78 | 79 | RVTEST_CODE_END 80 | 81 | .data 82 | RVTEST_DATA_BEGIN 83 | 84 | TEST_DATA 85 | 86 | tdat: 87 | tdat1: .half 0x00ff 88 | tdat2: .half 0xff00 89 | tdat3: .half 0x0ff0 90 | tdat4: .half 0xf00f 91 | 92 | RVTEST_DATA_END 93 | -------------------------------------------------------------------------------- /src/dsaf/ry_fetch.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | use ieee.numeric_std.all; 7 | 8 | use work.ry_constants.all; 9 | 10 | --! @brief Instruction fetch unit. 11 | entity ry_fetch is 12 | generic( 13 | RESET_ADDRESS : std_logic_vector(31 downto 0) 14 | ); 15 | port( 16 | clk : in std_logic; 17 | reset : in std_logic; 18 | 19 | -- Instruction memory connections: 20 | imem_address : out std_logic_vector(31 downto 0); 21 | imem_data_in : in std_logic_vector(31 downto 0); 22 | imem_req : out std_logic; 23 | imem_ack : in std_logic; 24 | 25 | -- Control inputs: 26 | stall : in std_logic; 27 | flush : in std_logic; 28 | branch : in std_logic; 29 | exception : in std_logic; 30 | 31 | branch_target : in std_logic_vector(31 downto 0); 32 | evec : in std_logic_vector(31 downto 0); 33 | 34 | -- Outputs to the instruction decode unit: 35 | instruction_data : out std_logic_vector(31 downto 0); 36 | instruction_address : out std_logic_vector(31 downto 0); 37 | instruction_ready : out std_logic 38 | ); 39 | end entity ry_fetch; 40 | 41 | architecture behaviour of ry_fetch is 42 | signal pc : std_logic_vector(31 downto 0); 43 | signal pc_next : std_logic_vector(31 downto 0); 44 | signal cancel_fetch : std_logic; 45 | begin 46 | 47 | imem_address <= pc_next when cancel_fetch = '0' else pc; 48 | 49 | instruction_data <= imem_data_in; 50 | instruction_ready <= imem_ack and (not stall) and (not cancel_fetch); 51 | instruction_address <= pc; 52 | 53 | imem_req <= not reset; 54 | 55 | set_pc: process(clk) 56 | begin 57 | if rising_edge(clk) then 58 | if reset = '1' then 59 | pc <= RESET_ADDRESS; 60 | cancel_fetch <= '0'; 61 | else 62 | if (exception = '1' or branch = '1') and imem_ack = '0' then 63 | cancel_fetch <= '1'; 64 | pc <= pc_next; 65 | elsif cancel_fetch = '1' and imem_ack = '1' then 66 | cancel_fetch <= '0'; 67 | else 68 | pc <= pc_next; 69 | end if; 70 | end if; 71 | end if; 72 | end process set_pc; 73 | 74 | calc_next_pc: process(reset, stall, branch, exception, imem_ack, branch_target, evec, pc, cancel_fetch) 75 | begin 76 | if exception = '1' then 77 | pc_next <= evec; 78 | elsif branch = '1' then 79 | pc_next <= branch_target; 80 | elsif imem_ack = '1' and stall = '0' and cancel_fetch = '0' then 81 | pc_next <= std_logic_vector(unsigned(pc) + 4); 82 | else 83 | pc_next <= pc; 84 | end if; 85 | end process calc_next_pc; 86 | 87 | end architecture behaviour; 88 | -------------------------------------------------------------------------------- /soc/ry_soc_memory.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple processor for FPGA Prototyping 2 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 3 | -- (c) Krishna Subramanian 4 | 5 | library ieee; 6 | use ieee.std_logic_1164.all; 7 | use ieee.numeric_std.all; 8 | 9 | use work.ry_utilities.all; 10 | 11 | --! @brief Simple memory module for use in Wishbone-based systems. 12 | entity ry_soc_memory is 13 | generic( 14 | MEMORY_SIZE : natural := 4096 --! Memory size in bytes. 15 | ); 16 | port( 17 | clk : in std_logic; 18 | reset : in std_logic; 19 | 20 | -- Wishbone interface: 21 | wb_adr_in : in std_logic_vector(log2(MEMORY_SIZE) - 1 downto 0); 22 | wb_dat_in : in std_logic_vector(31 downto 0); 23 | wb_dat_out : out std_logic_vector(31 downto 0); 24 | wb_cyc_in : in std_logic; 25 | wb_stb_in : in std_logic; 26 | wb_sel_in : in std_logic_vector( 3 downto 0); 27 | wb_we_in : in std_logic; 28 | wb_ack_out : out std_logic 29 | ); 30 | end entity ry_soc_memory; 31 | 32 | architecture behaviour of ry_soc_memory is 33 | type memory_array is array(0 to (MEMORY_SIZE / 4) - 1) of std_logic_vector(31 downto 0); 34 | signal memory : memory_array := (others => (others => '0')); 35 | 36 | attribute ram_style : string; 37 | attribute ram_style of memory : signal is "block"; 38 | 39 | type state_type is (IDLE, ACK); 40 | signal state : state_type; 41 | 42 | signal read_ack : std_logic; 43 | 44 | begin 45 | 46 | wb_ack_out <= read_ack and wb_stb_in; 47 | 48 | process(clk) 49 | begin 50 | if rising_edge(clk) then 51 | if reset = '1' then 52 | read_ack <= '0'; 53 | state <= IDLE; 54 | else 55 | if wb_cyc_in = '1' then 56 | case state is 57 | when IDLE => 58 | if wb_stb_in = '1' and wb_we_in = '1' then 59 | for i in 0 to 3 loop 60 | if wb_sel_in(i) = '1' then 61 | memory(to_integer(unsigned(wb_adr_in(wb_adr_in'left downto 2))))(((i + 1) * 8) - 1 downto i * 8) 62 | <= wb_dat_in(((i + 1) * 8) - 1 downto i * 8); 63 | end if; 64 | end loop; 65 | read_ack <= '1'; 66 | state <= ACK; 67 | elsif wb_stb_in = '1' then 68 | wb_dat_out <= memory(to_integer(unsigned(wb_adr_in(wb_adr_in'left downto 2)))); 69 | read_ack <= '1'; 70 | state <= ACK; 71 | end if; 72 | when ACK => 73 | if wb_stb_in = '0' then 74 | read_ack <= '0'; 75 | state <= IDLE; 76 | end if; 77 | end case; 78 | else 79 | state <= IDLE; 80 | read_ack <= '0'; 81 | end if; 82 | end if; 83 | end if; 84 | end process clk; 85 | 86 | end architecture behaviour; 87 | -------------------------------------------------------------------------------- /riscv-tests/lbu.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # lbu.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test lbu instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Basic tests 18 | #------------------------------------------------------------- 19 | 20 | TEST_LD_OP( 2, lbu, 0x00000000000000ff, 0, tdat ); 21 | TEST_LD_OP( 3, lbu, 0x0000000000000000, 1, tdat ); 22 | TEST_LD_OP( 4, lbu, 0x00000000000000f0, 2, tdat ); 23 | TEST_LD_OP( 5, lbu, 0x000000000000000f, 3, tdat ); 24 | 25 | # Test with negative offset 26 | 27 | TEST_LD_OP( 6, lbu, 0x00000000000000ff, -3, tdat4 ); 28 | TEST_LD_OP( 7, lbu, 0x0000000000000000, -2, tdat4 ); 29 | TEST_LD_OP( 8, lbu, 0x00000000000000f0, -1, tdat4 ); 30 | TEST_LD_OP( 9, lbu, 0x000000000000000f, 0, tdat4 ); 31 | 32 | # Test with a negative base 33 | 34 | TEST_CASE( 10, x5, 0x00000000000000ff, \ 35 | la x1, tdat; \ 36 | addi x1, x1, -32; \ 37 | lbu x5, 32(x1); \ 38 | ) 39 | 40 | # Test with unaligned base 41 | 42 | TEST_CASE( 11, x5, 0x0000000000000000, \ 43 | la x1, tdat; \ 44 | addi x1, x1, -6; \ 45 | lbu x5, 7(x1); \ 46 | ) 47 | 48 | #------------------------------------------------------------- 49 | # Bypassing tests 50 | #------------------------------------------------------------- 51 | 52 | TEST_LD_DEST_BYPASS( 12, 0, lbu, 0x00000000000000f0, 1, tdat2 ); 53 | TEST_LD_DEST_BYPASS( 13, 1, lbu, 0x000000000000000f, 1, tdat3 ); 54 | TEST_LD_DEST_BYPASS( 14, 2, lbu, 0x0000000000000000, 1, tdat1 ); 55 | 56 | TEST_LD_SRC1_BYPASS( 15, 0, lbu, 0x00000000000000f0, 1, tdat2 ); 57 | TEST_LD_SRC1_BYPASS( 16, 1, lbu, 0x000000000000000f, 1, tdat3 ); 58 | TEST_LD_SRC1_BYPASS( 17, 2, lbu, 0x0000000000000000, 1, tdat1 ); 59 | 60 | #------------------------------------------------------------- 61 | # Test write-after-write hazard 62 | #------------------------------------------------------------- 63 | 64 | TEST_CASE( 18, x2, 2, \ 65 | la x5, tdat; \ 66 | lbu x2, 0(x5); \ 67 | li x2, 2; \ 68 | ) 69 | 70 | TEST_CASE( 19, x2, 2, \ 71 | la x5, tdat; \ 72 | lbu x2, 0(x5); \ 73 | nop; \ 74 | li x2, 2; \ 75 | ) 76 | 77 | TEST_PASSFAIL 78 | 79 | RVTEST_CODE_END 80 | 81 | .data 82 | RVTEST_DATA_BEGIN 83 | 84 | TEST_DATA 85 | 86 | tdat: 87 | tdat1: .byte 0xff 88 | tdat2: .byte 0x00 89 | tdat3: .byte 0xf0 90 | tdat4: .byte 0x0f 91 | 92 | RVTEST_DATA_END 93 | -------------------------------------------------------------------------------- /riscv-tests/lhu.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # lhu.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test lhu instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Basic tests 18 | #------------------------------------------------------------- 19 | 20 | TEST_LD_OP( 2, lhu, 0x00000000000000ff, 0, tdat ); 21 | TEST_LD_OP( 3, lhu, 0x000000000000ff00, 2, tdat ); 22 | TEST_LD_OP( 4, lhu, 0x0000000000000ff0, 4, tdat ); 23 | TEST_LD_OP( 5, lhu, 0x000000000000f00f, 6, tdat ); 24 | 25 | # Test with negative offset 26 | 27 | TEST_LD_OP( 6, lhu, 0x00000000000000ff, -6, tdat4 ); 28 | TEST_LD_OP( 7, lhu, 0x000000000000ff00, -4, tdat4 ); 29 | TEST_LD_OP( 8, lhu, 0x0000000000000ff0, -2, tdat4 ); 30 | TEST_LD_OP( 9, lhu, 0x000000000000f00f, 0, tdat4 ); 31 | 32 | # Test with a negative base 33 | 34 | TEST_CASE( 10, x5, 0x00000000000000ff, \ 35 | la x1, tdat; \ 36 | addi x1, x1, -32; \ 37 | lhu x5, 32(x1); \ 38 | ) 39 | 40 | # Test with unaligned base 41 | 42 | TEST_CASE( 11, x5, 0x000000000000ff00, \ 43 | la x1, tdat; \ 44 | addi x1, x1, -5; \ 45 | lhu x5, 7(x1); \ 46 | ) 47 | 48 | #------------------------------------------------------------- 49 | # Bypassing tests 50 | #------------------------------------------------------------- 51 | 52 | TEST_LD_DEST_BYPASS( 12, 0, lhu, 0x0000000000000ff0, 2, tdat2 ); 53 | TEST_LD_DEST_BYPASS( 13, 1, lhu, 0x000000000000f00f, 2, tdat3 ); 54 | TEST_LD_DEST_BYPASS( 14, 2, lhu, 0x000000000000ff00, 2, tdat1 ); 55 | 56 | TEST_LD_SRC1_BYPASS( 15, 0, lhu, 0x0000000000000ff0, 2, tdat2 ); 57 | TEST_LD_SRC1_BYPASS( 16, 1, lhu, 0x000000000000f00f, 2, tdat3 ); 58 | TEST_LD_SRC1_BYPASS( 17, 2, lhu, 0x000000000000ff00, 2, tdat1 ); 59 | 60 | #------------------------------------------------------------- 61 | # Test write-after-write hazard 62 | #------------------------------------------------------------- 63 | 64 | TEST_CASE( 18, x2, 2, \ 65 | la x5, tdat; \ 66 | lhu x2, 0(x5); \ 67 | li x2, 2; \ 68 | ) 69 | 70 | TEST_CASE( 19, x2, 2, \ 71 | la x5, tdat; \ 72 | lhu x2, 0(x5); \ 73 | nop; \ 74 | li x2, 2; \ 75 | ) 76 | 77 | TEST_PASSFAIL 78 | 79 | RVTEST_CODE_END 80 | 81 | .data 82 | RVTEST_DATA_BEGIN 83 | 84 | TEST_DATA 85 | 86 | tdat: 87 | tdat1: .half 0x00ff 88 | tdat2: .half 0xff00 89 | tdat3: .half 0x0ff0 90 | tdat4: .half 0xf00f 91 | 92 | RVTEST_DATA_END 93 | -------------------------------------------------------------------------------- /riscv-tests/lw.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # lw.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test lw instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Basic tests 18 | #------------------------------------------------------------- 19 | 20 | TEST_LD_OP( 2, lw, 0x0000000000ff00ff, 0, tdat ); 21 | TEST_LD_OP( 3, lw, 0xffffffffff00ff00, 4, tdat ); 22 | TEST_LD_OP( 4, lw, 0x000000000ff00ff0, 8, tdat ); 23 | TEST_LD_OP( 5, lw, 0xfffffffff00ff00f, 12, tdat ); 24 | 25 | # Test with negative offset 26 | 27 | TEST_LD_OP( 6, lw, 0x0000000000ff00ff, -12, tdat4 ); 28 | TEST_LD_OP( 7, lw, 0xffffffffff00ff00, -8, tdat4 ); 29 | TEST_LD_OP( 8, lw, 0x000000000ff00ff0, -4, tdat4 ); 30 | TEST_LD_OP( 9, lw, 0xfffffffff00ff00f, 0, tdat4 ); 31 | 32 | # Test with a negative base 33 | 34 | TEST_CASE( 10, x5, 0x0000000000ff00ff, \ 35 | la x1, tdat; \ 36 | addi x1, x1, -32; \ 37 | lw x5, 32(x1); \ 38 | ) 39 | 40 | # Test with unaligned base 41 | 42 | TEST_CASE( 11, x5, 0xffffffffff00ff00, \ 43 | la x1, tdat; \ 44 | addi x1, x1, -3; \ 45 | lw x5, 7(x1); \ 46 | ) 47 | 48 | #------------------------------------------------------------- 49 | # Bypassing tests 50 | #------------------------------------------------------------- 51 | 52 | TEST_LD_DEST_BYPASS( 12, 0, lw, 0x000000000ff00ff0, 4, tdat2 ); 53 | TEST_LD_DEST_BYPASS( 13, 1, lw, 0xfffffffff00ff00f, 4, tdat3 ); 54 | TEST_LD_DEST_BYPASS( 14, 2, lw, 0xffffffffff00ff00, 4, tdat1 ); 55 | 56 | TEST_LD_SRC1_BYPASS( 15, 0, lw, 0x000000000ff00ff0, 4, tdat2 ); 57 | TEST_LD_SRC1_BYPASS( 16, 1, lw, 0xfffffffff00ff00f, 4, tdat3 ); 58 | TEST_LD_SRC1_BYPASS( 17, 2, lw, 0xffffffffff00ff00, 4, tdat1 ); 59 | 60 | #------------------------------------------------------------- 61 | # Test write-after-write hazard 62 | #------------------------------------------------------------- 63 | 64 | TEST_CASE( 18, x2, 2, \ 65 | la x5, tdat; \ 66 | lw x2, 0(x5); \ 67 | li x2, 2; \ 68 | ) 69 | 70 | TEST_CASE( 19, x2, 2, \ 71 | la x5, tdat; \ 72 | lw x2, 0(x5); \ 73 | nop; \ 74 | li x2, 2; \ 75 | ) 76 | 77 | TEST_PASSFAIL 78 | 79 | RVTEST_CODE_END 80 | 81 | .data 82 | RVTEST_DATA_BEGIN 83 | 84 | TEST_DATA 85 | 86 | tdat: 87 | tdat1: .word 0x00ff00ff 88 | tdat2: .word 0xff00ff00 89 | tdat3: .word 0x0ff00ff0 90 | tdat4: .word 0xf00ff00f 91 | 92 | RVTEST_DATA_END 93 | -------------------------------------------------------------------------------- /testbenches/tb_soc_timer.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | 7 | entity tb_soc_timer is 8 | end entity tb_soc_timer; 9 | 10 | architecture behaviour of tb_soc_timer is 11 | 12 | -- Clock signal: 13 | signal clk : std_logic := '0'; 14 | constant clk_period : time := 10 ns; 15 | 16 | -- Reset signal: 17 | signal reset : std_logic := '1'; 18 | 19 | -- IRQ signal: 20 | signal irq : std_logic; 21 | 22 | -- Wishbone interface: 23 | signal wb_adr_in : std_logic_vector(11 downto 0) := (others => '0'); 24 | signal wb_dat_in : std_logic_vector(31 downto 0) := (others => '0'); 25 | signal wb_dat_out : std_logic_vector(31 downto 0); 26 | signal wb_cyc_in : std_logic := '0'; 27 | signal wb_stb_in : std_logic := '0'; 28 | signal wb_we_in : std_logic := '0'; 29 | signal wb_ack_out : std_logic; 30 | 31 | begin 32 | 33 | uut: entity work.ry_soc_timer 34 | port map( 35 | clk => clk, 36 | reset => reset, 37 | irq => irq, 38 | wb_adr_in => wb_adr_in, 39 | wb_dat_in => wb_dat_in, 40 | wb_dat_out => wb_dat_out, 41 | wb_cyc_in => wb_cyc_in, 42 | wb_stb_in => wb_stb_in, 43 | wb_we_in => wb_we_in, 44 | wb_ack_out => wb_ack_out 45 | ); 46 | 47 | clock: process 48 | begin 49 | clk <= '1'; 50 | wait for clk_period / 2; 51 | clk <= '0'; 52 | wait for clk_period / 2; 53 | end process clock; 54 | 55 | stimulus: process 56 | begin 57 | wait for clk_period * 2; 58 | reset <= '0'; 59 | 60 | wait for clk_period; 61 | 62 | -- Set the compare register to 50: 63 | wb_cyc_in <= '1'; 64 | wb_stb_in <= '1'; 65 | wb_adr_in <= x"004"; 66 | wb_dat_in <= x"00000032"; 67 | wb_we_in <= '1'; 68 | wait until wb_ack_out = '1'; 69 | wait for clk_period; 70 | 71 | wb_stb_in <= '0'; 72 | wait for clk_period; 73 | 74 | -- Start the timer: 75 | wb_stb_in <= '1'; 76 | wb_adr_in <= x"000"; 77 | wb_dat_in <= x"00000003"; 78 | wait until wb_ack_out = '1'; 79 | wait for clk_period; 80 | 81 | wb_stb_in <= '0'; 82 | wb_cyc_in <= '0'; 83 | wb_we_in <= '0'; 84 | wait for clk_period; 85 | 86 | -- Wait for the interrupt: 87 | wait until irq = '1'; 88 | wait for clk_period; 89 | 90 | -- Reset the interrupt: 91 | wb_cyc_in <= '1'; 92 | wb_stb_in <= '1'; 93 | wb_we_in <= '1'; 94 | wb_adr_in <= x"000"; 95 | wb_dat_in <= x"00000003"; 96 | wait until wb_ack_out = '1'; 97 | wait for clk_period; 98 | 99 | wb_stb_in <= '0'; 100 | wb_cyc_in <= '0'; 101 | wb_we_in <= '0'; 102 | wait for clk_period; 103 | 104 | wait; 105 | end process stimulus; 106 | 107 | end architecture behaviour; 108 | -------------------------------------------------------------------------------- /riscv-tests/bgeu.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # bgeu.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test bgeu instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Branch tests 18 | #------------------------------------------------------------- 19 | 20 | # Each test checks both forward and backward branches 21 | 22 | TEST_BR2_OP_TAKEN( 2, bgeu, 0x00000000, 0x00000000 ); 23 | TEST_BR2_OP_TAKEN( 3, bgeu, 0x00000001, 0x00000001 ); 24 | TEST_BR2_OP_TAKEN( 4, bgeu, 0xffffffff, 0xffffffff ); 25 | TEST_BR2_OP_TAKEN( 5, bgeu, 0x00000001, 0x00000000 ); 26 | TEST_BR2_OP_TAKEN( 6, bgeu, 0xffffffff, 0xfffffffe ); 27 | TEST_BR2_OP_TAKEN( 7, bgeu, 0xffffffff, 0x00000000 ); 28 | 29 | TEST_BR2_OP_NOTTAKEN( 8, bgeu, 0x00000000, 0x00000001 ); 30 | TEST_BR2_OP_NOTTAKEN( 9, bgeu, 0xfffffffe, 0xffffffff ); 31 | TEST_BR2_OP_NOTTAKEN( 10, bgeu, 0x00000000, 0xffffffff ); 32 | TEST_BR2_OP_NOTTAKEN( 11, bgeu, 0x7fffffff, 0x80000000 ); 33 | 34 | #------------------------------------------------------------- 35 | # Bypassing tests 36 | #------------------------------------------------------------- 37 | 38 | TEST_BR2_SRC12_BYPASS( 12, 0, 0, bgeu, 0xefffffff, 0xf0000000 ); 39 | TEST_BR2_SRC12_BYPASS( 13, 0, 1, bgeu, 0xefffffff, 0xf0000000 ); 40 | TEST_BR2_SRC12_BYPASS( 14, 0, 2, bgeu, 0xefffffff, 0xf0000000 ); 41 | TEST_BR2_SRC12_BYPASS( 15, 1, 0, bgeu, 0xefffffff, 0xf0000000 ); 42 | TEST_BR2_SRC12_BYPASS( 16, 1, 1, bgeu, 0xefffffff, 0xf0000000 ); 43 | TEST_BR2_SRC12_BYPASS( 17, 2, 0, bgeu, 0xefffffff, 0xf0000000 ); 44 | 45 | TEST_BR2_SRC12_BYPASS( 18, 0, 0, bgeu, 0xefffffff, 0xf0000000 ); 46 | TEST_BR2_SRC12_BYPASS( 19, 0, 1, bgeu, 0xefffffff, 0xf0000000 ); 47 | TEST_BR2_SRC12_BYPASS( 20, 0, 2, bgeu, 0xefffffff, 0xf0000000 ); 48 | TEST_BR2_SRC12_BYPASS( 21, 1, 0, bgeu, 0xefffffff, 0xf0000000 ); 49 | TEST_BR2_SRC12_BYPASS( 22, 1, 1, bgeu, 0xefffffff, 0xf0000000 ); 50 | TEST_BR2_SRC12_BYPASS( 23, 2, 0, bgeu, 0xefffffff, 0xf0000000 ); 51 | 52 | #------------------------------------------------------------- 53 | # Test delay slot instructions not executed nor bypassed 54 | #------------------------------------------------------------- 55 | 56 | TEST_CASE( 24, x1, 3, \ 57 | li x1, 1; \ 58 | bgeu x1, x0, 1f; \ 59 | addi x1, x1, 1; \ 60 | addi x1, x1, 1; \ 61 | addi x1, x1, 1; \ 62 | addi x1, x1, 1; \ 63 | 1: addi x1, x1, 1; \ 64 | addi x1, x1, 1; \ 65 | ) 66 | 67 | TEST_PASSFAIL 68 | 69 | RVTEST_CODE_END 70 | 71 | .data 72 | RVTEST_DATA_BEGIN 73 | 74 | TEST_DATA 75 | 76 | RVTEST_DATA_END 77 | -------------------------------------------------------------------------------- /riscv-tests/srai.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # srai.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test srai instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Arithmetic tests 18 | #------------------------------------------------------------- 19 | 20 | TEST_IMM_OP( 2, srai, 0xffffff8000000000, 0xffffff8000000000, 0 ); 21 | TEST_IMM_OP( 3, srai, 0xffffffffc0000000, 0xffffffff80000000, 1 ); 22 | TEST_IMM_OP( 4, srai, 0xffffffffff000000, 0xffffffff80000000, 7 ); 23 | TEST_IMM_OP( 5, srai, 0xfffffffffffe0000, 0xffffffff80000000, 14 ); 24 | TEST_IMM_OP( 6, srai, 0xffffffffffffffff, 0xffffffff80000001, 31 ); 25 | 26 | TEST_IMM_OP( 7, srai, 0x000000007fffffff, 0x000000007fffffff, 0 ); 27 | TEST_IMM_OP( 8, srai, 0x000000003fffffff, 0x000000007fffffff, 1 ); 28 | TEST_IMM_OP( 9, srai, 0x0000000000ffffff, 0x000000007fffffff, 7 ); 29 | TEST_IMM_OP( 10, srai, 0x000000000001ffff, 0x000000007fffffff, 14 ); 30 | TEST_IMM_OP( 11, srai, 0x0000000000000000, 0x000000007fffffff, 31 ); 31 | 32 | TEST_IMM_OP( 12, srai, 0xffffffff81818181, 0xffffffff81818181, 0 ); 33 | TEST_IMM_OP( 13, srai, 0xffffffffc0c0c0c0, 0xffffffff81818181, 1 ); 34 | TEST_IMM_OP( 14, srai, 0xffffffffff030303, 0xffffffff81818181, 7 ); 35 | TEST_IMM_OP( 15, srai, 0xfffffffffffe0606, 0xffffffff81818181, 14 ); 36 | TEST_IMM_OP( 16, srai, 0xffffffffffffffff, 0xffffffff81818181, 31 ); 37 | 38 | #------------------------------------------------------------- 39 | # Source/Destination tests 40 | #------------------------------------------------------------- 41 | 42 | TEST_IMM_SRC1_EQ_DEST( 17, srai, 0xffffffffff000000, 0xffffffff80000000, 7 ); 43 | 44 | #------------------------------------------------------------- 45 | # Bypassing tests 46 | #------------------------------------------------------------- 47 | 48 | TEST_IMM_DEST_BYPASS( 18, 0, srai, 0xffffffffff000000, 0xffffffff80000000, 7 ); 49 | TEST_IMM_DEST_BYPASS( 19, 1, srai, 0xfffffffffffe0000, 0xffffffff80000000, 14 ); 50 | TEST_IMM_DEST_BYPASS( 20, 2, srai, 0xffffffffffffffff, 0xffffffff80000001, 31 ); 51 | 52 | TEST_IMM_SRC1_BYPASS( 21, 0, srai, 0xffffffffff000000, 0xffffffff80000000, 7 ); 53 | TEST_IMM_SRC1_BYPASS( 22, 1, srai, 0xfffffffffffe0000, 0xffffffff80000000, 14 ); 54 | TEST_IMM_SRC1_BYPASS( 23, 2, srai, 0xffffffffffffffff, 0xffffffff80000001, 31 ); 55 | 56 | TEST_IMM_ZEROSRC1( 24, srai, 0, 4 ); 57 | TEST_IMM_ZERODEST( 25, srai, 33, 10 ); 58 | 59 | TEST_PASSFAIL 60 | 61 | RVTEST_CODE_END 62 | 63 | .data 64 | RVTEST_DATA_BEGIN 65 | 66 | TEST_DATA 67 | 68 | RVTEST_DATA_END 69 | -------------------------------------------------------------------------------- /riscv-tests/or.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # or.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test or instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Logical tests 18 | #------------------------------------------------------------- 19 | 20 | TEST_RR_OP( 2, or, 0xff0fff0f, 0xff00ff00, 0x0f0f0f0f ); 21 | TEST_RR_OP( 3, or, 0xfff0fff0, 0x0ff00ff0, 0xf0f0f0f0 ); 22 | TEST_RR_OP( 4, or, 0x0fff0fff, 0x00ff00ff, 0x0f0f0f0f ); 23 | TEST_RR_OP( 5, or, 0xf0fff0ff, 0xf00ff00f, 0xf0f0f0f0 ); 24 | 25 | #------------------------------------------------------------- 26 | # Source/Destination tests 27 | #------------------------------------------------------------- 28 | 29 | TEST_RR_SRC1_EQ_DEST( 6, or, 0xff0fff0f, 0xff00ff00, 0x0f0f0f0f ); 30 | TEST_RR_SRC2_EQ_DEST( 7, or, 0xff0fff0f, 0xff00ff00, 0x0f0f0f0f ); 31 | TEST_RR_SRC12_EQ_DEST( 8, or, 0xff00ff00, 0xff00ff00 ); 32 | 33 | #------------------------------------------------------------- 34 | # Bypassing tests 35 | #------------------------------------------------------------- 36 | 37 | TEST_RR_DEST_BYPASS( 9, 0, or, 0xff0fff0f, 0xff00ff00, 0x0f0f0f0f ); 38 | TEST_RR_DEST_BYPASS( 10, 1, or, 0xfff0fff0, 0x0ff00ff0, 0xf0f0f0f0 ); 39 | TEST_RR_DEST_BYPASS( 11, 2, or, 0x0fff0fff, 0x00ff00ff, 0x0f0f0f0f ); 40 | 41 | TEST_RR_SRC12_BYPASS( 12, 0, 0, or, 0xff0fff0f, 0xff00ff00, 0x0f0f0f0f ); 42 | TEST_RR_SRC12_BYPASS( 13, 0, 1, or, 0xfff0fff0, 0x0ff00ff0, 0xf0f0f0f0 ); 43 | TEST_RR_SRC12_BYPASS( 14, 0, 2, or, 0x0fff0fff, 0x00ff00ff, 0x0f0f0f0f ); 44 | TEST_RR_SRC12_BYPASS( 15, 1, 0, or, 0xff0fff0f, 0xff00ff00, 0x0f0f0f0f ); 45 | TEST_RR_SRC12_BYPASS( 16, 1, 1, or, 0xfff0fff0, 0x0ff00ff0, 0xf0f0f0f0 ); 46 | TEST_RR_SRC12_BYPASS( 17, 2, 0, or, 0x0fff0fff, 0x00ff00ff, 0x0f0f0f0f ); 47 | 48 | TEST_RR_SRC21_BYPASS( 18, 0, 0, or, 0xff0fff0f, 0xff00ff00, 0x0f0f0f0f ); 49 | TEST_RR_SRC21_BYPASS( 19, 0, 1, or, 0xfff0fff0, 0x0ff00ff0, 0xf0f0f0f0 ); 50 | TEST_RR_SRC21_BYPASS( 20, 0, 2, or, 0x0fff0fff, 0x00ff00ff, 0x0f0f0f0f ); 51 | TEST_RR_SRC21_BYPASS( 21, 1, 0, or, 0xff0fff0f, 0xff00ff00, 0x0f0f0f0f ); 52 | TEST_RR_SRC21_BYPASS( 22, 1, 1, or, 0xfff0fff0, 0x0ff00ff0, 0xf0f0f0f0 ); 53 | TEST_RR_SRC21_BYPASS( 23, 2, 0, or, 0x0fff0fff, 0x00ff00ff, 0x0f0f0f0f ); 54 | 55 | TEST_RR_ZEROSRC1( 24, or, 0xff00ff00, 0xff00ff00 ); 56 | TEST_RR_ZEROSRC2( 25, or, 0x00ff00ff, 0x00ff00ff ); 57 | TEST_RR_ZEROSRC12( 26, or, 0 ); 58 | TEST_RR_ZERODEST( 27, or, 0x11111111, 0x22222222 ); 59 | 60 | TEST_PASSFAIL 61 | 62 | RVTEST_CODE_END 63 | 64 | .data 65 | RVTEST_DATA_BEGIN 66 | 67 | TEST_DATA 68 | 69 | RVTEST_DATA_END 70 | -------------------------------------------------------------------------------- /riscv-tests/and.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # and.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test and instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Logical tests 18 | #------------------------------------------------------------- 19 | 20 | TEST_RR_OP( 2, and, 0x0f000f00, 0xff00ff00, 0x0f0f0f0f ); 21 | TEST_RR_OP( 3, and, 0x00f000f0, 0x0ff00ff0, 0xf0f0f0f0 ); 22 | TEST_RR_OP( 4, and, 0x000f000f, 0x00ff00ff, 0x0f0f0f0f ); 23 | TEST_RR_OP( 5, and, 0xf000f000, 0xf00ff00f, 0xf0f0f0f0 ); 24 | 25 | #------------------------------------------------------------- 26 | # Source/Destination tests 27 | #------------------------------------------------------------- 28 | 29 | TEST_RR_SRC1_EQ_DEST( 6, and, 0x0f000f00, 0xff00ff00, 0x0f0f0f0f ); 30 | TEST_RR_SRC2_EQ_DEST( 7, and, 0x00f000f0, 0x0ff00ff0, 0xf0f0f0f0 ); 31 | TEST_RR_SRC12_EQ_DEST( 8, and, 0xff00ff00, 0xff00ff00 ); 32 | 33 | #------------------------------------------------------------- 34 | # Bypassing tests 35 | #------------------------------------------------------------- 36 | 37 | TEST_RR_DEST_BYPASS( 9, 0, and, 0x0f000f00, 0xff00ff00, 0x0f0f0f0f ); 38 | TEST_RR_DEST_BYPASS( 10, 1, and, 0x00f000f0, 0x0ff00ff0, 0xf0f0f0f0 ); 39 | TEST_RR_DEST_BYPASS( 11, 2, and, 0x000f000f, 0x00ff00ff, 0x0f0f0f0f ); 40 | 41 | TEST_RR_SRC12_BYPASS( 12, 0, 0, and, 0x0f000f00, 0xff00ff00, 0x0f0f0f0f ); 42 | TEST_RR_SRC12_BYPASS( 13, 0, 1, and, 0x00f000f0, 0x0ff00ff0, 0xf0f0f0f0 ); 43 | TEST_RR_SRC12_BYPASS( 14, 0, 2, and, 0x000f000f, 0x00ff00ff, 0x0f0f0f0f ); 44 | TEST_RR_SRC12_BYPASS( 15, 1, 0, and, 0x0f000f00, 0xff00ff00, 0x0f0f0f0f ); 45 | TEST_RR_SRC12_BYPASS( 16, 1, 1, and, 0x00f000f0, 0x0ff00ff0, 0xf0f0f0f0 ); 46 | TEST_RR_SRC12_BYPASS( 17, 2, 0, and, 0x000f000f, 0x00ff00ff, 0x0f0f0f0f ); 47 | 48 | TEST_RR_SRC21_BYPASS( 18, 0, 0, and, 0x0f000f00, 0xff00ff00, 0x0f0f0f0f ); 49 | TEST_RR_SRC21_BYPASS( 19, 0, 1, and, 0x00f000f0, 0x0ff00ff0, 0xf0f0f0f0 ); 50 | TEST_RR_SRC21_BYPASS( 20, 0, 2, and, 0x000f000f, 0x00ff00ff, 0x0f0f0f0f ); 51 | TEST_RR_SRC21_BYPASS( 21, 1, 0, and, 0x0f000f00, 0xff00ff00, 0x0f0f0f0f ); 52 | TEST_RR_SRC21_BYPASS( 22, 1, 1, and, 0x00f000f0, 0x0ff00ff0, 0xf0f0f0f0 ); 53 | TEST_RR_SRC21_BYPASS( 23, 2, 0, and, 0x000f000f, 0x00ff00ff, 0x0f0f0f0f ); 54 | 55 | TEST_RR_ZEROSRC1( 24, and, 0, 0xff00ff00 ); 56 | TEST_RR_ZEROSRC2( 25, and, 0, 0x00ff00ff ); 57 | TEST_RR_ZEROSRC12( 26, and, 0 ); 58 | TEST_RR_ZERODEST( 27, and, 0x11111111, 0x22222222 ); 59 | 60 | TEST_PASSFAIL 61 | 62 | RVTEST_CODE_END 63 | 64 | .data 65 | RVTEST_DATA_BEGIN 66 | 67 | TEST_DATA 68 | 69 | RVTEST_DATA_END 70 | -------------------------------------------------------------------------------- /riscv-tests/xor.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # xor.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test xor instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Logical tests 18 | #------------------------------------------------------------- 19 | 20 | TEST_RR_OP( 2, xor, 0xf00ff00f, 0xff00ff00, 0x0f0f0f0f ); 21 | TEST_RR_OP( 3, xor, 0xff00ff00, 0x0ff00ff0, 0xf0f0f0f0 ); 22 | TEST_RR_OP( 4, xor, 0x0ff00ff0, 0x00ff00ff, 0x0f0f0f0f ); 23 | TEST_RR_OP( 5, xor, 0x00ff00ff, 0xf00ff00f, 0xf0f0f0f0 ); 24 | 25 | #------------------------------------------------------------- 26 | # Source/Destination tests 27 | #------------------------------------------------------------- 28 | 29 | TEST_RR_SRC1_EQ_DEST( 6, xor, 0xf00ff00f, 0xff00ff00, 0x0f0f0f0f ); 30 | TEST_RR_SRC2_EQ_DEST( 7, xor, 0xf00ff00f, 0xff00ff00, 0x0f0f0f0f ); 31 | TEST_RR_SRC12_EQ_DEST( 8, xor, 0x00000000, 0xff00ff00 ); 32 | 33 | #------------------------------------------------------------- 34 | # Bypassing tests 35 | #------------------------------------------------------------- 36 | 37 | TEST_RR_DEST_BYPASS( 9, 0, xor, 0xf00ff00f, 0xff00ff00, 0x0f0f0f0f ); 38 | TEST_RR_DEST_BYPASS( 10, 1, xor, 0xff00ff00, 0x0ff00ff0, 0xf0f0f0f0 ); 39 | TEST_RR_DEST_BYPASS( 11, 2, xor, 0x0ff00ff0, 0x00ff00ff, 0x0f0f0f0f ); 40 | 41 | TEST_RR_SRC12_BYPASS( 12, 0, 0, xor, 0xf00ff00f, 0xff00ff00, 0x0f0f0f0f ); 42 | TEST_RR_SRC12_BYPASS( 13, 0, 1, xor, 0xff00ff00, 0x0ff00ff0, 0xf0f0f0f0 ); 43 | TEST_RR_SRC12_BYPASS( 14, 0, 2, xor, 0x0ff00ff0, 0x00ff00ff, 0x0f0f0f0f ); 44 | TEST_RR_SRC12_BYPASS( 15, 1, 0, xor, 0xf00ff00f, 0xff00ff00, 0x0f0f0f0f ); 45 | TEST_RR_SRC12_BYPASS( 16, 1, 1, xor, 0xff00ff00, 0x0ff00ff0, 0xf0f0f0f0 ); 46 | TEST_RR_SRC12_BYPASS( 17, 2, 0, xor, 0x0ff00ff0, 0x00ff00ff, 0x0f0f0f0f ); 47 | 48 | TEST_RR_SRC21_BYPASS( 18, 0, 0, xor, 0xf00ff00f, 0xff00ff00, 0x0f0f0f0f ); 49 | TEST_RR_SRC21_BYPASS( 19, 0, 1, xor, 0xff00ff00, 0x0ff00ff0, 0xf0f0f0f0 ); 50 | TEST_RR_SRC21_BYPASS( 20, 0, 2, xor, 0x0ff00ff0, 0x00ff00ff, 0x0f0f0f0f ); 51 | TEST_RR_SRC21_BYPASS( 21, 1, 0, xor, 0xf00ff00f, 0xff00ff00, 0x0f0f0f0f ); 52 | TEST_RR_SRC21_BYPASS( 22, 1, 1, xor, 0xff00ff00, 0x0ff00ff0, 0xf0f0f0f0 ); 53 | TEST_RR_SRC21_BYPASS( 23, 2, 0, xor, 0x0ff00ff0, 0x00ff00ff, 0x0f0f0f0f ); 54 | 55 | TEST_RR_ZEROSRC1( 24, xor, 0xff00ff00, 0xff00ff00 ); 56 | TEST_RR_ZEROSRC2( 25, xor, 0x00ff00ff, 0x00ff00ff ); 57 | TEST_RR_ZEROSRC12( 26, xor, 0 ); 58 | TEST_RR_ZERODEST( 27, xor, 0x11111111, 0x22222222 ); 59 | 60 | TEST_PASSFAIL 61 | 62 | RVTEST_CODE_END 63 | 64 | .data 65 | RVTEST_DATA_BEGIN 66 | 67 | TEST_DATA 68 | 69 | RVTEST_DATA_END 70 | -------------------------------------------------------------------------------- /riscy.h: -------------------------------------------------------------------------------- 1 | /* The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | (c) Krishna Subramanian 3 | */ 4 | #ifndef RISCY_H 5 | #define RISCY_H 6 | 7 | #include 8 | 9 | // Number of IRQs supported: 10 | #define RISCY_NUM_IRQS 8 11 | 12 | // Exception cause values: 13 | #define RISCY_MCAUSE_INSTR_MISALIGN 0x00 14 | #define RISCY_MCAUSE_INSTR_FETCH 0x01 15 | #define RISCY_MCAUSE_INVALID_INSTR 0x02 16 | #define RISCY_MCAUSE_BREAKPOINT 0x03 17 | #define RISCY_MCAUSE_LOAD_MISALIGN 0x04 18 | #define RISCY_MCAUSE_LOAD_ERROR 0x05 19 | #define RISCY_MCAUSE_STORE_MISALIGN 0x06 20 | #define RISCY_MCAUSE_STORE_ERROR 0x07 21 | #define RISCY_MCAUSE_ECALL 0x0b 22 | 23 | // IRQ base value 24 | #define RISCY_MCAUSE_IRQ_BASE 0x80000010 25 | 26 | // IRQ number mask 27 | #define RISCY_MCAUSE_IRQ_MASK 0x0f 28 | 29 | // Interrupt bit in the cause register: 30 | #define RISCY_MCAUSE_INTERRUPT_BIT 31 31 | 32 | // IRQ bit in the cause register: 33 | #define RISCY_MCAUSE_IRQ_BIT 4 34 | 35 | // Status register bit indices: 36 | #define STATUS_MIE 3 // Enable Interrupts 37 | #define STATUS_MPIE 7 // Previous value of Enable Interrupts 38 | 39 | #define riscy_enable_interrupts() asm volatile("csrsi mstatus, 1 << %[mie_bit]\n" \ 40 | :: [mie_bit] "i" (STATUS_MIE)) 41 | #define riscy_disable_interrupts() \ 42 | do { \ 43 | uint32_t temp = 1 << STATUS_MIE | 1 << STATUS_MPIE; \ 44 | asm volatile("csrc mstatus, %[temp]\n" :: [temp] "r" (temp)); \ 45 | } while(0) 46 | 47 | #define riscy_write_host(data) \ 48 | do { \ 49 | register uint32_t temp = data; \ 50 | asm volatile("csrw mtohost, %[temp]\n" \ 51 | :: [temp] "r" (temp)); \ 52 | } while(0); 53 | 54 | #define riscy_wfi() asm volatile("wfi\n\t") 55 | 56 | /** 57 | * Gets the value of the MCAUSE register. 58 | */ 59 | static inline uint32_t riscy_get_mcause(void) 60 | { 61 | register uint32_t retval = 0; 62 | asm volatile( 63 | "csrr %[retval], mcause\n" 64 | : [retval] "=r" (retval) 65 | ); 66 | 67 | return retval; 68 | } 69 | 70 | /** 71 | * Enables a specific IRQ. 72 | * @note To globally enable IRQs, use the @ref riscy_enable_interrupts() function. 73 | */ 74 | static inline void riscy_enable_irq(uint8_t n) 75 | { 76 | register uint32_t temp = 1 << (n + 24); 77 | asm volatile( 78 | "csrs mie, %[temp]\n" 79 | :: [temp] "r" (temp) 80 | ); 81 | } 82 | 83 | /** 84 | * Disables a specific IRQ. 85 | */ 86 | static inline void riscy_disable_irq(uint8_t n) 87 | { 88 | register uint32_t temp = 1 << (n + 24); 89 | asm volatile( 90 | "csrc mie, %[temp]\n" 91 | :: [temp] "r" (temp) 92 | ); 93 | } 94 | 95 | #define riscy_get_badaddr(n) \ 96 | do { \ 97 | register uint32_t temp = 0; \ 98 | asm volatile ( \ 99 | "csrr %[temp], mbadaddr\n" \ 100 | : [temp] "=r" (temp)); \ 101 | n = temp; \ 102 | } while(0) 103 | 104 | #endif 105 | 106 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RISCY 2 | Basic RISC-V RV32I CPU in VHDL for use in FPGA Prototyping 3 | 4 | 5 | The RISCY Processor is a simple RISC-V processor written in VHDL for use in FPGAs. It implements the 32-bit integer subset of the RISC-V Specification version 2.0 and supports large parts of the the machine mode specified in the RISC-V Privileged Architecture Specification v1.10. 6 | 7 | 8 | 9 | 10 | ![Datapath Diagram](https://github.com/mongrelgem/RISCY/blob/master/docs/diagram.png?raw=true) 11 | 12 | 13 | 14 | 15 | The processor has been tested on an Arty board using the example SoC design provided in the example/ directory and the applications found in the software/ directory. Synthesis and implementation has been tested on various versions of Xilinx' Vivado toolchain, most recently version 2018.2. 16 | 17 | 18 | 19 | ## Features 20 | 21 | * Supports the complete **32-bit RISC-V base integer ISA (RV32I) version 2.0** 22 | * Supports large parts of the machine mode defined in the RISC-V Privileged Architecture version 1.10 23 | * Support for maximum of 8 individually maskable external interrupts (IRQs) 24 | * Implements a classic 5-stage RISC pipeline 25 | * Optional Modular instruction cache 26 | * Included Hardware Timer with microsecond resolution and compare interupts 27 | * Supports the Wishbone bus ( version B4 ) 28 | 29 | ## Interfacing 30 | 31 | The processor includes a wishbone interface conforming to the B4 revision of the wishbone specification 32 | 33 | | Interface type | Master | 34 | | ------------- |:-------------------:| 35 | | Address port width | 32 bits | 36 | | Data port width | 32 bits | 37 | | Data port granularity | 8 bits | 38 | | Maximum Operand Size | 32 bits | 39 | | Endianess | Little | 40 | | Sequence of Data Transfer | In-order| 41 | 42 | ## Peripheral Interfacing 43 | 44 | The project includes a variety of Wishbone-compatible peripherals for use in system-on-chip designs based on the RISC processor. The main peripherals are: 45 | 46 | * **Timer** a 32-bit timer with compare interrupt 47 | * **GPIO** a configurable-width generic GPIO module 48 | * **Memory** a block RAM memory module 49 | * **UART** a UART module with hardware FIFOs, configurable baudrate and RX/TX interrupts 50 | 51 | ## Getting Started 52 | To instantiate the processor, add the source files from the src/ folder to your local project. Use the pp_potato entity to instantiate a processor with a Wishbone interface. Some generics are provided to configure the processor core. 53 | 54 | An example System-on-Chip for the Arty development board can be found in the example/ directory of the source repository. 55 | 56 | ## Compiler Toolchain 57 | 58 | In order to run programs on the RISCY processor, an appropriate compiler toolchain is needed. Follow the instructions on the [RISCV GNU toolchain](https://github.com/riscv/riscv-gnu-toolchain) repository site to build and install a 32-bit RISC-V toolchain. 59 | -------------------------------------------------------------------------------- /riscv-tests/sb.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # sb.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test sb instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Basic tests 18 | #------------------------------------------------------------- 19 | 20 | TEST_ST_OP( 2, lb, sb, 0xffffffffffffffaa, 0, tdat ); 21 | TEST_ST_OP( 3, lb, sb, 0x0000000000000000, 1, tdat ); 22 | TEST_ST_OP( 4, lh, sb, 0xffffffffffffefa0, 2, tdat ); 23 | TEST_ST_OP( 5, lb, sb, 0x000000000000000a, 3, tdat ); 24 | 25 | # Test with negative offset 26 | 27 | TEST_ST_OP( 6, lb, sb, 0xffffffffffffffaa, -3, tdat8 ); 28 | TEST_ST_OP( 7, lb, sb, 0x0000000000000000, -2, tdat8 ); 29 | TEST_ST_OP( 8, lb, sb, 0xffffffffffffffa0, -1, tdat8 ); 30 | TEST_ST_OP( 9, lb, sb, 0x000000000000000a, 0, tdat8 ); 31 | 32 | # Test with a negative base 33 | 34 | TEST_CASE( 10, x5, 0x78, \ 35 | la x1, tdat9; \ 36 | li x2, 0x12345678; \ 37 | addi x4, x1, -32; \ 38 | sb x2, 32(x4); \ 39 | lb x5, 0(x1); \ 40 | ) 41 | 42 | # Test with unaligned base 43 | 44 | TEST_CASE( 11, x5, 0xffffffffffffff98, \ 45 | la x1, tdat9; \ 46 | li x2, 0x00003098; \ 47 | addi x1, x1, -6; \ 48 | sb x2, 7(x1); \ 49 | la x4, tdat10; \ 50 | lb x5, 0(x4); \ 51 | ) 52 | 53 | #------------------------------------------------------------- 54 | # Bypassing tests 55 | #------------------------------------------------------------- 56 | 57 | TEST_ST_SRC12_BYPASS( 12, 0, 0, lb, sb, 0xffffffffffffffdd, 0, tdat ); 58 | TEST_ST_SRC12_BYPASS( 13, 0, 1, lb, sb, 0xffffffffffffffcd, 1, tdat ); 59 | TEST_ST_SRC12_BYPASS( 14, 0, 2, lb, sb, 0xffffffffffffffcc, 2, tdat ); 60 | TEST_ST_SRC12_BYPASS( 15, 1, 0, lb, sb, 0xffffffffffffffbc, 3, tdat ); 61 | TEST_ST_SRC12_BYPASS( 16, 1, 1, lb, sb, 0xffffffffffffffbb, 4, tdat ); 62 | TEST_ST_SRC12_BYPASS( 17, 2, 0, lb, sb, 0xffffffffffffffab, 5, tdat ); 63 | 64 | TEST_ST_SRC21_BYPASS( 18, 0, 0, lb, sb, 0x33, 0, tdat ); 65 | TEST_ST_SRC21_BYPASS( 19, 0, 1, lb, sb, 0x23, 1, tdat ); 66 | TEST_ST_SRC21_BYPASS( 20, 0, 2, lb, sb, 0x22, 2, tdat ); 67 | TEST_ST_SRC21_BYPASS( 21, 1, 0, lb, sb, 0x12, 3, tdat ); 68 | TEST_ST_SRC21_BYPASS( 22, 1, 1, lb, sb, 0x11, 4, tdat ); 69 | TEST_ST_SRC21_BYPASS( 23, 2, 0, lb, sb, 0x01, 5, tdat ); 70 | 71 | li a0, 0xef 72 | la a1, tdat 73 | sb a0, 3(a1) 74 | 75 | TEST_PASSFAIL 76 | 77 | RVTEST_CODE_END 78 | 79 | .data 80 | RVTEST_DATA_BEGIN 81 | 82 | TEST_DATA 83 | 84 | tdat: 85 | tdat1: .byte 0xef 86 | tdat2: .byte 0xef 87 | tdat3: .byte 0xef 88 | tdat4: .byte 0xef 89 | tdat5: .byte 0xef 90 | tdat6: .byte 0xef 91 | tdat7: .byte 0xef 92 | tdat8: .byte 0xef 93 | tdat9: .byte 0xef 94 | tdat10: .byte 0xef 95 | 96 | RVTEST_DATA_END 97 | -------------------------------------------------------------------------------- /libsoc/icerror.h: -------------------------------------------------------------------------------- 1 | // The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | // (c) Krishna Subramanian 3 | 4 | #ifndef LIBSOC_ICERROR_H 5 | #define LIBSOC_ICERROR_H 6 | 7 | // Interconnect Error Module registers: 8 | #define ICERROR_REG_STATUS 0x00 9 | #define ICERROR_REG_CONTROL 0x00 10 | #define ICERROR_REG_READ_ADDRESS 0x04 11 | #define ICERROR_REG_READ_MASK 0x08 12 | #define ICERROR_REG_WRITE_ADDRESS 0x0c 13 | #define ICERROR_REG_WRITE_MASK 0x10 14 | #define ICERROR_REG_WRITE_DATA 0x14 15 | 16 | // Interconnect Error Module control register bits: 17 | #define ICERROR_CONTROL_IRQ_RESET 0 18 | 19 | // Interconnect Error Module status register bits: 20 | #define ICERROR_STATUS_IRQ_STATUS 0 21 | #define ICERROR_STATUS_READ_ERROR 1 22 | #define ICERROR_STATUS_WRITE_ERROR 2 23 | 24 | struct icerror 25 | { 26 | volatile uint32_t * registers; 27 | }; 28 | 29 | enum icerror_access_type 30 | { 31 | ICERROR_ACCESS_READ, 32 | ICERROR_ACCESS_WRITE, 33 | ICERROR_ACCESS_NONE 34 | }; 35 | 36 | /** 37 | * Initializes an interconnect error instance. 38 | * @param module Pointer to an interconnect error instance structure. 39 | * @param base_address Base address of the hardware module. 40 | */ 41 | static inline void icerror_initialize(struct icerror * module, volatile void * base_address) 42 | { 43 | module->registers = base_address; 44 | } 45 | 46 | /** 47 | * Resets an interconnect error instance. 48 | * @param module Pointer to an interconnect error instance structure. 49 | */ 50 | static inline void icerror_reset(struct icerror * module) 51 | { 52 | module->registers[ICERROR_REG_CONTROL >> 2] = 1 << ICERROR_CONTROL_IRQ_RESET; 53 | } 54 | 55 | /** 56 | * Gets the access type for the previous access error. 57 | * @param module Pointer to an interconnect error instance structure. 58 | * @returns The access type for the previous access error. 59 | */ 60 | static inline enum icerror_access_type icerror_get_access_type(struct icerror * module) 61 | { 62 | if(module->registers[ICERROR_REG_STATUS >> 2] & (1 << ICERROR_STATUS_READ_ERROR)) 63 | return ICERROR_ACCESS_READ; 64 | else if(module->registers[ICERROR_REG_STATUS >> 2] & (1 << ICERROR_STATUS_WRITE_ERROR)) 65 | return ICERROR_ACCESS_WRITE; 66 | else 67 | return ICERROR_ACCESS_NONE; 68 | } 69 | 70 | /** 71 | * Gets the access address for the previous read error. 72 | * @param module Pointer to an interconnect error instance structure. 73 | * @returns The address of the previous read error. 74 | */ 75 | static inline uint32_t icerror_get_read_address(struct icerror * module) 76 | { 77 | return module->registers[ICERROR_REG_READ_ADDRESS >> 2]; 78 | } 79 | 80 | /** 81 | * Gets the access address for the previous write error. 82 | * @param module Pointer to an interconnect error instance structure. 83 | * @returns The address of the previous write error. 84 | */ 85 | static inline uint32_t icerror_get_write_address(struct icerror * module) 86 | { 87 | return module->registers[ICERROR_REG_WRITE_ADDRESS >> 2]; 88 | } 89 | 90 | #endif 91 | 92 | -------------------------------------------------------------------------------- /riscv-tests/sh.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # sh.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test sh instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Basic tests 18 | #------------------------------------------------------------- 19 | 20 | TEST_ST_OP( 2, lh, sh, 0x00000000000000aa, 0, tdat ); 21 | TEST_ST_OP( 3, lh, sh, 0xffffffffffffaa00, 2, tdat ); 22 | TEST_ST_OP( 4, lw, sh, 0xffffffffbeef0aa0, 4, tdat ); 23 | TEST_ST_OP( 5, lh, sh, 0xffffffffffffa00a, 6, tdat ); 24 | 25 | # Test with negative offset 26 | 27 | TEST_ST_OP( 6, lh, sh, 0x00000000000000aa, -6, tdat8 ); 28 | TEST_ST_OP( 7, lh, sh, 0xffffffffffffaa00, -4, tdat8 ); 29 | TEST_ST_OP( 8, lh, sh, 0x0000000000000aa0, -2, tdat8 ); 30 | TEST_ST_OP( 9, lh, sh, 0xffffffffffffa00a, 0, tdat8 ); 31 | 32 | # Test with a negative base 33 | 34 | TEST_CASE( 10, x5, 0x5678, \ 35 | la x1, tdat9; \ 36 | li x2, 0x12345678; \ 37 | addi x4, x1, -32; \ 38 | sh x2, 32(x4); \ 39 | lh x5, 0(x1); \ 40 | ) 41 | 42 | # Test with unaligned base 43 | 44 | TEST_CASE( 11, x5, 0x3098, \ 45 | la x1, tdat9; \ 46 | li x2, 0x00003098; \ 47 | addi x1, x1, -5; \ 48 | sh x2, 7(x1); \ 49 | la x4, tdat10; \ 50 | lh x5, 0(x4); \ 51 | ) 52 | 53 | #------------------------------------------------------------- 54 | # Bypassing tests 55 | #------------------------------------------------------------- 56 | 57 | TEST_ST_SRC12_BYPASS( 12, 0, 0, lh, sh, 0xffffffffffffccdd, 0, tdat ); 58 | TEST_ST_SRC12_BYPASS( 13, 0, 1, lh, sh, 0xffffffffffffbccd, 2, tdat ); 59 | TEST_ST_SRC12_BYPASS( 14, 0, 2, lh, sh, 0xffffffffffffbbcc, 4, tdat ); 60 | TEST_ST_SRC12_BYPASS( 15, 1, 0, lh, sh, 0xffffffffffffabbc, 6, tdat ); 61 | TEST_ST_SRC12_BYPASS( 16, 1, 1, lh, sh, 0xffffffffffffaabb, 8, tdat ); 62 | TEST_ST_SRC12_BYPASS( 17, 2, 0, lh, sh, 0xffffffffffffdaab, 10, tdat ); 63 | 64 | TEST_ST_SRC21_BYPASS( 18, 0, 0, lh, sh, 0x2233, 0, tdat ); 65 | TEST_ST_SRC21_BYPASS( 19, 0, 1, lh, sh, 0x1223, 2, tdat ); 66 | TEST_ST_SRC21_BYPASS( 20, 0, 2, lh, sh, 0x1122, 4, tdat ); 67 | TEST_ST_SRC21_BYPASS( 21, 1, 0, lh, sh, 0x0112, 6, tdat ); 68 | TEST_ST_SRC21_BYPASS( 22, 1, 1, lh, sh, 0x0011, 8, tdat ); 69 | TEST_ST_SRC21_BYPASS( 23, 2, 0, lh, sh, 0x3001, 10, tdat ); 70 | 71 | li a0, 0xbeef 72 | la a1, tdat 73 | sh a0, 6(a1) 74 | 75 | TEST_PASSFAIL 76 | 77 | RVTEST_CODE_END 78 | 79 | .data 80 | RVTEST_DATA_BEGIN 81 | 82 | TEST_DATA 83 | 84 | tdat: 85 | tdat1: .half 0xbeef 86 | tdat2: .half 0xbeef 87 | tdat3: .half 0xbeef 88 | tdat4: .half 0xbeef 89 | tdat5: .half 0xbeef 90 | tdat6: .half 0xbeef 91 | tdat7: .half 0xbeef 92 | tdat8: .half 0xbeef 93 | tdat9: .half 0xbeef 94 | tdat10: .half 0xbeef 95 | 96 | RVTEST_DATA_END 97 | -------------------------------------------------------------------------------- /riscv-tests/sw.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # sw.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test sw instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Basic tests 18 | #------------------------------------------------------------- 19 | 20 | TEST_ST_OP( 2, lw, sw, 0x0000000000aa00aa, 0, tdat ); 21 | TEST_ST_OP( 3, lw, sw, 0xffffffffaa00aa00, 4, tdat ); 22 | TEST_ST_OP( 4, lw, sw, 0x000000000aa00aa0, 8, tdat ); 23 | TEST_ST_OP( 5, lw, sw, 0xffffffffa00aa00a, 12, tdat ); 24 | 25 | # Test with negative offset 26 | 27 | TEST_ST_OP( 6, lw, sw, 0x0000000000aa00aa, -12, tdat8 ); 28 | TEST_ST_OP( 7, lw, sw, 0xffffffffaa00aa00, -8, tdat8 ); 29 | TEST_ST_OP( 8, lw, sw, 0x000000000aa00aa0, -4, tdat8 ); 30 | TEST_ST_OP( 9, lw, sw, 0xffffffffa00aa00a, 0, tdat8 ); 31 | 32 | # Test with a negative base 33 | 34 | TEST_CASE( 10, x5, 0x12345678, \ 35 | la x1, tdat9; \ 36 | li x2, 0x12345678; \ 37 | addi x4, x1, -32; \ 38 | sw x2, 32(x4); \ 39 | lw x5, 0(x1); \ 40 | ) 41 | 42 | # Test with unaligned base 43 | 44 | TEST_CASE( 11, x5, 0x58213098, \ 45 | la x1, tdat9; \ 46 | li x2, 0x58213098; \ 47 | addi x1, x1, -3; \ 48 | sw x2, 7(x1); \ 49 | la x4, tdat10; \ 50 | lw x5, 0(x4); \ 51 | ) 52 | 53 | #------------------------------------------------------------- 54 | # Bypassing tests 55 | #------------------------------------------------------------- 56 | 57 | TEST_ST_SRC12_BYPASS( 12, 0, 0, lw, sw, 0xffffffffaabbccdd, 0, tdat ); 58 | TEST_ST_SRC12_BYPASS( 13, 0, 1, lw, sw, 0xffffffffdaabbccd, 4, tdat ); 59 | TEST_ST_SRC12_BYPASS( 14, 0, 2, lw, sw, 0xffffffffddaabbcc, 8, tdat ); 60 | TEST_ST_SRC12_BYPASS( 15, 1, 0, lw, sw, 0xffffffffcddaabbc, 12, tdat ); 61 | TEST_ST_SRC12_BYPASS( 16, 1, 1, lw, sw, 0xffffffffccddaabb, 16, tdat ); 62 | TEST_ST_SRC12_BYPASS( 17, 2, 0, lw, sw, 0xffffffffbccddaab, 20, tdat ); 63 | 64 | TEST_ST_SRC21_BYPASS( 18, 0, 0, lw, sw, 0x00112233, 0, tdat ); 65 | TEST_ST_SRC21_BYPASS( 19, 0, 1, lw, sw, 0x30011223, 4, tdat ); 66 | TEST_ST_SRC21_BYPASS( 20, 0, 2, lw, sw, 0x33001122, 8, tdat ); 67 | TEST_ST_SRC21_BYPASS( 21, 1, 0, lw, sw, 0x23300112, 12, tdat ); 68 | TEST_ST_SRC21_BYPASS( 22, 1, 1, lw, sw, 0x22330011, 16, tdat ); 69 | TEST_ST_SRC21_BYPASS( 23, 2, 0, lw, sw, 0x12233001, 20, tdat ); 70 | 71 | TEST_PASSFAIL 72 | 73 | RVTEST_CODE_END 74 | 75 | .data 76 | RVTEST_DATA_BEGIN 77 | 78 | TEST_DATA 79 | 80 | tdat: 81 | tdat1: .word 0xdeadbeef 82 | tdat2: .word 0xdeadbeef 83 | tdat3: .word 0xdeadbeef 84 | tdat4: .word 0xdeadbeef 85 | tdat5: .word 0xdeadbeef 86 | tdat6: .word 0xdeadbeef 87 | tdat7: .word 0xdeadbeef 88 | tdat8: .word 0xdeadbeef 89 | tdat9: .word 0xdeadbeef 90 | tdat10: .word 0xdeadbeef 91 | 92 | RVTEST_DATA_END 93 | -------------------------------------------------------------------------------- /riscv-tests/sltu.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # sltu.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test sltu instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Arithmetic tests 18 | #------------------------------------------------------------- 19 | 20 | TEST_RR_OP( 2, sltu, 0, 0x00000000, 0x00000000 ); 21 | TEST_RR_OP( 3, sltu, 0, 0x00000001, 0x00000001 ); 22 | TEST_RR_OP( 4, sltu, 1, 0x00000003, 0x00000007 ); 23 | TEST_RR_OP( 5, sltu, 0, 0x00000007, 0x00000003 ); 24 | 25 | TEST_RR_OP( 6, sltu, 1, 0x00000000, 0xffff8000 ); 26 | TEST_RR_OP( 7, sltu, 0, 0x80000000, 0x00000000 ); 27 | TEST_RR_OP( 8, sltu, 1, 0x80000000, 0xffff8000 ); 28 | 29 | TEST_RR_OP( 9, sltu, 1, 0x00000000, 0x00007fff ); 30 | TEST_RR_OP( 10, sltu, 0, 0x7fffffff, 0x00000000 ); 31 | TEST_RR_OP( 11, sltu, 0, 0x7fffffff, 0x00007fff ); 32 | 33 | TEST_RR_OP( 12, sltu, 0, 0x80000000, 0x00007fff ); 34 | TEST_RR_OP( 13, sltu, 1, 0x7fffffff, 0xffff8000 ); 35 | 36 | TEST_RR_OP( 14, sltu, 1, 0x00000000, 0xffffffff ); 37 | TEST_RR_OP( 15, sltu, 0, 0xffffffff, 0x00000001 ); 38 | TEST_RR_OP( 16, sltu, 0, 0xffffffff, 0xffffffff ); 39 | 40 | #------------------------------------------------------------- 41 | # Source/Destination tests 42 | #------------------------------------------------------------- 43 | 44 | TEST_RR_SRC1_EQ_DEST( 17, sltu, 0, 14, 13 ); 45 | TEST_RR_SRC2_EQ_DEST( 18, sltu, 1, 11, 13 ); 46 | TEST_RR_SRC12_EQ_DEST( 19, sltu, 0, 13 ); 47 | 48 | #------------------------------------------------------------- 49 | # Bypassing tests 50 | #------------------------------------------------------------- 51 | 52 | TEST_RR_DEST_BYPASS( 20, 0, sltu, 1, 11, 13 ); 53 | TEST_RR_DEST_BYPASS( 21, 1, sltu, 0, 14, 13 ); 54 | TEST_RR_DEST_BYPASS( 22, 2, sltu, 1, 12, 13 ); 55 | 56 | TEST_RR_SRC12_BYPASS( 23, 0, 0, sltu, 0, 14, 13 ); 57 | TEST_RR_SRC12_BYPASS( 24, 0, 1, sltu, 1, 11, 13 ); 58 | TEST_RR_SRC12_BYPASS( 25, 0, 2, sltu, 0, 15, 13 ); 59 | TEST_RR_SRC12_BYPASS( 26, 1, 0, sltu, 1, 10, 13 ); 60 | TEST_RR_SRC12_BYPASS( 27, 1, 1, sltu, 0, 16, 13 ); 61 | TEST_RR_SRC12_BYPASS( 28, 2, 0, sltu, 1, 9, 13 ); 62 | 63 | TEST_RR_SRC21_BYPASS( 29, 0, 0, sltu, 0, 17, 13 ); 64 | TEST_RR_SRC21_BYPASS( 30, 0, 1, sltu, 1, 8, 13 ); 65 | TEST_RR_SRC21_BYPASS( 31, 0, 2, sltu, 0, 18, 13 ); 66 | TEST_RR_SRC21_BYPASS( 32, 1, 0, sltu, 1, 7, 13 ); 67 | TEST_RR_SRC21_BYPASS( 33, 1, 1, sltu, 0, 19, 13 ); 68 | TEST_RR_SRC21_BYPASS( 34, 2, 0, sltu, 1, 6, 13 ); 69 | 70 | TEST_RR_ZEROSRC1( 35, sltu, 1, -1 ); 71 | TEST_RR_ZEROSRC2( 36, sltu, 0, -1 ); 72 | TEST_RR_ZEROSRC12( 37, sltu, 0 ); 73 | TEST_RR_ZERODEST( 38, sltu, 16, 30 ); 74 | 75 | TEST_PASSFAIL 76 | 77 | RVTEST_CODE_END 78 | 79 | .data 80 | RVTEST_DATA_BEGIN 81 | 82 | TEST_DATA 83 | 84 | RVTEST_DATA_END 85 | -------------------------------------------------------------------------------- /src/ry_wb_arbiter.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | 7 | use work.ry_types.all; 8 | 9 | --! @brief Simple priority-based wishbone arbiter. 10 | --! This module is used as an arbiter between the instruction and data caches. 11 | entity ry_wb_arbiter is 12 | port( 13 | clk : in std_logic; 14 | reset : in std_logic; 15 | 16 | -- Wishbone input 1: 17 | m1_inputs : out wishbone_master_inputs; 18 | m1_outputs : in wishbone_master_outputs; 19 | 20 | -- Wishbone input 2: 21 | m2_inputs : out wishbone_master_inputs; 22 | m2_outputs : in wishbone_master_outputs; 23 | 24 | -- Wishbone interface: 25 | wb_adr_out : out std_logic_vector(31 downto 0); 26 | wb_sel_out : out std_logic_vector( 3 downto 0); 27 | wb_cyc_out : out std_logic; 28 | wb_stb_out : out std_logic; 29 | wb_we_out : out std_logic; 30 | wb_dat_out : out std_logic_vector(31 downto 0); 31 | wb_dat_in : in std_logic_vector(31 downto 0); 32 | wb_ack_in : in std_logic 33 | ); 34 | end entity ry_wb_arbiter; 35 | 36 | architecture behaviour of ry_wb_arbiter is 37 | 38 | type state_type is (IDLE, M1_BUSY, M2_BUSY); 39 | signal state : state_type := IDLE; 40 | 41 | begin 42 | 43 | m1_inputs <= (ack => wb_ack_in, dat => wb_dat_in) when state = M1_BUSY else (ack => '0', dat => (others => '0')); 44 | m2_inputs <= (ack => wb_ack_in, dat => wb_dat_in) when state = M2_BUSY else (ack => '0', dat => (others => '0')); 45 | 46 | output_mux: process(state, m1_outputs, m2_outputs) 47 | begin 48 | case state is 49 | when IDLE => 50 | wb_adr_out <= (others => '0'); 51 | wb_sel_out <= (others => '0'); 52 | wb_dat_out <= (others => '0'); 53 | wb_cyc_out <= '0'; 54 | wb_stb_out <= '0'; 55 | wb_we_out <= '0'; 56 | when M1_BUSY => 57 | wb_adr_out <= m1_outputs.adr; 58 | wb_sel_out <= m1_outputs.sel; 59 | wb_dat_out <= m1_outputs.dat; 60 | wb_cyc_out <= m1_outputs.cyc; 61 | wb_stb_out <= m1_outputs.stb; 62 | wb_we_out <= m1_outputs.we; 63 | when M2_BUSY => 64 | wb_adr_out <= m2_outputs.adr; 65 | wb_sel_out <= m2_outputs.sel; 66 | wb_dat_out <= m2_outputs.dat; 67 | wb_cyc_out <= m2_outputs.cyc; 68 | wb_stb_out <= m2_outputs.stb; 69 | wb_we_out <= m2_outputs.we; 70 | end case; 71 | end process output_mux; 72 | 73 | controller: process(clk) 74 | begin 75 | if rising_edge(clk) then 76 | if reset = '1' then 77 | state <= IDLE; 78 | else 79 | case state is 80 | when IDLE => 81 | if m1_outputs.cyc = '1' then 82 | state <= M1_BUSY; 83 | elsif m2_outputs.cyc = '1' then 84 | state <= M2_BUSY; 85 | end if; 86 | when M1_BUSY => 87 | if m1_outputs.cyc = '0' then 88 | state <= IDLE; 89 | end if; 90 | when M2_BUSY => 91 | if m2_outputs.cyc = '0' then 92 | state <= IDLE; 93 | end if; 94 | end case; 95 | end if; 96 | end if; 97 | end process controller; 98 | 99 | end architecture behaviour; 100 | -------------------------------------------------------------------------------- /src/dsaf/ry_wb_arbiter.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | 7 | use work.ry_types.all; 8 | 9 | --! @brief Simple priority-based wishbone arbiter. 10 | --! This module is used as an arbiter between the instruction and data caches. 11 | entity ry_wb_arbiter is 12 | port( 13 | clk : in std_logic; 14 | reset : in std_logic; 15 | 16 | -- Wishbone input 1: 17 | m1_inputs : out wishbone_master_inputs; 18 | m1_outputs : in wishbone_master_outputs; 19 | 20 | -- Wishbone input 2: 21 | m2_inputs : out wishbone_master_inputs; 22 | m2_outputs : in wishbone_master_outputs; 23 | 24 | -- Wishbone interface: 25 | wb_adr_out : out std_logic_vector(31 downto 0); 26 | wb_sel_out : out std_logic_vector( 3 downto 0); 27 | wb_cyc_out : out std_logic; 28 | wb_stb_out : out std_logic; 29 | wb_we_out : out std_logic; 30 | wb_dat_out : out std_logic_vector(31 downto 0); 31 | wb_dat_in : in std_logic_vector(31 downto 0); 32 | wb_ack_in : in std_logic 33 | ); 34 | end entity ry_wb_arbiter; 35 | 36 | architecture behaviour of ry_wb_arbiter is 37 | 38 | type state_type is (IDLE, M1_BUSY, M2_BUSY); 39 | signal state : state_type := IDLE; 40 | 41 | begin 42 | 43 | m1_inputs <= (ack => wb_ack_in, dat => wb_dat_in) when state = M1_BUSY else (ack => '0', dat => (others => '0')); 44 | m2_inputs <= (ack => wb_ack_in, dat => wb_dat_in) when state = M2_BUSY else (ack => '0', dat => (others => '0')); 45 | 46 | output_mux: process(state, m1_outputs, m2_outputs) 47 | begin 48 | case state is 49 | when IDLE => 50 | wb_adr_out <= (others => '0'); 51 | wb_sel_out <= (others => '0'); 52 | wb_dat_out <= (others => '0'); 53 | wb_cyc_out <= '0'; 54 | wb_stb_out <= '0'; 55 | wb_we_out <= '0'; 56 | when M1_BUSY => 57 | wb_adr_out <= m1_outputs.adr; 58 | wb_sel_out <= m1_outputs.sel; 59 | wb_dat_out <= m1_outputs.dat; 60 | wb_cyc_out <= m1_outputs.cyc; 61 | wb_stb_out <= m1_outputs.stb; 62 | wb_we_out <= m1_outputs.we; 63 | when M2_BUSY => 64 | wb_adr_out <= m2_outputs.adr; 65 | wb_sel_out <= m2_outputs.sel; 66 | wb_dat_out <= m2_outputs.dat; 67 | wb_cyc_out <= m2_outputs.cyc; 68 | wb_stb_out <= m2_outputs.stb; 69 | wb_we_out <= m2_outputs.we; 70 | end case; 71 | end process output_mux; 72 | 73 | controller: process(clk) 74 | begin 75 | if rising_edge(clk) then 76 | if reset = '1' then 77 | state <= IDLE; 78 | else 79 | case state is 80 | when IDLE => 81 | if m1_outputs.cyc = '1' then 82 | state <= M1_BUSY; 83 | elsif m2_outputs.cyc = '1' then 84 | state <= M2_BUSY; 85 | end if; 86 | when M1_BUSY => 87 | if m1_outputs.cyc = '0' then 88 | state <= IDLE; 89 | end if; 90 | when M2_BUSY => 91 | if m2_outputs.cyc = '0' then 92 | state <= IDLE; 93 | end if; 94 | end case; 95 | end if; 96 | end if; 97 | end process controller; 98 | 99 | end architecture behaviour; 100 | -------------------------------------------------------------------------------- /riscv-tests/slt.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # slt.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test slt instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Arithmetic tests 18 | #------------------------------------------------------------- 19 | 20 | TEST_RR_OP( 2, slt, 0, 0x0000000000000000, 0x0000000000000000 ); 21 | TEST_RR_OP( 3, slt, 0, 0x0000000000000001, 0x0000000000000001 ); 22 | TEST_RR_OP( 4, slt, 1, 0x0000000000000003, 0x0000000000000007 ); 23 | TEST_RR_OP( 5, slt, 0, 0x0000000000000007, 0x0000000000000003 ); 24 | 25 | TEST_RR_OP( 6, slt, 0, 0x0000000000000000, 0xffffffffffff8000 ); 26 | TEST_RR_OP( 7, slt, 1, 0xffffffff80000000, 0x0000000000000000 ); 27 | TEST_RR_OP( 8, slt, 1, 0xffffffff80000000, 0xffffffffffff8000 ); 28 | 29 | TEST_RR_OP( 9, slt, 1, 0x0000000000000000, 0x0000000000007fff ); 30 | TEST_RR_OP( 10, slt, 0, 0x000000007fffffff, 0x0000000000000000 ); 31 | TEST_RR_OP( 11, slt, 0, 0x000000007fffffff, 0x0000000000007fff ); 32 | 33 | TEST_RR_OP( 12, slt, 1, 0xffffffff80000000, 0x0000000000007fff ); 34 | TEST_RR_OP( 13, slt, 0, 0x000000007fffffff, 0xffffffffffff8000 ); 35 | 36 | TEST_RR_OP( 14, slt, 0, 0x0000000000000000, 0xffffffffffffffff ); 37 | TEST_RR_OP( 15, slt, 1, 0xffffffffffffffff, 0x0000000000000001 ); 38 | TEST_RR_OP( 16, slt, 0, 0xffffffffffffffff, 0xffffffffffffffff ); 39 | 40 | #------------------------------------------------------------- 41 | # Source/Destination tests 42 | #------------------------------------------------------------- 43 | 44 | TEST_RR_SRC1_EQ_DEST( 17, slt, 0, 14, 13 ); 45 | TEST_RR_SRC2_EQ_DEST( 18, slt, 1, 11, 13 ); 46 | TEST_RR_SRC12_EQ_DEST( 19, slt, 0, 13 ); 47 | 48 | #------------------------------------------------------------- 49 | # Bypassing tests 50 | #------------------------------------------------------------- 51 | 52 | TEST_RR_DEST_BYPASS( 20, 0, slt, 1, 11, 13 ); 53 | TEST_RR_DEST_BYPASS( 21, 1, slt, 0, 14, 13 ); 54 | TEST_RR_DEST_BYPASS( 22, 2, slt, 1, 12, 13 ); 55 | 56 | TEST_RR_SRC12_BYPASS( 23, 0, 0, slt, 0, 14, 13 ); 57 | TEST_RR_SRC12_BYPASS( 24, 0, 1, slt, 1, 11, 13 ); 58 | TEST_RR_SRC12_BYPASS( 25, 0, 2, slt, 0, 15, 13 ); 59 | TEST_RR_SRC12_BYPASS( 26, 1, 0, slt, 1, 10, 13 ); 60 | TEST_RR_SRC12_BYPASS( 27, 1, 1, slt, 0, 16, 13 ); 61 | TEST_RR_SRC12_BYPASS( 28, 2, 0, slt, 1, 9, 13 ); 62 | 63 | TEST_RR_SRC21_BYPASS( 29, 0, 0, slt, 0, 17, 13 ); 64 | TEST_RR_SRC21_BYPASS( 30, 0, 1, slt, 1, 8, 13 ); 65 | TEST_RR_SRC21_BYPASS( 31, 0, 2, slt, 0, 18, 13 ); 66 | TEST_RR_SRC21_BYPASS( 32, 1, 0, slt, 1, 7, 13 ); 67 | TEST_RR_SRC21_BYPASS( 33, 1, 1, slt, 0, 19, 13 ); 68 | TEST_RR_SRC21_BYPASS( 34, 2, 0, slt, 1, 6, 13 ); 69 | 70 | TEST_RR_ZEROSRC1( 35, slt, 0, -1 ); 71 | TEST_RR_ZEROSRC2( 36, slt, 1, -1 ); 72 | TEST_RR_ZEROSRC12( 37, slt, 0 ); 73 | TEST_RR_ZERODEST( 38, slt, 16, 30 ); 74 | 75 | TEST_PASSFAIL 76 | 77 | RVTEST_CODE_END 78 | 79 | .data 80 | RVTEST_DATA_BEGIN 81 | 82 | TEST_DATA 83 | 84 | RVTEST_DATA_END 85 | -------------------------------------------------------------------------------- /libsoc/timer.h: -------------------------------------------------------------------------------- 1 | // The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | // (c) Krishna Subramanian 3 | 4 | #ifndef LIBSOC_TIMER_H 5 | #define LIBSOC_TIMER_H 6 | 7 | #include 8 | 9 | // Timer register offsets: 10 | #define TIMER_REG_CONTROL 0x00 11 | #define TIMER_REG_COMPARE 0x04 12 | #define TIMER_REG_COUNTER 0x08 13 | 14 | // Timer control register bits: 15 | #define TIMER_CONTROL_RUN 0 16 | #define TIMER_CONTROL_CLEAR 1 17 | 18 | struct timer 19 | { 20 | volatile uint32_t * registers; 21 | }; 22 | 23 | /** 24 | * Initializes a timer instance. 25 | * @param module Pointer to a timer instance structure. 26 | * @param base_address Base address of the timer hardware module. 27 | */ 28 | static inline void timer_initialize(struct timer * module, volatile void * base_address) 29 | { 30 | module->registers = base_address; 31 | } 32 | 33 | /** 34 | * Resets a timer. 35 | * This stops the timer and resets its counter value to 0. 36 | * @param module Pointer to a timer instance structure. 37 | */ 38 | static inline void timer_reset(struct timer * module) 39 | { 40 | module->registers[TIMER_REG_CONTROL >> 2] = 1 << TIMER_CONTROL_CLEAR; 41 | } 42 | 43 | /** 44 | * Starts a timer. 45 | * @param module Pointer to a timer instance structure. 46 | */ 47 | static inline void timer_start(struct timer * module) 48 | { 49 | module->registers[TIMER_REG_CONTROL >> 2] = 1 << TIMER_CONTROL_RUN | 1 << TIMER_CONTROL_CLEAR; 50 | } 51 | 52 | /** 53 | * Stops a timer. 54 | * @param module Pointer to a timer instance structure. 55 | */ 56 | static inline void timer_stop(struct timer * module) 57 | { 58 | module->registers[TIMER_REG_CONTROL >> 2] = 0; 59 | } 60 | 61 | /** 62 | * Clears a timer. 63 | * @param module Pointer to a timer instance structure. 64 | */ 65 | static inline void timer_clear(struct timer * module) 66 | { 67 | module->registers[TIMER_REG_CONTROL >> 2] |= 1 << TIMER_CONTROL_CLEAR; 68 | } 69 | 70 | /** 71 | * Sets the compare register of a timer. 72 | * @param module Pointer to a timer instance structure. 73 | * @param compare Value to write to the timer compare register. 74 | * @warning Using this function while the timer is running could cause undefined bahviour. 75 | */ 76 | static inline void timer_set_compare(struct timer * module, uint32_t compare) 77 | { 78 | module->registers[TIMER_REG_COMPARE >> 2] = compare; 79 | } 80 | 81 | /** 82 | * Reads the current value of a timer's counter. 83 | * @param module Pointer to a timer instance structure. 84 | * @returns The value of the timer's counter register. 85 | */ 86 | static inline uint32_t timer_get_count(struct timer * module) 87 | { 88 | return module->registers[TIMER_REG_COUNTER >> 2]; 89 | } 90 | 91 | /** 92 | * Sets the value of a timer's counter register. 93 | * @param module Pointer to a timer instance structure. 94 | * @param counter New value of the timer's counter register. 95 | * @warning This function should only be used when the timer is stopped to avoid undefined behaviour. 96 | */ 97 | static inline void timer_set_count(struct timer * module, uint32_t counter) 98 | { 99 | module->registers[TIMER_REG_COUNTER >> 2] = counter; 100 | } 101 | 102 | #endif 103 | 104 | -------------------------------------------------------------------------------- /testbenches/tb_soc_uart.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | 7 | entity tb_soc_uart is 8 | end entity tb_soc_uart; 9 | 10 | architecture testbench of tb_soc_uart is 11 | 12 | -- Clock signal: 13 | signal clk : std_logic := '0'; 14 | constant clk_period : time := 10 ns; 15 | 16 | -- Reset signal: 17 | signal reset : std_logic := '1'; 18 | 19 | -- UART ports: 20 | signal txd : std_logic; 21 | signal rxd : std_logic := '1'; 22 | 23 | -- interrupt signals: 24 | signal irq : std_logic; 25 | 26 | -- Wishbone ports: 27 | signal wb_adr_in : std_logic_vector(11 downto 0) := (others => '0'); 28 | signal wb_dat_in : std_logic_vector( 7 downto 0) := (others => '0'); 29 | signal wb_dat_out : std_logic_vector( 7 downto 0); 30 | signal wb_we_in : std_logic := '0'; 31 | signal wb_cyc_in : std_logic := '0'; 32 | signal wb_stb_in : std_logic := '0'; 33 | signal wb_ack_out : std_logic; 34 | 35 | begin 36 | 37 | uut: entity work.ry_soc_uart 38 | port map( 39 | clk => clk, 40 | reset => reset, 41 | txd => txd, 42 | rxd => rxd, 43 | irq => irq, 44 | wb_adr_in => wb_adr_in, 45 | wb_dat_in => wb_dat_in, 46 | wb_dat_out => wb_dat_out, 47 | wb_we_in => wb_we_in, 48 | wb_cyc_in => wb_cyc_in, 49 | wb_stb_in => wb_stb_in, 50 | wb_ack_out => wb_ack_out 51 | ); 52 | 53 | clock: process 54 | begin 55 | clk <= '1'; 56 | wait for clk_period / 2; 57 | clk <= '0'; 58 | wait for clk_period / 2; 59 | end process clock; 60 | 61 | stimulus: process 62 | 63 | procedure uart_write(address : in std_logic_vector(11 downto 0); data : in std_logic_vector(7 downto 0)) is 64 | begin 65 | wb_adr_in <= address; 66 | wb_dat_in <= data; 67 | wb_we_in <= '1'; 68 | wb_cyc_in <= '1'; 69 | wb_stb_in <= '1'; 70 | 71 | wait until wb_ack_out = '1'; 72 | wait for clk_period; 73 | wb_stb_in <= '0'; 74 | wb_cyc_in <= '0'; 75 | wait for clk_period; 76 | end procedure uart_write; 77 | 78 | begin 79 | wait for clk_period * 2; 80 | reset <= '0'; 81 | 82 | -- Set the sample clock to obtain a 1 Mbps transfer rate: 83 | uart_write(x"00c", x"06"); 84 | 85 | -- Enable the data received interrupt: 86 | uart_write(x"010", x"01"); 87 | 88 | -- Send a byte on the UART: 89 | rxd <= '0'; -- Start bit 90 | wait for 1 us; 91 | rxd <= '0'; 92 | wait for 1 us; 93 | rxd <= '1'; 94 | wait for 1 us; 95 | rxd <= '0'; 96 | wait for 1 us; 97 | rxd <= '1'; 98 | wait for 1 us; 99 | rxd <= '0'; 100 | wait for 1 us; 101 | rxd <= '0'; 102 | wait for 1 us; 103 | rxd <= '0'; 104 | wait for 1 us; 105 | rxd <= '0'; 106 | wait for 1 us; 107 | rxd <= '1'; -- Stop bit 108 | wait for 1 us; 109 | 110 | wait until irq = '1'; 111 | 112 | -- Disable the IRQ: 113 | uart_write(x"010", x"00"); 114 | wait until irq = '0'; 115 | 116 | -- Output a "RISCY" on the UART: 117 | uart_write(x"000", x"50"); 118 | uart_write(x"000", x"6f"); 119 | uart_write(x"000", x"74"); 120 | uart_write(x"000", x"61"); 121 | uart_write(x"000", x"74"); 122 | uart_write(x"000", x"6f"); 123 | 124 | wait; 125 | end process stimulus; 126 | 127 | end architecture testbench; 128 | -------------------------------------------------------------------------------- /software/start.S: -------------------------------------------------------------------------------- 1 | # The RISCY Processor - A simple processor for FPGA Prototyping 2 | # The RISCY Processor - A simple RISC-V based processor for FPGAs 3 | # (c) Krishna Subramanian 4 | 5 | .section .init 6 | 7 | .global _start 8 | _start: 9 | 10 | // Sets the exception handler address: 11 | .hidden init_mtvec 12 | init_mtvec: 13 | la x1, _machine_exception_handler 14 | csrw mtvec, x1 15 | 16 | // Copies the .data from ROM to RAM - this is only used by the bootloader, which runs from ROM: 17 | #ifdef COPY_DATA_TO_RAM 18 | .hidden copy_data 19 | copy_data: 20 | la x1, __text_end // Copy source address 21 | la x2, __data_begin // Copy destination address 22 | la x3, __data_end // Copy destination end address 23 | 24 | beq x2, x3, 2f // Skip if there is no data to copy 25 | 26 | 1: 27 | lb x4, (x1) 28 | sb x4, (x2) 29 | addi x1, x1, 1 30 | addi x2, x2, 1 31 | 32 | bne x2, x3, 1b // Repeat as long as there is more data to copy 33 | 2: 34 | #endif 35 | 36 | // Clears the .bss (zero initialized data) section: 37 | .hidden clear_bss 38 | clear_bss: 39 | la x1, __bss_begin 40 | la x2, __bss_end 41 | beq x1, x2, 2f // Skip if there is no .bss section 42 | 43 | 1: 44 | sw x0, (x1) 45 | addi x1, x1, 4 46 | bne x1, x2, 1b 47 | 2: 48 | 49 | // Sets up the stack pointer: 50 | .hidden init_stack 51 | init_stack: 52 | la sp, __stack_top 53 | 54 | .hidden call_main 55 | call_main: 56 | call main 57 | 58 | 1: 59 | wfi 60 | j 1b 61 | 62 | .global _machine_exception_handler 63 | _machine_exception_handler: 64 | // Save all registers (to aid in debugging): 65 | addi sp, sp, -124 66 | sw x1, 0(sp) 67 | sw x2, 4(sp) 68 | sw x3, 8(sp) 69 | sw x4, 12(sp) 70 | sw x5, 16(sp) 71 | sw x6, 20(sp) 72 | sw x7, 24(sp) 73 | sw x8, 28(sp) 74 | sw x9, 32(sp) 75 | sw x10, 36(sp) 76 | sw x11, 40(sp) 77 | sw x12, 44(sp) 78 | sw x13, 48(sp) 79 | sw x14, 52(sp) 80 | sw x15, 56(sp) 81 | sw x16, 60(sp) 82 | sw x17, 64(sp) 83 | sw x18, 68(sp) 84 | sw x19, 72(sp) 85 | sw x20, 76(sp) 86 | sw x21, 80(sp) 87 | sw x22, 84(sp) 88 | sw x23, 88(sp) 89 | sw x24, 92(sp) 90 | sw x25, 96(sp) 91 | sw x26, 100(sp) 92 | sw x27, 104(sp) 93 | sw x28, 108(sp) 94 | sw x29, 112(sp) 95 | sw x30, 116(sp) 96 | sw x31, 120(sp) 97 | 98 | csrr a0, mcause # First parameter: cause 99 | csrr a1, mepc # Second parameter: exception location 100 | mv a2, sp # Third parameter: start of stored register array 101 | call exception_handler 102 | 103 | .hidden _machine_exception_return 104 | _machine_exception_return: 105 | // Restore all registers: 106 | lw x1, 0(sp) 107 | # lw x2, 4(sp) <- x2 = sp, so do not load this register 108 | lw x3, 8(sp) 109 | lw x4, 12(sp) 110 | lw x5, 16(sp) 111 | lw x6, 20(sp) 112 | lw x7, 24(sp) 113 | lw x8, 28(sp) 114 | lw x9, 32(sp) 115 | lw x10, 36(sp) 116 | lw x11, 40(sp) 117 | lw x12, 44(sp) 118 | lw x13, 48(sp) 119 | lw x14, 52(sp) 120 | lw x15, 56(sp) 121 | lw x16, 60(sp) 122 | lw x17, 64(sp) 123 | lw x18, 68(sp) 124 | lw x19, 72(sp) 125 | lw x20, 76(sp) 126 | lw x21, 80(sp) 127 | lw x22, 84(sp) 128 | lw x23, 88(sp) 129 | lw x24, 92(sp) 130 | lw x25, 96(sp) 131 | lw x26, 100(sp) 132 | lw x27, 104(sp) 133 | lw x28, 108(sp) 134 | lw x29, 112(sp) 135 | lw x30, 116(sp) 136 | lw x31, 120(sp) 137 | addi sp, sp, 124 138 | 139 | mret 140 | 141 | -------------------------------------------------------------------------------- /riscv-tests/sub.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # sub.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test sub instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Arithmetic tests 18 | #------------------------------------------------------------- 19 | 20 | TEST_RR_OP( 2, sub, 0x0000000000000000, 0x0000000000000000, 0x0000000000000000 ); 21 | TEST_RR_OP( 3, sub, 0x0000000000000000, 0x0000000000000001, 0x0000000000000001 ); 22 | TEST_RR_OP( 4, sub, 0xfffffffffffffffc, 0x0000000000000003, 0x0000000000000007 ); 23 | 24 | TEST_RR_OP( 5, sub, 0x0000000000008000, 0x0000000000000000, 0xffffffffffff8000 ); 25 | TEST_RR_OP( 6, sub, 0xffffffff80000000, 0xffffffff80000000, 0x0000000000000000 ); 26 | TEST_RR_OP( 7, sub, 0xffffffff80008000, 0xffffffff80000000, 0xffffffffffff8000 ); 27 | 28 | TEST_RR_OP( 8, sub, 0xffffffffffff8001, 0x0000000000000000, 0x0000000000007fff ); 29 | TEST_RR_OP( 9, sub, 0x000000007fffffff, 0x000000007fffffff, 0x0000000000000000 ); 30 | TEST_RR_OP( 10, sub, 0x000000007fff8000, 0x000000007fffffff, 0x0000000000007fff ); 31 | 32 | TEST_RR_OP( 11, sub, 0xffffffff7fff8001, 0xffffffff80000000, 0x0000000000007fff ); 33 | TEST_RR_OP( 12, sub, 0x0000000080007fff, 0x000000007fffffff, 0xffffffffffff8000 ); 34 | 35 | TEST_RR_OP( 13, sub, 0x0000000000000001, 0x0000000000000000, 0xffffffffffffffff ); 36 | TEST_RR_OP( 14, sub, 0xfffffffffffffffe, 0xffffffffffffffff, 0x0000000000000001 ); 37 | TEST_RR_OP( 15, sub, 0x0000000000000000, 0xffffffffffffffff, 0xffffffffffffffff ); 38 | 39 | #------------------------------------------------------------- 40 | # Source/Destination tests 41 | #------------------------------------------------------------- 42 | 43 | TEST_RR_SRC1_EQ_DEST( 16, sub, 2, 13, 11 ); 44 | TEST_RR_SRC2_EQ_DEST( 17, sub, 3, 14, 11 ); 45 | TEST_RR_SRC12_EQ_DEST( 18, sub, 0, 13 ); 46 | 47 | #------------------------------------------------------------- 48 | # Bypassing tests 49 | #------------------------------------------------------------- 50 | 51 | TEST_RR_DEST_BYPASS( 19, 0, sub, 2, 13, 11 ); 52 | TEST_RR_DEST_BYPASS( 20, 1, sub, 3, 14, 11 ); 53 | TEST_RR_DEST_BYPASS( 21, 2, sub, 4, 15, 11 ); 54 | 55 | TEST_RR_SRC12_BYPASS( 22, 0, 0, sub, 2, 13, 11 ); 56 | TEST_RR_SRC12_BYPASS( 23, 0, 1, sub, 3, 14, 11 ); 57 | TEST_RR_SRC12_BYPASS( 24, 0, 2, sub, 4, 15, 11 ); 58 | TEST_RR_SRC12_BYPASS( 25, 1, 0, sub, 2, 13, 11 ); 59 | TEST_RR_SRC12_BYPASS( 26, 1, 1, sub, 3, 14, 11 ); 60 | TEST_RR_SRC12_BYPASS( 27, 2, 0, sub, 4, 15, 11 ); 61 | 62 | TEST_RR_SRC21_BYPASS( 28, 0, 0, sub, 2, 13, 11 ); 63 | TEST_RR_SRC21_BYPASS( 29, 0, 1, sub, 3, 14, 11 ); 64 | TEST_RR_SRC21_BYPASS( 30, 0, 2, sub, 4, 15, 11 ); 65 | TEST_RR_SRC21_BYPASS( 31, 1, 0, sub, 2, 13, 11 ); 66 | TEST_RR_SRC21_BYPASS( 32, 1, 1, sub, 3, 14, 11 ); 67 | TEST_RR_SRC21_BYPASS( 33, 2, 0, sub, 4, 15, 11 ); 68 | 69 | TEST_RR_ZEROSRC1( 34, sub, 15, -15 ); 70 | TEST_RR_ZEROSRC2( 35, sub, 32, 32 ); 71 | TEST_RR_ZEROSRC12( 36, sub, 0 ); 72 | TEST_RR_ZERODEST( 37, sub, 16, 30 ); 73 | 74 | TEST_PASSFAIL 75 | 76 | RVTEST_CODE_END 77 | 78 | .data 79 | RVTEST_DATA_BEGIN 80 | 81 | TEST_DATA 82 | 83 | RVTEST_DATA_END 84 | -------------------------------------------------------------------------------- /riscv-tests/add.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # add.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test add instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Arithmetic tests 18 | #------------------------------------------------------------- 19 | 20 | TEST_RR_OP( 2, add, 0x00000000, 0x00000000, 0x00000000 ); 21 | TEST_RR_OP( 3, add, 0x00000002, 0x00000001, 0x00000001 ); 22 | TEST_RR_OP( 4, add, 0x0000000a, 0x00000003, 0x00000007 ); 23 | 24 | TEST_RR_OP( 5, add, 0xffffffffffff8000, 0x0000000000000000, 0xffffffffffff8000 ); 25 | TEST_RR_OP( 6, add, 0xffffffff80000000, 0xffffffff80000000, 0x00000000 ); 26 | TEST_RR_OP( 7, add, 0xffffffff7fff8000, 0xffffffff80000000, 0xffffffffffff8000 ); 27 | 28 | TEST_RR_OP( 8, add, 0x0000000000007fff, 0x0000000000000000, 0x0000000000007fff ); 29 | TEST_RR_OP( 9, add, 0x000000007fffffff, 0x000000007fffffff, 0x0000000000000000 ); 30 | TEST_RR_OP( 10, add, 0x0000000080007ffe, 0x000000007fffffff, 0x0000000000007fff ); 31 | 32 | TEST_RR_OP( 11, add, 0xffffffff80007fff, 0xffffffff80000000, 0x0000000000007fff ); 33 | TEST_RR_OP( 12, add, 0x000000007fff7fff, 0x000000007fffffff, 0xffffffffffff8000 ); 34 | 35 | TEST_RR_OP( 13, add, 0xffffffffffffffff, 0x0000000000000000, 0xffffffffffffffff ); 36 | TEST_RR_OP( 14, add, 0x0000000000000000, 0xffffffffffffffff, 0x0000000000000001 ); 37 | TEST_RR_OP( 15, add, 0xfffffffffffffffe, 0xffffffffffffffff, 0xffffffffffffffff ); 38 | 39 | TEST_RR_OP( 16, add, 0x0000000080000000, 0x0000000000000001, 0x000000007fffffff ); 40 | 41 | #------------------------------------------------------------- 42 | # Source/Destination tests 43 | #------------------------------------------------------------- 44 | 45 | TEST_RR_SRC1_EQ_DEST( 17, add, 24, 13, 11 ); 46 | TEST_RR_SRC2_EQ_DEST( 18, add, 25, 14, 11 ); 47 | TEST_RR_SRC12_EQ_DEST( 19, add, 26, 13 ); 48 | 49 | #------------------------------------------------------------- 50 | # Bypassing tests 51 | #------------------------------------------------------------- 52 | 53 | TEST_RR_DEST_BYPASS( 20, 0, add, 24, 13, 11 ); 54 | TEST_RR_DEST_BYPASS( 21, 1, add, 25, 14, 11 ); 55 | TEST_RR_DEST_BYPASS( 22, 2, add, 26, 15, 11 ); 56 | 57 | TEST_RR_SRC12_BYPASS( 23, 0, 0, add, 24, 13, 11 ); 58 | TEST_RR_SRC12_BYPASS( 24, 0, 1, add, 25, 14, 11 ); 59 | TEST_RR_SRC12_BYPASS( 25, 0, 2, add, 26, 15, 11 ); 60 | TEST_RR_SRC12_BYPASS( 26, 1, 0, add, 24, 13, 11 ); 61 | TEST_RR_SRC12_BYPASS( 27, 1, 1, add, 25, 14, 11 ); 62 | TEST_RR_SRC12_BYPASS( 28, 2, 0, add, 26, 15, 11 ); 63 | 64 | TEST_RR_SRC21_BYPASS( 29, 0, 0, add, 24, 13, 11 ); 65 | TEST_RR_SRC21_BYPASS( 30, 0, 1, add, 25, 14, 11 ); 66 | TEST_RR_SRC21_BYPASS( 31, 0, 2, add, 26, 15, 11 ); 67 | TEST_RR_SRC21_BYPASS( 32, 1, 0, add, 24, 13, 11 ); 68 | TEST_RR_SRC21_BYPASS( 33, 1, 1, add, 25, 14, 11 ); 69 | TEST_RR_SRC21_BYPASS( 34, 2, 0, add, 26, 15, 11 ); 70 | 71 | TEST_RR_ZEROSRC1( 35, add, 15, 15 ); 72 | TEST_RR_ZEROSRC2( 36, add, 32, 32 ); 73 | TEST_RR_ZEROSRC12( 37, add, 0 ); 74 | TEST_RR_ZERODEST( 38, add, 16, 30 ); 75 | 76 | TEST_PASSFAIL 77 | 78 | RVTEST_CODE_END 79 | 80 | .data 81 | RVTEST_DATA_BEGIN 82 | 83 | TEST_DATA 84 | 85 | RVTEST_DATA_END 86 | -------------------------------------------------------------------------------- /soc/ry_soc_timer.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple processor for FPGA Prototyping 2 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 3 | -- (c) Krishna Subramanian 4 | 5 | library ieee; 6 | use ieee.std_logic_1164.all; 7 | use ieee.numeric_std.all; 8 | 9 | --! @brief Simple timer module for generating periodic interrupts. 10 | --! 11 | --! The following registers are defined: 12 | --! |---------|------------------| 13 | --! | Address | Description | 14 | --! |---------|------------------| 15 | --! | 0x00 | Control register | 16 | --! | 0x04 | Compare register | 17 | --! | 0x08 | Counter register | 18 | --! |---------|------------------| 19 | --! 20 | --! The bits for the control register are: 21 | --! - 0: Run - set to '1' to enable the counter. 22 | --! - 1: Clear - set to '1' to clear the counter after a compare interrupt or to reset it. 23 | entity ry_soc_timer is 24 | port( 25 | clk : in std_logic; 26 | reset : in std_logic; 27 | 28 | -- Timer interrupt: 29 | irq : out std_logic; 30 | 31 | -- Wishbone interface: 32 | wb_adr_in : in std_logic_vector(11 downto 0); 33 | wb_dat_in : in std_logic_vector(31 downto 0); 34 | wb_dat_out : out std_logic_vector(31 downto 0); 35 | wb_cyc_in : in std_logic; 36 | wb_stb_in : in std_logic; 37 | wb_we_in : in std_logic; 38 | wb_ack_out : out std_logic 39 | ); 40 | end entity; 41 | 42 | architecture behaviour of ry_soc_timer is 43 | signal ctrl_run : std_logic; 44 | 45 | signal counter : std_logic_vector(31 downto 0); 46 | signal compare : std_logic_vector(31 downto 0); 47 | 48 | -- Wishbone acknowledge signal: 49 | signal ack : std_logic; 50 | begin 51 | 52 | wb_ack_out <= ack and wb_cyc_in and wb_stb_in; 53 | irq <= '1' when counter = compare else '0'; 54 | 55 | timer: process(clk) 56 | begin 57 | if rising_edge(clk) then 58 | if reset = '1' then 59 | wb_dat_out <= (others => '0'); 60 | ack <= '0'; 61 | 62 | ctrl_run <= '0'; 63 | counter <= (others => '0'); 64 | compare <= (others => '1'); 65 | else 66 | if ctrl_run = '1' and counter /= compare then 67 | counter <= std_logic_vector(unsigned(counter) + 1); 68 | end if; 69 | 70 | if wb_cyc_in = '1' and wb_stb_in = '1' and ack = '0' then 71 | if wb_we_in = '1' then 72 | case wb_adr_in is 73 | when x"000" => -- Write control register 74 | ctrl_run <= wb_dat_in(0); 75 | if wb_dat_in(1) = '1' then 76 | counter <= (others => '0'); 77 | end if; 78 | when x"004" => -- Write compare register 79 | compare <= wb_dat_in; 80 | when x"008" => -- Write count register 81 | counter <= wb_dat_in; 82 | when others => 83 | end case; 84 | ack <= '1'; 85 | else 86 | case wb_adr_in is 87 | when x"000" => -- Read control register 88 | wb_dat_out <= (0 => ctrl_run, others => '0'); 89 | when x"004" => -- Read compare register 90 | wb_dat_out <= compare; 91 | when x"008" => -- Read count register 92 | wb_dat_out <= counter; 93 | when others => 94 | wb_dat_out <= (others => '0'); 95 | end case; 96 | ack <= '1'; 97 | end if; 98 | elsif wb_stb_in = '0' then 99 | ack <= '0'; 100 | end if; 101 | end if; 102 | end if; 103 | end process timer; 104 | 105 | end architecture behaviour; 106 | -------------------------------------------------------------------------------- /testbenches/tb_soc_intercon.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | 7 | entity tb_soc_intercon is 8 | end entity tb_soc_intercon; 9 | 10 | architecture testbench of tb_soc_intercon is 11 | 12 | -- Clock signal: 13 | signal clk : std_logic := '0'; 14 | constant clk_period : time := 10 ns; 15 | 16 | -- Reset signal: 17 | signal reset : std_logic := '1'; 18 | 19 | -- IRQ signal: 20 | signal error_irq : std_logic; 21 | 22 | -- Wishbone interface: 23 | signal wb_adr_in : std_logic_vector(11 downto 0) := (others => '0'); 24 | signal wb_dat_in : std_logic_vector(31 downto 0) := (others => '0'); 25 | signal wb_dat_out : std_logic_vector(31 downto 0); 26 | signal wb_cyc_in : std_logic := '0'; 27 | signal wb_stb_in : std_logic := '0'; 28 | signal wb_we_in : std_logic := '0'; 29 | signal wb_ack_out : std_logic; 30 | 31 | -- Bus error interface: 32 | signal err_adr_in : std_logic_vector(31 downto 0) := (others => '0'); 33 | signal err_dat_in : std_logic_vector(31 downto 0) := (others => '0'); 34 | signal err_sel_in : std_logic_vector( 3 downto 0) := (others => '0'); 35 | signal err_cyc_in : std_logic := '0'; 36 | signal err_stb_in : std_logic := '0'; 37 | signal err_we_in : std_logic := '0'; 38 | signal err_ack_out : std_logic; 39 | 40 | begin 41 | 42 | uut: entity work.ry_soc_intercon 43 | port map( 44 | clk => clk, 45 | reset => reset, 46 | error_irq => error_irq, 47 | wb_adr_in => wb_adr_in, 48 | wb_dat_in => wb_dat_in, 49 | wb_dat_out => wb_dat_out, 50 | wb_cyc_in => wb_cyc_in, 51 | wb_stb_in => wb_stb_in, 52 | wb_we_in => wb_we_in, 53 | wb_ack_out => wb_ack_out, 54 | err_adr_in => err_adr_in, 55 | err_dat_in => err_dat_in, 56 | err_sel_in => err_sel_in, 57 | err_cyc_in => err_cyc_in, 58 | err_stb_in => err_stb_in, 59 | err_we_in => err_we_in, 60 | err_ack_out => err_ack_out 61 | ); 62 | 63 | clock: process 64 | begin 65 | clk <= '1'; 66 | wait for clk_period / 2; 67 | clk <= '0'; 68 | wait for clk_period / 2; 69 | end process clock; 70 | 71 | stimulus: process 72 | begin 73 | wait for clk_period * 2; 74 | reset <= '0'; 75 | 76 | wait for clk_period; 77 | 78 | -- Do an invalid bus access to see what happens: 79 | err_cyc_in <= '1'; 80 | err_stb_in <= '1'; 81 | err_adr_in <= x"deadbeef"; 82 | err_dat_in <= x"f000000d"; 83 | err_we_in <= '1'; 84 | wait until err_ack_out = '1'; 85 | wait for clk_period; 86 | 87 | assert error_irq = '1'; 88 | 89 | err_cyc_in <= '0'; 90 | err_stb_in <= '0'; 91 | wait for clk_period; 92 | 93 | -- Check the address: 94 | wb_adr_in <= x"00c"; 95 | wb_we_in <= '0'; 96 | wb_stb_in <= '1'; 97 | wb_cyc_in <= '1'; 98 | wait until wb_ack_out = '1'; 99 | wait for clk_period; 100 | 101 | assert wb_dat_out = x"deadbeef"; 102 | 103 | wb_stb_in <= '0'; 104 | wb_cyc_in <= '0'; 105 | wait for clk_period; 106 | 107 | -- Reset the interrupt: 108 | wb_adr_in <= x"000"; 109 | wb_dat_in <= x"00000001"; 110 | wb_we_in <= '1'; 111 | wb_cyc_in <= '1'; 112 | wb_stb_in <= '1'; 113 | wait until wb_ack_out = '1'; 114 | wait for clk_period; 115 | 116 | assert error_irq = '0'; 117 | 118 | wb_stb_in <= '0'; 119 | wb_cyc_in <= '0'; 120 | 121 | wait; 122 | end process stimulus; 123 | 124 | end architecture testbench; 125 | -------------------------------------------------------------------------------- /riscv-tests/srl.S: -------------------------------------------------------------------------------- 1 | # See LICENSE for license details. 2 | 3 | #***************************************************************************** 4 | # srl.S 5 | #----------------------------------------------------------------------------- 6 | # 7 | # Test srl instruction. 8 | # 9 | 10 | #include "riscv_test.h" 11 | #include "test_macros.h" 12 | 13 | RVTEST_RV32M 14 | RVTEST_CODE_BEGIN 15 | 16 | #------------------------------------------------------------- 17 | # Arithmetic tests 18 | #------------------------------------------------------------- 19 | 20 | #define TEST_SRL(n, v, a) \ 21 | TEST_RR_OP(n, srl, ((v) & ((1 << (__riscv_xlen-1) << 1) - 1)) >> (a), v, a) 22 | 23 | TEST_SRL( 2, 0xffffffff80000000, 0 ); 24 | TEST_SRL( 3, 0xffffffff80000000, 1 ); 25 | TEST_SRL( 4, 0xffffffff80000000, 7 ); 26 | TEST_SRL( 5, 0xffffffff80000000, 14 ); 27 | TEST_SRL( 6, 0xffffffff80000001, 31 ); 28 | 29 | TEST_SRL( 7, 0xffffffffffffffff, 0 ); 30 | TEST_SRL( 8, 0xffffffffffffffff, 1 ); 31 | TEST_SRL( 9, 0xffffffffffffffff, 7 ); 32 | TEST_SRL( 10, 0xffffffffffffffff, 14 ); 33 | TEST_SRL( 11, 0xffffffffffffffff, 31 ); 34 | 35 | TEST_SRL( 12, 0x0000000021212121, 0 ); 36 | TEST_SRL( 13, 0x0000000021212121, 1 ); 37 | TEST_SRL( 14, 0x0000000021212121, 7 ); 38 | TEST_SRL( 15, 0x0000000021212121, 14 ); 39 | TEST_SRL( 16, 0x0000000021212121, 31 ); 40 | 41 | # Verify that shifts only use bottom five bits 42 | 43 | TEST_RR_OP( 17, srl, 0x0000000021212121, 0x0000000021212121, 0xffffffffffffffc0 ); 44 | TEST_RR_OP( 18, srl, 0x0000000010909090, 0x0000000021212121, 0xffffffffffffffc1 ); 45 | TEST_RR_OP( 19, srl, 0x0000000000424242, 0x0000000021212121, 0xffffffffffffffc7 ); 46 | TEST_RR_OP( 20, srl, 0x0000000000008484, 0x0000000021212121, 0xffffffffffffffce ); 47 | TEST_RR_OP( 21, srl, 0x0000000000000000, 0x0000000021212121, 0xffffffffffffffff ); 48 | 49 | #------------------------------------------------------------- 50 | # Source/Destination tests 51 | #------------------------------------------------------------- 52 | 53 | TEST_RR_SRC1_EQ_DEST( 22, srl, 0x01000000, 0x80000000, 7 ); 54 | TEST_RR_SRC2_EQ_DEST( 23, srl, 0x00020000, 0x80000000, 14 ); 55 | TEST_RR_SRC12_EQ_DEST( 24, srl, 0, 7 ); 56 | 57 | #------------------------------------------------------------- 58 | # Bypassing tests 59 | #------------------------------------------------------------- 60 | 61 | TEST_RR_DEST_BYPASS( 25, 0, srl, 0x01000000, 0x80000000, 7 ); 62 | TEST_RR_DEST_BYPASS( 26, 1, srl, 0x00020000, 0x80000000, 14 ); 63 | TEST_RR_DEST_BYPASS( 27, 2, srl, 0x00000001, 0x80000000, 31 ); 64 | 65 | TEST_RR_SRC12_BYPASS( 28, 0, 0, srl, 0x01000000, 0x80000000, 7 ); 66 | TEST_RR_SRC12_BYPASS( 29, 0, 1, srl, 0x00020000, 0x80000000, 14 ); 67 | TEST_RR_SRC12_BYPASS( 30, 0, 2, srl, 0x00000001, 0x80000000, 31 ); 68 | TEST_RR_SRC12_BYPASS( 31, 1, 0, srl, 0x01000000, 0x80000000, 7 ); 69 | TEST_RR_SRC12_BYPASS( 32, 1, 1, srl, 0x00020000, 0x80000000, 14 ); 70 | TEST_RR_SRC12_BYPASS( 33, 2, 0, srl, 0x00000001, 0x80000000, 31 ); 71 | 72 | TEST_RR_SRC21_BYPASS( 34, 0, 0, srl, 0x01000000, 0x80000000, 7 ); 73 | TEST_RR_SRC21_BYPASS( 35, 0, 1, srl, 0x00020000, 0x80000000, 14 ); 74 | TEST_RR_SRC21_BYPASS( 36, 0, 2, srl, 0x00000001, 0x80000000, 31 ); 75 | TEST_RR_SRC21_BYPASS( 37, 1, 0, srl, 0x01000000, 0x80000000, 7 ); 76 | TEST_RR_SRC21_BYPASS( 38, 1, 1, srl, 0x00020000, 0x80000000, 14 ); 77 | TEST_RR_SRC21_BYPASS( 39, 2, 0, srl, 0x00000001, 0x80000000, 31 ); 78 | 79 | TEST_RR_ZEROSRC1( 40, srl, 0, 15 ); 80 | TEST_RR_ZEROSRC2( 41, srl, 32, 32 ); 81 | TEST_RR_ZEROSRC12( 42, srl, 0 ); 82 | TEST_RR_ZERODEST( 43, srl, 1024, 2048 ); 83 | 84 | TEST_PASSFAIL 85 | 86 | RVTEST_CODE_END 87 | 88 | .data 89 | RVTEST_DATA_BEGIN 90 | 91 | TEST_DATA 92 | 93 | RVTEST_DATA_END 94 | -------------------------------------------------------------------------------- /soc/ry_soc_gpio.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple processor for FPGA Prototyping 2 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 3 | -- (c) Krishna Subramanian 4 | 5 | library ieee; 6 | use ieee.std_logic_1164.all; 7 | use ieee.numeric_std.all; 8 | 9 | --! @brief Generic Wishbone GPIO Module. 10 | --! 11 | --! The following registers are defined: 12 | --! |---------|---------------------------------------------------------------| 13 | --! | Address | Description | 14 | --! |---------|---------------------------------------------------------------| 15 | --! | 0x00 | Input values, one bit per pin (read-only) | 16 | --! | 0x04 | Output values, one bit per pin (read/write) | 17 | --! | 0x08 | Direction register, one bit per pin. 0 is input, 1 is output. | 18 | --! |---------|---------------------------------------------------------------| 19 | --! 20 | --! Writes to the output register for input pins are ignored. 21 | entity ry_soc_gpio is 22 | generic( 23 | NUM_GPIOS : natural := 32 24 | ); 25 | port( 26 | clk : in std_logic; 27 | reset : in std_logic; 28 | 29 | -- GPIO interface: 30 | gpio : inout std_logic_vector(NUM_GPIOS - 1 downto 0); 31 | 32 | -- Wishbone interface: 33 | wb_adr_in : in std_logic_vector(11 downto 0); 34 | wb_dat_in : in std_logic_vector(31 downto 0); 35 | wb_dat_out : out std_logic_vector(31 downto 0); 36 | wb_cyc_in : in std_logic; 37 | wb_stb_in : in std_logic; 38 | wb_we_in : in std_logic; 39 | wb_ack_out : out std_logic 40 | ); 41 | end entity ry_soc_gpio; 42 | 43 | architecture behaviour of ry_soc_gpio is 44 | 45 | signal direction_register : std_logic_vector(NUM_GPIOS - 1 downto 0); 46 | signal output_register : std_logic_vector(NUM_GPIOS - 1 downto 0); 47 | signal input_register : std_logic_vector(NUM_GPIOS - 1 downto 0); 48 | 49 | signal ack : std_logic := '0'; 50 | 51 | begin 52 | 53 | assert NUM_GPIOS > 0 and NUM_GPIOS <= 32 54 | report "Only a number between 1 and 32 (inclusive) GPIOs are supported!" 55 | severity FAILURE; 56 | 57 | io_setup: for i in 0 to NUM_GPIOS - 1 generate 58 | gpio(i) <= 'Z' when direction_register(i) = '0' else output_register(i); 59 | input_register(i) <= gpio(i) when direction_register(i) = '0' else '0'; 60 | end generate; 61 | 62 | wb_ack_out <= ack and wb_cyc_in and wb_stb_in; 63 | 64 | wishbone: process(clk) 65 | begin 66 | if rising_edge(clk) then 67 | if reset = '1' then 68 | direction_register <= (others => '0'); 69 | output_register <= (others => '0'); 70 | wb_dat_out <= (others => '0'); 71 | ack <= '0'; 72 | else 73 | if wb_cyc_in = '1' and wb_stb_in = '1' and ack = '0' then 74 | if wb_we_in = '1' then 75 | case wb_adr_in is 76 | when x"004" => 77 | output_register <= wb_dat_in(NUM_GPIOS - 1 downto 0); 78 | when x"008" => 79 | direction_register <= wb_dat_in(NUM_GPIOS - 1 downto 0); 80 | when others => 81 | end case; 82 | ack <= '1'; 83 | else 84 | case wb_adr_in is 85 | when x"000" => 86 | wb_dat_out <= std_logic_vector(resize(unsigned(input_register), wb_dat_out'length)); 87 | when x"004" => 88 | wb_dat_out <= std_logic_vector(resize(unsigned(output_register), wb_dat_out'length)); 89 | when x"008" => 90 | wb_dat_out <= std_logic_vector(resize(unsigned(direction_register), wb_dat_out'length)); 91 | when others => 92 | end case; 93 | ack <= '1'; 94 | end if; 95 | elsif wb_stb_in = '0' then 96 | ack <= '0'; 97 | end if; 98 | end if; 99 | end if; 100 | end process wishbone; 101 | 102 | end architecture behaviour; 103 | -------------------------------------------------------------------------------- /src/ry_wb_adapter.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | use ieee.numeric_std.all; 7 | 8 | use work.ry_types.all; 9 | use work.ry_utilities.all; 10 | 11 | --! @brief Wishbone adapter, for connecting the processor to a Wishbone bus when not using caches. 12 | entity ry_wb_adapter is 13 | port( 14 | clk : in std_logic; 15 | reset : in std_logic; 16 | 17 | -- Processor data memory signals: 18 | signal mem_address : in std_logic_vector(31 downto 0); 19 | signal mem_data_in : in std_logic_vector(31 downto 0); -- Data in from the bus 20 | signal mem_data_out : out std_logic_vector(31 downto 0); -- Data out to the bus 21 | signal mem_data_size : in std_logic_vector( 1 downto 0); 22 | signal mem_read_req : in std_logic; 23 | signal mem_read_ack : out std_logic; 24 | signal mem_write_req : in std_logic; 25 | signal mem_write_ack : out std_logic; 26 | 27 | -- Wishbone interface: 28 | wb_inputs : in wishbone_master_inputs; 29 | wb_outputs : out wishbone_master_outputs 30 | ); 31 | end entity ry_wb_adapter; 32 | 33 | architecture behaviour of ry_wb_adapter is 34 | 35 | type states is (IDLE, READ_WAIT_ACK, WRITE_WAIT_ACK); 36 | signal state : states; 37 | 38 | signal mem_r_ack : std_logic; 39 | 40 | function get_data_shift(size : in std_logic_vector(1 downto 0); address : in std_logic_vector) 41 | return natural is 42 | begin 43 | case size is 44 | when b"01" => 45 | case address(1 downto 0) is 46 | when b"00" => 47 | return 0; 48 | when b"01" => 49 | return 8; 50 | when b"10" => 51 | return 16; 52 | when b"11" => 53 | return 24; 54 | when others => 55 | return 0; 56 | end case; 57 | when b"10" => 58 | if address(1) = '0' then 59 | return 0; 60 | else 61 | return 16; 62 | end if; 63 | when others => 64 | return 0; 65 | end case; 66 | end function get_data_shift; 67 | 68 | begin 69 | 70 | mem_write_ack <= '1' when state = WRITE_WAIT_ACK and wb_inputs.ack = '1' else '0'; 71 | mem_read_ack <= mem_r_ack; 72 | 73 | wishbone: process(clk) 74 | begin 75 | if rising_edge(clk) then 76 | if reset = '1' then 77 | state <= IDLE; 78 | wb_outputs.cyc <= '0'; 79 | wb_outputs.stb <= '0'; 80 | mem_r_ack <= '0'; 81 | else 82 | case state is 83 | when IDLE => 84 | mem_r_ack <= '0'; 85 | 86 | -- Prioritize requests from the data memory: 87 | if mem_write_req = '1' then 88 | wb_outputs.adr <= mem_address; 89 | wb_outputs.dat <= std_logic_vector(shift_left(unsigned(mem_data_in), 90 | get_data_shift(mem_data_size, mem_address))); 91 | wb_outputs.sel <= wb_get_data_sel(mem_data_size, mem_address); 92 | wb_outputs.cyc <= '1'; 93 | wb_outputs.stb <= '1'; 94 | wb_outputs.we <= '1'; 95 | state <= WRITE_WAIT_ACK; 96 | elsif mem_read_req = '1' then 97 | wb_outputs.adr <= mem_address; 98 | wb_outputs.sel <= wb_get_data_sel(mem_data_size, mem_address); 99 | wb_outputs.cyc <= '1'; 100 | wb_outputs.stb <= '1'; 101 | wb_outputs.we <= '0'; 102 | state <= READ_WAIT_ACK; 103 | end if; 104 | when READ_WAIT_ACK => 105 | if wb_inputs.ack = '1' then 106 | mem_data_out <= std_logic_vector(shift_right(unsigned(wb_inputs.dat), 107 | get_data_shift(mem_data_size, mem_address))); 108 | wb_outputs.cyc <= '0'; 109 | wb_outputs.stb <= '0'; 110 | mem_r_ack <= '1'; 111 | state <= IDLE; 112 | end if; 113 | when WRITE_WAIT_ACK => 114 | if wb_inputs.ack = '1' then 115 | wb_outputs.cyc <= '0'; 116 | wb_outputs.stb <= '0'; 117 | wb_outputs.we <= '0'; 118 | state <= IDLE; 119 | end if; 120 | end case; 121 | end if; 122 | end if; 123 | end process wishbone; 124 | 125 | end architecture behaviour; 126 | -------------------------------------------------------------------------------- /src/dsaf/ry_wb_adapter.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | use ieee.numeric_std.all; 7 | 8 | use work.ry_types.all; 9 | use work.ry_utilities.all; 10 | 11 | --! @brief Wishbone adapter, for connecting the processor to a Wishbone bus when not using caches. 12 | entity ry_wb_adapter is 13 | port( 14 | clk : in std_logic; 15 | reset : in std_logic; 16 | 17 | -- Processor data memory signals: 18 | signal mem_address : in std_logic_vector(31 downto 0); 19 | signal mem_data_in : in std_logic_vector(31 downto 0); -- Data in from the bus 20 | signal mem_data_out : out std_logic_vector(31 downto 0); -- Data out to the bus 21 | signal mem_data_size : in std_logic_vector( 1 downto 0); 22 | signal mem_read_req : in std_logic; 23 | signal mem_read_ack : out std_logic; 24 | signal mem_write_req : in std_logic; 25 | signal mem_write_ack : out std_logic; 26 | 27 | -- Wishbone interface: 28 | wb_inputs : in wishbone_master_inputs; 29 | wb_outputs : out wishbone_master_outputs 30 | ); 31 | end entity ry_wb_adapter; 32 | 33 | architecture behaviour of ry_wb_adapter is 34 | 35 | type states is (IDLE, READ_WAIT_ACK, WRITE_WAIT_ACK); 36 | signal state : states; 37 | 38 | signal mem_r_ack : std_logic; 39 | 40 | function get_data_shift(size : in std_logic_vector(1 downto 0); address : in std_logic_vector) 41 | return natural is 42 | begin 43 | case size is 44 | when b"01" => 45 | case address(1 downto 0) is 46 | when b"00" => 47 | return 0; 48 | when b"01" => 49 | return 8; 50 | when b"10" => 51 | return 16; 52 | when b"11" => 53 | return 24; 54 | when others => 55 | return 0; 56 | end case; 57 | when b"10" => 58 | if address(1) = '0' then 59 | return 0; 60 | else 61 | return 16; 62 | end if; 63 | when others => 64 | return 0; 65 | end case; 66 | end function get_data_shift; 67 | 68 | begin 69 | 70 | mem_write_ack <= '1' when state = WRITE_WAIT_ACK and wb_inputs.ack = '1' else '0'; 71 | mem_read_ack <= mem_r_ack; 72 | 73 | wishbone: process(clk) 74 | begin 75 | if rising_edge(clk) then 76 | if reset = '1' then 77 | state <= IDLE; 78 | wb_outputs.cyc <= '0'; 79 | wb_outputs.stb <= '0'; 80 | mem_r_ack <= '0'; 81 | else 82 | case state is 83 | when IDLE => 84 | mem_r_ack <= '0'; 85 | 86 | -- Prioritize requests from the data memory: 87 | if mem_write_req = '1' then 88 | wb_outputs.adr <= mem_address; 89 | wb_outputs.dat <= std_logic_vector(shift_left(unsigned(mem_data_in), 90 | get_data_shift(mem_data_size, mem_address))); 91 | wb_outputs.sel <= wb_get_data_sel(mem_data_size, mem_address); 92 | wb_outputs.cyc <= '1'; 93 | wb_outputs.stb <= '1'; 94 | wb_outputs.we <= '1'; 95 | state <= WRITE_WAIT_ACK; 96 | elsif mem_read_req = '1' then 97 | wb_outputs.adr <= mem_address; 98 | wb_outputs.sel <= wb_get_data_sel(mem_data_size, mem_address); 99 | wb_outputs.cyc <= '1'; 100 | wb_outputs.stb <= '1'; 101 | wb_outputs.we <= '0'; 102 | state <= READ_WAIT_ACK; 103 | end if; 104 | when READ_WAIT_ACK => 105 | if wb_inputs.ack = '1' then 106 | mem_data_out <= std_logic_vector(shift_right(unsigned(wb_inputs.dat), 107 | get_data_shift(mem_data_size, mem_address))); 108 | wb_outputs.cyc <= '0'; 109 | wb_outputs.stb <= '0'; 110 | mem_r_ack <= '1'; 111 | state <= IDLE; 112 | end if; 113 | when WRITE_WAIT_ACK => 114 | if wb_inputs.ack = '1' then 115 | wb_outputs.cyc <= '0'; 116 | wb_outputs.stb <= '0'; 117 | wb_outputs.we <= '0'; 118 | state <= IDLE; 119 | end if; 120 | end case; 121 | end if; 122 | end if; 123 | end process wishbone; 124 | 125 | end architecture behaviour; 126 | -------------------------------------------------------------------------------- /src/ry_types.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | 7 | package ry_types is 8 | 9 | --! Type used for register addresses. 10 | subtype register_address is std_logic_vector(4 downto 0); 11 | 12 | --! The available ALU operations. 13 | type alu_operation is ( 14 | ALU_AND, ALU_OR, ALU_XOR, 15 | ALU_SLT, ALU_SLTU, 16 | ALU_ADD, ALU_SUB, 17 | ALU_SRL, ALU_SLL, ALU_SRA, 18 | ALU_NOP, ALU_INVALID 19 | ); 20 | 21 | --! Types of branches. 22 | type branch_type is ( 23 | BRANCH_NONE, BRANCH_JUMP, BRANCH_JUMP_INDIRECT, BRANCH_CONDITIONAL, BRANCH_SRET 24 | ); 25 | 26 | --! Source of an ALU operand. 27 | type alu_operand_source is ( 28 | ALU_SRC_REG, ALU_SRC_IMM, ALU_SRC_SHAMT, ALU_SRC_PC, ALU_SRC_PC_NEXT, ALU_SRC_NULL, ALU_SRC_CSR 29 | ); 30 | 31 | --! Type of memory operation: 32 | type memory_operation_type is ( 33 | MEMOP_TYPE_NONE, MEMOP_TYPE_INVALID, MEMOP_TYPE_LOAD, MEMOP_TYPE_LOAD_UNSIGNED, MEMOP_TYPE_STORE 34 | ); 35 | 36 | -- Determines if a memory operation is a load: 37 | function memop_is_load(input : in memory_operation_type) return boolean; 38 | 39 | --! Size of a memory operation: 40 | type memory_operation_size is ( 41 | MEMOP_SIZE_BYTE, MEMOP_SIZE_HALFWORD, MEMOP_SIZE_WORD 42 | ); 43 | 44 | --! Wishbone master output signals: 45 | type wishbone_master_outputs is record 46 | adr : std_logic_vector(31 downto 0); 47 | sel : std_logic_vector( 3 downto 0); 48 | cyc : std_logic; 49 | stb : std_logic; 50 | we : std_logic; 51 | dat : std_logic_vector(31 downto 0); 52 | end record; 53 | 54 | --! Wishbone master input signals: 55 | type wishbone_master_inputs is record 56 | dat : std_logic_vector(31 downto 0); 57 | ack : std_logic; 58 | end record; 59 | 60 | --! State of the currently running test: 61 | type test_state is (TEST_IDLE, TEST_RUNNING, TEST_FAILED, TEST_PASSED); 62 | 63 | --! Current test context: 64 | type test_context is record 65 | state : test_state; 66 | number : std_logic_vector(29 downto 0); 67 | end record; 68 | 69 | --! Converts a test context to an std_logic_vector: 70 | function test_context_to_std_logic(input : in test_context) return std_logic_vector; 71 | 72 | --! Converts an std_logic_vector to a test context: 73 | function std_logic_to_test_context(input : in std_logic_vector(31 downto 0)) return test_context; 74 | 75 | end package ry_types; 76 | 77 | package body ry_types is 78 | 79 | function memop_is_load(input : in memory_operation_type) return boolean is 80 | begin 81 | return (input = MEMOP_TYPE_LOAD or input = MEMOP_TYPE_LOAD_UNSIGNED); 82 | end function memop_is_load; 83 | 84 | function test_context_to_std_logic(input : in test_context) return std_logic_vector is 85 | variable retval : std_logic_vector(31 downto 0); 86 | begin 87 | case input.state is 88 | when TEST_IDLE => 89 | retval(1 downto 0) := b"00"; 90 | when TEST_RUNNING => 91 | retval(1 downto 0) := b"01"; 92 | when TEST_FAILED => 93 | retval(1 downto 0) := b"10"; 94 | when TEST_PASSED => 95 | retval(1 downto 0) := b"11"; 96 | end case; 97 | 98 | retval(31 downto 2) := input.number; 99 | return retval; 100 | end function test_context_to_std_logic; 101 | 102 | function std_logic_to_test_context(input : in std_logic_vector(31 downto 0)) return test_context is 103 | variable retval : test_context; 104 | begin 105 | case input(1 downto 0) is 106 | when b"00" => 107 | retval.state := TEST_IDLE; 108 | when b"01" => 109 | retval.state := TEST_RUNNING; 110 | when b"10" => 111 | retval.state := TEST_FAILED; 112 | when b"11" => 113 | retval.state := TEST_PASSED; 114 | when others => 115 | retval.state := TEST_FAILED; 116 | end case; 117 | 118 | retval.number := input(31 downto 2); 119 | return retval; 120 | end function std_logic_to_test_context; 121 | 122 | end package body ry_types; 123 | -------------------------------------------------------------------------------- /src/dsaf/ry_types.vhd: -------------------------------------------------------------------------------- 1 | -- The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | -- (c) Krishna Subramanian 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | 7 | package ry_types is 8 | 9 | --! Type used for register addresses. 10 | subtype register_address is std_logic_vector(4 downto 0); 11 | 12 | --! The available ALU operations. 13 | type alu_operation is ( 14 | ALU_AND, ALU_OR, ALU_XOR, 15 | ALU_SLT, ALU_SLTU, 16 | ALU_ADD, ALU_SUB, 17 | ALU_SRL, ALU_SLL, ALU_SRA, 18 | ALU_NOP, ALU_INVALID 19 | ); 20 | 21 | --! Types of branches. 22 | type branch_type is ( 23 | BRANCH_NONE, BRANCH_JUMP, BRANCH_JUMP_INDIRECT, BRANCH_CONDITIONAL, BRANCH_SRET 24 | ); 25 | 26 | --! Source of an ALU operand. 27 | type alu_operand_source is ( 28 | ALU_SRC_REG, ALU_SRC_IMM, ALU_SRC_SHAMT, ALU_SRC_PC, ALU_SRC_PC_NEXT, ALU_SRC_NULL, ALU_SRC_CSR 29 | ); 30 | 31 | --! Type of memory operation: 32 | type memory_operation_type is ( 33 | MEMOP_TYPE_NONE, MEMOP_TYPE_INVALID, MEMOP_TYPE_LOAD, MEMOP_TYPE_LOAD_UNSIGNED, MEMOP_TYPE_STORE 34 | ); 35 | 36 | -- Determines if a memory operation is a load: 37 | function memop_is_load(input : in memory_operation_type) return boolean; 38 | 39 | --! Size of a memory operation: 40 | type memory_operation_size is ( 41 | MEMOP_SIZE_BYTE, MEMOP_SIZE_HALFWORD, MEMOP_SIZE_WORD 42 | ); 43 | 44 | --! Wishbone master output signals: 45 | type wishbone_master_outputs is record 46 | adr : std_logic_vector(31 downto 0); 47 | sel : std_logic_vector( 3 downto 0); 48 | cyc : std_logic; 49 | stb : std_logic; 50 | we : std_logic; 51 | dat : std_logic_vector(31 downto 0); 52 | end record; 53 | 54 | --! Wishbone master input signals: 55 | type wishbone_master_inputs is record 56 | dat : std_logic_vector(31 downto 0); 57 | ack : std_logic; 58 | end record; 59 | 60 | --! State of the currently running test: 61 | type test_state is (TEST_IDLE, TEST_RUNNING, TEST_FAILED, TEST_PASSED); 62 | 63 | --! Current test context: 64 | type test_context is record 65 | state : test_state; 66 | number : std_logic_vector(29 downto 0); 67 | end record; 68 | 69 | --! Converts a test context to an std_logic_vector: 70 | function test_context_to_std_logic(input : in test_context) return std_logic_vector; 71 | 72 | --! Converts an std_logic_vector to a test context: 73 | function std_logic_to_test_context(input : in std_logic_vector(31 downto 0)) return test_context; 74 | 75 | end package ry_types; 76 | 77 | package body ry_types is 78 | 79 | function memop_is_load(input : in memory_operation_type) return boolean is 80 | begin 81 | return (input = MEMOP_TYPE_LOAD or input = MEMOP_TYPE_LOAD_UNSIGNED); 82 | end function memop_is_load; 83 | 84 | function test_context_to_std_logic(input : in test_context) return std_logic_vector is 85 | variable retval : std_logic_vector(31 downto 0); 86 | begin 87 | case input.state is 88 | when TEST_IDLE => 89 | retval(1 downto 0) := b"00"; 90 | when TEST_RUNNING => 91 | retval(1 downto 0) := b"01"; 92 | when TEST_FAILED => 93 | retval(1 downto 0) := b"10"; 94 | when TEST_PASSED => 95 | retval(1 downto 0) := b"11"; 96 | end case; 97 | 98 | retval(31 downto 2) := input.number; 99 | return retval; 100 | end function test_context_to_std_logic; 101 | 102 | function std_logic_to_test_context(input : in std_logic_vector(31 downto 0)) return test_context is 103 | variable retval : test_context; 104 | begin 105 | case input(1 downto 0) is 106 | when b"00" => 107 | retval.state := TEST_IDLE; 108 | when b"01" => 109 | retval.state := TEST_RUNNING; 110 | when b"10" => 111 | retval.state := TEST_FAILED; 112 | when b"11" => 113 | retval.state := TEST_PASSED; 114 | when others => 115 | retval.state := TEST_FAILED; 116 | end case; 117 | 118 | retval.number := input(31 downto 2); 119 | return retval; 120 | end function std_logic_to_test_context; 121 | 122 | end package body ry_types; 123 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # The RISCY Processor - A simple RISC-V based processor for FPGAs 2 | # (c) Krishna Subramanian 3 | 4 | 5 | .PHONY: all clean riscy.prj 6 | 7 | SOURCE_FILES := \ 8 | src/ry_alu.vhd \ 9 | src/ry_alu_mux.vhd \ 10 | src/ry_alu_control_unit.vhd \ 11 | src/ry_icache.vhd \ 12 | src/ry_comparator.vhd \ 13 | src/ry_constants.vhd \ 14 | src/ry_control_unit.vhd \ 15 | src/ry_core.vhd \ 16 | src/ry_counter.vhd \ 17 | src/ry_csr.vhd \ 18 | src/ry_csr_unit.vhd \ 19 | src/ry_csr_alu.vhd \ 20 | src/ry_decode.vhd \ 21 | src/ry_execute.vhd \ 22 | src/ry_fetch.vhd \ 23 | src/ry_imm_decoder.vhd \ 24 | src/ry_memory.vhd \ 25 | src/ry_potato.vhd \ 26 | src/ry_register_file.vhd \ 27 | src/ry_types.vhd \ 28 | src/ry_utilities.vhd \ 29 | src/ry_wb_arbiter.vhd \ 30 | src/ry_wb_adapter.vhd \ 31 | src/ry_writeback.vhd 32 | TESTBENCHES := \ 33 | testbenches/tb_processor.vhd \ 34 | testbenches/tb_soc.vhd \ 35 | soc/ry_soc_memory.vhd 36 | 37 | TOOLCHAIN_PREFIX ?= riscv32-unknown-elf 38 | 39 | # ISA tests to use from the riscv-tests repository: 40 | RISCV_TESTS += \ 41 | simple \ 42 | add \ 43 | addi \ 44 | and \ 45 | andi \ 46 | auipc \ 47 | beq \ 48 | bge \ 49 | bgeu \ 50 | blt \ 51 | bltu \ 52 | bne \ 53 | jal \ 54 | jalr \ 55 | lb \ 56 | lbu \ 57 | lh \ 58 | lhu \ 59 | lui \ 60 | lw \ 61 | or \ 62 | ori \ 63 | sb \ 64 | sh \ 65 | sll \ 66 | slt \ 67 | slti \ 68 | sltiu \ 69 | sltu \ 70 | sra \ 71 | srai \ 72 | srl \ 73 | sub \ 74 | sw \ 75 | xor \ 76 | xori 77 | 78 | # Local tests to run: 79 | LOCAL_TESTS += \ 80 | csr_hazard 81 | 82 | # Compiler flags to use when building tests: 83 | TARGET_CFLAGS += -march=rv32i -Wall -O0 84 | TARGET_LDFLAGS += 85 | 86 | all: riscy.prj run-tests run-soc-tests 87 | 88 | riscy.prj: 89 | -$(RM) riscy.prj 90 | for file in $(SOURCE_FILES) $(TESTBENCHES); do \ 91 | echo "vhdl work $$file" >> riscy.prj; \ 92 | done 93 | 94 | copy-riscv-tests: 95 | test -d tests || mkdir tests 96 | for test in $(RISCV_TESTS); do \ 97 | cp riscv-tests/$$test.S tests; \ 98 | done 99 | 100 | compile-tests: copy-riscv-tests 101 | test -d tests-build || mkdir tests-build 102 | for test in $(RISCV_TESTS) $(LOCAL_TESTS); do \ 103 | echo "Compiling test $$test..."; \ 104 | $(TOOLCHAIN_PREFIX)-gcc -c $(TARGET_CFLAGS) -Driscy_TEST_ASSEMBLY -Iriscv-tests -o tests-build/$$test.o tests/$$test.S; \ 105 | $(TOOLCHAIN_PREFIX)-ld $(TARGET_LDFLAGS) -T tests.ld tests-build/$$test.o -o tests-build/$$test.elf; \ 106 | scripts/extract_hex.sh tests-build/$$test.elf tests-build/$$test-imem.hex tests-build/$$test-dmem.hex; \ 107 | done 108 | 109 | run-tests: riscy.prj compile-tests 110 | for test in $(RISCV_TESTS) $(LOCAL_TESTS); do \ 111 | echo -ne "Running test $$test:\t"; \ 112 | DMEM_FILENAME="empty_dmem.hex"; \ 113 | test -f tests-build/$$test-dmem.hex && DMEM_FILENAME="tests-build/$$test-dmem.hex"; \ 114 | xelab tb_processor -generic_top "IMEM_FILENAME=tests-build/$$test-imem.hex" -generic_top "DMEM_FILENAME=$$DMEM_FILENAME" -prj riscy.prj > /dev/null; \ 115 | xsim tb_processor -R --onfinish quit > tests-build/$$test.results; \ 116 | cat tests-build/$$test.results | awk '/Note:/ {print}' | sed 's/Note://' | awk '/Success|Failure/ {print}'; \ 117 | done 118 | 119 | run-soc-tests: riscy.prj compile-tests 120 | for test in $(RISCV_TESTS) $(LOCAL_TESTS); do \ 121 | echo -ne "Running SOC test $$test:\t"; \ 122 | DMEM_FILENAME="empty_dmem.hex"; \ 123 | test -f tests-build/$$test-dmem.hex && DMEM_FILENAME="tests-build/$$test-dmem.hex"; \ 124 | xelab tb_soc -generic_top "IMEM_FILENAME=tests-build/$$test-imem.hex" -generic_top "DMEM_FILENAME=$$DMEM_FILENAME" -prj riscy.prj > /dev/null; \ 125 | xsim tb_soc -R --onfinish quit > tests-build/$$test.results-soc; \ 126 | cat tests-build/$$test.results-soc | awk '/Note:/ {print}' | sed 's/Note://' | awk '/Success|Failure/ {print}'; \ 127 | done 128 | 129 | remove-xilinx-garbage: 130 | -$(RM) -r xsim.dir 131 | -$(RM) xelab.* webtalk* xsim* 132 | 133 | clean: remove-xilinx-garbage 134 | for test in $(RISCV_TESTS); do $(RM) tests/$$test.S; done 135 | -$(RM) -r tests-build 136 | -$(RM) riscy.prj 137 | 138 | distclean: clean 139 | 140 | --------------------------------------------------------------------------------