├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── sim ├── memio_test1.vec ├── memio_test2.vec ├── memio_test3.vec ├── regout_test1.vec ├── regout_test2.vec ├── regout_test3.vec ├── test1.vec ├── test2.vec └── test3.vec ├── src ├── alu.vhd ├── common.vhd ├── compare_unit.vhd ├── csr.vhd ├── csr_pkg.vhd ├── dpram.vhd ├── encode_pkg.vhd ├── ex.vhd ├── ex_pkg.vhd ├── id.vhd ├── id_pkg.vhd ├── if.vhd ├── if_pkg.vhd ├── pipeline.vhd ├── regfile.vhd ├── sim-pipeline.bat └── std_logic_textio.vhd ├── tests ├── compare_tb.vhd ├── decoder_tb.vhd ├── generate_ramfile.vhd ├── pipeline_tb.vhd ├── sim-compare.bat ├── sim-decode.bat ├── test_config1.vhd ├── test_config2.vhd └── test_config3.vhd └── verify_test_vecs /.gitignore: -------------------------------------------------------------------------------- 1 | # Emacs remnants 2 | *~ 3 | #*# 4 | *.vcd 5 | *.cf 6 | *.o 7 | *_tb 8 | sim/memio.vec 9 | sim/regout.vec 10 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, inforichland 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, this 8 | list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright notice, 11 | this list of conditions and the following disclaimer in the documentation 12 | and/or other materials provided with the distribution. 13 | 14 | * Neither the name of freezing-spice nor the names of its 15 | contributors may be used to endorse or promote products derived from 16 | this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 | DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 22 | FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 24 | SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 25 | CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26 | OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | GHDL=ghdl 2 | GHDLFLAGS= 3 | GHDLRUNFLAGS= 4 | 5 | # Correct order is crucial to avoid ghdl error 6 | SRC_PATH = src/ 7 | SRC = $(addprefix $(SRC_PATH), csr_pkg.vhd std_logic_textio.vhd common.vhd id_pkg.vhd encode_pkg.vhd alu.vhd compare_unit.vhd ex_pkg.vhd ex.vhd id.vhd if_pkg.vhd if.vhd regfile.vhd csr.vhd pipeline.vhd dpram.vhd) 8 | 9 | # 10 | PIPELINE_TB=tests/pipeline_tb.vhd 11 | 12 | #Name of each (non-pipeline) test 13 | TESTS_PATH = tests 14 | TESTS = decoder_tb compare_tb 15 | 16 | # Pipeline testbench vectors 17 | PIPELINE_TB_TEST_NUMBERS=1 2 3 18 | TEST_VECTORS=$(addprefix $(TESTS_PATH)/test_config, $(PIPELINE_TB_TEST_NUMBERS)) 19 | 20 | SIM_PATH=sim/ 21 | SIM_OUTPUTS=$(addprefix $(SIM_PATH), memio.vec regout.vec) 22 | 23 | # Default target 24 | .PHONY: all 25 | all: input_vectors $(TESTS) pipeline_tb 26 | 27 | .PHONY: tests 28 | tests: $(TESTS) pipeline_tb 29 | 30 | # Analyse, Elaborate and Run 31 | $(TESTS): 32 | $(GHDL) -a $(GHDLFLAGS) $(SRC) $(TESTS_PATH)/$@.vhd 33 | $(GHDL) -e $(GHDLFLAGS) $@ 34 | $(GHDL) -r $(GHDLRUNFLAGS) $@ --vcd=$@.vcd #--wave=$@.ghw 35 | .PHONY: $(TESTS) 36 | 37 | # pipeline_tb 38 | pipeline_tb: input_vectors test1 test2 test3 39 | .PHONY: pipeline_tb 40 | 41 | # test case 1 42 | test1: sim/test1.vec tests/test_config1.vhd input_vectors 43 | $(GHDL) -a $(GHDLFLAGS) $(SRC) $(TESTS_PATH)/test_config1.vhd $(PIPELINE_TB) 44 | $(GHDL) -e $(GHDLFLAGS) pipeline_tb 45 | $(GHDL) -r $(GHDLRUNFLAGS) pipeline_tb --vcd=pipeline_tb_test1.vcd 46 | ./verify_test_vecs test1 47 | .PHONY: test1 48 | 49 | # test case 2 50 | test2: sim/test2.vec tests/test_config2.vhd input_vectors 51 | $(GHDL) -a $(GHDLFLAGS) $(SRC) $(TESTS_PATH)/test_config2.vhd $(PIPELINE_TB) 52 | $(GHDL) -e $(GHDLFLAGS) pipeline_tb 53 | $(GHDL) -r $(GHDLRUNFLAGS) pipeline_tb --vcd=pipeline_tb_test2.vcd 54 | ./verify_test_vecs test2 55 | .PHONY: test2 56 | 57 | # test case 3 58 | test3: sim/test3.vec tests/test_config3.vhd input_vectors 59 | $(GHDL) -a $(GHDLFLAGS) $(SRC) $(TESTS_PATH)/test_config3.vhd $(PIPELINE_TB) 60 | $(GHDL) -e $(GHDLFLAGS) pipeline_tb 61 | $(GHDL) -r $(GHDLRUNFLAGS) pipeline_tb --vcd=pipeline_tb_test3.vcd 62 | ./verify_test_vecs test3 63 | .PHONY: test3 64 | 65 | # generation of test vectors 66 | .PHONY: $(TEST_VECTORS) 67 | $(TEST_VECTORS): 68 | $(GHDL) -a $(GHDLFLAGS) src/csr_pkg.vhd src/common.vhd src/id_pkg.vhd src/encode_pkg.vhd $@.vhd tests/generate_ramfile.vhd 69 | $(GHDL) -e $(GHDLFLAGS) generate_ramfile 70 | $(GHDL) -r $(GHDLRUNFLAGS) generate_ramfile 71 | .PHONY: input_vectors 72 | input_vectors: $(TEST_VECTORS) 73 | 74 | .PHONY: clean 75 | clean: 76 | $(GHDL) --clean 77 | rm *.cf *.vcd 78 | rm $(SIM_OUTPUTS) 79 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | README 2 | ====== 3 | 4 | Freezing Spice 5 | -------------- 6 | A pipelined 32-bit RISC-V implementation, written in VHDL. It is targeted for FPGA synthesis. 7 | 8 | Microarchitecture 9 | ----------------- 10 | + 5-stage pipeline ("classic MIPS") 11 | + Fetch 12 | + Decode 13 | + Execute 14 | + Memory access 15 | + Register file writeback 16 | + In-order, single-issue (see TODOs) 17 | + 2-cycle branch penalty for correctly predicted branches, 3 otherwise (hoping to improve these soon) 18 | + Most structural hazards that could be overcome w/ muxing are implemented as such ("bypassing" or "forwarding") 19 | 20 | Status 21 | ------ 22 | While not yet finished, a large part of the RV32-I instruction set is implemented. Note that I am not a professional CPU architect :) 23 | 24 | Implementation 25 | -------------- 26 | + VHDL - RTL 27 | + Simulation - GHDL / GtkWave 28 | + Synthesis - Xilinx ISE 14.7 - Spartan 6 (*TODO*) 29 | 30 | TODO 31 | ---- 32 | + Better tests! 33 | + Interrupts / Exceptions 34 | + More sophisticated Branch prediction 35 | + Caches 36 | + Out-of-order (maybe?) 37 | + Multiple-issue (maybe?) 38 | + Probably more... 39 | -------------------------------------------------------------------------------- /sim/memio_test1.vec: -------------------------------------------------------------------------------- 1 | W 00000008, 80001038 2 | R 00000008, 80001038 3 | -------------------------------------------------------------------------------- /sim/memio_test2.vec: -------------------------------------------------------------------------------- 1 | W 00000008, 80001038 2 | R 00000008, 80001038 3 | -------------------------------------------------------------------------------- /sim/memio_test3.vec: -------------------------------------------------------------------------------- 1 | R 00000000, 80008081 2 | W 00000010, FFFFFF81 3 | R 00000010, FFFFFF81 4 | -------------------------------------------------------------------------------- /sim/regout_test1.vec: -------------------------------------------------------------------------------- 1 | 01, 00000004 2 | 02, 00000008 3 | 03, 0000000C 4 | 04, 80001000 5 | 06, 00000014 6 | 05, 8000100C 7 | 08, 80001038 8 | 09, 00001038 9 | 0A, 80002070 10 | 01, 00000001 11 | 0B, 00000020 12 | 0C, 0000001A 13 | 0D, 0000000A 14 | -------------------------------------------------------------------------------- /sim/regout_test2.vec: -------------------------------------------------------------------------------- 1 | 01, 00000004 2 | 02, 00000008 3 | 03, 0000000C 4 | 04, 80001000 5 | 06, 00000014 6 | 05, 8000100C 7 | 08, 80001038 8 | 09, 00001038 9 | 0A, 80002070 10 | 0A, 80002070 11 | 0A, 80002070 12 | 0A, 80002070 13 | -------------------------------------------------------------------------------- /sim/regout_test3.vec: -------------------------------------------------------------------------------- 1 | 01, 00000004 2 | 02, 00000004 3 | 03, 00000008 4 | 01, 00000001 5 | 01, 00000003 6 | 01, 00000007 7 | 01, 00000001 8 | 0B, 00000020 9 | 0D, 00000021 10 | 04, FFFFFF81 11 | 0C, 00000009 12 | 01, FFFFFF81 13 | 04, FFFFFF78 14 | 06, 00000001 15 | 08, FFFFFFA1 16 | -------------------------------------------------------------------------------- /sim/test1.vec: -------------------------------------------------------------------------------- 1 | 00000000010000000000000010010011 2 | 00000000000000000000000000000000 3 | 00000000000000000000000000000000 4 | 00000000000000000000000000000000 5 | 00000000100000000000000100010011 6 | 00000000000000000000000000000000 7 | 00000000000000000000000000000000 8 | 00000000000000000000000000000000 9 | 00000000001000001000000110110011 10 | 00000000000000000000000000000000 11 | 00000000000000000000000000000000 12 | 00000000000000000000000000000000 13 | 10000000000000000001001000110111 14 | 00000000000000000000000000000000 15 | 00000000000000000000000000000000 16 | 00000000000000000000000000000000 17 | 00000010010000000000001101101111 18 | 00000000000000000000000000000000 19 | 00000000000000000000000000000000 20 | 00000000000000000000000000000000 21 | 00000000000100000000000010010011 22 | 00000000000000000000000000000000 23 | 00000000000000000000000000000000 24 | 00000000000000000000000000000000 25 | 00000000000100000000000010010011 26 | 00000000000000000000000000000000 27 | 00000000000000000000000000000000 28 | 00000000000000000000000000000000 29 | 00000000000100000000000010010011 30 | 00000000000000000000000000000000 31 | 00000000000000000000000000000000 32 | 00000000000000000000000000000000 33 | 00000000000100000000000010010011 34 | 00000000000000000000000000000000 35 | 00000000000000000000000000000000 36 | 00000000000000000000000000000000 37 | 00000000000100000000000010010011 38 | 00000000000000000000000000000000 39 | 00000000000000000000000000000000 40 | 00000000000000000000000000000000 41 | 00000000000000000000000000010011 42 | 00000000000000000000000000000000 43 | 00000000000000000000000000000000 44 | 00000000000000000000000000000000 45 | 00000000000000000000000000010011 46 | 00000000000000000000000000000000 47 | 00000000000000000000000000000000 48 | 00000000000000000000000000000000 49 | 00000000000000000000000000010011 50 | 00000000000000000000000000000000 51 | 00000000000000000000000000000000 52 | 00000000000000000000000000000000 53 | 00000000010000011000001010110011 54 | 00000000000000000000000000000000 55 | 00000000000000000000000000000000 56 | 00000000000000000000000000000000 57 | 10000000000000000001010000010111 58 | 00000000000000000000000000000000 59 | 00000000000000000000000000000000 60 | 00000000000000000000000000000000 61 | 00000000100000001010001000100011 62 | 00000000000000000000000000000000 63 | 00000000000000000000000000000000 64 | 00000000000000000000000000000000 65 | 00000000100000000001010010000011 66 | 00000000000000000000000000000000 67 | 00000000000000000000000000000000 68 | 00000000000000000000000000000000 69 | 00000000100101000000010100110011 70 | 00000000000000000000000000000000 71 | 00000000000000000000000000000000 72 | 00000000000000000000000000000000 73 | 00000000100001001001100001100011 74 | 00000000000000000000000000000000 75 | 00000000000000000000000000000000 76 | 00000000000000000000000000000000 77 | 00000000000100000000000010010011 78 | 00000000000000000000000000000000 79 | 00000000000000000000000000000000 80 | 00000000000000000000000000000000 81 | 00000000001100000000000010010011 82 | 00000000000000000000000000000000 83 | 00000000000000000000000000000000 84 | 00000000000000000000000000000000 85 | 00000000011100000000000010010011 86 | 00000000000000000000000000000000 87 | 00000000000000000000000000000000 88 | 00000000000000000000000000000000 89 | 00000000000100000000000010010011 90 | 00000000000000000000000000000000 91 | 00000000000000000000000000000000 92 | 00000000000000000000000000000000 93 | 00000001111100001000010110010011 94 | 00000000000000000000000000000000 95 | 00000000000000000000000000000000 96 | 00000000000000000000000000000000 97 | 11000000000000000010011001110011 98 | 00000000000000000000000000000000 99 | 00000000000000000000000000000000 100 | 00000000000000000000000000000000 101 | 11000000001000000010011011110011 102 | 00000000000000000000000000000000 103 | 00000000000000000000000000000000 104 | 00000000000000000000000000000000 105 | 00000000000000000000000000000000 106 | 00000000000000000000000000000000 107 | 00000000000000000000000000000000 108 | 00000000000000000000000000000000 109 | 00000000000000000000000000000000 110 | 00000000000000000000000000000000 111 | 00000000000000000000000000000000 112 | 00000000000000000000000000000000 113 | 00000000000000000000000000000000 114 | 00000000000000000000000000000000 115 | 00000000000000000000000000000000 116 | 00000000000000000000000000000000 117 | 00000000000000000000000000000000 118 | 00000000000000000000000000000000 119 | 00000000000000000000000000000000 120 | 00000000000000000000000000000000 121 | 00000000000000000000000000000000 122 | 00000000000000000000000000000000 123 | 00000000000000000000000000000000 124 | 00000000000000000000000000000000 125 | 00000000000000000000000000000000 126 | 00000000000000000000000000000000 127 | 00000000000000000000000000000000 128 | 00000000000000000000000000000000 129 | 00000000000000000000000000000000 130 | 00000000000000000000000000000000 131 | 00000000000000000000000000000000 132 | 00000000000000000000000000000000 133 | 00000000000000000000000000000000 134 | 00000000000000000000000000000000 135 | 00000000000000000000000000000000 136 | 00000000000000000000000000000000 137 | 00000000000000000000000000000000 138 | 00000000000000000000000000000000 139 | 00000000000000000000000000000000 140 | 00000000000000000000000000000000 141 | 00000000000000000000000000000000 142 | 00000000000000000000000000000000 143 | 00000000000000000000000000000000 144 | 00000000000000000000000000000000 145 | 00000000000000000000000000000000 146 | 00000000000000000000000000000000 147 | 00000000000000000000000000000000 148 | 00000000000000000000000000000000 149 | 00000000000000000000000000000000 150 | 00000000000000000000000000000000 151 | 00000000000000000000000000000000 152 | 00000000000000000000000000000000 153 | 00000000000000000000000000000000 154 | 00000000000000000000000000000000 155 | 00000000000000000000000000000000 156 | 00000000000000000000000000000000 157 | 00000000000000000000000000000000 158 | 00000000000000000000000000000000 159 | 00000000000000000000000000000000 160 | 00000000000000000000000000000000 161 | 00000000000000000000000000000000 162 | 00000000000000000000000000000000 163 | 00000000000000000000000000000000 164 | 00000000000000000000000000000000 165 | 00000000000000000000000000000000 166 | 00000000000000000000000000000000 167 | 00000000000000000000000000000000 168 | 00000000000000000000000000000000 169 | 00000000000000000000000000000000 170 | 00000000000000000000000000000000 171 | 00000000000000000000000000000000 172 | 00000000000000000000000000000000 173 | 00000000000000000000000000000000 174 | 00000000000000000000000000000000 175 | 00000000000000000000000000000000 176 | 00000000000000000000000000000000 177 | 00000000000000000000000000000000 178 | 00000000000000000000000000000000 179 | 00000000000000000000000000000000 180 | 00000000000000000000000000000000 181 | 00000000000000000000000000000000 182 | 00000000000000000000000000000000 183 | 00000000000000000000000000000000 184 | 00000000000000000000000000000000 185 | 00000000000000000000000000000000 186 | 00000000000000000000000000000000 187 | 00000000000000000000000000000000 188 | 00000000000000000000000000000000 189 | 00000000000000000000000000000000 190 | 00000000000000000000000000000000 191 | 00000000000000000000000000000000 192 | 00000000000000000000000000000000 193 | 00000000000000000000000000000000 194 | 00000000000000000000000000000000 195 | 00000000000000000000000000000000 196 | 00000000000000000000000000000000 197 | 00000000000000000000000000000000 198 | 00000000000000000000000000000000 199 | 00000000000000000000000000000000 200 | 00000000000000000000000000000000 201 | 00000000000000000000000000000000 202 | 00000000000000000000000000000000 203 | 00000000000000000000000000000000 204 | 00000000000000000000000000000000 205 | 00000000000000000000000000000000 206 | 00000000000000000000000000000000 207 | 00000000000000000000000000000000 208 | 00000000000000000000000000000000 209 | 00000000000000000000000000000000 210 | 00000000000000000000000000000000 211 | 00000000000000000000000000000000 212 | 00000000000000000000000000000000 213 | 00000000000000000000000000000000 214 | 00000000000000000000000000000000 215 | 00000000000000000000000000000000 216 | 00000000000000000000000000000000 217 | 00000000000000000000000000000000 218 | 00000000000000000000000000000000 219 | 00000000000000000000000000000000 220 | 00000000000000000000000000000000 221 | 00000000000000000000000000000000 222 | 00000000000000000000000000000000 223 | 00000000000000000000000000000000 224 | 00000000000000000000000000000000 225 | 00000000000000000000000000000000 226 | 00000000000000000000000000000000 227 | 00000000000000000000000000000000 228 | 00000000000000000000000000000000 229 | 00000000000000000000000000000000 230 | 00000000000000000000000000000000 231 | 00000000000000000000000000000000 232 | 00000000000000000000000000000000 233 | 00000000000000000000000000000000 234 | 00000000000000000000000000000000 235 | 00000000000000000000000000000000 236 | 00000000000000000000000000000000 237 | 00000000000000000000000000000000 238 | 00000000000000000000000000000000 239 | 00000000000000000000000000000000 240 | 00000000000000000000000000000000 241 | 00000000000000000000000000000000 242 | 00000000000000000000000000000000 243 | 00000000000000000000000000000000 244 | 00000000000000000000000000000000 245 | 00000000000000000000000000000000 246 | 00000000000000000000000000000000 247 | 00000000000000000000000000000000 248 | 00000000000000000000000000000000 249 | 00000000000000000000000000000000 250 | 00000000000000000000000000000000 251 | 00000000000000000000000000000000 252 | 00000000000000000000000000000000 253 | 00000000000000000000000000000000 254 | 00000000000000000000000000000000 255 | 00000000000000000000000000000000 256 | 00000000000000000000000000000000 257 | 00000000000000000000000000000000 258 | -------------------------------------------------------------------------------- /sim/test2.vec: -------------------------------------------------------------------------------- 1 | 00000000010000000000000010010011 2 | 00000000000000000000000000000000 3 | 00000000000000000000000000000000 4 | 00000000000000000000000000000000 5 | 00000000100000000000000100010011 6 | 00000000000000000000000000000000 7 | 00000000000000000000000000000000 8 | 00000000000000000000000000000000 9 | 00000000001000001000000110110011 10 | 00000000000000000000000000000000 11 | 00000000000000000000000000000000 12 | 00000000000000000000000000000000 13 | 10000000000000000001001000110111 14 | 00000000000000000000000000000000 15 | 00000000000000000000000000000000 16 | 00000000000000000000000000000000 17 | 00000010010000000000001101101111 18 | 00000000000000000000000000000000 19 | 00000000000000000000000000000000 20 | 00000000000000000000000000000000 21 | 00000000000100000000000010010011 22 | 00000000000000000000000000000000 23 | 00000000000000000000000000000000 24 | 00000000000000000000000000000000 25 | 00000000000100000000000010010011 26 | 00000000000000000000000000000000 27 | 00000000000000000000000000000000 28 | 00000000000000000000000000000000 29 | 00000000000100000000000010010011 30 | 00000000000000000000000000000000 31 | 00000000000000000000000000000000 32 | 00000000000000000000000000000000 33 | 00000000000100000000000010010011 34 | 00000000000000000000000000000000 35 | 00000000000000000000000000000000 36 | 00000000000000000000000000000000 37 | 00000000000100000000000010010011 38 | 00000000000000000000000000000000 39 | 00000000000000000000000000000000 40 | 00000000000000000000000000000000 41 | 00000000000000000000000000010011 42 | 00000000000000000000000000000000 43 | 00000000000000000000000000000000 44 | 00000000000000000000000000000000 45 | 00000000000000000000000000010011 46 | 00000000000000000000000000000000 47 | 00000000000000000000000000000000 48 | 00000000000000000000000000000000 49 | 00000000000000000000000000010011 50 | 00000000000000000000000000000000 51 | 00000000000000000000000000000000 52 | 00000000000000000000000000000000 53 | 00000000010000011000001010110011 54 | 00000000000000000000000000000000 55 | 00000000000000000000000000000000 56 | 00000000000000000000000000000000 57 | 10000000000000000001010000010111 58 | 00000000000000000000000000000000 59 | 00000000000000000000000000000000 60 | 00000000000000000000000000000000 61 | 00000000100000001010001000100011 62 | 00000000000000000000000000000000 63 | 00000000000000000000000000000000 64 | 00000000000000000000000000000000 65 | 00000000100000000001010010000011 66 | 00000000000000000000000000000000 67 | 00000000000000000000000000000000 68 | 00000000000000000000000000000000 69 | 00000000100101000000010100110011 70 | 00000000000000000000000000000000 71 | 00000000000000000000000000000000 72 | 00000000000000000000000000000000 73 | 11111110100001001001111011100011 74 | 00000000000000000000000000000000 75 | 00000000000000000000000000000000 76 | 00000000000000000000000000000000 77 | 00000000000100000000000010010011 78 | 00000000000000000000000000000000 79 | 00000000000000000000000000000000 80 | 00000000000000000000000000000000 81 | 00000000001100000000000010010011 82 | 00000000000000000000000000000000 83 | 00000000000000000000000000000000 84 | 00000000000000000000000000000000 85 | 00000000011100000000000010010011 86 | 00000000000000000000000000000000 87 | 00000000000000000000000000000000 88 | 00000000000000000000000000000000 89 | 00000000000100000000000010010011 90 | 00000000000000000000000000000000 91 | 00000000000000000000000000000000 92 | 00000000000000000000000000000000 93 | 00000001111100001000010110010011 94 | 00000000000000000000000000000000 95 | 00000000000000000000000000000000 96 | 00000000000000000000000000000000 97 | 00000000000000000000000000010011 98 | 00000000000000000000000000000000 99 | 00000000000000000000000000000000 100 | 00000000000000000000000000000000 101 | 00000000000000000000000000000000 102 | 00000000000000000000000000000000 103 | 00000000000000000000000000000000 104 | 00000000000000000000000000000000 105 | 00000000000000000000000000000000 106 | 00000000000000000000000000000000 107 | 00000000000000000000000000000000 108 | 00000000000000000000000000000000 109 | 00000000000000000000000000000000 110 | 00000000000000000000000000000000 111 | 00000000000000000000000000000000 112 | 00000000000000000000000000000000 113 | 00000000000000000000000000000000 114 | 00000000000000000000000000000000 115 | 00000000000000000000000000000000 116 | 00000000000000000000000000000000 117 | 00000000000000000000000000000000 118 | 00000000000000000000000000000000 119 | 00000000000000000000000000000000 120 | 00000000000000000000000000000000 121 | 00000000000000000000000000000000 122 | 00000000000000000000000000000000 123 | 00000000000000000000000000000000 124 | 00000000000000000000000000000000 125 | 00000000000000000000000000000000 126 | 00000000000000000000000000000000 127 | 00000000000000000000000000000000 128 | 00000000000000000000000000000000 129 | 00000000000000000000000000000000 130 | 00000000000000000000000000000000 131 | 00000000000000000000000000000000 132 | 00000000000000000000000000000000 133 | 00000000000000000000000000000000 134 | 00000000000000000000000000000000 135 | 00000000000000000000000000000000 136 | 00000000000000000000000000000000 137 | 00000000000000000000000000000000 138 | 00000000000000000000000000000000 139 | 00000000000000000000000000000000 140 | 00000000000000000000000000000000 141 | 00000000000000000000000000000000 142 | 00000000000000000000000000000000 143 | 00000000000000000000000000000000 144 | 00000000000000000000000000000000 145 | 00000000000000000000000000000000 146 | 00000000000000000000000000000000 147 | 00000000000000000000000000000000 148 | 00000000000000000000000000000000 149 | 00000000000000000000000000000000 150 | 00000000000000000000000000000000 151 | 00000000000000000000000000000000 152 | 00000000000000000000000000000000 153 | 00000000000000000000000000000000 154 | 00000000000000000000000000000000 155 | 00000000000000000000000000000000 156 | 00000000000000000000000000000000 157 | 00000000000000000000000000000000 158 | 00000000000000000000000000000000 159 | 00000000000000000000000000000000 160 | 00000000000000000000000000000000 161 | 00000000000000000000000000000000 162 | 00000000000000000000000000000000 163 | 00000000000000000000000000000000 164 | 00000000000000000000000000000000 165 | 00000000000000000000000000000000 166 | 00000000000000000000000000000000 167 | 00000000000000000000000000000000 168 | 00000000000000000000000000000000 169 | 00000000000000000000000000000000 170 | 00000000000000000000000000000000 171 | 00000000000000000000000000000000 172 | 00000000000000000000000000000000 173 | 00000000000000000000000000000000 174 | 00000000000000000000000000000000 175 | 00000000000000000000000000000000 176 | 00000000000000000000000000000000 177 | 00000000000000000000000000000000 178 | 00000000000000000000000000000000 179 | 00000000000000000000000000000000 180 | 00000000000000000000000000000000 181 | 00000000000000000000000000000000 182 | 00000000000000000000000000000000 183 | 00000000000000000000000000000000 184 | 00000000000000000000000000000000 185 | 00000000000000000000000000000000 186 | 00000000000000000000000000000000 187 | 00000000000000000000000000000000 188 | 00000000000000000000000000000000 189 | 00000000000000000000000000000000 190 | 00000000000000000000000000000000 191 | 00000000000000000000000000000000 192 | 00000000000000000000000000000000 193 | 00000000000000000000000000000000 194 | 00000000000000000000000000000000 195 | 00000000000000000000000000000000 196 | 00000000000000000000000000000000 197 | 00000000000000000000000000000000 198 | 00000000000000000000000000000000 199 | 00000000000000000000000000000000 200 | 00000000000000000000000000000000 201 | 00000000000000000000000000000000 202 | 00000000000000000000000000000000 203 | 00000000000000000000000000000000 204 | 00000000000000000000000000000000 205 | 00000000000000000000000000000000 206 | 00000000000000000000000000000000 207 | 00000000000000000000000000000000 208 | 00000000000000000000000000000000 209 | 00000000000000000000000000000000 210 | 00000000000000000000000000000000 211 | 00000000000000000000000000000000 212 | 00000000000000000000000000000000 213 | 00000000000000000000000000000000 214 | 00000000000000000000000000000000 215 | 00000000000000000000000000000000 216 | 00000000000000000000000000000000 217 | 00000000000000000000000000000000 218 | 00000000000000000000000000000000 219 | 00000000000000000000000000000000 220 | 00000000000000000000000000000000 221 | 00000000000000000000000000000000 222 | 00000000000000000000000000000000 223 | 00000000000000000000000000000000 224 | 00000000000000000000000000000000 225 | 00000000000000000000000000000000 226 | 00000000000000000000000000000000 227 | 00000000000000000000000000000000 228 | 00000000000000000000000000000000 229 | 00000000000000000000000000000000 230 | 00000000000000000000000000000000 231 | 00000000000000000000000000000000 232 | 00000000000000000000000000000000 233 | 00000000000000000000000000000000 234 | 00000000000000000000000000000000 235 | 00000000000000000000000000000000 236 | 00000000000000000000000000000000 237 | 00000000000000000000000000000000 238 | 00000000000000000000000000000000 239 | 00000000000000000000000000000000 240 | 00000000000000000000000000000000 241 | 00000000000000000000000000000000 242 | 00000000000000000000000000000000 243 | 00000000000000000000000000000000 244 | 00000000000000000000000000000000 245 | 00000000000000000000000000000000 246 | 00000000000000000000000000000000 247 | 00000000000000000000000000000000 248 | 00000000000000000000000000000000 249 | 00000000000000000000000000000000 250 | 00000000000000000000000000000000 251 | 00000000000000000000000000000000 252 | 00000000000000000000000000000000 253 | 00000000000000000000000000000000 254 | 00000000000000000000000000000000 255 | 00000000000000000000000000000000 256 | 00000000000000000000000000000000 257 | 00000000000000000000000000000000 258 | -------------------------------------------------------------------------------- /sim/test3.vec: -------------------------------------------------------------------------------- 1 | 00000000100000000000000000010011 2 | 00000000000000000000000000010011 3 | 00000000000000000000000000010011 4 | 00000000000000000000000000010011 5 | 00000000010000000000000010010011 6 | 00000000000000000000000000010011 7 | 00000000000000000000000000010011 8 | 00000000000000000000000000010011 9 | 00000000000100000000000100110011 10 | 00000000000000000000000000010011 11 | 00000000000000000000000000010011 12 | 00000000000000000000000000010011 13 | 00000000001000001000000110110011 14 | 00000000000000000000000000010011 15 | 00000000000000000000000000010011 16 | 00000000000000000000000000010011 17 | 11111110001000001000100011100011 18 | 00000000000000000000000000010011 19 | 00000000000000000000000000010011 20 | 00000000000000000000000000010011 21 | 00000000000100000000000010010011 22 | 00000000000000000000000000010011 23 | 00000000000000000000000000010011 24 | 00000000000000000000000000010011 25 | 00000000001100000000000010010011 26 | 00000000000000000000000000010011 27 | 00000000000000000000000000010011 28 | 00000000000000000000000000010011 29 | 00000000011100000000000010010011 30 | 00000000000000000000000000010011 31 | 00000000000000000000000000010011 32 | 00000000000000000000000000010011 33 | 00000000000100000000000010010011 34 | 00000000000000000000000000010011 35 | 00000000000000000000000000010011 36 | 00000000000000000000000000010011 37 | 00000001111100001000010110010011 38 | 00000000000000000000000000010011 39 | 00000000000000000000000000010011 40 | 00000000000000000000000000010011 41 | 00000000101100001000011010110011 42 | 00000000000000000000000000010011 43 | 00000000000000000000000000010011 44 | 00000000000000000000000000010011 45 | 11111101111101101000001000000011 46 | 00000000000000000000000000010011 47 | 00000000000000000000000000010011 48 | 00000000000000000000000000010011 49 | 00000000010000010010011000100011 50 | 00000000000000000000000000010011 51 | 00000000000000000000000000010011 52 | 00000000000000000000000000010011 53 | 11000000001000000010011001110011 54 | 00000000000000000000000000010011 55 | 00000000000000000000000000010011 56 | 00000000000000000000000000010011 57 | 00000000110000010010000010000011 58 | 00000000000000000000000000010011 59 | 00000000000000000000000000010011 60 | 00000000000000000000000000010011 61 | 01000000110000001000001000110011 62 | 00000000000000000000000000010011 63 | 00000000000000000000000000010011 64 | 00000000000000000000000000010011 65 | 00000000110100001111001100110011 66 | 00000000000000000000000000010011 67 | 00000000000000000000000000010011 68 | 00000000000000000000000000010011 69 | 00000000110100001110010000110011 70 | 00000000000000000000000000010011 71 | 00000000000000000000000000010011 72 | 00000000000000000000000000010011 73 | 00000000000000000000000000010011 74 | 00000000000000000000000000010011 75 | 00000000000000000000000000010011 76 | 00000000000000000000000000010011 77 | 00000000000000000000000000010011 78 | 00000000000000000000000000010011 79 | 00000000000000000000000000010011 80 | 00000000000000000000000000010011 81 | 00000000000000000000000000010011 82 | 00000000000000000000000000010011 83 | 00000000000000000000000000010011 84 | 00000000000000000000000000010011 85 | 00000000000000000000000000010011 86 | 00000000000000000000000000010011 87 | 00000000000000000000000000010011 88 | 00000000000000000000000000010011 89 | 00000000000000000000000000010011 90 | 00000000000000000000000000010011 91 | 00000000000000000000000000010011 92 | 00000000000000000000000000010011 93 | 00000000000000000000000000010011 94 | 00000000000000000000000000010011 95 | 00000000000000000000000000010011 96 | 00000000000000000000000000010011 97 | 00000000000000000000000000010011 98 | 00000000000000000000000000010011 99 | 00000000000000000000000000010011 100 | 00000000000000000000000000010011 101 | 00000000000000000000000000010011 102 | 00000000000000000000000000010011 103 | 00000000000000000000000000010011 104 | 00000000000000000000000000010011 105 | 00000000000000000000000000010011 106 | 00000000000000000000000000010011 107 | 00000000000000000000000000010011 108 | 00000000000000000000000000010011 109 | 00000000000000000000000000010011 110 | 00000000000000000000000000010011 111 | 00000000000000000000000000010011 112 | 00000000000000000000000000010011 113 | 00000000000000000000000000010011 114 | 00000000000000000000000000010011 115 | 00000000000000000000000000010011 116 | 00000000000000000000000000010011 117 | 00000000000000000000000000010011 118 | 00000000000000000000000000010011 119 | 00000000000000000000000000010011 120 | 00000000000000000000000000010011 121 | 00000000000000000000000000010011 122 | 00000000000000000000000000010011 123 | 00000000000000000000000000010011 124 | 00000000000000000000000000010011 125 | 00000000000000000000000000010011 126 | 00000000000000000000000000010011 127 | 00000000000000000000000000010011 128 | 00000000000000000000000000010011 129 | 00000000000000000000000000010011 130 | 00000000000000000000000000010011 131 | 00000000000000000000000000010011 132 | 00000000000000000000000000010011 133 | 00000000000000000000000000010011 134 | 00000000000000000000000000010011 135 | 00000000000000000000000000010011 136 | 00000000000000000000000000010011 137 | 00000000000000000000000000010011 138 | 00000000000000000000000000010011 139 | 00000000000000000000000000010011 140 | 00000000000000000000000000010011 141 | 00000000000000000000000000010011 142 | 00000000000000000000000000010011 143 | 00000000000000000000000000010011 144 | 00000000000000000000000000010011 145 | 00000000000000000000000000010011 146 | 00000000000000000000000000010011 147 | 00000000000000000000000000010011 148 | 00000000000000000000000000010011 149 | 00000000000000000000000000010011 150 | 00000000000000000000000000010011 151 | 00000000000000000000000000010011 152 | 00000000000000000000000000010011 153 | 00000000000000000000000000010011 154 | 00000000000000000000000000010011 155 | 00000000000000000000000000010011 156 | 00000000000000000000000000010011 157 | 00000000000000000000000000010011 158 | 00000000000000000000000000010011 159 | 00000000000000000000000000010011 160 | 00000000000000000000000000010011 161 | 00000000000000000000000000010011 162 | 00000000000000000000000000010011 163 | 00000000000000000000000000010011 164 | 00000000000000000000000000010011 165 | 00000000000000000000000000010011 166 | 00000000000000000000000000010011 167 | 00000000000000000000000000010011 168 | 00000000000000000000000000010011 169 | 00000000000000000000000000010011 170 | 00000000000000000000000000010011 171 | 00000000000000000000000000010011 172 | 00000000000000000000000000010011 173 | 00000000000000000000000000010011 174 | 00000000000000000000000000010011 175 | 00000000000000000000000000010011 176 | 00000000000000000000000000010011 177 | 00000000000000000000000000010011 178 | 00000000000000000000000000010011 179 | 00000000000000000000000000010011 180 | 00000000000000000000000000010011 181 | 00000000000000000000000000010011 182 | 00000000000000000000000000010011 183 | 00000000000000000000000000010011 184 | 00000000000000000000000000010011 185 | 00000000000000000000000000010011 186 | 00000000000000000000000000010011 187 | 00000000000000000000000000010011 188 | 00000000000000000000000000010011 189 | 00000000000000000000000000010011 190 | 00000000000000000000000000010011 191 | 00000000000000000000000000010011 192 | 00000000000000000000000000010011 193 | 00000000000000000000000000010011 194 | 00000000000000000000000000010011 195 | 00000000000000000000000000010011 196 | 00000000000000000000000000010011 197 | 00000000000000000000000000010011 198 | 00000000000000000000000000010011 199 | 00000000000000000000000000010011 200 | 00000000000000000000000000010011 201 | 00000000000000000000000000010011 202 | 00000000000000000000000000010011 203 | 00000000000000000000000000010011 204 | 00000000000000000000000000010011 205 | 00000000000000000000000000010011 206 | 00000000000000000000000000010011 207 | 00000000000000000000000000010011 208 | 00000000000000000000000000010011 209 | 00000000000000000000000000010011 210 | 00000000000000000000000000010011 211 | 00000000000000000000000000010011 212 | 00000000000000000000000000010011 213 | 00000000000000000000000000010011 214 | 00000000000000000000000000010011 215 | 00000000000000000000000000010011 216 | 00000000000000000000000000010011 217 | 00000000000000000000000000010011 218 | 00000000000000000000000000010011 219 | 00000000000000000000000000010011 220 | 00000000000000000000000000010011 221 | 00000000000000000000000000010011 222 | 00000000000000000000000000010011 223 | 00000000000000000000000000010011 224 | 00000000000000000000000000010011 225 | 00000000000000000000000000010011 226 | 00000000000000000000000000010011 227 | 00000000000000000000000000010011 228 | 00000000000000000000000000010011 229 | 00000000000000000000000000010011 230 | 00000000000000000000000000010011 231 | 00000000000000000000000000010011 232 | 00000000000000000000000000010011 233 | 00000000000000000000000000010011 234 | 00000000000000000000000000010011 235 | 00000000000000000000000000010011 236 | 00000000000000000000000000010011 237 | 00000000000000000000000000010011 238 | 00000000000000000000000000010011 239 | 00000000000000000000000000010011 240 | 00000000000000000000000000010011 241 | 00000000000000000000000000010011 242 | 00000000000000000000000000010011 243 | 00000000000000000000000000010011 244 | 00000000000000000000000000010011 245 | 00000000000000000000000000010011 246 | 00000000000000000000000000010011 247 | 00000000000000000000000000010011 248 | 00000000000000000000000000010011 249 | 00000000000000000000000000010011 250 | 00000000000000000000000000010011 251 | 00000000000000000000000000010011 252 | 00000000000000000000000000010011 253 | 00000000000000000000000000010011 254 | 00000000000000000000000000010011 255 | 00000000000000000000000000010011 256 | 00000000000000000000000000010011 257 | 00000000000000000000000000010011 258 | -------------------------------------------------------------------------------- /src/alu.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | use ieee.numeric_std.all; 4 | 5 | use work.common.all; 6 | 7 | entity alu is 8 | port (alu_func : in alu_func_t; 9 | op1 : in word; 10 | op2 : in word; 11 | result : out word); 12 | end entity alu; 13 | 14 | architecture behavioral of alu is 15 | 16 | begin -- architecture behavioral 17 | 18 | -- purpose: arithmetic and logic 19 | -- type : combinational 20 | -- inputs : alu_func, op1, op2 21 | -- outputs: result 22 | alu_proc : process (alu_func, op1, op2) is 23 | variable so1, so2 : signed(31 downto 0); 24 | variable uo1, uo2 : unsigned(31 downto 0); 25 | begin -- process alu_proc 26 | so1 := signed(op1); 27 | so2 := signed(op2); 28 | uo1 := unsigned(op1); 29 | uo2 := unsigned(op2); 30 | 31 | case (alu_func) is 32 | when ALU_ADD => result <= std_logic_vector(so1 + so2); 33 | when ALU_ADDU => result <= std_logic_vector(uo1 + uo2); 34 | when ALU_SUB => result <= std_logic_vector(so1 - so2); 35 | when ALU_SUBU => result <= std_logic_vector(uo1 - uo2); 36 | when ALU_SLT => 37 | if so1 < so2 then 38 | result <= "00000000000000000000000000000001"; 39 | else 40 | result <= (others => '0'); 41 | end if; 42 | when ALU_SLTU => 43 | if uo1 < uo2 then 44 | result <= "00000000000000000000000000000001"; 45 | else 46 | result <= (others => '0'); 47 | end if; 48 | 49 | when ALU_AND => result <= op1 and op2; 50 | when ALU_OR => result <= op1 or op2; 51 | when ALU_XOR => result <= op1 xor op2; 52 | when ALU_SLL => result <= std_logic_vector(shift_left(uo1, to_integer(uo2(4 downto 0)))); 53 | when ALU_SRA => result <= std_logic_vector(shift_right(so1, to_integer(uo2(4 downto 0)))); 54 | when ALU_SRL => result <= std_logic_vector(shift_right(uo1, to_integer(uo2(4 downto 0)))); 55 | when others => result <= op1; 56 | end case; 57 | end process alu_proc; 58 | 59 | end architecture behavioral; 60 | -------------------------------------------------------------------------------- /src/common.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | use ieee.numeric_std.all; 4 | use std.textio.all; 5 | 6 | package common is 7 | -- definition for a machine word 8 | subtype word is std_logic_vector(31 downto 0); 9 | subtype reg_addr_t is std_logic_vector(4 downto 0); 10 | 11 | subtype alu_func_t is std_logic_vector(3 downto 0); 12 | constant ALU_NONE : alu_func_t := "0000"; 13 | constant ALU_ADD : alu_func_t := "0001"; 14 | constant ALU_ADDU : alu_func_t := "0010"; 15 | constant ALU_SUB : alu_func_t := "0011"; 16 | constant ALU_SUBU : alu_func_t := "0100"; 17 | constant ALU_SLT : alu_func_t := "0101"; 18 | constant ALU_SLTU : alu_func_t := "0110"; 19 | constant ALU_AND : alu_func_t := "0111"; 20 | constant ALU_OR : alu_func_t := "1000"; 21 | constant ALU_XOR : alu_func_t := "1001"; 22 | constant ALU_SLL : alu_func_t := "1010"; 23 | constant ALU_SRA : alu_func_t := "1011"; 24 | constant ALU_SRL : alu_func_t := "1100"; 25 | 26 | subtype insn_type_t is std_logic_vector(3 downto 0); 27 | constant OP_ILLEGAL : insn_type_t := "0000"; 28 | constant OP_LUI : insn_type_t := "0001"; 29 | constant OP_AUIPC : insn_type_t := "0010"; 30 | constant OP_JAL : insn_type_t := "0011"; 31 | constant OP_JALR : insn_type_t := "0100"; 32 | constant OP_BRANCH : insn_type_t := "0101"; 33 | constant OP_LOAD : insn_type_t := "0110"; 34 | constant OP_STORE : insn_type_t := "0111"; 35 | constant OP_ALU : insn_type_t := "1000"; 36 | constant OP_STALL : insn_type_t := "1001"; 37 | constant OP_SYSTEM : insn_type_t := "1010"; 38 | 39 | subtype branch_type_t is std_logic_vector(2 downto 0); 40 | constant BRANCH_NONE : branch_type_t := "000"; 41 | constant BEQ : branch_type_t := "001"; 42 | constant BNE : branch_type_t := "010"; 43 | constant BLT : branch_type_t := "011"; 44 | constant BGE : branch_type_t := "100"; 45 | constant BLTU : branch_type_t := "101"; 46 | constant BGEU : branch_type_t := "110"; 47 | 48 | subtype load_type_t is std_logic_vector(2 downto 0); 49 | constant LOAD_NONE : load_type_t := "000"; 50 | constant LB : load_type_t := "001"; 51 | constant LH : load_type_t := "010"; 52 | constant LW : load_type_t := "011"; 53 | constant LBU : load_type_t := "100"; 54 | constant LHU : load_type_t := "101"; 55 | 56 | subtype store_type_t is std_logic_vector(1 downto 0); 57 | constant STORE_NONE : store_type_t := "00"; 58 | constant SB : store_type_t := "01"; 59 | constant SH : store_type_t := "10"; 60 | constant SW : store_type_t := "11"; 61 | 62 | subtype system_type_t is std_logic_vector(2 downto 0); 63 | constant SYSTEM_ECALL : system_type_t := "000"; 64 | constant SYSTEM_EBREAK : system_type_t := "001"; 65 | constant SYSTEM_CSRRW : system_type_t := "010"; 66 | constant SYSTEM_CSRRS : system_type_t := "011"; 67 | constant SYSTEM_CSRRC : system_type_t := "100"; 68 | constant SYSTEM_CSRRWI : system_type_t := "101"; 69 | constant SYSTEM_CSRRSI : system_type_t := "110"; 70 | constant SYSTEM_CSRRCI : system_type_t := "111"; 71 | 72 | -- print a string with a newline 73 | procedure println (str : in string); 74 | procedure print (slv : in std_logic_vector); 75 | procedure write(l : inout line; slv : in std_logic_vector); 76 | function hstr(slv : std_logic_vector) return string; 77 | 78 | -- instruction formats 79 | type r_insn_t is (R_ADD, R_SLT, R_SLTU, R_AND, R_OR, R_XOR, R_SLL, R_SRL, R_SUB, R_SRA); 80 | type i_insn_t is (I_JALR, I_LB, I_LH, I_LW, I_LBU, I_LHU, I_ADDI, I_SLTI, I_SLTIU, I_XORI, I_ORI, I_ANDI, I_SLLI, I_SRLI, I_SRAI); 81 | type s_insn_t is (S_SB, S_SH, S_SW); 82 | type sb_insn_t is (SB_BEQ, SB_BNE, SB_BLT, SB_BGE, SB_BLTU, SB_BGEU); 83 | type u_insn_t is (U_LUI, U_AUIPC); 84 | type uj_insn_t is (UJ_JAL); 85 | 86 | -- ADDI r0, r0, r0 87 | constant NOP : word := "00000000000000000000000000010011"; 88 | 89 | end package common; 90 | 91 | package body common is 92 | 93 | function hstr(slv : std_logic_vector) return string is 94 | variable hexlen : integer; 95 | variable longslv : std_logic_vector(67 downto 0) := (others => '0'); 96 | variable hex : string(1 to 16); 97 | variable fourbit : std_logic_vector(3 downto 0); 98 | begin 99 | hexlen := (slv'left+1)/4; 100 | if (slv'left+1) mod 4 /= 0 then 101 | hexlen := hexlen + 1; 102 | end if; 103 | longslv(slv'left downto 0) := slv; 104 | for i in (hexlen -1) downto 0 loop 105 | fourbit := longslv(((i*4)+3) downto (i*4)); 106 | case fourbit is 107 | when "0000" => hex(hexlen -I) := '0'; 108 | when "0001" => hex(hexlen -I) := '1'; 109 | when "0010" => hex(hexlen -I) := '2'; 110 | when "0011" => hex(hexlen -I) := '3'; 111 | when "0100" => hex(hexlen -I) := '4'; 112 | when "0101" => hex(hexlen -I) := '5'; 113 | when "0110" => hex(hexlen -I) := '6'; 114 | when "0111" => hex(hexlen -I) := '7'; 115 | when "1000" => hex(hexlen -I) := '8'; 116 | when "1001" => hex(hexlen -I) := '9'; 117 | when "1010" => hex(hexlen -I) := 'A'; 118 | when "1011" => hex(hexlen -I) := 'B'; 119 | when "1100" => hex(hexlen -I) := 'C'; 120 | when "1101" => hex(hexlen -I) := 'D'; 121 | when "1110" => hex(hexlen -I) := 'E'; 122 | when "1111" => hex(hexlen -I) := 'F'; 123 | when "ZZZZ" => hex(hexlen -I) := 'z'; 124 | when "UUUU" => hex(hexlen -I) := 'u'; 125 | when "XXXX" => hex(hexlen -I) := 'x'; 126 | when others => hex(hexlen -I) := '?'; 127 | end case; 128 | end loop; 129 | return hex(1 to hexlen); 130 | end hstr; 131 | 132 | -- print a string with a newline 133 | procedure println (str : in string) is 134 | variable l : line; 135 | begin -- procedure println 136 | write(l, str); 137 | writeline(output, l); 138 | end procedure println; 139 | 140 | procedure write(l : inout line; slv : in std_logic_vector) is 141 | begin 142 | for i in slv'range loop 143 | if slv(i) = '0' then 144 | write(l, string'("0")); 145 | elsif slv(i) = '1' then 146 | write(l, string'("1")); 147 | elsif slv(i) = 'X' then 148 | write(l, string'("X")); 149 | elsif slv(i) = 'U' then 150 | write(l, string'("U")); 151 | end if; 152 | end loop; -- i 153 | end procedure write; 154 | 155 | procedure print (slv : in std_logic_vector) is 156 | variable l : line; 157 | begin -- procedure print 158 | write(l, slv); 159 | writeline(output, l); 160 | end procedure print; 161 | 162 | end package body common; 163 | -------------------------------------------------------------------------------- /src/compare_unit.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | use ieee.numeric_std.all; 4 | 5 | use work.common.all; 6 | use work.id_pkg.all; 7 | 8 | entity compare_unit is 9 | port ( 10 | branch_type : in branch_type_t; 11 | op1 : in word; 12 | op2 : in word; 13 | compare_result : out std_logic); 14 | end entity compare_unit; 15 | 16 | architecture behavioral of compare_unit is 17 | signal compare : std_logic; 18 | begin -- architecture behavioral 19 | 20 | -- assign output 21 | compare_result <= compare; 22 | 23 | -- purpose: compares two numbers according to branch_type 24 | -- type : combinational 25 | -- inputs : branch_type, op1, op2 26 | -- outputs: compare_result 27 | compare_proc: process (branch_type, op1, op2) is 28 | variable ou1, ou2 : unsigned(31 downto 0); 29 | variable os1, os2 : signed(31 downto 0); 30 | begin -- process compare_proc 31 | ou1 := unsigned(op1); 32 | os1 := signed(op1); 33 | 34 | ou2 := unsigned(op2); 35 | os2 := signed(op2); 36 | 37 | compare <= '0'; 38 | 39 | case (branch_type) is 40 | when BEQ => 41 | if op1 = op2 then 42 | compare <= '1'; 43 | else 44 | compare <= '0'; 45 | end if; 46 | 47 | when BNE => 48 | if op1 /= op2 then 49 | compare <= '1'; 50 | else 51 | compare <= '0'; 52 | end if; 53 | 54 | when BLT => 55 | if os1 < os2 then 56 | compare <= '1'; 57 | else 58 | compare <= '0'; 59 | end if; 60 | 61 | when BGE => 62 | if os1 >= os2 then 63 | compare <= '1'; 64 | else 65 | compare <= '0'; 66 | end if; 67 | 68 | when BLTU => 69 | if ou1 < ou2 then 70 | compare <= '1'; 71 | else 72 | compare <= '0'; 73 | end if; 74 | 75 | when BGEU => 76 | if ou1 >= ou2 then 77 | compare <= '1'; 78 | else 79 | compare <= '0'; 80 | end if; 81 | 82 | when others => compare <= '0'; 83 | end case; 84 | end process compare_proc; 85 | 86 | end architecture behavioral; 87 | -------------------------------------------------------------------------------- /src/csr.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | use ieee.numeric_std.all; 4 | 5 | use work.common.all; 6 | use work.id_pkg.all; 7 | use work.csr_pkg.all; 8 | 9 | entity csr is 10 | port (clk : in std_logic; 11 | csr_in : in csr_in_t; 12 | value : out word); 13 | end entity csr; 14 | 15 | architecture behavioral of csr is 16 | signal cycler : unsigned(word'range) := (others => '0'); 17 | signal cyclerh : unsigned(word'range) := (others => '0'); 18 | signal timer : unsigned(word'range) := (others => '0'); 19 | signal timerh : unsigned(word'range) := (others => '0'); 20 | signal instretr : unsigned(word'range) := (others => '0'); 21 | signal instretrh : unsigned(word'range) := (others => '0'); 22 | 23 | constant c_word_max : unsigned(word'range) := (others => '1'); 24 | begin -- architecture behavioral 25 | 26 | -- purpose: Create the CSRs 27 | -- type : sequential 28 | -- inputs : clk 29 | -- outputs: value 30 | registers_proc : process (clk) is 31 | begin -- process registers_proc 32 | if rising_edge(clk) then 33 | -- CYCLE and CYCLEH 34 | if valid = '1' then 35 | cycler <= cycler + 1; 36 | if cycler = c_word_max then 37 | cyclerh <= cyclerh + 1; 38 | end if; 39 | end if; 40 | 41 | -- TIME and TIMEH 42 | if tick = '1' then 43 | timer <= timer + 1; 44 | if timer = c_word_max then 45 | timerh <= timerh + 1; 46 | end if; 47 | end if; 48 | 49 | -- INSTRET and INSTRETH 50 | if instret = '1' then 51 | instretr <= instretr + 1; 52 | if instretr = c_word_max then 53 | instretrh <= instretrh + 1; 54 | end if; 55 | end if; 56 | 57 | -- address decode 58 | case addr is 59 | when CSR_CYCLE => value <= std_logic_vector(cycler); 60 | when CSR_CYCLEH => value <= std_logic_vector(cyclerh); 61 | when CSR_TIME => value <= std_logic_vector(timer); 62 | when CSR_TIMEH => value <= std_logic_vector(timerh); 63 | when CSR_INSTRET => value <= std_logic_vector(instretr); 64 | when CSR_INSTRETH => value <= std_logic_vector(instretrh); 65 | when others => value <= (others => '0'); 66 | end case; 67 | 68 | end if; 69 | end process registers_proc; 70 | 71 | 72 | end architecture behavioral; 73 | -------------------------------------------------------------------------------- /src/csr_pkg.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | use ieee.numeric_std.all; 4 | 5 | use work.common.all; 6 | 7 | package csr_pkg is 8 | 9 | subtype csr_addr_t is std_logic_vector(11 downto 0); 10 | 11 | -- input record 12 | type csr_in_t is record 13 | csr_addr : csr_addr_t; 14 | rs1 : word; 15 | imm : word; 16 | system_type : system_type_t; 17 | valid : std_logic; -- '1' if this was a valid cycle that the core was executing 18 | instret : std_logic; -- '1' for instruction retired this cycle 19 | 20 | end record csr_in_t; 21 | 22 | ---------------------------------------------- 23 | -- User-mode (U) CSRs 24 | ---------------------------------------------- 25 | constant CSR_CYCLE : csr_addr_t := X"C00"; 26 | constant CSR_TIME : csr_addr_t := X"C01"; 27 | constant CSR_INSTRET : csr_addr_t := X"C02"; 28 | constant CSR_CYCLEH : csr_addr_t := X"C80"; 29 | constant CSR_TIMEH : csr_addr_t := X"C81"; 30 | constant CSR_INSTRETH : csr_addr_t := X"C82"; 31 | 32 | ---------------------------------------------- 33 | -- Machine-mode (M) CSRs 34 | ---------------------------------------------- 35 | 36 | -- Machine Information Registers 37 | constant CSR_MCPUID : csr_addr_t := X"F00"; 38 | constant CSR_MIMPID : csr_addr_t := X"F01"; 39 | constant CSR_MHARTID : csr_addr_t := X"F10"; 40 | 41 | -- Machine Trap Setup 42 | constant CSR_MSTATUS : csr_addr_t := X"300"; 43 | constant CSR_MTVEC : csr_addr_t := X"301"; 44 | constant CSR_MTDELEG : csr_addr_t := X"302"; 45 | constant CSR_MIE : csr_addr_t := X"304"; 46 | constant CSR_MTIMECMP : csr_addr_t := X"321"; 47 | 48 | -- Machine Timers and Counters 49 | constant CSR_MTIME : csr_addr_t := X"701"; 50 | constant CSR_MTIMEH : csr_addr_t := X"741"; 51 | 52 | -- Machine Trap Handling 53 | constant CSR_MSCRATCH : csr_addr_t := X"340"; 54 | constant CSR_MEPC : csr_addr_t := X"341"; 55 | constant CSR_MCAUSE : csr_addr_t := X"342"; 56 | constant CSR_MBADADDR : csr_addr_t := X"343"; 57 | constant CSR_MIP : csr_addr_t := X"344"; 58 | 59 | -- Machine Protection and Translation 60 | constant CSR_MBASE : csr_addr_t := X"380"; 61 | constant CSR_MBOUND : csr_addr_t := X"381"; 62 | constant CSR_MIBASE : csr_addr_t := X"382"; 63 | constant CSR_MIBOUND : csr_addr_t := X"383"; 64 | constant CSR_MDBASE : csr_addr_t := X"384"; 65 | constant CSR_MDBOUND : csr_addr_t := X"385"; 66 | 67 | end package csr_pkg; 68 | -------------------------------------------------------------------------------- /src/dpram.vhd: -------------------------------------------------------------------------------- 1 | -- Based on the Quartus II VHDL Template for True Dual-Port RAM with single clock 2 | -- Read-during-write on port A or B returns newly written data 3 | 4 | library ieee; 5 | use ieee.std_logic_1164.all; 6 | use ieee.numeric_std.all; 7 | --use ieee.std_logic_textio.all; 8 | use work.std_logic_textio.all; 9 | 10 | use std.textio.all; 11 | 12 | entity dpram is 13 | generic(g_data_width : natural := 16; 14 | g_addr_width : natural := 10; 15 | g_init : boolean := false; 16 | g_init_file : string := ""); 17 | port(clk : in std_logic; 18 | addr_a : in std_logic_vector(g_addr_width-1 downto 0); 19 | addr_b : in std_logic_vector(g_addr_width-1 downto 0); 20 | data_a : in std_logic_vector((g_data_width-1) downto 0); 21 | data_b : in std_logic_vector((g_data_width-1) downto 0); 22 | we_a : in std_logic := '1'; 23 | we_b : in std_logic := '1'; 24 | q_a : out std_logic_vector((g_data_width -1) downto 0); 25 | q_b : out std_logic_vector((g_data_width -1) downto 0)); 26 | end dpram; 27 | 28 | architecture rtl of dpram is 29 | 30 | -- Build a 2-D array type for the RAM 31 | subtype word_t is std_logic_vector((g_data_width-1) downto 0); 32 | type ram_t is array(0 to 2**g_addr_width-1) of word_t; 33 | 34 | -- function to initialize the RAM from a file 35 | impure function init_ram(fn : in string) return ram_t is 36 | file f : text; 37 | variable l : line; 38 | variable ram : ram_t; 39 | begin 40 | if g_init = true then 41 | file_open(f, fn, READ_MODE); 42 | for i in ram_t'range loop 43 | readline(f, l); 44 | read(l, ram(i)); 45 | end loop; 46 | file_close(f); 47 | else 48 | ram := (others => (others => '0')); 49 | end if; 50 | 51 | return ram; 52 | end function; 53 | 54 | -- Declare the RAM 55 | shared variable ram : ram_t := init_ram(g_init_file); --(others => (others => '0')); 56 | 57 | begin 58 | -- Port A 59 | process (clk) 60 | variable addr : natural range 0 to 2**g_addr_width-1; 61 | begin 62 | if (rising_edge(clk)) then 63 | addr := to_integer(unsigned(addr_a)); 64 | if (we_a = '1') then 65 | ram(addr) := data_a; 66 | end if; 67 | 68 | q_a <= ram(addr); 69 | end if; 70 | end process; 71 | 72 | -- Port B 73 | process (clk) 74 | variable addr : natural range 0 to 2**g_addr_width-1; 75 | begin 76 | if (rising_edge(clk)) then 77 | addr := to_integer(unsigned(addr_b)); 78 | if (we_b = '1') then 79 | ram(addr) := data_b; 80 | end if; 81 | 82 | q_b <= ram(addr); 83 | end if; 84 | end process; 85 | 86 | end rtl; 87 | -------------------------------------------------------------------------------- /src/encode_pkg.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | use ieee.numeric_std.all; 4 | 5 | use work.common.all; 6 | use work.id_pkg.all; 7 | use work.csr_pkg.all; 8 | 9 | package encode_pkg is 10 | 11 | subtype register_t is integer range 0 to 31; 12 | 13 | -- functions to encode the different types of instructions, organized by format 14 | function encode_r_type (insn_type : r_insn_t; 15 | rs1, rs2, rd : register_t) 16 | return word; 17 | 18 | function encode_i_type (insn_type : i_insn_t; 19 | imm : std_logic_vector(11 downto 0); 20 | rs1, rd : register_t) 21 | return word; 22 | 23 | function encode_s_type (insn_type : s_insn_t; 24 | imm : std_logic_vector(11 downto 0); 25 | rs1, rs2 : register_t) 26 | return word; 27 | 28 | function encode_sb_type (insn_type : sb_insn_t; 29 | imm : std_logic_vector(12 downto 1); 30 | rs1, rs2 : register_t) 31 | return word; 32 | 33 | function encode_u_type (insn_type : u_insn_t; 34 | imm_31_12 : std_logic_vector(31 downto 12); 35 | rd : register_t) 36 | return word; 37 | 38 | function encode_uj_type (insn_type : uj_insn_t; 39 | imm : std_logic_vector(20 downto 1); 40 | rd : register_t) 41 | return word; 42 | 43 | function encode_i_shift (i_insn : i_insn_t; 44 | shamt : std_logic_vector(4 downto 0); 45 | rs1, rd : register_t) 46 | return word; 47 | 48 | function encode_i_csr (csr_addr : csr_addr_t; 49 | rd : register_t) 50 | return word; 51 | 52 | end package encode_pkg; 53 | 54 | package body encode_pkg is 55 | 56 | -- purpose: encode a U-type instruction 57 | function encode_u_type (insn_type : u_insn_t; 58 | imm_31_12 : std_logic_vector(31 downto 12); 59 | rd : register_t) return word is 60 | variable result : word; 61 | begin -- function encode_lui 62 | result(31 downto 12) := imm_31_12; 63 | result(11 downto 7) := std_logic_vector(to_unsigned(rd, 5)); 64 | case insn_type is 65 | when U_LUI => result(6 downto 0) := c_op_lui; 66 | when U_AUIPC => result(6 downto 0) := c_op_auipc; 67 | end case; 68 | return result; 69 | end function encode_u_type; 70 | 71 | -- purpose: encode an R-type instruction 72 | function encode_r_type (insn_type : r_insn_t; 73 | rs1, rs2, rd : register_t) 74 | return word is 75 | variable result : word; 76 | begin -- function encode_r_type 77 | result(24 downto 20) := std_logic_vector(to_unsigned(rs2, 5)); 78 | result(19 downto 15) := std_logic_vector(to_unsigned(rs1, 5)); 79 | result(11 downto 7) := std_logic_vector(to_unsigned(rd, 5)); 80 | result(6 downto 0) := c_op_reg; 81 | case insn_type is 82 | when R_ADD => 83 | result(31 downto 25) := "0000000"; 84 | result(14 downto 12) := "000"; 85 | when R_SUB => 86 | result(31 downto 25) := "0100000"; 87 | result(14 downto 12) := "000"; 88 | when R_SLL => 89 | result(31 downto 25) := "0000000"; 90 | result(14 downto 12) := "001"; 91 | when R_SLT => 92 | result(31 downto 25) := "0000000"; 93 | result(14 downto 12) := "010"; 94 | when R_SLTU => 95 | result(31 downto 25) := "0000000"; 96 | result(14 downto 12) := "011"; 97 | when R_XOR => 98 | result(31 downto 25) := "0000000"; 99 | result(14 downto 12) := "100"; 100 | when R_SRL => 101 | result(31 downto 25) := "0000000"; 102 | result(14 downto 12) := "101"; 103 | when R_SRA => 104 | result(31 downto 25) := "0100000"; 105 | result(14 downto 12) := "101"; 106 | when R_OR => 107 | result(31 downto 25) := "0000000"; 108 | result(14 downto 12) := "110"; 109 | when R_AND => 110 | result(31 downto 25) := "0000000"; 111 | result(14 downto 12) := "111"; 112 | end case; 113 | return result; 114 | end function encode_r_type; 115 | 116 | -- purpose: encode a UJ-type instruction 117 | function encode_uj_type ( 118 | insn_type : uj_insn_t; 119 | imm : std_logic_vector(20 downto 1); 120 | rd : register_t) 121 | return word is 122 | variable result : word; 123 | begin -- function encode_uj_type 124 | result(31) := imm(20); 125 | result(30 downto 21) := imm(10 downto 1); 126 | result(20) := imm(11); 127 | result(19 downto 12) := imm(19 downto 12); 128 | result(11 downto 7) := std_logic_vector(to_unsigned(rd, 5)); 129 | case insn_type is 130 | when UJ_JAL => result(6 downto 0) := c_op_jal; 131 | end case; 132 | return result; 133 | end function encode_uj_type; 134 | 135 | -- purpose: encode an I-type instruction (for shifts only) 136 | function encode_i_shift ( 137 | i_insn : i_insn_t; 138 | shamt : std_logic_vector(4 downto 0); 139 | rs1, rd : register_t) 140 | return word is 141 | variable result : word; 142 | begin -- function encode_i_shift 143 | result(24 downto 20) := shamt; 144 | result(19 downto 15) := std_logic_vector(to_unsigned(rs1, 5)); 145 | result(11 downto 7) := std_logic_vector(to_unsigned(rd, 5)); 146 | result(6 downto 0) := c_op_imm; 147 | case (i_insn) is 148 | when I_SLLI => 149 | result(31 downto 25) := "0000000"; 150 | result(14 downto 12) := "001"; 151 | when I_SRLI => 152 | result(31 downto 25) := "0000000"; 153 | result(14 downto 12) := "101"; 154 | when I_SRAI => 155 | result(31 downto 25) := "0100000"; 156 | result(14 downto 12) := "101"; 157 | when others => 158 | assert false report "Not an immediate shift instruction" severity error; 159 | end case; 160 | return result; 161 | end function encode_i_shift; 162 | 163 | -- encode a CSR access instruction 164 | function encode_i_csr ( 165 | csr_addr : csr_addr_t; 166 | rd : register_t) 167 | return word is 168 | variable result : word; 169 | begin 170 | case csr_addr is 171 | when CSR_CYCLE => result(31 downto 20) := "110000000000"; 172 | when CSR_CYCLEH => result(31 downto 20) := "110010000000"; 173 | when CSR_TIME => result(31 downto 20) := "110000000001"; 174 | when CSR_TIMEH => result(31 downto 20) := "110010000001"; 175 | when CSR_INSTRET => result(31 downto 20) := "110000000010"; 176 | when CSR_INSTRETH => result(31 downto 20) := "110010000010"; 177 | when others => null; 178 | end case; 179 | result(19 downto 15) := "00000"; 180 | result(14 downto 12) := "010"; 181 | result(11 downto 7) := std_logic_vector(to_unsigned(rd, 5)); 182 | result(6 downto 0) := c_op_system; 183 | return result; 184 | end function encode_i_csr; 185 | 186 | -- purpose: encode an I-type instruction 187 | function encode_i_type (insn_type : i_insn_t; 188 | imm : std_logic_vector(11 downto 0); 189 | rs1, rd : register_t) 190 | return word is 191 | variable result : word; 192 | begin 193 | result(31 downto 20) := imm; 194 | result(19 downto 15) := std_logic_vector(to_unsigned(rs1, 5)); 195 | result(11 downto 7) := std_logic_vector(to_unsigned(rd, 5)); 196 | case insn_type is 197 | when I_JALR => 198 | result(14 downto 12) := "000"; 199 | result(6 downto 0) := c_op_jalr; 200 | when I_LB => 201 | result(14 downto 12) := "000"; 202 | result(6 downto 0) := c_op_load; 203 | when I_LH => 204 | result(14 downto 12) := "001"; 205 | result(6 downto 0) := c_op_load; 206 | when I_LW => 207 | result(14 downto 12) := "010"; 208 | result(6 downto 0) := c_op_load; 209 | when I_LBU => 210 | result(14 downto 12) := "100"; 211 | result(6 downto 0) := c_op_load; 212 | when I_LHU => 213 | result(14 downto 12) := "101"; 214 | result(6 downto 0) := c_op_load; 215 | when I_ADDI => 216 | result(14 downto 12) := "000"; 217 | result(6 downto 0) := c_op_imm; 218 | when I_SLTI => 219 | result(14 downto 12) := "010"; 220 | result(6 downto 0) := c_op_imm; 221 | when I_SLTIU => 222 | result(14 downto 12) := "011"; 223 | result(6 downto 0) := c_op_imm; 224 | when I_XORI => 225 | result(14 downto 12) := "100"; 226 | result(6 downto 0) := c_op_imm; 227 | when I_ORI => 228 | result(14 downto 12) := "110"; 229 | result(6 downto 0) := c_op_imm; 230 | when I_ANDI => 231 | result(14 downto 12) := "111"; 232 | result(6 downto 0) := c_op_imm; 233 | when others => 234 | assert false report "Use encode_i_shift" severity error; 235 | end case; 236 | return result; 237 | end function encode_i_type; 238 | 239 | -- purpose: encode an S-type instruction 240 | function encode_s_type (insn_type : s_insn_t; 241 | imm : std_logic_vector(11 downto 0); 242 | rs1, rs2 : register_t) 243 | return word is 244 | variable result : word; 245 | begin -- function encode_s_type 246 | result(31 downto 25) := imm(11 downto 5); 247 | result(24 downto 20) := std_logic_vector(to_unsigned(rs2, 5)); 248 | result(19 downto 15) := std_logic_vector(to_unsigned(rs1, 5)); 249 | result(11 downto 7) := imm(4 downto 0); 250 | result(6 downto 0) := c_op_store; 251 | case insn_type is 252 | when S_SB => result(14 downto 12) := "000"; 253 | when S_SH => result(14 downto 12) := "001"; 254 | when S_SW => result(14 downto 12) := "010"; 255 | end case; 256 | return result; 257 | end function encode_s_type; 258 | 259 | -- encode an SB-type instruction 260 | function encode_sb_type (insn_type : sb_insn_t; 261 | imm : std_logic_vector(12 downto 1); 262 | rs1, rs2 : register_t) 263 | return word is 264 | variable result : word; 265 | begin 266 | result(31) := imm(12); 267 | result(30 downto 25) := imm(10 downto 5); 268 | result(24 downto 20) := std_logic_vector(to_unsigned(rs2, 5)); 269 | result(19 downto 15) := std_logic_vector(to_unsigned(rs1, 5)); 270 | result(11 downto 8) := imm(4 downto 1); 271 | result(7) := imm(11); 272 | result(6 downto 0) := c_op_branch; 273 | case insn_type is 274 | when SB_BEQ => result(14 downto 12) := "000"; 275 | when SB_BNE => result(14 downto 12) := "001"; 276 | when SB_BLT => result(14 downto 12) := "100"; 277 | when SB_BGE => result(14 downto 12) := "101"; 278 | when SB_BLTU => result(14 downto 12) := "110"; 279 | when SB_BGEU => result(14 downto 12) := "111"; 280 | end case; 281 | return result; 282 | end function encode_sb_type; 283 | 284 | end package body encode_pkg; 285 | -------------------------------------------------------------------------------- /src/ex.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | use ieee.numeric_std.all; 4 | 5 | use work.common.all; 6 | use work.ex_pkg.all; 7 | 8 | entity instruction_executor is 9 | port (ex_d : in ex_in; 10 | ex_q : out ex_out); 11 | end entity instruction_executor; 12 | 13 | architecture Behavioral of instruction_executor is 14 | signal op1 : word; 15 | signal op2 : word; 16 | signal alu_out : word; 17 | signal compare_result : std_logic; 18 | signal return_addr : unsigned(word'range); 19 | 20 | constant c_four : unsigned(2 downto 0) := to_unsigned(4, 3); 21 | begin -- architecture Behavioral 22 | 23 | -- assign modules outputs 24 | ex_q.alu_result <= alu_out; 25 | ex_q.compare_result <= compare_result; 26 | ex_q.return_addr <= std_logic_vector(return_addr); 27 | 28 | -- ALU operand 1 multiplexer 29 | op1 <= ex_d.npc when (ex_d.insn_type = OP_BRANCH or 30 | ex_d.insn_type = OP_JAL or 31 | ex_d.insn_type = OP_JALR or 32 | ex_d.insn_type = OP_AUIPC) 33 | else ex_d.op1; 34 | 35 | -- ALU operand 2 multiplexer 36 | op2 <= ex_d.imm when ((ex_d.insn_type = OP_ALU and ex_d.use_imm = '1') or 37 | ex_d.insn_type = OP_BRANCH or 38 | ex_d.insn_type = OP_JAL or 39 | ex_d.insn_type = OP_JALR or 40 | ex_d.insn_type = OP_LOAD or 41 | ex_d.insn_type = OP_STORE or 42 | ex_d.insn_type = OP_AUIPC) 43 | else ex_d.op2; 44 | 45 | -- ALU 46 | arithmetic_logic_unit : entity work.alu(Behavioral) 47 | port map (alu_func => ex_d.alu_func, 48 | op1 => op1, 49 | op2 => op2, 50 | result => alu_out); 51 | 52 | -- compare unit 53 | conditionals : entity work.compare_unit(Behavioral) 54 | port map (branch_type => ex_d.branch_type, 55 | op1 => op1, 56 | op2 => op2, 57 | compare_result => compare_result); 58 | 59 | -- return address for JAL/JALR 60 | return_addr <= unsigned(ex_d.npc) + c_four; 61 | 62 | end architecture Behavioral; 63 | -------------------------------------------------------------------------------- /src/ex_pkg.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | use ieee.numeric_std.all; 4 | 5 | use work.common.all; 6 | 7 | package ex_pkg is 8 | 9 | -- inputs to execution stage 10 | type ex_in is record 11 | insn_type : insn_type_t; 12 | npc : word; 13 | op1 : word; 14 | op2 : word; 15 | use_imm : std_logic; 16 | alu_func : alu_func_t; 17 | branch_type : branch_type_t; 18 | imm : word; 19 | end record ex_in; 20 | 21 | -- outputs from execution stage 22 | type ex_out is record 23 | alu_result : word; 24 | compare_result : std_logic; 25 | return_addr : word; 26 | end record ex_out; 27 | 28 | end package ex_pkg; 29 | -------------------------------------------------------------------------------- /src/id.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | 4 | use work.common.all; 5 | use work.id_pkg.all; 6 | use work.csr_pkg.all; 7 | 8 | entity instruction_decoder is 9 | port (d : in word; 10 | q : out decoded_t); -- decoded data 11 | end entity instruction_decoder; 12 | 13 | architecture behavioral of instruction_decoder is 14 | ------------------------------------------------- 15 | -- Types 16 | ------------------------------------------------- 17 | 18 | type imm_type_t is (IMM_NONE, IMM_I, IMM_S, IMM_B, IMM_U, IMM_J, IMM_Z); 19 | 20 | ------------------------------------------------- 21 | -- Signals 22 | ------------------------------------------------- 23 | 24 | signal decoded : decoded_t := c_decoded_reset; 25 | begin -- architecture behavioral 26 | 27 | ------------------------------------------------- 28 | -- Assign module outputs 29 | ------------------------------------------------- 30 | q <= decoded; 31 | 32 | ------------------------------------------------- 33 | -- Decode the RISCV instruction 34 | ------------------------------------------------- 35 | decode_proc : process (d) is 36 | variable opcode : std_logic_vector(6 downto 0); 37 | variable funct3 : std_logic_vector(2 downto 0); 38 | variable imm_type : imm_type_t := IMM_NONE; 39 | variable insn : word; 40 | variable rd : std_logic_vector(4 downto 0); 41 | begin -- process decode_proc 42 | insn := d; 43 | rd := insn(11 downto 7); 44 | 45 | -- defaults & "global" fields 46 | opcode := insn(6 downto 0); 47 | funct3 := insn(14 downto 12); 48 | decoded.rs1 <= insn(19 downto 15); 49 | decoded.rs2 <= insn(24 downto 20); 50 | decoded.rd <= rd; 51 | decoded.opcode <= opcode; 52 | decoded.rs1_rd <= '0'; 53 | decoded.rs2_rd <= '0'; 54 | decoded.alu_func <= ALU_NONE; 55 | decoded.op2_src <= '0'; 56 | decoded.insn_type <= OP_ILLEGAL; 57 | decoded.load_type <= LOAD_NONE; 58 | decoded.store_type <= STORE_NONE; 59 | decoded.imm <= (others => 'X'); 60 | decoded.use_imm <= '0'; 61 | decoded.branch_type <= BRANCH_NONE; 62 | decoded.rf_we <= '0'; 63 | decoded.is_csr <= '0'; 64 | decoded.csr_addr <= (others => 'X'); 65 | 66 | case (opcode) is 67 | -- Load Upper Immediate 68 | when c_op_lui => 69 | decoded.insn_type <= OP_LUI; 70 | imm_type := IMM_U; 71 | if (rd /= "00000") then 72 | decoded.rf_we <= '1'; 73 | end if; 74 | 75 | -- Add Upper Immediate to PC 76 | when c_op_auipc => 77 | decoded.insn_type <= OP_AUIPC; 78 | imm_type := IMM_U; 79 | decoded.alu_func <= ALU_ADD; 80 | if (rd /= "00000") then 81 | decoded.rf_we <= '1'; 82 | end if; 83 | 84 | -- Jump And Link 85 | when c_op_jal => 86 | decoded.insn_type <= OP_JAL; 87 | decoded.alu_func <= ALU_ADD; 88 | imm_type := IMM_J; 89 | if (rd /= "00000") then 90 | decoded.rf_we <= '1'; 91 | end if; 92 | 93 | -- Jump And Link Register 94 | when c_op_jalr => 95 | decoded.insn_type <= OP_JALR; 96 | decoded.alu_func <= ALU_ADD; 97 | imm_type := IMM_I; 98 | decoded.rs1_rd <= '1'; 99 | if (rd /= "00000") then 100 | decoded.rf_we <= '1'; 101 | end if; 102 | 103 | -- Branch to target address, if condition is met 104 | when c_op_branch => 105 | decoded.insn_type <= OP_BRANCH; 106 | decoded.alu_func <= ALU_ADD; 107 | imm_type := IMM_B; 108 | decoded.rs1_rd <= '1'; 109 | decoded.rs2_rd <= '1'; 110 | 111 | case (funct3) is 112 | when "000" => decoded.branch_type <= BEQ; 113 | when "001" => decoded.branch_type <= BNE; 114 | when "100" => decoded.branch_type <= BLT; 115 | when "101" => decoded.branch_type <= BGE; 116 | when "110" => decoded.branch_type <= BLTU; 117 | when "111" => decoded.branch_type <= BGEU; 118 | when others => null; 119 | end case; 120 | 121 | -- load data from memory 122 | when c_op_load => 123 | decoded.insn_type <= OP_LOAD; 124 | imm_type := IMM_I; 125 | decoded.rs1_rd <= '1'; 126 | decoded.alu_func <= ALU_ADD; 127 | if (rd /= "00000") then 128 | decoded.rf_we <= '1'; 129 | end if; 130 | 131 | case (funct3) is 132 | when "000" => decoded.load_type <= LB; 133 | when "001" => decoded.load_type <= LH; 134 | when "010" => decoded.load_type <= LW; 135 | when "100" => decoded.load_type <= LBU; 136 | when "101" => decoded.load_type <= LHU; 137 | when others => null; 138 | end case; 139 | 140 | -- store data to memory 141 | when c_op_store => 142 | decoded.insn_type <= OP_STORE; 143 | imm_type := IMM_S; 144 | decoded.alu_func <= ALU_ADD; 145 | decoded.rs1_rd <= '1'; 146 | decoded.rs2_rd <= '1'; 147 | 148 | case (funct3) is 149 | when "000" => decoded.store_type <= SB; 150 | when "001" => decoded.store_type <= SH; 151 | when "010" => decoded.store_type <= SW; 152 | when others => null; 153 | end case; 154 | 155 | -- perform computation with immediate value and a register 156 | when c_op_imm => 157 | decoded.insn_type <= OP_ALU; 158 | decoded.op2_src <= '1'; 159 | imm_type := IMM_I; 160 | decoded.rs1_rd <= '1'; 161 | decoded.use_imm <= '1'; 162 | if (rd /= "00000") then 163 | decoded.rf_we <= '1'; 164 | end if; 165 | 166 | case (funct3) is 167 | when "000" => decoded.alu_func <= ALU_ADD; 168 | when "001" => decoded.alu_func <= ALU_SLL; 169 | when "010" => decoded.alu_func <= ALU_SLT; 170 | when "011" => decoded.alu_func <= ALU_SLTU; 171 | when "100" => decoded.alu_func <= ALU_XOR; 172 | when "110" => decoded.alu_func <= ALU_OR; 173 | when "111" => decoded.alu_func <= ALU_AND; 174 | when "101" => 175 | if (insn(30) = '1') then 176 | decoded.alu_func <= ALU_SRA; 177 | else 178 | decoded.alu_func <= ALU_SRL; 179 | end if; 180 | 181 | when others => null; 182 | end case; 183 | 184 | -- perform computation with two register values 185 | when c_op_reg => 186 | decoded.insn_type <= OP_ALU; 187 | decoded.rs1_rd <= '1'; 188 | decoded.rs2_rd <= '1'; 189 | if (rd /= "00000") then 190 | decoded.rf_we <= '1'; 191 | end if; 192 | 193 | case (funct3) is 194 | when "000" => 195 | if (insn(30) = '1') then 196 | decoded.alu_func <= ALU_SUB; 197 | else 198 | decoded.alu_func <= ALU_ADD; 199 | end if; 200 | when "001" => decoded.alu_func <= ALU_SLL; 201 | when "010" => decoded.alu_func <= ALU_SLT; 202 | when "011" => decoded.alu_func <= ALU_SLTU; 203 | when "100" => decoded.alu_func <= ALU_XOR; 204 | when "101" => 205 | if (insn(30) = '1') then 206 | decoded.alu_func <= ALU_SRA; 207 | else 208 | decoded.alu_func <= ALU_SRL; 209 | end if; 210 | when "110" => decoded.alu_func <= ALU_OR; 211 | when "111" => decoded.alu_func <= ALU_AND; 212 | when others => null; 213 | end case; 214 | 215 | -- system functions 216 | when c_op_system => 217 | decoded.insn_type <= OP_SYSTEM; 218 | decoded.csr_addr <= insn(31 downto 20); 219 | 220 | case (funct3) is 221 | when "000" => 222 | if insn(20) = '0' then 223 | decoded.system_type <= SYSTEM_ECALL; 224 | else 225 | decoded.system_type <= SYSTEM_EBREAK; 226 | end if; 227 | when "001" => 228 | decoded.system_type <= SYSTEM_CSRRW; 229 | decoded.rf_we <= '1'; 230 | decoded.rs1_rd <= '1'; 231 | when "010" => 232 | decoded.system_type <= SYSTEM_CSRRS; 233 | decoded.rf_we <= '1'; 234 | decoded.rs1_rd <= '1'; 235 | when "011" => 236 | decoded.system_type <= SYSTEM_CSRRC; 237 | decoded.rf_we <= '1'; 238 | decoded.rs1_rd <= '1'; 239 | when "101" => 240 | decoded.system_type <= SYSTEM_CSRRWI; 241 | decoded.rf_we <= '1'; 242 | decoded.use_imm <= '1'; 243 | when "110" => 244 | decoded.system_type <= SYSTEM_CSRRSI; 245 | decoded.rf_we <= '1'; 246 | decoded.use_imm <= '1'; 247 | when "111" => 248 | decoded.system_type <= SYSTEM_CSRRC; 249 | decoded.rf_we <= '1'; 250 | decoded.use_imm <= '1'; 251 | when others => 252 | decoded.insn_type <= OP_ILLEGAL; 253 | end case; 254 | 255 | when others => 256 | decoded.insn_type <= OP_ILLEGAL; 257 | end case; 258 | 259 | -- @TODO other insnructions 260 | --when c_op_misc_mem => 261 | -- insn_type <= OP_FENCE; 262 | 263 | -- decode and sign-extend the immediate value 264 | case imm_type is 265 | when IMM_I => 266 | for i in 31 downto 12 loop 267 | decoded.imm(i) <= insn(31); 268 | end loop; 269 | decoded.imm(11 downto 5) <= insn(31 downto 25); 270 | decoded.imm(4 downto 1) <= insn(24 downto 21); 271 | decoded.imm(0) <= insn(20); 272 | 273 | when IMM_S => 274 | for i in 31 downto 11 loop 275 | decoded.imm(i) <= insn(31); 276 | end loop; -- i 277 | decoded.imm(10 downto 5) <= insn(30 downto 25); 278 | decoded.imm(4 downto 1) <= insn(11 downto 8); 279 | decoded.imm(0) <= insn(7); 280 | 281 | when IMM_B => 282 | for i in 31 downto 13 loop 283 | decoded.imm(i) <= insn(31); 284 | end loop; -- i 285 | decoded.imm(12) <= insn(31); 286 | decoded.imm(11) <= insn(7); 287 | decoded.imm(10 downto 5) <= insn(30 downto 25); 288 | decoded.imm(4 downto 1) <= insn(11 downto 8); 289 | decoded.imm(0) <= '0'; 290 | 291 | when IMM_U => 292 | decoded.imm(31) <= insn(31); 293 | decoded.imm(30 downto 20) <= insn(30 downto 20); 294 | decoded.imm(19 downto 12) <= insn(19 downto 12); 295 | decoded.imm(11 downto 0) <= (others => '0'); 296 | 297 | when IMM_J => 298 | for i in 31 downto 20 loop 299 | decoded.imm(i) <= insn(31); 300 | end loop; -- i 301 | decoded.imm(19 downto 12) <= insn(19 downto 12); 302 | decoded.imm(11) <= insn(20); 303 | decoded.imm(10 downto 5) <= insn(30 downto 25); 304 | decoded.imm(4 downto 1) <= insn(24 downto 21); 305 | decoded.imm(0) <= '0'; 306 | 307 | when IMM_Z => 308 | for i in 31 downto 5 loop 309 | decoded.imm(i) <= insn(4); 310 | end loop; -- i 311 | decoded.imm(4 downto 0) <= insn(4 downto 0); 312 | 313 | when others => decoded.imm <= (others => 'X'); 314 | end case; 315 | 316 | end process decode_proc; 317 | 318 | end architecture behavioral; 319 | -------------------------------------------------------------------------------- /src/id_pkg.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | use std.textio.all; 4 | 5 | use work.common.all; 6 | use work.csr_pkg.all; 7 | 8 | package id_pkg is 9 | -- decoder input 10 | type id_in is record 11 | instruction : word; 12 | end record id_in; 13 | 14 | -- opcode type 15 | subtype opcode_t is std_logic_vector(6 downto 0); 16 | 17 | -- structure for decoded instruction 18 | type decoded_t is record 19 | alu_func : alu_func_t; 20 | op2_src : std_logic; 21 | insn_type : insn_type_t; 22 | branch_type : branch_type_t; 23 | load_type : load_type_t; 24 | store_type : store_type_t; 25 | rs1 : reg_addr_t; 26 | rs2 : reg_addr_t; 27 | rd : reg_addr_t; 28 | imm : word; 29 | opcode : opcode_t; 30 | rs1_rd : std_logic; 31 | rs2_rd : std_logic; 32 | use_imm : std_logic; 33 | rf_we : std_logic; 34 | csr_addr : csr_addr_t; 35 | system_type : system_type_t; 36 | end record decoded_t; 37 | 38 | -- value of decoding after reset 39 | constant c_decoded_reset : decoded_t := (alu_func => ALU_NONE, 40 | op2_src => '0', 41 | insn_type => OP_ILLEGAL, 42 | branch_type => BRANCH_NONE, 43 | load_type => LOAD_NONE, 44 | store_type => STORE_NONE, 45 | rs1 => "00000", 46 | rs2 => "00000", 47 | rd => "00000", 48 | imm => (others => '0'), 49 | opcode => (others => '0'), 50 | rs1_rd => '0', 51 | rs2_rd => '0', 52 | use_imm => '0', 53 | rf_we => '0', 54 | csr_addr => (others => '0'), 55 | system_type => SYSTEM_ECALL); 56 | 57 | -- Constants 58 | constant c_op_load : opcode_t := "0000011"; 59 | constant c_op_misc_mem : opcode_t := "0001111"; 60 | constant c_op_imm : opcode_t := "0010011"; 61 | constant c_op_auipc : opcode_t := "0010111"; 62 | constant c_op_store : opcode_t := "0100011"; 63 | constant c_op_reg : opcode_t := "0110011"; 64 | constant c_op_lui : opcode_t := "0110111"; 65 | constant c_op_branch : opcode_t := "1100011"; 66 | constant c_op_jalr : opcode_t := "1100111"; 67 | constant c_op_jal : opcode_t := "1101111"; 68 | constant c_op_system : opcode_t := "1110011"; 69 | 70 | procedure print_insn (insn_type : in insn_type_t); 71 | 72 | end package id_pkg; 73 | 74 | package body id_pkg is 75 | 76 | procedure print_insn (insn_type : in insn_type_t) is 77 | variable l : line; 78 | begin 79 | write(l, string'("Instruction type: ")); 80 | if insn_type = OP_LUI then 81 | write(l, string'("LUI")); 82 | writeline(output, l); 83 | elsif insn_type = OP_AUIPC then 84 | write(l, string'("AUIPC")); 85 | writeline(output, l); 86 | elsif insn_type = OP_JAL then 87 | write(l, string'("JAL")); 88 | writeline(output, l); 89 | elsif insn_type = OP_JALR then 90 | write(l, string'("JALR")); 91 | writeline(output, l); 92 | elsif insn_type = OP_BRANCH then 93 | write(l, string'("BRANCH")); 94 | writeline(output, l); 95 | elsif insn_type = OP_LOAD then 96 | write(l, string'("LOAD")); 97 | writeline(output, l); 98 | elsif insn_type = OP_STORE then 99 | write(l, string'("STORE")); 100 | writeline(output, l); 101 | elsif insn_type = OP_ALU then 102 | write(l, string'("ALU")); 103 | writeline(output, l); 104 | elsif insn_type = OP_STALL then 105 | write(l, string'("STALL")); 106 | writeline(output, l); 107 | elsif insn_type = OP_SYSTEM then 108 | write(l, string'("SYSTEM")); 109 | writeline(output, l); 110 | else 111 | write(l, string'("ILLEGAL")); 112 | writeline(output, l); 113 | end if; 114 | end procedure print_insn; 115 | 116 | end package body id_pkg; 117 | -------------------------------------------------------------------------------- /src/if.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | use ieee.numeric_std.all; 4 | 5 | use work.common.all; 6 | use work.if_pkg.all; 7 | 8 | entity instruction_fetch is 9 | port (clk : in std_logic; 10 | rst_n : in std_logic; 11 | d : in if_in; 12 | q : out if_out); 13 | end entity instruction_fetch; 14 | 15 | architecture Behavioral of instruction_fetch is 16 | ------------------------------------------------- 17 | -- Types 18 | ------------------------------------------------- 19 | 20 | type registers is record 21 | pc : unsigned(word'range); 22 | npc : unsigned(word'range); 23 | end record registers; 24 | 25 | ------------------------------------------------- 26 | -- Signals 27 | ------------------------------------------------- 28 | 29 | signal r, rin : registers; 30 | signal zero : std_logic := '1'; 31 | 32 | ------------------------------------------------- 33 | -- Constants 34 | ------------------------------------------------- 35 | 36 | constant c_four : unsigned(2 downto 0) := to_unsigned(4, 3); 37 | 38 | begin -- architecture Behavioral 39 | 40 | ------------------------------------------------- 41 | -- assign outputs 42 | ------------------------------------------------- 43 | q.fetch_addr <= std_logic_vector(rin.pc); 44 | q.pc <= std_logic_vector(r.pc); 45 | 46 | ------------------------------------------------- 47 | -- PC mux 48 | ------------------------------------------------- 49 | pc_next_proc : process (d, r, zero) is 50 | variable v : registers; 51 | begin -- process pc_next_proc 52 | -- defaults 53 | v := r; 54 | 55 | if (zero = '1') then 56 | v.pc := (others => '0'); 57 | elsif (d.irq = '1') then 58 | v.pc := IRQ_VECTOR_ADDRESS; 59 | elsif (d.load_pc = '1') then 60 | v.pc := unsigned(d.next_pc); 61 | elsif (d.stall = '1') then 62 | v.pc := r.pc; 63 | else 64 | v.pc := r.pc + c_four; 65 | end if; 66 | 67 | rin <= v; 68 | end process pc_next_proc; 69 | 70 | ------------------------------------------------- 71 | -- create the Program Counter register 72 | ------------------------------------------------- 73 | pc_reg_proc : process (clk, rst_n) is 74 | begin -- process pc_reg 75 | if (rst_n = '0') then 76 | r.pc <= (others => '0'); 77 | zero <= '1'; 78 | elsif (rising_edge(clk)) then 79 | r <= rin; 80 | zero <= '0'; 81 | end if; 82 | end process pc_reg_proc; 83 | 84 | end architecture Behavioral; 85 | -------------------------------------------------------------------------------- /src/if_pkg.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | use ieee.numeric_std.all; 4 | 5 | use work.common.all; 6 | 7 | package if_pkg is 8 | 9 | -- The CPU will vector to this address 10 | -- when an IRQ is asserted and the pipeline 11 | -- is in a safe place to do so. 12 | constant IRQ_VECTOR_ADDRESS : word := X"00000200"; 13 | 14 | -- inputs to Instruction Fetch stage 15 | type if_in is record 16 | insn : word; 17 | load_pc : std_logic; 18 | next_pc : word; 19 | stall : std_logic; 20 | irq : std_logic; 21 | end record if_in; 22 | 23 | -- outputs from Instruction Fetch stage 24 | type if_out is record 25 | fetch_addr : word; 26 | pc : word; 27 | end record if_out; 28 | 29 | end package if_pkg; 30 | -------------------------------------------------------------------------------- /src/pipeline.vhd: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------------------- 2 | -- Title : 5-stage RISCV integer pipeline 3 | -- Project : Freezing Spice 4 | ------------------------------------------------------------------------------- 5 | -- File : pipeline.vhd 6 | -- Author : Tim Wawrzynczak 7 | -- Created : 2015-07-07 8 | -- Last update: 2017-01-15 9 | -- Platform : FPGA 10 | -- Standard : VHDL'93/02 11 | ------------------------------------------------------------------------------- 12 | -- Description: RV32I 5-stage ("classic MIPS") pipeline: 13 | -- Instruction Fetch 14 | -- Instruction Decode 15 | -- Instruction Execute 16 | -- Memory Access 17 | -- Register File Writeback 18 | ------------------------------------------------------------------------------- 19 | -- Interrupts: 32-bit wide IRQ number 20 | -- Currently when an instruction signals that an interrupt 21 | -- needs to be taken, a "trap instruction" is immediately inserted into 22 | -- the pipeline. Once the trap instruction reaches the writeback stage, 23 | -- all instructions in the pipeline are flushed, and the IF stage steers 24 | -- the pipeline to the IRQ_VECTOR_ADDRESS. The pipeline will have inserted 25 | -- the IRQ number into the "MCAUSE" CSR. The ISR can read that register 26 | -- to determine the cause of the interrupt and can decide what to do with 27 | -- that information. 28 | -- 29 | -- Only one interrupt can be serviced at a time, due to this architectural 30 | -- choice; the 'irq' and 'irq_ack' I/O ports are used to handshake with 31 | -- an external interrupt controller. 32 | ------------------------------------------------------------------------------- 33 | -- Copyright (c) 2017 Tim Wawrzynczak 34 | ------------------------------------------------------------------------------- 35 | 36 | library ieee; 37 | use ieee.std_logic_1164.all; 38 | use ieee.numeric_std.all; 39 | use std.textio.all; 40 | 41 | use work.common.all; 42 | use work.if_pkg.all; 43 | use work.id_pkg.all; 44 | use work.ex_pkg.all; 45 | use work.csr_pkg.all; 46 | 47 | entity pipeline is 48 | generic (g_initial_pc : unsigned(31 downto 0) := (others => '0'); 49 | g_for_sim : boolean := false; 50 | g_regout_filename : string := "sim/regout.vec"); 51 | port (clk : in std_logic; 52 | rst_n : in std_logic; 53 | 54 | -- interrupt interface 55 | irq_num : in word; 56 | irq : in std_logic; 57 | irq_ack : out std_logic; 58 | 59 | -- Instruction interface 60 | insn_in : in word; 61 | insn_valid : in std_logic; 62 | insn_addr : out word; 63 | 64 | -- Data interface 65 | data_in : in word; 66 | data_out : out word; 67 | data_addr : out word; 68 | data_write_en : out std_logic; 69 | data_read_en : out std_logic; 70 | data_in_valid : in std_logic); 71 | end entity pipeline; 72 | 73 | architecture Behavioral of pipeline is 74 | 75 | ------------------------------------------------- 76 | -- IF signals 77 | ------------------------------------------------- 78 | signal if_d : if_in; 79 | signal if_q : if_out; 80 | 81 | ------------------------------------------------- 82 | -- IF/ID pipeline registers 83 | ------------------------------------------------- 84 | signal if_id_ir : word := (others => '0'); 85 | signal if_id_pc : word := (others => '0'); 86 | 87 | ------------------------------------------------- 88 | -- ID signals 89 | ------------------------------------------------- 90 | signal id_d : word; 91 | signal id_q : decoded_t; 92 | signal rs1_data : word; 93 | signal rs2_data : word; 94 | signal id_op1 : word; 95 | signal id_op2 : word; 96 | signal id_predict_taken : std_logic; 97 | signal id_branch_pc : word; 98 | 99 | ------------------------------------------------- 100 | -- ID/EX pipeline registers 101 | ------------------------------------------------- 102 | signal id_ex_pc : word := (others => '0'); 103 | signal id_ex_rs1_addr : std_logic_vector(4 downto 0) := (others => '0'); 104 | signal id_ex_rs2_addr : std_logic_vector(4 downto 0) := (others => '0'); 105 | signal id_ex_op1 : word := (others => '0'); 106 | signal id_ex_op2 : word := (others => '0'); 107 | signal id_ex_ir : word := NOP; 108 | signal id_ex_imm : word := (others => '0'); 109 | signal id_ex_insn_type : insn_type_t := OP_STALL; 110 | signal id_ex_use_imm : std_logic := '0'; 111 | signal id_ex_alu_func : alu_func_t := ALU_NONE; 112 | signal id_ex_branch_type : branch_type_t := BRANCH_NONE; 113 | signal id_ex_rd_addr : std_logic_vector(4 downto 0) := (others => '0'); 114 | signal id_ex_load_type : load_type_t := LOAD_NONE; 115 | signal id_ex_store_type : store_type_t := STORE_NONE; 116 | signal id_ex_rf_we : std_logic := '0'; 117 | signal id_ex_taken : std_logic := '0'; 118 | signal id_ex_is_csr : std_logic := '0'; 119 | signal id_ex_csr_addr : csr_addr_t := (others => '0'); 120 | 121 | ------------------------------------------------- 122 | -- EX signals 123 | ------------------------------------------------- 124 | signal ex_d : ex_in; 125 | signal ex_q : ex_out; 126 | signal ex_rf_data : word; 127 | signal ex_load_pc : std_logic; 128 | signal ex_data_addr : word; 129 | signal ex_branch_mispredict : std_logic; 130 | signal ex_csr_cycle_valid : std_logic; 131 | signal ex_csr_timer_tick : std_logic; 132 | signal ex_csr_instret : std_logic; 133 | 134 | ------------------------------------------------- 135 | -- EX/MEM pipeline registers 136 | ------------------------------------------------- 137 | signal ex_mem_load_pc : std_logic := '0'; 138 | signal ex_mem_next_pc : word := (others => '0'); 139 | signal ex_mem_rf_data : word := (others => '0'); 140 | signal ex_mem_return_addr : word := (others => '0'); 141 | signal ex_mem_load_type : load_type_t := LOAD_NONE; 142 | signal ex_mem_store_type : store_type_t := STORE_NONE; 143 | signal ex_mem_rd_addr : std_logic_vector(4 downto 0) := (others => '0'); 144 | signal ex_mem_insn_type : insn_type_t := OP_STALL; 145 | signal ex_mem_rf_we : std_logic := '0'; 146 | signal ex_mem_data_addr : word := (others => '0'); 147 | signal ex_mem_data_out : word := (others => '0'); 148 | signal ex_mem_rs1_addr : std_logic_vector(4 downto 0) := (others => '0'); 149 | signal ex_mem_rs2_addr : std_logic_vector(4 downto 0) := (others => '0'); 150 | signal ex_mem_csr_value : word := (others => '0'); 151 | signal ex_mem_is_csr : std_logic := '0'; 152 | 153 | ------------------------------------------------- 154 | -- MEM signals 155 | ------------------------------------------------- 156 | signal mem_we : std_logic; 157 | signal mem_re : std_logic; 158 | signal mem_data_addr : word; 159 | signal mem_data_out : word; 160 | signal mem_lmd_lh : word; 161 | signal mem_lmd_lb : word; 162 | signal mem_lmd_lhu : word; 163 | signal mem_lmd_lbu : word; 164 | signal mem_lmd : word; 165 | signal mem_rf_data_mux : word; 166 | signal mem_data_out_mux : word; 167 | 168 | ------------------------------------------------- 169 | -- MEM/WB pipeline registers 170 | ------------------------------------------------- 171 | signal mem_wb_rd_addr : std_logic_vector(4 downto 0) := (others => '0'); 172 | signal mem_wb_rf_we : std_logic := '0'; 173 | signal mem_wb_rf_data : word := (others => '0'); 174 | signal mem_wb_insn_type : insn_type_t := OP_STALL; 175 | signal mem_wb_lmd : word := (others => '0'); 176 | signal mem_wb_is_csr : std_logic := '0'; 177 | 178 | ------------------------------------------------- 179 | -- WB signals 180 | ------------------------------------------------- 181 | signal wb_rf_wr_addr : std_logic_vector(4 downto 0); 182 | signal wb_rf_wr_en : std_logic; 183 | signal wb_rf_wr_data : word; 184 | 185 | ------------------------------------------------- 186 | -- Stalling / killing 187 | ------------------------------------------------- 188 | signal branch_stall : std_logic; 189 | signal if_kill : std_logic; 190 | signal if_stall : std_logic; 191 | signal id_kill : std_logic; 192 | signal id_stall : std_logic; 193 | signal full_stall : std_logic; 194 | signal hazard_stall : std_logic; 195 | 196 | ------------------------------------------------- 197 | -- Interrupt signals 198 | ------------------------------------------------- 199 | signal in_irq : std_logic := '0'; 200 | signal trap_in_pipeline : std_logic := '0'; 201 | signal if_take_irq : std_logic := '0'; 202 | 203 | ------------------------------------------------- 204 | -- Simulation-specific signals 205 | ------------------------------------------------- 206 | file regout_file : text open write_mode is g_regout_filename; 207 | 208 | -- debug signals because VCD files can't contain information from VHDL records 209 | signal debug_rs1 : std_logic_vector(4 downto 0); 210 | signal debug_rs2 : std_logic_vector(4 downto 0); 211 | signal debug_alu_result : word; 212 | begin -- architecture Behavioral 213 | 214 | ------------------------------------------------- 215 | -- Drive module outputs 216 | ------------------------------------------------- 217 | 218 | -- instruction interface 219 | insn_addr <= if_q.fetch_addr; 220 | 221 | -- memory interface 222 | data_read_en <= mem_re; 223 | data_write_en <= mem_we; 224 | data_addr <= mem_data_addr; 225 | data_out <= mem_data_out; 226 | 227 | ------------------------------------------------- 228 | -- Detect when stalling / killing is necessary 229 | ------------------------------------------------- 230 | if_kill <= ex_mem_load_pc or (not insn_valid) or id_predict_taken or ex_branch_mispredict; 231 | if_stall <= ex_mem_load_pc or branch_stall or full_stall or hazard_stall; 232 | id_kill <= (ex_mem_load_pc or ex_branch_mispredict) and not id_predict_taken; 233 | id_stall <= branch_stall or full_stall or hazard_stall; 234 | 235 | -- being lazy and stalling on reads of CSR writes 236 | hazard_stall <= '1' when ((id_ex_is_csr = '1' and id_ex_rd_addr = id_q.rs1 and id_q.rs1 /= "00000" and id_ex_rf_we = '1') 237 | or (ex_mem_is_csr = '1' and ex_mem_rd_addr = id_q.rs1 and id_q.rs1 /= "00000" and ex_mem_rf_we = '1') 238 | or (mem_wb_is_csr = '1' and mem_wb_rd_addr = id_q.rs1 and id_q.rs1 /= "00000" and mem_wb_rf_we = '1') 239 | or (id_ex_is_csr = '1' and id_ex_rd_addr = id_q.rs2 and id_q.rs2 /= "00000" and id_ex_rf_we = '1') 240 | or (ex_mem_is_csr = '1' and ex_mem_rd_addr = id_q.rs2 and id_q.rs2 /= "00000" and ex_mem_rf_we = '1') 241 | or (mem_wb_is_csr = '1' and mem_wb_rd_addr = id_q.rs2 and id_q.rs2 /= "00000" and mem_wb_rf_we = '1')) 242 | else '0'; 243 | 244 | -- stall when a PC redirection is imminent 245 | branch_stall <= '1' when (id_ex_insn_type = OP_JAL or id_ex_insn_type = OP_JALR or 246 | (id_ex_insn_type = OP_BRANCH and ex_q.compare_result = '1')) 247 | else '0'; 248 | 249 | -- stall on data not being available (data cache misses in the future) 250 | full_stall <= '1' when (ex_mem_insn_type = OP_LOAD and data_in_valid = '0') 251 | else '0'; 252 | 253 | --------------------------------------------------- 254 | -- Instruction fetch 255 | --------------------------------------------------- 256 | 257 | -- inputs 258 | if_d.stall <= if_stall; 259 | if_d.load_pc <= ex_mem_load_pc or id_predict_taken or ex_branch_mispredict; 260 | if_d.next_pc <= ex_mem_next_pc when (ex_mem_load_pc = '1') else id_branch_pc; 261 | if_d.irq <= if_take_irq; 262 | 263 | -- instantiation 264 | if_stage : entity work.instruction_fetch(Behavioral) 265 | port map (clk, rst_n, if_d, if_q); 266 | 267 | ------------------------------------------------- 268 | -- IF/ID pipeline registers 269 | ------------------------------------------------- 270 | 271 | if_id_reg_proc : process (clk, rst_n) is 272 | begin -- process if_id_reg_proc 273 | if (rst_n = '0') then -- asynchronous reset (active low) 274 | if_id_ir <= NOP; 275 | if_id_pc <= (others => '0'); 276 | elsif (rising_edge(clk)) then 277 | if (id_stall = '0') then 278 | if (if_kill = '1') then 279 | if_id_ir <= NOP; 280 | else 281 | if_id_ir <= insn_in; 282 | end if; 283 | 284 | if_id_pc <= if_q.pc; 285 | end if; 286 | end if; 287 | end process if_id_reg_proc; 288 | 289 | --------------------------------------------------- 290 | -- Instruction decode 291 | --------------------------------------------------- 292 | 293 | -- register file 294 | register_file : entity work.regfile(rtl) 295 | port map (clk => clk, 296 | addra => id_q.rs1, 297 | addrb => id_q.rs2, 298 | rega => rs1_data, 299 | regb => rs2_data, 300 | addrw => wb_rf_wr_addr, 301 | dataw => wb_rf_wr_data, 302 | we => wb_rf_wr_en); 303 | 304 | -- instantiation of decoder 305 | id_stage : entity work.instruction_decoder(Behavioral) 306 | port map (if_id_ir, id_q); 307 | 308 | -- debug b/c VCD files can't contain signals from VHDL records 309 | gen_debug1 : if g_for_sim = true generate 310 | debug_rs1 <= id_q.rs1; 311 | debug_rs2 <= id_q.rs2; 312 | end generate gen_debug1; 313 | 314 | -- forwarding to ALU input multiplexer 315 | id_op1 <= ex_q.alu_result when (id_q.rs1 = id_ex_rd_addr and id_q.rs1 /= "00000" and id_kill = '0') else 316 | ex_mem_rf_data when (id_q.rs1 = ex_mem_rd_addr and id_q.rs1 /= "00000" and id_kill = '0') else 317 | mem_wb_rf_data when (id_q.rs1 = mem_wb_rd_addr and id_q.rs1 /= "00000" and id_kill = '0') else 318 | rs1_data; 319 | 320 | -- forwarding to ALU input multiplexer 321 | id_op2 <= ex_q.alu_result when (id_q.rs2 = id_ex_rd_addr and id_q.rs2 /= "00000" and id_kill = '0') else 322 | ex_mem_rf_data when (id_q.rs2 = ex_mem_rd_addr and id_q.rs2 /= "00000" and id_kill = '0') else 323 | mem_wb_rf_data when (id_q.rs2 = mem_wb_rd_addr and id_q.rs2 /= "00000" and id_kill = '0') else 324 | rs2_data; 325 | 326 | -- branch prediction: for now, predict backward branches as TAKEN 327 | -- and forward as NOT TAKEN (optimized for loops) 328 | id_predict_taken <= '1' when (id_q.imm(31) = '1' and (id_q.insn_type = OP_BRANCH or id_q.insn_type = OP_JAL or id_q.insn_type = OP_JALR)) 329 | else '0'; 330 | 331 | -- adder for branch prediction 332 | id_branch_pc <= word(unsigned(if_id_pc) + unsigned(id_q.imm)); 333 | 334 | --------------------------------------------------- 335 | -- ID/EX pipeline registers 336 | --------------------------------------------------- 337 | 338 | -- this is where instructions get issued, 339 | -- controlled by id_stall, full_stall, and id_kill 340 | id_ex_reg_proc : process (clk, rst_n) is 341 | begin -- process id_ex_reg_proc 342 | if (rst_n = '0') then -- asynchronous reset (active low) 343 | id_ex_pc <= (others => '0'); 344 | id_ex_rs1_addr <= (others => '0'); 345 | id_ex_rs2_addr <= (others => '0'); 346 | id_ex_op1 <= (others => '0'); 347 | id_ex_op2 <= (others => '0'); 348 | id_ex_ir <= (others => '0'); 349 | id_ex_insn_type <= OP_ILLEGAL; 350 | id_ex_is_csr <= '0'; 351 | id_ex_csr_addr <= (others => '0'); 352 | elsif (rising_edge(clk)) then 353 | id_ex_taken <= id_predict_taken; 354 | 355 | if (id_stall = '0' and full_stall = '0') then 356 | id_ex_rs1_addr <= id_q.rs1; 357 | id_ex_rs2_addr <= id_q.rs2; 358 | id_ex_op1 <= id_op1; 359 | id_ex_op2 <= id_op2; 360 | id_ex_use_imm <= id_q.use_imm; 361 | 362 | -- to kill an instruction 363 | if (id_kill = '1') then 364 | id_ex_ir <= NOP; 365 | id_ex_rd_addr <= (others => '0'); 366 | id_ex_insn_type <= OP_STALL; 367 | id_ex_rf_we <= '0'; 368 | id_ex_use_imm <= '0'; 369 | id_ex_imm <= (others => '0'); 370 | id_ex_alu_func <= ALU_NONE; 371 | id_ex_branch_type <= BRANCH_NONE; 372 | id_ex_load_type <= LOAD_NONE; 373 | id_ex_store_type <= STORE_NONE; 374 | id_ex_is_csr <= '0'; 375 | id_ex_csr_addr <= (others => '0'); 376 | else 377 | id_ex_pc <= if_id_pc; 378 | id_ex_ir <= if_id_ir; 379 | id_ex_rd_addr <= id_q.rd; 380 | id_ex_insn_type <= id_q.insn_type; 381 | id_ex_rf_we <= id_q.rf_we; 382 | id_ex_use_imm <= id_q.use_imm; 383 | id_ex_imm <= id_q.imm; 384 | id_ex_alu_func <= id_q.alu_func; 385 | id_ex_branch_type <= id_q.branch_type; 386 | id_ex_load_type <= id_q.load_type; 387 | id_ex_store_type <= id_q.store_type; 388 | id_ex_is_csr <= id_q.is_csr; 389 | id_ex_csr_addr <= id_q.csr_addr; 390 | end if; 391 | elsif (id_stall = '1' and full_stall = '0') then 392 | id_ex_ir <= NOP; 393 | id_ex_rd_addr <= (others => '0'); 394 | id_ex_insn_type <= OP_STALL; 395 | id_ex_rf_we <= '0'; 396 | id_ex_use_imm <= '0'; 397 | id_ex_imm <= (others => '0'); 398 | id_ex_alu_func <= ALU_NONE; 399 | id_ex_branch_type <= BRANCH_NONE; 400 | id_ex_load_type <= LOAD_NONE; 401 | id_ex_store_type <= STORE_NONE; 402 | id_ex_is_csr <= '0'; 403 | id_ex_csr_addr <= (others => '0'); 404 | end if; 405 | end if; 406 | end process id_ex_reg_proc; 407 | 408 | --------------------------------------------------- 409 | -- print instructions as they are issued 410 | --------------------------------------------------- 411 | print_decode : if (g_for_sim = true) generate 412 | print_decode_proc : process (id_ex_ir, id_ex_pc, id_ex_insn_type, id_ex_taken) is 413 | variable l : line; 414 | variable op1, op2 : word; 415 | begin -- process print_decode_proc 416 | write(l, to_integer(unsigned(id_ex_pc))); 417 | write(l, string'(" : 0x")); 418 | write(l, hstr(id_ex_ir)); 419 | writeline(output, l); 420 | 421 | -- differentiate NOPs in the simulation output 422 | if (id_ex_ir = NOP) then 423 | write(l, string'("Instruction type: NOP")); 424 | writeline(output, l); 425 | else 426 | print_insn(id_ex_insn_type); 427 | end if; 428 | 429 | print(id_ex_insn_type); 430 | 431 | if id_ex_insn_type = OP_ALU then 432 | if (id_ex_rs1_addr = ex_mem_rd_addr and ex_mem_insn_type = OP_LOAD) then 433 | write(l, string'("op1 := mem_lmd")); 434 | op1 := mem_lmd; 435 | elsif (id_ex_rs1_addr = mem_wb_rd_addr and mem_wb_insn_type = OP_LOAD) then 436 | write(l, string'("op1 := wb_rf_wr_data")); 437 | op1 := wb_rf_wr_data; 438 | elsif (ex_d.insn_type = OP_BRANCH or 439 | ex_d.insn_type = OP_JAL or 440 | ex_d.insn_type = OP_JALR or 441 | ex_d.insn_type = OP_AUIPC) then 442 | write(l, string'("op1 := id_ex_pc")); 443 | op1 := id_ex_pc; 444 | else 445 | write(l, string'("op1 := id_ex_op1")); 446 | op1 := id_ex_op1; 447 | end if; 448 | writeline(output, l); 449 | 450 | if (id_ex_rs2_addr = ex_mem_rd_addr and ex_mem_insn_type = OP_LOAD) then 451 | write(l, string'("op2 := mem_lmd")); 452 | op2 := mem_lmd; 453 | elsif (id_ex_rs2_addr = mem_wb_rd_addr and mem_wb_insn_type = OP_LOAD) then 454 | write(l, string'("op2 := wb_rf_wr_data")); 455 | op2 := wb_rf_wr_data; 456 | elsif ((id_ex_insn_type = OP_ALU and id_ex_use_imm = '1') or 457 | id_ex_insn_type = OP_BRANCH or 458 | id_ex_insn_type = OP_JAL or 459 | id_ex_insn_type = OP_JALR or 460 | id_ex_insn_type = OP_LOAD or 461 | id_ex_insn_type = OP_STORE or 462 | id_ex_insn_type = OP_AUIPC) then 463 | write(l, string'("op2 := id_ex_imm")); 464 | op1 := id_ex_imm; 465 | else 466 | write(l, string'("op2 := id_ex_op2")); 467 | op2 := id_ex_op2; 468 | end if; 469 | writeline(output, l); 470 | 471 | write(l, string'(" Op1: ")); 472 | write(l, hstr(op1)); 473 | write(l, string'(", Op2: ")); 474 | write(l, hstr(op2)); 475 | writeline(output, l); 476 | end if; 477 | 478 | if id_ex_taken = '1' then 479 | write(l, string'("Predicting branch as taken, redirecting PC to ")); 480 | writeline(output, l); 481 | print(id_branch_pc); 482 | end if; 483 | 484 | if (ex_branch_mispredict = '1') then 485 | write(l, string'("Branch incorrectly predicted, continuing . . .")); 486 | writeline(output, l); 487 | print(id_branch_pc); 488 | end if; 489 | 490 | writeline(output, l); 491 | end process print_decode_proc; 492 | end generate print_decode; 493 | 494 | --------------------------------------------------- 495 | -- Instruction execution stage 496 | --------------------------------------------------- 497 | 498 | -- inputs (includes multiplexers for ALU operands from the LMD "Load Memory 499 | -- Data" datapath) 500 | ex_d.insn_type <= id_ex_insn_type; 501 | ex_d.npc <= id_ex_pc; 502 | ex_d.op1 <= mem_lmd when (id_ex_rs1_addr = ex_mem_rd_addr and ex_mem_insn_type = OP_LOAD) 503 | else wb_rf_wr_data when (id_ex_rs1_addr = mem_wb_rd_addr and mem_wb_insn_type = OP_LOAD) 504 | else id_ex_op1; 505 | ex_d.op2 <= mem_lmd when (id_ex_rs2_addr = ex_mem_rd_addr and ex_mem_insn_type = OP_LOAD) 506 | else wb_rf_wr_data when (id_ex_rs2_addr = mem_wb_rd_addr and mem_wb_insn_type = OP_LOAD) 507 | else id_ex_op2; 508 | ex_d.use_imm <= id_ex_use_imm; 509 | ex_d.alu_func <= id_ex_alu_func; 510 | ex_d.branch_type <= id_ex_branch_type; 511 | ex_d.imm <= id_ex_imm; 512 | 513 | -- instantiation of execution stage 514 | ex_stage : entity work.instruction_executor(Behavioral) 515 | port map (ex_d, ex_q); 516 | 517 | -- inputs to CSRs 518 | ex_csr_cycle_valid <= '1' when rst_n = '1' else '0'; 519 | ex_csr_timer_tick <= '0'; -- TODO: implement 520 | ex_csr_instret <= mem_we or wb_rf_wr_en; 521 | 522 | -- instantiation of CSRs (core specific registers) 523 | inst_csrs : entity work.csr(behavioral) 524 | port map (clk => clk, 525 | en => id_ex_is_csr, 526 | addr => id_ex_csr_addr, 527 | valid => ex_csr_cycle_valid, 528 | tick => ex_csr_timer_tick, 529 | instret => ex_csr_instret, 530 | value => ex_mem_csr_value); 531 | 532 | -- simulation-specific signal 533 | gen_debug2 : if g_for_sim = true generate 534 | debug_alu_result <= ex_q.alu_result; 535 | end generate gen_debug2; 536 | 537 | -- multiplexer for Register File write data 538 | ex_rf_data <= ex_q.return_addr when (id_ex_insn_type = OP_JAL or id_ex_insn_type = OP_JALR) else 539 | id_ex_imm when (id_ex_insn_type = OP_LUI) else 540 | ex_q.alu_result; 541 | 542 | -- selecter for loading the PC with a new value 543 | ex_load_pc <= '1' when (id_ex_taken = '0' and (id_ex_insn_type = OP_JAL or id_ex_insn_type = OP_JALR or 544 | (id_ex_insn_type = OP_BRANCH and ex_q.compare_result = '1'))) else '0'; 545 | 546 | -- check for misprediction 547 | ex_branch_mispredict <= '1' when (id_ex_insn_type = OP_BRANCH and ex_q.compare_result = '0' and id_ex_taken = '1') else '0'; 548 | 549 | -- multiplexer for data memory address 550 | ex_data_addr <= ex_q.alu_result when (id_ex_insn_type = OP_LOAD or id_ex_insn_type = OP_STORE) else ex_mem_data_addr; 551 | 552 | --------------------------------------------------- 553 | -- EX/MEM pipeline registers 554 | --------------------------------------------------- 555 | 556 | -- purpose: Pipeline data between EX and MEM stages 557 | ex_mem_regs_proc : process (clk, rst_n) is 558 | begin -- process ex_mem_regs_proc 559 | if (rst_n = '0') then -- asynchronous reset (active low) 560 | ex_mem_load_pc <= '0'; 561 | ex_mem_next_pc <= (others => '0'); 562 | ex_mem_rf_data <= (others => '0'); 563 | ex_mem_return_addr <= (others => '0'); 564 | ex_mem_load_type <= LOAD_NONE; 565 | ex_mem_store_type <= STORE_NONE; 566 | ex_mem_rd_addr <= (others => '0'); 567 | ex_mem_insn_type <= OP_STALL; 568 | ex_mem_rf_we <= '0'; 569 | ex_mem_is_csr <= '0'; 570 | elsif (rising_edge(clk)) then 571 | if (full_stall = '0') then 572 | ex_mem_next_pc <= ex_q.alu_result; 573 | ex_mem_load_pc <= ex_load_pc; 574 | ex_mem_rf_data <= ex_rf_data; 575 | ex_mem_data_addr <= ex_data_addr; 576 | ex_mem_data_out <= id_ex_op2; 577 | ex_mem_load_type <= id_ex_load_type; 578 | ex_mem_store_type <= id_ex_store_type; 579 | ex_mem_rd_addr <= id_ex_rd_addr; 580 | ex_mem_insn_type <= id_ex_insn_type; 581 | ex_mem_rf_we <= id_ex_rf_we; 582 | ex_mem_rs1_addr <= id_ex_rs1_addr; -- only needed for forwarding 583 | ex_mem_rs2_addr <= id_ex_rs2_addr; -- only needed for forwarding 584 | ex_mem_is_csr <= id_ex_is_csr; 585 | end if; 586 | end if; 587 | end process ex_mem_regs_proc; 588 | 589 | --------------------------------------------------- 590 | -- Memory stage 591 | --------------------------------------------------- 592 | 593 | -- memory access logic 594 | mem_we <= '1' when ex_mem_insn_type = OP_STORE else '0'; 595 | mem_re <= '1' when ex_mem_insn_type = OP_LOAD else '0'; 596 | 597 | -- first level of data memory output muxing 598 | mem_data_out_mux <= mem_wb_lmd when (mem_wb_insn_type = OP_LOAD) else ex_mem_data_out; 599 | 600 | -- data memory interface multiplexers 601 | mem_data_addr <= ex_mem_data_addr; 602 | mem_data_out <= X"0000" & mem_data_out_mux(15 downto 0) when ex_mem_store_type = SH else 603 | X"000000" & mem_data_out_mux(7 downto 0) when ex_mem_store_type = SB else 604 | mem_data_out_mux; 605 | 606 | -- load halfword (signed) 607 | mem_lmd_lh <= word(resize(signed(data_in(15 downto 0)), word'length)); 608 | 609 | -- load byte (signed) 610 | mem_lmd_lb <= word(resize(signed(data_in(7 downto 0)), word'length)); 611 | 612 | -- load halfword unsigned 613 | mem_lmd_lhu <= word(resize(unsigned(data_in(15 downto 0)), word'length)); 614 | 615 | -- load byte unsigned 616 | mem_lmd_lbu <= word(resize(unsigned(data_in(7 downto 0)), word'length)); 617 | 618 | -- Load Memory Data register input 619 | with ex_mem_load_type select 620 | mem_lmd <= 621 | mem_lmd_lhu when LHU, 622 | mem_lmd_lbu when LBU, 623 | mem_lmd_lh when LH, 624 | mem_lmd_lb when LB, 625 | data_in when others; 626 | 627 | -- mux for register-file writeback data 628 | mem_rf_data_mux <= ex_mem_csr_value when ex_mem_is_csr = '1' 629 | else mem_lmd when ex_mem_insn_type = OP_LOAD 630 | else ex_mem_rf_data; 631 | 632 | --------------------------------------------------- 633 | -- MEM/WB pipeline registers 634 | --------------------------------------------------- 635 | 636 | -- purpose: Create the MEM/WB pipeline registers 637 | mem_wb_regs : process (clk, rst_n) is 638 | begin -- process mem_wb_regs 639 | if (rst_n = '0') then -- asynchronous reset (active low) 640 | mem_wb_rd_addr <= (others => '0'); 641 | mem_wb_rf_we <= '0'; 642 | mem_wb_rf_data <= (others => '0'); 643 | mem_wb_insn_type <= OP_STALL; 644 | elsif (rising_edge(clk)) then 645 | if (full_stall = '0') then 646 | mem_wb_rd_addr <= ex_mem_rd_addr; 647 | mem_wb_rf_we <= ex_mem_rf_we; 648 | mem_wb_insn_type <= ex_mem_insn_type; 649 | mem_wb_rf_data <= mem_rf_data_mux; 650 | mem_wb_is_csr <= ex_mem_is_csr; 651 | 652 | if (data_in_valid = '1') then 653 | mem_wb_lmd <= mem_lmd; 654 | end if; 655 | else 656 | mem_wb_rf_we <= '0'; 657 | mem_wb_is_csr <= '0'; 658 | end if; 659 | end if; 660 | end process mem_wb_regs; 661 | 662 | --------------------------------------------------- 663 | -- Writeback stage 664 | --------------------------------------------------- 665 | wb_rf_wr_addr <= mem_wb_rd_addr; 666 | wb_rf_wr_en <= mem_wb_rf_we; 667 | wb_rf_wr_data <= mem_wb_rf_data; 668 | 669 | --------------------------------------------------- 670 | -- print register file writebacks 671 | --------------------------------------------------- 672 | log_regs : if (g_for_sim = true) generate 673 | log_regs_proc : process (wb_rf_wr_addr, wb_rf_wr_en, wb_rf_wr_data) is 674 | variable l : line; 675 | begin -- process print_decode_proc 676 | if wb_rf_wr_en = '1' then 677 | write(l, hstr(wb_rf_wr_addr)); 678 | write(l, string'(", ")); 679 | write(l, hstr(wb_rf_wr_data)); 680 | writeline(regout_file, l); 681 | end if; 682 | end process log_regs_proc; 683 | end generate log_regs; 684 | 685 | end architecture Behavioral; 686 | -------------------------------------------------------------------------------- /src/regfile.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | use ieee.numeric_std.all; 4 | 5 | use work.common.all; 6 | 7 | entity regfile is 8 | port (clk : in std_logic; 9 | addra : in std_logic_vector(4 downto 0); 10 | addrb : in std_logic_vector(4 downto 0); 11 | rega : out word; 12 | regb : out word; 13 | addrw : in std_logic_vector(4 downto 0); 14 | dataw : in word; 15 | we : in std_logic); 16 | end entity regfile; 17 | 18 | -- 19 | -- Note: Because this core is FPGA-targeted, the idea is that these registers 20 | -- will get implemented as dual-port Distributed RAM. Because there is no 21 | -- such thing as triple-port memory in an FPGA (that I know of), and we 22 | -- need 3 ports to support 2 reads and 1 write per cycle, the easiest way 23 | -- to implement that is to have two identical banks of registers that contain 24 | -- the same data. Each uses 2 ports and everybody's happy. 25 | -- 26 | architecture rtl of regfile is 27 | type regbank_t is array (0 to 31) of word; 28 | 29 | signal regbank0 : regbank_t := (others => (others => '0')); 30 | signal regbank1 : regbank_t := (others => (others => '0')); 31 | begin -- architecture Behavioral 32 | 33 | -- purpose: create registers 34 | -- type : sequential 35 | -- inputs : clk 36 | -- outputs: 37 | registers_proc : process (clk) is 38 | begin -- process registers_proc 39 | if rising_edge(clk) then 40 | if (we = '1') then 41 | regbank0(to_integer(unsigned(addrw))) <= dataw; 42 | regbank1(to_integer(unsigned(addrw))) <= dataw; 43 | end if; 44 | end if; 45 | end process registers_proc; 46 | 47 | -- asynchronous read 48 | rega <= regbank0(to_integer(unsigned(addra))); 49 | regb <= regbank1(to_integer(unsigned(addrb))); 50 | 51 | end architecture rtl; 52 | -------------------------------------------------------------------------------- /src/sim-pipeline.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | REM ghdl -r pipeline_tb --stack-size=500000000 --vcd=pipeline_tb.vcd 4 | REM gtkwave decoder_tb.vcd 5 | REM decode_pkg.vhd 6 | 7 | del *.cf *.vcd 8 | ghdl -a common.vhd id_pkg.vhd decode.vhd encode_pkg.vhd alu.vhd compare_unit.vhd ex_pkg.vhd ex.vhd id.vhd if_pkg.vhd if.vhd regfile.vhd pipeline.vhd dpram.vhd ../tests/pipeline_tb.vhd 9 | ghdl -e pipeline_tb 10 | ghdl -r pipeline_tb --vcd=pipeline_tb.vcd 11 | -------------------------------------------------------------------------------- /src/std_logic_textio.vhd: -------------------------------------------------------------------------------- 1 | -- std_logic_textio.vhdl 2 | ---------------------------------------------------------------------------- 3 | -- 4 | -- Copyright (c) 1990, 1991, 1992 by Synopsys, Inc. All rights reserved. 5 | -- 6 | -- This source file may be used and distributed without restriction 7 | -- provided that this copyright statement is not removed from the file 8 | -- and that any derivative work contains this copyright notice. 9 | -- 10 | -- Package name: STD_LOGIC_TEXTIO 11 | -- 12 | -- Purpose: This package overloads the standard TEXTIO procedures 13 | -- READ and WRITE. 14 | -- 15 | -- Author: CRC, TS 16 | -- 17 | ---------------------------------------------------------------------------- 18 | 19 | use STD.textio.all; 20 | library IEEE; 21 | use IEEE.std_logic_1164.all; 22 | 23 | package STD_LOGIC_TEXTIO is 24 | --synopsys synthesis_off 25 | -- Read and Write procedures for STD_ULOGIC and STD_ULOGIC_VECTOR 26 | procedure READ(L:inout LINE; VALUE:out STD_ULOGIC); 27 | procedure READ(L:inout LINE; VALUE:out STD_ULOGIC; GOOD: out BOOLEAN); 28 | procedure READ(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR); 29 | procedure READ(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR; GOOD: out BOOLEAN); 30 | procedure WRITE(L:inout LINE; VALUE:in STD_ULOGIC; 31 | JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); 32 | procedure WRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR; 33 | JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); 34 | 35 | -- Read and Write procedures for STD_LOGIC_VECTOR 36 | procedure READ(L:inout LINE; VALUE:out STD_LOGIC_VECTOR); 37 | procedure READ(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out BOOLEAN); 38 | procedure WRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR; 39 | JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); 40 | 41 | -- 42 | -- Read and Write procedures for Hex and Octal values. 43 | -- The values appear in the file as a series of characters 44 | -- between 0-F (Hex), or 0-7 (Octal) respectively. 45 | -- 46 | 47 | -- Hex 48 | procedure HREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR); 49 | procedure HREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR; GOOD: out BOOLEAN); 50 | procedure HWRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR; 51 | JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); 52 | procedure HREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR); 53 | procedure HREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out BOOLEAN); 54 | procedure HWRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR; 55 | JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); 56 | 57 | -- Octal 58 | procedure OREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR); 59 | procedure OREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR; GOOD: out BOOLEAN); 60 | procedure OWRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR; 61 | JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); 62 | procedure OREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR); 63 | procedure OREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out BOOLEAN); 64 | procedure OWRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR; 65 | JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0); 66 | 67 | 68 | --synopsys synthesis_on 69 | end STD_LOGIC_TEXTIO; 70 | 71 | package body STD_LOGIC_TEXTIO is 72 | --synopsys synthesis_off 73 | 74 | -- Type and constant definitions used to map STD_ULOGIC values 75 | -- into/from character values. 76 | 77 | type MVL9plus is ('U', 'X', '0', '1', 'Z', 'W', 'L', 'H', '-', ERROR); 78 | type char_indexed_by_MVL9 is array (STD_ULOGIC) of character; 79 | type MVL9_indexed_by_char is array (character) of STD_ULOGIC; 80 | type MVL9plus_indexed_by_char is array (character) of MVL9plus; 81 | 82 | constant MVL9_to_char: char_indexed_by_MVL9 := "UX01ZWLH-"; 83 | constant char_to_MVL9: MVL9_indexed_by_char := 84 | ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z', 85 | 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => 'U'); 86 | constant char_to_MVL9plus: MVL9plus_indexed_by_char := 87 | ('U' => 'U', 'X' => 'X', '0' => '0', '1' => '1', 'Z' => 'Z', 88 | 'W' => 'W', 'L' => 'L', 'H' => 'H', '-' => '-', others => ERROR); 89 | 90 | 91 | -- Overloaded procedures. 92 | 93 | procedure READ(L:inout LINE; VALUE:out STD_ULOGIC; GOOD:out BOOLEAN) is 94 | variable c: character; 95 | begin 96 | loop -- skip white space 97 | read(l,c); 98 | exit when ((c /= ' ') and (c /= CR) and (c /= HT)); 99 | end loop; 100 | 101 | if (char_to_MVL9plus(c) = ERROR) then 102 | value := 'U'; 103 | good := FALSE; 104 | else 105 | value := char_to_MVL9(c); 106 | good := TRUE; 107 | end if; 108 | end READ; 109 | 110 | procedure READ(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR; GOOD:out BOOLEAN) is 111 | variable m: STD_ULOGIC; 112 | variable c: character; 113 | variable s: string(1 to value'length-1); 114 | variable mv: STD_ULOGIC_VECTOR(0 to value'length-1); 115 | constant allU: STD_ULOGIC_VECTOR(0 to value'length-1) 116 | := (others => 'U'); 117 | begin 118 | loop -- skip white space 119 | read(l,c); 120 | exit when ((c /= ' ') and (c /= CR) and (c /= HT)); 121 | end loop; 122 | 123 | if (char_to_MVL9plus(c) = ERROR) then 124 | value := allU; 125 | good := FALSE; 126 | return; 127 | end if; 128 | 129 | read(l, s); 130 | for i in 1 to value'length-1 loop 131 | if (char_to_MVL9plus(s(i)) = ERROR) then 132 | value := allU; 133 | good := FALSE; 134 | return; 135 | end if; 136 | end loop; 137 | 138 | mv(0) := char_to_MVL9(c); 139 | for i in 1 to value'length-1 loop 140 | mv(i) := char_to_MVL9(s(i)); 141 | end loop; 142 | value := mv; 143 | good := TRUE; 144 | end READ; 145 | 146 | procedure READ(L:inout LINE; VALUE:out STD_ULOGIC) is 147 | variable c: character; 148 | begin 149 | loop -- skip white space 150 | read(l,c); 151 | exit when ((c /= ' ') and (c /= CR) and (c /= HT)); 152 | end loop; 153 | 154 | if (char_to_MVL9plus(c) = ERROR) then 155 | value := 'U'; 156 | assert FALSE report "READ(STD_ULOGIC) Error: Character '" & 157 | c & "' read, expected STD_ULOGIC literal."; 158 | else 159 | value := char_to_MVL9(c); 160 | end if; 161 | end READ; 162 | 163 | procedure READ(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR) is 164 | variable m: STD_ULOGIC; 165 | variable c: character; 166 | variable s: string(1 to value'length-1); 167 | variable mv: STD_ULOGIC_VECTOR(0 to value'length-1); 168 | constant allU: STD_ULOGIC_VECTOR(0 to value'length-1) 169 | := (others => 'U'); 170 | begin 171 | loop -- skip white space 172 | read(l,c); 173 | exit when ((c /= ' ') and (c /= CR) and (c /= HT)); 174 | end loop; 175 | 176 | if (char_to_MVL9plus(c) = ERROR) then 177 | value := allU; 178 | assert FALSE report 179 | "READ(STD_ULOGIC_VECTOR) Error: Character '" & 180 | c & "' read, expected STD_ULOGIC literal."; 181 | return; 182 | end if; 183 | 184 | read(l, s); 185 | for i in 1 to value'length-1 loop 186 | if (char_to_MVL9plus(s(i)) = ERROR) then 187 | value := allU; 188 | assert FALSE report 189 | "READ(STD_ULOGIC_VECTOR) Error: Character '" & 190 | s(i) & "' read, expected STD_ULOGIC literal."; 191 | return; 192 | end if; 193 | end loop; 194 | 195 | mv(0) := char_to_MVL9(c); 196 | for i in 1 to value'length-1 loop 197 | mv(i) := char_to_MVL9(s(i)); 198 | end loop; 199 | value := mv; 200 | end READ; 201 | 202 | procedure WRITE(L:inout LINE; VALUE:in STD_ULOGIC; 203 | JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is 204 | begin 205 | write(l, MVL9_to_char(value), justified, field); 206 | end WRITE; 207 | 208 | 209 | procedure WRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR; 210 | JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is 211 | variable s: string(1 to value'length); 212 | variable m: STD_ULOGIC_VECTOR(1 to value'length) := value; 213 | begin 214 | for i in 1 to value'length loop 215 | s(i) := MVL9_to_char(m(i)); 216 | end loop; 217 | write(l, s, justified, field); 218 | end WRITE; 219 | 220 | -- Read and Write procedures for STD_LOGIC_VECTOR 221 | procedure READ(L:inout LINE; VALUE:out STD_LOGIC_VECTOR) is 222 | variable tmp: STD_ULOGIC_VECTOR(VALUE'length-1 downto 0); 223 | begin 224 | READ(L, tmp); 225 | VALUE := STD_LOGIC_VECTOR(tmp); 226 | end READ; 227 | 228 | procedure READ(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out BOOLEAN) is 229 | variable tmp: STD_ULOGIC_VECTOR(VALUE'length-1 downto 0); 230 | begin 231 | READ(L, tmp, GOOD); 232 | VALUE := STD_LOGIC_VECTOR(tmp); 233 | end READ; 234 | 235 | procedure WRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR; 236 | JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is 237 | begin 238 | WRITE(L, STD_ULOGIC_VECTOR(VALUE), JUSTIFIED, FIELD); 239 | end WRITE; 240 | 241 | 242 | -- 243 | -- Hex Read and Write procedures. 244 | -- 245 | 246 | -- 247 | -- Hex, and Octal Read and Write procedures for BIT_VECTOR 248 | -- (these procedures are not exported, they are only used 249 | -- by the STD_ULOGIC hex/octal reads and writes below. 250 | -- 251 | -- 252 | 253 | procedure Char2QuadBits(C: Character; 254 | RESULT: out Bit_Vector(3 downto 0); 255 | GOOD: out Boolean; 256 | ISSUE_ERROR: in Boolean) is 257 | begin 258 | case c is 259 | when '0' => result := x"0"; good := TRUE; 260 | when '1' => result := x"1"; good := TRUE; 261 | when '2' => result := x"2"; good := TRUE; 262 | when '3' => result := x"3"; good := TRUE; 263 | when '4' => result := x"4"; good := TRUE; 264 | when '5' => result := x"5"; good := TRUE; 265 | when '6' => result := x"6"; good := TRUE; 266 | when '7' => result := x"7"; good := TRUE; 267 | when '8' => result := x"8"; good := TRUE; 268 | when '9' => result := x"9"; good := TRUE; 269 | when 'A' => result := x"A"; good := TRUE; 270 | when 'B' => result := x"B"; good := TRUE; 271 | when 'C' => result := x"C"; good := TRUE; 272 | when 'D' => result := x"D"; good := TRUE; 273 | when 'E' => result := x"E"; good := TRUE; 274 | when 'F' => result := x"F"; good := TRUE; 275 | 276 | when 'a' => result := x"A"; good := TRUE; 277 | when 'b' => result := x"B"; good := TRUE; 278 | when 'c' => result := x"C"; good := TRUE; 279 | when 'd' => result := x"D"; good := TRUE; 280 | when 'e' => result := x"E"; good := TRUE; 281 | when 'f' => result := x"F"; good := TRUE; 282 | when others => 283 | if ISSUE_ERROR then 284 | assert FALSE report 285 | "HREAD Error: Read a '" & c & 286 | "', expected a Hex character (0-F)."; 287 | end if; 288 | good := FALSE; 289 | end case; 290 | end; 291 | 292 | procedure HREAD(L:inout LINE; VALUE:out BIT_VECTOR) is 293 | variable ok: boolean; 294 | variable c: character; 295 | constant ne: integer := value'length/4; 296 | variable bv: bit_vector(0 to value'length-1); 297 | variable s: string(1 to ne-1); 298 | begin 299 | if value'length mod 4 /= 0 then 300 | assert FALSE report 301 | "HREAD Error: Trying to read vector " & 302 | "with an odd (non multiple of 4) length"; 303 | return; 304 | end if; 305 | 306 | loop -- skip white space 307 | read(l,c); 308 | exit when ((c /= ' ') and (c /= CR) and (c /= HT)); 309 | end loop; 310 | 311 | Char2QuadBits(c, bv(0 to 3), ok, TRUE); 312 | if not ok then 313 | return; 314 | end if; 315 | 316 | read(L, s, ok); 317 | if not ok then 318 | assert FALSE 319 | report "HREAD Error: Failed to read the STRING"; 320 | return; 321 | end if; 322 | 323 | for i in 1 to ne-1 loop 324 | Char2QuadBits(s(i), bv(4*i to 4*i+3), ok, TRUE); 325 | if not ok then 326 | return; 327 | end if; 328 | end loop; 329 | value := bv; 330 | end HREAD; 331 | 332 | procedure HREAD(L:inout LINE; VALUE:out BIT_VECTOR;GOOD: out BOOLEAN) is 333 | variable ok: boolean; 334 | variable c: character; 335 | constant ne: integer := value'length/4; 336 | variable bv: bit_vector(0 to value'length-1); 337 | variable s: string(1 to ne-1); 338 | begin 339 | if value'length mod 4 /= 0 then 340 | good := FALSE; 341 | return; 342 | end if; 343 | 344 | loop -- skip white space 345 | read(l,c); 346 | exit when ((c /= ' ') and (c /= CR) and (c /= HT)); 347 | end loop; 348 | 349 | Char2QuadBits(c, bv(0 to 3), ok, FALSE); 350 | if not ok then 351 | good := FALSE; 352 | return; 353 | end if; 354 | 355 | read(L, s, ok); 356 | if not ok then 357 | good := FALSE; 358 | return; 359 | end if; 360 | 361 | for i in 1 to ne-1 loop 362 | Char2QuadBits(s(i), bv(4*i to 4*i+3), ok, FALSE); 363 | if not ok then 364 | good := FALSE; 365 | return; 366 | end if; 367 | end loop; 368 | good := TRUE; 369 | value := bv; 370 | end HREAD; 371 | 372 | 373 | procedure HWRITE(L:inout LINE; VALUE:in BIT_VECTOR; 374 | JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is 375 | variable quad: bit_vector(0 to 3); 376 | constant ne: integer := value'length/4; 377 | variable bv: bit_vector(0 to value'length-1) := value; 378 | variable s: string(1 to ne); 379 | begin 380 | if value'length mod 4 /= 0 then 381 | assert FALSE report 382 | "HWRITE Error: Trying to read vector " & 383 | "with an odd (non multiple of 4) length"; 384 | return; 385 | end if; 386 | 387 | for i in 0 to ne-1 loop 388 | quad := bv(4*i to 4*i+3); 389 | case quad is 390 | when x"0" => s(i+1) := '0'; 391 | when x"1" => s(i+1) := '1'; 392 | when x"2" => s(i+1) := '2'; 393 | when x"3" => s(i+1) := '3'; 394 | when x"4" => s(i+1) := '4'; 395 | when x"5" => s(i+1) := '5'; 396 | when x"6" => s(i+1) := '6'; 397 | when x"7" => s(i+1) := '7'; 398 | when x"8" => s(i+1) := '8'; 399 | when x"9" => s(i+1) := '9'; 400 | when x"A" => s(i+1) := 'A'; 401 | when x"B" => s(i+1) := 'B'; 402 | when x"C" => s(i+1) := 'C'; 403 | when x"D" => s(i+1) := 'D'; 404 | when x"E" => s(i+1) := 'E'; 405 | when x"F" => s(i+1) := 'F'; 406 | end case; 407 | end loop; 408 | write(L, s, JUSTIFIED, FIELD); 409 | end HWRITE; 410 | 411 | procedure Char2TriBits(C: Character; 412 | RESULT: out bit_vector(2 downto 0); 413 | GOOD: out Boolean; 414 | ISSUE_ERROR: in Boolean) is 415 | begin 416 | case c is 417 | when '0' => result := o"0"; good := TRUE; 418 | when '1' => result := o"1"; good := TRUE; 419 | when '2' => result := o"2"; good := TRUE; 420 | when '3' => result := o"3"; good := TRUE; 421 | when '4' => result := o"4"; good := TRUE; 422 | when '5' => result := o"5"; good := TRUE; 423 | when '6' => result := o"6"; good := TRUE; 424 | when '7' => result := o"7"; good := TRUE; 425 | when others => 426 | if ISSUE_ERROR then 427 | assert FALSE report 428 | "OREAD Error: Read a '" & c & 429 | "', expected an Octal character (0-7)."; 430 | end if; 431 | good := FALSE; 432 | end case; 433 | end; 434 | 435 | procedure OREAD(L:inout LINE; VALUE:out BIT_VECTOR) is 436 | variable c: character; 437 | variable ok: boolean; 438 | constant ne: integer := value'length/3; 439 | variable bv: bit_vector(0 to value'length-1); 440 | variable s: string(1 to ne-1); 441 | begin 442 | if value'length mod 3 /= 0 then 443 | assert FALSE report 444 | "OREAD Error: Trying to read vector " & 445 | "with an odd (non multiple of 3) length"; 446 | return; 447 | end if; 448 | 449 | loop -- skip white space 450 | read(l,c); 451 | exit when ((c /= ' ') and (c /= CR) and (c /= HT)); 452 | end loop; 453 | 454 | Char2TriBits(c, bv(0 to 2), ok, TRUE); 455 | if not ok then 456 | return; 457 | end if; 458 | 459 | read(L, s, ok); 460 | if not ok then 461 | assert FALSE 462 | report "OREAD Error: Failed to read the STRING"; 463 | return; 464 | end if; 465 | 466 | for i in 1 to ne-1 loop 467 | Char2TriBits(s(i), bv(3*i to 3*i+2), ok, TRUE); 468 | if not ok then 469 | return; 470 | end if; 471 | end loop; 472 | value := bv; 473 | end OREAD; 474 | 475 | procedure OREAD(L:inout LINE; VALUE:out BIT_VECTOR;GOOD: out BOOLEAN) is 476 | variable ok: boolean; 477 | variable c: character; 478 | constant ne: integer := value'length/3; 479 | variable bv: bit_vector(0 to value'length-1); 480 | variable s: string(1 to ne-1); 481 | begin 482 | if value'length mod 3 /= 0 then 483 | good := FALSE; 484 | return; 485 | end if; 486 | 487 | loop -- skip white space 488 | read(l,c); 489 | exit when ((c /= ' ') and (c /= CR) and (c /= HT)); 490 | end loop; 491 | 492 | Char2TriBits(c, bv(0 to 2), ok, FALSE); 493 | if not ok then 494 | good := FALSE; 495 | return; 496 | end if; 497 | 498 | read(L, s, ok); 499 | if not ok then 500 | good := FALSE; 501 | return; 502 | end if; 503 | 504 | for i in 1 to ne-1 loop 505 | Char2TriBits(s(i), bv(3*i to 3*i+2), ok, FALSE); 506 | if not ok then 507 | good := FALSE; 508 | return; 509 | end if; 510 | end loop; 511 | good := TRUE; 512 | value := bv; 513 | end OREAD; 514 | 515 | 516 | procedure OWRITE(L:inout LINE; VALUE:in BIT_VECTOR; 517 | JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is 518 | variable tri: bit_vector(0 to 2); 519 | constant ne: integer := value'length/3; 520 | variable bv: bit_vector(0 to value'length-1) := value; 521 | variable s: string(1 to ne); 522 | begin 523 | if value'length mod 3 /= 0 then 524 | assert FALSE report 525 | "OWRITE Error: Trying to read vector " & 526 | "with an odd (non multiple of 3) length"; 527 | return; 528 | end if; 529 | 530 | for i in 0 to ne-1 loop 531 | tri := bv(3*i to 3*i+2); 532 | case tri is 533 | when o"0" => s(i+1) := '0'; 534 | when o"1" => s(i+1) := '1'; 535 | when o"2" => s(i+1) := '2'; 536 | when o"3" => s(i+1) := '3'; 537 | when o"4" => s(i+1) := '4'; 538 | when o"5" => s(i+1) := '5'; 539 | when o"6" => s(i+1) := '6'; 540 | when o"7" => s(i+1) := '7'; 541 | end case; 542 | end loop; 543 | write(L, s, JUSTIFIED, FIELD); 544 | end OWRITE; 545 | 546 | -- Hex Read and Write procedures for STD_LOGIC_VECTOR 547 | procedure HREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR;GOOD:out BOOLEAN) is 548 | variable tmp: bit_vector(VALUE'length-1 downto 0); 549 | begin 550 | HREAD(L, tmp, GOOD); 551 | VALUE := To_X01(tmp); 552 | end HREAD; 553 | 554 | procedure HREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR) is 555 | variable tmp: bit_vector(VALUE'length-1 downto 0); 556 | begin 557 | HREAD(L, tmp); 558 | VALUE := To_X01(tmp); 559 | end HREAD; 560 | 561 | procedure HWRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR; 562 | JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is 563 | begin 564 | HWRITE(L, To_bitvector(VALUE),JUSTIFIED, FIELD); 565 | end HWRITE; 566 | 567 | -- Hex Read and Write procedures for STD_LOGIC_VECTOR 568 | 569 | procedure HREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR) is 570 | variable tmp: STD_ULOGIC_VECTOR(VALUE'length-1 downto 0); 571 | begin 572 | HREAD(L, tmp); 573 | VALUE := STD_LOGIC_VECTOR(tmp); 574 | end HREAD; 575 | 576 | procedure HREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out BOOLEAN) is 577 | variable tmp: STD_ULOGIC_VECTOR(VALUE'length-1 downto 0); 578 | begin 579 | HREAD(L, tmp, GOOD); 580 | VALUE := STD_LOGIC_VECTOR(tmp); 581 | end HREAD; 582 | 583 | procedure HWRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR; 584 | JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is 585 | begin 586 | HWRITE(L, To_bitvector(VALUE), JUSTIFIED, FIELD); 587 | end HWRITE; 588 | 589 | 590 | -- Octal Read and Write procedures for STD_ULOGIC_VECTOR 591 | procedure OREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR;GOOD:out BOOLEAN) is 592 | variable tmp: bit_vector(VALUE'length-1 downto 0); 593 | begin 594 | OREAD(L, tmp, GOOD); 595 | VALUE := To_X01(tmp); 596 | end OREAD; 597 | 598 | procedure OREAD(L:inout LINE; VALUE:out STD_ULOGIC_VECTOR) is 599 | variable tmp: bit_vector(VALUE'length-1 downto 0); 600 | begin 601 | OREAD(L, tmp); 602 | VALUE := To_X01(tmp); 603 | end OREAD; 604 | 605 | procedure OWRITE(L:inout LINE; VALUE:in STD_ULOGIC_VECTOR; 606 | JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is 607 | begin 608 | OWRITE(L, To_bitvector(VALUE),JUSTIFIED, FIELD); 609 | end OWRITE; 610 | 611 | -- Octal Read and Write procedures for STD_LOGIC_VECTOR 612 | 613 | procedure OREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR) is 614 | variable tmp: STD_ULOGIC_VECTOR(VALUE'length-1 downto 0); 615 | begin 616 | OREAD(L, tmp); 617 | VALUE := STD_LOGIC_VECTOR(tmp); 618 | end OREAD; 619 | 620 | procedure OREAD(L:inout LINE; VALUE:out STD_LOGIC_VECTOR; GOOD: out BOOLEAN) is 621 | variable tmp: STD_ULOGIC_VECTOR(VALUE'length-1 downto 0); 622 | begin 623 | OREAD(L, tmp, GOOD); 624 | VALUE := STD_LOGIC_VECTOR(tmp); 625 | end OREAD; 626 | 627 | procedure OWRITE(L:inout LINE; VALUE:in STD_LOGIC_VECTOR; 628 | JUSTIFIED:in SIDE := RIGHT; FIELD:in WIDTH := 0) is 629 | begin 630 | OWRITE(L, STD_ULOGIC_VECTOR(VALUE), JUSTIFIED, FIELD); 631 | end OWRITE; 632 | 633 | 634 | --synopsys synthesis_on 635 | end STD_LOGIC_TEXTIO; 636 | -------------------------------------------------------------------------------- /tests/compare_tb.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | use std.textio.all; 4 | 5 | use work.common.all; 6 | use work.id_pkg.all; 7 | 8 | entity compare_tb is 9 | end entity compare_tb; 10 | 11 | architecture test of compare_tb is 12 | signal branch_type : branch_type_t; 13 | signal op1 : word; 14 | signal op2 : word; 15 | signal compare_result : std_logic; 16 | begin -- architecture test 17 | 18 | uut : entity work.compare_unit(behavioral) 19 | port map ( 20 | branch_type => branch_type, 21 | op1 => op1, 22 | op2 => op2, 23 | compare_result => compare_result); 24 | 25 | process 26 | begin 27 | ---------------------------------------------------------------- 28 | -- BEQ 29 | ---------------------------------------------------------------- 30 | println("BEQ"); 31 | 32 | branch_type <= BEQ; 33 | op1 <= "00010001000100010001000100010001"; 34 | op2 <= "00010001000100010001000100010001"; 35 | wait for 1 ns; 36 | assert compare_result = '1' report "Invalid BEQ" severity error; 37 | 38 | op2 <= "00010001000100010001000100010000"; 39 | wait for 1 ns; 40 | assert compare_result = '0' report "Invalid BEQ" severity error; 41 | 42 | ---------------------------------------------------------------- 43 | -- BNE 44 | ---------------------------------------------------------------- 45 | println("BNE"); 46 | 47 | branch_type <= BNE; 48 | wait for 1 ns; 49 | assert compare_result = '1' report "Invalid BNE" severity error; 50 | 51 | op2 <= "00010001000100010001000100010001"; 52 | wait for 1 ns; 53 | assert compare_result = '0' report "Invalid BNE" severity error; 54 | 55 | ---------------------------------------------------------------- 56 | -- BLT 57 | ---------------------------------------------------------------- 58 | println("BLT"); 59 | 60 | branch_type <= BLT; 61 | op1 <= "00000000000000000000000000000001"; 62 | op2 <= "00000000000000000000000000000000"; 63 | wait for 1 ns; 64 | assert compare_result = '0' report "Invalid BLT" severity error; 65 | 66 | op1 <= "00000000000000000000000000000010"; 67 | wait for 1 ns; 68 | assert compare_result = '0' report "Invalid BLT" severity error; 69 | 70 | op2 <= "01111111111111111111111111111111"; 71 | wait for 1 ns; 72 | assert compare_result = '1' report "Invalid BLT" severity error; 73 | 74 | ---------------------------------------------------------------- 75 | -- BGE 76 | ---------------------------------------------------------------- 77 | println("BGE"); 78 | 79 | branch_type <= BGE; 80 | wait for 1 ns; 81 | assert compare_result = '0' report "Invalid BGE" severity error; 82 | 83 | op1 <= "00000000000000000000000000000010"; 84 | op2 <= "00000000000000000000000000000010"; 85 | wait for 1 ns; 86 | assert compare_result = '1' report "Invalid BGE" severity error; 87 | 88 | op1 <= "11111111111111111111111111111111"; 89 | wait for 1 ns; 90 | assert compare_result = '0' report "Invalid BGE" severity error; 91 | 92 | op2 <= "11111111111111111111111111111110"; 93 | wait for 1 ns; 94 | assert compare_result = '1' report "Invalid BGE" severity error; 95 | 96 | ---------------------------------------------------------------- 97 | -- BLTU 98 | ---------------------------------------------------------------- 99 | println("BLTU"); 100 | 101 | branch_type <= BLTU; 102 | wait for 1 ns; 103 | assert compare_result = '0' report "Invalid BLTU" severity error; 104 | 105 | op1 <= "11111111111111111111111111111100"; 106 | wait for 1 ns; 107 | assert compare_result = '1' report "Invalid BLTU" severity error; 108 | 109 | op2 <= "11111111111111111111111111111100"; 110 | wait for 1 ns; 111 | assert compare_result = '0' report "Invalid BLTU" severity error; 112 | 113 | ---------------------------------------------------------------- 114 | -- BGEU 115 | ---------------------------------------------------------------- 116 | println("BGEU"); 117 | 118 | branch_type <= BGEU; 119 | wait for 1 ns; 120 | assert compare_result = '1' report "Invalid BGEU" severity error; 121 | 122 | op1 <= "00000000000000000000000000000000"; 123 | op2 <= "00000000000000000000000000000000"; 124 | wait for 1 ns; 125 | assert compare_result = '1' report "Invalid BGEU" severity error; 126 | 127 | op1 <= "00000000000000000000000000000001"; 128 | wait for 1 ns; 129 | assert compare_result = '1' report "Invalid BGEU" severity error; 130 | 131 | op1 <= "11111111111111111111111111111111"; 132 | op2 <= "11111111111111111111111111111110"; 133 | wait for 1 ns; 134 | assert compare_result = '1' report "Invalid BGEU" severity error; 135 | 136 | ---------------------------------------------------------------- 137 | println("Simulation complete"); 138 | ---------------------------------------------------------------- 139 | 140 | wait; 141 | 142 | end process; 143 | 144 | end architecture test; 145 | -------------------------------------------------------------------------------- /tests/decoder_tb.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | 4 | use work.id_pkg.all; 5 | use work.common.all; 6 | use work.encode_pkg.all; 7 | 8 | entity decoder_tb is 9 | end entity decoder_tb; 10 | 11 | architecture testbench of decoder_tb is 12 | -- inputs 13 | signal insn : word; 14 | -- outputs 15 | signal decoded : decoded_t; 16 | 17 | procedure verify_r_type (insn_type : in insn_type_t; 18 | r_insn : in r_insn_t; 19 | rs1, rs2, d : in std_logic_vector(4 downto 0)) is 20 | begin 21 | print_insn(insn_type); 22 | assert decoded.insn_type = insn_type report "Invalid instruction type" severity error; 23 | case (r_insn) is 24 | when R_ADD => assert decoded.alu_func = ALU_ADD report "Invalid ALU function" severity error; 25 | when R_SLT => assert decoded.alu_func = ALU_SLT report "Invalid ALU function" severity error; 26 | when R_SLTU => assert decoded.alu_func = ALU_SLTU report "Invalid ALU function" severity error; 27 | when R_AND => assert decoded.alu_func = ALU_AND report "Invalid ALU function" severity error; 28 | when R_OR => assert decoded.alu_func = ALU_OR report "Invalid ALU function" severity error; 29 | when R_XOR => assert decoded.alu_func = ALU_XOR report "Invalid ALU function" severity error; 30 | when R_SLL => assert decoded.alu_func = ALU_SLL report "Invalid ALU function" severity error; 31 | when R_SRL => assert decoded.alu_func = ALU_SRL report "Invalid ALU function" severity error; 32 | when R_SUB => assert decoded.alu_func = ALU_SUB report "Invalid ALU function" severity error; 33 | when R_SRA => assert decoded.alu_func = ALU_SRA report "Invalid ALU function" severity error; 34 | end case; 35 | end procedure verify_r_type; 36 | 37 | -- purpose: verify U-type instruction 38 | procedure verify_u_type ( 39 | insn_type : in insn_type_t; 40 | imm : in word; 41 | rd : in std_logic_vector(4 downto 0)) is 42 | begin 43 | print_insn(insn_type); 44 | assert decoded.insn_type = insn_type report "Invalid instruction type" severity error; 45 | assert decoded.imm = imm report "Invalid Immediate Value" severity error; 46 | assert decoded.rd = rd report "Invalid Rd" severity error; 47 | end procedure verify_u_type; 48 | 49 | -- purpose: verify UJ-type instruction 50 | procedure verify_uj_type ( 51 | insn_type : in insn_type_t; 52 | imm : in word; 53 | rd : in std_logic_vector(4 downto 0)) is 54 | begin -- procedure verify_uj_type 55 | print_insn(insn_type); 56 | assert decoded.insn_type = insn_type report "Invalid instruction type" severity error; 57 | assert decoded.imm = imm report "Invalid immediate" severity error; 58 | assert decoded.rd = rd report "Invalid Rd" severity error; 59 | end procedure verify_uj_type; 60 | 61 | -- purpose: verify a decoded I-type instruction 62 | procedure verify_i_type (insn_type : in insn_type_t; 63 | i_type : in i_insn_t; 64 | imm : in word; 65 | rs1, rd : in std_logic_vector(4 downto 0)) is 66 | begin -- procedure verify_i_type 67 | print_insn(insn_type); 68 | assert decoded.insn_type = insn_type report "Invalid instruction type" severity error; 69 | assert decoded.imm = imm report "Invalid immediate" severity error; 70 | assert decoded.rs1 = rs1 report "Invalid Rs1" severity error; 71 | assert decoded.rd = rd report "Invalid Rd" severity error; 72 | case (insn_type) is 73 | when OP_LOAD => 74 | case i_type is 75 | when I_LB => assert decoded.load_type = LB report "Invalid load type" severity error; 76 | when I_LH => assert decoded.load_type = LH report "Invalid load type" severity error; 77 | when I_LW => assert decoded.load_type = LW report "Invalid load type" severity error; 78 | when I_LBU => assert decoded.load_type = LBU report "Invalid load type" severity error; 79 | when I_LHU => assert decoded.load_type = LHU report "Invalid load type" severity error; 80 | when others => assert false report "Unexpected load type" severity error; 81 | end case; 82 | when OP_ALU => 83 | case i_type is 84 | when I_ADDI => assert decoded.alu_func = ALU_ADD report "Invalid ALU function" severity error; 85 | when I_SLTI => assert decoded.alu_func = ALU_SLT report "Invalid ALU function" severity error; 86 | when I_SLTIU => assert decoded.alu_func = ALU_SLTU report "Invalid ALU function" severity error; 87 | when I_XORI => assert decoded.alu_func = ALU_XOR report "Invalid ALU function" severity error; 88 | when I_ORI => assert decoded.alu_func = ALU_OR report "Invalid ALU function" severity error; 89 | when I_ANDI => assert decoded.alu_func = ALU_AND report "Invalid ALU function" severity error; 90 | when others => assert false report "Unexpected ALU function" severity error; 91 | end case; 92 | when OP_JALR => null; 93 | when others => 94 | assert false report "Unexpected instruction type" severity error; 95 | end case; 96 | end procedure verify_i_type; 97 | 98 | procedure verify_s_type (insn_type : in insn_type_t; 99 | s_type : in s_insn_t; 100 | imm : in word; 101 | rs1, rs2 : in std_logic_vector(4 downto 0)) is 102 | begin 103 | print_insn(insn_type); 104 | assert decoded.insn_type = insn_type report "Invalid instruction type" severity error; 105 | assert decoded.imm = imm report "" severity error; 106 | assert decoded.rs1 = rs1 report "Invalid Rs1" severity error; 107 | assert decoded.rs2 = rs2 report "Invalid Rs2" severity error; 108 | case s_type is 109 | when S_SB => assert decoded.store_type = SB report "Invalid store type" severity error; 110 | when S_SH => assert decoded.store_type = SH report "Invalid store type" severity error; 111 | when S_SW => assert decoded.store_type = SW report "Invalid store type" severity error; 112 | when others => assert false report "Unexpected store type" severity error; 113 | end case; 114 | end procedure verify_s_type; 115 | 116 | -- purpose: verify a decoded SB-type instruction 117 | procedure verify_sb_type ( 118 | insn_type : in insn_type_t; 119 | imm : in word; 120 | branch_type : in branch_type_t; 121 | rs1, rs2 : in std_logic_vector(4 downto 0)) is 122 | begin -- procedure verify_sb_type 123 | print_insn(insn_type); 124 | assert decoded.insn_type = insn_type report "Invalid instruction type" severity error; 125 | assert decoded.imm = imm report "Invalid immediate" severity error; 126 | assert decoded.branch_type = branch_type report "Invalid branch type" severity error; 127 | assert decoded.rs1 = rs1 report "Invalid Rs1" severity error; 128 | assert decoded.rs2 = rs2 report "Invalid Rs2" severity error; 129 | end procedure verify_sb_type; 130 | 131 | -- purpose: verify a decoded I-type shift instruction 132 | procedure verify_i_shift ( 133 | i_insn : in i_insn_t; 134 | shamt : in std_logic_vector(4 downto 0); 135 | rs1, rd : in std_logic_vector(4 downto 0)) is 136 | begin -- procedure verify_i_shift 137 | println("Instruction type: ALU SHIFT"); 138 | assert decoded.insn_type = OP_ALU report "Expected OP_ALU" severity error; 139 | case i_insn is 140 | when I_SLLI => 141 | assert decoded.alu_func = ALU_SLL report "Invalid ALU type" severity error; 142 | when I_SRLI => 143 | assert decoded.alu_func = ALU_SRL report "Invalid ALU type" severity error; 144 | when I_SRAI => 145 | assert decoded.alu_func = ALU_SRA report "Invalid ALU type" severity error; 146 | when others => 147 | assert false report "Invalid Shift type" severity error; 148 | end case; 149 | 150 | end procedure verify_i_shift; 151 | 152 | begin -- architecture test 153 | 154 | uut : entity work.instruction_decoder(behavioral) 155 | port map (d => insn, 156 | q => decoded); 157 | 158 | -- purpose: provide stimulus and verification of the RISCV decoder 159 | -- type : combinational 160 | -- inputs : 161 | -- outputs: asserts 162 | stimulus_proc : process is 163 | begin -- process stimulus_proc 164 | 165 | -- LUI 166 | insn <= encode_u_type(U_LUI, "01010101010101010101", 31); 167 | wait for 1 ns; 168 | verify_u_type(OP_LUI, "01010101010101010101000000000000", "11111"); 169 | 170 | -- AUIPC 171 | insn <= encode_u_type(U_AUIPC, "10101010101010101010", 21); 172 | wait for 1 ns; 173 | verify_u_type(OP_AUIPC, "10101010101010101010000000000000", "10101"); 174 | 175 | -- JAL 176 | insn <= encode_uj_type(UJ_JAL, "11010101001010101010", 10); 177 | wait for 1 ns; 178 | verify_uj_type(OP_JAL, "11111111111110101010010101010100", "01010"); 179 | 180 | -- JALR 181 | insn <= encode_i_type(I_JALR, "110011001100", 6, 5); 182 | wait for 1 ns; 183 | verify_i_type(OP_JALR, I_JALR, "11111111111111111111110011001100", "00110", "00101"); 184 | 185 | -- BEQ 186 | insn <= encode_sb_type(SB_BEQ, "101101101101", 20, 1); 187 | wait for 1 ns; 188 | verify_sb_type(OP_BRANCH, "11111111111111111111011011011010", BEQ, "10100", "00001"); 189 | 190 | -- BNE 191 | insn <= encode_sb_type(SB_BNE, "000010000101", 16, 18); 192 | wait for 1 ns; 193 | verify_sb_type(OP_BRANCH, "00000000000000000000000100001010", BNE, "10000", "10010"); 194 | 195 | -- BLT 196 | insn <= encode_sb_type(SB_BLT, "001011001110", 15, 14); 197 | wait for 1 ns; 198 | verify_sb_type(OP_BRANCH, "00000000000000000000010110011100", BLT, "01111", "01110"); 199 | 200 | -- BGE 201 | insn <= encode_sb_type(SB_BGE, "001010101001", 13, 12); 202 | wait for 1 ns; 203 | verify_sb_type(OP_BRANCH, "00000000000000000000010101010010", BGE, "01101", "01100"); 204 | 205 | -- BLTU 206 | insn <= encode_sb_type(SB_BLTU, "001010101001", 13, 12); 207 | wait for 1 ns; 208 | verify_sb_type(OP_BRANCH, "00000000000000000000010101010010", BLTU, "01101", "01100"); 209 | 210 | -- BGEU 211 | insn <= encode_sb_type(SB_BGEU, "101111000110", 11, 10); 212 | wait for 1 ns; 213 | verify_sb_type(OP_BRANCH, "11111111111111111111011110001100", BGEU, "01011", "01010"); 214 | 215 | -- LB 216 | insn <= encode_i_type(I_LB, "000111000111", 9, 8); 217 | wait for 1 ns; 218 | verify_i_type(OP_LOAD, I_LB, "00000000000000000000000111000111", "01001", "01000"); 219 | 220 | -- LH 221 | insn <= encode_i_type(I_LH, "011011011011", 7, 6); 222 | wait for 1 ns; 223 | verify_i_type(OP_LOAD, I_LH, "00000000000000000000011011011011", "00111", "00110"); 224 | 225 | -- LW 226 | insn <= encode_i_type(I_LW, "011011011010", 5, 4); 227 | wait for 1 ns; 228 | verify_i_type(OP_LOAD, I_LW, "00000000000000000000011011011010", "00101", "00100"); 229 | 230 | -- LBU 231 | insn <= encode_i_type(I_LBU, "110110110110", 3, 2); 232 | wait for 1 ns; 233 | verify_i_type(OP_LOAD, I_LBU, "11111111111111111111110110110110", "00011", "00010"); 234 | 235 | -- LHU 236 | insn <= encode_i_type(I_LHU, "111111111111", 1, 0); 237 | wait for 1 ns; 238 | verify_i_type(OP_LOAD, I_LHU, "11111111111111111111111111111111", "00001", "00000"); 239 | 240 | -- SB 241 | insn <= encode_s_type(S_SB, "011111111110", 21, 22); 242 | wait for 1 ns; 243 | verify_s_type(OP_STORE, S_SB, "00000000000000000000011111111110", "10101", "10110"); 244 | 245 | -- SH 246 | insn <= encode_s_type(S_SH, "011111111110", 21, 22); 247 | wait for 1 ns; 248 | verify_s_type(OP_STORE, S_SH, "00000000000000000000011111111110", "10101", "10110"); 249 | 250 | -- SW 251 | insn <= encode_s_type(S_SW, "001111111110", 23, 24); 252 | wait for 1 ns; 253 | verify_s_type(OP_STORE, S_SW, "00000000000000000000001111111110", "10111", "11000"); 254 | 255 | -- ADDI 256 | insn <= encode_i_type(I_ADDI, "111111111111", 25, 26); 257 | wait for 1 ns; 258 | verify_i_type(OP_ALU, I_ADDI, "11111111111111111111111111111111", "11001", "11010"); 259 | 260 | -- SLTI 261 | insn <= encode_i_type(I_SLTI, "111111111110", 27, 28); 262 | wait for 1 ns; 263 | verify_i_type(OP_ALU, I_SLTI, "11111111111111111111111111111110", "11011", "11100"); 264 | 265 | -- SLTIU 266 | insn <= encode_i_type(I_SLTIU, "111111111100", 29, 30); 267 | wait for 1 ns; 268 | verify_i_type(OP_ALU, I_SLTIU, "11111111111111111111111111111100", "11101", "11110"); 269 | 270 | -- XORI 271 | insn <= encode_i_type(I_XORI, "111111111110", 31, 30); 272 | wait for 1 ns; 273 | verify_i_type(OP_ALU, I_XORI, "11111111111111111111111111111110", "11111", "11110"); 274 | 275 | -- ORI 276 | insn <= encode_i_type(I_ORI, "111111111110", 1, 2); 277 | wait for 1 ns; 278 | verify_i_type(OP_ALU, I_ORI, "11111111111111111111111111111110", "00001", "00010"); 279 | 280 | -- ANDI 281 | insn <= encode_i_type(I_ANDI, "111111111110", 3, 4); 282 | wait for 1 ns; 283 | verify_i_type(OP_ALU, I_ANDI, "11111111111111111111111111111110", "00011", "00100"); 284 | 285 | -- SLLI 286 | insn <= encode_i_shift(I_SLLI, "11100", 5, 6); 287 | wait for 1 ns; 288 | verify_i_shift(I_SLLI, "11100", "00101", "00110"); 289 | 290 | -- SRLI 291 | insn <= encode_i_shift(I_SRLI, "11101", 7, 8); 292 | wait for 1 ns; 293 | verify_i_shift(I_SRLI, "11101", "00101", "00110"); 294 | 295 | -- SRAI 296 | insn <= encode_i_shift(I_SRAI, "11110", 9, 10); 297 | wait for 1 ns; 298 | verify_i_shift(I_SRAI, "11110", "00101", "00110"); 299 | 300 | -- ADD 301 | insn <= encode_r_type(R_ADD, 2, 4, 8); 302 | wait for 1 ns; 303 | verify_r_type(OP_ALU, R_ADD, "00010", "00100", "01000"); 304 | 305 | -- SUB 306 | insn <= encode_r_type(R_SUB, 16, 31, 1); 307 | wait for 1 ns; 308 | verify_r_type(OP_ALU, R_SUB, "10000", "11111", "00001"); 309 | 310 | -- SLL 311 | insn <= encode_r_type(R_SLL, 0, 0, 0); 312 | wait for 1 ns; 313 | verify_r_type(OP_ALU, R_SLL, "00000", "00000", "00000"); 314 | 315 | -- SLT 316 | insn <= encode_r_type(R_SLT, 16, 8, 4); 317 | wait for 1 ns; 318 | verify_r_type(OP_ALU, R_SLT, "10000", "01000", "00100"); 319 | 320 | -- SLTU 321 | insn <= encode_r_type(R_SLTU, 24, 12, 6); 322 | wait for 1 ns; 323 | verify_r_type(OP_ALU, R_SLTU, "11000", "01100", "00110"); 324 | 325 | -- XOR 326 | insn <= encode_r_type(R_XOR, 0, 0, 0); 327 | wait for 1 ns; 328 | verify_r_type(OP_ALU, R_XOR, "00000", "00000", "00000"); 329 | 330 | -- SRL 331 | insn <= encode_r_type(R_SRL, 0, 0, 0); 332 | wait for 1 ns; 333 | verify_r_type(OP_ALU, R_SRL, "00000", "00000", "00000"); 334 | 335 | -- SRA 336 | insn <= encode_r_type(R_SRA, 0, 0, 0); 337 | wait for 1 ns; 338 | verify_r_type(OP_ALU, R_SRA, "00000", "00000", "00000"); 339 | 340 | -- OR 341 | insn <= encode_r_type(R_OR, 0, 0, 0); 342 | wait for 1 ns; 343 | verify_r_type(OP_ALU, R_OR, "00000", "00000", "00000"); 344 | 345 | -- AND 346 | insn <= encode_r_type(R_AND, 0, 0, 0); 347 | wait for 1 ns; 348 | verify_r_type(OP_ALU, R_AND, "00000", "00000", "00000"); 349 | 350 | -- @todo others 351 | 352 | ---------------------------------------------------------------- 353 | println("Verification complete"); 354 | ---------------------------------------------------------------- 355 | 356 | wait; 357 | 358 | end process stimulus_proc; 359 | 360 | end architecture testbench; 361 | -------------------------------------------------------------------------------- /tests/generate_ramfile.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | use ieee.numeric_std.all; 4 | use std.textio.all; 5 | 6 | use work.common.all; 7 | 8 | --------------------------------------------------------------------------------- 9 | -- This module assumes the test_config package has a record type which 10 | -- contains a 'filename' field of type string, and a 'test' field of type 11 | -- ram_t (an array of words) which contain the instruction bitvectors. 12 | -- It will then write those instructions to a file in the format understood 13 | -- by the 'dpram' module's initialization functionality. This makes it possible 14 | -- to load a new "RAM" for instructions and static data at each simulation. 15 | --------------------------------------------------------------------------------- 16 | use work.test_config.all; 17 | 18 | entity generate_ramfile is 19 | end entity generate_ramfile; 20 | 21 | architecture script of generate_ramfile is 22 | 23 | -- purpose: Generate ramfiles 24 | procedure main is 25 | file testfile : text; 26 | variable outline : line; 27 | variable ok : file_open_status; 28 | begin -- procedure main 29 | 30 | -- 31 | -- Create test files 32 | -- 33 | -- 34 | 35 | file_open(ok, testfile, test_configuration.filename, WRITE_MODE); 36 | if ok = open_ok then 37 | for l in test_configuration.test'range loop 38 | write(outline, test_configuration.test(l)); 39 | writeline(testfile, outline); 40 | end loop; -- l 41 | file_close(testfile); 42 | else 43 | write(outline, string'("Failed to open file ")); 44 | write(outline, test_configuration.filename); 45 | writeline(output, outline); 46 | end if; 47 | 48 | end procedure main; 49 | 50 | begin -- architecture script 51 | 52 | main_proc : process is 53 | variable outline : line; 54 | begin -- process main_proc 55 | main; 56 | write(outline, string'("generate_ramfile done.")); 57 | writeline(output, outline); 58 | wait; 59 | end process main_proc; 60 | 61 | end architecture script; 62 | 63 | -------------------------------------------------------------------------------- /tests/pipeline_tb.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | use ieee.numeric_std.all; 4 | use std.textio.all; 5 | 6 | use work.common.all; 7 | use work.id_pkg.all; 8 | use work.encode_pkg.all; 9 | use work.test_config.all; 10 | 11 | entity pipeline_tb is 12 | end entity pipeline_tb; 13 | 14 | architecture testbench of pipeline_tb is 15 | signal clk : std_logic := '0'; 16 | signal rst_n : std_logic := '1'; 17 | 18 | -- inputs 19 | signal insn_in : word := (others => '0'); 20 | signal insn_addr : word := (others => '0'); 21 | signal insn_valid : std_logic := '0'; 22 | 23 | -- shift registers to simulate delays in accessing memory 24 | constant c_data_in_delay : integer := 4; -- number of delay cycles for memory reads 25 | type data_in_sr_t is array (0 to c_data_in_delay - 1) of std_logic_vector(31 downto 0); --word; 26 | type data_in_valid_sr_t is array (0 to c_data_in_delay - 1) of std_logic; 27 | signal data_in : data_in_sr_t := (others => (others => '0')); 28 | signal data_in_valid : data_in_valid_sr_t := (others => '0'); 29 | signal data_valid : std_logic; 30 | 31 | -- outputs 32 | signal data_write_en : std_logic; 33 | signal data_read_en : std_logic; 34 | signal data_addr : word; 35 | signal data_out : word; 36 | 37 | -- simulation specific 38 | signal done : boolean := false; 39 | constant clk_period : time := 10 ns; -- 100 MHz 40 | file memfile : text open write_mode is "sim/memio.vec"; 41 | 42 | -- data memory 43 | type ram_t is array(0 to 100) of word; 44 | signal ram : ram_t := (0 => X"80008081", 45 | others => (others => '0')); 46 | begin 47 | 48 | instruction_memory : entity work.dpram(rtl) 49 | generic map (g_data_width => 32, 50 | g_addr_width => 8, 51 | g_init => true, 52 | g_init_file => pipeline_tb_test_vector_input_filename) 53 | port map (clk => clk, 54 | addr_a => insn_addr(7 downto 0), 55 | data_a => (others => '0'), 56 | we_a => '0', 57 | q_a => insn_in, 58 | addr_b => (others => '0'), 59 | data_b => (others => '0'), 60 | we_b => '0', 61 | q_b => open); 62 | 63 | -- create a clock 64 | clk <= '0' when done else (not clk) after clk_period / 2; 65 | 66 | -- purpose: data memory 67 | ram_proc : process (clk, rst_n) is 68 | variable addr : integer; 69 | variable valid : std_logic; 70 | begin 71 | if rst_n = '0' then 72 | reset_shift_regs : for i in data_in'range loop 73 | data_in(i) <= (others => '0'); 74 | data_in_valid(i) <= '0'; 75 | end loop reset_shift_regs; 76 | elsif rising_edge(clk) then 77 | -- default values 78 | data_in_valid(0) <= '0'; 79 | data_in(0) <= (others => '0'); 80 | 81 | -- create shift registers 82 | shift_regs : for i in 1 to data_in'high loop 83 | data_in(i) <= data_in(i - 1); 84 | data_in_valid(i) <= data_in_valid(i - 1); 85 | end loop shift_regs; 86 | 87 | if ((data_in_valid(data_in_valid'high) = '0') 88 | and (data_in_valid(data_in_valid'high - 1) = '1')) then 89 | valid := '1'; 90 | else 91 | valid := '0'; 92 | end if; 93 | 94 | data_valid <= valid; 95 | 96 | -- writes/reads 97 | addr := to_integer(unsigned(data_addr)); 98 | if data_write_en = '1' then 99 | ram(addr) <= data_out; 100 | elsif data_read_en = '1' then 101 | data_in(0) <= ram(addr); 102 | data_in_valid(0) <= '1'; 103 | end if; 104 | end if; 105 | end process ram_proc; 106 | 107 | --------------------------------------------------- 108 | -- print memory bus transactions 109 | --------------------------------------------------- 110 | log_memio_proc : process (data_write_en, data_read_en, data_valid, clk) is 111 | variable l : line; 112 | begin -- process log_memio_proc 113 | if data_write_en = '1' and clk = '0' then 114 | write(l, string'("W ")); 115 | write(l, hstr(data_addr)); 116 | write(l, string'(", ")); 117 | write(l, hstr(data_out)); 118 | writeline(memfile, l); 119 | end if; 120 | 121 | if (data_valid = '1' and clk = '0') then 122 | write(l, string'("R ")); 123 | write(l, hstr(data_addr)); 124 | write(l, string'(", ")); 125 | write(l, hstr(data_in(data_in'high))); 126 | writeline(memfile, l); 127 | end if; 128 | end process log_memio_proc; 129 | 130 | -- instantiate the unit under test 131 | uut : entity work.pipeline(Behavioral) 132 | generic map ( 133 | g_initial_pc => (others => '0'), 134 | g_for_sim => true) 135 | port map ( 136 | clk => clk, 137 | rst_n => rst_n, 138 | insn_in => insn_in, 139 | insn_addr => insn_addr, 140 | insn_valid => insn_valid, 141 | data_in => data_in(data_in'high), 142 | data_out => data_out, 143 | data_addr => data_addr, 144 | data_write_en => data_write_en, 145 | data_read_en => data_read_en, 146 | data_in_valid => data_valid); 147 | 148 | -- purpose: Provide stimulus to test the pipeline 149 | stimulus_proc : process is 150 | variable i : natural := 0; 151 | begin -- process stimulus_proc 152 | -- reset sequence 153 | println ("Beginning simulation"); 154 | 155 | -- fill up the instruction memory 156 | rst_n <= '0'; 157 | wait for clk_period * 2; 158 | rst_n <= '1'; 159 | 160 | -- begin stimulus 161 | wait for clk_period; 162 | insn_valid <= '1'; 163 | 164 | -- run for a bit. 165 | wait for clk_period * 35; 166 | 167 | -- finished with simulation 168 | ---------------------------------------------------------------- 169 | println("Simulation complete"); 170 | ---------------------------------------------------------------- 171 | 172 | done <= true; 173 | wait; 174 | 175 | end process stimulus_proc; 176 | 177 | end architecture testbench; 178 | -------------------------------------------------------------------------------- /tests/sim-compare.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | del *.cf *.vcd 4 | ghdl -a ../src/common.vhd ../src/decode_pkg.vhd ../src/compare_unit.vhd compare_tb.vhd 5 | ghdl -e compare_tb 6 | ghdl -r compare_tb --vcd=compare_tb.vcd 7 | 8 | REM gtkwave compare_tb.vcd 9 | -------------------------------------------------------------------------------- /tests/sim-decode.bat: -------------------------------------------------------------------------------- 1 | @echo off 2 | 3 | del *.cf *.vcd 4 | ghdl -a ../src/common.vhd ../src/decode_pkg.vhd ../src/decode.vhd ../src/encode_pkg.vhd decoder_tb.vhd 5 | ghdl -e decoder_tb 6 | ghdl -r decoder_tb --vcd=decoder_tb.vcd 7 | 8 | REM gtkwave decoder_tb.vcd 9 | -------------------------------------------------------------------------------- /tests/test_config1.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | use work.encode_pkg.all; 4 | use work.common.all; 5 | use work.csr_pkg.all; 6 | 7 | package test_config is 8 | 9 | constant pipeline_tb_test_vector_input_filename : string := "sim/test1.vec"; 10 | 11 | -- arrays of instructions 12 | type ram_t is array (natural range 0 to 256) of word; 13 | 14 | -- Test 1 : add, RAW hazard, WAR hazard, predicted-not-taken (incorrectly) forward branch, 15 | -- unconditional branch, store to memory, load from stored memory (stalls) 16 | constant test1 : ram_t := (0 => encode_i_type(I_ADDI, "000000000100", 0, 1), -- ADDI x0, x1, 4 17 | 4 => encode_i_type(I_ADDI, "000000001000", 0, 2), -- ADDI x0, x2, 8 18 | 8 => encode_r_type(R_ADD, 1, 2, 3), -- ADD x1, x2, x3 19 | 12 => encode_u_type(U_LUI, "10000000000000000001", 4), -- LUI 0x80001, x4 20 | 16 => encode_uj_type(UJ_JAL, "00000000000000010010", 6), -- JAL 18, x6 21 | 20 => encode_i_type(I_ADDI, "000000000001", 0, 1), -- ADDI x0, x1, 1 -- this should not get executed 22 | 24 => encode_i_type(I_ADDI, "000000000001", 0, 1), -- ADDI x0, x1, 1 -- this should not get executed 23 | 28 => encode_i_type(I_ADDI, "000000000001", 0, 1), -- ADDI x0, x1, 1 -- this should not get executed 24 | 32 => encode_i_type(I_ADDI, "000000000001", 0, 1), -- ADDI x0, x1, 1 -- this should not get executed 25 | 36 => encode_i_type(I_ADDI, "000000000001", 0, 1), -- ADDI x0, x1, 1 -- this should not get executed 26 | 40 => NOP, 27 | 44 => NOP, 28 | 48 => NOP, 29 | 52 => encode_r_type(R_ADD, 3, 4, 5), -- ADD x3, x4, x5 30 | 56 => encode_u_type(U_AUIPC, "10000000000000000001", 8), -- AUIPC 0x80001, x8 31 | -- store the value in x8 into address 8 (offset 4 + value in x1 (4)) 32 | 60 => encode_s_type(S_SW, "000000000100", 1, 8), -- SW x1, x8, 4 33 | -- load the halfword value that was just stored (into address 8) into register 9 34 | 64 => encode_i_type(I_LH, "000000001000", 0, 9), -- LH x0, x9, 8 35 | 68 => encode_r_type(R_ADD, 8, 9, 10), -- ADD x8, x9, x10 36 | -- jump forward to instruction 88 37 | 72 => encode_sb_type(SB_BNE, "000000001000", 9, 8), -- BNE x9, x8, 16 38 | 76 => encode_i_type(I_ADDI, "000000000001", 0, 1), -- ADDI x0, x1, 1 -- this should not get executed 39 | 80 => encode_i_type(I_ADDI, "000000000011", 0, 1), -- ADDI x0, x1, 3 -- this should not get executed 40 | 84 => encode_i_type(I_ADDI, "000000000111", 0, 1), -- ADDI x0, x1, 3 -- this should not get executed 41 | 88 => encode_i_type(I_ADDI, "000000000001", 0, 1), -- ADDI x0, x1, 3 -- this should not get executed 42 | 92 => encode_i_type(I_ADDI, "000000011111", 1, 11), -- ADDI x0, x1, 3 -- this should not get executed 43 | 96 => encode_i_csr(CSR_CYCLE, 12), -- RDCYCLE x12 44 | 100 => encode_i_csr(CSR_INSTRET, 13), 45 | others => (others => '0')); 46 | 47 | -- with current branch prediction scheme (backwards as taken, forwards as not-taken), 48 | -- these are the only 3 scenarios that can happen w/ regards to branches. 49 | 50 | type test_config_t is record 51 | filename : string(1 to 13); 52 | test : ram_t; 53 | end record test_config_t; 54 | 55 | constant test_configuration : test_config_t := ( "sim/test1.vec", test1 ); 56 | 57 | end package test_config; 58 | -------------------------------------------------------------------------------- /tests/test_config2.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | use work.encode_pkg.all; 4 | use work.common.all; 5 | 6 | package test_config is 7 | 8 | constant pipeline_tb_test_vector_input_filename : string := ( "sim/test2.vec" ); 9 | 10 | -- arrays of instructions 11 | type ram_t is array (natural range 0 to 256) of word; 12 | 13 | -- Test 2 : add, RAW, WAR, predicted-taken (corrently) backwards branch, 14 | -- unconditional branch, store to memory, load from stored memory (stalls) 15 | constant test2 : ram_t := (0 => encode_i_type(I_ADDI, "000000000100", 0, 1), -- ADDI x0, x1, 4 16 | 4 => encode_i_type(I_ADDI, "000000001000", 0, 2), -- ADDI x0, x2, 8 17 | 8 => encode_r_type(R_ADD, 1, 2, 3), -- ADD x1, x2, x3 18 | 12 => encode_u_type(U_LUI, "10000000000000000001", 4), -- LUI 0x80001, x4 19 | 16 => encode_uj_type(UJ_JAL, "00000000000000010010", 6), -- JAL 18, x6 20 | 20 => encode_i_type(I_ADDI, "000000000001", 0, 1), -- ADDI x0, x1, 1 -- this should not get executed 21 | 24 => encode_i_type(I_ADDI, "000000000001", 0, 1), -- ADDI x0, x1, 1 -- this should not get executed 22 | 28 => encode_i_type(I_ADDI, "000000000001", 0, 1), -- ADDI x0, x1, 1 -- this should not get executed 23 | 32 => encode_i_type(I_ADDI, "000000000001", 0, 1), -- ADDI x0, x1, 1 -- this should not get executed 24 | 36 => encode_i_type(I_ADDI, "000000000001", 0, 1), -- ADDI x0, x1, 1 -- this should not get executed 25 | 40 => NOP, 26 | 44 => NOP, 27 | 48 => NOP, 28 | 52 => encode_r_type(R_ADD, 3, 4, 5), -- ADD x3, x4, x5 29 | 56 => encode_u_type(U_AUIPC, "10000000000000000001", 8), -- AUIPC 0x80001, x8 30 | -- store the value in x8 into address 8 (offset 4 + value in x1 (4)) 31 | 60 => encode_s_type(S_SW, "000000000100", 1, 8), -- SW x1, x8, 4 32 | -- load the halfword value that was just stored (into address 8) into register 9 33 | 64 => encode_i_type(I_LH, "000000001000", 0, 9), -- LH x0, x9, 8 34 | 68 => encode_r_type(R_ADD, 8, 9, 10), -- ADD x8, x9, x10 35 | -- loop back to the previous address 36 | 72 => encode_sb_type(SB_BNE, "111111111110", 9, 8), -- BNE x9, x8, -4 37 | 76 => encode_i_type(I_ADDI, "000000000001", 0, 1), -- ADDI x0, x1, 1 -- this should not get executed 38 | 80 => encode_i_type(I_ADDI, "000000000011", 0, 1), -- ADDI x0, x1, 3 -- this should not get executed 39 | 84 => encode_i_type(I_ADDI, "000000000111", 0, 1), -- ADDI x0, x1, 3 -- this should not get executed 40 | 88 => encode_i_type(I_ADDI, "000000000001", 0, 1), -- ADDI x0, x1, 3 -- this should not get executed 41 | 92 => encode_i_type(I_ADDI, "000000011111", 1, 11), -- ADDI x0, x1, 3 -- this should not get executed 42 | 96 => NOP, 43 | others => (others => '0')); 44 | 45 | -- Test 3 (TODO): WAW, WAR, RAW, reads/writes to register 0, 46 | -- incorrectly-predicted-taken backwards branch 47 | 48 | -- with current branch prediction scheme (backwards as taken, forwards as not-taken), 49 | -- these are the only 3 scenarios that can happen w/ regards to branches. 50 | 51 | type test_config_t is record 52 | filename : string(1 to 13); 53 | test : ram_t; 54 | end record test_config_t; 55 | 56 | constant test_configuration : test_config_t := ( pipeline_tb_test_vector_input_filename, test2 ); 57 | 58 | end package test_config; 59 | -------------------------------------------------------------------------------- /tests/test_config3.vhd: -------------------------------------------------------------------------------- 1 | library ieee; 2 | use ieee.std_logic_1164.all; 3 | use work.encode_pkg.all; 4 | use work.common.all; 5 | use work.csr_pkg.all; 6 | 7 | package test_config is 8 | 9 | constant pipeline_tb_test_vector_input_filename : string := "sim/test3.vec"; 10 | 11 | -- arrays of instructions 12 | type ram_t is array (natural range 0 to 256) of word; 13 | 14 | -- Test 3 (TODO): WAW, WAR, RAW, reads/writes to register 0, 15 | -- incorrectly-predicted-taken backwards branch, 16 | -- data dependency between load then store 17 | constant test3 : ram_t := (0 => encode_i_type(I_ADDI, "000000001000", 0, 0), 18 | 4 => encode_i_type(I_ADDI, "000000000100", 0, 1), 19 | 8 => encode_r_type(R_ADD, 0, 1, 2), 20 | 12 => encode_r_type(R_ADD, 1, 2, 3), 21 | 16 => encode_sb_type(SB_BEQ, "111111111000", 1, 2), 22 | 20 => encode_i_type(I_ADDI, "000000000001", 0, 1), -- ADDI x0, x1, 1 23 | 24 => encode_i_type(I_ADDI, "000000000011", 0, 1), -- ADDI x0, x1, 3 24 | 28 => encode_i_type(I_ADDI, "000000000111", 0, 1), -- ADDI x0, x1, 7 25 | 32 => encode_i_type(I_ADDI, "000000000001", 0, 1), -- ADDI x0, x1, 1 26 | 36 => encode_i_type(I_ADDI, "000000011111", 1, 11), -- ADDI x1, x11, 20 27 | 40 => encode_r_type(R_ADD, 1, 11, 13), 28 | -- load value at address -33(x13) into x4 29 | 44 => encode_i_type(I_LB, "111111011111", 13, 4), 30 | -- store to address 12(x2) the value in x4 31 | 48 => encode_s_type(S_SW, "000000001100", 2, 4), 32 | -- retired instruction count 33 | 52 => encode_i_csr(CSR_INSTRET, 12), 34 | -- load value at 12(x2) into x1 35 | 56 => encode_i_type(I_LW, "000000001100", 2, 1), 36 | -- x1 - x12 goes into x4 37 | 60 => encode_r_type(R_SUB, 1, 12, 4), 38 | -- x1 and x13 goes into x6 39 | 64 => encode_r_type(R_AND, 1, 13, 6), 40 | 41 | 68 => encode_r_type(R_OR, 1, 13, 8), 42 | others => NOP); 43 | 44 | type test_config_t is record 45 | filename : string(1 to 13); 46 | test : ram_t; 47 | end record test_config_t; 48 | 49 | constant test_configuration : test_config_t := ("sim/test3.vec", test3); 50 | 51 | end package test_config; 52 | -------------------------------------------------------------------------------- /verify_test_vecs: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # diff this simulation run's output files against the "golden" ones for test1 3 | 4 | diff -s sim/memio.vec sim/memio_$1.vec 5 | diff -s sim/regout.vec sim/regout_$1.vec 6 | --------------------------------------------------------------------------------