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 37 to Rev 38
    Reverse comparison

Rev 37 → Rev 38

/neorv32_cpu.vhd
10,6 → 10,8
-- # * neorv32_cpu_decompressor.vhd - Compressed instructions decoder #
-- # * neorv32_cpu_regfile.vhd - Data register file #
-- # #
-- # * neorv32_package.vhd - Main CPU/processor package file #
-- # #
-- # Check out the processor's data sheet for more information: docs/NEORV32.pdf #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
159,6 → 161,8
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 < PMP_GRANULARITY < 33)." severity error;
-- Instruction prefetch buffer size --
assert not (is_power_of_two_f(ipb_entries_c) = false) report "NEORV32 CPU CONFIG ERROR! Number of entries in instruction prefetch buffer <ipb_entries_c> has to be a power of two." severity error;
 
 
-- Control Unit ---------------------------------------------------------------------------
289,7 → 293,7
if (CPU_EXTENSION_RISCV_M = true) generate
neorv32_cpu_cp_muldiv_inst: neorv32_cpu_cp_muldiv
generic map (
FAST_MUL_EN => FAST_MUL_EN -- use DSPs for faster multiplication
FAST_MUL_EN => FAST_MUL_EN -- use DSPs for faster multiplication
)
port map (
-- global control --
313,7 → 317,7
end generate;
 
 
-- Co-Processor 1: Not implemented yet ----------------------------------------------------
-- Co-Processor 1: Not implemented (yet) --------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- control: ctrl cp1_start
-- inputs: rs1 rs2 alu_cmp alu_opb
321,7 → 325,7
cp1_valid <= '0';
 
 
-- Co-Processor 2: Not implemented yet ----------------------------------------------------
-- Co-Processor 2: Not implemented (yet) --------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- control: ctrl cp2_start
-- inputs: rs1 rs2 alu_cmp alu_opb
329,7 → 333,7
cp2_valid <= '0';
 
 
-- Co-Processor 3: Not implemented yet ----------------------------------------------------
-- Co-Processor 3: Not implemented (yet) --------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- control: ctrl cp3_start
-- inputs: rs1 rs2 alu_cmp alu_opb
350,6 → 354,7
port map (
-- global control --
clk_i => clk_i, -- global clock, rising edge
rstn_i => rstn_i, -- global reset, low-active, async
ctrl_i => ctrl, -- main control bus
-- cpu instruction fetch interface --
fetch_pc_i => fetch_pc, -- PC for instruction fetch
/neorv32_cpu_bus.vhd
52,6 → 52,7
port (
-- global control --
clk_i : in std_ulogic; -- global clock, rising edge
rstn_i : in std_ulogic := '0'; -- global reset, low-active, async
ctrl_i : in std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus
-- cpu instruction fetch interface --
fetch_pc_i : in std_ulogic_vector(data_width_c-1 downto 0); -- PC for instruction fetch
289,9 → 290,14
 
-- Instruction Fetch Arbiter --------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
ifetch_arbiter: process(clk_i)
ifetch_arbiter: process(rstn_i, clk_i)
begin
if rising_edge(clk_i) then
if (rstn_i = '0') then
i_arbiter.rd_req <= '0';
i_arbiter.err_align <= '0';
i_arbiter.err_bus <= '0';
i_arbiter.timeout <= (others => '0');
elsif rising_edge(clk_i) then
-- instruction fetch request --
if (i_arbiter.rd_req = '0') then -- idle
i_arbiter.rd_req <= ctrl_i(ctrl_bus_if_c);
333,9 → 339,15
 
-- Data Access Arbiter --------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
data_access_arbiter: process(clk_i)
data_access_arbiter: process(rstn_i, clk_i)
begin
if rising_edge(clk_i) then
if (rstn_i = '0') then
d_arbiter.wr_req <= '0';
d_arbiter.rd_req <= '0';
d_arbiter.err_align <= '0';
d_arbiter.err_bus <= '0';
d_arbiter.timeout <= (others => '0');
elsif rising_edge(clk_i) then
-- data access request --
if (d_arbiter.wr_req = '0') and (d_arbiter.rd_req = '0') then -- idle
d_arbiter.wr_req <= ctrl_i(ctrl_bus_wr_c);
/neorv32_cpu_control.vhd
521,11 → 521,11
 
-- Immediate Generator --------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
imm_gen: process(clk_i)
imm_gen: process(execute_engine.i_reg, clk_i)
variable opcode_v : std_ulogic_vector(6 downto 0);
begin
opcode_v := execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c+2) & "11";
if rising_edge(clk_i) then
opcode_v := execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c+2) & "11";
case opcode_v is -- save some bits here, LSBs are always 11 for rv32
when opcode_store_c => -- S-immediate
imm_o(31 downto 11) <= (others => execute_engine.i_reg(31)); -- sign extension
1233,7 → 1233,7
 
 
-- ****************************************************************************************************************************
-- Exception and Interrupt Control
-- Exception and Interrupt (= Trap) Control
-- ****************************************************************************************************************************
 
 
1305,7 → 1305,7
trap_ctrl.cause_nxt <= (others => '0');
trap_ctrl.irq_ack_nxt <= (others => '0');
 
-- the following traps are caused by asynchronous exceptions (-> interrupts)
-- the following traps are caused by *asynchronous* exceptions (= interrupts)
-- here we do need a specific acknowledge mask since several sources can trigger at once
 
-- interrupt: 1.11 machine external interrupt --
1345,45 → 1345,45
trap_ctrl.irq_ack_nxt(interrupt_firq_3_c) <= '1';
 
 
-- the following traps are caused by synchronous exceptions
-- the following traps are caused by *synchronous* exceptions (= classic exceptions)
-- here we do not need a specific acknowledge mask since only one exception (the one
-- with highest priority) can trigger at once
-- with highest priority) is evaluated at once
 
