├── syn ├── basys3 │ ├── device.mak │ ├── hdl_filelist.tcl │ └── constraint_filelist.tcl ├── zedboard │ ├── device.mak │ ├── hdl_filelist.tcl │ └── constraint_filelist.tcl ├── common │ └── hdl_filelist.tcl ├── README.md ├── synth.tcl ├── route.tcl └── Makefile ├── bitstreams └── README.md ├── doc ├── Rudi-RV32i.pdf ├── System_diagram.pdf └── README.md ├── src ├── test_benches │ ├── README.md │ └── tb_riscv_test.vhd ├── boards │ ├── zedboard │ │ ├── README.md │ │ └── zedboard_top_level.vhd │ └── basys3 │ │ ├── README.md │ │ ├── cmod_a7.xdc │ │ ├── basys3.xdc │ │ └── basys3_top_level.vhd ├── systems │ ├── README.md │ └── top_level.vhd ├── peripheral │ ├── README.md │ ├── peripheral_ram.vhd │ ├── peripheral_millis.vhd │ ├── peripheral_gpio.vhd │ └── peripheral_serial.vhd ├── program_memory │ ├── README.md │ ├── ram_memory.vhd │ ├── ram_memory_test.vhd │ └── program_memory_test.vhd ├── README.md ├── cpu │ ├── README.md │ ├── data_bus_mux_a.vhd │ ├── data_bus_mux_b.vhd │ ├── result_bus_mux.vhd │ ├── register_file.vhd │ ├── sign_extender.vhd │ ├── alu.vhd │ ├── branch_test.vhd │ ├── shifter.vhd │ ├── program_counter.vhd │ └── riscv_cpu.vhd └── bus │ ├── README.md │ ├── bus_expander.vhd │ └── bus_bridge.vhd ├── vivado ├── build.sh ├── README.md ├── sim.tcl └── build.tcl ├── .gitignore ├── c ├── Makefile ├── README.md ├── setup.s ├── linker_script ├── gen_mem.sh ├── test.c ├── template_ram_memory.vhd └── template_program_memory.vhd ├── LICENSE └── README.md /syn/basys3/device.mak: -------------------------------------------------------------------------------- 1 | DEVICE ?= xc7a35tcpg236-1 2 | -------------------------------------------------------------------------------- /syn/zedboard/device.mak: -------------------------------------------------------------------------------- 1 | DEVICE ?= xc7z020-clg484-1 2 | -------------------------------------------------------------------------------- /bitstreams/README.md: -------------------------------------------------------------------------------- 1 | ./bitstreams - the target location for the ./vivado/build.tcl script 2 | -------------------------------------------------------------------------------- /doc/Rudi-RV32i.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hamsternz/Rudi-RV32I/HEAD/doc/Rudi-RV32i.pdf -------------------------------------------------------------------------------- /src/test_benches/README.md: -------------------------------------------------------------------------------- 1 | src/test_benches - Test benches that can be used to verify the RTL 2 | -------------------------------------------------------------------------------- /doc/System_diagram.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hamsternz/Rudi-RV32I/HEAD/doc/System_diagram.pdf -------------------------------------------------------------------------------- /syn/basys3/hdl_filelist.tcl: -------------------------------------------------------------------------------- 1 | # board specific stuff 2 | read_vhdl ../../src/boards/basys3/basys3_top_level.vhd 3 | -------------------------------------------------------------------------------- /vivado/build.sh: -------------------------------------------------------------------------------- 1 | . /opt/Xilinx/Vivado/2019.2/settings64.sh 2 | echo source build.tcl | vivado -mode tcl 3 | 4 | -------------------------------------------------------------------------------- /syn/zedboard/hdl_filelist.tcl: -------------------------------------------------------------------------------- 1 | # board specific stuff 2 | read_vhdl ../../src/boards/zedboard/zedboard_top_level.vhd 3 | -------------------------------------------------------------------------------- /syn/basys3/constraint_filelist.tcl: -------------------------------------------------------------------------------- 1 | # Load files with project-specific constraints 2 | read_xdc ../../src/boards/basys3/basys3.xdc 3 | -------------------------------------------------------------------------------- /syn/zedboard/constraint_filelist.tcl: -------------------------------------------------------------------------------- 1 | # Load files with project-specific constraints 2 | read_xdc ../../src/boards/zedboard/zedboard.xdc 3 | -------------------------------------------------------------------------------- /doc/README.md: -------------------------------------------------------------------------------- 1 | ./doc - documentation for the Rudi-RV32I project 2 | 3 | Files in this directory: 4 | 5 | * Rudi-RV32I.pdf - The structure diagram for the CPU 6 | * System_diagram.pdf - The structure of a useful system. 7 | -------------------------------------------------------------------------------- /src/boards/zedboard/README.md: -------------------------------------------------------------------------------- 1 | ./src/boards/zedboard - Board specific top level designs, and constraints 2 | 3 | - zedboard.xdc - Constriants for a system with Serial and LEDs. 4 | - zedboard_top_level.vhd - HDL for top level with serial and GPIO. 5 | -------------------------------------------------------------------------------- /src/boards/basys3/README.md: -------------------------------------------------------------------------------- 1 | ./src/boards/basys3 - Board specific top level designs, and constraints 2 | 3 | - basys3.xdc - Constriants for a system with Serial and LEDs. 4 | - basys3_top_level.vhd - HDL for top level with serial and GPIO. 5 | - cmod_a7.xdc - Constriants for a system with just serial (not used) 6 | -------------------------------------------------------------------------------- /src/systems/README.md: -------------------------------------------------------------------------------- 1 | src/systems - Complete systems (CPU, bus and perhiperals) 2 | 3 | Files in this directory are: 4 | 5 | - top_level.vhd - A system with a serial port, 4kB RAM and 4kB ROM. Used during testing 6 | - top_level_expanded.vhd - An expanded system, with serial, 16-bit GPIO, 4kB RAM and 4kB ROM. 7 | -------------------------------------------------------------------------------- /src/peripheral/README.md: -------------------------------------------------------------------------------- 1 | src/perhierals - Various things that can be hung off of the CPU bus 2 | 3 | - README.md - This file 4 | - peripheral_gpio.vhd - A GPIO port 5 | - peripheral_millis.vhd - A millisecond counter peripheral 6 | - peripheral_ram.vhd - A sample RAM block 7 | - peripheral_serial - A serial port 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | backups 2 | backup.sh 3 | c/test 4 | bitstreams/basys3_top_level.bit 5 | vivado/.Xil/ 6 | vivado/riscv.cache/ 7 | vivado/riscv.hw/ 8 | vivado/riscv.ip_user_files/ 9 | vivado/riscv.runs/ 10 | vivado/riscv.sim/ 11 | vivado/riscv.xpr 12 | vivado/tb_riscv_behav.wcfg 13 | vivado/usage_statistics_webtalk.html 14 | vivado/usage_statistics_webtalk.xml 15 | -------------------------------------------------------------------------------- /src/program_memory/README.md: -------------------------------------------------------------------------------- 1 | ./src/program_memory - HDL Files that contain the program memory and RAM contents. 2 | 3 | - README.md - This file 4 | - program_memory.vhd - Empty 4kB ROM component 5 | - ram_memory.vhd - Empty 4kB RAM component 6 | - program_memory_test.vhd - ROM generated from ../c/test.c using the gen_mem.sh script 7 | - ram_memory_test.vhd - RAM generated from ../c/test.c using the gen_mem.sh script 8 | -------------------------------------------------------------------------------- /vivado/README.md: -------------------------------------------------------------------------------- 1 | ./vivado - Odds and ends to help with the Xilinx Vivado tools 2 | 3 | In this directory: 4 | 5 | - README.md - This file 6 | - build.sh - Bash script to launch Vivado to generate a bitstream 7 | - build.tcl - TCL script to build the design (without writing the bitstream) 8 | - test.sh - Bash script to run the basic ISA tests. 9 | - test.tcl - TCL script to run the test bench to verify basic ISA operation 10 | 11 | If you want to use the GUI create your own Vivado project and just add in the required VHDL and constraints. 12 | -------------------------------------------------------------------------------- /src/README.md: -------------------------------------------------------------------------------- 1 | ./src - The FPGA HDL source 2 | 3 | This directory contains: 4 | 5 | * README.md - This file 6 | * boards - Board specific files (HDL and constraints) 7 | * bus - HDL for the bus adpaters that connect the CPU to peripherals 8 | * cpu - The main CPU design HDL files 9 | * peripheral - HDL for peripherals that can be hung of the bus 10 | * program_memory - RAM and ROM HDL files 11 | * systems - HDL for complete system definitions (CPU + Memory + Peripherals) 12 | * test_benches - Test benchs that can be used during validation and testing 13 | -------------------------------------------------------------------------------- /src/cpu/README.md: -------------------------------------------------------------------------------- 1 | src/cpu - A RISC-V 32-bit RV32I CPU 2 | 3 | * README.md - This file 4 | * alu.vhd - Arithmetic and Logic Unit 5 | * branch_test.vhd - testing for conditional branches 6 | * data_bus_mux_a.vhd - MUX that directs data into the 'A' side of the ALU and Shifter. 7 | * data_bus_mux_b.vhd - MUX that directs data into the 'B' side of the ALU and Shifter. 8 | * decode.vhd - Instruction Decoder 9 | * program_counter.vhd - Manages the program counter 10 | * register_file.vhd - The register file 11 | * result_bus_mux.vhd - Selects what will be written back to the register file 12 | * riscv_cpu.vhd - Top level structural design of the CPU 13 | * shifter.vhd - Barrel shifter 14 | * sign_extender.vhd - Masks and sign-extends values coming from memory. 15 | -------------------------------------------------------------------------------- /c/Makefile: -------------------------------------------------------------------------------- 1 | CC=/opt/riscv/bin/riscv32-unknown-linux-gnu-gcc 2 | AS=/opt/riscv/bin/riscv32-unknown-linux-gnu-as 3 | COPTS= -Wall -pedantic 4 | 5 | all : test 6 | ./gen_mem.sh test 7 | rm setup.o test.o 8 | 9 | test : test.o setup.o 10 | echo "---------------------------------------------------------" >> /dev/null 11 | echo "-- Do not call anything main() - it will end up linked at" >> /dev/null 12 | echo "-- the start of the program, rather than the setup code" >> /dev/null 13 | echo "---------------------------------------------------------" >> /dev/null 14 | /opt/riscv/bin/riscv32-unknown-linux-gnu-ld -Ttext 0xF0000000 -Tdata 0x10000000 -T linker_script setup.o test.o -o test /opt/riscv/lib/gcc/riscv32-unknown-linux-gnu/9.2.0/libgcc.a 15 | 16 | 17 | setup.o : setup.s 18 | $(AS) -o setup.o --march=rv32i setup.s 19 | 20 | test.o : test.c 21 | $(CC) -c test.c $(COPTS) 22 | 23 | -------------------------------------------------------------------------------- /src/bus/README.md: -------------------------------------------------------------------------------- 1 | ./src/bus - Bus adapters to allow peripherals to be connected to the CPU 2 | 3 | Bus bridges connect the CPU to peripherals 4 | 5 | - README.md - this file 6 | - bus_bridge.vhd - Can connect the top level CPU bus to three devices (usually RAM, ROM and one peripheral) 7 | - bus_expander.vhd - Expands one device port to three more device ports 8 | 9 | If you set "use_clk" to '1' on these the bus will be registered, increasing latency of loads and stores 10 | by one cycle, but possibly improving overall system timing. 11 | 12 | NOTE: Output bus addresses are masked using the "window mask", setting these bits 13 | to zero. So say you connect a bus to 0xE000000 with the mask of 0xFFFF0000, the 14 | addresses on the device will be mapped to 0x00000000 to 0x0000FFFF - so the downstream 15 | devices should then be looking for that range. If you look for the original 16 | 0xE0000000-0xE000FFFF range you will never see it! 17 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Mike Field 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 all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /syn/common/hdl_filelist.tcl: -------------------------------------------------------------------------------- 1 | # These are files that are common to any boards 2 | 3 | # read all design files 4 | read_vhdl ../../src/systems/top_level_expanded.vhd 5 | 6 | # The CPU design 7 | read_vhdl ../../src/cpu/riscv_cpu.vhd 8 | read_vhdl ../../src/cpu/decode.vhd 9 | read_vhdl ../../src/cpu/data_bus_mux_a.vhd 10 | read_vhdl ../../src/cpu/data_bus_mux_b.vhd 11 | read_vhdl ../../src/cpu/result_bus_mux.vhd 12 | read_vhdl ../../src/cpu/program_counter.vhd 13 | read_vhdl ../../src/cpu/shifter.vhd 14 | read_vhdl ../../src/cpu/alu.vhd 15 | read_vhdl ../../src/cpu/sign_extender.vhd 16 | read_vhdl ../../src/cpu/register_file.vhd 17 | read_vhdl ../../src/cpu/branch_test.vhd 18 | 19 | # The Program ROM and RAM 20 | read_vhdl ../../src/program_memory/program_memory_test.vhd 21 | read_vhdl ../../src/program_memory/ram_memory_test.vhd 22 | 23 | # The 'external' CPU bus - bridge, RAM and Serial peripherals 24 | read_vhdl ../../src/bus/bus_bridge.vhd 25 | read_vhdl ../../src/bus/bus_expander.vhd 26 | read_vhdl ../../src/peripheral/peripheral_gpio.vhd 27 | read_vhdl ../../src/peripheral/peripheral_ram.vhd 28 | read_vhdl ../../src/peripheral/peripheral_serial.vhd 29 | read_vhdl ../../src/peripheral/peripheral_millis.vhd 30 | -------------------------------------------------------------------------------- /vivado/sim.tcl: -------------------------------------------------------------------------------- 1 | # read all design files 2 | read_vhdl ../src/cpu/sign_extender.vhd 3 | read_vhdl ../src/cpu/data_bus_mux_a.vhd 4 | read_vhdl ../src/cpu/decode.vhd 5 | read_vhdl ../src/cpu/data_bus_mux_b.vhd 6 | read_vhdl ../src/cpu/program_counter.vhd 7 | read_vhdl ../src/cpu/alu.vhd 8 | read_vhdl ../src/cpu/result_bus_mux.vhd 9 | read_vhdl ../src/cpu/riscv_cpu.vhd 10 | read_vhdl ../src/cpu/register_file.vhd 11 | read_vhdl ../src/cpu/branch_test.vhd 12 | read_vhdl ../src/cpu/shifter.vhd 13 | 14 | # Top level system design (CPU + Memories + Peripherals) 15 | read_vhdl ../src/systems/top_level.vhd 16 | read_vhdl ../src/systems/top_level_expanded.vhd 17 | 18 | # The memory containing test code 19 | read_vhdl ../src/program_memory/program_memory.vhd 20 | read_vhdl ../src/program_memory/ram_memory.vhd 21 | 22 | # The CPU bus - bridge, RAM and Serial peripherals 23 | read_vhdl ../src/bus/bus_bridge.vhd 24 | read_vhdl ../src/peripheral/peripheral_serial.vhd 25 | read_vhdl ../src/peripheral/peripheral_gpio.vhd 26 | read_vhdl ../src/peripheral/peripheral_ram.vhd 27 | 28 | # Test bench 29 | read_vhdl ../src/test_benches/tb_riscv.vhd 30 | 31 | save_project_as sim -force 32 | set_property top tb_riscv [get_fileset sim_1] 33 | launch_simulation -simset sim_1 -mode behavioral 34 | run 5us 35 | quit 36 | -------------------------------------------------------------------------------- /src/test_benches/tb_riscv_test.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------- 2 | -- Company: 3 | -- Engineer: 4 | -- 5 | -- Create Date: 17.12.2019 23:11:15 6 | -- Design Name: 7 | -- Module Name: tb_riscv - Behavioral 8 | -- Project Name: 9 | -- Target Devices: 10 | -- Tool Versions: 11 | -- Description: 12 | -- 13 | -- Dependencies: 14 | -- 15 | -- Revision: 16 | -- Revision 0.01 - File Created 17 | -- Additional Comments: 18 | -- 19 | ---------------------------------------------------------------------------------- 20 | 21 | 22 | library IEEE; 23 | use IEEE.STD_LOGIC_1164.ALL; 24 | 25 | entity tb_riscv is 26 | end tb_riscv; 27 | 28 | architecture Behavioral of tb_riscv is 29 | 30 | component top_level is 31 | port ( clk : in STD_LOGIC; 32 | debug_sel : in STD_LOGIC_VECTOR(4 downto 0); 33 | debug_data : out STD_LOGIC_VECTOR(31 downto 0)); 34 | end component; 35 | 36 | signal clk : std_logic := '0'; 37 | signal debug_sel : STD_LOGIC_VECTOR( 4 downto 0) := "00001"; 38 | signal debug_data : STD_LOGIC_VECTOR(31 downto 0); 39 | signal cache_last_addr : std_logic := '0'; 40 | begin 41 | 42 | process 43 | begin 44 | wait for 5 ns; 45 | clk <= '0'; 46 | wait for 5 ns; 47 | clk <= '1'; 48 | end process; 49 | 50 | 51 | i_top_level: top_level port map( 52 | clk => clk, 53 | 54 | debug_sel => debug_sel, 55 | debug_data => debug_data); 56 | end Behavioral; 57 | 58 | -------------------------------------------------------------------------------- /c/README.md: -------------------------------------------------------------------------------- 1 | ./c - files to support programming The Rudi-RV32I using C. 2 | 3 | If you have the RISCV GCC toolset built and installed in /opt/riscv, you should be able to just run "make" to have test.c compiled and the resulting program and data converted into HDL in ../src/program_memory/. 4 | 5 | It compiles the program, links it and then extracts the resulting .data and .text segments, and merges it into template_program_memory.vhd and template_ram_memory.vhd - ready to be included in your design. 6 | 7 | The binary is linked such that RAM is located at 0x10000000 and program code at 0xF0000000. You need to reflect this in your system design. 8 | 9 | Files in this directory are: 10 | 11 | README.md - This file 12 | gen_mem.sh - Script to extract the .data and .text segments from a binary and convert to HDL 13 | linker_script - Custom linker script to control the placement of .rodata and sdata segments 14 | Makefile - Makefile to compile "test.c" and build the required HDL 15 | template_program_memory.vhd - The Template used to create the HDL to infer the program (ROM) memory 16 | template_ram_memory.vhd - The Template uses to create the HDL to infer the RAM memory 17 | test.c - A short sample test program 18 | setup.s - Assembler to set up the C environment (i.e. set the stack pointer to the end of RAM) 19 | 20 | If you have any weirdness, check for missing sections by running: 21 | 22 | /opt/riscv/bin/riscv32-unknown-linux-gnu-objdump -s test 23 | 24 | Everything should be in the .data or .text segments - oh, and .comment can be ignored) 25 | -------------------------------------------------------------------------------- /c/setup.s: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # c/setup.s - Set up the C execution environment 3 | # 4 | # Part of the Rudi-RV32I project 5 | # 6 | # See https://github.com/hamsternz/Rudi-RV32I 7 | # 8 | # MIT License 9 | # 10 | ############################################################################### 11 | # 12 | # Copyright (c) 2020 Mike Field 13 | # 14 | # Permission is hereby granted, free of charge, to any person obtaining a copy 15 | # of this software and associated documentation files (the "Software"), to deal 16 | # in the Software without restriction, including without limitation the rights 17 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | # copies of the Software, and to permit persons to whom the Software is 19 | # furnished to do so, subject to the following conditions: 20 | # 21 | # The above copyright notice and this permission notice shall be included in all 22 | # copies or substantial portions of the Software. 23 | # 24 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | # SOFTWARE. 31 | # 32 | ############################################################################### 33 | 34 | .text 35 | .align 2 36 | .globl _start 37 | .type _start, @function 38 | .org 0 39 | _start: 40 | lui a1,0x10001 41 | # Set the stack address to 0x10000FFC 42 | addi sp, a1, -4 43 | # Call the main function 44 | jal ra, test_program 45 | j _start 46 | -------------------------------------------------------------------------------- /src/boards/basys3/cmod_a7.xdc: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # cmod_a7.xdc - Constraints for the CMOD A7 board 3 | # 4 | # Part of the Rudi-RV32I project 5 | # 6 | # See https://github.com/hamsternz/Rudi-RV32I 7 | # 8 | # MIT License 9 | # 10 | ############################################################################### 11 | # 12 | # Copyright (c) 2020 Mike Field 13 | # 14 | # Permission is hereby granted, free of charge, to any person obtaining a copy 15 | # of this software and associated documentation files (the "Software"), to deal 16 | # in the Software without restriction, including without limitation the rights 17 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | # copies of the Software, and to permit persons to whom the Software is 19 | # furnished to do so, subject to the following conditions: 20 | # 21 | # The above copyright notice and this permission notice shall be included in all 22 | # copies or substantial portions of the Software. 23 | # 24 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | # SOFTWARE. 31 | # 32 | ############################################################################### 33 | ## 12 MHz Clock Signal 34 | set_property -dict { PACKAGE_PIN L17 IOSTANDARD LVCMOS33 } [get_ports { clk }]; #IO_L12P_T1_MRCC_14 Sch=gclk 35 | create_clock -add -name clk_pin -period 15.00 -waveform {0 7.5} [get_ports {clk}]; 36 | 37 | ## UART 38 | set_property -dict { PACKAGE_PIN J18 IOSTANDARD LVCMOS33 } [get_ports { uart_rxd_out }]; #IO_L7N_T1_D10_14 Sch=uart_rxd_out 39 | set_property -dict { PACKAGE_PIN J17 IOSTANDARD LVCMOS33 } [get_ports { uart_txd_in }]; #IO_L7P_T1_D09_14 Sch=uart_txd_in 40 | 41 | -------------------------------------------------------------------------------- /syn/README.md: -------------------------------------------------------------------------------- 1 | ## Usage: 2 | 3 | To build the full project, type `cd syn` then `make`. The default project is `basys3`. 4 | 5 | To build for another board/project, type `PROJECT=zedboard make` (replace `zedboard` with your project name). `make PROJECT=zedboard` also works. 6 | 7 | Build commands are: 8 | 9 | ​ `make` - Create a bitfile for this project 10 | 11 | ​ `make synth` - Only run synthesis for this project. 12 | 13 | ​ `make route` - Don't re-run synthesis, just place and route the design, then make a bitfile 14 | 15 | ​ `make clean` - Delete all build files (but not the bitfile) 16 | 17 | ​ `make clean_all` - Delete all build files (including the bitfile) 18 | 19 | The build flow will create a subdirectory under `/` which it will build in. It will create a `synth.dcp` file and a `route.dcp` file, which you can open in Vivado using "File -> Open Checkpoint". The final bitfile is saved under ``. 20 | 21 | 22 | 23 | ## Files: 24 | 25 | ./syn - The FPGA build area 26 | 27 | This directory contains: 28 | 29 | * README.md - This file 30 | * common/hdl_filelist.tcl (important) - a list of the VHDL files that are common to all boards 31 | * common/constraint_filelist.tcl (optional) - a list of constraint files that are common to all boards 32 | * /device.mak - A single line which gives the FPGA part 33 | * /hdl_filelist.tcl - a list of VHDL files that are unique to this board/project 34 | * /constraint_filelist.tcl - a list of constraint files that are unique to this board/project 35 | 36 | 37 | 38 | ## Board/Project Filename Requirements: 39 | 40 | If you're adding a new board/project, then you need: 41 | 42 | `syn//device.mak` - A single line which sets the FPGA part 43 | 44 | `syn//hdl_filelist.tcl` - a TCL file which points to the board-specific HDL files (kept in `src/boards//`) 45 | 46 | `syn//constraint_filelist.tcl` - a TCL file which points to the board-specific constraint files (kept in `src/boards//`) 47 | 48 | `src/boards//.xdc` (pointed to by `syn//constraint_filelist.tcl`) 49 | 50 | `src/boards//_top_level.vhd` (pointed to by `syn//hdl_filelist.tcl` ) 51 | 52 | -------------------------------------------------------------------------------- /syn/synth.tcl: -------------------------------------------------------------------------------- 1 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 | # Project TCL command file 3 | # See UG835: Vivado Design Suite Tcl Command Reference Guide for details 4 | 5 | 6 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 7 | # Read TCL script command-line arguments 8 | set OUT_DIR [ lindex $argv 0 ] 9 | set SYNTH_DCP [ lindex $argv 1 ] 10 | set DEVICE [ lindex $argv 2 ] 11 | set PROJECT [ lindex $argv 3 ] 12 | set PROJECT_TOP [ lindex $argv 4 ] 13 | 14 | 15 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 16 | # Create the Vivado project 17 | # Options used are: 18 | # -in_memory : Create an in-memory project 19 | create_project -in_memory -part ${DEVICE} 20 | 21 | set_property target_language VHDL [ current_project ] 22 | 23 | 24 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 25 | # Load the project's source files 26 | # If a common HDL filelist exists, then load that file first 27 | if { [file exists "common/hdl_filelist.tcl"] == 1} { 28 | cd common 29 | source hdl_filelist.tcl 30 | cd .. 31 | } 32 | cd ${PROJECT} 33 | source hdl_filelist.tcl 34 | cd .. 35 | 36 | 37 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 38 | # Read physical and timing constraints from one of more files 39 | # If a common set of constraints exists, then load that file first 40 | if { [file exists "common/constraint_filelist.tcl"] == 1} { 41 | cd common 42 | source constraint_filelist.tcl 43 | cd .. 44 | } 45 | cd ${PROJECT} 46 | source constraint_filelist.tcl 47 | cd .. 48 | 49 | 50 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 51 | # Synthesize a design using Vivado Synthesis and open that design 52 | # synth_design [-generic G_BLAHBLAH] -top -part 53 | # Options used are: 54 | # -top : Specify the top module name 55 | # -part : Target part 56 | synth_design -top ${PROJECT_TOP} -part ${DEVICE} -flatten_hierarchy none 57 | 58 | 59 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 60 | # Write a checkpoint of the current design. 61 | # Options used are: 62 | # -force : overwrite existing 63 | write_checkpoint ${OUT_DIR}/${SYNTH_DCP}.dcp -force 64 | -------------------------------------------------------------------------------- /syn/route.tcl: -------------------------------------------------------------------------------- 1 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 2 | # Project TCL command file 3 | # See UG835: Vivado Design Suite Tcl Command Reference Guide for details 4 | 5 | 6 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 7 | # Read TCL script command-line arguments 8 | set OUT_DIR [ lindex $argv 0 ] 9 | set SYNTH_DCP [ lindex $argv 1 ] 10 | set ROUTE_DCP [ lindex $argv 2 ] 11 | set PROJECT [ lindex $argv 3 ] 12 | 13 | 14 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 15 | # Open a design checkpoint in a new project 16 | # Options used are: 17 | # (none) 18 | open_checkpoint ${OUT_DIR}/${SYNTH_DCP}.dcp 19 | 20 | 21 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 22 | # Optimize the current netlist. This will perform the retarget, propconst, 23 | # sweep and bram_power_opt optimizations by default. 24 | # Options used are: 25 | # (none) 26 | opt_design 27 | 28 | 29 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 30 | # Automatically place ports and leaf-level instances. 31 | # Options used are: 32 | # (none) 33 | place_design 34 | 35 | 36 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 37 | # Route the current design 38 | # Options used are: 39 | # (none) 40 | route_design 41 | 42 | 43 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 44 | # Check the design for possible timing problems 45 | # Options used are: 46 | # -file : Filename to output results to. 47 | check_timing -file ${OUT_DIR}/${ROUTE_DCP}_timing.txt 48 | 49 | 50 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 51 | # Generate the FPGA usage report 52 | # Options used are: 53 | # -file : Filename to output results to. 54 | report_utilization -file ${OUT_DIR}/${ROUTE_DCP}_util.txt 55 | 56 | 57 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 58 | # Write a checkpoint of the current design. 59 | # Options used are: 60 | # -force : overwrite existing 61 | write_checkpoint ${OUT_DIR}/${ROUTE_DCP}.dcp -force 62 | 63 | 64 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 65 | # Write a bitstream for the current design. 66 | # Options used are: 67 | # -force : Overwrite existing file 68 | write_bitstream ${PROJECT}/${PROJECT}.bit -force 69 | -------------------------------------------------------------------------------- /src/cpu/data_bus_mux_a.vhd: -------------------------------------------------------------------------------- 1 | --############################################################################### 2 | --# data_bus_mux_a.vhd - The MUX for the A data bus 3 | --# 4 | --# Part of the Rudi-RV32I project 5 | --# 6 | --# See https://github.com/hamsternz/Rudi-RV32I 7 | --# 8 | --# MIT License 9 | --# 10 | --############################################################################### 11 | --# 12 | --# Copyright (c) 2020 Mike Field 13 | --# 14 | --# Permission is hereby granted, free of charge, to any person obtaining a copy 15 | --# of this software and associated documentation files (the "Software"), to deal 16 | --# in the Software without restriction, including without limitation the rights 17 | --# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | --# copies of the Software, and to permit persons to whom the Software is 19 | --# furnished to do so, subject to the following conditions: 20 | --# 21 | --# The above copyright notice and this permission notice shall be included in all 22 | --# copies or substantial portions of the Software. 23 | --# 24 | --# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | --# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | --# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | --# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | --# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | --# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | --# SOFTWARE. 31 | --# 32 | --############################################################################### 33 | 34 | library IEEE; 35 | use IEEE.STD_LOGIC_1164.ALL; 36 | use IEEE.numeric_std.all; 37 | 38 | 39 | entity data_bus_mux_a is 40 | port ( bus_select : in STD_LOGIC_VECTOR( 0 downto 0); 41 | zero : in STD_LOGIC_VECTOR( 0 downto 0); 42 | reg_read_port : in STD_LOGIC_VECTOR(31 downto 0); 43 | pc : in STD_LOGIC_VECTOR(31 downto 0); 44 | data_bus : out STD_LOGIC_VECTOR(31 downto 0)); 45 | end entity; 46 | 47 | architecture Behavioral of data_bus_mux_a is 48 | -- MUXing for the A and B data buses - must agree with decode.vhd 49 | constant A_BUS_REGISTER : STD_LOGIC_VECTOR(0 downto 0) := "0"; 50 | constant A_BUS_PC : STD_LOGIC_VECTOR(0 downto 0) := "1"; 51 | begin 52 | 53 | process(bus_select, reg_read_port, pc, zero) 54 | begin 55 | if zero = "1" then 56 | data_bus <= (others => '0'); 57 | else 58 | case bus_select is 59 | when A_BUS_PC => 60 | data_bus <= pc; 61 | when others => 62 | data_bus <= reg_read_port; 63 | end case; 64 | end if; 65 | end process; 66 | 67 | end Behavioral; 68 | -------------------------------------------------------------------------------- /src/cpu/data_bus_mux_b.vhd: -------------------------------------------------------------------------------- 1 | --############################################################################### 2 | --# data_bus_mux_b.vhd - The mux for the B data bus 3 | --# 4 | --# Part of the Rudi-RV32I project 5 | --# 6 | --# See https://github.com/hamsternz/Rudi-RV32I 7 | --# 8 | --# MIT License 9 | --# 10 | --############################################################################### 11 | --# 12 | --# Copyright (c) 2020 Mike Field 13 | --# 14 | --# Permission is hereby granted, free of charge, to any person obtaining a copy 15 | --# of this software and associated documentation files (the "Software"), to deal 16 | --# in the Software without restriction, including without limitation the rights 17 | --# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | --# copies of the Software, and to permit persons to whom the Software is 19 | --# furnished to do so, subject to the following conditions: 20 | --# 21 | --# The above copyright notice and this permission notice shall be included in all 22 | --# copies or substantial portions of the Software. 23 | --# 24 | --# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | --# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | --# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | --# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | --# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | --# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | --# SOFTWARE. 31 | --# 32 | --############################################################################### 33 | 34 | library IEEE; 35 | use IEEE.STD_LOGIC_1164.ALL; 36 | use IEEE.numeric_std.all; 37 | 38 | 39 | entity data_bus_mux_b is 40 | port ( bus_select : in STD_LOGIC_VECTOR( 0 downto 0); 41 | zero : in STD_LOGIC_VECTOR( 0 downto 0); 42 | reg_read_port : in STD_LOGIC_VECTOR(31 downto 0); 43 | immedediate : in STD_LOGIC_VECTOR(31 downto 0); 44 | data_bus : out STD_LOGIC_VECTOR(31 downto 0)); 45 | end entity; 46 | 47 | architecture Behavioral of data_bus_mux_b is 48 | -- MUXing for the B data bus - must agree with decode.vhd 49 | constant B_BUS_REGISTER : STD_LOGIC_VECTOR(0 downto 0) := "0"; 50 | constant B_BUS_IMMEDIATE : STD_LOGIC_VECTOR(0 downto 0) := "1"; 51 | begin 52 | 53 | process(bus_select, reg_read_port, immedediate, zero) 54 | begin 55 | if zero = "1" then 56 | data_bus <= (others => '0'); 57 | else 58 | case bus_select is 59 | when B_BUS_IMMEDIATE => 60 | data_bus <= immedediate; 61 | when others => 62 | data_bus <= reg_read_port; 63 | end case; 64 | end if; 65 | end process; 66 | 67 | end Behavioral; 68 | -------------------------------------------------------------------------------- /c/linker_script: -------------------------------------------------------------------------------- 1 | /******************************************************************************* 2 | # c/linker_script - script to generate HDL memory files 3 | # 4 | # Part of the Rudi-RV32I project 5 | # 6 | # See https://github.com/hamsternz/Rudi-RV32I 7 | # 8 | # MIT License 9 | # 10 | ############################################################################### 11 | # 12 | # Copyright (c) 2020 Mike Field 13 | # 14 | # Permission is hereby granted, free of charge, to any person obtaining a copy 15 | # of this software and associated documentation files (the "Software"), to deal 16 | # in the Software without restriction, including without limitation the rights 17 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | # copies of the Software, and to permit persons to whom the Software is 19 | # furnished to do so, subject to the following conditions: 20 | # 21 | # The above copyright notice and this permission notice shall be included in all 22 | # copies or substantial portions of the Software. 23 | # 24 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | # SOFTWARE. 31 | # 32 | *******************************************************************************/ 33 | 34 | OUTPUT_FORMAT("elf32-littleriscv", "elf32-littleriscv", "elf32-littleriscv") 35 | OUTPUT_ARCH(riscv) 36 | ENTRY(_start) 37 | 38 | SEARCH_DIR("=/opt/riscv/riscv32-unknown-linux-gnu/lib32/ilp32d"); SEARCH_DIR("=/opt/riscv/riscv32-unknown-linux-gnu/lib32"); SEARCH_DIR("=/usr/local/lib32/ilp32d"); SEARCH_DIR("=/usr/local/lib32"); SEARCH_DIR("=/lib32/ilp32d"); SEARCH_DIR("=/lib32"); SEARCH_DIR("=/usr/lib32/ilp32d"); SEARCH_DIR("=/usr/lib32"); SEARCH_DIR("=/opt/riscv/riscv32-unknown-linux-gnu/lib"); SEARCH_DIR("=/usr/local/lib"); SEARCH_DIR("=/lib"); SEARCH_DIR("=/usr/lib"); 39 | 40 | SECTIONS 41 | { 42 | .text : 43 | { 44 | *(.text.unlikely .text.*_unlikely .text.unlikely.*) 45 | *(.text.exit .text.exit.*) 46 | *(.text.startup .text.startup.*) 47 | *(.text.hot .text.hot.*) 48 | *(.text .stub .text.* .gnu.linkonce.t.*) 49 | /* Put .rodata in .text */ 50 | *(.rodata .rodata.* .gnu.linkonce.r.*) 51 | *(.rodata1) 52 | /* .gnu.warning sections are handled specially by elf32.em. */ 53 | *(.gnu.warning) 54 | } 55 | .data : 56 | { 57 | __DATA_BEGIN__ = .; 58 | *(.data .data.* .gnu.linkonce.d.*) 59 | SORT(CONSTRUCTORS) 60 | *(.srodata.cst16) *(.srodata.cst8) *(.srodata.cst4) *(.srodata.cst2) *(.srodata .srodata.*) 61 | *(.sdata .sdata.* .gnu.linkonce.s.*) 62 | *(.sdata2 .sdata2.* .gnu.linkonce.s2.*) 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /syn/Makefile: -------------------------------------------------------------------------------- 1 | # ========================================================================= 2 | # Makefile syntax: 3 | # variable = value 4 | # variable ?= value (if value isn't already set, such as an environment variable) 5 | # 6 | # target: dependency1 dependency2 ... 7 | # command 8 | 9 | # ========================================================================= 10 | # Key project names and directories 11 | # Note: The top level HDL file must be named ${PROJECT}_top_level 12 | # The build system expects it to be placed in Rudi-RV32I\src\boards\${PROJECT} 13 | PROJECT ?= basys3 14 | PROJECT_TOP ?= ${PROJECT}_top_level 15 | 16 | # Set the FPGA device and output directory 17 | include ${PROJECT}/device.mak 18 | OUT_DIR = ${PROJECT}/${DEVICE} 19 | 20 | 21 | # ========================================================================= 22 | # Build names 23 | SYNTH_NAME = synth 24 | ROUTE_NAME = route 25 | 26 | 27 | # ========================================================================= 28 | # Xilinx Vivado build flags are in the respective '.tcl' files 29 | # See UG894 for details 30 | 31 | 32 | # ========================================================================= 33 | # Build recipes 34 | # 00 - Miscellaneous 'make' recpies 35 | # 36 | # 01a - Load design/cores: read_vhdl xxx.vhd read_checkpoint xxx.dcp 37 | # 01b - Synthesis: synth_design 38 | # 39 | # 02 - Place and Route: 40 | # 02a - Optimisation: opt_design -verbose 41 | # 02b - Place: place_design 42 | # 02c - Route: route_design 43 | # 44 | # 03 - BitGen (Bitstream Generation): write_bitstream 45 | 46 | 47 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 48 | # 00a - Make everything 49 | # Typing 'make' by itself runs the first target entry in the makefile 50 | all: synth route 51 | 52 | # 00b - Housekeeping 53 | clean: 54 | rm -fR .Xil ${PROJECT}/${DEVICE} 55 | 56 | clean_all: 57 | rm -fR .Xil ${PROJECT}/${DEVICE} ${PROJECT}/${PROJECT}.bit 58 | 59 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 60 | # 01 - Synthesis 61 | .PHONY: synth 62 | synth: ${OUT_DIR}/${SYNTH_NAME}.dcp 63 | ${OUT_DIR}/${SYNTH_NAME}.dcp : ../src/boards/${PROJECT}/${PROJECT_TOP}.vhd ${SYNTH_NAME}.tcl 64 | 65 | # Invoke the synthesis script 66 | @echo 67 | @echo 68 | @echo '## --- Running Synthesis --- ##' 69 | @echo 70 | mkdir -p ${OUT_DIR} 71 | vivado -mode batch -source ${SYNTH_NAME}.tcl \ 72 | -log ${OUT_DIR}/${SYNTH_NAME}.log -journal ${OUT_DIR}/${SYNTH_NAME}.jou \ 73 | -tclargs ${OUT_DIR} ${SYNTH_NAME} ${DEVICE} ${PROJECT} ${PROJECT_TOP} 74 | 75 | 76 | # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 77 | # 02 - Optimise, Place and Route: route_design 78 | .PHONY: route 79 | route: ${OUT_DIR}/${ROUTE_NAME}.dcp 80 | ${OUT_DIR}/${ROUTE_NAME}.dcp : ${OUT_DIR}/${SYNTH_NAME}.dcp ${ROUTE_NAME}.tcl 81 | 82 | # Invoke the opt, place and route script 83 | @echo 84 | @echo 85 | @echo '## --- Running Place and Route --- ##' 86 | @echo 87 | vivado -mode batch -source ${ROUTE_NAME}.tcl \ 88 | -log ${OUT_DIR}/${ROUTE_NAME}.log -journal ${OUT_DIR}/${ROUTE_NAME}.jou \ 89 | -tclargs ${OUT_DIR} ${SYNTH_NAME} ${ROUTE_NAME} ${PROJECT} 90 | -------------------------------------------------------------------------------- /c/gen_mem.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ############################################################################### 3 | # gen_mem.sh - script to generate HDL memory files 4 | # 5 | # Part of the Rudi-RV32I project 6 | # 7 | # See https://github.com/hamsternz/Rudi-RV32I 8 | # 9 | # MIT License 10 | # 11 | ############################################################################### 12 | # 13 | # Copyright (c) 2020 Mike Field 14 | # 15 | # Permission is hereby granted, free of charge, to any person obtaining a copy 16 | # of this software and associated documentation files (the "Software"), to deal 17 | # in the Software without restriction, including without limitation the rights 18 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 19 | # copies of the Software, and to permit persons to whom the Software is 20 | # furnished to do so, subject to the following conditions: 21 | # 22 | # The above copyright notice and this permission notice shall be included in all 23 | # copies or substantial portions of the Software. 24 | # 25 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 26 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 27 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 28 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 29 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 30 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 31 | # SOFTWARE. 32 | # 33 | ############################################################################### 34 | OBJCOPY=/opt/riscv/bin/riscv32-unknown-linux-gnu-objcopy 35 | 36 | if [ ! -f "$1" ] 37 | then 38 | echo No file name given 39 | exit 40 | fi 41 | 42 | $OBJCOPY $1 /dev/null --dump-section .data=data.section.$$ --dump-section .text=text.section.$$ 43 | 44 | if [ ! -f data.section.$$ -o ! -f text.section.$$ ] 45 | then 46 | echo Unable to dump sections 47 | exit 48 | fi 49 | 50 | ( 51 | ############################# 52 | ##### Output file header 53 | ############################# 54 | grep ^H: template_program_memory.vhd | cut -c 3- 55 | 56 | ############################# 57 | ##### Output Program data 58 | ############################# 59 | cat text.section.$$ | od -An -w4 -v -tx4 | awk '{ print " " NR-1 " => x\"" $1 "\"," }' 60 | 61 | ############################# 62 | ##### Output file footer 63 | ############################# 64 | grep ^F: template_program_memory.vhd | cut -c 3- 65 | ) > ../src/program_memory/program_memory_$1.vhd 66 | 67 | ( 68 | ############################# 69 | ##### Output file header 70 | ############################# 71 | grep ^H: template_ram_memory.vhd | cut -c 3- 72 | 73 | ############################# 74 | ##### Output Program data 75 | ############################# 76 | cat data.section.$$ | od -An -w4 -v -tx4 | awk '{ print " " NR-1 " => x\"" $1 "\"," }' 77 | 78 | ############################# 79 | ##### Output file footer 80 | ############################# 81 | grep ^F: template_ram_memory.vhd | cut -c 3- 82 | ) > ../src/program_memory/ram_memory_$1.vhd 83 | 84 | rm data.section.$$ text.section.$$ 85 | -------------------------------------------------------------------------------- /c/test.c: -------------------------------------------------------------------------------- 1 | /****************************************************************************** 2 | # test.c - A test C programm 3 | # 4 | # Part of the Rudi-RV32I project 5 | # 6 | # See https://github.com/hamsternz/Rudi-RV32I 7 | # 8 | # MIT License 9 | # 10 | ############################################################################### 11 | # 12 | # Copyright (c) 2020 Mike Field 13 | # 14 | # Permission is hereby granted, free of charge, to any person obtaining a copy 15 | # of this software and associated documentation files (the "Software"), to deal 16 | # in the Software without restriction, including without limitation the rights 17 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | # copies of the Software, and to permit persons to whom the Software is 19 | # furnished to do so, subject to the following conditions: 20 | # 21 | # The above copyright notice and this permission notice shall be included in all 22 | # copies or substantial portions of the Software. 23 | # 24 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | # SOFTWARE. 31 | # 32 | ******************************************************************************/ 33 | 34 | char text[] = "Hello world!\r\n"; 35 | char az[] = "Text "; 36 | char bz[] = " characters long\r\n"; 37 | 38 | volatile char *serial_tx = (char *)0xE0000000; 39 | volatile char *serial_tx_full = (char *)0xE0000004; 40 | volatile char *serial_rx = (char *)0xE0000008; 41 | volatile char *serial_rx_empty = (char *)0xE000000C; 42 | volatile int *gpio_value = (int *)0xE0000010; 43 | volatile int *gpio_direction = (int *)0xE0000014; 44 | 45 | int getchar(void) { 46 | 47 | // Wait until status is zero 48 | while(*serial_rx_empty) { 49 | } 50 | 51 | // Output character 52 | return *serial_rx; 53 | } 54 | 55 | int putchar(int c) { 56 | 57 | // Wait until status is zero 58 | while(*serial_tx_full) { 59 | } 60 | 61 | // Output character 62 | *serial_tx = c; 63 | return c; 64 | } 65 | 66 | int puts(char *s) { 67 | int n = 0; 68 | while(*s) { 69 | putchar(*s); 70 | s++; 71 | n++; 72 | } 73 | return n; 74 | } 75 | 76 | int mylen(char *s) { 77 | int n = 0; 78 | while(*s) { 79 | s++; 80 | n++; 81 | } 82 | return n; 83 | } 84 | 85 | int test_program(void) { 86 | puts("System restart\r\n"); 87 | 88 | /* Check some junk in memory */ 89 | puts("String is "); 90 | putchar('0'+mylen(az)); 91 | puts(" characters long\r\n"); 92 | 93 | puts(az); 94 | putchar('0'+mylen(az)); 95 | puts(bz); 96 | 97 | /* Run a serial port echo */ 98 | *gpio_direction = 0xFFFF; 99 | while(1) { 100 | putchar(getchar()); 101 | *gpio_value = *gpio_value + 1; 102 | } 103 | return 0; 104 | } 105 | -------------------------------------------------------------------------------- /vivado/build.tcl: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # build.tcl - A vivado build script 3 | # 4 | # Part of the Rudi-RV32I project 5 | # 6 | # See https://github.com/hamsternz/Rudi-RV32I 7 | # 8 | # MIT License 9 | # 10 | ############################################################################### 11 | # 12 | # Copyright (c) 2020 Mike Field 13 | # 14 | # Permission is hereby granted, free of charge, to any person obtaining a copy 15 | # of this software and associated documentation files (the "Software"), to deal 16 | # in the Software without restriction, including without limitation the rights 17 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | # copies of the Software, and to permit persons to whom the Software is 19 | # furnished to do so, subject to the following conditions: 20 | # 21 | # The above copyright notice and this permission notice shall be included in all 22 | # copies or substantial portions of the Software. 23 | # 24 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | # SOFTWARE. 31 | # 32 | ############################################################################### 33 | 34 | set_part "xc7a35tcpg236-1" 35 | 36 | # read all design files 37 | read_vhdl ../src/systems/top_level_expanded.vhd 38 | 39 | # The CPU design 40 | read_vhdl ../src/cpu/riscv_cpu.vhd 41 | read_vhdl ../src/cpu/decode.vhd 42 | read_vhdl ../src/cpu/data_bus_mux_a.vhd 43 | read_vhdl ../src/cpu/data_bus_mux_b.vhd 44 | read_vhdl ../src/cpu/result_bus_mux.vhd 45 | read_vhdl ../src/cpu/program_counter.vhd 46 | read_vhdl ../src/cpu/shifter.vhd 47 | read_vhdl ../src/cpu/alu.vhd 48 | read_vhdl ../src/cpu/sign_extender.vhd 49 | read_vhdl ../src/cpu/register_file.vhd 50 | read_vhdl ../src/cpu/branch_test.vhd 51 | 52 | # The Program ROM and RAM 53 | read_vhdl ../src/program_memory/program_memory_test.vhd 54 | read_vhdl ../src/program_memory/ram_memory_test.vhd 55 | 56 | # The 'external' CPU bus - bridge, RAM and Serial peripherals 57 | read_vhdl ../src/bus/bus_bridge.vhd 58 | read_vhdl ../src/bus/bus_expander.vhd 59 | read_vhdl ../src/peripheral/peripheral_gpio.vhd 60 | read_vhdl ../src/peripheral/peripheral_ram.vhd 61 | read_vhdl ../src/peripheral/peripheral_serial.vhd 62 | read_vhdl ../src/peripheral/peripheral_millis.vhd 63 | 64 | # board specific stuff 65 | read_vhdl ../src/boards/basys3_top_level.vhd 66 | read_xdc ../src/boards/basys3.xdc 67 | 68 | # Synthesize Design 69 | synth_design -top basys3_top_level -part "xc7a35tcpg236-1" -flatten_hierarchy none 70 | write_checkpoint basys3_top_level_synth.dcp 71 | 72 | # Opt Design 73 | opt_design 74 | # Place Design 75 | place_design 76 | # Route Design 77 | route_design 78 | 79 | write_checkpoint basys3_top_level_route.dcp 80 | 81 | # Write the bitstream 82 | write_bitstream -force -file ../bitstreams/basys3_top_level.bit 83 | 84 | # Generate reports 85 | report_timing -nworst 1 86 | report_utilization -hierarchical 87 | -------------------------------------------------------------------------------- /src/cpu/result_bus_mux.vhd: -------------------------------------------------------------------------------- 1 | --############################################################################### 2 | --# result_bus_mux - decides which result can be written back to the register file 3 | --# 4 | --# Part of the Rudi-RV32I project 5 | --# 6 | --# See https://github.com/hamsternz/Rudi-RV32I 7 | --# 8 | --# MIT License 9 | --# 10 | --############################################################################### 11 | --# 12 | --# Copyright (c) 2020 Mike Field 13 | --# 14 | --# Permission is hereby granted, free of charge, to any person obtaining a copy 15 | --# of this software and associated documentation files (the "Software"), to deal 16 | --# in the Software without restriction, including without limitation the rights 17 | --# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | --# copies of the Software, and to permit persons to whom the Software is 19 | --# furnished to do so, subject to the following conditions: 20 | --# 21 | --# The above copyright notice and this permission notice shall be included in all 22 | --# copies or substantial portions of the Software. 23 | --# 24 | --# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | --# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | --# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | --# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | --# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | --# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | --# SOFTWARE. 31 | --# 32 | --############################################################################### 33 | 34 | library IEEE; 35 | use IEEE.STD_LOGIC_1164.ALL; 36 | use IEEE.numeric_std.all; 37 | 38 | 39 | entity result_bus_mux is 40 | port ( res_src : in STD_LOGIC_VECTOR( 1 downto 0); 41 | res_alu : in STD_LOGIC_VECTOR(31 downto 0); 42 | res_shifter : in STD_LOGIC_VECTOR(31 downto 0); 43 | res_pc_plus_four : in STD_LOGIC_VECTOR(31 downto 0); 44 | res_memory : in STD_LOGIC_VECTOR(31 downto 0); 45 | res_bus : out STD_LOGIC_VECTOR(31 downto 0)); 46 | end entity; 47 | 48 | architecture Behavioral of result_bus_mux is 49 | -- Selction of what is going to the reginster file 50 | -- Selction of what is going to the reginster file 51 | constant RESULT_ALU : STD_LOGIC_VECTOR(1 downto 0) := "00"; 52 | constant RESULT_SHIFTER : STD_LOGIC_VECTOR(1 downto 0) := "01"; 53 | constant RESULT_MEMORY : STD_LOGIC_VECTOR(1 downto 0) := "10"; 54 | constant RESULT_PC_PLUS_4 : STD_LOGIC_VECTOR(1 downto 0) := "11"; 55 | signal aux : std_logic_vector(31 downto 0); 56 | begin 57 | 58 | -- Select between things with less timing slack 59 | process(res_src, res_alu, aux, res_shifter, res_pc_plus_four, res_memory) 60 | begin 61 | case res_src is 62 | when RESULT_ALU => 63 | res_bus <= res_alu; 64 | when RESULT_PC_PLUS_4 => 65 | res_bus <= res_pc_plus_four; 66 | when RESULT_MEMORY => 67 | res_bus <= res_memory; 68 | when RESULT_SHIFTER => 69 | res_bus <= res_shifter; 70 | when others => 71 | res_bus <= res_alu; 72 | end case; 73 | end process; 74 | 75 | end Behavioral; 76 | -------------------------------------------------------------------------------- /src/cpu/register_file.vhd: -------------------------------------------------------------------------------- 1 | --############################################################################### 2 | --# register_file.vhd - The register file 3 | --# 4 | --# Part of the Rudi-RV32I project 5 | --# 6 | --# See https://github.com/hamsternz/Rudi-RV32I 7 | --# 8 | --# MIT License 9 | --# 10 | --############################################################################### 11 | --# 12 | --# Copyright (c) 2020 Mike Field 13 | --# 14 | --# Permission is hereby granted, free of charge, to any person obtaining a copy 15 | --# of this software and associated documentation files (the "Software"), to deal 16 | --# in the Software without restriction, including without limitation the rights 17 | --# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | --# copies of the Software, and to permit persons to whom the Software is 19 | --# furnished to do so, subject to the following conditions: 20 | --# 21 | --# The above copyright notice and this permission notice shall be included in all 22 | --# copies or substantial portions of the Software. 23 | --# 24 | --# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | --# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | --# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | --# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | --# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | --# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | --# SOFTWARE. 31 | --# 32 | --############################################################################### 33 | 34 | library IEEE; 35 | use IEEE.STD_LOGIC_1164.ALL; 36 | use IEEE.numeric_std.all; 37 | 38 | 39 | entity register_file is 40 | port ( clk : in STD_LOGIC; 41 | read_port_1_addr : in STD_LOGIC_VECTOR(4 downto 0); 42 | read_data_1 : out STD_LOGIC_VECTOR(31 downto 0); 43 | read_port_2_addr : in STD_LOGIC_VECTOR(4 downto 0); 44 | read_data_2 : out STD_LOGIC_VECTOR(31 downto 0); 45 | busy : in STD_LOGIC; 46 | write_port_addr : in STD_LOGIC_VECTOR(4 downto 0); 47 | write_data : in STD_LOGIC_VECTOR(31 downto 0); 48 | debug_sel : in STD_LOGIC_VECTOR(4 downto 0); 49 | debug_data : out STD_LOGIC_VECTOR(31 downto 0)); 50 | end entity; 51 | 52 | architecture Behavioral of register_file is 53 | type a_registers is array(0 to 31) of std_logic_vector(31 downto 0); 54 | signal registers_1 : a_registers := (others => (others => '0')); -- NOTE REGISTER 0 *MUST BE KEPT AS ZERO!* 55 | signal registers_2 : a_registers := (others => (others => '0')); 56 | signal registers_debug : a_registers := (others => (others => '0')); 57 | begin 58 | 59 | read_data_1 <= registers_1(to_integer(unsigned(read_port_1_addr))); 60 | read_data_2 <= registers_2(to_integer(unsigned(read_port_2_addr))); 61 | debug_data <= registers_debug(to_integer(unsigned(debug_sel))); 62 | 63 | write_proc : process(clk) 64 | begin 65 | if rising_edge(clk) then 66 | if write_port_addr /= "00000" and busy = '0' then 67 | registers_1(to_integer(unsigned(write_port_addr))) <= write_data; 68 | registers_2(to_integer(unsigned(write_port_addr))) <= write_data; 69 | registers_debug(to_integer(unsigned(write_port_addr))) <= write_data; 70 | end if; 71 | end if; 72 | end process; 73 | end Behavioral; 74 | -------------------------------------------------------------------------------- /src/cpu/sign_extender.vhd: -------------------------------------------------------------------------------- 1 | --############################################################################### 2 | --# sign_extender.vhd - Masks and extends the sign on values form memory 3 | --# 4 | --# Part of the Rudi-RV32I project 5 | --# 6 | --# See https://github.com/hamsternz/Rudi-RV32I 7 | --# 8 | --# MIT License 9 | --# 10 | --############################################################################### 11 | --# 12 | --# Copyright (c) 2020 Mike Field 13 | --# 14 | --# Permission is hereby granted, free of charge, to any person obtaining a copy 15 | --# of this software and associated documentation files (the "Software"), to deal 16 | --# in the Software without restriction, including without limitation the rights 17 | --# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | --# copies of the Software, and to permit persons to whom the Software is 19 | --# furnished to do so, subject to the following conditions: 20 | --# 21 | --# The above copyright notice and this permission notice shall be included in all 22 | --# copies or substantial portions of the Software. 23 | --# 24 | --# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | --# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | --# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | --# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | --# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | --# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | --# SOFTWARE. 31 | --# 32 | --############################################################################### 33 | 34 | library IEEE; 35 | use IEEE.STD_LOGIC_1164.ALL; 36 | use IEEE.numeric_std.all; 37 | 38 | entity sign_extender is 39 | port ( sign_ex_mode : in STD_LOGIC_VECTOR(0 downto 0); 40 | sign_ex_width : in STD_LOGIC_VECTOR(1 downto 0); 41 | a : in STD_LOGIC_VECTOR(31 downto 0); 42 | b : out STD_LOGIC_VECTOR(31 downto 0)); 43 | end entity; 44 | 45 | architecture Behavioral of sign_extender is 46 | -- Must agree with decode.vhd 47 | constant SIGN_EX_WIDTH_B : STD_LOGIC_VECTOR(1 downto 0) := "00"; 48 | constant SIGN_EX_WIDTH_H : STD_LOGIC_VECTOR(1 downto 0) := "01"; 49 | constant SIGN_EX_WIDTH_W : STD_LOGIC_VECTOR(1 downto 0) := "10"; 50 | constant SIGN_EX_WIDTH_X : STD_LOGIC_VECTOR(1 downto 0) := "11"; 51 | constant SIGN_EX_SIGNED : STD_LOGIC_VECTOR(0 downto 0) := "0"; 52 | constant SIGN_EX_UNSIGNED : STD_LOGIC_VECTOR(0 downto 0) := "1"; 53 | signal padding : STD_LOGIC_VECTOR(31 downto 8); 54 | begin 55 | 56 | process(sign_ex_mode, sign_ex_width, a) 57 | begin 58 | padding <= (others => '0'); 59 | if sign_ex_mode = SIGN_EX_SIGNED then 60 | case sign_ex_width is 61 | when SIGN_EX_WIDTH_B => 62 | if a(7) = '1' then 63 | padding <= (others => '1'); 64 | end if; 65 | when others => 66 | if a(15) = '1' then 67 | padding <= (others => '1'); 68 | end if; 69 | end case; 70 | end if; 71 | end process; 72 | 73 | process(a, sign_ex_width, padding) 74 | begin 75 | case sign_ex_width is 76 | when SIGN_EX_WIDTH_B => 77 | b <= padding(31 downto 8) & a( 7 downto 0); 78 | when SIGN_EX_WIDTH_H => 79 | b <= padding(31 downto 16) & a(15 downto 0); 80 | when SIGN_EX_WIDTH_W => 81 | b <= a; 82 | when others => 83 | b <= a; 84 | end case; 85 | end process; 86 | end Behavioral; 87 | -------------------------------------------------------------------------------- /src/program_memory/ram_memory.vhd: -------------------------------------------------------------------------------- 1 | --############################################################################### 2 | --# ram_memory.vhd - The RAM memory 3 | --# 4 | --# Part of the Rudi-RV32I project 5 | --# 6 | --# See https://github.com/hamsternz/Rudi-RV32I 7 | --# 8 | --# MIT License 9 | --# 10 | --############################################################################### 11 | --# 12 | --# Copyright (c) 2020 Mike Field 13 | --# 14 | --# Permission is hereby granted, free of charge, to any person obtaining a copy 15 | --# of this software and associated documentation files (the "Software"), to deal 16 | --# in the Software without restriction, including without limitation the rights 17 | --# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | --# copies of the Software, and to permit persons to whom the Software is 19 | --# furnished to do so, subject to the following conditions: 20 | --# 21 | --# The above copyright notice and this permission notice shall be included in all 22 | --# copies or substantial portions of the Software. 23 | --# 24 | --# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | --# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | --# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | --# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | --# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | --# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | --# SOFTWARE. 31 | --# 32 | --############################################################################### 33 | 34 | library IEEE; 35 | use IEEE.STD_LOGIC_1164.ALL; 36 | use IEEE.numeric_std.all; 37 | 38 | entity ram_memory is 39 | port ( clk : in STD_LOGIC; 40 | bus_busy : out STD_LOGIC; 41 | bus_addr : in STD_LOGIC_VECTOR(11 downto 2); 42 | bus_enable : in STD_LOGIC; 43 | bus_write_mask : in STD_LOGIC_VECTOR(3 downto 0); 44 | bus_write_data : in STD_LOGIC_VECTOR(31 downto 0); 45 | bus_read_data : out STD_LOGIC_VECTOR(31 downto 0) := (others => '0')); 46 | end entity; 47 | 48 | architecture Behavioral of ram_memory is 49 | type a_memory is array (0 to 1023) of STD_LOGIC_VECTOR(31 downto 0); 50 | signal memory : a_memory := ( 51 | others => (others=>'0')); 52 | signal data_valid : STD_LOGIC := '1'; 53 | begin 54 | 55 | 56 | process(bus_enable, bus_write_mask, data_valid) 57 | begin 58 | bus_busy <= '0'; 59 | if bus_enable = '1' and bus_write_mask = "0000" then 60 | if data_valid = '0' then 61 | bus_busy <= '1'; 62 | end if; 63 | end if; 64 | end process; 65 | 66 | process(clk) 67 | begin 68 | if rising_edge(clk) then 69 | data_valid <= '0'; 70 | if bus_enable = '1' then 71 | if bus_write_mask(0) = '1' then 72 | memory(to_integer(unsigned(bus_addr)))( 7 downto 0) <= bus_write_data( 7 downto 0); 73 | end if; 74 | if bus_write_mask(1) = '1' then 75 | memory(to_integer(unsigned(bus_addr)))(15 downto 8) <= bus_write_data(15 downto 8); 76 | end if; 77 | if bus_write_mask(2) = '1' then 78 | memory(to_integer(unsigned(bus_addr)))(23 downto 16) <= bus_write_data(23 downto 16); 79 | end if; 80 | if bus_write_mask(3) = '1' then 81 | memory(to_integer(unsigned(bus_addr)))(31 downto 24) <= bus_write_data(31 downto 24); 82 | end if; 83 | 84 | if bus_write_mask = "0000" and data_valid = '0' then 85 | data_valid <= '1'; 86 | end if; 87 | bus_read_data <= memory(to_integer(unsigned(bus_addr))); 88 | end if; 89 | end if; 90 | end process; 91 | 92 | end Behavioral; 93 | -------------------------------------------------------------------------------- /src/peripheral/peripheral_ram.vhd: -------------------------------------------------------------------------------- 1 | --############################################################################### 2 | --# peripheral_ram.vhd - The RAM peripheral 3 | --# 4 | --# Part of the Rudi-RV32I project 5 | --# 6 | --# See https://github.com/hamsternz/Rudi-RV32I 7 | --# 8 | --# MIT License 9 | --# 10 | --############################################################################### 11 | --# 12 | --# Copyright (c) 2020 Mike Field 13 | --# 14 | --# Permission is hereby granted, free of charge, to any person obtaining a copy 15 | --# of this software and associated documentation files (the "Software"), to deal 16 | --# in the Software without restriction, including without limitation the rights 17 | --# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | --# copies of the Software, and to permit persons to whom the Software is 19 | --# furnished to do so, subject to the following conditions: 20 | --# 21 | --# The above copyright notice and this permission notice shall be included in all 22 | --# copies or substantial portions of the Software. 23 | --# 24 | --# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | --# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | --# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | --# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | --# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | --# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | --# SOFTWARE. 31 | --# 32 | --############################################################################### 33 | 34 | library IEEE; 35 | use IEEE.STD_LOGIC_1164.ALL; 36 | use IEEE.numeric_std.all; 37 | 38 | entity peripheral_ram is 39 | port ( clk : in STD_LOGIC; 40 | bus_busy : out STD_LOGIC; 41 | bus_addr : in STD_LOGIC_VECTOR(11 downto 2); 42 | bus_enable : in STD_LOGIC; 43 | bus_write_mask : in STD_LOGIC_VECTOR(3 downto 0); 44 | bus_write_data : in STD_LOGIC_VECTOR(31 downto 0); 45 | bus_read_data : out STD_LOGIC_VECTOR(31 downto 0) := (others => '0')); 46 | end entity; 47 | 48 | architecture Behavioral of peripheral_ram is 49 | type a_memory is array (0 to 1023) of STD_LOGIC_VECTOR(31 downto 0); 50 | signal memory : a_memory := (others => (others=>'0')); 51 | signal data_valid : STD_LOGIC := '1'; 52 | begin 53 | 54 | 55 | process(bus_enable, bus_write_mask, data_valid) 56 | begin 57 | bus_busy <= '0'; 58 | if bus_enable = '1' and bus_write_mask = "0000" then 59 | if data_valid = '0' then 60 | bus_busy <= '1'; 61 | end if; 62 | end if; 63 | end process; 64 | 65 | process(clk) 66 | begin 67 | if rising_edge(clk) then 68 | data_valid <= '0'; 69 | if bus_enable = '1' then 70 | if bus_write_mask(0) = '1' then 71 | memory(to_integer(unsigned(bus_addr)))( 7 downto 0) <= bus_write_data( 7 downto 0); 72 | end if; 73 | if bus_write_mask(1) = '1' then 74 | memory(to_integer(unsigned(bus_addr)))(15 downto 8) <= bus_write_data(15 downto 8); 75 | end if; 76 | if bus_write_mask(2) = '1' then 77 | memory(to_integer(unsigned(bus_addr)))(23 downto 16) <= bus_write_data(23 downto 16); 78 | end if; 79 | if bus_write_mask(3) = '1' then 80 | memory(to_integer(unsigned(bus_addr)))(31 downto 24) <= bus_write_data(31 downto 24); 81 | end if; 82 | 83 | if bus_write_mask = "0000" and data_valid = '0' then 84 | data_valid <= '1'; 85 | end if; 86 | bus_read_data <= memory(to_integer(unsigned(bus_addr))); 87 | end if; 88 | end if; 89 | end process; 90 | 91 | end Behavioral; 92 | -------------------------------------------------------------------------------- /src/cpu/alu.vhd: -------------------------------------------------------------------------------- 1 | --############################################################################### 2 | --# alu.vhd - The arithmetic and logic unit 3 | --# 4 | --# Part of the Rudi-RV32I project 5 | --# 6 | --# See https://github.com/hamsternz/Rudi-RV32I 7 | --# 8 | --# MIT License 9 | --# 10 | --############################################################################### 11 | --# 12 | --# Copyright (c) 2020 Mike Field 13 | --# 14 | --# Permission is hereby granted, free of charge, to any person obtaining a copy 15 | --# of this software and associated documentation files (the "Software"), to deal 16 | --# in the Software without restriction, including without limitation the rights 17 | --# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | --# copies of the Software, and to permit persons to whom the Software is 19 | --# furnished to do so, subject to the following conditions: 20 | --# 21 | --# The above copyright notice and this permission notice shall be included in all 22 | --# copies or substantial portions of the Software. 23 | --# 24 | --# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | --# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | --# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | --# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | --# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | --# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | --# SOFTWARE. 31 | --# 32 | --############################################################################### 33 | 34 | library IEEE; 35 | use IEEE.STD_LOGIC_1164.ALL; 36 | use IEEE.numeric_std.all; 37 | 38 | entity alu is 39 | port ( alu_mode : in STD_LOGIC_VECTOR(2 downto 0); 40 | a : in STD_LOGIC_VECTOR(31 downto 0); 41 | b : in STD_LOGIC_VECTOR(31 downto 0); 42 | c : out STD_LOGIC_VECTOR(31 downto 0) := (others => '0')); 43 | end entity; 44 | 45 | architecture Behavioral of alu is 46 | -- Must agree with decode.vhd 47 | -- Logical and addition functions 48 | constant ALU_OR : STD_LOGIC_VECTOR(2 downto 0) := "000"; 49 | constant ALU_AND : STD_LOGIC_VECTOR(2 downto 0) := "001"; 50 | constant ALU_XOR : STD_LOGIC_VECTOR(2 downto 0) := "010"; 51 | constant ALU_UNUSED : STD_LOGIC_VECTOR(2 downto 0) := "011"; 52 | constant ALU_ADD : STD_LOGIC_VECTOR(2 downto 0) := "100"; 53 | constant ALU_SUB : STD_LOGIC_VECTOR(2 downto 0) := "101"; 54 | constant ALU_LESS_THAN_SIGNED : STD_LOGIC_VECTOR(2 downto 0) := "110"; 55 | constant ALU_LESS_THAN_UNSIGNED : STD_LOGIC_VECTOR(2 downto 0) := "111"; 56 | begin 57 | 58 | process(alu_mode, a, b) 59 | variable a_dash : unsigned(31 downto 0); 60 | variable b_dash : unsigned(31 downto 0); 61 | begin 62 | a_dash := unsigned(a); 63 | b_dash := unsigned(b); 64 | if alu_mode(0) = '0' then 65 | a_dash(31) := not a_dash(31); 66 | b_dash(31) := not b_dash(31); 67 | end if; 68 | case alu_mode is 69 | when ALU_OR => 70 | c <= a OR b; 71 | when ALU_AND => 72 | c <= a AND b; 73 | when ALU_XOR => 74 | c <= a XOR b; 75 | when ALU_UNUSED => 76 | c <= a XOR b; 77 | when ALU_ADD => 78 | c <= std_logic_vector(unsigned(a) + unsigned(b)); 79 | when ALU_SUB => 80 | c <= std_logic_vector(unsigned(a) - unsigned(b)); 81 | when ALU_LESS_THAN_SIGNED | ALU_LESS_THAN_UNSIGNED => 82 | c <= (others => '0'); 83 | if a_dash < b_dash then 84 | c(0) <= '1'; 85 | end if; 86 | when others => 87 | end case; 88 | end process; 89 | end Behavioral; 90 | -------------------------------------------------------------------------------- /c/template_ram_memory.vhd: -------------------------------------------------------------------------------- 1 | H:--############################################################################### 2 | H:--# ram_memory.vhd - A generated HDL memory files 3 | H:--# 4 | H:--# Part of the Rudi-RV32I project 5 | H:--# 6 | H:--# See https://github.com/hamsternz/Rudi-RV32I 7 | H:--# 8 | H:--# MIT License 9 | H:--# 10 | H:--############################################################################### 11 | H:--# 12 | H:--# Copyright (c) 2020 Mike Field 13 | H:--# 14 | H:--# Permission is hereby granted, free of charge, to any person obtaining a copy 15 | H:--# of this software and associated documentation files (the "Software"), to deal 16 | H:--# in the Software without restriction, including without limitation the rights 17 | H:--# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | H:--# copies of the Software, and to permit persons to whom the Software is 19 | H:--# furnished to do so, subject to the following conditions: 20 | H:--# 21 | H:--# The above copyright notice and this permission notice shall be included in all 22 | H:--# copies or substantial portions of the Software. 23 | H:--# 24 | H:--# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | H:--# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | H:--# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | H:--# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | H:--# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | H:--# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | H:--# SOFTWARE. 31 | H:--# 32 | H:--############################################################################### 33 | H:library IEEE; 34 | H:use IEEE.STD_LOGIC_1164.ALL; 35 | H:use IEEE.numeric_std.all; 36 | H: 37 | H:entity ram_memory is 38 | H: port ( clk : in STD_LOGIC; 39 | H: bus_busy : out STD_LOGIC; 40 | H: bus_addr : in STD_LOGIC_VECTOR(11 downto 2); 41 | H: bus_enable : in STD_LOGIC; 42 | H: bus_write_mask : in STD_LOGIC_VECTOR(3 downto 0); 43 | H: bus_write_data : in STD_LOGIC_VECTOR(31 downto 0); 44 | H: bus_read_data : out STD_LOGIC_VECTOR(31 downto 0) := (others => '0')); 45 | H:end entity; 46 | H: 47 | H:architecture Behavioral of ram_memory is 48 | H: type a_memory is array (0 to 1023) of STD_LOGIC_VECTOR(31 downto 0); 49 | H: signal memory : a_memory := ( 50 | F: others => (others=>'0')); 51 | F: signal data_valid : STD_LOGIC := '1'; 52 | F:begin 53 | F: 54 | F: 55 | F:process(bus_enable, bus_write_mask, data_valid) 56 | F:begin 57 | F: bus_busy <= '0'; 58 | F: if bus_enable = '1' and bus_write_mask = "0000" then 59 | F: if data_valid = '0' then 60 | F: bus_busy <= '1'; 61 | F: end if; 62 | F: end if; 63 | F:end process; 64 | F: 65 | F:process(clk) 66 | F:begin 67 | F: if rising_edge(clk) then 68 | F: data_valid <= '0'; 69 | F: if bus_enable = '1' then 70 | F: if bus_write_mask(0) = '1' then 71 | F: memory(to_integer(unsigned(bus_addr)))( 7 downto 0) <= bus_write_data( 7 downto 0); 72 | F: end if; 73 | F: if bus_write_mask(1) = '1' then 74 | F: memory(to_integer(unsigned(bus_addr)))(15 downto 8) <= bus_write_data(15 downto 8); 75 | F: end if; 76 | F: if bus_write_mask(2) = '1' then 77 | F: memory(to_integer(unsigned(bus_addr)))(23 downto 16) <= bus_write_data(23 downto 16); 78 | F: end if; 79 | F: if bus_write_mask(3) = '1' then 80 | F: memory(to_integer(unsigned(bus_addr)))(31 downto 24) <= bus_write_data(31 downto 24); 81 | F: end if; 82 | F: 83 | F: if bus_write_mask = "0000" and data_valid = '0' then 84 | F: data_valid <= '1'; 85 | F: end if; 86 | F: bus_read_data <= memory(to_integer(unsigned(bus_addr))); 87 | F: end if; 88 | F: end if; 89 | F:end process; 90 | F: 91 | F:end Behavioral; 92 | -------------------------------------------------------------------------------- /src/boards/basys3/basys3.xdc: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # basys3.xdc - Constraints for the Basys3 board. 3 | # 4 | # Part of the Rudi-RV32I project 5 | # 6 | # See https://github.com/hamsternz/Rudi-RV32I 7 | # 8 | # MIT License 9 | # 10 | ############################################################################### 11 | # 12 | # Copyright (c) 2020 Mike Field 13 | # 14 | # Permission is hereby granted, free of charge, to any person obtaining a copy 15 | # of this software and associated documentation files (the "Software"), to deal 16 | # in the Software without restriction, including without limitation the rights 17 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | # copies of the Software, and to permit persons to whom the Software is 19 | # furnished to do so, subject to the following conditions: 20 | # 21 | # The above copyright notice and this permission notice shall be included in all 22 | # copies or substantial portions of the Software. 23 | # 24 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | # SOFTWARE. 31 | # 32 | ############################################################################### 33 | 34 | set_property PACKAGE_PIN W5 [get_ports clk100mhz] 35 | set_property IOSTANDARD LVCMOS33 [get_ports clk100mhz] 36 | create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports clk100mhz] 37 | 38 | ## Button C might be used for reset 39 | set_property PACKAGE_PIN U18 [get_ports btnC] 40 | set_property IOSTANDARD LVCMOS33 [get_ports btnC] 41 | 42 | ## UART 43 | set_property PACKAGE_PIN A18 [get_ports uart_rxd_out] 44 | set_property IOSTANDARD LVCMOS33 [get_ports uart_rxd_out] 45 | set_property PACKAGE_PIN B18 [get_ports uart_txd_in] 46 | set_property IOSTANDARD LVCMOS33 [get_ports uart_txd_in] 47 | 48 | ## LEDs 49 | set_property PACKAGE_PIN U16 [get_ports {led[0]}] 50 | set_property IOSTANDARD LVCMOS33 [get_ports {led[0]}] 51 | set_property PACKAGE_PIN E19 [get_ports {led[1]}] 52 | set_property IOSTANDARD LVCMOS33 [get_ports {led[1]}] 53 | set_property PACKAGE_PIN U19 [get_ports {led[2]}] 54 | set_property IOSTANDARD LVCMOS33 [get_ports {led[2]}] 55 | set_property PACKAGE_PIN V19 [get_ports {led[3]}] 56 | set_property IOSTANDARD LVCMOS33 [get_ports {led[3]}] 57 | set_property PACKAGE_PIN W18 [get_ports {led[4]}] 58 | set_property IOSTANDARD LVCMOS33 [get_ports {led[4]}] 59 | set_property PACKAGE_PIN U15 [get_ports {led[5]}] 60 | set_property IOSTANDARD LVCMOS33 [get_ports {led[5]}] 61 | set_property PACKAGE_PIN U14 [get_ports {led[6]}] 62 | set_property IOSTANDARD LVCMOS33 [get_ports {led[6]}] 63 | set_property PACKAGE_PIN V14 [get_ports {led[7]}] 64 | set_property IOSTANDARD LVCMOS33 [get_ports {led[7]}] 65 | set_property PACKAGE_PIN V13 [get_ports {led[8]}] 66 | set_property IOSTANDARD LVCMOS33 [get_ports {led[8]}] 67 | set_property PACKAGE_PIN V3 [get_ports {led[9]}] 68 | set_property IOSTANDARD LVCMOS33 [get_ports {led[9]}] 69 | set_property PACKAGE_PIN W3 [get_ports {led[10]}] 70 | set_property IOSTANDARD LVCMOS33 [get_ports {led[10]}] 71 | set_property PACKAGE_PIN U3 [get_ports {led[11]}] 72 | set_property IOSTANDARD LVCMOS33 [get_ports {led[11]}] 73 | set_property PACKAGE_PIN P3 [get_ports {led[12]}] 74 | set_property IOSTANDARD LVCMOS33 [get_ports {led[12]}] 75 | set_property PACKAGE_PIN N3 [get_ports {led[13]}] 76 | set_property IOSTANDARD LVCMOS33 [get_ports {led[13]}] 77 | set_property PACKAGE_PIN P1 [get_ports {led[14]}] 78 | set_property IOSTANDARD LVCMOS33 [get_ports {led[14]}] 79 | set_property PACKAGE_PIN L1 [get_ports {led[15]}] 80 | set_property IOSTANDARD LVCMOS33 [get_ports {led[15]}] 81 | -------------------------------------------------------------------------------- /c/template_program_memory.vhd: -------------------------------------------------------------------------------- 1 | H:--############################################################################### 2 | H:--# program_memory.vhd - A generated HDL memory files 3 | H:--# 4 | H:--# Part of the Rudi-RV32I project 5 | H:--# 6 | H:--# See https://github.com/hamsternz/Rudi-RV32I 7 | H:--# 8 | H:--# MIT License 9 | H:--# 10 | H:--############################################################################### 11 | H:--# 12 | H:--# Copyright (c) 2020 Mike Field 13 | H:--# 14 | H:--# Permission is hereby granted, free of charge, to any person obtaining a copy 15 | H:--# of this software and associated documentation files (the "Software"), to deal 16 | H:--# in the Software without restriction, including without limitation the rights 17 | H:--# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | H:--# copies of the Software, and to permit persons to whom the Software is 19 | H:--# furnished to do so, subject to the following conditions: 20 | H:--# 21 | H:--# The above copyright notice and this permission notice shall be included in all 22 | H:--# copies or substantial portions of the Software. 23 | H:--# 24 | H:--# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | H:--# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | H:--# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | H:--# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | H:--# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | H:--# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | H:--# SOFTWARE. 31 | H:--# 32 | H:--############################################################################### 33 | H:library IEEE; 34 | H:use IEEE.STD_LOGIC_1164.ALL; 35 | H:use IEEE.numeric_std.all; 36 | H: 37 | H:entity program_memory is 38 | H: port ( clk : in STD_LOGIC; 39 | H: -- Instruction interface 40 | H: pc_next : in STD_LOGIC_VECTOR(31 downto 0); 41 | H: instr_reg : out STD_LOGIC_VECTOR(31 downto 0); 42 | H: -- CPU Bus interface 43 | H: bus_busy : out STD_LOGIC; 44 | H: bus_addr : in STD_LOGIC_VECTOR(11 downto 2); 45 | H: bus_enable : in STD_LOGIC; 46 | H: bus_write_mask : in STD_LOGIC_VECTOR(3 downto 0); 47 | H: bus_write_data : in STD_LOGIC_VECTOR(31 downto 0); 48 | H: bus_read_data : out STD_LOGIC_VECTOR(31 downto 0) := (others => '0')); 49 | H:end entity; 50 | H: 51 | H:architecture Behavioral of program_memory is 52 | H: 53 | H: type a_prog_memory is array (0 to 1023) of STD_LOGIC_VECTOR(31 downto 0); 54 | H: signal prog_memory : a_prog_memory := ( 55 | F: others => "000000000001" & "00001" & "000" & "00001" & "0010011" -- r01 <= r01 + 1 56 | F: ); 57 | F: attribute keep : string; 58 | F: attribute ram_style : string; 59 | F: 60 | F: signal data_valid : STD_LOGIC := '1'; 61 | F:begin 62 | F: 63 | F:------------------------ 64 | F:-- PROGRAM ROM INTERFACE 65 | F:------------------------ 66 | F:process(clk) 67 | F: begin 68 | F: if rising_edge(clk) then 69 | F: if pc_next(31 downto 12) = x"F0000" then 70 | F: instr_reg <= prog_memory(to_integer(unsigned(pc_next(11 downto 2)))); 71 | F: else 72 | F: instr_reg <= (others => '0'); 73 | F: end if; 74 | F: end if; 75 | F: end process; 76 | F: 77 | F:--------------------------------------------------------- 78 | F:-- MAIN SYSTEM BUS INTERFACE 79 | F:--------------------------------------------------------- 80 | F:process(bus_enable, bus_write_mask, data_valid) 81 | F:begin 82 | F: bus_busy <= '0'; 83 | F: if bus_enable = '1' and bus_write_mask = "0000" then 84 | F: if data_valid = '0' then 85 | F: bus_busy <= '1'; 86 | F: end if; 87 | F: end if; 88 | F:end process; 89 | F: 90 | F:process(clk) 91 | F:begin 92 | F: if rising_edge(clk) then 93 | F: data_valid <= '0'; 94 | F: if bus_enable = '1' then 95 | F: -- Writes are ignored 96 | F: 97 | F: if bus_write_mask = "0000" and data_valid = '0' then 98 | F: data_valid <= '1'; 99 | F: end if; 100 | F: bus_read_data <= prog_memory(to_integer(unsigned(bus_addr))); 101 | F: end if; 102 | F: end if; 103 | F:end process; 104 | F: 105 | F:end Behavioral; 106 | -------------------------------------------------------------------------------- /src/program_memory/ram_memory_test.vhd: -------------------------------------------------------------------------------- 1 | --############################################################################### 2 | --# ram_memory.vhd - A generated HDL memory files 3 | --# 4 | --# Part of the Rudi-RV32I project 5 | --# 6 | --# See https://github.com/hamsternz/Rudi-RV32I 7 | --# 8 | --# MIT License 9 | --# 10 | --############################################################################### 11 | --# 12 | --# Copyright (c) 2020 Mike Field 13 | --# 14 | --# Permission is hereby granted, free of charge, to any person obtaining a copy 15 | --# of this software and associated documentation files (the "Software"), to deal 16 | --# in the Software without restriction, including without limitation the rights 17 | --# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | --# copies of the Software, and to permit persons to whom the Software is 19 | --# furnished to do so, subject to the following conditions: 20 | --# 21 | --# The above copyright notice and this permission notice shall be included in all 22 | --# copies or substantial portions of the Software. 23 | --# 24 | --# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | --# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | --# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | --# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | --# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | --# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | --# SOFTWARE. 31 | --# 32 | --############################################################################### 33 | library IEEE; 34 | use IEEE.STD_LOGIC_1164.ALL; 35 | use IEEE.numeric_std.all; 36 | 37 | entity ram_memory is 38 | port ( clk : in STD_LOGIC; 39 | bus_busy : out STD_LOGIC; 40 | bus_addr : in STD_LOGIC_VECTOR(11 downto 2); 41 | bus_enable : in STD_LOGIC; 42 | bus_write_mask : in STD_LOGIC_VECTOR(3 downto 0); 43 | bus_write_data : in STD_LOGIC_VECTOR(31 downto 0); 44 | bus_read_data : out STD_LOGIC_VECTOR(31 downto 0) := (others => '0')); 45 | end entity; 46 | 47 | architecture Behavioral of ram_memory is 48 | type a_memory is array (0 to 1023) of STD_LOGIC_VECTOR(31 downto 0); 49 | signal memory : a_memory := ( 50 | 0 => x"6c6c6548", 51 | 1 => x"6f77206f", 52 | 2 => x"21646c72", 53 | 3 => x"00000a0d", 54 | 4 => x"61686320", 55 | 5 => x"74636172", 56 | 6 => x"20737265", 57 | 7 => x"676e6f6c", 58 | 8 => x"00000a0d", 59 | 9 => x"74786554", 60 | 10 => x"00000020", 61 | 11 => x"e0000000", 62 | 12 => x"e0000004", 63 | 13 => x"e0000008", 64 | 14 => x"e000000c", 65 | 15 => x"e0000010", 66 | 16 => x"e0000014", 67 | others => (others=>'0')); 68 | signal data_valid : STD_LOGIC := '1'; 69 | begin 70 | 71 | 72 | process(bus_enable, bus_write_mask, data_valid) 73 | begin 74 | bus_busy <= '0'; 75 | if bus_enable = '1' and bus_write_mask = "0000" then 76 | if data_valid = '0' then 77 | bus_busy <= '1'; 78 | end if; 79 | end if; 80 | end process; 81 | 82 | process(clk) 83 | begin 84 | if rising_edge(clk) then 85 | data_valid <= '0'; 86 | if bus_enable = '1' then 87 | if bus_write_mask(0) = '1' then 88 | memory(to_integer(unsigned(bus_addr)))( 7 downto 0) <= bus_write_data( 7 downto 0); 89 | end if; 90 | if bus_write_mask(1) = '1' then 91 | memory(to_integer(unsigned(bus_addr)))(15 downto 8) <= bus_write_data(15 downto 8); 92 | end if; 93 | if bus_write_mask(2) = '1' then 94 | memory(to_integer(unsigned(bus_addr)))(23 downto 16) <= bus_write_data(23 downto 16); 95 | end if; 96 | if bus_write_mask(3) = '1' then 97 | memory(to_integer(unsigned(bus_addr)))(31 downto 24) <= bus_write_data(31 downto 24); 98 | end if; 99 | 100 | if bus_write_mask = "0000" and data_valid = '0' then 101 | data_valid <= '1'; 102 | end if; 103 | bus_read_data <= memory(to_integer(unsigned(bus_addr))); 104 | end if; 105 | end if; 106 | end process; 107 | 108 | end Behavioral; 109 | -------------------------------------------------------------------------------- /src/peripheral/peripheral_millis.vhd: -------------------------------------------------------------------------------- 1 | --############################################################################### 2 | --# peripheral_millis.vhd - A millisecond counter 3 | --# 4 | --# A GPIO peripheral 5 | --# 6 | --# See https://github.com/hamsternz/Rudi-RV32I 7 | --# 8 | --# MIT License 9 | --# 10 | --############################################################################### 11 | --# 12 | --# Copyright (c) 2020 Mike Field 13 | --# 14 | --# Permission is hereby granted, free of charge, to any person obtaining a copy 15 | --# of this software and associated documentation files (the "Software"), to deal 16 | --# in the Software without restriction, including without limitation the rights 17 | --# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | --# copies of the Software, and to permit persons to whom the Software is 19 | --# furnished to do so, subject to the following conditions: 20 | --# 21 | --# The above copyright notice and this permission notice shall be included in all 22 | --# copies or substantial portions of the Software. 23 | --# 24 | --# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | --# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | --# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | --# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | --# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | --# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | --# SOFTWARE. 31 | --# 32 | --############################################################################### 33 | 34 | library IEEE; 35 | use IEEE.STD_LOGIC_1164.ALL; 36 | use IEEE.numeric_std.all; 37 | 38 | 39 | entity peripheral_millis is 40 | generic ( clock_freq : natural ); 41 | port ( clk : in STD_LOGIC; 42 | 43 | bus_busy : out STD_LOGIC; 44 | bus_addr : in STD_LOGIC_VECTOR(3 downto 2); 45 | bus_enable : in STD_LOGIC; 46 | bus_write_mask : in STD_LOGIC_VECTOR(3 downto 0); 47 | bus_write_data : in STD_LOGIC_VECTOR(31 downto 0); 48 | bus_read_data : out STD_LOGIC_VECTOR(31 downto 0) := (others => '0'); 49 | 50 | gpio : inout STD_LOGIC_VECTOR); 51 | 52 | end entity; 53 | 54 | architecture Behavioral of peripheral_millis is 55 | signal data_valid : STD_LOGIC := '1'; 56 | 57 | signal millis : UNSIGNED(31 downto 0) := (others => '0'); 58 | signal divider : unsigned(17 downto 0) := (others => '0'); 59 | signal lock : std_logic := '1'; 60 | begin 61 | 62 | process(bus_enable, bus_write_mask, data_valid) 63 | begin 64 | bus_busy <= '0'; 65 | if bus_enable = '1' and bus_write_mask = "0000" then 66 | if data_valid = '0' then 67 | bus_busy <= '1'; 68 | end if; 69 | end if; 70 | end process; 71 | 72 | process(clk) 73 | begin 74 | if rising_edge(clk) then 75 | -- Update the counters 76 | if divider = (clock_freq/1000)-1 then 77 | divider <= (others => '0'); 78 | millis <= millis + 1; 79 | else 80 | divider <= divider+1; 81 | end if; 82 | 83 | -- Process the bus request 84 | data_valid <= '0'; 85 | bus_read_data <= x"00000000"; 86 | if bus_enable = '1' then 87 | if bus_write_mask /= "0000" then 88 | case bus_addr is 89 | when "00" => 90 | if bus_write_mask(0) = '1' and lock = '0' then 91 | divider <= (others => '0'); 92 | millis <= unsigned(bus_write_data); 93 | end if; 94 | when "01" => 95 | if bus_write_mask(0) = '1' then 96 | lock <= bus_write_data(0); 97 | end if; 98 | -- other registers are read only 99 | when others => 100 | end case; 101 | else 102 | if data_valid = '0' then 103 | data_valid <= '1'; 104 | end if; 105 | 106 | case bus_addr is 107 | when "00" => bus_read_data <= std_logic_vector(millis); 108 | when "01" => bus_read_data <= (others => '0'); bus_read_data(0) <= lock; 109 | when others => bus_read_data <= (others => '0'); 110 | end case; 111 | end if; 112 | end if; 113 | end if; 114 | end process; 115 | 116 | end Behavioral; 117 | -------------------------------------------------------------------------------- /src/peripheral/peripheral_gpio.vhd: -------------------------------------------------------------------------------- 1 | --############################################################################### 2 | --# peripheral_gpio.vhd - The serial port peripheral 3 | --# 4 | --# A GPIO peripheral 5 | --# 6 | --# See https://github.com/hamsternz/Rudi-RV32I 7 | --# 8 | --# MIT License 9 | --# 10 | --############################################################################### 11 | --# 12 | --# Copyright (c) 2020 Mike Field 13 | --# 14 | --# Permission is hereby granted, free of charge, to any person obtaining a copy 15 | --# of this software and associated documentation files (the "Software"), to deal 16 | --# in the Software without restriction, including without limitation the rights 17 | --# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | --# copies of the Software, and to permit persons to whom the Software is 19 | --# furnished to do so, subject to the following conditions: 20 | --# 21 | --# The above copyright notice and this permission notice shall be included in all 22 | --# copies or substantial portions of the Software. 23 | --# 24 | --# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | --# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | --# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | --# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | --# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | --# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | --# SOFTWARE. 31 | --# 32 | --############################################################################### 33 | 34 | library IEEE; 35 | use IEEE.STD_LOGIC_1164.ALL; 36 | 37 | entity peripheral_gpio is 38 | port ( clk : in STD_LOGIC; 39 | 40 | bus_busy : out STD_LOGIC; 41 | bus_addr : in STD_LOGIC_VECTOR(3 downto 2); 42 | bus_enable : in STD_LOGIC; 43 | bus_write_mask : in STD_LOGIC_VECTOR(3 downto 0); 44 | bus_write_data : in STD_LOGIC_VECTOR(31 downto 0); 45 | bus_read_data : out STD_LOGIC_VECTOR(31 downto 0) := (others => '0'); 46 | 47 | gpio : inout STD_LOGIC_VECTOR); 48 | 49 | end entity; 50 | 51 | architecture Behavioral of peripheral_gpio is 52 | signal data_valid : STD_LOGIC := '1'; 53 | 54 | signal direction : STD_LOGIC_VECTOR(31 downto 0) := (others => '0'); 55 | signal output_value : STD_LOGIC_VECTOR(31 downto 0) := (others => '0'); 56 | signal read_value : STD_LOGIC_VECTOR(31 downto 0) := (others => '0'); 57 | 58 | begin 59 | 60 | process(bus_enable, bus_write_mask, data_valid) 61 | begin 62 | bus_busy <= '0'; 63 | if bus_enable = '1' and bus_write_mask = "0000" then 64 | if data_valid = '0' then 65 | bus_busy <= '1'; 66 | end if; 67 | end if; 68 | end process; 69 | 70 | process(gpio) 71 | begin 72 | read_value <= (others => '0'); 73 | read_value(gpio'high downto 0) <= gpio; 74 | end process; 75 | 76 | process(direction,output_value) 77 | begin 78 | for i in 0 to gpio'high loop 79 | if direction(i) = '0' then 80 | gpio(i) <= 'Z'; 81 | else 82 | gpio(i) <= output_value(i); 83 | end if; 84 | end loop; 85 | end process; 86 | 87 | process(clk) 88 | begin 89 | if rising_edge(clk) then 90 | data_valid <= '0'; 91 | bus_read_data <= x"00000000"; 92 | if bus_enable = '1' then 93 | if bus_write_mask /= "0000" then 94 | case bus_addr is 95 | when "00" => 96 | if bus_write_mask(0) = '1' then 97 | output_value <= bus_write_data; 98 | end if; 99 | when "01" => 100 | if bus_write_mask(0) = '1' then 101 | direction <= bus_write_data; 102 | end if; 103 | -- other registers are read only 104 | when others => 105 | end case; 106 | else 107 | if data_valid = '0' then 108 | data_valid <= '1'; 109 | end if; 110 | 111 | case bus_addr is 112 | when "00" => bus_read_data <= read_value; 113 | when "01" => bus_read_data <= direction; 114 | when others => bus_read_data <= (others => '0'); 115 | end case; 116 | end if; 117 | end if; 118 | end if; 119 | end process; 120 | 121 | end Behavioral; 122 | -------------------------------------------------------------------------------- /src/cpu/branch_test.vhd: -------------------------------------------------------------------------------- 1 | --############################################################################### 2 | --# branch_test.vhd - THe branch test unit 3 | --# 4 | --# Part of the Rudi-RV32I project 5 | --# 6 | --# See https://github.com/hamsternz/Rudi-RV32I 7 | --# 8 | --# MIT License 9 | --# 10 | --############################################################################### 11 | --# 12 | --# Copyright (c) 2020 Mike Field 13 | --# 14 | --# Permission is hereby granted, free of charge, to any person obtaining a copy 15 | --# of this software and associated documentation files (the "Software"), to deal 16 | --# in the Software without restriction, including without limitation the rights 17 | --# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | --# copies of the Software, and to permit persons to whom the Software is 19 | --# furnished to do so, subject to the following conditions: 20 | --# 21 | --# The above copyright notice and this permission notice shall be included in all 22 | --# copies or substantial portions of the Software. 23 | --# 24 | --# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | --# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | --# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | --# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | --# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | --# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | --# SOFTWARE. 31 | --# 32 | --############################################################################### 33 | 34 | library IEEE; 35 | use IEEE.STD_LOGIC_1164.ALL; 36 | use IEEE.numeric_std.all; 37 | 38 | entity branch_test is 39 | port ( branch_test_mode : in STD_LOGIC_VECTOR(2 downto 0); 40 | branch_test_enable : in STD_LOGIC; 41 | minimize_size : in STD_LOGIC; 42 | a : in STD_LOGIC_VECTOR(31 downto 0); 43 | b : in STD_LOGIC_VECTOR(31 downto 0); 44 | take_branch : out STD_LOGIC); 45 | end entity; 46 | 47 | 48 | architecture Behavioral of branch_test is 49 | 50 | constant BRANCH_TEST_EQ : STD_LOGIC_VECTOR(2 downto 0) := "000"; 51 | constant BRANCH_TEST_NE : STD_LOGIC_VECTOR(2 downto 0) := "001"; 52 | constant BRANCH_TEST_TRUE : STD_LOGIC_VECTOR(2 downto 0) := "010"; 53 | constant BRANCH_TEST_FALSE : STD_LOGIC_VECTOR(2 downto 0) := "011"; 54 | constant BRANCH_TEST_LT : STD_LOGIC_VECTOR(2 downto 0) := "100"; 55 | constant BRANCH_TEST_GE : STD_LOGIC_VECTOR(2 downto 0) := "101"; 56 | constant BRANCH_TEST_LTU : STD_LOGIC_VECTOR(2 downto 0) := "110"; 57 | constant BRANCH_TEST_GEU : STD_LOGIC_VECTOR(2 downto 0) := "111"; 58 | 59 | signal test_is_true : std_logic; 60 | 61 | begin 62 | take_branch <= test_is_true and branch_test_enable; 63 | 64 | process(branch_test_mode, a, b, minimize_size) 65 | variable a_dash : std_logic_vector(31 downto 0); 66 | variable b_dash : std_logic_vector(31 downto 0); 67 | begin 68 | if minimize_size = '0' then 69 | --- This branch uses 44 70 | case branch_test_mode(2 downto 1) is 71 | 72 | when "00" => -- EQ and NE 73 | if a = b then 74 | test_is_true <= NOT branch_test_mode(0); 75 | else 76 | test_is_true <= branch_test_mode(0); 77 | end if; 78 | 79 | when "01" => -- TRUE and FALSE 80 | test_is_true <= NOT branch_test_mode(0); 81 | 82 | when "10" => -- SIGNED LT and GE 83 | if SIGNED(a) < SIGNED(b) then 84 | test_is_true <= NOT branch_test_mode(0); 85 | else 86 | test_is_true <= branch_test_mode(0); 87 | end if; 88 | 89 | when "11" => -- unsigned LT and GE 90 | if UNSIGNED(a) < UNSIGNED(b) then 91 | test_is_true <= NOT branch_test_mode(0); 92 | else 93 | test_is_true <= branch_test_mode(0); 94 | end if; 95 | 96 | when others => 97 | test_is_true <= NOT branch_test_mode(0); 98 | end case; 99 | else 100 | -- this branch uses 29 LUTs 101 | a_dash := a; 102 | b_dash := b; 103 | -- Map signed values to unsigned values for compraison 104 | if branch_test_mode = BRANCH_TEST_GE or branch_test_mode = BRANCH_TEST_LT then 105 | a_dash(a_dash'high) := NOT a_dash(a_dash'high); 106 | b_dash(b_dash'high) := NOT b_dash(b_dash'high); 107 | end if; 108 | 109 | case branch_test_mode(2 downto 1) is 110 | 111 | when "00" => -- EQ and NE 112 | if a_dash = b_dash then 113 | test_is_true <= NOT branch_test_mode(0); 114 | else 115 | test_is_true <= branch_test_mode(0); 116 | end if; 117 | 118 | when "01" => -- TRUE and FALSE 119 | test_is_true <= NOT branch_test_mode(0); 120 | 121 | when "10" => -- SIGNED LT and GE (with range moved) 122 | if UNSIGNED(a_dash) < UNSIGNED(b_dash) then 123 | test_is_true <= NOT branch_test_mode(0); 124 | else 125 | test_is_true <= branch_test_mode(0); 126 | end if; 127 | 128 | when "11" => -- unsigned LT and GE 129 | if UNSIGNED(a_dash) < UNSIGNED(b_dash) then 130 | test_is_true <= NOT branch_test_mode(0); 131 | else 132 | test_is_true <= branch_test_mode(0); 133 | end if; 134 | 135 | when others => 136 | test_is_true <= NOT branch_test_mode(0); 137 | end case; 138 | end if; 139 | end process; 140 | 141 | end Behavioral; 142 | -------------------------------------------------------------------------------- /src/cpu/shifter.vhd: -------------------------------------------------------------------------------- 1 | --############################################################################### 2 | --# shifter.vhd - The barrel shifter 3 | --# 4 | --# Part of the Rudi-RV32I project 5 | --# 6 | --# See https://github.com/hamsternz/Rudi-RV32I 7 | --# 8 | --# MIT License 9 | --# 10 | --############################################################################### 11 | --# 12 | --# Copyright (c) 2020 Mike Field 13 | --# 14 | --# Permission is hereby granted, free of charge, to any person obtaining a copy 15 | --# of this software and associated documentation files (the "Software"), to deal 16 | --# in the Software without restriction, including without limitation the rights 17 | --# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | --# copies of the Software, and to permit persons to whom the Software is 19 | --# furnished to do so, subject to the following conditions: 20 | --# 21 | --# The above copyright notice and this permission notice shall be included in all 22 | --# copies or substantial portions of the Software. 23 | --# 24 | --# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | --# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | --# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | --# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | --# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | --# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | --# SOFTWARE. 31 | --# 32 | --############################################################################### 33 | 34 | library IEEE; 35 | use IEEE.STD_LOGIC_1164.ALL; 36 | 37 | entity shifter is 38 | port ( shift_mode : in STD_LOGIC_VECTOR(1 downto 0) := "00"; 39 | minimize_size : in STD_LOGIC; 40 | a : in STD_LOGIC_VECTOR(31 downto 0); 41 | b : in STD_LOGIC_VECTOR(31 downto 0); 42 | c : out STD_LOGIC_VECTOR(31 downto 0) := (others => '0')); 43 | end entity; 44 | 45 | architecture Behavioral of shifter is 46 | -- Must agree with decode.vhd 47 | constant SHIFTER_LEFT_LOGICAL : STD_LOGIC_VECTOR(1 downto 0) := "00"; 48 | constant SHIFTER_LEFT_ARITH : STD_LOGIC_VECTOR(1 downto 0) := "01"; -- not used 49 | constant SHIFTER_RIGHT_LOGICAL : STD_LOGIC_VECTOR(1 downto 0) := "10"; 50 | constant SHIFTER_RIGHT_ARITH : STD_LOGIC_VECTOR(1 downto 0) := "11"; 51 | 52 | signal padding : std_logic_vector(15 downto 0); 53 | begin 54 | 55 | process(shift_mode,a) 56 | begin 57 | -- Generate the padding for right shifts (either logical or arithmetic) 58 | if (shift_mode = SHIFTER_LEFT_ARITH OR shift_mode = SHIFTER_RIGHT_ARITH) AND a(a'high) = '1' then 59 | padding <= (others => '1'); 60 | else 61 | padding <= (others => '0'); 62 | end if; 63 | end process; 64 | 65 | process(shift_mode, a, b, padding, minimize_size) 66 | variable t : STD_LOGIC_VECTOR(31 downto 0); 67 | begin 68 | if minimize_size = '1' then 69 | -- Swap bit order if shifting to the right 70 | if shift_mode = SHIFTER_RIGHT_LOGICAL OR shift_mode = SHIFTER_RIGHT_ARITH then 71 | t := a; 72 | else 73 | t := a( 0) & a( 1) & a( 2) & a( 3) & a( 4) & a( 5) & a( 6) & a( 7) 74 | & a( 8) & a( 9) & a(10) & a(11) & a(12) & a(13) & a(14) & a(15) 75 | & a(16) & a(17) & a(18) & a(19) & a(20) & a(21) & a(22) & a(23) 76 | & a(24) & a(25) & a(26) & a(27) & a(28) & a(29) & a(30) & a(31); 77 | end if; 78 | 79 | if b(4) = '1' then 80 | t := padding(15 downto 0) & t(31 downto 16); 81 | end if; 82 | 83 | if b(3) = '1' then 84 | t := padding(7 downto 0) & t(31 downto 8); 85 | end if; 86 | 87 | if b(2) = '1' then 88 | t := padding(3 downto 0) & t(31 downto 4); 89 | end if; 90 | 91 | if b(1) = '1' then 92 | t := padding(1 downto 0) & t(31 downto 2); 93 | end if; 94 | 95 | if b(0) = '1' then 96 | t := padding(0 downto 0) & t(31 downto 1); 97 | end if; 98 | 99 | if shift_mode = SHIFTER_RIGHT_LOGICAL OR shift_mode = SHIFTER_RIGHT_ARITH then 100 | c <= t; 101 | else 102 | c <= t( 0) & t( 1) & t( 2) & t( 3) & t( 4) & t( 5) & t( 6) & t( 7) 103 | & t( 8) & t( 9) & t(10) & t(11) & t(12) & t(13) & t(14) & t(15) 104 | & t(16) & t(17) & t(18) & t(19) & t(20) & t(21) & t(22) & t(23) 105 | & t(24) & t(25) & t(26) & t(27) & t(28) & t(29) & t(30) & t(31); 106 | end if; 107 | else 108 | t := a; 109 | if shift_mode = SHIFTER_LEFT_LOGICAL OR shift_mode = SHIFTER_LEFT_ARITH then 110 | if b(4) = '1' then 111 | t := t(15 downto 0) & x"0000"; 112 | end if; 113 | 114 | if b(3) = '1' then 115 | t := t(23 downto 0) & x"00"; 116 | end if; 117 | 118 | if b(2) = '1' then 119 | t := t(27 downto 0) & x"0"; 120 | end if; 121 | 122 | if b(1) = '1' then 123 | t := t(29 downto 0) & "00"; 124 | end if; 125 | 126 | if b(0) = '1' then 127 | t := t(30 downto 0) & "0"; 128 | end if; 129 | else 130 | if b(4) = '1' then 131 | t := padding(15 downto 0) & t(31 downto 16); 132 | end if; 133 | 134 | if b(3) = '1' then 135 | t := padding(7 downto 0) & t(31 downto 8); 136 | end if; 137 | 138 | if b(2) = '1' then 139 | t := padding(3 downto 0) & t(31 downto 4); 140 | end if; 141 | 142 | if b(1) = '1' then 143 | t := padding(1 downto 0) & t(31 downto 2); 144 | end if; 145 | 146 | if b(0) = '1' then 147 | t := padding(0 downto 0) & t(31 downto 1); 148 | end if; 149 | end if; 150 | 151 | c <= t; 152 | end if; 153 | end process; 154 | end Behavioral; 155 | -------------------------------------------------------------------------------- /src/cpu/program_counter.vhd: -------------------------------------------------------------------------------- 1 | --############################################################################### 2 | --# program_counter.vhd - Management of the program counter and related signals 3 | --# 4 | --# Part of the Rudi-RV32I project 5 | --# 6 | --# See https://github.com/hamsternz/Rudi-RV32I 7 | --# 8 | --# MIT License 9 | --# 10 | --############################################################################### 11 | --# 12 | --# Copyright (c) 2020 Mike Field 13 | --# 14 | --# Permission is hereby granted, free of charge, to any person obtaining a copy 15 | --# of this software and associated documentation files (the "Software"), to deal 16 | --# in the Software without restriction, including without limitation the rights 17 | --# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | --# copies of the Software, and to permit persons to whom the Software is 19 | --# furnished to do so, subject to the following conditions: 20 | --# 21 | --# The above copyright notice and this permission notice shall be included in all 22 | --# copies or substantial portions of the Software. 23 | --# 24 | --# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | --# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | --# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | --# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | --# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | --# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | --# SOFTWARE. 31 | --# 32 | --############################################################################### 33 | 34 | library IEEE; 35 | use IEEE.STD_LOGIC_1164.ALL; 36 | use IEEE.numeric_std.all; 37 | 38 | 39 | entity program_counter is 40 | port ( clk : in STD_LOGIC; 41 | busy : in STD_LOGIC; 42 | minimize_size : in STD_LOGIC; 43 | 44 | pc_mode : in STD_LOGIC_VECTOR(1 downto 0); 45 | take_branch : in STD_LOGIC; 46 | pc_jump_offset : in STD_LOGIC_VECTOR(31 downto 0); 47 | pc_branch_offset : in STD_LOGIC_VECTOR(31 downto 0); 48 | pc_jumpreg_offset : in STD_LOGIC_VECTOR(31 downto 0); 49 | a : in STD_LOGIC_VECTOR(31 downto 0); 50 | 51 | pc : out STD_LOGIC_VECTOR(31 downto 0); 52 | pc_next : out STD_LOGIC_VECTOR(31 downto 0); 53 | pc_plus_four : out STD_LOGIC_VECTOR(31 downto 0)); 54 | end entity; 55 | 56 | architecture Behavioral of program_counter is 57 | signal current_pc : unsigned(31 downto 0) := x"FFFFFFF0"; 58 | signal next_instr : unsigned(31 downto 0); 59 | signal test_is_true : STD_LOGIC; 60 | 61 | constant PC_JMP_RELATIVE : STD_LOGIC_VECTOR(1 downto 0) := "00"; 62 | constant PC_JMP_REG_RELATIVE : STD_LOGIC_VECTOR(1 downto 0) := "01"; 63 | constant PC_JMP_RELATIVE_CONDITIONAL : STD_LOGIC_VECTOR(1 downto 0) := "10"; 64 | constant PC_RESET_STATE : STD_LOGIC_VECTOR(1 downto 0) := "11"; 65 | 66 | constant BRANCH_TEST_EQ : STD_LOGIC_VECTOR(2 downto 0) := "000"; 67 | constant BRANCH_TEST_NE : STD_LOGIC_VECTOR(2 downto 0) := "001"; 68 | constant BRANCH_TEST_TRUE : STD_LOGIC_VECTOR(2 downto 0) := "010"; 69 | constant BRANCH_TEST_FALSE : STD_LOGIC_VECTOR(2 downto 0) := "011"; 70 | constant BRANCH_TEST_LT : STD_LOGIC_VECTOR(2 downto 0) := "100"; 71 | constant BRANCH_TEST_GE : STD_LOGIC_VECTOR(2 downto 0) := "101"; 72 | constant BRANCH_TEST_LTU : STD_LOGIC_VECTOR(2 downto 0) := "110"; 73 | constant BRANCH_TEST_GEU : STD_LOGIC_VECTOR(2 downto 0) := "111"; 74 | 75 | constant RESET_VECTOR : STD_LOGIC_VECTOR(31 downto 0) := x"F0000000"; 76 | 77 | begin 78 | 79 | pc <= std_logic_vector(current_pc); 80 | pc_plus_four <= std_logic_vector(current_pc + 4); 81 | 82 | 83 | process(next_instr, busy,current_pc) 84 | begin 85 | if busy = '1' then 86 | pc_next <= std_logic_vector(current_pc); 87 | else 88 | pc_next <= std_logic_vector(next_instr); 89 | end if; 90 | end process; 91 | 92 | process(pc_mode, current_pc, a, pc_branch_offset, pc_jump_offset, take_branch, minimize_size) 93 | variable add_LHS : unsigned(31 downto 0); 94 | variable add_RHS : unsigned(31 downto 0); 95 | begin 96 | if minimize_size = '1' then 97 | -- Uses 74 LUTs 98 | case pc_mode is 99 | when PC_JMP_RELATIVE_CONDITIONAL => add_LHS := unsigned(current_pc); 100 | when PC_JMP_RELATIVE => add_LHS := unsigned(current_pc); 101 | when PC_JMP_REG_RELATIVE => add_LHS := unsigned(a); 102 | when others => add_LHS := unsigned(RESET_VECTOR); 103 | end case; 104 | 105 | case pc_mode is 106 | when PC_JMP_RELATIVE_CONDITIONAL => 107 | if take_branch = '1' then 108 | add_RHS := unsigned(pc_branch_offset); 109 | else 110 | add_RHS := to_unsigned(4,32); 111 | end if; 112 | when PC_JMP_RELATIVE => add_RHS := unsigned(pc_jump_offset); 113 | when PC_JMP_REG_RELATIVE => add_RHS := unsigned(pc_jumpreg_offset); 114 | when others => add_RHS := x"00000000"; 115 | end case; 116 | next_instr <= (add_LHS + add_RHS) AND x"FFFFFFFC"; 117 | else 118 | -- Uses 155 LUTs 119 | if take_branch = '1' then 120 | next_instr <= (unsigned(current_pc) + unsigned(pc_branch_offset)) AND x"FFFFFFFC"; 121 | else 122 | case pc_mode is 123 | when PC_JMP_RELATIVE_CONDITIONAL => next_instr <= current_pc + 4; 124 | when PC_JMP_RELATIVE => next_instr <= (unsigned(current_pc) + unsigned(pc_jump_offset)) AND x"FFFFFFFC"; 125 | when PC_JMP_REG_RELATIVE => next_instr <= (unsigned(a) + unsigned(pc_jumpreg_offset)) AND x"FFFFFFFC"; 126 | when PC_RESET_STATE => next_instr <= x"F0000000"; 127 | when others => next_instr <= x"F0000000"; 128 | end case; 129 | end if; 130 | end if; 131 | end process; 132 | 133 | 134 | process(clk) 135 | begin 136 | if rising_edge(clk) then 137 | if busy = '0' then 138 | current_pc <= next_instr; 139 | end if; 140 | end if; 141 | end process; 142 | 143 | end Behavioral; 144 | -------------------------------------------------------------------------------- /src/boards/basys3/basys3_top_level.vhd: -------------------------------------------------------------------------------- 1 | --############################################################################### 2 | --# basys3_top_level.vhd - Top level HDL design for the Basys3 board 3 | --# 4 | --# Part of the Rudi-RV32I project 5 | --# 6 | --# See https://github.com/hamsternz/Rudi-RV32I 7 | --# 8 | --# MIT License 9 | --# 10 | --############################################################################### 11 | --# 12 | --# Copyright (c) 2020 Mike Field 13 | --# 14 | --# Permission is hereby granted, free of charge, to any person obtaining a copy 15 | --# of this software and associated documentation files (the "Software"), to deal 16 | --# in the Software without restriction, including without limitation the rights 17 | --# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | --# copies of the Software, and to permit persons to whom the Software is 19 | --# furnished to do so, subject to the following conditions: 20 | --# 21 | --# The above copyright notice and this permission notice shall be included in all 22 | --# copies or substantial portions of the Software. 23 | --# 24 | --# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | --# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | --# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | --# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | --# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | --# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | --# SOFTWARE. 31 | --# 32 | --############################################################################### 33 | library IEEE; 34 | use IEEE.STD_LOGIC_1164.ALL; 35 | 36 | library UNISIM; 37 | use UNISIM.vcomponents.all; 38 | 39 | entity basys3_top_level is 40 | port ( clk100mhz : in STD_LOGIC; 41 | btnC : in STD_LOGIC; 42 | led : inout std_logic_vector(15 downto 0); 43 | uart_rxd_out : out STD_LOGIC := '1'; 44 | uart_txd_in : in STD_LOGIC); 45 | end entity; 46 | 47 | architecture Behavioral of basys3_top_level is 48 | constant ext_clock_rate : natural := 100000000; 49 | constant multiplier : real := 10.000; 50 | constant divider : real := 14.750; 51 | constant bus_bridge_use_clk : std_logic := '0'; 52 | constant bus_expander_use_clk : std_logic := '0'; 53 | constant cpu_minimize_size : std_logic := '0'; 54 | 55 | component top_level_expanded is 56 | generic ( clock_freq : natural := 50000000; 57 | bus_bridge_use_clk : std_logic := '1'; 58 | bus_expander_use_clk : std_logic := '1'; 59 | cpu_minimize_size : std_logic := '1'); 60 | port ( clk : in STD_LOGIC; 61 | uart_rxd_out : out STD_LOGIC := '1'; 62 | uart_txd_in : in STD_LOGIC; 63 | gpio : inout std_logic_vector(15 downto 0); 64 | debug_sel : in STD_LOGIC_VECTOR(4 downto 0); 65 | debug_data : out STD_LOGIC_VECTOR(31 downto 0)); 66 | end component; 67 | signal clk : STD_LOGIC; 68 | signal fb : STD_LOGIC; 69 | begin 70 | 71 | MMCME2_BASE_inst : MMCME2_BASE 72 | generic map ( 73 | BANDWIDTH => "OPTIMIZED", -- Jitter programming (OPTIMIZED, HIGH, LOW) 74 | CLKFBOUT_MULT_F => multiplier, -- Multiply value for all CLKOUT (2.000-64.000). 75 | CLKFBOUT_PHASE => 0.0, -- Phase offset in degrees of CLKFB (-360.000-360.000). 76 | CLKIN1_PERIOD => 0.0, -- Input clock period in ns to ps resolution (i.e. 33.333 is 30 MHz). 77 | -- CLKOUT0_DIVIDE - CLKOUT6_DIVIDE: Divide amount for each CLKOUT (1-128) 78 | CLKOUT1_DIVIDE => 1, 79 | CLKOUT2_DIVIDE => 1, 80 | CLKOUT3_DIVIDE => 1, 81 | CLKOUT4_DIVIDE => 1, 82 | CLKOUT5_DIVIDE => 1, 83 | CLKOUT6_DIVIDE => 1, 84 | CLKOUT0_DIVIDE_F => divider, -- Divide amount for CLKOUT0 (1.000-128.000). 85 | -- CLKOUT0_DUTY_CYCLE - CLKOUT6_DUTY_CYCLE: Duty cycle for each CLKOUT (0.01-0.99). 86 | CLKOUT0_DUTY_CYCLE => 0.5, 87 | CLKOUT1_DUTY_CYCLE => 0.5, 88 | CLKOUT2_DUTY_CYCLE => 0.5, 89 | CLKOUT3_DUTY_CYCLE => 0.5, 90 | CLKOUT4_DUTY_CYCLE => 0.5, 91 | CLKOUT5_DUTY_CYCLE => 0.5, 92 | CLKOUT6_DUTY_CYCLE => 0.5, 93 | -- CLKOUT0_PHASE - CLKOUT6_PHASE: Phase offset for each CLKOUT (-360.000-360.000). 94 | CLKOUT0_PHASE => 0.0, 95 | CLKOUT1_PHASE => 0.0, 96 | CLKOUT2_PHASE => 0.0, 97 | CLKOUT3_PHASE => 0.0, 98 | CLKOUT4_PHASE => 0.0, 99 | CLKOUT5_PHASE => 0.0, 100 | CLKOUT6_PHASE => 0.0, 101 | CLKOUT4_CASCADE => FALSE, -- Cascade CLKOUT4 counter with CLKOUT6 (FALSE, TRUE) 102 | DIVCLK_DIVIDE => 1, -- Master division value (1-106) 103 | REF_JITTER1 => 0.0, -- Reference input jitter in UI (0.000-0.999). 104 | STARTUP_WAIT => FALSE -- Delays DONE until MMCM is locked (FALSE, TRUE) 105 | ) 106 | port map ( 107 | -- Clock Outputs: 1-bit (each) output: User configurable clock outputs 108 | CLKOUT0 => clk, -- 1-bit output: CLKOUT0 109 | CLKOUT0B => open, -- 1-bit output: Inverted CLKOUT0 110 | CLKOUT1 => open, -- 1-bit output: CLKOUT1 111 | CLKOUT1B => open, -- 1-bit output: Inverted CLKOUT1 112 | CLKOUT2 => open, -- 1-bit output: CLKOUT2 113 | CLKOUT2B => open, -- 1-bit output: Inverted CLKOUT2 114 | CLKOUT3 => open, -- 1-bit output: CLKOUT3 115 | CLKOUT3B => open, -- 1-bit output: Inverted CLKOUT3 116 | CLKOUT4 => open, -- 1-bit output: CLKOUT4 117 | CLKOUT5 => open, -- 1-bit output: CLKOUT5 118 | CLKOUT6 => open, -- 1-bit output: CLKOUT6 119 | -- Feedback Clocks: 1-bit (each) output: Clock feedback ports 120 | CLKFBOUT => fb, -- 1-bit output: Feedback clock 121 | CLKFBOUTB => open, -- 1-bit output: Inverted CLKFBOUT 122 | -- Status Ports: 1-bit (each) output: MMCM status ports 123 | LOCKED => open, -- 1-bit output: LOCK 124 | -- Clock Inputs: 1-bit (each) input: Clock input 125 | CLKIN1 => clk100mhz, -- 1-bit input: Clock 126 | -- Control Ports: 1-bit (each) input: MMCM control ports 127 | PWRDWN => '0', -- 1-bit input: Power-down 128 | RST => '0', -- 1-bit input: Reset 129 | -- Feedback Clocks: 1-bit (each) input: Clock feedback ports 130 | CLKFBIN => fb -- 1-bit input: Feedback clock 131 | ); 132 | 133 | i_top_level_expanded: top_level_expanded generic map ( 134 | clock_freq => natural(real(ext_clock_rate)*multiplier/divider), 135 | bus_bridge_use_clk => bus_bridge_use_clk, 136 | bus_expander_use_clk => bus_expander_use_clk, 137 | cpu_minimize_size => cpu_minimize_size 138 | ) port map ( 139 | clk => clk, 140 | uart_rxd_out => uart_rxd_out, 141 | uart_txd_in => uart_txd_in, 142 | gpio => led, 143 | debug_sel => "00000", 144 | debug_data => open); 145 | end Behavioral; 146 | 147 | -------------------------------------------------------------------------------- /src/peripheral/peripheral_serial.vhd: -------------------------------------------------------------------------------- 1 | --############################################################################### 2 | --# peripheral_serial.vhd - The serial port peripheral 3 | --# 4 | --# Part of the Rudi-RV32I project 5 | --# 6 | --# See https://github.com/hamsternz/Rudi-RV32I 7 | --# 8 | --# MIT License 9 | --# 10 | --############################################################################### 11 | --# 12 | --# Copyright (c) 2020 Mike Field 13 | --# 14 | --# Permission is hereby granted, free of charge, to any person obtaining a copy 15 | --# of this software and associated documentation files (the "Software"), to deal 16 | --# in the Software without restriction, including without limitation the rights 17 | --# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | --# copies of the Software, and to permit persons to whom the Software is 19 | --# furnished to do so, subject to the following conditions: 20 | --# 21 | --# The above copyright notice and this permission notice shall be included in all 22 | --# copies or substantial portions of the Software. 23 | --# 24 | --# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | --# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | --# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | --# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | --# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | --# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | --# SOFTWARE. 31 | --# 32 | --############################################################################### 33 | 34 | library IEEE; 35 | use IEEE.STD_LOGIC_1164.ALL; 36 | use IEEE.numeric_std.all; 37 | 38 | entity peripheral_serial is 39 | 40 | generic ( clock_freq : natural; 41 | baud_rate : natural); 42 | 43 | port ( clk : in STD_LOGIC; 44 | 45 | bus_busy : out STD_LOGIC; 46 | bus_addr : in STD_LOGIC_VECTOR(3 downto 2); 47 | bus_enable : in STD_LOGIC; 48 | bus_write_mask : in STD_LOGIC_VECTOR(3 downto 0); 49 | bus_write_data : in STD_LOGIC_VECTOR(31 downto 0); 50 | bus_read_data : out STD_LOGIC_VECTOR(31 downto 0) := (others => '0'); 51 | 52 | serial_rx : in STD_LOGIC; 53 | serial_tx : out STD_LOGIC := '1'); 54 | 55 | end entity; 56 | 57 | architecture Behavioral of peripheral_serial is 58 | signal data_valid : STD_LOGIC := '1'; 59 | 60 | -- Make the bus side of the perhipheral look like a FIFO 61 | signal fifo_wr : STD_LOGIC := '0'; 62 | signal fifo_wr_data : STD_LOGIC_VECTOR(7 downto 0) := (others => '0'); 63 | signal fifo_rd : STD_LOGIC := '0'; 64 | signal fifo_rd_data : STD_LOGIC_VECTOR(7 downto 0) := (others => '0'); 65 | signal fifo_full : STD_LOGIC := '0'; 66 | signal fifo_empty : STD_LOGIC := '1'; 67 | 68 | signal data_tx_sr : STD_LOGIC_VECTOR(9 downto 0) := (others => '1'); 69 | signal busy_tx_sr : STD_LOGIC_VECTOR(9 downto 0) := (others => '0'); 70 | signal data_rx_sr : STD_LOGIC_VECTOR(37 downto 0) := (others => '1'); 71 | signal baud_tick : STD_LOGIC := '0'; 72 | signal baud_tick_4x : STD_LOGIC := '0'; 73 | signal tick_divider : UNSIGNED(1 downto 0) := (others => '0'); 74 | signal baud_rx_counter : UNSIGNED(29 downto 0) := (others => '0'); -- Good to about 1GHz 75 | 76 | begin 77 | fifo_full <= busy_tx_sr(0); 78 | 79 | process(bus_enable, bus_write_mask, data_valid) 80 | begin 81 | bus_busy <= '0'; 82 | if bus_enable = '1' and bus_write_mask = "0000" then 83 | if data_valid = '0' then 84 | bus_busy <= '1'; 85 | end if; 86 | end if; 87 | end process; 88 | 89 | process(clk) 90 | begin 91 | if rising_edge(clk) then 92 | ---------------------------------- 93 | -- Processing outbound serial data 94 | ---------------------------------- 95 | if baud_tick = '1' then 96 | serial_tx <= data_tx_sr(0); 97 | busy_tx_sr <= '0' & busy_tx_sr(busy_tx_sr'high downto 1); 98 | data_tx_sr <= '1' & data_tx_sr(data_tx_sr'high downto 1); 99 | end if; 100 | 101 | if fifo_wr = '1' and busy_tx_sr(0) = '0' then 102 | data_tx_sr <= '1' & fifo_wr_data & '0'; 103 | busy_tx_sr <= (others => '1'); 104 | end if; 105 | 106 | ---------------------------------- 107 | -- Handle the bus request 108 | ---------------------------------- 109 | data_valid <= '0'; 110 | bus_read_data <= x"00000000"; 111 | fifo_wr <= '0'; 112 | fifo_rd <= '0'; 113 | if bus_enable = '1' then 114 | if bus_write_mask /= "0000" then 115 | case bus_addr is 116 | -- write SERIAL_OUT register 117 | when "00" => 118 | if bus_write_mask(0) = '1' then 119 | fifo_wr_data <= bus_write_data(7 downto 0); fifo_wr <= '1'; 120 | end if; 121 | -- other registers are read only 122 | when others => 123 | end case; 124 | else 125 | if data_valid = '0' then 126 | data_valid <= '1'; 127 | end if; 128 | 129 | case bus_addr is 130 | -- read SERIAL_OUT register (reads as zeros) 131 | when "00" => bus_read_data <= x"00000000"; 132 | -- read SERIAL_OUT_STATUS register 133 | when "01" => bus_read_data <= x"00000000"; bus_read_data(0) <= fifo_full; 134 | -- read SERIAL_IN register 135 | when "10" => bus_read_data <= x"00000000"; bus_read_data(7 downto 0) <= fifo_rd_data; fifo_rd <= '1'; 136 | -- read SERIAL_IN_STATUS register 137 | when "11" => bus_read_data <= x"00000000"; bus_read_data(0) <= fifo_empty; 138 | when others => 139 | end case; 140 | end if; 141 | end if; 142 | 143 | --------------------------------------- 144 | -- Process incoming data 145 | --------------------------------------- 146 | if fifo_rd = '1' then 147 | fifo_empty <= '1'; 148 | end if; 149 | 150 | if baud_tick_4x = '1' then 151 | -- Look for start and stop bits 152 | if data_rx_sr(2 downto 0) = "000" AND data_rx_sr(37) = '1' then 153 | -- Put data in the 1-deep fifo 154 | fifo_rd_data <= data_rx_sr(33) & data_rx_sr(29) & data_rx_sr(25) & data_rx_sr(21) & 155 | data_rx_sr(17) & data_rx_sr(13) & data_rx_sr(9) & data_rx_sr(5); 156 | fifo_empty <= '0'; 157 | -- reset the shift register 158 | data_rx_sr <= (others => '1'); 159 | else 160 | data_rx_sr <= serial_rx & data_rx_sr(data_rx_sr'high downto 1); 161 | end if; 162 | end if; 163 | 164 | ----------------------------------------- 165 | -- Work out where the next baud ticks are 166 | ----------------------------------------- 167 | baud_tick_4x <= '0'; 168 | baud_tick <= '0'; 169 | if baud_rx_counter < baud_rate*4 then 170 | baud_rx_counter <= baud_rx_counter - baud_rate*4 + clock_freq; 171 | if tick_divider = "11" then 172 | baud_tick <= '1'; 173 | end if; 174 | baud_tick_4x <= '1'; 175 | tick_divider <= tick_divider + 1; 176 | else 177 | baud_rx_counter <= baud_rx_counter - baud_rate*4; 178 | end if; 179 | end if; 180 | end process; 181 | 182 | 183 | 184 | end Behavioral; 185 | -------------------------------------------------------------------------------- /src/bus/bus_expander.vhd: -------------------------------------------------------------------------------- 1 | --############################################################################### 2 | --# bus_expander.vhd - A primative bridge from the CPU to peripheral bus. 3 | --# 4 | --# Part of the Rudi-RV32I project 5 | --# 6 | --# See https://github.com/hamsternz/Rudi-RV32I 7 | --# 8 | --# MIT License 9 | --# 10 | --############################################################################### 11 | --# 12 | --# Copyright (c) 2020 Mike Field 13 | --# 14 | --# Permission is hereby granted, free of charge, to any person obtaining a copy 15 | --# of this software and associated documentation files (the "Software"), to deal 16 | --# in the Software without restriction, including without limitation the rights 17 | --# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | --# copies of the Software, and to permit persons to whom the Software is 19 | --# furnished to do so, subject to the following conditions: 20 | --# 21 | --# The above copyright notice and this permission notice shall be included in all 22 | --# copies or substantial portions of the Software. 23 | --# 24 | --# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | --# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | --# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | --# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | --# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | --# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | --# SOFTWARE. 31 | --# 32 | --############################################################################### 33 | library IEEE; 34 | use IEEE.STD_LOGIC_1164.ALL; 35 | 36 | entity bus_expander is 37 | generic ( use_clk : in STD_LOGIC); 38 | port ( clk : in STD_LOGIC; 39 | -- Upstream (slave) interfaces 40 | s0_bus_busy : out STD_LOGIC; 41 | s0_bus_addr : in STD_LOGIC_VECTOR(31 downto 2); 42 | s0_bus_enable : in STD_LOGIC; 43 | s0_bus_write_mask : in STD_LOGIC_VECTOR( 3 downto 0); 44 | s0_bus_write_data : in STD_LOGIC_VECTOR(31 downto 0); 45 | s0_bus_read_data : out STD_LOGIC_VECTOR(31 downto 0) := (others => '0'); 46 | 47 | -- Downstream (master) interfaces 48 | m0_window_base : in STD_LOGIC_VECTOR(31 downto 0); 49 | m0_window_mask : in STD_LOGIC_VECTOR(31 downto 0); 50 | m0_bus_busy : in STD_LOGIC; 51 | m0_bus_addr : out STD_LOGIC_VECTOR(31 downto 2); 52 | m0_bus_enable : out STD_LOGIC; 53 | m0_bus_write_mask : out STD_LOGIC_VECTOR( 3 downto 0); 54 | m0_bus_write_data : out STD_LOGIC_VECTOR(31 downto 0); 55 | m0_bus_read_data : in STD_LOGIC_VECTOR(31 downto 0) := (others => '0'); 56 | 57 | m1_window_base : in STD_LOGIC_VECTOR(31 downto 0); 58 | m1_window_mask : in STD_LOGIC_VECTOR(31 downto 0); 59 | m1_bus_busy : in STD_LOGIC; 60 | m1_bus_addr : out STD_LOGIC_VECTOR(31 downto 2); 61 | m1_bus_enable : out STD_LOGIC; 62 | m1_bus_write_mask : out STD_LOGIC_VECTOR( 3 downto 0); 63 | m1_bus_write_data : out STD_LOGIC_VECTOR(31 downto 0); 64 | m1_bus_read_data : in STD_LOGIC_VECTOR(31 downto 0) := (others => '0'); 65 | 66 | m2_window_base : in STD_LOGIC_VECTOR(31 downto 0); 67 | m2_window_mask : in STD_LOGIC_VECTOR(31 downto 0); 68 | m2_bus_busy : in STD_LOGIC; 69 | m2_bus_addr : out STD_LOGIC_VECTOR(31 downto 2); 70 | m2_bus_enable : out STD_LOGIC; 71 | m2_bus_write_mask : out STD_LOGIC_VECTOR( 3 downto 0); 72 | m2_bus_write_data : out STD_LOGIC_VECTOR(31 downto 0); 73 | m2_bus_read_data : in STD_LOGIC_VECTOR(31 downto 0) := (others => '0') 74 | ); 75 | end entity; 76 | 77 | 78 | architecture Behavioral of bus_expander is 79 | signal active : std_logic_vector( 2 downto 0) := (others => '0'); 80 | 81 | signal addr : STD_LOGIC_VECTOR(31 downto 0) := (others => '0'); 82 | signal write_data : STD_LOGIC_VECTOR(31 downto 0) := (others => '0'); 83 | signal write_mask : STD_LOGIC_VECTOR( 3 downto 0) := (others => '0'); 84 | signal latched_addr : STD_LOGIC_VECTOR(31 downto 0) := (others => '0'); 85 | signal latched_write_data : STD_LOGIC_VECTOR(31 downto 0) := (others => '0'); 86 | signal latched_write_mask : STD_LOGIC_VECTOR( 3 downto 0) := (others => '0'); 87 | signal idle : STD_LOGIC := '0'; 88 | signal busy : STD_LOGIC := '0'; 89 | begin 90 | 91 | m0_bus_enable <= active(0); 92 | m0_bus_addr <= addr(31 downto 2) AND NOT m0_window_mask(31 downto 2); 93 | m0_bus_write_data <= write_data; 94 | m0_bus_write_mask <= write_mask; 95 | 96 | m1_bus_enable <= active(1); 97 | m1_bus_addr <= addr(31 downto 2) AND NOT m1_window_mask(31 downto 2); 98 | m1_bus_write_data <= write_data; 99 | m1_bus_write_mask <= write_mask; 100 | 101 | m2_bus_enable <= active(2); 102 | m2_bus_addr <= addr(31 downto 2) AND NOT m2_window_mask(31 downto 2); 103 | m2_bus_write_data <= write_data; 104 | m2_bus_write_mask <= write_mask; 105 | 106 | s0_bus_busy <= busy; 107 | 108 | busy <= (s0_bus_enable and idle and use_clk) 109 | or (m0_bus_busy and active(0)) 110 | or (m2_bus_busy and active(2)) 111 | or (m1_bus_busy and active(1)); 112 | 113 | with use_clk select addr <= latched_addr when '1', s0_bus_addr & "00" when others; 114 | with use_clk select write_data <= latched_write_data when '1', s0_bus_write_data when others; 115 | with use_clk select write_mask <= latched_write_mask when '1', s0_bus_write_mask when others; 116 | 117 | process(idle, addr, s0_bus_enable, 118 | m0_window_mask, m0_window_base, 119 | m1_window_mask, m1_window_base, 120 | m2_window_mask, m2_window_base) 121 | begin 122 | -- work out which port is busy (if any) 123 | active <= (others => '0'); 124 | if use_clk = '1' then 125 | if idle = '0' then 126 | if (addr(31 downto 2) and m0_window_mask(31 downto 2)) = m0_window_base(31 downto 2) then 127 | active(0) <= '1'; 128 | end if; 129 | if (addr(31 downto 2) and m1_window_mask(31 downto 2)) = m1_window_base(31 downto 2) then 130 | active(1) <= '1'; 131 | end if; 132 | if (addr(31 downto 2) and m2_window_mask(31 downto 2)) = m2_window_base(31 downto 2) then 133 | active(2) <= '1'; 134 | end if; 135 | end if; 136 | else 137 | if s0_bus_enable = '1' then 138 | if (addr(31 downto 2) and m0_window_mask(31 downto 2)) = m0_window_base(31 downto 2) then 139 | active(0) <= '1'; 140 | end if; 141 | if (addr(31 downto 2) and m1_window_mask(31 downto 2)) = m1_window_base(31 downto 2) then 142 | active(1) <= '1'; 143 | end if; 144 | if (addr(31 downto 2) and m2_window_mask(31 downto 2)) = m2_window_base(31 downto 2) then 145 | active(2) <= '1'; 146 | end if; 147 | end if; 148 | end if; 149 | end process; 150 | 151 | process(clk) 152 | begin 153 | if rising_edge(clk) then 154 | idle <= '1'; 155 | if s0_bus_enable = '1' then 156 | -- Take note of if the bus is currently busy 157 | -- Hold the address and write info in local registers. 158 | -- This is needed to give an endpoint for static timing analysis 159 | -- even if we don't expect these to change during the transaction. 160 | idle <= not busy; 161 | latched_addr <= s0_bus_addr & "00"; 162 | latched_write_data <= s0_bus_write_data; 163 | latched_write_mask <= s0_bus_write_mask; 164 | end if; 165 | end if; 166 | end process; 167 | 168 | process(active, m0_bus_read_data, m1_bus_read_data, m2_bus_read_data) 169 | begin 170 | case active is 171 | when "001" => s0_bus_read_data <= m0_bus_read_data; 172 | when "010" => s0_bus_read_data <= m1_bus_read_data; 173 | when "100" => s0_bus_read_data <= m2_bus_read_data; 174 | when others => s0_bus_read_data <= m2_bus_read_data; -- Multiple active (most likely an error!) 175 | end case; 176 | end process; 177 | 178 | end Behavioral; 179 | -------------------------------------------------------------------------------- /src/program_memory/program_memory_test.vhd: -------------------------------------------------------------------------------- 1 | --############################################################################### 2 | --# program_memory.vhd - A generated HDL memory files 3 | --# 4 | --# Part of the Rudi-RV32I project 5 | --# 6 | --# See https://github.com/hamsternz/Rudi-RV32I 7 | --# 8 | --# MIT License 9 | --# 10 | --############################################################################### 11 | --# 12 | --# Copyright (c) 2020 Mike Field 13 | --# 14 | --# Permission is hereby granted, free of charge, to any person obtaining a copy 15 | --# of this software and associated documentation files (the "Software"), to deal 16 | --# in the Software without restriction, including without limitation the rights 17 | --# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | --# copies of the Software, and to permit persons to whom the Software is 19 | --# furnished to do so, subject to the following conditions: 20 | --# 21 | --# The above copyright notice and this permission notice shall be included in all 22 | --# copies or substantial portions of the Software. 23 | --# 24 | --# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | --# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | --# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | --# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | --# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | --# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | --# SOFTWARE. 31 | --# 32 | --############################################################################### 33 | library IEEE; 34 | use IEEE.STD_LOGIC_1164.ALL; 35 | use IEEE.numeric_std.all; 36 | 37 | entity program_memory is 38 | port ( clk : in STD_LOGIC; 39 | -- Instruction interface 40 | pc_next : in STD_LOGIC_VECTOR(31 downto 0); 41 | instr_reg : out STD_LOGIC_VECTOR(31 downto 0); 42 | -- CPU Bus interface 43 | bus_busy : out STD_LOGIC; 44 | bus_addr : in STD_LOGIC_VECTOR(11 downto 2); 45 | bus_enable : in STD_LOGIC; 46 | bus_write_mask : in STD_LOGIC_VECTOR(3 downto 0); 47 | bus_write_data : in STD_LOGIC_VECTOR(31 downto 0); 48 | bus_read_data : out STD_LOGIC_VECTOR(31 downto 0) := (others => '0')); 49 | end entity; 50 | 51 | architecture Behavioral of program_memory is 52 | 53 | type a_prog_memory is array (0 to 1023) of STD_LOGIC_VECTOR(31 downto 0); 54 | signal prog_memory : a_prog_memory := ( 55 | 0 => x"100015b7", 56 | 1 => x"ffc58113", 57 | 2 => x"154000ef", 58 | 3 => x"ff5ff06f", 59 | 4 => x"ff010113", 60 | 5 => x"00812623", 61 | 6 => x"01010413", 62 | 7 => x"00000013", 63 | 8 => x"100007b7", 64 | 9 => x"0387a783", 65 | 10 => x"0007c783", 66 | 11 => x"0ff7f793", 67 | 12 => x"fe0798e3", 68 | 13 => x"100007b7", 69 | 14 => x"0347a783", 70 | 15 => x"0007c783", 71 | 16 => x"0ff7f793", 72 | 17 => x"00078513", 73 | 18 => x"00c12403", 74 | 19 => x"01010113", 75 | 20 => x"00008067", 76 | 21 => x"fe010113", 77 | 22 => x"00812e23", 78 | 23 => x"02010413", 79 | 24 => x"fea42623", 80 | 25 => x"00000013", 81 | 26 => x"100007b7", 82 | 27 => x"0307a783", 83 | 28 => x"0007c783", 84 | 29 => x"0ff7f793", 85 | 30 => x"fe0798e3", 86 | 31 => x"100007b7", 87 | 32 => x"02c7a783", 88 | 33 => x"fec42703", 89 | 34 => x"0ff77713", 90 | 35 => x"00e78023", 91 | 36 => x"fec42783", 92 | 37 => x"00078513", 93 | 38 => x"01c12403", 94 | 39 => x"02010113", 95 | 40 => x"00008067", 96 | 41 => x"fd010113", 97 | 42 => x"02112623", 98 | 43 => x"02812423", 99 | 44 => x"03010413", 100 | 45 => x"fca42e23", 101 | 46 => x"fe042623", 102 | 47 => x"02c0006f", 103 | 48 => x"fdc42783", 104 | 49 => x"0007c783", 105 | 50 => x"00078513", 106 | 51 => x"f89ff0ef", 107 | 52 => x"fdc42783", 108 | 53 => x"00178793", 109 | 54 => x"fcf42e23", 110 | 55 => x"fec42783", 111 | 56 => x"00178793", 112 | 57 => x"fef42623", 113 | 58 => x"fdc42783", 114 | 59 => x"0007c783", 115 | 60 => x"fc0798e3", 116 | 61 => x"fec42783", 117 | 62 => x"00078513", 118 | 63 => x"02c12083", 119 | 64 => x"02812403", 120 | 65 => x"03010113", 121 | 66 => x"00008067", 122 | 67 => x"fd010113", 123 | 68 => x"02812623", 124 | 69 => x"03010413", 125 | 70 => x"fca42e23", 126 | 71 => x"fe042623", 127 | 72 => x"01c0006f", 128 | 73 => x"fdc42783", 129 | 74 => x"00178793", 130 | 75 => x"fcf42e23", 131 | 76 => x"fec42783", 132 | 77 => x"00178793", 133 | 78 => x"fef42623", 134 | 79 => x"fdc42783", 135 | 80 => x"0007c783", 136 | 81 => x"fe0790e3", 137 | 82 => x"fec42783", 138 | 83 => x"00078513", 139 | 84 => x"02c12403", 140 | 85 => x"03010113", 141 | 86 => x"00008067", 142 | 87 => x"ff010113", 143 | 88 => x"00112623", 144 | 89 => x"00812423", 145 | 90 => x"01010413", 146 | 91 => x"f00007b7", 147 | 92 => x"22478513", 148 | 93 => x"f31ff0ef", 149 | 94 => x"f00007b7", 150 | 95 => x"23878513", 151 | 96 => x"f25ff0ef", 152 | 97 => x"100007b7", 153 | 98 => x"02478513", 154 | 99 => x"f81ff0ef", 155 | 100 => x"00050793", 156 | 101 => x"03078793", 157 | 102 => x"00078513", 158 | 103 => x"eb9ff0ef", 159 | 104 => x"f00007b7", 160 | 105 => x"24478513", 161 | 106 => x"efdff0ef", 162 | 107 => x"100007b7", 163 | 108 => x"02478513", 164 | 109 => x"ef1ff0ef", 165 | 110 => x"100007b7", 166 | 111 => x"02478513", 167 | 112 => x"f4dff0ef", 168 | 113 => x"00050793", 169 | 114 => x"03078793", 170 | 115 => x"00078513", 171 | 116 => x"e85ff0ef", 172 | 117 => x"100007b7", 173 | 118 => x"01078513", 174 | 119 => x"ec9ff0ef", 175 | 120 => x"100007b7", 176 | 121 => x"0407a783", 177 | 122 => x"00010737", 178 | 123 => x"fff70713", 179 | 124 => x"00e7a023", 180 | 125 => x"e1dff0ef", 181 | 126 => x"00050793", 182 | 127 => x"00078513", 183 | 128 => x"e55ff0ef", 184 | 129 => x"100007b7", 185 | 130 => x"03c7a783", 186 | 131 => x"0007a703", 187 | 132 => x"100007b7", 188 | 133 => x"03c7a783", 189 | 134 => x"00170713", 190 | 135 => x"00e7a023", 191 | 136 => x"fd5ff06f", 192 | 137 => x"74737953", 193 | 138 => x"72206d65", 194 | 139 => x"61747365", 195 | 140 => x"0a0d7472", 196 | 141 => x"00000000", 197 | 142 => x"69727453", 198 | 143 => x"6920676e", 199 | 144 => x"00002073", 200 | 145 => x"61686320", 201 | 146 => x"74636172", 202 | 147 => x"20737265", 203 | 148 => x"676e6f6c", 204 | 149 => x"00000a0d", 205 | others => "000000000001" & "00001" & "000" & "00001" & "0010011" -- r01 <= r01 + 1 206 | ); 207 | attribute keep : string; 208 | attribute ram_style : string; 209 | 210 | signal data_valid : STD_LOGIC := '1'; 211 | begin 212 | 213 | ------------------------ 214 | -- PROGRAM ROM INTERFACE 215 | ------------------------ 216 | process(clk) 217 | begin 218 | if rising_edge(clk) then 219 | if pc_next(31 downto 12) = x"F0000" then 220 | instr_reg <= prog_memory(to_integer(unsigned(pc_next(11 downto 2)))); 221 | else 222 | instr_reg <= (others => '0'); 223 | end if; 224 | end if; 225 | end process; 226 | 227 | --------------------------------------------------------- 228 | -- MAIN SYSTEM BUS INTERFACE 229 | --------------------------------------------------------- 230 | process(bus_enable, bus_write_mask, data_valid) 231 | begin 232 | bus_busy <= '0'; 233 | if bus_enable = '1' and bus_write_mask = "0000" then 234 | if data_valid = '0' then 235 | bus_busy <= '1'; 236 | end if; 237 | end if; 238 | end process; 239 | 240 | process(clk) 241 | begin 242 | if rising_edge(clk) then 243 | data_valid <= '0'; 244 | if bus_enable = '1' then 245 | -- Writes are ignored 246 | 247 | if bus_write_mask = "0000" and data_valid = '0' then 248 | data_valid <= '1'; 249 | end if; 250 | bus_read_data <= prog_memory(to_integer(unsigned(bus_addr))); 251 | end if; 252 | end if; 253 | end process; 254 | 255 | end Behavioral; 256 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Rudi-RV32I 2 | ========== 3 | 4 | Rudi-RV32I is a simple, small, RISC-V processor, supporting the RV32I instruction set, that can be programmed using GCC. 5 | 6 | This was a holiday project over Christmas 2019/2020. It has been designed with three key things in mind: 7 | 8 | - Minimize complexity 9 | - Minimize required resources 10 | - Maximize Understandability 11 | 12 | ## THIS IS CURRENTLY IN ALPHA TESTING 13 | This currently works as intended for all my designs, but you are more than likely to discover bugs. 14 | 15 | ## What is special about this design? 16 | Rudi-RV32 is somewhat unique as it features no pipelining at all. All instructions can 17 | complete in a single cycle, including the shift operations. Memory operations might take 18 | longer as the external bus can stall the CPU if required. 19 | 20 | Even with this lack of pipelining, the processor can run at > 80MHz in an Artix-7 grade 21 | 1 FPGA, and a compact "minimal version" can run at over 50MHz. 22 | 23 | A full 32-bit system, with 4kB of Program memory and 4kB of RAM and a serial port can 24 | be realized in little as 750 LUTs - 575 for the CPU itself, the rest for the system 25 | bus and serial console. 26 | 27 | ## Project structure 28 | 29 | * ./c - files to support programming the CPU in C 30 | * ./src - HDL Sources 31 | * ./src/test_benches - Test benches 32 | * ./src/program_memory - HDL for RAMs and ROMs 33 | * ./src/systems - HDL for complete systems - CPUs, RAMs, ROMs and perhipherals 34 | * ./src/boards - Booard specific HDL and constraints 35 | * ./src/bus - CPU bus to peripheral bus adapters 36 | * ./src/peripheral - Various peripherals 37 | * ./src/cpu - HDL for the Rudi-RV32I CPU 38 | * ./bitstreams - destintation for bitstreams from the ./vivado/build.tcl script 39 | * ./vivado - Scripts for building and testing in vivado 40 | 41 | ## Current Peripherals 42 | 43 | * 19200 serial console 44 | * 32-bit wide GPIO 45 | * Millisecond counter 46 | 47 | ## Current known issues / gotchas 48 | 49 | * Unaligned memory accesses are not supported by the current bus bridge design - currently high bits read as zeros 50 | * Still in active development and testing - most likely has unknown issues. 51 | * Needs more documentation on how to configure and use. 52 | 53 | ## Getting started 54 | 55 | It's not hard - as long as you get the right RISC-V GNU toolchain installed. 56 | 57 | * Install Xilinx Vivado 58 | * Install RISC-V GNU toolchain from https://github.com/riscv/riscv-gnu-toolchain in /opt/riscv - use the rv32ia ISA and ilp32 ABI. Use this configure command when building the RISC-V toolchain: 59 | ``` 60 | ./configure --prefix=/opt/riscv --with-arch=rv32ia --with-abi=ilp32 61 | ``` 62 | * In the './c' directory run 'make' to build the memory images from "test.c" 63 | * In the "./vivado" directory, run "build.sh" to build the bitstream 64 | 65 | You should now have a bitstream for Basys3 in ./bitstreams - program it and connect to the serial port at 19200. 66 | 67 | ## Performance/size in different configurations: 68 | 69 | Different configurations can be configured by setting the generics on the top level design: 70 | 71 | component top_level_expanded is 72 | generic ( clock_freq : natural := 50000000; 73 | bus_bridge_use_clk : std_logic := '1'; 74 | bus_expander_use_clk : std_logic := '1'; 75 | cpu_minimize_size : std_logic := '1'); 76 | port ( clk : in STD_LOGIC; 77 | uart_rxd_out : out STD_LOGIC := '1'; 78 | uart_txd_in : in STD_LOGIC; 79 | gpio : inout std_logic_vector(15 downto 0); 80 | debug_sel : in STD_LOGIC_VECTOR(4 downto 0); 81 | debug_data : out STD_LOGIC_VECTOR(31 downto 0)); 82 | end component; 83 | 84 | (clock_freq is used to work out baud rate dividers - it does not actually set the clock frequency) 85 | 86 | All configurations include a serial port, a GPIO port and a millisecond counter. Apart fgrom the first line these were contrainted to where timing was just met. 87 | 88 | +------------+-----------+--------------------+----------------------+--------------------+-- -----+-----+----------+--------+ 89 | | Constraint | Clock MHz | Clocked Bus Bridge | Clocked Bus Expander | Minimize CPU Size | LUTs | FFs | CPU LUTs | CPU FFs| 90 | +------------+-----------+--------------------+----------------------+--------------------+-- -----+-----+----------+--------+ 91 | | 20.000 ns | 50.00 MHz | No | No | Yes | 891 | 301 | 597 | 30 | 92 | | 17.625 ns | 56.73 MHz | No | No | Yes | 941 | 306 | 620 | 30 | 93 | | 16.375 ns | 61.06 MHz | No | Yes | Yes | 920 | 347 | 598 | 30 | 94 | | 14.750 ns | 67.79 MHz | No | No | No | 1108 | 307 | 781 | 31 | 95 | | 13.625 ns | 73.39 MHz | Yes | No | Yes | 909 | 377 | 597 | 30 | 96 | | 12.500 ns | 80.00 MHz | Yes | No | No | 1078 | 375 | 762 | 31 | 97 | +------------+-----------+--------------------+----------------------+--------------------+-- -----+-----+----------+--------+ 98 | 99 | The "Bus Bridge Use Clock" opotion adds a cycle of latency to memory accesses, making loads take three cycles and stores take two cycles. "Bus Expander Use Clock" adds a cycle of latency when talking with peripherals connected to it. Usually if you use the "Clocked Bus Bridge" You would have no need to clock the Bus Expander. 100 | 101 | Usage when constained to 50 MHz, with three peripherals, with clocks not used in the bus bridge or bus expander: 102 | 103 | +----------------------------+--------------------+------------+------------+---------+------+-----+--------+ 104 | | Instance | Module | Total LUTs | Logic LUTs | LUTRAMs | SRLs | FFs | RAMB36 | 105 | +----------------------------+--------------------+------------+------------+---------+------+-----+--------+ 106 | | basys3_top_level | (top) | 891 | 834 | 48 | 9 | 301 | 2 | 107 | | (basys3_top_level) | (top) | 0 | 0 | 0 | 0 | 0 | 0 | 108 | | i_top_level_expanded | top_level_expanded | 891 | 834 | 48 | 9 | 301 | 2 | 109 | | (i_top_level_expanded) | top_level_expanded | 1 | 0 | 0 | 1 | 1 | 0 | 110 | | i_bus_bridge | bus_bridge | 102 | 102 | 0 | 0 | 0 | 0 | 111 | | i_bus_expander | bus_expander | 42 | 42 | 0 | 0 | 0 | 0 | 112 | | i_peripheral_gpio | peripheral_gpio | 35 | 35 | 0 | 0 | 81 | 0 | 113 | | i_peripheral_millis | peripheral_millis | 42 | 42 | 0 | 0 | 84 | 0 | 114 | | i_peripheral_serial | peripheral_serial | 67 | 59 | 0 | 8 | 103 | 0 | 115 | | i_program_memory | program_memory | 5 | 5 | 0 | 0 | 1 | 1 | 116 | | i_ram_memory | ram_memory | 1 | 1 | 0 | 0 | 1 | 1 | 117 | | i_riscv_cpu | riscv_cpu | 597 | 549 | 48 | 0 | 30 | 0 | 118 | | i_alu | alu | 144 | 144 | 0 | 0 | 0 | 0 | 119 | | i_branch_test | branch_test | 29 | 29 | 0 | 0 | 0 | 0 | 120 | | i_data_bus_mux_a | data_bus_mux_a | 32 | 32 | 0 | 0 | 0 | 0 | 121 | | i_data_bus_mux_b | data_bus_mux_b | 22 | 22 | 0 | 0 | 0 | 0 | 122 | | i_decoder | decoder | 66 | 66 | 0 | 0 | 0 | 0 | 123 | | i_program_counter | program_counter | 86 | 86 | 0 | 0 | 30 | 0 | 124 | | i_register_file | register_file | 49 | 1 | 48 | 0 | 0 | 0 | 125 | | i_result_bus_mux | result_bus_mux | 32 | 32 | 0 | 0 | 0 | 0 | 126 | | i_shifter | shifter | 113 | 113 | 0 | 0 | 0 | 0 | 127 | | i_sign_extender | sign_extender | 24 | 24 | 0 | 0 | 0 | 0 | 128 | +----------------------------+--------------------+------------+------------+---------+------+-----+--------+ 129 | 130 | Smaller, faster systems are possible by taking short cuts - for example, if you don't fully decode the program memory address 131 | space you can save two levels of logic, and clock closer to 90 MHz. 132 | 133 | ## Say thanks! 134 | This design is licensed under the MIT license, so you are pretty much free to do whatever you want with it. 135 | 136 | If you find this really useful please drop me an email to say thanks. I'll love to hear what you are doing with it. 137 | 138 | If you find this really useful or is used commercially, consider buying me a virtual pizza, virtual beer or virtual dinner via PayPal. 139 | 140 | -------------------------------------------------------------------------------- /src/bus/bus_bridge.vhd: -------------------------------------------------------------------------------- 1 | --############################################################################### 2 | --# bus_bridge.vhd - A primative bridge from the CPU to peripheral bus. 3 | --# 4 | --# Part of the Rudi-RV32I project 5 | --# 6 | --# See https://github.com/hamsternz/Rudi-RV32I 7 | --# 8 | --# MIT License 9 | --# 10 | --############################################################################### 11 | --# 12 | --# Copyright (c) 2020 Mike Field 13 | --# 14 | --# Permission is hereby granted, free of charge, to any person obtaining a copy 15 | --# of this software and associated documentation files (the "Software"), to deal 16 | --# in the Software without restriction, including without limitation the rights 17 | --# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | --# copies of the Software, and to permit persons to whom the Software is 19 | --# furnished to do so, subject to the following conditions: 20 | --# 21 | --# The above copyright notice and this permission notice shall be included in all 22 | --# copies or substantial portions of the Software. 23 | --# 24 | --# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | --# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | --# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | --# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | --# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | --# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | --# SOFTWARE. 31 | --# 32 | --############################################################################### 33 | library IEEE; 34 | use IEEE.STD_LOGIC_1164.ALL; 35 | use IEEE.numeric_std.all; 36 | 37 | entity bus_bridge is 38 | generic (use_clk : in STD_LOGIC); 39 | port ( clk : in STD_LOGIC; 40 | cpu_bus_busy : out STD_LOGIC; 41 | cpu_bus_addr : in STD_LOGIC_VECTOR(31 downto 0); 42 | cpu_bus_width : in STD_LOGIC_VECTOR( 1 downto 0); 43 | cpu_bus_dout : in STD_LOGIC_VECTOR(31 downto 0); 44 | cpu_bus_write : in STD_LOGIC; 45 | cpu_bus_enable : in STD_LOGIC; 46 | cpu_bus_din : out STD_LOGIC_VECTOR(31 downto 0); 47 | 48 | m0_window_base : in STD_LOGIC_VECTOR(31 downto 0); 49 | m0_window_mask : in STD_LOGIC_VECTOR(31 downto 0); 50 | m0_bus_busy : in STD_LOGIC; 51 | m0_bus_addr : out STD_LOGIC_VECTOR(31 downto 2); 52 | m0_bus_enable : out STD_LOGIC; 53 | m0_bus_write_mask : out STD_LOGIC_VECTOR( 3 downto 0); 54 | m0_bus_write_data : out STD_LOGIC_VECTOR(31 downto 0); 55 | m0_bus_read_data : in STD_LOGIC_VECTOR(31 downto 0) := (others => '0'); 56 | 57 | m1_window_base : in STD_LOGIC_VECTOR(31 downto 0); 58 | m1_window_mask : in STD_LOGIC_VECTOR(31 downto 0); 59 | m1_bus_busy : in STD_LOGIC; 60 | m1_bus_addr : out STD_LOGIC_VECTOR(31 downto 2); 61 | m1_bus_enable : out STD_LOGIC; 62 | m1_bus_write_mask : out STD_LOGIC_VECTOR( 3 downto 0); 63 | m1_bus_write_data : out STD_LOGIC_VECTOR(31 downto 0); 64 | m1_bus_read_data : in STD_LOGIC_VECTOR(31 downto 0) := (others => '0'); 65 | 66 | m2_window_base : in STD_LOGIC_VECTOR(31 downto 0); 67 | m2_window_mask : in STD_LOGIC_VECTOR(31 downto 0); 68 | m2_bus_busy : in STD_LOGIC; 69 | m2_bus_addr : out STD_LOGIC_VECTOR(31 downto 2); 70 | m2_bus_enable : out STD_LOGIC; 71 | m2_bus_write_mask : out STD_LOGIC_VECTOR( 3 downto 0); 72 | m2_bus_write_data : out STD_LOGIC_VECTOR(31 downto 0); 73 | m2_bus_read_data : in STD_LOGIC_VECTOR(31 downto 0) := (others => '0') 74 | ); 75 | end entity; 76 | 77 | 78 | architecture Behavioral of bus_bridge is 79 | signal active : std_logic_vector( 2 downto 0); 80 | signal addr : STD_LOGIC_VECTOR(31 downto 0) := (others => '0'); 81 | signal write : std_logic; 82 | signal width : std_logic_vector( 1 downto 0); 83 | signal write_data : STD_LOGIC_VECTOR(31 downto 0) := (others => '0'); 84 | signal latched_addr : STD_LOGIC_VECTOR(31 downto 0) := (others => '0'); 85 | signal latched_write : std_logic; 86 | signal latched_width : std_logic_vector( 1 downto 0); 87 | signal latched_write_data : STD_LOGIC_VECTOR(31 downto 0) := (others => '0'); 88 | signal write_mask : STD_LOGIC_VECTOR( 3 downto 0); 89 | signal write_data_aligned : STD_LOGIC_VECTOR(31 downto 0); 90 | signal read_data : STD_LOGIC_VECTOR(31 downto 0); 91 | 92 | signal idle : STD_LOGIC := '0'; 93 | signal busy : STD_LOGIC := '0'; 94 | 95 | begin 96 | 97 | m0_bus_enable <= active(0); 98 | m0_bus_addr <= addr(31 downto 2) AND NOT m0_window_mask(31 downto 2); 99 | m0_bus_write_data <= write_data_aligned; 100 | m0_bus_write_mask <= write_mask; 101 | 102 | m1_bus_enable <= active(1); 103 | m1_bus_addr <= addr(31 downto 2) AND NOT m1_window_mask(31 downto 2); 104 | m1_bus_write_data <= write_data_aligned; 105 | m1_bus_write_mask <= write_mask; 106 | 107 | m2_bus_enable <= active(2); 108 | m2_bus_addr <= addr(31 downto 2) AND NOT m2_window_mask(31 downto 2); 109 | m2_bus_write_data <= write_data_aligned; 110 | m2_bus_write_mask <= write_mask; 111 | 112 | cpu_bus_busy <= busy; 113 | 114 | -- Tell the CPU interface when we are busy. 115 | busy <= (cpu_bus_enable and idle and use_clk) 116 | or (m0_bus_busy and active(0)) 117 | or (m2_bus_busy and active(2)) 118 | or (m1_bus_busy and active(1)); 119 | 120 | with use_clk select addr <= latched_addr when '1', cpu_bus_addr when others; 121 | with use_clk select write <= latched_write when '1', cpu_bus_write when others; 122 | with use_clk select write_data <= latched_write_data when '1', cpu_bus_dout when others; 123 | with use_clk select width <= latched_width when '1', cpu_bus_width when others; 124 | 125 | process(write_data, addr) 126 | begin 127 | case addr(1 downto 0) is 128 | when "00" => write_data_aligned <= write_data(31 downto 0); 129 | when "01" => write_data_aligned <= write_data(23 downto 0) & x"00"; 130 | when "10" => write_data_aligned <= write_data(15 downto 0) & x"0000"; 131 | when others => write_data_aligned <= write_data( 7 downto 0) & x"000000"; 132 | end case; 133 | end process; 134 | 135 | process(write, width, addr) 136 | begin 137 | write_mask <= "0000"; 138 | if write = '1' then 139 | case width & addr(1 downto 0) is 140 | when "0000" => write_mask <= "0001"; 141 | when "0001" => write_mask <= "0010"; 142 | when "0010" => write_mask <= "0100"; 143 | when "0011" => write_mask <= "1000"; 144 | 145 | when "0100" => write_mask <= "0011"; 146 | when "0101" => write_mask <= "0110"; 147 | when "0110" => write_mask <= "1100"; 148 | when "0111" => write_mask <= "1000"; 149 | 150 | when "1000" => write_mask <= "1111"; 151 | when "1001" => write_mask <= "1110"; 152 | when "1010" => write_mask <= "1100"; 153 | when "1011" => write_mask <= "1000"; 154 | 155 | when others => write_mask <= "0000"; 156 | end case; 157 | end if; 158 | end process; 159 | 160 | process(idle, addr, cpu_bus_enable, 161 | m0_window_base, m0_window_mask, 162 | m1_window_base, m1_window_mask, 163 | m2_window_base, m2_window_mask) 164 | begin 165 | active <= (others => '0'); 166 | if use_clk = '1' then 167 | if idle = '0' then 168 | if (addr and m0_window_mask) = m0_window_base then 169 | active(0) <= '1'; 170 | end if; 171 | 172 | if (addr and m1_window_mask) = m1_window_base then 173 | active(1) <= '1'; 174 | end if; 175 | 176 | if (addr and m2_window_mask) = m2_window_base then 177 | active(2) <= '1'; 178 | end if; 179 | end if; 180 | else 181 | if cpu_bus_enable = '1' then 182 | if (addr and m0_window_mask) = m0_window_base then 183 | active(0) <= '1'; 184 | end if; 185 | 186 | if (addr and m1_window_mask) = m1_window_base then 187 | active(1) <= '1'; 188 | end if; 189 | 190 | if (addr and m2_window_mask) = m2_window_base then 191 | active(2) <= '1'; 192 | end if; 193 | end if; 194 | end if; 195 | end process; 196 | 197 | process(clk) 198 | begin 199 | if rising_edge(clk) then 200 | idle <= '1'; 201 | if cpu_bus_enable = '1' then 202 | -- Take note of if the bus is currently busy 203 | idle <= not busy; 204 | -- Hold the address and write info in local registers. 205 | -- This is needed to give an endpoint for static timing analysis 206 | -- even if we don't expect these to change during the transaction. 207 | latched_addr <= cpu_bus_addr; 208 | latched_write_data <= cpu_bus_dout; 209 | latched_width <= cpu_bus_width; 210 | latched_write <= cpu_bus_write; 211 | end if; 212 | end if; 213 | end process; 214 | 215 | ------------------------------------ 216 | -- Work out which data is being read 217 | ------------------------------------ 218 | process(active, m0_bus_read_data, m1_bus_read_data, m2_bus_read_data) 219 | begin 220 | case active is 221 | when "001" => read_data <= m0_bus_read_data; 222 | when "010" => read_data <= m1_bus_read_data; 223 | when "100" => read_data <= m2_bus_read_data; 224 | when others => read_data <= m2_bus_read_data; -- Multiple active (most likely an error!) 225 | end case; 226 | end process; 227 | 228 | ------------------------------------------- 229 | -- Correct alignment and send it to the CPU 230 | ------------------------------------------- 231 | process(read_data, addr) 232 | begin 233 | case addr(1 downto 0) is 234 | when "00" => cpu_bus_din <= read_data(31 downto 0); 235 | when "01" => cpu_bus_din <= x"00" & read_data(31 downto 8); 236 | when "10" => cpu_bus_din <= x"0000" & read_data(31 downto 16); 237 | when "11" => cpu_bus_din <= x"000000" & read_data(31 downto 24); 238 | when others => cpu_bus_din <= read_data(31 downto 0); 239 | end case; 240 | end process; 241 | 242 | end Behavioral; 243 | -------------------------------------------------------------------------------- /src/systems/top_level.vhd: -------------------------------------------------------------------------------- 1 | --############################################################################### 2 | --# top_level.vhd - Top level design 3 | --# 4 | --# Part of the Rudi-RV32I project 5 | --# 6 | --# See https://github.com/hamsternz/Rudi-RV32I 7 | --# 8 | --# MIT License 9 | --# 10 | --############################################################################### 11 | --# 12 | --# Copyright (c) 2020 Mike Field 13 | --# 14 | --# Permission is hereby granted, free of charge, to any person obtaining a copy 15 | --# of this software and associated documentation files (the "Software"), to deal 16 | --# in the Software without restriction, including without limitation the rights 17 | --# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | --# copies of the Software, and to permit persons to whom the Software is 19 | --# furnished to do so, subject to the following conditions: 20 | --# 21 | --# The above copyright notice and this permission notice shall be included in all 22 | --# copies or substantial portions of the Software. 23 | --# 24 | --# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | --# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | --# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | --# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | --# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | --# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | --# SOFTWARE. 31 | --# 32 | --############################################################################### 33 | 34 | library IEEE; 35 | use IEEE.STD_LOGIC_1164.ALL; 36 | use IEEE.numeric_std.all; 37 | 38 | entity top_level is 39 | generic ( clock_freq : natural := 50000000; 40 | minimize_size : std_logic := '1'); 41 | port ( clk : in STD_LOGIC; 42 | uart_rxd_out : out STD_LOGIC := '1'; 43 | uart_txd_in : in STD_LOGIC; 44 | debug_sel : in STD_LOGIC_VECTOR(4 downto 0); 45 | debug_data : out STD_LOGIC_VECTOR(31 downto 0)); 46 | end entity; 47 | 48 | architecture Behavioral of top_level is 49 | 50 | component riscv_cpu is 51 | port ( clk : in STD_LOGIC; 52 | pc_next : out STD_LOGIC_VECTOR(31 downto 0); 53 | reset : in STD_LOGIC; 54 | minimize_size : in STD_LOGIC; 55 | 56 | bus_busy : in STD_LOGIC; 57 | bus_addr : out STD_LOGIC_VECTOR(31 downto 0); 58 | bus_width : out STD_LOGIC_VECTOR(1 downto 0); 59 | bus_write : out STD_LOGIC; 60 | bus_enable : out STD_LOGIC; 61 | bus_dout : out STD_LOGIC_VECTOR(31 downto 0); 62 | bus_din : in STD_LOGIC_VECTOR(31 downto 0); 63 | 64 | instr_reg : in STD_LOGIC_VECTOR(31 downto 0); 65 | debug_pc : out STD_LOGIC_VECTOR(31 downto 0); 66 | debug_sel : in STD_LOGIC_VECTOR(4 downto 0); 67 | debug_data : out STD_LOGIC_VECTOR(31 downto 0)); 68 | end component; 69 | 70 | signal pc_next : STD_LOGIC_VECTOR(31 downto 0); 71 | signal instr_reg : STD_LOGIC_VECTOR(31 downto 0); 72 | 73 | component program_memory is 74 | port ( clk : in STD_LOGIC; 75 | 76 | pc_next : in STD_LOGIC_VECTOR(31 downto 0); 77 | instr_reg : out STD_LOGIC_VECTOR(31 downto 0); 78 | 79 | bus_busy : out STD_LOGIC; 80 | bus_addr : in STD_LOGIC_VECTOR(11 downto 2); 81 | bus_enable : in STD_LOGIC; 82 | bus_write_mask : in STD_LOGIC_VECTOR(3 downto 0); 83 | bus_write_data : in STD_LOGIC_VECTOR(31 downto 0); 84 | bus_read_data : out STD_LOGIC_VECTOR(31 downto 0) := (others => '0')); 85 | 86 | end component; 87 | 88 | component bus_bridge is 89 | port ( clk : in STD_LOGIC; 90 | cpu_bus_busy : out STD_LOGIC; 91 | cpu_bus_addr : in STD_LOGIC_VECTOR(31 downto 0); 92 | cpu_bus_width : in STD_LOGIC_VECTOR( 1 downto 0); 93 | cpu_bus_dout : in STD_LOGIC_VECTOR(31 downto 0); 94 | cpu_bus_write : in STD_LOGIC; 95 | cpu_bus_enable : in STD_LOGIC; 96 | cpu_bus_din : out STD_LOGIC_VECTOR(31 downto 0); 97 | 98 | m0_window_base : in STD_LOGIC_VECTOR(31 downto 0); 99 | m0_window_mask : in STD_LOGIC_VECTOR(31 downto 0); 100 | m0_bus_busy : in STD_LOGIC; 101 | m0_bus_addr : out STD_LOGIC_VECTOR(31 downto 2); 102 | m0_bus_enable : out STD_LOGIC; 103 | m0_bus_write_mask : out STD_LOGIC_VECTOR( 3 downto 0); 104 | m0_bus_write_data : out STD_LOGIC_VECTOR(31 downto 0); 105 | m0_bus_read_data : in STD_LOGIC_VECTOR(31 downto 0); 106 | 107 | m1_window_base : in STD_LOGIC_VECTOR(31 downto 0); 108 | m1_window_mask : in STD_LOGIC_VECTOR(31 downto 0); 109 | m1_bus_busy : in STD_LOGIC; 110 | m1_bus_addr : out STD_LOGIC_VECTOR(31 downto 2); 111 | m1_bus_enable : out STD_LOGIC; 112 | m1_bus_write_mask : out STD_LOGIC_VECTOR( 3 downto 0); 113 | m1_bus_write_data : out STD_LOGIC_VECTOR(31 downto 0); 114 | m1_bus_read_data : in STD_LOGIC_VECTOR(31 downto 0); 115 | 116 | m2_window_base : in STD_LOGIC_VECTOR(31 downto 0); 117 | m2_window_mask : in STD_LOGIC_VECTOR(31 downto 0); 118 | m2_bus_busy : in STD_LOGIC; 119 | m2_bus_addr : out STD_LOGIC_VECTOR(31 downto 2); 120 | m2_bus_enable : out STD_LOGIC; 121 | m2_bus_write_mask : out STD_LOGIC_VECTOR( 3 downto 0); 122 | m2_bus_write_data : out STD_LOGIC_VECTOR(31 downto 0); 123 | m2_bus_read_data : in STD_LOGIC_VECTOR(31 downto 0)); 124 | end component; 125 | 126 | signal m0_bus_enable : STD_LOGIC; 127 | signal m0_bus_busy : STD_LOGIC; 128 | signal m0_bus_addr : STD_LOGIC_VECTOR(31 downto 2); 129 | signal m0_bus_write_mask : STD_LOGIC_VECTOR( 3 downto 0); 130 | signal m0_bus_write_data : STD_LOGIC_VECTOR(31 downto 0); 131 | signal m0_bus_read_data : STD_LOGIC_VECTOR(31 downto 0); 132 | 133 | 134 | signal m1_bus_busy : STD_LOGIC; 135 | signal m1_bus_addr : STD_LOGIC_VECTOR(31 downto 2); 136 | signal m1_bus_enable : STD_LOGIC; 137 | signal m1_bus_write_mask : STD_LOGIC_VECTOR( 3 downto 0); 138 | signal m1_bus_write_data : STD_LOGIC_VECTOR(31 downto 0); 139 | signal m1_bus_read_data : STD_LOGIC_VECTOR(31 downto 0); 140 | 141 | signal m2_bus_busy : STD_LOGIC; 142 | signal m2_bus_addr : STD_LOGIC_VECTOR(31 downto 2); 143 | signal m2_bus_enable : STD_LOGIC; 144 | signal m2_bus_write_mask : STD_LOGIC_VECTOR( 3 downto 0); 145 | signal m2_bus_write_data : STD_LOGIC_VECTOR(31 downto 0); 146 | signal m2_bus_read_data : STD_LOGIC_VECTOR(31 downto 0); 147 | 148 | component ram_memory is 149 | port ( clk : in STD_LOGIC; 150 | bus_enable : in STD_LOGIC; 151 | bus_addr : in STD_LOGIC_VECTOR(11 downto 2); 152 | bus_write_mask : in STD_LOGIC_VECTOR(3 downto 0); 153 | bus_write_data : in STD_LOGIC_VECTOR(31 downto 0); 154 | bus_busy : out STD_LOGIC; 155 | bus_read_data : out STD_LOGIC_VECTOR(31 downto 0)); 156 | end component; 157 | 158 | component peripheral_serial is 159 | generic ( clock_freq : natural; 160 | baud_rate : natural); 161 | port ( clk : in STD_LOGIC; 162 | bus_enable : in STD_LOGIC; 163 | bus_addr : in STD_LOGIC_VECTOR(3 downto 2); 164 | bus_write_mask : in STD_LOGIC_VECTOR(3 downto 0); 165 | bus_write_data : in STD_LOGIC_VECTOR(31 downto 0); 166 | bus_read_data : out STD_LOGIC_VECTOR(31 downto 0); 167 | bus_busy : out STD_LOGIC; 168 | 169 | serial_rx : in STD_LOGIC; 170 | serial_tx : out STD_LOGIC); 171 | end component; 172 | 173 | signal reset_sr : std_logic_vector(3 downto 0) := "1111"; 174 | 175 | signal debug_pc : STD_LOGIC_VECTOR(31 downto 0); 176 | 177 | signal cpu_bus_busy : STD_LOGIC := '1'; 178 | signal cpu_bus_addr : STD_LOGIC_VECTOR(31 downto 0); 179 | signal cpu_bus_width : STD_LOGIC_VECTOR(1 downto 0); 180 | signal cpu_bus_write : STD_LOGIC; 181 | signal cpu_bus_enable : STD_LOGIC; 182 | signal cpu_bus_dout : STD_LOGIC_VECTOR(31 downto 0); 183 | signal cpu_bus_din : STD_LOGIC_VECTOR(31 downto 0) := (others => '0'); 184 | begin 185 | 186 | process(clk) 187 | begin 188 | if rising_edge(clk) then 189 | reset_sr <= '0' & reset_sr(reset_sr'high downto 1); 190 | end if; 191 | end process; 192 | 193 | i_riscv_cpu: riscv_cpu port map( 194 | clk => clk, 195 | instr_reg => instr_reg, 196 | 197 | reset => reset_sr(0), 198 | minimize_size => minimize_size, 199 | 200 | bus_busy => cpu_bus_busy, 201 | bus_addr => cpu_bus_addr, 202 | bus_width => cpu_bus_width, 203 | bus_write => cpu_bus_write, 204 | bus_enable => cpu_bus_enable, 205 | bus_dout => cpu_bus_dout, 206 | bus_din => cpu_bus_din, 207 | 208 | pc_next => pc_next, 209 | debug_pc => debug_pc, 210 | debug_sel => debug_sel, 211 | debug_data => debug_data); 212 | 213 | 214 | i_bus_bridge: bus_bridge port map ( 215 | clk => clk, 216 | cpu_bus_busy => cpu_bus_busy, 217 | cpu_bus_addr => cpu_bus_addr, 218 | cpu_bus_width => cpu_bus_width, 219 | cpu_bus_dout => cpu_bus_dout, 220 | cpu_bus_write => cpu_bus_write, 221 | cpu_bus_enable => cpu_bus_enable, 222 | cpu_bus_din => cpu_bus_din, 223 | 224 | -- System RAM 225 | m0_window_base => x"10000000", 226 | m0_window_mask => x"FFFFF000", 227 | m0_bus_busy => m0_bus_busy, 228 | m0_bus_addr => m0_bus_addr, 229 | m0_bus_enable => m0_bus_enable, 230 | m0_bus_write_mask => m0_bus_write_mask, 231 | m0_bus_write_data => m0_bus_write_data, 232 | m0_bus_read_data => m0_bus_read_data, 233 | -- Serial console 234 | m1_window_base => x"E0000000", 235 | m1_window_mask => x"FFFFFFF0", 236 | m1_bus_busy => m1_bus_busy, 237 | m1_bus_addr => m1_bus_addr, 238 | m1_bus_enable => m1_bus_enable, 239 | m1_bus_write_mask => m1_bus_write_mask, 240 | m1_bus_write_data => m1_bus_write_data, 241 | m1_bus_read_data => m1_bus_read_data, 242 | -- Program ROM 243 | m2_window_base => x"F0000000", 244 | m2_window_mask => x"FFFFF000", 245 | m2_bus_busy => m2_bus_busy, 246 | m2_bus_addr => m2_bus_addr, 247 | m2_bus_enable => m2_bus_enable, 248 | m2_bus_write_mask => m2_bus_write_mask, 249 | m2_bus_write_data => m2_bus_write_data, 250 | m2_bus_read_data => m2_bus_read_data 251 | ); 252 | 253 | i_program_memory: program_memory port map ( 254 | clk => clk, 255 | 256 | pc_next => pc_next, 257 | instr_reg => instr_reg, 258 | 259 | bus_enable => m2_bus_enable, 260 | bus_addr => m2_bus_addr(11 downto 2), 261 | bus_busy => m2_bus_busy, 262 | bus_write_mask => m2_bus_write_mask, 263 | bus_write_data => m2_bus_write_data, 264 | bus_read_data => m2_bus_read_data); 265 | 266 | i_ram_memory: ram_memory port map ( 267 | clk => clk, 268 | bus_enable => m0_bus_enable, 269 | bus_addr => m0_bus_addr(11 downto 2), 270 | bus_busy => m0_bus_busy, 271 | bus_write_mask => m0_bus_write_mask, 272 | bus_write_data => m0_bus_write_data, 273 | bus_read_data => m0_bus_read_data); 274 | 275 | i_peripheral_serial: peripheral_serial generic map ( 276 | clock_freq => clock_freq, 277 | baud_rate => 19200 278 | ) port map ( 279 | clk => clk, 280 | bus_enable => m1_bus_enable, 281 | bus_addr => m1_bus_addr(3 downto 2), 282 | bus_busy => m1_bus_busy, 283 | bus_write_mask => m1_bus_write_mask, 284 | bus_write_data => m1_bus_write_data, 285 | bus_read_data => m1_bus_read_data, 286 | serial_rx => uart_txd_in, 287 | serial_tx => uart_rxd_out); 288 | 289 | end Behavioral; 290 | -------------------------------------------------------------------------------- /src/boards/zedboard/zedboard_top_level.vhd: -------------------------------------------------------------------------------- 1 | --############################################################################### 2 | --# zedboard_top_level.vhd - Top level HDL design for the Avnet Zedboard 3 | --# 4 | --# Part of the Rudi-RV32I project 5 | --# 6 | --# See https://github.com/hamsternz/Rudi-RV32I 7 | --# 8 | --# MIT License 9 | --# 10 | --############################################################################### 11 | --# 12 | --# Copyright (c) 2020 Mike Field and Iain Waugh 13 | --# 14 | --# Permission is hereby granted, free of charge, to any person obtaining a copy 15 | --# of this software and associated documentation files (the "Software"), to deal 16 | --# in the Software without restriction, including without limitation the rights 17 | --# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | --# copies of the Software, and to permit persons to whom the Software is 19 | --# furnished to do so, subject to the following conditions: 20 | --# 21 | --# The above copyright notice and this permission notice shall be included in all 22 | --# copies or substantial portions of the Software. 23 | --# 24 | --# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | --# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | --# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | --# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | --# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | --# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | --# SOFTWARE. 31 | --# 32 | --############################################################################### 33 | 34 | library ieee; 35 | use ieee.std_logic_1164.all; 36 | use ieee.numeric_std.all; 37 | 38 | library UNISIM; 39 | use UNISIM.vcomponents.all; 40 | 41 | entity zedboard_top_level is 42 | port ( 43 | ---------------------------------------------------------------------------- 44 | -- Clock Source - Bank 13 45 | clk100MHz : in std_logic; -- "GCLK" 46 | 47 | ---------------------------------------------------------------------------- 48 | -- Audio Codec - Bank 13 - Connects to ADAU1761BCPZ 49 | i_audio_adr0 : in std_logic; -- "AC-ADR0" 50 | o_audio_adr1 : out std_logic; -- "AC-ADR1" 51 | io_audio_gpio : inout std_logic_vector(3 downto 0); -- "AC-GPIO[3:0]" 52 | o_audio_mclk : out std_logic; -- "AC-MCLK" 53 | o_audio_sck : out std_logic; -- "AC-SCK" 54 | io_audio_sda : inout std_logic; -- "AC-SDA" 55 | 56 | ---------------------------------------------------------------------------- 57 | -- OLED Display - Bank 13 58 | o_oled_dc : out std_logic; -- "OLED-DC" 59 | o_oled_res : out std_logic; -- "OLED-RES" 60 | o_oled_sclk : out std_logic; -- "OLED-SCLK" 61 | o_oled_sdin : out std_logic; -- "OLED-SDIN" 62 | o_oled_vbat : out std_logic; -- "OLED-VBAT" 63 | o_oled_vdd : out std_logic; -- "OLED-VDD" 64 | 65 | ---------------------------------------------------------------------------- 66 | -- HDMI Output - Bank 33 67 | o_hdmi_clk : out std_logic; -- "HD-CLK" 68 | o_hdmi_hsync : out std_logic; -- "HD-HSYNC" 69 | o_hdmi_vsync : out std_logic; -- "HD-VSYNC" 70 | o_hdmi_data : out std_logic_vector(15 downto 0); -- "HD-D[15:0]" 71 | o_hdmi_dval : out std_logic; -- "HD-DE" 72 | o_hdmi_int : out std_logic; -- "HD-INT" 73 | io_hdmi_scl : inout std_logic; -- "HD-SCL" 74 | io_hdmi_sda : inout std_logic; -- "HD-SDA" 75 | o_hdmi_spdif : out std_logic; -- "HD-SPDIF" 76 | i_hdmi_spdifo : in std_logic; -- "HD-SPDIFO" 77 | 78 | ---------------------------------------------------------------------------- 79 | -- User LEDs - Bank 33 80 | o_led : out std_logic_vector(7 downto 0); -- "LD[7:0]" 81 | 82 | ---------------------------------------------------------------------------- 83 | -- VGA Output - Bank 33 84 | o_vga_hs : out std_logic; -- "VGA-HS" 85 | o_vga_vs : out std_logic; -- "VGA-VS" 86 | o_vga_red : out unsigned(3 downto 0); -- "VGA-R[3:0]" 87 | o_vga_green : out unsigned(3 downto 0); -- "VGA-G[3:0]" 88 | o_vga_blue : out unsigned(3 downto 0); -- "VGA-B[3:0]" 89 | 90 | ---------------------------------------------------------------------------- 91 | -- User Push Buttons - Bank 34 92 | i_btn_c : in std_logic; -- "BTNC" 93 | i_btn_d : in std_logic; -- "BTND" 94 | i_btn_l : in std_logic; -- "BTNL" 95 | i_btn_r : in std_logic; -- "BTNR" 96 | i_btn_u : in std_logic; -- "BTNU" 97 | 98 | -- ---------------------------------------------------------------------------- 99 | -- USB OTG Reset - Bank 34 100 | o_otg_vbusoc : out std_logic; -- "OTG-VBUSOC" 101 | 102 | ---------------------------------------------------------------------------- 103 | -- XADC GIO - Bank 34 104 | io_xadc_gio : inout std_logic_vector(3 downto 0); -- "XADC-GIO[3:0]" 105 | 106 | ---------------------------------------------------------------------------- 107 | -- Miscellaneous - Bank 34 108 | i_pudc_b : in std_logic; -- "PUDC_B" 109 | 110 | ---------------------------------------------------------------------------- 111 | -- USB OTG Reset - Bank 35 112 | o_otg_reset_n : out std_logic; -- "OTG-RESETN" 113 | 114 | ---------------------------------------------------------------------------- 115 | -- User DIP Switches - Bank 35 116 | i_sw : in std_logic_vector(7 downto 0); -- "SW[7:0]" 117 | 118 | ---------------------------------------------------------------------------- 119 | -- XADC AD Channels - Bank 35 120 | i_ad0n_r : in std_logic; -- "XADC-AD0N-R" 121 | i_ad0p_r : in std_logic; -- "XADC-AD0P-R" 122 | i_ad8n_n : in std_logic; -- "XADC-AD8N-R" 123 | i_ad8p_r : in std_logic; -- "XADC-AD8P-R" 124 | 125 | ---------------------------------------------------------------------------- 126 | -- FMC Expansion Connector - Bank 13 127 | io_fmc_scl : inout std_logic; -- "FMC-SCL" 128 | io_fmc_sda : inout std_logic; -- "FMC-SDA" 129 | 130 | ---------------------------------------------------------------------------- 131 | -- FMC Expansion Connector - Bank 33 132 | i_fmc_prsnt : in std_logic; -- "FMC-PRSNT" 133 | 134 | ---------------------------------------------------------------------------- 135 | -- Partial PMOD JA (used as a UART) 136 | ja1 : out std_logic; 137 | ja2 : in std_logic 138 | ); 139 | end entity; 140 | 141 | architecture Behavioral of zedboard_top_level is 142 | 143 | constant ext_clock_rate : natural := 100000000; 144 | constant multiplier : real := 10.000; 145 | constant divider : real := 14.750; 146 | constant bus_bridge_use_clk : std_logic := '0'; 147 | constant bus_expander_use_clk : std_logic := '0'; 148 | constant cpu_minimize_size : std_logic := '0'; 149 | 150 | -- Internal clocking signals 151 | signal clk : std_logic; 152 | signal fb : std_logic; 153 | 154 | signal gpio : std_logic_vector(15 downto 0); 155 | 156 | -- Tristate breakout signals 157 | signal i_audio_gpio : std_logic_vector(3 downto 0); 158 | signal o_audio_gpio : std_logic_vector(3 downto 0) := (others => '0'); 159 | signal audio_gpio_out : std_logic := '0'; 160 | 161 | signal i_audio_sda : std_logic; 162 | signal o_audio_sda : std_logic := '0'; 163 | signal audio_sda_out : std_logic := '0'; 164 | 165 | signal i_hdmi_scl : std_logic; 166 | signal o_hdmi_scl : std_logic := '0'; 167 | signal hdmi_scl_out : std_logic := '0'; 168 | 169 | signal i_hdmi_sda : std_logic; 170 | signal o_hdmi_sda : std_logic := '0'; 171 | signal hdmi_sda_out : std_logic := '0'; 172 | 173 | signal i_xadc_gio : std_logic_vector(3 downto 0); 174 | signal o_xadc_gio : std_logic_vector(3 downto 0) := (others => '0'); 175 | signal xadc_gio_out : std_logic := '0'; 176 | 177 | signal i_fmc_scl : std_logic; 178 | signal o_fmc_scl : std_logic := '0'; 179 | signal fmc_scl_out : std_logic := '0'; 180 | 181 | signal i_fmc_sda : std_logic; 182 | signal o_fmc_sda : std_logic := '0'; 183 | signal fmc_sda_out : std_logic := '0'; 184 | 185 | begin 186 | 187 | MMCME2_BASE_inst : MMCME2_BASE 188 | generic map ( 189 | BANDWIDTH => "OPTIMIZED", -- Jitter programming (OPTIMIZED, HIGH, LOW) 190 | CLKFBOUT_MULT_F => multiplier, -- Multiply value for all CLKOUT (2.000-64.000). 191 | CLKFBOUT_PHASE => 0.0, -- Phase offset in degrees of CLKFB (-360.000-360.000). 192 | CLKIN1_PERIOD => 0.0, -- Input clock period in ns to ps resolution (i.e. 33.333 is 30 MHz). 193 | -- CLKOUT0_DIVIDE - CLKOUT6_DIVIDE: Divide amount for each CLKOUT (1-128) 194 | CLKOUT1_DIVIDE => 1, 195 | CLKOUT2_DIVIDE => 1, 196 | CLKOUT3_DIVIDE => 1, 197 | CLKOUT4_DIVIDE => 1, 198 | CLKOUT5_DIVIDE => 1, 199 | CLKOUT6_DIVIDE => 1, 200 | CLKOUT0_DIVIDE_F => divider, -- Divide amount for CLKOUT0 (1.000-128.000). 201 | -- CLKOUT0_DUTY_CYCLE - CLKOUT6_DUTY_CYCLE: Duty cycle for each CLKOUT (0.01-0.99). 202 | CLKOUT0_DUTY_CYCLE => 0.5, 203 | CLKOUT1_DUTY_CYCLE => 0.5, 204 | CLKOUT2_DUTY_CYCLE => 0.5, 205 | CLKOUT3_DUTY_CYCLE => 0.5, 206 | CLKOUT4_DUTY_CYCLE => 0.5, 207 | CLKOUT5_DUTY_CYCLE => 0.5, 208 | CLKOUT6_DUTY_CYCLE => 0.5, 209 | -- CLKOUT0_PHASE - CLKOUT6_PHASE: Phase offset for each CLKOUT (-360.000-360.000). 210 | CLKOUT0_PHASE => 0.0, 211 | CLKOUT1_PHASE => 0.0, 212 | CLKOUT2_PHASE => 0.0, 213 | CLKOUT3_PHASE => 0.0, 214 | CLKOUT4_PHASE => 0.0, 215 | CLKOUT5_PHASE => 0.0, 216 | CLKOUT6_PHASE => 0.0, 217 | CLKOUT4_CASCADE => false, -- Cascade CLKOUT4 counter with CLKOUT6 (FALSE, TRUE) 218 | DIVCLK_DIVIDE => 1, -- Master division value (1-106) 219 | REF_JITTER1 => 0.0, -- Reference input jitter in UI (0.000-0.999). 220 | STARTUP_WAIT => false -- Delays DONE until MMCM is locked (FALSE, TRUE) 221 | ) 222 | port map ( 223 | -- Clock Outputs: 1-bit (each) output: User configurable clock outputs 224 | CLKOUT0 => clk, -- 1-bit output: CLKOUT0 225 | CLKOUT0B => open, -- 1-bit output: Inverted CLKOUT0 226 | CLKOUT1 => open, -- 1-bit output: CLKOUT1 227 | CLKOUT1B => open, -- 1-bit output: Inverted CLKOUT1 228 | CLKOUT2 => open, -- 1-bit output: CLKOUT2 229 | CLKOUT2B => open, -- 1-bit output: Inverted CLKOUT2 230 | CLKOUT3 => open, -- 1-bit output: CLKOUT3 231 | CLKOUT3B => open, -- 1-bit output: Inverted CLKOUT3 232 | CLKOUT4 => open, -- 1-bit output: CLKOUT4 233 | CLKOUT5 => open, -- 1-bit output: CLKOUT5 234 | CLKOUT6 => open, -- 1-bit output: CLKOUT6 235 | -- Feedback Clocks: 1-bit (each) output: Clock feedback ports 236 | CLKFBOUT => fb, -- 1-bit output: Feedback clock 237 | CLKFBOUTB => open, -- 1-bit output: Inverted CLKFBOUT 238 | -- Status Ports: 1-bit (each) output: MMCM status ports 239 | LOCKED => open, -- 1-bit output: LOCK 240 | -- Clock Inputs: 1-bit (each) input: Clock input 241 | CLKIN1 => clk100MHz, -- 1-bit input: Clock 242 | -- Control Ports: 1-bit (each) input: MMCM control ports 243 | PWRDWN => '0', -- 1-bit input: Power-down 244 | RST => '0', -- 1-bit input: Reset 245 | -- Feedback Clocks: 1-bit (each) input: Clock feedback ports 246 | CLKFBIN => fb -- 1-bit input: Feedback clock 247 | ); 248 | 249 | i_top_level_expanded : entity work.top_level_expanded 250 | generic map ( 251 | clock_freq => natural(real(ext_clock_rate)/divider), 252 | bus_bridge_use_clk => bus_bridge_use_clk, 253 | bus_expander_use_clk => bus_expander_use_clk, 254 | cpu_minimize_size => cpu_minimize_size 255 | ) 256 | port map ( 257 | clk => clk, 258 | uart_rxd_out => ja1, 259 | uart_txd_in => ja2, 260 | gpio => gpio, 261 | debug_sel => "00000", 262 | debug_data => open 263 | ); 264 | o_led <= gpio(7 downto 0); 265 | 266 | 267 | --========================================================================== 268 | -- 269 | -- Tie off unused ports/signal (don't leave them floating) 270 | 271 | ---------------------------------------------------------------------------- 272 | -- Audio Codec - Bank 13 - Connects to ADAU1761BCPZ 273 | o_audio_adr1 <= '0'; 274 | o_audio_mclk <= '0'; 275 | o_audio_sck <= '0'; 276 | 277 | i_audio_gpio <= io_audio_gpio; 278 | io_audio_gpio <= o_audio_gpio when audio_gpio_out = '1' else (others => 'Z'); 279 | 280 | i_audio_sda <= io_audio_sda; 281 | io_audio_sda <= o_audio_sda when audio_sda_out = '1' else 'Z'; 282 | 283 | ---------------------------------------------------------------------------- 284 | -- OLED Display - Bank 13 285 | o_oled_dc <= '0'; 286 | o_oled_res <= '0'; 287 | o_oled_sclk <= '0'; 288 | o_oled_sdin <= '0'; 289 | o_oled_vbat <= '0'; 290 | o_oled_vdd <= '0'; 291 | 292 | ---------------------------------------------------------------------------- 293 | -- HDMI Output - Bank 33 294 | o_hdmi_clk <= '0'; 295 | o_hdmi_hsync <= '0'; 296 | o_hdmi_vsync <= '0'; 297 | o_hdmi_data <= (others => '0'); 298 | o_hdmi_dval <= '0'; 299 | o_hdmi_int <= '0'; 300 | o_hdmi_spdif <= '0'; 301 | 302 | i_hdmi_scl <= io_hdmi_scl; 303 | io_hdmi_scl <= o_hdmi_scl when hdmi_scl_out = '1' else 'Z'; 304 | 305 | i_hdmi_sda <= io_hdmi_sda; 306 | io_hdmi_sda <= o_hdmi_sda when hdmi_sda_out = '1' else 'Z'; 307 | 308 | i_xadc_gio <= io_xadc_gio; 309 | io_xadc_gio <= o_xadc_gio when xadc_gio_out = '1' else (others => 'Z'); 310 | 311 | ---------------------------------------------------------------------------- 312 | -- USB OTG Reset - Bank 35 313 | o_otg_vbusoc <= '0'; 314 | o_otg_reset_n <= '0'; 315 | 316 | ---------------------------------------------------------------------------- 317 | -- FMC Expansion Connector - Bank 13 318 | i_fmc_scl <= io_fmc_scl; 319 | io_fmc_scl <= o_fmc_scl when fmc_scl_out = '1' else 'Z'; 320 | 321 | i_fmc_sda <= io_fmc_sda; 322 | io_fmc_sda <= o_fmc_sda when fmc_sda_out = '1' else 'Z'; 323 | 324 | end Behavioral; 325 | -------------------------------------------------------------------------------- /src/cpu/riscv_cpu.vhd: -------------------------------------------------------------------------------- 1 | --############################################################################### 2 | --# riscv_cpu.vhd - The core cpu 3 | --# 4 | --# Part of the Rudi-RV32I project 5 | --# 6 | --# See https://github.com/hamsternz/Rudi-RV32I 7 | --# 8 | --# MIT License 9 | --# 10 | --############################################################################### 11 | --# 12 | --# Copyright (c) 2020 Mike Field 13 | --# 14 | --# Permission is hereby granted, free of charge, to any person obtaining a copy 15 | --# of this software and associated documentation files (the "Software"), to deal 16 | --# in the Software without restriction, including without limitation the rights 17 | --# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 18 | --# copies of the Software, and to permit persons to whom the Software is 19 | --# furnished to do so, subject to the following conditions: 20 | --# 21 | --# The above copyright notice and this permission notice shall be included in all 22 | --# copies or substantial portions of the Software. 23 | --# 24 | --# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 25 | --# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 26 | --# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 27 | --# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 28 | --# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 29 | --# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30 | --# SOFTWARE. 31 | --# 32 | --############################################################################### 33 | 34 | library IEEE; 35 | use IEEE.STD_LOGIC_1164.ALL; 36 | use IEEE.numeric_std.all; 37 | 38 | entity riscv_cpu is 39 | port ( clk : in STD_LOGIC; 40 | pc_next : out STD_LOGIC_VECTOR(31 downto 0); 41 | instr_reg : in STD_LOGIC_VECTOR(31 downto 0); 42 | 43 | reset : in STD_LOGIC; 44 | minimize_size : in STD_LOGIC := '0'; 45 | 46 | bus_busy : in STD_LOGIC; 47 | bus_addr : out STD_LOGIC_VECTOR(31 downto 0); 48 | bus_width : out STD_LOGIC_VECTOR(1 downto 0); 49 | bus_dout : out STD_LOGIC_VECTOR(31 downto 0); 50 | bus_write : out STD_LOGIC; 51 | bus_enable : out STD_LOGIC; 52 | bus_din : in STD_LOGIC_VECTOR(31 downto 0); 53 | 54 | debug_pc : out STD_LOGIC_VECTOR(31 downto 0); 55 | debug_sel : in STD_LOGIC_VECTOR(4 downto 0); 56 | debug_data : out STD_LOGIC_VECTOR(31 downto 0)); 57 | end entity; 58 | 59 | 60 | architecture Behavioral of riscv_cpu is 61 | -- signal instr_reg : STD_LOGIC_VECTOR(31 downto 0); 62 | 63 | component data_bus_mux_a is 64 | port ( bus_select : in STD_LOGIC_VECTOR( 0 downto 0); 65 | zero : in STD_LOGIC_VECTOR( 0 downto 0); 66 | reg_read_port : in STD_LOGIC_VECTOR(31 downto 0); 67 | pc : in STD_LOGIC_VECTOR(31 downto 0); 68 | data_bus : out STD_LOGIC_VECTOR(31 downto 0)); 69 | end component; 70 | 71 | 72 | component sign_extender is 73 | port ( sign_ex_mode : in STD_LOGIC_VECTOR(0 downto 0); 74 | sign_ex_width : in STD_LOGIC_VECTOR(1 downto 0); 75 | a : in STD_LOGIC_VECTOR(31 downto 0); 76 | b : out STD_LOGIC_VECTOR(31 downto 0)); 77 | end component; 78 | signal sign_extended : STD_LOGIC_VECTOR(31 downto 0); 79 | 80 | component data_bus_mux_b is 81 | port ( bus_select : in STD_LOGIC_VECTOR( 0 downto 0); 82 | zero : in STD_LOGIC_VECTOR( 0 downto 0); 83 | reg_read_port : in STD_LOGIC_VECTOR(31 downto 0); 84 | immedediate : in STD_LOGIC_VECTOR(31 downto 0); 85 | data_bus : out STD_LOGIC_VECTOR(31 downto 0)); 86 | end component; 87 | 88 | component result_bus_mux is 89 | port ( res_src : in STD_LOGIC_VECTOR( 1 downto 0); 90 | res_alu : in STD_LOGIC_VECTOR(31 downto 0); 91 | res_shifter : in STD_LOGIC_VECTOR(31 downto 0); 92 | res_pc_plus_four : in STD_LOGIC_VECTOR(31 downto 0); 93 | res_memory : in STD_LOGIC_VECTOR(31 downto 0); 94 | res_bus : out STD_LOGIC_VECTOR(31 downto 0)); 95 | end component; 96 | 97 | signal a_bus : STD_LOGIC_VECTOR(31 downto 0); 98 | signal b_bus : STD_LOGIC_VECTOR(31 downto 0); 99 | signal c_bus : STD_LOGIC_VECTOR(31 downto 0); 100 | signal pc : STD_LOGIC_VECTOR(31 downto 0); 101 | signal pc_plus_four : STD_LOGIC_VECTOR(31 downto 0); 102 | 103 | component decoder is 104 | port ( reset : in STD_LOGIC; 105 | minimize_size : in STD_LOGIC := '0'; 106 | instr : in STD_LOGIC_VECTOR(31 downto 0); 107 | out_immed : out STD_LOGIC_VECTOR(31 downto 0) := (others => '0'); 108 | 109 | out_reg_a : out STD_LOGIC_VECTOR(4 downto 0) := (others => '0'); 110 | out_select_a : out STD_LOGIC_VECTOR(0 downto 0) := (others => '0'); 111 | out_zero_a : out STD_LOGIC_VECTOR(0 downto 0) := (others => '0'); 112 | 113 | out_reg_b : out STD_LOGIC_VECTOR(4 downto 0) := (others => '0'); 114 | out_select_b : out STD_LOGIC_VECTOR(0 downto 0) := (others => '0'); 115 | out_zero_b : out STD_LOGIC_VECTOR(0 downto 0) := (others => '0'); 116 | 117 | out_bus_width : out STD_LOGIC_VECTOR(1 downto 0); 118 | out_bus_write : out STD_LOGIC; 119 | out_bus_enable : out STD_LOGIC; 120 | 121 | out_pc_mode : out STD_LOGIC_VECTOR(1 downto 0) := "00"; 122 | out_pc_jump_offset : out STD_LOGIC_VECTOR(31 downto 0) := (others => '0'); 123 | out_pc_branch_offset : out STD_LOGIC_VECTOR(31 downto 0) := (others => '0'); 124 | out_loadstore_offset : out STD_LOGIC_VECTOR(31 downto 0) := (others => '0'); 125 | out_alu_mode : out STD_LOGIC_VECTOR(2 downto 0) := "000"; 126 | out_branch_test_mode : out STD_LOGIC_VECTOR(2 downto 0) := "000"; 127 | out_branch_test_enable : out STD_LOGIC := '0'; 128 | out_shift_mode : out STD_LOGIC_VECTOR(1 downto 0) := "00"; 129 | 130 | out_sign_ex_mode : out STD_LOGIC_VECTOR(0 downto 0) := "0"; 131 | out_sign_ex_width : out STD_LOGIC_VECTOR(1 downto 0) := "00"; 132 | 133 | out_result_src : out STD_LOGIC_VECTOR(1 downto 0) := (others => '0'); 134 | out_rdest : out STD_LOGIC_VECTOR(4 downto 0) := (others => '0')); 135 | end component; 136 | 137 | signal decode_immed : STD_LOGIC_VECTOR(31 downto 0) := (others => '0'); 138 | signal decode_register_a : STD_LOGIC_VECTOR(4 downto 0) := (others => '0'); 139 | signal decode_register_b : STD_LOGIC_VECTOR(4 downto 0) := (others => '0'); 140 | signal decode_select_a : STD_LOGIC_VECTOR(0 downto 0); 141 | signal decode_select_b : STD_LOGIC_VECTOR(0 downto 0); 142 | signal decode_zero_a : STD_LOGIC_VECTOR(0 downto 0); 143 | signal decode_zero_b : STD_LOGIC_VECTOR(0 downto 0); 144 | 145 | signal decode_pc_mode : STD_LOGIC_VECTOR(1 downto 0) := "00"; 146 | signal decode_pc_jump_offset : STD_LOGIC_VECTOR(31 downto 0) := (others => '0'); 147 | signal decode_pc_branch_offset : STD_LOGIC_VECTOR(31 downto 0) := (others => '0'); 148 | signal decode_loadstore_offset : STD_LOGIC_VECTOR(31 downto 0) := (others => '0'); 149 | 150 | signal decode_alu_mode : STD_LOGIC_VECTOR(2 downto 0) := "000"; 151 | signal decode_branch_test_mode : STD_LOGIC_VECTOR(2 downto 0) := "000"; 152 | signal decode_branch_test_enable : STD_LOGIC := '0'; 153 | signal decode_shift_mode : STD_LOGIC_VECTOR(1 downto 0) := "00"; 154 | signal decode_bus_write : STD_LOGIC; 155 | signal decode_bus_enable : STD_LOGIC; 156 | signal decode_bus_width : STD_LOGIC_VECTOR(1 downto 0); 157 | 158 | signal decode_sign_ex_mode : STD_LOGIC_VECTOR(0 downto 0); 159 | signal decode_sign_ex_width : STD_LOGIC_VECTOR(1 downto 0); 160 | 161 | signal decode_result_src : STD_LOGIC_VECTOR(1 downto 0) := (others => '0'); 162 | signal decode_register_dest : STD_LOGIC_VECTOR(4 downto 0) := (others => '0'); 163 | 164 | component alu is 165 | port ( alu_mode : in STD_LOGIC_VECTOR(2 downto 0); 166 | a : in STD_LOGIC_VECTOR(31 downto 0); 167 | b : in STD_LOGIC_VECTOR(31 downto 0); 168 | c : out STD_LOGIC_VECTOR(31 downto 0) := (others => '0')); 169 | end component; 170 | signal c_alu : STD_LOGIC_VECTOR(31 downto 0); 171 | 172 | 173 | component shifter is 174 | port ( shift_mode : in STD_LOGIC_VECTOR(1 downto 0) := "00"; 175 | minimize_size : in STD_LOGIC; 176 | a : in STD_LOGIC_VECTOR(31 downto 0); 177 | b : in STD_LOGIC_VECTOR(31 downto 0); 178 | c : out STD_LOGIC_VECTOR(31 downto 0) := (others => '0')); 179 | end component; 180 | signal c_shifter : STD_LOGIC_VECTOR(31 downto 0); 181 | 182 | component register_file is 183 | port ( clk : in STD_LOGIC; 184 | busy : in STD_LOGIC; 185 | read_port_1_addr : in STD_LOGIC_VECTOR( 4 downto 0); 186 | read_data_1 : out STD_LOGIC_VECTOR(31 downto 0); 187 | read_port_2_addr : in STD_LOGIC_VECTOR( 4 downto 0); 188 | read_data_2 : out STD_LOGIC_VECTOR(31 downto 0); 189 | write_port_addr : in STD_LOGIC_VECTOR( 4 downto 0); 190 | write_data : in STD_LOGIC_VECTOR(31 downto 0); 191 | debug_sel : in STD_LOGIC_VECTOR(4 downto 0); 192 | debug_data : out STD_LOGIC_VECTOR(31 downto 0)); 193 | end component; 194 | signal reg_read_data_a : STD_LOGIC_VECTOR(31 downto 0); 195 | signal reg_read_data_b : STD_LOGIC_VECTOR(31 downto 0); 196 | 197 | component branch_test is 198 | port ( branch_test_mode : in STD_LOGIC_VECTOR(2 downto 0); 199 | branch_test_enable : in STD_LOGIC; 200 | minimize_size : in STD_LOGIC; 201 | a : in STD_LOGIC_VECTOR(31 downto 0); 202 | b : in STD_LOGIC_VECTOR(31 downto 0); 203 | take_branch : out STD_LOGIC); 204 | end component; 205 | 206 | signal take_branch : std_logic; 207 | 208 | component program_counter is 209 | port ( clk : in STD_LOGIC; 210 | busy : in STD_LOGIC; 211 | minimize_size : in STD_LOGIC; 212 | 213 | pc_mode : in STD_LOGIC_VECTOR(1 downto 0); 214 | take_branch : in STD_LOGIC; 215 | pc_jump_offset : in STD_LOGIC_VECTOR(31 downto 0); 216 | pc_branch_offset : in STD_LOGIC_VECTOR(31 downto 0); 217 | pc_jumpreg_offset: in STD_LOGIC_VECTOR(31 downto 0); 218 | 219 | a : in STD_LOGIC_VECTOR(31 downto 0); 220 | 221 | pc : out STD_LOGIC_VECTOR(31 downto 0); 222 | pc_next : out STD_LOGIC_VECTOR(31 downto 0); 223 | pc_plus_four : out STD_LOGIC_VECTOR(31 downto 0)); 224 | end component; 225 | 226 | 227 | begin 228 | debug_pc <= pc; 229 | 230 | -- Set up the RAM address 231 | bus_write <= decode_bus_write; 232 | bus_enable <= decode_bus_enable; 233 | bus_width <= decode_bus_width; 234 | bus_dout <= reg_read_data_b; 235 | 236 | process(minimize_size, decode_loadstore_offset, reg_read_data_a, c_alu, decode_immed) 237 | begin 238 | if minimize_size = '1' then 239 | bus_addr <= c_alu; 240 | else 241 | bus_addr <= std_logic_vector(unsigned(reg_read_data_a)+unsigned(decode_loadstore_offset)); 242 | -- bus_addr <= std_logic_vector(unsigned(reg_read_data_a)+unsigned(decode_immed)); 243 | end if; 244 | end process; 245 | 246 | i_decoder: decoder port map ( 247 | instr => instr_reg, 248 | minimize_size => minimize_size, 249 | reset => reset, 250 | 251 | out_bus_write => decode_bus_write, 252 | out_bus_enable => decode_bus_enable, 253 | out_bus_width => decode_bus_width, 254 | 255 | out_immed => decode_immed, 256 | 257 | out_reg_a => decode_register_a, 258 | out_select_a => decode_select_a, 259 | out_zero_a => decode_zero_a, 260 | 261 | out_reg_b => decode_register_b, 262 | out_select_b => decode_select_b, 263 | out_zero_b => decode_zero_b, 264 | 265 | out_pc_mode => decode_pc_mode, 266 | out_pc_jump_offset => decode_pc_jump_offset, 267 | out_pc_branch_offset => decode_pc_branch_offset, 268 | out_loadstore_offset => decode_loadstore_offset, 269 | 270 | out_alu_mode => decode_alu_mode, 271 | out_branch_test_mode => decode_branch_test_mode, 272 | out_branch_test_enable => decode_branch_test_enable, 273 | out_shift_mode => decode_shift_mode, 274 | 275 | out_result_src => decode_result_src, 276 | 277 | out_sign_ex_mode => decode_sign_ex_mode, 278 | out_sign_ex_width => decode_sign_ex_width, 279 | 280 | out_rdest => decode_register_dest); 281 | 282 | i_alu: alu port map ( 283 | alu_mode => decode_alu_mode, 284 | a => a_bus, 285 | b => b_bus, 286 | c => c_alu); 287 | 288 | i_shifter: shifter port map ( 289 | shift_mode => decode_shift_mode, 290 | minimize_size => minimize_size, 291 | a => reg_read_data_a, --a_bus, 292 | b => b_bus, 293 | c => c_shifter); 294 | 295 | i_sign_extender: sign_extender PORT MAP ( 296 | sign_ex_mode => decode_sign_ex_mode, 297 | sign_ex_width => decode_sign_ex_width, 298 | a => bus_din, 299 | b => sign_extended); 300 | 301 | i_result_bus_mux: result_bus_mux port map ( 302 | res_src => decode_result_src, 303 | res_alu => c_alu, 304 | res_shifter => c_shifter, 305 | res_pc_plus_four => pc_plus_four, 306 | res_memory => sign_extended, 307 | res_bus => c_bus); 308 | 309 | i_register_file: register_file port map ( 310 | clk => clk, 311 | read_port_1_addr => decode_register_a, 312 | read_data_1 => reg_read_data_a, 313 | read_port_2_addr => decode_register_b, 314 | read_data_2 => reg_read_data_b, 315 | 316 | write_port_addr => decode_register_dest, 317 | write_data => c_bus, 318 | busy => bus_busy, 319 | 320 | debug_sel => debug_sel, 321 | debug_data => debug_data); 322 | 323 | i_data_bus_mux_a: data_bus_mux_a port map ( 324 | bus_select => decode_select_a, 325 | zero => decode_zero_a, 326 | reg_read_port => reg_read_data_a, 327 | pc => pc, 328 | data_bus => a_bus); 329 | 330 | i_data_bus_mux_b: data_bus_mux_b port map ( 331 | bus_select => decode_select_b, 332 | zero => decode_zero_b, 333 | reg_read_port => reg_read_data_b, 334 | immedediate => decode_immed, 335 | data_bus => b_bus); 336 | 337 | i_branch_test: branch_test port map ( 338 | branch_test_mode => decode_branch_test_mode, 339 | branch_test_enable => decode_branch_test_enable, 340 | minimize_size => minimize_size, 341 | a => reg_read_data_a, 342 | b => reg_read_data_b, 343 | take_branch => take_branch); 344 | 345 | i_program_counter: program_counter port map ( 346 | clk => clk, 347 | busy => bus_busy, 348 | minimize_size => minimize_size, 349 | 350 | pc_mode => decode_pc_mode, 351 | take_branch => take_branch, 352 | pc_jump_offset => decode_pc_jump_offset, 353 | pc_branch_offset => decode_pc_branch_offset, 354 | pc_jumpreg_offset=> decode_immed, 355 | a => reg_read_data_a, 356 | -- outputs 357 | pc => pc, 358 | pc_next => pc_next, 359 | pc_plus_four => pc_plus_four); 360 | 361 | end Behavioral; 362 | --------------------------------------------------------------------------------