-- ################################################################################################# -- # << The NEORV32 RISC-V Processor - Top Entity >> # -- # ********************************************************************************************* # -- # Check out the processor's online documentation for more information: # -- # HQ: https://github.com/stnolting/neorv32 # -- # Data Sheet: https://stnolting.github.io/neorv32 # -- # User Guide: https://stnolting.github.io/neorv32/ug # -- # ********************************************************************************************* # -- # BSD 3-Clause License # -- # # -- # The NEORV32 RISC-V Processor, https://github.com/stnolting/neorv32 # -- # 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. # -- ################################################################################################# library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; library neorv32; use neorv32.neorv32_package.all; entity neorv32_top is generic ( -- General -- CLOCK_FREQUENCY : natural; -- clock frequency of clk_i in Hz CLOCK_GATING_EN : boolean := false; -- enable clock gating when in sleep mode HART_ID : std_ulogic_vector(31 downto 0) := x"00000000"; -- hardware thread ID VENDOR_ID : std_ulogic_vector(31 downto 0) := x"00000000"; -- vendor's JEDEC ID INT_BOOTLOADER_EN : boolean := false; -- boot configuration: true = boot explicit bootloader; false = boot from int/ext (I)MEM -- On-Chip Debugger (OCD) -- ON_CHIP_DEBUGGER_EN : boolean := false; -- implement on-chip debugger DM_LEGACY_MODE : boolean := false; -- debug module spec version: false = v1.0, true = v0.13 -- RISC-V CPU Extensions -- CPU_EXTENSION_RISCV_A : boolean := false; -- implement atomic memory operations extension? CPU_EXTENSION_RISCV_B : boolean := false; -- implement bit-manipulation extension? CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension? CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension? CPU_EXTENSION_RISCV_M : boolean := false; -- implement mul/div extension? CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension? CPU_EXTENSION_RISCV_Zfinx : boolean := false; -- implement 32-bit floating-point extension (using INT regs!) CPU_EXTENSION_RISCV_Zicntr : boolean := true; -- implement base counters? CPU_EXTENSION_RISCV_Zicond : boolean := false; -- implement integer conditional operations? CPU_EXTENSION_RISCV_Zihpm : boolean := false; -- implement hardware performance monitors? CPU_EXTENSION_RISCV_Zmmul : boolean := false; -- implement multiply-only M sub-extension? CPU_EXTENSION_RISCV_Zxcfu : boolean := false; -- implement custom (instr.) functions unit? -- Tuning Options -- FAST_MUL_EN : boolean := false; -- use DSPs for M extension's multiplier FAST_SHIFT_EN : boolean := false; -- use barrel shifter for shift operations REGFILE_HW_RST : boolean := false; -- implement full hardware reset for register file -- Physical Memory Protection (PMP) -- PMP_NUM_REGIONS : natural range 0 to 16 := 0; -- number of regions (0..16) PMP_MIN_GRANULARITY : natural := 4; -- minimal region granularity in bytes, has to be a power of 2, min 4 bytes PMP_TOR_MODE_EN : boolean := true; -- implement TOR mode PMP_NAP_MODE_EN : boolean := true; -- implement NAPOT/NA4 modes -- Hardware Performance Monitors (HPM) -- HPM_NUM_CNTS : natural range 0 to 13 := 0; -- number of implemented HPM counters (0..13) HPM_CNT_WIDTH : natural range 0 to 64 := 40; -- total size of HPM counters (0..64) -- Atomic Memory Access - Reservation Set Granularity -- AMO_RVS_GRANULARITY : natural := 4; -- size in bytes, has to be a power of 2, min 4 -- Internal Instruction memory (IMEM) -- MEM_INT_IMEM_EN : boolean := false; -- implement processor-internal instruction memory MEM_INT_IMEM_SIZE : natural := 16*1024; -- size of processor-internal instruction memory in bytes (use a power of 2) -- Internal Data memory (DMEM) -- MEM_INT_DMEM_EN : boolean := false; -- implement processor-internal data memory MEM_INT_DMEM_SIZE : natural := 8*1024; -- size of processor-internal data memory in bytes (use a power of 2) -- Internal Instruction Cache (iCACHE) -- ICACHE_EN : boolean := false; -- implement instruction cache ICACHE_NUM_BLOCKS : natural range 1 to 256 := 4; -- i-cache: number of blocks (min 1), has to be a power of 2 ICACHE_BLOCK_SIZE : natural range 4 to 2**16 := 64; -- i-cache: block size in bytes (min 4), has to be a power of 2 ICACHE_ASSOCIATIVITY : natural range 1 to 2 := 1; -- i-cache: associativity / number of sets (1=direct_mapped), has to be a power of 2 -- Internal Data Cache (dCACHE) -- DCACHE_EN : boolean := false; -- implement data cache DCACHE_NUM_BLOCKS : natural range 1 to 256 := 4; -- d-cache: number of blocks (min 1), has to be a power of 2 DCACHE_BLOCK_SIZE : natural range 4 to 2**16 := 64; -- d-cache: block size in bytes (min 4), has to be a power of 2 -- External memory interface (WISHBONE) -- MEM_EXT_EN : boolean := false; -- implement external memory bus interface? MEM_EXT_TIMEOUT : natural := 255; -- cycles after a pending bus access auto-terminates (0 = disabled) MEM_EXT_PIPE_MODE : boolean := false; -- protocol: false=classic/standard wishbone mode, true=pipelined wishbone mode MEM_EXT_BIG_ENDIAN : boolean := false; -- byte order: true=big-endian, false=little-endian MEM_EXT_ASYNC_RX : boolean := false; -- use register buffer for RX data when false MEM_EXT_ASYNC_TX : boolean := false; -- use register buffer for TX data when false -- Execute in-place module (XIP) -- XIP_EN : boolean := false; -- implement execute in place module (XIP)? XIP_CACHE_EN : boolean := false; -- implement XIP cache? XIP_CACHE_NUM_BLOCKS : natural range 1 to 256 := 8; -- number of blocks (min 1), has to be a power of 2 XIP_CACHE_BLOCK_SIZE : natural range 1 to 2**16 := 256; -- block size in bytes (min 4), has to be a power of 2 -- External Interrupts Controller (XIRQ) -- XIRQ_NUM_CH : natural range 0 to 32 := 0; -- number of external IRQ channels (0..32) XIRQ_TRIGGER_TYPE : std_ulogic_vector(31 downto 0) := x"ffffffff"; -- trigger type: 0=level, 1=edge XIRQ_TRIGGER_POLARITY : std_ulogic_vector(31 downto 0) := x"ffffffff"; -- trigger polarity: 0=low-level/falling-edge, 1=high-level/rising-edge -- Processor peripherals -- IO_GPIO_NUM : natural range 0 to 64 := 0; -- number of GPIO input/output pairs (0..64) IO_MTIME_EN : boolean := false; -- implement machine system timer (MTIME)? IO_UART0_EN : boolean := false; -- implement primary universal asynchronous receiver/transmitter (UART0)? IO_UART0_RX_FIFO : natural range 1 to 2**15 := 1; -- RX fifo depth, has to be a power of two, min 1 IO_UART0_TX_FIFO : natural range 1 to 2**15 := 1; -- TX fifo depth, has to be a power of two, min 1 IO_UART1_EN : boolean := false; -- implement secondary universal asynchronous receiver/transmitter (UART1)? IO_UART1_RX_FIFO : natural range 1 to 2**15 := 1; -- RX fifo depth, has to be a power of two, min 1 IO_UART1_TX_FIFO : natural range 1 to 2**15 := 1; -- TX fifo depth, has to be a power of two, min 1 IO_SPI_EN : boolean := false; -- implement serial peripheral interface (SPI)? IO_SPI_FIFO : natural range 1 to 2**15 := 1; -- RTX fifo depth, has to be a power of two, min 1 IO_SDI_EN : boolean := false; -- implement serial data interface (SDI)? IO_SDI_FIFO : natural range 1 to 2**15 := 1; -- RTX fifo depth, has to be zero or a power of two, min 1 IO_TWI_EN : boolean := false; -- implement two-wire interface (TWI)? IO_PWM_NUM_CH : natural range 0 to 12 := 0; -- number of PWM channels to implement (0..12); 0 = disabled IO_WDT_EN : boolean := false; -- implement watch dog timer (WDT)? IO_TRNG_EN : boolean := false; -- implement true random number generator (TRNG)? IO_TRNG_FIFO : natural range 1 to 2**15 := 1; -- data fifo depth, has to be a power of two, min 1 IO_CFS_EN : boolean := false; -- implement custom functions subsystem (CFS)? IO_CFS_CONFIG : std_ulogic_vector(31 downto 0) := x"00000000"; -- custom CFS configuration generic IO_CFS_IN_SIZE : natural := 32; -- size of CFS input conduit in bits IO_CFS_OUT_SIZE : natural := 32; -- size of CFS output conduit in bits IO_NEOLED_EN : boolean := false; -- implement NeoPixel-compatible smart LED interface (NEOLED)? IO_NEOLED_TX_FIFO : natural range 1 to 2**15 := 1; -- NEOLED FIFO depth, has to be a power of two, min 1 IO_GPTMR_EN : boolean := false; -- implement general purpose timer (GPTMR)? IO_ONEWIRE_EN : boolean := false; -- implement 1-wire interface (ONEWIRE)? IO_DMA_EN : boolean := false; -- implement direct memory access controller (DMA)? IO_SLINK_EN : boolean := false; -- implement stream link interface (SLINK)? IO_SLINK_RX_FIFO : natural range 1 to 2**15 := 1; -- RX fifo depth, has to be a power of two, min 1 IO_SLINK_TX_FIFO : natural range 1 to 2**15 := 1; -- TX fifo depth, has to be a power of two, min 1 IO_CRC_EN : boolean := false -- implement cyclic redundancy check unit (CRC)? ); port ( -- Global control -- clk_i : in std_ulogic; -- global clock, rising edge rstn_i : in std_ulogic; -- global reset, low-active, async -- JTAG on-chip debugger interface (available if ON_CHIP_DEBUGGER_EN = true) -- jtag_trst_i : in std_ulogic := 'H'; -- low-active TAP reset (optional) jtag_tck_i : in std_ulogic := 'L'; -- serial clock jtag_tdi_i : in std_ulogic := 'L'; -- serial data input jtag_tdo_o : out std_ulogic; -- serial data output jtag_tms_i : in std_ulogic := 'L'; -- mode select -- Wishbone bus interface (available if MEM_EXT_EN = true) -- wb_tag_o : out std_ulogic_vector(02 downto 0); -- request tag wb_adr_o : out std_ulogic_vector(31 downto 0); -- address wb_dat_i : in std_ulogic_vector(31 downto 0) := (others => 'L'); -- read data wb_dat_o : out std_ulogic_vector(31 downto 0); -- write data wb_we_o : out std_ulogic; -- read/write wb_sel_o : out std_ulogic_vector(03 downto 0); -- byte enable wb_stb_o : out std_ulogic; -- strobe wb_cyc_o : out std_ulogic; -- valid cycle wb_ack_i : in std_ulogic := 'L'; -- transfer acknowledge wb_err_i : in std_ulogic := 'L'; -- transfer error -- Stream Link Interface (available if IO_SLINK_EN = true) -- slink_rx_dat_i : in std_ulogic_vector(31 downto 0) := (others => 'L'); -- RX input data slink_rx_val_i : in std_ulogic := 'L'; -- RX valid input slink_rx_lst_i : in std_ulogic := 'L'; -- last element of stream slink_rx_rdy_o : out std_ulogic; -- RX ready to receive slink_tx_dat_o : out std_ulogic_vector(31 downto 0); -- TX output data slink_tx_val_o : out std_ulogic; -- TX valid output slink_tx_lst_o : out std_ulogic; -- last element of stream slink_tx_rdy_i : in std_ulogic := 'L'; -- TX ready to send -- XIP (execute in place via SPI) signals (available if XIP_EN = true) -- xip_csn_o : out std_ulogic; -- chip-select, low-active xip_clk_o : out std_ulogic; -- serial clock xip_dat_i : in std_ulogic := 'L'; -- device data input xip_dat_o : out std_ulogic; -- controller data output -- GPIO (available if IO_GPIO_NUM > 0) -- gpio_o : out std_ulogic_vector(63 downto 0); -- parallel output gpio_i : in std_ulogic_vector(63 downto 0) := (others => 'L'); -- parallel input -- primary UART0 (available if IO_UART0_EN = true) -- uart0_txd_o : out std_ulogic; -- UART0 send data uart0_rxd_i : in std_ulogic := 'L'; -- UART0 receive data uart0_rts_o : out std_ulogic; -- HW flow control: UART0.RX ready to receive ("RTR"), low-active, optional uart0_cts_i : in std_ulogic := 'L'; -- HW flow control: UART0.TX allowed to transmit, low-active, optional -- secondary UART1 (available if IO_UART1_EN = true) -- uart1_txd_o : out std_ulogic; -- UART1 send data uart1_rxd_i : in std_ulogic := 'L'; -- UART1 receive data uart1_rts_o : out std_ulogic; -- HW flow control: UART1.RX ready to receive ("RTR"), low-active, optional uart1_cts_i : in std_ulogic := 'L'; -- HW flow control: UART1.TX allowed to transmit, low-active, optional -- SPI (available if IO_SPI_EN = true) -- spi_clk_o : out std_ulogic; -- SPI serial clock spi_dat_o : out std_ulogic; -- controller data out, peripheral data in spi_dat_i : in std_ulogic := 'L'; -- controller data in, peripheral data out spi_csn_o : out std_ulogic_vector(07 downto 0); -- chip-select -- SDI (available if IO_SDI_EN = true) -- sdi_clk_i : in std_ulogic := 'L'; -- SDI serial clock sdi_dat_o : out std_ulogic; -- controller data out, peripheral data in sdi_dat_i : in std_ulogic := 'L'; -- controller data in, peripheral data out sdi_csn_i : in std_ulogic := 'H'; -- chip-select -- TWI (available if IO_TWI_EN = true) -- twi_sda_i : in std_ulogic := 'H'; -- serial data line sense input twi_sda_o : out std_ulogic; -- serial data line output (pull low only) twi_scl_i : in std_ulogic := 'H'; -- serial clock line sense input twi_scl_o : out std_ulogic; -- serial clock line output (pull low only) -- 1-Wire Interface (available if IO_ONEWIRE_EN = true) -- onewire_i : in std_ulogic := 'H'; -- 1-wire bus sense input onewire_o : out std_ulogic; -- 1-wire bus output (pull low only) -- PWM (available if IO_PWM_NUM_CH > 0) -- pwm_o : out std_ulogic_vector(11 downto 0); -- pwm channels -- Custom Functions Subsystem IO (available if IO_CFS_EN = true) -- cfs_in_i : in std_ulogic_vector(IO_CFS_IN_SIZE-1 downto 0) := (others => 'L'); -- custom CFS inputs conduit cfs_out_o : out std_ulogic_vector(IO_CFS_OUT_SIZE-1 downto 0); -- custom CFS outputs conduit -- NeoPixel-compatible smart LED interface (available if IO_NEOLED_EN = true) -- neoled_o : out std_ulogic; -- async serial data line -- Machine timer system time (available if IO_MTIME_EN = true) -- mtime_time_o : out std_ulogic_vector(63 downto 0); -- current system time -- GPTMR timer capture (available if IO_GPTMR_EN = true) -- gptmr_trig_i : in std_ulogic := 'L'; -- capture trigger -- External platform interrupts (available if XIRQ_NUM_CH > 0) -- xirq_i : in std_ulogic_vector(31 downto 0) := (others => 'L'); -- IRQ channels -- CPU interrupts -- mtime_irq_i : in std_ulogic := 'L'; -- machine timer interrupt, available if IO_MTIME_EN = false msw_irq_i : in std_ulogic := 'L'; -- machine software interrupt mext_irq_i : in std_ulogic := 'L' -- machine external interrupt ); end neorv32_top; architecture neorv32_top_rtl of neorv32_top is -- auto-configuration -- constant cpu_boot_addr_c : std_ulogic_vector(31 downto 0) := cond_sel_suv_f(INT_BOOTLOADER_EN, mem_boot_base_c, mem_imem_base_c); constant imem_as_rom_c : boolean := not INT_BOOTLOADER_EN; constant io_gpio_en_c : boolean := boolean(IO_GPIO_NUM > 0); constant io_xirq_en_c : boolean := boolean(XIRQ_NUM_CH > 0); constant io_pwm_en_c : boolean := boolean(IO_PWM_NUM_CH > 0); -- make sure physical memory sizes are a power of two -- constant imem_size_valid_c : boolean := is_power_of_two_f(MEM_INT_IMEM_SIZE); constant imem_size_pow2_c : natural := 2**index_size_f(MEM_INT_IMEM_SIZE); constant imem_size_c : natural := cond_sel_natural_f(imem_size_valid_c, MEM_INT_IMEM_SIZE, imem_size_pow2_c); -- constant dmem_size_valid_c : boolean := is_power_of_two_f(MEM_INT_DMEM_SIZE); constant dmem_size_pow2_c : natural := 2**index_size_f(MEM_INT_DMEM_SIZE); constant dmem_size_c : natural := cond_sel_natural_f(dmem_size_valid_c, MEM_INT_DMEM_SIZE, dmem_size_pow2_c); -- reset generator -- signal rstn_wdt : std_ulogic; signal rstn_sys_sreg, rstn_ext_sreg : std_ulogic_vector(3 downto 0); signal rstn_sys, rstn_ext : std_ulogic; signal rst_cause : std_ulogic_vector(1 downto 0); -- clock generator -- signal clk_cpu : std_ulogic; -- CPU core clock, can be switched off signal clk_div, clk_div_ff : std_ulogic_vector(11 downto 0); signal clk_gen : std_ulogic_vector(07 downto 0); signal clk_gen_en, clk_gen_en_ff : std_ulogic; -- type cg_en_t is record wdt, uart0, uart1, spi, twi, pwm, cfs, neoled, gptmr, xip, onewire : std_ulogic; end record; signal cg_en : cg_en_t; -- CPU status -- signal cpu_debug, cpu_sleep : std_ulogic; -- cpu is in debug/sleep mode -- debug module interface (DMI) -- signal dmi_req : dmi_req_t; signal dmi_rsp : dmi_rsp_t; -- debug core interface (DCI) -- signal dci_ndmrstn, dci_halt_req : std_ulogic; -- bus: core complex -- signal cpu_i_req, cpu_d_req : bus_req_t; -- CPU core signal cpu_i_rsp, cpu_d_rsp : bus_rsp_t; -- CPU core signal icache_req, dcache_req : bus_req_t; -- CPU caches signal icache_rsp, dcache_rsp : bus_rsp_t; -- CPU caches signal core_req : bus_req_t; -- core complex (CPU + caches) signal core_rsp : bus_rsp_t; -- core complex (CPU + caches) -- bus: core complex + DMA -- signal main_req, main2_req, dma_req : bus_req_t; -- core complex (CPU + caches + DMA) signal main_rsp, main2_rsp, dma_rsp : bus_rsp_t; -- core complex (CPU + caches + DMA) -- bus: main sections -- signal imem_req, dmem_req, xip_req, boot_req, io_req, xbus_req : bus_req_t; signal imem_rsp, dmem_rsp, xip_rsp, boot_rsp, io_rsp, xbus_rsp : bus_rsp_t; -- bus: IO devices -- type io_devices_t is ( IODEV_OCD, IODEV_SYSINFO, IODEV_NEOLED, IODEV_GPIO, IODEV_WDT, IODEV_TRNG, IODEV_TWI, IODEV_SPI, IODEV_SDI, IODEV_UART1, IODEV_UART0, IODEV_MTIME, IODEV_XIRQ, IODEV_ONEWIRE, IODEV_GPTMR, IODEV_PWM, IODEV_XIP, IODEV_CRC, IODEV_DMA, IODEV_SLINK, IODEV_CFS ); type iodev_req_t is array (io_devices_t) of bus_req_t; type iodev_rsp_t is array (io_devices_t) of bus_rsp_t; signal iodev_req : iodev_req_t; signal iodev_rsp : iodev_rsp_t; -- IRQs -- signal cpu_firq : std_ulogic_vector(15 downto 0); type irq_t is record wdt, uart0_rx, uart0_tx, uart1_rx, uart1_tx, spi, sdi, twi, cfs, neoled, xirq, gptmr, onewire, dma, trng, slink : std_ulogic; end record; signal firq : irq_t; signal mtime_irq : std_ulogic; -- misc -- signal mtime_time : std_ulogic_vector(63 downto 0); begin -- ************************************************************************************************************************** -- Sanity Checks -- ************************************************************************************************************************** sanity_checks: if (true) generate -- say hello -- assert false report "[NEORV32] The NEORV32 RISC-V Processor " & "(version 0x" & to_hstring32_f(hw_version_c) & "), " & "github.com/stnolting/neorv32" severity note; -- show main SoC configuration -- assert false report "[NEORV32] Processor Configuration: " & cond_sel_string_f(MEM_INT_IMEM_EN, "IMEM ", "") & cond_sel_string_f(MEM_INT_DMEM_EN, "DMEM ", "") & cond_sel_string_f(INT_BOOTLOADER_EN, "BOOTROM ", "") & cond_sel_string_f(ICACHE_EN, "I-CACHE ", "") & cond_sel_string_f(DCACHE_EN, "D-CACHE ", "") & cond_sel_string_f(MEM_EXT_EN, "WISHBONE ", "") & cond_sel_string_f(io_gpio_en_c, "GPIO ", "") & cond_sel_string_f(IO_MTIME_EN, "MTIME ", "") & cond_sel_string_f(IO_UART0_EN, "UART0 ", "") & cond_sel_string_f(IO_UART1_EN, "UART1 ", "") & cond_sel_string_f(IO_SPI_EN, "SPI ", "") & cond_sel_string_f(IO_SDI_EN, "SDI ", "") & cond_sel_string_f(IO_TWI_EN, "TWI ", "") & cond_sel_string_f(io_pwm_en_c, "PWM ", "") & cond_sel_string_f(IO_WDT_EN, "WDT ", "") & cond_sel_string_f(IO_TRNG_EN, "TRNG ", "") & cond_sel_string_f(IO_CFS_EN, "CFS ", "") & cond_sel_string_f(IO_NEOLED_EN, "NEOLED ", "") & cond_sel_string_f(io_xirq_en_c, "XIRQ ", "") & cond_sel_string_f(IO_GPTMR_EN, "GPTMR ", "") & cond_sel_string_f(XIP_EN, "XIP ", "") & cond_sel_string_f(IO_ONEWIRE_EN, "ONEWIRE ", "") & cond_sel_string_f(IO_DMA_EN, "DMA ", "") & cond_sel_string_f(IO_SLINK_EN, "SLINK ", "") & cond_sel_string_f(IO_CRC_EN, "CRC ", "") & cond_sel_string_f(true, "SYSINFO ", "") & -- always enabled cond_sel_string_f(ON_CHIP_DEBUGGER_EN, "OCD ", "") & "" severity note; -- IMEM size -- assert not ((imem_size_valid_c = false) and (MEM_INT_IMEM_EN = true)) report "[NEORV32] Auto-adjusting invalid IMEM size configuration." severity warning; -- DMEM size -- assert not ((dmem_size_valid_c = false) and (MEM_INT_DMEM_EN = true)) report "[NEORV32] Auto-adjusting invalid DMEM size configuration." severity warning; end generate; -- /sanity_checks -- ************************************************************************************************************************** -- Clock and Reset Generators -- ************************************************************************************************************************** generators: if (true) generate -- Reset Generator ------------------------------------------------------------------------ -- ------------------------------------------------------------------------------------------- reset_generator: process(rstn_i, clk_i) begin if (rstn_i = '0') then rstn_ext_sreg <= (others => '0'); rstn_ext <= '0'; rstn_sys_sreg <= (others => '0'); rstn_sys <= '0'; elsif falling_edge(clk_i) then -- inverted clock to release reset _before_ all FFs trigger (rising edge) -- external reset -- rstn_ext_sreg <= rstn_ext_sreg(rstn_ext_sreg'left-1 downto 0) & '1'; -- active for at least clock cycles rstn_ext <= and_reduce_f(rstn_ext_sreg); -- internal reset -- if (rstn_wdt = '0') or (dci_ndmrstn = '0') then -- sync reset sources rstn_sys_sreg <= (others => '0'); else rstn_sys_sreg <= rstn_sys_sreg(rstn_sys_sreg'left-1 downto 0) & '1'; -- active for at least clock cycles end if; rstn_sys <= and_reduce_f(rstn_sys_sreg); end if; end process reset_generator; -- Reset Cause ---------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- reset_cause: process(rstn_ext, clk_i) begin if (rstn_ext = '0') then rst_cause <= "00"; -- reset from external pin elsif falling_edge(clk_i) then if (dci_ndmrstn = '0') then rst_cause <= "01"; -- reset from on-chip debugger elsif (rstn_wdt = '0') then rst_cause <= "10"; -- reset from watchdog timer end if; end if; end process reset_cause; -- Clock Generator ------------------------------------------------------------------------ -- ------------------------------------------------------------------------------------------- clock_generator: process(rstn_sys, clk_i) begin if (rstn_sys = '0') then clk_gen_en_ff <= '0'; clk_div <= (others => '0'); clk_div_ff <= (others => '0'); elsif rising_edge(clk_i) then clk_gen_en_ff <= clk_gen_en; if (clk_gen_en_ff = '1') then clk_div <= std_ulogic_vector(unsigned(clk_div) + 1); else -- reset if disabled clk_div <= (others => '0'); end if; clk_div_ff <= clk_div; end if; end process clock_generator; -- clock enables: rising edge detectors -- clk_gen(clk_div2_c) <= clk_div(0) and (not clk_div_ff(0)); -- clk/2 clk_gen(clk_div4_c) <= clk_div(1) and (not clk_div_ff(1)); -- clk/4 clk_gen(clk_div8_c) <= clk_div(2) and (not clk_div_ff(2)); -- clk/8 clk_gen(clk_div64_c) <= clk_div(5) and (not clk_div_ff(5)); -- clk/64 clk_gen(clk_div128_c) <= clk_div(6) and (not clk_div_ff(6)); -- clk/128 clk_gen(clk_div1024_c) <= clk_div(9) and (not clk_div_ff(9)); -- clk/1024 clk_gen(clk_div2048_c) <= clk_div(10) and (not clk_div_ff(10)); -- clk/2048 clk_gen(clk_div4096_c) <= clk_div(11) and (not clk_div_ff(11)); -- clk/4096 -- fresh clocks anyone? -- clk_gen_en <= cg_en.wdt or cg_en.uart0 or cg_en.uart1 or cg_en.spi or cg_en.twi or cg_en.pwm or cg_en.cfs or cg_en.neoled or cg_en.gptmr or cg_en.xip or cg_en.onewire; -- Clock Gating --------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- neorv32_clockgate_inst_true: if CLOCK_GATING_EN generate neorv32_clockgate_inst: entity neorv32.neorv32_clockgate port map ( clk_i => clk_i, rstn_i => rstn_sys, halt_i => cpu_sleep, clk_o => clk_cpu ); end generate; neorv32_clockgate_inst_false: if not CLOCK_GATING_EN generate clk_cpu <= clk_i; end generate; end generate; -- /generators -- ************************************************************************************************************************** -- Core Complex -- ************************************************************************************************************************** core_complex: if (true) generate -- CPU Core ------------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- neorv32_cpu_inst: entity neorv32.neorv32_cpu generic map ( -- General -- HART_ID => HART_ID, VENDOR_ID => VENDOR_ID, CPU_BOOT_ADDR => cpu_boot_addr_c, CPU_DEBUG_PARK_ADDR => dm_park_entry_c, CPU_DEBUG_EXC_ADDR => dm_exc_entry_c, -- RISC-V CPU Extensions -- CPU_EXTENSION_RISCV_A => CPU_EXTENSION_RISCV_A, CPU_EXTENSION_RISCV_B => CPU_EXTENSION_RISCV_B, CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, CPU_EXTENSION_RISCV_E => CPU_EXTENSION_RISCV_E, CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M, CPU_EXTENSION_RISCV_U => CPU_EXTENSION_RISCV_U, CPU_EXTENSION_RISCV_Zfinx => CPU_EXTENSION_RISCV_Zfinx, CPU_EXTENSION_RISCV_Zicntr => CPU_EXTENSION_RISCV_Zicntr, CPU_EXTENSION_RISCV_Zicond => CPU_EXTENSION_RISCV_Zicond, CPU_EXTENSION_RISCV_Zihpm => CPU_EXTENSION_RISCV_Zihpm, CPU_EXTENSION_RISCV_Zmmul => CPU_EXTENSION_RISCV_Zmmul, CPU_EXTENSION_RISCV_Zxcfu => CPU_EXTENSION_RISCV_Zxcfu, CPU_EXTENSION_RISCV_Sdext => ON_CHIP_DEBUGGER_EN, CPU_EXTENSION_RISCV_Sdtrig => ON_CHIP_DEBUGGER_EN, -- Tuning Options -- FAST_MUL_EN => FAST_MUL_EN, FAST_SHIFT_EN => FAST_SHIFT_EN, REGFILE_HW_RST => REGFILE_HW_RST, -- Physical Memory Protection (PMP) -- PMP_NUM_REGIONS => PMP_NUM_REGIONS, PMP_MIN_GRANULARITY => PMP_MIN_GRANULARITY, PMP_TOR_MODE_EN => PMP_TOR_MODE_EN, PMP_NAP_MODE_EN => PMP_NAP_MODE_EN, -- Hardware Performance Monitors (HPM) -- HPM_NUM_CNTS => HPM_NUM_CNTS, HPM_CNT_WIDTH => HPM_CNT_WIDTH ) port map ( -- global control -- clk_i => clk_cpu, clk_aux_i => clk_i, rstn_i => rstn_sys, sleep_o => cpu_sleep, debug_o => cpu_debug, -- interrupts -- msi_i => msw_irq_i, mei_i => mext_irq_i, mti_i => mtime_irq, firq_i => cpu_firq, dbi_i => dci_halt_req, -- instruction bus interface -- ibus_req_o => cpu_i_req, ibus_rsp_i => cpu_i_rsp, -- data bus interface -- dbus_req_o => cpu_d_req, dbus_rsp_i => cpu_d_rsp ); -- fast interrupt requests (FIRQs) -- cpu_firq(00) <= firq.wdt; -- highest priority cpu_firq(01) <= firq.cfs; cpu_firq(02) <= firq.uart0_rx; cpu_firq(03) <= firq.uart0_tx; cpu_firq(04) <= firq.uart1_rx; cpu_firq(05) <= firq.uart1_tx; cpu_firq(06) <= firq.spi; cpu_firq(07) <= firq.twi; cpu_firq(08) <= firq.xirq; cpu_firq(09) <= firq.neoled; cpu_firq(10) <= firq.dma; cpu_firq(11) <= firq.sdi; cpu_firq(12) <= firq.gptmr; cpu_firq(13) <= firq.onewire; cpu_firq(14) <= firq.slink; cpu_firq(15) <= firq.trng; -- lowest priority -- CPU Instruction Cache ------------------------------------------------------------------ -- ------------------------------------------------------------------------------------------- neorv32_icache_inst_true: if ICACHE_EN generate neorv32_icache_inst: entity neorv32.neorv32_icache generic map ( ICACHE_NUM_BLOCKS => ICACHE_NUM_BLOCKS, ICACHE_BLOCK_SIZE => ICACHE_BLOCK_SIZE, ICACHE_NUM_SETS => ICACHE_ASSOCIATIVITY, ICACHE_UC_PBEGIN => uncached_begin_c(31 downto 28) ) port map ( clk_i => clk_cpu, rstn_i => rstn_sys, cpu_req_i => cpu_i_req, cpu_rsp_o => cpu_i_rsp, bus_req_o => icache_req, bus_rsp_i => icache_rsp ); end generate; neorv32_icache_inst_false: if not ICACHE_EN generate icache_req <= cpu_i_req; cpu_i_rsp <= icache_rsp; end generate; -- CPU Data Cache ------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- neorv32_dcache_inst_true: if DCACHE_EN generate neorv32_dcache_inst: entity neorv32.neorv32_dcache generic map ( DCACHE_NUM_BLOCKS => DCACHE_NUM_BLOCKS, DCACHE_BLOCK_SIZE => DCACHE_BLOCK_SIZE, DCACHE_UC_PBEGIN => uncached_begin_c(31 downto 28) ) port map ( clk_i => clk_cpu, rstn_i => rstn_sys, cpu_req_i => cpu_d_req, cpu_rsp_o => cpu_d_rsp, bus_req_o => dcache_req, bus_rsp_i => dcache_rsp ); end generate; neorv32_dcache_inst_false: if not DCACHE_EN generate dcache_req <= cpu_d_req; cpu_d_rsp <= dcache_rsp; end generate; -- Core Complex Bus Switch ---------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- neorv32_core_bus_switch_inst: entity neorv32.neorv32_bus_switch generic map ( PORT_A_READ_ONLY => false, PORT_B_READ_ONLY => true -- i-fetch is read-only ) port map ( clk_i => clk_cpu, rstn_i => rstn_sys, a_req_i => dcache_req, -- prioritized a_rsp_o => dcache_rsp, b_req_i => icache_req, b_rsp_o => icache_rsp, x_req_o => core_req, x_rsp_i => core_rsp ); end generate; -- /core_complex -- ************************************************************************************************************************** -- Direct Memory Access Controller (DMA) Complex -- ************************************************************************************************************************** neorv32_dma_complex_true: if IO_DMA_EN generate -- DMA Controller ------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- neorv32_dma_inst: entity neorv32.neorv32_dma port map ( clk_i => clk_i, rstn_i => rstn_sys, bus_req_i => iodev_req(IODEV_DMA), bus_rsp_o => iodev_rsp(IODEV_DMA), dma_req_o => dma_req, dma_rsp_i => dma_rsp, firq_i => cpu_firq, irq_o => firq.dma ); -- DMA Bus Switch ------------------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- neorv32_dma_bus_switch_inst: entity neorv32.neorv32_bus_switch generic map ( PORT_A_READ_ONLY => false, PORT_B_READ_ONLY => false ) port map ( clk_i => clk_i, rstn_i => rstn_sys, a_req_i => core_req, -- prioritized a_rsp_o => core_rsp, b_req_i => dma_req, b_rsp_o => dma_rsp, x_req_o => main_req, x_rsp_i => main_rsp ); end generate; -- /neorv32_dma_complex_true neorv32_dma_complex_false: if not IO_DMA_EN generate iodev_rsp(IODEV_DMA) <= rsp_terminate_c; main_req <= core_req; core_rsp <= main_rsp; firq.dma <= '0'; end generate; -- ************************************************************************************************************************** -- Reservation Set Controller (for atomic LR/SC memory accesses) -- ************************************************************************************************************************** neorv32_bus_reservation_set_true: if CPU_EXTENSION_RISCV_A generate neorv32_bus_reservation_set_inst: entity neorv32.neorv32_bus_reservation_set generic map ( GRANULARITY => AMO_RVS_GRANULARITY ) port map ( clk_i => clk_i, rstn_i => rstn_sys, rvs_addr_o => open, -- yet unused rvs_valid_o => open, -- yet unused rvs_clear_i => '0', -- yet unused core_req_i => main_req, core_rsp_o => main_rsp, sys_req_o => main2_req, sys_rsp_i => main2_rsp ); end generate; neorv32_bus_reservation_set_false: if not CPU_EXTENSION_RISCV_A generate main2_req <= main_req; main_rsp <= main2_rsp; end generate; -- ************************************************************************************************************************** -- Address Region Gateway -- ************************************************************************************************************************** neorv32_bus_gateway_inst: entity neorv32.neorv32_bus_gateway generic map ( TIMEOUT => bus_timeout_c, -- IMEM port -- IMEM_ENABLE => MEM_INT_IMEM_EN, IMEM_BASE => mem_imem_base_c, IMEM_SIZE => imem_size_c, -- DMEM port -- DMEM_ENABLE => MEM_INT_DMEM_EN, DMEM_BASE => mem_dmem_base_c, DMEM_SIZE => dmem_size_c, -- XIP port -- XIP_ENABLE => XIP_EN, XIP_BASE => mem_xip_base_c, XIP_SIZE => mem_xip_size_c, -- BOOT ROM port -- BOOT_ENABLE => INT_BOOTLOADER_EN, BOOT_BASE => mem_boot_base_c, BOOT_SIZE => mem_boot_size_c, -- IO port -- IO_ENABLE => true, -- always enabled (mandatory core module) IO_BASE => mem_io_base_c, IO_SIZE => mem_io_size_c, -- EXT port -- EXT_ENABLE => MEM_EXT_EN ) port map ( -- global control -- clk_i => clk_i, rstn_i => rstn_sys, -- host port -- main_req_i => main2_req, main_rsp_o => main2_rsp, -- section ports -- imem_req_o => imem_req, imem_rsp_i => imem_rsp, dmem_req_o => dmem_req, dmem_rsp_i => dmem_rsp, xip_req_o => xip_req, xip_rsp_i => xip_rsp, boot_req_o => boot_req, boot_rsp_i => boot_rsp, io_req_o => io_req, io_rsp_i => io_rsp, ext_req_o => xbus_req, ext_rsp_i => xbus_rsp ); -- ************************************************************************************************************************** -- Memory System -- ************************************************************************************************************************** memory_system: if (true) generate -- Processor-Internal Instruction Memory (IMEM) ------------------------------------------- -- ------------------------------------------------------------------------------------------- neorv32_int_imem_inst_true: if MEM_INT_IMEM_EN generate neorv32_int_imem_inst: entity neorv32.neorv32_imem generic map ( IMEM_SIZE => imem_size_c, IMEM_AS_IROM => imem_as_rom_c ) port map ( clk_i => clk_i, rstn_i => rstn_sys, bus_req_i => imem_req, bus_rsp_o => imem_rsp ); end generate; neorv32_int_imem_inst_false: if not MEM_INT_IMEM_EN generate imem_rsp <= rsp_terminate_c; end generate; -- Processor-Internal Data Memory (DMEM) -------------------------------------------------- -- ------------------------------------------------------------------------------------------- neorv32_int_dmem_inst_true: if MEM_INT_DMEM_EN generate neorv32_int_dmem_inst: entity neorv32.neorv32_dmem generic map ( DMEM_SIZE => dmem_size_c ) port map ( clk_i => clk_i, rstn_i => rstn_sys, bus_req_i => dmem_req, bus_rsp_o => dmem_rsp ); end generate; neorv32_int_dmem_inst_false: if not MEM_INT_DMEM_EN generate dmem_rsp <= rsp_terminate_c; end generate; -- Processor-Internal Bootloader ROM (BOOTROM) -------------------------------------------- -- ------------------------------------------------------------------------------------------- neorv32_boot_rom_inst_true: if INT_BOOTLOADER_EN generate neorv32_boot_rom_inst: entity neorv32.neorv32_boot_rom port map ( clk_i => clk_i, rstn_i => rstn_sys, bus_req_i => boot_req, bus_rsp_o => boot_rsp ); end generate; neorv32_boot_rom_inst_false: if not INT_BOOTLOADER_EN generate boot_rsp <= rsp_terminate_c; end generate; -- Execute In Place Module (XIP) ---------------------------------------------------------- -- ------------------------------------------------------------------------------------------- neorv32_xip_inst_true: if XIP_EN generate neorv32_xip_inst: entity neorv32.neorv32_xip generic map ( XIP_CACHE_EN => XIP_CACHE_EN, XIP_CACHE_NUM_BLOCKS => XIP_CACHE_NUM_BLOCKS, XIP_CACHE_BLOCK_SIZE => XIP_CACHE_BLOCK_SIZE ) port map ( -- global control -- clk_i => clk_i, rstn_i => rstn_sys, bus_req_i => iodev_req(IODEV_XIP), bus_rsp_o => iodev_rsp(IODEV_XIP), xip_req_i => xip_req, xip_rsp_o => xip_rsp, clkgen_en_o => cg_en.xip, clkgen_i => clk_gen, spi_csn_o => xip_csn_o, spi_clk_o => xip_clk_o, spi_dat_i => xip_dat_i, spi_dat_o => xip_dat_o ); end generate; neorv32_xip_inst_false: if not XIP_EN generate iodev_rsp(IODEV_XIP) <= rsp_terminate_c; xip_rsp <= rsp_terminate_c; cg_en.xip <= '0'; xip_csn_o <= '1'; xip_clk_o <= '0'; xip_dat_o <= '0'; end generate; -- External Wishbone Gateway (WISHBONE) --------------------------------------------------- -- ------------------------------------------------------------------------------------------- neorv32_wishbone_inst_true: if MEM_EXT_EN generate neorv32_wishbone_inst: entity neorv32.neorv32_wishbone generic map ( BUS_TIMEOUT => MEM_EXT_TIMEOUT, PIPE_MODE => MEM_EXT_PIPE_MODE, BIG_ENDIAN => MEM_EXT_BIG_ENDIAN, ASYNC_RX => MEM_EXT_ASYNC_RX, ASYNC_TX => MEM_EXT_ASYNC_TX ) port map ( clk_i => clk_i, rstn_i => rstn_sys, bus_req_i => xbus_req, bus_rsp_o => xbus_rsp, -- wb_tag_o => wb_tag_o, wb_adr_o => wb_adr_o, wb_dat_i => wb_dat_i, wb_dat_o => wb_dat_o, wb_we_o => wb_we_o, wb_sel_o => wb_sel_o, wb_stb_o => wb_stb_o, wb_cyc_o => wb_cyc_o, wb_ack_i => wb_ack_i, wb_err_i => wb_err_i ); end generate; neorv32_wishbone_inst_false: if not MEM_EXT_EN generate xbus_rsp <= rsp_terminate_c; wb_adr_o <= (others => '0'); wb_dat_o <= (others => '0'); wb_we_o <= '0'; wb_sel_o <= (others => '0'); wb_stb_o <= '0'; wb_cyc_o <= '0'; wb_tag_o <= (others => '0'); end generate; end generate; -- /memory_system -- ************************************************************************************************************************** -- IO/Peripheral Modules -- ************************************************************************************************************************** io_system: if (true) generate -- IO Switch ------------------------------------------------------------------------------ -- ------------------------------------------------------------------------------------------- neorv32_bus_io_switch_inst: entity neorv32.neorv32_bus_io_switch generic map ( DEV_SIZE => iodev_size_c, -- size of a single IO device -- device port enable and base address -- DEV_00_EN => ON_CHIP_DEBUGGER_EN, DEV_00_BASE => base_io_dm_c, DEV_01_EN => true, DEV_01_BASE => base_io_sysinfo_c, -- always enabled (mandatory core module) DEV_02_EN => IO_NEOLED_EN, DEV_02_BASE => base_io_neoled_c, DEV_03_EN => io_gpio_en_c, DEV_03_BASE => base_io_gpio_c, DEV_04_EN => IO_WDT_EN, DEV_04_BASE => base_io_wdt_c, DEV_05_EN => IO_TRNG_EN, DEV_05_BASE => base_io_trng_c, DEV_06_EN => IO_TWI_EN, DEV_06_BASE => base_io_twi_c, DEV_07_EN => IO_SPI_EN, DEV_07_BASE => base_io_spi_c, DEV_08_EN => IO_SDI_EN, DEV_08_BASE => base_io_sdi_c, DEV_09_EN => IO_UART1_EN, DEV_09_BASE => base_io_uart1_c, DEV_10_EN => IO_UART0_EN, DEV_10_BASE => base_io_uart0_c, DEV_11_EN => IO_MTIME_EN, DEV_11_BASE => base_io_mtime_c, DEV_12_EN => io_xirq_en_c, DEV_12_BASE => base_io_xirq_c, DEV_13_EN => IO_ONEWIRE_EN, DEV_13_BASE => base_io_onewire_c, DEV_14_EN => IO_GPTMR_EN, DEV_14_BASE => base_io_gptmr_c, DEV_15_EN => io_pwm_en_c, DEV_15_BASE => base_io_pwm_c, DEV_16_EN => XIP_EN, DEV_16_BASE => base_io_xip_c, DEV_17_EN => IO_CRC_EN, DEV_17_BASE => base_io_crc_c, DEV_18_EN => IO_DMA_EN, DEV_18_BASE => base_io_dma_c, DEV_19_EN => IO_SLINK_EN, DEV_19_BASE => base_io_slink_c, DEV_20_EN => IO_CFS_EN, DEV_20_BASE => base_io_cfs_c ) port map ( -- host port -- main_req_i => io_req, main_rsp_o => io_rsp, -- device ports -- dev_00_req_o => iodev_req(IODEV_OCD), dev_00_rsp_i => iodev_rsp(IODEV_OCD), dev_01_req_o => iodev_req(IODEV_SYSINFO), dev_01_rsp_i => iodev_rsp(IODEV_SYSINFO), dev_02_req_o => iodev_req(IODEV_NEOLED), dev_02_rsp_i => iodev_rsp(IODEV_NEOLED), dev_03_req_o => iodev_req(IODEV_GPIO), dev_03_rsp_i => iodev_rsp(IODEV_GPIO), dev_04_req_o => iodev_req(IODEV_WDT), dev_04_rsp_i => iodev_rsp(IODEV_WDT), dev_05_req_o => iodev_req(IODEV_TRNG), dev_05_rsp_i => iodev_rsp(IODEV_TRNG), dev_06_req_o => iodev_req(IODEV_TWI), dev_06_rsp_i => iodev_rsp(IODEV_TWI), dev_07_req_o => iodev_req(IODEV_SPI), dev_07_rsp_i => iodev_rsp(IODEV_SPI), dev_08_req_o => iodev_req(IODEV_SDI), dev_08_rsp_i => iodev_rsp(IODEV_SDI), dev_09_req_o => iodev_req(IODEV_UART1), dev_09_rsp_i => iodev_rsp(IODEV_UART1), dev_10_req_o => iodev_req(IODEV_UART0), dev_10_rsp_i => iodev_rsp(IODEV_UART0), dev_11_req_o => iodev_req(IODEV_MTIME), dev_11_rsp_i => iodev_rsp(IODEV_MTIME), dev_12_req_o => iodev_req(IODEV_XIRQ), dev_12_rsp_i => iodev_rsp(IODEV_XIRQ), dev_13_req_o => iodev_req(IODEV_ONEWIRE), dev_13_rsp_i => iodev_rsp(IODEV_ONEWIRE), dev_14_req_o => iodev_req(IODEV_GPTMR), dev_14_rsp_i => iodev_rsp(IODEV_GPTMR), dev_15_req_o => iodev_req(IODEV_PWM), dev_15_rsp_i => iodev_rsp(IODEV_PWM), dev_16_req_o => iodev_req(IODEV_XIP), dev_16_rsp_i => iodev_rsp(IODEV_XIP), dev_17_req_o => iodev_req(IODEV_CRC), dev_17_rsp_i => iodev_rsp(IODEV_CRC), dev_18_req_o => iodev_req(IODEV_DMA), dev_18_rsp_i => iodev_rsp(IODEV_DMA), dev_19_req_o => iodev_req(IODEV_SLINK), dev_19_rsp_i => iodev_rsp(IODEV_SLINK), dev_20_req_o => iodev_req(IODEV_CFS), dev_20_rsp_i => iodev_rsp(IODEV_CFS) ); -- Custom Functions Subsystem (CFS) ------------------------------------------------------- -- ------------------------------------------------------------------------------------------- neorv32_cfs_inst_true: if IO_CFS_EN generate neorv32_cfs_inst: entity neorv32.neorv32_cfs generic map ( CFS_CONFIG => IO_CFS_CONFIG, CFS_IN_SIZE => IO_CFS_IN_SIZE, CFS_OUT_SIZE => IO_CFS_OUT_SIZE ) port map ( clk_i => clk_i, rstn_i => rstn_sys, bus_req_i => iodev_req(IODEV_CFS), bus_rsp_o => iodev_rsp(IODEV_CFS), clkgen_en_o => cg_en.cfs, clkgen_i => clk_gen, irq_o => firq.cfs, cfs_in_i => cfs_in_i, cfs_out_o => cfs_out_o ); end generate; neorv32_cfs_inst_false: if not IO_CFS_EN generate iodev_rsp(IODEV_CFS) <= rsp_terminate_c; cg_en.cfs <= '0'; firq.cfs <= '0'; cfs_out_o <= (others => '0'); end generate; -- Serial Data Interface (SDI) ------------------------------------------------------------ -- ------------------------------------------------------------------------------------------- neorv32_sdi_inst_true: if IO_SDI_EN generate neorv32_sdi_inst: entity neorv32.neorv32_sdi generic map ( RTX_FIFO => IO_SDI_FIFO ) port map ( clk_i => clk_i, rstn_i => rstn_sys, bus_req_i => iodev_req(IODEV_SDI), bus_rsp_o => iodev_rsp(IODEV_SDI), sdi_csn_i => sdi_csn_i, sdi_clk_i => sdi_clk_i, sdi_dat_i => sdi_dat_i, sdi_dat_o => sdi_dat_o, irq_o => firq.sdi ); end generate; neorv32_sdi_inst_false: if not IO_SDI_EN generate iodev_rsp(IODEV_SDI) <= rsp_terminate_c; sdi_dat_o <= '0'; firq.sdi <= '0'; end generate; -- General Purpose Input/Output Port (GPIO) ----------------------------------------------- -- ------------------------------------------------------------------------------------------- neorv32_gpio_inst_true: if io_gpio_en_c generate neorv32_gpio_inst: entity neorv32.neorv32_gpio generic map ( GPIO_NUM => IO_GPIO_NUM ) port map ( clk_i => clk_i, rstn_i => rstn_sys, bus_req_i => iodev_req(IODEV_GPIO), bus_rsp_o => iodev_rsp(IODEV_GPIO), gpio_o => gpio_o, gpio_i => gpio_i ); end generate; neorv32_gpio_inst_false: if not io_gpio_en_c generate iodev_rsp(IODEV_GPIO) <= rsp_terminate_c; gpio_o <= (others => '0'); end generate; -- Watch Dog Timer (WDT) ------------------------------------------------------------------ -- ------------------------------------------------------------------------------------------- neorv32_wdt_inst_true: if IO_WDT_EN generate neorv32_wdt_inst: entity neorv32.neorv32_wdt port map ( clk_i => clk_i, rstn_i => rstn_sys, rst_cause_i => rst_cause, bus_req_i => iodev_req(IODEV_WDT), bus_rsp_o => iodev_rsp(IODEV_WDT), cpu_debug_i => cpu_debug, cpu_sleep_i => cpu_sleep, clkgen_en_o => cg_en.wdt, clkgen_i => clk_gen, irq_o => firq.wdt, rstn_o => rstn_wdt ); end generate; neorv32_wdt_inst_false: if not IO_WDT_EN generate iodev_rsp(IODEV_WDT) <= rsp_terminate_c; firq.wdt <= '0'; rstn_wdt <= '1'; cg_en.wdt <= '0'; end generate; -- Machine System Timer (MTIME) ----------------------------------------------------------- -- ------------------------------------------------------------------------------------------- neorv32_mtime_inst_true: if IO_MTIME_EN generate neorv32_mtime_inst: entity neorv32.neorv32_mtime port map ( clk_i => clk_i, rstn_i => rstn_sys, bus_req_i => iodev_req(IODEV_MTIME), bus_rsp_o => iodev_rsp(IODEV_MTIME), time_o => mtime_time, irq_o => mtime_irq ); -- synchronize system time output LO -- mtime_sync: process(rstn_sys, clk_i) begin if (rstn_sys = '0') then mtime_time_o(31 downto 0) <= (others => '0'); elsif rising_edge(clk_i) then mtime_time_o(31 downto 0) <= mtime_time(31 downto 0); end if; end process mtime_sync; -- system time output HI -- mtime_time_o(63 downto 32) <= mtime_time(63 downto 32); end generate; neorv32_mtime_inst_false: if not IO_MTIME_EN generate iodev_rsp(IODEV_MTIME) <= rsp_terminate_c; mtime_irq <= mtime_irq_i; mtime_time_o <= (others => '0'); end generate; -- Primary Universal Asynchronous Receiver/Transmitter (UART0) ---------------------------- -- ------------------------------------------------------------------------------------------- neorv32_uart0_inst_true: if IO_UART0_EN generate neorv32_uart0_inst: entity neorv32.neorv32_uart generic map ( SIM_LOG_FILE => "neorv32.uart0.sim_mode.text.out", UART_RX_FIFO => IO_UART0_RX_FIFO, UART_TX_FIFO => IO_UART0_TX_FIFO ) port map ( clk_i => clk_i, rstn_i => rstn_sys, bus_req_i => iodev_req(IODEV_UART0), bus_rsp_o => iodev_rsp(IODEV_UART0), clkgen_en_o => cg_en.uart0, clkgen_i => clk_gen, uart_txd_o => uart0_txd_o, uart_rxd_i => uart0_rxd_i, uart_rts_o => uart0_rts_o, uart_cts_i => uart0_cts_i, irq_rx_o => firq.uart0_rx, irq_tx_o => firq.uart0_tx ); end generate; neorv32_uart0_inst_false: if not IO_UART0_EN generate iodev_rsp(IODEV_UART0) <= rsp_terminate_c; uart0_txd_o <= '0'; uart0_rts_o <= '1'; cg_en.uart0 <= '0'; firq.uart0_rx <= '0'; firq.uart0_tx <= '0'; end generate; -- Secondary Universal Asynchronous Receiver/Transmitter (UART1) -------------------------- -- ------------------------------------------------------------------------------------------- neorv32_uart1_inst_true: if IO_UART1_EN generate neorv32_uart1_inst: entity neorv32.neorv32_uart generic map ( SIM_LOG_FILE => "neorv32.uart1.sim_mode.text.out", UART_RX_FIFO => IO_UART1_RX_FIFO, UART_TX_FIFO => IO_UART1_TX_FIFO ) port map ( clk_i => clk_i, rstn_i => rstn_sys, bus_req_i => iodev_req(IODEV_UART1), bus_rsp_o => iodev_rsp(IODEV_UART1), clkgen_en_o => cg_en.uart1, clkgen_i => clk_gen, uart_txd_o => uart1_txd_o, uart_rxd_i => uart1_rxd_i, uart_rts_o => uart1_rts_o, uart_cts_i => uart1_cts_i, irq_rx_o => firq.uart1_rx, irq_tx_o => firq.uart1_tx ); end generate; neorv32_uart1_inst_false: if not IO_UART1_EN generate iodev_rsp(IODEV_UART1) <= rsp_terminate_c; uart1_txd_o <= '0'; uart1_rts_o <= '1'; cg_en.uart1 <= '0'; firq.uart1_rx <= '0'; firq.uart1_tx <= '0'; end generate; -- Serial Peripheral Interface (SPI) ------------------------------------------------------ -- ------------------------------------------------------------------------------------------- neorv32_spi_inst_true: if IO_SPI_EN generate neorv32_spi_inst: entity neorv32.neorv32_spi generic map ( IO_SPI_FIFO => IO_SPI_FIFO ) port map ( clk_i => clk_i, rstn_i => rstn_sys, bus_req_i => iodev_req(IODEV_SPI), bus_rsp_o => iodev_rsp(IODEV_SPI), clkgen_en_o => cg_en.spi, clkgen_i => clk_gen, spi_clk_o => spi_clk_o, spi_dat_o => spi_dat_o, spi_dat_i => spi_dat_i, spi_csn_o => spi_csn_o, irq_o => firq.spi ); end generate; neorv32_spi_inst_false: if not IO_SPI_EN generate iodev_rsp(IODEV_SPI) <= rsp_terminate_c; spi_clk_o <= '0'; spi_dat_o <= '0'; spi_csn_o <= (others => '1'); cg_en.spi <= '0'; firq.spi <= '0'; end generate; -- Two-Wire Interface (TWI) --------------------------------------------------------------- -- ------------------------------------------------------------------------------------------- neorv32_twi_inst_true: if IO_TWI_EN generate neorv32_twi_inst: entity neorv32.neorv32_twi port map ( clk_i => clk_i, rstn_i => rstn_sys, bus_req_i => iodev_req(IODEV_TWI), bus_rsp_o => iodev_rsp(IODEV_TWI), clkgen_en_o => cg_en.twi, clkgen_i => clk_gen, twi_sda_i => twi_sda_i, twi_sda_o => twi_sda_o, twi_scl_i => twi_scl_i, twi_scl_o => twi_scl_o, irq_o => firq.twi ); end generate; neorv32_twi_inst_false: if not IO_TWI_EN generate iodev_rsp(IODEV_TWI) <= rsp_terminate_c; twi_sda_o <= '1'; twi_scl_o <= '1'; cg_en.twi <= '0'; firq.twi <= '0'; end generate; -- Pulse-Width Modulation Controller (PWM) ------------------------------------------------ -- ------------------------------------------------------------------------------------------- neorv32_pwm_inst_true: if io_pwm_en_c generate neorv32_pwm_inst: entity neorv32.neorv32_pwm generic map ( NUM_CHANNELS => IO_PWM_NUM_CH ) port map ( clk_i => clk_i, rstn_i => rstn_sys, bus_req_i => iodev_req(IODEV_PWM), bus_rsp_o => iodev_rsp(IODEV_PWM), clkgen_en_o => cg_en.pwm, clkgen_i => clk_gen, pwm_o => pwm_o ); end generate; neorv32_pwm_inst_false: if not io_pwm_en_c generate iodev_rsp(IODEV_PWM) <= rsp_terminate_c; cg_en.pwm <= '0'; pwm_o <= (others => '0'); end generate; -- True Random Number Generator (TRNG) ---------------------------------------------------- -- ------------------------------------------------------------------------------------------- neorv32_trng_inst_true: if IO_TRNG_EN generate neorv32_trng_inst: entity neorv32.neorv32_trng generic map ( IO_TRNG_FIFO => IO_TRNG_FIFO ) port map ( clk_i => clk_i, rstn_i => rstn_sys, bus_req_i => iodev_req(IODEV_TRNG), bus_rsp_o => iodev_rsp(IODEV_TRNG), irq_o => firq.trng ); end generate; neorv32_trng_inst_false: if not IO_TRNG_EN generate iodev_rsp(IODEV_TRNG) <= rsp_terminate_c; firq.trng <= '0'; end generate; -- Smart LED (WS2811/WS2812) Interface (NEOLED) ------------------------------------------- -- ------------------------------------------------------------------------------------------- neorv32_neoled_inst_true: if IO_NEOLED_EN generate neorv32_neoled_inst: entity neorv32.neorv32_neoled generic map ( FIFO_DEPTH => IO_NEOLED_TX_FIFO ) port map ( clk_i => clk_i, rstn_i => rstn_sys, bus_req_i => iodev_req(IODEV_NEOLED), bus_rsp_o => iodev_rsp(IODEV_NEOLED), clkgen_en_o => cg_en.neoled, clkgen_i => clk_gen, irq_o => firq.neoled, neoled_o => neoled_o ); end generate; neorv32_neoled_inst_false: if not IO_NEOLED_EN generate iodev_rsp(IODEV_NEOLED) <= rsp_terminate_c; cg_en.neoled <= '0'; firq.neoled <= '0'; neoled_o <= '0'; end generate; -- External Interrupt Controller (XIRQ) --------------------------------------------------- -- ------------------------------------------------------------------------------------------- neorv32_xirq_inst_true: if io_xirq_en_c generate neorv32_xirq_inst: entity neorv32.neorv32_xirq generic map ( XIRQ_NUM_CH => XIRQ_NUM_CH, XIRQ_TRIGGER_TYPE => XIRQ_TRIGGER_TYPE, XIRQ_TRIGGER_POLARITY => XIRQ_TRIGGER_POLARITY ) port map ( -- host access -- clk_i => clk_i, rstn_i => rstn_sys, bus_req_i => iodev_req(IODEV_XIRQ), bus_rsp_o => iodev_rsp(IODEV_XIRQ), xirq_i => xirq_i, cpu_irq_o => firq.xirq ); end generate; neorv32_xirq_inst_false: if not io_xirq_en_c generate iodev_rsp(IODEV_XIRQ) <= rsp_terminate_c; firq.xirq <= '0'; end generate; -- General Purpose Timer (GPTMR) ---------------------------------------------------------- -- ------------------------------------------------------------------------------------------- neorv32_gptmr_inst_true: if IO_GPTMR_EN generate neorv32_gptmr_inst: entity neorv32.neorv32_gptmr port map ( clk_i => clk_i, rstn_i => rstn_sys, bus_req_i => iodev_req(IODEV_GPTMR), bus_rsp_o => iodev_rsp(IODEV_GPTMR), clkgen_en_o => cg_en.gptmr, clkgen_i => clk_gen, irq_o => firq.gptmr, capture_i => gptmr_trig_i ); end generate; neorv32_gptmr_inst_false: if not IO_GPTMR_EN generate iodev_rsp(IODEV_GPTMR) <= rsp_terminate_c; cg_en.gptmr <= '0'; firq.gptmr <= '0'; end generate; -- 1-Wire Interface Controller (ONEWIRE) -------------------------------------------------- -- ------------------------------------------------------------------------------------------- neorv32_onewire_inst_true: if IO_ONEWIRE_EN generate neorv32_onewire_inst: entity neorv32.neorv32_onewire port map ( clk_i => clk_i, rstn_i => rstn_sys, bus_req_i => iodev_req(IODEV_ONEWIRE), bus_rsp_o => iodev_rsp(IODEV_ONEWIRE), clkgen_en_o => cg_en.onewire, clkgen_i => clk_gen, onewire_i => onewire_i, onewire_o => onewire_o, irq_o => firq.onewire ); end generate; neorv32_onewire_inst_false: if not IO_ONEWIRE_EN generate iodev_rsp(IODEV_ONEWIRE) <= rsp_terminate_c; onewire_o <= '1'; cg_en.onewire <= '0'; firq.onewire <= '0'; end generate; -- Stream Link Interface (SLINK) ---------------------------------------------------------- -- ------------------------------------------------------------------------------------------- neorv32_slink_inst_true: if IO_SLINK_EN generate neorv32_slink_inst: entity neorv32.neorv32_slink generic map ( SLINK_RX_FIFO => IO_SLINK_RX_FIFO, SLINK_TX_FIFO => IO_SLINK_TX_FIFO ) port map ( -- Host access -- clk_i => clk_i, rstn_i => rstn_sys, bus_req_i => iodev_req(IODEV_SLINK), bus_rsp_o => iodev_rsp(IODEV_SLINK), irq_o => firq.slink, -- RX stream interface -- slink_rx_data_i => slink_rx_dat_i, slink_rx_valid_i => slink_rx_val_i, slink_rx_last_i => slink_rx_lst_i, slink_rx_ready_o => slink_rx_rdy_o, -- TX stream interface -- slink_tx_data_o => slink_tx_dat_o, slink_tx_valid_o => slink_tx_val_o, slink_tx_last_o => slink_tx_lst_o, slink_tx_ready_i => slink_tx_rdy_i ); end generate; neorv32_slink_inst_false: if not IO_SLINK_EN generate iodev_rsp(IODEV_SLINK) <= rsp_terminate_c; firq.slink <= '0'; slink_rx_rdy_o <= '0'; slink_tx_dat_o <= (others => '0'); slink_tx_val_o <= '0'; slink_tx_lst_o <= '0'; end generate; -- Cyclic Redundancy Check Unit (CRC) ----------------------------------------------------- -- ------------------------------------------------------------------------------------------- neorv32_crc_inst_true: if IO_CRC_EN generate neorv32_crc_inst: entity neorv32.neorv32_crc port map ( clk_i => clk_i, rstn_i => rstn_sys, bus_req_i => iodev_req(IODEV_CRC), bus_rsp_o => iodev_rsp(IODEV_CRC) ); end generate; neorv32_crc_inst_false: if not IO_CRC_EN generate iodev_rsp(IODEV_CRC) <= rsp_terminate_c; end generate; -- System Configuration Information Memory (SYSINFO) -------------------------------------- -- ------------------------------------------------------------------------------------------- neorv32_sysinfo_inst: entity neorv32.neorv32_sysinfo generic map ( -- General -- CLOCK_FREQUENCY => CLOCK_FREQUENCY, CLOCK_GATING_EN => CLOCK_GATING_EN, INT_BOOTLOADER_EN => INT_BOOTLOADER_EN, -- Internal Instruction memory -- MEM_INT_IMEM_EN => MEM_INT_IMEM_EN, MEM_INT_IMEM_SIZE => imem_size_c, -- Internal Data memory -- MEM_INT_DMEM_EN => MEM_INT_DMEM_EN, MEM_INT_DMEM_SIZE => dmem_size_c, -- Reservation Set Granularity -- AMO_RVS_GRANULARITY => AMO_RVS_GRANULARITY, -- Instruction cache -- ICACHE_EN => ICACHE_EN, ICACHE_NUM_BLOCKS => ICACHE_NUM_BLOCKS, ICACHE_BLOCK_SIZE => ICACHE_BLOCK_SIZE, ICACHE_ASSOCIATIVITY => ICACHE_ASSOCIATIVITY, -- Data cache -- DCACHE_EN => DCACHE_EN, DCACHE_NUM_BLOCKS => DCACHE_NUM_BLOCKS, DCACHE_BLOCK_SIZE => DCACHE_BLOCK_SIZE, -- External memory interface -- MEM_EXT_EN => MEM_EXT_EN, MEM_EXT_BIG_ENDIAN => MEM_EXT_BIG_ENDIAN, -- On-Chip Debugger -- ON_CHIP_DEBUGGER_EN => ON_CHIP_DEBUGGER_EN, -- Processor peripherals -- IO_GPIO_EN => io_gpio_en_c, IO_MTIME_EN => IO_MTIME_EN, IO_UART0_EN => IO_UART0_EN, IO_UART1_EN => IO_UART1_EN, IO_SPI_EN => IO_SPI_EN, IO_SDI_EN => IO_SDI_EN, IO_TWI_EN => IO_TWI_EN, IO_PWM_EN => io_pwm_en_c, IO_WDT_EN => IO_WDT_EN, IO_TRNG_EN => IO_TRNG_EN, IO_CFS_EN => IO_CFS_EN, IO_NEOLED_EN => IO_NEOLED_EN, IO_XIRQ_EN => io_xirq_en_c, IO_GPTMR_EN => IO_GPTMR_EN, XIP_EN => XIP_EN, IO_ONEWIRE_EN => IO_ONEWIRE_EN, IO_DMA_EN => IO_DMA_EN, IO_SLINK_EN => IO_SLINK_EN, IO_CRC_EN => IO_CRC_EN ) port map ( clk_i => clk_i, rstn_i => rstn_sys, bus_req_i => iodev_req(IODEV_SYSINFO), bus_rsp_o => iodev_rsp(IODEV_SYSINFO) ); end generate; -- /io_system -- ************************************************************************************************************************** -- On-Chip Debugger Complex -- ************************************************************************************************************************** neorv32_neorv32_ocd_inst_true: if ON_CHIP_DEBUGGER_EN generate -- On-Chip Debugger - Debug Transport Module (DTM) ---------------------------------------- -- ------------------------------------------------------------------------------------------- neorv32_debug_dtm_inst: entity neorv32.neorv32_debug_dtm generic map ( IDCODE_VERSION => (others => '0'), IDCODE_PARTID => (others => '0'), IDCODE_MANID => (others => '0') ) port map ( -- global control -- clk_i => clk_i, rstn_i => rstn_ext, -- jtag connection -- jtag_trst_i => jtag_trst_i, jtag_tck_i => jtag_tck_i, jtag_tdi_i => jtag_tdi_i, jtag_tdo_o => jtag_tdo_o, jtag_tms_i => jtag_tms_i, -- debug module interface (DMI) -- dmi_req_o => dmi_req, dmi_rsp_i => dmi_rsp ); -- On-Chip Debugger - Debug Module (DM) --------------------------------------------------- -- ------------------------------------------------------------------------------------------- neorv32_debug_dm_inst: entity neorv32.neorv32_debug_dm generic map ( CPU_BASE_ADDR => base_io_dm_c, LEGACY_MODE => DM_LEGACY_MODE ) port map ( -- global control -- clk_i => clk_i, rstn_i => rstn_ext, cpu_debug_i => cpu_debug, -- debug module interface (DMI) -- dmi_req_i => dmi_req, dmi_rsp_o => dmi_rsp, -- CPU bus access -- bus_req_i => iodev_req(IODEV_OCD), bus_rsp_o => iodev_rsp(IODEV_OCD), -- CPU control -- cpu_ndmrstn_o => dci_ndmrstn, cpu_halt_req_o => dci_halt_req ); end generate; neorv32_debug_ocd_inst_false: if not ON_CHIP_DEBUGGER_EN generate iodev_rsp(IODEV_OCD) <= rsp_terminate_c; jtag_tdo_o <= jtag_tdi_i; -- JTAG feed-through dci_ndmrstn <= '1'; dci_halt_req <= '0'; end generate; end neorv32_top_rtl;