-- trap/fault: 0.1 instruction access fault --
-- exception: 0.1 instruction access fault --
elsif (trap_ctrl.exc_buf(exception_iaccess_c) = '1') then
trap_ctrl.cause_nxt <= trap_iba_c;
 
-- trap/fault: 0.2 illegal instruction --
-- exception: 0.2 illegal instruction --
elsif (trap_ctrl.exc_buf(exception_iillegal_c) = '1') then
trap_ctrl.cause_nxt <= trap_iil_c;
 
-- trap/fault: 0.0 instruction address misaligned --
-- exception: 0.0 instruction address misaligned --
elsif (trap_ctrl.exc_buf(exception_ialign_c) = '1') then
trap_ctrl.cause_nxt <= trap_ima_c;
 
 
-- trap/fault: 0.11 environment call from M-mode --
-- exception: 0.11 environment call from M-mode --
elsif (trap_ctrl.exc_buf(exception_m_envcall_c) = '1') then
trap_ctrl.cause_nxt <= trap_menv_c;
 
-- trap/fault: 0.3 breakpoint --
-- exception: 0.3 breakpoint --
elsif (trap_ctrl.exc_buf(exception_break_c) = '1') then
trap_ctrl.cause_nxt <= trap_brk_c;
 
 
-- trap/fault: 0.6 store address misaligned -
-- exception: 0.6 store address misaligned -
elsif (trap_ctrl.exc_buf(exception_salign_c) = '1') then
trap_ctrl.cause_nxt <= trap_sma_c;
 
-- trap/fault: 0.4 load address misaligned --
-- exception: 0.4 load address misaligned --
elsif (trap_ctrl.exc_buf(exception_lalign_c) = '1') then
trap_ctrl.cause_nxt <= trap_lma_c;
 
-- trap/fault: 0.7 store access fault --
-- exception: 0.7 store access fault --
elsif (trap_ctrl.exc_buf(exception_saccess_c) = '1') then
trap_ctrl.cause_nxt <= trap_sbe_c;
 
-- trap/fault: 0.5 load access fault --
-- exception: 0.5 load access fault --
elsif (trap_ctrl.exc_buf(exception_laccess_c) = '1') then
trap_ctrl.cause_nxt <= trap_lbe_c;
 
1407,11 → 1407,11
-- CSR operand source --
if (execute_engine.i_reg(instr_funct3_msb_c) = '1') then -- immediate
csr_operand_v := (others => '0');
csr_operand_v(4 downto 0) := execute_engine.i_reg(19 downto 15);
csr_operand_v(4 downto 0) := execute_engine.i_reg(19 downto 15); -- uimm5
else -- register
csr_operand_v := rs1_i;
end if;
-- "mini ALU" for CSR update operations --
-- tiny ALU for CSR access operations --
case execute_engine.i_reg(instr_funct3_lsb_c+1 downto instr_funct3_lsb_c) is
when "10" => csr.wdata <= csr.rdata or csr_operand_v; -- CSRRS(I)
when "11" => csr.wdata <= csr.rdata and (not csr_operand_v); -- CSRRC(I)
1680,7 → 1680,9
csr.rdata(00) <= '0'; -- A CPU extension
csr.rdata(01) <= '0'; -- B CPU extension
csr.rdata(02) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_C); -- C CPU extension
csr.rdata(03) <= '0'; -- D CPU extension
csr.rdata(04) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- E CPU extension
csr.rdata(05) <= '0'; -- F CPU extension
csr.rdata(08) <= not bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- I CPU extension (if not E)
csr.rdata(12) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_M); -- M CPU extension
csr.rdata(20) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_U); -- U CPU extension
/neorv32_imem.vhd
57,7 → 57,6
rden_i : in std_ulogic; -- read enable
wren_i : in std_ulogic; -- write enable
ben_i : in std_ulogic_vector(03 downto 0); -- byte write enable
upen_i : in std_ulogic; -- update enable
addr_i : in std_ulogic_vector(31 downto 0); -- address
data_i : in std_ulogic_vector(31 downto 0); -- data in
data_o : out std_ulogic_vector(31 downto 0); -- data out
167,7 → 166,7
rdata(31 downto 24) <= imem_file_rom_hh(to_integer(unsigned(addr)));
 
