├── README.md ├── RISCV-GCC-compile-scripts ├── Makefile ├── assembly.dump ├── assembly.s └── compile_notes.txt ├── Software ├── Layers.c ├── assembly - full_connected.s └── assembly.s ├── hdl ├── README.md ├── common │ ├── README.md │ ├── ram_sp_ar.vhd │ ├── ram_sp_ar_bw.vhd │ ├── ram_tdp_rf.vhd │ ├── sdp_bram.sv │ ├── sdp_bwe_bram.sv │ ├── sdp_distram.sv │ ├── tdp_bram.sv │ └── tdp_bwe_bram.sv ├── packages │ ├── cache_pkg.vhd │ ├── typedef_pkg.sv │ └── util_pkg.vhd └── riscv-v │ ├── README.md │ ├── rtl │ ├── riscv_v.sv │ └── riscv_v_w_mem_subsystem.sv │ ├── scalar_axif_m_ctrl │ └── rtl │ │ └── riscv_axif_m_ctrl.vhd │ ├── scalar_axil_s_ctrl │ └── rtl │ │ └── riscv_axil_s_ctrl.vhd │ ├── scalar_cache │ └── rtl │ │ └── cache_contr_nway_vnv_axi.vhd │ ├── scalar_core │ └── rtl │ │ ├── ALU.vhd │ │ ├── TOP_RISCV.vhd │ │ ├── alu_decoder.vhd │ │ ├── control_path.vhd │ │ ├── ctrl_decoder.vhd │ │ ├── data_path.vhd │ │ ├── forwarding_unit.vhd │ │ ├── hazard_unit.vhd │ │ ├── immediate.vhd │ │ ├── register_bank.vhd │ │ └── white_box.sv │ ├── tb │ └── README │ ├── vector_axif_m_ctrl │ └── rtl │ │ ├── axim_ctrl.sv │ │ ├── axim_ctrl_axi_read_master.sv │ │ ├── axim_ctrl_axi_write_master.sv │ │ └── axim_ctrl_counter.sv │ └── vector_core │ ├── README.md │ ├── mem_subs │ ├── buff_array │ │ └── rtl │ │ │ └── buff_array.sv │ ├── m_cu │ │ ├── README.md │ │ ├── rtl │ │ │ ├── axi_m_controller.v │ │ │ ├── m_cu.sv │ │ │ └── m_cu_old.sv │ │ └── tb │ │ │ └── m_cu_tb.sv │ ├── rtl │ │ └── mem_subsys.sv │ └── tb │ │ ├── mem_subsys.wcfg │ │ └── mem_subsys_tb.sv │ ├── rtl │ ├── vector_core.sv │ └── vector_core_old.sv │ ├── scheduler │ ├── README.md │ └── rtl │ │ └── scheduler.sv │ ├── v_cu │ ├── README.md │ ├── README.md~ │ └── rtl │ │ ├── Address_counter.sv │ │ ├── Column_offset_register.sv │ │ ├── Complete_sublane_driver.sv │ │ ├── Complete_sublane_driver_new.sv │ │ ├── Data_validation.sv │ │ ├── Driver_vlane_interconnect.sv │ │ ├── Partial_sublane_driver.sv │ │ ├── Vlane_with_low_lvl_ctrl.sv │ │ ├── port_allocate_unit.sv │ │ ├── renaming_unit.sv │ │ ├── resource_allocate_unit.sv │ │ └── v_cu.sv │ └── v_lane │ ├── README.md │ ├── rtl │ ├── Vector_Lane.sv │ ├── alu.sv │ ├── alu_submodule.sv │ └── vrf.sv │ └── tb │ ├── alu_submodule_tb.sv │ ├── alu_tb.sv │ └── vrf_tb.sv ├── images ├── Vector_core.drawio.png ├── Vector_lane.drawio.png ├── Vector_processor_if.drawio.png ├── Vector_scalar_core.drawio.png └── Vector_zbornik.drawio.png ├── scripts ├── README.md ├── main.tcl ├── riscv-v_bd_synth_impl_binary.tcl ├── riscv-v_package_ip.tcl └── riscv_v_axi_bd_wrapper.xsa ├── synth ├── Makefile ├── README.md ├── impl_opt.tcl ├── run_synth.tcl └── synth_opt.tcl ├── verif ├── AXI4_Agent │ ├── AXI4_agent.sv │ ├── AXI4_agent_pkg.sv │ ├── AXI4_driver.sv │ ├── AXI4_monitor.sv │ ├── AXI4_seq_item.sv │ └── AXI4_sequencer.sv ├── Assembly_code │ ├── #assembly_test.b# │ ├── assembly_code.b │ └── assembly_test.b ├── Configurations │ ├── config.sv │ └── configurations_pkg.sv ├── Sequences │ ├── base_seq.sv │ ├── bd_instr_if_seq.sv │ └── riscv_v_seq_pkg.sv ├── axi_if.sv ├── backdoor_connections.sv ├── backdoor_if.sv ├── bd_instr_if_Agent │ ├── bd_instr_if_agent.sv │ ├── bd_instr_if_agent_pkg.sv │ ├── bd_instr_if_driver.sv │ ├── bd_instr_if_monitor.sv │ ├── bd_instr_if_seq_item.sv │ └── bd_instr_if_sequencer.sv ├── bd_v_data_if_Agent │ ├── bd_v_data_if_agent.sv │ ├── bd_v_data_if_agent_pkg.sv │ ├── bd_v_data_if_driver.sv │ ├── bd_v_data_if_monitor.sv │ ├── bd_v_data_if_seq_item.sv │ └── bd_v_data_if_sequencer.sv ├── bd_v_instr_if_Agent │ ├── bd_v_instr_if_agent.sv │ ├── bd_v_instr_if_agent_pkg.sv │ ├── bd_v_instr_if_monitor.sv │ └── bd_v_instr_if_seq_item.sv ├── defines.sv ├── riscv_sc_scoreboard.sv ├── riscv_v_env.sv ├── riscv_v_if.sv ├── riscv_v_scoreboard.sv ├── test_base.sv ├── test_pkg.sv ├── test_simple.sv ├── test_simple_2.sv └── top.sv ├── vitis_test_app ├── assembly.h ├── helloworld.c ├── lscript.ld └── platform.c └── vivado_pjt ├── create_pjt.tcl └── riscv_v_verif_top_behav.wcfg /README.md: -------------------------------------------------------------------------------- 1 | # RISC-V-vector-processor-for-the-acceleration-of-Machine-learning-algorithms 2 | 3 | ## Project description 4 | 5 | In the last ten years the emergence of highly advanced machine learning algorithms 6 | and especially neural networks has caused major changes in many engineering disciplines. 7 | For that reason we wanted to create a piece of hardware that would be general enough 8 | to execute various types of machine learning algorithms. 9 | With the introduction of the vector extension to the RISC-V ISA, this option has become 10 | even more interesting, because hard work of creating a meaningful set of instructions has 11 | already been done in advance and additionally it gives engineers who want to work with it 12 | more flexibility because of its open-source nature. 13 | 14 | Beacuse this project is a work in progress it is susceptible to further changes. 15 | 16 | ## Directories 17 | * hdl - Contains hardware source files and also some simple test benches used to verify 18 | basic functionality of some modules. 19 | * RISCV-GCC_compile-scripts - contains scripts used to compile RISCV assembly code. 20 | Check sections COMPILE SCRIPTS for more information 21 | * synth-Contains scripts which enable vivado synthesis and implementation of hardware 22 | from bash 23 | * verif-Contains main source file used to create the verification environment 24 | * vivado_pjt-Contains scripts used to create vivado project and add all hardware and verification files. 25 | Check section SIMULATION. 26 | * Software - Contains assembly and .c examples 27 | * Vitis_test_app - contains example software used for programming of Zedboard from Vitis. 28 | * Scripts - .tcl files used for packaging of all the hardware files 29 | 30 | ## PROJECT STATUS 31 | 32 | * Sheet of implemented and verified instructions can be found on the next [link:](https://docs.google.com/spreadsheets/d/1fCqdjVGNh2V0TndOiQdK-zKLkYkHDLEMYcRyQqehwq8/edit?usp=sharing) 33 | 34 | ## Steps to Run and test the hardware on the board 35 | 36 | * Open Vitis and create new board platform using .xca file from scripts directory. If you 37 | want to generate your own .xca file follow steps from README in scripts directory. 38 | * Create new application project and use source files from Vitis_test_app_directory. 39 | * Program FPGA and run the application. It will compare results that application calculated 40 | and results core outputed. 41 | * The application will by default run an assembly.s code in RISCV-GCC_compile-scripts directory 42 | 43 | ## SIMULATION 44 | 45 | To simulate the design in Vivado next .tcl script needs to be sourced to it: 46 | 47 | vivado_pjt/create_pjt.tcl 48 | 49 | The easiest way to do this is to open Vivado GUI and source the script by 50 | clicking tools -> Run Tcl Script 51 | 52 | Script adds all files that are needed. Simulation needs some RISCV assembly code, 53 | and the default one used by the verification environment is: 54 | 55 | RISCV-GCC-compile-scripts/assembly.dump 56 | 57 | If you want to generate your own assembly code, RISCV-GCC compiler needs to be downloaded. 58 | 59 | ## RISCV-GCC compiler 60 | 61 | Create installs dir: 62 | 63 | ```bash 64 | mkdir installs 65 | ``` 66 | 67 | And in it clone the next repository: 68 | 69 | ```bash 70 | cd installs 71 | 72 | git clone https://github.com/riscv-collab/riscv-gnu-toolchain 73 | ``` 74 | Go into cloned directory and folow the steps provided in its README file. 75 | 76 | After everything has been installed you can go into RISCV-GCC-compile-scripts directory 77 | rewrite assembly.s file (write your own assembly instructions) and compile them 78 | with the next command: 79 | 80 | ```bash 81 | make 82 | ``` 83 | 84 | The makefile will automaticaly compile everything and create assembly.dump file that 85 | is used by the simulator 86 | 87 | ## TOOLS USED 88 | 89 | * Vivado: used for hardware simulation and implementation. 90 | * Vitis: used for testing hardware on board. 91 | * RISCV-GCC compiler: used for compiling assembly code. 92 | 93 | 94 | 95 | 96 | 97 | 98 | -------------------------------------------------------------------------------- /RISCV-GCC-compile-scripts/Makefile: -------------------------------------------------------------------------------- 1 | 2 | src ?= assembly.s 3 | all: assembly.dump 4 | 5 | assembly.dump: assembly.o 6 | ../installs/riscv-gcc/riscv64-unknown-elf/bin/objdump -d assembly.o > assembly.dump 7 | assembly.o: $(src) 8 | ../installs/riscv-gcc/riscv64-unknown-elf/bin/as -march=rv64iv -o assembly.o $(src) 9 | 10 | .PHONY:clean 11 | clean: 12 | @rm -r -f -d *.dump *.o *~ 13 | -------------------------------------------------------------------------------- /RISCV-GCC-compile-scripts/assembly.dump: -------------------------------------------------------------------------------- 1 | 2 | assembly.o: file format elf64-littleriscv 3 | 4 | 5 | Disassembly of section .text: 6 | 7 | 0000000000000000 : 8 | 0: 10050513 addi a0,a0,256 9 | 4: 40058593 addi a1,a1,1024 10 | 8: 40060613 addi a2,a2,1024 11 | c: 40060613 addi a2,a2,1024 12 | 10: 40068693 addi a3,a3,1024 13 | 14: 40068693 addi a3,a3,1024 14 | 18: 40068693 addi a3,a3,1024 15 | 1c: 40068693 addi a3,a3,1024 16 | 20: 40070713 addi a4,a4,1024 17 | 24: 40070713 addi a4,a4,1024 18 | 28: 40070713 addi a4,a4,1024 19 | 2c: 00180813 addi a6,a6,1 20 | 30: 00000793 li a5,0 21 | 34: 00057fd7 vsetvli t6,a0,e8,m1,tu,mu,d1 22 | 38: 00a008b3 add a7,zero,a0 23 | 3c: 02058007 vle8.v v0,(a1) 24 | 40: 97c06e57 vmul.vx v28,v28,zero 25 | 44: 96806457 vmul.vx v8,v8,zero 26 | 27 | 0000000000000048 : 28 | 48: 02068807 vle8.v v16,(a3) 29 | 4c: 96082857 vmul.vv v16,v0,v16 30 | 50: 030e2e57 vredsum.vs v28,v16,v28 31 | 54: fff88893 addi a7,a7,-1 32 | 58: 00088a63 beqz a7,6c 33 | 5c: 3bc84457 vslideup.vx v8,v28,a6 34 | 60: 02804e57 vadd.vx v28,v8,zero 35 | 64: 00a686b3 add a3,a3,a0 36 | 68: fe1ff0ef jal ra,48 37 | 38 | 000000000000006c : 39 | 6c: 00000013 nop 40 | 70: 02060407 vle8.v v8,(a2) 41 | 74: 03c40e57 vadd.vv v28,v28,v8 42 | 78: 02070e27 vse8.v v28,(a4) 43 | 44 | 000000000000007c : 45 | 7c: 00000013 nop 46 | 80: 00000013 nop 47 | 84: 00000013 nop 48 | 88: 00000013 nop 49 | 8c: 00000013 nop 50 | 90: fedff0ef jal ra,7c 51 | -------------------------------------------------------------------------------- /RISCV-GCC-compile-scripts/assembly.s: -------------------------------------------------------------------------------- 1 | .text # Start text section 2 | .balign 4 # align 4 byte instructions by 4 bytes 3 | 4 | 5 | addi x10, x10, 256 # Number of Pixels/Weights 6 | addi x11, x11, 1024 # Pointer to start of image 7 | addi x12, x12, 1024 # Pointer to start of biases 8 | addi x12, x12, 1024 # Pointer to start of biases 9 | addi x13, x13, 1024 # Pointer to start of result 10 | addi x13, x13, 1024 # Pointer to start of result 11 | addi x13, x13, 1024 # Pointer to start of result 12 | addi x13, x13, 1024 # Pointer to start of result 13 | addi x14, x14, 1024 # Pointer to start of weights 14 | addi x14, x14, 1024 # Pointer to start of weights 15 | addi x14, x14, 1024 # Pointer to start of weights 16 | addi x16, x16, 1 # Pointer to start of weights 17 | addi x15, x0, 0 18 | vsetvli x31, x10, e8, m1 # 8-bit data 19 | 20 | add x17, x0, x10 # Set iterator to number of pixels 21 | 22 | vle8.v v0, (x11) # load image in v0 ~ fixed for all output pixels 23 | vmul.vx v28, v28, x0 #reset to zero 24 | vmul.vx v8, v8, x0 #reset to zero 25 | 26 | l_image_loop: 27 | 28 | vle8.v v16, (x13) # load first set of weights in v16 29 | vmul.vv v16, v0, v16 # Multiply weights and pixels 30 | 31 | 32 | vredsum.vs v28, v16, v28 # sum 33 | 34 | addi x17, x17, -1 # one output pixel done, reduce iterator of the loop 35 | beq x17, x0, l_image_loop_exit 36 | 37 | 38 | vslideup.vx v8, v28, x16 # slide up result by one each time, 39 | vadd.vx v28, v8, x0 # add up v28 with v8 to add pixel to result 40 | 41 | add x13, x13, x10 # increment weight pointer to next set of weights 42 | 43 | jal l_image_loop 44 | l_image_loop_exit:nop 45 | 46 | 47 | vle8.v v8, (x12) # load biases in v8 ~ fixed for all output pixels 48 | vadd.vv v28, v28, v8 49 | vse8.v v28, (x14) # load image in v0 50 | 51 | 52 | l_finished:nop 53 | nop 54 | nop 55 | nop 56 | nop 57 | jal l_finished 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /RISCV-GCC-compile-scripts/compile_notes.txt: -------------------------------------------------------------------------------- 1 | 2 | /home/nikola/Documents/git_repos/RISC-V-vector-processor/ara/install/riscv-llvm/bin/clang -march=rv64gcv0p10 -mabi=lp64d -menable-experimental-extensions -mno-relax -fuse-ld=lld -mcmodel=medany -I/home/nikola/Documents/git_repos/RISC-V-vector-processor/ara/apps/common -std=gnu99 -O3 -ffast-math -fno-common -fno-builtin-printf -DNR_LANES=4 -DVLEN=4096 -Wunused-variable -Wall -Wextra -Wno-unused-command-line-argument -c hello_world/main.c -o hello_world/main.c.o 3 | 4 | /home/nikola/Documents/git_repos/RISC-V-vector-processor/ara/install/riscv-llvm/bin/clang -march=rv64gcv0p10 -mabi=lp64d -menable-experimental-extensions -mno-relax -fuse-ld=lld -mcmodel=medany -I/home/nikola/Documents/git_repos/RISC-V-vector-processor/ara/apps/common -std=gnu99 -O3 -ffast-math -fno-common -fno-builtin-printf -DNR_LANES=4 -DVLEN=4096 -Wunused-variable -Wall -Wextra -Wno-unused-command-line-argument -c common/crt0.S -o common/crt0-llvm.S.o 5 | 6 | # This command reads a binary file and creates a dump file with all instructions 7 | /home/nikola/Documents/git_repos/RISC-V-vector-processor/ara/install/riscv-llvm/bin/llvm-objdump --mattr=+experimental-v -D bcd2a > hello_world.dump 8 | 9 | 10 | 11 | 12 | ## Two commands below use riscv64 tool chaing to generate outputs 13 | # This command takes an assembly file (.s) and creates and object file (.o) 14 | ../installs/riscv-gcc/riscv64-unknown-elf/bin/as -march=rv64gcv -o bcd2ascii.o bcd2ascii.s 15 | 16 | # This command takes in object file and generates .elf file 17 | ../installs/riscv-gcc/riscv64-unknown-elf/bin/ld start_bcd2a.o bcd2ascii.o -o bcd2a 18 | 19 | # Create object dump out of .o file. From this we can extract instruction hex 20 | ../installs/riscv-gcc/riscv64-unknown-elf/bin/objdump -d bcd2ascii.o > bcd2ascii.dump 21 | -------------------------------------------------------------------------------- /Software/assembly - full_connected.s: -------------------------------------------------------------------------------- 1 | # x6 = N, x12 = M, x13 = P, x7 = X pointer, x8 = Y pointer, x9 = Z pointer 2 | 3 | addi x6, x0, 5120 # Bias 4 | addi x7, x0, 0 # X 5 | addi x8, x0, 512 # Y 6 | addi x9, x0, 2560 # Z 7 | 8 | addi x12, x0, 32 # M 9 | addi x11, x0, 64 # P 10 | 11 | # NxM * MxP = NxP 12 | # 1xM * MxP = 1xP 13 | 14 | vmul.vx v8, v8, x0 # Initializing v8 with zeros 15 | add x13, x0, x11 # P 16 | 17 | loop3: 18 | vsetvli x16, x11, e16, m2 # 16-bit data 19 | add x18, x0, x16 20 | 21 | loop2: 22 | add x10, x0, x12 # x10 = M 23 | vsetvli x5, x10, e16, m2 # 16-bit data 24 | vmul.vx v6, v6, x0 # Initializing v6 with zeros 25 | 26 | loop1: 27 | vsetvli x5, x10, e8, m1 # 8-bit data 28 | vle8.v v0, (x7) # Load a vector form the first matrix 29 | vle8.v v2, (x8) # Load a vector from the second matrix 30 | vwmul.vv v4, v0, v2 # Multiply two vectors 31 | vsetvli x5, x10, e16, m2 # 16-bit data 32 | vredsum.vs v6, v4, v6 # Sum reduction 33 | sub x10, x10, x5 # Calculate how many elements are left to process 34 | add x7, x7, x5 # Increment pointer for X 35 | add x8, x8, x5 # Increment pointer for Y 36 | bgtz x10, loop1 # Checks if x6 is zero. It should check if x6 is less than zero 37 | 38 | vsetvli x16, x11, e16, m2 # To get the proper vector length 39 | vslideup.vi v8, v8, 1 # v8[i + 1] = v8[i] 40 | vadd.vv v8, v8, v6 # Inserts v6[0] in v8 41 | add x8, x8, 1 # Increment pointer for Y 42 | addi x30, x0, 1 43 | sub x16, x16, x30 44 | bnez x16, loop2 45 | 46 | vle16.v v10, (x6) # Load bias 47 | vadd.vv v8, v8, v10 # Add bias to the calculated result 48 | vse16.v v8, (x9) # Store result 49 | vmul.vx v8, v8, x0 # Resetting v8 50 | slli x30, x18, 2 # 1 and 4 in case of 8-bit and 32-bir results 51 | add x9, x9, x30 # Increment pointer for Z 52 | sub x11, x11, x18 # For one row of matrix X P columns of matrix Y have to be processed 53 | bgtz x11, loop3 # Check if x11 is zero 54 | -------------------------------------------------------------------------------- /Software/assembly.s: -------------------------------------------------------------------------------- 1 | # x6 = N, x12 = M, x13 = P, x7 = X pointer, x8 = Y pointer, x9 = Z pointer 2 | 3 | addi x7, x0, 0 # X 4 | addi x8, x0, 512 # Y 5 | addi x9, x0, 2560 # Z 6 | 7 | addi x6, x0, 16 # N 8 | addi x12, x0, 32 # M 9 | addi x13, x0, 64 # P 10 | 11 | vmul.vx v8, v8, x0 # Initializing v8 with zeros 12 | 13 | loop4: 14 | add x11, x0, x13 # x11 = P 15 | 16 | loop3: 17 | vsetvli x16, x11, e16, m2 # 16-bit data 18 | add x18, x0, x16 19 | 20 | loop2: 21 | add x10, x0, x12 # x10 = M 22 | # slli x15, x11, 2 # Needed in case of 32-bit data 23 | # slli x15, x11, 1 # Needed in case of 16-bit data 24 | vsetvli x5, x10, e16, m2 # 16-bit data 25 | vmul.vx v6, v6, x0 # Initializing v6 with zeros 26 | 27 | loop1: 28 | vsetvli x5, x10, e8, m1 # 8-bit data 29 | vle8.v v0, (x7) # Load a vector form the first matrix 30 | vlse8.v v2, (x8), x11 # Load a vector from the second matrix, if 16-bit or 32-bit data is used, then instead of x11 x15 should be used 31 | vwmul.vv v4, v0, v2 # Multiply two vectors 32 | vsetvli x5, x10, e16, m2 # 16-bit data 33 | vredsum.vs v6, v4, v6 # Sum reduction 34 | sub x10, x10, x5 # Calculate how many elements are left to process 35 | # slli x5, x5, 2 # Needed if 32-bit date used 36 | # slli x5, x5, 1 # Needed if 16-bit date used 37 | add x7, x7, x5 # Increment pointer for X 38 | add x28, x0, x13 # x28 = P 39 | add x29, x0, x0 # x29 = 0 40 | 41 | multiply: 42 | add x29, x29, x5 # x29 += x5 43 | addi x30, x0, 1 44 | sub x28, x28, x30 45 | bnez x28, multiply 46 | 47 | add x8, x8, x29 # Increment pointer for Y 48 | bgtz x10, loop1 # Checks if x6 is zero. It should check if x6 is less than zero 49 | 50 | vsetvli x16, x11, e16, m2 # To get the proper vector length 51 | vslideup.vi v8, v8, 1 # v8[i + 1] = v8[i] 52 | vadd.vv v8, v8, v6 # Inserts v6[0] in v8 53 | add x8, x8, 1 # Increment pointer for Y, determines which column in matrix Y is next, 2 and 4 for 16- and 32-bit inputs, respectively 54 | addi x30, x0, 1 55 | sub x16, x16, x30 56 | bnez x16, loop2 57 | 58 | vse16.v v8, (x9) # Store result, ovaj store treba modifikovati 59 | vmul.vx v8, v8, x0 # Resetting v8 60 | slli x30, x18, 2 # 1 and 4 in case of 8-bit and 32-bir results 61 | addi x9, x9, x30 # Increment pointer for Z 62 | sub x11, x11, x18 # For one row of matrix X P columns of matrix Y have to be processed 63 | bgtz x11, loop3 # Check if x11 is zero 64 | 65 | addi x30, x0, 1 66 | sub x6, x6, x30 # We have to go through all the rows of matrix X 67 | add x7, x7, x12 # Increment pointer for Y 68 | bnez x6, loop4 # Check if x6 is zero 69 | -------------------------------------------------------------------------------- /hdl/README.md: -------------------------------------------------------------------------------- 1 | # HDL 2 | 3 | This directory contains all design files that are a part of RISCV processor -------------------------------------------------------------------------------- /hdl/common/README.md: -------------------------------------------------------------------------------- 1 | # COMMON -------------------------------------------------------------------------------- /hdl/common/ram_sp_ar.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | library work; 3 | use ieee.std_logic_1164.all; 4 | use ieee.numeric_std.all; 5 | use work.cache_pkg.all; 6 | USE std.textio.all; 7 | 8 | entity ram_sp_ar is 9 | generic ( 10 | RAM_WIDTH : integer := 24; -- Specify RAM data width 11 | RAM_DEPTH : integer := 16; -- Specify RAM depth (number of entries) 12 | INIT_FILE : string := "" -- Specify name/location of RAM initialization file if using one (leave blank if not) 13 | ); 14 | 15 | port ( 16 | addra : in std_logic_vector((clogb2(RAM_DEPTH)-1) downto 0); -- Address bus, width determined from RAM_DEPTH 17 | dina : in std_logic_vector(RAM_WIDTH-1 downto 0); -- RAM input data 18 | clk : in std_logic; -- Clock 19 | wea : in std_logic; -- Write enable 20 | ena : in std_logic; -- RAM Enable, for additional power savings, disable port when not in use 21 | douta : out std_logic_vector(RAM_WIDTH-1 downto 0) -- RAM output data 22 | ); 23 | 24 | end ram_sp_ar; 25 | 26 | architecture rtl of ram_sp_ar is 27 | 28 | constant C_RAM_WIDTH : integer := RAM_WIDTH; 29 | constant C_RAM_DEPTH : integer := RAM_DEPTH; 30 | constant C_INIT_FILE : string := INIT_FILE; 31 | 32 | 33 | type ram_type is array (0 to C_RAM_DEPTH-1) of std_logic_vector (C_RAM_WIDTH-1 downto 0); -- 2D Array Declaration for RAM signal 34 | 35 | -- The folowing code either initializes the memory values to a specified file or to all zeros to match hardware 36 | impure function initramfromfile (ramfilename : in string) return ram_type is 37 | file ramfile : text is in ramfilename; 38 | variable ramfileline : line; 39 | variable ram_s : ram_type; 40 | variable bitvec : bit_vector(C_RAM_WIDTH-1 downto 0); 41 | begin 42 | for i in ram_type'range loop 43 | readline (ramfile, ramfileline); 44 | read (ramfileline, bitvec); 45 | ram_s(i) := to_stdlogicvector(bitvec); 46 | end loop; 47 | return ram_s; 48 | end function; 49 | 50 | impure function init_from_file_or_zeroes(ramfile : string) return ram_type is 51 | begin 52 | if ramfile = "" then 53 | return (others => (others => '0')); 54 | else 55 | return InitRamFromFile(ramfile); 56 | end if; 57 | end; 58 | -- Following code defines RAM 59 | signal ram_s : ram_type := init_from_file_or_zeroes(C_INIT_FILE); 60 | attribute ram_style : string; 61 | attribute ram_style of ram_s : signal is "distributed"; 62 | begin 63 | 64 | lutram_proc: process(clk) 65 | begin 66 | if(clk'event and clk = '1') then 67 | if(ena = '1') then 68 | if(wea = '1') then 69 | ram_s(to_integer(unsigned(addra))) <= dina; 70 | end if; 71 | end if; 72 | end if; 73 | end process; 74 | 75 | douta <= ram_s(to_integer(unsigned(addra))); 76 | 77 | 78 | end rtl; 79 | -------------------------------------------------------------------------------- /hdl/common/ram_sp_ar_bw.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | library work; 3 | use ieee.std_logic_1164.all; 4 | use ieee.numeric_std.all; 5 | use work.cache_pkg.all; 6 | USE std.textio.all; 7 | 8 | entity RAM_sp_ar_bw is 9 | generic ( 10 | NB_COL : integer := 4; -- Specify number of columns (number of bytes) 11 | COL_WIDTH : integer := 8; -- Specify column width (byte width, typically 8 or 9) 12 | RAM_DEPTH : integer := 256; -- Specify RAM depth (number of entries) 13 | RAM_PERFORMANCE : string := "LOW_LATENCY"; -- Select "HIGH_PERFORMANCE" or "LOW_LATENCY" 14 | INIT_FILE : string := "" -- Specify name/location of RAM initialization file if using one (leave blank if not) 15 | ); 16 | 17 | port ( 18 | addra : in std_logic_vector((clogb2(RAM_DEPTH)-1) downto 0); -- Port A Address bus, width determined from RAM_DEPTH 19 | dina : in std_logic_vector(NB_COL*COL_WIDTH-1 downto 0); -- Port A RAM input data 20 | clk : in std_logic; -- Clock 21 | wea : in std_logic_vector(NB_COL-1 downto 0); -- Port A Write enable 22 | ena : in std_logic; -- Port A RAM Enable, for additional power savings, disable port when not in use 23 | rsta : in std_logic; -- Port A Output reset (does not affect memory contents) 24 | regcea: in std_logic; -- Port A Output register enable 25 | douta : out std_logic_vector(NB_COL*COL_WIDTH-1 downto 0) -- Port A RAM output data 26 | ); 27 | 28 | end RAM_sp_ar_bw; 29 | 30 | architecture rtl of RAM_sp_ar_bw is 31 | 32 | constant C_NB_COL : integer := NB_COL; 33 | constant C_COL_WIDTH : integer := COL_WIDTH; 34 | constant C_RAM_DEPTH : integer := RAM_DEPTH; 35 | constant C_RAM_PERFORMANCE : string := RAM_PERFORMANCE; 36 | constant C_INIT_FILE : string := INIT_FILE; 37 | 38 | 39 | signal douta_reg : std_logic_vector(C_NB_COL*C_COL_WIDTH-1 downto 0) := (others => '0'); 40 | 41 | type ram_type is array (0 to C_RAM_DEPTH-1) of std_logic_vector (C_NB_COL*C_COL_WIDTH-1 downto 0); -- 2D Array Declaration for RAM signal 42 | 43 | signal ram_data_a : std_logic_vector(C_NB_COL*C_COL_WIDTH-1 downto 0) ; 44 | -- The folowing code either initializes the memory values to a specified file or to all zeros to match hardware 45 | 46 | impure function initramfromfile (ramfilename : in string) return ram_type is 47 | file ramfile : text is in ramfilename; 48 | variable ramfileline : line; 49 | variable i : integer := 0; 50 | 51 | variable ram_array : ram_type; 52 | variable bitvec : bit_vector(C_NB_COL*C_COL_WIDTH-1 downto 0); 53 | begin 54 | ram_array := (others => (others => '0')); 55 | while not endfile(ramfile) loop 56 | readline (ramfile, ramfileline); 57 | read (ramfileline, bitvec); 58 | ram_array(i) := to_stdlogicvector(bitvec); 59 | i:=i+1; 60 | end loop; 61 | return ram_array; 62 | end function; 63 | 64 | impure function init_from_file_or_zeroes(ramfile : string) return ram_type is 65 | begin 66 | if ramfile = "" then 67 | return (others => (others => '0')); 68 | else 69 | return InitRamFromFile(ramfile); 70 | end if; 71 | end; 72 | 73 | -- Following code defines RAM 74 | signal ram_array : ram_type := init_from_file_or_zeroes(C_INIT_FILE); 75 | attribute ram_style : string; 76 | attribute ram_style of ram_array : signal is "distributed"; 77 | 78 | 79 | begin 80 | 81 | lutram_proc: process(clk) 82 | begin 83 | if(clk'event and clk = '1') then 84 | if(ena = '1') then 85 | for i in 0 to C_NB_COL-1 loop 86 | if(wea(i) = '1') then 87 | ram_array(to_integer(unsigned(addra)))((i+1)*C_COL_WIDTH-1 downto i*C_COL_WIDTH) <= 88 | dina((i+1)*C_COL_WIDTH-1 downto i*C_COL_WIDTH); 89 | end if; 90 | end loop; 91 | end if; 92 | end if; 93 | end process; 94 | 95 | ram_data_a <= ram_array(to_integer(unsigned(addra))); 96 | 97 | -- Following code generates LOW_LATENCY (no output register) 98 | -- Following is a async read at the cost of a longer adress-to-out timing 99 | no_output_register : if C_RAM_PERFORMANCE = "LOW_LATENCY" generate 100 | douta <= ram_data_a; 101 | end generate; 102 | 103 | -- Following code generates HIGH_PERFORMANCE (use output register) 104 | -- Following is a 1 clock cycle read latency with improved clock-to-out timing 105 | output_register : if C_RAM_PERFORMANCE = "HIGH_PERFORMANCE" generate 106 | process(clk) 107 | begin 108 | if(clk'event and clk = '1') then 109 | if(rsta = '1') then 110 | douta_reg <= (others => '0'); 111 | elsif(regcea = '1') then 112 | douta_reg <= ram_data_a; 113 | end if; 114 | end if; 115 | end process; 116 | douta <= douta_reg; 117 | 118 | end generate; 119 | end rtl; 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /hdl/common/ram_tdp_rf.vhd: -------------------------------------------------------------------------------- 1 | 2 | -- Xilinx True Dual Port RAM Byte Write Read First Single Clock 3 | -- This code implements a parameterizable true dual port memory (both ports can read and write). 4 | -- The behavior of this RAM is when data is written, the prior memory contents at the write 5 | -- address are presented on the output port. If the output data is 6 | -- not needed during writes or the last read value is desired to be retained, 7 | -- it is suggested to use a no change RAM as it is more power efficient. 8 | -- If a reset or enable is not necessary, it may be tied off or removed from the code. 9 | -- Modify the parameters for the desired RAM characteristics. 10 | library ieee; 11 | library work; 12 | use ieee.std_logic_1164.all; 13 | use ieee.numeric_std.all; 14 | use work.cache_pkg.all; 15 | USE std.textio.all; 16 | 17 | entity RAM_tdp_rf is 18 | generic ( 19 | 20 | RAM_WIDTH : integer := 26; -- Specify RAM data width 21 | RAM_DEPTH : integer := 64; -- Specify RAM depth (number of entries) 22 | RAM_PERFORMANCE : string := "HIGH_PERFORMANCE"; -- Select "HIGH_PERFORMANCE" or "LOW_LATENCY" 23 | INIT_FILE : string := "" -- Specify name/location of RAM initialization file if using one (leave blank if not) 24 | ); 25 | 26 | port ( 27 | addra : in std_logic_vector((clogb2(RAM_DEPTH)-1) downto 0); -- Port A Address bus, width determined from RAM_DEPTH 28 | addrb : in std_logic_vector((clogb2(RAM_DEPTH)-1) downto 0); -- Port B Address bus, width determined from RAM_DEPTH 29 | dina : in std_logic_vector(RAM_WIDTH-1 downto 0); -- Port A RAM input data 30 | dinb : in std_logic_vector(RAM_WIDTH-1 downto 0); -- Port B RAM input data 31 | clk : in std_logic; -- Clock 32 | wea : in std_logic; -- Port A Write enable 33 | web : in std_logic; -- Port B Write enable 34 | ena : in std_logic; -- Port A RAM Enable, for additional power savings, disable port when not in use 35 | enb : in std_logic; -- Port B RAM Enable, for additional power savings, disable port when not in use 36 | rsta : in std_logic; -- Port A Output reset (does not affect memory contents) 37 | rstb : in std_logic; -- Port B Output reset (does not affect memory contents) 38 | regcea: in std_logic; -- Port A Output register enable 39 | regceb: in std_logic; -- Port B Output register enable 40 | douta : out std_logic_vector(RAM_WIDTH-1 downto 0); -- Port A RAM output data 41 | doutb : out std_logic_vector(RAM_WIDTH-1 downto 0) -- Port B RAM output data 42 | ); 43 | 44 | end RAM_tdp_rf; 45 | 46 | architecture rtl of RAM_tdp_rf is 47 | 48 | constant C_RAM_WIDTH : integer := RAM_WIDTH; -- Specify RAM data width 49 | constant C_RAM_DEPTH : integer := RAM_DEPTH; 50 | constant C_RAM_PERFORMANCE : string := RAM_PERFORMANCE; 51 | constant C_INIT_FILE : string := INIT_FILE; 52 | 53 | 54 | signal douta_reg : std_logic_vector(RAM_WIDTH-1 downto 0) := (others => '0'); 55 | signal doutb_reg : std_logic_vector(RAM_WIDTH-1 downto 0) := (others => '0'); 56 | 57 | type ram_type is array (0 to C_RAM_DEPTH-1) of std_logic_vector (RAM_WIDTH-1 downto 0); -- 2D Array Declaration for RAM signal 58 | 59 | signal ram_data_a : std_logic_vector(RAM_WIDTH-1 downto 0) ; 60 | signal ram_data_b : std_logic_vector(RAM_WIDTH-1 downto 0) ; 61 | 62 | -- The folowing code either initializes the memory values to a specified file or to all zeros to match hardware 63 | 64 | impure function initramfromfile (ramfilename : in string) return ram_type is 65 | file ramfile : text is in ramfilename; 66 | variable ramfileline : line; 67 | variable i : integer := 0; 68 | 69 | variable ram_array_v : ram_type; 70 | variable bitvec : bit_vector(RAM_WIDTH-1 downto 0); 71 | begin 72 | ram_array_v := (others => (others => '0')); 73 | while not endfile(ramfile) loop 74 | readline (ramfile, ramfileline); 75 | read (ramfileline, bitvec); 76 | ram_array_v(i) := to_stdlogicvector(bitvec); 77 | i:=i+1; 78 | end loop; 79 | return ram_array_v; 80 | end function; 81 | 82 | impure function init_from_file_or_zeroes(ramfile : string) return ram_type is 83 | begin 84 | if ramfile = "" then 85 | return (others => (others => '0')); 86 | else 87 | return InitRamFromFile(ramfile) ; 88 | end if; 89 | end; 90 | 91 | -- Following code defines RAM 92 | shared variable ram_array_v : ram_type := init_from_file_or_zeroes(C_INIT_FILE); 93 | attribute ram_style : string; 94 | attribute ram_style of ram_array_v : variable is "block"; 95 | 96 | begin 97 | 98 | process(clk) 99 | begin 100 | if(clk'event and clk = '1') then 101 | if(ena = '1') then 102 | ram_data_a <= ram_array_v(to_integer(unsigned(addra))); 103 | if(wea = '1') then 104 | ram_array_v(to_integer(unsigned(addra))) := dina; 105 | end if; 106 | end if; 107 | end if; 108 | end process; 109 | 110 | process(clk) 111 | begin 112 | if(clk'event and clk = '1') then 113 | if(enb = '1') then 114 | ram_data_b <= ram_array_v(to_integer(unsigned(addrb))); 115 | if(web = '1') then 116 | ram_array_v(to_integer(unsigned(addrb))):= dinb; 117 | end if; 118 | end if; 119 | end if; 120 | end process; 121 | 122 | -- Following code generates LOW_LATENCY (no output register) 123 | -- Following is a 1 clock cycle read latency at the cost of a longer clock-to-out timing 124 | 125 | no_output_register : if C_RAM_PERFORMANCE = "LOW_LATENCY" generate 126 | douta <= ram_data_a; 127 | doutb <= ram_data_b; 128 | end generate; 129 | 130 | -- Following code generates HIGH_PERFORMANCE (use output register) 131 | -- Following is a 2 clock cycle read latency with improved clock-to-out timing 132 | 133 | output_register : if C_RAM_PERFORMANCE = "HIGH_PERFORMANCE" generate 134 | process(clk) 135 | begin 136 | if(clk'event and clk = '1') then 137 | if(rsta = '1') then 138 | douta_reg <= (others => '0'); 139 | elsif(regcea = '1') then 140 | douta_reg <= ram_data_a; 141 | end if; 142 | end if; 143 | end process; 144 | douta <= douta_reg; 145 | 146 | process(clk) 147 | begin 148 | if(clk'event and clk = '1') then 149 | if(rstb = '1') then 150 | doutb_reg <= (others => '0'); 151 | elsif(regceb = '1') then 152 | doutb_reg <= ram_data_b; 153 | end if; 154 | end if; 155 | end process; 156 | doutb <= doutb_reg; 157 | 158 | end generate; 159 | end rtl; 160 | 161 | 162 | 163 | 164 | -------------------------------------------------------------------------------- /hdl/common/sdp_bram.sv: -------------------------------------------------------------------------------- 1 | module sdp_bram #( 2 | parameter WIDTH = 32 , // Specify RAM data width 3 | parameter DEPTH = 512, // Specify RAM depth (number of entries) 4 | parameter RAM_PERFORMANCE = "LLOW_LATENCY", // Select "HIGH_PERFORMANCE" or "LOW_LATENCY" 5 | parameter CASCADE_HEIGHT = 0, 6 | parameter INIT_FILE = "" // Specify name/location of RAM initialization file if using one (leave blank if not) 7 | ) 8 | ( 9 | input [clogb2(DEPTH-1)-1:0] addra, // Port A address bus, width determined from RAM_DEPTH 10 | input [clogb2(DEPTH-1)-1:0] addrb, // Port B address bus, width determined from RAM_DEPTH 11 | input [WIDTH-1:0] dina, // Port A RAM input data 12 | input clk, // Clock 13 | input wea, // Port A write enable 14 | input ena, // Port A RAM Enable, for additional power savings, disable port when not in use 15 | input enb, // Port B RAM Enable, for additional power savings, disable port when not in use 16 | //input clk, // Clock 17 | input rstb, // Port B output reset (does not affect ram contents) 18 | input oreg_enb, // Port B output register enable 19 | output [WIDTH-1:0] doutb // Port B RAM output data 20 | ); 21 | 22 | 23 | 24 | (* cascade_height = CASCADE_HEIGHT *)(* ram_style = "block" *) reg [WIDTH-1:0] ram[DEPTH]; 25 | 26 | reg [WIDTH-1:0] ram_data_b = {WIDTH{1'b0}}; 27 | //int i=0; 28 | 29 | // The following code either initializes the ram values to a specified file or to all zeros to match hardware 30 | generate 31 | if (INIT_FILE != "") begin: use_init_file 32 | initial 33 | $readmemh(INIT_FILE, ram, 0, DEPTH-1); 34 | end else begin: init_memory_to_zero 35 | integer ram_index; 36 | initial 37 | for (ram_index = 0; ram_index < DEPTH; ram_index = ram_index + 1) 38 | begin 39 | ram[ram_index] = {WIDTH{1'b1}}; 40 | end 41 | end 42 | endgenerate 43 | // PORT A 44 | always @(posedge clk) begin 45 | if (ena) 46 | if (wea) 47 | ram[addra] <= dina; 48 | end 49 | 50 | // PORT B 51 | always @(posedge clk) begin 52 | if (enb) 53 | ram_data_b <= ram[addrb]; 54 | end 55 | 56 | // The following code generates HIGH_PERFORMANCE (use output register) or LOW_LATENCY (no output register) 57 | generate 58 | if (RAM_PERFORMANCE == "LOW_LATENCY") begin: no_output_register 59 | 60 | // The following is a 1 clock cycle read latency at the cost of a longer clock-to-out timing 61 | 62 | assign doutb = ram_data_b; 63 | 64 | end else begin: output_register 65 | 66 | // The following is a 2 clock cycle read latency with improve clock-to-out timing 67 | 68 | reg [WIDTH-1:0] doutb_reg = {WIDTH{1'b0}}; 69 | 70 | always @(posedge clk) 71 | if (rstb) 72 | doutb_reg <= {WIDTH{1'b0}}; 73 | else if (oreg_enb) 74 | doutb_reg <= ram_data_b; 75 | 76 | assign doutb = doutb_reg; 77 | 78 | end 79 | endgenerate 80 | 81 | // The following function calculates the address width based on specified RAM depth 82 | function integer clogb2; 83 | input integer depth; 84 | for (clogb2=0; depth>0; clogb2=clogb2+1) 85 | depth = depth >> 1; 86 | endfunction 87 | 88 | endmodule 89 | 90 | 91 | -------------------------------------------------------------------------------- /hdl/common/sdp_bwe_bram.sv: -------------------------------------------------------------------------------- 1 | 2 | // Xilinx Simple Dual Port Single Clock RAM with Byte-write 3 | // This code implements a parameterizable SDP single clock memory. 4 | // If a reset or enable is not necessary, it may be tied off or removed from the code. 5 | 6 | module sdp_bwe_bram #( 7 | parameter NB_COL = 8, // Specify number of columns (number of bytes) 8 | parameter COL_WIDTH = 8, // Specify column width (byte width, typically 8 or 9) 9 | parameter RAM_DEPTH = 512, // Specify RAM depth (number of entries) 10 | parameter RAM_PERFORMANCE = "HIGH_PERFORMANCE", // Select "HIGH_PERFORMANCE" or "LOW_LATENCY" 11 | parameter INIT_FILE = "" // Specify name/location of RAM initialization file if using one (leave blank if not) 12 | ) ( 13 | input clka, // Clock 14 | input clkb, // Clock 15 | input [clogb2(RAM_DEPTH-1)-1:0] addra, // Write address bus, width determined from RAM_DEPTH 16 | input [(NB_COL*COL_WIDTH)-1:0] dina, // RAM input data 17 | input [NB_COL-1:0] wea, // Byte-write enable 18 | input [clogb2(RAM_DEPTH-1)-1:0] addrb, // Read address bus, width determined from RAM_DEPTH 19 | output [(NB_COL*COL_WIDTH)-1:0] doutb, // RAM output data 20 | input enb, // Read Enable, for additional power savings, disable when not in use 21 | input rstb, // Output reset (does not affect memory contents) 22 | input regceb // Output register enable 23 | ); 24 | 25 | reg [(NB_COL*COL_WIDTH)-1:0] BRAM [RAM_DEPTH-1:0]; 26 | reg [(NB_COL*COL_WIDTH)-1:0] ram_data = {(NB_COL*COL_WIDTH){1'b0}}; 27 | reg [(NB_COL*COL_WIDTH)-1:0] in_data_reg = {(NB_COL*COL_WIDTH){1'b0}}; 28 | 29 | // The following code either initializes the memory values to a specified file or to all zeros to match hardware 30 | 31 | /* -----\/----- EXCLUDED -----\/----- 32 | generate 33 | if (INIT_FILE != "") begin: use_init_file 34 | initial 35 | $readmemh(INIT_FILE, BRAM, 0, RAM_DEPTH-1); 36 | end else begin: init_bram_to_zero 37 | integer ram_index; 38 | initial 39 | for (ram_index = 0; ram_index < RAM_DEPTH; ram_index = ram_index + 1) 40 | //BRAM[ram_index] = ram_index%16; 41 | BRAM[ram_index] = {(NB_COL*COL_WIDTH){1'b0}}; 42 | end 43 | endgenerate 44 | -----/\----- EXCLUDED -----/\----- */ 45 | 46 | // Registers 47 | //logic [clogb2(RAM_DEPTH-1)-1:0] addra_reg; 48 | //logic [(NB_COL*COL_WIDTH)-1:0] dina_reg; 49 | //logic [NB_COL-1:0] wea_reg; 50 | 51 | //always_ff@(posedge clka) begin 52 | // addra_reg <= addra; 53 | // dina_reg <= dina; 54 | // wea_reg <= wea; 55 | //end 56 | 57 | always @(posedge clkb) 58 | if (enb) 59 | ram_data <= BRAM[addrb]; 60 | 61 | /* -----\/----- EXCLUDED -----\/----- 62 | always @(posedge clka) 63 | in_data_reg <= dina; 64 | -----/\----- EXCLUDED -----/\----- */ 65 | 66 | generate 67 | genvar i; 68 | for (i = 0; i < NB_COL; i = i+1) begin: byte_write 69 | always @(posedge clka) 70 | if (wea[i]) 71 | BRAM[addra][(i+1)*COL_WIDTH-1:i*COL_WIDTH] <= dina[(i+1)*COL_WIDTH-1:i*COL_WIDTH]; 72 | //BRAM[addra][(i+1)*COL_WIDTH-1:i*COL_WIDTH] <= in_data_reg[(i+1)*COL_WIDTH-1:i*COL_WIDTH]; 73 | end 74 | endgenerate 75 | 76 | // The following code generates HIGH_PERFORMANCE (use output register) or LOW_LATENCY (no output register) 77 | generate 78 | if (RAM_PERFORMANCE == "LOW_LATENCY") begin: no_output_register 79 | 80 | // The following is a 1 clock cycle read latency at the cost of a longer clock-to-out timing 81 | assign doutb = ram_data; 82 | 83 | end else begin: output_register 84 | 85 | // The following is a 2 clock cycle read latency with improve clock-to-out timing 86 | 87 | reg [(NB_COL*COL_WIDTH)-1:0] doutb_reg = {(NB_COL*COL_WIDTH){1'b0}}; 88 | 89 | always @(posedge clkb) 90 | if (rstb) 91 | doutb_reg <= {(NB_COL*COL_WIDTH){1'b0}}; 92 | else if (regceb) 93 | doutb_reg <= ram_data; 94 | 95 | assign doutb = doutb_reg; 96 | 97 | end 98 | endgenerate 99 | 100 | // The following function calculates the address width based on specified RAM depth 101 | function integer clogb2; 102 | input integer depth; 103 | for (clogb2=0; depth>0; clogb2=clogb2+1) 104 | depth = depth >> 1; 105 | endfunction 106 | 107 | endmodule 108 | 109 | // The following is an instantiation template for sdp_bwe_bram 110 | /* 111 | // Xilinx Simple Dual Port Single Clock RAM with Byte-write 112 | sdp_bwe_bram #( 113 | .NB_COL(4), // Specify number of columns (number of bytes) 114 | .COL_WIDTH(9), // Specify column width (byte width, typically 8 or 9) 115 | .RAM_DEPTH(1024), // Specify RAM depth (number of entries) 116 | .RAM_PERFORMANCE("HIGH_PERFORMANCE"), // Select "HIGH_PERFORMANCE" or "LOW_LATENCY" 117 | .INIT_FILE("") // Specify name/location of RAM initialization file if using one (leave blank if not) 118 | ) your_instance_name ( 119 | .addra(addra), // Write address bus, width determined from RAM_DEPTH 120 | .addrb(addrb), // Read address bus, width determined from RAM_DEPTH 121 | .dina(dina), // RAM input data, width determined from NB_COL*COL_WIDTH 122 | .clk(clk), // Clock 123 | .wea(wea), // Byte-write enable, width determined from NB_COL 124 | .enb(enb), // Read Enable, for additional power savings, disable when not in use 125 | .rstb(rstb), // Output reset (does not affect memory contents) 126 | .regceb(regceb), // Output register enable 127 | .doutb(doutb) // RAM output data, width determined from NB_COL*COL_WIDTH 128 | ); 129 | */ 130 | 131 | 132 | -------------------------------------------------------------------------------- /hdl/common/sdp_distram.sv: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // Copyright (c) 2021 Neuronix AI Labs; All rights reserved. 3 | //------------------------------------------------------------------------------ 4 | // File name : xilinx_distram_sdp_ram.sv 5 | // Author : Elchanan Rappaport, elchananr@Veriests.com 6 | // Created : 31-Jan-2021 7 | // Description : Distributed RAM behavioral model 8 | // Notes : 9 | //------------------------------------------------------------------------------ 10 | 11 | module sdp_distram #( 12 | parameter WIDTH = 1, 13 | parameter DEPTH = 512, 14 | parameter OUT_PIPE_STAGES = 0 15 | ) (/*AUTOARG*/ 16 | // Outputs 17 | doutb, 18 | // Inputs 19 | clka, clkb, rstb, wea, regceb, addra, dina, enb, addrb 20 | ); 21 | 22 | input clka; 23 | input clkb; 24 | input rstb; 25 | input wea; 26 | input regceb; 27 | input [$clog2(DEPTH)-1:0] addra; 28 | input [WIDTH-1:0] dina; 29 | input enb; 30 | output [WIDTH-1:0] doutb; 31 | input [$clog2(DEPTH)-1:0] addrb; 32 | 33 | (* ram_style = "distributed" *) reg [WIDTH-1:0] ram [DEPTH-1:0] = '{default:0}; 34 | 35 | always @(posedge clka) 36 | begin 37 | if (wea) 38 | ram[addra] <= dina; 39 | end 40 | 41 | generate 42 | if (OUT_PIPE_STAGES == 0) 43 | begin 44 | assign doutb = ram[addrb]; 45 | end 46 | else 47 | begin 48 | reg [OUT_PIPE_STAGES-1:0][WIDTH-1:0] doutb_d_reg; 49 | always@(posedge clkb) 50 | begin 51 | if (rstb) 52 | begin 53 | doutb_d_reg <= 0; 54 | end 55 | else 56 | begin 57 | if (enb) 58 | doutb_d_reg[0] <= ram[addrb]; 59 | if (regceb) 60 | begin 61 | for (int i=1; i0; clogb2=clogb2+1) 109 | depth = depth >> 1; 110 | endfunction 111 | 112 | endmodule 113 | 114 | 115 | -------------------------------------------------------------------------------- /hdl/common/tdp_bwe_bram.sv: -------------------------------------------------------------------------------- 1 | // Xilinx True Dual Port RAM, Single Clock 2 | // This code implements a parameterizable true dual port ram (both ports can read and write). 3 | // This is a no change RAM which retains the last read value on the output during writes 4 | // which is the most power efficient mode. 5 | // If a reset or enable is not necessary, it may be tied off or removed from the code. 6 | 7 | module tdp_bwe_bram # 8 | ( 9 | parameter NUM_COL = 16, 10 | parameter COL_WIDTH = 8, //Max 9 11 | parameter DEPTH = 2048, // Specify RAM depth (number of entries) 12 | parameter WIDTH = NUM_COL*COL_WIDTH, // Specify RAM data width 13 | parameter RAM_PERFORMANCE = "HIGH_PERFORMANCE", // Select "HIGH_PERFORMANCE" or "LOW_LATENCY" 14 | parameter CASCADE_HEIGHT = 0, // Select "HIGH_PERFORMANCE" or "LOW_LATENCY" 15 | parameter INIT_FILE = "" // Specify name/location of RAM initialization file if using one (leave blank if not) 16 | ) 17 | ( 18 | input [clogb2(DEPTH-1)-1:0] addra, // Port A address bus, width determined from RAM_DEPTH 19 | input [clogb2(DEPTH-1)-1:0] addrb, // Port B address bus, width determined from RAM_DEPTH 20 | input [WIDTH-1:0] dina, // Port A RAM input data 21 | input [WIDTH-1:0] dinb, // Port B RAM input data 22 | input clka, // Clock 23 | //input byte_wea, // Port A write enable 24 | input [NUM_COL - 1 : 0] byte_wea, 25 | //input byte_web, // Port B write enable 26 | input [NUM_COL - 1 : 0] byte_web, 27 | input ena, // Port A RAM Enable, for additional power savings, disable port when not in use 28 | input enb, // Port B RAM Enable, for additional power savings, disable port when not in use 29 | input clkb, // Clock 30 | input rsta, // Port A output reset (does not affect ram contents) 31 | input rstb, // Port B output reset (does not affect ram contents) 32 | input oreg_ena, // Port A output register enable 33 | input oreg_enb, // Port B output register enable 34 | output [WIDTH-1:0] douta, // Port A RAM output data 35 | output [WIDTH-1:0] doutb // Port B RAM output data 36 | ); 37 | 38 | 39 | 40 | 41 | 42 | (* cascade_height = CASCADE_HEIGHT *)(* ram_style = "block" *) reg [WIDTH-1:0] ram[DEPTH]; 43 | 44 | reg [WIDTH-1:0] ram_data_a = {WIDTH{1'b0}}; 45 | reg [WIDTH-1:0] ram_data_b = {WIDTH{1'b0}}; 46 | 47 | // The following code either initializes the ram values to a specified file or to all zeros to match hardware 48 | generate 49 | if (INIT_FILE != "") begin: use_init_file 50 | initial 51 | $readmemh(INIT_FILE, ram, 0, DEPTH-1); 52 | end else begin: init_memory_to_zero 53 | integer ram_index; 54 | initial 55 | for (ram_index = 0; ram_index < DEPTH; ram_index = ram_index + 1) 56 | ram[ram_index] = {WIDTH{1'b0}}; 57 | end 58 | endgenerate 59 | // PORT A 60 | always @(posedge clka) begin 61 | if (ena) begin 62 | for (int i = 0; i0; clogb2=clogb2+1) 118 | depth = depth >> 1; 119 | endfunction 120 | 121 | endmodule 122 | 123 | 124 | -------------------------------------------------------------------------------- /hdl/packages/cache_pkg.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | 4 | package cache_pkg is 5 | 6 | -- Integer log2 function 7 | function clogb2 (depth: in natural) return integer; 8 | 9 | end cache_pkg; 10 | 11 | package body cache_pkg is 12 | 13 | function clogb2 (depth: in natural) return integer is 14 | variable temp : integer := depth; 15 | variable ret_val : integer := 0; 16 | begin 17 | while temp > 1 loop 18 | ret_val := ret_val + 1; 19 | temp := temp / 2; 20 | end loop; 21 | return ret_val; 22 | end function; 23 | 24 | end package body cache_pkg; 25 | -------------------------------------------------------------------------------- /hdl/packages/typedef_pkg.sv: -------------------------------------------------------------------------------- 1 | `ifndef TYPEDEF_ENUM_PKG 2 | `define TYPEDEF_ENUM_PKG 3 | 4 | // 8 bits for alu mode, MSB bit says if operations is signed or not 5 | package typedef_pkg; 6 | typedef enum logic [8:0] {// add sub 7 | add_op=9'b110000000, sub_op=9'b110000011, 8 | addu_op=9'b000000000, subu_op=9'b000000011, 9 | // logic operations 10 | xor_op=9'b000000100,xnor_op=9'b000000101, and_op=9'b000001100, nand_op=9'b000001110, 11 | or_op=9'b000011100, nor_op=9'b000011110, andnot_op=9'b000001111, ornot_op=9'b000011111, 12 | // Compare operations, output is one bit LSB 13 | slt_op=9'b110100000, sgt_op=9'b110100001, seq_op=9'b110100010, sle_op=9'b110100101, 14 | sltu_op=9'b000100011, sgtu_op=9'b000100100, sleu_op=9'b000100101, sneq_op=9'b000100110, 15 | 16 | // Multiply operations 17 | mul_op=9'b111010000, mulhu_op=9'b001011000, mulu_op=9'b001010000, mulh_op=9'b111011000, mulhsu_op=9'b101011000, mulsu_op=9'b101010000, 18 | mul_add_op=9'b111000000, mul_acc_op=9'b111000100, mul_subacc_op=9'b111000111, mulu_add_op=9'b001000000, 19 | mulus_add_op=9'b011000000, mulsu_add_op=9'b101000000, mul_sub_op=9'b111000011, 20 | 21 | // Shifts 22 | sll_op=9'b01100000, srl_op=9'b01100001, sra_op=9'b11100010, nsrl_op=9'b01100011, 23 | nsra_op=9'b11100100 24 | } alu_op; 25 | 26 | /* -----\/----- EXCLUDED -----\/----- 27 | typedef enum logic [11:0] {OPMVV_101xxx_rdy=0, OPMVX_101xxx_rdy=1, 28 | STORE_IDX_rdy=2,STORE_rdy=3, LOAD_IDX_rdy=4, 29 | LOAD_rdy=5, OPMVV_rdy=6, OPMVX_rdy=7, 30 | OPIVV_rdy=8, OPIVI_rdy=9, OPIVX_rdy=10} instruction_rdy; 31 | -----/\----- EXCLUDED -----/\----- */ 32 | 33 | typedef enum logic [12:0] {OPMVV_101xxx_vld=13'b0000000000001, OPMVX_101xxx_vld=13'b0000000000010, 34 | STORE_IDX_vld=13'b0000000000100,STORE_vld=13'b0000000001000, LOAD_IDX_vld=13'b0000000010000, 35 | LOAD_vld=13'b0000000100000, OPMVV_vld=13'b0000001000000, OPMVX_vld=13'b0000010000000, 36 | OPIVV_vld=13'b0000100000000, OPIVI_vld=13'b0001000000000, OPIVX_vld=13'b0010000000000, OPCFG_vld= 13'b1000000000000, SLIDE_vld= 13'b0100000000000} instruction_vld; 37 | typedef enum logic [12:0] {OPMVV_101xxx_rdy=13'b0000000000001, OPMVX_101xxx_rdy=13'b0000000000010, 38 | STORE_IDX_rdy=13'b0000000000100,STORE_rdy=13'b0000000001000, LOAD_IDX_rdy=13'b0000000010000, 39 | LOAD_rdy=13'b0000000100000, OPMVV_rdy=13'b0000001000000, OPMVX_rdy=13'b0000010000000, 40 | OPIVV_rdy=13'b0000100000000, OPIVI_rdy=13'b0001000000000, OPIVX_rdy=13'b0010000000000, OPCFG_rdy= 13'b1000000000000, SLIDE_rdy= 13'b0100000000000} instruction_rdy; 41 | 42 | typedef enum logic [6:0] {v_st_opcode=7'b0100111, v_ld_opcode=7'b0000111, 43 | v_arith_opcode=7'b1010111} opcode; 44 | 45 | typedef enum logic [2:0] {OPIVV=3'b000, OPFVV=3'b001, OPMVV=3'b010, OPIVI=3'b011, 46 | OPIVX=3'b100, OPFVF=3'b101, OPMVX=3'b110, OPCFG=3'b111} arith_funct3; 47 | 48 | typedef enum logic [1:0] {unit_stride=2'b00, idx_unordered=2'b01, 49 | strided=2'b10, idx_ordered=2'b11} v_mop; 50 | 51 | endpackage : typedef_pkg 52 | 53 | 54 | 55 | 56 | `endif 57 | -------------------------------------------------------------------------------- /hdl/packages/util_pkg.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | 4 | -- Declarations 5 | package util_pkg is 6 | 7 | type alu_op_t is (and_op,or_op,xor_op,add_op,sub_op,lts_op,ltu_op,sll_op,srl_op,sra_op); 8 | type fwd_a_t is (dont_fwd_a, fwd_a_from_mem, fwd_a_from_wb ); 9 | type fwd_b_t is (dont_fwd_b, fwd_b_from_mem, fwd_b_from_wb ); 10 | function clogb2( depth : natural) return integer; 11 | 12 | end package util_pkg; 13 | 14 | 15 | -- Definitions 16 | package body util_pkg is 17 | 18 | function clogb2( depth : natural) return integer is 19 | variable temp : integer := depth; 20 | variable ret_val : integer := 0; 21 | begin 22 | while temp > 1 loop 23 | ret_val := ret_val + 1; 24 | temp := temp / 2; 25 | end loop; 26 | return ret_val; 27 | end function; 28 | 29 | end package body util_pkg; 30 | -------------------------------------------------------------------------------- /hdl/riscv-v/README.md: -------------------------------------------------------------------------------- 1 | # RISCV-V -------------------------------------------------------------------------------- /hdl/riscv-v/rtl/riscv_v.sv: -------------------------------------------------------------------------------- 1 | module riscv_v # 2 | ( 3 | parameter integer C_M_AXI_ADDR_WIDTH = 32, 4 | parameter integer C_M_AXI_DATA_WIDTH = 32, 5 | parameter integer C_XFER_SIZE_WIDTH = 32, 6 | parameter VLEN=4096, 7 | parameter V_LANES=4, 8 | parameter CHAINING=4) 9 | ( 10 | input clk, 11 | input clk2, 12 | input ce, 13 | input rstn, 14 | // Scalar core interface 15 | output fencei_o, 16 | input instr_ready_i, 17 | input data_ready_i, 18 | output [31:0] pc_reg_o, 19 | 20 | // Instruction memory interface 21 | output [31:0] instr_mem_address_o, 22 | input [31:0] instr_mem_read_i, 23 | // Scalar Data memory interface 24 | output [31:0] data_mem_address_o, 25 | input [31:0] data_mem_read_i, 26 | output [31:0] data_mem_write_o, 27 | output [3:0] data_mem_we_o, 28 | output data_mem_re_o, 29 | // MCU <=> AXIM CONTROL IF [read channel] 30 | output [C_M_AXI_ADDR_WIDTH-1:0] ctrl_raddr_offset_o, 31 | output [C_XFER_SIZE_WIDTH-1:0] ctrl_rxfer_size_o, 32 | output ctrl_rstart_o, 33 | input ctrl_rdone_i , 34 | input [C_M_AXI_DATA_WIDTH-1:0] rd_tdata_i , 35 | input rd_tvalid_i , 36 | output rd_tready_o, 37 | input rd_tlast_i , 38 | // MCU <=> AXIM CONTROL IF [write channel] 39 | output [C_M_AXI_ADDR_WIDTH-1:0] ctrl_waddr_offset_o , 40 | output [C_XFER_SIZE_WIDTH-1:0] ctrl_wxfer_size_o , 41 | output ctrl_wstart_o , 42 | input ctrl_wdone_i , 43 | output [C_M_AXI_DATA_WIDTH-1:0] wr_tdata_o , 44 | output wr_tvalid_o , 45 | input wr_tready_i , 46 | output ctrl_wstrb_msk_en_o, 47 | output [3 : 0] wr_tstrb_msk_o // ALEKSA HAS CHANGED THIS 48 | ); 49 | 50 | 51 | //---------------------------- VECTOR CORE INTERFACE--------------------------- 52 | // Vector core status signals 53 | logic all_v_stores_executed=1'b1; 54 | logic all_v_loads_executed=1'b1; 55 | logic vector_stall; 56 | // Signals going to M_CU inside vector core 57 | logic scalar_load_req; 58 | logic scalar_store_req; 59 | 60 | // Values of rs1 and rs2 from register bank going to Vector core 61 | logic [31:0] v_instruction; 62 | logic [31:0] rs1; 63 | logic [31:0] rs2; 64 | 65 | scalar_core scalar_core_inst 66 | ( 67 | .clk ( clk), 68 | .ce ( ce), 69 | .reset ( rstn), 70 | //instruction if 71 | .instr_ready_i ( instr_ready_i), 72 | .fencei_o (fencei_o), 73 | .instr_mem_address_o ( instr_mem_address_o), 74 | .pc_reg_o (pc_reg_o), 75 | .instr_mem_read_i ( instr_mem_read_i), 76 | // Vector if 77 | .all_v_stores_executed_i ( all_v_stores_executed), 78 | .all_v_loads_executed_i ( all_v_loads_executed), 79 | .vector_stall_i ( vector_stall), 80 | .scalar_load_req_o ( scalar_load_req), 81 | .scalar_store_req_o ( scalar_store_req), 82 | .v_instruction_o ( v_instruction), 83 | .rs1_o ( rs1), 84 | .rs2_o ( rs2), 85 | //data if 86 | .data_ready_i ( data_ready_i), 87 | .data_mem_address_o ( data_mem_address_o), 88 | .data_mem_read_i ( data_mem_read_i), 89 | .data_mem_write_o ( data_mem_write_o), 90 | .data_mem_we_o ( data_mem_we_o), 91 | .data_mem_re_o ( data_mem_re_o)); 92 | 93 | vector_core # 94 | (.VLEN (VLEN), 95 | .VLANE_NUM (V_LANES)) 96 | vector_core_inst 97 | (/*AUTO_INST*/ 98 | // Outputs 99 | .ctrl_raddr_offset_o (ctrl_raddr_offset_o[C_M_AXI_ADDR_WIDTH-1:0]), 100 | .ctrl_rxfer_size_o (ctrl_rxfer_size_o[C_XFER_SIZE_WIDTH-1:0]), 101 | .ctrl_rstart_o (ctrl_rstart_o), 102 | .rd_tready_o (rd_tready_o), 103 | .ctrl_waddr_offset_o (ctrl_waddr_offset_o[C_M_AXI_ADDR_WIDTH-1:0]), 104 | .ctrl_wxfer_size_o (ctrl_wxfer_size_o[C_XFER_SIZE_WIDTH-1:0]), 105 | .ctrl_wstart_o (ctrl_wstart_o), 106 | .ctrl_wstrb_msk_en_o (ctrl_wstrb_msk_en_o), 107 | .wr_tstrb_msk_o (wr_tstrb_msk_o), 108 | .wr_tdata_o (wr_tdata_o[C_M_AXI_DATA_WIDTH-1:0]), 109 | .wr_tvalid_o (wr_tvalid_o), 110 | // Inputs 111 | .clk (clk), 112 | .clk2 (clk2), 113 | .rstn (rstn), 114 | .ctrl_rdone_i (ctrl_rdone_i), 115 | .rd_tdata_i (rd_tdata_i[C_M_AXI_DATA_WIDTH-1:0]), 116 | .rd_tvalid_i (rd_tvalid_i), 117 | .rd_tlast_i (rd_tlast_i), 118 | .ctrl_wdone_i (ctrl_wdone_i), 119 | .wr_tready_i (wr_tready_i), 120 | //scheduler i/o 121 | .rs1_i (rs1[31:0]), 122 | .rs2_i (rs2[31:0]), 123 | .vector_instr_i (v_instruction[31:0]), 124 | .vector_stall_o (vector_stall)); 125 | 126 | 127 | 128 | 129 | endmodule 130 | 131 | // Local Variables: 132 | // verilog-library-extensions:(".v" ".sv" "_stub.v" "_bb.v") 133 | // verilog-library-directories:("." "../../../../common/" "../vector_core/rtl") 134 | // End: 135 | -------------------------------------------------------------------------------- /hdl/riscv-v/scalar_core/rtl/ALU.vhd: -------------------------------------------------------------------------------- 1 | LIBRARY ieee; 2 | USE ieee.std_logic_1164.ALL; 3 | USE ieee.numeric_std.ALL; 4 | use ieee.math_real.all; 5 | use work.util_pkg.all; 6 | 7 | 8 | ENTITY ALU IS 9 | GENERIC( 10 | WIDTH : NATURAL := 32); 11 | PORT( 12 | a_i : in STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0); --first input 13 | b_i : in STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0); --second input 14 | op_i : in alu_op_t; --operation select 15 | res_o : out STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0)); --result 16 | --zero_o : out STD_LOGIC; --zero flag 17 | --of_o : out STD_LOGIC; --overflow flag 18 | END ALU; 19 | 20 | ARCHITECTURE behavioral OF ALU IS 21 | 22 | constant l2WIDTH : natural := integer(ceil(log2(real(WIDTH)))); 23 | signal lts_res,ltu_res,add_res,sub_res,or_res,and_res,res_s,xor_res : STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0); 24 | signal eq_res,sll_res,srl_res,sra_res : STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0); 25 | --signal divu_res,divs_res,rems_res,remu_res : STD_LOGIC_VECTOR(WIDTH-1 DOWNTO 0); 26 | --signal muls_res,mulu_res : STD_LOGIC_VECTOR(2*WIDTH-1 DOWNTO 0); 27 | --signal mulsu_res : STD_LOGIC_VECTOR(2*WIDTH+1 DOWNTO 0); 28 | 29 | 30 | BEGIN 31 | 32 | -- addition 33 | add_res <= std_logic_vector(unsigned(a_i) + unsigned(b_i)); 34 | -- subtraction 35 | sub_res <= std_logic_vector(unsigned(a_i) - unsigned(b_i)); 36 | -- and gate 37 | and_res <= a_i and b_i; 38 | -- or gate 39 | or_res <= a_i or b_i; 40 | -- xor gate 41 | xor_res <= a_i xor b_i; 42 | -- equal 43 | --eq_res <= std_logic_vector(to_unsigned(1,WIDTH)) when (signed(a_i) = signed(b_i)) else 44 | --std_logic_vector(to_unsigned(0,WIDTH)); 45 | -- less then signed 46 | lts_res <= std_logic_vector(to_unsigned(1,WIDTH)) when (signed(a_i) < signed(b_i)) else 47 | std_logic_vector(to_unsigned(0,WIDTH)); 48 | -- less then unsigned 49 | ltu_res <= std_logic_vector(to_unsigned(1,WIDTH)) when (unsigned(a_i) < unsigned(b_i)) else 50 | std_logic_vector(to_unsigned(0,WIDTH)); 51 | --shift results 52 | sll_res <= std_logic_vector(shift_left(unsigned(a_i), to_integer(unsigned(b_i(l2WIDTH downto 0))))); 53 | srl_res <= std_logic_vector(shift_right(unsigned(a_i), to_integer(unsigned(b_i(l2WIDTH downto 0))))); 54 | sra_res <= std_logic_vector(shift_right(signed(a_i), to_integer(unsigned(b_i(l2WIDTH downto 0))))); 55 | --multiplication 56 | --muls_res <= std_logic_vector(signed(a_i)*signed(b_i)); 57 | --mulsu_res <= std_logic_vector(signed(a_i(WIDTH-1) & a_i)*signed('0' & b_i)); 58 | --mulu_res <= std_logic_vector(unsigned(a_i)*unsigned(b_i)); 59 | --division 60 | --divs_res <= std_logic_vector(signed(a_i)/signed(b_i)) when b_i /= std_logic_vector(to_unsigned(0,WIDTH)) else 61 | -- (others => '1'); 62 | --divu_res <= std_logic_vector(unsigned(a_i)/unsigned(b_i)) when b_i /= std_logic_vector(to_unsigned(0,WIDTH)) else 63 | -- (others => '1'); 64 | --mode 65 | --rems_res <= std_logic_vector(signed(a_i) rem signed(b_i)) when b_i /= std_logic_vector(to_unsigned(0,WIDTH)) else 66 | -- (others => '1'); 67 | --remu_res <= std_logic_vector(unsigned(a_i) rem unsigned(b_i)) when b_i /= std_logic_vector(to_unsigned(0,WIDTH)) else 68 | -- (others => '1'); 69 | 70 | -- SELECT RESULT 71 | res_o <= res_s; 72 | with op_i select 73 | res_s <= and_res when and_op, --and 74 | or_res when or_op, --or 75 | xor_res when xor_op, --xor 76 | add_res when add_op, --add (changed opcode) 77 | sub_res when sub_op, --sub 78 | --eq_res when eq_op, -- set equal 79 | lts_res when lts_op, -- set less than signed 80 | ltu_res when ltu_op, -- set less than unsigned 81 | sll_res when sll_op, -- shift left logic 82 | srl_res when srl_op, -- shift right logic 83 | sra_res when sra_op, -- shift right arithmetic 84 | --mulu_res(WIDTH-1 downto 0) when mulu_op, -- multiply lower 85 | --muls_res(2*WIDTH-1 downto WIDTH) when mulhs_op, -- multiply higher signed 86 | --mulsu_res(2*WIDTH-1 downto WIDTH) when mulhsu_op, -- multiply higher signed and unsigned 87 | --mulu_res(2*WIDTH-1 downto WIDTH) when mulhu_op, -- multiply higher unsigned 88 | --divu_res when divu_op, -- divide unsigned 89 | --divs_res when divs_op, -- divide signed 90 | --remu_res when remu_op, -- reminder signed 91 | --rems_res when rems_op, -- reminder signed 92 | (others => '1') when others; 93 | 94 | 95 | -- flag outputs 96 | -- set zero output flag when result is zero 97 | --zero_o <= '1' when res_s = std_logic_vector(to_unsigned(0,WIDTH)) else 98 | --'0'; 99 | -- overflow happens when inputs have same sign, and output has different 100 | --of_o <= '1' when ((op_i=add_op and (a_i(WIDTH-1)=b_i(WIDTH-1)) and ((a_i(WIDTH-1) xor res_s(WIDTH-1))='1')) or (op_i=sub_op and (a_i(WIDTH-1)=res_s(WIDTH-1)) and ((a_i(WIDTH-1) xor b_i(WIDTH-1))='1'))) else '0'; 101 | 102 | 103 | END behavioral; 104 | -------------------------------------------------------------------------------- /hdl/riscv-v/scalar_core/rtl/TOP_RISCV.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | use ieee.numeric_std.all; 4 | use work.util_pkg.all; 5 | 6 | entity scalar_core is 7 | port( 8 | -- Synchronization ports 9 | clk : in std_logic; 10 | ce : in std_logic; 11 | reset : in std_logic; 12 | instr_ready_i : in std_logic; 13 | data_ready_i : in std_logic; 14 | fencei_o : out std_logic; 15 | pc_reg_o : out std_logic_vector(31 downto 0); 16 | -- Instruction memory interface 17 | instr_mem_address_o : out std_logic_vector(31 downto 0); 18 | instr_mem_read_i : in std_logic_vector(31 downto 0); 19 | 20 | --instr_mem_flush_o : out std_logic; 21 | --instr_mem_en_o : out std_logic; 22 | 23 | ---------------------------- VECTOR CORE INTERFACE--------------------------- 24 | -- Vector core status signals 25 | all_v_stores_executed_i : in std_logic; 26 | all_v_loads_executed_i : in std_logic; 27 | vector_stall_i : in std_logic; 28 | -- Signals going to M_CU inside vector core 29 | scalar_load_req_o : out std_logic; 30 | scalar_store_req_o : out std_logic; 31 | 32 | -- Values of rs1 and rs2 from register bank going to Vector core 33 | v_instruction_o : out std_logic_vector(31 downto 0); 34 | rs1_o : out std_logic_vector(31 downto 0); 35 | rs2_o : out std_logic_vector(31 downto 0); 36 | -------------------------------------------------------------------------------------------- 37 | 38 | 39 | -- Data memory interface 40 | data_mem_address_o : out std_logic_vector(31 downto 0); 41 | data_mem_read_i : in std_logic_vector(31 downto 0); 42 | data_mem_write_o : out std_logic_vector(31 downto 0); 43 | data_mem_we_o : out std_logic_vector(3 downto 0); 44 | data_mem_re_o : out std_logic); 45 | end entity; 46 | 47 | architecture structural of scalar_core is 48 | 49 | signal set_a_zero_s : std_logic; 50 | signal mem_to_reg_s : std_logic_vector(1 downto 0); 51 | signal load_type_s : std_logic_vector(2 downto 0); 52 | signal alu_op_s : alu_op_t; 53 | signal alu_src_b_s : std_logic; 54 | signal alu_src_a_s : std_logic; 55 | signal rd_we_s : std_logic; 56 | signal pc_next_sel_s : std_logic; 57 | 58 | signal if_id_flush_s : std_logic; 59 | signal id_ex_flush_s : std_logic; 60 | 61 | signal alu_forward_a_s : fwd_a_t; 62 | signal alu_forward_b_s : fwd_b_t; 63 | signal branch_condition_s : std_logic; 64 | signal branch_op_s : std_logic_vector(1 downto 0); 65 | 66 | signal pc_en_s : std_logic; 67 | signal if_id_en_s : std_logic; 68 | 69 | signal instr_mem_id_s : std_logic_vector(31 downto 0); 70 | signal instr_mem_en_s : std_logic; 71 | begin 72 | -- data_path instance 73 | data_path_1 : entity work.data_path 74 | port map ( 75 | -- global synchronization signals 76 | clk => clk, 77 | ce => ce, 78 | instr_ready_i => instr_ready_i, 79 | data_ready_i => data_ready_i, 80 | reset => reset, 81 | -- operands come from instruction memory 82 | instr_mem_address_o => instr_mem_address_o, 83 | instr_mem_read_i => instr_mem_read_i, 84 | instr_mem_id_o => instr_mem_id_s, 85 | -- interface towards data memory 86 | data_mem_address_o => data_mem_address_o, 87 | data_mem_write_o => data_mem_write_o, 88 | data_mem_read_i => data_mem_read_i, 89 | 90 | -- Vector core interface 91 | v_instruction_o => v_instruction_o, 92 | rs1_o => rs1_o, 93 | rs2_o => rs2_o, 94 | vector_stall_i => vector_stall_i, 95 | -- control signals come from control path 96 | set_a_zero_i => set_a_zero_s, 97 | mem_to_reg_i => mem_to_reg_s, 98 | load_type_i => load_type_s, 99 | alu_op_i => alu_op_s, 100 | alu_src_b_i => alu_src_b_s, 101 | alu_src_a_i => alu_src_a_s, 102 | rd_we_i => rd_we_s, 103 | pc_next_sel_i => pc_next_sel_s, 104 | branch_op_i => branch_op_s, 105 | -- control signals for forwaring 106 | alu_forward_a_i => alu_forward_a_s, 107 | alu_forward_b_i => alu_forward_b_s, 108 | branch_condition_o => branch_condition_s, 109 | -- control signals for flushing 110 | if_id_flush_i => if_id_flush_s, 111 | id_ex_flush_i => id_ex_flush_s, 112 | -- control signals for stalling 113 | pc_reg_o => pc_reg_o, 114 | pc_en_i => pc_en_s, 115 | if_id_en_i => if_id_en_s); 116 | 117 | --flush current instruction 118 | --instr_mem_flush_o <= '1' when (if_id_flush_s = '1' or instr_ready_i = '0') else '0'; 119 | -- stall currnet instruction 120 | instr_mem_en_s <= '0' when (if_id_en_s = '0' or data_ready_i = '0' or vector_stall_i = '1') else '1'; 121 | 122 | 123 | 124 | -- Control_path instance 125 | control_path_1 : entity work.control_path 126 | port map ( 127 | -- global synchronization signals 128 | clk => clk, 129 | ce => ce, 130 | instr_ready_i => instr_ready_i, 131 | data_ready_i => data_ready_i, 132 | reset => reset, 133 | -- Vector core status signals 134 | all_v_stores_executed_i => all_v_stores_executed_i, 135 | all_v_loads_executed_i => all_v_loads_executed_i, 136 | vector_stall_i => vector_stall_i, 137 | -- Vector core control signals 138 | scalar_load_req_o => scalar_load_req_o, 139 | scalar_store_req_o => scalar_store_req_o, 140 | -- instruction is read from memory 141 | instruction_i => instr_mem_id_s, 142 | -- control signals are forwarded to data_path 143 | set_a_zero_o => set_a_zero_s, 144 | mem_to_reg_o => mem_to_reg_s, 145 | load_type_o => load_type_s, 146 | alu_op_o => alu_op_s, 147 | alu_src_b_o => alu_src_b_s, 148 | alu_src_a_o => alu_src_a_s, 149 | rd_we_o => rd_we_s, 150 | pc_next_sel_o => pc_next_sel_s, 151 | branch_op_o => branch_op_s, 152 | -- control signals for forwarding 153 | alu_forward_a_o => alu_forward_a_s, 154 | alu_forward_b_o => alu_forward_b_s, 155 | branch_condition_i => branch_condition_s, 156 | -- control signals for flushing 157 | data_mem_we_o => data_mem_we_o, 158 | if_id_flush_o => if_id_flush_s, 159 | id_ex_flush_o => id_ex_flush_s, 160 | -- control signals for stalling 161 | pc_en_o => pc_en_s, 162 | if_id_en_o => if_id_en_s, 163 | fencei_o => fencei_o, 164 | data_mem_re_o => data_mem_re_o); 165 | 166 | 167 | --instr_mem_flush_o <= if_id_flush_s; 168 | --instr_mem_en_o <= if_id_en_s; 169 | end architecture; 170 | -------------------------------------------------------------------------------- /hdl/riscv-v/scalar_core/rtl/alu_decoder.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | use ieee.numeric_std.all; 4 | use work.util_pkg.all; 5 | 6 | entity alu_decoder is 7 | port ( 8 | -- from data_path 9 | alu_2bit_op_i : in std_logic_vector(1 downto 0); 10 | funct3_i : in std_logic_vector (2 downto 0); 11 | funct7_i : in std_logic_vector (6 downto 0); 12 | -- to data_path 13 | alu_op_o : out alu_op_t); 14 | end entity; 15 | 16 | architecture behavioral of alu_decoder is 17 | signal funct7_5_s : std_logic; 18 | begin 19 | 20 | funct7_5_s <= funct7_i(5); 21 | --finds appropriate alu operation from control_decoder output and funct fields 22 | alu_dec : process(alu_2bit_op_i, funct3_i, funct7_5_s)is 23 | begin 24 | --default 25 | alu_op_o <= add_op; 26 | case alu_2bit_op_i is 27 | when "00" => 28 | alu_op_o <= add_op; 29 | --when "01" => 30 | --case(funct3_i(2 downto 1))is 31 | --when "00" => 32 | --alu_op_o <= eq_op; 33 | --when "10" => 34 | --alu_op_o <= lts_op; 35 | --when others => 36 | --alu_op_o <= ltu_op; 37 | --end case; 38 | when others => 39 | case funct3_i is 40 | when "000" => 41 | alu_op_o <= add_op; 42 | if(alu_2bit_op_i = "10" and funct7_i(5) = '1') then 43 | alu_op_o <= sub_op; 44 | --elsif(funct7_i(0) = '1')then 45 | --alu_op_o <= mulu_op; 46 | end if; 47 | when "001" => 48 | alu_op_o <= sll_op; 49 | --if(alu_2bit_op_i = "10" and funct7_i(0) = '1') then 50 | --alu_op_o <= mulhs_op; 51 | --end if; 52 | when "010" => 53 | alu_op_o <= lts_op; 54 | --if(alu_2bit_op_i = "10" and funct7_i(0) = '1') then 55 | --alu_op_o <= mulhsu_op; 56 | --end if; 57 | when "011" => 58 | alu_op_o <= ltu_op; 59 | --if(alu_2bit_op_i = "10" and funct7_i(0) = '1') then 60 | --alu_op_o <= mulhu_op; 61 | --end if; 62 | when "100" => 63 | alu_op_o <= xor_op; 64 | --if(alu_2bit_op_i = "10" and funct7_i(0) = '1') then 65 | --alu_op_o <= divs_op; 66 | --end if; 67 | when "101" => 68 | alu_op_o <= srl_op; 69 | if(funct7_i(5) = '1')then 70 | alu_op_o <= sra_op; 71 | end if; 72 | --if(alu_2bit_op_i = "10" and funct7_i(0) = '1') then 73 | --alu_op_o <= divu_op; 74 | --end if; 75 | when "110" => 76 | alu_op_o <= or_op; 77 | --if(alu_2bit_op_i = "10" and funct7_i(0) = '1') then 78 | --alu_op_o <= rems_op; 79 | --end if; 80 | when others => 81 | alu_op_o <= and_op; 82 | --if(alu_2bit_op_i = "10" and funct7_i(0) = '1') then 83 | --alu_op_o <= remu_op; 84 | --end if; 85 | end case; 86 | end case; 87 | end process; 88 | 89 | end architecture; 90 | -------------------------------------------------------------------------------- /hdl/riscv-v/scalar_core/rtl/ctrl_decoder.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | use ieee.numeric_std.all; 4 | 5 | entity ctrl_decoder is 6 | port ( -- from data_path 7 | opcode_i : in std_logic_vector (6 downto 0); 8 | funct3_i : in std_logic_vector(2 downto 0); 9 | -- to data_path 10 | branch_type_o : out std_logic_vector(1 downto 0); 11 | mem_to_reg_o : out std_logic_vector(1 downto 0); 12 | data_mem_we_o : out std_logic; 13 | alu_src_b_o : out std_logic; 14 | alu_src_a_o : out std_logic; 15 | rd_we_o : out std_logic; 16 | set_a_zero_o : out std_logic; 17 | rs1_in_use_o : out std_logic; 18 | rs2_in_use_o : out std_logic; 19 | scalar_load_req_o : out std_logic; 20 | scalar_store_req_o : out std_logic; 21 | vector_instr_o : out std_logic; 22 | fencei_o : out std_logic; 23 | alu_2bit_op_o : out std_logic_vector(1 downto 0) 24 | 25 | ); 26 | end entity; 27 | 28 | architecture behavioral of ctrl_decoder is 29 | begin 30 | 31 | contol_dec : process(opcode_i, funct3_i)is 32 | begin 33 | --default 34 | branch_type_o <= "00"; 35 | mem_to_reg_o <= "00"; 36 | data_mem_we_o <= '0'; 37 | alu_src_b_o <= '0'; 38 | alu_src_a_o <= '0'; 39 | rd_we_o <= '0'; 40 | alu_2bit_op_o <= "00"; 41 | set_a_zero_o <= '0'; 42 | rs1_in_use_o <= '0'; 43 | rs2_in_use_o <= '0'; 44 | scalar_load_req_o <= '0'; 45 | scalar_store_req_o <= '0'; 46 | vector_instr_o <= '0'; 47 | fencei_o <= '0'; 48 | case opcode_i is 49 | when "0000011" => --LOAD 50 | mem_to_reg_o <= "10"; 51 | alu_src_b_o <= '1'; 52 | rd_we_o <= '1'; 53 | rs1_in_use_o <= '1'; 54 | scalar_load_req_o <= '1'; 55 | when "0100011" => --STORE 56 | data_mem_we_o <= '1'; 57 | alu_src_b_o <= '1'; 58 | rs1_in_use_o <= '1'; 59 | rs2_in_use_o <= '1'; 60 | scalar_store_req_o <= '1'; 61 | when "0110011" => --R type 62 | alu_2bit_op_o <= "10"; 63 | rd_we_o <= '1'; 64 | rs1_in_use_o <= '1'; 65 | rs2_in_use_o <= '1'; 66 | when "0010011" => --I type 67 | alu_2bit_op_o <= "11"; 68 | alu_src_b_o <= '1'; 69 | rd_we_o <= '1'; 70 | rs1_in_use_o <= '1'; 71 | when "1100011" => --B type 72 | alu_2bit_op_o <= "00"; 73 | alu_src_a_o <= '1'; 74 | alu_src_b_o <= '1'; 75 | branch_type_o <= "01"; 76 | rs1_in_use_o <= '1'; 77 | rs2_in_use_o <= '1'; 78 | when "1101111" => -- JAL 79 | rd_we_o <= '1'; 80 | alu_src_a_o <= '1'; 81 | alu_src_b_o <= '1'; 82 | mem_to_reg_o <= "01"; 83 | branch_type_o <= "10"; 84 | when "1100111" => -- JALR 85 | rs1_in_use_o <= '1'; 86 | mem_to_reg_o <= "01"; 87 | rd_we_o <= '1'; 88 | alu_src_b_o <= '1'; 89 | branch_type_o <= "11"; 90 | when "0010111" => -- AUIPC 91 | rd_we_o <= '1'; 92 | alu_src_b_o <= '1'; 93 | alu_src_a_o <= '1'; 94 | when "0110111" => -- LUI 95 | set_a_zero_o <= '1'; 96 | rd_we_o <= '1'; 97 | alu_src_b_o <= '1'; 98 | when "0000111" => -- vector load 99 | vector_instr_o <= '1'; 100 | rs1_in_use_o <= '1'; 101 | rs2_in_use_o <= '1'; 102 | when "0100111" => -- vector store 103 | vector_instr_o <= '1'; 104 | rs1_in_use_o <= '1'; 105 | rs2_in_use_o <= '1'; 106 | when "1010111" => -- vector arith 107 | vector_instr_o <= '1'; 108 | case funct3_i is 109 | when "100"=> 110 | rs1_in_use_o <= '1'; 111 | when "111"=> 112 | rs1_in_use_o <= '1'; 113 | when others => 114 | end case; 115 | when "0001111" => --FENCE.I 116 | fencei_o <= '1'; 117 | when others => 118 | end case; 119 | end process; 120 | 121 | end architecture; 122 | 123 | -------------------------------------------------------------------------------- /hdl/riscv-v/scalar_core/rtl/forwarding_unit.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | use ieee.numeric_std.all; 4 | use work.util_pkg.all; 5 | 6 | 7 | entity forwarding_unit is 8 | port ( 9 | -- mem inputs 10 | rd_we_mem_i : in std_logic; 11 | rd_address_mem_i : in std_logic_vector(4 downto 0); 12 | -- wb inputs 13 | rd_we_wb_i : in std_logic; 14 | rd_address_wb_i : in std_logic_vector(4 downto 0); 15 | -- forward control outputs 16 | alu_forward_a_o : out fwd_a_t; 17 | alu_forward_b_o : out fwd_b_t; 18 | -- ex inputs 19 | rs1_address_ex_i : in std_logic_vector(4 downto 0); 20 | rs2_address_ex_i : in std_logic_vector(4 downto 0)); 21 | end entity; 22 | 23 | architecture Behavioral of forwarding_unit is 24 | --constant zero_c : std_logic_vector (4 downto 0) := std_logic_vector(to_unsigned(0, 5)); 25 | begin 26 | 27 | --process that checks whether forwarding for instructions in EX stage is needed or not. 28 | -- forwarding from MEM stage has advantage over forwading information from WB 29 | -- stage, because information contained there is more recent than in WB. 30 | forward_proc : process(rd_we_mem_i, rd_address_mem_i, rd_we_wb_i, rd_address_wb_i,rs1_address_ex_i, rs2_address_ex_i)is 31 | begin 32 | alu_forward_a_o <= dont_fwd_a; 33 | alu_forward_b_o <= dont_fwd_b; 34 | -- forwarding from WB stage 35 | if (rd_we_wb_i = '1' )then -- and rd_address_wb_i /= zero_c 36 | if (rd_address_wb_i = rs1_address_ex_i)then 37 | alu_forward_a_o <= fwd_a_from_wb; 38 | end if; 39 | if(rd_address_wb_i = rs2_address_ex_i)then 40 | alu_forward_b_o <= fwd_b_from_wb; 41 | end if; 42 | end if; 43 | -- forwarding from MEM stage 44 | if (rd_we_mem_i = '1' )then -- and rd_address_mem_i /= zero_c 45 | if (rd_address_mem_i = rs1_address_ex_i)then 46 | alu_forward_a_o <= fwd_a_from_mem; 47 | end if; 48 | if (rd_address_mem_i = rs2_address_ex_i)then 49 | alu_forward_b_o <= fwd_b_from_mem; 50 | end if; 51 | end if; 52 | end process; 53 | 54 | 55 | end architecture; 56 | -------------------------------------------------------------------------------- /hdl/riscv-v/scalar_core/rtl/hazard_unit.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | use ieee.numeric_std.all; 4 | 5 | entity hazard_unit is 6 | port ( 7 | -- inputs 8 | rs1_address_id_i : in std_logic_vector(4 downto 0); 9 | rs2_address_id_i : in std_logic_vector(4 downto 0); 10 | rs1_in_use_i : in std_logic; 11 | rs2_in_use_i : in std_logic; 12 | rd_address_ex_i : in std_logic_vector(4 downto 0); 13 | mem_to_reg_ex_i : in std_logic_vector(1 downto 0); 14 | scalar_load_req_i: in std_logic; 15 | scalar_store_req_i: in std_logic; 16 | --Vector core status signals 17 | all_v_stores_executed_i:in std_logic; 18 | all_v_loads_executed_i:in std_logic; 19 | vector_stall_i : in std_logic; 20 | vector_instr_i: in std_logic; 21 | -- control outputs 22 | pc_en_o : out std_logic; 23 | if_id_en_o : out std_logic; 24 | control_pass_o : out std_logic 25 | ); 26 | end entity; 27 | 28 | 29 | architecture behavioral of hazard_unit is 30 | signal en_s : std_logic := '0'; 31 | begin 32 | 33 | -- stalls pipeline when hazard is detected by setting enable signals to zero 34 | hazard_det: process (rs1_address_id_i, rs2_address_id_i, rd_address_ex_i, 35 | mem_to_reg_ex_i, rs1_in_use_i, rs2_in_use_i, scalar_load_req_i, scalar_store_req_i, 36 | all_v_loads_executed_i, all_v_stores_executed_i, vector_stall_i, vector_instr_i) is 37 | begin 38 | -- Load in ex.st. 39 | -- Its loading the value that is used in the next instruction (id.st.) 40 | -- => stall the pipeline 41 | if(((rs1_address_id_i = rd_address_ex_i and rs1_in_use_i = '1') or 42 | (rs2_address_id_i = rd_address_ex_i and rs2_in_use_i = '1')) and 43 | mem_to_reg_ex_i = "10") then 44 | en_s <= '0'; 45 | elsif ((scalar_load_req_i = '1' and not(all_v_stores_executed_i) = '1') or 46 | (scalar_store_req_i = '1' and (not(all_v_stores_executed_i) = '1' or not(all_v_loads_executed_i ) = '1'))) then 47 | -- defualt, dont do anything 48 | en_s <= '0'; 49 | elsif (vector_stall_i = '1' and vector_instr_i = '1') then --we are_checking_ex_phase_instr 50 | en_s <= '0'; 51 | else 52 | en_s <= '1'; 53 | end if; 54 | end process; 55 | 56 | -- if '0' stalls pc register 57 | pc_en_o <= en_s; 58 | -- if '0' stalls if/id register and instruction memory 59 | if_id_en_o <= en_s; 60 | -- when pipeline needs to stall this output if set to '0' 61 | -- flushes control signals in ID/EX stage to stop them from changing anything 62 | control_pass_o <= en_s; 63 | 64 | end architecture; 65 | -------------------------------------------------------------------------------- /hdl/riscv-v/scalar_core/rtl/immediate.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | use ieee.numeric_std.all; 4 | 5 | 6 | entity immediate is 7 | port (instruction_i : in std_logic_vector (31 downto 0); 8 | immediate_extended_o : out std_logic_vector (31 downto 0)); 9 | end entity; 10 | 11 | 12 | architecture Behavioral of immediate is 13 | signal opcode : std_logic_vector(6 downto 0); 14 | signal instruction_type : std_logic_vector(2 downto 0); 15 | signal funct3 : std_logic_vector(2 downto 0); 16 | signal extension : std_logic_vector(19 downto 0); 17 | 18 | constant r_type_instruction : std_logic_vector(2 downto 0) := "000"; 19 | constant i_type_instruction : std_logic_vector(2 downto 0) := "001"; 20 | constant s_type_instruction : std_logic_vector(2 downto 0) := "010"; 21 | constant b_type_instruction : std_logic_vector(2 downto 0) := "011"; 22 | constant u_type_instruction : std_logic_vector(2 downto 0) := "100"; 23 | constant j_type_instruction : std_logic_vector(2 downto 0) := "101"; 24 | constant shamt_instruction : std_logic_vector(2 downto 0) := "110"; 25 | constant fence_ecall_ebreak : std_logic_vector(2 downto 0) := "111"; 26 | 27 | begin 28 | 29 | opcode <= instruction_i(6 downto 0); 30 | extension <= (others => instruction_i(31)); 31 | funct3 <= instruction_i(14 downto 12); 32 | 33 | -- based on opcode find instruction type 34 | process (opcode, funct3) is 35 | begin 36 | case opcode(6 downto 2) is 37 | when "01100" => 38 | instruction_type <= r_type_instruction; 39 | when "00000" => 40 | instruction_type <= i_type_instruction; 41 | when "00100" => 42 | if(funct3 = "001" or funct3 = "101") then 43 | instruction_type <= shamt_instruction; 44 | else 45 | instruction_type <= i_type_instruction; 46 | end if; 47 | when "11001" => 48 | instruction_type <= i_type_instruction; 49 | when "01000" => 50 | instruction_type <= s_type_instruction; 51 | when "11000" => 52 | instruction_type <= b_type_instruction; 53 | when "01101" => 54 | instruction_type <= u_type_instruction; 55 | when "00101" => 56 | instruction_type <= u_type_instruction; 57 | when "11011" => 58 | instruction_type <= j_type_instruction; 59 | when others => 60 | instruction_type <= fence_ecall_ebreak; 61 | end case; 62 | end process; 63 | 64 | -- based on instruction type from previous process extend data 65 | process (instruction_i, instruction_type, extension, funct3) is 66 | begin 67 | case instruction_type is 68 | when i_type_instruction => 69 | immediate_extended_o <= extension & instruction_i(31 downto 20); 70 | when shamt_instruction => 71 | immediate_extended_o <= std_logic_vector(to_unsigned(0, 27)) & instruction_i(24 downto 20); 72 | when b_type_instruction => 73 | immediate_extended_o <= extension(18 downto 0) & instruction_i(31) & instruction_i(7) & 74 | instruction_i(30 downto 25) & instruction_i(11 downto 8) & '0'; 75 | when s_type_instruction => 76 | immediate_extended_o <= extension(19 downto 0) & instruction_i(31 downto 25) & instruction_i(11 downto 7); 77 | when u_type_instruction => 78 | immediate_extended_o <= instruction_i(31 downto 12) & std_logic_vector(to_unsigned(0, 12)); 79 | when j_type_instruction => 80 | immediate_extended_o <= extension(10 downto 0) & instruction_i(31) & instruction_i(19 downto 12) & 81 | instruction_i(20) & instruction_i(30 downto 21) & '0'; 82 | when others => 83 | immediate_extended_o <= (others => '0'); 84 | end case; 85 | end process; 86 | end architecture; 87 | 88 | 89 | -------------------------------------------------------------------------------- /hdl/riscv-v/scalar_core/rtl/register_bank.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | use ieee.numeric_std.all; 4 | 5 | 6 | entity register_bank is 7 | generic (WIDTH : positive := 32); 8 | port (clk : in std_logic; 9 | reset : in std_logic; 10 | rs1_address_i : in std_logic_vector(4 downto 0); 11 | rs2_address_i : in std_logic_vector(4 downto 0); 12 | rs1_data_o : out std_logic_vector(WIDTH - 1 downto 0); 13 | rs2_data_o : out std_logic_vector(WIDTH - 1 downto 0); 14 | rd_we_i : in std_logic; 15 | rd_address_i : in std_logic_vector(4 downto 0); 16 | rd_data_i : in std_logic_vector(WIDTH - 1 downto 0)); 17 | 18 | end entity; 19 | 20 | architecture Behavioral of register_bank is 21 | type reg_bank is array (0 to 31) of std_logic_vector(31 downto 0); 22 | signal reg_bank_s : reg_bank; 23 | 24 | --DEBUG LOGIC 25 | signal rs1_data_s:std_logic_vector (31 downto 0); 26 | signal rs2_data_s:std_logic_vector (31 downto 0); 27 | begin 28 | 29 | -- synchronous write, reset 30 | reg_bank_write : process (clk) is 31 | begin 32 | if (falling_edge(clk))then 33 | if (reset = '0')then 34 | reg_bank_s <= (others => (others => '0')); 35 | elsif (rd_we_i = '1') then 36 | reg_bank_s(to_integer(unsigned(rd_address_i))) <= rd_data_i; 37 | end if; 38 | end if; 39 | end process; 40 | 41 | -- asynchronous read (zero-th registe set to zero as per spec) 42 | reg_bank_read : process (rs1_address_i, rs2_address_i, reg_bank_s) is 43 | begin 44 | if(to_integer(unsigned(rs1_address_i)) = 0) then 45 | rs1_data_o <= std_logic_vector(to_unsigned(0, WIDTH)); 46 | else 47 | rs1_data_o <= reg_bank_s(to_integer(unsigned(rs1_address_i))); 48 | end if; 49 | 50 | if(to_integer(unsigned(rs2_address_i)) = 0) then 51 | rs2_data_o <= std_logic_vector(to_unsigned(0, WIDTH)); 52 | else 53 | rs2_data_o <= reg_bank_s(to_integer(unsigned(rs2_address_i))); 54 | end if; 55 | end process; 56 | 57 | 58 | --***********Debug logic*************************** 59 | 60 | rs1_data_s <= reg_bank_s(to_integer(unsigned(rs1_address_i))); 61 | rs2_data_s <= reg_bank_s(to_integer(unsigned(rs2_address_i))); 62 | white_box_inst: entity work.white_box 63 | port map ( 64 | rd_we_i => rd_we_i, 65 | rs1_address_i => rs1_address_i, 66 | rs2_address_i => rs2_address_i, 67 | rs1_data_o => rs1_data_s, 68 | rs2_data_o => rs2_data_s, 69 | rd_address_i => rd_address_i, 70 | rd_data_i => rd_data_i, 71 | scalar_reg_bank => reg_bank_s); 72 | 73 | end architecture; 74 | -------------------------------------------------------------------------------- /hdl/riscv-v/scalar_core/rtl/white_box.sv: -------------------------------------------------------------------------------- 1 | //This module enables viewing scalar signals from the outside (Testbench) 2 | 3 | module white_box( 4 | input rd_we_i, 5 | input [4:0 ] rs1_address_i, 6 | input [4:0] rs2_address_i, 7 | input [31:0] rs1_data_o, 8 | input [31:0] rs2_data_o, 9 | input [4:0] rd_address_i, 10 | input [31:0] rd_data_i, 11 | input [0:31][31:0] scalar_reg_bank 12 | ); 13 | 14 | endmodule 15 | -------------------------------------------------------------------------------- /hdl/riscv-v/tb/README: -------------------------------------------------------------------------------- 1 | # RISCV-V TB -------------------------------------------------------------------------------- /hdl/riscv-v/vector_axif_m_ctrl/rtl/axim_ctrl_counter.sv: -------------------------------------------------------------------------------- 1 | // This is a generated file. Use and modify at your own risk. 2 | // Modified by Djordje Miseljic | e-mail: djordjemiseljic@uns.ac.rs 3 | //////////////////////////////////////////////////////////////////////////////// 4 | 5 | // default_nettype of none prevents implicit wire declaration. 6 | `default_nettype none 7 | 8 | module axim_ctrl_counter #( 9 | parameter integer C_WIDTH = 4, 10 | parameter [C_WIDTH-1:0] C_INIT = {C_WIDTH{1'b0}} 11 | ) 12 | ( 13 | input wire clk, 14 | input wire clken, 15 | input wire rst, 16 | input wire load, 17 | input wire incr, 18 | input wire decr, 19 | input wire [C_WIDTH-1:0] load_value, 20 | output wire [C_WIDTH-1:0] count, 21 | output wire is_zero 22 | ); 23 | 24 | ///////////////////////////////////////////////////////////////////////////// 25 | // Local Parameters 26 | ///////////////////////////////////////////////////////////////////////////// 27 | localparam [C_WIDTH-1:0] LP_ZERO = {C_WIDTH{1'b0}}; 28 | localparam [C_WIDTH-1:0] LP_ONE = {{C_WIDTH-1{1'b0}},1'b1}; 29 | localparam [C_WIDTH-1:0] LP_MAX = {C_WIDTH{1'b1}}; 30 | 31 | ///////////////////////////////////////////////////////////////////////////// 32 | // Variables 33 | ///////////////////////////////////////////////////////////////////////////// 34 | reg [C_WIDTH-1:0] count_r = C_INIT; 35 | reg is_zero_r = (C_INIT == LP_ZERO); 36 | 37 | ///////////////////////////////////////////////////////////////////////////// 38 | // Begin RTL 39 | ///////////////////////////////////////////////////////////////////////////// 40 | assign count = count_r; 41 | 42 | always @(posedge clk) begin 43 | if (rst) begin 44 | count_r <= C_INIT; 45 | end 46 | else if (clken) begin 47 | if (load) begin 48 | count_r <= load_value; 49 | end 50 | else if (incr & ~decr) begin 51 | count_r <= count_r + 1'b1; 52 | end 53 | else if (~incr & decr) begin 54 | count_r <= count_r - 1'b1; 55 | end 56 | else 57 | count_r <= count_r; 58 | end 59 | end 60 | 61 | assign is_zero = is_zero_r; 62 | 63 | always @(posedge clk) begin 64 | if (rst) begin 65 | is_zero_r <= (C_INIT == LP_ZERO); 66 | end 67 | else if (clken) begin 68 | if (load) begin 69 | is_zero_r <= (load_value == LP_ZERO); 70 | end 71 | else begin 72 | is_zero_r <= incr ^ decr ? (decr && (count_r == LP_ONE)) || (incr && (count_r == LP_MAX)) : is_zero_r; 73 | end 74 | end 75 | else begin 76 | is_zero_r <= is_zero_r; 77 | end 78 | end 79 | 80 | 81 | endmodule : axim_ctrl_counter 82 | `default_nettype wire 83 | 84 | -------------------------------------------------------------------------------- /hdl/riscv-v/vector_core/README.md: -------------------------------------------------------------------------------- 1 | #Vector Core -------------------------------------------------------------------------------- /hdl/riscv-v/vector_core/mem_subs/m_cu/README.md: -------------------------------------------------------------------------------- 1 | # M_CU (memory control unit) -------------------------------------------------------------------------------- /hdl/riscv-v/vector_core/rtl/vector_core_old.sv: -------------------------------------------------------------------------------- 1 | module vector_core # 2 | (parameter VLEN=4096, 3 | parameter V_LANES=16, 4 | parameter CHAINING=4) 5 | ( 6 | input clk, 7 | input rstn, 8 | 9 | //scalar core interface 10 | input [31:0] rs1_i, 11 | input [31:0] rs2_i, 12 | input [31:0] vector_instr_i, 13 | output vector_stall_o 14 | //data interface 15 | ); 16 | 17 | // Beginning of automatic wires (for undeclared instantiated-module outputs) 18 | logic [10:0] instr_vld; // From scheduler_inst of scheduler.v 19 | logic [31:0] mcu_base_addr; // From scheduler_inst of scheduler.v 20 | logic [2:0] mcu_data_width; // From scheduler_inst of scheduler.v 21 | logic mcu_idx_ld_st; // From scheduler_inst of scheduler.v 22 | logic mcu_ld_vld; // From scheduler_inst of scheduler.v 23 | logic mcu_st_vld; // From scheduler_inst of scheduler.v 24 | logic [31:0] mcu_stride; // From scheduler_inst of scheduler.v 25 | logic mcu_strided_ld_st; // From scheduler_inst of scheduler.v 26 | logic mcu_unit_ld_st; // From scheduler_inst of scheduler.v 27 | logic [31:0] vector_instr; // From scheduler_inst of scheduler.v 28 | 29 | //Scheduler inputs 30 | logic [1:0] sew=2'b0; 31 | logic [10:0] instr_rdy='{default:'1}; 32 | logic mcu_ld_rdy=1'b1; 33 | logic mcu_ld_buffered=1'b1; 34 | logic mcu_st_rdy=1'b1; 35 | 36 | // End of automatics 37 | /*INSTANTIATE SCHEDULER*/ 38 | scheduler scheduler_inst 39 | (/*AUTOINST*/ 40 | // Outputs 41 | .vector_stall_o (vector_stall_o), 42 | .instr_vld_o (instr_vld[10:0]), 43 | .vector_instr_o (vector_instr[31:0]), 44 | .mcu_ld_vld_o (mcu_ld_vld), 45 | .mcu_st_vld_o (mcu_st_vld), 46 | .mcu_base_addr_o (mcu_base_addr[31:0]), 47 | .mcu_stride_o (mcu_stride[31:0]), 48 | .mcu_data_width_o (mcu_data_width[2:0]), 49 | .mcu_idx_ld_st_o (mcu_idx_ld_st), 50 | .mcu_strided_ld_st_o (mcu_strided_ld_st), 51 | .mcu_unit_ld_st_o (mcu_unit_ld_st), 52 | // Inputs 53 | .clk (clk), 54 | .rstn (rstn), 55 | .vector_instr_i (vector_instr_i[31:0]), 56 | .rs1_i (rs1_i[31:0]), 57 | .rs2_i (rs2_i[31:0]), 58 | .sew_i (sew[1:0]), 59 | .instr_rdy_i (instr_rdy[10:0]), 60 | .mcu_ld_rdy_i (mcu_ld_rdy), 61 | .mcu_ld_buffered_i (mcu_ld_buffered), 62 | .mcu_st_rdy_i (mcu_st_rdy)); 63 | /*INSTANTIATE V_CU*/ 64 | 65 | /*INSTANTIATE M_CU*/ 66 | 67 | /*INSTANTIATE V_LANES*/ 68 | 69 | 70 | endmodule 71 | 72 | // Local Variables: 73 | // verilog-library-extensions:(".v" ".sv" "_stub.v" "_bb.v") 74 | // verilog-library-directories:("." "../../common/" "../scheduler/rtl/") 75 | // End: 76 | -------------------------------------------------------------------------------- /hdl/riscv-v/vector_core/scheduler/README.md: -------------------------------------------------------------------------------- 1 | # Scheduler -------------------------------------------------------------------------------- /hdl/riscv-v/vector_core/v_cu/README.md: -------------------------------------------------------------------------------- 1 | #V_CU (vector control unit) -------------------------------------------------------------------------------- /hdl/riscv-v/vector_core/v_cu/README.md~: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nikola2444/RISC-V-vector-processor/e6422101a6209dd723b0501778cc1840ea2f4259/hdl/riscv-v/vector_core/v_cu/README.md~ -------------------------------------------------------------------------------- /hdl/riscv-v/vector_core/v_cu/rtl/Data_validation.sv: -------------------------------------------------------------------------------- 1 | module Data_validation 2 | #( 3 | parameter MAX_VL_PER_LANE = 4 * 8 * 8, 4 | parameter VLANE_NUM = 8 5 | ) 6 | ( 7 | input clk_i, 8 | input rst_i, 9 | 10 | input logic [$clog2(VLANE_NUM * MAX_VL_PER_LANE) - 1 : 0] vl_i, 11 | input logic shift_en_i, 12 | input logic shift_partial_i, 13 | input logic load_i, 14 | 15 | output logic [VLANE_NUM - 1 : 0] valid_o, 16 | output logic partial_results_valid_o 17 | 18 | ); 19 | 20 | ///////////////////////////////////////////////////////////////////////////////////////////////// 21 | // vl_i % VLANE_NUM, vl_i / VLANE_NUM 22 | logic [$clog2(MAX_VL_PER_LANE) - 1 : 0] base_counter, div; 23 | logic [$clog2(VLANE_NUM) - 1 : 0] mod; 24 | logic [VLANE_NUM - 1 : 0] last_valid, last_valid_comb; 25 | logic [VLANE_NUM - 2 : 0] partial_results_reg; 26 | 27 | assign mod = vl_i[$clog2(VLANE_NUM) - 1 : 0]; 28 | assign div = vl_i >> $clog2(VLANE_NUM); 29 | assign partial_results_valid_o = partial_results_reg[0]; 30 | 31 | always_comb begin 32 | last_valid_comb = 0; 33 | for(int i = 0; i < 2 ** $clog2(VLANE_NUM); i++) begin 34 | if(i < mod) begin 35 | last_valid_comb[i] = 1; 36 | end 37 | end 38 | 39 | valid_o = ((base_counter == div) ? last_valid : {VLANE_NUM{1'b1}}) & {VLANE_NUM{shift_en_i}}; 40 | end 41 | 42 | always_ff@(posedge clk_i) begin 43 | if(!rst_i) begin 44 | base_counter <= 0; 45 | last_valid <= 0; 46 | partial_results_reg <= 0; 47 | end 48 | else begin 49 | if(load_i) begin 50 | base_counter <= 0; 51 | last_valid <= last_valid_comb; 52 | 53 | partial_results_reg <= {(VLANE_NUM - 1){1'b1}}; 54 | if(div == 0) begin 55 | partial_results_reg <= last_valid_comb[VLANE_NUM - 1 : 1]; // bit 0 -> LANE 1, bit 1 -> LANE 2, ... 56 | end 57 | end 58 | else if(shift_en_i) begin 59 | if(base_counter == div) begin 60 | if(last_valid != 0) begin 61 | last_valid <= 0; 62 | end 63 | end 64 | else begin 65 | base_counter <= base_counter + 1; 66 | end 67 | end 68 | else if(shift_partial_i) begin 69 | for(int i = 0; i < VLANE_NUM - 2; i++) begin 70 | partial_results_reg[i] <= partial_results_reg[i + 1]; 71 | end 72 | partial_results_reg[VLANE_NUM - 2] <= 0; 73 | end 74 | end 75 | end 76 | 77 | 78 | endmodule 79 | -------------------------------------------------------------------------------- /hdl/riscv-v/vector_core/v_cu/rtl/port_allocate_unit.sv: -------------------------------------------------------------------------------- 1 | module port_allocate_unit# 2 | (parameter R_PORTS_NUM = 8, 3 | parameter W_PORTS_NUM = 4) 4 | ( 5 | input logic clk, 6 | input logic rstn, 7 | 8 | output logic [12:0] instr_rdy_o, 9 | input logic [12:0] instr_vld_i, 10 | input logic vrf_starting_addr_vld_i, 11 | input logic [W_PORTS_NUM-1:0] dependancy_issue_i, 12 | input logic slide_instr_check_i, 13 | output logic [W_PORTS_NUM-1:0] start_o, 14 | input logic [W_PORTS_NUM-1:0] port_rdy_i, 15 | output logic [$clog2(R_PORTS_NUM)-1:0] op3_port_sel_o, 16 | output logic [1:0] store_driver_o, 17 | 18 | 19 | output alloc_port_vld_o 20 | ); 21 | 22 | logic [$clog2(W_PORTS_NUM)-1:0] port_group_to_allocate_reg, port_group_to_allocate_next; 23 | logic [R_PORTS_NUM/2-1:0] r_port_status; 24 | logic [3:0] store_in_progress_reg; 25 | logic [3:0] load_in_progress_reg; 26 | logic [1:0] store_driver_idx; 27 | 28 | 29 | 30 | assign store_driver_idx = store_in_progress_reg == 1 ? 0: 31 | store_in_progress_reg == 2 ? 1: 32 | store_in_progress_reg == 4 ? 2 : 3; 33 | assign store_driver_o = store_driver_idx; 34 | always @(posedge clk) 35 | begin 36 | if (!rstn) 37 | begin 38 | store_in_progress_reg <= 'h0; 39 | end 40 | else 41 | begin 42 | if (alloc_port_vld_o && (instr_vld_i[3:2]!=0 && instr_rdy_o[3:2]!=0)) 43 | begin 44 | store_in_progress_reg <= start_o; 45 | end 46 | else if (port_rdy_i[store_driver_idx]) 47 | store_in_progress_reg <= 'h0; 48 | end 49 | end 50 | 51 | assign load_driver_idx = load_in_progress_reg == 1 ? 0: 52 | load_in_progress_reg == 2 ? 1: 53 | load_in_progress_reg == 4 ? 2 : 3; 54 | always @(posedge clk) 55 | begin 56 | if (!rstn) 57 | begin 58 | load_in_progress_reg <= 'h0; 59 | end 60 | else 61 | begin 62 | if (alloc_port_vld_o && instr_vld_i[5]) 63 | begin 64 | load_in_progress_reg <= start_o; 65 | end 66 | else if (port_rdy_i[load_driver_idx]) 67 | load_in_progress_reg <= 'h0; 68 | end 69 | end 70 | 71 | 72 | 73 | 74 | assign mvv_101xxx_instr_check = instr_vld_i[1]; 75 | 76 | // Sequential logic that updatas register that tells which port group we are using. 77 | always @(posedge clk) 78 | begin 79 | if (!rstn) 80 | begin 81 | port_group_to_allocate_reg <= 'h0; 82 | end 83 | else 84 | begin 85 | if (slide_instr_check_i && port_group_to_allocate_reg!=0) 86 | port_group_to_allocate_reg <= 0; 87 | else if (start_o[port_group_to_allocate_reg]) 88 | port_group_to_allocate_reg <= port_group_to_allocate_next; 89 | else if (port_rdy_i[port_group_to_allocate_reg]!=1) 90 | port_group_to_allocate_reg <= port_group_to_allocate_next; 91 | end 92 | end 93 | 94 | assign port_group_to_allocate_next = port_group_to_allocate_reg + 1; 95 | 96 | always_comb 97 | begin 98 | for (int i=0;i src_path= 17 | 18 | Example: 19 | make run_synth top=find src_path=../../sources/design/find.sv 20 | 21 | 22 | 2) Synthesis of multiple files is done in a similar manner 23 | but a .f file, in which all the files being sythesized 24 | are listed, is needed. 25 | 26 | Example 27 | 28 | make run_synth top=alu src_path=custom_synth.f 29 | 30 | 31 | In .f file, files that are being synthesized need to be 32 | listed like shown below: 33 | 34 | --------------------------F_FILE------------------------- 35 | 36 | ../hdl/riscv-v/vector_core/v_lane/rtl/alu.sv 37 | ../hdl/riscv-v/vector_core/v_lane/rtl/vrf.sv 38 | 39 | 40 | --------------------------F_FILE------------------------- 41 | 42 | 43 | 44 | ----------------------------IMPLEMENTATION-------------------------------- 45 | 46 | Implementation is done in a similar manner but instead 47 | of make run_synth you need to type make run_impl 48 | 49 | EXAMPLE1: Implementation of vector processor design 50 | 51 | make run_impl 52 | 53 | EXAMPLE2: Implementation of a single HDL file 54 | 55 | make run_impl top=find src_path=../../sources/design/find.sv 56 | 57 | EXAMPLE3: Implementation of a multiple HDL files 58 | 59 | make run_impla top=find src_path=custom_synth.f 60 | 61 | 62 | ----------------------------RESULTS--------------------------------------- 63 | Synthesis results will appear in a directory wich has a name of module 64 | being synthesized concataneted to a time stamp. In this directory 65 | 4 kinds of reports will appear: 66 | 67 | -Hierarchy report: resource utilization of each component in 68 | the hierarchy. 69 | -Module report: specifies which components were used to implement 70 | the desing (LUT2, LUT3, LUT4, LUT RAM....) 71 | -Timing_summary_synthesis report: Timing report after synthesis 72 | -Timing_summary_implementation report: Timing report after implementation 73 | 74 | ----------------------------ADVANCED------------------------------------- 75 | Besides top and src_path argumets, make file can also accept: 76 | 77 | 1) frequency: You can set syntesis and implementation frequency 78 | (Default is 250Mhz). Example is showed below: 79 | 80 | make run_synth top=activation_pipe src_path=custom_synth.f frequency=300 81 | 82 | 2) clk_name: This argument needs to be set if clk name of top 83 | module is not "clk" and is lets say ap_clk. Example 84 | is showed bellow. 85 | 86 | make run_synth top=activation_pipe src_path=custom_synth.f clk_name=ap_clk 87 | 88 | 3) clk2_name: This argument needs to be set if module has 2 clocks 89 | .Example is showed bellow. 90 | 91 | make run_synth top=activation_pipe src_path=custom_synth.f clk_name=ap_clk clk2_name=ap_clk_2 92 | 93 | 4) optimize: "yes" or "no" (defaut is "no"). If this is set to yes, 94 | synthesis script reads configuration from impl_opt.tcl 95 | and synth_opt.tcl files, in which you can set what optimization 96 | you want the tool to do during synthesis and during implementation. 97 | Example is shown below 98 | 99 | make run_synth top=activation_pipe src_path=custom_synth.f optimize=yes 100 | 101 | 5) part_name: If you want to synthesize for another board, you need 102 | to set board part (default part_name is "xc7z020clg484-1", which is zedboard). 103 | Example is showed bellow: 104 | 105 | make run_synth top=activation_pipe src_path=custom_synth.f part_name="xc7z020clg484-1" 106 | -------------------------------------------------------------------------------- /synth/impl_opt.tcl: -------------------------------------------------------------------------------- 1 | 2 | if { [string match "yes" $optimize] } { 3 | # TO OPTIMIZE DESITH IMPLEMENTATION ADD LISTED ARGUMENTS TO OPT_DESIGN, 4 | #PLACE_DESYGN, PHYS_OPT_DESIGN AND ROUTE DESIGN, IF NOT EXPERIENCED CHANGE 5 | #ONLY "DIRECTIVE" OPTION 6 | 7 | #********************OPT_DESIGN options******************************************** 8 | opt_design -directive "Explore" 9 | 10 | #You can add one of listed arguments to opt_design. Check UG835 for more information on them 11 | 12 | #Example: 13 | # opt_design "-directive "Explore" \ 14 | # -debug log 15 | 16 | 17 | #-retarget 18 | #-propconst 19 | #-sweep 20 | #-bram_power_opt 21 | #-remap 22 | #-aggressive_remap 23 | #-resynth_area 24 | #-resynth_seq_area 25 | 26 | #posible directives: "Explore", "ExploreArea", "ExploreWithRemap", "ExploreSequentialArea", 27 | # "AddRemap", "NoBramPowerOpt", "RuntimeOptimized", "Default" 28 | #-directive 29 | 30 | #-muxf_remap 31 | #-hier_fanout_limit 32 | #-bufg_opt 33 | #-shift_register_opt 34 | #-dsp_register_opt 35 | #-control_set_merge 36 | #-merge_equivalent_drivers 37 | #-carry_remap 38 | #-debug_log 39 | #-quiet 40 | #-verbose 41 | 42 | 43 | #********************PLACE_DESIGN OPTIONS******************************************** 44 | place_design -directive "ExtraTimingOpt" 45 | # Check UG835 page 1086 for all directive options 46 | #-directive 47 | #-no_timing_driven 48 | #-timing_summary 49 | #-unplace 50 | #-post_place_opt 51 | #-no_fanout_opt 52 | #-no_bufg_opt 53 | #-quiet 54 | #-verbose 55 | 56 | 57 | #********************PHYS_OPT_DESIGN OPTIONS******************************************** 58 | phys_opt_design -directive "AggressiveExplore" 59 | 60 | #-fanout_opt 61 | #-placement_opt 62 | #-routing_opt 63 | #-slr_crossing_opt 64 | #-rewire 65 | #-insert_negative_edge_ffs 66 | #-critical_cell_opt 67 | #-dsp_register_opt 68 | #-bram_register_opt 69 | #-uram_register_opt 70 | #-bram_enable_opt 71 | #-shift_register_opt 72 | #-hold_fix 73 | #-aggressive_hold_fix 74 | #-retime 75 | #-force_replication_on_nets 76 | #-directive 77 | #-critical_pin_opt 78 | #-clock_opt 79 | #-path_groups 80 | #-tns_cleanup 81 | #-sll_reg_hold_fix 82 | #-quiet 83 | #-verbose 84 | 85 | #********************ROUTE_DESIGN OPTIONS******************************************** 86 | route_design -directive "MoreGlobalIterations" 87 | #-unroute 88 | #-release_memory 89 | #-nets #READ UG935 on how to se this 90 | #-physical_nets 91 | #-pins #READ UG935 on how to se this 92 | #-directive # Check UG835 page 1485 for all directive options 93 | #-tns_cleanup 94 | #-no_timing_driven 95 | #-preserve -delay #READ UG935 on how to se this 96 | #-auto_delay -max_delay #READ UG935 on how to se this 97 | #-min_delay 98 | #-timing_summary 99 | #-finalize 100 | #-ultrathreads 101 | #-quiet 102 | #-verbose 103 | 104 | 105 | } 106 | -------------------------------------------------------------------------------- /synth/synth_opt.tcl: -------------------------------------------------------------------------------- 1 | if { [string match "no" $optimize] } { 2 | # DO NOT TOUCH! THESE ARE DEFUALUT CONFIGURATIONS 3 | set flatten_hierarchy "none" 4 | set directive "default" 5 | set bufg "12" 6 | set fanout_limit "10000" 7 | set shreg_min_size "5" 8 | set fsm_extraction "one_hot" 9 | set resource_sharing "off" 10 | set control_set_opt_threshold "auto" 11 | set no_lc "-no_lc" 12 | } else { 13 | #CHANGE THESE IS YOU WANT SYNTHESIS OPTIMIZATION 14 | # CHECK Xilinx UG901 .pdf for more information 15 | 16 | #Possible options: "auto", "rebuilt", "none" 17 | set flatten_hierarchy "rebuilt" 18 | #possible options: "default", "RuntimeOptimized", "AreaOptimized_high", "AreaOptimized_medium", 19 | # "AlternateRoutability", "AreaMapLargeShiftRegToBRAM", "AreaMultThresholdDSP", 20 | # "FewerCarryChains", "PerformanceOptimized" 21 | set directive "PerformanceOptimized" 22 | 23 | set bufg "12" 24 | set fanout_limit "10000" 25 | set shreg_min_size "5" 26 | #Possible options: "one_hot" "sequential", "johnson", "gray", "auto", "none" 27 | set fsm_extraction "one_hot" 28 | 29 | set resource_sharing "auto" 30 | set control_set_opt_threshold "auto" 31 | set no_lc "-no_lc" 32 | } 33 | -------------------------------------------------------------------------------- /verif/AXI4_Agent/AXI4_agent.sv: -------------------------------------------------------------------------------- 1 | class AXI4_agent extends uvm_agent; 2 | 3 | // components 4 | AXI4_driver drv; 5 | 6 | AXI4_monitor mon; 7 | virtual interface axi4_if vif; 8 | // configuration 9 | riscv_v_config cfg; 10 | int value; 11 | `uvm_component_utils_begin ( AXI4_agent) 12 | `uvm_field_object(cfg, UVM_DEFAULT) 13 | `uvm_component_utils_end 14 | 15 | function new(string name = " AXI4_agent", uvm_component parent = null); 16 | super.new(name,parent); 17 | endfunction 18 | 19 | function void build_phase(uvm_phase phase); 20 | super.build_phase(phase); 21 | /************Geting from configuration database*******************/ 22 | if (!uvm_config_db#(virtual axi4_if)::get(this, "", "axi4_if", vif)) 23 | `uvm_fatal("NOVIF",{"virtual interface must be set:",get_full_name(),".vif"}) 24 | 25 | if(!uvm_config_db#(riscv_v_config)::get(this, "", "riscv_v_config", cfg)) 26 | `uvm_fatal("NOCONFIG",{"Config object must be set for: ",get_full_name(),".cfg"}) 27 | 28 | /*****************************************************************/ 29 | 30 | /************Setting to configuration database********************/ 31 | uvm_config_db#(virtual axi4_if)::set(this, "*", "axi4_if", vif); 32 | /*****************************************************************/ 33 | 34 | mon = AXI4_monitor::type_id::create("mon", this); 35 | if(cfg.is_active == UVM_ACTIVE) begin 36 | drv = AXI4_driver::type_id::create("drv", this); 37 | end 38 | endfunction : build_phase 39 | 40 | function void connect_phase(uvm_phase phase); 41 | super.connect_phase(phase); 42 | /* -----\/----- EXCLUDED -----\/----- 43 | if(cfg.is_active == UVM_ACTIVE) begin 44 | drv.seq_item_port.connect(seqr.seq_item_export); 45 | end 46 | -----/\----- EXCLUDED -----/\----- */ 47 | endfunction : connect_phase 48 | 49 | endclass : AXI4_agent 50 | -------------------------------------------------------------------------------- /verif/AXI4_Agent/AXI4_agent_pkg.sv: -------------------------------------------------------------------------------- 1 | `ifndef AXI4_AGENT_PKG 2 | `define AXI4_AGENT_PKG 3 | 4 | 5 | package AXI4_agent_pkg; 6 | 7 | import uvm_pkg::*; 8 | `include "uvm_macros.svh" 9 | 10 | ////////////////////////////////////////////////////////// 11 | // include Agent components : driver,monitor,sequencer 12 | ///////////////////////////////////////////////////////// 13 | import configurations_pkg::*; 14 | 15 | `include "AXI4_seq_item.sv" 16 | `include "AXI4_driver.sv" 17 | `include "AXI4_monitor.sv" 18 | `include "AXI4_agent.sv" 19 | 20 | endpackage 21 | 22 | `endif 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /verif/AXI4_Agent/AXI4_driver.sv: -------------------------------------------------------------------------------- 1 | `ifndef AXI4_DRIVER_SV 2 | `define AXI4_DRIVER_SV 3 | class AXI4_driver extends uvm_driver#(AXI4_seq_item); 4 | 5 | `uvm_component_utils(AXI4_driver) 6 | 7 | //logic [31:0] ddr_mem[4096]; 8 | typedef enum {rd_idle_phase, rd_phase} read_fsm; 9 | read_fsm axi_read_channel = rd_idle_phase; 10 | 11 | typedef enum {wr_idle_phase, wr_phase, resp_phase} write_fsm; 12 | write_fsm axi_write_channel = wr_idle_phase; 13 | 14 | virtual interface axi4_if vif; 15 | function new(string name = "AXI4_driver", uvm_component parent = null); 16 | super.new(name,parent); 17 | endfunction 18 | 19 | function void connect_phase(uvm_phase phase); 20 | super.connect_phase(phase); 21 | if (!uvm_config_db#(virtual axi4_if)::get(this, "", "axi4_if", vif)) 22 | `uvm_fatal("NOVIF",{"virtual interface must be set for: ",get_full_name(),".vif"}) 23 | 24 | 25 | 26 | endfunction : connect_phase 27 | 28 | 29 | task main_phase(uvm_phase phase); 30 | 31 | 32 | forever begin 33 | fork 34 | // Two threads, one for AXI4 read port and the other 35 | // for AXI4 write port. 36 | start_axi4_read_slave(); 37 | start_axi4_write_slave(); 38 | join 39 | end 40 | endtask : main_phase 41 | 42 | 43 | task start_axi4_read_slave (); 44 | int num_of_data_read = 0; 45 | int rd_transfer_base_addr=0; 46 | int read_burst_length=0; 47 | forever begin 48 | @(negedge vif.clk); 49 | case (axi_read_channel) 50 | rd_idle_phase: begin 51 | read_burst_length = vif.burst_len; 52 | vif.m_axi_rlast = 0; 53 | vif.m_axi_arready = 0; 54 | vif.m_axi_rvalid = 0; 55 | if (vif.m_axi_arvalid) begin 56 | axi_read_channel = rd_phase; 57 | vif.m_axi_arready = 1'b1; 58 | rd_transfer_base_addr = vif.m_axi_araddr/4; 59 | //$display("going to rd phase"); 60 | read_burst_length = vif.m_axi_arlen; 61 | end 62 | end 63 | rd_phase: begin 64 | vif.m_axi_arready = 1'b0; 65 | vif.m_axi_rdata = vif.ddr_mem[rd_transfer_base_addr + num_of_data_read]; 66 | //vif.m_axi_rvalid = $random(); 67 | vif.m_axi_rvalid = 1'b1; 68 | if (vif.m_axi_rready && vif.m_axi_rvalid) begin 69 | if ((num_of_data_read+1)%(read_burst_length+1) == 0 && num_of_data_read != 0) begin 70 | axi_read_channel = rd_idle_phase; 71 | vif.m_axi_rlast = 1; 72 | num_of_data_read = 0; 73 | end 74 | else begin 75 | vif.m_axi_rlast = 0; 76 | num_of_data_read++; 77 | end 78 | end 79 | end 80 | endcase 81 | end 82 | endtask // startaxi4_read_slave 83 | 84 | 85 | task start_axi4_write_slave (); 86 | int i = 0; 87 | int wr_transfer_base_addr=0; 88 | int write_burst_length; 89 | forever begin 90 | @(negedge vif.clk); 91 | case (axi_write_channel) 92 | wr_idle_phase: begin 93 | i = 0; 94 | vif.m_axi_bvalid = 0; 95 | write_burst_length = vif.burst_len; 96 | vif.m_axi_awready = 0; 97 | vif.m_axi_wready = 0; 98 | if (vif.m_axi_awvalid) begin 99 | vif.m_axi_awready = 1; 100 | axi_write_channel = wr_phase; 101 | wr_transfer_base_addr = vif.m_axi_awaddr/4; 102 | write_burst_length = vif.m_axi_awlen; 103 | end 104 | end 105 | wr_phase: begin 106 | vif.m_axi_awready = 1'b0; 107 | vif.m_axi_wready = $random(); 108 | if (vif.m_axi_wready && vif.m_axi_wvalid) begin 109 | vif.ddr_mem[wr_transfer_base_addr+i]=vif.m_axi_wdata[31:0]; 110 | i++; 111 | if (vif.m_axi_wlast) 112 | axi_write_channel = resp_phase; 113 | //$display("vif.ddr_mem[%d]=%d",wr_transfer_base_addr+i, vif.ddr_mem[wr_transfer_base_addr+i]); 114 | end 115 | end 116 | resp_phase:begin 117 | vif.m_axi_wready = 1'b0; 118 | //vif.m_axi_bresp = 2'b00; 119 | vif.m_axi_bvalid = 1; 120 | i = 0; 121 | if (vif.m_axi_bready) 122 | axi_write_channel = wr_idle_phase; 123 | end 124 | endcase 125 | end 126 | endtask // startaxi4_read_slave 127 | endclass : AXI4_driver 128 | 129 | `endif 130 | 131 | -------------------------------------------------------------------------------- /verif/AXI4_Agent/AXI4_monitor.sv: -------------------------------------------------------------------------------- 1 | `ifndef AXI4_MONITOR 2 | `define AXI4_MONITOR 3 | class AXI4_monitor extends uvm_monitor; 4 | 5 | // control fileds 6 | bit checks_enable = 1; 7 | bit coverage_enable = 1; 8 | 9 | uvm_analysis_port #(AXI4_seq_item) item_collected_port; 10 | 11 | `uvm_component_utils_begin(AXI4_monitor) 12 | `uvm_field_int(checks_enable, UVM_DEFAULT) 13 | `uvm_field_int(coverage_enable, UVM_DEFAULT) 14 | `uvm_component_utils_end 15 | 16 | // The virtual interface used to drive and view HDL signals. 17 | virtual interface axi4_if vif; 18 | 19 | // current transaction 20 | AXI4_seq_item curr_it; 21 | 22 | // coverage can go here 23 | // ... 24 | 25 | function new(string name = "AXI4_monitor", uvm_component parent = null); 26 | super.new(name,parent); 27 | item_collected_port = new("item_collected_port", this); 28 | endfunction 29 | 30 | function void connect_phase(uvm_phase phase); 31 | super.connect_phase(phase); 32 | if (!uvm_config_db#(virtual axi4_if)::get(this, "", "axi4_if", vif)) 33 | `uvm_fatal("NOVIF",{"virtual interface must be set:",get_full_name(),".vif"}) 34 | endfunction : connect_phase 35 | 36 | task main_phase(uvm_phase phase); 37 | forever begin 38 | @(negedge vif.clk); 39 | // curr_it = AXI4_seq_item::type_id::create("curr_it", this); 40 | // ... 41 | // collect transactions 42 | // ... 43 | // item_collected_port.write(curr_it); 44 | 45 | end 46 | endtask : main_phase 47 | 48 | endclass : AXI4_monitor 49 | `endif 50 | -------------------------------------------------------------------------------- /verif/AXI4_Agent/AXI4_seq_item.sv: -------------------------------------------------------------------------------- 1 | `ifndef AXI4_SEQ_ITEM_SV 2 | `define AXI4_SEQ_ITEM_SV 3 | 4 | parameter DATA_WIDTH = 32; 5 | parameter RESP_WIDTH = 2; 6 | parameter CMD_WIDTH = 4; 7 | 8 | class AXI4_seq_item extends uvm_sequence_item; 9 | 10 | logic [31:0] instruction; 11 | logic [31:0] instruction_addr; 12 | 13 | `uvm_object_utils_begin(AXI4_seq_item) 14 | `uvm_field_int(instruction, UVM_DEFAULT) 15 | `uvm_field_int(instruction_addr, UVM_DEFAULT) 16 | `uvm_object_utils_end 17 | 18 | function new (string name = "AXI4_seq_item"); 19 | super.new(name); 20 | endfunction // new 21 | 22 | endclass : AXI4_seq_item 23 | 24 | `endif 25 | -------------------------------------------------------------------------------- /verif/AXI4_Agent/AXI4_sequencer.sv: -------------------------------------------------------------------------------- 1 | `ifndef BD_INSTR_IF_SEQUENCER_SV 2 | `define BD_INSTR_IF_SEQUENCER_SV 3 | 4 | class bd_instr_if_sequencer extends uvm_sequencer#(AXI4_seq_item); 5 | 6 | `uvm_component_utils(bd_instr_if_sequencer) 7 | 8 | function new(string name = "bd_instr_if_sequencer", uvm_component parent = null); 9 | super.new(name,parent); 10 | endfunction 11 | 12 | endclass : bd_instr_if_sequencer 13 | 14 | `endif 15 | 16 | -------------------------------------------------------------------------------- /verif/Assembly_code/#assembly_test.b#: -------------------------------------------------------------------------------- 1 | 00000010000000011000111100010011 2 | 00000000001100010011001011010111 3 | 00000000001100010000001011010111 4 | 00001000001100010100001011010111 5 | -------------------------------------------------------------------------------- /verif/Assembly_code/assembly_code.b: -------------------------------------------------------------------------------- 1 | 00000000010100000000000100010011 2 | 00000000010000000000000100010011 3 | 11111110001000100000110011100011 4 | -------------------------------------------------------------------------------- /verif/Assembly_code/assembly_test.b: -------------------------------------------------------------------------------- 1 | 00000010000000011000111100010011 2 | 00000000001100010011001011010111 3 | 00000000001100010000001011010111 4 | 00001000001100010100001011010111 5 | -------------------------------------------------------------------------------- /verif/Configurations/config.sv: -------------------------------------------------------------------------------- 1 | class riscv_v_config extends uvm_object; 2 | 3 | uvm_active_passive_enum is_active = UVM_ACTIVE; 4 | int use_s_instr_backdoor = 0; 5 | int use_v_data_backdoor = 0; 6 | int use_s_data_backdoor = 1; 7 | int instr_agent_active = use_s_instr_backdoor; 8 | `uvm_object_utils_begin (riscv_v_config) 9 | `uvm_field_enum(uvm_active_passive_enum, is_active, UVM_DEFAULT) 10 | `uvm_object_utils_end 11 | 12 | function new(string name = "riscv_v_config"); 13 | super.new(name); 14 | endfunction 15 | 16 | endclass : riscv_v_config 17 | -------------------------------------------------------------------------------- /verif/Configurations/configurations_pkg.sv: -------------------------------------------------------------------------------- 1 | `ifndef CONFIGURATION_PKG_SV 2 | `define CONFIGURATION_PKG_SV 3 | 4 | package configurations_pkg; 5 | 6 | import uvm_pkg::*; // import the UVM library 7 | localparam DDR_DEPTH=4096; 8 | typedef logic [31:0] ddr_mem_type[DDR_DEPTH]; 9 | int use_s_instr_backdoor = 1; 10 | int use_v_data_backdoor = 1; 11 | int use_s_data_backdoor = 1; 12 | 13 | `include "uvm_macros.svh" // Include the UVM macros 14 | 15 | `include "config.sv" 16 | 17 | 18 | 19 | endpackage : configurations_pkg 20 | 21 | `endif 22 | 23 | -------------------------------------------------------------------------------- /verif/Sequences/base_seq.sv: -------------------------------------------------------------------------------- 1 | `ifndef RISCV_V_BASE_SEQ_SV 2 | `define RISCV_V_BASE_SEQ_SV 3 | 4 | class riscv_v_base_seq extends uvm_sequence#(bd_instr_if_seq_item); 5 | 6 | `uvm_object_utils(riscv_v_base_seq) 7 | `uvm_declare_p_sequencer(bd_instr_if_sequencer) 8 | 9 | function new(string name = "riscv_v_base_seq"); 10 | super.new(name); 11 | endfunction 12 | 13 | // objections are raised in pre_body 14 | virtual task pre_body(); 15 | uvm_phase phase = get_starting_phase(); 16 | //if (phase != null) 17 | //phase.raise_objection(this, {"Running sequence '", get_full_name(), "'"}); 18 | //uvm_test_done.set_drain_time(this, 100ms); 19 | endtask : pre_body 20 | 21 | // objections are dropped in post_body 22 | virtual task post_body(); 23 | //uvm_phase phase = get_starting_phase(); 24 | //if (phase != null) 25 | //phase.drop_objection(this, {"Completed sequence '", get_full_name(), "'"}); 26 | endtask : post_body 27 | 28 | endclass : riscv_v_base_seq 29 | 30 | `endif 31 | -------------------------------------------------------------------------------- /verif/Sequences/bd_instr_if_seq.sv: -------------------------------------------------------------------------------- 1 | `ifndef RISCV_V_SIMPLE_SEQ_SV 2 | `define RISCV_V_SIMPLE_SEQ_SV 3 | 4 | class riscv_v_simple_seq extends riscv_v_base_seq; 5 | 6 | `uvm_object_utils (riscv_v_simple_seq) 7 | typedef logic [31 : 0] instr_queue[$]; 8 | //string assembly_file_path = "../../../../../../verif/Assembly_code/assembly_test.b"; 9 | string assembly_file_path = "../../../../../../RISCV-GCC-compile-scripts/assembly.dump"; 10 | //string assembly_file_path = "assembly_test.b"; 11 | instr_queue instr_queue_1; 12 | 13 | function new(string name = "riscv_v_simple_seq"); 14 | super.new(name); 15 | endfunction 16 | 17 | virtual task body(); 18 | // Ask for address 19 | //instr_queue_1 = read_instr_from_file (assembly_file_path); 20 | instr_queue_1 = read_instr_from_dump_file (assembly_file_path); 21 | req = bd_instr_if_seq_item::type_id::create("req"); 22 | while(1) 23 | begin 24 | start_item(req); 25 | finish_item(req); 26 | req.instruction=instr_queue_1[req.instruction_addr/4]; 27 | // Send the data 28 | start_item(req); 29 | finish_item(req); 30 | end 31 | endtask : body 32 | 33 | function instr_queue read_instr_from_file (string assembly_file_path); 34 | logic [31:0] instr; 35 | int fd = $fopen (assembly_file_path, "r"); 36 | instr_queue instr_queue_1; 37 | while (!$feof(fd)) begin 38 | $fscanf(fd,"%b\n",instr); 39 | instr_queue_1.push_back(instr); 40 | end 41 | 42 | foreach (instr_queue_1[i]) 43 | `uvm_info(get_type_name(), 44 | $sformatf("instruction[%d]: %b", i, instr_queue_1[i]), 45 | UVM_FULL) 46 | return instr_queue_1; 47 | endfunction // read_instr_from_file 48 | 49 | function instr_queue read_instr_from_dump_file (string assembly_file_path); 50 | logic [31:0] instr; 51 | string instr_string; 52 | int fd = $fopen (assembly_file_path, "r"); 53 | instr_queue instr_queue_1; 54 | while (!$feof(fd)) begin 55 | $fgets(instr_string, fd); 56 | for (int i = 0; i < instr_string.len(); i++) 57 | begin 58 | if (instr_string[i]=="." || instr_string[i]==">") 59 | break; 60 | if (instr_string[i]==":") 61 | begin 62 | $sscanf(instr_string.substr(i, instr_string.len()-1), (": %h "), instr); 63 | instr_queue_1.push_back(instr); 64 | end 65 | end 66 | end 67 | 68 | 69 | foreach (instr_queue_1[i]) 70 | `uvm_info(get_type_name(), 71 | $sformatf("instruction[%d]: %h", i, instr_queue_1[i]), 72 | UVM_FULL) 73 | 74 | return instr_queue_1; 75 | endfunction 76 | endclass : riscv_v_simple_seq 77 | 78 | `endif 79 | -------------------------------------------------------------------------------- /verif/Sequences/riscv_v_seq_pkg.sv: -------------------------------------------------------------------------------- 1 | `ifndef RISCV_V_SEQ_PKG_SV 2 | `define RISCV_V_SEQ_PKG_SV 3 | package riscv_v_seq_pkg; 4 | import uvm_pkg::*; // import the UVM library 5 | `include "uvm_macros.svh" // Include the UVM macros 6 | import bd_instr_if_agent_pkg::bd_instr_if_seq_item; 7 | import bd_instr_if_agent_pkg::bd_instr_if_sequencer; 8 | `include "base_seq.sv" 9 | `include "bd_instr_if_seq.sv" 10 | endpackage 11 | `endif 12 | -------------------------------------------------------------------------------- /verif/axi_if.sv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Nikola2444/RISC-V-vector-processor/e6422101a6209dd723b0501778cc1840ea2f4259/verif/axi_if.sv -------------------------------------------------------------------------------- /verif/backdoor_if.sv: -------------------------------------------------------------------------------- 1 | `ifndef BACKDOOR_INSTR_IF_SV 2 | `define BACKDOOR_INSTR_IF_SV 3 | 4 | interface backdoor_instr_if (input clk, logic rstn); 5 | logic instr_ready; 6 | logic [31:0] instr_mem_address; 7 | logic [31:0] instr_mem_read; 8 | logic instr_mem_flush; 9 | logic instr_mem_en; 10 | endinterface:backdoor_instr_if 11 | 12 | interface backdoor_v_instr_if (input clk, logic rstn); 13 | logic [3:0] start; 14 | logic [3:0] ready; 15 | logic [31:0] v_instruction; 16 | logic [31:0] v_rs1_scalar; 17 | logic [31:0] v_rs2_scalar; 18 | logic [11:0] v_instr_vld; 19 | logic [11:0] v_instr_rdy; 20 | logic [2:0] lmul; 21 | logic [2:0] sew; 22 | logic [31:0] vl; 23 | logic [31:0] vrf_read_ram [`V_LANES][2][4][`VRF_DEPTH-1:0]; 24 | 25 | endinterface:backdoor_v_instr_if 26 | 27 | interface backdoor_register_bank_if (input clk, logic rstn); 28 | logic rd_we_i; 29 | logic [4:0 ] rs1_address_i; 30 | logic [4:0] rs2_address_i; 31 | logic [31:0] rs1_data_o ; 32 | logic [31:0] rs2_data_o; 33 | logic [4:0] rd_address_i; 34 | logic [31:0] rd_data_i; 35 | logic [0:31][31:0] scalar_reg_bank; 36 | endinterface:backdoor_register_bank_if 37 | 38 | interface backdoor_sc_data_if (input clk, logic rstn); 39 | logic data_ready_i; 40 | logic [31:0] data_mem_address_o; 41 | logic [31:0] data_mem_read_i; 42 | logic [31:0] data_mem_write_o; 43 | logic data_mem_we_o; 44 | logic data_mem_re_o; 45 | 46 | endinterface:backdoor_sc_data_if 47 | 48 | interface backdoor_v_data_if (input clk, logic rstn, output reg [31:0] ddr_mem[`DDR_DEPTH]); 49 | logic [31:0] ctrl_raddr_offset_o; 50 | logic [31:0] ctrl_rxfer_size_o; 51 | logic ctrl_rstart_o; 52 | logic rd_tready_o; 53 | logic [31:0] rd_tdata_i; 54 | logic rd_tvalid_i; 55 | logic rd_tlast_i; 56 | logic ctrl_rdone_i; 57 | 58 | logic [31:0] ctrl_waddr_offset_o; 59 | logic [31:0] ctrl_wxfer_size_o; 60 | logic [31:0] wr_tdata_o; 61 | logic ctrl_wstart_o; 62 | logic wr_tvalid_o; 63 | logic wr_tready_i; 64 | logic ctrl_wdone_i; 65 | endinterface:backdoor_v_data_if 66 | 67 | 68 | `endif 69 | -------------------------------------------------------------------------------- /verif/bd_instr_if_Agent/bd_instr_if_agent.sv: -------------------------------------------------------------------------------- 1 | class bd_instr_if_agent extends uvm_agent; 2 | 3 | // components 4 | bd_instr_if_driver drv; 5 | bd_instr_if_sequencer seqr; 6 | bd_instr_if_monitor mon; 7 | 8 | virtual interface backdoor_instr_if backdoor_instr_vif; 9 | virtual interface backdoor_register_bank_if backdoor_register_bank_vif; 10 | virtual interface backdoor_sc_data_if backdoor_sc_data_vif; 11 | // configuration 12 | riscv_v_config cfg; 13 | int value; 14 | `uvm_component_utils_begin (bd_instr_if_agent) 15 | `uvm_field_object(cfg, UVM_DEFAULT) 16 | `uvm_component_utils_end 17 | 18 | function new(string name = "bd_instr_if_agent", uvm_component parent = null); 19 | super.new(name,parent); 20 | endfunction 21 | 22 | function void build_phase(uvm_phase phase); 23 | super.build_phase(phase); 24 | /************Geting from configuration database*******************/ 25 | if (!uvm_config_db#(virtual backdoor_instr_if)::get(this, "", "backdoor_instr_if", backdoor_instr_vif)) 26 | `uvm_fatal("NOVIF",{"virtual interface must be set:",get_full_name(),".vif"}) 27 | if (!uvm_config_db#(virtual backdoor_sc_data_if)::get(this, "", "backdoor_sc_data_if", backdoor_sc_data_vif)) 28 | `uvm_fatal("NOVIF",{"virtual interface must be set:",get_full_name(),".vif"}) 29 | if (!uvm_config_db#(virtual backdoor_register_bank_if)::get(this, "", "backdoor_register_bank_if", backdoor_register_bank_vif)) 30 | `uvm_fatal("NOVIF",{"virtual interface must be set:",get_full_name(),".vif"}) 31 | 32 | if(!uvm_config_db#(riscv_v_config)::get(this, "", "riscv_v_config", cfg)) 33 | `uvm_fatal("NOCONFIG",{"Config object must be set for: ",get_full_name(),".cfg"}) 34 | 35 | /*****************************************************************/ 36 | 37 | /************Setting to configuration database********************/ 38 | uvm_config_db#(virtual backdoor_instr_if)::set(this, "*", "backdoor_instr_if", backdoor_instr_vif); 39 | uvm_config_db#(virtual backdoor_sc_data_if)::set(this, "*", "backdoor_sc_data_if", backdoor_sc_data_vif); 40 | uvm_config_db#(virtual backdoor_register_bank_if)::set(this, "*", "backdoor_register_bank_if", backdoor_register_bank_vif); 41 | /*****************************************************************/ 42 | 43 | mon = bd_instr_if_monitor::type_id::create("mon", this); 44 | if(cfg.instr_agent_active == 1) begin 45 | drv = bd_instr_if_driver::type_id::create("drv", this); 46 | seqr = bd_instr_if_sequencer::type_id::create("seqr", this); 47 | end 48 | endfunction : build_phase 49 | 50 | function void connect_phase(uvm_phase phase); 51 | super.connect_phase(phase); 52 | if(cfg.instr_agent_active == 1) begin 53 | drv.seq_item_port.connect(seqr.seq_item_export); 54 | end 55 | endfunction : connect_phase 56 | 57 | endclass : bd_instr_if_agent 58 | -------------------------------------------------------------------------------- /verif/bd_instr_if_Agent/bd_instr_if_agent_pkg.sv: -------------------------------------------------------------------------------- 1 | `ifndef BD_INSTR_IF_AGENT_PKG 2 | `define BD_INSTR_IF_AGENT_PKG 3 | 4 | package bd_instr_if_agent_pkg; 5 | 6 | import uvm_pkg::*; 7 | `include "uvm_macros.svh" 8 | 9 | ////////////////////////////////////////////////////////// 10 | // include Agent components : driver,monitor,sequencer 11 | ///////////////////////////////////////////////////////// 12 | import configurations_pkg::*; 13 | 14 | `include "bd_instr_if_seq_item.sv" 15 | `include "bd_instr_if_sequencer.sv" 16 | `include "bd_instr_if_driver.sv" 17 | `include "bd_instr_if_monitor.sv" 18 | `include "bd_instr_if_agent.sv" 19 | 20 | endpackage 21 | 22 | `endif 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /verif/bd_instr_if_Agent/bd_instr_if_driver.sv: -------------------------------------------------------------------------------- 1 | `ifndef BD_INSTR_IF_DRIVER_SV 2 | `define BD_INSTR_IF_DRIVER_SV 3 | class bd_instr_if_driver extends uvm_driver#(bd_instr_if_seq_item); 4 | 5 | `uvm_component_utils(bd_instr_if_driver) 6 | 7 | typedef enum {idle, send_instruction} instr_send_states; 8 | instr_send_states instr_send_fsm = idle; 9 | 10 | virtual interface backdoor_instr_if backdoor_instr_vif; 11 | function new(string name = "bd_instr_if_driver", uvm_component parent = null); 12 | super.new(name,parent); 13 | if (!uvm_config_db#(virtual backdoor_instr_if)::get(this, "", "backdoor_instr_if", backdoor_instr_vif)) 14 | `uvm_fatal("NOVIF",{"virtual interface must be set:",get_full_name(),".vif"}) 15 | endfunction 16 | 17 | function void connect_phase(uvm_phase phase); 18 | super.connect_phase(phase); 19 | 20 | endfunction : connect_phase 21 | 22 | 23 | task main_phase(uvm_phase phase); 24 | backdoor_instr_vif.instr_ready = 1'b0; 25 | forever begin 26 | 27 | @(negedge backdoor_instr_vif.clk); 28 | if (backdoor_instr_vif.rstn) 29 | begin 30 | 31 | seq_item_port.get_next_item(req); 32 | req.instruction_addr = backdoor_instr_vif.instr_mem_address; 33 | seq_item_port.item_done(); 34 | 35 | seq_item_port.get_next_item(req); 36 | `uvm_info(get_type_name(), 37 | $sformatf("Driver sending...\n%s", req.sprint()), 38 | UVM_HIGH) 39 | backdoor_instr_vif.instr_mem_read = req.instruction; 40 | backdoor_instr_vif.instr_ready = 1'b1; 41 | // do actual driving here 42 | /* TODO */ 43 | seq_item_port.item_done(); 44 | end 45 | end 46 | endtask : main_phase 47 | 48 | endclass : bd_instr_if_driver 49 | 50 | `endif 51 | 52 | -------------------------------------------------------------------------------- /verif/bd_instr_if_Agent/bd_instr_if_monitor.sv: -------------------------------------------------------------------------------- 1 | `ifndef BD_INSTR_IF_MONITOR 2 | `define BD_INSTR_IF_MONITOR 3 | class bd_instr_if_monitor extends uvm_monitor; 4 | 5 | // control fileds 6 | bit checks_enable = 1; 7 | bit coverage_enable = 1; 8 | logic [31:0] sc_instr_queue[$]; 9 | logic [31:0] sc_instr_addr_queue[$]; 10 | logic [31:0] sc_st_instr_queue[$]; 11 | logic [31:0] v_instr_queue[$]; 12 | 13 | 14 | 15 | int branch_skip; 16 | uvm_analysis_port #(bd_instr_if_seq_item) item_collected_port; 17 | 18 | `uvm_component_utils_begin(bd_instr_if_monitor) 19 | `uvm_field_int(checks_enable, UVM_DEFAULT) 20 | `uvm_field_int(coverage_enable, UVM_DEFAULT) 21 | `uvm_component_utils_end 22 | 23 | // The virtual interface used to drive and view HDL signals. 24 | virtual interface backdoor_instr_if backdoor_instr_vif; 25 | virtual interface backdoor_register_bank_if backdoor_register_bank_vif; 26 | virtual interface backdoor_sc_data_if backdoor_sc_data_vif; 27 | 28 | // current transaction 29 | bd_instr_if_seq_item curr_it; 30 | logic[31:0] store_data_queue[$]; 31 | 32 | // coverage can go here 33 | // ... 34 | 35 | function new(string name = "bd_instr_if_monitor", uvm_component parent = null); 36 | super.new(name,parent); 37 | item_collected_port = new("item_collected_port", this); 38 | if (!uvm_config_db#(virtual backdoor_instr_if)::get(this, "", "backdoor_instr_if", backdoor_instr_vif)) 39 | `uvm_fatal("NOVIF",{"virtual interface must be set:",get_full_name(),".vif"}) 40 | if (!uvm_config_db#(virtual backdoor_sc_data_if)::get(this, "", "backdoor_sc_data_if", backdoor_sc_data_vif)) 41 | `uvm_fatal("NOVIF",{"virtual interface must be set:",get_full_name(),".vif"}) 42 | if (!uvm_config_db#(virtual backdoor_register_bank_if)::get(this, "", "backdoor_register_bank_if", backdoor_register_bank_vif)) 43 | `uvm_fatal("NOVIF",{"virtual interface must be set:",get_full_name(),".vif"}) 44 | 45 | endfunction 46 | 47 | function void connect_phase(uvm_phase phase); 48 | super.connect_phase(phase); 49 | 50 | endfunction : connect_phase 51 | 52 | task main_phase(uvm_phase phase); 53 | for (int i=0; i<6; i++) 54 | begin 55 | sc_instr_queue[i] = 0;// nop instructions go first 56 | sc_instr_addr_queue[i] = 0;// nop instructions go first 57 | end 58 | forever begin 59 | @(negedge backdoor_instr_vif.clk); 60 | if (backdoor_instr_vif.rstn) 61 | begin 62 | fork 63 | begin 64 | collect_instruction(); 65 | end 66 | 67 | begin 68 | collect_and_check_data(); 69 | end 70 | join_none 71 | end 72 | 73 | 74 | 75 | // ... 76 | // collect transactions 77 | // ... 78 | // item_collected_port.write(curr_it); 79 | 80 | end 81 | endtask : main_phase 82 | 83 | task collect_instruction(); 84 | if (backdoor_instr_vif.instr_mem_en && backdoor_instr_vif.instr_ready) 85 | begin 86 | begin 87 | if (backdoor_instr_vif.instr_mem_read[2:0] != 3'b111) // scalar instruction 88 | begin 89 | sc_instr_queue.push_back(backdoor_instr_vif.instr_mem_read); //save non store instr 90 | sc_instr_addr_queue.push_back(backdoor_instr_vif.instr_mem_address); //save non store instr 91 | end 92 | else 93 | begin 94 | v_instr_queue.push_back(backdoor_instr_vif.instr_mem_read); 95 | sc_instr_queue.push_back(0); //save non store instr 96 | sc_instr_addr_queue.push_back(backdoor_instr_vif.instr_mem_address); //save non store instr 97 | end 98 | end 99 | end 100 | endtask // collect_instruction 101 | 102 | task collect_and_check_data(); 103 | logic [0:31][31:0] sc_reg_bank; 104 | 105 | fork 106 | begin // non store thread 107 | if (sc_instr_queue.size() != 0) 108 | begin 109 | curr_it=bd_instr_if_seq_item::type_id::create("seq_item", this); 110 | curr_it.scalar_reg_bank_new=backdoor_register_bank_vif.scalar_reg_bank; 111 | curr_it.instruction = sc_instr_queue.pop_front(); 112 | curr_it.instruction_addr=sc_instr_addr_queue.pop_front(); 113 | if (curr_it.instruction[6:0] == 7'b1100011) 114 | curr_it.store_data = store_data_queue.pop_front(); 115 | //$display ("New_reg bank: %x, time: %d", curr_it.scalar_reg_bank_new, $time); 116 | item_collected_port.write(curr_it); 117 | end 118 | end // non store thread 119 | 120 | 121 | begin // store thread 122 | if (backdoor_sc_data_vif.data_mem_we_o) 123 | begin 124 | store_data_queue.push_front(backdoor_sc_data_vif.data_mem_write_o); 125 | end 126 | end // store thread 127 | 128 | join_none 129 | endtask // collect_and_check_data 130 | 131 | 132 | endclass : bd_instr_if_monitor 133 | `endif 134 | -------------------------------------------------------------------------------- /verif/bd_instr_if_Agent/bd_instr_if_seq_item.sv: -------------------------------------------------------------------------------- 1 | `ifndef BD_INSTR_IF_SEQ_ITEM_SV 2 | `define BD_INSTR_IF_SEQ_ITEM_SV 3 | 4 | parameter DATA_WIDTH = 32; 5 | parameter RESP_WIDTH = 2; 6 | parameter CMD_WIDTH = 4; 7 | 8 | class bd_instr_if_seq_item extends uvm_sequence_item; 9 | 10 | logic [31:0] instruction; 11 | logic [31:0] instruction_addr; 12 | logic [31:0] store_data; 13 | logic [0:31][31:0] scalar_reg_bank_new; 14 | logic [0:31][31:0] scalar_reg_bank_old; 15 | 16 | `uvm_object_utils_begin(bd_instr_if_seq_item) 17 | `uvm_field_int(instruction, UVM_DEFAULT) 18 | `uvm_field_int(instruction_addr, UVM_DEFAULT) 19 | `uvm_field_int(scalar_reg_bank_old, UVM_DEFAULT) 20 | `uvm_field_int(scalar_reg_bank_new, UVM_DEFAULT) 21 | `uvm_field_int(store_data, UVM_DEFAULT) 22 | `uvm_object_utils_end 23 | 24 | function new (string name = "bd_instr_if_seq_item"); 25 | super.new(name); 26 | endfunction // new 27 | 28 | endclass : bd_instr_if_seq_item 29 | 30 | `endif 31 | -------------------------------------------------------------------------------- /verif/bd_instr_if_Agent/bd_instr_if_sequencer.sv: -------------------------------------------------------------------------------- 1 | `ifndef BD_INSTR_IF_SEQUENCER_SV 2 | `define BD_INSTR_IF_SEQUENCER_SV 3 | 4 | class bd_instr_if_sequencer extends uvm_sequencer#(bd_instr_if_seq_item); 5 | 6 | `uvm_component_utils(bd_instr_if_sequencer) 7 | 8 | function new(string name = "bd_instr_if_sequencer", uvm_component parent = null); 9 | super.new(name,parent); 10 | endfunction 11 | 12 | endclass : bd_instr_if_sequencer 13 | 14 | `endif 15 | 16 | -------------------------------------------------------------------------------- /verif/bd_v_data_if_Agent/bd_v_data_if_agent.sv: -------------------------------------------------------------------------------- 1 | class bd_v_data_if_agent extends uvm_agent; 2 | 3 | // components 4 | bd_v_data_if_driver drv; 5 | bd_v_data_if_sequencer seqr; 6 | bd_v_data_if_monitor mon; 7 | 8 | virtual interface backdoor_v_data_if backdoor_v_data_vif; 9 | // configuration 10 | riscv_v_config cfg; 11 | int value; 12 | `uvm_component_utils_begin (bd_v_data_if_agent) 13 | `uvm_field_object(cfg, UVM_DEFAULT) 14 | `uvm_component_utils_end 15 | 16 | function new(string name = "bd_v_data_if_agent", uvm_component parent = null); 17 | super.new(name,parent); 18 | endfunction 19 | 20 | function void build_phase(uvm_phase phase); 21 | super.build_phase(phase); 22 | /************Geting from configuration database*******************/ 23 | if (!uvm_config_db#(virtual backdoor_v_data_if)::get(this, "", "backdoor_v_data_if", backdoor_v_data_vif)) 24 | `uvm_fatal("NOVIF",{"virtual interface must be set:",get_full_name(),".vif"}) 25 | 26 | 27 | if(!uvm_config_db#(riscv_v_config)::get(this, "", "riscv_v_config", cfg)) 28 | `uvm_fatal("NOCONFIG",{"Config object must be set for: ",get_full_name(),".cfg"}) 29 | 30 | /*****************************************************************/ 31 | 32 | /************Setting to configuration database********************/ 33 | uvm_config_db#(virtual backdoor_v_data_if)::set(this, "*", "backdoor_v_data_if", backdoor_v_data_vif); 34 | /*****************************************************************/ 35 | 36 | mon = bd_v_data_if_monitor::type_id::create("mon", this); 37 | if(cfg.is_active == UVM_ACTIVE) begin 38 | drv = bd_v_data_if_driver::type_id::create("drv", this); 39 | seqr = bd_v_data_if_sequencer::type_id::create("seqr", this); 40 | end 41 | endfunction : build_phase 42 | 43 | function void connect_phase(uvm_phase phase); 44 | super.connect_phase(phase); 45 | if(cfg.is_active == UVM_ACTIVE) begin 46 | drv.seq_item_port.connect(seqr.seq_item_export); 47 | end 48 | endfunction : connect_phase 49 | 50 | endclass : bd_v_data_if_agent 51 | -------------------------------------------------------------------------------- /verif/bd_v_data_if_Agent/bd_v_data_if_agent_pkg.sv: -------------------------------------------------------------------------------- 1 | `ifndef BD_V_DATA_IF_AGENT_PKG 2 | `define BD_V_DATA_IF_AGENT_PKG 3 | 4 | package bd_v_data_if_agent_pkg; 5 | 6 | import uvm_pkg::*; 7 | `include "uvm_macros.svh" 8 | 9 | ////////////////////////////////////////////////////////// 10 | // include Agent components : driver,monitor,sequencer 11 | ///////////////////////////////////////////////////////// 12 | import configurations_pkg::*; 13 | 14 | `include "bd_v_data_if_seq_item.sv" 15 | `include "bd_v_data_if_sequencer.sv" 16 | `include "bd_v_data_if_driver.sv" 17 | `include "bd_v_data_if_monitor.sv" 18 | `include "bd_v_data_if_agent.sv" 19 | 20 | endpackage 21 | 22 | `endif 23 | 24 | 25 | 26 | -------------------------------------------------------------------------------- /verif/bd_v_data_if_Agent/bd_v_data_if_driver.sv: -------------------------------------------------------------------------------- 1 | `ifndef BD_V_DATA_IF_DRIVER_SV 2 | `define BD_V_DATA_IF_DRIVER_SV 3 | class bd_v_data_if_driver extends uvm_driver#(bd_v_data_if_seq_item); 4 | 5 | `uvm_component_utils(bd_v_data_if_driver) 6 | 7 | typedef enum {rd_idle_phase, rd_phase} read_fsm; 8 | read_fsm read_channel = rd_idle_phase; 9 | 10 | typedef enum {wr_idle_phase, wr_phase, resp_phase} write_fsm; 11 | write_fsm write_channel = wr_idle_phase; 12 | 13 | //logic [31:0] backdoor_v_data_vif.ddr_mem[4096]; 14 | 15 | virtual interface backdoor_v_data_if backdoor_v_data_vif; 16 | function new(string name = "bd_v_data_if_driver", uvm_component parent = null); 17 | super.new(name,parent); 18 | if (!uvm_config_db#(virtual backdoor_v_data_if)::get(this, "", "backdoor_v_data_if", backdoor_v_data_vif)) 19 | `uvm_fatal("NOVIF",{"virtual interface must be set:",get_full_name(),".vif"}) 20 | endfunction 21 | 22 | function void connect_phase(uvm_phase phase); 23 | super.connect_phase(phase); 24 | 25 | endfunction : connect_phase 26 | 27 | 28 | task main_phase(uvm_phase phase); 29 | forever begin 30 | fork 31 | start_read_slave(); 32 | start_write_slave(); 33 | join 34 | end 35 | endtask : main_phase 36 | 37 | task start_read_slave (); 38 | logic [31:0] ctrl_raddr_offset; 39 | logic [31:0] ctrl_rxfer_size; 40 | int data_offset=0; 41 | forever 42 | begin 43 | @(negedge backdoor_v_data_vif.clk); 44 | case(read_channel) 45 | rd_idle_phase: begin 46 | backdoor_v_data_vif.ctrl_rdone_i = 1'b0; 47 | backdoor_v_data_vif.rd_tvalid_i = 0; 48 | backdoor_v_data_vif.rd_tlast_i = 1'b0; 49 | if (backdoor_v_data_vif.ctrl_rstart_o) 50 | begin 51 | data_offset = 0; 52 | ctrl_raddr_offset = backdoor_v_data_vif.ctrl_raddr_offset_o; 53 | ctrl_rxfer_size = backdoor_v_data_vif.ctrl_rxfer_size_o/4; 54 | read_channel = rd_phase; 55 | end 56 | end 57 | rd_phase: begin 58 | backdoor_v_data_vif.rd_tvalid_i = $urandom_range(0, 1); 59 | if (backdoor_v_data_vif.rd_tready_o && backdoor_v_data_vif.rd_tvalid_i) 60 | begin 61 | backdoor_v_data_vif.rd_tdata_i = backdoor_v_data_vif.ddr_mem[ctrl_raddr_offset+data_offset]; 62 | data_offset++; 63 | if (data_offset==ctrl_rxfer_size) 64 | begin 65 | backdoor_v_data_vif.ctrl_rdone_i = 1'b1; 66 | backdoor_v_data_vif.rd_tlast_i = 1'b1; 67 | read_channel=rd_idle_phase; 68 | end 69 | end 70 | end 71 | endcase 72 | end 73 | endtask // startread_slave 74 | 75 | task start_write_slave (); 76 | logic [31:0] ctrl_waddr_offset; 77 | logic [31:0] ctrl_wxfer_size; 78 | int data_offset=0; 79 | 80 | forever 81 | begin 82 | @(negedge backdoor_v_data_vif.clk); 83 | case(write_channel) 84 | wr_idle_phase: begin 85 | backdoor_v_data_vif.wr_tready_i = 0; 86 | backdoor_v_data_vif.ctrl_wdone_i=1'b0; 87 | if (backdoor_v_data_vif.ctrl_wstart_o) 88 | begin 89 | data_offset = 0; 90 | ctrl_waddr_offset = backdoor_v_data_vif.ctrl_waddr_offset_o; 91 | ctrl_wxfer_size = backdoor_v_data_vif.ctrl_wxfer_size_o; 92 | write_channel = wr_phase; 93 | end 94 | end 95 | wr_phase: begin 96 | backdoor_v_data_vif.wr_tready_i = $urandom_range(0, 1); 97 | if (backdoor_v_data_vif.wr_tready_i && backdoor_v_data_vif.wr_tvalid_o) 98 | begin 99 | backdoor_v_data_vif.ddr_mem[ctrl_waddr_offset+data_offset] = backdoor_v_data_vif.wr_tdata_o; 100 | data_offset++; 101 | if (data_offset==ctrl_wxfer_size) 102 | begin 103 | backdoor_v_data_vif.ctrl_wdone_i=1'b1; 104 | write_channel=wr_idle_phase; 105 | end 106 | end 107 | end 108 | endcase 109 | end 110 | endtask 111 | 112 | endclass : bd_v_data_if_driver 113 | 114 | `endif 115 | 116 | -------------------------------------------------------------------------------- /verif/bd_v_data_if_Agent/bd_v_data_if_monitor.sv: -------------------------------------------------------------------------------- 1 | `ifndef BD_V_DATA_IF_MONITOR 2 | `define BD_V_DATA_IF_MONITOR 3 | class bd_v_data_if_monitor extends uvm_monitor; 4 | 5 | // control fileds 6 | bit checks_enable = 1; 7 | bit coverage_enable = 1; 8 | logic [31:0] instr_queue[$]; 9 | uvm_analysis_port #(bd_v_data_if_seq_item) item_collected_port; 10 | 11 | `uvm_component_utils_begin(bd_v_data_if_monitor) 12 | `uvm_field_int(checks_enable, UVM_DEFAULT) 13 | `uvm_field_int(coverage_enable, UVM_DEFAULT) 14 | `uvm_component_utils_end 15 | 16 | // The virtual interface used to drive and view HDL signals. 17 | virtual interface backdoor_instr_if backdoor_instr_vif; 18 | virtual interface backdoor_register_bank_if backdoor_register_bank_vif; 19 | virtual interface backdoor_sc_data_if backdoor_sc_data_vif; 20 | 21 | // current transaction 22 | bd_v_data_if_seq_item curr_it; 23 | 24 | // coverage can go here 25 | // ... 26 | 27 | function new(string name = "bd_v_data_if_monitor", uvm_component parent = null); 28 | super.new(name,parent); 29 | item_collected_port = new("item_collected_port", this); 30 | 31 | /* -----\/----- EXCLUDED -----\/----- 32 | if (!uvm_config_db#(virtual backdoor_sc_data_if)::get(this, "", "backdoor_sc_data_if", backdoor_sc_data_vif)) 33 | `uvm_fatal("NOVIF",{"virtual interface must be set:",get_full_name(),".vif"}) 34 | -----/\----- EXCLUDED -----/\----- */ 35 | 36 | endfunction 37 | 38 | function void connect_phase(uvm_phase phase); 39 | super.connect_phase(phase); 40 | 41 | endfunction : connect_phase 42 | 43 | task main_phase(uvm_phase phase); 44 | // forever begin 45 | // curr_it = bd_v_data_if_seq_item::type_id::create("curr_it", this); 46 | // ... 47 | // collect transactions 48 | // ... 49 | // item_collected_port.write(curr_it); 50 | 51 | // end 52 | endtask : main_phase 53 | 54 | endclass : bd_v_data_if_monitor 55 | `endif 56 | -------------------------------------------------------------------------------- /verif/bd_v_data_if_Agent/bd_v_data_if_seq_item.sv: -------------------------------------------------------------------------------- 1 | `ifndef BD_V_DATA_IF_SEQ_ITEM_SV 2 | `define BD_V_DATA_IF_SEQ_ITEM_SV 3 | 4 | parameter DATA_WIDTH = 32; 5 | parameter RESP_WIDTH = 2; 6 | parameter CMD_WIDTH = 4; 7 | 8 | class bd_v_data_if_seq_item extends uvm_sequence_item; 9 | 10 | logic [31:0] instruction; 11 | logic [31:0] instruction_addr; 12 | 13 | `uvm_object_utils_begin(bd_v_data_if_seq_item) 14 | `uvm_field_int(instruction, UVM_DEFAULT) 15 | `uvm_field_int(instruction_addr, UVM_DEFAULT) 16 | `uvm_object_utils_end 17 | 18 | function new (string name = "bd_v_data_if_seq_item"); 19 | super.new(name); 20 | endfunction // new 21 | 22 | endclass : bd_v_data_if_seq_item 23 | 24 | `endif 25 | -------------------------------------------------------------------------------- /verif/bd_v_data_if_Agent/bd_v_data_if_sequencer.sv: -------------------------------------------------------------------------------- 1 | `ifndef BD_V_DATA_IF_SEQUENCER_SV 2 | `define BD_V_DATA_IF_SEQUENCER_SV 3 | 4 | class bd_v_data_if_sequencer extends uvm_sequencer#(bd_v_data_if_seq_item); 5 | 6 | `uvm_component_utils(bd_v_data_if_sequencer) 7 | 8 | function new(string name = "bd_v_data_if_sequencer", uvm_component parent = null); 9 | super.new(name,parent); 10 | endfunction 11 | 12 | endclass : bd_v_data_if_sequencer 13 | 14 | `endif 15 | 16 | -------------------------------------------------------------------------------- /verif/bd_v_instr_if_Agent/bd_v_instr_if_agent.sv: -------------------------------------------------------------------------------- 1 | `ifndef BD_V_INSTR_IF_AGENT 2 | `define BD_V_INSTR_IF_AGENT 3 | class bd_v_instr_if_agent extends uvm_agent; 4 | 5 | // components 6 | 7 | bd_v_instr_if_monitor mon; 8 | 9 | virtual interface backdoor_v_instr_if backdoor_v_instr_vif; 10 | 11 | // configuration 12 | riscv_v_config cfg; 13 | int value; 14 | `uvm_component_utils_begin (bd_v_instr_if_agent) 15 | `uvm_field_object(cfg, UVM_DEFAULT) 16 | `uvm_component_utils_end 17 | 18 | function new(string name = "bd_v_instr_if_agent", uvm_component parent = null); 19 | super.new(name,parent); 20 | endfunction 21 | 22 | function void build_phase(uvm_phase phase); 23 | super.build_phase(phase); 24 | /************Geting from configuration database*******************/ 25 | if (!uvm_config_db#(virtual backdoor_v_instr_if)::get(this, "", "backdoor_v_instr_if", backdoor_v_instr_vif)) 26 | `uvm_fatal("NOVIF",{"virtual interface must be set:",get_full_name(),".vif"}) 27 | 28 | if(!uvm_config_db#(riscv_v_config)::get(this, "", "riscv_v_config", cfg)) 29 | `uvm_fatal("NOCONFIG",{"Config object must be set for: ",get_full_name(),".cfg"}) 30 | 31 | /*****************************************************************/ 32 | 33 | /************Setting to configuration database********************/ 34 | uvm_config_db#(virtual backdoor_v_instr_if)::set(this, "*", "backdoor_v_instr_if", backdoor_v_instr_vif); 35 | 36 | /*****************************************************************/ 37 | 38 | mon = bd_v_instr_if_monitor::type_id::create("mon", this); 39 | endfunction : build_phase 40 | 41 | function void connect_phase(uvm_phase phase); 42 | super.connect_phase(phase); 43 | 44 | endfunction : connect_phase 45 | 46 | endclass : bd_v_instr_if_agent 47 | `endif 48 | -------------------------------------------------------------------------------- /verif/bd_v_instr_if_Agent/bd_v_instr_if_agent_pkg.sv: -------------------------------------------------------------------------------- 1 | `ifndef BD_V_INSTR_IF_AGENT_PKG 2 | `define BD_V_INSTR_IF_AGENT_PKG 3 | 4 | package bd_v_instr_if_agent_pkg; 5 | 6 | import uvm_pkg::*; 7 | `include "uvm_macros.svh" 8 | 9 | ////////////////////////////////////////////////////////// 10 | // include Agent components : driver,monitor,sequencer 11 | ///////////////////////////////////////////////////////// 12 | import configurations_pkg::*; 13 | 14 | `include "bd_v_instr_if_seq_item.sv" 15 | `include "bd_v_instr_if_monitor.sv" 16 | `include "bd_v_instr_if_agent.sv" 17 | 18 | endpackage 19 | 20 | `endif 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /verif/bd_v_instr_if_Agent/bd_v_instr_if_monitor.sv: -------------------------------------------------------------------------------- 1 | `ifndef BD_V_INSTR_IF_MONITOR 2 | `define BD_V_INSTR_IF_MONITOR 3 | class bd_v_instr_if_monitor extends uvm_monitor; 4 | 5 | // control fileds 6 | bit checks_enable = 1; 7 | bit coverage_enable = 1; 8 | logic [31:0] v_instr_queue[$]; 9 | 10 | 11 | 12 | int branch_skip; 13 | uvm_analysis_port #(bd_v_instr_if_seq_item) item_collected_port; 14 | 15 | `uvm_component_utils_begin(bd_v_instr_if_monitor) 16 | `uvm_field_int(checks_enable, UVM_DEFAULT) 17 | `uvm_field_int(coverage_enable, UVM_DEFAULT) 18 | `uvm_component_utils_end 19 | 20 | // The virtual interface used to drive and view HDL signals. 21 | virtual interface backdoor_v_instr_if vif; 22 | 23 | // current transaction 24 | bd_v_instr_if_seq_item curr_it[4]; 25 | logic[31:0] store_data_queue[$]; 26 | typedef enum {wait_for_start, wait_for_rdy} instr_send_states; 27 | 28 | logic [31:0] instr_queue[4][$]; 29 | logic [2:0] sew_queue[4][$]; 30 | logic [2:0] lmul_queue[4][$]; 31 | logic [31:0] vl_queue[4][$]; 32 | logic [31:0] scalar_queue[4][$]; 33 | logic [31:0] scalar2_queue[4][$]; 34 | int driver_processing[4] = '{default:'0}; 35 | int watch_dog_cnt=0; 36 | // coverage can go here 37 | // ... 38 | 39 | function new(string name = "bd_v_instr_if_monitor", uvm_component parent = null); 40 | super.new(name,parent); 41 | item_collected_port = new("item_collected_port", this); 42 | if (!uvm_config_db#(virtual backdoor_v_instr_if)::get(this, "", "backdoor_v_instr_if", vif)) 43 | `uvm_fatal("NOVIF",{"virtual interface must be set:",get_full_name(),".vif"}) 44 | 45 | 46 | endfunction 47 | 48 | function void connect_phase(uvm_phase phase); 49 | super.connect_phase(phase); 50 | 51 | endfunction : connect_phase 52 | 53 | task main_phase(uvm_phase phase); 54 | int drop_obj=0; 55 | phase.raise_objection(this); 56 | forever begin 57 | @(negedge vif.clk); 58 | fork 59 | begin 60 | lane_driver(0); 61 | end 62 | begin 63 | lane_driver(1); 64 | end 65 | begin 66 | lane_driver(2); 67 | end 68 | begin 69 | lane_driver(3); 70 | end 71 | join_none 72 | 73 | if(vif.v_instruction[6:0]==7'h13) 74 | watch_dog_cnt++; 75 | if (vif.start==0 && vif.ready==4'b1111 && watch_dog_cnt > 10 && drop_obj==0) 76 | begin 77 | drop_obj = 1; 78 | phase.drop_objection(this); 79 | end 80 | // ... 81 | // collect transactions 82 | // ... 83 | // item_collected_port.write(curr_it); 84 | 85 | end 86 | endtask : main_phase 87 | 88 | task lane_driver(int idx); 89 | 90 | 91 | if (driver_processing[idx]==1 && vif.ready[idx]) 92 | begin 93 | fork 94 | begin 95 | driver_processing[idx] = 0; 96 | for (int i=0; i<8; i++) // wait for VECTOR core to finish with the processing, max 8 clk needed 97 | begin 98 | @(negedge vif.clk); 99 | end 100 | 101 | curr_it[idx]=bd_v_instr_if_seq_item::type_id::create("bd_v_instr_if_seq_item", this); 102 | curr_it[idx].v_instruction = instr_queue[idx].pop_front(); 103 | curr_it[idx].sew = sew_queue[idx].pop_front(); 104 | curr_it[idx].lmul = lmul_queue[idx].pop_front(); 105 | curr_it[idx].vl = vl_queue[idx].pop_front(); 106 | curr_it[idx].scalar = scalar_queue[idx].pop_front(); 107 | curr_it[idx].scalar2 = scalar2_queue[idx].pop_front(); 108 | curr_it[idx].vrf_read_ram = vif.vrf_read_ram; 109 | item_collected_port.write(curr_it[idx]); 110 | $display("READY DRIVER IDX IS: %d, v_instruction:%x", idx, curr_it[idx].v_instruction); 111 | end 112 | join_none 113 | end 114 | if (vif.start[idx] && vif.ready[idx]) 115 | begin 116 | $display("START DRIVER IDX IS: %d, v_instruction:%x", idx, vif.v_instruction); 117 | driver_processing[idx] = 1; 118 | instr_queue[idx].push_back(vif.v_instruction); 119 | sew_queue[idx].push_back( vif.sew); 120 | lmul_queue[idx].push_back(vif.lmul); 121 | vl_queue[idx].push_back(vif.vl); 122 | scalar_queue[idx].push_back(vif.v_rs1_scalar); 123 | scalar2_queue[idx].push_back(vif.v_rs2_scalar); 124 | end 125 | endtask 126 | 127 | 128 | 129 | endclass : bd_v_instr_if_monitor 130 | `endif 131 | -------------------------------------------------------------------------------- /verif/bd_v_instr_if_Agent/bd_v_instr_if_seq_item.sv: -------------------------------------------------------------------------------- 1 | `ifndef BD_V_INSTR_IF_SEQ_ITEM_SV 2 | `define BD_V_INSTR_IF_SEQ_ITEM_SV 3 | `include "../defines.sv" 4 | parameter DATA_WIDTH = 32; 5 | parameter RESP_WIDTH = 2; 6 | parameter CMD_WIDTH = 4; 7 | 8 | class bd_v_instr_if_seq_item extends uvm_sequence_item; 9 | 10 | logic [31:0] v_instruction; 11 | logic [2:0] sew; 12 | logic [2:0] lmul; 13 | logic [31:0] vl; 14 | logic [31:0] scalar; 15 | logic [31:0] scalar2; 16 | logic [31:0] vrf_read_ram [`V_LANES][2][4][`VRF_DEPTH-1:0]; 17 | 18 | `uvm_object_utils_begin(bd_v_instr_if_seq_item) 19 | `uvm_field_int(v_instruction, UVM_DEFAULT) 20 | `uvm_field_int(sew, UVM_DEFAULT) 21 | `uvm_field_int(lmul, UVM_DEFAULT) 22 | `uvm_field_int(scalar, UVM_DEFAULT) 23 | `uvm_field_int(vl, UVM_DEFAULT) 24 | `uvm_object_utils_end 25 | 26 | function new (string name = "bd_v_instr_if_seq_item"); 27 | super.new(name); 28 | endfunction // new 29 | 30 | endclass : bd_v_instr_if_seq_item 31 | 32 | `endif 33 | -------------------------------------------------------------------------------- /verif/defines.sv: -------------------------------------------------------------------------------- 1 | 2 | `define DDR_DEPTH 131072 3 | `define V_LANES 4 4 | `define VLEN 4096 5 | `define VRF_DEPTH `VLEN/`V_LANES 6 | -------------------------------------------------------------------------------- /verif/riscv_v_env.sv: -------------------------------------------------------------------------------- 1 | `ifndef RISCV_V_ENV_SV 2 | `define RISCV_V_ENV_SV 3 | 4 | class riscv_v_env extends uvm_env; 5 | 6 | bd_instr_if_agent bd_instr_agent; 7 | bd_v_instr_if_agent bd_v_instr_agent; 8 | bd_v_data_if_agent bd_v_data_agent; 9 | AXI4_agent v_axi4_agent; 10 | AXI4_agent s_axi4_agent; 11 | riscv_v_config cfg; 12 | riscv_sc_scoreboard sc_scbd; 13 | riscv_v_scoreboard v_scbd; 14 | virtual interface axi4_if v_axi4_vif; 15 | virtual interface axi4_if s_axi4_vif; 16 | virtual interface backdoor_instr_if backdoor_instr_vif; 17 | virtual interface backdoor_v_instr_if backdoor_v_instr_vif; 18 | virtual interface backdoor_register_bank_if backdoor_register_bank_vif; 19 | virtual interface backdoor_sc_data_if backdoor_sc_data_vif; 20 | virtual interface backdoor_v_data_if backdoor_v_data_vif; 21 | `uvm_component_utils (riscv_v_env) 22 | 23 | function new(string name = "riscv_v_env", uvm_component parent = null); 24 | super.new(name,parent); 25 | endfunction 26 | 27 | function void build_phase(uvm_phase phase); 28 | super.build_phase(phase); 29 | /************Geting from configuration database*******************/ 30 | if (!uvm_config_db#(virtual axi4_if)::get(this, "", "v_axi4_if", v_axi4_vif)) 31 | `uvm_fatal("NOVIF",{"virtual interface must be set:",get_full_name(),".v_axi4_vif"}) 32 | if (!uvm_config_db#(virtual axi4_if)::get(this, "", "s_axi4_if", s_axi4_vif)) 33 | `uvm_fatal("NOVIF",{"virtual interface must be set:",get_full_name(),".s_axi4_vif"}) 34 | if (!uvm_config_db#(virtual backdoor_instr_if)::get(this, "", "backdoor_instr_if", backdoor_instr_vif)) 35 | `uvm_fatal("NOVIF",{"virtual interface must be set:",get_full_name(),".backdoor_instr_vif"}) 36 | if (!uvm_config_db#(virtual backdoor_v_instr_if)::get(this, "", "backdoor_v_instr_if", backdoor_v_instr_vif)) 37 | `uvm_fatal("NOVIF",{"virtual interface must be set:",get_full_name(),".backdoor_instr_vif"}) 38 | 39 | if (!uvm_config_db#(virtual backdoor_sc_data_if)::get(this, "", "backdoor_sc_data_if", backdoor_sc_data_vif)) 40 | `uvm_fatal("NOVIF",{"virtual interface must be set:",get_full_name(),".backdoor_sc_data_vif"}) 41 | if (!uvm_config_db#(virtual backdoor_register_bank_if)::get(this, "", "backdoor_register_bank_if", backdoor_register_bank_vif)) 42 | `uvm_fatal("NOVIF",{"virtual interface must be set:",get_full_name(),".backdoor_register_bank_vif"}) 43 | if (!uvm_config_db#(virtual backdoor_v_data_if)::get(this, "", "backdoor_v_data_if", backdoor_v_data_vif)) 44 | `uvm_fatal("NOVIF",{"virtual interface must be set:",get_full_name(),".backdoor_v_data_vif"}) 45 | 46 | if(!uvm_config_db#(riscv_v_config)::get(this, "", "riscv_v_config", cfg)) 47 | `uvm_fatal("NOCONFIG",{"Config object must be set for: ",get_full_name(),".cfg"}) 48 | /*****************************************************************/ 49 | 50 | /************Setting to configuration database********************/ 51 | uvm_config_db#(riscv_v_config)::set(this, "*", "riscv_v_config", cfg); 52 | uvm_config_db#(virtual axi4_if)::set(this, "v_axi4_agent", "axi4_if", v_axi4_vif); 53 | uvm_config_db#(virtual axi4_if)::set(this, "v_scbd", "v_axi4_if", v_axi4_vif); 54 | uvm_config_db#(virtual axi4_if)::set(this, "s_axi4_agent", "axi4_if", s_axi4_vif); 55 | uvm_config_db#(virtual backdoor_instr_if)::set(this, "bd_instr_agent", "backdoor_instr_if", backdoor_instr_vif); 56 | uvm_config_db#(virtual backdoor_v_instr_if)::set(this, "bd_v_instr_agent", "backdoor_v_instr_if", backdoor_v_instr_vif); 57 | uvm_config_db#(virtual backdoor_v_instr_if)::set(this, "v_scbd", "backdoor_v_instr_if", backdoor_v_instr_vif); 58 | uvm_config_db#(virtual backdoor_sc_data_if)::set(this, "bd_instr_agent", "backdoor_sc_data_if", backdoor_sc_data_vif); 59 | uvm_config_db#(virtual backdoor_register_bank_if)::set(this, "bd_instr_agent", "backdoor_register_bank_if", backdoor_register_bank_vif); 60 | uvm_config_db#(virtual backdoor_v_data_if)::set(this, "bd_v_data_agent", "backdoor_v_data_if", backdoor_v_data_vif); 61 | /*****************************************************************/ 62 | 63 | bd_instr_agent = bd_instr_if_agent::type_id::create("bd_instr_agent", this); 64 | bd_v_instr_agent = bd_v_instr_if_agent::type_id::create("bd_v_instr_agent", this); 65 | s_axi4_agent = AXI4_agent::type_id::create("s_axi4_agent", this); 66 | //if (cfg.use_v_data_backdoor==1) 67 | //bd_v_data_agent = bd_v_data_if_agent::type_id::create("bd_v_data_agent", this); 68 | //else 69 | v_axi4_agent = AXI4_agent::type_id::create("v_axi4_agent", this); 70 | 71 | sc_scbd = riscv_sc_scoreboard::type_id::create("sc_scbd", this); 72 | v_scbd = riscv_v_scoreboard::type_id::create("v_scbd", this); 73 | 74 | 75 | endfunction : build_phase 76 | 77 | function void connect_phase(uvm_phase phase); 78 | super.connect_phase(phase); 79 | bd_instr_agent.mon.item_collected_port.connect(sc_scbd.item_collected_imp_s); 80 | bd_v_instr_agent.mon.item_collected_port.connect(v_scbd.item_collected_imp_v); 81 | endfunction 82 | 83 | endclass : riscv_v_env 84 | 85 | `endif 86 | -------------------------------------------------------------------------------- /verif/riscv_v_if.sv: -------------------------------------------------------------------------------- 1 | `ifndef RISCV_V_IF_SV 2 | `define RISCV_V_IF_SV 3 | 4 | interface axi4_if (input clk, logic rstn, output reg [31:0] ddr_mem[`DDR_DEPTH], input logic[31:0] burst_len); 5 | // AXI FULL VECTOR CORE IF 6 | parameter integer C_M_AXI_ADDR_WIDTH = 32; 7 | parameter integer C_M_AXI_DATA_WIDTH = 32; 8 | parameter integer C_XFER_SIZE_WIDTH = 32; 9 | parameter integer VLEN = 4096; 10 | parameter integer V_LANES = 16; 11 | parameter integer CHAINING = 4; 12 | 13 | 14 | logic m_axi_awvalid ; 15 | logic m_axi_awready ; 16 | logic [C_M_AXI_ADDR_WIDTH-1:0] m_axi_awaddr ; 17 | logic [8-1:0] m_axi_awlen ; 18 | logic m_axi_wvalid ; 19 | logic m_axi_wready ; 20 | logic [C_M_AXI_DATA_WIDTH-1:0] m_axi_wdata ; 21 | logic [C_M_AXI_DATA_WIDTH/8-1:0] m_axi_wstrb ; 22 | logic m_axi_wlast ; 23 | logic m_axi_arvalid ; 24 | logic m_axi_arready ; 25 | logic [C_M_AXI_ADDR_WIDTH-1:0] m_axi_araddr ; 26 | logic [8-1:0] m_axi_arlen ; 27 | logic m_axi_rvalid ; 28 | logic m_axi_rready ; 29 | logic [C_M_AXI_DATA_WIDTH-1:0] m_axi_rdata ; 30 | logic m_axi_rlast ; 31 | logic m_axi_bvalid ; 32 | logic m_axi_bready; 33 | 34 | endinterface : axi4_if 35 | 36 | `endif 37 | -------------------------------------------------------------------------------- /verif/test_base.sv: -------------------------------------------------------------------------------- 1 | `ifndef TEST_BASE_SV 2 | `define TEST_BASE_SV 3 | 4 | class test_base extends uvm_test; 5 | 6 | riscv_v_env env; 7 | riscv_v_config cfg; 8 | 9 | `uvm_component_utils(test_base) 10 | 11 | function new(string name = "test_base", uvm_component parent = null); 12 | super.new(name,parent); 13 | endfunction : new 14 | 15 | function void build_phase(uvm_phase phase); 16 | super.build_phase(phase); 17 | cfg = riscv_v_config::type_id::create("cfg"); 18 | uvm_config_db#(riscv_v_config)::set(this, "env", "riscv_v_config", cfg); 19 | env = riscv_v_env::type_id::create("env", this); 20 | endfunction : build_phase 21 | 22 | function void end_of_elaboration_phase(uvm_phase phase); 23 | super.end_of_elaboration_phase(phase); 24 | uvm_top.print_topology(); 25 | endfunction : end_of_elaboration_phase 26 | 27 | endclass : test_base 28 | 29 | `endif 30 | -------------------------------------------------------------------------------- /verif/test_pkg.sv: -------------------------------------------------------------------------------- 1 | `ifndef RISCV_V_TEST_PKG_SV 2 | `define RISCV_V_TEST_PKG_SV 3 | 4 | package riscv_v_test_pkg; 5 | 6 | import uvm_pkg::* ; // import the UVM library 7 | `include "uvm_macros.svh" // Include the UVM macros 8 | 9 | 10 | import configurations_pkg::*; 11 | import bd_instr_if_agent_pkg::*; 12 | import bd_v_instr_if_agent_pkg::*; 13 | import bd_v_data_if_agent_pkg::*; 14 | import AXI4_agent_pkg::*; 15 | import riscv_v_seq_pkg::*; 16 | 17 | `include "riscv_sc_scoreboard.sv" 18 | `include "riscv_v_scoreboard.sv" 19 | `include "riscv_v_env.sv" 20 | `include "test_base.sv" 21 | `include "test_simple.sv" 22 | `include "test_simple_2.sv" 23 | 24 | 25 | endpackage : riscv_v_test_pkg 26 | `include "defines.sv" 27 | `include "riscv_v_if.sv" 28 | `include "backdoor_if.sv" 29 | 30 | `endif 31 | 32 | -------------------------------------------------------------------------------- /verif/test_simple.sv: -------------------------------------------------------------------------------- 1 | `ifndef TEST_SIMPLE_SV 2 | `define TEST_SIMPLE_SV 3 | 4 | class test_simple extends test_base; 5 | 6 | `uvm_component_utils(test_simple) 7 | 8 | riscv_v_simple_seq simple_seq; 9 | 10 | function new(string name = "test_simple", uvm_component parent = null); 11 | super.new(name,parent); 12 | endfunction : new 13 | 14 | function void build_phase(uvm_phase phase); 15 | super.build_phase(phase); 16 | simple_seq = riscv_v_simple_seq::type_id::create("simple_seq"); 17 | endfunction : build_phase 18 | 19 | task main_phase(uvm_phase phase); 20 | if (cfg.use_s_instr_backdoor) 21 | begin 22 | //phase.raise_objection(this); 23 | simple_seq.start(env.bd_instr_agent.seqr); 24 | //phase.drop_objection(this); 25 | end 26 | endtask : main_phase 27 | 28 | endclass 29 | 30 | `endif 31 | -------------------------------------------------------------------------------- /verif/test_simple_2.sv: -------------------------------------------------------------------------------- 1 | `ifndef TEST_SIMPLE_2_SV 2 | `define TEST_SIMPLE_2_SV 3 | 4 | class test_simple_2 extends test_base; 5 | 6 | `uvm_component_utils(test_simple_2) 7 | 8 | function new(string name = "test_simple_2", uvm_component parent = null); 9 | super.new(name,parent); 10 | endfunction : new 11 | 12 | function void build_phase(uvm_phase phase); 13 | super.build_phase(phase); 14 | 15 | uvm_config_db#(uvm_object_wrapper)::set(this, 16 | "seqr.main_phase", 17 | "default_sequence", 18 | riscv_v_simple_seq::type_id::get()); 19 | endfunction : build_phase 20 | 21 | endclass 22 | 23 | `endif 24 | -------------------------------------------------------------------------------- /vitis_test_app/assembly.h: -------------------------------------------------------------------------------- 1 | #ifndef ASSEMBLY_H 2 | #define ASSEMBLY_H 3 | 4 | static int assembly [] = { 5 | 6 | 0x10000513, 7 | 0x40058593, 8 | 0x40060613, 9 | 0x40060613, 10 | 0x40068693, 11 | 0x40068693, 12 | 0x40068693, 13 | 0x40068693, 14 | 0x40070713, 15 | 0x40070713, 16 | 0x40070713, 17 | 0x00180813, 18 | 0x00000793, 19 | 0x00057fd7, 20 | 0x00a008b3, 21 | 0x02058007, 22 | 0x97c06e57, 23 | 0x96806457, 24 | 0x02068807, 25 | 0x96082857, 26 | 0x030e2e57, 27 | 0xfff88893, 28 | 0x00088a63, 29 | 0x3bc84457, 30 | 0x02804e57, 31 | 0x00a686b3, 32 | 0xfe1ff0ef, 33 | 0x00000013, 34 | 0x02060407, 35 | 0x03c40e57, 36 | 0x00057fd7, 37 | 0x02070e27, 38 | 0x00000013, 39 | 0x00000013, 40 | 0x00000013, 41 | 0x00000013, 42 | 0x00000013, 43 | 0xfedff0ef 44 | 45 | 46 | }; 47 | #endif 48 | -------------------------------------------------------------------------------- /vitis_test_app/helloworld.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | * 3 | * Copyright (C) 2009 - 2014 Xilinx, Inc. All rights reserved. 4 | * 5 | * Permission is hereby granted, free of charge, to any person obtaining a copy 6 | * of this software and associated documentation files (the "Software"), to deal 7 | * in the Software without restriction, including without limitation the rights 8 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | * copies of the Software, and to permit persons to whom the Software is 10 | * furnished to do so, subject to the following conditions: 11 | * 12 | * The above copyright notice and this permission notice shall be included in 13 | * all copies or substantial portions of the Software. 14 | * 15 | * Use of the Software is limited solely to applications: 16 | * (a) running on a Xilinx device, or 17 | * (b) that interact with a Xilinx device through a bus or interconnect. 18 | * 19 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 | * XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 23 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF 24 | * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | * SOFTWARE. 26 | * 27 | * Except as contained in this notice, the name of the Xilinx shall not be used 28 | * in advertising or otherwise to promote the sale, use or other dealings in 29 | * this Software without prior written authorization from Xilinx. 30 | * 31 | ******************************************************************************/ 32 | 33 | /* 34 | * helloworld.c: simple test application 35 | * 36 | * This application configures UART 16550 to baud rate 9600. 37 | * PS7 UART (Zynq) is not initialized by this application, since 38 | * bootrom/bsp configures it to baud rate 115200 39 | * 40 | * ------------------------------------------------ 41 | * | UART TYPE BAUD RATE | 42 | * ------------------------------------------------ 43 | * uartns550 9600 44 | * uartlite Configurable only in HW design 45 | * ps7_uart 115200 (configured by bootrom/bsp) 46 | */ 47 | #include 48 | #include 49 | #include 50 | 51 | #include "xil_cache.h" 52 | #include "xil_printf.h" 53 | #include "xil_io.h" 54 | 55 | #include "platform.h" 56 | #include "xparameters.h" 57 | 58 | #include "assembly.h" 59 | 60 | // SUPPORT CONSTANTS 61 | #define MEMORY_SIZE 8*1024 62 | #define FIRST_N_NBYTES 128 63 | // REGISTERS 64 | #define USR_RISCV_CE (XPAR_RISCV_V_0_BASEADDR + 0) 65 | #define USR_MEM_BASE_ADDRESS (XPAR_RISCV_V_0_BASEADDR + 4) 66 | #define USR_RISCV_PC (XPAR_RISCV_V_0_BASEADDR + 8) 67 | #define LAYER_LEN 256 68 | int main() 69 | { 70 | int read_pc = 0; 71 | int read_ce = 0; 72 | u32 main_memory [MEMORY_SIZE] = {0}; 73 | u8 * main_memory_bw = (u8 *) main_memory; // byte-wise access to main memory 74 | u8 exp_result [LAYER_LEN] = {0}; // bytewise access to main memory 75 | 76 | init_platform(); 77 | // Invalidate range of memory which we are using as main 78 | Xil_DCacheInvalidateRange((int)main_memory,MEMORY_SIZE); 79 | Xil_ICacheInvalidateRange((int)main_memory,MEMORY_SIZE); 80 | for(int i = 0; i < MEMORY_SIZE; i++) 81 | main_memory[i] = 0; 82 | // Read program counter and clock enable values 83 | // To make sure processor isn't running 84 | read_pc = Xil_In32(USR_RISCV_PC); 85 | read_ce = Xil_In32(USR_RISCV_CE); 86 | printf("\nPC value: %d\n CE value: %d\n",read_pc,read_ce); 87 | // Processor needs to know base adress of memory, 88 | // It will start executing from this locatons onward. 89 | printf("\nThis is first memory address %p\n",&main_memory[0]); 90 | Xil_Out32(USR_MEM_BASE_ADDRESS, (u32)&main_memory[0]); 91 | 92 | // *************** INITIALIZE WITH MACHINE CODE ***************************************** 93 | // Find size of assembly program (machine code), then initialize memory 94 | size_t assembly_num_el = sizeof(assembly)/sizeof(assembly[0]); 95 | for (int i=0; i