OpenCores
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;

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.