elsif (BOOTLOADER_USE = true) then -- implement IMEM as non-initialized RAM
if (wren_i = '1') and (upen_i = '1') then
if (wren_i = '1') then
if (ben_i(0) = '1') then
imem_file_ram_ll(to_integer(unsigned(addr))) <= data_i(07 downto 00);
end if;
187,7 → 186,7
rdata(31 downto 24) <= imem_file_ram_hh(to_integer(unsigned(addr)));
 
else -- implement IMEM as PRE-INITIALIZED RAM
if (wren_i = '1') and (upen_i = '1') then
if (wren_i = '1') then
if (ben_i(0) = '1') then
imem_file_init_ram_ll(to_integer(unsigned(addr))) <= data_i(07 downto 00);
end if;
/neorv32_package.vhd
42,7 → 42,7
-- -------------------------------------------------------------------------------------------
constant ispace_base_c : std_ulogic_vector(31 downto 0) := x"00000000"; -- default instruction memory address space base address
constant dspace_base_c : std_ulogic_vector(31 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 trigger an access exception
constant bus_timeout_c : natural := 127; -- cycles after which an *unacknwoledged* bus access will timeout and trigger an access exception
constant wb_pipe_mode_c : boolean := false; -- false: classic/standard wishbone mode, true: pipelined wishbone mode
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 by the CPU HW
50,7 → 50,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"01040700"; -- no touchy!
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01040702"; -- no touchy!
constant pmp_max_r_c : natural := 8; -- max PMP regions - FIXED!
constant archid_c : natural := 19; -- official NEORV32 architecture ID - hands off!
 
762,6 → 762,7
port (
-- global control --
clk_i : in std_ulogic; -- global clock, rising edge
rstn_i : in std_ulogic := '0'; -- global reset, low-active, async
ctrl_i : in std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus
-- cpu instruction fetch interface --
fetch_pc_i : in std_ulogic_vector(data_width_c-1 downto 0); -- PC for instruction fetch
880,7 → 881,6
rden_i : in std_ulogic; -- read enable
wren_i : in std_ulogic; -- write enable
ben_i : in std_ulogic_vector(03 downto 0); -- byte write enable
upen_i : in std_ulogic; -- update enable
addr_i : in std_ulogic_vector(31 downto 0); -- address
data_i : in std_ulogic_vector(31 downto 0); -- data in
data_o : out std_ulogic_vector(31 downto 0); -- data out
1361,8 → 1361,10
-- -------------------------------------------------------------------------------------------
function is_power_of_two_f(input : natural) return boolean is
begin
if ((input / 2) /= 0) and ((input mod 2) = 0) then
if (input = 1) then -- 2^0
return true;
elsif ((input / 2) /= 0) and ((input mod 2) = 0) then
return true;
else
return false;
end if;
/neorv32_top.vhd
463,7 → 463,6
rden_i => p_bus.re, -- read enable
wren_i => p_bus.we, -- write enable
ben_i => p_bus.ben, -- byte write enable
upen_i => '1', -- update enable
addr_i => p_bus.addr, -- address
data_i => p_bus.wdata, -- data in
data_o => imem_rdata, -- data out
/neorv32_wishbone.vhd
101,7 → 101,7
signal wb_access : std_ulogic;
 
-- bus arbiter
type ctrl_state_t is (IDLE, BUSY, CANCELED);
type ctrl_state_t is (IDLE, BUSY, CANCELED, RESYNC);
type ctrl_t is record
state : ctrl_state_t;
state_prev : ctrl_state_t;
204,7 → 204,7
ctrl.state <= IDLE;
end if;
 
when CANCELED => --
when CANCELED => -- wait for cycle to be completed either by peripheral or by timeout (ignore result of transfer)
-- ------------------------------------------------------------
ctrl.wr_req <= ctrl.wr_req or wren_i; -- buffer new request
ctrl.rd_req <= ctrl.rd_req or rden_i; -- buffer new request
212,6 → 212,12
-- or wait for a timeout and force termination
ctrl.timeout <= std_ulogic_vector(unsigned(ctrl.timeout) - 1); -- timeout counter
if (wb_ack_i = '1') or (or_all_f(ctrl.timeout) = '0') then
ctrl.state <= RESYNC;
end if;
 
when RESYNC => -- make sure transfer is done!
-- ------------------------------------------------------------
if (wb_ack_i = '0') then
ctrl.state <= IDLE;
end if;
 
241,7 → 247,7
wb_cyc_o <= cyc_int;
 
stb_int <= '1' when ((ctrl.state = BUSY) and (ctrl.state_prev = IDLE)) else '0';
cyc_int <= '0' when (ctrl.state = IDLE) else '1';
cyc_int <= '0' when ((ctrl.state = IDLE) or (ctrl.state = RESYNC)) else '1';
 
 
end neorv32_wishbone_rtl;

powered by: WebSVN 2.1.0

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