├── out └── .gitignore ├── .gitignore ├── mrisc32-a1-pipeline.png ├── misc ├── README.md └── mrisc32.sdc ├── make_png.sh ├── rtl ├── sau │ ├── Makefile │ └── sau.vhd ├── ctrl │ ├── Makefile │ ├── cctrl.vhd │ └── sync.vhd ├── agu │ ├── Makefile │ ├── vector_stride_gen.vhd │ └── agu.vhd ├── core │ ├── Makefile │ ├── dcache.vhd │ └── core_1mem.vhd ├── muldiv │ ├── Makefile │ ├── div_stage.vhd │ └── div_pipelined.vhd ├── Makefile ├── common │ ├── Makefile │ ├── debug.vhd │ ├── skid_buffer_bit.vhd │ ├── comparator.vhd │ ├── skid_buffer.vhd │ ├── ram_dual_port.vhd │ ├── fifo.vhd │ └── config.vhd ├── fpu │ ├── Makefile │ ├── fpu_test_gen.cpp │ ├── float_compose.vhd │ ├── itof_clz_and_left_shift.vhd │ ├── float_compare.vhd │ ├── funp.vhd │ └── float_decompose.vhd ├── alu │ ├── Makefile │ ├── sel32.vhd │ ├── rev32.vhd │ ├── xchgsr.vhd │ ├── add32.vhd │ ├── sub32.vhd │ ├── shuf32.vhd │ └── popcnt32.vhd ├── pipeline │ ├── Makefile │ ├── reg.vhd │ ├── pc_plus_4.vhd │ ├── pc_plus_offset.vhd │ ├── register_file.vhd │ ├── register_file_read_port.vhd │ └── forward_to_vector_control.vhd └── toplevel.vhd ├── benchmark ├── Makefile ├── benchmark.sdc ├── mul32_bench.vhd ├── div_bench.vhd └── fpu_bench.vhd ├── test ├── programs │ ├── simple.s │ ├── Makefile │ ├── memory.s │ └── branches.s ├── Makefile ├── shuf32_tb.vhd ├── popcnt32_tb.vhd ├── reg_tb.vhd ├── comparator_tb.vhd ├── float_decompose_tb.vhd ├── skid_buffer_tb.vhd ├── clz32_tb.vhd ├── funp_tb.vhd └── vector_stride_gen_tb.vhd ├── run_test.sh ├── Makefile ├── run_program.sh └── README.md /out/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.cf 3 | *_tb 4 | *.bin 5 | *_gen 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.elf 3 | *.bin 4 | *_tb 5 | *.vcd 6 | *.ghw 7 | *.gtkw 8 | 9 | -------------------------------------------------------------------------------- /mrisc32-a1-pipeline.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mrisc32/mrisc32-a1/HEAD/mrisc32-a1-pipeline.png -------------------------------------------------------------------------------- /misc/README.md: -------------------------------------------------------------------------------- 1 | # Miscellaneous 2 | 3 | ## mrisc32.sdc 4 | 5 | Constraints file that defines a 100 MHz clock. Useful for quick synthesis checks (e.g. in Intel Quartus). 6 | 7 | -------------------------------------------------------------------------------- /make_png.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | GFX_START=32768 4 | GFX_W=256 5 | GFX_H=256 6 | GFX_SIZE=$((${GFX_W} * ${GFX_H})) 7 | 8 | if [ $# -eq 0 ] ; then 9 | echo "Usage: $0 ram-dump-file" 10 | exit 1 11 | fi 12 | 13 | RAM_FILE="$1" 14 | PNG_FILE="${RAM_FILE}.png" 15 | 16 | cat "${RAM_FILE}" | tail -c +$((${GFX_START} + 1)) | head -c ${GFX_SIZE} | convert -size ${GFX_W}x${GFX_H} -depth 8 gray:- "${PNG_FILE}" 17 | 18 | -------------------------------------------------------------------------------- /misc/mrisc32.sdc: -------------------------------------------------------------------------------- 1 | # Constrain clock port i_clk with a 10 ns requirement (100 MHz). 2 | create_clock -period 12.5 [get_ports i_clk] 3 | 4 | # Automatically apply a generate clock on the output of phase-locked loops (PLLs). 5 | # This command can be safely left in the SDC even if no PLLs exist in the design. 6 | derive_pll_clocks 7 | 8 | # Constrain the input I/O path. 9 | set_input_delay -clock i_clk -max 2 [all_inputs] 10 | set_input_delay -clock i_clk -min 1 [all_inputs] 11 | 12 | -------------------------------------------------------------------------------- /rtl/sau/Makefile: -------------------------------------------------------------------------------- 1 | #################################################################################################### 2 | # Copyright (c) 2018 Marcus Geelnard 3 | # 4 | # This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | # authors be held liable for any damages arising from the use of this software. 6 | # 7 | # Permission is granted to anyone to use this software for any purpose, including commercial 8 | # applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | # 10 | # 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | # the original software. If you use this software in a product, an acknowledgment in the 12 | # product documentation would be appreciated but is not required. 13 | # 14 | # 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | # being the original software. 16 | # 17 | # 3. This notice may not be removed or altered from any source distribution. 18 | #################################################################################################### 19 | 20 | SAU_PATH = rtl/sau 21 | 22 | SRCS += \ 23 | $(SAU_PATH)/sau_impl.vhd \ 24 | $(SAU_PATH)/sau.vhd 25 | 26 | -------------------------------------------------------------------------------- /rtl/ctrl/Makefile: -------------------------------------------------------------------------------- 1 | #################################################################################################### 2 | # Copyright (c) 2023 Marcus Geelnard 3 | # 4 | # This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | # authors be held liable for any damages arising from the use of this software. 6 | # 7 | # Permission is granted to anyone to use this software for any purpose, including commercial 8 | # applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | # 10 | # 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | # the original software. If you use this software in a product, an acknowledgment in the 12 | # product documentation would be appreciated but is not required. 13 | # 14 | # 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | # being the original software. 16 | # 17 | # 3. This notice may not be removed or altered from any source distribution. 18 | #################################################################################################### 19 | 20 | CTRL_PATH = rtl/ctrl 21 | 22 | SRCS += \ 23 | $(CTRL_PATH)/cctrl.vhd \ 24 | $(CTRL_PATH)/sync.vhd 25 | 26 | -------------------------------------------------------------------------------- /rtl/agu/Makefile: -------------------------------------------------------------------------------- 1 | #################################################################################################### 2 | # Copyright (c) 2018 Marcus Geelnard 3 | # 4 | # This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | # authors be held liable for any damages arising from the use of this software. 6 | # 7 | # Permission is granted to anyone to use this software for any purpose, including commercial 8 | # applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | # 10 | # 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | # the original software. If you use this software in a product, an acknowledgment in the 12 | # product documentation would be appreciated but is not required. 13 | # 14 | # 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | # being the original software. 16 | # 17 | # 3. This notice may not be removed or altered from any source distribution. 18 | #################################################################################################### 19 | 20 | AGU_PATH = rtl/agu 21 | 22 | SRCS += \ 23 | $(AGU_PATH)/vector_stride_gen.vhd \ 24 | $(AGU_PATH)/agu.vhd 25 | 26 | -------------------------------------------------------------------------------- /benchmark/Makefile: -------------------------------------------------------------------------------- 1 | #################################################################################################### 2 | # Copyright (c) 2018 Marcus Geelnard 3 | # 4 | # This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | # authors be held liable for any damages arising from the use of this software. 6 | # 7 | # Permission is granted to anyone to use this software for any purpose, including commercial 8 | # applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | # 10 | # 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | # the original software. If you use this software in a product, an acknowledgment in the 12 | # product documentation would be appreciated but is not required. 13 | # 14 | # 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | # being the original software. 16 | # 17 | # 3. This notice may not be removed or altered from any source distribution. 18 | #################################################################################################### 19 | 20 | BENCHMARK_PATH = benchmark 21 | 22 | SRCS += \ 23 | $(BENCHMARK_PATH)/mul32_bench.vhd \ 24 | $(BENCHMARK_PATH)/fpu_bench.vhd 25 | -------------------------------------------------------------------------------- /benchmark/benchmark.sdc: -------------------------------------------------------------------------------- 1 | #################################################################################################### 2 | ## Copyright (c) 2018 Marcus Geelnard 3 | ## 4 | ## This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | ## authors be held liable for any damages arising from the use of this software. 6 | ## 7 | ## Permission is granted to anyone to use this software for any purpose, including commercial 8 | ## applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | ## 10 | ## 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | ## the original software. If you use this software in a product, an acknowledgment in the 12 | ## product documentation would be appreciated but is not required. 13 | ## 14 | ## 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | ## being the original software. 16 | ## 17 | ## 3. This notice may not be removed or altered from any source distribution. 18 | #################################################################################################### 19 | 20 | # Default system clock: 142.857 MHz (7 ns) 21 | create_clock -name {i_clk} -period 7.0 -waveform { 0.0 3.5 } [get_ports {i_clk}] 22 | 23 | -------------------------------------------------------------------------------- /rtl/core/Makefile: -------------------------------------------------------------------------------- 1 | #################################################################################################### 2 | # Copyright (c) 2019 Marcus Geelnard 3 | # 4 | # This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | # authors be held liable for any damages arising from the use of this software. 6 | # 7 | # Permission is granted to anyone to use this software for any purpose, including commercial 8 | # applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | # 10 | # 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | # the original software. If you use this software in a product, an acknowledgment in the 12 | # product documentation would be appreciated but is not required. 13 | # 14 | # 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | # being the original software. 16 | # 17 | # 3. This notice may not be removed or altered from any source distribution. 18 | #################################################################################################### 19 | 20 | CORE_PATH = rtl/core 21 | 22 | SRCS += \ 23 | $(CORE_PATH)/icache.vhd \ 24 | $(CORE_PATH)/dcache.vhd \ 25 | $(CORE_PATH)/core.vhd \ 26 | $(CORE_PATH)/mem_arbiter.vhd \ 27 | $(CORE_PATH)/core_1mem.vhd 28 | 29 | -------------------------------------------------------------------------------- /rtl/muldiv/Makefile: -------------------------------------------------------------------------------- 1 | #################################################################################################### 2 | # Copyright (c) 2018 Marcus Geelnard 3 | # 4 | # This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | # authors be held liable for any damages arising from the use of this software. 6 | # 7 | # Permission is granted to anyone to use this software for any purpose, including commercial 8 | # applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | # 10 | # 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | # the original software. If you use this software in a product, an acknowledgment in the 12 | # product documentation would be appreciated but is not required. 13 | # 14 | # 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | # being the original software. 16 | # 17 | # 3. This notice may not be removed or altered from any source distribution. 18 | #################################################################################################### 19 | 20 | MULDIV_PATH = rtl/muldiv 21 | 22 | SRCS += \ 23 | $(MULDIV_PATH)/mul_impl.vhd \ 24 | $(MULDIV_PATH)/mul.vhd \ 25 | $(MULDIV_PATH)/div.vhd \ 26 | $(MULDIV_PATH)/div_impl.vhd \ 27 | $(MULDIV_PATH)/div_stage.vhd \ 28 | $(MULDIV_PATH)/div_pipelined.vhd 29 | 30 | -------------------------------------------------------------------------------- /rtl/Makefile: -------------------------------------------------------------------------------- 1 | #################################################################################################### 2 | # Copyright (c) 2018 Marcus Geelnard 3 | # 4 | # This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | # authors be held liable for any damages arising from the use of this software. 6 | # 7 | # Permission is granted to anyone to use this software for any purpose, including commercial 8 | # applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | # 10 | # 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | # the original software. If you use this software in a product, an acknowledgment in the 12 | # product documentation would be appreciated but is not required. 13 | # 14 | # 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | # being the original software. 16 | # 17 | # 3. This notice may not be removed or altered from any source distribution. 18 | #################################################################################################### 19 | 20 | include rtl/common/Makefile 21 | include rtl/agu/Makefile 22 | include rtl/alu/Makefile 23 | include rtl/ctrl/Makefile 24 | include rtl/fpu/Makefile 25 | include rtl/muldiv/Makefile 26 | include rtl/sau/Makefile 27 | include rtl/pipeline/Makefile 28 | include rtl/core/Makefile 29 | 30 | SRCS += \ 31 | rtl/toplevel.vhd 32 | 33 | -------------------------------------------------------------------------------- /rtl/common/Makefile: -------------------------------------------------------------------------------- 1 | #################################################################################################### 2 | # Copyright (c) 2018 Marcus Geelnard 3 | # 4 | # This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | # authors be held liable for any damages arising from the use of this software. 6 | # 7 | # Permission is granted to anyone to use this software for any purpose, including commercial 8 | # applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | # 10 | # 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | # the original software. If you use this software in a product, an acknowledgment in the 12 | # product documentation would be appreciated but is not required. 13 | # 14 | # 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | # being the original software. 16 | # 17 | # 3. This notice may not be removed or altered from any source distribution. 18 | #################################################################################################### 19 | 20 | COMMON_PATH = rtl/common 21 | 22 | SRCS += \ 23 | $(COMMON_PATH)/comparator.vhd \ 24 | $(COMMON_PATH)/config.vhd \ 25 | $(COMMON_PATH)/debug.vhd \ 26 | $(COMMON_PATH)/fifo.vhd \ 27 | $(COMMON_PATH)/ram_dual_port.vhd \ 28 | $(COMMON_PATH)/skid_buffer.vhd \ 29 | $(COMMON_PATH)/skid_buffer_bit.vhd \ 30 | $(COMMON_PATH)/types.vhd 31 | 32 | -------------------------------------------------------------------------------- /rtl/fpu/Makefile: -------------------------------------------------------------------------------- 1 | #################################################################################################### 2 | # Copyright (c) 2018 Marcus Geelnard 3 | # 4 | # This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | # authors be held liable for any damages arising from the use of this software. 6 | # 7 | # Permission is granted to anyone to use this software for any purpose, including commercial 8 | # applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | # 10 | # 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | # the original software. If you use this software in a product, an acknowledgment in the 12 | # product documentation would be appreciated but is not required. 13 | # 14 | # 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | # being the original software. 16 | # 17 | # 3. This notice may not be removed or altered from any source distribution. 18 | #################################################################################################### 19 | 20 | FPU_PATH = rtl/fpu 21 | 22 | SRCS += \ 23 | $(FPU_PATH)/float_decompose.vhd \ 24 | $(FPU_PATH)/float_compose.vhd \ 25 | $(FPU_PATH)/float_compare.vhd \ 26 | $(FPU_PATH)/fadd.vhd \ 27 | $(FPU_PATH)/fmul.vhd \ 28 | $(FPU_PATH)/ftoi.vhd \ 29 | $(FPU_PATH)/itof_clz_and_left_shift.vhd \ 30 | $(FPU_PATH)/itof.vhd \ 31 | $(FPU_PATH)/funp.vhd \ 32 | $(FPU_PATH)/fpack.vhd \ 33 | $(FPU_PATH)/fpu_impl.vhd \ 34 | $(FPU_PATH)/fpu.vhd 35 | 36 | -------------------------------------------------------------------------------- /rtl/alu/Makefile: -------------------------------------------------------------------------------- 1 | #################################################################################################### 2 | # Copyright (c) 2018 Marcus Geelnard 3 | # 4 | # This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | # authors be held liable for any damages arising from the use of this software. 6 | # 7 | # Permission is granted to anyone to use this software for any purpose, including commercial 8 | # applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | # 10 | # 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | # the original software. If you use this software in a product, an acknowledgment in the 12 | # product documentation would be appreciated but is not required. 13 | # 14 | # 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | # being the original software. 16 | # 17 | # 3. This notice may not be removed or altered from any source distribution. 18 | #################################################################################################### 19 | 20 | ALU_PATH = rtl/alu 21 | 22 | SRCS += \ 23 | $(ALU_PATH)/add32.vhd \ 24 | $(ALU_PATH)/clz32.vhd \ 25 | $(ALU_PATH)/crc32.vhd \ 26 | $(ALU_PATH)/crc32c.vhd \ 27 | $(ALU_PATH)/cmp32.vhd \ 28 | $(ALU_PATH)/pack32.vhd \ 29 | $(ALU_PATH)/popcnt32.vhd \ 30 | $(ALU_PATH)/rev32.vhd \ 31 | $(ALU_PATH)/sel32.vhd \ 32 | $(ALU_PATH)/shift32.vhd \ 33 | $(ALU_PATH)/shuf32.vhd \ 34 | $(ALU_PATH)/sub32.vhd \ 35 | $(ALU_PATH)/xchgsr.vhd \ 36 | $(ALU_PATH)/alu.vhd 37 | 38 | -------------------------------------------------------------------------------- /rtl/common/debug.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2019 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | library ieee; 21 | use ieee.std_logic_1164.all; 22 | use work.config.all; 23 | 24 | package debug is 25 | -- Set this to true to enable debug trace output. 26 | constant C_DEBUG_ENABLE_TRACE : boolean := false; 27 | 28 | type T_DEBUG_TRACE is record 29 | valid : std_logic; 30 | src_a_valid : std_logic; 31 | src_b_valid : std_logic; 32 | src_c_valid : std_logic; 33 | pc : std_logic_vector(C_WORD_SIZE-1 downto 0); 34 | src_a : std_logic_vector(C_WORD_SIZE-1 downto 0); 35 | src_b : std_logic_vector(C_WORD_SIZE-1 downto 0); 36 | src_c : std_logic_vector(C_WORD_SIZE-1 downto 0); 37 | end record T_DEBUG_TRACE; 38 | end package; 39 | -------------------------------------------------------------------------------- /rtl/pipeline/Makefile: -------------------------------------------------------------------------------- 1 | #################################################################################################### 2 | # Copyright (c) 2018 Marcus Geelnard 3 | # 4 | # This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | # authors be held liable for any damages arising from the use of this software. 6 | # 7 | # Permission is granted to anyone to use this software for any purpose, including commercial 8 | # applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | # 10 | # 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | # the original software. If you use this software in a product, an acknowledgment in the 12 | # product documentation would be appreciated but is not required. 13 | # 14 | # 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | # being the original software. 16 | # 17 | # 3. This notice may not be removed or altered from any source distribution. 18 | #################################################################################################### 19 | 20 | PIPELINE_PATH = rtl/pipeline 21 | 22 | SRCS += \ 23 | $(PIPELINE_PATH)/reg.vhd \ 24 | $(PIPELINE_PATH)/register_file.vhd \ 25 | $(PIPELINE_PATH)/register_file_read_port.vhd \ 26 | $(PIPELINE_PATH)/vector_control.vhd \ 27 | $(PIPELINE_PATH)/pc_plus_4.vhd \ 28 | $(PIPELINE_PATH)/pc_plus_offset.vhd \ 29 | $(PIPELINE_PATH)/branch_predictor.vhd \ 30 | $(PIPELINE_PATH)/fetch.vhd \ 31 | $(PIPELINE_PATH)/decode.vhd \ 32 | $(PIPELINE_PATH)/register_fetch.vhd \ 33 | $(PIPELINE_PATH)/execute.vhd \ 34 | $(PIPELINE_PATH)/memory.vhd \ 35 | $(PIPELINE_PATH)/forward_to_vector_control.vhd \ 36 | $(PIPELINE_PATH)/forward_to_ex.vhd \ 37 | $(PIPELINE_PATH)/pipeline.vhd 38 | 39 | -------------------------------------------------------------------------------- /test/programs/simple.s: -------------------------------------------------------------------------------- 1 | ; -*- mode: mr32asm; tab-width: 8; indent-tabs-mode: t; -*- 2 | ;-------------------------------------------------------------------------------------------------- 3 | ; Copyright (c) 2022 Marcus Geelnard 4 | ; 5 | ; This software is provided 'as-is', without any express or implied warranty. In no event will the 6 | ; authors be held liable for any damages arising from the use of this software. 7 | ; 8 | ; Permission is granted to anyone to use this software for any purpose, including commercial 9 | ; applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | ; 11 | ; 1. The origin of this software must not be misrepresented; you must not claim that you wrote 12 | ; the original software. If you use this software in a product, an acknowledgment in the 13 | ; product documentation would be appreciated but is not required. 14 | ; 15 | ; 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 16 | ; being the original software. 17 | ; 18 | ; 3. This notice may not be removed or altered from any source distribution. 19 | ;-------------------------------------------------------------------------------------------------- 20 | 21 | ;-------------------------------------------------------------------------------------------------- 22 | ; A simple program that is useful for basic debugging. 23 | ;-------------------------------------------------------------------------------------------------- 24 | 25 | .section .text.start, "ax" 26 | .globl _start 27 | _start: 28 | ldi sp, #0x10000 29 | 30 | ldi r1, #1 31 | loop: 32 | add r2, r1, #7 33 | mul r3, r2, #11 34 | stw r3, [sp, #-4] ; Should stall, waiting for the mul result. 35 | add r1, r1, #1 36 | slt r2, r1, #5 37 | bs r2, loop 38 | 39 | div r3, r2, #9 ; Should stall 40 | b _start ; Should give branch correction during stall 41 | 42 | -------------------------------------------------------------------------------- /test/programs/Makefile: -------------------------------------------------------------------------------- 1 | # -*- mode: Makefile; tab-width: 8; indent-tabs-mode: t; -*- 2 | #################################################################################################### 3 | # Copyright (c) 2021 Marcus Geelnard 4 | # 5 | # This software is provided 'as-is', without any express or implied warranty. In no event will the 6 | # authors be held liable for any damages arising from the use of this software. 7 | # 8 | # Permission is granted to anyone to use this software for any purpose, including commercial 9 | # applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | # 11 | # 1. The origin of this software must not be misrepresented; you must not claim that you wrote 12 | # the original software. If you use this software in a product, an acknowledgment in the 13 | # product documentation would be appreciated but is not required. 14 | # 15 | # 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 16 | # being the original software. 17 | # 18 | # 3. This notice may not be removed or altered from any source distribution. 19 | #################################################################################################### 20 | 21 | TEST_PROGRAMS_PATH = test/programs 22 | 23 | EXTRA += \ 24 | $(WORKDIR)/branches.bin \ 25 | $(WORKDIR)/memory.bin \ 26 | $(WORKDIR)/simple.bin 27 | 28 | $(WORKDIR)/branches.bin: $(TEST_PROGRAMS_PATH)/branches.s 29 | mrisc32-elf-gcc -mno-crt0 -mno-ctor-dtor $< -o $(WORKDIR)/branches.elf 30 | mrisc32-elf-objcopy -O binary $(WORKDIR)/branches.elf $@ 31 | 32 | $(WORKDIR)/memory.bin: $(TEST_PROGRAMS_PATH)/memory.s 33 | mrisc32-elf-gcc -mno-crt0 -mno-ctor-dtor $< -o $(WORKDIR)/memory.elf 34 | mrisc32-elf-objcopy -O binary $(WORKDIR)/memory.elf $@ 35 | 36 | $(WORKDIR)/simple.bin: $(TEST_PROGRAMS_PATH)/simple.s 37 | mrisc32-elf-gcc -mno-crt0 -mno-ctor-dtor $< -o $(WORKDIR)/simple.elf 38 | mrisc32-elf-objcopy -O binary $(WORKDIR)/simple.elf $@ 39 | 40 | -------------------------------------------------------------------------------- /run_test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #################################################################################################### 4 | # Copyright (c) 2018 Marcus Geelnard 5 | # 6 | # This software is provided 'as-is', without any express or implied warranty. In no event will the 7 | # authors be held liable for any damages arising from the use of this software. 8 | # 9 | # Permission is granted to anyone to use this software for any purpose, including commercial 10 | # applications, and to alter it and redistribute it freely, subject to the following restrictions: 11 | # 12 | # 1. The origin of this software must not be misrepresented; you must not claim that you wrote 13 | # the original software. If you use this software in a product, an acknowledgment in the 14 | # product documentation would be appreciated but is not required. 15 | # 16 | # 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 17 | # being the original software. 18 | # 19 | # 3. This notice may not be removed or altered from any source distribution. 20 | #################################################################################################### 21 | 22 | WORKDIR=out 23 | GHDL=ghdl 24 | GHDLFLAGS="--std=08 --work=work --workdir=${WORKDIR}" 25 | 26 | for i in {0..5}; do 27 | if [ "$1" = "--vcd" ]; then 28 | VCD=yes 29 | shift 30 | fi 31 | if [ "$1" = "--wave" ]; then 32 | WAVE=yes 33 | shift 34 | fi 35 | if [ "$1" = "--assert" ]; then 36 | GHDLRUNFLAGS="${GHDLRUNFLAGS} --assert-level=warning --backtrace-severity=warning" 37 | shift 38 | fi 39 | done 40 | 41 | for i in $*; do 42 | echo "** TEST: $i" 43 | if [ "x${VCD}" = "xyes" ]; then 44 | ${GHDL} -r ${GHDLFLAGS} "$i" "--vcd=${WORKDIR}/$i.vcd" ${GHDLRUNFLAGS} 45 | elif [ "x${WAVE}" = "xyes" ]; then 46 | ${GHDL} -r ${GHDLFLAGS} "$i" "--wave=${WORKDIR}/$i.ghw" ${GHDLRUNFLAGS} 47 | else 48 | ${GHDL} -r ${GHDLFLAGS} "$i" ${GHDLRUNFLAGS} 49 | fi 50 | echo "" 51 | done 52 | 53 | -------------------------------------------------------------------------------- /test/programs/memory.s: -------------------------------------------------------------------------------- 1 | ; -*- mode: mr32asm; tab-width: 8; indent-tabs-mode: t; -*- 2 | ;-------------------------------------------------------------------------------------------------- 3 | ; Copyright (c) 2022 Marcus Geelnard 4 | ; 5 | ; This software is provided 'as-is', without any express or implied warranty. In no event will the 6 | ; authors be held liable for any damages arising from the use of this software. 7 | ; 8 | ; Permission is granted to anyone to use this software for any purpose, including commercial 9 | ; applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | ; 11 | ; 1. The origin of this software must not be misrepresented; you must not claim that you wrote 12 | ; the original software. If you use this software in a product, an acknowledgment in the 13 | ; product documentation would be appreciated but is not required. 14 | ; 15 | ; 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 16 | ; being the original software. 17 | ; 18 | ; 3. This notice may not be removed or altered from any source distribution. 19 | ;-------------------------------------------------------------------------------------------------- 20 | 21 | ;-------------------------------------------------------------------------------------------------- 22 | ; A program that tests various aspects of memory accesses. 23 | ;-------------------------------------------------------------------------------------------------- 24 | 25 | .section .text.start, "ax" 26 | .globl _start 27 | _start: 28 | ldi sp, #0x10000 29 | 30 | outer_loop: 31 | ldi r1, #0x12345678 32 | 33 | stw r1, [sp, #0] 34 | stw r1, [sp, #4] 35 | stw r1, [sp, #8] 36 | 37 | nop 38 | nop 39 | nop 40 | 41 | ldw r1, [sp, #0] 42 | ldw r2, [sp, #4] 43 | ldw r3, [sp, #8] 44 | 45 | nop 46 | nop 47 | nop 48 | 49 | ldh r1, [sp, #0] 50 | sth r1, [sp, #4] 51 | ldh r2, [sp, #2] 52 | sth r2, [sp, #6] 53 | 54 | nop 55 | nop 56 | nop 57 | 58 | b outer_loop 59 | 60 | -------------------------------------------------------------------------------- /rtl/pipeline/reg.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2018 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | library ieee; 21 | use ieee.std_logic_1164.all; 22 | 23 | entity reg is 24 | generic(WIDTH : positive := 32); 25 | port( 26 | i_clk : in std_logic; 27 | i_rst : in std_logic; 28 | 29 | i_we : in std_logic; -- Write enable 30 | i_data_w : in std_logic_vector(WIDTH-1 downto 0); -- Data to be written 31 | o_data : out std_logic_vector(WIDTH-1 downto 0) -- Register content (read data) 32 | ); 33 | end reg; 34 | 35 | architecture behavioural of reg is 36 | begin 37 | -- We update the register content on positive clock edges. 38 | process(i_clk, i_rst) 39 | begin 40 | if i_rst = '1' then 41 | o_data <= (others => '0'); 42 | elsif rising_edge(i_clk) then 43 | if (i_we = '1') then 44 | o_data <= i_data_w; 45 | end if; 46 | end if; 47 | end process; 48 | end behavioural; 49 | -------------------------------------------------------------------------------- /rtl/fpu/fpu_test_gen.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | float raw2float(const uint32_t x) { 6 | float y; 7 | std::memcpy(&y, &x, sizeof(y)); 8 | return y; 9 | } 10 | 11 | uint32_t float2raw(const float x) { 12 | uint32_t y; 13 | std::memcpy(&y, &x, sizeof(y)); 14 | return y; 15 | } 16 | 17 | // Print decomposed. 18 | void pd(const uint32_t x) { 19 | const auto sign = (x & 0x80000000u) != 0u; 20 | const auto exp = (x >> 23) & 0xffu; 21 | const auto significand = (x & 0x7fffffu) | 0x800000u; 22 | printf("(%s, %02x, %06x)", sign ? "-" : "+", exp, significand); 23 | } 24 | 25 | void fmul(const uint32_t a, const uint32_t b) { 26 | const auto c = float2raw(raw2float(a) * raw2float(b)); 27 | printf("0x%08x * 0x%08x = 0x%08x\n", a, b, c); 28 | printf("%.8g * %.8g = %.8g\n", 29 | raw2float(a), raw2float(b), raw2float(c)); 30 | pd(a); printf(" * "); pd(b); printf(" = "); pd(c); printf("\n\n"); 31 | } 32 | 33 | void fadd(const uint32_t a, const uint32_t b) { 34 | const auto c = float2raw(raw2float(a) + raw2float(b)); 35 | printf("0x%08x + 0x%08x = 0x%08x\n", a, b, c); 36 | printf("%.8g + %.8g = %.8g\n", 37 | raw2float(a), raw2float(b), raw2float(c)); 38 | pd(a); printf(" + "); pd(b); printf(" = "); pd(c); printf("\n\n"); 39 | } 40 | 41 | void fsub(const uint32_t a, const uint32_t b) { 42 | fadd(a, b ^ 0x80000000u); 43 | } 44 | 45 | int main() { 46 | fmul(0x40490fdbu, 0x40f8a3d7u); 47 | fmul(0x7f000000u, 0xff000000u); 48 | fmul(0x00000000u, 0x7f800000u); 49 | fmul(0x402df854u, 0x3fb504f3u); 50 | fmul(0x7f555555u, 0x3f8ccccdu); 51 | fmul(0x7f555555u, 0x3fa66666u); 52 | fmul(0x00d55555u, 0x3f000000u); 53 | fmul(0x3fb504f3u, 0x3fb504f3u); 54 | fmul(0x3fb504f3u, 0x3fb504f4u); 55 | fmul(0xc0000000u, 0x7f800000u); 56 | 57 | fadd(0x40490fdbu, 0x40f8a3d7u); 58 | fadd(0x3f800000u, 0x3f800000u); 59 | fsub(0x40490fdbu, 0x40f8a3d7u); 60 | fadd(0x7e7fffffu, 0x7e7fffffu); 61 | fadd(0x7f000000u, 0x7f000000u); 62 | fsub(0x00880000u, 0x00800000u); 63 | } 64 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #################################################################################################### 2 | # Copyright (c) 2018 Marcus Geelnard 3 | # 4 | # This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | # authors be held liable for any damages arising from the use of this software. 6 | # 7 | # Permission is granted to anyone to use this software for any purpose, including commercial 8 | # applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | # 10 | # 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | # the original software. If you use this software in a product, an acknowledgment in the 12 | # product documentation would be appreciated but is not required. 13 | # 14 | # 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | # being the original software. 16 | # 17 | # 3. This notice may not be removed or altered from any source distribution. 18 | #################################################################################################### 19 | 20 | WORKDIR = out 21 | SW_SRC_DIR = ../../sw 22 | 23 | GHDL = ghdl 24 | GHDLWARNINGS = \ 25 | -Wbinding \ 26 | -Wreserved \ 27 | -Wlibrary \ 28 | -Wvital-generic \ 29 | -Wbody \ 30 | -Wspecs \ 31 | -Wunused \ 32 | -Werror 33 | GHDLFLAGS = --std=08 -g --work=work --workdir=$(WORKDIR) $(GHDLWARNINGS) 34 | 35 | .PHONY: all clean 36 | 37 | default: all 38 | 39 | SRCS = 40 | TESTS = 41 | EXTRA = 42 | 43 | include rtl/Makefile 44 | include test/Makefile 45 | include benchmark/Makefile 46 | include test/programs/Makefile 47 | 48 | all: $(TESTS) $(EXTRA) 49 | 50 | $(TESTS): $(WORKDIR)/work-obj93.cf $(SRCS) 51 | $(GHDL) -m $(GHDLFLAGS) $@ 52 | 53 | clean: 54 | $(GHDL) --clean 55 | rm -rf *.o *_tb *.vcd *.ghw $(WORKDIR)/*.o $(WORKDIR)/*.cf $(WORKDIR)/*_tb $(WORKDIR)/*.vcd $(WORKDIR)/*.ghw 56 | 57 | $(WORKDIR)/work-obj93.cf: $(SRCS) 58 | $(GHDL) -i $(GHDLFLAGS) $(SRCS) 59 | 60 | -------------------------------------------------------------------------------- /run_program.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #################################################################################################### 4 | # Copyright (c) 2019 Marcus Geelnard 5 | # 6 | # This software is provided 'as-is', without any express or implied warranty. In no event will the 7 | # authors be held liable for any damages arising from the use of this software. 8 | # 9 | # Permission is granted to anyone to use this software for any purpose, including commercial 10 | # applications, and to alter it and redistribute it freely, subject to the following restrictions: 11 | # 12 | # 1. The origin of this software must not be misrepresented; you must not claim that you wrote 13 | # the original software. If you use this software in a product, an acknowledgment in the 14 | # product documentation would be appreciated but is not required. 15 | # 16 | # 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 17 | # being the original software. 18 | # 19 | # 3. This notice may not be removed or altered from any source distribution. 20 | #################################################################################################### 21 | 22 | WORKDIR=out 23 | GHDL=ghdl 24 | GHDLFLAGS="--std=08 --work=work --workdir=${WORKDIR}" 25 | 26 | for i in {0..5}; do 27 | if [ "$1" = "--vcd" ]; then 28 | VCD=yes 29 | shift 30 | fi 31 | if [ "$1" = "--wave" ]; then 32 | WAVE=yes 33 | shift 34 | fi 35 | if [ "$1" = "--assert" ]; then 36 | GHDLRUNFLAGS="${GHDLRUNFLAGS} --assert-level=warning --backtrace-severity=warning" 37 | shift 38 | fi 39 | done 40 | 41 | # Copy the compiled program so that the VHDL test bench can find it. 42 | cp "$1" out/core_tb_prg.bin 43 | 44 | # Run the core_tb test bench. 45 | if [ "x${VCD}" = "xyes" ]; then 46 | ${GHDL} -r ${GHDLFLAGS} core_tb "--vcd=${WORKDIR}/core_tb.vcd" ${GHDLRUNFLAGS} 47 | elif [ "x${WAVE}" = "xyes" ]; then 48 | ${GHDL} -r ${GHDLFLAGS} core_tb "--wave=${WORKDIR}/core_tb.ghw" ${GHDLRUNFLAGS} 49 | else 50 | ${GHDL} -r ${GHDLFLAGS} core_tb ${GHDLRUNFLAGS} 51 | fi 52 | -------------------------------------------------------------------------------- /rtl/common/skid_buffer_bit.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2021 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | ---------------------------------------------------------------------------------------------------- 21 | -- This is a single-bit signal implementation of the skid_buffer. 22 | ---------------------------------------------------------------------------------------------------- 23 | 24 | library ieee; 25 | use ieee.std_logic_1164.all; 26 | 27 | entity skid_buffer_bit is 28 | port( 29 | i_clk : in std_logic; 30 | i_rst : in std_logic; 31 | i_stall : in std_logic; 32 | 33 | i_d : in std_logic; 34 | o_q : out std_logic 35 | ); 36 | end skid_buffer_bit; 37 | 38 | architecture rtl of skid_buffer_bit is 39 | signal s_d_latched : std_logic; 40 | begin 41 | -- Latch D during stall. 42 | process(i_clk, i_rst) 43 | begin 44 | if i_rst = '1' then 45 | s_d_latched <= '0'; 46 | elsif rising_edge(i_clk) then 47 | if i_stall = '1' then 48 | if i_d = '1' then 49 | s_d_latched <= '1'; 50 | end if; 51 | else 52 | s_d_latched <= '0'; 53 | end if; 54 | end if; 55 | end process; 56 | 57 | -- Select output signal. 58 | o_q <= i_d or s_d_latched; 59 | end rtl; 60 | -------------------------------------------------------------------------------- /rtl/pipeline/pc_plus_4.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2018 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | ---------------------------------------------------------------------------------------------------- 21 | -- Increment a PC by 4. 22 | -- 23 | -- This is implemented as a 30-bit adder, and the two least significant bits are set to zero. 24 | ---------------------------------------------------------------------------------------------------- 25 | 26 | library ieee; 27 | use ieee.std_logic_1164.all; 28 | use ieee.numeric_std.all; 29 | use work.config.all; 30 | 31 | entity pc_plus_4 is 32 | port( 33 | i_pc : in std_logic_vector(C_WORD_SIZE-1 downto 0); 34 | o_result : out std_logic_vector(C_WORD_SIZE-1 downto 0) 35 | ); 36 | end pc_plus_4; 37 | 38 | architecture rtl of pc_plus_4 is 39 | signal s_pc : unsigned(C_WORD_SIZE-3 downto 0); 40 | signal s_one : unsigned(0 downto 0); 41 | signal s_result : unsigned(C_WORD_SIZE-3 downto 0); 42 | begin 43 | -- Convert the signals to unsigned and add. 44 | s_pc <= resize(unsigned(i_pc(C_WORD_SIZE-1 downto 2)), C_WORD_SIZE-2); 45 | s_one(0) <= '1'; 46 | s_result <= s_pc + s_one; 47 | 48 | -- Convert the result back to std_logic_vector, and append two zeros. 49 | o_result(C_WORD_SIZE-1 downto 2) <= std_logic_vector(s_result); 50 | o_result(1 downto 0) <= "00"; 51 | end rtl; 52 | 53 | -------------------------------------------------------------------------------- /rtl/common/comparator.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2018 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | library ieee; 21 | use ieee.std_logic_1164.all; 22 | 23 | entity comparator is 24 | generic(WIDTH : positive := 32); 25 | port( 26 | i_src : in std_logic_vector(WIDTH-1 downto 0); 27 | o_z : out std_logic; 28 | o_nz : out std_logic; 29 | o_s : out std_logic; 30 | o_ns : out std_logic; 31 | o_lt : out std_logic; 32 | o_ge : out std_logic; 33 | o_le : out std_logic; 34 | o_gt : out std_logic 35 | ); 36 | end comparator; 37 | 38 | architecture rtl of comparator is 39 | constant ALL_ZEROS : std_logic_vector(WIDTH-1 downto 0) := (others => '0'); 40 | constant ALL_ONES : std_logic_vector(WIDTH-1 downto 0) := (others => '1'); 41 | signal s_z : std_logic; 42 | signal s_s : std_logic; 43 | signal s_lt : std_logic; 44 | signal s_ge : std_logic; 45 | begin 46 | -- Evaluate the sign and zero/one:ness. 47 | s_z <= '1' when i_src = ALL_ZEROS else '0'; 48 | s_s <= '1' when i_src = ALL_ONES else '0'; 49 | s_lt <= i_src(WIDTH-1); 50 | s_ge <= not i_src(WIDTH-1); 51 | 52 | -- Generate output signals. 53 | o_z <= s_z; 54 | o_nz <= not s_z; 55 | o_s <= s_s; 56 | o_ns <= not s_s; 57 | o_lt <= s_lt; 58 | o_ge <= s_ge; 59 | o_le <= s_z or s_lt; 60 | o_gt <= s_ge and not s_z; 61 | end rtl; 62 | 63 | -------------------------------------------------------------------------------- /rtl/alu/sel32.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2018 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | library ieee; 21 | use ieee.std_logic_1164.all; 22 | use work.types.all; 23 | 24 | entity sel32 is 25 | port( 26 | i_src_a : in std_logic_vector(31 downto 0); 27 | i_src_b : in std_logic_vector(31 downto 0); 28 | i_src_c : in std_logic_vector(31 downto 0); 29 | i_packed_mode : in T_PACKED_MODE; 30 | o_result : out std_logic_vector(31 downto 0) 31 | ); 32 | end sel32; 33 | 34 | architecture rtl of sel32 is 35 | signal s_sel_0 : std_logic_vector(31 downto 0); 36 | signal s_sel_1 : std_logic_vector(31 downto 0); 37 | signal s_sel_2 : std_logic_vector(31 downto 0); 38 | signal s_sel_3 : std_logic_vector(31 downto 0); 39 | begin 40 | -- There are four different flavors of the SEL instruction, each with different 41 | -- permutations of the operands. 42 | s_sel_0 <= (i_src_a and i_src_c) or (i_src_b and not i_src_c); 43 | s_sel_1 <= (i_src_a and not i_src_c) or (i_src_b and i_src_c); 44 | s_sel_2 <= (i_src_c and i_src_a) or (i_src_b and not i_src_a); 45 | s_sel_3 <= (i_src_c and not i_src_a) or (i_src_b and i_src_a); 46 | 47 | SelMux: with i_packed_mode select 48 | o_result <= 49 | s_sel_0 when "00", 50 | s_sel_1 when "01", 51 | s_sel_2 when "10", 52 | s_sel_3 when "11", 53 | (others => '-') when others; 54 | end rtl; 55 | -------------------------------------------------------------------------------- /benchmark/mul32_bench.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2018 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | library ieee; 21 | use ieee.std_logic_1164.all; 22 | use work.types.all; 23 | 24 | entity mul32_bench is 25 | port( 26 | i_clk : in std_logic; 27 | i_rst : in std_logic; 28 | i_src_a : in std_logic_vector(31 downto 0); 29 | i_src_b : in std_logic_vector(31 downto 0); 30 | i_signed_op : in std_logic; 31 | o_result : out std_logic_vector(63 downto 0) 32 | ); 33 | end mul32_bench; 34 | 35 | architecture rtl of mul32_bench is 36 | signal s_src_a : std_logic_vector(31 downto 0); 37 | signal s_src_b : std_logic_vector(31 downto 0); 38 | signal s_signed_op : std_logic; 39 | signal s_next_result : std_logic_vector(63 downto 0); 40 | begin 41 | dut_0: entity work.mul32 42 | port map ( 43 | i_src_a => s_src_a, 44 | i_src_b => s_src_b, 45 | i_signed_op => s_signed_op, 46 | o_result => s_next_result 47 | ); 48 | 49 | process(i_clk, i_rst) 50 | begin 51 | if i_rst = '1' then 52 | s_src_a <= (others => '0'); 53 | s_src_b <= (others => '0'); 54 | s_signed_op <= '0'; 55 | o_result <= (others => '0'); 56 | elsif rising_edge(i_clk) then 57 | s_src_a <= i_src_a; 58 | s_src_b <= i_src_b; 59 | s_signed_op <= i_signed_op; 60 | o_result <= s_next_result; 61 | end if; 62 | end process; 63 | end rtl; 64 | -------------------------------------------------------------------------------- /rtl/alu/rev32.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2018 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | library ieee; 21 | use ieee.std_logic_1164.all; 22 | use ieee.numeric_std.all; 23 | use work.types.all; 24 | use work.config.all; 25 | 26 | entity rev32 is 27 | generic( 28 | CONFIG : T_CORE_CONFIG 29 | ); 30 | port( 31 | i_src : in std_logic_vector(31 downto 0); 32 | i_packed_mode : in T_PACKED_MODE; 33 | o_result : out std_logic_vector(31 downto 0) 34 | ); 35 | end rev32; 36 | 37 | architecture rtl of rev32 is 38 | begin 39 | PACKED_GEN: if CONFIG.HAS_PO generate 40 | process(i_src, i_packed_mode) 41 | variable v_lo : integer; 42 | variable v_hi : integer; 43 | begin 44 | if i_packed_mode = C_PACKED_BYTE then 45 | for k in 0 to 3 loop 46 | v_lo := k * 8; 47 | v_hi := v_lo + 7; 48 | for j in 0 to 7 loop 49 | o_result(v_lo + j) <= i_src(v_hi - j); 50 | end loop; 51 | end loop; 52 | elsif i_packed_mode = C_PACKED_HALF_WORD then 53 | for k in 0 to 1 loop 54 | v_lo := k * 16; 55 | v_hi := v_lo + 15; 56 | for j in 0 to 15 loop 57 | o_result(v_lo + j) <= i_src(v_hi - j); 58 | end loop; 59 | end loop; 60 | else 61 | -- C_PACKED_NONE 62 | for j in 0 to 31 loop 63 | o_result(j) <= i_src(31 - j); 64 | end loop; 65 | end if; 66 | end process; 67 | else generate 68 | -- In unpacked mode we only have to consider the 32-bit result. 69 | Rev32Gen: for j in 0 to 31 generate 70 | o_result(j) <= i_src(31 - j); 71 | end generate; 72 | end generate; 73 | end rtl; 74 | -------------------------------------------------------------------------------- /rtl/fpu/float_compose.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2018 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | library ieee; 21 | use ieee.std_logic_1164.all; 22 | use work.types.all; 23 | 24 | ---------------------------------------------------------------------------------------------------- 25 | -- This entity composes floating point number components into an IEEE 754 binary floating point 26 | -- number. 27 | -- 28 | -- IEEE 754 incompatibilities/simplifications: 29 | -- - Denormals are not supported. 30 | ---------------------------------------------------------------------------------------------------- 31 | 32 | entity float_compose is 33 | generic( 34 | WIDTH : positive := 32; 35 | EXP_BITS : positive := 8; 36 | FRACT_BITS : positive := 23 37 | ); 38 | port( 39 | i_props : in T_FLOAT_PROPS; 40 | i_exponent : in std_logic_vector(EXP_BITS-1 downto 0); 41 | i_significand : in std_logic_vector(FRACT_BITS downto 0); 42 | 43 | o_result : out std_logic_vector(WIDTH-1 downto 0) 44 | ); 45 | end float_compose; 46 | 47 | architecture rtl of float_compose is 48 | begin 49 | -- We currently always flush denormals to zero. 50 | o_result(WIDTH-1) <= i_props.is_neg; 51 | o_result(WIDTH-2 downto FRACT_BITS) <= 52 | (WIDTH-2 downto FRACT_BITS => '1') when (i_props.is_nan or i_props.is_inf) = '1' else 53 | (WIDTH-2 downto FRACT_BITS => '0') when i_props.is_zero = '1' else 54 | i_exponent; 55 | o_result(FRACT_BITS-1 downto 0) <= 56 | (FRACT_BITS-1 downto 0 => '1') when i_props.is_nan = '1' else 57 | (FRACT_BITS-1 downto 0 => '0') when (i_props.is_inf or i_props.is_zero) = '1' else 58 | i_significand(FRACT_BITS-1 downto 0); 59 | end rtl; 60 | -------------------------------------------------------------------------------- /rtl/alu/xchgsr.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2021 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | library ieee; 21 | use ieee.std_logic_1164.all; 22 | use work.types.all; 23 | use work.config.all; 24 | 25 | entity xchgsr is 26 | generic( 27 | CONFIG : T_CORE_CONFIG 28 | ); 29 | port( 30 | i_reg_read : in std_logic_vector(C_WORD_SIZE-1 downto 0); 31 | i_reg_write : in std_logic_vector(C_WORD_SIZE-1 downto 0); 32 | i_we : in std_logic; 33 | o_result : out std_logic_vector(C_WORD_SIZE-1 downto 0) 34 | ); 35 | end xchgsr; 36 | 37 | architecture rtl of xchgsr is 38 | begin 39 | -- Read system register. 40 | process(i_reg_read) 41 | begin 42 | if i_reg_read = x"00000000" then 43 | -- CPU_FEATURES_0 (CPU feature flags register 0): 44 | -- 0: VM (Vector operatoin module) 45 | -- 1: PM (Packed operation module) 46 | -- 2: FM (Floating-point module) 47 | -- 3: SM (Saturating and halving arithmetic module) 48 | o_result(0) <= to_std_logic(CONFIG.HAS_VEC); 49 | o_result(1) <= to_std_logic(CONFIG.HAS_PO); 50 | o_result(2) <= to_std_logic(CONFIG.HAS_FP); 51 | o_result(3) <= to_std_logic(CONFIG.HAS_SA); 52 | o_result(C_WORD_SIZE-1 downto 4) <= (others => '0'); 53 | elsif i_reg_read = x"00000010" then 54 | -- MAX_VL (Maximum vector length register). 55 | o_result <= to_word(C_VEC_REG_ELEMENTS); 56 | elsif i_reg_read = x"00000011" then 57 | -- LOG2_MAX_VL (Maximum vector length register). 58 | o_result <= to_word(C_LOG2_VEC_REG_ELEMENTS); 59 | else 60 | -- All reserved registers are zero. 61 | o_result <= (others => '0'); 62 | end if; 63 | end process; 64 | 65 | -- TODO(m): Implement register write operations (we probably need clock and 66 | -- reset signals for that). 67 | end rtl; 68 | -------------------------------------------------------------------------------- /rtl/toplevel.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2019 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | ---------------------------------------------------------------------------------------------------- 21 | -- This is the top level entity, mostly intended for simple FPGA synthesis & fitting tests. The 22 | -- entity consists of a single CPU core and exposes a single 32-bit Wishbone memory interface. 23 | ---------------------------------------------------------------------------------------------------- 24 | 25 | library ieee; 26 | use ieee.std_logic_1164.all; 27 | use work.config.all; 28 | 29 | entity toplevel is 30 | port( 31 | -- Control signals. 32 | i_clk : in std_logic; 33 | i_rst : in std_logic; 34 | 35 | -- Memory interface to the outside world (Wishbone B4 pipelined master). 36 | o_wb_cyc : out std_logic; 37 | o_wb_stb : out std_logic; 38 | o_wb_adr : out std_logic_vector(C_WORD_SIZE-1 downto 2); 39 | o_wb_dat : out std_logic_vector(C_WORD_SIZE-1 downto 0); 40 | o_wb_we : out std_logic; 41 | o_wb_sel : out std_logic_vector(C_WORD_SIZE/8-1 downto 0); 42 | i_wb_dat : in std_logic_vector(C_WORD_SIZE-1 downto 0); 43 | i_wb_ack : in std_logic; 44 | i_wb_stall : in std_logic; 45 | i_wb_err : in std_logic 46 | ); 47 | end toplevel; 48 | 49 | architecture rtl of toplevel is 50 | begin 51 | core_1: entity work.core 52 | port map ( 53 | i_clk => i_clk, 54 | i_rst => i_rst, 55 | 56 | -- Data interface. 57 | o_wb_cyc => o_wb_cyc, 58 | o_wb_stb => o_wb_stb, 59 | o_wb_adr => o_wb_adr, 60 | o_wb_dat => o_wb_dat, 61 | o_wb_we => o_wb_we, 62 | o_wb_sel => o_wb_sel, 63 | i_wb_dat => i_wb_dat, 64 | i_wb_ack => i_wb_ack, 65 | i_wb_stall => i_wb_stall, 66 | i_wb_err => i_wb_err 67 | ); 68 | end rtl; 69 | -------------------------------------------------------------------------------- /rtl/agu/vector_stride_gen.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2018 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | library ieee; 21 | use ieee.std_logic_1164.all; 22 | use ieee.numeric_std.all; 23 | use work.config.all; 24 | 25 | --------------------------------------------------------------------------------------------------- 26 | -- This implements the vector memory address offset generation logic. 27 | --------------------------------------------------------------------------------------------------- 28 | 29 | entity vector_stride_gen is 30 | port ( 31 | i_clk : in std_logic; 32 | i_rst : in std_logic; 33 | i_stall : in std_logic; 34 | 35 | i_is_first_vector_op_cycle : in std_logic; 36 | i_stride : in std_logic_vector(C_WORD_SIZE-1 downto 0); 37 | 38 | o_offset : out std_logic_vector(C_WORD_SIZE-1 downto 0) 39 | ); 40 | end vector_stride_gen; 41 | 42 | architecture rtl of vector_stride_gen is 43 | signal s_stride : std_logic_vector(C_WORD_SIZE-1 downto 0); 44 | signal s_offset : std_logic_vector(C_WORD_SIZE-1 downto 0); 45 | signal s_next_offset : std_logic_vector(C_WORD_SIZE-1 downto 0); 46 | begin 47 | -- State machine. 48 | process(i_clk, i_rst) 49 | begin 50 | if i_rst = '1' then 51 | s_offset <= (others => '0'); 52 | s_stride <= (others => '0'); 53 | elsif rising_edge(i_clk) then 54 | if i_stall = '0' then 55 | if i_is_first_vector_op_cycle = '1' then 56 | s_stride <= i_stride; 57 | s_offset <= i_stride; 58 | else 59 | s_offset <= s_next_offset; 60 | end if; 61 | end if; 62 | end if; 63 | end process; 64 | 65 | -- Calculate the next offset. 66 | s_next_offset <= std_logic_vector(unsigned(s_offset) + unsigned(s_stride)); 67 | 68 | -- Outputs. 69 | o_offset <= (others => '0') when i_is_first_vector_op_cycle = '1' else s_offset; 70 | end rtl; 71 | -------------------------------------------------------------------------------- /rtl/muldiv/div_stage.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2018 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | ---------------------------------------------------------------------------------------------------- 21 | -- This is single stage of an unsigned integer divider. 22 | ---------------------------------------------------------------------------------------------------- 23 | 24 | library ieee; 25 | use ieee.std_logic_1164.all; 26 | use ieee.numeric_std.all; 27 | 28 | entity div_stage is 29 | generic( 30 | WIDTH : positive 31 | ); 32 | port( 33 | -- Inputs (async). 34 | i_n : in std_logic_vector(WIDTH-1 downto 0); 35 | i_d : in std_logic_vector(WIDTH-1 downto 0); 36 | i_q : in std_logic_vector(WIDTH-1 downto 0); 37 | i_r : in std_logic_vector(WIDTH-1 downto 0); 38 | 39 | -- Outputs (async). 40 | o_n : out std_logic_vector(WIDTH-1 downto 0); 41 | o_d : out std_logic_vector(WIDTH-1 downto 0); 42 | o_q : out std_logic_vector(WIDTH-1 downto 0); 43 | o_r : out std_logic_vector(WIDTH-1 downto 0) 44 | ); 45 | end div_stage; 46 | 47 | architecture rtl of div_stage is 48 | signal s_prim : std_logic_vector(WIDTH-1 downto 0); 49 | signal s_prim_minus_d : std_logic_vector(WIDTH downto 0); 50 | signal s_no_underflow : std_logic; 51 | begin 52 | -- Calculate R' = (R << 1) | N(WIDTH-1) 53 | s_prim <= i_r(WIDTH-2 downto 0) & i_n(WIDTH-1); 54 | 55 | -- Calculate R' - D. 56 | s_prim_minus_d <= std_logic_vector(resize(unsigned(s_prim), WIDTH+1) - resize(unsigned(i_d), WIDTH+1)); 57 | s_no_underflow <= not s_prim_minus_d(WIDTH); 58 | 59 | -- N = N << 1 60 | o_n <= i_n(WIDTH-2 downto 0) & "0"; 61 | 62 | -- D = D 63 | o_d <= i_d; 64 | 65 | -- Q = (Q << 1) | s_no_underflow 66 | o_q <= i_q(WIDTH-2 downto 0) & s_no_underflow; 67 | 68 | -- R = R' > D ? (R' - D) : R' 69 | o_r <= s_prim_minus_d(WIDTH-1 downto 0) when s_no_underflow = '1' else s_prim; 70 | end rtl; 71 | -------------------------------------------------------------------------------- /rtl/pipeline/pc_plus_offset.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2018 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | ---------------------------------------------------------------------------------------------------- 21 | -- Increment a PC by a 21-bit signed word-offset. 22 | -- 23 | -- This is implemented as a (21+9)-bit adder, and the two least significant bits are set to zero. 24 | ---------------------------------------------------------------------------------------------------- 25 | 26 | library ieee; 27 | use ieee.std_logic_1164.all; 28 | use ieee.numeric_std.all; 29 | use work.config.all; 30 | 31 | entity pc_plus_offset is 32 | generic( 33 | OFFSET_SIZE : integer := 21 -- Number of bits for the offset signal. 34 | ); 35 | port( 36 | i_pc : in std_logic_vector(C_WORD_SIZE-1 downto 0); 37 | i_offset : in std_logic_vector(OFFSET_SIZE-1 downto 0); 38 | o_result : out std_logic_vector(C_WORD_SIZE-1 downto 0) 39 | ); 40 | end pc_plus_offset; 41 | 42 | architecture rtl of pc_plus_offset is 43 | signal s_offset_sign_extended : std_logic_vector(C_WORD_SIZE-3 downto 0); 44 | signal s_pc : unsigned(C_WORD_SIZE-3 downto 0); 45 | signal s_offset : unsigned(C_WORD_SIZE-3 downto 0); 46 | signal s_result : unsigned(C_WORD_SIZE-3 downto 0); 47 | begin 48 | -- Sign-extend the offset. 49 | s_offset_sign_extended(C_WORD_SIZE-3 downto OFFSET_SIZE-1) <= (others => i_offset(OFFSET_SIZE-1)); 50 | s_offset_sign_extended(OFFSET_SIZE-2 downto 0) <= i_offset(OFFSET_SIZE-2 downto 0); 51 | 52 | -- Convert the signals to unsigned and add. 53 | s_pc <= resize(unsigned(i_pc(C_WORD_SIZE-1 downto 2)), C_WORD_SIZE-2); 54 | s_offset <= resize(unsigned(s_offset_sign_extended), C_WORD_SIZE-2); 55 | s_result <= s_pc + s_offset; 56 | 57 | -- Convert the result back to std_logic_vector, and append two zeros. 58 | o_result(C_WORD_SIZE-1 downto 2) <= std_logic_vector(s_result); 59 | o_result(1 downto 0) <= "00"; 60 | end rtl; 61 | 62 | -------------------------------------------------------------------------------- /rtl/common/skid_buffer.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2021 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | ---------------------------------------------------------------------------------------------------- 21 | -- This skid buffer implementation has the following behavior: 22 | -- 23 | -- * When i_stall is asserted, the input signal is recorded if i_valid is asserted. 24 | -- * The output signal is either the pass-through of the input signal, or a reproduction of the 25 | -- last recorded input signal (during the first cycle that i_stall is de-asserted, unless i_valid 26 | -- is asserted in which case the input signal is passed through). 27 | ---------------------------------------------------------------------------------------------------- 28 | 29 | library ieee; 30 | use ieee.std_logic_1164.all; 31 | 32 | entity skid_buffer is 33 | generic( 34 | WIDTH : integer := 1 35 | ); 36 | port( 37 | i_clk : in std_logic; 38 | i_rst : in std_logic; 39 | i_stall : in std_logic; 40 | 41 | i_d : in std_logic_vector(WIDTH-1 downto 0); 42 | i_valid : in std_logic; 43 | 44 | o_q : out std_logic_vector(WIDTH-1 downto 0); 45 | o_valid : out std_logic 46 | ); 47 | end skid_buffer; 48 | 49 | architecture rtl of skid_buffer is 50 | signal s_d_latched : std_logic_vector(WIDTH-1 downto 0); 51 | signal s_valid_latched : std_logic; 52 | begin 53 | -- Latch D during stall. 54 | process(i_clk, i_rst) 55 | begin 56 | if i_rst = '1' then 57 | s_d_latched <= (others => '0'); 58 | s_valid_latched <= '0'; 59 | elsif rising_edge(i_clk) then 60 | if i_stall = '1' then 61 | if i_valid = '1' then 62 | s_d_latched <= i_d; 63 | s_valid_latched <= '1'; 64 | end if; 65 | else 66 | s_valid_latched <= '0'; 67 | end if; 68 | end if; 69 | end process; 70 | 71 | -- Select output signal. 72 | o_q <= i_d when i_valid = '1' else s_d_latched; 73 | o_valid <= i_valid or s_valid_latched; 74 | end rtl; 75 | -------------------------------------------------------------------------------- /test/Makefile: -------------------------------------------------------------------------------- 1 | #################################################################################################### 2 | # Copyright (c) 2019 Marcus Geelnard 3 | # 4 | # This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | # authors be held liable for any damages arising from the use of this software. 6 | # 7 | # Permission is granted to anyone to use this software for any purpose, including commercial 8 | # applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | # 10 | # 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | # the original software. If you use this software in a product, an acknowledgment in the 12 | # product documentation would be appreciated but is not required. 13 | # 14 | # 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | # being the original software. 16 | # 17 | # 3. This notice may not be removed or altered from any source distribution. 18 | #################################################################################################### 19 | 20 | TEST_PATH = test 21 | 22 | CP = cp 23 | 24 | SRCS += \ 25 | $(TEST_PATH)/alu_tb.vhd \ 26 | $(TEST_PATH)/clz32_tb.vhd \ 27 | $(TEST_PATH)/comparator_tb.vhd \ 28 | $(TEST_PATH)/core_tb.vhd \ 29 | $(TEST_PATH)/div_impl_tb.vhd \ 30 | $(TEST_PATH)/div_pipelined_tb.vhd \ 31 | $(TEST_PATH)/fadd_tb.vhd \ 32 | $(TEST_PATH)/fetch_tb.vhd \ 33 | $(TEST_PATH)/float_compare_tb.vhd \ 34 | $(TEST_PATH)/float_decompose_tb.vhd \ 35 | $(TEST_PATH)/fmul_tb.vhd \ 36 | $(TEST_PATH)/fpu_tb.vhd \ 37 | $(TEST_PATH)/ftoi_tb.vhd \ 38 | $(TEST_PATH)/funp_tb.vhd \ 39 | $(TEST_PATH)/itof_clz_and_left_shift_tb.vhd \ 40 | $(TEST_PATH)/itof_tb.vhd \ 41 | $(TEST_PATH)/mem_arbiter_tb.vhd \ 42 | $(TEST_PATH)/memory_tb.vhd \ 43 | $(TEST_PATH)/mul_tb.vhd \ 44 | $(TEST_PATH)/popcnt32_tb.vhd \ 45 | $(TEST_PATH)/reg_tb.vhd \ 46 | $(TEST_PATH)/sau_tb.vhd \ 47 | $(TEST_PATH)/shift32_tb.vhd \ 48 | $(TEST_PATH)/shuf32_tb.vhd \ 49 | $(TEST_PATH)/skid_buffer_tb.vhd \ 50 | $(TEST_PATH)/vector_control_tb.vhd \ 51 | $(TEST_PATH)/vector_stride_gen_tb.vhd 52 | 53 | TESTS += \ 54 | alu_tb \ 55 | clz32_tb \ 56 | comparator_tb \ 57 | core_tb \ 58 | div_impl_tb \ 59 | div_pipelined_tb \ 60 | fadd_tb \ 61 | fetch_tb \ 62 | float_compare_tb \ 63 | float_decompose_tb \ 64 | fmul_tb \ 65 | fpu_tb \ 66 | ftoi_tb \ 67 | funp_tb \ 68 | itof_clz_and_left_shift_tb \ 69 | itof_tb \ 70 | mem_arbiter_tb \ 71 | memory_tb \ 72 | mul_tb \ 73 | popcnt32_tb \ 74 | reg_tb \ 75 | sau_tb \ 76 | shift32_tb \ 77 | shuf32_tb \ 78 | skid_buffer_tb \ 79 | vector_control_tb \ 80 | vector_stride_gen_tb 81 | 82 | EXTRA += \ 83 | $(WORKDIR)/fpu_test_gen 84 | 85 | # Data generator for FPU test data. 86 | $(WORKDIR)/fpu_test_gen: $(FPU_PATH)/fpu_test_gen.cpp 87 | g++ $(FPU_PATH)/fpu_test_gen.cpp -o $(WORKDIR)/fpu_test_gen 88 | 89 | -------------------------------------------------------------------------------- /rtl/agu/agu.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2018 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | library ieee; 21 | use ieee.std_logic_1164.all; 22 | use ieee.numeric_std.all; 23 | use work.config.all; 24 | 25 | entity agu is 26 | port( 27 | i_clk : in std_logic; 28 | i_rst : in std_logic; 29 | i_stall : in std_logic; 30 | 31 | i_is_first_vector_op_cycle : in std_logic; 32 | i_address_offset_is_stride : in std_logic; 33 | i_base : in std_logic_vector(C_WORD_SIZE-1 downto 0); 34 | i_offset : in std_logic_vector(C_WORD_SIZE-1 downto 0); 35 | i_offset_shift : in std_logic_vector(1 downto 0); 36 | o_result : out std_logic_vector(C_WORD_SIZE-1 downto 0) 37 | ); 38 | end agu; 39 | 40 | architecture rtl of agu is 41 | signal s_scaled_offset : std_logic_vector(C_WORD_SIZE-1 downto 0); 42 | signal s_stride_offset : std_logic_vector(C_WORD_SIZE-1 downto 0); 43 | signal s_offset : std_logic_vector(C_WORD_SIZE-1 downto 0); 44 | begin 45 | -- Scale the index offset. 46 | s_scaled_offset <= i_offset(C_WORD_SIZE-2 downto 0) & "0" when i_offset_shift = "01" else 47 | i_offset(C_WORD_SIZE-3 downto 0) & "00" when i_offset_shift = "10" else 48 | i_offset(C_WORD_SIZE-4 downto 0) & "000" when i_offset_shift = "11" else 49 | i_offset; 50 | 51 | -- Stride generation (for certain vector memory addressing modes). 52 | vector_stride_gen_1: entity work.vector_stride_gen 53 | port map ( 54 | i_clk => i_clk, 55 | i_rst => i_rst, 56 | i_stall => i_stall, 57 | i_is_first_vector_op_cycle => i_is_first_vector_op_cycle, 58 | i_stride => s_scaled_offset, 59 | o_offset => s_stride_offset 60 | ); 61 | 62 | -- Select which offset to use: constant offset or stride offset. 63 | s_offset <= s_stride_offset when i_address_offset_is_stride = '1' else s_scaled_offset; 64 | 65 | -- The resulting address is the base address plus the offset. 66 | o_result <= std_logic_vector(unsigned(i_base) + unsigned(s_offset)); 67 | end rtl; 68 | 69 | -------------------------------------------------------------------------------- /test/programs/branches.s: -------------------------------------------------------------------------------- 1 | ; -*- mode: mr32asm; tab-width: 8; indent-tabs-mode: t; -*- 2 | ;-------------------------------------------------------------------------------------------------- 3 | ; Copyright (c) 2021 Marcus Geelnard 4 | ; 5 | ; This software is provided 'as-is', without any express or implied warranty. In no event will the 6 | ; authors be held liable for any damages arising from the use of this software. 7 | ; 8 | ; Permission is granted to anyone to use this software for any purpose, including commercial 9 | ; applications, and to alter it and redistribute it freely, subject to the following restrictions: 10 | ; 11 | ; 1. The origin of this software must not be misrepresented; you must not claim that you wrote 12 | ; the original software. If you use this software in a product, an acknowledgment in the 13 | ; product documentation would be appreciated but is not required. 14 | ; 15 | ; 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 16 | ; being the original software. 17 | ; 18 | ; 3. This notice may not be removed or altered from any source distribution. 19 | ;-------------------------------------------------------------------------------------------------- 20 | 21 | ;-------------------------------------------------------------------------------------------------- 22 | ; This program exercises various forms of branches. 23 | ;-------------------------------------------------------------------------------------------------- 24 | 25 | .section .text.start, "ax" 26 | .globl _start 27 | _start: 28 | ldi sp, #0x10000 29 | bl loop_x2 30 | bl calls1 31 | bl calls2 32 | bl recursion 33 | b _start 34 | 35 | loop_x2: 36 | ldi r1, #3 ; Outer loop count 37 | 1: ldi r2, #5 ; Inner loop count 38 | 2: slt r3, r2, #2 39 | bs r3, 3f ; ~50% taken forward branch 40 | stw r2, [sp, #-4] ; Data port access (may result in WB stall) 41 | 3: add r2, r2, #-1 42 | bnz r2, 2b ; Inner loop backward branch (likely taken) 43 | add r1, r1, #-1 44 | bnz r1, 1b ; Outer loop backward branch (likely taken) 45 | ret ; Return branch (100% taken) 46 | 47 | calls1: 48 | mov r20, lr 49 | ldi r1, #3 50 | 1: bl subroutine1 ; 100% taken subroutine call. 51 | bl subroutine2 ; 100% taken subroutine call. 52 | add r1, r1, #-1 53 | bnz r1, 1b 54 | mov lr, r20 55 | ret 56 | 57 | calls2: 58 | mov r20, lr 59 | ldi r1, #3 60 | 1: bl subroutine1 ; 100% taken subroutine call. 61 | bl subroutine2 ; 100% taken subroutine call. 62 | bl subroutine1 ; Call again to mess up return BTB entry. 63 | bl subroutine2 ; Call again to mess up return BTB entry. 64 | add r1, r1, #-1 65 | bnz r1, 1b 66 | mov lr, r20 67 | b subroutine2 ; Tail call (100% taken) 68 | 69 | subroutine1: 70 | ; Return directly after call instruction. 71 | ret ; Return branch (100% taken) 72 | 73 | subroutine2: 74 | nop 75 | nop 76 | nop 77 | nop 78 | nop 79 | ret ; Return branch (100% taken) 80 | 81 | recursion: 82 | ldi r1, #40 83 | 1: bz r1, 2f 84 | add sp, sp, #-4 85 | stw lr, [sp, #0] 86 | add r1, r1, #-1 87 | bl recursion_sub1 88 | bl 1b 89 | ldw lr, [sp, #0] 90 | add sp, sp, #4 91 | 2: ret 92 | 93 | recursion_sub1: 94 | ret 95 | 96 | -------------------------------------------------------------------------------- /rtl/fpu/itof_clz_and_left_shift.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2019 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | ---------------------------------------------------------------------------------------------------- 21 | -- Left-shift an integer until there are no more leasing zeros, and count the number of leading 22 | -- zeros (i.e. the shift amount) at the same time. 23 | ---------------------------------------------------------------------------------------------------- 24 | 25 | library ieee; 26 | use ieee.std_logic_1164.all; 27 | use ieee.numeric_std.all; 28 | use work.types.all; 29 | 30 | entity itof_clz_and_left_shift is 31 | generic( 32 | WIDTH : positive := 32; 33 | LOG2_WIDTH : positive := 5 34 | ); 35 | port( 36 | -- Inputs (async). 37 | i_src : in std_logic_vector(WIDTH-1 downto 0); 38 | 39 | -- Outputs (async). 40 | o_result : out std_logic_vector(WIDTH-1 downto 0); 41 | o_left_shift : out std_logic_vector(LOG2_WIDTH-1 downto 0) 42 | ); 43 | end itof_clz_and_left_shift; 44 | 45 | architecture rtl of itof_clz_and_left_shift is 46 | begin 47 | process(i_src) 48 | variable v_shifted_src : unsigned(WIDTH-1 downto 0); 49 | variable v_lz_chunk_size : integer range 0 to WIDTH/2; 50 | variable v_lz_bit_no : integer range -1 to LOG2_WIDTH-1; 51 | variable v_left_shift : unsigned(LOG2_WIDTH-1 downto 0); 52 | begin 53 | v_shifted_src := unsigned(i_src); 54 | v_lz_bit_no := LOG2_WIDTH-1; 55 | v_lz_chunk_size := WIDTH/2; 56 | while v_lz_chunk_size > 0 loop 57 | if v_shifted_src(WIDTH-1 downto WIDTH-v_lz_chunk_size) = to_unsigned(0, v_lz_chunk_size) then 58 | v_left_shift(v_lz_bit_no) := '1'; 59 | v_shifted_src := v_shifted_src(WIDTH-1-v_lz_chunk_size downto 0) & to_unsigned(0, v_lz_chunk_size); 60 | else 61 | v_left_shift(v_lz_bit_no) := '0'; 62 | end if; 63 | v_lz_bit_no := v_lz_bit_no - 1; 64 | v_lz_chunk_size := v_lz_chunk_size / 2; 65 | end loop; 66 | 67 | -- Output signals. 68 | o_result <= std_logic_vector(v_shifted_src); 69 | o_left_shift <= std_logic_vector(v_left_shift); 70 | end process; 71 | end rtl; 72 | 73 | -------------------------------------------------------------------------------- /test/shuf32_tb.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2018 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | library ieee; 21 | use ieee.std_logic_1164.all; 22 | use work.types.all; 23 | use work.config.all; 24 | 25 | -- A testbench has no ports. 26 | entity shuf32_tb is 27 | end shuf32_tb; 28 | 29 | architecture behav of shuf32_tb is 30 | signal s_src_a : std_logic_vector(C_WORD_SIZE-1 downto 0); 31 | signal s_src_b : std_logic_vector(C_WORD_SIZE-1 downto 0); 32 | signal s_result : std_logic_vector(C_WORD_SIZE-1 downto 0); 33 | begin 34 | -- Component instantiation. 35 | shuf32_0: entity work.shuf32 36 | port map ( 37 | i_src_a => s_src_a, 38 | i_src_b => s_src_b, 39 | o_result => s_result 40 | ); 41 | 42 | process 43 | -- The patterns to apply. 44 | type pattern_type is record 45 | -- Inputs 46 | src_a : std_logic_vector(C_WORD_SIZE-1 downto 0); 47 | src_b : std_logic_vector(C_WORD_SIZE-1 downto 0); 48 | 49 | -- Expected outputs 50 | result : std_logic_vector(C_WORD_SIZE-1 downto 0); 51 | end record; 52 | type pattern_array is array (natural range <>) of pattern_type; 53 | constant patterns : pattern_array := ( 54 | (X"860F3355", 55 | 32B"0000001010011", 56 | X"55330F86"), 57 | (X"860F3355", 58 | 32B"0001001000000", 59 | X"33335555"), 60 | (X"860F3355", 61 | 32B"0100101110111", 62 | X"00000000"), 63 | (X"860F3355", 64 | 32B"1100101110111", 65 | X"000000FF"), 66 | (X"860F3355", 67 | 32B"1111011110010", 68 | X"FF86000F") 69 | ); 70 | begin 71 | -- Test all the patterns in the pattern array. 72 | for i in patterns'range loop 73 | -- Set the inputs. 74 | s_src_a <= patterns(i).src_a; 75 | s_src_b <= patterns(i).src_b; 76 | 77 | -- Wait for the results. 78 | wait for 1 ns; 79 | 80 | -- Check the outputs. 81 | assert s_result = patterns(i).result 82 | report "Bad SHUF32 result:" & lf & 83 | " a=" & to_string(s_src_a) & lf & 84 | " b=" & to_string(s_src_b) & lf & 85 | " r=" & to_string(s_result) & lf & 86 | " (e=" & to_string(patterns(i).result) & ")" 87 | severity error; 88 | end loop; 89 | assert false report "End of test" severity note; 90 | -- Wait forever; this will finish the simulation. 91 | wait; 92 | end process; 93 | end behav; 94 | -------------------------------------------------------------------------------- /benchmark/div_bench.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2018 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | library ieee; 21 | use ieee.std_logic_1164.all; 22 | use work.types.all; 23 | 24 | entity div_bench is 25 | port( 26 | i_clk : in std_logic; 27 | i_rst : in std_logic; 28 | i_stall : in std_logic; 29 | o_stall : out std_logic; 30 | 31 | -- Inputs (async). 32 | i_enable : in std_logic; 33 | i_op : in T_DIV_OP; 34 | i_packed_mode : in T_PACKED_MODE; 35 | i_src_a : in std_logic_vector(31 downto 0); 36 | i_src_b : in std_logic_vector(31 downto 0); 37 | 38 | -- Outputs (async). 39 | o_next_result : out std_logic_vector(31 downto 0); 40 | o_next_result_ready : out std_logic 41 | ); 42 | end div_bench; 43 | 44 | architecture rtl of div_bench is 45 | signal s_stall_in : std_logic; 46 | signal s_stall_out : std_logic; 47 | signal s_enable : std_logic; 48 | signal s_op : T_DIV_OP; 49 | signal s_packed_mode : T_PACKED_MODE; 50 | signal s_src_a : std_logic_vector(31 downto 0); 51 | signal s_src_b : std_logic_vector(31 downto 0); 52 | signal s_next_result : std_logic_vector(31 downto 0); 53 | signal s_next_result_ready : std_logic; 54 | begin 55 | dut_0: entity work.div 56 | port map ( 57 | i_clk => i_clk, 58 | i_rst => i_rst, 59 | i_stall => s_stall_in, 60 | o_stall => s_stall_out, 61 | i_enable => s_enable, 62 | i_op => s_op, 63 | i_packed_mode => s_packed_mode, 64 | i_src_a => s_src_a, 65 | i_src_b => s_src_b, 66 | o_next_result => s_next_result, 67 | o_next_result_ready => s_next_result_ready 68 | ); 69 | 70 | -- Input/output registers. 71 | process(i_clk, i_rst) 72 | begin 73 | if i_rst = '1' then 74 | s_stall_in <= '0'; 75 | s_src_a <= (others => '0'); 76 | s_src_b <= (others => '0'); 77 | s_enable <= '0'; 78 | s_op <= (others => '0'); 79 | s_packed_mode <= (others => '0'); 80 | o_stall <= '0'; 81 | o_next_result <= (others => '0'); 82 | o_next_result_ready <= '0'; 83 | elsif rising_edge(i_clk) then 84 | -- Inputs. 85 | s_stall_in <= i_stall; 86 | s_src_a <= i_src_a; 87 | s_src_b <= i_src_b; 88 | s_enable <= i_enable; 89 | s_op <= i_op; 90 | s_packed_mode <= i_packed_mode; 91 | 92 | -- Outputs. 93 | o_stall <= s_stall_out; 94 | o_next_result <= s_next_result; 95 | o_next_result_ready <= s_next_result_ready; 96 | end if; 97 | end process; 98 | end rtl; 99 | -------------------------------------------------------------------------------- /test/popcnt32_tb.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2021 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | library ieee; 21 | use ieee.std_logic_1164.all; 22 | use ieee.numeric_std.all; 23 | use work.config.all; 24 | use work.types.all; 25 | 26 | entity popcnt32_tb is 27 | end popcnt32_tb; 28 | 29 | architecture behavioral of popcnt32_tb is 30 | signal s_src : std_logic_vector(31 downto 0); 31 | signal s_packed_mode : T_PACKED_MODE; 32 | signal s_result : std_logic_vector(31 downto 0); 33 | begin 34 | popcnt32_0: entity work.popcnt32 35 | generic map ( 36 | CONFIG => C_CORE_CONFIG_FULL 37 | ) 38 | port map ( 39 | i_src => s_src, 40 | i_packed_mode => s_packed_mode, 41 | o_result => s_result 42 | ); 43 | 44 | process 45 | type pattern_array is array (natural range <>) of std_logic_vector(31 downto 0); 46 | constant patterns : pattern_array := ( 47 | ("00000000000000000000000000000000"), 48 | ("00000000000000000000000000000001"), 49 | ("00000000000000000000000000000010"), 50 | ("00001000100001000000010000100101"), 51 | ("10101010101010101010101010101010"), 52 | ("11100011111100011100110111001111"), 53 | ("11111111111111111111111111111111") 54 | ); 55 | 56 | function refPopcnt32(x: std_logic_vector(31 downto 0)) return std_logic_vector is 57 | variable v_count : unsigned(31 downto 0); 58 | begin 59 | v_count := to_unsigned(0, 32); 60 | for i in 31 downto 0 loop 61 | if x(i) = '1' then 62 | v_count := v_count + 1; 63 | end if; 64 | end loop; 65 | return std_logic_vector(v_count); 66 | end function; 67 | 68 | begin 69 | -- Test some values from 0 to 2^32-1. 70 | for i in patterns'range loop 71 | for k in 0 to 10000 loop 72 | -- Set the input. 73 | s_src <= to_word(k*55) or patterns(i); 74 | s_packed_mode <= C_PACKED_NONE; -- TODO(m): Add this to the test pattern. 75 | 76 | -- Wait for the results. 77 | wait for 1 ns; 78 | 79 | -- Check the output. 80 | assert s_result = refPopcnt32(s_src) 81 | report "Bad count value:" & lf & 82 | " src=" & to_string(s_src) & lf & 83 | " cnt=" & to_string(s_result) & " (expected " & to_string(refPopcnt32(s_src)) & ")" 84 | severity error; 85 | end loop; 86 | end loop; 87 | assert false report "End of test" severity note; 88 | -- Wait forever; this will finish the simulation. 89 | wait; 90 | end process; 91 | end behavioral; 92 | 93 | -------------------------------------------------------------------------------- /rtl/fpu/float_compare.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2018 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | library ieee; 21 | use ieee.std_logic_1164.all; 22 | use ieee.numeric_std.all; 23 | use work.types.all; 24 | 25 | ---------------------------------------------------------------------------------------------------- 26 | -- Compare floating point numbers. 27 | ---------------------------------------------------------------------------------------------------- 28 | 29 | entity float_compare is 30 | generic( 31 | WIDTH : positive := 32 32 | ); 33 | port( 34 | i_src_a : in std_logic_vector(WIDTH-1 downto 0); 35 | i_src_b : in std_logic_vector(WIDTH-1 downto 0); 36 | 37 | i_props_a : T_FLOAT_PROPS; 38 | i_props_b : T_FLOAT_PROPS; 39 | 40 | o_magn_lt : out std_logic; 41 | o_eq : out std_logic; 42 | o_ne : out std_logic; 43 | o_lt : out std_logic; 44 | o_le : out std_logic 45 | ); 46 | end float_compare; 47 | 48 | architecture rtl of float_compare is 49 | signal s_magn_a : unsigned(WIDTH-2 downto 0); 50 | signal s_magn_b : unsigned(WIDTH-2 downto 0); 51 | signal s_both_zero : std_logic; 52 | signal s_any_nan : std_logic; 53 | signal s_magn_eq : std_logic; 54 | signal s_magn_lt : std_logic; 55 | 56 | signal s_eq : std_logic; 57 | signal s_lt : std_logic; 58 | begin 59 | -- Extract the raw magnitudes. 60 | s_magn_a <= unsigned(i_src_a(WIDTH-2 downto 0)); 61 | s_magn_b <= unsigned(i_src_b(WIDTH-2 downto 0)); 62 | 63 | -- According to IEEE 754, -0 == +0, which is a special case. 64 | s_both_zero <= i_props_a.is_zero and i_props_b.is_zero; 65 | 66 | -- According to IEEE 754, we need special treatment of NaN: 67 | -- - NaN != x for any x (including NaN). 68 | -- - NaN is never less than or greater than any x (including NaN). 69 | s_any_nan <= i_props_a.is_nan or i_props_b.is_nan; 70 | 71 | -- Compare exponents and magnitudes. 72 | s_magn_eq <= '1' when s_magn_a = s_magn_b else '0'; 73 | s_magn_lt <= '1' when s_magn_a < s_magn_b else '0'; 74 | 75 | -- Equal? 76 | s_eq <= (s_magn_eq and (not (i_props_a.is_neg xor i_props_b.is_neg))) or 77 | s_both_zero; 78 | 79 | -- Less than? 80 | s_lt <= '0' when s_both_zero = '1' else 81 | s_magn_lt when (i_props_a.is_neg = '0' and i_props_b.is_neg = '0') else 82 | (not (s_magn_lt or s_eq)) when (i_props_a.is_neg = '1' and i_props_b.is_neg = '1') else 83 | '1' when (i_props_a.is_neg = '1' and i_props_b.is_neg = '0') else 84 | '0'; 85 | 86 | -- Outputs. 87 | o_magn_lt <= s_magn_lt; 88 | o_eq <= s_eq and not s_any_nan; 89 | o_ne <= (not s_eq) or s_any_nan; 90 | o_lt <= s_lt and not s_any_nan; 91 | o_le <= (s_eq or s_lt) and not s_any_nan; 92 | end rtl; 93 | -------------------------------------------------------------------------------- /rtl/common/ram_dual_port.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2018 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | library ieee; 21 | use ieee.std_logic_1164.all; 22 | use ieee.numeric_std.all; 23 | 24 | ---------------------------------------------------------------------------------------------------- 25 | -- This is a configurable synchronous dual port RAM (one read port and one write port). 26 | -- 27 | -- Altera/Intel: Synthesizes to dedicated RAM blocks. 28 | -- Xilinx: Should synthesize to block RAM (untested). 29 | ---------------------------------------------------------------------------------------------------- 30 | 31 | entity ram_dual_port is 32 | generic( 33 | WIDTH : positive; 34 | ADDR_BITS : positive; 35 | PREFER_DISTRIBUTED : boolean := false -- Prefer distributed RAM (logic cells) instead of BRAM 36 | ); 37 | port( 38 | i_clk: in std_logic; 39 | i_write_data: in std_logic_vector(WIDTH-1 downto 0); 40 | i_write_addr: in std_logic_vector(ADDR_BITS-1 downto 0); 41 | i_we: in std_logic; 42 | i_read_addr: in std_logic_vector(ADDR_BITS-1 downto 0); 43 | o_read_data: out std_logic_vector(WIDTH-1 downto 0) 44 | ); 45 | end ram_dual_port; 46 | 47 | architecture rtl of ram_dual_port is 48 | function get_intel_ram_style return string is 49 | begin 50 | if PREFER_DISTRIBUTED then 51 | return "MLAB"; 52 | end if; 53 | return ""; 54 | end function; 55 | 56 | function get_xilinx_ram_style return string is 57 | begin 58 | if PREFER_DISTRIBUTED then 59 | return "distributed"; 60 | end if; 61 | return "auto"; 62 | end function; 63 | 64 | constant C_NUM_WORDS : positive := 2**ADDR_BITS; 65 | constant C_INTEL_RAM_STYLE : string := get_intel_ram_style; 66 | constant C_XILINX_RAM_STYLE : string := get_xilinx_ram_style; 67 | 68 | type T_RAM_BLOCK is array (0 to C_NUM_WORDS-1) of std_logic_vector(WIDTH-1 downto 0); 69 | signal s_ram_block : T_RAM_BLOCK; 70 | 71 | -- Intel/Altera attributes. 72 | attribute RAMSTYLE : string; 73 | attribute RAMSTYLE of s_ram_block : signal is C_INTEL_RAM_STYLE; 74 | 75 | -- Xilinx attributes. 76 | attribute RAM_STYLE : string; 77 | attribute RAM_STYLE of s_ram_block : signal is C_XILINX_RAM_STYLE; 78 | begin 79 | process(i_clk) 80 | variable v_write_addr : integer range 0 to C_NUM_WORDS-1; 81 | variable v_read_addr : integer range 0 to C_NUM_WORDS-1; 82 | begin 83 | if rising_edge(i_clk) then 84 | if i_we = '1' then 85 | v_write_addr := to_integer(unsigned(i_write_addr)); 86 | s_ram_block(v_write_addr) <= i_write_data; 87 | end if; 88 | v_read_addr := to_integer(unsigned(i_read_addr)); 89 | o_read_data <= s_ram_block(v_read_addr); 90 | end if; 91 | end process; 92 | end rtl; 93 | 94 | -------------------------------------------------------------------------------- /test/reg_tb.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2018 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | library ieee; 21 | use ieee.std_logic_1164.all; 22 | use ieee.numeric_std.all; 23 | use work.types.all; 24 | 25 | entity reg_tb is 26 | end reg_tb; 27 | 28 | architecture behavioral of reg_tb is 29 | signal s_clk : std_logic; 30 | signal s_rst : std_logic; 31 | signal s_we : std_logic; 32 | signal s_data_w : std_logic_vector(3 downto 0); 33 | signal s_data : std_logic_vector(3 downto 0); 34 | begin 35 | reg_0: entity work.reg 36 | generic map ( 37 | WIDTH => 4 38 | ) 39 | port map ( 40 | i_clk => s_clk, 41 | i_rst => s_rst, 42 | i_we => s_we, 43 | i_data_w => s_data_w, 44 | o_data => s_data 45 | ); 46 | 47 | process 48 | -- Patterns to apply. 49 | type pattern_type is record 50 | -- Inputs 51 | clk : std_logic; 52 | rst : std_logic; 53 | we : std_logic; 54 | data_w : std_logic_vector(3 downto 0); 55 | 56 | -- Expected outputs 57 | data : std_logic_vector(3 downto 0); 58 | end record; 59 | type pattern_array is array (natural range <>) of pattern_type; 60 | constant patterns : pattern_array := ( 61 | ('1', '0', '0', "1111", "0000"), 62 | ('0', '0', '1', "1111", "0000"), 63 | ('1', '0', '1', "1111", "1111"), 64 | ('0', '0', '0', "0011", "1111"), 65 | ('1', '0', '0', "0011", "1111"), 66 | ('0', '0', '1', "0011", "1111"), 67 | ('1', '0', '1', "0011", "0011"), 68 | ('0', '1', '0', "0011", "0000") 69 | ); 70 | begin 71 | -- Start by resetting the register (to have defined signals). 72 | s_rst <= '1'; 73 | s_clk <= '0'; 74 | s_we <= '0'; 75 | s_data_w <= "1010"; 76 | 77 | wait for 1 ns; 78 | s_rst <= '0'; 79 | 80 | -- Test all the patterns in the pattern array. 81 | for i in patterns'range loop 82 | -- Set the inputs. 83 | s_clk <= patterns(i).clk; 84 | s_rst <= patterns(i).rst; 85 | s_we <= patterns(i).we; 86 | s_data_w <= patterns(i).data_w; 87 | 88 | -- Wait for the results. 89 | wait for 1 ns; 90 | 91 | -- Check the outputs. 92 | assert s_data = patterns(i).data 93 | report "Bad register data:" & lf & 94 | " i = " & integer'image(i) & lf & 95 | " data = " & to_string(s_data) & lf & 96 | " (expected " & to_string(patterns(i).data) & ")" 97 | severity error; 98 | end loop; 99 | assert false report "End of test" severity note; 100 | -- Wait forever; this will finish the simulation. 101 | wait; 102 | end process; 103 | end behavioral; 104 | 105 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## This repo has moved to: https://gitlab.com/mrisc32/mrisc32-a1 2 | 3 | # MRISC32-A1 4 | 5 | This is a [VHDL](https://en.wikipedia.org/wiki/VHDL) implementation of a single issue, in-order CPU that implements the [MRISC32](https://github.com/mrisc32/mrisc32) ISA. The working name for the CPU is *MRISC32-A1*. 6 | 7 | ## Overview 8 | 9 | ![MRISC32-A1 pipleine](mrisc32-a1-pipeline.png) 10 | 11 | ## Progress 12 | 13 | The CPU is nearing completion but still under development. The following components have been implemented: 14 | 15 | * A 9-stage pipeline. 16 | - PC and branching logic. 17 | - Instruction fetch. 18 | - Decode. 19 | - Register fetch. 20 | - Execute. 21 | - Data read/write logic (scalar and vector). 22 | - Register write-back. 23 | - Operand forwarding. 24 | * The integer ALU. 25 | - Supports all packed and unpacked integer ALU operations. 26 | - All ALU operations finish in one cycle. 27 | * A pipelined (three-cycle) integer multiply unit. 28 | - Supports all packed and unpacked integer multiplication operations. 29 | * A semi-pipelined integer and floating point division unit. 30 | - The integer division pipeline is 3 stages long, while the floating point division pipeline is 4 stages long. 31 | - 32-bit division: 15/12 cycles stall (integer/float). 32 | - 2 x 16-bit division: 7/5 cycles stall (integer/float). 33 | - 4 x 8-bit division: 3/2 cycles stall (integer/float). 34 | * A pipelined (two-cycle) Saturating Arithmetic Unit (SAU). 35 | - Supports all packed and unpacked saturating and halving arithmetic instructions. 36 | * An IEEE 754 compliant(ish) FPU. 37 | - The following single-cycle FPU instructions are implemented: 38 | - FMIN, FMAX 39 | - FSEQ, FSNE, FSLT, FSLE, FSUNORD, FSORD 40 | - The following three-cycle FPU instructions are implemented: 41 | - ITOF, UTOF, FTOI, FTOU, FTOIR, FTOUR 42 | - The following four-cycle FPU instructions are implemented: 43 | - FADD, FSUB, FMUL 44 | - Both packed and unpacked FPU operations are implemented. 45 | * The scalar register file. 46 | - There are three read ports and one write port. 47 | * The vector register file. 48 | - There are two read ports and one write port. 49 | - Each vector register has 16 elements (configurable). 50 | * An address generation unit (AGU). 51 | - The AGU supports all addressing modes. 52 | * Branch prediction and correction. 53 | - A direct mapped 2-bit dynamic branch predictor (512 entries, configurable). 54 | - A return address stack predictor (16 entries, configurable). 55 | - The branch misprediction penalty is 3 cycles (a correctly predicted branch incurs no penalty). 56 | * A direct mapped instruction cache. 57 | * Two 32-bit Wishbone (B4 pipelined) interfaces to the memory. 58 | - Instruction and data requests have separate Wishbone interfaces. 59 | - One memory request can be completed every cycle per interface. 60 | 61 | **TODO**: Data cache, interrupt logic. 62 | 63 | ## Configurability 64 | 65 | The aim is for the MRISC32-A1 to implement the complete MRISC32 ISA, which means that it is a fairly large design (including an FPU, hardware multiplication and division, packed operations, etc). 66 | 67 | If the design is too large or complex for a certain target chip (FPGA), it is possible to disable many features via `T_CORE_CONFIG` (see [config.vhd](rtl/common/config.vhd)). E.g. setting `HAS_MUL` to `false` will disable support for hardware multiplication. 68 | 69 | It is also possible to change the vector register size by chaging the value of `C_LOG2_VEC_REG_ELEMENTS` (4 means 16 elements, 5 means 32 elements, 8 means 256 elements, and so on). 70 | 71 | ## Performance 72 | 73 | The MRISC32-A1 can issue **one operation per clock cycle**. 74 | 75 | When synthesized against an [Intel Cyclone V FPGA](https://www.intel.com/content/www/us/en/products/programmable/fpga/cyclone-v.html), the maximum running frequency is close to **100 MHz**. 76 | 77 | -------------------------------------------------------------------------------- /rtl/ctrl/cctrl.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2023 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | ---------------------------------------------------------------------------------------------------- 21 | -- Cache control: Implementation of the CCTRL instruction. 22 | ---------------------------------------------------------------------------------------------------- 23 | 24 | library ieee; 25 | use ieee.std_logic_1164.all; 26 | use work.types.all; 27 | use work.config.all; 28 | 29 | entity cctrl is 30 | port( 31 | -- Control signals. 32 | i_clk : in std_logic; 33 | i_rst : in std_logic; 34 | 35 | -- Inputs. 36 | i_en : in std_logic; 37 | i_op : in T_CCTRL_OP; 38 | i_src_a : in std_logic_vector(C_WORD_SIZE-1 downto 0); 39 | i_src_c : in std_logic_vector(C_WORD_SIZE-1 downto 0); 40 | 41 | -- Outputs. 42 | o_invalidate_icache : out std_logic; 43 | o_invalidate_dcache : out std_logic; 44 | o_invalidate_branch_predictor : out std_logic; 45 | o_flush_dcache : out std_logic; 46 | o_result : out std_logic_vector(C_WORD_SIZE-1 downto 0) 47 | ); 48 | end cctrl; 49 | 50 | architecture rtl of cctrl is 51 | begin 52 | process(i_rst, i_clk) 53 | begin 54 | if i_rst = '1' then 55 | o_invalidate_icache <= '0'; 56 | o_invalidate_dcache <= '0'; 57 | o_invalidate_branch_predictor <= '0'; 58 | o_flush_dcache <= '0'; 59 | elsif rising_edge(i_clk) then 60 | -- Default values when there is no CCTRL operation. 61 | o_invalidate_icache <= '0'; 62 | o_invalidate_dcache <= '0'; 63 | o_invalidate_branch_predictor <= '0'; 64 | o_flush_dcache <= '0'; 65 | 66 | if i_en = '1' and i_op = C_CCTRL_CCTRL then 67 | if i_src_a = 32x"000" then 68 | -- Invalidate entire icache. 69 | o_invalidate_icache <= '1'; 70 | elsif i_src_a = 32x"001" then 71 | -- Invalidate entire dcache. 72 | o_invalidate_dcache <= '1'; 73 | elsif i_src_a = 32x"002" then 74 | -- Invalidate entire branch predictor. 75 | o_invalidate_branch_predictor <= '1'; 76 | elsif i_src_a = 32x"100" then 77 | -- Invalidate icache cache line given by address i_src_c. 78 | -- TODO(m): Implement me! 79 | elsif i_src_a = 32x"101" then 80 | -- Invalidate dcache cache line given by address i_src_c. 81 | -- TODO(m): Implement me! 82 | elsif i_src_a = 32x"201" then 83 | -- Flush entire dcache. 84 | o_flush_dcache <= '1'; 85 | elsif i_src_a = 32x"301" then 86 | -- Flush dcache cache line given by address i_src_c. 87 | -- TODO(m): Implement me! 88 | end if; 89 | end if; 90 | end if; 91 | end process; 92 | 93 | -- The result of a CCTRL operation is always the input argument. 94 | o_result <= i_src_c; 95 | end rtl; 96 | -------------------------------------------------------------------------------- /rtl/fpu/funp.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2020 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | ---------------------------------------------------------------------------------------------------- 21 | -- This entity implements FUNPL and FUNPH (unpack floating-point from low and high half, 22 | -- respectively). 23 | ---------------------------------------------------------------------------------------------------- 24 | 25 | library ieee; 26 | use ieee.std_logic_1164.all; 27 | use ieee.numeric_std.all; 28 | use work.types.all; 29 | 30 | entity funp is 31 | generic( 32 | WIDTH : positive := 32; 33 | EXP_BITS : positive := 8; 34 | EXP_BIAS : positive := 127; 35 | FRACT_BITS : positive := 23; 36 | 37 | PACKED_WIDTH : positive := 16; 38 | PACKED_EXP_BITS : positive := 5; 39 | PACKED_EXP_BIAS : positive := 15; 40 | PACKED_FRACT_BITS : positive := 10 41 | ); 42 | port( 43 | i_input : in std_logic_vector(WIDTH-1 downto 0); 44 | i_extract_high : in std_logic; 45 | o_result : out std_logic_vector(WIDTH-1 downto 0) 46 | ); 47 | end funp; 48 | 49 | architecture rtl of funp is 50 | function unpack(x : std_logic_vector(PACKED_WIDTH-1 downto 0)) return std_logic_vector is 51 | variable v_sign : std_logic; 52 | variable v_packed_exp : std_logic_vector(PACKED_EXP_BITS-1 downto 0); 53 | variable v_packed_fract : std_logic_vector(PACKED_FRACT_BITS-1 downto 0); 54 | 55 | variable v_exp_is_all_ones : boolean; 56 | variable v_exp_is_all_zero : boolean; 57 | 58 | variable v_exp : std_logic_vector(EXP_BITS-1 downto 0); 59 | variable v_fract : std_logic_vector(FRACT_BITS-1 downto 0); 60 | begin 61 | -- Decompose. 62 | v_sign := x(PACKED_WIDTH-1); 63 | v_packed_exp := x(PACKED_WIDTH-2 downto PACKED_FRACT_BITS); 64 | v_packed_fract := x(PACKED_FRACT_BITS-1 downto 0); 65 | 66 | -- Exponent. 67 | v_exp_is_all_ones := (v_packed_exp = (v_packed_exp'range => '1')); 68 | v_exp_is_all_zero := (v_packed_exp = (v_packed_exp'range => '0')); 69 | if v_exp_is_all_ones then 70 | v_exp := (v_exp'range => '1'); 71 | elsif v_exp_is_all_zero then 72 | v_exp := (v_exp'range => '0'); 73 | else 74 | v_exp := std_logic_vector(resize(unsigned(v_packed_exp), EXP_BITS) - PACKED_EXP_BIAS + EXP_BIAS); 75 | end if; 76 | 77 | -- Fraction. 78 | v_fract := v_packed_fract & ((FRACT_BITS-PACKED_FRACT_BITS)-1 downto 0 => '0'); 79 | 80 | return v_sign & v_exp & v_fract; 81 | end function; 82 | 83 | signal s_float_hi : std_logic_vector(PACKED_WIDTH-1 downto 0); 84 | signal s_float_lo : std_logic_vector(PACKED_WIDTH-1 downto 0); 85 | begin 86 | -- Extract the high and low parts of the input word. 87 | s_float_hi <= i_input(WIDTH-1 downto WIDTH/2); 88 | s_float_lo <= i_input(WIDTH/2-1 downto 0); 89 | 90 | -- Unpack it. 91 | o_result <= unpack(s_float_hi) when i_extract_high = '1' else 92 | unpack(s_float_lo); 93 | end rtl; 94 | -------------------------------------------------------------------------------- /rtl/ctrl/sync.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2023 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | ---------------------------------------------------------------------------------------------------- 21 | -- Synchronize instruction stream. 22 | ---------------------------------------------------------------------------------------------------- 23 | 24 | library ieee; 25 | use ieee.std_logic_1164.all; 26 | use work.types.all; 27 | use work.config.all; 28 | 29 | entity sync is 30 | port( 31 | -- Control signals. 32 | i_clk : in std_logic; 33 | i_rst : in std_logic; 34 | 35 | -- Inputs. 36 | i_en : in std_logic; 37 | i_op : in T_SYNC_OP; 38 | 39 | -- Outputs. 40 | o_stall : out std_logic; 41 | o_done : out std_logic; 42 | o_cancel_pending_instructions : out std_logic; 43 | o_result : out std_logic_vector(C_WORD_SIZE-1 downto 0) 44 | ); 45 | end sync; 46 | 47 | architecture rtl of sync is 48 | type T_STATE is (READY, STALLING, DONE); 49 | signal s_state : T_STATE; 50 | 51 | constant C_DELAY : integer := 1500; 52 | signal s_delay_cnt : integer range 0 to C_DELAY; 53 | 54 | signal s_sync_req : std_logic; 55 | begin 56 | -- Did we get a SYNC request? 57 | -- Note: This signal is typically held high during the entire stall period. 58 | s_sync_req <= '1' when i_en = '1' and i_op = C_SYNC_SYNC else '0'; 59 | 60 | -- Counter state machine: We just delay/stall for a number of cycles that will allow for memory 61 | -- writes to finish (ideally we should have some communication with the dcache logic & write 62 | -- queue). Once the delay is finished we send a request to cancel pending instructions in the 63 | -- pipeline. 64 | process(i_rst, i_clk) 65 | begin 66 | if i_rst = '1' then 67 | s_state <= READY; 68 | s_delay_cnt <= 0; 69 | o_done <= '0'; 70 | o_cancel_pending_instructions <= '0'; 71 | elsif rising_edge(i_clk) then 72 | -- Default values if not changed by the state machine. 73 | o_done <= '0'; 74 | o_cancel_pending_instructions <= '0'; 75 | 76 | case s_state is 77 | when READY => 78 | s_delay_cnt <= 0; 79 | if s_sync_req = '1' then 80 | s_state <= STALLING; 81 | end if; 82 | 83 | when STALLING => 84 | s_delay_cnt <= s_delay_cnt + 1; 85 | if s_delay_cnt = C_DELAY-1 then 86 | s_state <= DONE; 87 | end if; 88 | 89 | when DONE => 90 | o_done <= '1'; 91 | o_cancel_pending_instructions <= '1'; 92 | s_state <= READY; 93 | end case; 94 | end if; 95 | end process; 96 | 97 | -- Shall we stall the pipeline? 98 | o_stall <= '1' when (s_state = READY and s_sync_req = '1') or s_state = STALLING else '0'; 99 | 100 | -- The result is always zero. 101 | o_result <= (others => '0'); 102 | end rtl; 103 | -------------------------------------------------------------------------------- /rtl/alu/add32.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2018 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | library ieee; 21 | use ieee.std_logic_1164.all; 22 | use ieee.numeric_std.all; 23 | use work.types.all; 24 | use work.config.all; 25 | 26 | entity add32 is 27 | generic( 28 | CONFIG : T_CORE_CONFIG 29 | ); 30 | port( 31 | i_src_a : in std_logic_vector(31 downto 0); 32 | i_src_b : in std_logic_vector(31 downto 0); 33 | i_packed_mode : in T_PACKED_MODE; 34 | o_result : out std_logic_vector(31 downto 0) 35 | ); 36 | end add32; 37 | 38 | architecture rtl of add32 is 39 | signal s_res_32 : unsigned(31 downto 0); 40 | 41 | signal s_res_16_0 : unsigned(15 downto 0); 42 | signal s_res_16_1 : unsigned(15 downto 0); 43 | 44 | signal s_res_8_0 : unsigned(7 downto 0); 45 | signal s_res_8_1 : unsigned(7 downto 0); 46 | signal s_res_8_2 : unsigned(7 downto 0); 47 | signal s_res_8_3 : unsigned(7 downto 0); 48 | begin 49 | -- 32-bit addition. 50 | s_res_32 <= unsigned(i_src_a) + unsigned(i_src_b); 51 | 52 | PACKED_GEN: if CONFIG.HAS_PO generate 53 | -- 2x 16-bit addition. 54 | s_res_16_0 <= unsigned(i_src_a(15 downto 0)) + unsigned(i_src_b(15 downto 0)); 55 | s_res_16_1 <= unsigned(i_src_a(31 downto 16)) + unsigned(i_src_b(31 downto 16)); 56 | 57 | -- 4x 8-bit addition. 58 | s_res_8_0 <= unsigned(i_src_a(7 downto 0)) + unsigned(i_src_b(7 downto 0)); 59 | s_res_8_1 <= unsigned(i_src_a(15 downto 8)) + unsigned(i_src_b(15 downto 8)); 60 | s_res_8_2 <= unsigned(i_src_a(23 downto 16)) + unsigned(i_src_b(23 downto 16)); 61 | s_res_8_3 <= unsigned(i_src_a(31 downto 24)) + unsigned(i_src_b(31 downto 24)); 62 | 63 | -- Output the result. 64 | o_result(7 downto 0) <= 65 | std_logic_vector(s_res_8_0) when i_packed_mode = C_PACKED_BYTE else 66 | std_logic_vector(s_res_16_0(7 downto 0)) when i_packed_mode = C_PACKED_HALF_WORD else 67 | std_logic_vector(s_res_32(7 downto 0)); 68 | o_result(15 downto 8) <= 69 | std_logic_vector(s_res_8_1) when i_packed_mode = C_PACKED_BYTE else 70 | std_logic_vector(s_res_16_0(15 downto 8)) when i_packed_mode = C_PACKED_HALF_WORD else 71 | std_logic_vector(s_res_32(15 downto 8)); 72 | o_result(23 downto 16) <= 73 | std_logic_vector(s_res_8_2) when i_packed_mode = C_PACKED_BYTE else 74 | std_logic_vector(s_res_16_1(7 downto 0)) when i_packed_mode = C_PACKED_HALF_WORD else 75 | std_logic_vector(s_res_32(23 downto 16)); 76 | o_result(31 downto 24) <= 77 | std_logic_vector(s_res_8_3) when i_packed_mode = C_PACKED_BYTE else 78 | std_logic_vector(s_res_16_1(15 downto 8)) when i_packed_mode = C_PACKED_HALF_WORD else 79 | std_logic_vector(s_res_32(31 downto 24)); 80 | else generate 81 | -- In unpacked mode we only have to consider the 32-bit result. 82 | o_result <= std_logic_vector(s_res_32); 83 | end generate; 84 | end rtl; 85 | -------------------------------------------------------------------------------- /rtl/alu/sub32.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2018 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | library ieee; 21 | use ieee.std_logic_1164.all; 22 | use ieee.numeric_std.all; 23 | use work.types.all; 24 | use work.config.all; 25 | 26 | entity sub32 is 27 | generic( 28 | CONFIG : T_CORE_CONFIG 29 | ); 30 | port( 31 | i_src_a : in std_logic_vector(31 downto 0); 32 | i_src_b : in std_logic_vector(31 downto 0); 33 | i_packed_mode : in T_PACKED_MODE; 34 | o_result : out std_logic_vector(31 downto 0) 35 | ); 36 | end sub32; 37 | 38 | architecture rtl of sub32 is 39 | signal s_res_32 : unsigned(31 downto 0); 40 | 41 | signal s_res_16_0 : unsigned(15 downto 0); 42 | signal s_res_16_1 : unsigned(15 downto 0); 43 | 44 | signal s_res_8_0 : unsigned(7 downto 0); 45 | signal s_res_8_1 : unsigned(7 downto 0); 46 | signal s_res_8_2 : unsigned(7 downto 0); 47 | signal s_res_8_3 : unsigned(7 downto 0); 48 | begin 49 | -- 32-bit subtracion. 50 | s_res_32 <= unsigned(i_src_b) - unsigned(i_src_a); 51 | 52 | PACKED_GEN: if CONFIG.HAS_PO generate 53 | -- 2x 16-bit subtracion. 54 | s_res_16_0 <= unsigned(i_src_b(15 downto 0)) - unsigned(i_src_a(15 downto 0)); 55 | s_res_16_1 <= unsigned(i_src_b(31 downto 16)) - unsigned(i_src_a(31 downto 16)); 56 | 57 | -- 4x 8-bit subtracion. 58 | s_res_8_0 <= unsigned(i_src_b(7 downto 0)) - unsigned(i_src_a(7 downto 0)); 59 | s_res_8_1 <= unsigned(i_src_b(15 downto 8)) - unsigned(i_src_a(15 downto 8)); 60 | s_res_8_2 <= unsigned(i_src_b(23 downto 16)) - unsigned(i_src_a(23 downto 16)); 61 | s_res_8_3 <= unsigned(i_src_b(31 downto 24)) - unsigned(i_src_a(31 downto 24)); 62 | 63 | -- Output the result. 64 | o_result(7 downto 0) <= 65 | std_logic_vector(s_res_8_0) when i_packed_mode = C_PACKED_BYTE else 66 | std_logic_vector(s_res_16_0(7 downto 0)) when i_packed_mode = C_PACKED_HALF_WORD else 67 | std_logic_vector(s_res_32(7 downto 0)); 68 | o_result(15 downto 8) <= 69 | std_logic_vector(s_res_8_1) when i_packed_mode = C_PACKED_BYTE else 70 | std_logic_vector(s_res_16_0(15 downto 8)) when i_packed_mode = C_PACKED_HALF_WORD else 71 | std_logic_vector(s_res_32(15 downto 8)); 72 | o_result(23 downto 16) <= 73 | std_logic_vector(s_res_8_2) when i_packed_mode = C_PACKED_BYTE else 74 | std_logic_vector(s_res_16_1(7 downto 0)) when i_packed_mode = C_PACKED_HALF_WORD else 75 | std_logic_vector(s_res_32(23 downto 16)); 76 | o_result(31 downto 24) <= 77 | std_logic_vector(s_res_8_3) when i_packed_mode = C_PACKED_BYTE else 78 | std_logic_vector(s_res_16_1(15 downto 8)) when i_packed_mode = C_PACKED_HALF_WORD else 79 | std_logic_vector(s_res_32(31 downto 24)); 80 | else generate 81 | -- In unpacked mode we only have to consider the 32-bit result. 82 | o_result <= std_logic_vector(s_res_32); 83 | end generate; 84 | end rtl; 85 | -------------------------------------------------------------------------------- /rtl/alu/shuf32.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2018 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | library ieee; 21 | use ieee.std_logic_1164.all; 22 | 23 | entity shuf32 is 24 | port( 25 | i_src_a : in std_logic_vector(31 downto 0); 26 | i_src_b : in std_logic_vector(31 downto 0); 27 | o_result : out std_logic_vector(31 downto 0) 28 | ); 29 | end shuf32; 30 | 31 | architecture rtl of shuf32 is 32 | signal s_sign_fill : std_logic; 33 | signal s_fill_bit_0 : std_logic; 34 | signal s_fill_bit_1 : std_logic; 35 | signal s_fill_bit_2 : std_logic; 36 | signal s_fill_bit_3 : std_logic; 37 | begin 38 | -- Is this a sign-fill or zero-fill operation? 39 | s_sign_fill <= i_src_b(12); 40 | 41 | -- Determine fill bits for the four different source bytes. 42 | s_fill_bit_0 <= i_src_a(7) and s_sign_fill; 43 | s_fill_bit_1 <= i_src_a(15) and s_sign_fill; 44 | s_fill_bit_2 <= i_src_a(23) and s_sign_fill; 45 | s_fill_bit_3 <= i_src_a(31) and s_sign_fill; 46 | 47 | -- Select the outputs for the four result bytes. 48 | ShufMux1: with i_src_b(2 downto 0) select 49 | o_result(7 downto 0) <= 50 | i_src_a(7 downto 0) when "000", 51 | i_src_a(15 downto 8) when "001", 52 | i_src_a(23 downto 16) when "010", 53 | i_src_a(31 downto 24) when "011", 54 | (others => s_fill_bit_0) when "100", 55 | (others => s_fill_bit_1) when "101", 56 | (others => s_fill_bit_2) when "110", 57 | (others => s_fill_bit_3) when "111", 58 | (others => '-') when others; 59 | 60 | ShufMux2: with i_src_b(5 downto 3) select 61 | o_result(15 downto 8) <= 62 | i_src_a(7 downto 0) when "000", 63 | i_src_a(15 downto 8) when "001", 64 | i_src_a(23 downto 16) when "010", 65 | i_src_a(31 downto 24) when "011", 66 | (others => s_fill_bit_0) when "100", 67 | (others => s_fill_bit_1) when "101", 68 | (others => s_fill_bit_2) when "110", 69 | (others => s_fill_bit_3) when "111", 70 | (others => '-') when others; 71 | 72 | ShufMux3: with i_src_b(8 downto 6) select 73 | o_result(23 downto 16) <= 74 | i_src_a(7 downto 0) when "000", 75 | i_src_a(15 downto 8) when "001", 76 | i_src_a(23 downto 16) when "010", 77 | i_src_a(31 downto 24) when "011", 78 | (others => s_fill_bit_0) when "100", 79 | (others => s_fill_bit_1) when "101", 80 | (others => s_fill_bit_2) when "110", 81 | (others => s_fill_bit_3) when "111", 82 | (others => '-') when others; 83 | 84 | ShufMux4: with i_src_b(11 downto 9) select 85 | o_result(31 downto 24) <= 86 | i_src_a(7 downto 0) when "000", 87 | i_src_a(15 downto 8) when "001", 88 | i_src_a(23 downto 16) when "010", 89 | i_src_a(31 downto 24) when "011", 90 | (others => s_fill_bit_0) when "100", 91 | (others => s_fill_bit_1) when "101", 92 | (others => s_fill_bit_2) when "110", 93 | (others => s_fill_bit_3) when "111", 94 | (others => '-') when others; 95 | end rtl; 96 | -------------------------------------------------------------------------------- /rtl/pipeline/register_file.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2020 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | library ieee; 21 | use ieee.std_logic_1164.all; 22 | use ieee.numeric_std.all; 23 | use work.types.all; 24 | use work.config.all; 25 | 26 | --------------------------------------------------------------------------------------------------- 27 | -- This implements the scalar and vector register files, with the following properties: 28 | -- 29 | -- * There are three generic read ports. 30 | -- * There is a single write port. 31 | -- * Reading the Z or VZ registers always returns zero (0). 32 | -- * Writing to the Z or VZ registers has no effect (no operation). 33 | -- * Register content is undefined after reset. 34 | --------------------------------------------------------------------------------------------------- 35 | 36 | entity register_file is 37 | generic ( 38 | ENABLE_VECTOR_REGISTERS : boolean 39 | ); 40 | port ( 41 | i_clk : in std_logic; 42 | i_rst : in std_logic; 43 | i_stall_read_ports : in std_logic; 44 | 45 | -- Asynchronous read requestes (three read ports). 46 | i_rd_port_a : in T_SRC_REG; 47 | i_rd_port_b : in T_SRC_REG; 48 | i_rd_port_c : in T_SRC_REG; 49 | 50 | -- Output read data. 51 | o_data_a : out std_logic_vector(C_WORD_SIZE-1 downto 0); 52 | o_data_b : out std_logic_vector(C_WORD_SIZE-1 downto 0); 53 | o_data_c : out std_logic_vector(C_WORD_SIZE-1 downto 0); 54 | 55 | -- We have one write port. 56 | i_wr_port : in T_DST_REG; 57 | i_data_w : in std_logic_vector(C_WORD_SIZE-1 downto 0) 58 | ); 59 | end register_file; 60 | 61 | architecture rtl of register_file is 62 | begin 63 | -- Read port A. 64 | read_port_a: entity work.register_file_read_port 65 | generic map ( 66 | ENABLE_VECTOR_REGISTERS => ENABLE_VECTOR_REGISTERS 67 | ) 68 | port map ( 69 | i_clk => i_clk, 70 | i_rst => i_rst, 71 | i_stall => i_stall_read_ports, 72 | i_rd_port => i_rd_port_a, 73 | o_data => o_data_a, 74 | i_wr_port => i_wr_port, 75 | i_data_w => i_data_w 76 | ); 77 | 78 | -- Read port B. 79 | read_port_b: entity work.register_file_read_port 80 | generic map ( 81 | ENABLE_VECTOR_REGISTERS => ENABLE_VECTOR_REGISTERS 82 | ) 83 | port map ( 84 | i_clk => i_clk, 85 | i_rst => i_rst, 86 | i_stall => i_stall_read_ports, 87 | i_rd_port => i_rd_port_b, 88 | o_data => o_data_b, 89 | i_wr_port => i_wr_port, 90 | i_data_w => i_data_w 91 | ); 92 | 93 | -- Read port C. 94 | read_port_c: entity work.register_file_read_port 95 | generic map ( 96 | ENABLE_VECTOR_REGISTERS => ENABLE_VECTOR_REGISTERS 97 | ) 98 | port map ( 99 | i_clk => i_clk, 100 | i_rst => i_rst, 101 | i_stall => i_stall_read_ports, 102 | i_rd_port => i_rd_port_c, 103 | o_data => o_data_c, 104 | i_wr_port => i_wr_port, 105 | i_data_w => i_data_w 106 | ); 107 | end rtl; 108 | -------------------------------------------------------------------------------- /test/comparator_tb.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2018 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | library ieee; 21 | use ieee.std_logic_1164.all; 22 | 23 | entity comparator_tb is 24 | end comparator_tb; 25 | 26 | architecture behavioral of comparator_tb is 27 | signal s_src : std_logic_vector(7 downto 0); 28 | signal s_z : std_logic; 29 | signal s_nz : std_logic; 30 | signal s_s : std_logic; 31 | signal s_ns : std_logic; 32 | signal s_lt : std_logic; 33 | signal s_ge : std_logic; 34 | signal s_le : std_logic; 35 | signal s_gt : std_logic; 36 | begin 37 | comparator_0: entity work.comparator 38 | generic map ( 39 | WIDTH => 8 40 | ) 41 | port map ( 42 | i_src => s_src, 43 | o_z => s_z, 44 | o_nz => s_nz, 45 | o_s => s_s, 46 | o_ns => s_ns, 47 | o_lt => s_lt, 48 | o_ge => s_ge, 49 | o_le => s_le, 50 | o_gt => s_gt 51 | ); 52 | 53 | process 54 | -- The patterns to apply. 55 | type pattern_type is record 56 | -- Inputs 57 | src : std_logic_vector(7 downto 0); 58 | 59 | -- Expected outputs 60 | z : std_logic; 61 | nz : std_logic; 62 | s : std_logic; 63 | ns : std_logic; 64 | lt : std_logic; 65 | ge : std_logic; 66 | le : std_logic; 67 | gt : std_logic; 68 | end record; 69 | type pattern_array is array (natural range <>) of pattern_type; 70 | constant patterns : pattern_array := ( 71 | ("00000000", '1', '0', '0', '1', '0', '1', '1', '0'), 72 | ("00000001", '0', '1', '0', '1', '0', '1', '0', '1'), 73 | ("01111111", '0', '1', '0', '1', '0', '1', '0', '1'), 74 | ("11000000", '0', '1', '0', '1', '1', '0', '1', '0'), 75 | ("11111111", '0', '1', '1', '0', '1', '0', '1', '0') 76 | ); 77 | begin 78 | -- Test all the patterns in the pattern array. 79 | for i in patterns'range loop 80 | -- Set the inputs. 81 | s_src <= patterns(i).src; 82 | 83 | -- Wait for the results. 84 | wait for 1 ns; 85 | 86 | -- Check the outputs. 87 | assert s_z = patterns(i).z 88 | report "Bad Z value" severity error; 89 | assert s_nz = patterns(i).nz 90 | report "Bad NZ value" severity error; 91 | assert s_s = patterns(i).s 92 | report "Bad S value" severity error; 93 | assert s_ns = patterns(i).ns 94 | report "Bad NS value" severity error; 95 | assert s_lt = patterns(i).lt 96 | report "Bad LT value" severity error; 97 | assert s_ge = patterns(i).ge 98 | report "Bad GE value" severity error; 99 | assert s_le = patterns(i).le 100 | report "Bad LE value" severity error; 101 | assert s_gt = patterns(i).gt 102 | report "Bad GT value" severity error; 103 | end loop; 104 | assert false report "End of test" severity note; 105 | -- Wait forever; this will finish the simulation. 106 | wait; 107 | end process; 108 | end behavioral; 109 | 110 | -------------------------------------------------------------------------------- /rtl/fpu/float_decompose.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2018 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | library ieee; 21 | use ieee.std_logic_1164.all; 22 | use work.types.all; 23 | 24 | ---------------------------------------------------------------------------------------------------- 25 | -- This entity decomposes an IEEE 754 binary floating point number into its components, and reports 26 | -- various properties (such as NaN and infinity). 27 | -- 28 | -- IEEE 754 compatibility: 29 | -- - The sign, exponent and significand components are extracted. 30 | -- - NaN is correctly identified. 31 | -- - +/- infinity is correctly identified. 32 | -- - +/- zero is correctly identified. 33 | -- 34 | -- Incompatibilities/simplifications: 35 | -- - Denormals are always reported as zero. 36 | ---------------------------------------------------------------------------------------------------- 37 | 38 | entity float_decompose is 39 | generic( 40 | WIDTH : positive := 32; 41 | EXP_BITS : positive := 8; 42 | FRACT_BITS : positive := 23 43 | ); 44 | port( 45 | i_src : in std_logic_vector(WIDTH-1 downto 0); 46 | 47 | o_props : out T_FLOAT_PROPS; 48 | o_exponent : out std_logic_vector(EXP_BITS-1 downto 0); 49 | o_significand : out std_logic_vector(FRACT_BITS downto 0) 50 | ); 51 | end float_decompose; 52 | 53 | architecture rtl of float_decompose is 54 | signal s_exponent : std_logic_vector(EXP_BITS-1 downto 0); 55 | signal s_fraction : std_logic_vector(FRACT_BITS-1 downto 0); 56 | 57 | signal s_exponent_is_all_ones : std_logic; 58 | signal s_exponent_is_all_zero : std_logic; 59 | signal s_fraction_is_all_zero : std_logic; 60 | signal s_is_zero : std_logic; 61 | begin 62 | -- Decompose the floating point number. 63 | s_exponent <= i_src(WIDTH-2 downto FRACT_BITS); 64 | s_fraction <= i_src(FRACT_BITS-1 downto 0); 65 | 66 | -- Analyze the different parts. 67 | s_exponent_is_all_ones <= '1' when (s_exponent = (s_exponent'range => '1')) else '0'; 68 | s_exponent_is_all_zero <= '1' when (s_exponent = (s_exponent'range => '0')) else '0'; 69 | s_fraction_is_all_zero <= '1' when (s_fraction = (s_fraction'range => '0')) else '0'; 70 | 71 | -- The number is negative when the MSB is set. 72 | o_props.is_neg <= i_src(WIDTH-1); 73 | 74 | -- The definition of an IEEE 754 NaN is: 75 | -- sign = either 0 or 1. 76 | -- biased exponent = all 1 bits. 77 | -- fraction = anything except all 0 bits. 78 | o_props.is_nan <= s_exponent_is_all_ones and not s_fraction_is_all_zero; 79 | 80 | -- The definition of an IEEE 754 Infinity is: 81 | -- sign = 0 for positive infinity, 1 for negative infinity. 82 | -- biased exponent = all 1 bits. 83 | -- fraction = all 0 bits. 84 | o_props.is_inf <= s_exponent_is_all_ones and s_fraction_is_all_zero; 85 | 86 | -- According to IEEE 754 a number is zero when: 87 | -- biased exponent = all 0 bits. 88 | -- fraction = all 0 bits. 89 | -- Note: We ignore the fraction part, so we effectively treat denormals as zeros too. 90 | s_is_zero <= s_exponent_is_all_zero; 91 | o_props.is_zero <= s_is_zero; 92 | 93 | o_exponent <= s_exponent; 94 | o_significand <= '1' & s_fraction when s_is_zero = '0' else (others => '0'); 95 | end rtl; 96 | -------------------------------------------------------------------------------- /benchmark/fpu_bench.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2019 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | library ieee; 21 | use ieee.std_logic_1164.all; 22 | use work.types.all; 23 | 24 | entity fpu_bench is 25 | port( 26 | -- Control signals. 27 | i_clk : in std_logic; 28 | i_rst : in std_logic; 29 | i_stall : in std_logic; 30 | 31 | -- Inputs (sync). 32 | i_enable : in std_logic; 33 | i_op : in T_FPU_OP; 34 | i_packed_mode : in T_PACKED_MODE; 35 | i_src_a : in std_logic_vector(C_WORD_SIZE-1 downto 0); 36 | i_src_b : in std_logic_vector(C_WORD_SIZE-1 downto 0); 37 | 38 | -- Outputs (sync). 39 | o_f1_result : out std_logic_vector(C_WORD_SIZE-1 downto 0); 40 | o_f1_result_ready : out std_logic; 41 | o_f3_result : out std_logic_vector(C_WORD_SIZE-1 downto 0); 42 | o_f3_result_ready : out std_logic; 43 | o_f4_result : out std_logic_vector(C_WORD_SIZE-1 downto 0); 44 | o_f4_result_ready : out std_logic 45 | ); 46 | end fpu_bench; 47 | 48 | architecture rtl of fpu_bench is 49 | signal s_enable : std_logic; 50 | signal s_op : T_FPU_OP; 51 | signal s_packed_mode : T_PACKED_MODE; 52 | signal s_src_a : std_logic_vector(C_WORD_SIZE-1 downto 0); 53 | signal s_src_b : std_logic_vector(C_WORD_SIZE-1 downto 0); 54 | 55 | signal s_f1_next_result : std_logic_vector(C_WORD_SIZE-1 downto 0); 56 | signal s_f1_next_result_ready : std_logic; 57 | signal s_f3_next_result : std_logic_vector(C_WORD_SIZE-1 downto 0); 58 | signal s_f3_next_result_ready : std_logic; 59 | signal s_f4_next_result : std_logic_vector(C_WORD_SIZE-1 downto 0); 60 | signal s_f4_next_result_ready : std_logic; 61 | begin 62 | dut_0: entity work.fpu 63 | port map ( 64 | i_clk => i_clk, 65 | i_rst => i_rst, 66 | i_stall => i_stall, 67 | 68 | i_enable => s_enable, 69 | i_op => s_op, 70 | i_packed_mode => s_packed_mode, 71 | i_src_a => s_src_a, 72 | i_src_b => s_src_b, 73 | o_f1_next_result => s_f1_next_result, 74 | o_f1_next_result_ready => s_f1_next_result_ready, 75 | o_f3_next_result => s_f3_next_result, 76 | o_f3_next_result_ready => s_f3_next_result_ready, 77 | o_f4_next_result => s_f4_next_result, 78 | o_f4_next_result_ready => s_f4_next_result_ready 79 | ); 80 | 81 | process(i_clk, i_rst) 82 | begin 83 | if i_rst = '1' then 84 | s_enable <= '0'; 85 | s_op <= (others => '0'); 86 | s_packed_mode <= (others => '0'); 87 | s_src_a <= (others => '0'); 88 | s_src_b <= (others => '0'); 89 | o_f1_result <= (others => '0'); 90 | o_f1_result_ready <= '0'; 91 | o_f3_result <= (others => '0'); 92 | o_f3_result_ready <= '0'; 93 | o_f4_result <= (others => '0'); 94 | o_f4_result_ready <= '0'; 95 | elsif rising_edge(i_clk) then 96 | s_enable <= i_enable; 97 | s_op <= i_op; 98 | s_packed_mode <= i_packed_mode; 99 | s_src_a <= i_src_a; 100 | s_src_b <= i_src_b; 101 | o_f1_result <= s_f1_next_result; 102 | o_f1_result_ready <= s_f1_next_result_ready; 103 | o_f3_result <= s_f3_next_result; 104 | o_f3_result_ready <= s_f3_next_result_ready; 105 | o_f4_result <= s_f4_next_result; 106 | o_f4_result_ready <= s_f4_next_result_ready; 107 | end if; 108 | end process; 109 | end rtl; 110 | -------------------------------------------------------------------------------- /rtl/common/fifo.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2023 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | ---------------------------------------------------------------------------------------------------- 21 | -- Based on "Register based FIFO" by nandland: https://nandland.com/register-based-fifo/ 22 | ---------------------------------------------------------------------------------------------------- 23 | 24 | library ieee; 25 | use ieee.std_logic_1164.all; 26 | use ieee.numeric_std.all; 27 | 28 | entity fifo is 29 | generic ( 30 | G_WIDTH : integer := 32; 31 | G_DEPTH : integer := 16 32 | ); 33 | port ( 34 | -- Control signals. 35 | i_rst : in std_logic; 36 | i_clk : in std_logic; 37 | 38 | -- FIFO Write Interface. 39 | i_wr_en : in std_logic; 40 | i_wr_data : in std_logic_vector(G_WIDTH-1 downto 0); 41 | o_full : out std_logic; 42 | 43 | -- FIFO Read Interface. 44 | i_rd_en : in std_logic; 45 | o_rd_data : out std_logic_vector(G_WIDTH-1 downto 0); 46 | o_empty : out std_logic 47 | ); 48 | end fifo; 49 | 50 | architecture rtl of fifo is 51 | type T_FIFO_DATA is array (0 to G_DEPTH-1) of std_logic_vector(G_WIDTH-1 downto 0); 52 | signal s_fifo_data : T_FIFO_DATA := (others => (others => '0')); 53 | 54 | -- Ensure that the FIFO data is using registers, not BRAM. 55 | attribute RAMSTYLE : string; 56 | attribute RAMSTYLE of s_fifo_data : signal is "MLAB"; -- Intel/Altera 57 | attribute RAM_STYLE : string; 58 | attribute RAM_STYLE of s_fifo_data : signal is "distributed"; -- Xilinx 59 | 60 | signal s_wr_idx : integer range 0 to G_DEPTH-1 := 0; 61 | signal s_rd_idx : integer range 0 to G_DEPTH-1 := 0; 62 | signal s_fifo_count : integer range 0 to G_DEPTH := 0; 63 | 64 | signal s_full : std_logic; 65 | signal s_empty : std_logic; 66 | begin 67 | process (i_rst, i_clk) is 68 | begin 69 | if i_rst = '1' then 70 | s_fifo_count <= 0; 71 | s_wr_idx <= 0; 72 | s_rd_idx <= 0; 73 | elsif rising_edge(i_clk) then 74 | -- Keeps track of the total number of words in the FIFO. 75 | if i_wr_en = '1' and i_rd_en = '0' then 76 | s_fifo_count <= s_fifo_count + 1; 77 | elsif i_wr_en = '0' and i_rd_en = '1' then 78 | s_fifo_count <= s_fifo_count - 1; 79 | end if; 80 | 81 | -- Keeps track of the write index (and controls roll-over). 82 | if i_wr_en = '1' and s_full = '0' then 83 | if s_wr_idx = G_DEPTH - 1 then 84 | s_wr_idx <= 0; 85 | else 86 | s_wr_idx <= s_wr_idx + 1; 87 | end if; 88 | end if; 89 | 90 | -- Keeps track of the read index (and controls roll-over). 91 | if i_rd_en = '1' and s_empty = '0' then 92 | if s_rd_idx = G_DEPTH - 1 then 93 | s_rd_idx <= 0; 94 | else 95 | s_rd_idx <= s_rd_idx + 1; 96 | end if; 97 | end if; 98 | 99 | -- Registers the input data when there is a write. 100 | if i_wr_en = '1' then 101 | s_fifo_data(s_wr_idx) <= i_wr_data; 102 | end if; 103 | end if; 104 | end process; 105 | 106 | o_rd_data <= s_fifo_data(s_rd_idx); 107 | 108 | -- TODO(m): Make the full/empty signals registered. 109 | s_full <= '1' when s_fifo_count = G_DEPTH else '0'; 110 | s_empty <= '1' when s_fifo_count = 0 else '0'; 111 | 112 | o_full <= s_full; 113 | o_empty <= s_empty; 114 | end rtl; 115 | -------------------------------------------------------------------------------- /test/float_decompose_tb.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2018 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | library ieee; 21 | use ieee.std_logic_1164.all; 22 | use work.types.all; 23 | 24 | entity float_decompose_tb is 25 | end float_decompose_tb; 26 | 27 | architecture behavioral of float_decompose_tb is 28 | signal s_src : std_logic_vector(31 downto 0); 29 | signal s_props : T_FLOAT_PROPS; 30 | begin 31 | float_decompose_0: entity work.float_decompose 32 | generic map ( 33 | WIDTH => F32_WIDTH, 34 | EXP_BITS => F32_EXP_BITS, 35 | FRACT_BITS => F32_FRACT_BITS 36 | ) 37 | port map ( 38 | i_src => s_src, 39 | o_props => s_props 40 | ); 41 | 42 | process 43 | -- The patterns to apply. 44 | type pattern_type is record 45 | -- Inputs 46 | src : std_logic_vector(31 downto 0); 47 | 48 | -- Expected outputs 49 | props : T_FLOAT_PROPS; 50 | end record; 51 | type pattern_array is array (natural range <>) of pattern_type; 52 | constant patterns : pattern_array := ( 53 | (X"00000000", ('0', '0', '0', '1')), 54 | (X"80000000", ('1', '0', '0', '1')), 55 | (X"7F800000", ('0', '0', '1', '0')), 56 | (X"FF800000", ('1', '0', '1', '0')), 57 | (X"7FFFFFFF", ('0', '1', '0', '0')), 58 | (X"FFFFFFFF", ('1', '1', '0', '0')), 59 | (X"7F800010", ('0', '1', '0', '0')), 60 | (X"7FC00000", ('0', '1', '0', '0')), 61 | (X"FFC00000", ('1', '1', '0', '0')), 62 | (X"80000001", ('1', '0', '0', '1')) 63 | ); 64 | begin 65 | -- Test all the patterns in the pattern array. 66 | for i in patterns'range loop 67 | -- Set the inputs. 68 | s_src <= patterns(i).src; 69 | 70 | -- Wait for the results. 71 | wait for 1 ns; 72 | 73 | -- Check the outputs. 74 | assert s_props.is_neg = patterns(i).props.is_neg 75 | report "Incorrect sign value:" & lf & 76 | " src=" & to_string(s_src) & lf & 77 | " sign=" & to_string(s_props.is_neg) & lf & 78 | " expected: " & to_string(patterns(i).props.is_neg) 79 | severity error; 80 | 81 | assert s_props.is_nan = patterns(i).props.is_nan 82 | report "Incorrect is_nan value:" & lf & 83 | " src=" & to_string(s_src) & lf & 84 | " is_nan=" & to_string(s_props.is_nan) & lf & 85 | " expected: " & to_string(patterns(i).props.is_nan) 86 | severity error; 87 | 88 | assert s_props.is_inf = patterns(i).props.is_inf 89 | report "Incorrect is_inf value:" & lf & 90 | " src=" & to_string(s_src) & lf & 91 | " is_inf=" & to_string(s_props.is_inf) & lf & 92 | " expected: " & to_string(patterns(i).props.is_inf) 93 | severity error; 94 | 95 | assert s_props.is_zero = patterns(i).props.is_zero 96 | report "Incorrect is_zero value:" & lf & 97 | " src=" & to_string(s_src) & lf & 98 | " is_zero=" & to_string(s_props.is_zero) & lf & 99 | " expected: " & to_string(patterns(i).props.is_zero) 100 | severity error; 101 | 102 | end loop; 103 | assert false report "End of test" severity note; 104 | -- Wait forever; this will finish the simulation. 105 | wait; 106 | end process; 107 | end behavioral; 108 | 109 | -------------------------------------------------------------------------------- /test/skid_buffer_tb.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2018 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | library ieee; 21 | use ieee.std_logic_1164.all; 22 | use ieee.numeric_std.all; 23 | use work.types.all; 24 | 25 | entity skid_buffer_tb is 26 | end skid_buffer_tb; 27 | 28 | architecture behavioral of skid_buffer_tb is 29 | signal s_clk : std_logic; 30 | signal s_rst : std_logic; 31 | signal s_stall : std_logic; 32 | signal s_d : std_logic_vector(3 downto 0); 33 | signal s_valid_w : std_logic; 34 | signal s_q : std_logic_vector(3 downto 0); 35 | signal s_valid : std_logic; 36 | begin 37 | skid_buffer_0: entity work.skid_buffer 38 | generic map ( 39 | WIDTH => 4 40 | ) 41 | port map ( 42 | i_clk => s_clk, 43 | i_rst => s_rst, 44 | i_stall => s_stall, 45 | i_d => s_d, 46 | i_valid => s_valid_w, 47 | o_q => s_q, 48 | o_valid => s_valid 49 | ); 50 | 51 | process 52 | -- Patterns to apply. 53 | type pattern_type is record 54 | -- Inputs 55 | stall : std_logic; 56 | d : std_logic_vector(3 downto 0); 57 | valid_w : std_logic; 58 | 59 | -- Expected outputs 60 | q : std_logic_vector(3 downto 0); 61 | valid : std_logic; 62 | end record; 63 | type pattern_array is array (natural range <>) of pattern_type; 64 | constant patterns : pattern_array := ( 65 | ('0', "1111", '1', "1111", '1'), 66 | ('0', "0100", '0', "0000", '0'), 67 | ('1', "0101", '0', "0000", '0'), 68 | ('1', "0110", '1', "0110", '1'), 69 | ('1', "0111", '0', "0110", '1'), 70 | ('1', "1000", '0', "0110", '1'), 71 | ('0', "1001", '0', "0110", '0'), 72 | ('0', "1010", '0', "0110", '0'), 73 | ('1', "1011", '0', "0110", '0'), 74 | ('1', "1100", '1', "1100", '1'), 75 | ('0', "1101", '1', "1101", '1'), 76 | ('0', "1110", '0', "1100", '0') 77 | ); 78 | begin 79 | -- Start by resetting the entity (to have defined signals). 80 | s_rst <= '1'; 81 | s_clk <= '0'; 82 | s_stall <= '0'; 83 | s_valid_w <= '0'; 84 | s_d <= (others => '0'); 85 | 86 | wait for 1 ns; 87 | s_rst <= '0'; 88 | wait for 1 ns; 89 | 90 | -- Test all the patterns in the pattern array. 91 | for i in patterns'range loop 92 | -- Set the inputs. 93 | s_stall <= patterns(i).stall; 94 | s_valid_w <= patterns(i).valid_w; 95 | s_d <= patterns(i).d; 96 | 97 | -- Tick the clock. 98 | wait for 1 ns; 99 | s_clk <= '1'; 100 | wait for 1 ns; 101 | s_clk <= '0'; 102 | 103 | -- Check the outputs. 104 | assert s_q = patterns(i).q 105 | report "Bad q:" & lf & 106 | " i = " & integer'image(i) & lf & 107 | " q = " & to_string(s_q) & lf & 108 | " (expected " & to_string(patterns(i).q) & ")" 109 | severity error; 110 | assert s_valid = patterns(i).valid 111 | report "Bad valid:" & lf & 112 | " i = " & integer'image(i) & lf & 113 | " valid = " & to_string(s_valid) & lf & 114 | " (expected " & to_string(patterns(i).valid) & ")" 115 | severity error; 116 | end loop; 117 | assert false report "End of test" severity note; 118 | -- Wait forever; this will finish the simulation. 119 | wait; 120 | end process; 121 | end behavioral; 122 | 123 | -------------------------------------------------------------------------------- /test/clz32_tb.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2018 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | library ieee; 21 | use ieee.std_logic_1164.all; 22 | use ieee.numeric_std.all; 23 | use work.config.all; 24 | use work.types.all; 25 | 26 | entity clz32_tb is 27 | end clz32_tb; 28 | 29 | architecture behavioral of clz32_tb is 30 | signal s_src : std_logic_vector(31 downto 0); 31 | signal s_packed_mode : T_PACKED_MODE; 32 | signal s_result : std_logic_vector(31 downto 0); 33 | begin 34 | clz32_0: entity work.clz32 35 | generic map ( 36 | CONFIG => C_CORE_CONFIG_FULL 37 | ) 38 | port map ( 39 | i_src => s_src, 40 | i_packed_mode => s_packed_mode, 41 | o_result => s_result 42 | ); 43 | 44 | process 45 | type pattern_array is array (natural range <>) of std_logic_vector(31 downto 0); 46 | constant patterns : pattern_array := ( 47 | ("00000000000000000000000000000000"), 48 | ("00000000000000000000000000000001"), 49 | ("00000000000000000000000000000010"), 50 | ("00000000000000000000000000000100"), 51 | ("00000000000000000000000000001000"), 52 | ("00000000000000000000000000010000"), 53 | ("00000000000000000000000000100000"), 54 | ("00000000000000000000000001000000"), 55 | ("00000000000000000000000010000000"), 56 | ("00000000000000000000000100000000"), 57 | ("00000000000000000000001000000000"), 58 | ("00000000000000000000010000000000"), 59 | ("00000000000000000000100000000000"), 60 | ("00000000000000000001000000000000"), 61 | ("00000000000000000010000000000000"), 62 | ("00000000000000000100000000000000"), 63 | ("00000000000000001000000000000000"), 64 | ("00000000000000010000000000000000"), 65 | ("00000000000000100000000000000000"), 66 | ("00000000000001000000000000000000"), 67 | ("00000000000010000000000000000000"), 68 | ("00000000000100000000000000000000"), 69 | ("00000000001000000000000000000000"), 70 | ("00000000010000000000000000000000"), 71 | ("00000000100000000000000000000000"), 72 | ("00000001000000000000000000000000"), 73 | ("00000010000000000000000000000000"), 74 | ("00000100000000000000000000000000"), 75 | ("00001000000000000000000000000000"), 76 | ("00010000000000000000000000000000"), 77 | ("00100000000000000000000000000000"), 78 | ("01000000000000000000000000000000"), 79 | ("10000000000000000000000000000000") 80 | ); 81 | 82 | function refClz32(x: std_logic_vector(31 downto 0)) return std_logic_vector is 83 | begin 84 | for i in 31 downto 0 loop 85 | if x(i) = '1' then 86 | return std_logic_vector(to_unsigned(31-i, 32)); 87 | end if; 88 | end loop; 89 | return std_logic_vector(to_unsigned(32, 32)); 90 | end function; 91 | 92 | begin 93 | -- Test some values from 0 to 2^32-1. 94 | for i in patterns'range loop 95 | for k in 0 to 10000 loop 96 | -- Set the input. 97 | s_src <= to_word(k*55) or patterns(i); 98 | s_packed_mode <= C_PACKED_NONE; -- TODO(m): Add this to the test pattern. 99 | 100 | -- Wait for the results. 101 | wait for 1 ns; 102 | 103 | -- Check the output. 104 | assert s_result = refClz32(s_src) 105 | report "Bad count value:" & lf & 106 | " src=" & to_string(s_src) & lf & 107 | " cnt=" & to_string(s_result) & " (expected " & to_string(refClz32(s_src)) & ")" 108 | severity error; 109 | end loop; 110 | end loop; 111 | assert false report "End of test" severity note; 112 | -- Wait forever; this will finish the simulation. 113 | wait; 114 | end process; 115 | end behavioral; 116 | 117 | -------------------------------------------------------------------------------- /test/funp_tb.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2020 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | library ieee; 21 | use ieee.std_logic_1164.all; 22 | use ieee.numeric_std.all; 23 | use work.types.all; 24 | 25 | -- A testbench has no ports. 26 | entity funp_tb is 27 | end funp_tb; 28 | 29 | architecture behav of funp_tb is 30 | -- IEEE 754 binary-32 31 | constant WIDTH : positive := 32; 32 | constant EXP_BITS : positive := 8; 33 | constant EXP_BIAS : positive := 127; 34 | constant FRACT_BITS : positive := WIDTH - 1 - EXP_BITS; 35 | 36 | -- IEEE 754 binary-16 37 | constant PACKED_WIDTH : positive := 16; 38 | constant PACKED_EXP_BITS : positive := 5; 39 | constant PACKED_EXP_BIAS : positive := 15; 40 | constant PACKED_FRACT_BITS : positive := PACKED_WIDTH - 1 - PACKED_EXP_BITS; 41 | 42 | signal s_clk : std_logic; 43 | 44 | signal s_input : std_logic_vector(WIDTH-1 downto 0); 45 | signal s_extract_high : std_logic; 46 | signal s_result : std_logic_vector(WIDTH-1 downto 0); 47 | begin 48 | -- Component instantiation. 49 | funp_0: entity work.funp 50 | port map ( 51 | i_input => s_input, 52 | i_extract_high => s_extract_high, 53 | o_result => s_result 54 | ); 55 | 56 | process 57 | -- The patterns to apply. 58 | type pattern_type is record 59 | -- Inputs. 60 | extract_high : std_logic; 61 | flt16_1 : std_logic_vector(PACKED_WIDTH-1 downto 0); 62 | flt16_2 : std_logic_vector(PACKED_WIDTH-1 downto 0); 63 | 64 | -- Expected outputs. 65 | result : std_logic_vector(WIDTH-1 downto 0); 66 | end record; 67 | type pattern_array is array (natural range <>) of pattern_type; 68 | constant patterns : pattern_array := ( 69 | ( 70 | -- LO(0.0, 0.0) = 0.0 71 | '0', 16X"0000", 16X"0000", 32X"00000000" 72 | ), 73 | ( 74 | -- HI(0.0, 0.0) = 0.0 75 | '1', 16X"0000", 16X"0000", 32X"00000000" 76 | ), 77 | ( 78 | -- LO(1.0, 2.0) = 2.0 79 | '0', 16X"3c00", 16X"4000", 32X"40000000" 80 | ), 81 | ( 82 | -- HI(1.0, 2.0) = 1.0 83 | '1', 16X"3c00", 16X"4000", 32X"3f800000" 84 | ), 85 | ( 86 | -- LO(-1.0, 3.998046875) = 3.998046875 87 | '0', 16X"bc00", 16X"43ff", 32X"407fe000" 88 | ), 89 | ( 90 | -- HI(-1.0, 3.998046875) = -1.0 91 | '1', 16X"bc00", 16X"43ff", 32X"bf800000" 92 | ), 93 | ( 94 | -- LO(-Inf, NaN) = NaN 95 | '0', 16X"fc00", 16X"7fff", 32X"7fffe000" 96 | ), 97 | ( 98 | -- HI(-Inf, NaN) = -Inf 99 | '1', 16X"fc00", 16X"7fff", 32X"ff800000" 100 | ) 101 | ); 102 | begin 103 | -- Reset all inputs. 104 | s_extract_high <= '0'; 105 | s_input <= (others => '0'); 106 | 107 | -- Reset the entity. 108 | s_clk <= '0'; 109 | wait for 1 ns; 110 | s_clk <= '1'; 111 | wait until s_clk = '1'; 112 | 113 | -- Test all the patterns in the pattern array. 114 | for i in patterns'range loop 115 | -- Prepare the input signal s. 116 | s_extract_high <= patterns(i).extract_high; 117 | s_input <= patterns(i).flt16_1 & patterns(i).flt16_2; 118 | 119 | -- Tick the clock (this is really unnecessary - just here for wave debugging). 120 | wait for 1 ns; 121 | s_clk <= '0'; 122 | wait for 1 ns; 123 | s_clk <= '1'; 124 | wait until s_clk = '1'; 125 | 126 | -- Check the outputs. 127 | assert s_result = patterns(i).result 128 | report "Bad result (" & integer'image(i) & "):" & lf & 129 | " r=" & to_string(s_result) & 130 | " (e=" & to_string(patterns(i).result) & ")" 131 | severity error; 132 | end loop; 133 | assert false report "End of test" severity note; 134 | -- Wait forever; this will finish the simulation. 135 | wait; 136 | end process; 137 | end behav; 138 | -------------------------------------------------------------------------------- /rtl/alu/popcnt32.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2021 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | library ieee; 21 | use ieee.std_logic_1164.all; 22 | use ieee.numeric_std.all; 23 | use work.types.all; 24 | use work.config.all; 25 | 26 | entity popcnt32 is 27 | generic( 28 | CONFIG : T_CORE_CONFIG 29 | ); 30 | port( 31 | i_src : in std_logic_vector(31 downto 0); 32 | i_packed_mode : in T_PACKED_MODE; 33 | o_result : out std_logic_vector(31 downto 0) 34 | ); 35 | end popcnt32; 36 | 37 | 38 | --------------------------------------------------------------------------------------------------- 39 | -- The popcnt (population count) function is implemented as a 5-level adder tree. 40 | --------------------------------------------------------------------------------------------------- 41 | 42 | architecture rtl of popcnt32 is 43 | -- Level 1 44 | subtype t_uint2 is unsigned(1 downto 0); 45 | type t_lvl1_array is array (15 downto 0) of t_uint2; 46 | signal s_c1 : t_lvl1_array; 47 | 48 | -- Level 2 49 | subtype t_uint3 is unsigned(2 downto 0); 50 | type t_lvl2_array is array (7 downto 0) of t_uint3; 51 | signal s_c2 : t_lvl2_array; 52 | 53 | -- Level 3 54 | subtype t_uint4 is unsigned(3 downto 0); 55 | type t_lvl3_array is array (3 downto 0) of t_uint4; 56 | signal s_c3 : t_lvl3_array; 57 | 58 | -- Level 4 59 | subtype t_uint5 is unsigned(4 downto 0); 60 | type t_lvl4_array is array (1 downto 0) of t_uint5; 61 | signal s_c4 : t_lvl4_array; 62 | 63 | -- Level 5 64 | subtype t_uint6 is unsigned(5 downto 0); 65 | signal s_c5 : t_uint6; 66 | 67 | signal s_result_32 : std_logic_vector(31 downto 0); 68 | signal s_result_16 : std_logic_vector(31 downto 0); 69 | signal s_result_8 : std_logic_vector(31 downto 0); 70 | 71 | function add2bits(a : std_logic; b : std_logic) return unsigned is 72 | variable av : std_logic_vector(1 downto 0); 73 | variable bv : std_logic_vector(1 downto 0); 74 | begin 75 | av := '0' & a; 76 | bv := '0' & b; 77 | return unsigned(av) + unsigned(bv); 78 | end function; 79 | begin 80 | -- Level 1 81 | Lvl1Gen: for k in 15 downto 0 generate 82 | s_c1(k) <= add2bits(i_src(2*k+1), i_src(2*k)); 83 | end generate; 84 | 85 | -- Level 2 86 | Lvl2Gen: for k in 7 downto 0 generate 87 | s_c2(k) <= ("0" & s_c1(2*k+1)) + ("0" & s_c1(2*k)); 88 | end generate; 89 | 90 | -- Level 3 91 | Lvl3Gen: for k in 3 downto 0 generate 92 | s_c3(k) <= ("0" & s_c2(2*k+1)) + ("0" & s_c2(2*k)); 93 | end generate; 94 | 95 | -- Level 4 96 | Lvl4Gen: for k in 1 downto 0 generate 97 | s_c4(k) <= ("0" & s_c3(2*k+1)) + ("0" & s_c3(2*k)); 98 | end generate; 99 | 100 | -- Level 5 (final level) 101 | s_c5 <= ("0" & s_c4(1)) + ("0" & s_c4(0)); 102 | 103 | -- 32-bit result. 104 | s_result_32(31 downto 6) <= (others => '0'); 105 | s_result_32(5 downto 0) <= std_logic_vector(s_c5); 106 | 107 | PACKED_GEN: if CONFIG.HAS_PO generate 108 | -- 16x2-bit result. 109 | s_result_16(31 downto 21) <= (others => '0'); 110 | s_result_16(20 downto 16) <= std_logic_vector(s_c4(1)); 111 | s_result_16(15 downto 5) <= (others => '0'); 112 | s_result_16(4 downto 0) <= std_logic_vector(s_c4(0)); 113 | 114 | -- 8x4-bit result. 115 | s_result_8(31 downto 28) <= (others => '0'); 116 | s_result_8(27 downto 24) <= std_logic_vector(s_c3(3)); 117 | s_result_8(23 downto 20) <= (others => '0'); 118 | s_result_8(19 downto 16) <= std_logic_vector(s_c3(2)); 119 | s_result_8(15 downto 12) <= (others => '0'); 120 | s_result_8(11 downto 8) <= std_logic_vector(s_c3(1)); 121 | s_result_8(7 downto 4) <= (others => '0'); 122 | s_result_8(3 downto 0) <= std_logic_vector(s_c3(0)); 123 | 124 | -- Select outputs. 125 | o_result <= s_result_8 when i_packed_mode = C_PACKED_BYTE else 126 | s_result_16 when i_packed_mode = C_PACKED_HALF_WORD else 127 | s_result_32; 128 | else generate 129 | -- In unpacked mode we only have to consider the 32-bit result. 130 | o_result <= s_result_32; 131 | end generate; 132 | end rtl; 133 | -------------------------------------------------------------------------------- /rtl/core/dcache.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2020 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | library ieee; 21 | use ieee.std_logic_1164.all; 22 | use work.config.all; 23 | 24 | entity dcache is 25 | generic( 26 | CONFIG : T_CORE_CONFIG 27 | ); 28 | port( 29 | -- Control signals. 30 | i_clk : in std_logic; 31 | i_rst : in std_logic; 32 | 33 | -- Data interface (slave). 34 | i_data_req : in std_logic; 35 | i_data_adr : in std_logic_vector(C_WORD_SIZE-1 downto 2); 36 | i_data_dat : in std_logic_vector(C_WORD_SIZE-1 downto 0); 37 | i_data_we : in std_logic; 38 | i_data_sel : in std_logic_vector(C_WORD_SIZE/8-1 downto 0); 39 | o_data_dat : out std_logic_vector(C_WORD_SIZE-1 downto 0); 40 | o_data_ack : out std_logic; 41 | o_data_busy : out std_logic; 42 | 43 | -- Memory interface (WB master). 44 | o_mem_cyc : out std_logic; 45 | o_mem_stb : out std_logic; 46 | o_mem_adr : out std_logic_vector(C_WORD_SIZE-1 downto 2); 47 | o_mem_dat : out std_logic_vector(C_WORD_SIZE-1 downto 0); 48 | o_mem_we : out std_logic; 49 | o_mem_sel : out std_logic_vector(C_WORD_SIZE/8-1 downto 0); 50 | i_mem_dat : in std_logic_vector(C_WORD_SIZE-1 downto 0); 51 | i_mem_ack : in std_logic; 52 | i_mem_stall : in std_logic; 53 | i_mem_err : in std_logic 54 | ); 55 | end dcache; 56 | 57 | architecture rtl of dcache is 58 | constant C_REQ_FIFO_DEPTH : integer := 32; 59 | constant C_REQ_FIFO_WIDTH : integer := 1; 60 | 61 | signal s_start_req : std_logic; 62 | signal s_ignore_ack : std_logic; 63 | signal s_immediate_ack : std_logic; 64 | 65 | signal s_fifo_wr_en : std_logic; 66 | signal s_fifo_wr_data : std_logic_vector(C_REQ_FIFO_WIDTH-1 downto 0); 67 | signal s_fifo_full : std_logic; 68 | signal s_fifo_rd_en : std_logic; 69 | signal s_fifo_rd_data : std_logic_vector(C_REQ_FIFO_WIDTH-1 downto 0); 70 | signal s_fifo_empty : std_logic; 71 | begin 72 | -- TODO(m): Implement a proper write-through cache to speed up read operations. 73 | 74 | -- We use a FIFO to keep track of ongoing requests. 75 | req_fifo: entity work.fifo 76 | generic map ( 77 | G_WIDTH => C_REQ_FIFO_WIDTH, 78 | G_DEPTH => C_REQ_FIFO_DEPTH 79 | ) 80 | port map ( 81 | i_rst => i_rst, 82 | i_clk => i_clk, 83 | i_wr_en => s_fifo_wr_en, 84 | i_wr_data => s_fifo_wr_data, 85 | o_full => s_fifo_full, 86 | i_rd_en => s_fifo_rd_en, 87 | o_rd_data => s_fifo_rd_data, 88 | o_empty => s_fifo_empty 89 | ); 90 | 91 | -- Shall we send a new request? 92 | s_start_req <= i_data_req and (not i_mem_stall) and (not s_fifo_full); 93 | 94 | -- Write requests are ACKed immediately (on the next cycle) whenever possible. 95 | process (i_rst, i_clk) is 96 | begin 97 | if i_rst = '1' then 98 | s_immediate_ack <= '0'; 99 | elsif rising_edge(i_clk) then 100 | s_immediate_ack <= s_start_req and i_data_we; 101 | end if; 102 | end process; 103 | 104 | -- We ignore ACKs from the Wishbone interface that have already been ACKed. 105 | s_ignore_ack <= s_fifo_rd_data(0); 106 | 107 | -- Queue memory requests in the FIFO. The purpose is to match ACKs from the Wishbone bus with 108 | -- the requests that we have sent. 109 | s_fifo_wr_en <= s_start_req; 110 | s_fifo_wr_data(0) <= i_data_we; 111 | 112 | -- Read from the request FIFO when we get an ACK from the Wishbone bus. 113 | s_fifo_rd_en <= i_mem_ack and (not s_fifo_empty); 114 | 115 | -- We just forward all requests to the main memory interface. 116 | o_mem_cyc <= i_data_req or (not s_fifo_empty); 117 | o_mem_stb <= i_data_req and (not s_fifo_full); 118 | o_mem_adr <= i_data_adr; 119 | o_mem_dat <= i_data_dat; 120 | o_mem_we <= i_data_we; 121 | o_mem_sel <= i_data_sel; 122 | 123 | -- ...send the result back. 124 | -- Note: s_immediate_ack and a non-ignored i_mem_ack SHOULD never happen at the same time. 125 | -- If they did, one of those ACKs would be lost, which would be bad. 126 | o_data_ack <= s_immediate_ack or (i_mem_ack and (not s_ignore_ack)); 127 | o_data_busy <= i_mem_stall or s_fifo_full; 128 | o_data_dat <= i_mem_dat; 129 | end rtl; 130 | -------------------------------------------------------------------------------- /rtl/pipeline/register_file_read_port.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2020 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | library ieee; 21 | use ieee.std_logic_1164.all; 22 | use ieee.numeric_std.all; 23 | use work.types.all; 24 | use work.config.all; 25 | 26 | entity register_file_read_port is 27 | generic ( 28 | ENABLE_VECTOR_REGISTERS : boolean 29 | ); 30 | port ( 31 | i_clk : in std_logic; 32 | i_rst : in std_logic; 33 | i_stall : in std_logic; 34 | 35 | -- Asynchronous read request. 36 | i_rd_port : in T_SRC_REG; 37 | 38 | -- Output read data. 39 | o_data : out std_logic_vector(C_WORD_SIZE-1 downto 0); 40 | 41 | -- We have one write port. 42 | i_wr_port : in T_DST_REG; 43 | i_data_w : in std_logic_vector(C_WORD_SIZE-1 downto 0) 44 | ); 45 | end register_file_read_port; 46 | 47 | architecture rtl of register_file_read_port is 48 | constant C_SCALAR_ADDR_BITS : positive := C_LOG2_NUM_REGS; 49 | constant C_VECTOR_ADDR_BITS : positive := C_LOG2_NUM_REGS + C_LOG2_VEC_REG_ELEMENTS; 50 | 51 | signal s_rd_port : T_SRC_REG; 52 | signal s_prev_rd_port : T_SRC_REG; 53 | 54 | signal s_req_z : std_logic; 55 | signal s_prev_req_z : std_logic; 56 | 57 | signal s_scalar_read_addr : std_logic_vector(C_SCALAR_ADDR_BITS-1 downto 0); 58 | signal s_scalar_write_addr : std_logic_vector(C_SCALAR_ADDR_BITS-1 downto 0); 59 | signal s_scalar_we : std_logic; 60 | signal s_scalar_read_data : std_logic_vector(C_WORD_SIZE-1 downto 0); 61 | signal s_vector_read_data : std_logic_vector(C_WORD_SIZE-1 downto 0); 62 | 63 | function is_zero_reg(src_reg : T_SRC_REG) return std_logic is 64 | begin 65 | if src_reg.reg = to_vector(C_Z_REG, C_LOG2_NUM_REGS) then 66 | return '1'; 67 | else 68 | return '0'; 69 | end if; 70 | end function; 71 | 72 | begin 73 | -- Latch the read operations. 74 | process(i_clk, i_rst) 75 | begin 76 | if i_rst = '1' then 77 | s_prev_rd_port.reg <= (others => '0'); 78 | s_prev_rd_port.element <= (others => '0'); 79 | s_prev_rd_port.is_vector <= '0'; 80 | s_prev_req_z <= '0'; 81 | elsif rising_edge(i_clk) then 82 | if i_stall = '0' then 83 | s_prev_rd_port <= s_rd_port; 84 | s_prev_req_z <= s_req_z; 85 | end if; 86 | end if; 87 | end process; 88 | 89 | -- Handle stall: Use inputs or latched inputs from the previous cycle. 90 | s_rd_port <= s_prev_rd_port when i_stall = '1' else i_rd_port; 91 | s_req_z <= s_prev_req_z when i_stall = '1' else is_zero_reg(i_rd_port); 92 | 93 | -- Prepare scalar read & write signals. 94 | s_scalar_read_addr <= s_rd_port.reg; 95 | s_scalar_write_addr <= i_wr_port.reg; 96 | s_scalar_we <= i_wr_port.is_target and not i_wr_port.is_vector; 97 | 98 | -- Scalar registers RAM. 99 | scalar_ram_1: entity work.ram_dual_port 100 | generic map ( 101 | WIDTH => C_WORD_SIZE, 102 | ADDR_BITS => C_SCALAR_ADDR_BITS, 103 | PREFER_DISTRIBUTED => true 104 | ) 105 | port map ( 106 | i_clk => i_clk, 107 | i_write_data => i_data_w, 108 | i_write_addr => s_scalar_write_addr, 109 | i_we => s_scalar_we, 110 | i_read_addr => s_scalar_read_addr, 111 | o_read_data => s_scalar_read_data 112 | ); 113 | 114 | vreg_gen: if ENABLE_VECTOR_REGISTERS generate 115 | signal s_vector_read_addr : std_logic_vector(C_VECTOR_ADDR_BITS-1 downto 0); 116 | signal s_vector_write_addr : std_logic_vector(C_VECTOR_ADDR_BITS-1 downto 0); 117 | signal s_vector_we : std_logic; 118 | begin 119 | -- Prepare vector read & write signals. 120 | s_vector_read_addr <= s_rd_port.reg & s_rd_port.element; 121 | s_vector_write_addr <= i_wr_port.reg & i_wr_port.element; 122 | s_vector_we <= i_wr_port.is_target and i_wr_port.is_vector; 123 | 124 | -- Vector registers RAM. 125 | vector_ram_1: entity work.ram_dual_port 126 | generic map ( 127 | WIDTH => C_WORD_SIZE, 128 | ADDR_BITS => C_VECTOR_ADDR_BITS 129 | ) 130 | port map ( 131 | i_clk => i_clk, 132 | i_write_data => i_data_w, 133 | i_write_addr => s_vector_write_addr, 134 | i_we => s_vector_we, 135 | i_read_addr => s_vector_read_addr, 136 | o_read_data => s_vector_read_data 137 | ); 138 | else generate 139 | s_vector_read_data <= (others => '0'); 140 | end generate; 141 | 142 | -- Output signal. 143 | o_data <= (others => '0') when s_prev_req_z = '1' else 144 | s_scalar_read_data when s_prev_rd_port.is_vector = '0' else 145 | s_vector_read_data; 146 | end rtl; 147 | -------------------------------------------------------------------------------- /test/vector_stride_gen_tb.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2018 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | library ieee; 21 | use ieee.std_logic_1164.all; 22 | use ieee.numeric_std.all; 23 | use work.types.all; 24 | use work.config.all; 25 | 26 | entity vector_stride_gen_tb is 27 | end vector_stride_gen_tb; 28 | 29 | architecture behavioral of vector_stride_gen_tb is 30 | signal s_clk : std_logic; 31 | signal s_rst : std_logic; 32 | signal s_stall : std_logic; 33 | signal s_is_first_vector_op_cycle : std_logic; 34 | signal s_stride : std_logic_vector(C_WORD_SIZE-1 downto 0); 35 | signal s_offset : std_logic_vector(C_WORD_SIZE-1 downto 0); 36 | 37 | -- Clock period. 38 | constant C_HALF_PERIOD : time := 2 ns; 39 | begin 40 | vector_stride_gen_0: entity work.vector_stride_gen 41 | port map ( 42 | i_clk => s_clk, 43 | i_rst => s_rst, 44 | i_stall => s_stall, 45 | i_is_first_vector_op_cycle => s_is_first_vector_op_cycle, 46 | i_stride => s_stride, 47 | o_offset => s_offset 48 | ); 49 | 50 | process 51 | -- The patterns to apply. 52 | type pattern_type is record 53 | -- Inputs 54 | stall : std_logic; 55 | is_first_vector_op_cycle : std_logic; 56 | stride : std_logic_vector(C_WORD_SIZE-1 downto 0); 57 | 58 | -- Expected outputs 59 | offset : std_logic_vector(C_WORD_SIZE-1 downto 0); 60 | end record; 61 | type pattern_array is array (natural range <>) of pattern_type; 62 | constant patterns : pattern_array := ( 63 | -- The first state should be zero. 64 | ('0', '0', to_word(0), to_word(0)), 65 | ('0', '0', to_word(0), to_word(0)), 66 | 67 | -- Run a vector operation with stride 8. 68 | ('0', '1', to_word(8), to_word(0)), 69 | ('0', '0', to_word(8), to_word(8)), 70 | ('0', '0', to_word(8), to_word(16)), 71 | ('0', '0', to_word(8), to_word(24)), 72 | ('0', '0', to_word(8), to_word(32)), 73 | ('0', '0', to_word(8), to_word(40)), 74 | 75 | -- Stall... 76 | ('1', '0', to_word(8), to_word(48)), 77 | ('1', '0', to_word(8), to_word(48)), 78 | ('1', '0', to_word(8), to_word(48)), 79 | ('1', '0', to_word(8), to_word(48)), 80 | 81 | -- Continue. 82 | ('0', '0', to_word(8), to_word(48)), 83 | ('0', '0', to_word(8), to_word(56)), 84 | 85 | -- Restart with a stride of 96. 86 | ('0', '1', to_word(96), to_word(0)), 87 | ('0', '0', to_word(96), to_word(96)), 88 | 89 | -- Restart with a stride of -20. 90 | ('0', '1', to_word(-20), to_word(0)), 91 | ('0', '0', to_word(-20), to_word(-20)), 92 | ('0', '0', to_word(-20), to_word(-40)), 93 | ('0', '0', to_word(-20), to_word(-60)), 94 | ('0', '0', to_word(-20), to_word(-80)), 95 | 96 | -- Change the stride without restarting: should not affect the result. 97 | ('0', '0', to_word(123), to_word(-100)), 98 | ('0', '0', to_word(1), to_word(-120)), 99 | ('0', '0', to_word(0), to_word(-140)) 100 | ); 101 | begin 102 | -- Reset all inputs. 103 | s_clk <= '0'; 104 | s_stall <= '0'; 105 | s_is_first_vector_op_cycle <= '0'; 106 | s_stride <= (others => '0'); 107 | 108 | -- Start by resetting the register file. 109 | s_rst <= '1'; 110 | wait for C_HALF_PERIOD; 111 | s_clk <= '1'; 112 | wait for C_HALF_PERIOD; 113 | s_clk <= '0'; 114 | s_rst <= '0'; 115 | wait for C_HALF_PERIOD; 116 | s_clk <= '1'; 117 | 118 | -- Test all the patterns in the pattern array. 119 | for i in patterns'range loop 120 | wait until s_clk = '1'; 121 | 122 | -- Set the inputs. 123 | s_stall <= patterns(i).stall; 124 | s_is_first_vector_op_cycle <= patterns(i).is_first_vector_op_cycle; 125 | s_stride <= patterns(i).stride; 126 | 127 | -- Tick the clock. 128 | wait for C_HALF_PERIOD; 129 | s_clk <= '0'; 130 | 131 | -- Wait for the result to be produced. 132 | wait until s_clk = '0'; 133 | 134 | -- Check the outputs. 135 | assert s_offset = patterns(i).offset 136 | report "Bad offset (" & integer'image(i) & "):" & lf & 137 | " " & to_string(s_offset) & " (expected " & to_string(patterns(i).offset) & ")" 138 | severity error; 139 | 140 | -- Tick the clock. 141 | wait for C_HALF_PERIOD; 142 | s_clk <= '1'; 143 | end loop; 144 | 145 | assert false report "End of test" severity note; 146 | -- Wait forever; this will finish the simulation. 147 | wait; 148 | end process; 149 | end behavioral; 150 | 151 | -------------------------------------------------------------------------------- /rtl/common/config.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2019 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | ---------------------------------------------------------------------------------------------------- 21 | -- This file contains the configuration options for MRISC32-A1. 22 | ---------------------------------------------------------------------------------------------------- 23 | 24 | library ieee; 25 | use ieee.std_logic_1164.all; 26 | 27 | package config is 28 | -------------------------------------------------------------------------------------------------- 29 | -- CPU word size. 30 | -- NOTE: The word size must currently be 32 bits, so this must not be changed. 31 | -------------------------------------------------------------------------------------------------- 32 | constant C_LOG2_WORD_SIZE : integer := 5; 33 | constant C_WORD_SIZE : integer := 2**C_LOG2_WORD_SIZE; 34 | 35 | -------------------------------------------------------------------------------------------------- 36 | -- Number of registers. 37 | -- NOTE: The the number of register must currently be 32, so this must not be changed. 38 | -------------------------------------------------------------------------------------------------- 39 | constant C_LOG2_NUM_REGS : integer := 5; 40 | constant C_NUM_REGS : integer := 2**C_LOG2_NUM_REGS; 41 | 42 | -------------------------------------------------------------------------------------------------- 43 | -- Number of vector elements in each vector register. 44 | -- NOTE: The the number of vector elements should be at least 16. 45 | -- TODO(m): Make this part of T_CORE_CONFIG instead. 46 | -------------------------------------------------------------------------------------------------- 47 | constant C_LOG2_VEC_REG_ELEMENTS : integer := 4; 48 | constant C_VEC_REG_ELEMENTS : integer := 2**C_LOG2_VEC_REG_ELEMENTS; 49 | 50 | ------------------------------------------------------------------------------------------------ 51 | -- Hardware allocated registers. 52 | -- NOTE: Changing these values should be possible, but it has not been tested so it may be 53 | -- broken. 54 | ------------------------------------------------------------------------------------------------ 55 | constant C_Z_REG : integer := 0; -- Z = R0 56 | constant C_LR_REG : integer := 30; -- LR = R30 57 | constant C_VL_REG : integer := 31; -- VL = R31 58 | 59 | -- For some instructions R31 is interpreted as PC rather than VL. 60 | constant C_PC_REG : integer := 31; 61 | 62 | 63 | -------------------------------------------------------------------------------------------------- 64 | -- Per-core configuration parameters (pass these when instantiating the core entity). 65 | -------------------------------------------------------------------------------------------------- 66 | 67 | type T_CORE_CONFIG is record 68 | -- The start PC after reset. 69 | RESET_PC : std_logic_vector(C_WORD_SIZE-1 downto 0); 70 | 71 | -- Support vector operations (including the register file, V0-V31). 72 | HAS_VEC : boolean; 73 | 74 | -- Support packed operations (i.e. .B, .H versions of instructions). 75 | HAS_PO : boolean; 76 | 77 | -- Include hardware multiply (integer only). 78 | HAS_MUL : boolean; 79 | 80 | -- Include hardware division (integer and floating point). 81 | HAS_DIV : boolean; 82 | 83 | -- Support saturating and halving arithmetic operations. 84 | HAS_SA : boolean; 85 | 86 | -- Include an FPU. 87 | -- NOTE: For full floating point support, HAS_DIV must also be true. 88 | HAS_FP : boolean; 89 | 90 | -- Support the FSQRT instruction. 91 | -- NOTE: This has not yet been implemented, so this flag should always be set to false. 92 | HAS_SQRT : boolean; 93 | 94 | -- Enable the branch predictor. 95 | ENABLE_BRANCH_PREDICTOR : boolean; 96 | end record T_CORE_CONFIG; 97 | 98 | 99 | -- Full configuration. 100 | constant C_CORE_CONFIG_FULL : T_CORE_CONFIG := ( 101 | RESET_PC => X"00000200", 102 | HAS_VEC => true, 103 | HAS_PO => true, 104 | HAS_MUL => true, 105 | HAS_DIV => true, 106 | HAS_SA => true, 107 | HAS_FP => true, 108 | HAS_SQRT => false, 109 | ENABLE_BRANCH_PREDICTOR => true 110 | ); 111 | 112 | -- Minimal configuration. 113 | constant C_CORE_CONFIG_MINIMAL : T_CORE_CONFIG := ( 114 | RESET_PC => X"00000200", 115 | HAS_VEC => false, 116 | HAS_PO => false, 117 | HAS_MUL => false, 118 | HAS_DIV => false, 119 | HAS_SA => false, 120 | HAS_FP => false, 121 | HAS_SQRT => false, 122 | ENABLE_BRANCH_PREDICTOR => false 123 | ); 124 | 125 | -- Default configuration: Full. 126 | constant C_CORE_CONFIG_DEFAULT : T_CORE_CONFIG := C_CORE_CONFIG_FULL; 127 | end package; 128 | -------------------------------------------------------------------------------- /rtl/core/core_1mem.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2020 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | ---------------------------------------------------------------------------------------------------- 21 | -- This is a single CPU core, with a von Neumann architecture (with a single memory interface). 22 | ---------------------------------------------------------------------------------------------------- 23 | 24 | library ieee; 25 | use ieee.std_logic_1164.all; 26 | use work.config.all; 27 | use work.debug.all; 28 | 29 | entity core_1mem is 30 | generic( 31 | CONFIG : T_CORE_CONFIG := C_CORE_CONFIG_DEFAULT 32 | ); 33 | port( 34 | -- Control signals. 35 | i_clk : in std_logic; 36 | i_rst : in std_logic; 37 | 38 | -- Memory interface (Wishbone B4 pipelined master). 39 | o_mem_cyc : out std_logic; 40 | o_mem_stb : out std_logic; 41 | o_mem_adr : out std_logic_vector(C_WORD_SIZE-1 downto 2); 42 | o_mem_dat : out std_logic_vector(C_WORD_SIZE-1 downto 0); 43 | o_mem_we : out std_logic; 44 | o_mem_sel : out std_logic_vector(C_WORD_SIZE/8-1 downto 0); 45 | i_mem_dat : in std_logic_vector(C_WORD_SIZE-1 downto 0); 46 | i_mem_ack : in std_logic; 47 | i_mem_stall : in std_logic; 48 | i_mem_err : in std_logic; 49 | 50 | -- Debug trace interface. 51 | o_debug_trace : out T_DEBUG_TRACE 52 | ); 53 | end core_1mem; 54 | 55 | architecture rtl of core_1mem is 56 | -- L1I master signals. 57 | signal s_imem_cyc : std_logic; 58 | signal s_imem_stb : std_logic; 59 | signal s_imem_adr : std_logic_vector(C_WORD_SIZE-1 downto 2); 60 | signal s_imem_dat : std_logic_vector(C_WORD_SIZE-1 downto 0); 61 | signal s_imem_ack : std_logic; 62 | signal s_imem_stall : std_logic; 63 | signal s_imem_err : std_logic; 64 | 65 | -- L1D master signals. 66 | signal s_dmem_cyc : std_logic; 67 | signal s_dmem_stb : std_logic; 68 | signal s_dmem_adr : std_logic_vector(C_WORD_SIZE-1 downto 2); 69 | signal s_dmem_dat_w : std_logic_vector(C_WORD_SIZE-1 downto 0); 70 | signal s_dmem_we : std_logic; 71 | signal s_dmem_sel : std_logic_vector(C_WORD_SIZE/8-1 downto 0); 72 | signal s_dmem_dat : std_logic_vector(C_WORD_SIZE-1 downto 0); 73 | signal s_dmem_ack : std_logic; 74 | signal s_dmem_stall : std_logic; 75 | signal s_dmem_err : std_logic; 76 | begin 77 | -------------------------------------------------------------------------------------------------- 78 | -- Pipeline. 79 | -------------------------------------------------------------------------------------------------- 80 | 81 | core_1: entity work.core 82 | generic map( 83 | CONFIG => CONFIG 84 | ) 85 | port map ( 86 | i_clk => i_clk, 87 | i_rst => i_rst, 88 | 89 | -- Instruction interface. 90 | o_imem_cyc => s_imem_cyc, 91 | o_imem_stb => s_imem_stb, 92 | o_imem_adr => s_imem_adr, 93 | i_imem_dat => s_imem_dat, 94 | i_imem_ack => s_imem_ack, 95 | i_imem_stall => s_imem_stall, 96 | i_imem_err => s_imem_err, 97 | 98 | -- Data interface. 99 | o_dmem_cyc => s_dmem_cyc, 100 | o_dmem_stb => s_dmem_stb, 101 | o_dmem_adr => s_dmem_adr, 102 | o_dmem_dat => s_dmem_dat_w, 103 | o_dmem_we => s_dmem_we, 104 | o_dmem_sel => s_dmem_sel, 105 | i_dmem_dat => s_dmem_dat, 106 | i_dmem_ack => s_dmem_ack, 107 | i_dmem_stall => s_dmem_stall, 108 | i_dmem_err => s_dmem_err, 109 | 110 | -- Debug trace interface. 111 | o_debug_trace => o_debug_trace 112 | ); 113 | 114 | -- Memory arbiter. 115 | arbiter_1: entity work.mem_arbiter 116 | port map ( 117 | i_clk => i_clk, 118 | i_rst => i_rst, 119 | 120 | -- Instruction interface. 121 | i_instr_cyc => s_imem_cyc, 122 | i_instr_stb => s_imem_stb, 123 | i_instr_adr => s_imem_adr, 124 | o_instr_dat => s_imem_dat, 125 | o_instr_ack => s_imem_ack, 126 | o_instr_stall => s_imem_stall, 127 | o_instr_err => s_imem_err, 128 | 129 | -- Data interface. 130 | i_data_cyc => s_dmem_cyc, 131 | i_data_stb => s_dmem_stb, 132 | i_data_we => s_dmem_we, 133 | i_data_sel => s_dmem_sel, 134 | i_data_adr => s_dmem_adr, 135 | i_data_dat_w => s_dmem_dat_w, 136 | o_data_dat => s_dmem_dat, 137 | o_data_ack => s_dmem_ack, 138 | o_data_stall => s_dmem_stall, 139 | o_data_err => s_dmem_err, 140 | 141 | -- Memory interface. 142 | o_mem_cyc => o_mem_cyc, 143 | o_mem_stb => o_mem_stb, 144 | o_mem_we => o_mem_we, 145 | o_mem_sel => o_mem_sel, 146 | o_mem_adr => o_mem_adr, 147 | o_mem_dat_w => o_mem_dat, 148 | i_mem_dat => i_mem_dat, 149 | i_mem_ack => i_mem_ack, 150 | i_mem_stall => i_mem_stall, 151 | i_mem_err => i_mem_err 152 | ); 153 | 154 | end rtl; 155 | -------------------------------------------------------------------------------- /rtl/muldiv/div_pipelined.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2018 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | ---------------------------------------------------------------------------------------------------- 21 | -- This is a pipelined divider for signed or unsigned integers. 22 | -- 23 | -- * One division operation can start each clock cycle. 24 | -- * An N-bit division operation takes N clock cycles to complete. 25 | -- 26 | -- TODO: 27 | -- * Add support for blocking/stalling mode. 28 | -- - Non-blocking mode shall be used when the next instruction is a division (to enable single 29 | -- cycle divisions for vector instructions). 30 | -- - Otherwise blocking mode shall be used (to ensure proper EX pipeline scheduling). 31 | ---------------------------------------------------------------------------------------------------- 32 | 33 | library ieee; 34 | use ieee.std_logic_1164.all; 35 | use ieee.numeric_std.all; 36 | use work.types.all; 37 | 38 | entity div_pipelined is 39 | generic( 40 | WIDTH : positive 41 | ); 42 | port( 43 | -- Control signals. 44 | i_clk : in std_logic; 45 | i_rst : in std_logic; 46 | 47 | -- Inputs (async). 48 | i_enable : in std_logic; 49 | i_op : in T_DIV_OP; -- Operation 50 | i_src_a : in std_logic_vector(WIDTH-1 downto 0); -- Source operand A 51 | i_src_b : in std_logic_vector(WIDTH-1 downto 0); -- Source operand B 52 | i_dst_reg : in T_DST_REG; 53 | 54 | -- Outputs (async). 55 | o_result : out std_logic_vector(WIDTH-1 downto 0); 56 | o_result_dst_reg : out T_DST_REG; 57 | o_result_ready : out std_logic 58 | ); 59 | end div_pipelined; 60 | 61 | architecture rtl of div_pipelined is 62 | constant NUM_STEPS : integer := WIDTH; 63 | 64 | type T_DIV_STATE is record 65 | n : std_logic_vector(WIDTH-1 downto 0); 66 | d : std_logic_vector(WIDTH-1 downto 0); 67 | q : std_logic_vector(WIDTH-1 downto 0); 68 | r : std_logic_vector(WIDTH-1 downto 0); 69 | op : T_DIV_OP; 70 | dst_reg : T_DST_REG; 71 | end record; 72 | 73 | type T_DIV_PIPELINE_REGS is array (0 to NUM_STEPS) of T_DIV_STATE; 74 | signal s_next_div_state : T_DIV_PIPELINE_REGS; 75 | signal s_div_state : T_DIV_PIPELINE_REGS; 76 | signal s_first_state : T_DIV_STATE; 77 | signal s_final_state : T_DIV_STATE; 78 | begin 79 | -- Prepare inputs. 80 | -- TODO(m): Handle sign. 81 | s_first_state.n <= i_src_a when i_enable = '1' else (others => '0'); 82 | s_first_state.d <= i_src_b when i_enable = '1' else (0 => '1', others => '0'); 83 | s_first_state.q <= (others => '0'); 84 | s_first_state.r <= (others => '0'); 85 | 86 | s_first_state.op <= i_op; 87 | 88 | s_first_state.dst_reg.is_target <= i_dst_reg.is_target and i_enable; 89 | s_first_state.dst_reg.reg <= i_dst_reg.reg; 90 | s_first_state.dst_reg.element <= i_dst_reg.element; 91 | s_first_state.dst_reg.is_vector <= i_dst_reg.is_vector; 92 | 93 | s_div_state(0) <= s_first_state; 94 | 95 | DivPipeGen: for k in 1 to NUM_STEPS generate 96 | -- Divider stage. 97 | div_stage_x: entity work.div_stage 98 | generic map ( 99 | WIDTH => WIDTH 100 | ) 101 | port map ( 102 | i_n => s_div_state(k-1).n, 103 | i_d => s_div_state(k-1).d, 104 | i_q => s_div_state(k-1).q, 105 | i_r => s_div_state(k-1).r, 106 | o_n => s_next_div_state(k).n, 107 | o_d => s_next_div_state(k).d, 108 | o_q => s_next_div_state(k).q, 109 | o_r => s_next_div_state(k).r 110 | ); 111 | 112 | -- Forward the operation information from the previous pipeline stage. 113 | s_next_div_state(k).dst_reg <= s_div_state(k-1).dst_reg; 114 | s_next_div_state(k).op <= s_div_state(k-1).op; 115 | 116 | -- Pipeline flops. 117 | process(i_clk, i_rst) 118 | begin 119 | if i_rst = '1' then 120 | s_div_state(k).n <= (others => '0'); 121 | s_div_state(k).d <= (others => '0'); 122 | s_div_state(k).q <= (others => '0'); 123 | s_div_state(k).r <= (others => '0'); 124 | s_div_state(k).dst_reg.is_target <= '0'; 125 | s_div_state(k).dst_reg.reg <= (others => '0'); 126 | s_div_state(k).dst_reg.element <= (others => '0'); 127 | s_div_state(k).dst_reg.is_vector <= '0'; 128 | elsif rising_edge(i_clk) then 129 | s_div_state(k) <= s_next_div_state(k); 130 | end if; 131 | end process; 132 | end generate; 133 | 134 | s_final_state <= s_div_state(NUM_STEPS); 135 | 136 | -- Outputs. 137 | -- TODO(m): Handle sign. 138 | ResultMux: with s_final_state.op select 139 | o_result <= 140 | s_final_state.q when C_DIV_DIV | C_DIV_DIVU, 141 | s_final_state.r when C_DIV_REM | C_DIV_REMU, 142 | (others => '0') when others; 143 | 144 | o_result_dst_reg <= s_final_state.dst_reg; 145 | o_result_ready <= s_final_state.dst_reg.is_target; 146 | end rtl; 147 | -------------------------------------------------------------------------------- /rtl/pipeline/forward_to_vector_control.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2018 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | ---------------------------------------------------------------------------------------------------- 21 | -- Operand forwarding for the ID stage. 22 | -- 23 | -- The VL (Vector Length) value may be forwarded from later pipeline stages. 24 | -- 25 | -- This entity decides: 26 | -- 27 | -- * Whether or not the pipeline needs to be stalled to wait for a value that is not yet ready. 28 | -- * Whether or not to use a forwarded value. 29 | -- * Which value to use (from which pipeline stage). 30 | ---------------------------------------------------------------------------------------------------- 31 | 32 | library ieee; 33 | use ieee.std_logic_1164.all; 34 | use work.types.all; 35 | use work.config.all; 36 | 37 | entity forward_to_vector_control is 38 | port( 39 | -- Do we need the VL value? 40 | i_vl_requested : in std_logic; 41 | 42 | -- Operand information from the different pipeline stages. 43 | i_dst_reg_from_id : in T_DST_REG; 44 | 45 | i_dst_reg_from_rf : in T_DST_REG; 46 | 47 | i_dst_reg_from_ex1 : in T_DST_REG; 48 | i_value_from_ex1 : in std_logic_vector(C_WORD_SIZE-1 downto 0); 49 | i_ready_from_ex1 : in std_logic; 50 | 51 | i_dst_reg_from_ex2 : in T_DST_REG; 52 | i_value_from_ex2 : in std_logic_vector(C_WORD_SIZE-1 downto 0); 53 | i_ready_from_ex2 : in std_logic; 54 | 55 | i_dst_reg_from_ex3 : in T_DST_REG; 56 | i_value_from_ex3 : in std_logic_vector(C_WORD_SIZE-1 downto 0); 57 | i_ready_from_ex3 : in std_logic; 58 | 59 | i_dst_reg_from_ex4 : in T_DST_REG; 60 | i_value_from_ex4 : in std_logic_vector(C_WORD_SIZE-1 downto 0); 61 | 62 | -- Operand selection for the ID stage. 63 | o_value : out std_logic_vector(C_WORD_SIZE-1 downto 0); 64 | o_use_value : out std_logic; 65 | o_value_ready : out std_logic 66 | ); 67 | end forward_to_vector_control; 68 | 69 | architecture rtl of forward_to_vector_control is 70 | signal s_reg_from_id : std_logic; 71 | signal s_reg_from_rf : std_logic; 72 | signal s_reg_from_ex1 : std_logic; 73 | signal s_reg_from_ex2 : std_logic; 74 | signal s_reg_from_ex3 : std_logic; 75 | signal s_reg_from_ex4 : std_logic; 76 | 77 | signal s_use_value : std_logic; 78 | signal s_value_ready : std_logic; 79 | begin 80 | -- Determine which stages are writing to the VL register. 81 | -- Note: VL is a scalar register, so we only care about scalar registers and do not have 82 | -- to match against individual vector elements. This saves time since the register 83 | -- matching logic is a critical path. 84 | s_reg_from_id <= i_dst_reg_from_id.is_target when 85 | (i_dst_reg_from_id.reg = to_vector(C_VL_REG, C_LOG2_NUM_REGS)) and 86 | (i_dst_reg_from_id.is_vector = '0') else '0'; 87 | s_reg_from_rf <= i_dst_reg_from_rf.is_target when 88 | (i_dst_reg_from_rf.reg = to_vector(C_VL_REG, C_LOG2_NUM_REGS)) and 89 | (i_dst_reg_from_rf.is_vector = '0') else '0'; 90 | s_reg_from_ex1 <= i_dst_reg_from_ex1.is_target when 91 | (i_dst_reg_from_ex1.reg = to_vector(C_VL_REG, C_LOG2_NUM_REGS)) and 92 | (i_dst_reg_from_ex1.is_vector = '0') else '0'; 93 | s_reg_from_ex2 <= i_dst_reg_from_ex2.is_target when 94 | (i_dst_reg_from_ex2.reg = to_vector(C_VL_REG, C_LOG2_NUM_REGS)) and 95 | (i_dst_reg_from_ex2.is_vector = '0') else '0'; 96 | s_reg_from_ex3 <= i_dst_reg_from_ex3.is_target when 97 | (i_dst_reg_from_ex3.reg = to_vector(C_VL_REG, C_LOG2_NUM_REGS)) and 98 | (i_dst_reg_from_ex3.is_vector = '0') else '0'; 99 | s_reg_from_ex4 <= i_dst_reg_from_ex4.is_target when 100 | (i_dst_reg_from_ex4.reg = to_vector(C_VL_REG, C_LOG2_NUM_REGS)) and 101 | (i_dst_reg_from_ex4.is_vector = '0') else '0'; 102 | 103 | -- Which value to forward? 104 | o_value <= i_value_from_ex1 when (s_reg_from_ex1 and i_ready_from_ex1) = '1' else 105 | i_value_from_ex2 when (s_reg_from_ex2 and i_ready_from_ex2) = '1' else 106 | i_value_from_ex3 when (s_reg_from_ex3 and i_ready_from_ex3) = '1' else 107 | i_value_from_ex4; 108 | 109 | -- Should the forwarded pipeline value be used instead of register file value? 110 | s_use_value <= s_reg_from_id or s_reg_from_rf or s_reg_from_ex1 or s_reg_from_ex2 or s_reg_from_ex3 or s_reg_from_ex4; 111 | 112 | -- Is the value ready for use? 113 | s_value_ready <= '0' when (s_reg_from_id or s_reg_from_rf) = '1' else 114 | i_ready_from_ex1 when s_reg_from_ex1 = '1' else 115 | i_ready_from_ex2 when s_reg_from_ex2 = '1' else 116 | i_ready_from_ex3 when s_reg_from_ex3 = '1' else 117 | '1'; 118 | 119 | -- Mask the outputs: We should only forward the value if VL is requested. 120 | o_use_value <= s_use_value and i_vl_requested; 121 | o_value_ready <= s_value_ready and i_vl_requested; 122 | end rtl; 123 | 124 | -------------------------------------------------------------------------------- /rtl/sau/sau.vhd: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------------------------------------------------- 2 | -- Copyright (c) 2018 Marcus Geelnard 3 | -- 4 | -- This software is provided 'as-is', without any express or implied warranty. In no event will the 5 | -- authors be held liable for any damages arising from the use of this software. 6 | -- 7 | -- Permission is granted to anyone to use this software for any purpose, including commercial 8 | -- applications, and to alter it and redistribute it freely, subject to the following restrictions: 9 | -- 10 | -- 1. The origin of this software must not be misrepresented; you must not claim that you wrote 11 | -- the original software. If you use this software in a product, an acknowledgment in the 12 | -- product documentation would be appreciated but is not required. 13 | -- 14 | -- 2. Altered source versions must be plainly marked as such, and must not be misrepresented as 15 | -- being the original software. 16 | -- 17 | -- 3. This notice may not be removed or altered from any source distribution. 18 | ---------------------------------------------------------------------------------------------------- 19 | 20 | ---------------------------------------------------------------------------------------------------- 21 | -- This is the SAU. 22 | ---------------------------------------------------------------------------------------------------- 23 | 24 | library ieee; 25 | use ieee.std_logic_1164.all; 26 | use ieee.numeric_std.all; 27 | use work.types.all; 28 | use work.config.all; 29 | 30 | entity sau is 31 | generic( 32 | CONFIG : T_CORE_CONFIG 33 | ); 34 | port( 35 | -- Control signals. 36 | i_clk : in std_logic; 37 | i_rst : in std_logic; 38 | i_stall : in std_logic; 39 | 40 | -- Inputs (async). 41 | i_enable : in std_logic; 42 | i_op : in T_SAU_OP; 43 | i_packed_mode : in T_PACKED_MODE; 44 | i_src_a : in std_logic_vector(C_WORD_SIZE-1 downto 0); 45 | i_src_b : in std_logic_vector(C_WORD_SIZE-1 downto 0); 46 | 47 | -- Outputs (async). 48 | o_next_result : out std_logic_vector(C_WORD_SIZE-1 downto 0); 49 | o_next_result_ready : out std_logic 50 | ); 51 | end sau; 52 | 53 | architecture rtl of sau is 54 | signal s_sau32_enable : std_logic; 55 | signal s_next_sau32_result : std_logic_vector(C_WORD_SIZE-1 downto 0); 56 | signal s_next_sau32_result_ready : std_logic; 57 | 58 | signal s_sau16_enable : std_logic; 59 | signal s_next_sau16_result : std_logic_vector(C_WORD_SIZE-1 downto 0); 60 | signal s_next_sau16_result_ready : std_logic; 61 | 62 | signal s_sau8_enable : std_logic; 63 | signal s_next_sau8_result : std_logic_vector(C_WORD_SIZE-1 downto 0); 64 | signal s_next_sau8_result_ready : std_logic; 65 | begin 66 | -- Select SAU width. 67 | s_sau32_enable <= i_enable when i_packed_mode = C_PACKED_NONE else '0'; 68 | s_sau16_enable <= i_enable when i_packed_mode = C_PACKED_HALF_WORD else '0'; 69 | s_sau8_enable <= i_enable when i_packed_mode = C_PACKED_BYTE else '0'; 70 | 71 | -- 32-bit pipeline. 72 | SAU32_0: entity work.sau_impl 73 | generic map ( 74 | WIDTH => 32 75 | ) 76 | port map ( 77 | i_clk => i_clk, 78 | i_rst => i_rst, 79 | i_stall => i_stall, 80 | i_enable => s_sau32_enable, 81 | i_op => i_op, 82 | i_src_a => i_src_a, 83 | i_src_b => i_src_b, 84 | o_next_result => s_next_sau32_result, 85 | o_next_result_ready => s_next_sau32_result_ready 86 | ); 87 | 88 | PACKED_GEN: if CONFIG.HAS_PO generate 89 | -- 16-bit pipelines. 90 | SAU16Gen: for k in 1 to 2 generate 91 | signal s_next_result_ready : std_logic_vector(1 to 2); 92 | begin 93 | SAU16_1: entity work.sau_impl 94 | generic map ( 95 | WIDTH => 16 96 | ) 97 | port map ( 98 | i_clk => i_clk, 99 | i_rst => i_rst, 100 | i_stall => i_stall, 101 | i_enable => s_sau16_enable, 102 | i_op => i_op, 103 | i_src_a => i_src_a((16*k)-1 downto 16*(k-1)), 104 | i_src_b => i_src_b((16*k)-1 downto 16*(k-1)), 105 | o_next_result => s_next_sau16_result((16*k)-1 downto 16*(k-1)), 106 | o_next_result_ready => s_next_result_ready(k) 107 | ); 108 | 109 | -- Note: For some signals we only have to consider one of the parallel pipelines. 110 | SAU16ExtractSignals: if k=1 generate 111 | s_next_sau16_result_ready <= s_next_result_ready(1); 112 | end generate; 113 | end generate; 114 | 115 | -- 8-bit pipelines. 116 | SAU8Gen: for k in 1 to 4 generate 117 | signal s_next_result_ready : std_logic_vector(1 to 4); 118 | begin 119 | SAU8_x: entity work.sau_impl 120 | generic map ( 121 | WIDTH => 8 122 | ) 123 | port map ( 124 | i_clk => i_clk, 125 | i_rst => i_rst, 126 | i_stall => i_stall, 127 | i_enable => s_sau8_enable, 128 | i_op => i_op, 129 | i_src_a => i_src_a((8*k)-1 downto 8*(k-1)), 130 | i_src_b => i_src_b((8*k)-1 downto 8*(k-1)), 131 | o_next_result => s_next_sau8_result((8*k)-1 downto 8*(k-1)), 132 | o_next_result_ready => s_next_result_ready(k) 133 | ); 134 | 135 | -- Note: For some signals we only have to consider one of the parallel pipelines. 136 | SAU8ExtractSignals: if k=1 generate 137 | s_next_sau8_result_ready <= s_next_result_ready(1); 138 | end generate; 139 | end generate; 140 | 141 | -- Select the output signals from the first pipeline stage. 142 | o_next_result <= 143 | s_next_sau32_result when s_next_sau32_result_ready = '1' else 144 | s_next_sau16_result when s_next_sau16_result_ready = '1' else 145 | s_next_sau8_result when s_next_sau8_result_ready = '1' else 146 | (others => '-'); 147 | o_next_result_ready <= s_next_sau32_result_ready or 148 | s_next_sau16_result_ready or 149 | s_next_sau8_result_ready; 150 | else generate 151 | -- In unpacked mode we only have to consider the 32-bit result. 152 | o_next_result <= s_next_sau32_result; 153 | o_next_result_ready <= s_next_sau32_result_ready; 154 | end generate; 155 | end rtl; 156 | --------------------------------------------------------------------------------