URL
https://opencores.org/ocsvn/neorv32/neorv32/trunk
Subversion Repositories neorv32
Compare Revisions
- This comparison shows the changes necessary to convert path
/neorv32/trunk/rtl/core
- from Rev 29 to Rev 30
- ↔ Reverse comparison
Rev 29 → Rev 30
/neorv32_devnull.vhd
File deleted
/neorv32_cpu.vhd
67,9 → 67,7
-- Physical Memory Protection (PMP) -- |
PMP_USE : boolean := false; -- implement PMP? |
PMP_NUM_REGIONS : natural := 4; -- number of regions (max 8) |
PMP_GRANULARITY : natural := 14; -- minimal region granularity (1=8B, 2=16B, 3=32B, ...) default is 64k |
-- Bus Interface -- |
BUS_TIMEOUT : natural := 15 -- cycles after which a valid bus access will timeout |
PMP_GRANULARITY : natural := 14 -- minimal region granularity (1=8B, 2=16B, 3=32B, ...) default is 64k |
); |
port ( |
-- global control -- |
157,8 → 155,6
assert not ((PMP_NUM_REGIONS > pmp_max_r_c) and (PMP_USE = true)) report "NEORV32 CPU CONFIG ERROR! Number of PMP regions out of valid range." severity error; |
-- PMP granulartiy -- |
assert not (((PMP_GRANULARITY < 1) or (PMP_GRANULARITY > 32)) and (PMP_USE = true)) report "NEORV32 CPU CONFIG ERROR! Invalid PMP granulartiy (0 < G < 33)." severity error; |
-- Bus timeout -- |
assert not (BUS_TIMEOUT < 1) report "NEORV32 CPU CONFIG ERROR! Invalid bus timeout - must be at least 1 cycle." severity error; |
|
|
-- Control Unit --------------------------------------------------------------------------- |
315,7 → 311,6
neorv32_cpu_bus_inst: neorv32_cpu_bus |
generic map ( |
CPU_EXTENSION_RISCV_C => CPU_EXTENSION_RISCV_C, -- implement compressed extension? |
BUS_TIMEOUT => BUS_TIMEOUT, -- cycles after which a valid bus access will timeout |
-- Physical memory protection (PMP) -- |
PMP_USE => PMP_USE, -- implement physical memory protection? |
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (1..4) |
/neorv32_cpu_bus.vhd
44,7 → 44,6
entity neorv32_cpu_bus is |
generic ( |
CPU_EXTENSION_RISCV_C : boolean := true; -- implement compressed extension? |
BUS_TIMEOUT : natural := 15; -- cycles after which a valid bus access will timeout |
-- Physical memory protection (PMP) -- |
PMP_USE : boolean := false; -- implement physical memory protection? |
PMP_NUM_REGIONS : natural := 4; -- number of regions (1..4) |
135,7 → 134,7
wr_req : std_ulogic; -- write access in progress |
err_align : std_ulogic; -- alignment error |
err_bus : std_ulogic; -- bus access error |
timeout : std_ulogic_vector(index_size_f(BUS_TIMEOUT)-1 downto 0); |
timeout : std_ulogic_vector(index_size_f(bus_timeout_c)-1 downto 0); |
end record; |
signal i_arbiter, d_arbiter : bus_arbiter_t; |
|
314,7 → 313,7
i_arbiter.rd_req <= ctrl_i(ctrl_bus_if_c); |
i_arbiter.err_align <= i_misaligned; |
i_arbiter.err_bus <= '0'; |
i_arbiter.timeout <= std_ulogic_vector(to_unsigned(BUS_TIMEOUT, index_size_f(BUS_TIMEOUT))); |
i_arbiter.timeout <= std_ulogic_vector(to_unsigned(bus_timeout_c, index_size_f(bus_timeout_c))); |
else -- in progress |
i_arbiter.timeout <= std_ulogic_vector(unsigned(i_arbiter.timeout) - 1); |
i_arbiter.err_align <= (i_arbiter.err_align or i_misaligned) and (not ctrl_i(ctrl_bus_ierr_ack_c)); |
368,7 → 367,7
d_arbiter.rd_req <= ctrl_i(ctrl_bus_rd_c); |
d_arbiter.err_align <= d_misaligned; |
d_arbiter.err_bus <= '0'; |
d_arbiter.timeout <= std_ulogic_vector(to_unsigned(BUS_TIMEOUT, index_size_f(BUS_TIMEOUT))); |
d_arbiter.timeout <= std_ulogic_vector(to_unsigned(bus_timeout_c, index_size_f(bus_timeout_c))); |
else -- in progress |
d_arbiter.timeout <= std_ulogic_vector(unsigned(d_arbiter.timeout) - 1); |
d_arbiter.err_align <= (d_arbiter.err_align or d_misaligned) and (not ctrl_i(ctrl_bus_derr_ack_c)); |
/neorv32_cpu_control.vhd
925,6 → 925,8
-- ------------------------------------------------------------------------------------------- |
invalid_csr_access_check: process(execute_engine.i_reg, csr.privilege) |
variable is_m_mode_v : std_ulogic; |
variable csr_wacc_v : std_ulogic; -- to check access to read-only CSRs |
-- variable csr_racc_v : std_ulogic; -- to check access to write-only CSRs |
begin |
-- are we in machine mode? -- |
if (csr.privilege = priv_mode_m_c) then |
933,50 → 935,60
is_m_mode_v := '0'; |
end if; |
|
-- is this CSR instruction really going to write/read to/from a CSR? -- |
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or |
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) then |
csr_wacc_v := '1'; -- always write CSR |
-- csr_racc_v := or_all_f(execute_engine.i_reg(instr_rd_msb_c downto instr_rd_lsb_c)); -- read allowed if rd != 0 |
else |
csr_wacc_v := or_all_f(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c)); -- write allowed if rs1/uimm5 != 0 |
-- csr_racc_v := '1'; -- always read CSR |
end if; |
|
-- check CSR access -- |
case execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c) is |
when csr_mstatus_c => csr_acc_valid <= is_m_mode_v; |
when csr_misa_c => csr_acc_valid <= is_m_mode_v; |
when csr_mie_c => csr_acc_valid <= is_m_mode_v; |
when csr_mtvec_c => csr_acc_valid <= is_m_mode_v; |
when csr_mscratch_c => csr_acc_valid <= is_m_mode_v; |
when csr_mepc_c => csr_acc_valid <= is_m_mode_v; |
when csr_mcause_c => csr_acc_valid <= is_m_mode_v; |
when csr_mtval_c => csr_acc_valid <= is_m_mode_v; |
when csr_mip_c => csr_acc_valid <= is_m_mode_v; |
when csr_mstatus_c => csr_acc_valid <= is_m_mode_v; -- M-mode only |
when csr_misa_c => csr_acc_valid <= is_m_mode_v;-- and (not csr_wacc_v); -- M-mode only, MISA is read-only for the NEORV32 but we don't cause an exception here for compatibility |
when csr_mie_c => csr_acc_valid <= is_m_mode_v; -- M-mode only |
when csr_mtvec_c => csr_acc_valid <= is_m_mode_v; -- M-mode only |
when csr_mscratch_c => csr_acc_valid <= is_m_mode_v; -- M-mode only |
when csr_mepc_c => csr_acc_valid <= is_m_mode_v; -- M-mode only |
when csr_mcause_c => csr_acc_valid <= is_m_mode_v; -- M-mode only |
when csr_mtval_c => csr_acc_valid <= is_m_mode_v; -- M-mode only |
when csr_mip_c => csr_acc_valid <= is_m_mode_v; -- M-mode only |
-- |
when csr_pmpcfg0_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 1)) and is_m_mode_v; |
when csr_pmpcfg1_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 5)) and is_m_mode_v; |
when csr_pmpcfg0_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 1)) and is_m_mode_v; -- M-mode only |
when csr_pmpcfg1_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 5)) and is_m_mode_v; -- M-mode only |
-- |
when csr_pmpaddr0_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 1)) and is_m_mode_v; |
when csr_pmpaddr1_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 2)) and is_m_mode_v; |
when csr_pmpaddr2_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 3)) and is_m_mode_v; |
when csr_pmpaddr3_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 4)) and is_m_mode_v; |
when csr_pmpaddr4_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 5)) and is_m_mode_v; |
when csr_pmpaddr5_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 6)) and is_m_mode_v; |
when csr_pmpaddr6_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 7)) and is_m_mode_v; |
when csr_pmpaddr7_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 8)) and is_m_mode_v; |
when csr_pmpaddr0_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 1)) and is_m_mode_v; -- M-mode only |
when csr_pmpaddr1_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 2)) and is_m_mode_v; -- M-mode only |
when csr_pmpaddr2_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 3)) and is_m_mode_v; -- M-mode only |
when csr_pmpaddr3_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 4)) and is_m_mode_v; -- M-mode only |
when csr_pmpaddr4_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 5)) and is_m_mode_v; -- M-mode only |
when csr_pmpaddr5_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 6)) and is_m_mode_v; -- M-mode only |
when csr_pmpaddr6_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 7)) and is_m_mode_v; -- M-mode only |
when csr_pmpaddr7_c => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 8)) and is_m_mode_v; -- M-mode only |
-- |
when csr_mcycle_c => csr_acc_valid <= is_m_mode_v; |
when csr_minstret_c => csr_acc_valid <= is_m_mode_v; |
when csr_mcycle_c => csr_acc_valid <= is_m_mode_v; -- M-mode only |
when csr_minstret_c => csr_acc_valid <= is_m_mode_v; -- M-mode only |
-- |
when csr_mcycleh_c => csr_acc_valid <= is_m_mode_v; |
when csr_minstreth_c => csr_acc_valid <= is_m_mode_v; |
when csr_mcycleh_c => csr_acc_valid <= is_m_mode_v; -- M-mode only |
when csr_minstreth_c => csr_acc_valid <= is_m_mode_v; -- M-mode only |
-- |
when csr_cycle_c => csr_acc_valid <= '1'; |
when csr_time_c => csr_acc_valid <= '1'; |
when csr_instret_c => csr_acc_valid <= '1'; |
when csr_cycle_c => csr_acc_valid <= (not csr_wacc_v); -- all modes, read-only |
when csr_time_c => csr_acc_valid <= (not csr_wacc_v); -- all modes, read-only |
when csr_instret_c => csr_acc_valid <= (not csr_wacc_v); -- all modes, read-only |
-- |
when csr_cycleh_c => csr_acc_valid <= '1'; |
when csr_timeh_c => csr_acc_valid <= '1'; |
when csr_instreth_c => csr_acc_valid <= '1'; |
when csr_cycleh_c => csr_acc_valid <= (not csr_wacc_v); -- all modes, read-only |
when csr_timeh_c => csr_acc_valid <= (not csr_wacc_v); -- all modes, read-only |
when csr_instreth_c => csr_acc_valid <= (not csr_wacc_v); -- all modes, read-only |
-- |
when csr_mvendorid_c => csr_acc_valid <= is_m_mode_v; |
when csr_marchid_c => csr_acc_valid <= is_m_mode_v; |
when csr_mimpid_c => csr_acc_valid <= is_m_mode_v; |
when csr_mhartid_c => csr_acc_valid <= is_m_mode_v; |
when csr_mvendorid_c => csr_acc_valid <= is_m_mode_v and (not csr_wacc_v); -- M-mode only, read-only |
when csr_marchid_c => csr_acc_valid <= is_m_mode_v and (not csr_wacc_v); -- M-mode only, read-only |
when csr_mimpid_c => csr_acc_valid <= is_m_mode_v and (not csr_wacc_v); -- M-mode only, read-only |
when csr_mhartid_c => csr_acc_valid <= is_m_mode_v and (not csr_wacc_v); -- M-mode only, read-only |
-- |
when csr_mzext_c => csr_acc_valid <= is_m_mode_v; |
when csr_mzext_c => csr_acc_valid <= is_m_mode_v and (not csr_wacc_v); -- M-mode only, read-only |
-- |
when others => csr_acc_valid <= '0'; -- undefined, invalid access |
end case; |
1472,6 → 1484,11
if (execute_engine.i_reg(23 downto 20) = csr_mepc_c(3 downto 0)) then -- R/W: mepc - machine exception program counter |
csr.mepc <= csr.wdata(data_width_c-1 downto 1) & '0'; |
end if; |
if (execute_engine.i_reg(23 downto 20) = csr_mcause_c(3 downto 0)) then -- R/W: mcause - machine trap cause |
csr.mcause <= (others => '0'); |
csr.mcause(csr.mcause'left) <= csr.wdata(31); -- 1: interrupt, 0: exception |
csr.mcause(4 downto 0) <= csr.wdata(4 downto 0); -- identifier |
end if; |
if (execute_engine.i_reg(23 downto 20) = csr_mtval_c(3 downto 0)) then -- R/W: mtval - machine bad address or instruction |
csr.mtval <= csr.wdata; |
end if; |
1506,6 → 1523,11
|
-- mstatus: context switch -- |
if (trap_ctrl.env_start_ack = '1') then -- ENTER: trap handler starting? |
-- trap ID code -- |
csr.mcause <= (others => '0'); |
csr.mcause(csr.mcause'left) <= trap_ctrl.cause(trap_ctrl.cause'left); -- 1: interrupt, 0: exception |
csr.mcause(4 downto 0) <= trap_ctrl.cause(4 downto 0); -- identifier |
-- |
csr.mstatus_mie <= '0'; -- disable interrupts |
csr.mstatus_mpie <= csr.mstatus_mie; -- buffer previous mie state |
if (CPU_EXTENSION_RISCV_U = true) then -- implement user mode |
1527,18 → 1549,6
end if; |
end if; |
|
-- -------------------------------------------------------------------------------- |
-- CSRs that can be written by hardware only |
-- -------------------------------------------------------------------------------- |
|
-- mcause |
if (trap_ctrl.env_start_ack = '1') then -- trap handler starting? |
-- trap ID code -- |
csr.mcause <= (others => '0'); |
csr.mcause(csr.mcause'left) <= trap_ctrl.cause(trap_ctrl.cause'left); -- 1: interrupt, 0: exception |
csr.mcause(4 downto 0) <= trap_ctrl.cause(4 downto 0); -- identifier |
end if; |
|
end if; |
end process csr_write_access; |
|
/neorv32_package.vhd
41,7 → 41,7
-- Architecture Constants ----------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
constant data_width_c : natural := 32; -- data width - do not change! |
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01040402"; -- no touchy! |
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01040405"; -- no touchy! |
constant pmp_max_r_c : natural := 8; -- max PMP regions - FIXED! |
|
-- Architecture Configuration ------------------------------------------------------------- |
48,6 → 48,7
-- ------------------------------------------------------------------------------------------- |
constant ispace_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"00000000"; -- default instruction memory address space base address |
constant dspace_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"80000000"; -- default data memory address space base address |
constant bus_timeout_c : natural := 127; -- cycles after which a valid bus access will timeout and triggers an access exception |
constant ipb_entries_c : natural := 2; -- entries in instruction prefetch buffer, must be a power of 2, default=2 |
constant rf_r0_is_reg_c : boolean := true; -- reg_file.r0 is a physical register that has to be initialized to zero |
|
94,10 → 95,10
constant gpio_in_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF80"; |
constant gpio_out_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF84"; |
|
-- Dummy Device (with SIMULATION output) (DEVNULL) -- |
constant devnull_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF88"; -- base address, fixed! |
constant devnull_size_c : natural := 1*4; -- bytes |
constant devnull_data_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF88"; |
-- True Random Number Generator (TRNG) -- |
constant trng_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF88"; -- base address, fixed! |
constant trng_size_c : natural := 1*4; -- bytes |
constant trng_ctrl_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF88"; |
|
-- Watch Dog Timer (WDT) -- |
constant wdt_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFF8C"; -- base address, fixed! |
136,14 → 137,9
constant pwm_ctrl_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFB8"; |
constant pwm_duty_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFBC"; |
|
-- True Random Number Generator (TRNG) -- |
constant trng_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFC0"; -- base address, fixed! |
constant trng_size_c : natural := 1*4; -- bytes |
constant trng_ctrl_addr_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFC0"; |
|
-- RESERVED -- |
--constant ???_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFC4"; -- base address, fixed! |
--constant ???_size_c : natural := 3*4; -- bytes |
--constant ???_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFC0"; -- base address, fixed! |
--constant ???_size_c : natural := 4*4; -- bytes |
|
-- Custom Functions Unit (CFU) -- |
constant cfu_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"FFFFFFD0"; -- base address, fixed! |
178,7 → 174,7
constant ctrl_rf_rd_adr3_c : natural := 15; -- destiantion register address bit 3 |
constant ctrl_rf_rd_adr4_c : natural := 16; -- destiantion register address bit 4 |
constant ctrl_rf_wb_en_c : natural := 17; -- write back enable |
constant ctrl_rf_r0_we_c : natural := 18; -- allow write access to r0 (zero), also forces dst=r0 |
constant ctrl_rf_r0_we_c : natural := 18; -- allow write access to r0 (zero) |
-- alu -- |
constant ctrl_alu_cmd0_c : natural := 19; -- ALU command bit 0 |
constant ctrl_alu_cmd1_c : natural := 20; -- ALU command bit 1 |
471,7 → 467,6
-- External memory interface -- |
MEM_EXT_USE : boolean := false; -- implement external memory bus interface? |
MEM_EXT_REG_STAGES : natural := 2; -- number of interface register stages (0,1,2) |
MEM_EXT_TIMEOUT : natural := 15; -- cycles after which a valid bus access will timeout (>=1) |
-- Processor peripherals -- |
IO_GPIO_USE : boolean := true; -- implement general purpose input/output port unit (GPIO)? |
IO_MTIME_USE : boolean := true; -- implement machine system timer (MTIME)? |
481,7 → 476,6
IO_PWM_USE : boolean := true; -- implement pulse-width modulation unit (PWM)? |
IO_WDT_USE : boolean := true; -- implement watch dog timer (WDT)? |
IO_TRNG_USE : boolean := false; -- implement true random number generator (TRNG)? |
IO_DEVNULL_USE : boolean := true; -- implement dummy device (DEVNULL)? |
IO_CFU_USE : boolean := false -- implement custom functions unit (CFU)? |
); |
port ( |
542,9 → 536,7
-- Physical Memory Protection (PMP) -- |
PMP_USE : boolean := false; -- implement PMP? |
PMP_NUM_REGIONS : natural := 4; -- number of regions (max 8) |
PMP_GRANULARITY : natural := 14; -- minimal region granularity (1=8B, 2=16B, 3=32B, ...) default is 64k |
-- Bus Interface -- |
BUS_TIMEOUT : natural := 15 -- cycles after which a valid bus access will timeout |
PMP_GRANULARITY : natural := 14 -- minimal region granularity (1=8B, 2=16B, 3=32B, ...) default is 64k |
); |
port ( |
-- global control -- |
722,7 → 714,6
component neorv32_cpu_bus |
generic ( |
CPU_EXTENSION_RISCV_C : boolean := true; -- implement compressed extension? |
BUS_TIMEOUT : natural := 15; -- cycles after which a valid bus access will timeout |
-- Physical memory protection (PMP) -- |
PMP_USE : boolean := false; -- implement physical memory protection? |
PMP_NUM_REGIONS : natural := 4; -- number of regions (1..4) |
1100,21 → 1091,6
); |
end component; |
|
-- Component: Dummy Device with SIM Output (DEVNULL) -------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
component neorv32_devnull |
port ( |
-- host access -- |
clk_i : in std_ulogic; -- global clock line |
addr_i : in std_ulogic_vector(31 downto 0); -- address |
rden_i : in std_ulogic; -- read enable |
wren_i : in std_ulogic; -- write enable |
data_i : in std_ulogic_vector(31 downto 0); -- data in |
data_o : out std_ulogic_vector(31 downto 0); -- data out |
ack_o : out std_ulogic -- transfer acknowledge |
); |
end component; |
|
-- Component: Custom Functions Unit (CFU) ------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
component neorv32_cfu |
1164,7 → 1140,6
IO_PWM_USE : boolean := true; -- implement pulse-width modulation unit (PWM)? |
IO_WDT_USE : boolean := true; -- implement watch dog timer (WDT)? |
IO_TRNG_USE : boolean := true; -- implement true random number generator (TRNG)? |
IO_DEVNULL_USE : boolean := true; -- implement dummy device (DEVNULL)? |
IO_CFU_USE : boolean := true -- implement custom functions unit (CFU)? |
); |
port ( |
/neorv32_sysinfo.vhd
66,7 → 66,6
IO_PWM_USE : boolean := true; -- implement pulse-width modulation unit (PWM)? |
IO_WDT_USE : boolean := true; -- implement watch dog timer (WDT)? |
IO_TRNG_USE : boolean := true; -- implement true random number generator (TRNG)? |
IO_DEVNULL_USE : boolean := true; -- implement dummy device (DEVNULL)? |
IO_CFU_USE : boolean := true -- implement custom functions unit (CFU)? |
); |
port ( |
133,9 → 132,8
sysinfo_mem(2)(22) <= bool_to_ulogic_f(IO_WDT_USE); -- watch dog timer (WDT) implemented? |
sysinfo_mem(2)(23) <= bool_to_ulogic_f(IO_CFU_USE); -- custom functions unit (CFU) implemented? |
sysinfo_mem(2)(24) <= bool_to_ulogic_f(IO_TRNG_USE); -- true random number generator (TRNG) implemented? |
sysinfo_mem(2)(25) <= bool_to_ulogic_f(IO_DEVNULL_USE); -- dummy device (DEVNULL) implemented? |
-- |
sysinfo_mem(2)(31 downto 26) <= (others => '0'); -- reserved |
sysinfo_mem(2)(31 downto 25) <= (others => '0'); -- reserved |
|
-- SYSINFO(3): reserved -- |
sysinfo_mem(3) <= (others => '0'); -- reserved |
/neorv32_top.vhd
74,7 → 74,6
-- External memory interface -- |
MEM_EXT_USE : boolean := false; -- implement external memory bus interface? |
MEM_EXT_REG_STAGES : natural := 2; -- number of interface register stages (0,1,2) |
MEM_EXT_TIMEOUT : natural := 15; -- cycles after which a valid bus access will timeout |
-- Processor peripherals -- |
IO_GPIO_USE : boolean := true; -- implement general purpose input/output port unit (GPIO)? |
IO_MTIME_USE : boolean := true; -- implement machine system timer (MTIME)? |
84,7 → 83,6
IO_PWM_USE : boolean := true; -- implement pulse-width modulation unit (PWM)? |
IO_WDT_USE : boolean := true; -- implement watch dog timer (WDT)? |
IO_TRNG_USE : boolean := false; -- implement true random number generator (TRNG)? |
IO_DEVNULL_USE : boolean := true; -- implement dummy device (DEVNULL)? |
IO_CFU_USE : boolean := false -- implement custom functions unit (CFU)? |
); |
port ( |
201,8 → 199,6
signal wdt_ack : std_ulogic; |
signal trng_rdata : std_ulogic_vector(data_width_c-1 downto 0); |
signal trng_ack : std_ulogic; |
signal devnull_rdata : std_ulogic_vector(data_width_c-1 downto 0); |
signal devnull_ack : std_ulogic; |
signal cfu_rdata : std_ulogic_vector(data_width_c-1 downto 0); |
signal cfu_ack : std_ulogic; |
signal sysinfo_rdata : std_ulogic_vector(data_width_c-1 downto 0); |
236,8 → 232,6
assert not (dspace_base_c(1 downto 0) /= "00") report "NEORV32 PROCESSOR CONFIG ERROR! Data memory space base address must be 4-byte-aligned." severity error; |
assert not ((ispace_base_c(index_size_f(MEM_INT_IMEM_SIZE)-1 downto 0) /= imem_align_check_c) and (MEM_INT_IMEM_USE = true)) report "NEORV32 PROCESSOR CONFIG ERROR! Instruction memory space base address has to be aligned to IMEM size." severity error; |
assert not ((dspace_base_c(index_size_f(MEM_INT_DMEM_SIZE)-1 downto 0) /= dmem_align_check_c) and (MEM_INT_DMEM_USE = true)) report "NEORV32 PROCESSOR CONFIG ERROR! Data memory space base address has to be aligned to DMEM size." severity error; |
-- memory system - max latency -- |
assert not (MEM_EXT_TIMEOUT < 1) report "NEORV32 PROCESSOR CONFIG ERROR! Invalid bus timeout. Processor-internal components have 1 cycle latency." severity error; |
-- clock -- |
assert not (CLOCK_FREQUENCY = 0) report "NEORV32 PROCESSOR CONFIG ERROR! Core clock frequency (CLOCK_FREQUENCY) not specified." severity error; |
-- memory layout notifier -- |
322,9 → 316,7
-- Physical Memory Protection (PMP) -- |
PMP_USE => PMP_USE, -- implement PMP? |
PMP_NUM_REGIONS => PMP_NUM_REGIONS, -- number of regions (max 8) |
PMP_GRANULARITY => PMP_GRANULARITY, -- minimal region granularity (1=8B, 2=16B, 3=32B, ...) default is 64k |
-- Bus Interface -- |
BUS_TIMEOUT => MEM_EXT_TIMEOUT -- cycles after which a valid bus access will timeout |
PMP_GRANULARITY => PMP_GRANULARITY -- minimal region granularity (1=8B, 2=16B, 3=32B, ...) default is 64k |
) |
port map ( |
-- global control -- |
418,11 → 410,11
|
-- processor bus: CPU data input -- |
p_bus.rdata <= (imem_rdata or dmem_rdata or bootrom_rdata) or wishbone_rdata or (gpio_rdata or mtime_rdata or uart_rdata or |
spi_rdata or twi_rdata or pwm_rdata or wdt_rdata or trng_rdata or devnull_rdata or cfu_rdata or sysinfo_rdata); |
spi_rdata or twi_rdata or pwm_rdata or wdt_rdata or trng_rdata or cfu_rdata or sysinfo_rdata); |
|
-- processor bus: CPU data ACK input -- |
p_bus.ack <= (imem_ack or dmem_ack or bootrom_ack) or wishbone_ack or (gpio_ack or mtime_ack or uart_ack or |
spi_ack or twi_ack or pwm_ack or wdt_ack or trng_ack or devnull_ack or cfu_ack or sysinfo_ack); |
spi_ack or twi_ack or pwm_ack or wdt_ack or trng_ack or cfu_ack or sysinfo_ack); |
|
-- processor bus: CPU data bus error input -- |
p_bus.err <= wishbone_err; |
837,30 → 829,6
end generate; |
|
|
-- Dummy Device (DEVNULL) ----------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
neorv32_devnull_inst_true: |
if (IO_DEVNULL_USE = true) generate |
neorv32_devnull_inst: neorv32_devnull |
port map ( |
-- host access -- |
clk_i => clk_i, -- global clock line |
addr_i => p_bus.addr, -- address |
rden_i => io_rden, -- read enable |
wren_i => io_wren, -- write enable |
data_i => p_bus.wdata, -- data in |
data_o => devnull_rdata, -- data out |
ack_o => devnull_ack -- transfer acknowledge |
); |
end generate; |
|
neorv32_devnull_inst_false: |
if (IO_DEVNULL_USE = false) generate |
devnull_rdata <= (others => '0'); |
devnull_ack <= '0'; |
end generate; |
|
|
-- Custom Functions Unit (CFU) ------------------------------------------------------------ |
-- ------------------------------------------------------------------------------------------- |
neorv32_cfu_inst_true: |
921,7 → 889,6
IO_PWM_USE => IO_PWM_USE, -- implement pulse-width modulation unit (PWM)? |
IO_WDT_USE => IO_WDT_USE, -- implement watch dog timer (WDT)? |
IO_TRNG_USE => IO_TRNG_USE, -- implement true random number generator (TRNG)? |
IO_DEVNULL_USE => IO_DEVNULL_USE, -- implement dummy device (DEVNULL)? |
IO_CFU_USE => IO_CFU_USE -- implement custom functions unit (CFU)? |
) |
port map ( |
/neorv32_uart.vhd
4,6 → 4,14
-- # Fixed frame config: 8-bit, no parity bit, 1 stop bit, programmable BAUD rate (via clock pre- # |
-- # scaler and BAUD value config register. # |
-- # Interrupt: UART_RX_available or UART_TX_done # |
-- # # |
-- # SIMULATION: # |
-- # When the simulation mode is enabled (setting the ctrl.ctrl_uart_sim_en_c bit) any write # |
-- # access to the TX register will not trigger any UART activity. Instead, the written data is # |
-- # output to the simulation environment. The lowest 8 bits of the written data are printed as # |
-- # ASCII char to the simulator console. This char is also stored to a text file # |
-- # "neorv32.uart.sim_mode.text.out". The full 32-bit write data is also stored as 8-hex char # |
-- # encoded value to text file "neorv32.uart.sim_mode.data.out". # |
-- # ********************************************************************************************* # |
-- # BSD 3-Clause License # |
-- # # |
42,6 → 50,7
|
library neorv32; |
use neorv32.neorv32_package.all; |
use std.textio.all; -- obviously only for simulation |
|
entity neorv32_uart is |
port ( |
66,6 → 75,11
|
architecture neorv32_uart_rtl of neorv32_uart is |
|
-- simulation output configuration -- |
constant sim_screen_output_en_c : boolean := true; -- output lowest byte as char to simulator console when enabled |
constant sim_text_output_en_c : boolean := true; -- output lowest byte as char to text file when enabled |
constant sim_data_output_en_c : boolean := true; -- dump 32-word to file when enabled |
|
-- IO space: module base address -- |
constant hi_abb_c : natural := index_size_f(io_size_c)-1; -- high address boundary bit |
constant lo_abb_c : natural := index_size_f(uart_size_c); -- low address boundary bit |
88,6 → 102,8
constant ctrl_uart_baud10_c : natural := 10; -- r/w: UART baud config bit 10 |
constant ctrl_uart_baud11_c : natural := 11; -- r/w: UART baud config bit 11 |
-- |
constant ctrl_uart_sim_en_c : natural := 12; -- r/w: UART SIMULATION OUTPUT enable |
-- |
constant ctrl_uart_prsc0_c : natural := 24; -- r/w: UART baud prsc bit 0 |
constant ctrl_uart_prsc1_c : natural := 25; -- r/w: UART baud prsc bit 1 |
constant ctrl_uart_prsc2_c : natural := 26; -- r/w: UART baud prsc bit 2 |
180,11 → 196,11
if rising_edge(clk_i) then |
-- serial engine -- |
uart_tx_done <= '0'; |
if (uart_tx_busy = '0') or (ctrl(ctrl_uart_en_c) = '0') then -- idle or disabled |
if (uart_tx_busy = '0') or (ctrl(ctrl_uart_en_c) = '0') or (ctrl(ctrl_uart_sim_en_c) = '1') then -- idle or disabled or in SIM mode |
uart_tx_busy <= '0'; |
uart_tx_baud_cnt <= ctrl(ctrl_uart_baud11_c downto ctrl_uart_baud00_c); |
uart_tx_bitcnt <= "1010"; -- 10 bit |
if (wr_en = '1') and (ctrl(ctrl_uart_en_c) = '1') and (addr = uart_rtx_addr_c) then |
if (wr_en = '1') and (ctrl(ctrl_uart_en_c) = '1') and (addr = uart_rtx_addr_c) and (ctrl(ctrl_uart_sim_en_c) = '0') then -- write trigger and not in SIM mode |
uart_tx_sreg <= '1' & data_i(7 downto 0) & '0'; -- stopbit & data & startbit |
uart_tx_busy <= '1'; |
end if; |
256,4 → 272,56
uart_irq_o <= (uart_rx_busy_ff and (not uart_rx_busy) and ctrl(ctrl_uart_rx_irq_c)) or (uart_tx_done and ctrl(ctrl_uart_tx_irq_c)); |
|
|
-- SIMULATION Output ---------------------------------------------------------------------- |
-- ------------------------------------------------------------------------------------------- |
sim_output: process(clk_i) -- for SIMULATION ONLY! |
file file_devnull_text_out : text open write_mode is "neorv32.uart.sim_mode.text.out"; |
file file_devnull_data_out : text open write_mode is "neorv32.uart.sim_mode.data.out"; |
variable char_v : integer; |
variable line_screen_v : line; -- we need several line variables here since "writeline" seems to flush the source variable |
variable line_text_v : line; |
variable line_data_v : line; |
begin |
if rising_edge(clk_i) then |
if (ctrl(ctrl_uart_en_c) = '1') and (ctrl(ctrl_uart_sim_en_c) = '1') then -- UART enabled and simulation output selected? |
if (wr_en = '1') and (addr = uart_rtx_addr_c) then -- write access to tx register |
|
-- print lowest byte to ASCII char -- |
char_v := to_integer(unsigned(data_i(7 downto 0))); |
if (char_v >= 128) then -- out of range? |
char_v := 0; |
end if; |
|
if (char_v /= 10) and (char_v /= 13) then -- skip line breaks - they are issued via "writeline" |
if (sim_screen_output_en_c = true) then |
write(line_screen_v, character'val(char_v)); |
end if; |
if (sim_text_output_en_c = true) then |
write(line_text_v, character'val(char_v)); |
end if; |
end if; |
|
if (char_v = 10) then -- line break: write to screen and text file |
if (sim_screen_output_en_c = true) then |
writeline(output, line_screen_v); |
end if; |
if (sim_text_output_en_c = true) then |
writeline(file_devnull_text_out, line_text_v); |
end if; |
end if; |
|
-- dump raw data as 8 hex char text to file -- |
if (sim_data_output_en_c = true) then |
for x in 7 downto 0 loop |
write(line_data_v, to_hexchar_f(data_i(3+x*4 downto 0+x*4))); -- write in hex form |
end loop; -- x |
writeline(file_devnull_data_out, line_data_v); |
end if; |
|
end if; |
end if; |
end if; |
end process sim_output; |
|
|
end neorv32_uart_rtl; |