├── LICENSE ├── README.md ├── core └── riscv │ ├── riscv_alu.v │ ├── riscv_core.v │ ├── riscv_csr.v │ ├── riscv_csr_regfile.v │ ├── riscv_decode.v │ ├── riscv_decoder.v │ ├── riscv_defs.v │ ├── riscv_divider.v │ ├── riscv_exec.v │ ├── riscv_fetch.v │ ├── riscv_issue.v │ ├── riscv_lsu.v │ ├── riscv_mmu.v │ ├── riscv_multiplier.v │ ├── riscv_pipe_ctrl.v │ ├── riscv_regfile.v │ ├── riscv_trace_sim.v │ └── riscv_xilinx_2r1w.v ├── doc ├── core_exec.png ├── mem_d_interface.png ├── mem_i_interface.png ├── overview.png ├── riscv_isa_spec.pdf └── riscv_privileged_spec.pdf ├── isa_sim ├── README.md ├── cosim_api.cpp ├── cosim_api.h ├── elf_load.cpp ├── elf_load.h ├── images │ ├── basic.elf │ └── linux.elf ├── main.cpp ├── makefile ├── memory.h ├── riscv.cpp ├── riscv.h ├── riscv_inst_dump.cpp ├── riscv_inst_dump.h ├── riscv_isa.h ├── riscv_main.cpp └── riscv_main.h ├── top_cache_axi ├── src_v │ ├── dcache.v │ ├── dcache_axi.v │ ├── dcache_axi_axi.v │ ├── dcache_core.v │ ├── dcache_core_data_ram.v │ ├── dcache_core_tag_ram.v │ ├── dcache_if_pmem.v │ ├── dcache_mux.v │ ├── dcache_pmem_mux.v │ ├── icache.v │ ├── icache_data_ram.v │ ├── icache_tag_ram.v │ └── riscv_top.v └── tb │ ├── axi4.h │ ├── axi4_defines.h │ ├── main.cpp │ ├── makefile │ ├── makefile.build_sysc_tb │ ├── makefile.build_verilated │ ├── makefile.generate_verilated │ ├── riscv_top.cpp │ ├── riscv_top.h │ ├── sc_reset_gen.h │ ├── tb_axi4_mem.cpp │ ├── tb_axi4_mem.h │ ├── tb_memory.h │ ├── testbench.h │ └── testbench_vbase.h ├── top_tcm_axi ├── src_v │ ├── dport_axi.v │ ├── dport_mux.v │ ├── riscv_tcm_top.v │ ├── tcm_mem.v │ ├── tcm_mem_pmem.v │ └── tcm_mem_ram.v └── tb │ ├── axi4.h │ ├── axi4_lite.h │ ├── main.cpp │ ├── makefile │ ├── makefile.build_sysc_tb │ ├── makefile.build_verilated │ ├── makefile.generate_verilated │ ├── riscv_tcm_top_rtl.cpp │ ├── riscv_tcm_top_rtl.h │ ├── sc_reset_gen.h │ ├── testbench.h │ └── testbench_vbase.h └── top_tcm_wrapper ├── dport_axi.v ├── dport_mux.v ├── riscv_tcm_wrapper.v ├── tcm_mem.v ├── tcm_mem_pmem.v └── tcm_mem_ram.v /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, ultraembedded 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 the {organization} 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 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # RISC-V Core 2 | 3 | Github: [http://github.com/ultraembedded/riscv](http://github.com/ultraembedded/riscv) 4 | 5 | A 32-bit RISC-V core written in Verilog and an instruction set simulator supporting RV32IM. 6 | This core has been tested against a co-simulation model and exercised on FPGA. 7 | 8 | **For a higher performance dual issue CPU with branch prediction, see my latest RISC-V core here;** 9 | [http://github.com/ultraembedded/biriscv](http://github.com/ultraembedded/biriscv) 10 | 11 | ## Overview 12 | ![](doc/overview.png) 13 | 14 | ## Features 15 | * 32-bit RISC-V ISA CPU core. 16 | * Support RISC-V integer (I), multiplication and division (M), and CSR instructions (Z) extensions (RV32IMZicsr). 17 | * Supports user, supervisor and machine mode privilege levels. 18 | * Basic MMU support - capable of booting Linux with atomics (RV-A) SW emulation. 19 | * Implements base ISA spec [v2.1](https://github.com/ultraembedded/riscv/tree/master/doc/riscv_isa_spec.pdf) and privileged ISA spec [v1.11](https://github.com/ultraembedded/riscv/tree/master/doc/riscv_privileged_spec.pdf). 20 | * Verified using [Google's RISCV-DV](https://github.com/google/riscv-dv) random instruction sequences using cosimulation against [C++ ISA model](https://github.com/ultraembedded/exactstep). 21 | * Support for instruction / data cache, AXI bus interfaces or tightly coupled memories. 22 | * Configurable number of pipeline stages and result forwarding options. 23 | * Synthesizable Verilog 2001, Verilator and FPGA friendly. 24 | * Coremark: **2.94 CoreMark/MHz** 25 | * Dhrystone: **1.25 DMIPS/MHz** ('legal compile options' / 337 instructions per iteration) 26 | * Want higher performance (**4.1CM/MHz** / **1.9DMIPS/MHz**) - see [my improved core](http://github.com/ultraembedded/biriscv). 27 | 28 | #### Configuration 29 | 30 | | Param Name | Valid Range | Description | 31 | | ------------------------- |:--------------------:| ----------------------------------------------| 32 | | SUPPORT_SUPER | 1/0 | Enable supervisor / user privilege levels. | 33 | | SUPPORT_MMU | 1/0 | Enable basic memory management unit. | 34 | | SUPPORT_MULDIV | 1/0 | Enable HW multiply / divide (RV-M). | 35 | | SUPPORT_LOAD_BYPASS | 1/0 | Support load result bypass paths. | 36 | | SUPPORT_MUL_BYPASS | 1/0 | Support multiply result bypass paths. | 37 | | SUPPORT_REGFILE_XILINX | 1/0 | Support Xilinx optimised register file. | 38 | | EXTRA_DECODE_STAGE | 1/0 | Extra decode pipe stage for improved timing. | 39 | | MEM_CACHE_ADDR_MIN | 32'h0 - 32'hffffffff | Lowest cacheable memory address. | 40 | | MEM_CACHE_ADDR_MAX | 32'h0 - 32'hffffffff | Highest cacheable memory address. | 41 | 42 | ## Directories 43 | 44 | | Name | Contents | 45 | | ------------------- | --------------------------------------------------- | 46 | | core/riscv | RISC-V pipelined RV32IM CPU core (Verilog) | 47 | | isa_sim | Instruction set simulator (C) | 48 | | top_tcm_axi/src_v | Example instance with 64KB DP-RAM & AXI Interfaces | 49 | | top_tcm_axi/tb | System-C testbench for the core | 50 | | top_cache_axi/src_v | Example instance with instruction and data caches. | 51 | | top_cache_axi/tb | System-C testbench for the core | 52 | 53 | ## Example Core Instance (with TCM memory) 54 | 55 | The top (top_tcm_axi/src_v/riscv_tcm_top.v) contains; 56 | * Instances one of the above cores, adding RAM and standard bus interfaces. 57 | * 64KB dual ported RAM for (I/D code and data). 58 | * AXI4 slave port for loading the RAM, DMA access, etc (including support for burst access). 59 | * AXI4-Lite master port for CPU access to peripherals. 60 | * Separate reset for CPU core to dual ported RAM / AXI interface (to allow program code to be loaded prior to CPU reset de-assertion). 61 | 62 | ### Memory Map 63 | 64 | | Range | Description | 65 | | ------------------------- | --------------------------------------------------- | 66 | | 0x0000_0000 - 0x0000_ffff | 64KB TCM Memory | 67 | | 0x0000_2000 | Boot address (configurable, see RISCV_BOOT_ADDRESS) | 68 | | 0x8000_0000 - 0xffff_ffff | Peripheral address space (from AXI4-L port) | 69 | 70 | ### Interfaces 71 | 72 | | Name | Description | 73 | | ------------ | --------------------------------------------------------------------- | 74 | | clk_i | Clock input | 75 | | rst_i | Async reset, active-high. Reset memory / AXI interface. | 76 | | rst_cpu_i | Async reset, active-high. Reset CPU core (excluding AXI / memory). | 77 | | axi_t_* | AXI4 slave interface for access to 64KB TCM memory. | 78 | | axi_i_* | AXI4-Lite master interface for CPU access to peripherals. | 79 | | intr_i | Active high interrupt input (for connection external int controller). | 80 | 81 | ### Testbench 82 | 83 | A basic System-C / Verilator based testbench for the core is provided. 84 | 85 | Dependencies; 86 | * gcc 87 | * make 88 | * libelf 89 | * System-C (specify path using SYSTEMC_HOME) 90 | * Verilator (specify path using VERILATOR_SRC) 91 | 92 | To build the testbench; 93 | ``` 94 | cd top_tcm_axi/tb 95 | make 96 | ```` 97 | 98 | To run the provided test executable; 99 | ``` 100 | cd top_tcm_axi/tb 101 | make run 102 | ```` 103 | 104 | ## Example Core Instance (with caches) 105 | 106 | The top (top_cache_axi/src_v/riscv_top.v) contains; 107 | * Instances one of the above cores, adding RAM and standard bus interfaces. 108 | * 16KB 2-way set associative instruction cache 109 | * 16KB 2-way set associative data cache with write-back and allocate on write. 110 | * 2 x AXI4 master port for CPU access to instruction / data / peripherals. 111 | 112 | ### Interfaces 113 | 114 | | Name | Description | 115 | | -------------- | --------------------------------------------------------------------- | 116 | | clk_i | Clock input | 117 | | rst_i | Async reset, active-high. Reset memory / AXI interface. | 118 | | axi_i_* | AXI4 master interface for CPU access to instruction memory. | 119 | | axi_d_* | AXI4 master interface for CPU access to data / peripheral memories. | 120 | | intr_i | Active high interrupt input (for connection external int controller). | 121 | | reset_vector_i | Boot vector. | 122 | 123 | ## Execution Example 124 | ![](doc/core_exec.png) 125 | -------------------------------------------------------------------------------- /core/riscv/riscv_alu.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // RISC-V Core 3 | // V1.0.1 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2019 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: BSD 10 | //----------------------------------------------------------------- 11 | // 12 | // Copyright (c) 2014-2019, Ultra-Embedded.com 13 | // All rights reserved. 14 | // 15 | // Redistribution and use in source and binary forms, with or without 16 | // modification, are permitted provided that the following conditions 17 | // are met: 18 | // - Redistributions of source code must retain the above copyright 19 | // notice, this list of conditions and the following disclaimer. 20 | // - Redistributions in binary form must reproduce the above copyright 21 | // notice, this list of conditions and the following disclaimer 22 | // in the documentation and/or other materials provided with the 23 | // distribution. 24 | // - Neither the name of the author nor the names of its contributors 25 | // may be used to endorse or promote products derived from this 26 | // software without specific prior written permission. 27 | // 28 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 32 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 35 | // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 36 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 38 | // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 | // SUCH DAMAGE. 40 | //----------------------------------------------------------------- 41 | module riscv_alu 42 | ( 43 | // Inputs 44 | input [ 3:0] alu_op_i 45 | ,input [ 31:0] alu_a_i 46 | ,input [ 31:0] alu_b_i 47 | 48 | // Outputs 49 | ,output [ 31:0] alu_p_o 50 | ); 51 | 52 | //----------------------------------------------------------------- 53 | // Includes 54 | //----------------------------------------------------------------- 55 | `include "riscv_defs.v" 56 | 57 | //----------------------------------------------------------------- 58 | // Registers 59 | //----------------------------------------------------------------- 60 | reg [31:0] result_r; 61 | 62 | reg [31:16] shift_right_fill_r; 63 | reg [31:0] shift_right_1_r; 64 | reg [31:0] shift_right_2_r; 65 | reg [31:0] shift_right_4_r; 66 | reg [31:0] shift_right_8_r; 67 | 68 | reg [31:0] shift_left_1_r; 69 | reg [31:0] shift_left_2_r; 70 | reg [31:0] shift_left_4_r; 71 | reg [31:0] shift_left_8_r; 72 | 73 | wire [31:0] sub_res_w = alu_a_i - alu_b_i; 74 | 75 | //----------------------------------------------------------------- 76 | // ALU 77 | //----------------------------------------------------------------- 78 | always @ (alu_op_i or alu_a_i or alu_b_i or sub_res_w) 79 | begin 80 | shift_right_fill_r = 16'b0; 81 | shift_right_1_r = 32'b0; 82 | shift_right_2_r = 32'b0; 83 | shift_right_4_r = 32'b0; 84 | shift_right_8_r = 32'b0; 85 | 86 | shift_left_1_r = 32'b0; 87 | shift_left_2_r = 32'b0; 88 | shift_left_4_r = 32'b0; 89 | shift_left_8_r = 32'b0; 90 | 91 | case (alu_op_i) 92 | //---------------------------------------------- 93 | // Shift Left 94 | //---------------------------------------------- 95 | `ALU_SHIFTL : 96 | begin 97 | if (alu_b_i[0] == 1'b1) 98 | shift_left_1_r = {alu_a_i[30:0],1'b0}; 99 | else 100 | shift_left_1_r = alu_a_i; 101 | 102 | if (alu_b_i[1] == 1'b1) 103 | shift_left_2_r = {shift_left_1_r[29:0],2'b00}; 104 | else 105 | shift_left_2_r = shift_left_1_r; 106 | 107 | if (alu_b_i[2] == 1'b1) 108 | shift_left_4_r = {shift_left_2_r[27:0],4'b0000}; 109 | else 110 | shift_left_4_r = shift_left_2_r; 111 | 112 | if (alu_b_i[3] == 1'b1) 113 | shift_left_8_r = {shift_left_4_r[23:0],8'b00000000}; 114 | else 115 | shift_left_8_r = shift_left_4_r; 116 | 117 | if (alu_b_i[4] == 1'b1) 118 | result_r = {shift_left_8_r[15:0],16'b0000000000000000}; 119 | else 120 | result_r = shift_left_8_r; 121 | end 122 | //---------------------------------------------- 123 | // Shift Right 124 | //---------------------------------------------- 125 | `ALU_SHIFTR, `ALU_SHIFTR_ARITH: 126 | begin 127 | // Arithmetic shift? Fill with 1's if MSB set 128 | if (alu_a_i[31] == 1'b1 && alu_op_i == `ALU_SHIFTR_ARITH) 129 | shift_right_fill_r = 16'b1111111111111111; 130 | else 131 | shift_right_fill_r = 16'b0000000000000000; 132 | 133 | if (alu_b_i[0] == 1'b1) 134 | shift_right_1_r = {shift_right_fill_r[31], alu_a_i[31:1]}; 135 | else 136 | shift_right_1_r = alu_a_i; 137 | 138 | if (alu_b_i[1] == 1'b1) 139 | shift_right_2_r = {shift_right_fill_r[31:30], shift_right_1_r[31:2]}; 140 | else 141 | shift_right_2_r = shift_right_1_r; 142 | 143 | if (alu_b_i[2] == 1'b1) 144 | shift_right_4_r = {shift_right_fill_r[31:28], shift_right_2_r[31:4]}; 145 | else 146 | shift_right_4_r = shift_right_2_r; 147 | 148 | if (alu_b_i[3] == 1'b1) 149 | shift_right_8_r = {shift_right_fill_r[31:24], shift_right_4_r[31:8]}; 150 | else 151 | shift_right_8_r = shift_right_4_r; 152 | 153 | if (alu_b_i[4] == 1'b1) 154 | result_r = {shift_right_fill_r[31:16], shift_right_8_r[31:16]}; 155 | else 156 | result_r = shift_right_8_r; 157 | end 158 | //---------------------------------------------- 159 | // Arithmetic 160 | //---------------------------------------------- 161 | `ALU_ADD : 162 | begin 163 | result_r = (alu_a_i + alu_b_i); 164 | end 165 | `ALU_SUB : 166 | begin 167 | result_r = sub_res_w; 168 | end 169 | //---------------------------------------------- 170 | // Logical 171 | //---------------------------------------------- 172 | `ALU_AND : 173 | begin 174 | result_r = (alu_a_i & alu_b_i); 175 | end 176 | `ALU_OR : 177 | begin 178 | result_r = (alu_a_i | alu_b_i); 179 | end 180 | `ALU_XOR : 181 | begin 182 | result_r = (alu_a_i ^ alu_b_i); 183 | end 184 | //---------------------------------------------- 185 | // Comparision 186 | //---------------------------------------------- 187 | `ALU_LESS_THAN : 188 | begin 189 | result_r = (alu_a_i < alu_b_i) ? 32'h1 : 32'h0; 190 | end 191 | `ALU_LESS_THAN_SIGNED : 192 | begin 193 | if (alu_a_i[31] != alu_b_i[31]) 194 | result_r = alu_a_i[31] ? 32'h1 : 32'h0; 195 | else 196 | result_r = sub_res_w[31] ? 32'h1 : 32'h0; 197 | end 198 | default : 199 | begin 200 | result_r = alu_a_i; 201 | end 202 | endcase 203 | end 204 | 205 | assign alu_p_o = result_r; 206 | 207 | endmodule 208 | -------------------------------------------------------------------------------- /core/riscv/riscv_decode.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // RISC-V Core 3 | // V1.0.1 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2019 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: BSD 10 | //----------------------------------------------------------------- 11 | // 12 | // Copyright (c) 2014-2019, Ultra-Embedded.com 13 | // All rights reserved. 14 | // 15 | // Redistribution and use in source and binary forms, with or without 16 | // modification, are permitted provided that the following conditions 17 | // are met: 18 | // - Redistributions of source code must retain the above copyright 19 | // notice, this list of conditions and the following disclaimer. 20 | // - Redistributions in binary form must reproduce the above copyright 21 | // notice, this list of conditions and the following disclaimer 22 | // in the documentation and/or other materials provided with the 23 | // distribution. 24 | // - Neither the name of the author nor the names of its contributors 25 | // may be used to endorse or promote products derived from this 26 | // software without specific prior written permission. 27 | // 28 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 32 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 35 | // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 36 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 38 | // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 | // SUCH DAMAGE. 40 | //----------------------------------------------------------------- 41 | 42 | module riscv_decode 43 | //----------------------------------------------------------------- 44 | // Params 45 | //----------------------------------------------------------------- 46 | #( 47 | parameter SUPPORT_MULDIV = 1 48 | ,parameter EXTRA_DECODE_STAGE = 0 49 | ) 50 | //----------------------------------------------------------------- 51 | // Ports 52 | //----------------------------------------------------------------- 53 | ( 54 | // Inputs 55 | input clk_i 56 | ,input rst_i 57 | ,input fetch_in_valid_i 58 | ,input [ 31:0] fetch_in_instr_i 59 | ,input [ 31:0] fetch_in_pc_i 60 | ,input fetch_in_fault_fetch_i 61 | ,input fetch_in_fault_page_i 62 | ,input fetch_out_accept_i 63 | ,input squash_decode_i 64 | 65 | // Outputs 66 | ,output fetch_in_accept_o 67 | ,output fetch_out_valid_o 68 | ,output [ 31:0] fetch_out_instr_o 69 | ,output [ 31:0] fetch_out_pc_o 70 | ,output fetch_out_fault_fetch_o 71 | ,output fetch_out_fault_page_o 72 | ,output fetch_out_instr_exec_o 73 | ,output fetch_out_instr_lsu_o 74 | ,output fetch_out_instr_branch_o 75 | ,output fetch_out_instr_mul_o 76 | ,output fetch_out_instr_div_o 77 | ,output fetch_out_instr_csr_o 78 | ,output fetch_out_instr_rd_valid_o 79 | ,output fetch_out_instr_invalid_o 80 | ); 81 | 82 | 83 | 84 | wire enable_muldiv_w = SUPPORT_MULDIV; 85 | 86 | //----------------------------------------------------------------- 87 | // Extra decode stage (to improve cycle time) 88 | //----------------------------------------------------------------- 89 | generate 90 | if (EXTRA_DECODE_STAGE) 91 | begin 92 | wire [31:0] fetch_in_instr_w = (fetch_in_fault_page_i | fetch_in_fault_fetch_i) ? 32'b0 : fetch_in_instr_i; 93 | reg [66:0] buffer_q; 94 | 95 | always @(posedge clk_i or posedge rst_i) 96 | if (rst_i) 97 | buffer_q <= 67'b0; 98 | else if (squash_decode_i) 99 | buffer_q <= 67'b0; 100 | else if (fetch_out_accept_i || !fetch_out_valid_o) 101 | buffer_q <= {fetch_in_valid_i, fetch_in_fault_page_i, fetch_in_fault_fetch_i, fetch_in_instr_w, fetch_in_pc_i}; 102 | 103 | assign {fetch_out_valid_o, 104 | fetch_out_fault_page_o, 105 | fetch_out_fault_fetch_o, 106 | fetch_out_instr_o, 107 | fetch_out_pc_o} = buffer_q; 108 | 109 | riscv_decoder 110 | u_dec 111 | ( 112 | .valid_i(fetch_out_valid_o) 113 | ,.fetch_fault_i(fetch_out_fault_page_o | fetch_out_fault_fetch_o) 114 | ,.enable_muldiv_i(enable_muldiv_w) 115 | ,.opcode_i(fetch_out_instr_o) 116 | 117 | ,.invalid_o(fetch_out_instr_invalid_o) 118 | ,.exec_o(fetch_out_instr_exec_o) 119 | ,.lsu_o(fetch_out_instr_lsu_o) 120 | ,.branch_o(fetch_out_instr_branch_o) 121 | ,.mul_o(fetch_out_instr_mul_o) 122 | ,.div_o(fetch_out_instr_div_o) 123 | ,.csr_o(fetch_out_instr_csr_o) 124 | ,.rd_valid_o(fetch_out_instr_rd_valid_o) 125 | ); 126 | 127 | assign fetch_in_accept_o = fetch_out_accept_i; 128 | end 129 | //----------------------------------------------------------------- 130 | // Straight through decode 131 | //----------------------------------------------------------------- 132 | else 133 | begin 134 | wire [31:0] fetch_in_instr_w = (fetch_in_fault_page_i | fetch_in_fault_fetch_i) ? 32'b0 : fetch_in_instr_i; 135 | 136 | riscv_decoder 137 | u_dec 138 | ( 139 | .valid_i(fetch_in_valid_i) 140 | ,.fetch_fault_i(fetch_in_fault_fetch_i | fetch_in_fault_page_i) 141 | ,.enable_muldiv_i(enable_muldiv_w) 142 | ,.opcode_i(fetch_out_instr_o) 143 | 144 | ,.invalid_o(fetch_out_instr_invalid_o) 145 | ,.exec_o(fetch_out_instr_exec_o) 146 | ,.lsu_o(fetch_out_instr_lsu_o) 147 | ,.branch_o(fetch_out_instr_branch_o) 148 | ,.mul_o(fetch_out_instr_mul_o) 149 | ,.div_o(fetch_out_instr_div_o) 150 | ,.csr_o(fetch_out_instr_csr_o) 151 | ,.rd_valid_o(fetch_out_instr_rd_valid_o) 152 | ); 153 | 154 | // Outputs 155 | assign fetch_out_valid_o = fetch_in_valid_i; 156 | assign fetch_out_pc_o = fetch_in_pc_i; 157 | assign fetch_out_instr_o = fetch_in_instr_w; 158 | assign fetch_out_fault_page_o = fetch_in_fault_page_i; 159 | assign fetch_out_fault_fetch_o = fetch_in_fault_fetch_i; 160 | 161 | assign fetch_in_accept_o = fetch_out_accept_i; 162 | end 163 | endgenerate 164 | 165 | 166 | endmodule 167 | -------------------------------------------------------------------------------- /core/riscv/riscv_divider.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // RISC-V Core 3 | // V1.0.1 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2019 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: BSD 10 | //----------------------------------------------------------------- 11 | // 12 | // Copyright (c) 2014-2019, Ultra-Embedded.com 13 | // All rights reserved. 14 | // 15 | // Redistribution and use in source and binary forms, with or without 16 | // modification, are permitted provided that the following conditions 17 | // are met: 18 | // - Redistributions of source code must retain the above copyright 19 | // notice, this list of conditions and the following disclaimer. 20 | // - Redistributions in binary form must reproduce the above copyright 21 | // notice, this list of conditions and the following disclaimer 22 | // in the documentation and/or other materials provided with the 23 | // distribution. 24 | // - Neither the name of the author nor the names of its contributors 25 | // may be used to endorse or promote products derived from this 26 | // software without specific prior written permission. 27 | // 28 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 32 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 35 | // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 36 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 38 | // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 | // SUCH DAMAGE. 40 | //----------------------------------------------------------------- 41 | 42 | module riscv_divider 43 | ( 44 | // Inputs 45 | input clk_i 46 | ,input rst_i 47 | ,input opcode_valid_i 48 | ,input [ 31:0] opcode_opcode_i 49 | ,input [ 31:0] opcode_pc_i 50 | ,input opcode_invalid_i 51 | ,input [ 4:0] opcode_rd_idx_i 52 | ,input [ 4:0] opcode_ra_idx_i 53 | ,input [ 4:0] opcode_rb_idx_i 54 | ,input [ 31:0] opcode_ra_operand_i 55 | ,input [ 31:0] opcode_rb_operand_i 56 | 57 | // Outputs 58 | ,output writeback_valid_o 59 | ,output [ 31:0] writeback_value_o 60 | ); 61 | 62 | 63 | 64 | //----------------------------------------------------------------- 65 | // Includes 66 | //----------------------------------------------------------------- 67 | `include "riscv_defs.v" 68 | 69 | //------------------------------------------------------------- 70 | // Registers / Wires 71 | //------------------------------------------------------------- 72 | reg valid_q; 73 | reg [31:0] wb_result_q; 74 | 75 | //------------------------------------------------------------- 76 | // Divider 77 | //------------------------------------------------------------- 78 | wire inst_div_w = (opcode_opcode_i & `INST_DIV_MASK) == `INST_DIV; 79 | wire inst_divu_w = (opcode_opcode_i & `INST_DIVU_MASK) == `INST_DIVU; 80 | wire inst_rem_w = (opcode_opcode_i & `INST_REM_MASK) == `INST_REM; 81 | wire inst_remu_w = (opcode_opcode_i & `INST_REMU_MASK) == `INST_REMU; 82 | 83 | wire div_rem_inst_w = ((opcode_opcode_i & `INST_DIV_MASK) == `INST_DIV) || 84 | ((opcode_opcode_i & `INST_DIVU_MASK) == `INST_DIVU) || 85 | ((opcode_opcode_i & `INST_REM_MASK) == `INST_REM) || 86 | ((opcode_opcode_i & `INST_REMU_MASK) == `INST_REMU); 87 | 88 | wire signed_operation_w = ((opcode_opcode_i & `INST_DIV_MASK) == `INST_DIV) || ((opcode_opcode_i & `INST_REM_MASK) == `INST_REM); 89 | wire div_operation_w = ((opcode_opcode_i & `INST_DIV_MASK) == `INST_DIV) || ((opcode_opcode_i & `INST_DIVU_MASK) == `INST_DIVU); 90 | 91 | reg [31:0] dividend_q; 92 | reg [62:0] divisor_q; 93 | reg [31:0] quotient_q; 94 | reg [31:0] q_mask_q; 95 | reg div_inst_q; 96 | reg div_busy_q; 97 | reg invert_res_q; 98 | 99 | wire div_start_w = opcode_valid_i & div_rem_inst_w; 100 | wire div_complete_w = !(|q_mask_q) & div_busy_q; 101 | 102 | always @(posedge clk_i or posedge rst_i) 103 | if (rst_i) 104 | begin 105 | div_busy_q <= 1'b0; 106 | dividend_q <= 32'b0; 107 | divisor_q <= 63'b0; 108 | invert_res_q <= 1'b0; 109 | quotient_q <= 32'b0; 110 | q_mask_q <= 32'b0; 111 | div_inst_q <= 1'b0; 112 | end 113 | else if (div_start_w) 114 | begin 115 | 116 | div_busy_q <= 1'b1; 117 | div_inst_q <= div_operation_w; 118 | 119 | if (signed_operation_w && opcode_ra_operand_i[31]) 120 | dividend_q <= -opcode_ra_operand_i; 121 | else 122 | dividend_q <= opcode_ra_operand_i; 123 | 124 | if (signed_operation_w && opcode_rb_operand_i[31]) 125 | divisor_q <= {-opcode_rb_operand_i, 31'b0}; 126 | else 127 | divisor_q <= {opcode_rb_operand_i, 31'b0}; 128 | 129 | invert_res_q <= (((opcode_opcode_i & `INST_DIV_MASK) == `INST_DIV) && (opcode_ra_operand_i[31] != opcode_rb_operand_i[31]) && |opcode_rb_operand_i) || 130 | (((opcode_opcode_i & `INST_REM_MASK) == `INST_REM) && opcode_ra_operand_i[31]); 131 | 132 | quotient_q <= 32'b0; 133 | q_mask_q <= 32'h80000000; 134 | end 135 | else if (div_complete_w) 136 | begin 137 | div_busy_q <= 1'b0; 138 | end 139 | else if (div_busy_q) 140 | begin 141 | if (divisor_q <= {31'b0, dividend_q}) 142 | begin 143 | dividend_q <= dividend_q - divisor_q[31:0]; 144 | quotient_q <= quotient_q | q_mask_q; 145 | end 146 | 147 | divisor_q <= {1'b0, divisor_q[62:1]}; 148 | q_mask_q <= {1'b0, q_mask_q[31:1]}; 149 | end 150 | 151 | reg [31:0] div_result_r; 152 | always @ * 153 | begin 154 | div_result_r = 32'b0; 155 | 156 | if (div_inst_q) 157 | div_result_r = invert_res_q ? -quotient_q : quotient_q; 158 | else 159 | div_result_r = invert_res_q ? -dividend_q : dividend_q; 160 | end 161 | 162 | always @(posedge clk_i or posedge rst_i) 163 | if (rst_i) 164 | valid_q <= 1'b0; 165 | else 166 | valid_q <= div_complete_w; 167 | 168 | always @(posedge clk_i or posedge rst_i) 169 | if (rst_i) 170 | wb_result_q <= 32'b0; 171 | else if (div_complete_w) 172 | wb_result_q <= div_result_r; 173 | 174 | assign writeback_valid_o = valid_q; 175 | assign writeback_value_o = wb_result_q; 176 | 177 | 178 | 179 | endmodule 180 | -------------------------------------------------------------------------------- /core/riscv/riscv_multiplier.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // RISC-V Core 3 | // V1.0.1 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2019 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: BSD 10 | //----------------------------------------------------------------- 11 | // 12 | // Copyright (c) 2014-2019, Ultra-Embedded.com 13 | // All rights reserved. 14 | // 15 | // Redistribution and use in source and binary forms, with or without 16 | // modification, are permitted provided that the following conditions 17 | // are met: 18 | // - Redistributions of source code must retain the above copyright 19 | // notice, this list of conditions and the following disclaimer. 20 | // - Redistributions in binary form must reproduce the above copyright 21 | // notice, this list of conditions and the following disclaimer 22 | // in the documentation and/or other materials provided with the 23 | // distribution. 24 | // - Neither the name of the author nor the names of its contributors 25 | // may be used to endorse or promote products derived from this 26 | // software without specific prior written permission. 27 | // 28 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 32 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 35 | // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 36 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 38 | // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 | // SUCH DAMAGE. 40 | //----------------------------------------------------------------- 41 | 42 | module riscv_multiplier 43 | ( 44 | // Inputs 45 | input clk_i 46 | ,input rst_i 47 | ,input opcode_valid_i 48 | ,input [ 31:0] opcode_opcode_i 49 | ,input [ 31:0] opcode_pc_i 50 | ,input opcode_invalid_i 51 | ,input [ 4:0] opcode_rd_idx_i 52 | ,input [ 4:0] opcode_ra_idx_i 53 | ,input [ 4:0] opcode_rb_idx_i 54 | ,input [ 31:0] opcode_ra_operand_i 55 | ,input [ 31:0] opcode_rb_operand_i 56 | ,input hold_i 57 | 58 | // Outputs 59 | ,output [ 31:0] writeback_value_o 60 | ); 61 | 62 | 63 | 64 | //----------------------------------------------------------------- 65 | // Includes 66 | //----------------------------------------------------------------- 67 | `include "riscv_defs.v" 68 | 69 | localparam MULT_STAGES = 2; // 2 or 3 70 | 71 | //------------------------------------------------------------- 72 | // Registers / Wires 73 | //------------------------------------------------------------- 74 | reg [31:0] result_e2_q; 75 | reg [31:0] result_e3_q; 76 | 77 | reg [32:0] operand_a_e1_q; 78 | reg [32:0] operand_b_e1_q; 79 | reg mulhi_sel_e1_q; 80 | 81 | //------------------------------------------------------------- 82 | // Multiplier 83 | //------------------------------------------------------------- 84 | wire [64:0] mult_result_w; 85 | reg [32:0] operand_b_r; 86 | reg [32:0] operand_a_r; 87 | reg [31:0] result_r; 88 | 89 | wire mult_inst_w = ((opcode_opcode_i & `INST_MUL_MASK) == `INST_MUL) || 90 | ((opcode_opcode_i & `INST_MULH_MASK) == `INST_MULH) || 91 | ((opcode_opcode_i & `INST_MULHSU_MASK) == `INST_MULHSU) || 92 | ((opcode_opcode_i & `INST_MULHU_MASK) == `INST_MULHU); 93 | 94 | 95 | always @ * 96 | begin 97 | if ((opcode_opcode_i & `INST_MULHSU_MASK) == `INST_MULHSU) 98 | operand_a_r = {opcode_ra_operand_i[31], opcode_ra_operand_i[31:0]}; 99 | else if ((opcode_opcode_i & `INST_MULH_MASK) == `INST_MULH) 100 | operand_a_r = {opcode_ra_operand_i[31], opcode_ra_operand_i[31:0]}; 101 | else // MULHU || MUL 102 | operand_a_r = {1'b0, opcode_ra_operand_i[31:0]}; 103 | end 104 | 105 | always @ * 106 | begin 107 | if ((opcode_opcode_i & `INST_MULHSU_MASK) == `INST_MULHSU) 108 | operand_b_r = {1'b0, opcode_rb_operand_i[31:0]}; 109 | else if ((opcode_opcode_i & `INST_MULH_MASK) == `INST_MULH) 110 | operand_b_r = {opcode_rb_operand_i[31], opcode_rb_operand_i[31:0]}; 111 | else // MULHU || MUL 112 | operand_b_r = {1'b0, opcode_rb_operand_i[31:0]}; 113 | end 114 | 115 | 116 | // Pipeline flops for multiplier 117 | always @(posedge clk_i or posedge rst_i) 118 | if (rst_i) 119 | begin 120 | operand_a_e1_q <= 33'b0; 121 | operand_b_e1_q <= 33'b0; 122 | mulhi_sel_e1_q <= 1'b0; 123 | end 124 | else if (hold_i) 125 | ; 126 | else if (opcode_valid_i && mult_inst_w) 127 | begin 128 | operand_a_e1_q <= operand_a_r; 129 | operand_b_e1_q <= operand_b_r; 130 | mulhi_sel_e1_q <= ~((opcode_opcode_i & `INST_MUL_MASK) == `INST_MUL); 131 | end 132 | else 133 | begin 134 | operand_a_e1_q <= 33'b0; 135 | operand_b_e1_q <= 33'b0; 136 | mulhi_sel_e1_q <= 1'b0; 137 | end 138 | 139 | assign mult_result_w = {{ 32 {operand_a_e1_q[32]}}, operand_a_e1_q}*{{ 32 {operand_b_e1_q[32]}}, operand_b_e1_q}; 140 | 141 | always @ * 142 | begin 143 | result_r = mulhi_sel_e1_q ? mult_result_w[63:32] : mult_result_w[31:0]; 144 | end 145 | 146 | always @(posedge clk_i or posedge rst_i) 147 | if (rst_i) 148 | result_e2_q <= 32'b0; 149 | else if (~hold_i) 150 | result_e2_q <= result_r; 151 | 152 | always @(posedge clk_i or posedge rst_i) 153 | if (rst_i) 154 | result_e3_q <= 32'b0; 155 | else if (~hold_i) 156 | result_e3_q <= result_e2_q; 157 | 158 | assign writeback_value_o = (MULT_STAGES == 3) ? result_e3_q : result_e2_q; 159 | 160 | 161 | endmodule 162 | -------------------------------------------------------------------------------- /core/riscv/riscv_xilinx_2r1w.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // RISC-V Core 3 | // V1.0.1 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2019 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: BSD 10 | //----------------------------------------------------------------- 11 | // 12 | // Copyright (c) 2014-2019, Ultra-Embedded.com 13 | // All rights reserved. 14 | // 15 | // Redistribution and use in source and binary forms, with or without 16 | // modification, are permitted provided that the following conditions 17 | // are met: 18 | // - Redistributions of source code must retain the above copyright 19 | // notice, this list of conditions and the following disclaimer. 20 | // - Redistributions in binary form must reproduce the above copyright 21 | // notice, this list of conditions and the following disclaimer 22 | // in the documentation and/or other materials provided with the 23 | // distribution. 24 | // - Neither the name of the author nor the names of its contributors 25 | // may be used to endorse or promote products derived from this 26 | // software without specific prior written permission. 27 | // 28 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 32 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 35 | // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 36 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 38 | // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 | // SUCH DAMAGE. 40 | //----------------------------------------------------------------- 41 | //----------------------------------------------------------------- 42 | // Module - Xilinx register file (2 async read, 1 write port) 43 | //----------------------------------------------------------------- 44 | module riscv_xilinx_2r1w 45 | ( 46 | // Inputs 47 | input clk_i 48 | ,input rst_i 49 | ,input [ 4:0] rd0_i 50 | ,input [ 31:0] rd0_value_i 51 | ,input [ 4:0] ra_i 52 | ,input [ 4:0] rb_i 53 | 54 | // Outputs 55 | ,output [ 31:0] ra_value_o 56 | ,output [ 31:0] rb_value_o 57 | ); 58 | 59 | 60 | //----------------------------------------------------------------- 61 | // Registers / Wires 62 | //----------------------------------------------------------------- 63 | wire [31:0] reg_rs1_w; 64 | wire [31:0] reg_rs2_w; 65 | wire [31:0] rs1_0_15_w; 66 | wire [31:0] rs1_16_31_w; 67 | wire [31:0] rs2_0_15_w; 68 | wire [31:0] rs2_16_31_w; 69 | wire write_enable_w; 70 | wire write_banka_w; 71 | wire write_bankb_w; 72 | 73 | //----------------------------------------------------------------- 74 | // Register File (using RAM16X1D ) 75 | //----------------------------------------------------------------- 76 | genvar i; 77 | 78 | // Registers 0 - 15 79 | generate 80 | for (i=0;i<32;i=i+1) 81 | begin : reg_loop1 82 | RAM16X1D reg_bit1a(.WCLK(clk_i), .WE(write_banka_w), .A0(rd0_i[0]), .A1(rd0_i[1]), .A2(rd0_i[2]), .A3(rd0_i[3]), .D(rd0_value_i[i]), .DPRA0(ra_i[0]), .DPRA1(ra_i[1]), .DPRA2(ra_i[2]), .DPRA3(ra_i[3]), .DPO(rs1_0_15_w[i]), .SPO(/* open */)); 83 | RAM16X1D reg_bit2a(.WCLK(clk_i), .WE(write_banka_w), .A0(rd0_i[0]), .A1(rd0_i[1]), .A2(rd0_i[2]), .A3(rd0_i[3]), .D(rd0_value_i[i]), .DPRA0(rb_i[0]), .DPRA1(rb_i[1]), .DPRA2(rb_i[2]), .DPRA3(rb_i[3]), .DPO(rs2_0_15_w[i]), .SPO(/* open */)); 84 | end 85 | endgenerate 86 | 87 | // Registers 16 - 31 88 | generate 89 | for (i=0;i<32;i=i+1) 90 | begin : reg_loop2 91 | RAM16X1D reg_bit1b(.WCLK(clk_i), .WE(write_bankb_w), .A0(rd0_i[0]), .A1(rd0_i[1]), .A2(rd0_i[2]), .A3(rd0_i[3]), .D(rd0_value_i[i]), .DPRA0(ra_i[0]), .DPRA1(ra_i[1]), .DPRA2(ra_i[2]), .DPRA3(ra_i[3]), .DPO(rs1_16_31_w[i]), .SPO(/* open */)); 92 | RAM16X1D reg_bit2b(.WCLK(clk_i), .WE(write_bankb_w), .A0(rd0_i[0]), .A1(rd0_i[1]), .A2(rd0_i[2]), .A3(rd0_i[3]), .D(rd0_value_i[i]), .DPRA0(rb_i[0]), .DPRA1(rb_i[1]), .DPRA2(rb_i[2]), .DPRA3(rb_i[3]), .DPO(rs2_16_31_w[i]), .SPO(/* open */)); 93 | end 94 | endgenerate 95 | 96 | //----------------------------------------------------------------- 97 | // Combinatorial Assignments 98 | //----------------------------------------------------------------- 99 | assign reg_rs1_w = (ra_i[4] == 1'b0) ? rs1_0_15_w : rs1_16_31_w; 100 | assign reg_rs2_w = (rb_i[4] == 1'b0) ? rs2_0_15_w : rs2_16_31_w; 101 | 102 | assign write_enable_w = (rd0_i != 5'b00000); 103 | 104 | assign write_banka_w = (write_enable_w & (~rd0_i[4])); 105 | assign write_bankb_w = (write_enable_w & rd0_i[4]); 106 | 107 | reg [31:0] ra_value_r; 108 | reg [31:0] rb_value_r; 109 | 110 | // Register read ports 111 | always @ * 112 | begin 113 | if (ra_i == 5'b00000) 114 | ra_value_r = 32'h00000000; 115 | else 116 | ra_value_r = reg_rs1_w; 117 | 118 | if (rb_i == 5'b00000) 119 | rb_value_r = 32'h00000000; 120 | else 121 | rb_value_r = reg_rs2_w; 122 | end 123 | 124 | assign ra_value_o = ra_value_r; 125 | assign rb_value_o = rb_value_r; 126 | 127 | endmodule 128 | 129 | //------------------------------------------------------------- 130 | // RAM16X1D: Verilator target RAM16X1D model 131 | //------------------------------------------------------------- 132 | `ifdef verilator 133 | module RAM16X1D (DPO, SPO, A0, A1, A2, A3, D, DPRA0, DPRA1, DPRA2, DPRA3, WCLK, WE); 134 | 135 | parameter INIT = 16'h0000; 136 | 137 | output DPO, SPO; 138 | 139 | input A0, A1, A2, A3, D, DPRA0, DPRA1, DPRA2, DPRA3, WCLK, WE; 140 | 141 | reg [15:0] mem; 142 | wire [3:0] adr; 143 | 144 | assign adr = {A3, A2, A1, A0}; 145 | assign SPO = mem[adr]; 146 | assign DPO = mem[{DPRA3, DPRA2, DPRA1, DPRA0}]; 147 | 148 | initial 149 | mem = INIT; 150 | 151 | always @(posedge WCLK) 152 | if (WE == 1'b1) 153 | mem[adr] <= D; 154 | 155 | endmodule 156 | `endif 157 | -------------------------------------------------------------------------------- /doc/core_exec.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultraembedded/riscv/7ae6f803e30f78c6ea3121e73c3adf50ff912730/doc/core_exec.png -------------------------------------------------------------------------------- /doc/mem_d_interface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultraembedded/riscv/7ae6f803e30f78c6ea3121e73c3adf50ff912730/doc/mem_d_interface.png -------------------------------------------------------------------------------- /doc/mem_i_interface.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultraembedded/riscv/7ae6f803e30f78c6ea3121e73c3adf50ff912730/doc/mem_i_interface.png -------------------------------------------------------------------------------- /doc/overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultraembedded/riscv/7ae6f803e30f78c6ea3121e73c3adf50ff912730/doc/overview.png -------------------------------------------------------------------------------- /doc/riscv_isa_spec.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultraembedded/riscv/7ae6f803e30f78c6ea3121e73c3adf50ff912730/doc/riscv_isa_spec.pdf -------------------------------------------------------------------------------- /doc/riscv_privileged_spec.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultraembedded/riscv/7ae6f803e30f78c6ea3121e73c3adf50ff912730/doc/riscv_privileged_spec.pdf -------------------------------------------------------------------------------- /isa_sim/README.md: -------------------------------------------------------------------------------- 1 | # RISC-V Instruction Set Simulator 2 | 3 | A simple RISC-V instruction set simulator for RV32IM. 4 | 5 | ## Building 6 | 7 | Dependencies; 8 | * gcc 9 | * make 10 | * libelf 11 | * libbfd 12 | 13 | To install the dependencies on Linux Ubuntu/Mint; 14 | ``` 15 | sudo apt-get install libelf-dev binutils-dev 16 | ``` 17 | 18 | To build the executable, type: 19 | ``` 20 | make 21 | ```` 22 | 23 | ## Usage 24 | 25 | The simulator will load and run a compiled ELF (compiled with RV32I or RV32IM compiler options); 26 | ``` 27 | # Using a makerule 28 | make run 29 | 30 | # Or running directly 31 | ./riscv-sim -f images/basic.elf 32 | ./riscv-sim -f images/linux.elf -b 0x80000000 -s 33554432 33 | ``` 34 | 35 | There are two example pre-compiled ELFs provided, one which is a basic machine mode only test program, and one 36 | which boots Linux (modified 4.19 compiled for RV32IM). 37 | 38 | ## Extensions 39 | 40 | The following primitives can be used to print to the console or to exit a simulation; 41 | ``` 42 | 43 | #define CSR_SIM_CTRL_EXIT (0 << 24) 44 | #define CSR_SIM_CTRL_PUTC (1 << 24) 45 | 46 | static inline void sim_exit(int exitcode) 47 | { 48 | unsigned int arg = CSR_SIM_CTRL_EXIT | ((unsigned char)exitcode); 49 | asm volatile ("csrw dscratch,%0": : "r" (arg)); 50 | } 51 | 52 | static inline void sim_putc(int ch) 53 | { 54 | unsigned int arg = CSR_SIM_CTRL_PUTC | (ch & 0xFF); 55 | asm volatile ("csrw dscratch,%0": : "r" (arg)); 56 | } 57 | ``` 58 | -------------------------------------------------------------------------------- /isa_sim/cosim_api.h: -------------------------------------------------------------------------------- 1 | #ifndef __CPU_API_H__ 2 | #define __CPU_API_H__ 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | //-------------------------------------------------------------------- 10 | // Cosimulation events 11 | //-------------------------------------------------------------------- 12 | typedef enum e_cosim_event 13 | { 14 | COSIM_EVENT_LOAD, 15 | COSIM_EVENT_LOAD_RESULT, 16 | COSIM_EVENT_STORE, 17 | COSIM_EVENT_MAX 18 | } t_cosim_event; 19 | 20 | class cosim_event 21 | { 22 | public: 23 | t_cosim_event type; 24 | uint32_t arg1; 25 | uint32_t arg2; 26 | }; 27 | 28 | //-------------------------------------------------------------------- 29 | // Abstract interface for CPU simulation API 30 | //-------------------------------------------------------------------- 31 | class cosim_cpu_api 32 | { 33 | public: 34 | // Reset core to execute from specified PC 35 | virtual void reset(uint32_t pc) = 0; 36 | 37 | // Status 38 | virtual bool get_fault(void) = 0; 39 | virtual bool get_stopped(void) = 0; 40 | virtual bool get_break(void) { return false; } 41 | 42 | // Execute one instruction 43 | virtual void step(void) = 0; 44 | 45 | // Breakpoints 46 | virtual bool set_breakpoint(uint32_t pc) { return false; } 47 | virtual bool clr_breakpoint(uint32_t pc) { return false; } 48 | 49 | // State after execution 50 | virtual uint32_t get_opcode(void) = 0; 51 | virtual uint32_t get_pc(void) = 0; 52 | virtual bool get_reg_valid(int r) = 0; 53 | virtual uint32_t get_register(int r) = 0; 54 | virtual int get_num_reg(void) = 0; 55 | 56 | virtual void set_register(int r, uint32_t val) = 0; 57 | virtual void set_pc(uint32_t val) { } 58 | 59 | // Trigger interrupt 60 | virtual void set_interrupt(int irq) = 0; 61 | 62 | // Instruction trace 63 | virtual void enable_trace(uint32_t mask) = 0; 64 | 65 | // Event Queue 66 | std::queue event_q[COSIM_EVENT_MAX]; 67 | void event_push(t_cosim_event ev, uint32_t arg1, uint32_t arg2) 68 | { 69 | cosim_event item; 70 | 71 | item.type = ev; 72 | item.arg1 = arg1; 73 | item.arg2 = arg2; 74 | 75 | event_q[ev].push(item); 76 | } 77 | bool event_ready(t_cosim_event ev) { return !event_q[ev].empty(); } 78 | cosim_event event_pop(t_cosim_event ev) 79 | { 80 | cosim_event item = event_q[ev].front(); 81 | event_q[ev].pop(); 82 | return item; 83 | } 84 | }; 85 | 86 | //-------------------------------------------------------------------- 87 | // Abstract interface for memory access 88 | //-------------------------------------------------------------------- 89 | class cosim_mem_api 90 | { 91 | public: 92 | virtual bool create_memory(uint32_t addr, uint32_t size, uint8_t *mem = NULL) = 0; 93 | virtual bool valid_addr(uint32_t addr) = 0; 94 | virtual void write(uint32_t addr, uint8_t data) = 0; 95 | virtual uint8_t read(uint32_t addr) = 0; 96 | }; 97 | 98 | //-------------------------------------------------------------------- 99 | // Structures 100 | //-------------------------------------------------------------------- 101 | class cosim_cpu_item 102 | { 103 | public: 104 | std::string name; 105 | cosim_cpu_api *cpu; 106 | }; 107 | 108 | class cosim_mem_item 109 | { 110 | public: 111 | std::string name; 112 | cosim_mem_api *mem; 113 | uint32_t base; 114 | uint32_t size; 115 | }; 116 | 117 | //-------------------------------------------------------------------- 118 | // Class: Cosimulation framework 119 | //-------------------------------------------------------------------- 120 | class cosim: public cosim_cpu_api, cosim_mem_api 121 | { 122 | private: 123 | static cosim * s_instance; 124 | cosim() { m_dump_file = NULL; } 125 | 126 | public: 127 | static cosim *instance(void) 128 | { 129 | if (!s_instance) 130 | s_instance = new cosim(); 131 | return s_instance; 132 | } 133 | 134 | void attach_cpu(std::string name, cosim_cpu_api *p); 135 | void attach_mem(std::string name, cosim_mem_api *p, uint32_t base, uint32_t size); 136 | 137 | // cosim_cpu_api 138 | 139 | // Reset core to execute from specified PC 140 | void reset(uint32_t pc); 141 | 142 | // Status 143 | bool get_fault(void); 144 | bool get_stopped(void); 145 | 146 | // Execute one instruction 147 | void step(void); 148 | 149 | // State after execution 150 | uint32_t get_opcode(void); 151 | uint32_t get_pc(void); 152 | bool get_reg_valid(int r); 153 | uint32_t get_register(int r); 154 | int get_num_reg(void); 155 | 156 | void set_register(int r, uint32_t val); 157 | 158 | // Trigger interrupt 159 | void set_interrupt(int irq); 160 | 161 | void enable_trace(uint32_t mask); 162 | 163 | // cosim_mem_api 164 | bool create_memory(uint32_t addr, uint32_t size, uint8_t *mem = NULL); 165 | bool valid_addr(uint32_t addr); 166 | void write(uint32_t addr, uint8_t data); 167 | uint8_t read(uint32_t addr); 168 | 169 | void write_word(uint32_t addr, uint32_t data); 170 | uint32_t read_word(uint32_t addr); 171 | 172 | void at_exit(uint32_t exitcode); 173 | 174 | // Set memory dump on exit 175 | void dump_on_exit(const char *filename, uint32_t dump_start, uint32_t dump_end) 176 | { 177 | m_dump_file = filename; 178 | m_dump_start = dump_start; 179 | m_dump_end = dump_end; 180 | } 181 | 182 | private: 183 | std::vector m_cpu; 184 | std::vector m_mem; 185 | 186 | const char * m_dump_file; 187 | uint32_t m_dump_start; 188 | uint32_t m_dump_end; 189 | }; 190 | 191 | #endif 192 | -------------------------------------------------------------------------------- /isa_sim/elf_load.cpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // RISC-V ISA Simulator 3 | // V1.0 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2017 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: BSD 10 | //----------------------------------------------------------------- 11 | // 12 | // Copyright (c) 2014, Ultra-Embedded.com 13 | // All rights reserved. 14 | // 15 | // Redistribution and use in source and binary forms, with or without 16 | // modification, are permitted provided that the following conditions 17 | // are met: 18 | // - Redistributions of source code must retain the above copyright 19 | // notice, this list of conditions and the following disclaimer. 20 | // - Redistributions in binary form must reproduce the above copyright 21 | // notice, this list of conditions and the following disclaimer 22 | // in the documentation and/or other materials provided with the 23 | // distribution. 24 | // - Neither the name of the author nor the names of its contributors 25 | // may be used to endorse or promote products derived from this 26 | // software without specific prior written permission. 27 | // 28 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 32 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 35 | // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 36 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 38 | // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 | // SUCH DAMAGE. 40 | //----------------------------------------------------------------- 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | #include 47 | #include 48 | #include 49 | 50 | #include "elf_load.h" 51 | 52 | //----------------------------------------------------------------- 53 | // elf_load 54 | //----------------------------------------------------------------- 55 | int elf_load(const char *filename, cb_mem_create fn_create, cb_mem_load fn_load, void *arg, uint32_t *start_addr) 56 | { 57 | int fd; 58 | Elf * e; 59 | Elf_Kind ek; 60 | Elf_Scn *scn; 61 | Elf_Data *data; 62 | Elf32_Shdr *shdr; 63 | size_t shstrndx; 64 | 65 | if (elf_version ( EV_CURRENT ) == EV_NONE) 66 | return 0; 67 | 68 | if ((fd = open ( filename , O_RDONLY , 0)) < 0) 69 | return 0; 70 | 71 | if ((e = elf_begin ( fd , ELF_C_READ, NULL )) == NULL) 72 | return 0; 73 | 74 | ek = elf_kind ( e ); 75 | if (ek != ELF_K_ELF) 76 | return 0; 77 | 78 | // Get section name header index 79 | if (elf_getshdrstrndx(e, &shstrndx)!=0) 80 | return 0; 81 | 82 | // Get entry point 83 | if (start_addr) 84 | { 85 | GElf_Ehdr _ehdr; 86 | GElf_Ehdr *ehdr = gelf_getehdr(e, &_ehdr); 87 | *start_addr = (uint32_t)ehdr->e_entry; 88 | } 89 | 90 | int section_idx = 0; 91 | while ((scn = elf_getscn(e, section_idx)) != NULL) 92 | { 93 | shdr = elf32_getshdr(scn); 94 | 95 | // Section which need allocating 96 | if ((shdr->sh_flags & SHF_ALLOC) && (shdr->sh_size > 0)) 97 | { 98 | data = elf_getdata(scn, NULL); 99 | 100 | printf("Memory: 0x%x - 0x%x (Size=%dKB) [%s]\n", shdr->sh_addr, shdr->sh_addr + shdr->sh_size - 1, shdr->sh_size / 1024, elf_strptr(e, shstrndx, shdr->sh_name)); 101 | 102 | if (!fn_create(arg, shdr->sh_addr, shdr->sh_size)) 103 | { 104 | fprintf(stderr, "ERROR: Cannot allocate memory region\n"); 105 | close (fd); 106 | return 0; 107 | } 108 | 109 | if (shdr->sh_type == SHT_PROGBITS) 110 | { 111 | int i; 112 | for (i=0;ish_size;i++) 113 | { 114 | if (!fn_load(arg, shdr->sh_addr + i, ((uint8_t*)data->d_buf)[i])) 115 | { 116 | fprintf(stderr, "ERROR: Cannot write byte to 0x%08x\n", shdr->sh_addr + i); 117 | close (fd); 118 | return 0; 119 | } 120 | } 121 | } 122 | } 123 | 124 | section_idx++; 125 | } 126 | 127 | elf_end ( e ); 128 | close ( fd ); 129 | 130 | return 1; 131 | } 132 | //----------------------------------------------------------------- 133 | // elf_get_symbol 134 | //----------------------------------------------------------------- 135 | long elf_get_symbol(const char *filename, const char *symname) 136 | { 137 | bfd *ibfd; 138 | asymbol **symtab; 139 | long nsize, nsyms, i; 140 | symbol_info syminfo; 141 | char **matching; 142 | 143 | bfd_init(); 144 | ibfd = bfd_openr(filename, NULL); 145 | 146 | if (ibfd == NULL) 147 | { 148 | printf("bfd_openr error\n"); 149 | return -1; 150 | } 151 | 152 | if (!bfd_check_format_matches(ibfd, bfd_object, &matching)) 153 | { 154 | printf("format_matches\n"); 155 | return -1; 156 | } 157 | 158 | nsize = bfd_get_symtab_upper_bound (ibfd); 159 | symtab = (asymbol **)malloc(nsize); 160 | nsyms = bfd_canonicalize_symtab(ibfd, symtab); 161 | 162 | for (i = 0; i < nsyms; i++) { 163 | if (strcmp(symtab[i]->name, symname) == 0) { 164 | bfd_symbol_info(symtab[i], &syminfo); 165 | return (long) syminfo.value; 166 | } 167 | } 168 | 169 | bfd_close(ibfd); 170 | return -1; 171 | } 172 | -------------------------------------------------------------------------------- /isa_sim/elf_load.h: -------------------------------------------------------------------------------- 1 | #ifndef __ELF_LOAD_H__ 2 | #define __ELF_LOAD_H__ 3 | 4 | #include 5 | 6 | //------------------------------------------------------------- 7 | // Types 8 | //------------------------------------------------------------- 9 | typedef int (*cb_mem_create)(void *arg, uint32_t base, uint32_t size); 10 | typedef int (*cb_mem_load)(void *arg, uint32_t addr, uint8_t data); 11 | 12 | //------------------------------------------------------------- 13 | // Functions 14 | //------------------------------------------------------------- 15 | int elf_load(const char *filename, cb_mem_create fn_create, cb_mem_load fn_load, void *arg, uint32_t *start_addr); 16 | long elf_get_symbol(const char *filename, const char *symname); 17 | 18 | #endif -------------------------------------------------------------------------------- /isa_sim/images/basic.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultraembedded/riscv/7ae6f803e30f78c6ea3121e73c3adf50ff912730/isa_sim/images/basic.elf -------------------------------------------------------------------------------- /isa_sim/images/linux.elf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ultraembedded/riscv/7ae6f803e30f78c6ea3121e73c3adf50ff912730/isa_sim/images/linux.elf -------------------------------------------------------------------------------- /isa_sim/main.cpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // RISC-V ISA Simulator 3 | // V1.0 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2017 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: BSD 10 | //----------------------------------------------------------------- 11 | // 12 | // Copyright (c) 2014, Ultra-Embedded.com 13 | // All rights reserved. 14 | // 15 | // Redistribution and use in source and binary forms, with or without 16 | // modification, are permitted provided that the following conditions 17 | // are met: 18 | // - Redistributions of source code must retain the above copyright 19 | // notice, this list of conditions and the following disclaimer. 20 | // - Redistributions in binary form must reproduce the above copyright 21 | // notice, this list of conditions and the following disclaimer 22 | // in the documentation and/or other materials provided with the 23 | // distribution. 24 | // - Neither the name of the author nor the names of its contributors 25 | // may be used to endorse or promote products derived from this 26 | // software without specific prior written permission. 27 | // 28 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 32 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 35 | // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 36 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 38 | // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 | // SUCH DAMAGE. 40 | //----------------------------------------------------------------- 41 | #include 42 | #include 43 | #include 44 | #include 45 | 46 | #include "riscv_main.h" 47 | #include "riscv.h" 48 | #include "cosim_api.h" 49 | 50 | //----------------------------------------------------------------- 51 | // main 52 | //----------------------------------------------------------------- 53 | int main(int argc, char *argv[]) 54 | { 55 | int exitcode; 56 | 57 | Riscv * sim = new Riscv(); 58 | 59 | cosim::instance()->attach_cpu("sim", sim); 60 | cosim::instance()->attach_mem("sim", sim, 0, 0xFFFFFFFF); 61 | 62 | exitcode = riscv_main(sim, argc, argv); 63 | 64 | // Show execution stats 65 | sim->stats_dump(); 66 | 67 | delete sim; 68 | sim = NULL; 69 | 70 | return exitcode; 71 | } 72 | -------------------------------------------------------------------------------- /isa_sim/makefile: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | ## Simulator Makefile 3 | ############################################################################### 4 | 5 | # Target 6 | TARGET ?= riscv-sim 7 | TARGET_LIB ?= libisa_sim.a 8 | 9 | RUN_ELF ?= images/linux.elf 10 | RUN_OPTS ?= "-b 0x80000000 -s 33554432" 11 | 12 | # Options 13 | MMU ?= yes 14 | 15 | CFLAGS = -O2 -fPIC 16 | ifeq ($(MMU), yes) 17 | CFLAGS += -DCONFIG_MMU 18 | endif 19 | 20 | LDFLAGS = 21 | LIBS = -lelf -lbfd 22 | 23 | # Source Files 24 | SRC_DIR = . 25 | 26 | ############################################################################### 27 | # Variables 28 | ############################################################################### 29 | OBJ_DIR ?= obj/$(TARGET)/ 30 | 31 | ############################################################################### 32 | # Variables: Lists of objects, source and deps 33 | ############################################################################### 34 | # SRC / Object list 35 | src2obj = $(OBJ_DIR)$(patsubst %$(suffix $(1)),%.o,$(notdir $(1))) 36 | 37 | SRC ?= $(foreach src,$(SRC_DIR),$(wildcard $(src)/*.cpp)) 38 | OBJ ?= $(foreach src,$(SRC),$(call src2obj,$(src))) 39 | LIB_OBJ ?= $(foreach src,$(filter-out main.cpp,$(SRC)),$(call src2obj,$(src))) 40 | 41 | ############################################################################### 42 | # Rules: Compilation macro 43 | ############################################################################### 44 | define template_cpp 45 | $(call src2obj,$(1)): $(1) | $(OBJ_DIR) 46 | @echo "# Compiling $(notdir $(1))" 47 | @g++ $(CFLAGS) -c $$< -o $$@ 48 | endef 49 | 50 | ############################################################################### 51 | # Rules 52 | ############################################################################### 53 | all: $(TARGET) lib 54 | 55 | $(OBJ_DIR): 56 | @mkdir -p $@ 57 | 58 | $(foreach src,$(SRC),$(eval $(call template_cpp,$(src)))) 59 | 60 | $(TARGET): $(OBJ) makefile 61 | g++ $(LDFLAGS) $(OBJ) $(LIBS) -o $@ 62 | 63 | lib: $(LIB_OBJ) 64 | g++ -shared -o $(TARGET_LIB) $(LIB_OBJ) 65 | 66 | clean: 67 | -rm -rf $(OBJ_DIR) $(TARGET) $(TARGET_LIB) 68 | 69 | run: $(TARGET) 70 | ./$(TARGET) -f $(RUN_ELF) $(RUN_OPTS) 71 | -------------------------------------------------------------------------------- /isa_sim/memory.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // RISC-V ISA Simulator 3 | // V1.0 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2017 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: BSD 10 | //----------------------------------------------------------------- 11 | // 12 | // Copyright (c) 2014, Ultra-Embedded.com 13 | // All rights reserved. 14 | // 15 | // Redistribution and use in source and binary forms, with or without 16 | // modification, are permitted provided that the following conditions 17 | // are met: 18 | // - Redistributions of source code must retain the above copyright 19 | // notice, this list of conditions and the following disclaimer. 20 | // - Redistributions in binary form must reproduce the above copyright 21 | // notice, this list of conditions and the following disclaimer 22 | // in the documentation and/or other materials provided with the 23 | // distribution. 24 | // - Neither the name of the author nor the names of its contributors 25 | // may be used to endorse or promote products derived from this 26 | // software without specific prior written permission. 27 | // 28 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 32 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 35 | // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 36 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 38 | // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 | // SUCH DAMAGE. 40 | //----------------------------------------------------------------- 41 | #ifndef __MEMORY_H__ 42 | #define __MEMORY_H__ 43 | 44 | #include 45 | 46 | //-------------------------------------------------------------------- 47 | // Abstract interface for memories 48 | //-------------------------------------------------------------------- 49 | class Memory 50 | { 51 | public: 52 | virtual void reset(void) = 0; 53 | virtual uint32_t load(uint32_t address, int width, bool signedLoad) = 0; 54 | virtual void store(uint32_t address, uint32_t data, int width) = 0; 55 | }; 56 | 57 | //----------------------------------------------------------------- 58 | // Simple little endian memory 59 | //----------------------------------------------------------------- 60 | class SimpleMemory: public Memory 61 | { 62 | public: 63 | SimpleMemory(int size) 64 | { 65 | Mem = new uint32_t[(size + 3)/4]; 66 | Size = size; 67 | } 68 | SimpleMemory(uint8_t * buf, int size) 69 | { 70 | Mem = (uint32_t*)buf; 71 | Size = size; 72 | } 73 | 74 | virtual void reset(void) 75 | { 76 | memset(Mem, 0, Size); 77 | } 78 | 79 | virtual uint32_t load(uint32_t address, int width, bool signedLoad) 80 | { 81 | uint32_t data = 0; 82 | 83 | switch (width) 84 | { 85 | case 4: 86 | assert(!(address & 3)); 87 | data = Mem[address / 4]; 88 | break; 89 | case 2: 90 | assert(!(address & 1)); 91 | 92 | if (address & 2) 93 | data = (Mem[address / 4] >> 16) & 0xFFFF; 94 | else 95 | data = (Mem[address / 4] >> 0) & 0xFFFF; 96 | 97 | if (signedLoad) 98 | if (data & (1 << 15)) 99 | data |= 0xFFFF0000; 100 | break; 101 | case 1: 102 | switch (address & 3) 103 | { 104 | case 3: 105 | data = (Mem[address / 4] >> 24) & 0xFF; 106 | break; 107 | case 2: 108 | data = (Mem[address / 4] >> 16) & 0xFF; 109 | break; 110 | case 1: 111 | data = (Mem[address / 4] >> 8) & 0xFF; 112 | break; 113 | case 0: 114 | data = (Mem[address / 4] >> 0) & 0xFF; 115 | break; 116 | } 117 | 118 | if (signedLoad) 119 | if (data & (1 << 7)) 120 | data |= 0xFFFFFF00; 121 | break; 122 | } 123 | 124 | return data; 125 | } 126 | 127 | virtual void store(uint32_t address, uint32_t data, int width) 128 | { 129 | switch (width) 130 | { 131 | case 4: 132 | assert(!(address & 3)); 133 | Mem[address / 4] = data; 134 | break; 135 | case 2: 136 | assert(!(address & 1)); 137 | if (address & 2) 138 | Mem[address / 4] = (Mem[address / 4] & 0x0000FFFF) | ((data << 16) & 0xFFFF0000); 139 | else 140 | Mem[address / 4] = (Mem[address / 4] & 0xFFFF0000) | ((data << 0) & 0x0000FFFF); 141 | break; 142 | case 1: 143 | switch (address & 3) 144 | { 145 | case 3: 146 | Mem[address / 4] = (Mem[address / 4] & 0x00FFFFFF) | ((data << 24) & 0xFF000000); 147 | break; 148 | case 2: 149 | Mem[address / 4] = (Mem[address / 4] & 0xFF00FFFF) | ((data << 16) & 0x00FF0000); 150 | break; 151 | case 1: 152 | Mem[address / 4] = (Mem[address / 4] & 0xFFFF00FF) | ((data << 8) & 0x0000FF00); 153 | break; 154 | case 0: 155 | Mem[address / 4] = (Mem[address / 4] & 0xFFFFFF00) | ((data << 0) & 0x000000FF); 156 | break; 157 | } 158 | break; 159 | } 160 | } 161 | 162 | private: 163 | uint32_t *Mem; 164 | int Size; 165 | }; 166 | 167 | #endif 168 | -------------------------------------------------------------------------------- /isa_sim/riscv_inst_dump.h: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // RISC-V ISA Simulator 3 | // V0.1 4 | // Ultra-Embedded.com 5 | // Copyright 2014 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: BSD 10 | //----------------------------------------------------------------- 11 | // 12 | // Copyright (c) 2014, Ultra-Embedded.com 13 | // All rights reserved. 14 | // 15 | // Redistribution and use in source and binary forms, with or without 16 | // modification, are permitted provided that the following conditions 17 | // are met: 18 | // - Redistributions of source code must retain the above copyright 19 | // notice, this list of conditions and the following disclaimer. 20 | // - Redistributions in binary form must reproduce the above copyright 21 | // notice, this list of conditions and the following disclaimer 22 | // in the documentation and/or other materials provided with the 23 | // distribution. 24 | // - Neither the name of the author nor the names of its contributors 25 | // may be used to endorse or promote products derived from this 26 | // software without specific prior written permission. 27 | // 28 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 32 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 35 | // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 36 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 38 | // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 | // SUCH DAMAGE. 40 | //----------------------------------------------------------------- 41 | #ifndef __RISCV_INST_DUMP_H__ 42 | #define __RISCV_INST_DUMP_H__ 43 | 44 | #include 45 | 46 | //-------------------------------------------------------------------- 47 | // Prototypes: 48 | //-------------------------------------------------------------------- 49 | bool riscv_inst_decode(char *str, uint32_t pc, uint32_t opcode); 50 | void riscv_inst_print(uint32_t pc, uint32_t opcode); 51 | 52 | #endif 53 | -------------------------------------------------------------------------------- /isa_sim/riscv_main.cpp: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // RISC-V ISA Simulator 3 | // V1.0 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2017 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: BSD 10 | //----------------------------------------------------------------- 11 | // 12 | // Copyright (c) 2014, Ultra-Embedded.com 13 | // All rights reserved. 14 | // 15 | // Redistribution and use in source and binary forms, with or without 16 | // modification, are permitted provided that the following conditions 17 | // are met: 18 | // - Redistributions of source code must retain the above copyright 19 | // notice, this list of conditions and the following disclaimer. 20 | // - Redistributions in binary form must reproduce the above copyright 21 | // notice, this list of conditions and the following disclaimer 22 | // in the documentation and/or other materials provided with the 23 | // distribution. 24 | // - Neither the name of the author nor the names of its contributors 25 | // may be used to endorse or promote products derived from this 26 | // software without specific prior written permission. 27 | // 28 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 32 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 35 | // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 36 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 38 | // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 | // SUCH DAMAGE. 40 | //----------------------------------------------------------------- 41 | #include 42 | #include 43 | #include 44 | #include 45 | #include 46 | 47 | #include "riscv.h" 48 | #include "elf_load.h" 49 | #include "cosim_api.h" 50 | 51 | #include "riscv_main.h" 52 | 53 | //----------------------------------------------------------------- 54 | // mem_create: Create memory region 55 | //----------------------------------------------------------------- 56 | static int mem_create(void *arg, uint32_t base, uint32_t size) 57 | { 58 | return cosim::instance()->create_memory(base, size); 59 | } 60 | //----------------------------------------------------------------- 61 | // mem_load: Load byte into memory 62 | //----------------------------------------------------------------- 63 | static int mem_load(void *arg, uint32_t addr, uint8_t data) 64 | { 65 | cosim::instance()->write(addr, data); 66 | return cosim::instance()->valid_addr(addr); 67 | } 68 | //----------------------------------------------------------------- 69 | // riscv_main 70 | //----------------------------------------------------------------- 71 | int riscv_main(cosim_cpu_api *sim, int argc, char *argv[]) 72 | { 73 | unsigned _cycles = 0; 74 | int max_cycles = -1; 75 | char *filename = NULL; 76 | int help = 0; 77 | int trace = 0; 78 | uint32_t trace_mask = 1; 79 | uint32_t stop_pc = 0xFFFFFFFF; 80 | uint32_t trace_pc = 0xFFFFFFFF; 81 | uint32_t mem_base = 0x00000000; 82 | uint32_t mem_size = (32 * 1024 * 1024); 83 | bool explicit_mem = false; 84 | char * dump_file = NULL; 85 | char * dump_sym_start = NULL; 86 | char * dump_sym_end = NULL; 87 | int c; 88 | 89 | while ((c = getopt (argc, argv, "t:v:f:c:r:d:b:s:e:p:j:k:")) != -1) 90 | { 91 | switch(c) 92 | { 93 | case 't': 94 | trace = strtoul(optarg, NULL, 0); 95 | break; 96 | case 'v': 97 | trace_mask = strtoul(optarg, NULL, 0); 98 | break; 99 | case 'r': 100 | stop_pc = strtoul(optarg, NULL, 0); 101 | break; 102 | case 'f': 103 | filename = optarg; 104 | break; 105 | case 'c': 106 | max_cycles = (int)strtoul(optarg, NULL, 0); 107 | break; 108 | case 'b': 109 | mem_base = strtoul(optarg, NULL, 0); 110 | explicit_mem = true; 111 | break; 112 | case 's': 113 | mem_size = strtoul(optarg, NULL, 0); 114 | explicit_mem = true; 115 | break; 116 | case 'e': 117 | trace_pc = strtoul(optarg, NULL, 0); 118 | break; 119 | case 'p': 120 | dump_file = optarg; 121 | break; 122 | case 'j': 123 | dump_sym_start = optarg; 124 | break; 125 | case 'k': 126 | dump_sym_end = optarg; 127 | break; 128 | case '?': 129 | default: 130 | help = 1; 131 | break; 132 | } 133 | } 134 | 135 | if (help || filename == NULL) 136 | { 137 | fprintf (stderr,"Usage:\n"); 138 | fprintf (stderr,"-f filename.elf = Executable to load (ELF)\n"); 139 | fprintf (stderr,"-t [0/1] = Enable program trace\n"); 140 | fprintf (stderr,"-v 0xX = Trace Mask\n"); 141 | fprintf (stderr,"-c nnnn = Max instructions to execute\n"); 142 | fprintf (stderr,"-r 0xnnnn = Stop at PC address\n"); 143 | fprintf (stderr,"-e 0xnnnn = Trace from PC address\n"); 144 | fprintf (stderr,"-b 0xnnnn = Memory base address (for binary loads)\n"); 145 | fprintf (stderr,"-s nnnn = Memory size (for binary loads)\n"); 146 | fprintf (stderr,"-p dumpfile.bin = Post simulation memory dump file\n"); 147 | fprintf (stderr,"-j sym_name = Symbol for memory dump start\n"); 148 | fprintf (stderr,"-k sym_name = Symbol for memory dump end\n"); 149 | exit(-1); 150 | } 151 | 152 | if (explicit_mem) 153 | { 154 | printf("MEM: Create memory 0x%08x-%08x\n", mem_base, mem_base + mem_size-1); 155 | mem_create(NULL, mem_base, mem_size); 156 | } 157 | 158 | uint32_t start_addr = 0; 159 | 160 | // Load ELF file 161 | if (elf_load(filename, mem_create, mem_load, sim, &start_addr)) 162 | { 163 | printf("Starting from 0x%08x\n", start_addr); 164 | 165 | // Register dump handler 166 | if (dump_file) 167 | { 168 | cosim::instance()->dump_on_exit(dump_file, 169 | (uint32_t)elf_get_symbol(filename, dump_sym_start), 170 | (uint32_t)elf_get_symbol(filename, dump_sym_end)); 171 | } 172 | 173 | // Reset CPU to given start PC 174 | sim->reset(start_addr); 175 | 176 | // Enable trace? 177 | if (trace) 178 | sim->enable_trace(trace_mask); 179 | 180 | _cycles = 0; 181 | 182 | uint32_t current_pc = 0; 183 | while (!sim->get_fault() && !sim->get_stopped() && current_pc != stop_pc) 184 | { 185 | current_pc = sim->get_pc(); 186 | sim->step(); 187 | _cycles++; 188 | 189 | if (max_cycles != -1 && max_cycles == _cycles) 190 | break; 191 | 192 | // Turn trace on 193 | if (trace_pc == current_pc) 194 | sim->enable_trace(trace_mask); 195 | } 196 | 197 | cosim::instance()->at_exit(sim->get_fault()); 198 | } 199 | else 200 | fprintf (stderr,"Error: Could not open %s\n", filename); 201 | 202 | // Fault occurred? 203 | if (sim->get_fault()) 204 | return 1; 205 | else 206 | return 0; 207 | } 208 | -------------------------------------------------------------------------------- /isa_sim/riscv_main.h: -------------------------------------------------------------------------------- 1 | #ifndef __RISCV_MAIN_H__ 2 | #define __RISCV_MAIN_H__ 3 | 4 | #include "cosim_api.h" 5 | 6 | //------------------------------------------------------------- 7 | // Functions 8 | //------------------------------------------------------------- 9 | int riscv_main(cosim_cpu_api *sim, int argc, char *argv[]); 10 | 11 | #endif -------------------------------------------------------------------------------- /top_cache_axi/src_v/dcache_core_data_ram.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // RISC-V Top 3 | // V0.6 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2019 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: BSD 10 | //----------------------------------------------------------------- 11 | // 12 | // Copyright (c) 2014, Ultra-Embedded.com 13 | // All rights reserved. 14 | // 15 | // Redistribution and use in source and binary forms, with or without 16 | // modification, are permitted provided that the following conditions 17 | // are met: 18 | // - Redistributions of source code must retain the above copyright 19 | // notice, this list of conditions and the following disclaimer. 20 | // - Redistributions in binary form must reproduce the above copyright 21 | // notice, this list of conditions and the following disclaimer 22 | // in the documentation and/or other materials provided with the 23 | // distribution. 24 | // - Neither the name of the author nor the names of its contributors 25 | // may be used to endorse or promote products derived from this 26 | // software without specific prior written permission. 27 | // 28 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 32 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 35 | // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 36 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 38 | // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 | // SUCH DAMAGE. 40 | //----------------------------------------------------------------- 41 | 42 | //----------------------------------------------------------------- 43 | // Generated File 44 | //----------------------------------------------------------------- 45 | module dcache_core_data_ram 46 | ( 47 | // Inputs 48 | input clk0_i 49 | ,input rst0_i 50 | ,input [ 10:0] addr0_i 51 | ,input [ 31:0] data0_i 52 | ,input [ 3:0] wr0_i 53 | ,input clk1_i 54 | ,input rst1_i 55 | ,input [ 10:0] addr1_i 56 | ,input [ 31:0] data1_i 57 | ,input [ 3:0] wr1_i 58 | 59 | // Outputs 60 | ,output [ 31:0] data0_o 61 | ,output [ 31:0] data1_o 62 | ); 63 | 64 | 65 | 66 | //----------------------------------------------------------------- 67 | // Dual Port RAM 8KB 68 | // Mode: Read First 69 | //----------------------------------------------------------------- 70 | /* verilator lint_off MULTIDRIVEN */ 71 | reg [31:0] ram [2047:0] /*verilator public*/; 72 | /* verilator lint_on MULTIDRIVEN */ 73 | 74 | reg [31:0] ram_read0_q; 75 | reg [31:0] ram_read1_q; 76 | 77 | 78 | // Synchronous write 79 | always @ (posedge clk0_i) 80 | begin 81 | if (wr0_i[0]) 82 | ram[addr0_i][7:0] <= data0_i[7:0]; 83 | if (wr0_i[1]) 84 | ram[addr0_i][15:8] <= data0_i[15:8]; 85 | if (wr0_i[2]) 86 | ram[addr0_i][23:16] <= data0_i[23:16]; 87 | if (wr0_i[3]) 88 | ram[addr0_i][31:24] <= data0_i[31:24]; 89 | 90 | ram_read0_q <= ram[addr0_i]; 91 | end 92 | 93 | always @ (posedge clk1_i) 94 | begin 95 | if (wr1_i[0]) 96 | ram[addr1_i][7:0] <= data1_i[7:0]; 97 | if (wr1_i[1]) 98 | ram[addr1_i][15:8] <= data1_i[15:8]; 99 | if (wr1_i[2]) 100 | ram[addr1_i][23:16] <= data1_i[23:16]; 101 | if (wr1_i[3]) 102 | ram[addr1_i][31:24] <= data1_i[31:24]; 103 | 104 | ram_read1_q <= ram[addr1_i]; 105 | end 106 | 107 | assign data0_o = ram_read0_q; 108 | assign data1_o = ram_read1_q; 109 | 110 | 111 | 112 | endmodule 113 | -------------------------------------------------------------------------------- /top_cache_axi/src_v/dcache_core_tag_ram.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // RISC-V Top 3 | // V0.6 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2019 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: BSD 10 | //----------------------------------------------------------------- 11 | // 12 | // Copyright (c) 2014, Ultra-Embedded.com 13 | // All rights reserved. 14 | // 15 | // Redistribution and use in source and binary forms, with or without 16 | // modification, are permitted provided that the following conditions 17 | // are met: 18 | // - Redistributions of source code must retain the above copyright 19 | // notice, this list of conditions and the following disclaimer. 20 | // - Redistributions in binary form must reproduce the above copyright 21 | // notice, this list of conditions and the following disclaimer 22 | // in the documentation and/or other materials provided with the 23 | // distribution. 24 | // - Neither the name of the author nor the names of its contributors 25 | // may be used to endorse or promote products derived from this 26 | // software without specific prior written permission. 27 | // 28 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 32 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 35 | // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 36 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 38 | // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 | // SUCH DAMAGE. 40 | //----------------------------------------------------------------- 41 | 42 | //----------------------------------------------------------------- 43 | // Generated File 44 | //----------------------------------------------------------------- 45 | module dcache_core_tag_ram 46 | ( 47 | // Inputs 48 | input clk0_i 49 | ,input rst0_i 50 | ,input [ 7:0] addr0_i 51 | ,input clk1_i 52 | ,input rst1_i 53 | ,input [ 7:0] addr1_i 54 | ,input [ 20:0] data1_i 55 | ,input wr1_i 56 | 57 | // Outputs 58 | ,output [ 20:0] data0_o 59 | ); 60 | 61 | 62 | 63 | //----------------------------------------------------------------- 64 | // Tag RAM 0KB (256 x 21) 65 | // Mode: Write First 66 | //----------------------------------------------------------------- 67 | /* verilator lint_off MULTIDRIVEN */ 68 | reg [20:0] ram [255:0] /*verilator public*/; 69 | /* verilator lint_on MULTIDRIVEN */ 70 | 71 | reg [20:0] ram_read0_q; 72 | 73 | always @ (posedge clk1_i) 74 | begin 75 | if (wr1_i) 76 | ram[addr1_i] = data1_i; 77 | 78 | ram_read0_q = ram[addr0_i]; 79 | end 80 | 81 | assign data0_o = ram_read0_q; 82 | 83 | 84 | endmodule 85 | -------------------------------------------------------------------------------- /top_cache_axi/src_v/dcache_mux.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // RISC-V Top 3 | // V0.6 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2019 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: BSD 10 | //----------------------------------------------------------------- 11 | // 12 | // Copyright (c) 2014, Ultra-Embedded.com 13 | // All rights reserved. 14 | // 15 | // Redistribution and use in source and binary forms, with or without 16 | // modification, are permitted provided that the following conditions 17 | // are met: 18 | // - Redistributions of source code must retain the above copyright 19 | // notice, this list of conditions and the following disclaimer. 20 | // - Redistributions in binary form must reproduce the above copyright 21 | // notice, this list of conditions and the following disclaimer 22 | // in the documentation and/or other materials provided with the 23 | // distribution. 24 | // - Neither the name of the author nor the names of its contributors 25 | // may be used to endorse or promote products derived from this 26 | // software without specific prior written permission. 27 | // 28 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 32 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 35 | // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 36 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 38 | // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 | // SUCH DAMAGE. 40 | //----------------------------------------------------------------- 41 | 42 | //----------------------------------------------------------------- 43 | // Generated File 44 | //----------------------------------------------------------------- 45 | module dcache_mux 46 | ( 47 | // Inputs 48 | input clk_i 49 | ,input rst_i 50 | ,input [ 31:0] mem_addr_i 51 | ,input [ 31:0] mem_data_wr_i 52 | ,input mem_rd_i 53 | ,input [ 3:0] mem_wr_i 54 | ,input mem_cacheable_i 55 | ,input [ 10:0] mem_req_tag_i 56 | ,input mem_invalidate_i 57 | ,input mem_writeback_i 58 | ,input mem_flush_i 59 | ,input [ 31:0] mem_cached_data_rd_i 60 | ,input mem_cached_accept_i 61 | ,input mem_cached_ack_i 62 | ,input mem_cached_error_i 63 | ,input [ 10:0] mem_cached_resp_tag_i 64 | ,input [ 31:0] mem_uncached_data_rd_i 65 | ,input mem_uncached_accept_i 66 | ,input mem_uncached_ack_i 67 | ,input mem_uncached_error_i 68 | ,input [ 10:0] mem_uncached_resp_tag_i 69 | 70 | // Outputs 71 | ,output [ 31:0] mem_data_rd_o 72 | ,output mem_accept_o 73 | ,output mem_ack_o 74 | ,output mem_error_o 75 | ,output [ 10:0] mem_resp_tag_o 76 | ,output [ 31:0] mem_cached_addr_o 77 | ,output [ 31:0] mem_cached_data_wr_o 78 | ,output mem_cached_rd_o 79 | ,output [ 3:0] mem_cached_wr_o 80 | ,output mem_cached_cacheable_o 81 | ,output [ 10:0] mem_cached_req_tag_o 82 | ,output mem_cached_invalidate_o 83 | ,output mem_cached_writeback_o 84 | ,output mem_cached_flush_o 85 | ,output [ 31:0] mem_uncached_addr_o 86 | ,output [ 31:0] mem_uncached_data_wr_o 87 | ,output mem_uncached_rd_o 88 | ,output [ 3:0] mem_uncached_wr_o 89 | ,output mem_uncached_cacheable_o 90 | ,output [ 10:0] mem_uncached_req_tag_o 91 | ,output mem_uncached_invalidate_o 92 | ,output mem_uncached_writeback_o 93 | ,output mem_uncached_flush_o 94 | ,output cache_active_o 95 | ); 96 | 97 | 98 | 99 | wire hold_w; 100 | reg cache_access_q; 101 | 102 | assign mem_cached_addr_o = mem_addr_i; 103 | assign mem_cached_data_wr_o = mem_data_wr_i; 104 | assign mem_cached_rd_o = (mem_cacheable_i & ~hold_w) ? mem_rd_i : 1'b0; 105 | assign mem_cached_wr_o = (mem_cacheable_i & ~hold_w) ? mem_wr_i : 4'b0; 106 | assign mem_cached_cacheable_o = mem_cacheable_i; 107 | assign mem_cached_req_tag_o = mem_req_tag_i; 108 | assign mem_cached_invalidate_o = (mem_cacheable_i & ~hold_w) ? mem_invalidate_i : 1'b0; 109 | assign mem_cached_writeback_o = (mem_cacheable_i & ~hold_w) ? mem_writeback_i : 1'b0; 110 | assign mem_cached_flush_o = (mem_cacheable_i & ~hold_w) ? mem_flush_i : 1'b0; 111 | 112 | assign mem_uncached_addr_o = mem_addr_i; 113 | assign mem_uncached_data_wr_o = mem_data_wr_i; 114 | assign mem_uncached_rd_o = (~mem_cacheable_i & ~hold_w) ? mem_rd_i : 1'b0; 115 | assign mem_uncached_wr_o = (~mem_cacheable_i & ~hold_w) ? mem_wr_i : 4'b0; 116 | assign mem_uncached_cacheable_o = mem_cacheable_i; 117 | assign mem_uncached_req_tag_o = mem_req_tag_i; 118 | assign mem_uncached_invalidate_o = (~mem_cacheable_i & ~hold_w) ? mem_invalidate_i : 1'b0; 119 | assign mem_uncached_writeback_o = (~mem_cacheable_i & ~hold_w) ? mem_writeback_i : 1'b0; 120 | assign mem_uncached_flush_o = (~mem_cacheable_i & ~hold_w) ? mem_flush_i : 1'b0; 121 | 122 | assign mem_accept_o =(mem_cacheable_i ? mem_cached_accept_i : mem_uncached_accept_i) & !hold_w; 123 | assign mem_data_rd_o = cache_access_q ? mem_cached_data_rd_i : mem_uncached_data_rd_i; 124 | assign mem_ack_o = cache_access_q ? mem_cached_ack_i : mem_uncached_ack_i; 125 | assign mem_error_o = cache_access_q ? mem_cached_error_i : mem_uncached_error_i; 126 | assign mem_resp_tag_o = cache_access_q ? mem_cached_resp_tag_i : mem_uncached_resp_tag_i; 127 | 128 | wire request_w = mem_rd_i | mem_wr_i != 4'b0 | mem_flush_i | mem_invalidate_i | mem_writeback_i; 129 | 130 | reg [4:0] pending_r; 131 | reg [4:0] pending_q; 132 | always @ * 133 | begin 134 | pending_r = pending_q; 135 | 136 | if ((request_w && mem_accept_o) && !mem_ack_o) 137 | pending_r = pending_r + 5'd1; 138 | else if (!(request_w && mem_accept_o) && mem_ack_o) 139 | pending_r = pending_r - 5'd1; 140 | end 141 | 142 | always @ (posedge clk_i or posedge rst_i) 143 | if (rst_i) 144 | pending_q <= 5'b0; 145 | else 146 | pending_q <= pending_r; 147 | 148 | always @ (posedge clk_i or posedge rst_i) 149 | if (rst_i) 150 | cache_access_q <= 1'b0; 151 | else if (request_w && mem_accept_o) 152 | cache_access_q <= mem_cacheable_i; 153 | 154 | assign hold_w = (|pending_q) && (cache_access_q != mem_cacheable_i); 155 | 156 | assign cache_active_o = (|pending_q) ? cache_access_q : mem_cacheable_i; 157 | 158 | 159 | endmodule 160 | -------------------------------------------------------------------------------- /top_cache_axi/src_v/dcache_pmem_mux.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // RISC-V Top 3 | // V0.6 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2019 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: BSD 10 | //----------------------------------------------------------------- 11 | // 12 | // Copyright (c) 2014, Ultra-Embedded.com 13 | // All rights reserved. 14 | // 15 | // Redistribution and use in source and binary forms, with or without 16 | // modification, are permitted provided that the following conditions 17 | // are met: 18 | // - Redistributions of source code must retain the above copyright 19 | // notice, this list of conditions and the following disclaimer. 20 | // - Redistributions in binary form must reproduce the above copyright 21 | // notice, this list of conditions and the following disclaimer 22 | // in the documentation and/or other materials provided with the 23 | // distribution. 24 | // - Neither the name of the author nor the names of its contributors 25 | // may be used to endorse or promote products derived from this 26 | // software without specific prior written permission. 27 | // 28 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 32 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 35 | // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 36 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 38 | // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 | // SUCH DAMAGE. 40 | //----------------------------------------------------------------- 41 | 42 | //----------------------------------------------------------------- 43 | // Generated File 44 | //----------------------------------------------------------------- 45 | module dcache_pmem_mux 46 | ( 47 | // Inputs 48 | input clk_i 49 | ,input rst_i 50 | ,input outport_accept_i 51 | ,input outport_ack_i 52 | ,input outport_error_i 53 | ,input [ 31:0] outport_read_data_i 54 | ,input select_i 55 | ,input [ 3:0] inport0_wr_i 56 | ,input inport0_rd_i 57 | ,input [ 7:0] inport0_len_i 58 | ,input [ 31:0] inport0_addr_i 59 | ,input [ 31:0] inport0_write_data_i 60 | ,input [ 3:0] inport1_wr_i 61 | ,input inport1_rd_i 62 | ,input [ 7:0] inport1_len_i 63 | ,input [ 31:0] inport1_addr_i 64 | ,input [ 31:0] inport1_write_data_i 65 | 66 | // Outputs 67 | ,output [ 3:0] outport_wr_o 68 | ,output outport_rd_o 69 | ,output [ 7:0] outport_len_o 70 | ,output [ 31:0] outport_addr_o 71 | ,output [ 31:0] outport_write_data_o 72 | ,output inport0_accept_o 73 | ,output inport0_ack_o 74 | ,output inport0_error_o 75 | ,output [ 31:0] inport0_read_data_o 76 | ,output inport1_accept_o 77 | ,output inport1_ack_o 78 | ,output inport1_error_o 79 | ,output [ 31:0] inport1_read_data_o 80 | ); 81 | 82 | 83 | 84 | 85 | //----------------------------------------------------------------- 86 | // Output Mux 87 | //----------------------------------------------------------------- 88 | reg [ 3:0] outport_wr_r; 89 | reg outport_rd_r; 90 | reg [ 7:0] outport_len_r; 91 | reg [ 31:0] outport_addr_r; 92 | reg [ 31:0] outport_write_data_r; 93 | reg select_q; 94 | 95 | always @ * 96 | begin 97 | case (select_i) 98 | 1'd1: 99 | begin 100 | outport_wr_r = inport1_wr_i; 101 | outport_rd_r = inport1_rd_i; 102 | outport_len_r = inport1_len_i; 103 | outport_addr_r = inport1_addr_i; 104 | outport_write_data_r = inport1_write_data_i; 105 | end 106 | default: 107 | begin 108 | outport_wr_r = inport0_wr_i; 109 | outport_rd_r = inport0_rd_i; 110 | outport_len_r = inport0_len_i; 111 | outport_addr_r = inport0_addr_i; 112 | outport_write_data_r = inport0_write_data_i; 113 | end 114 | endcase 115 | end 116 | 117 | assign outport_wr_o = outport_wr_r; 118 | assign outport_rd_o = outport_rd_r; 119 | assign outport_len_o = outport_len_r; 120 | assign outport_addr_o = outport_addr_r; 121 | assign outport_write_data_o = outport_write_data_r; 122 | 123 | // Delayed version of selector to match phase of response signals 124 | always @ (posedge clk_i or posedge rst_i) 125 | if (rst_i) 126 | select_q <= 1'b0; 127 | else 128 | select_q <= select_i; 129 | 130 | assign inport0_ack_o = (select_q == 1'd0) && outport_ack_i; 131 | assign inport0_error_o = (select_q == 1'd0) && outport_error_i; 132 | assign inport0_read_data_o = outport_read_data_i; 133 | assign inport0_accept_o = (select_i == 1'd0) && outport_accept_i; 134 | assign inport1_ack_o = (select_q == 1'd1) && outport_ack_i; 135 | assign inport1_error_o = (select_q == 1'd1) && outport_error_i; 136 | assign inport1_read_data_o = outport_read_data_i; 137 | assign inport1_accept_o = (select_i == 1'd1) && outport_accept_i; 138 | 139 | 140 | endmodule 141 | -------------------------------------------------------------------------------- /top_cache_axi/src_v/icache_data_ram.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // RISC-V Top 3 | // V0.6 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2019 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: BSD 10 | //----------------------------------------------------------------- 11 | // 12 | // Copyright (c) 2014, Ultra-Embedded.com 13 | // All rights reserved. 14 | // 15 | // Redistribution and use in source and binary forms, with or without 16 | // modification, are permitted provided that the following conditions 17 | // are met: 18 | // - Redistributions of source code must retain the above copyright 19 | // notice, this list of conditions and the following disclaimer. 20 | // - Redistributions in binary form must reproduce the above copyright 21 | // notice, this list of conditions and the following disclaimer 22 | // in the documentation and/or other materials provided with the 23 | // distribution. 24 | // - Neither the name of the author nor the names of its contributors 25 | // may be used to endorse or promote products derived from this 26 | // software without specific prior written permission. 27 | // 28 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 32 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 35 | // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 36 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 38 | // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 | // SUCH DAMAGE. 40 | //----------------------------------------------------------------- 41 | 42 | //----------------------------------------------------------------- 43 | // Generated File 44 | //----------------------------------------------------------------- 45 | module icache_data_ram 46 | ( 47 | // Inputs 48 | input clk_i 49 | ,input rst_i 50 | ,input [ 10:0] addr_i 51 | ,input [ 31:0] data_i 52 | ,input wr_i 53 | 54 | // Outputs 55 | ,output [ 31:0] data_o 56 | ); 57 | 58 | 59 | 60 | 61 | //----------------------------------------------------------------- 62 | // Single Port RAM 8KB 63 | // Mode: Read First 64 | //----------------------------------------------------------------- 65 | reg [31:0] ram [2047:0] /*verilator public*/; 66 | reg [31:0] ram_read_q; 67 | 68 | // Synchronous write 69 | always @ (posedge clk_i) 70 | begin 71 | if (wr_i) 72 | ram[addr_i] <= data_i; 73 | ram_read_q <= ram[addr_i]; 74 | end 75 | 76 | assign data_o = ram_read_q; 77 | 78 | 79 | 80 | endmodule 81 | -------------------------------------------------------------------------------- /top_cache_axi/src_v/icache_tag_ram.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // RISC-V Top 3 | // V0.6 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2019 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: BSD 10 | //----------------------------------------------------------------- 11 | // 12 | // Copyright (c) 2014, Ultra-Embedded.com 13 | // All rights reserved. 14 | // 15 | // Redistribution and use in source and binary forms, with or without 16 | // modification, are permitted provided that the following conditions 17 | // are met: 18 | // - Redistributions of source code must retain the above copyright 19 | // notice, this list of conditions and the following disclaimer. 20 | // - Redistributions in binary form must reproduce the above copyright 21 | // notice, this list of conditions and the following disclaimer 22 | // in the documentation and/or other materials provided with the 23 | // distribution. 24 | // - Neither the name of the author nor the names of its contributors 25 | // may be used to endorse or promote products derived from this 26 | // software without specific prior written permission. 27 | // 28 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 32 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 35 | // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 36 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 38 | // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 | // SUCH DAMAGE. 40 | //----------------------------------------------------------------- 41 | 42 | //----------------------------------------------------------------- 43 | // Generated File 44 | //----------------------------------------------------------------- 45 | module icache_tag_ram 46 | ( 47 | // Inputs 48 | input clk_i 49 | ,input rst_i 50 | ,input [ 7:0] addr_i 51 | ,input [ 19:0] data_i 52 | ,input wr_i 53 | 54 | // Outputs 55 | ,output [ 19:0] data_o 56 | ); 57 | 58 | 59 | 60 | 61 | //----------------------------------------------------------------- 62 | // Single Port RAM 0KB 63 | // Mode: Read First 64 | //----------------------------------------------------------------- 65 | reg [19:0] ram [255:0] /*verilator public*/; 66 | reg [19:0] ram_read_q; 67 | 68 | // Synchronous write 69 | always @ (posedge clk_i) 70 | begin 71 | if (wr_i) 72 | ram[addr_i] <= data_i; 73 | ram_read_q <= ram[addr_i]; 74 | end 75 | 76 | assign data_o = ram_read_q; 77 | 78 | 79 | 80 | endmodule 81 | -------------------------------------------------------------------------------- /top_cache_axi/tb/axi4.h: -------------------------------------------------------------------------------- 1 | #ifndef AXI4_H 2 | #define AXI4_H 3 | 4 | #include 5 | 6 | //---------------------------------------------------------------- 7 | // Interface (master) 8 | //---------------------------------------------------------------- 9 | class axi4_master 10 | { 11 | public: 12 | // Members 13 | sc_uint <1> AWVALID; 14 | sc_uint <32> AWADDR; 15 | sc_uint <4> AWID; 16 | sc_uint <8> AWLEN; 17 | sc_uint <2> AWBURST; 18 | sc_uint <1> WVALID; 19 | sc_uint <32> WDATA; 20 | sc_uint <4> WSTRB; 21 | sc_uint <1> WLAST; 22 | sc_uint <1> BREADY; 23 | sc_uint <1> ARVALID; 24 | sc_uint <32> ARADDR; 25 | sc_uint <4> ARID; 26 | sc_uint <8> ARLEN; 27 | sc_uint <2> ARBURST; 28 | sc_uint <1> RREADY; 29 | 30 | // Construction 31 | axi4_master() { init(); } 32 | 33 | void init(void) 34 | { 35 | AWVALID = 0; 36 | AWADDR = 0; 37 | AWID = 0; 38 | AWLEN = 0; 39 | AWBURST = 0; 40 | WVALID = 0; 41 | WDATA = 0; 42 | WSTRB = 0; 43 | WLAST = 0; 44 | BREADY = 0; 45 | ARVALID = 0; 46 | ARADDR = 0; 47 | ARID = 0; 48 | ARLEN = 0; 49 | ARBURST = 0; 50 | RREADY = 0; 51 | } 52 | 53 | bool operator == (const axi4_master & v) const 54 | { 55 | bool eq = true; 56 | eq &= (AWVALID == v.AWVALID); 57 | eq &= (AWADDR == v.AWADDR); 58 | eq &= (AWID == v.AWID); 59 | eq &= (AWLEN == v.AWLEN); 60 | eq &= (AWBURST == v.AWBURST); 61 | eq &= (WVALID == v.WVALID); 62 | eq &= (WDATA == v.WDATA); 63 | eq &= (WSTRB == v.WSTRB); 64 | eq &= (WLAST == v.WLAST); 65 | eq &= (BREADY == v.BREADY); 66 | eq &= (ARVALID == v.ARVALID); 67 | eq &= (ARADDR == v.ARADDR); 68 | eq &= (ARID == v.ARID); 69 | eq &= (ARLEN == v.ARLEN); 70 | eq &= (ARBURST == v.ARBURST); 71 | eq &= (RREADY == v.RREADY); 72 | return eq; 73 | } 74 | 75 | friend void sc_trace(sc_trace_file *tf, const axi4_master & v, const std::string & path) 76 | { 77 | sc_trace(tf,v.AWVALID, path + "/awvalid"); 78 | sc_trace(tf,v.AWADDR, path + "/awaddr"); 79 | sc_trace(tf,v.AWID, path + "/awid"); 80 | sc_trace(tf,v.AWLEN, path + "/awlen"); 81 | sc_trace(tf,v.AWBURST, path + "/awburst"); 82 | sc_trace(tf,v.WVALID, path + "/wvalid"); 83 | sc_trace(tf,v.WDATA, path + "/wdata"); 84 | sc_trace(tf,v.WSTRB, path + "/wstrb"); 85 | sc_trace(tf,v.WLAST, path + "/wlast"); 86 | sc_trace(tf,v.BREADY, path + "/bready"); 87 | sc_trace(tf,v.ARVALID, path + "/arvalid"); 88 | sc_trace(tf,v.ARADDR, path + "/araddr"); 89 | sc_trace(tf,v.ARID, path + "/arid"); 90 | sc_trace(tf,v.ARLEN, path + "/arlen"); 91 | sc_trace(tf,v.ARBURST, path + "/arburst"); 92 | sc_trace(tf,v.RREADY, path + "/rready"); 93 | } 94 | 95 | friend ostream& operator << (ostream& os, axi4_master const & v) 96 | { 97 | os << hex << "AWVALID: " << v.AWVALID << " "; 98 | os << hex << "AWADDR: " << v.AWADDR << " "; 99 | os << hex << "AWID: " << v.AWID << " "; 100 | os << hex << "AWLEN: " << v.AWLEN << " "; 101 | os << hex << "AWBURST: " << v.AWBURST << " "; 102 | os << hex << "WVALID: " << v.WVALID << " "; 103 | os << hex << "WDATA: " << v.WDATA << " "; 104 | os << hex << "WSTRB: " << v.WSTRB << " "; 105 | os << hex << "WLAST: " << v.WLAST << " "; 106 | os << hex << "BREADY: " << v.BREADY << " "; 107 | os << hex << "ARVALID: " << v.ARVALID << " "; 108 | os << hex << "ARADDR: " << v.ARADDR << " "; 109 | os << hex << "ARID: " << v.ARID << " "; 110 | os << hex << "ARLEN: " << v.ARLEN << " "; 111 | os << hex << "ARBURST: " << v.ARBURST << " "; 112 | os << hex << "RREADY: " << v.RREADY << " "; 113 | return os; 114 | } 115 | 116 | friend istream& operator >> ( istream& is, axi4_master & val) 117 | { 118 | // Not implemented 119 | return is; 120 | } 121 | }; 122 | 123 | #define MEMBER_COPY_AXI4_MASTER(s,d) do { \ 124 | s.AWVALID = d.AWVALID; \ 125 | s.AWADDR = d.AWADDR; \ 126 | s.AWID = d.AWID; \ 127 | s.AWLEN = d.AWLEN; \ 128 | s.AWBURST = d.AWBURST; \ 129 | s.WVALID = d.WVALID; \ 130 | s.WDATA = d.WDATA; \ 131 | s.WSTRB = d.WSTRB; \ 132 | s.WLAST = d.WLAST; \ 133 | s.BREADY = d.BREADY; \ 134 | s.ARVALID = d.ARVALID; \ 135 | s.ARADDR = d.ARADDR; \ 136 | s.ARID = d.ARID; \ 137 | s.ARLEN = d.ARLEN; \ 138 | s.ARBURST = d.ARBURST; \ 139 | s.RREADY = d.RREADY; \ 140 | } while (0) 141 | 142 | //---------------------------------------------------------------- 143 | // Interface (slave) 144 | //---------------------------------------------------------------- 145 | class axi4_slave 146 | { 147 | public: 148 | // Members 149 | sc_uint <1> AWREADY; 150 | sc_uint <1> WREADY; 151 | sc_uint <1> BVALID; 152 | sc_uint <2> BRESP; 153 | sc_uint <4> BID; 154 | sc_uint <1> ARREADY; 155 | sc_uint <1> RVALID; 156 | sc_uint <32> RDATA; 157 | sc_uint <2> RRESP; 158 | sc_uint <4> RID; 159 | sc_uint <1> RLAST; 160 | 161 | // Construction 162 | axi4_slave() { init(); } 163 | 164 | void init(void) 165 | { 166 | AWREADY = 0; 167 | WREADY = 0; 168 | BVALID = 0; 169 | BRESP = 0; 170 | BID = 0; 171 | ARREADY = 0; 172 | RVALID = 0; 173 | RDATA = 0; 174 | RRESP = 0; 175 | RID = 0; 176 | RLAST = 0; 177 | } 178 | 179 | bool operator == (const axi4_slave & v) const 180 | { 181 | bool eq = true; 182 | eq &= (AWREADY == v.AWREADY); 183 | eq &= (WREADY == v.WREADY); 184 | eq &= (BVALID == v.BVALID); 185 | eq &= (BRESP == v.BRESP); 186 | eq &= (BID == v.BID); 187 | eq &= (ARREADY == v.ARREADY); 188 | eq &= (RVALID == v.RVALID); 189 | eq &= (RDATA == v.RDATA); 190 | eq &= (RRESP == v.RRESP); 191 | eq &= (RID == v.RID); 192 | eq &= (RLAST == v.RLAST); 193 | return eq; 194 | } 195 | 196 | friend void sc_trace(sc_trace_file *tf, const axi4_slave & v, const std::string & path) 197 | { 198 | sc_trace(tf,v.AWREADY, path + "/awready"); 199 | sc_trace(tf,v.WREADY, path + "/wready"); 200 | sc_trace(tf,v.BVALID, path + "/bvalid"); 201 | sc_trace(tf,v.BRESP, path + "/bresp"); 202 | sc_trace(tf,v.BID, path + "/bid"); 203 | sc_trace(tf,v.ARREADY, path + "/arready"); 204 | sc_trace(tf,v.RVALID, path + "/rvalid"); 205 | sc_trace(tf,v.RDATA, path + "/rdata"); 206 | sc_trace(tf,v.RRESP, path + "/rresp"); 207 | sc_trace(tf,v.RID, path + "/rid"); 208 | sc_trace(tf,v.RLAST, path + "/rlast"); 209 | } 210 | 211 | friend ostream& operator << (ostream& os, axi4_slave const & v) 212 | { 213 | os << hex << "AWREADY: " << v.AWREADY << " "; 214 | os << hex << "WREADY: " << v.WREADY << " "; 215 | os << hex << "BVALID: " << v.BVALID << " "; 216 | os << hex << "BRESP: " << v.BRESP << " "; 217 | os << hex << "BID: " << v.BID << " "; 218 | os << hex << "ARREADY: " << v.ARREADY << " "; 219 | os << hex << "RVALID: " << v.RVALID << " "; 220 | os << hex << "RDATA: " << v.RDATA << " "; 221 | os << hex << "RRESP: " << v.RRESP << " "; 222 | os << hex << "RID: " << v.RID << " "; 223 | os << hex << "RLAST: " << v.RLAST << " "; 224 | return os; 225 | } 226 | 227 | friend istream& operator >> ( istream& is, axi4_slave & val) 228 | { 229 | // Not implemented 230 | return is; 231 | } 232 | }; 233 | 234 | #define MEMBER_COPY_AXI4_SLAVE(s,d) do { \ 235 | s.AWREADY = d.AWREADY; \ 236 | s.WREADY = d.WREADY; \ 237 | s.BVALID = d.BVALID; \ 238 | s.BRESP = d.BRESP; \ 239 | s.BID = d.BID; \ 240 | s.ARREADY = d.ARREADY; \ 241 | s.RVALID = d.RVALID; \ 242 | s.RDATA = d.RDATA; \ 243 | s.RRESP = d.RRESP; \ 244 | s.RID = d.RID; \ 245 | s.RLAST = d.RLAST; \ 246 | } while (0) 247 | 248 | 249 | #endif 250 | -------------------------------------------------------------------------------- /top_cache_axi/tb/axi4_defines.h: -------------------------------------------------------------------------------- 1 | #ifndef AXI4_DEFINES_H 2 | #define AXI4_DEFINES_H 3 | 4 | //-------------------------------------------------------------------- 5 | // Defines 6 | //-------------------------------------------------------------------- 7 | #define AXI4_ADDR_W 32 8 | #define AXI4_DATA_W 32 9 | #define AXI4_AXLEN_W 8 10 | #define AXI4_AXBURST_W 2 11 | #define AXI4_RESP_W 2 12 | #define AXI4_ID_W 4 13 | 14 | //-------------------------------------------------------------------- 15 | // Enumerations 16 | //-------------------------------------------------------------------- 17 | enum eAXI4_BURST 18 | { 19 | AXI4_BURST_FIXED, 20 | AXI4_BURST_INCR, 21 | AXI4_BURST_WRAP 22 | }; 23 | 24 | enum eAXI4_RESP 25 | { 26 | AXI4_RESP_OKAY, 27 | AXI4_RESP_EXOKAY, 28 | AXI4_RESP_SLVERR, 29 | AXI4_RESP_DECERR 30 | }; 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /top_cache_axi/tb/main.cpp: -------------------------------------------------------------------------------- 1 | #include "sc_reset_gen.h" 2 | #include "testbench.h" 3 | #include 4 | #include 5 | #include 6 | 7 | //-------------------------------------------------------------------- 8 | // Defines 9 | //-------------------------------------------------------------------- 10 | #ifndef SIM_TIME_RESOLUTION 11 | #define SIM_TIME_RESOLUTION 1 12 | #endif 13 | #ifndef SIM_TIME_SCALE 14 | #define SIM_TIME_SCALE SC_NS 15 | #endif 16 | 17 | #ifndef CLK0_PERIOD 18 | #define CLK0_PERIOD 10 19 | #endif 20 | 21 | #ifndef CLK0_NAME 22 | #define CLK0_NAME clk 23 | #endif 24 | 25 | #ifndef RST0_NAME 26 | #define RST0_NAME rst 27 | #endif 28 | 29 | #define xstr(a) str(a) 30 | #define str(a) #a 31 | 32 | //-------------------------------------------------------------------- 33 | // Locals 34 | //-------------------------------------------------------------------- 35 | static testbench *tb = NULL; 36 | 37 | //-------------------------------------------------------------------- 38 | // assert_handler: Handling of sc_assert 39 | //-------------------------------------------------------------------- 40 | static void assert_handler(const sc_report& rep, const sc_actions& actions) 41 | { 42 | sc_report_handler::default_handler(rep, actions & ~SC_ABORT); 43 | 44 | if ( actions & SC_ABORT ) 45 | { 46 | cout << "TEST FAILED" << endl; 47 | if (tb) 48 | tb->abort(); 49 | abort(); 50 | } 51 | } 52 | //-------------------------------------------------------------------- 53 | // exit_override 54 | //-------------------------------------------------------------------- 55 | static void exit_override(void) 56 | { 57 | if (tb) 58 | tb->abort(); 59 | } 60 | //-------------------------------------------------------------------- 61 | // vl_finish: Handling of verilog $finish 62 | //-------------------------------------------------------------------- 63 | void vl_finish (const char* filename, int linenum, const char* hier) 64 | { 65 | // Jump to exit handler! 66 | exit(0); 67 | } 68 | //----------------------------------------------------------------- 69 | // sigint_handler 70 | //----------------------------------------------------------------- 71 | static void sigint_handler(int s) 72 | { 73 | exit_override(); 74 | 75 | // Jump to exit handler! 76 | exit(1); 77 | } 78 | //-------------------------------------------------------------------- 79 | // sc_main 80 | //-------------------------------------------------------------------- 81 | int sc_main(int argc, char* argv[]) 82 | { 83 | bool trace = true; 84 | int seed = 1; 85 | int last_argc = 0; 86 | const char * vcd_name = "sysc_wave"; 87 | 88 | // Env variable seed override 89 | char *s = getenv("SEED"); 90 | if (s && strcmp(s, "")) 91 | seed = strtol(s, NULL, 0); 92 | 93 | for (int i=1;iCLK0_NAME(CLK0_NAME); 145 | tb->RST0_NAME(clk0_rst.rst); 146 | 147 | // Waves 148 | if (trace) 149 | tb->add_trace(sc_create_vcd_trace_file(vcd_name), ""); 150 | 151 | tb->set_argcv(argc - last_argc, &argv[last_argc]); 152 | 153 | // Go! 154 | sc_start(); 155 | 156 | return 0; 157 | } 158 | -------------------------------------------------------------------------------- /top_cache_axi/tb/makefile: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | ## Tool paths 3 | ############################################################################### 4 | VERILATOR_SRC ?= /usr/share/verilator/include 5 | SYSTEMC_HOME ?= /usr/local/systemc-2.3.1 6 | 7 | TEST_IMAGE ?= ../../isa_sim/images/basic.elf 8 | 9 | CORE ?= riscv 10 | 11 | export VERILATOR_SRC 12 | export SYSTEMC_HOME 13 | 14 | ############################################################################### 15 | ## Makefile 16 | ############################################################################### 17 | all: build 18 | 19 | build: 20 | make -C ../../isa_sim lib 21 | make -f makefile.generate_verilated CORE=$(CORE) 22 | make -f makefile.build_verilated 23 | make -f makefile.build_sysc_tb 24 | 25 | clean: 26 | make -f makefile.generate_verilated CORE=$(CORE) $@ 27 | make -f makefile.build_verilated $@ 28 | make -f makefile.build_sysc_tb $@ 29 | -rm *.vcd 30 | 31 | run: build 32 | ./build/test.x -f $(TEST_IMAGE) -------------------------------------------------------------------------------- /top_cache_axi/tb/makefile.build_sysc_tb: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Variables 3 | ############################################################################### 4 | VERILATOR_SRC ?= /usr/share/verilator/include 5 | SYSTEMC_HOME ?= /usr/local/systemc-2.3.1 6 | 7 | OBJ_DIR ?= obj/ 8 | EXE_DIR ?= build/ 9 | SRC_DIR ?= ./ 10 | 11 | TARGET ?= test.x 12 | 13 | # Additional include directories 14 | INCLUDE_PATH ?= 15 | INCLUDE_PATH += $(SRC_DIR) 16 | INCLUDE_PATH += ./verilated 17 | INCLUDE_PATH += ../../isa_sim 18 | INCLUDE_PATH += $(VERILATOR_SRC) 19 | INCLUDE_PATH += $(VERILATOR_SRC)/vltstd 20 | INCLUDE_PATH += $(SYSTEMC_HOME)/include 21 | 22 | # Dependancies 23 | LIB_PATH ?= 24 | LIB_PATH += ./lib 25 | LIB_PATH += ../../isa_sim 26 | LIBS = -lisa_sim -lsyscverilated -lelf -lbfd 27 | 28 | # Flags 29 | CFLAGS ?= -fpic -O2 30 | CFLAGS += $(patsubst %,-I%,$(INCLUDE_PATH)) 31 | CFLAGS += -DVM_TRACE=1 32 | LDFLAGS ?= -O2 33 | LDFLAGS += -L$(SYSTEMC_HOME)/lib-linux64 34 | LDFLAGS += $(patsubst %,-L%,$(LIB_PATH)) 35 | 36 | EXTRA_CLEAN_FILES ?= 37 | 38 | # SRC / Object list 39 | src2obj = $(OBJ_DIR)$(patsubst %$(suffix $(1)),%.o,$(notdir $(1))) 40 | SRC ?= $(foreach src,$(SRC_DIR),$(wildcard $(src)/*.cpp)) 41 | OBJ ?= $(foreach src,$(SRC),$(call src2obj,$(src))) 42 | 43 | ############################################################################### 44 | # Rules 45 | ############################################################################### 46 | define template_c 47 | $(call src2obj,$(1)): $(1) | $(OBJ_DIR) 48 | g++ $(CFLAGS) -c $$< -o $$@ 49 | endef 50 | 51 | all: $(EXE_DIR)$(TARGET) 52 | 53 | $(OBJ_DIR) $(EXE_DIR): 54 | mkdir -p $@ 55 | 56 | $(foreach src,$(SRC),$(eval $(call template_c,$(src)))) 57 | 58 | $(EXE_DIR)$(TARGET): $(OBJ) | $(EXE_DIR) 59 | g++ $(LDFLAGS) $(OBJ) -o $@ -lsystemc $(LIBS) 60 | 61 | clean: 62 | rm -rf $(EXE_DIR) $(OBJ_DIR) $(EXTRA_CLEAN_FILES) 63 | -------------------------------------------------------------------------------- /top_cache_axi/tb/makefile.build_verilated: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Variables 3 | ############################################################################### 4 | VERILATOR_SRC ?= /usr/share/verilator/include 5 | SYSTEMC_HOME ?= /usr/local/systemc-2.3.1 6 | 7 | SRC_DIR ?= verilated/ 8 | OBJ_DIR ?= obj_verilated/ 9 | LIB_DIR ?= lib/ 10 | 11 | LIBNAME ?= libsyscverilated.a 12 | 13 | # Additional include directories 14 | INCLUDE_PATH ?= 15 | INCLUDE_PATH += $(SRC_DIR) 16 | INCLUDE_PATH += $(SYSTEMC_HOME)/include 17 | INCLUDE_PATH += $(VERILATOR_SRC) 18 | INCLUDE_PATH += $(VERILATOR_SRC)/vltstd 19 | 20 | # Flags 21 | CFLAGS ?= 22 | CFLAGS += -DVM_TRACE=1 -DVL_USER_FINISH=1 23 | CFLAGS += -fpic 24 | CFLAGS += $(patsubst %,-I%,$(INCLUDE_PATH)) 25 | CFLAGS += $(EXTRA_CFLAGS) 26 | 27 | LIB_OPT ?= $(SYSTEMC_HOME)/lib-linux64/libsystemc.a 28 | 29 | # SRC / Object list 30 | src2obj = $(OBJ_DIR)$(patsubst %$(suffix $(1)),%.o,$(notdir $(1))) 31 | SRC_LIST = $(foreach src,$(SRC_DIR),$(wildcard $(src)/*.cpp)) 32 | SRC_LIST += $(VERILATOR_SRC)/verilated.cpp 33 | SRC_LIST += $(VERILATOR_SRC)/verilated_vcd_c.cpp 34 | SRC_LIST += $(VERILATOR_SRC)/verilated_vcd_sc.cpp 35 | 36 | OBJ ?= $(foreach src,$(SRC_LIST),$(call src2obj,$(src))) 37 | 38 | ############################################################################### 39 | # Rules 40 | ############################################################################### 41 | define template_c 42 | $(call src2obj,$(1)): $(1) | $(OBJ_DIR) 43 | g++ $(CFLAGS) -c $$< -o $$@ 44 | endef 45 | 46 | all: $(LIB_DIR)$(LIBNAME) 47 | 48 | $(OBJ_DIR) $(LIB_DIR): 49 | mkdir -p $@ 50 | 51 | $(foreach src,$(SRC_LIST),$(eval $(call template_c,$(src)))) 52 | 53 | $(LIB_DIR)$(LIBNAME): $(OBJ) | $(LIB_DIR) 54 | g++ -shared -o $(LIB_DIR)$(LIBNAME) $(LIB_OPT) $(OBJ) 55 | 56 | clean: 57 | rm -rf $(LIB_DIR) $(OBJ_DIR) 58 | -------------------------------------------------------------------------------- /top_cache_axi/tb/makefile.generate_verilated: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Variables 3 | ############################################################################### 4 | CORE ?= core 5 | PARAMS ?= 6 | OUTPUT_DIR ?= verilated 7 | SRC_DIR ?= ../src_v 8 | SRC_TYPE ?= v 9 | SRC_V_DIR ?= ../src_v 10 | OUTPUT_SUFFIX ?= 11 | SRC ?= riscv_top 12 | NAME ?= riscv_top 13 | 14 | RTL_INCLUDE = ../../core/$(CORE) 15 | 16 | # Verilator options 17 | VERILATE_PARAMS ?= --trace 18 | VERILATOR_OPTS ?= --pins-sc-uint 19 | 20 | OLDER_VERILATOR := $(shell verilator --l2-name v 2>&1 | grep "Invalid Option" | wc -l) 21 | 22 | ifeq ($(OLDER_VERILATOR),0) 23 | VERILATOR_OPTS += --l2-name v 24 | endif 25 | 26 | TARGETS ?= $(OUTPUT_DIR)/V$(NAME) 27 | 28 | ############################################################################### 29 | # Rules 30 | ############################################################################### 31 | all: $(TARGETS) 32 | 33 | $(OUTPUT_DIR): 34 | mkdir -p $@ 35 | 36 | $(OUTPUT_DIR)/V$(NAME): $(SRC_DIR)/$(SRC).$(SRC_TYPE) | $(OUTPUT_DIR) 37 | verilator --sc $(patsubst $(OUTPUT_DIR)/V$(NAME), $(SRC_V_DIR)/$(NAME), $@) --Mdir $(OUTPUT_DIR) -I./$(SRC_V_DIR) $(patsubst %,-I%,$(RTL_INCLUDE)) $(VERILATOR_OPTS) $(VERILATE_PARAMS) 38 | 39 | clean: 40 | rm -rf $(TARGETS) $(OUTPUT_DIR) 41 | -------------------------------------------------------------------------------- /top_cache_axi/tb/riscv_top.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef RISCV_TOP_H 3 | #define RISCV_TOP_H 4 | #include 5 | 6 | #include "axi4.h" 7 | #include "axi4.h" 8 | 9 | class Vriscv_top; 10 | class VerilatedVcdC; 11 | 12 | //------------------------------------------------------------- 13 | // riscv_top: RTL wrapper class 14 | //------------------------------------------------------------- 15 | class riscv_top: public sc_module 16 | { 17 | public: 18 | sc_in clk_in; 19 | sc_in rst_in; 20 | sc_in intr_in; 21 | sc_in > reset_vector_in; 22 | 23 | sc_in axi_i_in; 24 | sc_out axi_i_out; 25 | sc_in axi_d_in; 26 | sc_out axi_d_out; 27 | 28 | //------------------------------------------------------------- 29 | // Constructor 30 | //------------------------------------------------------------- 31 | SC_HAS_PROCESS(riscv_top); 32 | riscv_top(sc_module_name name); 33 | 34 | //------------------------------------------------------------- 35 | // Trace 36 | //------------------------------------------------------------- 37 | virtual void add_trace(sc_trace_file *vcd, std::string prefix) 38 | { 39 | #undef TRACE_SIGNAL 40 | #define TRACE_SIGNAL(s) sc_trace(vcd,s,prefix + #s) 41 | 42 | TRACE_SIGNAL(clk_in); 43 | TRACE_SIGNAL(rst_in); 44 | TRACE_SIGNAL(intr_in); 45 | TRACE_SIGNAL(reset_vector_in); 46 | TRACE_SIGNAL(axi_i_in); 47 | TRACE_SIGNAL(axi_i_out); 48 | TRACE_SIGNAL(axi_d_in); 49 | TRACE_SIGNAL(axi_d_out); 50 | 51 | #undef TRACE_SIGNAL 52 | } 53 | 54 | void async_outputs(void); 55 | void trace_rtl(void); 56 | void trace_enable(VerilatedVcdC *p); 57 | void trace_enable(VerilatedVcdC *p, sc_core::sc_time start_time); 58 | 59 | //------------------------------------------------------------- 60 | // Signals 61 | //------------------------------------------------------------- 62 | private: 63 | sc_signal m_clk_in; 64 | sc_signal m_rst_in; 65 | sc_signal m_axi_i_awready_in; 66 | sc_signal m_axi_i_wready_in; 67 | sc_signal m_axi_i_bvalid_in; 68 | sc_signal > m_axi_i_bresp_in; 69 | sc_signal > m_axi_i_bid_in; 70 | sc_signal m_axi_i_arready_in; 71 | sc_signal m_axi_i_rvalid_in; 72 | sc_signal > m_axi_i_rdata_in; 73 | sc_signal > m_axi_i_rresp_in; 74 | sc_signal > m_axi_i_rid_in; 75 | sc_signal m_axi_i_rlast_in; 76 | sc_signal m_axi_d_awready_in; 77 | sc_signal m_axi_d_wready_in; 78 | sc_signal m_axi_d_bvalid_in; 79 | sc_signal > m_axi_d_bresp_in; 80 | sc_signal > m_axi_d_bid_in; 81 | sc_signal m_axi_d_arready_in; 82 | sc_signal m_axi_d_rvalid_in; 83 | sc_signal > m_axi_d_rdata_in; 84 | sc_signal > m_axi_d_rresp_in; 85 | sc_signal > m_axi_d_rid_in; 86 | sc_signal m_axi_d_rlast_in; 87 | sc_signal m_intr_in; 88 | sc_signal > m_reset_vector_in; 89 | 90 | sc_signal m_axi_i_awvalid_out; 91 | sc_signal > m_axi_i_awaddr_out; 92 | sc_signal > m_axi_i_awid_out; 93 | sc_signal > m_axi_i_awlen_out; 94 | sc_signal > m_axi_i_awburst_out; 95 | sc_signal m_axi_i_wvalid_out; 96 | sc_signal > m_axi_i_wdata_out; 97 | sc_signal > m_axi_i_wstrb_out; 98 | sc_signal m_axi_i_wlast_out; 99 | sc_signal m_axi_i_bready_out; 100 | sc_signal m_axi_i_arvalid_out; 101 | sc_signal > m_axi_i_araddr_out; 102 | sc_signal > m_axi_i_arid_out; 103 | sc_signal > m_axi_i_arlen_out; 104 | sc_signal > m_axi_i_arburst_out; 105 | sc_signal m_axi_i_rready_out; 106 | sc_signal m_axi_d_awvalid_out; 107 | sc_signal > m_axi_d_awaddr_out; 108 | sc_signal > m_axi_d_awid_out; 109 | sc_signal > m_axi_d_awlen_out; 110 | sc_signal > m_axi_d_awburst_out; 111 | sc_signal m_axi_d_wvalid_out; 112 | sc_signal > m_axi_d_wdata_out; 113 | sc_signal > m_axi_d_wstrb_out; 114 | sc_signal m_axi_d_wlast_out; 115 | sc_signal m_axi_d_bready_out; 116 | sc_signal m_axi_d_arvalid_out; 117 | sc_signal > m_axi_d_araddr_out; 118 | sc_signal > m_axi_d_arid_out; 119 | sc_signal > m_axi_d_arlen_out; 120 | sc_signal > m_axi_d_arburst_out; 121 | sc_signal m_axi_d_rready_out; 122 | 123 | public: 124 | Vriscv_top *m_rtl; 125 | #if VM_TRACE 126 | VerilatedVcdC * m_vcd; 127 | bool m_delay_waves; 128 | sc_core::sc_time m_waves_start; 129 | #endif 130 | }; 131 | 132 | #endif -------------------------------------------------------------------------------- /top_cache_axi/tb/sc_reset_gen.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | //----------------------------------------------------------------- 4 | // Module 5 | //----------------------------------------------------------------- 6 | SC_MODULE(sc_reset_gen) 7 | { 8 | public: 9 | sc_in clk; 10 | sc_signal rst; 11 | 12 | void thread(void) 13 | { 14 | rst.write(true); 15 | wait(); 16 | rst.write(false); 17 | } 18 | 19 | SC_HAS_PROCESS(sc_reset_gen); 20 | sc_reset_gen(sc_module_name name): sc_module(name) 21 | { 22 | SC_CTHREAD(thread, clk); 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /top_cache_axi/tb/tb_axi4_mem.cpp: -------------------------------------------------------------------------------- 1 | #include "tb_axi4_mem.h" 2 | #include 3 | 4 | //----------------------------------------------------------------- 5 | // process: Handle AXI requests 6 | //----------------------------------------------------------------- 7 | void tb_axi4_mem::process(void) 8 | { 9 | std::queue axi_rd_q; 10 | std::queue axi_wr_q; 11 | 12 | axi4_master axi_wr_req; 13 | 14 | while (1) 15 | { 16 | axi4_master axi_i = axi_in.read(); 17 | axi4_slave axi_o = axi_out.read(); 18 | 19 | // Read command 20 | if (axi_i.ARVALID && axi_o.ARREADY) 21 | { 22 | sc_uint next_addr = axi_i.ARADDR & ~calc_wrap_mask(0); 23 | axi4_master axi_first = axi_i; 24 | 25 | // Unroll burst 26 | for (int i=0;i<((int)(axi_first.ARLEN) + 1);i++) 27 | { 28 | axi4_master item = axi_first; 29 | 30 | item.ARVALID = true; 31 | item.ARADDR = next_addr; 32 | item.WLAST = (i == axi_first.ARLEN); 33 | 34 | axi_rd_q.push(item); 35 | 36 | // Generate next address 37 | next_addr = calc_next_addr(next_addr, axi_first.ARBURST, axi_first.ARLEN); 38 | } 39 | } 40 | 41 | // Write command 42 | if (axi_i.AWVALID && axi_o.AWREADY) 43 | { 44 | // Record command 45 | axi_wr_req = axi_i; 46 | } 47 | 48 | // Write data 49 | if (axi_i.WVALID && axi_o.WREADY) 50 | { 51 | sc_assert(axi_wr_req.AWVALID); 52 | 53 | axi4_master item = axi_wr_req; 54 | 55 | item.AWVALID = true; 56 | item.AWADDR = axi_wr_req.AWADDR; 57 | 58 | item.WVALID = true; 59 | item.WDATA = axi_i.WDATA; 60 | item.WSTRB = axi_i.WSTRB; 61 | item.WLAST = axi_i.WLAST; 62 | 63 | axi_wr_q.push(item); 64 | 65 | // Generate next address 66 | axi_wr_req.AWADDR = calc_next_addr(axi_wr_req.AWADDR, axi_wr_req.AWBURST, axi_wr_req.AWLEN); 67 | 68 | // Last item 69 | if (item.WLAST) 70 | axi_wr_req.AWVALID = false; 71 | } 72 | 73 | if (axi_o.RVALID && axi_i.RREADY) 74 | { 75 | axi_o.RVALID = false; 76 | axi_o.RDATA = 0; 77 | axi_o.RID = 0; 78 | axi_o.RRESP = 0; 79 | axi_o.RLAST = false; 80 | } 81 | 82 | if (!axi_o.RVALID && axi_rd_q.size() > 0 && !delay_cycle()) 83 | { 84 | axi4_master item = axi_rd_q.front(); 85 | axi_rd_q.pop(); 86 | 87 | axi_o.RVALID = true; 88 | axi_o.RDATA = read32((uint32_t)item.ARADDR); 89 | axi_o.RID = item.ARID; 90 | axi_o.RLAST = item.WLAST; 91 | axi_o.RRESP = AXI4_RESP_OKAY; 92 | } 93 | 94 | if (axi_o.BVALID && axi_i.BREADY) 95 | { 96 | axi_o.BVALID = false; 97 | axi_o.BID = 0; 98 | axi_o.BRESP = 0; 99 | } 100 | 101 | if (!axi_o.BVALID && axi_wr_q.size() > 0 && !delay_cycle()) 102 | { 103 | axi4_master item = axi_wr_q.front(); 104 | axi_wr_q.pop(); 105 | 106 | write32((uint32_t)item.AWADDR, (uint32_t)item.WDATA, (uint8_t)item.WSTRB); 107 | 108 | axi_o.BVALID = item.WLAST; 109 | axi_o.BID = item.AWID; 110 | axi_o.BRESP = AXI4_RESP_OKAY; 111 | } 112 | 113 | // Randomize handshaking 114 | axi_o.ARREADY = !delay_cycle() && (axi_rd_q.size() < 128); 115 | axi_o.AWREADY = !delay_cycle() && (axi_wr_q.size() < 128); 116 | axi_o.WREADY = axi_o.AWREADY && !delay_cycle(); 117 | axi_o.AWREADY&= !axi_wr_req.AWVALID; 118 | 119 | axi_out.write(axi_o); 120 | 121 | wait(); 122 | } 123 | } 124 | //----------------------------------------------------------------- 125 | // calc_next_addr: Calculate next addr based on burst type 126 | //----------------------------------------------------------------- 127 | sc_uint tb_axi4_mem::calc_next_addr(sc_uint addr, sc_uint type, sc_uint len) 128 | { 129 | sc_uint mask = calc_wrap_mask(len); 130 | 131 | switch (type) 132 | { 133 | case AXI4_BURST_WRAP: 134 | return (addr & ~mask) | ((addr + (AXI4_DATA_W/8)) & mask); 135 | case AXI4_BURST_INCR: 136 | return addr + (AXI4_DATA_W/8); 137 | case AXI4_BURST_FIXED: 138 | default: 139 | return addr; 140 | } 141 | 142 | return 0; // Invalid 143 | } 144 | //----------------------------------------------------------------- 145 | // calc_wrap_mask: Calculate wrap mask for wrapping bursts 146 | //----------------------------------------------------------------- 147 | sc_uint tb_axi4_mem::calc_wrap_mask(sc_uint len) 148 | { 149 | switch (len) 150 | { 151 | case (1 - 1): 152 | return 0x03; 153 | case (2 - 1): 154 | return 0x07; 155 | case (4 - 1): 156 | return 0x0F; 157 | case (8 - 1): 158 | return 0x1F; 159 | case (16 - 1): 160 | default: 161 | return 0x3F; 162 | } 163 | 164 | return 0; // Invalid 165 | } 166 | //----------------------------------------------------------------- 167 | // write32: Write a 32-bit word to memory 168 | //----------------------------------------------------------------- 169 | void tb_axi4_mem::write32(uint32_t addr, uint32_t data, uint8_t strb) 170 | { 171 | for (int i=0;i<4;i++) 172 | if (strb & (1 << i)) 173 | tb_memory::write(addr + i,data >> (i*8)); 174 | } 175 | //----------------------------------------------------------------- 176 | // read32: Read a 32-bit word from memory 177 | //----------------------------------------------------------------- 178 | uint32_t tb_axi4_mem::read32(uint32_t addr) 179 | { 180 | uint32_t data = 0; 181 | for (int i=0;i<4;i++) 182 | data |= ((uint32_t)tb_memory::read(addr + i)) << (i*8); 183 | return data; 184 | } 185 | //----------------------------------------------------------------- 186 | // write: Byte write 187 | //----------------------------------------------------------------- 188 | void tb_axi4_mem::write(uint32_t addr, uint8_t data) 189 | { 190 | tb_memory::write(addr, data); 191 | } 192 | //----------------------------------------------------------------- 193 | // read: Byte read 194 | //----------------------------------------------------------------- 195 | uint8_t tb_axi4_mem::read(uint32_t addr) 196 | { 197 | return tb_memory::read(addr); 198 | } 199 | -------------------------------------------------------------------------------- /top_cache_axi/tb/tb_axi4_mem.h: -------------------------------------------------------------------------------- 1 | #ifndef TB_AXI4_MEM_H 2 | #define TB_AXI4_MEM_H 3 | 4 | #include "axi4.h" 5 | #include "axi4_defines.h" 6 | #include "tb_memory.h" 7 | 8 | //------------------------------------------------------------- 9 | // tb_axi4_mem: AXI4 testbench memory 10 | //------------------------------------------------------------- 11 | class tb_axi4_mem: public sc_module, public tb_memory 12 | { 13 | public: 14 | //------------------------------------------------------------- 15 | // Interface I/O 16 | //------------------------------------------------------------- 17 | sc_in clk_in; 18 | sc_in rst_in; 19 | 20 | sc_in axi_in; 21 | sc_out axi_out; 22 | 23 | //------------------------------------------------------------- 24 | // Constructor 25 | //------------------------------------------------------------- 26 | SC_HAS_PROCESS(tb_axi4_mem); 27 | tb_axi4_mem(sc_module_name name): sc_module(name) 28 | { 29 | SC_CTHREAD(process, clk_in.pos()); 30 | m_enable_delays = true; 31 | } 32 | 33 | //------------------------------------------------------------- 34 | // Trace 35 | //------------------------------------------------------------- 36 | void add_trace(sc_trace_file *vcd, std::string prefix) 37 | { 38 | #undef TRACE_SIGNAL 39 | #define TRACE_SIGNAL(s) sc_trace(vcd,s,prefix + #s) 40 | 41 | TRACE_SIGNAL(axi_out); 42 | TRACE_SIGNAL(axi_in); 43 | 44 | #undef TRACE_SIGNAL 45 | } 46 | 47 | //------------------------------------------------------------- 48 | // API 49 | //------------------------------------------------------------- 50 | void enable_delays(bool enable) { m_enable_delays = enable; } 51 | void write(uint32_t addr, uint8_t data); 52 | uint8_t read(uint32_t addr); 53 | void write32(uint32_t addr, uint32_t data, uint8_t strb = 0xF); 54 | uint32_t read32(uint32_t addr); 55 | 56 | void process(void); 57 | bool delay_cycle(void) { return m_enable_delays ? rand() & 1 : 0; } 58 | 59 | sc_uint calc_wrap_mask(sc_uint len); 60 | sc_uint calc_next_addr(sc_uint addr, sc_uint type, sc_uint len); 61 | 62 | protected: 63 | bool m_enable_delays; 64 | }; 65 | 66 | #endif -------------------------------------------------------------------------------- /top_cache_axi/tb/tb_memory.h: -------------------------------------------------------------------------------- 1 | #ifndef TB_MEMORY_H 2 | #define TB_MEMORY_H 3 | 4 | #include 5 | #include 6 | 7 | #define TB_MEM_MAX_REGIONS 10 8 | 9 | //----------------------------------------------------------------- 10 | // tb_mem_region: Memory region entity 11 | //----------------------------------------------------------------- 12 | class tb_mem_region 13 | { 14 | public: 15 | tb_mem_region(uint32_t base, uint32_t size, uint8_t *pMem = NULL) 16 | { 17 | m_base = base; 18 | m_size = size; 19 | m_mem = pMem ? pMem : new uint8_t[size]; 20 | m_trace = false; 21 | } 22 | 23 | uint32_t get_base(void) { return m_base; } 24 | uint32_t get_size(void) { return m_size; } 25 | 26 | bool match(uint32_t addr) 27 | { 28 | return (addr >= m_base) && (addr < (m_base + m_size)); 29 | } 30 | 31 | void write(uint32_t addr, uint8_t data) 32 | { 33 | if (match(addr)) 34 | { 35 | if (m_trace) printf("WRITE: %08x=%02x\n", addr, data); 36 | m_mem[addr - m_base] = data; 37 | } 38 | } 39 | 40 | uint8_t read(uint32_t addr) 41 | { 42 | if (match(addr)) 43 | { 44 | if (m_trace) printf("READ: %08x=%02x\n", addr, m_mem[addr - m_base]); 45 | return m_mem[addr - m_base]; 46 | } 47 | else 48 | return 0; 49 | } 50 | 51 | uint8_t *get_array(void) { return m_mem; } 52 | void trace_access(bool en) { m_trace = en; } 53 | 54 | protected: 55 | uint32_t m_base; 56 | uint32_t m_size; 57 | 58 | uint8_t * m_mem; 59 | 60 | bool m_trace; 61 | }; 62 | 63 | //----------------------------------------------------------------- 64 | // tb_mem_record: Transaction detail 65 | //----------------------------------------------------------------- 66 | class tb_mem_record 67 | { 68 | public: 69 | tb_mem_record(bool write, uint32_t addr, uint8_t data) 70 | { 71 | m_time = sc_time_stamp(); 72 | m_is_write = write; 73 | m_addr = addr; 74 | m_data = data; 75 | } 76 | 77 | public: 78 | sc_time m_time; 79 | bool m_is_write; 80 | uint32_t m_addr; 81 | uint8_t m_data; 82 | }; 83 | 84 | //----------------------------------------------------------------- 85 | // tb_memory: Memory base class 86 | //----------------------------------------------------------------- 87 | class tb_memory 88 | { 89 | public: 90 | tb_memory() 91 | { 92 | for (int i=0;imatch(base) || m_mem[i]->match(base + size - 1)) 108 | return false; 109 | return false; 110 | } 111 | 112 | bool add_region(uint8_t *mem, uint32_t base, uint32_t size) 113 | { 114 | for (int i=0;imatch(base) || m_mem[i]->match(base + size - 1)) 122 | return false; 123 | return false; 124 | } 125 | 126 | bool valid_addr(uint32_t addr) 127 | { 128 | for (int i=0;imatch(addr)) 130 | return true; 131 | 132 | return false; 133 | } 134 | 135 | void trace_access(uint32_t addr, bool en) 136 | { 137 | for (int i=0;imatch(addr)) 139 | m_mem[i]->trace_access(en); 140 | } 141 | 142 | void write(uint32_t addr, uint8_t data) 143 | { 144 | bool found = false; 145 | 146 | if (m_record_accesses) 147 | m_accesses.push(tb_mem_record(true, addr, data)); 148 | 149 | for (int i=0;imatch(addr)) 151 | { 152 | m_mem[i]->write(addr, data); 153 | found = true; 154 | } 155 | 156 | if (!found) 157 | { 158 | printf("ERROR: Write out of range 0x%08x\n", addr); 159 | sc_assert(0); 160 | } 161 | } 162 | 163 | uint8_t read(uint32_t addr) 164 | { 165 | for (int i=0;imatch(addr)) 167 | { 168 | uint8_t data = m_mem[i]->read(addr); 169 | if (m_record_accesses) 170 | m_accesses.push(tb_mem_record(false, addr, data)); 171 | return data; 172 | } 173 | 174 | printf("ERROR: Read out of range 0x%08x\n", addr); 175 | sc_assert(0); 176 | return 0; 177 | } 178 | 179 | uint8_t* get_array(uint32_t addr) 180 | { 181 | for (int i=0;imatch(addr)) 183 | return m_mem[i]->get_array(); 184 | 185 | printf("ERROR: Access out of range 0x%08x\n", addr); 186 | sc_assert(0); 187 | return NULL; 188 | } 189 | 190 | void records_enable(bool enable) { m_record_accesses = enable; } 191 | bool records_available(void) { return m_accesses.size() != 0; } 192 | tb_mem_record records_pop(void) { tb_mem_record v = m_accesses.front(); m_accesses.pop(); return v; } 193 | 194 | protected: 195 | tb_mem_region * m_mem[TB_MEM_MAX_REGIONS]; 196 | bool m_record_accesses; 197 | std::queue m_accesses; 198 | }; 199 | 200 | #endif -------------------------------------------------------------------------------- /top_cache_axi/tb/testbench.h: -------------------------------------------------------------------------------- 1 | #include "systemc.h" 2 | 3 | #include "riscv_main.h" 4 | #include "testbench_vbase.h" 5 | #include "tb_axi4_mem.h" 6 | 7 | #include "cosim_api.h" 8 | 9 | #include "riscv_top.h" 10 | #include "Vriscv_top.h" 11 | #include "Vriscv_top__Syms.h" 12 | 13 | #include "riscv.h" 14 | #include "elf_load.h" 15 | 16 | #include 17 | 18 | //----------------------------------------------------------------- 19 | // Module 20 | //----------------------------------------------------------------- 21 | class testbench: public testbench_vbase, public cosim_cpu_api, public cosim_mem_api 22 | { 23 | public: 24 | 25 | //----------------------------------------------------------------- 26 | // Instances / Members 27 | //----------------------------------------------------------------- 28 | riscv_top *m_dut; 29 | tb_axi4_mem *m_icache_mem; 30 | tb_axi4_mem *m_dcache_mem; 31 | 32 | sc_signal mem_i_in; 33 | sc_signal mem_i_out; 34 | 35 | sc_signal mem_d_in; 36 | sc_signal mem_d_out; 37 | 38 | sc_signal < bool > intr_in; 39 | 40 | sc_signal < sc_uint <32> > reset_vector_in; 41 | 42 | int m_argc; 43 | char** m_argv; 44 | 45 | //----------------------------------------------------------------- 46 | // process 47 | //----------------------------------------------------------------- 48 | void process(void) 49 | { 50 | int exitcode; 51 | 52 | cosim::instance()->attach_cpu("rtl", this); 53 | cosim::instance()->attach_mem("rtl", this, 0, 0xFFFFFFFF); 54 | 55 | wait(); 56 | 57 | exit(riscv_main(cosim::instance(), m_argc, m_argv)); 58 | } 59 | 60 | //----------------------------------------------------------------- 61 | // Trace 62 | //----------------------------------------------------------------- 63 | void add_trace(sc_trace_file * fp, std::string prefix) 64 | { 65 | // Add signals to trace file 66 | #define TRACE_SIGNAL(a) sc_trace(fp,a,#a); 67 | TRACE_SIGNAL(clk); 68 | TRACE_SIGNAL(rst); 69 | 70 | m_dut->add_trace(fp, ""); 71 | } 72 | 73 | 74 | void set_testcase(int tc) { } 75 | void set_delays(bool en) { } 76 | void set_iterations(int iterations) { } 77 | void set_argcv(int argc, char* argv[]) { m_argc = argc; m_argv = argv; } 78 | 79 | SC_HAS_PROCESS(testbench); 80 | testbench(sc_module_name name): testbench_vbase(name) 81 | { 82 | m_dut = new riscv_top("DUT"); 83 | m_dut->clk_in(clk); 84 | m_dut->rst_in(rst); 85 | m_dut->axi_i_out(mem_i_out); 86 | m_dut->axi_i_in(mem_i_in); 87 | m_dut->axi_d_out(mem_d_out); 88 | m_dut->axi_d_in(mem_d_in); 89 | m_dut->intr_in(intr_in); 90 | m_dut->reset_vector_in(reset_vector_in); 91 | 92 | // Instruction Cache Memory 93 | m_icache_mem = new tb_axi4_mem("ICACHE_MEM"); 94 | m_icache_mem->clk_in(clk); 95 | m_icache_mem->rst_in(rst); 96 | m_icache_mem->axi_in(mem_i_out); 97 | m_icache_mem->axi_out(mem_i_in); 98 | 99 | // Data Cache Memory 100 | m_dcache_mem = new tb_axi4_mem("DCACHE_MEM"); 101 | m_dcache_mem->clk_in(clk); 102 | m_dcache_mem->rst_in(rst); 103 | m_dcache_mem->axi_in(mem_d_out); 104 | m_dcache_mem->axi_out(mem_d_in); 105 | 106 | m_cycles = 0; 107 | 108 | verilator_trace_enable("verilator.vcd", m_dut); 109 | } 110 | 111 | //----------------------------------------------------------------- 112 | // create_memory: Create memory region 113 | //----------------------------------------------------------------- 114 | bool create_memory(uint32_t base, uint32_t size, uint8_t *mem = NULL) 115 | { 116 | base = base & ~(32-1); 117 | size = (size + 31) & ~(32-1); 118 | 119 | while (m_icache_mem->valid_addr(base)) 120 | base += 1; 121 | 122 | while (m_icache_mem->valid_addr(base + size - 1)) 123 | size -= 1; 124 | 125 | m_icache_mem->add_region(base, size); 126 | m_dcache_mem->add_region(m_icache_mem->get_array(base), base, size); 127 | 128 | memset(m_icache_mem->get_array(base), 0, size); 129 | 130 | return true; 131 | } 132 | 133 | bool valid_addr(uint32_t addr) { return true; } 134 | //----------------------------------------------------------------- 135 | // write: Write byte into memory 136 | //----------------------------------------------------------------- 137 | void write(uint32_t addr, uint8_t data) 138 | { 139 | m_dcache_mem->write(addr, data); 140 | } 141 | //----------------------------------------------------------------- 142 | // write: Read byte from memory 143 | //----------------------------------------------------------------- 144 | uint8_t read(uint32_t addr) 145 | { 146 | return m_dcache_mem->read(addr); 147 | } 148 | 149 | // Status 150 | bool get_fault(void) { return false; } 151 | bool get_stopped(void) { return false; } 152 | 153 | void step(void) 154 | { 155 | wait(); 156 | m_cycles++; 157 | } 158 | 159 | // Reset core to execute from specified PC 160 | void reset(uint32_t addr) 161 | { 162 | reset_vector_in.write(addr); 163 | } 164 | 165 | // Trigger interrupt 166 | void set_interrupt(int irq) { } 167 | 168 | void enable_trace(uint32_t mask) { } 169 | 170 | // State after execution 171 | uint32_t get_opcode(void) { } 172 | uint32_t get_pc(void) 173 | { 174 | static uint32_t last_pc = 0; 175 | 176 | if (m_dut->m_rtl->__VlSymsp->TOP__v__u_core__u_issue.complete_valid0()) 177 | last_pc = m_dut->m_rtl->__VlSymsp->TOP__v__u_core__u_issue.complete_pc0(); 178 | 179 | 180 | return last_pc; 181 | } 182 | bool get_reg_valid(int r){ return 0; }//m_dut->u_core.u_decode.get_reg_valid(r); } 183 | uint32_t get_register(int r) { return 0; }//m_dut->u_core.u_decode.get_register(r); } 184 | int get_num_reg(void) { return 32; } 185 | 186 | void set_register(int r, uint32_t val) 187 | { 188 | //m_dut->u_core.u_decode.set_register(r, val); 189 | } 190 | 191 | uint32_t m_cycles; 192 | }; 193 | -------------------------------------------------------------------------------- /top_cache_axi/tb/testbench_vbase.h: -------------------------------------------------------------------------------- 1 | #ifndef TESTBENCH_VBASE_H 2 | #define TESTBENCH_VBASE_H 3 | 4 | #include 5 | #include "verilated.h" 6 | #include "verilated_vcd_sc.h" 7 | 8 | #define verilator_trace_enable(vcd_filename, dut) \ 9 | if (waves_enabled()) \ 10 | { \ 11 | Verilated::traceEverOn(true); \ 12 | VerilatedVcdC *v_vcd = new VerilatedVcdC; \ 13 | sc_core::sc_time delay_us; \ 14 | if (waves_delayed(delay_us)) \ 15 | dut->trace_enable (v_vcd, delay_us); \ 16 | else \ 17 | dut->trace_enable (v_vcd); \ 18 | v_vcd->open (vcd_filename); \ 19 | this->m_verilate_vcd = v_vcd; \ 20 | } 21 | 22 | //----------------------------------------------------------------- 23 | // Module 24 | //----------------------------------------------------------------- 25 | class testbench_vbase: public sc_module 26 | { 27 | public: 28 | sc_in clk; 29 | sc_in rst; 30 | 31 | virtual void set_testcase(int tc) { } 32 | virtual void set_delays(bool en) { } 33 | virtual void set_iterations(int iterations) { } 34 | virtual void set_argcv(int argc, char* argv[]) { } 35 | 36 | virtual void process(void) { while (1) wait(); } 37 | virtual void monitor(void) { while (1) wait(); } 38 | 39 | SC_HAS_PROCESS(testbench_vbase); 40 | testbench_vbase(sc_module_name name): sc_module(name) 41 | { 42 | SC_CTHREAD(process, clk); 43 | SC_CTHREAD(monitor, clk); 44 | } 45 | 46 | virtual void add_trace(sc_trace_file * fp, std::string prefix) { } 47 | 48 | virtual void abort(void) 49 | { 50 | cout << "TB: Aborted at " << sc_time_stamp() << endl; 51 | if (m_verilate_vcd) 52 | { 53 | m_verilate_vcd->flush(); 54 | m_verilate_vcd->close(); 55 | m_verilate_vcd = NULL; 56 | } 57 | } 58 | 59 | bool waves_enabled(void) 60 | { 61 | char *s = getenv("ENABLE_WAVES"); 62 | if (s && !strcmp(s, "no")) 63 | return false; 64 | else 65 | return true; 66 | } 67 | 68 | bool waves_delayed(sc_core::sc_time &delay) 69 | { 70 | char *s = getenv("WAVES_DELAY_US"); 71 | if (s != NULL) 72 | { 73 | uint32_t us = strtoul(s, NULL, 0); 74 | printf("WAVES: Delay start until %duS\n", us); 75 | delay = sc_core::sc_time(us, SC_US); 76 | return true; 77 | } 78 | else 79 | return false; 80 | } 81 | 82 | std::string getenv_str(std::string name, std::string defval) 83 | { 84 | char *s = getenv(name.c_str()); 85 | if (!s || (s && !strcmp(s, ""))) 86 | return defval; 87 | else 88 | return std::string(s); 89 | } 90 | 91 | protected: 92 | VerilatedVcdC *m_verilate_vcd; 93 | }; 94 | 95 | #endif -------------------------------------------------------------------------------- /top_tcm_axi/src_v/dport_mux.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // RISC-V Top 3 | // V0.6 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2019 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: BSD 10 | //----------------------------------------------------------------- 11 | // 12 | // Copyright (c) 2014, Ultra-Embedded.com 13 | // All rights reserved. 14 | // 15 | // Redistribution and use in source and binary forms, with or without 16 | // modification, are permitted provided that the following conditions 17 | // are met: 18 | // - Redistributions of source code must retain the above copyright 19 | // notice, this list of conditions and the following disclaimer. 20 | // - Redistributions in binary form must reproduce the above copyright 21 | // notice, this list of conditions and the following disclaimer 22 | // in the documentation and/or other materials provided with the 23 | // distribution. 24 | // - Neither the name of the author nor the names of its contributors 25 | // may be used to endorse or promote products derived from this 26 | // software without specific prior written permission. 27 | // 28 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 32 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 35 | // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 36 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 38 | // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 | // SUCH DAMAGE. 40 | //----------------------------------------------------------------- 41 | 42 | //----------------------------------------------------------------- 43 | // Generated File 44 | //----------------------------------------------------------------- 45 | module dport_mux 46 | //----------------------------------------------------------------- 47 | // Params 48 | //----------------------------------------------------------------- 49 | #( 50 | parameter TCM_MEM_BASE = 0 51 | ) 52 | //----------------------------------------------------------------- 53 | // Ports 54 | //----------------------------------------------------------------- 55 | ( 56 | // Inputs 57 | input clk_i 58 | ,input rst_i 59 | ,input [ 31:0] mem_addr_i 60 | ,input [ 31:0] mem_data_wr_i 61 | ,input mem_rd_i 62 | ,input [ 3:0] mem_wr_i 63 | ,input mem_cacheable_i 64 | ,input [ 10:0] mem_req_tag_i 65 | ,input mem_invalidate_i 66 | ,input mem_writeback_i 67 | ,input mem_flush_i 68 | ,input [ 31:0] mem_tcm_data_rd_i 69 | ,input mem_tcm_accept_i 70 | ,input mem_tcm_ack_i 71 | ,input mem_tcm_error_i 72 | ,input [ 10:0] mem_tcm_resp_tag_i 73 | ,input [ 31:0] mem_ext_data_rd_i 74 | ,input mem_ext_accept_i 75 | ,input mem_ext_ack_i 76 | ,input mem_ext_error_i 77 | ,input [ 10:0] mem_ext_resp_tag_i 78 | 79 | // Outputs 80 | ,output [ 31:0] mem_data_rd_o 81 | ,output mem_accept_o 82 | ,output mem_ack_o 83 | ,output mem_error_o 84 | ,output [ 10:0] mem_resp_tag_o 85 | ,output [ 31:0] mem_tcm_addr_o 86 | ,output [ 31:0] mem_tcm_data_wr_o 87 | ,output mem_tcm_rd_o 88 | ,output [ 3:0] mem_tcm_wr_o 89 | ,output mem_tcm_cacheable_o 90 | ,output [ 10:0] mem_tcm_req_tag_o 91 | ,output mem_tcm_invalidate_o 92 | ,output mem_tcm_writeback_o 93 | ,output mem_tcm_flush_o 94 | ,output [ 31:0] mem_ext_addr_o 95 | ,output [ 31:0] mem_ext_data_wr_o 96 | ,output mem_ext_rd_o 97 | ,output [ 3:0] mem_ext_wr_o 98 | ,output mem_ext_cacheable_o 99 | ,output [ 10:0] mem_ext_req_tag_o 100 | ,output mem_ext_invalidate_o 101 | ,output mem_ext_writeback_o 102 | ,output mem_ext_flush_o 103 | ); 104 | 105 | 106 | 107 | //----------------------------------------------------------------- 108 | // Dcache_if mux 109 | //----------------------------------------------------------------- 110 | wire hold_w; 111 | 112 | /* verilator lint_off UNSIGNED */ 113 | wire tcm_access_w = (mem_addr_i >= TCM_MEM_BASE && mem_addr_i < (TCM_MEM_BASE + 32'd65536)); 114 | /* verilator lint_on UNSIGNED */ 115 | 116 | reg tcm_access_q; 117 | reg [4:0] pending_q; 118 | 119 | assign mem_tcm_addr_o = mem_addr_i; 120 | assign mem_tcm_data_wr_o = mem_data_wr_i; 121 | assign mem_tcm_rd_o = (tcm_access_w & ~hold_w) ? mem_rd_i : 1'b0; 122 | assign mem_tcm_wr_o = (tcm_access_w & ~hold_w) ? mem_wr_i : 4'b0; 123 | assign mem_tcm_cacheable_o = mem_cacheable_i; 124 | assign mem_tcm_req_tag_o = mem_req_tag_i; 125 | assign mem_tcm_invalidate_o = (tcm_access_w & ~hold_w) ? mem_invalidate_i : 1'b0; 126 | assign mem_tcm_writeback_o = (tcm_access_w & ~hold_w) ? mem_writeback_i : 1'b0; 127 | assign mem_tcm_flush_o = (tcm_access_w & ~hold_w) ? mem_flush_i : 1'b0; 128 | 129 | assign mem_ext_addr_o = mem_addr_i; 130 | assign mem_ext_data_wr_o = mem_data_wr_i; 131 | assign mem_ext_rd_o = (~tcm_access_w & ~hold_w) ? mem_rd_i : 1'b0; 132 | assign mem_ext_wr_o = (~tcm_access_w & ~hold_w) ? mem_wr_i : 4'b0; 133 | assign mem_ext_cacheable_o = mem_cacheable_i; 134 | assign mem_ext_req_tag_o = mem_req_tag_i; 135 | assign mem_ext_invalidate_o = (~tcm_access_w & ~hold_w) ? mem_invalidate_i : 1'b0; 136 | assign mem_ext_writeback_o = (~tcm_access_w & ~hold_w) ? mem_writeback_i : 1'b0; 137 | assign mem_ext_flush_o = (~tcm_access_w & ~hold_w) ? mem_flush_i : 1'b0; 138 | 139 | assign mem_accept_o =(tcm_access_w ? mem_tcm_accept_i : mem_ext_accept_i) & !hold_w; 140 | assign mem_data_rd_o = tcm_access_q ? mem_tcm_data_rd_i : mem_ext_data_rd_i; 141 | assign mem_ack_o = tcm_access_q ? mem_tcm_ack_i : mem_ext_ack_i; 142 | assign mem_error_o = tcm_access_q ? mem_tcm_error_i : mem_ext_error_i; 143 | assign mem_resp_tag_o = tcm_access_q ? mem_tcm_resp_tag_i : mem_ext_resp_tag_i; 144 | 145 | wire request_w = mem_rd_i || mem_wr_i != 4'b0 || mem_flush_i || mem_invalidate_i || mem_writeback_i; 146 | 147 | reg [4:0] pending_r; 148 | always @ * 149 | begin 150 | pending_r = pending_q; 151 | 152 | if ((request_w && mem_accept_o) && !mem_ack_o) 153 | pending_r = pending_r + 5'd1; 154 | else if (!(request_w && mem_accept_o) && mem_ack_o) 155 | pending_r = pending_r - 5'd1; 156 | end 157 | 158 | always @ (posedge clk_i or posedge rst_i) 159 | if (rst_i) 160 | pending_q <= 5'b0; 161 | else 162 | pending_q <= pending_r; 163 | 164 | always @ (posedge clk_i or posedge rst_i) 165 | if (rst_i) 166 | tcm_access_q <= 1'b0; 167 | else if (request_w && mem_accept_o) 168 | tcm_access_q <= tcm_access_w; 169 | 170 | assign hold_w = (|pending_q) && (tcm_access_q != tcm_access_w); 171 | 172 | 173 | 174 | endmodule 175 | -------------------------------------------------------------------------------- /top_tcm_axi/src_v/tcm_mem_ram.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // RISC-V Top 3 | // V0.6 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2019 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: BSD 10 | //----------------------------------------------------------------- 11 | // 12 | // Copyright (c) 2014, Ultra-Embedded.com 13 | // All rights reserved. 14 | // 15 | // Redistribution and use in source and binary forms, with or without 16 | // modification, are permitted provided that the following conditions 17 | // are met: 18 | // - Redistributions of source code must retain the above copyright 19 | // notice, this list of conditions and the following disclaimer. 20 | // - Redistributions in binary form must reproduce the above copyright 21 | // notice, this list of conditions and the following disclaimer 22 | // in the documentation and/or other materials provided with the 23 | // distribution. 24 | // - Neither the name of the author nor the names of its contributors 25 | // may be used to endorse or promote products derived from this 26 | // software without specific prior written permission. 27 | // 28 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 32 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 35 | // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 36 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 38 | // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 | // SUCH DAMAGE. 40 | //----------------------------------------------------------------- 41 | 42 | //----------------------------------------------------------------- 43 | // Generated File 44 | //----------------------------------------------------------------- 45 | module tcm_mem_ram 46 | ( 47 | // Inputs 48 | input clk0_i 49 | ,input rst0_i 50 | ,input [ 13:0] addr0_i 51 | ,input [ 31:0] data0_i 52 | ,input [ 3:0] wr0_i 53 | ,input clk1_i 54 | ,input rst1_i 55 | ,input [ 13:0] addr1_i 56 | ,input [ 31:0] data1_i 57 | ,input [ 3:0] wr1_i 58 | 59 | // Outputs 60 | ,output [ 31:0] data0_o 61 | ,output [ 31:0] data1_o 62 | ); 63 | 64 | 65 | 66 | //----------------------------------------------------------------- 67 | // Dual Port RAM 64KB 68 | // Mode: Read First 69 | //----------------------------------------------------------------- 70 | /* verilator lint_off MULTIDRIVEN */ 71 | reg [31:0] ram [16383:0] /*verilator public*/; 72 | /* verilator lint_on MULTIDRIVEN */ 73 | 74 | reg [31:0] ram_read0_q; 75 | reg [31:0] ram_read1_q; 76 | 77 | 78 | // Synchronous write 79 | always @ (posedge clk0_i) 80 | begin 81 | if (wr0_i[0]) 82 | ram[addr0_i][7:0] <= data0_i[7:0]; 83 | if (wr0_i[1]) 84 | ram[addr0_i][15:8] <= data0_i[15:8]; 85 | if (wr0_i[2]) 86 | ram[addr0_i][23:16] <= data0_i[23:16]; 87 | if (wr0_i[3]) 88 | ram[addr0_i][31:24] <= data0_i[31:24]; 89 | 90 | ram_read0_q <= ram[addr0_i]; 91 | end 92 | 93 | always @ (posedge clk1_i) 94 | begin 95 | if (wr1_i[0]) 96 | ram[addr1_i][7:0] <= data1_i[7:0]; 97 | if (wr1_i[1]) 98 | ram[addr1_i][15:8] <= data1_i[15:8]; 99 | if (wr1_i[2]) 100 | ram[addr1_i][23:16] <= data1_i[23:16]; 101 | if (wr1_i[3]) 102 | ram[addr1_i][31:24] <= data1_i[31:24]; 103 | 104 | ram_read1_q <= ram[addr1_i]; 105 | end 106 | 107 | assign data0_o = ram_read0_q; 108 | assign data1_o = ram_read1_q; 109 | 110 | 111 | 112 | endmodule 113 | -------------------------------------------------------------------------------- /top_tcm_axi/tb/axi4_lite.h: -------------------------------------------------------------------------------- 1 | #ifndef AXI4_LITE_H 2 | #define AXI4_LITE_H 3 | 4 | #include 5 | 6 | //---------------------------------------------------------------- 7 | // Interface (master) 8 | //---------------------------------------------------------------- 9 | class axi4_lite_master 10 | { 11 | public: 12 | // Members 13 | sc_uint <1> AWVALID; 14 | sc_uint <32> AWADDR; 15 | sc_uint <1> WVALID; 16 | sc_uint <32> WDATA; 17 | sc_uint <4> WSTRB; 18 | sc_uint <1> BREADY; 19 | sc_uint <1> ARVALID; 20 | sc_uint <32> ARADDR; 21 | sc_uint <1> RREADY; 22 | 23 | // Construction 24 | axi4_lite_master() { init(); } 25 | 26 | void init(void) 27 | { 28 | AWVALID = 0; 29 | AWADDR = 0; 30 | WVALID = 0; 31 | WDATA = 0; 32 | WSTRB = 0; 33 | BREADY = 0; 34 | ARVALID = 0; 35 | ARADDR = 0; 36 | RREADY = 0; 37 | } 38 | 39 | bool operator == (const axi4_lite_master & v) const 40 | { 41 | bool eq = true; 42 | eq &= (AWVALID == v.AWVALID); 43 | eq &= (AWADDR == v.AWADDR); 44 | eq &= (WVALID == v.WVALID); 45 | eq &= (WDATA == v.WDATA); 46 | eq &= (WSTRB == v.WSTRB); 47 | eq &= (BREADY == v.BREADY); 48 | eq &= (ARVALID == v.ARVALID); 49 | eq &= (ARADDR == v.ARADDR); 50 | eq &= (RREADY == v.RREADY); 51 | return eq; 52 | } 53 | 54 | friend void sc_trace(sc_trace_file *tf, const axi4_lite_master & v, const std::string & path) 55 | { 56 | sc_trace(tf,v.AWVALID, path + "/awvalid"); 57 | sc_trace(tf,v.AWADDR, path + "/awaddr"); 58 | sc_trace(tf,v.WVALID, path + "/wvalid"); 59 | sc_trace(tf,v.WDATA, path + "/wdata"); 60 | sc_trace(tf,v.WSTRB, path + "/wstrb"); 61 | sc_trace(tf,v.BREADY, path + "/bready"); 62 | sc_trace(tf,v.ARVALID, path + "/arvalid"); 63 | sc_trace(tf,v.ARADDR, path + "/araddr"); 64 | sc_trace(tf,v.RREADY, path + "/rready"); 65 | } 66 | 67 | friend ostream& operator << (ostream& os, axi4_lite_master const & v) 68 | { 69 | os << hex << "AWVALID: " << v.AWVALID << " "; 70 | os << hex << "AWADDR: " << v.AWADDR << " "; 71 | os << hex << "WVALID: " << v.WVALID << " "; 72 | os << hex << "WDATA: " << v.WDATA << " "; 73 | os << hex << "WSTRB: " << v.WSTRB << " "; 74 | os << hex << "BREADY: " << v.BREADY << " "; 75 | os << hex << "ARVALID: " << v.ARVALID << " "; 76 | os << hex << "ARADDR: " << v.ARADDR << " "; 77 | os << hex << "RREADY: " << v.RREADY << " "; 78 | return os; 79 | } 80 | 81 | friend istream& operator >> ( istream& is, axi4_lite_master & val) 82 | { 83 | // Not implemented 84 | return is; 85 | } 86 | }; 87 | 88 | #define MEMBER_COPY_AXI4_LITE_MASTER(s,d) do { \ 89 | s.AWVALID = d.AWVALID; \ 90 | s.AWADDR = d.AWADDR; \ 91 | s.WVALID = d.WVALID; \ 92 | s.WDATA = d.WDATA; \ 93 | s.WSTRB = d.WSTRB; \ 94 | s.BREADY = d.BREADY; \ 95 | s.ARVALID = d.ARVALID; \ 96 | s.ARADDR = d.ARADDR; \ 97 | s.RREADY = d.RREADY; \ 98 | } while (0) 99 | 100 | //---------------------------------------------------------------- 101 | // Interface (slave) 102 | //---------------------------------------------------------------- 103 | class axi4_lite_slave 104 | { 105 | public: 106 | // Members 107 | sc_uint <1> AWREADY; 108 | sc_uint <1> WREADY; 109 | sc_uint <1> BVALID; 110 | sc_uint <2> BRESP; 111 | sc_uint <1> ARREADY; 112 | sc_uint <1> RVALID; 113 | sc_uint <32> RDATA; 114 | sc_uint <2> RRESP; 115 | 116 | // Construction 117 | axi4_lite_slave() { init(); } 118 | 119 | void init(void) 120 | { 121 | AWREADY = 0; 122 | WREADY = 0; 123 | BVALID = 0; 124 | BRESP = 0; 125 | ARREADY = 0; 126 | RVALID = 0; 127 | RDATA = 0; 128 | RRESP = 0; 129 | } 130 | 131 | bool operator == (const axi4_lite_slave & v) const 132 | { 133 | bool eq = true; 134 | eq &= (AWREADY == v.AWREADY); 135 | eq &= (WREADY == v.WREADY); 136 | eq &= (BVALID == v.BVALID); 137 | eq &= (BRESP == v.BRESP); 138 | eq &= (ARREADY == v.ARREADY); 139 | eq &= (RVALID == v.RVALID); 140 | eq &= (RDATA == v.RDATA); 141 | eq &= (RRESP == v.RRESP); 142 | return eq; 143 | } 144 | 145 | friend void sc_trace(sc_trace_file *tf, const axi4_lite_slave & v, const std::string & path) 146 | { 147 | sc_trace(tf,v.AWREADY, path + "/awready"); 148 | sc_trace(tf,v.WREADY, path + "/wready"); 149 | sc_trace(tf,v.BVALID, path + "/bvalid"); 150 | sc_trace(tf,v.BRESP, path + "/bresp"); 151 | sc_trace(tf,v.ARREADY, path + "/arready"); 152 | sc_trace(tf,v.RVALID, path + "/rvalid"); 153 | sc_trace(tf,v.RDATA, path + "/rdata"); 154 | sc_trace(tf,v.RRESP, path + "/rresp"); 155 | } 156 | 157 | friend ostream& operator << (ostream& os, axi4_lite_slave const & v) 158 | { 159 | os << hex << "AWREADY: " << v.AWREADY << " "; 160 | os << hex << "WREADY: " << v.WREADY << " "; 161 | os << hex << "BVALID: " << v.BVALID << " "; 162 | os << hex << "BRESP: " << v.BRESP << " "; 163 | os << hex << "ARREADY: " << v.ARREADY << " "; 164 | os << hex << "RVALID: " << v.RVALID << " "; 165 | os << hex << "RDATA: " << v.RDATA << " "; 166 | os << hex << "RRESP: " << v.RRESP << " "; 167 | return os; 168 | } 169 | 170 | friend istream& operator >> ( istream& is, axi4_lite_slave & val) 171 | { 172 | // Not implemented 173 | return is; 174 | } 175 | }; 176 | 177 | #define MEMBER_COPY_AXI4_LITE_SLAVE(s,d) do { \ 178 | s.AWREADY = d.AWREADY; \ 179 | s.WREADY = d.WREADY; \ 180 | s.BVALID = d.BVALID; \ 181 | s.BRESP = d.BRESP; \ 182 | s.ARREADY = d.ARREADY; \ 183 | s.RVALID = d.RVALID; \ 184 | s.RDATA = d.RDATA; \ 185 | s.RRESP = d.RRESP; \ 186 | } while (0) 187 | 188 | 189 | #endif 190 | -------------------------------------------------------------------------------- /top_tcm_axi/tb/main.cpp: -------------------------------------------------------------------------------- 1 | #include "sc_reset_gen.h" 2 | #include "testbench.h" 3 | #include 4 | #include 5 | #include 6 | 7 | //-------------------------------------------------------------------- 8 | // Defines 9 | //-------------------------------------------------------------------- 10 | #ifndef SIM_TIME_RESOLUTION 11 | #define SIM_TIME_RESOLUTION 1 12 | #endif 13 | #ifndef SIM_TIME_SCALE 14 | #define SIM_TIME_SCALE SC_NS 15 | #endif 16 | 17 | #ifndef CLK0_PERIOD 18 | #define CLK0_PERIOD 10 19 | #endif 20 | 21 | #ifndef CLK0_NAME 22 | #define CLK0_NAME clk 23 | #endif 24 | 25 | #ifndef RST0_NAME 26 | #define RST0_NAME rst 27 | #endif 28 | 29 | #define xstr(a) str(a) 30 | #define str(a) #a 31 | 32 | //-------------------------------------------------------------------- 33 | // Locals 34 | //-------------------------------------------------------------------- 35 | static testbench *tb = NULL; 36 | 37 | //-------------------------------------------------------------------- 38 | // assert_handler: Handling of sc_assert 39 | //-------------------------------------------------------------------- 40 | static void assert_handler(const sc_report& rep, const sc_actions& actions) 41 | { 42 | sc_report_handler::default_handler(rep, actions & ~SC_ABORT); 43 | 44 | if ( actions & SC_ABORT ) 45 | { 46 | cout << "TEST FAILED" << endl; 47 | if (tb) 48 | tb->abort(); 49 | abort(); 50 | } 51 | } 52 | //-------------------------------------------------------------------- 53 | // exit_override 54 | //-------------------------------------------------------------------- 55 | static void exit_override(void) 56 | { 57 | if (tb) 58 | tb->abort(); 59 | } 60 | //-------------------------------------------------------------------- 61 | // vl_finish: Handling of verilog $finish 62 | //-------------------------------------------------------------------- 63 | void vl_finish (const char* filename, int linenum, const char* hier) 64 | { 65 | // Jump to exit handler! 66 | exit(0); 67 | } 68 | //----------------------------------------------------------------- 69 | // sigint_handler 70 | //----------------------------------------------------------------- 71 | static void sigint_handler(int s) 72 | { 73 | exit_override(); 74 | 75 | // Jump to exit handler! 76 | exit(1); 77 | } 78 | //-------------------------------------------------------------------- 79 | // sc_main 80 | //-------------------------------------------------------------------- 81 | int sc_main(int argc, char* argv[]) 82 | { 83 | bool trace = true; 84 | int seed = 1; 85 | int last_argc = 0; 86 | const char * vcd_name = "sysc_wave"; 87 | 88 | // Env variable seed override 89 | char *s = getenv("SEED"); 90 | if (s && strcmp(s, "")) 91 | seed = strtol(s, NULL, 0); 92 | 93 | for (int i=1;iCLK0_NAME(CLK0_NAME); 145 | tb->RST0_NAME(clk0_rst.rst); 146 | 147 | // Waves 148 | if (trace) 149 | tb->add_trace(sc_create_vcd_trace_file(vcd_name), ""); 150 | 151 | tb->set_argcv(argc - last_argc, &argv[last_argc]); 152 | 153 | // Go! 154 | sc_start(); 155 | 156 | return 0; 157 | } 158 | -------------------------------------------------------------------------------- /top_tcm_axi/tb/makefile: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | ## Tool paths 3 | ############################################################################### 4 | VERILATOR_SRC ?= /usr/share/verilator/include 5 | SYSTEMC_HOME ?= /usr/local/systemc-2.3.1 6 | 7 | TEST_IMAGE ?= ../../isa_sim/images/basic.elf 8 | 9 | CORE ?= riscv 10 | 11 | export VERILATOR_SRC 12 | export SYSTEMC_HOME 13 | 14 | ############################################################################### 15 | ## Makefile 16 | ############################################################################### 17 | all: build 18 | 19 | build: 20 | make -C ../../isa_sim lib 21 | make -f makefile.generate_verilated CORE=$(CORE) 22 | make -f makefile.build_verilated 23 | make -f makefile.build_sysc_tb 24 | 25 | clean: 26 | make -f makefile.generate_verilated CORE=$(CORE) $@ 27 | make -f makefile.build_verilated $@ 28 | make -f makefile.build_sysc_tb $@ 29 | -rm *.vcd 30 | 31 | run: build 32 | ./build/test.x -f $(TEST_IMAGE) -------------------------------------------------------------------------------- /top_tcm_axi/tb/makefile.build_sysc_tb: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Variables 3 | ############################################################################### 4 | VERILATOR_SRC ?= /usr/share/verilator/include 5 | SYSTEMC_HOME ?= /usr/local/systemc-2.3.1 6 | 7 | OBJ_DIR ?= obj/ 8 | EXE_DIR ?= build/ 9 | SRC_DIR ?= ./ 10 | 11 | TARGET ?= test.x 12 | 13 | # Additional include directories 14 | INCLUDE_PATH ?= 15 | INCLUDE_PATH += $(SRC_DIR) 16 | INCLUDE_PATH += ./verilated 17 | INCLUDE_PATH += ../../isa_sim 18 | INCLUDE_PATH += $(VERILATOR_SRC) 19 | INCLUDE_PATH += $(VERILATOR_SRC)/vltstd 20 | INCLUDE_PATH += $(SYSTEMC_HOME)/include 21 | 22 | # Dependancies 23 | LIB_PATH ?= 24 | LIB_PATH += ./lib 25 | LIB_PATH += ../../isa_sim 26 | LIBS = -lisa_sim -lsyscverilated -lelf -lbfd 27 | 28 | # Flags 29 | CFLAGS ?= -fpic -O2 30 | CFLAGS += $(patsubst %,-I%,$(INCLUDE_PATH)) 31 | CFLAGS += -DVM_TRACE=1 32 | LDFLAGS ?= -O2 33 | LDFLAGS += -L$(SYSTEMC_HOME)/lib-linux64 34 | LDFLAGS += $(patsubst %,-L%,$(LIB_PATH)) 35 | 36 | EXTRA_CLEAN_FILES ?= 37 | 38 | # SRC / Object list 39 | src2obj = $(OBJ_DIR)$(patsubst %$(suffix $(1)),%.o,$(notdir $(1))) 40 | SRC ?= $(foreach src,$(SRC_DIR),$(wildcard $(src)/*.cpp)) 41 | OBJ ?= $(foreach src,$(SRC),$(call src2obj,$(src))) 42 | 43 | ############################################################################### 44 | # Rules 45 | ############################################################################### 46 | define template_c 47 | $(call src2obj,$(1)): $(1) | $(OBJ_DIR) 48 | g++ $(CFLAGS) -c $$< -o $$@ 49 | endef 50 | 51 | all: $(EXE_DIR)$(TARGET) 52 | 53 | $(OBJ_DIR) $(EXE_DIR): 54 | mkdir -p $@ 55 | 56 | $(foreach src,$(SRC),$(eval $(call template_c,$(src)))) 57 | 58 | $(EXE_DIR)$(TARGET): $(OBJ) | $(EXE_DIR) 59 | g++ $(LDFLAGS) $(OBJ) -o $@ -lsystemc $(LIBS) 60 | 61 | clean: 62 | rm -rf $(EXE_DIR) $(OBJ_DIR) $(EXTRA_CLEAN_FILES) 63 | -------------------------------------------------------------------------------- /top_tcm_axi/tb/makefile.build_verilated: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Variables 3 | ############################################################################### 4 | VERILATOR_SRC ?= /usr/share/verilator/include 5 | SYSTEMC_HOME ?= /usr/local/systemc-2.3.1 6 | 7 | SRC_DIR ?= verilated/ 8 | OBJ_DIR ?= obj_verilated/ 9 | LIB_DIR ?= lib/ 10 | 11 | LIBNAME ?= libsyscverilated.a 12 | 13 | # Additional include directories 14 | INCLUDE_PATH ?= 15 | INCLUDE_PATH += $(SRC_DIR) 16 | INCLUDE_PATH += $(SYSTEMC_HOME)/include 17 | INCLUDE_PATH += $(VERILATOR_SRC) 18 | INCLUDE_PATH += $(VERILATOR_SRC)/vltstd 19 | 20 | # Flags 21 | CFLAGS ?= 22 | CFLAGS += -DVM_TRACE=1 -DVL_USER_FINISH=1 23 | CFLAGS += -fpic 24 | CFLAGS += $(patsubst %,-I%,$(INCLUDE_PATH)) 25 | CFLAGS += $(EXTRA_CFLAGS) 26 | 27 | LIB_OPT ?= $(SYSTEMC_HOME)/lib-linux64/libsystemc.a 28 | 29 | # SRC / Object list 30 | src2obj = $(OBJ_DIR)$(patsubst %$(suffix $(1)),%.o,$(notdir $(1))) 31 | SRC_LIST = $(foreach src,$(SRC_DIR),$(wildcard $(src)/*.cpp)) 32 | SRC_LIST += $(VERILATOR_SRC)/verilated.cpp 33 | SRC_LIST += $(VERILATOR_SRC)/verilated_vcd_c.cpp 34 | SRC_LIST += $(VERILATOR_SRC)/verilated_vcd_sc.cpp 35 | 36 | OBJ ?= $(foreach src,$(SRC_LIST),$(call src2obj,$(src))) 37 | 38 | ############################################################################### 39 | # Rules 40 | ############################################################################### 41 | define template_c 42 | $(call src2obj,$(1)): $(1) | $(OBJ_DIR) 43 | g++ $(CFLAGS) -c $$< -o $$@ 44 | endef 45 | 46 | all: $(LIB_DIR)$(LIBNAME) 47 | 48 | $(OBJ_DIR) $(LIB_DIR): 49 | mkdir -p $@ 50 | 51 | $(foreach src,$(SRC_LIST),$(eval $(call template_c,$(src)))) 52 | 53 | $(LIB_DIR)$(LIBNAME): $(OBJ) | $(LIB_DIR) 54 | g++ -shared -o $(LIB_DIR)$(LIBNAME) $(LIB_OPT) $(OBJ) 55 | 56 | clean: 57 | rm -rf $(LIB_DIR) $(OBJ_DIR) 58 | -------------------------------------------------------------------------------- /top_tcm_axi/tb/makefile.generate_verilated: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Variables 3 | ############################################################################### 4 | CORE ?= core 5 | PARAMS ?= 6 | OUTPUT_DIR ?= verilated 7 | SRC_DIR ?= ../src_v 8 | SRC_TYPE ?= v 9 | SRC_V_DIR ?= ../src_v 10 | OUTPUT_SUFFIX ?= 11 | SRC ?= riscv_tcm_top 12 | NAME ?= riscv_tcm_top 13 | 14 | RTL_INCLUDE = ../../core/$(CORE) 15 | 16 | # Verilator options 17 | VERILATE_PARAMS ?= --trace 18 | VERILATOR_OPTS ?= --pins-sc-uint 19 | 20 | OLDER_VERILATOR := $(shell verilator --l2-name v 2>&1 | grep "Invalid Option" | wc -l) 21 | 22 | ifeq ($(OLDER_VERILATOR),0) 23 | VERILATOR_OPTS += --l2-name v 24 | endif 25 | 26 | TARGETS ?= $(OUTPUT_DIR)/V$(NAME) 27 | 28 | ############################################################################### 29 | # Rules 30 | ############################################################################### 31 | all: $(TARGETS) 32 | 33 | $(OUTPUT_DIR): 34 | mkdir -p $@ 35 | 36 | $(OUTPUT_DIR)/V$(NAME): $(SRC_DIR)/$(SRC).$(SRC_TYPE) | $(OUTPUT_DIR) 37 | verilator --sc $(patsubst $(OUTPUT_DIR)/V$(NAME), $(SRC_V_DIR)/$(NAME), $@) --Mdir $(OUTPUT_DIR) -I./$(SRC_V_DIR) $(patsubst %,-I%,$(RTL_INCLUDE)) $(VERILATOR_OPTS) $(VERILATE_PARAMS) 38 | 39 | clean: 40 | rm -rf $(TARGETS) $(OUTPUT_DIR) 41 | -------------------------------------------------------------------------------- /top_tcm_axi/tb/riscv_tcm_top_rtl.cpp: -------------------------------------------------------------------------------- 1 | #include "riscv_tcm_top_rtl.h" 2 | #include "Vriscv_tcm_top.h" 3 | 4 | #if VM_TRACE 5 | #include "verilated.h" 6 | #include "verilated_vcd_c.h" 7 | #endif 8 | 9 | //------------------------------------------------------------- 10 | // Constructor 11 | //------------------------------------------------------------- 12 | riscv_tcm_top_rtl::riscv_tcm_top_rtl(sc_module_name name): sc_module(name) 13 | { 14 | m_rtl = new Vriscv_tcm_top("Vriscv_tcm_top"); 15 | m_rtl->clk_i(m_clk_in); 16 | m_rtl->rst_i(m_rst_in); 17 | m_rtl->rst_cpu_i(m_rst_cpu_in); 18 | m_rtl->axi_i_awready_i(m_axi_i_awready_in); 19 | m_rtl->axi_i_wready_i(m_axi_i_wready_in); 20 | m_rtl->axi_i_bvalid_i(m_axi_i_bvalid_in); 21 | m_rtl->axi_i_bresp_i(m_axi_i_bresp_in); 22 | m_rtl->axi_i_arready_i(m_axi_i_arready_in); 23 | m_rtl->axi_i_rvalid_i(m_axi_i_rvalid_in); 24 | m_rtl->axi_i_rdata_i(m_axi_i_rdata_in); 25 | m_rtl->axi_i_rresp_i(m_axi_i_rresp_in); 26 | m_rtl->axi_t_awvalid_i(m_axi_t_awvalid_in); 27 | m_rtl->axi_t_awaddr_i(m_axi_t_awaddr_in); 28 | m_rtl->axi_t_awid_i(m_axi_t_awid_in); 29 | m_rtl->axi_t_awlen_i(m_axi_t_awlen_in); 30 | m_rtl->axi_t_awburst_i(m_axi_t_awburst_in); 31 | m_rtl->axi_t_wvalid_i(m_axi_t_wvalid_in); 32 | m_rtl->axi_t_wdata_i(m_axi_t_wdata_in); 33 | m_rtl->axi_t_wstrb_i(m_axi_t_wstrb_in); 34 | m_rtl->axi_t_wlast_i(m_axi_t_wlast_in); 35 | m_rtl->axi_t_bready_i(m_axi_t_bready_in); 36 | m_rtl->axi_t_arvalid_i(m_axi_t_arvalid_in); 37 | m_rtl->axi_t_araddr_i(m_axi_t_araddr_in); 38 | m_rtl->axi_t_arid_i(m_axi_t_arid_in); 39 | m_rtl->axi_t_arlen_i(m_axi_t_arlen_in); 40 | m_rtl->axi_t_arburst_i(m_axi_t_arburst_in); 41 | m_rtl->axi_t_rready_i(m_axi_t_rready_in); 42 | m_rtl->intr_i(m_intr_in); 43 | m_rtl->axi_i_awvalid_o(m_axi_i_awvalid_out); 44 | m_rtl->axi_i_awaddr_o(m_axi_i_awaddr_out); 45 | m_rtl->axi_i_wvalid_o(m_axi_i_wvalid_out); 46 | m_rtl->axi_i_wdata_o(m_axi_i_wdata_out); 47 | m_rtl->axi_i_wstrb_o(m_axi_i_wstrb_out); 48 | m_rtl->axi_i_bready_o(m_axi_i_bready_out); 49 | m_rtl->axi_i_arvalid_o(m_axi_i_arvalid_out); 50 | m_rtl->axi_i_araddr_o(m_axi_i_araddr_out); 51 | m_rtl->axi_i_rready_o(m_axi_i_rready_out); 52 | m_rtl->axi_t_awready_o(m_axi_t_awready_out); 53 | m_rtl->axi_t_wready_o(m_axi_t_wready_out); 54 | m_rtl->axi_t_bvalid_o(m_axi_t_bvalid_out); 55 | m_rtl->axi_t_bresp_o(m_axi_t_bresp_out); 56 | m_rtl->axi_t_bid_o(m_axi_t_bid_out); 57 | m_rtl->axi_t_arready_o(m_axi_t_arready_out); 58 | m_rtl->axi_t_rvalid_o(m_axi_t_rvalid_out); 59 | m_rtl->axi_t_rdata_o(m_axi_t_rdata_out); 60 | m_rtl->axi_t_rresp_o(m_axi_t_rresp_out); 61 | m_rtl->axi_t_rid_o(m_axi_t_rid_out); 62 | m_rtl->axi_t_rlast_o(m_axi_t_rlast_out); 63 | 64 | SC_METHOD(async_outputs); 65 | sensitive << clk_in; 66 | sensitive << rst_in; 67 | sensitive << rst_cpu_in; 68 | sensitive << intr_in; 69 | sensitive << axi_i_in; 70 | sensitive << axi_t_in; 71 | sensitive << m_axi_i_awvalid_out; 72 | sensitive << m_axi_i_awaddr_out; 73 | sensitive << m_axi_i_wvalid_out; 74 | sensitive << m_axi_i_wdata_out; 75 | sensitive << m_axi_i_wstrb_out; 76 | sensitive << m_axi_i_bready_out; 77 | sensitive << m_axi_i_arvalid_out; 78 | sensitive << m_axi_i_araddr_out; 79 | sensitive << m_axi_i_rready_out; 80 | sensitive << m_axi_t_awready_out; 81 | sensitive << m_axi_t_wready_out; 82 | sensitive << m_axi_t_bvalid_out; 83 | sensitive << m_axi_t_bresp_out; 84 | sensitive << m_axi_t_bid_out; 85 | sensitive << m_axi_t_arready_out; 86 | sensitive << m_axi_t_rvalid_out; 87 | sensitive << m_axi_t_rdata_out; 88 | sensitive << m_axi_t_rresp_out; 89 | sensitive << m_axi_t_rid_out; 90 | sensitive << m_axi_t_rlast_out; 91 | 92 | #if VM_TRACE 93 | m_vcd = NULL; 94 | m_delay_waves = false; 95 | SC_METHOD(trace_rtl); 96 | sensitive << clk_in; 97 | #endif 98 | } 99 | //------------------------------------------------------------- 100 | // trace_rtl 101 | //------------------------------------------------------------- 102 | void riscv_tcm_top_rtl::trace_rtl(void) 103 | { 104 | #if VM_TRACE 105 | if (m_delay_waves) 106 | { 107 | if (sc_time_stamp() > m_waves_start) 108 | { 109 | cout << "WAVES: Delayed start reached - " << sc_time_stamp() << endl; 110 | m_delay_waves = false; 111 | } 112 | } 113 | else if (m_vcd) 114 | m_vcd->dump((int)(sc_time_stamp().to_double())); 115 | #endif 116 | } 117 | //------------------------------------------------------------- 118 | // trace_enable 119 | //------------------------------------------------------------- 120 | void riscv_tcm_top_rtl::trace_enable(VerilatedVcdC * p) 121 | { 122 | #if VM_TRACE 123 | m_vcd = p; 124 | m_rtl->trace (m_vcd, 99); 125 | #endif 126 | } 127 | void riscv_tcm_top_rtl::trace_enable(VerilatedVcdC *p, sc_core::sc_time start_time) 128 | { 129 | #if VM_TRACE 130 | m_vcd = p; 131 | m_delay_waves = true; 132 | m_waves_start = start_time; 133 | m_rtl->trace (m_vcd, 99); 134 | #endif 135 | } 136 | //------------------------------------------------------------- 137 | // async_outputs 138 | //------------------------------------------------------------- 139 | void riscv_tcm_top_rtl::async_outputs(void) 140 | { 141 | m_clk_in.write(clk_in.read()); 142 | m_rst_in.write(rst_in.read()); 143 | m_rst_cpu_in.write(rst_cpu_in.read()); 144 | m_intr_in.write(intr_in.read()); 145 | 146 | axi4_lite_slave axi_i_i = axi_i_in.read(); 147 | m_axi_i_awready_in.write(axi_i_i.AWREADY); 148 | m_axi_i_wready_in.write(axi_i_i.WREADY); 149 | m_axi_i_bvalid_in.write(axi_i_i.BVALID); 150 | m_axi_i_bresp_in.write(axi_i_i.BRESP); 151 | m_axi_i_arready_in.write(axi_i_i.ARREADY); 152 | m_axi_i_rvalid_in.write(axi_i_i.RVALID); 153 | m_axi_i_rdata_in.write(axi_i_i.RDATA); 154 | m_axi_i_rresp_in.write(axi_i_i.RRESP); 155 | 156 | 157 | axi4_lite_master axi_i_o; 158 | axi_i_o.AWVALID = m_axi_i_awvalid_out.read(); 159 | axi_i_o.AWADDR = m_axi_i_awaddr_out.read(); 160 | axi_i_o.WVALID = m_axi_i_wvalid_out.read(); 161 | axi_i_o.WDATA = m_axi_i_wdata_out.read(); 162 | axi_i_o.WSTRB = m_axi_i_wstrb_out.read(); 163 | axi_i_o.BREADY = m_axi_i_bready_out.read(); 164 | axi_i_o.ARVALID = m_axi_i_arvalid_out.read(); 165 | axi_i_o.ARADDR = m_axi_i_araddr_out.read(); 166 | axi_i_o.RREADY = m_axi_i_rready_out.read(); 167 | axi_i_out.write(axi_i_o); 168 | axi4_master axi_t_i = axi_t_in.read(); 169 | m_axi_t_awvalid_in.write(axi_t_i.AWVALID); 170 | m_axi_t_awaddr_in.write(axi_t_i.AWADDR); 171 | m_axi_t_awid_in.write(axi_t_i.AWID); 172 | m_axi_t_awlen_in.write(axi_t_i.AWLEN); 173 | m_axi_t_awburst_in.write(axi_t_i.AWBURST); 174 | m_axi_t_wvalid_in.write(axi_t_i.WVALID); 175 | m_axi_t_wdata_in.write(axi_t_i.WDATA); 176 | m_axi_t_wstrb_in.write(axi_t_i.WSTRB); 177 | m_axi_t_wlast_in.write(axi_t_i.WLAST); 178 | m_axi_t_bready_in.write(axi_t_i.BREADY); 179 | m_axi_t_arvalid_in.write(axi_t_i.ARVALID); 180 | m_axi_t_araddr_in.write(axi_t_i.ARADDR); 181 | m_axi_t_arid_in.write(axi_t_i.ARID); 182 | m_axi_t_arlen_in.write(axi_t_i.ARLEN); 183 | m_axi_t_arburst_in.write(axi_t_i.ARBURST); 184 | m_axi_t_rready_in.write(axi_t_i.RREADY); 185 | 186 | 187 | axi4_slave axi_t_o; 188 | axi_t_o.AWREADY = m_axi_t_awready_out.read(); 189 | axi_t_o.WREADY = m_axi_t_wready_out.read(); 190 | axi_t_o.BVALID = m_axi_t_bvalid_out.read(); 191 | axi_t_o.BRESP = m_axi_t_bresp_out.read(); 192 | axi_t_o.BID = m_axi_t_bid_out.read(); 193 | axi_t_o.ARREADY = m_axi_t_arready_out.read(); 194 | axi_t_o.RVALID = m_axi_t_rvalid_out.read(); 195 | axi_t_o.RDATA = m_axi_t_rdata_out.read(); 196 | axi_t_o.RRESP = m_axi_t_rresp_out.read(); 197 | axi_t_o.RID = m_axi_t_rid_out.read(); 198 | axi_t_o.RLAST = m_axi_t_rlast_out.read(); 199 | axi_t_out.write(axi_t_o); 200 | 201 | } 202 | -------------------------------------------------------------------------------- /top_tcm_axi/tb/riscv_tcm_top_rtl.h: -------------------------------------------------------------------------------- 1 | #ifndef RISCV_TCM_TOP_RTL_H 2 | #define RISCV_TCM_TOP_RTL_H 3 | 4 | #include 5 | 6 | #include "axi4_lite.h" 7 | #include "axi4.h" 8 | 9 | class Vriscv_tcm_top; 10 | class VerilatedVcdC; 11 | 12 | //------------------------------------------------------------- 13 | // riscv_tcm_top_rtl: RTL wrapper class 14 | //------------------------------------------------------------- 15 | class riscv_tcm_top_rtl: public sc_module 16 | { 17 | public: 18 | sc_in clk_in; 19 | sc_in rst_in; 20 | sc_in rst_cpu_in; 21 | sc_in < sc_uint <32> > intr_in; 22 | 23 | sc_in axi_i_in; 24 | sc_out axi_i_out; 25 | sc_in axi_t_in; 26 | sc_out axi_t_out; 27 | 28 | //------------------------------------------------------------- 29 | // Constructor 30 | //------------------------------------------------------------- 31 | SC_HAS_PROCESS(riscv_tcm_top_rtl); 32 | riscv_tcm_top_rtl(sc_module_name name); 33 | 34 | //------------------------------------------------------------- 35 | // Trace 36 | //------------------------------------------------------------- 37 | virtual void add_trace(sc_trace_file *vcd, std::string prefix) 38 | { 39 | #undef TRACE_SIGNAL 40 | #define TRACE_SIGNAL(s) sc_trace(vcd,s,prefix + #s) 41 | 42 | TRACE_SIGNAL(clk_in); 43 | TRACE_SIGNAL(rst_in); 44 | TRACE_SIGNAL(rst_cpu_in); 45 | TRACE_SIGNAL(intr_in); 46 | TRACE_SIGNAL(axi_i_in); 47 | TRACE_SIGNAL(axi_i_out); 48 | TRACE_SIGNAL(axi_t_in); 49 | TRACE_SIGNAL(axi_t_out); 50 | 51 | #undef TRACE_SIGNAL 52 | } 53 | 54 | void async_outputs(void); 55 | void trace_rtl(void); 56 | void trace_enable(VerilatedVcdC *p); 57 | void trace_enable(VerilatedVcdC *p, sc_core::sc_time start_time); 58 | 59 | //------------------------------------------------------------- 60 | // Signals 61 | //------------------------------------------------------------- 62 | private: 63 | sc_signal m_clk_in; 64 | sc_signal m_rst_in; 65 | sc_signal m_rst_cpu_in; 66 | sc_signal m_axi_i_awready_in; 67 | sc_signal m_axi_i_wready_in; 68 | sc_signal m_axi_i_bvalid_in; 69 | sc_signal > m_axi_i_bresp_in; 70 | sc_signal m_axi_i_arready_in; 71 | sc_signal m_axi_i_rvalid_in; 72 | sc_signal > m_axi_i_rdata_in; 73 | sc_signal > m_axi_i_rresp_in; 74 | sc_signal m_axi_t_awvalid_in; 75 | sc_signal > m_axi_t_awaddr_in; 76 | sc_signal > m_axi_t_awid_in; 77 | sc_signal > m_axi_t_awlen_in; 78 | sc_signal > m_axi_t_awburst_in; 79 | sc_signal m_axi_t_wvalid_in; 80 | sc_signal > m_axi_t_wdata_in; 81 | sc_signal > m_axi_t_wstrb_in; 82 | sc_signal m_axi_t_wlast_in; 83 | sc_signal m_axi_t_bready_in; 84 | sc_signal m_axi_t_arvalid_in; 85 | sc_signal > m_axi_t_araddr_in; 86 | sc_signal > m_axi_t_arid_in; 87 | sc_signal > m_axi_t_arlen_in; 88 | sc_signal > m_axi_t_arburst_in; 89 | sc_signal m_axi_t_rready_in; 90 | sc_signal > m_intr_in; 91 | 92 | sc_signal m_axi_i_awvalid_out; 93 | sc_signal > m_axi_i_awaddr_out; 94 | sc_signal m_axi_i_wvalid_out; 95 | sc_signal > m_axi_i_wdata_out; 96 | sc_signal > m_axi_i_wstrb_out; 97 | sc_signal m_axi_i_bready_out; 98 | sc_signal m_axi_i_arvalid_out; 99 | sc_signal > m_axi_i_araddr_out; 100 | sc_signal m_axi_i_rready_out; 101 | sc_signal m_axi_t_awready_out; 102 | sc_signal m_axi_t_wready_out; 103 | sc_signal m_axi_t_bvalid_out; 104 | sc_signal > m_axi_t_bresp_out; 105 | sc_signal > m_axi_t_bid_out; 106 | sc_signal m_axi_t_arready_out; 107 | sc_signal m_axi_t_rvalid_out; 108 | sc_signal > m_axi_t_rdata_out; 109 | sc_signal > m_axi_t_rresp_out; 110 | sc_signal > m_axi_t_rid_out; 111 | sc_signal m_axi_t_rlast_out; 112 | 113 | public: 114 | Vriscv_tcm_top *m_rtl; 115 | #if VM_TRACE 116 | VerilatedVcdC * m_vcd; 117 | bool m_delay_waves; 118 | sc_core::sc_time m_waves_start; 119 | #endif 120 | }; 121 | 122 | #endif -------------------------------------------------------------------------------- /top_tcm_axi/tb/sc_reset_gen.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | //----------------------------------------------------------------- 4 | // Module 5 | //----------------------------------------------------------------- 6 | SC_MODULE(sc_reset_gen) 7 | { 8 | public: 9 | sc_in clk; 10 | sc_signal rst; 11 | 12 | void thread(void) 13 | { 14 | rst.write(true); 15 | wait(); 16 | rst.write(false); 17 | } 18 | 19 | SC_HAS_PROCESS(sc_reset_gen); 20 | sc_reset_gen(sc_module_name name): sc_module(name) 21 | { 22 | SC_CTHREAD(thread, clk); 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /top_tcm_axi/tb/testbench.h: -------------------------------------------------------------------------------- 1 | #include "testbench_vbase.h" 2 | 3 | #include "riscv_main.h" 4 | #include "riscv.h" 5 | #include "elf_load.h" 6 | 7 | #include 8 | 9 | #include "cosim_api.h" 10 | 11 | #include "riscv_tcm_top_rtl.h" 12 | #include "Vriscv_tcm_top.h" 13 | #include "Vriscv_tcm_top__Syms.h" 14 | 15 | #include "verilated.h" 16 | #include "verilated_vcd_sc.h" 17 | 18 | //----------------------------------------------------------------- 19 | // Module 20 | //----------------------------------------------------------------- 21 | class testbench: public testbench_vbase, public cosim_cpu_api, public cosim_mem_api 22 | { 23 | public: 24 | //----------------------------------------------------------------- 25 | // Instances / Members 26 | //----------------------------------------------------------------- 27 | riscv_tcm_top_rtl *m_dut; 28 | 29 | int m_argc; 30 | char** m_argv; 31 | //----------------------------------------------------------------- 32 | // Signals 33 | //----------------------------------------------------------------- 34 | sc_signal rst_cpu_in; 35 | 36 | sc_signal axi_t_in; 37 | sc_signal axi_t_out; 38 | 39 | sc_signal axi_i_out; 40 | sc_signal axi_i_in; 41 | 42 | sc_signal < sc_uint <32> > intr_in; 43 | 44 | 45 | //----------------------------------------------------------------- 46 | // process: Main loop for CPU execution 47 | //----------------------------------------------------------------- 48 | void process(void) 49 | { 50 | cosim::instance()->attach_cpu("rtl", this); 51 | cosim::instance()->attach_mem("rtl", this, 0, 0xFFFFFFFF); 52 | wait(); 53 | exit(riscv_main(cosim::instance(), m_argc, m_argv)); 54 | } 55 | 56 | void set_argcv(int argc, char* argv[]) { m_argc = argc; m_argv = argv; } 57 | 58 | //----------------------------------------------------------------- 59 | // Construction 60 | //----------------------------------------------------------------- 61 | SC_HAS_PROCESS(testbench); 62 | testbench(sc_module_name name): testbench_vbase(name) 63 | { 64 | m_dut = new riscv_tcm_top_rtl("DUT"); 65 | m_dut->clk_in(clk); 66 | m_dut->rst_in(rst); 67 | m_dut->rst_cpu_in(rst_cpu_in); 68 | m_dut->axi_t_out(axi_t_out); 69 | m_dut->axi_t_in(axi_t_in); 70 | m_dut->axi_i_out(axi_i_out); 71 | m_dut->axi_i_in(axi_i_in); 72 | m_dut->intr_in(intr_in); 73 | 74 | verilator_trace_enable("verilator.vcd", m_dut); 75 | } 76 | //----------------------------------------------------------------- 77 | // Trace 78 | //----------------------------------------------------------------- 79 | void add_trace(sc_trace_file * fp, std::string prefix) 80 | { 81 | if (!waves_enabled()) 82 | return; 83 | 84 | // Add signals to trace file 85 | #define TRACE_SIGNAL(a) sc_trace(fp,a,#a); 86 | TRACE_SIGNAL(clk); 87 | TRACE_SIGNAL(rst); 88 | 89 | m_dut->add_trace(fp, ""); 90 | } 91 | 92 | //----------------------------------------------------------------- 93 | // create_memory: Create memory region 94 | //----------------------------------------------------------------- 95 | bool create_memory(uint32_t base, uint32_t size, uint8_t *mem = NULL) 96 | { 97 | sc_assert(base >= 0x00000000 && ((base + size) < (0x00000000 + (64 * 1024)))); 98 | return true; 99 | } 100 | //----------------------------------------------------------------- 101 | // valid_addr: Check address range 102 | //----------------------------------------------------------------- 103 | bool valid_addr(uint32_t addr) { return true; } 104 | //----------------------------------------------------------------- 105 | // write: Write byte into memory 106 | //----------------------------------------------------------------- 107 | void write(uint32_t addr, uint8_t data) 108 | { 109 | m_dut->m_rtl->__VlSymsp->TOP__v__u_tcm.write(addr, data); 110 | } 111 | //----------------------------------------------------------------- 112 | // write: Read byte from memory 113 | //----------------------------------------------------------------- 114 | uint8_t read(uint32_t addr) 115 | { 116 | return m_dut->m_rtl->__VlSymsp->TOP__v__u_tcm.read(addr); 117 | } 118 | //----------------------------------------------------------------- 119 | // step: Execute 1 clock cycle 120 | //----------------------------------------------------------------- 121 | void step(void) 122 | { 123 | wait(); 124 | } 125 | //----------------------------------------------------------------- 126 | // reset: Release core from reset 127 | //----------------------------------------------------------------- 128 | void reset(uint32_t addr) 129 | { 130 | rst_cpu_in.write(true); 131 | wait(); 132 | rst_cpu_in.write(false); 133 | } 134 | 135 | // Not supported 136 | bool get_stopped(void) { return false; } 137 | bool get_fault(void) { return false; } 138 | void set_interrupt(int irq) { } 139 | void enable_trace(uint32_t mask) { } 140 | uint32_t get_opcode(void) { } 141 | uint32_t get_pc(void) { return 0; } 142 | bool get_reg_valid(int r){ return 0; } 143 | uint32_t get_register(int r) { return 0; } 144 | int get_num_reg(void) { return 32; } 145 | void set_register(int r, uint32_t val) { } 146 | }; 147 | -------------------------------------------------------------------------------- /top_tcm_axi/tb/testbench_vbase.h: -------------------------------------------------------------------------------- 1 | #ifndef TESTBENCH_VBASE_H 2 | #define TESTBENCH_VBASE_H 3 | 4 | #include 5 | #include "verilated.h" 6 | #include "verilated_vcd_sc.h" 7 | 8 | #define verilator_trace_enable(vcd_filename, dut) \ 9 | if (waves_enabled()) \ 10 | { \ 11 | Verilated::traceEverOn(true); \ 12 | VerilatedVcdC *v_vcd = new VerilatedVcdC; \ 13 | sc_core::sc_time delay_us; \ 14 | if (waves_delayed(delay_us)) \ 15 | dut->trace_enable (v_vcd, delay_us); \ 16 | else \ 17 | dut->trace_enable (v_vcd); \ 18 | v_vcd->open (vcd_filename); \ 19 | this->m_verilate_vcd = v_vcd; \ 20 | } 21 | 22 | //----------------------------------------------------------------- 23 | // Module 24 | //----------------------------------------------------------------- 25 | class testbench_vbase: public sc_module 26 | { 27 | public: 28 | sc_in clk; 29 | sc_in rst; 30 | 31 | virtual void set_testcase(int tc) { } 32 | virtual void set_delays(bool en) { } 33 | virtual void set_iterations(int iterations) { } 34 | virtual void set_argcv(int argc, char* argv[]) { } 35 | 36 | virtual void process(void) { while (1) wait(); } 37 | virtual void monitor(void) { while (1) wait(); } 38 | 39 | SC_HAS_PROCESS(testbench_vbase); 40 | testbench_vbase(sc_module_name name): sc_module(name) 41 | { 42 | SC_CTHREAD(process, clk); 43 | SC_CTHREAD(monitor, clk); 44 | } 45 | 46 | virtual void add_trace(sc_trace_file * fp, std::string prefix) { } 47 | 48 | virtual void abort(void) 49 | { 50 | cout << "TB: Aborted at " << sc_time_stamp() << endl; 51 | if (m_verilate_vcd) 52 | { 53 | m_verilate_vcd->flush(); 54 | m_verilate_vcd->close(); 55 | m_verilate_vcd = NULL; 56 | } 57 | } 58 | 59 | bool waves_enabled(void) 60 | { 61 | char *s = getenv("ENABLE_WAVES"); 62 | if (s && !strcmp(s, "no")) 63 | return false; 64 | else 65 | return true; 66 | } 67 | 68 | bool waves_delayed(sc_core::sc_time &delay) 69 | { 70 | char *s = getenv("WAVES_DELAY_US"); 71 | if (s != NULL) 72 | { 73 | uint32_t us = strtoul(s, NULL, 0); 74 | printf("WAVES: Delay start until %duS\n", us); 75 | delay = sc_core::sc_time(us, SC_US); 76 | return true; 77 | } 78 | else 79 | return false; 80 | } 81 | 82 | std::string getenv_str(std::string name, std::string defval) 83 | { 84 | char *s = getenv(name.c_str()); 85 | if (!s || (s && !strcmp(s, ""))) 86 | return defval; 87 | else 88 | return std::string(s); 89 | } 90 | 91 | protected: 92 | VerilatedVcdC *m_verilate_vcd; 93 | }; 94 | 95 | #endif -------------------------------------------------------------------------------- /top_tcm_wrapper/dport_mux.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // RISC-V Top 3 | // V0.6 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2019 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: BSD 10 | //----------------------------------------------------------------- 11 | // 12 | // Copyright (c) 2014, Ultra-Embedded.com 13 | // All rights reserved. 14 | // 15 | // Redistribution and use in source and binary forms, with or without 16 | // modification, are permitted provided that the following conditions 17 | // are met: 18 | // - Redistributions of source code must retain the above copyright 19 | // notice, this list of conditions and the following disclaimer. 20 | // - Redistributions in binary form must reproduce the above copyright 21 | // notice, this list of conditions and the following disclaimer 22 | // in the documentation and/or other materials provided with the 23 | // distribution. 24 | // - Neither the name of the author nor the names of its contributors 25 | // may be used to endorse or promote products derived from this 26 | // software without specific prior written permission. 27 | // 28 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 32 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 35 | // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 36 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 38 | // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 | // SUCH DAMAGE. 40 | //----------------------------------------------------------------- 41 | 42 | //----------------------------------------------------------------- 43 | // Generated File 44 | //----------------------------------------------------------------- 45 | module dport_mux 46 | //----------------------------------------------------------------- 47 | // Params 48 | //----------------------------------------------------------------- 49 | #( 50 | parameter TCM_MEM_BASE = 0 51 | ) 52 | //----------------------------------------------------------------- 53 | // Ports 54 | //----------------------------------------------------------------- 55 | ( 56 | // Inputs 57 | input clk_i 58 | ,input rst_i 59 | ,input [ 31:0] mem_addr_i 60 | ,input [ 31:0] mem_data_wr_i 61 | ,input mem_rd_i 62 | ,input [ 3:0] mem_wr_i 63 | ,input mem_cacheable_i 64 | ,input [ 10:0] mem_req_tag_i 65 | ,input mem_invalidate_i 66 | ,input mem_writeback_i 67 | ,input mem_flush_i 68 | ,input [ 31:0] mem_tcm_data_rd_i 69 | ,input mem_tcm_accept_i 70 | ,input mem_tcm_ack_i 71 | ,input mem_tcm_error_i 72 | ,input [ 10:0] mem_tcm_resp_tag_i 73 | ,input [ 31:0] mem_ext_data_rd_i 74 | ,input mem_ext_accept_i 75 | ,input mem_ext_ack_i 76 | ,input mem_ext_error_i 77 | ,input [ 10:0] mem_ext_resp_tag_i 78 | 79 | // Outputs 80 | ,output [ 31:0] mem_data_rd_o 81 | ,output mem_accept_o 82 | ,output mem_ack_o 83 | ,output mem_error_o 84 | ,output [ 10:0] mem_resp_tag_o 85 | ,output [ 31:0] mem_tcm_addr_o 86 | ,output [ 31:0] mem_tcm_data_wr_o 87 | ,output mem_tcm_rd_o 88 | ,output [ 3:0] mem_tcm_wr_o 89 | ,output mem_tcm_cacheable_o 90 | ,output [ 10:0] mem_tcm_req_tag_o 91 | ,output mem_tcm_invalidate_o 92 | ,output mem_tcm_writeback_o 93 | ,output mem_tcm_flush_o 94 | ,output [ 31:0] mem_ext_addr_o 95 | ,output [ 31:0] mem_ext_data_wr_o 96 | ,output mem_ext_rd_o 97 | ,output [ 3:0] mem_ext_wr_o 98 | ,output mem_ext_cacheable_o 99 | ,output [ 10:0] mem_ext_req_tag_o 100 | ,output mem_ext_invalidate_o 101 | ,output mem_ext_writeback_o 102 | ,output mem_ext_flush_o 103 | ); 104 | 105 | 106 | 107 | //----------------------------------------------------------------- 108 | // Dcache_if mux 109 | //----------------------------------------------------------------- 110 | wire hold_w; 111 | 112 | /* verilator lint_off UNSIGNED */ 113 | wire tcm_access_w = (mem_addr_i >= TCM_MEM_BASE && mem_addr_i < (TCM_MEM_BASE + 32'd65536)); 114 | /* verilator lint_on UNSIGNED */ 115 | 116 | reg tcm_access_q; 117 | reg [4:0] pending_q; 118 | 119 | assign mem_tcm_addr_o = mem_addr_i; 120 | assign mem_tcm_data_wr_o = mem_data_wr_i; 121 | assign mem_tcm_rd_o = (tcm_access_w & ~hold_w) ? mem_rd_i : 1'b0; 122 | assign mem_tcm_wr_o = (tcm_access_w & ~hold_w) ? mem_wr_i : 4'b0; 123 | assign mem_tcm_cacheable_o = mem_cacheable_i; 124 | assign mem_tcm_req_tag_o = mem_req_tag_i; 125 | assign mem_tcm_invalidate_o = (tcm_access_w & ~hold_w) ? mem_invalidate_i : 1'b0; 126 | assign mem_tcm_writeback_o = (tcm_access_w & ~hold_w) ? mem_writeback_i : 1'b0; 127 | assign mem_tcm_flush_o = (tcm_access_w & ~hold_w) ? mem_flush_i : 1'b0; 128 | 129 | assign mem_ext_addr_o = mem_addr_i; 130 | assign mem_ext_data_wr_o = mem_data_wr_i; 131 | assign mem_ext_rd_o = (~tcm_access_w & ~hold_w) ? mem_rd_i : 1'b0; 132 | assign mem_ext_wr_o = (~tcm_access_w & ~hold_w) ? mem_wr_i : 4'b0; 133 | assign mem_ext_cacheable_o = mem_cacheable_i; 134 | assign mem_ext_req_tag_o = mem_req_tag_i; 135 | assign mem_ext_invalidate_o = (~tcm_access_w & ~hold_w) ? mem_invalidate_i : 1'b0; 136 | assign mem_ext_writeback_o = (~tcm_access_w & ~hold_w) ? mem_writeback_i : 1'b0; 137 | assign mem_ext_flush_o = (~tcm_access_w & ~hold_w) ? mem_flush_i : 1'b0; 138 | 139 | assign mem_accept_o =(tcm_access_w ? mem_tcm_accept_i : mem_ext_accept_i) & !hold_w; 140 | assign mem_data_rd_o = tcm_access_q ? mem_tcm_data_rd_i : mem_ext_data_rd_i; 141 | assign mem_ack_o = tcm_access_q ? mem_tcm_ack_i : mem_ext_ack_i; 142 | assign mem_error_o = tcm_access_q ? mem_tcm_error_i : mem_ext_error_i; 143 | assign mem_resp_tag_o = tcm_access_q ? mem_tcm_resp_tag_i : mem_ext_resp_tag_i; 144 | 145 | wire request_w = mem_rd_i || mem_wr_i != 4'b0 || mem_flush_i || mem_invalidate_i || mem_writeback_i; 146 | 147 | reg [4:0] pending_r; 148 | always @ * 149 | begin 150 | pending_r = pending_q; 151 | 152 | if ((request_w && mem_accept_o) && !mem_ack_o) 153 | pending_r = pending_r + 5'd1; 154 | else if (!(request_w && mem_accept_o) && mem_ack_o) 155 | pending_r = pending_r - 5'd1; 156 | end 157 | 158 | always @ (posedge clk_i or posedge rst_i) 159 | if (rst_i) 160 | pending_q <= 5'b0; 161 | else 162 | pending_q <= pending_r; 163 | 164 | always @ (posedge clk_i or posedge rst_i) 165 | if (rst_i) 166 | tcm_access_q <= 1'b0; 167 | else if (request_w && mem_accept_o) 168 | tcm_access_q <= tcm_access_w; 169 | 170 | assign hold_w = (|pending_q) && (tcm_access_q != tcm_access_w); 171 | 172 | 173 | 174 | endmodule 175 | -------------------------------------------------------------------------------- /top_tcm_wrapper/tcm_mem_ram.v: -------------------------------------------------------------------------------- 1 | //----------------------------------------------------------------- 2 | // RISC-V Top 3 | // V0.6 4 | // Ultra-Embedded.com 5 | // Copyright 2014-2019 6 | // 7 | // admin@ultra-embedded.com 8 | // 9 | // License: BSD 10 | //----------------------------------------------------------------- 11 | // 12 | // Copyright (c) 2014, Ultra-Embedded.com 13 | // All rights reserved. 14 | // 15 | // Redistribution and use in source and binary forms, with or without 16 | // modification, are permitted provided that the following conditions 17 | // are met: 18 | // - Redistributions of source code must retain the above copyright 19 | // notice, this list of conditions and the following disclaimer. 20 | // - Redistributions in binary form must reproduce the above copyright 21 | // notice, this list of conditions and the following disclaimer 22 | // in the documentation and/or other materials provided with the 23 | // distribution. 24 | // - Neither the name of the author nor the names of its contributors 25 | // may be used to endorse or promote products derived from this 26 | // software without specific prior written permission. 27 | // 28 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 29 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 30 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 31 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 32 | // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 33 | // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 34 | // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR 35 | // BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 36 | // LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 37 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 38 | // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 | // SUCH DAMAGE. 40 | //----------------------------------------------------------------- 41 | 42 | //----------------------------------------------------------------- 43 | // Generated File 44 | //----------------------------------------------------------------- 45 | module tcm_mem_ram 46 | ( 47 | // Inputs 48 | input clk0_i 49 | ,input rst0_i 50 | ,input [ 13:0] addr0_i 51 | ,input [ 31:0] data0_i 52 | ,input [ 3:0] wr0_i 53 | ,input clk1_i 54 | ,input rst1_i 55 | ,input [ 13:0] addr1_i 56 | ,input [ 31:0] data1_i 57 | ,input [ 3:0] wr1_i 58 | 59 | // Outputs 60 | ,output [ 31:0] data0_o 61 | ,output [ 31:0] data1_o 62 | ); 63 | 64 | 65 | 66 | //----------------------------------------------------------------- 67 | // Dual Port RAM 64KB 68 | // Mode: Read First 69 | //----------------------------------------------------------------- 70 | /* verilator lint_off MULTIDRIVEN */ 71 | reg [31:0] ram [16383:0] /*verilator public*/; 72 | /* verilator lint_on MULTIDRIVEN */ 73 | 74 | reg [31:0] ram_read0_q; 75 | reg [31:0] ram_read1_q; 76 | 77 | 78 | // Synchronous write 79 | always @ (posedge clk0_i) 80 | begin 81 | if (wr0_i[0]) 82 | ram[addr0_i][7:0] <= data0_i[7:0]; 83 | if (wr0_i[1]) 84 | ram[addr0_i][15:8] <= data0_i[15:8]; 85 | if (wr0_i[2]) 86 | ram[addr0_i][23:16] <= data0_i[23:16]; 87 | if (wr0_i[3]) 88 | ram[addr0_i][31:24] <= data0_i[31:24]; 89 | 90 | ram_read0_q <= ram[addr0_i]; 91 | end 92 | 93 | always @ (posedge clk1_i) 94 | begin 95 | if (wr1_i[0]) 96 | ram[addr1_i][7:0] <= data1_i[7:0]; 97 | if (wr1_i[1]) 98 | ram[addr1_i][15:8] <= data1_i[15:8]; 99 | if (wr1_i[2]) 100 | ram[addr1_i][23:16] <= data1_i[23:16]; 101 | if (wr1_i[3]) 102 | ram[addr1_i][31:24] <= data1_i[31:24]; 103 | 104 | ram_read1_q <= ram[addr1_i]; 105 | end 106 | 107 | assign data0_o = ram_read0_q; 108 | assign data1_o = ram_read1_q; 109 | 110 | 111 | 112 | endmodule 113 | --------------------------------------------------------------------------------