neorv32/rtl/core/neorv32_package.vhd

1217 lines
71 KiB
VHDL

-- #################################################################################################
-- # << NEORV32 - Main VHDL Package File (CPU and SoC) >> #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
-- # Copyright (c) 2024, Stephan Nolting. All rights reserved. #
-- # #
-- # Redistribution and use in source and binary forms, with or without modification, are #
-- # permitted provided that the following conditions are met: #
-- # #
-- # 1. Redistributions of source code must retain the above copyright notice, this list of #
-- # conditions and the following disclaimer. #
-- # #
-- # 2. Redistributions in binary form must reproduce the above copyright notice, this list of #
-- # conditions and the following disclaimer in the documentation and/or other materials #
-- # provided with the distribution. #
-- # #
-- # 3. Neither the name of the copyright holder nor the names of its contributors may be used to #
-- # endorse or promote products derived from this software without specific prior written #
-- # permission. #
-- # #
-- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS #
-- # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF #
-- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE #
-- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, #
-- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
-- # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED #
-- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING #
-- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED #
-- # OF THE POSSIBILITY OF SUCH DAMAGE. #
-- # ********************************************************************************************* #
-- # The NEORV32 RISC-V Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting #
-- #################################################################################################
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
package neorv32_package is
-- ****************************************************************************************************************************
-- Architecture Configuration and Constants
-- ****************************************************************************************************************************
-- Architecture Configuration -------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- max response time for processor-internal bus transactions --
-- cycles after which an unacknowledged internal bus access will timeout raising a bus fault exception
constant bus_timeout_c : natural := 15; -- default = 15
-- instruction monitor: raise exception if multi-cycle operation times out --
constant monitor_mc_tmo_c : natural := 9; -- = log2 of max execution cycles; default = 2^9 = 512 cycles
-- Architecture Constants -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01090508"; -- hardware version
constant archid_c : natural := 19; -- official RISC-V architecture ID
constant XLEN : natural := 32; -- native data path width
-- Check if we're inside the Matrix -------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant is_simulation_c : boolean := false -- seems like we're on real hardware
-- pragma translate_off
-- synthesis translate_off
-- RTL_SYNTHESIS OFF
or true -- this MIGHT be a simulation
-- RTL_SYNTHESIS ON
-- synthesis translate_on
-- pragma translate_on
;
-- ****************************************************************************************************************************
-- Processor Address Space Layout
-- ****************************************************************************************************************************
-- Main Address Regions ---
constant mem_imem_base_c : std_ulogic_vector(31 downto 0) := x"00000000"; -- IMEM size via generic
constant mem_dmem_base_c : std_ulogic_vector(31 downto 0) := x"80000000"; -- DMEM size via generic
constant mem_xip_base_c : std_ulogic_vector(31 downto 0) := x"e0000000"; -- page (4MSBs) only!
constant mem_xip_size_c : natural := 256*1024*1024;
constant mem_boot_base_c : std_ulogic_vector(31 downto 0) := x"ffffc000";
constant mem_boot_size_c : natural := 8*1024;
constant mem_io_base_c : std_ulogic_vector(31 downto 0) := x"ffffe000";
constant mem_io_size_c : natural := 8*1024;
-- Start of uncached memory access (256MB page / 4MSBs only) --
constant uncached_begin_c : std_ulogic_vector(31 downto 0) := x"f0000000";
-- IO Address Map --
constant iodev_size_c : natural := 256; -- size of a single IO device (bytes)
--constant base_io_???_c : std_ulogic_vector(31 downto 0) := x"ffffe000"; -- reserved
--constant base_io_???_c : std_ulogic_vector(31 downto 0) := x"ffffe100"; -- reserved
--constant base_io_???_c : std_ulogic_vector(31 downto 0) := x"ffffe200"; -- reserved
--constant base_io_???_c : std_ulogic_vector(31 downto 0) := x"ffffe300"; -- reserved
--constant base_io_???_c : std_ulogic_vector(31 downto 0) := x"ffffe400"; -- reserved
--constant base_io_???_c : std_ulogic_vector(31 downto 0) := x"ffffe500"; -- reserved
--constant base_io_???_c : std_ulogic_vector(31 downto 0) := x"ffffe600"; -- reserved
--constant base_io_???_c : std_ulogic_vector(31 downto 0) := x"ffffe700"; -- reserved
--constant base_io_???_c : std_ulogic_vector(31 downto 0) := x"ffffe800"; -- reserved
--constant base_io_???_c : std_ulogic_vector(31 downto 0) := x"ffffe900"; -- reserved
--constant base_io_???_c : std_ulogic_vector(31 downto 0) := x"ffffea00"; -- reserved
constant base_io_cfs_c : std_ulogic_vector(31 downto 0) := x"ffffeb00";
constant base_io_slink_c : std_ulogic_vector(31 downto 0) := x"ffffec00";
constant base_io_dma_c : std_ulogic_vector(31 downto 0) := x"ffffed00";
constant base_io_crc_c : std_ulogic_vector(31 downto 0) := x"ffffee00";
constant base_io_xip_c : std_ulogic_vector(31 downto 0) := x"ffffef00";
constant base_io_pwm_c : std_ulogic_vector(31 downto 0) := x"fffff000";
constant base_io_gptmr_c : std_ulogic_vector(31 downto 0) := x"fffff100";
constant base_io_onewire_c : std_ulogic_vector(31 downto 0) := x"fffff200";
constant base_io_xirq_c : std_ulogic_vector(31 downto 0) := x"fffff300";
constant base_io_mtime_c : std_ulogic_vector(31 downto 0) := x"fffff400";
constant base_io_uart0_c : std_ulogic_vector(31 downto 0) := x"fffff500";
constant base_io_uart1_c : std_ulogic_vector(31 downto 0) := x"fffff600";
constant base_io_sdi_c : std_ulogic_vector(31 downto 0) := x"fffff700";
constant base_io_spi_c : std_ulogic_vector(31 downto 0) := x"fffff800";
constant base_io_twi_c : std_ulogic_vector(31 downto 0) := x"fffff900";
constant base_io_trng_c : std_ulogic_vector(31 downto 0) := x"fffffa00";
constant base_io_wdt_c : std_ulogic_vector(31 downto 0) := x"fffffb00";
constant base_io_gpio_c : std_ulogic_vector(31 downto 0) := x"fffffc00";
constant base_io_neoled_c : std_ulogic_vector(31 downto 0) := x"fffffd00";
constant base_io_sysinfo_c : std_ulogic_vector(31 downto 0) := x"fffffe00";
constant base_io_dm_c : std_ulogic_vector(31 downto 0) := x"ffffff00";
-- On-Chip Debugger - Debug Module Entry Points (Code ROM) --
constant dm_exc_entry_c : std_ulogic_vector(31 downto 0) := x"ffffff00"; -- = base_io_dm_c + 0, exceptions entry point
constant dm_park_entry_c : std_ulogic_vector(31 downto 0) := x"ffffff08"; -- = base_io_dm_c + 8, normal entry point
-- ****************************************************************************************************************************
-- SoC Definitions
-- ****************************************************************************************************************************
-- SoC Clock Select -----------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant clk_div2_c : natural := 0;
constant clk_div4_c : natural := 1;
constant clk_div8_c : natural := 2;
constant clk_div64_c : natural := 3;
constant clk_div128_c : natural := 4;
constant clk_div1024_c : natural := 5;
constant clk_div2048_c : natural := 6;
constant clk_div4096_c : natural := 7;
-- Internal Memory Types ------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
type mem32_t is array (natural range <>) of std_ulogic_vector(31 downto 0); -- memory with 32-bit entries
type mem8_t is array (natural range <>) of std_ulogic_vector(07 downto 0); -- memory with 8-bit entries
-- Internal Bus Interface -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- bus request --
type bus_req_t is record
addr : std_ulogic_vector(31 downto 0); -- access address
data : std_ulogic_vector(31 downto 0); -- write data
ben : std_ulogic_vector(03 downto 0); -- byte enable
stb : std_ulogic; -- request strobe (single-shot)
rw : std_ulogic; -- 0=read, 1=write
src : std_ulogic; -- access source (1=instruction fetch, 0=data access)
priv : std_ulogic; -- set if privileged (machine-mode) access
rvso : std_ulogic; -- set if reservation set operation (atomic LR/SC)
fence : std_ulogic; -- fence(.i) operation, independent of STB
end record;
-- bus response --
type bus_rsp_t is record
data : std_ulogic_vector(31 downto 0); -- read data
ack : std_ulogic; -- access acknowledge (single-shot)
err : std_ulogic; -- access error (single-shot)
end record;
-- source (request) termination --
constant req_terminate_c : bus_req_t := (
addr => (others => '0'),
data => (others => '0'),
ben => (others => '0'),
stb => '0',
rw => '0',
src => '0',
priv => '0',
rvso => '0',
fence => '0'
);
-- endpoint (response) termination --
constant rsp_terminate_c : bus_rsp_t := (
data => (others => '0'),
ack => '0',
err => '0'
);
-- Debug Module Interface -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- request --
type dmi_req_t is record
addr : std_ulogic_vector(06 downto 0);
op : std_ulogic_vector(01 downto 0);
data : std_ulogic_vector(31 downto 0);
end record;
-- request operation --
constant dmi_req_nop_c : std_ulogic_vector(1 downto 0) := "00"; -- no operation
constant dmi_req_rd_c : std_ulogic_vector(1 downto 0) := "01"; -- read access
constant dmi_req_wr_c : std_ulogic_vector(1 downto 0) := "10"; -- write access
-- response --
type dmi_rsp_t is record
data : std_ulogic_vector(31 downto 0);
ack : std_ulogic;
end record;
-- ****************************************************************************************************************************
-- RISC-V ISA Definitions
-- ****************************************************************************************************************************
-- RISC-V 32-Bit Instruction Word Layout --------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant instr_opcode_lsb_c : natural := 0; -- opcode bit 0
constant instr_opcode_msb_c : natural := 6; -- opcode bit 6
constant instr_rd_lsb_c : natural := 7; -- destination register address bit 0
constant instr_rd_msb_c : natural := 11; -- destination register address bit 4
constant instr_funct3_lsb_c : natural := 12; -- funct3 bit 0
constant instr_funct3_msb_c : natural := 14; -- funct3 bit 2
constant instr_rs1_lsb_c : natural := 15; -- source register 1 address bit 0
constant instr_rs1_msb_c : natural := 19; -- source register 1 address bit 4
constant instr_rs2_lsb_c : natural := 20; -- source register 2 address bit 0
constant instr_rs2_msb_c : natural := 24; -- source register 2 address bit 4
constant instr_rs3_lsb_c : natural := 27; -- source register 3 address bit 0
constant instr_rs3_msb_c : natural := 31; -- source register 3 address bit 4
constant instr_funct7_lsb_c : natural := 25; -- funct7 bit 0
constant instr_funct7_msb_c : natural := 31; -- funct7 bit 6
constant instr_funct12_lsb_c : natural := 20; -- funct12 bit 0
constant instr_funct12_msb_c : natural := 31; -- funct12 bit 11
constant instr_imm12_lsb_c : natural := 20; -- immediate12 bit 0
constant instr_imm12_msb_c : natural := 31; -- immediate12 bit 11
constant instr_imm20_lsb_c : natural := 12; -- immediate20 bit 0
constant instr_imm20_msb_c : natural := 31; -- immediate20 bit 21
constant instr_funct5_lsb_c : natural := 27; -- funct5 select bit 0
constant instr_funct5_msb_c : natural := 31; -- funct5 select bit 4
-- RISC-V Opcodes -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- alu --
constant opcode_alui_c : std_ulogic_vector(6 downto 0) := "0010011"; -- ALU operation with immediate
constant opcode_alu_c : std_ulogic_vector(6 downto 0) := "0110011"; -- ALU operation
constant opcode_lui_c : std_ulogic_vector(6 downto 0) := "0110111"; -- load upper immediate
constant opcode_auipc_c : std_ulogic_vector(6 downto 0) := "0010111"; -- add upper immediate to PC
-- control flow --
constant opcode_jal_c : std_ulogic_vector(6 downto 0) := "1101111"; -- jump and link
constant opcode_jalr_c : std_ulogic_vector(6 downto 0) := "1100111"; -- jump and link with register
constant opcode_branch_c : std_ulogic_vector(6 downto 0) := "1100011"; -- branch
-- memory access --
constant opcode_load_c : std_ulogic_vector(6 downto 0) := "0000011"; -- load
constant opcode_store_c : std_ulogic_vector(6 downto 0) := "0100011"; -- store
constant opcode_amo_c : std_ulogic_vector(6 downto 0) := "0101111"; -- atomic memory access
constant opcode_fence_c : std_ulogic_vector(6 downto 0) := "0001111"; -- fence / fence.i
-- system/csr --
constant opcode_system_c : std_ulogic_vector(6 downto 0) := "1110011"; -- system/csr access
-- floating point operations --
constant opcode_fop_c : std_ulogic_vector(6 downto 0) := "1010011"; -- dual/single operand instruction
-- official custom RISC-V opcodes - free for custom instructions --
constant opcode_cust0_c : std_ulogic_vector(6 downto 0) := "0001011"; -- custom-0
constant opcode_cust1_c : std_ulogic_vector(6 downto 0) := "0101011"; -- custom-1
constant opcode_cust2_c : std_ulogic_vector(6 downto 0) := "1011011"; -- custom-2
constant opcode_cust3_c : std_ulogic_vector(6 downto 0) := "1111011"; -- custom-3
-- RISC-V Funct3 --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- control flow --
constant funct3_beq_c : std_ulogic_vector(2 downto 0) := "000"; -- branch if equal
constant funct3_bne_c : std_ulogic_vector(2 downto 0) := "001"; -- branch if not equal
constant funct3_blt_c : std_ulogic_vector(2 downto 0) := "100"; -- branch if less than
constant funct3_bge_c : std_ulogic_vector(2 downto 0) := "101"; -- branch if greater than or equal
constant funct3_bltu_c : std_ulogic_vector(2 downto 0) := "110"; -- branch if less than (unsigned)
constant funct3_bgeu_c : std_ulogic_vector(2 downto 0) := "111"; -- branch if greater than or equal (unsigned)
-- memory access --
constant funct3_lb_c : std_ulogic_vector(2 downto 0) := "000"; -- load byte (signed)
constant funct3_lh_c : std_ulogic_vector(2 downto 0) := "001"; -- load half word (signed)
constant funct3_lw_c : std_ulogic_vector(2 downto 0) := "010"; -- load word (signed)
constant funct3_lbu_c : std_ulogic_vector(2 downto 0) := "100"; -- load byte (unsigned)
constant funct3_lhu_c : std_ulogic_vector(2 downto 0) := "101"; -- load half word (unsigned)
constant funct3_lwu_c : std_ulogic_vector(2 downto 0) := "110"; -- load word (unsigned)
constant funct3_sb_c : std_ulogic_vector(2 downto 0) := "000"; -- store byte
constant funct3_sh_c : std_ulogic_vector(2 downto 0) := "001"; -- store half word
constant funct3_sw_c : std_ulogic_vector(2 downto 0) := "010"; -- store word
-- alu --
constant funct3_subadd_c : std_ulogic_vector(2 downto 0) := "000"; -- sub/add via funct7
constant funct3_sll_c : std_ulogic_vector(2 downto 0) := "001"; -- shift logical left
constant funct3_slt_c : std_ulogic_vector(2 downto 0) := "010"; -- set on less
constant funct3_sltu_c : std_ulogic_vector(2 downto 0) := "011"; -- set on less unsigned
constant funct3_xor_c : std_ulogic_vector(2 downto 0) := "100"; -- xor
constant funct3_sr_c : std_ulogic_vector(2 downto 0) := "101"; -- shift right via funct7
constant funct3_or_c : std_ulogic_vector(2 downto 0) := "110"; -- or
constant funct3_and_c : std_ulogic_vector(2 downto 0) := "111"; -- and
-- system/csr --
constant funct3_env_c : std_ulogic_vector(2 downto 0) := "000"; -- ecall, ebreak, mret, wfi, ...
constant funct3_csrrw_c : std_ulogic_vector(2 downto 0) := "001"; -- csr r/w
constant funct3_csrrs_c : std_ulogic_vector(2 downto 0) := "010"; -- csr read & set
constant funct3_csrrc_c : std_ulogic_vector(2 downto 0) := "011"; -- csr read & clear
constant funct3_csril_c : std_ulogic_vector(2 downto 0) := "100"; -- undefined/illegal csr command
constant funct3_csrrwi_c : std_ulogic_vector(2 downto 0) := "101"; -- csr r/w immediate
constant funct3_csrrsi_c : std_ulogic_vector(2 downto 0) := "110"; -- csr read & set immediate
constant funct3_csrrci_c : std_ulogic_vector(2 downto 0) := "111"; -- csr read & clear immediate
-- fence --
constant funct3_fence_c : std_ulogic_vector(2 downto 0) := "000"; -- fence - order IO/memory access
constant funct3_fencei_c : std_ulogic_vector(2 downto 0) := "001"; -- fence.i - instruction stream sync
-- RISC-V Funct12 - SYSTEM ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant funct12_ecall_c : std_ulogic_vector(11 downto 0) := x"000"; -- ecall
constant funct12_ebreak_c : std_ulogic_vector(11 downto 0) := x"001"; -- ebreak
constant funct12_wfi_c : std_ulogic_vector(11 downto 0) := x"105"; -- wfi
constant funct12_mret_c : std_ulogic_vector(11 downto 0) := x"302"; -- mret
constant funct12_dret_c : std_ulogic_vector(11 downto 0) := x"7b2"; -- dret
-- RISC-V Floating-Point Stuff ------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant float_single_c : std_ulogic_vector(1 downto 0) := "00"; -- single-precision (32-bit)
--constant float_double_c : std_ulogic_vector(1 downto 0) := "01"; -- double-precision (64-bit)
--constant float_half_c : std_ulogic_vector(1 downto 0) := "10"; -- half-precision (16-bit)
--constant float_quad_c : std_ulogic_vector(1 downto 0) := "11"; -- quad-precision (128-bit)
-- number class flags --
constant fp_class_neg_inf_c : natural := 0; -- negative infinity
constant fp_class_neg_norm_c : natural := 1; -- negative normal number
constant fp_class_neg_denorm_c : natural := 2; -- negative subnormal number
constant fp_class_neg_zero_c : natural := 3; -- negative zero
constant fp_class_pos_zero_c : natural := 4; -- positive zero
constant fp_class_pos_denorm_c : natural := 5; -- positive subnormal number
constant fp_class_pos_norm_c : natural := 6; -- positive normal number
constant fp_class_pos_inf_c : natural := 7; -- positive infinity
constant fp_class_snan_c : natural := 8; -- signaling NaN (sNaN)
constant fp_class_qnan_c : natural := 9; -- quiet NaN (qNaN)
-- exception flags --
constant fp_exc_nx_c : natural := 0; -- inexact
constant fp_exc_uf_c : natural := 1; -- underflow
constant fp_exc_of_c : natural := 2; -- overflow
constant fp_exc_dz_c : natural := 3; -- division by zero
constant fp_exc_nv_c : natural := 4; -- invalid operation
-- special values (single-precision) --
constant fp_single_qnan_c : std_ulogic_vector(31 downto 0) := x"7fc00000"; -- quiet NaN
constant fp_single_snan_c : std_ulogic_vector(31 downto 0) := x"7fa00000"; -- signaling NaN
constant fp_single_pos_max_c : std_ulogic_vector(31 downto 0) := x"7f7FFFFF"; -- positive max
constant fp_single_neg_max_c : std_ulogic_vector(31 downto 0) := x"Ff7FFFFF"; -- negative max
constant fp_single_pos_inf_c : std_ulogic_vector(31 downto 0) := x"7f800000"; -- positive infinity
constant fp_single_neg_inf_c : std_ulogic_vector(31 downto 0) := x"ff800000"; -- negative infinity
constant fp_single_pos_zero_c : std_ulogic_vector(31 downto 0) := x"00000000"; -- positive zero
constant fp_single_neg_zero_c : std_ulogic_vector(31 downto 0) := x"80000000"; -- negative zero
-- RISC-V CSRs ----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- user floating-point CSRs --
constant csr_fflags_c : std_ulogic_vector(11 downto 0) := x"001";
constant csr_frm_c : std_ulogic_vector(11 downto 0) := x"002";
constant csr_fcsr_c : std_ulogic_vector(11 downto 0) := x"003";
-- machine trap setup --
constant csr_mstatus_c : std_ulogic_vector(11 downto 0) := x"300";
constant csr_misa_c : std_ulogic_vector(11 downto 0) := x"301";
constant csr_mie_c : std_ulogic_vector(11 downto 0) := x"304";
constant csr_mtvec_c : std_ulogic_vector(11 downto 0) := x"305";
constant csr_mcounteren_c : std_ulogic_vector(11 downto 0) := x"306";
constant csr_mstatush_c : std_ulogic_vector(11 downto 0) := x"310";
-- machine configuration --
constant csr_menvcfg_c : std_ulogic_vector(11 downto 0) := x"30a";
constant csr_menvcfgh_c : std_ulogic_vector(11 downto 0) := x"31a";
-- machine counter setup --
constant csr_mcountinhibit_c : std_ulogic_vector(11 downto 0) := x"320";
constant csr_mhpmevent3_c : std_ulogic_vector(11 downto 0) := x"323";
constant csr_mhpmevent4_c : std_ulogic_vector(11 downto 0) := x"324";
constant csr_mhpmevent5_c : std_ulogic_vector(11 downto 0) := x"325";
constant csr_mhpmevent6_c : std_ulogic_vector(11 downto 0) := x"326";
constant csr_mhpmevent7_c : std_ulogic_vector(11 downto 0) := x"327";
constant csr_mhpmevent8_c : std_ulogic_vector(11 downto 0) := x"328";
constant csr_mhpmevent9_c : std_ulogic_vector(11 downto 0) := x"329";
constant csr_mhpmevent10_c : std_ulogic_vector(11 downto 0) := x"32a";
constant csr_mhpmevent11_c : std_ulogic_vector(11 downto 0) := x"32b";
constant csr_mhpmevent12_c : std_ulogic_vector(11 downto 0) := x"32c";
constant csr_mhpmevent13_c : std_ulogic_vector(11 downto 0) := x"32d";
constant csr_mhpmevent14_c : std_ulogic_vector(11 downto 0) := x"32e";
constant csr_mhpmevent15_c : std_ulogic_vector(11 downto 0) := x"32f";
-- machine trap handling --
constant csr_mscratch_c : std_ulogic_vector(11 downto 0) := x"340";
constant csr_mepc_c : std_ulogic_vector(11 downto 0) := x"341";
constant csr_mcause_c : std_ulogic_vector(11 downto 0) := x"342";
constant csr_mtval_c : std_ulogic_vector(11 downto 0) := x"343";
constant csr_mip_c : std_ulogic_vector(11 downto 0) := x"344";
constant csr_mtinst_c : std_ulogic_vector(11 downto 0) := x"34a";
-- physical memory protection - configuration --
constant csr_pmpcfg0_c : std_ulogic_vector(11 downto 0) := x"3a0";
constant csr_pmpcfg1_c : std_ulogic_vector(11 downto 0) := x"3a1";
constant csr_pmpcfg2_c : std_ulogic_vector(11 downto 0) := x"3a2";
constant csr_pmpcfg3_c : std_ulogic_vector(11 downto 0) := x"3a3";
-- physical memory protection - address --
constant csr_pmpaddr0_c : std_ulogic_vector(11 downto 0) := x"3b0";
constant csr_pmpaddr1_c : std_ulogic_vector(11 downto 0) := x"3b1";
constant csr_pmpaddr2_c : std_ulogic_vector(11 downto 0) := x"3b2";
constant csr_pmpaddr3_c : std_ulogic_vector(11 downto 0) := x"3b3";
constant csr_pmpaddr4_c : std_ulogic_vector(11 downto 0) := x"3b4";
constant csr_pmpaddr5_c : std_ulogic_vector(11 downto 0) := x"3b5";
constant csr_pmpaddr6_c : std_ulogic_vector(11 downto 0) := x"3b6";
constant csr_pmpaddr7_c : std_ulogic_vector(11 downto 0) := x"3b7";
constant csr_pmpaddr8_c : std_ulogic_vector(11 downto 0) := x"3b8";
constant csr_pmpaddr9_c : std_ulogic_vector(11 downto 0) := x"3b9";
constant csr_pmpaddr10_c : std_ulogic_vector(11 downto 0) := x"3ba";
constant csr_pmpaddr11_c : std_ulogic_vector(11 downto 0) := x"3bb";
constant csr_pmpaddr12_c : std_ulogic_vector(11 downto 0) := x"3bc";
constant csr_pmpaddr13_c : std_ulogic_vector(11 downto 0) := x"3bd";
constant csr_pmpaddr14_c : std_ulogic_vector(11 downto 0) := x"3be";
constant csr_pmpaddr15_c : std_ulogic_vector(11 downto 0) := x"3bf";
-- trigger module registers --
constant csr_tselect_c : std_ulogic_vector(11 downto 0) := x"7a0";
constant csr_tdata1_c : std_ulogic_vector(11 downto 0) := x"7a1";
constant csr_tdata2_c : std_ulogic_vector(11 downto 0) := x"7a2";
constant csr_tinfo_c : std_ulogic_vector(11 downto 0) := x"7a4";
-- debug mode registers --
constant csr_dcsr_c : std_ulogic_vector(11 downto 0) := x"7b0";
constant csr_dpc_c : std_ulogic_vector(11 downto 0) := x"7b1";
constant csr_dscratch0_c : std_ulogic_vector(11 downto 0) := x"7b2";
-- NEORV32-specific user-mode registers --
constant csr_cfureg0_c : std_ulogic_vector(11 downto 0) := x"800";
constant csr_cfureg1_c : std_ulogic_vector(11 downto 0) := x"801";
constant csr_cfureg2_c : std_ulogic_vector(11 downto 0) := x"802";
constant csr_cfureg3_c : std_ulogic_vector(11 downto 0) := x"803";
-- machine counters/timers --
constant csr_mcycle_c : std_ulogic_vector(11 downto 0) := x"b00";
--constant csr_mtime_c : std_ulogic_vector(11 downto 0) := x"b01";
constant csr_minstret_c : std_ulogic_vector(11 downto 0) := x"b02";
constant csr_mhpmcounter3_c : std_ulogic_vector(11 downto 0) := x"b03";
constant csr_mhpmcounter4_c : std_ulogic_vector(11 downto 0) := x"b04";
constant csr_mhpmcounter5_c : std_ulogic_vector(11 downto 0) := x"b05";
constant csr_mhpmcounter6_c : std_ulogic_vector(11 downto 0) := x"b06";
constant csr_mhpmcounter7_c : std_ulogic_vector(11 downto 0) := x"b07";
constant csr_mhpmcounter8_c : std_ulogic_vector(11 downto 0) := x"b08";
constant csr_mhpmcounter9_c : std_ulogic_vector(11 downto 0) := x"b09";
constant csr_mhpmcounter10_c : std_ulogic_vector(11 downto 0) := x"b0a";
constant csr_mhpmcounter11_c : std_ulogic_vector(11 downto 0) := x"b0b";
constant csr_mhpmcounter12_c : std_ulogic_vector(11 downto 0) := x"b0c";
constant csr_mhpmcounter13_c : std_ulogic_vector(11 downto 0) := x"b0d";
constant csr_mhpmcounter14_c : std_ulogic_vector(11 downto 0) := x"b0e";
constant csr_mhpmcounter15_c : std_ulogic_vector(11 downto 0) := x"b0f";
--
constant csr_mcycleh_c : std_ulogic_vector(11 downto 0) := x"b80";
--constant csr_mtimeh_c : std_ulogic_vector(11 downto 0) := x"b81";
constant csr_minstreth_c : std_ulogic_vector(11 downto 0) := x"b82";
constant csr_mhpmcounter3h_c : std_ulogic_vector(11 downto 0) := x"b83";
constant csr_mhpmcounter4h_c : std_ulogic_vector(11 downto 0) := x"b84";
constant csr_mhpmcounter5h_c : std_ulogic_vector(11 downto 0) := x"b85";
constant csr_mhpmcounter6h_c : std_ulogic_vector(11 downto 0) := x"b86";
constant csr_mhpmcounter7h_c : std_ulogic_vector(11 downto 0) := x"b87";
constant csr_mhpmcounter8h_c : std_ulogic_vector(11 downto 0) := x"b88";
constant csr_mhpmcounter9h_c : std_ulogic_vector(11 downto 0) := x"b89";
constant csr_mhpmcounter10h_c : std_ulogic_vector(11 downto 0) := x"b8a";
constant csr_mhpmcounter11h_c : std_ulogic_vector(11 downto 0) := x"b8b";
constant csr_mhpmcounter12h_c : std_ulogic_vector(11 downto 0) := x"b8c";
constant csr_mhpmcounter13h_c : std_ulogic_vector(11 downto 0) := x"b8d";
constant csr_mhpmcounter14h_c : std_ulogic_vector(11 downto 0) := x"b8e";
constant csr_mhpmcounter15h_c : std_ulogic_vector(11 downto 0) := x"b8f";
-- user counters/timers --
constant csr_cycle_c : std_ulogic_vector(11 downto 0) := x"c00";
--constant csr_time_c : std_ulogic_vector(11 downto 0) := x"c01";
constant csr_instret_c : std_ulogic_vector(11 downto 0) := x"c02";
constant csr_hpmcounter3_c : std_ulogic_vector(11 downto 0) := x"c03";
constant csr_hpmcounter4_c : std_ulogic_vector(11 downto 0) := x"c04";
constant csr_hpmcounter5_c : std_ulogic_vector(11 downto 0) := x"c05";
constant csr_hpmcounter6_c : std_ulogic_vector(11 downto 0) := x"c06";
constant csr_hpmcounter7_c : std_ulogic_vector(11 downto 0) := x"c07";
constant csr_hpmcounter8_c : std_ulogic_vector(11 downto 0) := x"c08";
constant csr_hpmcounter9_c : std_ulogic_vector(11 downto 0) := x"c09";
constant csr_hpmcounter10_c : std_ulogic_vector(11 downto 0) := x"c0a";
constant csr_hpmcounter11_c : std_ulogic_vector(11 downto 0) := x"c0b";
constant csr_hpmcounter12_c : std_ulogic_vector(11 downto 0) := x"c0c";
constant csr_hpmcounter13_c : std_ulogic_vector(11 downto 0) := x"c0d";
constant csr_hpmcounter14_c : std_ulogic_vector(11 downto 0) := x"c0e";
constant csr_hpmcounter15_c : std_ulogic_vector(11 downto 0) := x"c0f";
--
constant csr_cycleh_c : std_ulogic_vector(11 downto 0) := x"c80";
--constant csr_timeh_c : std_ulogic_vector(11 downto 0) := x"c81";
constant csr_instreth_c : std_ulogic_vector(11 downto 0) := x"c82";
constant csr_hpmcounter3h_c : std_ulogic_vector(11 downto 0) := x"c83";
constant csr_hpmcounter4h_c : std_ulogic_vector(11 downto 0) := x"c84";
constant csr_hpmcounter5h_c : std_ulogic_vector(11 downto 0) := x"c85";
constant csr_hpmcounter6h_c : std_ulogic_vector(11 downto 0) := x"c86";
constant csr_hpmcounter7h_c : std_ulogic_vector(11 downto 0) := x"c87";
constant csr_hpmcounter8h_c : std_ulogic_vector(11 downto 0) := x"c88";
constant csr_hpmcounter9h_c : std_ulogic_vector(11 downto 0) := x"c89";
constant csr_hpmcounter10h_c : std_ulogic_vector(11 downto 0) := x"c8a";
constant csr_hpmcounter11h_c : std_ulogic_vector(11 downto 0) := x"c8b";
constant csr_hpmcounter12h_c : std_ulogic_vector(11 downto 0) := x"c8c";
constant csr_hpmcounter13h_c : std_ulogic_vector(11 downto 0) := x"c8d";
constant csr_hpmcounter14h_c : std_ulogic_vector(11 downto 0) := x"c8e";
constant csr_hpmcounter15h_c : std_ulogic_vector(11 downto 0) := x"c8f";
-- machine information registers --
constant csr_mvendorid_c : std_ulogic_vector(11 downto 0) := x"f11";
constant csr_marchid_c : std_ulogic_vector(11 downto 0) := x"f12";
constant csr_mimpid_c : std_ulogic_vector(11 downto 0) := x"f13";
constant csr_mhartid_c : std_ulogic_vector(11 downto 0) := x"f14";
constant csr_mconfigptr_c : std_ulogic_vector(11 downto 0) := x"f15";
-- NEORV32-specific machine-mode registers --
constant csr_mxisa_c : std_ulogic_vector(11 downto 0) := x"fc0";
-- ****************************************************************************************************************************
-- CPU Control
-- ****************************************************************************************************************************
-- Main CPU Control Bus -------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
type ctrl_bus_t is record
-- register file --
rf_wb_en : std_ulogic; -- write back enable
rf_rs1 : std_ulogic_vector(04 downto 0); -- source register 1 address
rf_rs2 : std_ulogic_vector(04 downto 0); -- source register 2 address
rf_rs3 : std_ulogic_vector(04 downto 0); -- source register 3 address
rf_rd : std_ulogic_vector(04 downto 0); -- destination register address
rf_mux : std_ulogic_vector(01 downto 0); -- input source select
rf_zero_we : std_ulogic; -- allow/force write access to x0
-- alu --
alu_op : std_ulogic_vector(02 downto 0); -- ALU operation select
alu_opa_mux : std_ulogic; -- operand A select (0=rs1, 1=PC)
alu_opb_mux : std_ulogic; -- operand B select (0=rs2, 1=IMM)
alu_unsigned : std_ulogic; -- is unsigned ALU operation
alu_cp_trig : std_ulogic_vector(05 downto 0); -- co-processor trigger (one-hot)
-- load/store unit --
lsu_req : std_ulogic; -- trigger memory access request
lsu_rw : std_ulogic; -- 0: read access, 1: write access
lsu_mo_we : std_ulogic; -- memory address and data output register write enable
lsu_fence : std_ulogic; -- fence(.i) operation
lsu_priv : std_ulogic; -- effective privilege level for load/store
-- instruction word --
ir_funct3 : std_ulogic_vector(02 downto 0); -- funct3 bit field
ir_funct12 : std_ulogic_vector(11 downto 0); -- funct12 bit field
ir_opcode : std_ulogic_vector(06 downto 0); -- opcode bit field
-- cpu status --
cpu_priv : std_ulogic; -- effective privilege mode
cpu_sleep : std_ulogic; -- set when CPU is in sleep mode
cpu_trap : std_ulogic; -- set when CPU is entering trap exec
cpu_debug : std_ulogic; -- set when CPU is in debug mode
end record;
-- control bus reset initializer --
constant ctrl_bus_zero_c : ctrl_bus_t := (
rf_wb_en => '0',
rf_rs1 => (others => '0'),
rf_rs2 => (others => '0'),
rf_rs3 => (others => '0'),
rf_rd => (others => '0'),
rf_mux => (others => '0'),
rf_zero_we => '0',
alu_op => (others => '0'),
alu_opa_mux => '0',
alu_opb_mux => '0',
alu_unsigned => '0',
alu_cp_trig => (others => '0'),
lsu_req => '0',
lsu_rw => '0',
lsu_mo_we => '0',
lsu_fence => '0',
lsu_priv => '0',
ir_funct3 => (others => '0'),
ir_funct12 => (others => '0'),
ir_opcode => (others => '0'),
cpu_priv => '0',
cpu_sleep => '0',
cpu_trap => '0',
cpu_debug => '0'
);
-- Comparator Bus -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant cmp_equal_c : natural := 0;
constant cmp_less_c : natural := 1; -- for signed and unsigned comparisons
-- CPU Co-Processor IDs -------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant cp_sel_shifter_c : natural := 0; -- CP0: shift operations (base ISA)
constant cp_sel_muldiv_c : natural := 1; -- CP1: multiplication/division operations ('M' extensions)
constant cp_sel_bitmanip_c : natural := 2; -- CP2: bit manipulation ('B' extensions)
constant cp_sel_fpu_c : natural := 3; -- CP3: floating-point unit ('Zfinx' extension)
constant cp_sel_cfu_c : natural := 4; -- CP4: custom instructions CFU ('Zxcfu' extension)
constant cp_sel_cond_c : natural := 5; -- CP5: conditional operations ('Zicond' extension)
-- ALU Function Codes [DO NOT CHANGE ENCODING!] -------------------------------------------
-- -------------------------------------------------------------------------------------------
constant alu_op_add_c : std_ulogic_vector(2 downto 0) := "000"; -- result <= A + B
constant alu_op_sub_c : std_ulogic_vector(2 downto 0) := "001"; -- result <= A - B
constant alu_op_cp_c : std_ulogic_vector(2 downto 0) := "010"; -- result <= ALU co-processor
constant alu_op_slt_c : std_ulogic_vector(2 downto 0) := "011"; -- result <= A < B
constant alu_op_movb_c : std_ulogic_vector(2 downto 0) := "100"; -- result <= B
constant alu_op_xor_c : std_ulogic_vector(2 downto 0) := "101"; -- result <= A xor B
constant alu_op_or_c : std_ulogic_vector(2 downto 0) := "110"; -- result <= A or B
constant alu_op_and_c : std_ulogic_vector(2 downto 0) := "111"; -- result <= A and B
-- Register File Input Select -------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant rf_mux_alu_c : std_ulogic_vector(1 downto 0) := "00"; -- register file <= alu result
constant rf_mux_mem_c : std_ulogic_vector(1 downto 0) := "01"; -- register file <= memory read data
constant rf_mux_csr_c : std_ulogic_vector(1 downto 0) := "10"; -- register file <= CSR read data
constant rf_mux_ret_c : std_ulogic_vector(1 downto 0) := "11"; -- register file <= link-PC (return address)
-- Trap ID Codes --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- MSB: 1 = interrupt, 0 = sync. exception
-- MSB-1: 1 = entry to debug mode, 0 = normal trapping
-- RISC-V compliant synchronous exceptions --
constant trap_ima_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "00000"; -- 0: instruction misaligned
constant trap_iaf_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "00001"; -- 1: instruction access fault
constant trap_iil_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "00010"; -- 2: illegal instruction
constant trap_brk_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "00011"; -- 3: environment breakpoint
constant trap_lma_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "00100"; -- 4: load address misaligned
constant trap_laf_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "00101"; -- 5: load access fault
constant trap_sma_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "00110"; -- 6: store address misaligned
constant trap_saf_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "00111"; -- 7: store access fault
constant trap_env_c : std_ulogic_vector(6 downto 0) := "0" & "0" & "010UU"; -- 8..11: environment call from u/s/h/m
-- RISC-V compliant asynchronous exceptions (interrupts) --
constant trap_msi_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "00011"; -- 3: machine software interrupt
constant trap_mti_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "00111"; -- 7: machine timer interrupt
constant trap_mei_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "01011"; -- 11: machine external interrupt
-- NEORV32-specific (RISC-V custom) asynchronous exceptions (interrupts) --
constant trap_firq0_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "10000"; -- 16: fast interrupt 0
constant trap_firq1_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "10001"; -- 17: fast interrupt 1
constant trap_firq2_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "10010"; -- 18: fast interrupt 2
constant trap_firq3_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "10011"; -- 19: fast interrupt 3
constant trap_firq4_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "10100"; -- 20: fast interrupt 4
constant trap_firq5_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "10101"; -- 21: fast interrupt 5
constant trap_firq6_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "10110"; -- 22: fast interrupt 6
constant trap_firq7_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "10111"; -- 23: fast interrupt 7
constant trap_firq8_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "11000"; -- 24: fast interrupt 8
constant trap_firq9_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "11001"; -- 25: fast interrupt 9
constant trap_firq10_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "11010"; -- 26: fast interrupt 10
constant trap_firq11_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "11011"; -- 27: fast interrupt 11
constant trap_firq12_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "11100"; -- 28: fast interrupt 12
constant trap_firq13_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "11101"; -- 29: fast interrupt 13
constant trap_firq14_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "11110"; -- 30: fast interrupt 14
constant trap_firq15_c : std_ulogic_vector(6 downto 0) := "1" & "0" & "11111"; -- 31: fast interrupt 15
-- entering debug mode (sync./async. exceptions) --
constant trap_db_break_c : std_ulogic_vector(6 downto 0) := "0" & "1" & "00001"; -- 1: break instruction (sync)
constant trap_db_trig_c : std_ulogic_vector(6 downto 0) := "0" & "1" & "00010"; -- 2: hardware trigger (sync)
constant trap_db_halt_c : std_ulogic_vector(6 downto 0) := "1" & "1" & "00011"; -- 3: external halt request (async)
constant trap_db_step_c : std_ulogic_vector(6 downto 0) := "1" & "1" & "00100"; -- 4: single-stepping (async)
-- Trap System ----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- exception source bits --
constant exc_iaccess_c : natural := 0; -- instruction access fault
constant exc_illegal_c : natural := 1; -- illegal instruction
constant exc_ialign_c : natural := 2; -- instruction address misaligned
constant exc_ecall_c : natural := 3; -- environment call
constant exc_ebreak_c : natural := 4; -- breakpoint
constant exc_salign_c : natural := 5; -- store address misaligned
constant exc_lalign_c : natural := 6; -- load address misaligned
constant exc_saccess_c : natural := 7; -- store access fault
constant exc_laccess_c : natural := 8; -- load access fault
constant exc_db_break_c : natural := 9; -- enter debug mode via ebreak instruction
constant exc_db_hw_c : natural := 10; -- enter debug mode via hw trigger
--
constant exc_width_c : natural := 11; -- length of this list in bits
-- interrupt source bits --
constant irq_msi_irq_c : natural := 0; -- machine software interrupt
constant irq_mti_irq_c : natural := 1; -- machine timer interrupt
constant irq_mei_irq_c : natural := 2; -- machine external interrupt
constant irq_firq_0_c : natural := 3; -- fast interrupt channel 0
constant irq_firq_1_c : natural := 4; -- fast interrupt channel 1
constant irq_firq_2_c : natural := 5; -- fast interrupt channel 2
constant irq_firq_3_c : natural := 6; -- fast interrupt channel 3
constant irq_firq_4_c : natural := 7; -- fast interrupt channel 4
constant irq_firq_5_c : natural := 8; -- fast interrupt channel 5
constant irq_firq_6_c : natural := 9; -- fast interrupt channel 6
constant irq_firq_7_c : natural := 10; -- fast interrupt channel 7
constant irq_firq_8_c : natural := 11; -- fast interrupt channel 8
constant irq_firq_9_c : natural := 12; -- fast interrupt channel 9
constant irq_firq_10_c : natural := 13; -- fast interrupt channel 10
constant irq_firq_11_c : natural := 14; -- fast interrupt channel 11
constant irq_firq_12_c : natural := 15; -- fast interrupt channel 12
constant irq_firq_13_c : natural := 16; -- fast interrupt channel 13
constant irq_firq_14_c : natural := 17; -- fast interrupt channel 14
constant irq_firq_15_c : natural := 18; -- fast interrupt channel 15
constant irq_db_halt_c : natural := 19; -- enter debug mode via external halt request
constant irq_db_step_c : natural := 20; -- enter debug mode via single-stepping
--
constant irq_width_c : natural := 21; -- length of this list in bits
-- Privilege Modes ------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant priv_mode_m_c : std_ulogic := '1'; -- machine mode
constant priv_mode_u_c : std_ulogic := '0'; -- user mode
-- HPM Events -----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- RISC-V-compliant --
constant hpmcnt_event_cy_c : natural := 0; -- active cycle
constant hpmcnt_event_tm_c : natural := 1; -- time (unused/reserved)
constant hpmcnt_event_ir_c : natural := 2; -- retired instruction
-- NEORV32-specific --
constant hpmcnt_event_compr_c : natural := 3; -- executed compressed instruction
constant hpmcnt_event_wait_dis_c : natural := 4; -- instruction dispatch wait cycle
constant hpmcnt_event_wait_alu_c : natural := 5; -- multi-cycle ALU co-processor wait cycle
constant hpmcnt_event_branch_c : natural := 6; -- executed branch instruction
constant hpmcnt_event_branched_c : natural := 7; -- control flow transfer
constant hpmcnt_event_load_c : natural := 8; -- load operation
constant hpmcnt_event_store_c : natural := 9; -- store operation
constant hpmcnt_event_wait_lsu_c : natural := 10; -- load-store unit memory wait cycle
constant hpmcnt_event_trap_c : natural := 11; -- entered trap
--
constant hpmcnt_event_size_c : natural := 12; -- length of this list
-- ****************************************************************************************************************************
-- Helper Functions
-- ****************************************************************************************************************************
function index_size_f(input : natural) return natural;
function cond_sel_int_f(cond : boolean; val_t : integer; val_f : integer) return integer;
function cond_sel_natural_f(cond : boolean; val_t : natural; val_f : natural) return natural;
function cond_sel_suv_f(cond : boolean; val_t : std_ulogic_vector; val_f : std_ulogic_vector) return std_ulogic_vector;
function cond_sel_string_f(cond : boolean; val_t : string; val_f : string) return string;
function bool_to_ulogic_f(cond : boolean) return std_ulogic;
function bin_to_gray_f(input : std_ulogic_vector) return std_ulogic_vector;
function gray_to_bin_f(input : std_ulogic_vector) return std_ulogic_vector;
function or_reduce_f(input : std_ulogic_vector) return std_ulogic;
function and_reduce_f(input : std_ulogic_vector) return std_ulogic;
function xor_reduce_f(input : std_ulogic_vector) return std_ulogic;
function su_undefined_f(input : std_ulogic) return boolean;
function to_hexchar_f(input : std_ulogic_vector(3 downto 0)) return character;
function to_hstring32_f(input : std_ulogic_vector(31 downto 0)) return string;
function bit_rev_f(input : std_ulogic_vector) return std_ulogic_vector;
function is_power_of_two_f(input : natural) return boolean;
function bswap32_f(input : std_ulogic_vector) return std_ulogic_vector;
function popcount_f(input : std_ulogic_vector) return natural;
function leading_zeros_f(input : std_ulogic_vector) return natural;
impure function mem32_init_f(init : mem32_t; depth : natural) return mem32_t;
-- ****************************************************************************************************************************
-- NEORV32 Processor Top Entity (component prototype)
-- ****************************************************************************************************************************
component neorv32_top
generic (
-- General --
CLOCK_FREQUENCY : natural;
CLOCK_GATING_EN : boolean := false;
HART_ID : std_ulogic_vector(31 downto 0) := x"00000000";
VENDOR_ID : std_ulogic_vector(31 downto 0) := x"00000000";
INT_BOOTLOADER_EN : boolean := false;
-- On-Chip Debugger (OCD) --
ON_CHIP_DEBUGGER_EN : boolean := false;
DM_LEGACY_MODE : boolean := false;
-- RISC-V CPU Extensions --
CPU_EXTENSION_RISCV_A : boolean := false;
CPU_EXTENSION_RISCV_B : boolean := false;
CPU_EXTENSION_RISCV_C : boolean := false;
CPU_EXTENSION_RISCV_E : boolean := false;
CPU_EXTENSION_RISCV_M : boolean := false;
CPU_EXTENSION_RISCV_U : boolean := false;
CPU_EXTENSION_RISCV_Zfinx : boolean := false;
CPU_EXTENSION_RISCV_Zicntr : boolean := true;
CPU_EXTENSION_RISCV_Zicond : boolean := false;
CPU_EXTENSION_RISCV_Zihpm : boolean := false;
CPU_EXTENSION_RISCV_Zmmul : boolean := false;
CPU_EXTENSION_RISCV_Zxcfu : boolean := false;
-- Tuning Options --
FAST_MUL_EN : boolean := false;
FAST_SHIFT_EN : boolean := false;
REGFILE_HW_RST : boolean := false;
-- Physical Memory Protection (PMP) --
PMP_NUM_REGIONS : natural range 0 to 16 := 0;
PMP_MIN_GRANULARITY : natural := 4;
PMP_TOR_MODE_EN : boolean := true;
PMP_NAP_MODE_EN : boolean := true;
-- Hardware Performance Monitors (HPM) --
HPM_NUM_CNTS : natural range 0 to 13 := 0;
HPM_CNT_WIDTH : natural range 0 to 64 := 40;
-- Atomic Memory Access - Reservation Set Granularity --
AMO_RVS_GRANULARITY : natural := 4;
-- Internal Instruction memory (IMEM) --
MEM_INT_IMEM_EN : boolean := false;
MEM_INT_IMEM_SIZE : natural := 16*1024;
-- Internal Data memory (DMEM) --
MEM_INT_DMEM_EN : boolean := false;
MEM_INT_DMEM_SIZE : natural := 8*1024;
-- Internal Instruction Cache (iCACHE) --
ICACHE_EN : boolean := false;
ICACHE_NUM_BLOCKS : natural range 1 to 256 := 4;
ICACHE_BLOCK_SIZE : natural range 4 to 2**16 := 64;
ICACHE_ASSOCIATIVITY : natural range 1 to 2 := 1;
-- Internal Data Cache (dCACHE) --
DCACHE_EN : boolean := false;
DCACHE_NUM_BLOCKS : natural range 1 to 256 := 4;
DCACHE_BLOCK_SIZE : natural range 4 to 2**16 := 64;
-- External memory interface (WISHBONE) --
MEM_EXT_EN : boolean := false;
MEM_EXT_TIMEOUT : natural := 255;
MEM_EXT_PIPE_MODE : boolean := false;
MEM_EXT_BIG_ENDIAN : boolean := false;
MEM_EXT_ASYNC_RX : boolean := false;
MEM_EXT_ASYNC_TX : boolean := false;
-- Execute in-place module (XIP) --
XIP_EN : boolean := false;
XIP_CACHE_EN : boolean := false;
XIP_CACHE_NUM_BLOCKS : natural range 1 to 256 := 8;
XIP_CACHE_BLOCK_SIZE : natural range 1 to 2**16 := 256;
-- External Interrupts Controller (XIRQ) --
XIRQ_NUM_CH : natural range 0 to 32 := 0;
XIRQ_TRIGGER_TYPE : std_ulogic_vector(31 downto 0) := x"ffffffff";
XIRQ_TRIGGER_POLARITY : std_ulogic_vector(31 downto 0) := x"ffffffff";
-- Processor peripherals --
IO_GPIO_NUM : natural range 0 to 64 := 0;
IO_MTIME_EN : boolean := false;
IO_UART0_EN : boolean := false;
IO_UART0_RX_FIFO : natural range 1 to 2**15 := 1;
IO_UART0_TX_FIFO : natural range 1 to 2**15 := 1;
IO_UART1_EN : boolean := false;
IO_UART1_RX_FIFO : natural range 1 to 2**15 := 1;
IO_UART1_TX_FIFO : natural range 1 to 2**15 := 1;
IO_SPI_EN : boolean := false;
IO_SPI_FIFO : natural range 1 to 2**15 := 1;
IO_SDI_EN : boolean := false;
IO_SDI_FIFO : natural range 1 to 2**15 := 1;
IO_TWI_EN : boolean := false;
IO_PWM_NUM_CH : natural range 0 to 12 := 0;
IO_WDT_EN : boolean := false;
IO_TRNG_EN : boolean := false;
IO_TRNG_FIFO : natural range 1 to 2**15 := 1;
IO_CFS_EN : boolean := false;
IO_CFS_CONFIG : std_ulogic_vector(31 downto 0) := x"00000000";
IO_CFS_IN_SIZE : natural := 32;
IO_CFS_OUT_SIZE : natural := 32;
IO_NEOLED_EN : boolean := false;
IO_NEOLED_TX_FIFO : natural range 1 to 2**15 := 1;
IO_GPTMR_EN : boolean := false;
IO_ONEWIRE_EN : boolean := false;
IO_DMA_EN : boolean := false;
IO_SLINK_EN : boolean := false;
IO_SLINK_RX_FIFO : natural range 1 to 2**15 := 1;
IO_SLINK_TX_FIFO : natural range 1 to 2**15 := 1;
IO_CRC_EN : boolean := false
);
port (
-- Global control --
clk_i : in std_ulogic;
rstn_i : in std_ulogic;
-- JTAG on-chip debugger interface --
jtag_trst_i : in std_ulogic := 'H';
jtag_tck_i : in std_ulogic := 'L';
jtag_tdi_i : in std_ulogic := 'L';
jtag_tdo_o : out std_ulogic;
jtag_tms_i : in std_ulogic := 'L';
-- Wishbone bus interface (available if MEM_EXT_EN = true) --
wb_tag_o : out std_ulogic_vector(02 downto 0);
wb_adr_o : out std_ulogic_vector(31 downto 0);
wb_dat_i : in std_ulogic_vector(31 downto 0) := (others => 'L');
wb_dat_o : out std_ulogic_vector(31 downto 0);
wb_we_o : out std_ulogic;
wb_sel_o : out std_ulogic_vector(03 downto 0);
wb_stb_o : out std_ulogic;
wb_cyc_o : out std_ulogic;
wb_ack_i : in std_ulogic := 'L';
wb_err_i : in std_ulogic := 'L';
-- Stream Link Interface (available if IO_SLINK_EN = true) --
slink_rx_dat_i : in std_ulogic_vector(31 downto 0) := (others => 'L');
slink_rx_val_i : in std_ulogic := 'L';
slink_rx_lst_i : in std_ulogic := 'L';
slink_rx_rdy_o : out std_ulogic;
slink_tx_dat_o : out std_ulogic_vector(31 downto 0);
slink_tx_val_o : out std_ulogic;
slink_tx_lst_o : out std_ulogic;
slink_tx_rdy_i : in std_ulogic := 'L';
-- XIP (execute in-place via SPI) signals (available if XIP_EN = true) --
xip_csn_o : out std_ulogic;
xip_clk_o : out std_ulogic;
xip_dat_i : in std_ulogic := 'L';
xip_dat_o : out std_ulogic;
-- GPIO (available if IO_GPIO_NUM > 0) --
gpio_o : out std_ulogic_vector(63 downto 0);
gpio_i : in std_ulogic_vector(63 downto 0) := (others => 'L');
-- primary UART0 (available if IO_UART0_EN = true) --
uart0_txd_o : out std_ulogic;
uart0_rxd_i : in std_ulogic := 'L';
uart0_rts_o : out std_ulogic;
uart0_cts_i : in std_ulogic := 'L';
-- secondary UART1 (available if IO_UART1_EN = true) --
uart1_txd_o : out std_ulogic;
uart1_rxd_i : in std_ulogic := 'L'; -- UART1 receive data
uart1_rts_o : out std_ulogic;
uart1_cts_i : in std_ulogic := 'L';
-- SPI (available if IO_SPI_EN = true) --
spi_clk_o : out std_ulogic;
spi_dat_o : out std_ulogic;
spi_dat_i : in std_ulogic := 'L';
spi_csn_o : out std_ulogic_vector(07 downto 0); -- SPI CS
-- SDI (available if IO_SDI_EN = true) --
sdi_clk_i : in std_ulogic := 'L';
sdi_dat_o : out std_ulogic;
sdi_dat_i : in std_ulogic := 'L';
sdi_csn_i : in std_ulogic := 'H';
-- TWI (available if IO_TWI_EN = true) --
twi_sda_i : in std_ulogic := 'H';
twi_sda_o : out std_ulogic;
twi_scl_i : in std_ulogic := 'H';
twi_scl_o : out std_ulogic;
-- 1-Wire Interface (available if IO_ONEWIRE_EN = true) --
onewire_i : in std_ulogic := 'H';
onewire_o : out std_ulogic;
-- PWM (available if IO_PWM_NUM_CH > 0) --
pwm_o : out std_ulogic_vector(11 downto 0); -- pwm channels
-- Custom Functions Subsystem IO --
cfs_in_i : in std_ulogic_vector(IO_CFS_IN_SIZE-1 downto 0) := (others => 'L');
cfs_out_o : out std_ulogic_vector(IO_CFS_OUT_SIZE-1 downto 0);
-- NeoPixel-compatible smart LED interface (available if IO_NEOLED_EN = true) --
neoled_o : out std_ulogic;
-- Machine timer system time (available if IO_MTIME_EN = true) --
mtime_time_o : out std_ulogic_vector(63 downto 0);
-- GPTMR timer capture (available if IO_GPTMR_EN = true) --
gptmr_trig_i : in std_ulogic := 'L';
-- External platform interrupts (available if XIRQ_NUM_CH > 0) --
xirq_i : in std_ulogic_vector(31 downto 0) := (others => 'L');
-- CPU Interrupts --
mtime_irq_i : in std_ulogic := 'L';
msw_irq_i : in std_ulogic := 'L';
mext_irq_i : in std_ulogic := 'L'
);
end component;
end neorv32_package;
package body neorv32_package is
-- ****************************************************************************************************************************
-- Helper Functions
-- ****************************************************************************************************************************
-- Minimal required number of bits to represent <input> numbers ---------------------------
-- -------------------------------------------------------------------------------------------
function index_size_f(input : natural) return natural is
begin
for i in 0 to natural'high loop
if (2**i >= input) then
return i;
end if;
end loop;
return 0;
end function index_size_f;
-- Conditional select integer -------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
function cond_sel_int_f(cond : boolean; val_t : integer; val_f : integer) return integer is
begin
if cond then
return val_t;
else
return val_f;
end if;
end function cond_sel_int_f;
-- Conditional select natural -------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
function cond_sel_natural_f(cond : boolean; val_t : natural; val_f : natural) return natural is
begin
if cond then
return val_t;
else
return val_f;
end if;
end function cond_sel_natural_f;
-- Conditional select std_ulogic_vector ---------------------------------------------------
-- -------------------------------------------------------------------------------------------
function cond_sel_suv_f(cond : boolean; val_t : std_ulogic_vector; val_f : std_ulogic_vector) return std_ulogic_vector is
begin
if cond then
return val_t;
else
return val_f;
end if;
end function cond_sel_suv_f;
-- Conditional select string --------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
function cond_sel_string_f(cond : boolean; val_t : string; val_f : string) return string is
begin
if cond then
return val_t;
else
return val_f;
end if;
end function cond_sel_string_f;
-- Convert boolean to std_ulogic ----------------------------------------------------------
-- -------------------------------------------------------------------------------------------
function bool_to_ulogic_f(cond : boolean) return std_ulogic is
begin
if cond then
return '1';
else
return '0';
end if;
end function bool_to_ulogic_f;
-- Convert binary to gray -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
function bin_to_gray_f(input : std_ulogic_vector) return std_ulogic_vector is
variable tmp_v : std_ulogic_vector(input'range);
begin
tmp_v(input'length-1) := input(input'length-1); -- keep MSB
for i in input'length-2 downto 0 loop
tmp_v(i) := input(i) xor input(i+1);
end loop;
return tmp_v;
end function bin_to_gray_f;
-- Convert gray to binary -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
function gray_to_bin_f(input : std_ulogic_vector) return std_ulogic_vector is
variable tmp_v : std_ulogic_vector(input'range);
begin
tmp_v(input'length-1) := input(input'length-1); -- keep MSB
for i in input'length-2 downto 0 loop
tmp_v(i) := tmp_v(i+1) xor input(i);
end loop;
return tmp_v;
end function gray_to_bin_f;
-- OR all bits ----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
function or_reduce_f(input : std_ulogic_vector) return std_ulogic is
variable tmp_v : std_ulogic;
begin
tmp_v := '0';
for i in input'range loop
tmp_v := tmp_v or input(i);
end loop;
return tmp_v;
end function or_reduce_f;
-- AND all bits ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
function and_reduce_f(input : std_ulogic_vector) return std_ulogic is
variable tmp_v : std_ulogic;
begin
tmp_v := '1';
for i in input'range loop
tmp_v := tmp_v and input(i);
end loop;
return tmp_v;
end function and_reduce_f;
-- XOR all bits ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
function xor_reduce_f(input : std_ulogic_vector) return std_ulogic is
variable tmp_v : std_ulogic;
begin
tmp_v := '0';
for i in input'range loop
tmp_v := tmp_v xor input(i);
end loop;
return tmp_v;
end function xor_reduce_f;
-- Check if std_ulogic is not '1' or '0' --------------------------------------------------
-- -------------------------------------------------------------------------------------------
function su_undefined_f(input : std_ulogic) return boolean is
begin
case input is
when '1' | '0' => return false;
when others => return true;
end case;
end function su_undefined_f;
-- Convert std_ulogic_vector to lowercase HEX char ----------------------------------------
-- -------------------------------------------------------------------------------------------
function to_hexchar_f(input : std_ulogic_vector(3 downto 0)) return character is
variable hex_v : string(1 to 16);
begin
hex_v := "0123456789abcdef";
if su_undefined_f(input(3)) or su_undefined_f(input(2)) or
su_undefined_f(input(1)) or su_undefined_f(input(0)) then
return '?';
else
return hex_v(to_integer(unsigned(input)) + 1);
end if;
end function to_hexchar_f;
-- Convert 32-bit std_ulogic_vector to hex string -----------------------------------------
-- -------------------------------------------------------------------------------------------
function to_hstring32_f(input : std_ulogic_vector(31 downto 0)) return string is
variable res_v : string(1 to 8);
begin
for i in 7 downto 0 loop
res_v(8-i) := to_hexchar_f(input(i*4+3 downto i*4+0));
end loop;
return res_v;
end function to_hstring32_f;
-- Bit reversal ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
function bit_rev_f(input : std_ulogic_vector) return std_ulogic_vector is
variable output_v : std_ulogic_vector(input'range);
begin
for i in 0 to input'length-1 loop
output_v(input'length-i-1) := input(i);
end loop;
return output_v;
end function bit_rev_f;
-- Test if input number is a power of two -------------------------------------------------
-- -------------------------------------------------------------------------------------------
function is_power_of_two_f(input : natural) return boolean is
variable tmp : unsigned(31 downto 0);
begin
if (input = 0) then
return false;
elsif (input = 1) then
return true;
else
tmp := to_unsigned(input, 32);
if ((tmp and (tmp - 1)) = 0) then
return true;
else
return false;
end if;
end if;
end function is_power_of_two_f;
-- Swap all bytes of a 32-bit word (endianness conversion) --------------------------------
-- -------------------------------------------------------------------------------------------
function bswap32_f(input : std_ulogic_vector) return std_ulogic_vector is
variable output_v : std_ulogic_vector(input'range);
begin
output_v(07 downto 00) := input(31 downto 24);
output_v(15 downto 08) := input(23 downto 16);
output_v(23 downto 16) := input(15 downto 08);
output_v(31 downto 24) := input(07 downto 00);
return output_v;
end function bswap32_f;
-- Population count (number of set bits) --------------------------------------------------
-- -------------------------------------------------------------------------------------------
function popcount_f(input : std_ulogic_vector) return natural is
variable cnt_v : natural range 0 to input'length;
begin
cnt_v := 0;
for i in input'length-1 downto 0 loop
if (input(i) = '1') then
cnt_v := cnt_v + 1;
end if;
end loop;
return cnt_v;
end function popcount_f;
-- Count leading zeros --------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
function leading_zeros_f(input : std_ulogic_vector) return natural is
variable cnt_v : natural range 0 to input'length;
begin
cnt_v := 0;
for i in input'length-1 downto 0 loop
if (input(i) = '0') then
cnt_v := cnt_v + 1;
else
exit;
end if;
end loop;
return cnt_v;
end function leading_zeros_f;
-- Initialize mem32_t array from another mem32_t array ------------------------------------
-- -------------------------------------------------------------------------------------------
impure function mem32_init_f(init : mem32_t; depth : natural) return mem32_t is
variable mem_v : mem32_t(0 to depth-1);
begin
mem_v := (others => (others => '0')); -- [IMPORTANT] make sure remaining memory entries are set to zero
if (init'length > depth) then
return mem_v;
end if;
for i in 0 to init'length-1 loop -- initialize only in range of source data array
mem_v(i) := init(i);
end loop;
return mem_v;
end function mem32_init_f;
end neorv32_package;
-- ****************************************************************************************************************************
-- Additional Packages
-- ****************************************************************************************************************************
-- Prototype Definition: bootloader_init_image --------------------------------------------
-- -------------------------------------------------------------------------------------------
-- > memory content in 'neorv32_bootloader_image.vhd', auto-generated by 'image_gen'
-- > used by 'neorv32_boot_rom.vhd'
-- > enables body-only recompile in case of firmware change (NEORV32 PR #338)
library ieee;
use ieee.std_logic_1164.all;
library neorv32;
use neorv32.neorv32_package.all;
package neorv32_bootloader_image is
constant bootloader_init_image : mem32_t;
end neorv32_bootloader_image;
-- Prototype Definition: neorv32_application_image ----------------------------------------
-- -------------------------------------------------------------------------------------------
-- > memory content in 'neorv32_application_image.vhd', auto-generated by 'image_gen'
-- > used by 'mem/neorv32_imem.*.vhd'
-- > enables body-only recompile in case of firmware change (NEORV32 PR #338)
library ieee;
use ieee.std_logic_1164.all;
library neorv32;
use neorv32.neorv32_package.all;
package neorv32_application_image is
constant application_init_image : mem32_t;
end neorv32_application_image;