Line 6... |
Line 6... |
-- # Data Sheet: https://stnolting.github.io/neorv32 #
|
-- # Data Sheet: https://stnolting.github.io/neorv32 #
|
-- # User Guide: https://stnolting.github.io/neorv32/ug #
|
-- # User Guide: https://stnolting.github.io/neorv32/ug #
|
-- # ********************************************************************************************* #
|
-- # ********************************************************************************************* #
|
-- # BSD 3-Clause License #
|
-- # BSD 3-Clause License #
|
-- # #
|
-- # #
|
-- # Copyright (c) 2021, Stephan Nolting. All rights reserved. #
|
-- # Copyright (c) 2022, Stephan Nolting. All rights reserved. #
|
-- # #
|
-- # #
|
-- # Redistribution and use in source and binary forms, with or without modification, are #
|
-- # Redistribution and use in source and binary forms, with or without modification, are #
|
-- # permitted provided that the following conditions are met: #
|
-- # permitted provided that the following conditions are met: #
|
-- # #
|
-- # #
|
-- # 1. Redistributions of source code must retain the above copyright notice, this list of #
|
-- # 1. Redistributions of source code must retain the above copyright notice, this list of #
|
Line 88... |
Line 88... |
|
|
-- Internal Data memory (DMEM) --
|
-- Internal Data memory (DMEM) --
|
MEM_INT_DMEM_EN : boolean := false; -- implement processor-internal data memory
|
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
|
MEM_INT_DMEM_SIZE : natural := 8*1024; -- size of processor-internal data memory in bytes
|
|
|
-- Internal Cache memory (iCACHE) --
|
-- Internal Instruction Cache (iCACHE) --
|
ICACHE_EN : boolean := false; -- implement instruction cache
|
ICACHE_EN : boolean := false; -- implement instruction cache
|
ICACHE_NUM_BLOCKS : natural := 4; -- i-cache: number of blocks (min 1), has to be a power of 2
|
ICACHE_NUM_BLOCKS : natural := 4; -- i-cache: number of blocks (min 1), has to be a power of 2
|
ICACHE_BLOCK_SIZE : natural := 64; -- i-cache: block size in bytes (min 4), has to be a power of 2
|
ICACHE_BLOCK_SIZE : natural := 64; -- i-cache: block size in bytes (min 4), has to be a power of 2
|
ICACHE_ASSOCIATIVITY : natural := 1; -- i-cache: associativity / number of sets (1=direct_mapped), has to be a power of 2
|
ICACHE_ASSOCIATIVITY : natural := 1; -- i-cache: associativity / number of sets (1=direct_mapped), has to be a power of 2
|
|
|
Line 132... |
Line 132... |
IO_CFS_CONFIG : std_ulogic_vector(31 downto 0) := x"00000000"; -- custom CFS configuration generic
|
IO_CFS_CONFIG : std_ulogic_vector(31 downto 0) := x"00000000"; -- custom CFS configuration generic
|
IO_CFS_IN_SIZE : positive := 32; -- size of CFS input conduit in bits
|
IO_CFS_IN_SIZE : positive := 32; -- size of CFS input conduit in bits
|
IO_CFS_OUT_SIZE : positive := 32; -- size of CFS output conduit in bits
|
IO_CFS_OUT_SIZE : positive := 32; -- size of CFS output conduit in bits
|
IO_NEOLED_EN : boolean := false; -- implement NeoPixel-compatible smart LED interface (NEOLED)?
|
IO_NEOLED_EN : boolean := false; -- implement NeoPixel-compatible smart LED interface (NEOLED)?
|
IO_NEOLED_TX_FIFO : natural := 1; -- NEOLED TX FIFO depth, 1..32k, has to be a power of two
|
IO_NEOLED_TX_FIFO : natural := 1; -- NEOLED TX FIFO depth, 1..32k, has to be a power of two
|
IO_GPTMR_EN : boolean := false -- implement general purpose timer (GPTMR)?
|
IO_GPTMR_EN : boolean := false; -- implement general purpose timer (GPTMR)?
|
|
IO_XIP_EN : boolean := false -- implement execute in place module (XIP)?
|
);
|
);
|
port (
|
port (
|
-- Global control --
|
-- Global control --
|
clk_i : in std_ulogic; -- global clock, rising edge
|
clk_i : in std_ulogic; -- global clock, rising edge
|
rstn_i : in std_ulogic; -- global reset, low-active, async
|
rstn_i : in std_ulogic; -- global reset, low-active, async
|
Line 163... |
Line 164... |
|
|
-- Advanced memory control signals (available if MEM_EXT_EN = true) --
|
-- Advanced memory control signals (available if MEM_EXT_EN = true) --
|
fence_o : out std_ulogic; -- indicates an executed FENCE operation
|
fence_o : out std_ulogic; -- indicates an executed FENCE operation
|
fencei_o : out std_ulogic; -- indicates an executed FENCEI operation
|
fencei_o : out std_ulogic; -- indicates an executed FENCEI operation
|
|
|
|
-- XIP (execute in place via SPI) signals (available if IO_XIP_EN = true) --
|
|
xip_csn_o : out std_ulogic; -- chip-select, low-active
|
|
xip_clk_o : out std_ulogic; -- serial clock
|
|
xip_sdi_i : in std_ulogic := 'L'; -- device data input
|
|
xip_sdo_o : out std_ulogic; -- controller data output
|
|
|
-- TX stream interfaces (available if SLINK_NUM_TX > 0) --
|
-- TX stream interfaces (available if SLINK_NUM_TX > 0) --
|
slink_tx_dat_o : out sdata_8x32_t; -- output data
|
slink_tx_dat_o : out sdata_8x32_t; -- output data
|
slink_tx_val_o : out std_ulogic_vector(7 downto 0); -- valid output
|
slink_tx_val_o : out std_ulogic_vector(7 downto 0); -- valid output
|
slink_tx_rdy_i : in std_ulogic_vector(7 downto 0) := (others => 'L'); -- ready to send
|
slink_tx_rdy_i : in std_ulogic_vector(7 downto 0) := (others => 'L'); -- ready to send
|
|
|
Line 200... |
Line 207... |
-- TWI (available if IO_TWI_EN = true) --
|
-- TWI (available if IO_TWI_EN = true) --
|
twi_sda_io : inout std_logic := 'U'; -- twi serial data line
|
twi_sda_io : inout std_logic := 'U'; -- twi serial data line
|
twi_scl_io : inout std_logic := 'U'; -- twi serial clock line
|
twi_scl_io : inout std_logic := 'U'; -- twi serial clock line
|
|
|
-- PWM (available if IO_PWM_NUM_CH > 0) --
|
-- PWM (available if IO_PWM_NUM_CH > 0) --
|
pwm_o : out std_ulogic_vector(IO_PWM_NUM_CH-1 downto 0); -- pwm channels
|
pwm_o : out std_ulogic_vector(59 downto 0); -- pwm channels
|
|
|
-- Custom Functions Subsystem IO (available if IO_CFS_EN = true) --
|
-- 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 => 'U'); -- custom CFS inputs conduit
|
cfs_in_i : in std_ulogic_vector(IO_CFS_IN_SIZE-1 downto 0) := (others => 'U'); -- custom CFS inputs conduit
|
cfs_out_o : out std_ulogic_vector(IO_CFS_OUT_SIZE-1 downto 0); -- custom CFS outputs conduit
|
cfs_out_o : out std_ulogic_vector(IO_CFS_OUT_SIZE-1 downto 0); -- custom CFS outputs conduit
|
|
|
Line 214... |
Line 221... |
-- System time --
|
-- System time --
|
mtime_i : in std_ulogic_vector(63 downto 0) := (others => 'U'); -- current system time from ext. MTIME (if IO_MTIME_EN = false)
|
mtime_i : in std_ulogic_vector(63 downto 0) := (others => 'U'); -- current system time from ext. MTIME (if IO_MTIME_EN = false)
|
mtime_o : out std_ulogic_vector(63 downto 0); -- current system time from int. MTIME (if IO_MTIME_EN = true)
|
mtime_o : out std_ulogic_vector(63 downto 0); -- current system time from int. MTIME (if IO_MTIME_EN = true)
|
|
|
-- External platform interrupts (available if XIRQ_NUM_CH > 0) --
|
-- External platform interrupts (available if XIRQ_NUM_CH > 0) --
|
xirq_i : in std_ulogic_vector(XIRQ_NUM_CH-1 downto 0) := (others => 'L'); -- IRQ channels
|
xirq_i : in std_ulogic_vector(31 downto 0) := (others => 'L'); -- IRQ channels
|
|
|
-- CPU interrupts --
|
-- CPU interrupts --
|
mtime_irq_i : in std_ulogic := 'L'; -- machine timer interrupt, available if IO_MTIME_EN = false
|
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
|
msw_irq_i : in std_ulogic := 'L'; -- machine software interrupt
|
mext_irq_i : in std_ulogic := 'L' -- machine external interrupt
|
mext_irq_i : in std_ulogic := 'L' -- machine external interrupt
|
Line 236... |
Line 243... |
|
|
-- helpers --
|
-- helpers --
|
constant io_slink_en_c : boolean := boolean(SLINK_NUM_RX > 0) or boolean(SLINK_NUM_TX > 0); -- implement slink at all?
|
constant io_slink_en_c : boolean := boolean(SLINK_NUM_RX > 0) or boolean(SLINK_NUM_TX > 0); -- implement slink at all?
|
|
|
-- reset generator --
|
-- reset generator --
|
signal rstn_gen : std_ulogic_vector(7 downto 0) := (others => '0'); -- initialize (=reset) via (for FPGAs only)
|
signal rstn_gen : std_ulogic_vector(7 downto 0) := (others => '0'); -- initialize (=reset) via bitstream (for FPGAs only)
|
signal ext_rstn : std_ulogic;
|
signal ext_rstn : std_ulogic;
|
signal sys_rstn : std_ulogic;
|
signal sys_rstn : std_ulogic;
|
signal wdt_rstn : std_ulogic;
|
signal wdt_rstn : std_ulogic;
|
|
|
-- clock generator --
|
-- clock generator --
|
signal clk_div : std_ulogic_vector(11 downto 0);
|
signal clk_div : std_ulogic_vector(11 downto 0);
|
signal clk_div_ff : std_ulogic_vector(11 downto 0);
|
signal clk_div_ff : std_ulogic_vector(11 downto 0);
|
signal clk_gen : std_ulogic_vector(07 downto 0);
|
signal clk_gen : std_ulogic_vector(07 downto 0);
|
signal clk_gen_en : std_ulogic_vector(08 downto 0);
|
signal clk_gen_en : std_ulogic_vector(09 downto 0);
|
|
signal clk_gen_en_ff : std_ulogic;
|
--
|
--
|
signal wdt_cg_en : std_ulogic;
|
signal wdt_cg_en : std_ulogic;
|
signal uart0_cg_en : std_ulogic;
|
signal uart0_cg_en : std_ulogic;
|
signal uart1_cg_en : std_ulogic;
|
signal uart1_cg_en : std_ulogic;
|
signal spi_cg_en : std_ulogic;
|
signal spi_cg_en : std_ulogic;
|
signal twi_cg_en : std_ulogic;
|
signal twi_cg_en : std_ulogic;
|
signal pwm_cg_en : std_ulogic;
|
signal pwm_cg_en : std_ulogic;
|
signal cfs_cg_en : std_ulogic;
|
signal cfs_cg_en : std_ulogic;
|
signal neoled_cg_en : std_ulogic;
|
signal neoled_cg_en : std_ulogic;
|
signal gptmr_cg_en : std_ulogic;
|
signal gptmr_cg_en : std_ulogic;
|
|
signal xip_cg_en : std_ulogic;
|
|
|
-- bus interface --
|
-- bus interface --
|
type bus_interface_t is record
|
type bus_interface_t is record
|
addr : std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
|
addr : std_ulogic_vector(data_width_c-1 downto 0); -- bus access address
|
rdata : std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
|
rdata : std_ulogic_vector(data_width_c-1 downto 0); -- bus read data
|
Line 310... |
Line 319... |
err : std_ulogic;
|
err : std_ulogic;
|
end record;
|
end record;
|
constant resp_bus_entry_terminate_c : resp_bus_entry_t := (rdata => (others => '0'), ack => '0', err => '0');
|
constant resp_bus_entry_terminate_c : resp_bus_entry_t := (rdata => (others => '0'), ack => '0', err => '0');
|
|
|
-- module response bus - device ID --
|
-- module response bus - device ID --
|
type resp_bus_id_t is (RESP_BUSKEEPER, RESP_IMEM, RESP_DMEM, RESP_BOOTROM, RESP_WISHBONE, RESP_GPIO, RESP_MTIME, RESP_UART0, RESP_UART1, RESP_SPI,
|
type resp_bus_id_t is (RESP_BUSKEEPER, RESP_IMEM, RESP_DMEM, RESP_BOOTROM, RESP_WISHBONE, RESP_GPIO, RESP_MTIME,
|
RESP_TWI, RESP_PWM, RESP_WDT, RESP_TRNG, RESP_CFS, RESP_NEOLED, RESP_SYSINFO, RESP_OCD, RESP_SLINK, RESP_XIRQ, RESP_GPTMR);
|
RESP_UART0, RESP_UART1, RESP_SPI, RESP_TWI, RESP_PWM, RESP_WDT, RESP_TRNG, RESP_CFS,
|
|
RESP_NEOLED, RESP_SYSINFO, RESP_OCD, RESP_SLINK, RESP_XIRQ, RESP_GPTMR, RESP_XIP_CT, RESP_XIP_IF);
|
|
|
-- module response bus --
|
-- module response bus --
|
type resp_bus_t is array (resp_bus_id_t) of resp_bus_entry_t;
|
type resp_bus_t is array (resp_bus_id_t) of resp_bus_entry_t;
|
signal resp_bus : resp_bus_t := (others => resp_bus_entry_terminate_c);
|
signal resp_bus : resp_bus_t := (others => resp_bus_entry_terminate_c);
|
|
|
Line 338... |
Line 348... |
|
|
-- misc --
|
-- misc --
|
signal mtime_time : std_ulogic_vector(63 downto 0); -- current system time from MTIME
|
signal mtime_time : std_ulogic_vector(63 downto 0); -- current system time from MTIME
|
signal ext_timeout : std_ulogic;
|
signal ext_timeout : std_ulogic;
|
signal ext_access : std_ulogic;
|
signal ext_access : std_ulogic;
|
|
signal xip_access : std_ulogic;
|
|
signal xip_enable : std_ulogic;
|
|
signal xip_page : std_ulogic_vector(3 downto 0);
|
signal debug_mode : std_ulogic;
|
signal debug_mode : std_ulogic;
|
|
|
begin
|
begin
|
|
|
-- Processor IO/Peripherals Configuration -------------------------------------------------
|
-- Processor IO/Peripherals Configuration -------------------------------------------------
|
Line 360... |
Line 373... |
cond_sel_string_f(IO_CFS_EN, "CFS ", "") &
|
cond_sel_string_f(IO_CFS_EN, "CFS ", "") &
|
cond_sel_string_f(io_slink_en_c, "SLINK ", "") &
|
cond_sel_string_f(io_slink_en_c, "SLINK ", "") &
|
cond_sel_string_f(IO_NEOLED_EN, "NEOLED ", "") &
|
cond_sel_string_f(IO_NEOLED_EN, "NEOLED ", "") &
|
cond_sel_string_f(boolean(XIRQ_NUM_CH > 0), "XIRQ ", "") &
|
cond_sel_string_f(boolean(XIRQ_NUM_CH > 0), "XIRQ ", "") &
|
cond_sel_string_f(IO_GPTMR_EN, "GPTMR ", "") &
|
cond_sel_string_f(IO_GPTMR_EN, "GPTMR ", "") &
|
|
cond_sel_string_f(IO_XIP_EN, "XIP ", "") &
|
""
|
""
|
severity note;
|
severity note;
|
|
|
|
|
-- Sanity Checks --------------------------------------------------------------------------
|
-- Sanity Checks --------------------------------------------------------------------------
|
Line 419... |
Line 433... |
-- Clock Generator ------------------------------------------------------------------------
|
-- Clock Generator ------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
clock_generator: process(sys_rstn, clk_i)
|
clock_generator: process(sys_rstn, clk_i)
|
begin
|
begin
|
if (sys_rstn = '0') then
|
if (sys_rstn = '0') then
|
clk_gen_en <= (others => '-');
|
clk_gen_en_ff <= '-';
|
clk_div <= (others => '0');
|
clk_div <= (others => '0'); -- reset required
|
clk_div_ff <= (others => '-');
|
clk_div_ff <= (others => '-');
|
clk_gen <= (others => '-');
|
clk_gen <= (others => '-');
|
elsif rising_edge(clk_i) then
|
elsif rising_edge(clk_i) then
|
-- fresh clocks anyone? --
|
clk_gen_en_ff <= or_reduce_f(clk_gen_en);
|
clk_gen_en(0) <= wdt_cg_en;
|
|
clk_gen_en(1) <= uart0_cg_en;
|
|
clk_gen_en(2) <= uart1_cg_en;
|
|
clk_gen_en(3) <= spi_cg_en;
|
|
clk_gen_en(4) <= twi_cg_en;
|
|
clk_gen_en(5) <= pwm_cg_en;
|
|
clk_gen_en(6) <= cfs_cg_en;
|
|
clk_gen_en(7) <= neoled_cg_en;
|
|
clk_gen_en(8) <= gptmr_cg_en;
|
|
-- actual clock generator --
|
-- actual clock generator --
|
if (or_reduce_f(clk_gen_en) = '1') then
|
if (clk_gen_en_ff = '1') then
|
clk_div <= std_ulogic_vector(unsigned(clk_div) + 1);
|
clk_div <= std_ulogic_vector(unsigned(clk_div) + 1);
|
end if;
|
end if;
|
-- clock enables: rising edge detectors --
|
-- clock enables: rising edge detectors --
|
clk_div_ff <= clk_div;
|
clk_div_ff <= clk_div;
|
clk_gen(clk_div2_c) <= clk_div(0) and (not clk_div_ff(0)); -- CLK/2
|
clk_gen(clk_div2_c) <= clk_div(0) and (not clk_div_ff(0)); -- CLK/2
|
Line 451... |
Line 456... |
clk_gen(clk_div2048_c) <= clk_div(10) and (not clk_div_ff(10)); -- CLK/2048
|
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
|
clk_gen(clk_div4096_c) <= clk_div(11) and (not clk_div_ff(11)); -- CLK/4096
|
end if;
|
end if;
|
end process clock_generator;
|
end process clock_generator;
|
|
|
|
-- fresh clocks anyone? --
|
|
clk_gen_en(0) <= wdt_cg_en;
|
|
clk_gen_en(1) <= uart0_cg_en;
|
|
clk_gen_en(2) <= uart1_cg_en;
|
|
clk_gen_en(3) <= spi_cg_en;
|
|
clk_gen_en(4) <= twi_cg_en;
|
|
clk_gen_en(5) <= pwm_cg_en;
|
|
clk_gen_en(6) <= cfs_cg_en;
|
|
clk_gen_en(7) <= neoled_cg_en;
|
|
clk_gen_en(8) <= gptmr_cg_en;
|
|
clk_gen_en(9) <= xip_cg_en;
|
|
|
|
|
-- CPU Core -------------------------------------------------------------------------------
|
-- CPU Core -------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
neorv32_cpu_inst: neorv32_cpu
|
neorv32_cpu_inst: neorv32_cpu
|
generic map (
|
generic map (
|
Line 465... |
Line 482... |
-- RISC-V CPU Extensions --
|
-- RISC-V CPU Extensions --
|
CPU_EXTENSION_RISCV_A => CPU_EXTENSION_RISCV_A, -- implement atomic extension?
|
CPU_EXTENSION_RISCV_A => CPU_EXTENSION_RISCV_A, -- implement atomic extension?
|
CPU_EXTENSION_RISCV_B => CPU_EXTENSION_RISCV_B, -- implement bit-manipulation extension?
|
CPU_EXTENSION_RISCV_B => CPU_EXTENSION_RISCV_B, -- implement bit-manipulation extension?
|
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension?
|
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension?
|
CPU_EXTENSION_RISCV_E => CPU_EXTENSION_RISCV_E, -- implement embedded RF extension?
|
CPU_EXTENSION_RISCV_E => CPU_EXTENSION_RISCV_E, -- implement embedded RF extension?
|
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M, -- implement muld/div extension?
|
CPU_EXTENSION_RISCV_M => CPU_EXTENSION_RISCV_M, -- implement mul/div extension?
|
CPU_EXTENSION_RISCV_U => CPU_EXTENSION_RISCV_U, -- implement user mode extension?
|
CPU_EXTENSION_RISCV_U => CPU_EXTENSION_RISCV_U, -- implement user mode extension?
|
CPU_EXTENSION_RISCV_Zfinx => CPU_EXTENSION_RISCV_Zfinx, -- implement 32-bit floating-point extension (using INT reg!)
|
CPU_EXTENSION_RISCV_Zfinx => CPU_EXTENSION_RISCV_Zfinx, -- implement 32-bit floating-point extension (using INT reg!)
|
CPU_EXTENSION_RISCV_Zicsr => CPU_EXTENSION_RISCV_Zicsr, -- implement CSR system?
|
CPU_EXTENSION_RISCV_Zicsr => CPU_EXTENSION_RISCV_Zicsr, -- implement CSR system?
|
CPU_EXTENSION_RISCV_Zicntr => CPU_EXTENSION_RISCV_Zicntr, -- implement base counters?
|
CPU_EXTENSION_RISCV_Zicntr => CPU_EXTENSION_RISCV_Zicntr, -- implement base counters?
|
CPU_EXTENSION_RISCV_Zihpm => CPU_EXTENSION_RISCV_Zihpm, -- implement hardware performance monitors?
|
CPU_EXTENSION_RISCV_Zihpm => CPU_EXTENSION_RISCV_Zihpm, -- implement hardware performance monitors?
|
Line 536... |
Line 553... |
|
|
-- advanced memory control --
|
-- advanced memory control --
|
fence_o <= cpu_d.fence; -- indicates an executed FENCE operation
|
fence_o <= cpu_d.fence; -- indicates an executed FENCE operation
|
fencei_o <= cpu_i.fence; -- indicates an executed FENCEI operation
|
fencei_o <= cpu_i.fence; -- indicates an executed FENCEI operation
|
|
|
-- fast interrupt requests (FIRQs) --
|
-- fast interrupt requests (FIRQs) - triggers are SINGLE-SHOT --
|
-- these signals are single-shot --
|
|
fast_irq(00) <= wdt_irq; -- HIGHEST PRIORITY - watchdog
|
fast_irq(00) <= wdt_irq; -- HIGHEST PRIORITY - watchdog
|
fast_irq(01) <= cfs_irq; -- custom functions subsystem
|
fast_irq(01) <= cfs_irq; -- custom functions subsystem
|
fast_irq(02) <= uart0_rxd_irq; -- primary UART (UART0) RX
|
fast_irq(02) <= uart0_rxd_irq; -- primary UART (UART0) RX
|
fast_irq(03) <= uart0_txd_irq; -- primary UART (UART0) TX
|
fast_irq(03) <= uart0_txd_irq; -- primary UART (UART0) TX
|
fast_irq(04) <= uart1_rxd_irq; -- secondary UART (UART1) RX
|
fast_irq(04) <= uart1_rxd_irq; -- secondary UART (UART1) RX
|
fast_irq(05) <= uart1_txd_irq; -- secondary UART (UART1) TX
|
fast_irq(05) <= uart1_txd_irq; -- secondary UART (UART1) TX
|
fast_irq(06) <= spi_irq; -- SPI
|
fast_irq(06) <= spi_irq; -- SPI transfer done
|
fast_irq(07) <= twi_irq; -- TWI
|
fast_irq(07) <= twi_irq; -- TWI transfer done
|
fast_irq(08) <= xirq_irq; -- external interrupt controller
|
fast_irq(08) <= xirq_irq; -- external interrupt controller
|
fast_irq(09) <= neoled_irq; -- NEOLED buffer free
|
fast_irq(09) <= neoled_irq; -- NEOLED buffer IRQ
|
fast_irq(10) <= slink_rx_irq; -- SLINK RX
|
fast_irq(10) <= slink_rx_irq; -- SLINK RX
|
fast_irq(11) <= slink_tx_irq; -- SLINK TX
|
fast_irq(11) <= slink_tx_irq; -- SLINK TX
|
fast_irq(12) <= gptmr_irq; -- general purpose timer
|
fast_irq(12) <= gptmr_irq; -- general purpose timer
|
--
|
--
|
fast_irq(13) <= '0'; -- reserved
|
fast_irq(13) <= '0'; -- reserved
|
Line 689... |
Line 705... |
clk_i => clk_i, -- global clock line
|
clk_i => clk_i, -- global clock line
|
rstn_i => sys_rstn, -- global reset line, low-active, use as async
|
rstn_i => sys_rstn, -- global reset line, low-active, use as async
|
addr_i => p_bus.addr, -- address
|
addr_i => p_bus.addr, -- address
|
rden_i => io_rden, -- read enable
|
rden_i => io_rden, -- read enable
|
wren_i => io_wren, -- byte write enable
|
wren_i => io_wren, -- byte write enable
|
|
data_i => p_bus.wdata, -- data in
|
data_o => resp_bus(RESP_BUSKEEPER).rdata, -- data out
|
data_o => resp_bus(RESP_BUSKEEPER).rdata, -- data out
|
ack_o => resp_bus(RESP_BUSKEEPER).ack, -- transfer acknowledge
|
ack_o => resp_bus(RESP_BUSKEEPER).ack, -- transfer acknowledge
|
err_o => bus_error, -- transfer error
|
err_o => bus_error, -- transfer error
|
-- bus monitoring --
|
-- bus monitoring --
|
bus_addr_i => p_bus.addr, -- address
|
bus_addr_i => p_bus.addr, -- address
|
bus_rden_i => p_bus.re, -- read enable
|
bus_rden_i => p_bus.re, -- read enable
|
bus_wren_i => p_bus.we, -- write enable
|
bus_wren_i => p_bus.we, -- write enable
|
bus_ack_i => p_bus.ack, -- transfer acknowledge from bus system
|
bus_ack_i => p_bus.ack, -- transfer acknowledge from bus system
|
bus_err_i => p_bus.err, -- transfer error from bus system
|
bus_err_i => p_bus.err, -- transfer error from bus system
|
bus_tmo_i => ext_timeout, -- transfer timeout (external interface)
|
bus_tmo_i => ext_timeout, -- transfer timeout (external interface)
|
bus_ext_i => ext_access -- external bus access
|
bus_ext_i => ext_access, -- external bus access
|
|
bus_xip_i => xip_access -- pending XIP access
|
);
|
);
|
|
|
-- unused, BUSKEEPER **directly** issues error to the CPU --
|
-- unused, BUSKEEPER **directly** issues error to the CPU --
|
resp_bus(RESP_BUSKEEPER).err <= '0';
|
resp_bus(RESP_BUSKEEPER).err <= '0';
|
|
|
Line 823... |
Line 841... |
ack_o => resp_bus(RESP_WISHBONE).ack, -- transfer acknowledge
|
ack_o => resp_bus(RESP_WISHBONE).ack, -- transfer acknowledge
|
err_o => resp_bus(RESP_WISHBONE).err, -- transfer error
|
err_o => resp_bus(RESP_WISHBONE).err, -- transfer error
|
tmo_o => ext_timeout, -- transfer timeout
|
tmo_o => ext_timeout, -- transfer timeout
|
priv_i => p_bus.priv, -- current CPU privilege level
|
priv_i => p_bus.priv, -- current CPU privilege level
|
ext_o => ext_access, -- active external access
|
ext_o => ext_access, -- active external access
|
|
-- xip configuration --
|
|
xip_en_i => xip_enable, -- XIP module enabled
|
|
xip_page_i => xip_page, -- XIP memory page
|
-- wishbone interface --
|
-- wishbone interface --
|
wb_tag_o => wb_tag_o, -- request tag
|
wb_tag_o => wb_tag_o, -- request tag
|
wb_adr_o => wb_adr_o, -- address
|
wb_adr_o => wb_adr_o, -- address
|
wb_dat_i => wb_dat_i, -- read data
|
wb_dat_i => wb_dat_i, -- read data
|
wb_dat_o => wb_dat_o, -- write data
|
wb_dat_o => wb_dat_o, -- write data
|
Line 855... |
Line 876... |
wb_lock_o <= '0';
|
wb_lock_o <= '0';
|
wb_tag_o <= (others => '0');
|
wb_tag_o <= (others => '0');
|
end generate;
|
end generate;
|
|
|
|
|
|
-- Execute In Place Module (XIP) ----------------------------------------------------------
|
|
-- -------------------------------------------------------------------------------------------
|
|
neorv32_xip_inst_true:
|
|
if (IO_XIP_EN = true) generate
|
|
neorv32_xip_inst: neorv32_xip
|
|
port map (
|
|
-- global control --
|
|
clk_i => clk_i, -- global clock line
|
|
rstn_i => sys_rstn, -- global reset line, low-active
|
|
-- host access: control register access port --
|
|
ct_addr_i => p_bus.addr, -- address
|
|
ct_rden_i => io_rden, -- read enable
|
|
ct_wren_i => io_wren, -- write enable
|
|
ct_data_i => p_bus.wdata, -- data in
|
|
ct_data_o => resp_bus(RESP_XIP_CT).rdata, -- data out
|
|
ct_ack_o => resp_bus(RESP_XIP_CT).ack, -- transfer acknowledge
|
|
-- host access: instruction fetch access port (read-only) --
|
|
if_addr_i => p_bus.addr, -- address
|
|
if_rden_i => p_bus.re, -- read enable
|
|
if_data_o => resp_bus(RESP_XIP_IF).rdata, -- data out
|
|
if_ack_o => resp_bus(RESP_XIP_IF).ack, -- transfer acknowledge
|
|
-- status --
|
|
xip_en_o => xip_enable, -- XIP enable
|
|
xip_acc_o => xip_access, -- pending XIP access
|
|
xip_page_o => xip_page, -- XIP page
|
|
-- clock generator --
|
|
clkgen_en_o => xip_cg_en, -- enable clock generator
|
|
clkgen_i => clk_gen,
|
|
-- SPI device interface --
|
|
spi_csn_o => xip_csn_o, -- chip-select, low-active
|
|
spi_clk_o => xip_clk_o, -- serial clock
|
|
spi_data_i => xip_sdi_i, -- device data output
|
|
spi_data_o => xip_sdo_o -- controller data output
|
|
);
|
|
resp_bus(RESP_XIP_CT).err <= '0'; -- no access error possible
|
|
resp_bus(RESP_XIP_IF).err <= '0'; -- no access error possible
|
|
end generate;
|
|
|
|
neorv32_xip_inst_false:
|
|
if (IO_XIP_EN = false) generate
|
|
resp_bus(RESP_XIP_CT) <= resp_bus_entry_terminate_c;
|
|
resp_bus(RESP_XIP_IF) <= resp_bus_entry_terminate_c;
|
|
--
|
|
xip_enable <= '0';
|
|
xip_access <= '0';
|
|
xip_page <= (others => '0');
|
|
xip_cg_en <= '0';
|
|
xip_csn_o <= '1';
|
|
xip_clk_o <= '0';
|
|
xip_sdo_o <= '0';
|
|
end generate;
|
|
|
|
|
|
-- ****************************************************************************************************************************
|
|
-- IO/Peripheral Modules
|
|
-- ****************************************************************************************************************************
|
|
|
|
|
-- IO Access? -----------------------------------------------------------------------------
|
-- IO Access? -----------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
io_acc <= '1' when (p_bus.addr(data_width_c-1 downto index_size_f(io_size_c)) = io_base_c(data_width_c-1 downto index_size_f(io_size_c))) else '0';
|
io_acc <= '1' when (p_bus.addr(data_width_c-1 downto index_size_f(io_size_c)) = io_base_c(data_width_c-1 downto index_size_f(io_size_c))) else '0';
|
io_rden <= io_acc and p_bus.re and (not p_bus.src); -- PMA: no_execute for IO region
|
io_rden <= io_acc and p_bus.re and (not p_bus.src); -- PMA: no_execute for IO region
|
-- the default NEORV32 peripheral/IO devices in the IO area can only be written in word mode (reduces HW complexity)
|
-- the default NEORV32 peripheral/IO devices in the IO area can only be written in word mode (reduces HW complexity)
|
Line 898... |
Line 977... |
end generate;
|
end generate;
|
|
|
neorv32_cfs_inst_false:
|
neorv32_cfs_inst_false:
|
if (IO_CFS_EN = false) generate
|
if (IO_CFS_EN = false) generate
|
resp_bus(RESP_CFS) <= resp_bus_entry_terminate_c;
|
resp_bus(RESP_CFS) <= resp_bus_entry_terminate_c;
|
|
--
|
cfs_cg_en <= '0';
|
cfs_cg_en <= '0';
|
cfs_irq <= '0';
|
cfs_irq <= '0';
|
cfs_out_o <= (others => '0');
|
cfs_out_o <= (others => '0');
|
end generate;
|
end generate;
|
|
|
Line 918... |
Line 998... |
rden_i => io_rden, -- read enable
|
rden_i => io_rden, -- read enable
|
wren_i => io_wren, -- write enable
|
wren_i => io_wren, -- write enable
|
data_i => p_bus.wdata, -- data in
|
data_i => p_bus.wdata, -- data in
|
data_o => resp_bus(RESP_GPIO).rdata, -- data out
|
data_o => resp_bus(RESP_GPIO).rdata, -- data out
|
ack_o => resp_bus(RESP_GPIO).ack, -- transfer acknowledge
|
ack_o => resp_bus(RESP_GPIO).ack, -- transfer acknowledge
|
|
err_o => resp_bus(RESP_GPIO).err, -- transfer error
|
-- parallel io --
|
-- parallel io --
|
gpio_o => gpio_o,
|
gpio_o => gpio_o,
|
gpio_i => gpio_i
|
gpio_i => gpio_i
|
);
|
);
|
resp_bus(RESP_GPIO).err <= '0'; -- no access error possible
|
|
end generate;
|
end generate;
|
|
|
neorv32_gpio_inst_false:
|
neorv32_gpio_inst_false:
|
if (IO_GPIO_EN = false) generate
|
if (IO_GPIO_EN = false) generate
|
resp_bus(RESP_GPIO) <= resp_bus_entry_terminate_c;
|
resp_bus(RESP_GPIO) <= resp_bus_entry_terminate_c;
|
|
--
|
gpio_o <= (others => '0');
|
gpio_o <= (others => '0');
|
end generate;
|
end generate;
|
|
|
|
|
-- Watch Dog Timer (WDT) ------------------------------------------------------------------
|
-- Watch Dog Timer (WDT) ------------------------------------------------------------------
|
Line 965... |
Line 1046... |
end generate;
|
end generate;
|
|
|
neorv32_wdt_inst_false:
|
neorv32_wdt_inst_false:
|
if (IO_WDT_EN = false) generate
|
if (IO_WDT_EN = false) generate
|
resp_bus(RESP_WDT) <= resp_bus_entry_terminate_c;
|
resp_bus(RESP_WDT) <= resp_bus_entry_terminate_c;
|
|
--
|
wdt_irq <= '0';
|
wdt_irq <= '0';
|
wdt_rstn <= '1';
|
wdt_rstn <= '1';
|
wdt_cg_en <= '0';
|
wdt_cg_en <= '0';
|
end generate;
|
end generate;
|
|
|
Line 996... |
Line 1078... |
end generate;
|
end generate;
|
|
|
neorv32_mtime_inst_false:
|
neorv32_mtime_inst_false:
|
if (IO_MTIME_EN = false) generate
|
if (IO_MTIME_EN = false) generate
|
resp_bus(RESP_MTIME) <= resp_bus_entry_terminate_c;
|
resp_bus(RESP_MTIME) <= resp_bus_entry_terminate_c;
|
|
--
|
mtime_time <= mtime_i; -- use external machine timer time signal
|
mtime_time <= mtime_i; -- use external machine timer time signal
|
mtime_irq <= mtime_irq_i; -- use external machine timer interrupt
|
mtime_irq <= mtime_irq_i; -- use external machine timer interrupt
|
end generate;
|
end generate;
|
|
|
|
|
Line 1059... |
Line 1142... |
end generate;
|
end generate;
|
|
|
neorv32_uart0_inst_false:
|
neorv32_uart0_inst_false:
|
if (IO_UART0_EN = false) generate
|
if (IO_UART0_EN = false) generate
|
resp_bus(RESP_UART0) <= resp_bus_entry_terminate_c;
|
resp_bus(RESP_UART0) <= resp_bus_entry_terminate_c;
|
|
--
|
uart0_txd_o <= '0';
|
uart0_txd_o <= '0';
|
uart0_rts_o <= '0';
|
uart0_rts_o <= '0';
|
uart0_cg_en <= '0';
|
uart0_cg_en <= '0';
|
uart0_rxd_irq <= '0';
|
uart0_rxd_irq <= '0';
|
uart0_txd_irq <= '0';
|
uart0_txd_irq <= '0';
|
Line 1105... |
Line 1189... |
end generate;
|
end generate;
|
|
|
neorv32_uart1_inst_false:
|
neorv32_uart1_inst_false:
|
if (IO_UART1_EN = false) generate
|
if (IO_UART1_EN = false) generate
|
resp_bus(RESP_UART1) <= resp_bus_entry_terminate_c;
|
resp_bus(RESP_UART1) <= resp_bus_entry_terminate_c;
|
|
--
|
uart1_txd_o <= '0';
|
uart1_txd_o <= '0';
|
uart1_rts_o <= '0';
|
uart1_rts_o <= '0';
|
uart1_cg_en <= '0';
|
uart1_cg_en <= '0';
|
uart1_rxd_irq <= '0';
|
uart1_rxd_irq <= '0';
|
uart1_txd_irq <= '0';
|
uart1_txd_irq <= '0';
|
Line 1144... |
Line 1229... |
end generate;
|
end generate;
|
|
|
neorv32_spi_inst_false:
|
neorv32_spi_inst_false:
|
if (IO_SPI_EN = false) generate
|
if (IO_SPI_EN = false) generate
|
resp_bus(RESP_SPI) <= resp_bus_entry_terminate_c;
|
resp_bus(RESP_SPI) <= resp_bus_entry_terminate_c;
|
|
--
|
spi_sck_o <= '0';
|
spi_sck_o <= '0';
|
spi_sdo_o <= '0';
|
spi_sdo_o <= '0';
|
spi_csn_o <= (others => '1'); -- CSn lines are low-active
|
spi_csn_o <= (others => '1'); -- CSn lines are low-active
|
spi_cg_en <= '0';
|
spi_cg_en <= '0';
|
spi_irq <= '0';
|
spi_irq <= '0';
|
Line 1181... |
Line 1267... |
end generate;
|
end generate;
|
|
|
neorv32_twi_inst_false:
|
neorv32_twi_inst_false:
|
if (IO_TWI_EN = false) generate
|
if (IO_TWI_EN = false) generate
|
resp_bus(RESP_TWI) <= resp_bus_entry_terminate_c;
|
resp_bus(RESP_TWI) <= resp_bus_entry_terminate_c;
|
|
--
|
twi_sda_io <= 'Z';
|
twi_sda_io <= 'Z';
|
twi_scl_io <= 'Z';
|
twi_scl_io <= 'Z';
|
twi_cg_en <= '0';
|
twi_cg_en <= '0';
|
twi_irq <= '0';
|
twi_irq <= '0';
|
end generate;
|
end generate;
|
Line 1217... |
Line 1304... |
end generate;
|
end generate;
|
|
|
neorv32_pwm_inst_false:
|
neorv32_pwm_inst_false:
|
if (IO_PWM_NUM_CH = 0) generate
|
if (IO_PWM_NUM_CH = 0) generate
|
resp_bus(RESP_PWM) <= resp_bus_entry_terminate_c;
|
resp_bus(RESP_PWM) <= resp_bus_entry_terminate_c;
|
|
--
|
pwm_cg_en <= '0';
|
pwm_cg_en <= '0';
|
pwm_o <= (others => '0');
|
pwm_o <= (others => '0');
|
end generate;
|
end generate;
|
|
|
|
|
Line 1277... |
Line 1365... |
end generate;
|
end generate;
|
|
|
neorv32_neoled_inst_false:
|
neorv32_neoled_inst_false:
|
if (IO_NEOLED_EN = false) generate
|
if (IO_NEOLED_EN = false) generate
|
resp_bus(RESP_NEOLED) <= resp_bus_entry_terminate_c;
|
resp_bus(RESP_NEOLED) <= resp_bus_entry_terminate_c;
|
|
--
|
neoled_cg_en <= '0';
|
neoled_cg_en <= '0';
|
neoled_irq <= '0';
|
neoled_irq <= '0';
|
neoled_o <= '0';
|
neoled_o <= '0';
|
end generate;
|
end generate;
|
|
|
Line 1321... |
Line 1410... |
end generate;
|
end generate;
|
|
|
neorv32_slink_inst_false:
|
neorv32_slink_inst_false:
|
if (io_slink_en_c = false) generate
|
if (io_slink_en_c = false) generate
|
resp_bus(RESP_SLINK) <= resp_bus_entry_terminate_c;
|
resp_bus(RESP_SLINK) <= resp_bus_entry_terminate_c;
|
|
--
|
slink_tx_irq <= '0';
|
slink_tx_irq <= '0';
|
slink_rx_irq <= '0';
|
slink_rx_irq <= '0';
|
slink_tx_dat_o <= (others => (others => '0'));
|
slink_tx_dat_o <= (others => (others => '0'));
|
slink_tx_val_o <= (others => '0');
|
slink_tx_val_o <= (others => '0');
|
slink_rx_rdy_o <= (others => '0');
|
slink_rx_rdy_o <= (others => '0');
|
Line 1359... |
Line 1449... |
end generate;
|
end generate;
|
|
|
neorv32_xirq_inst_false:
|
neorv32_xirq_inst_false:
|
if (XIRQ_NUM_CH = 0) generate
|
if (XIRQ_NUM_CH = 0) generate
|
resp_bus(RESP_XIRQ) <= resp_bus_entry_terminate_c;
|
resp_bus(RESP_XIRQ) <= resp_bus_entry_terminate_c;
|
|
--
|
xirq_irq <= '0';
|
xirq_irq <= '0';
|
end generate;
|
end generate;
|
|
|
|
|
-- General Purpose Timer (GPTMR) ----------------------------------------------------------
|
-- General Purpose Timer (GPTMR) ----------------------------------------------------------
|
Line 1389... |
Line 1480... |
end generate;
|
end generate;
|
|
|
neorv32_gptmr_inst_false:
|
neorv32_gptmr_inst_false:
|
if (IO_GPTMR_EN = false) generate
|
if (IO_GPTMR_EN = false) generate
|
resp_bus(RESP_GPTMR) <= resp_bus_entry_terminate_c;
|
resp_bus(RESP_GPTMR) <= resp_bus_entry_terminate_c;
|
|
--
|
gptmr_cg_en <= '0';
|
gptmr_cg_en <= '0';
|
gptmr_irq <= '0';
|
gptmr_irq <= '0';
|
end generate;
|
end generate;
|
|
|
|
|
Line 1445... |
Line 1537... |
IO_TRNG_EN => IO_TRNG_EN, -- implement true random number generator (TRNG)?
|
IO_TRNG_EN => IO_TRNG_EN, -- implement true random number generator (TRNG)?
|
IO_CFS_EN => IO_CFS_EN, -- implement custom functions subsystem (CFS)?
|
IO_CFS_EN => IO_CFS_EN, -- implement custom functions subsystem (CFS)?
|
IO_SLINK_EN => io_slink_en_c, -- implement stream link interface?
|
IO_SLINK_EN => io_slink_en_c, -- implement stream link interface?
|
IO_NEOLED_EN => IO_NEOLED_EN, -- implement NeoPixel-compatible smart LED interface (NEOLED)?
|
IO_NEOLED_EN => IO_NEOLED_EN, -- implement NeoPixel-compatible smart LED interface (NEOLED)?
|
IO_XIRQ_NUM_CH => XIRQ_NUM_CH, -- number of external interrupt (XIRQ) channels to implement
|
IO_XIRQ_NUM_CH => XIRQ_NUM_CH, -- number of external interrupt (XIRQ) channels to implement
|
IO_GPTMR_EN => IO_GPTMR_EN -- implement general purpose timer (GPTMR)?
|
IO_GPTMR_EN => IO_GPTMR_EN, -- implement general purpose timer (GPTMR)?
|
|
IO_XIP_EN => IO_XIP_EN -- implement execute in place module (XIP)?
|
)
|
)
|
port map (
|
port map (
|
-- host access --
|
-- host access --
|
clk_i => clk_i, -- global clock line
|
clk_i => clk_i, -- global clock line
|
addr_i => p_bus.addr, -- address
|
addr_i => p_bus.addr, -- address
|
rden_i => io_rden, -- read enable
|
rden_i => io_rden, -- read enable
|
|
wren_i => io_wren, -- write enable
|
data_o => resp_bus(RESP_SYSINFO).rdata, -- data out
|
data_o => resp_bus(RESP_SYSINFO).rdata, -- data out
|
ack_o => resp_bus(RESP_SYSINFO).ack -- transfer acknowledge
|
ack_o => resp_bus(RESP_SYSINFO).ack, -- transfer acknowledge
|
|
err_o => resp_bus(RESP_SYSINFO).err -- transfer error
|
);
|
);
|
|
|
resp_bus(RESP_SYSINFO).err <= '0'; -- no access error possible
|
|
|
|
|
|
-- **************************************************************************************************************************
|
-- **************************************************************************************************************************
|
-- On-Chip Debugger Complex
|
-- On-Chip Debugger Complex
|
-- **************************************************************************************************************************
|
-- **************************************************************************************************************************
|
|
|
Line 1500... |
Line 1593... |
resp_bus(RESP_OCD).err <= '0'; -- no access error possible
|
resp_bus(RESP_OCD).err <= '0'; -- no access error possible
|
end generate;
|
end generate;
|
|
|
neorv32_debug_dm_false:
|
neorv32_debug_dm_false:
|
if (ON_CHIP_DEBUGGER_EN = false) generate
|
if (ON_CHIP_DEBUGGER_EN = false) generate
|
|
--
|
dmi.req_ready <= '0';
|
dmi.req_ready <= '0';
|
dmi.resp_valid <= '0';
|
dmi.resp_valid <= '0';
|
dmi.resp_data <= (others => '0');
|
dmi.resp_data <= (others => '0');
|
dmi.resp_err <= '0';
|
dmi.resp_err <= '0';
|
--
|
--
|