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
    from Rev 25 to Rev 26
    Reverse comparison

Rev 25 → Rev 26

/docs/NEORV32.pdf Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
/rtl/core/neorv32_cfu.vhd
142,7 → 142,7
begin
if rising_edge(clk_i) then
-- transfer ack --
ack_o <= wr_en or rd_en;
ack_o <= wr_en or rd_en; -- required for the CPU to check the CFU is answering a bus read OR write request
 
-- write access --
if (wr_en = '1') then
163,15 → 163,13
-- read access --
data_o <= (others => '0'); -- make sure the output is zero if there is no actual read access
if (rd_en = '1') then
if (addr = cfu_reg0_addr_c) then
data_o <= cfu_reg_out(0);
elsif (addr = cfu_reg1_addr_c) then
data_o <= cfu_reg_out(1);
elsif (addr = cfu_reg2_addr_c) then
data_o <= cfu_reg_out(2);
else -- addr = cfu_reg3_addr_c
data_o <= cfu_reg_out(3);
end if;
case addr is
when cfu_reg0_addr_c => data_o <= cfu_reg_out(0);
when cfu_reg1_addr_c => data_o <= cfu_reg_out(1);
when cfu_reg2_addr_c => data_o <= cfu_reg_out(2);
when cfu_reg3_addr_c => data_o <= cfu_reg_out(3);
when others => data_o <= (others => '0');
end case;
end if;
end if;
end process rw_access;
/rtl/core/neorv32_cpu_alu.vhd
120,23 → 120,23
-- -------------------------------------------------------------------------------------------
input_op_mux: process(ctrl_i, csr_i, pc2_i, rs1_i, rs2_i, imm_i)
begin
-- opa (first ALU input operand) --
-- operand a (first ALU input operand) --
case ctrl_i(ctrl_alu_opa_mux_msb_c downto ctrl_alu_opa_mux_lsb_c) is
when "00" => opa <= rs1_i;
when "01" => opa <= pc2_i;
when others => opa <= csr_i;
end case;
-- opb (second ALU input operand) --
-- operand b (second ALU input operand) --
if (ctrl_i(ctrl_alu_opb_mux_c) = '0') then
opb <= rs2_i;
else
opb <= imm_i;
end if;
-- opc (second operand for comparison and SUB) --
-- operand c (third ALU input operand for comparison and SUB) --
if (ctrl_i(ctrl_alu_opc_mux_c) = '0') then
opc <= rs2_i;
else
opc <= imm_i;
else
opc <= rs2_i;
end if;
end process input_op_mux;
 
150,10 → 150,10
cmp_less <= cmp_sub(cmp_sub'left); -- carry (borrow) indicates a "less"
sub_res <= cmp_sub(data_width_c-1 downto 0); -- use the less-comparator also for SUB operations
 
-- equal (x = y) --
cmp_equal <= '1' when (rs1_i = opc) else '0';
-- equal (for branch check only) --
cmp_equal <= '1' when (rs1_i = rs2_i) else '0';
 
-- output for branch condition evaluation -
-- output for branch condition evaluation --
cmp_o(alu_cmp_equal_c) <= cmp_equal;
cmp_o(alu_cmp_less_c) <= cmp_less;
 
161,7 → 161,7
-- Binary Adder ---------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
add_res <= std_ulogic_vector(unsigned(opa) + unsigned(opb));
add_o <= add_res; -- direct output
add_o <= add_res; -- direct output (for PC modification)
 
 
-- Iterative Shifter Unit -----------------------------------------------------------------
/rtl/core/neorv32_cpu_control.vhd
621,32 → 621,28
ctrl_nxt(ctrl_bus_size_lsb_c) <= execute_engine.i_reg(instr_funct3_lsb_c+0); -- transfer size lsb (00=byte, 01=half-word)
ctrl_nxt(ctrl_bus_size_msb_c) <= execute_engine.i_reg(instr_funct3_lsb_c+1); -- transfer size msb (10=word, 11=?)
ctrl_nxt(ctrl_cp_cmd2_c downto ctrl_cp_cmd0_c) <= execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c); -- CP operation
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_muldiv_c; -- only CP0 (MULDIV) implemented yet
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- default ALU operation: ADD(I)
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_muldiv_c; -- only CP0 (=MULDIV) implemented yet
ctrl_nxt(ctrl_rf_rd_adr4_c downto ctrl_rf_rd_adr0_c) <= ctrl(ctrl_rf_rd_adr4_c downto ctrl_rf_rd_adr0_c); -- keep rd addr
ctrl_nxt(ctrl_rf_rs1_adr4_c downto ctrl_rf_rs1_adr0_c) <= ctrl(ctrl_rf_rs1_adr4_c downto ctrl_rf_rs1_adr0_c); -- keep rs1 addr
ctrl_nxt(ctrl_rf_rs2_adr4_c downto ctrl_rf_rs2_adr0_c) <= ctrl(ctrl_rf_rs2_adr4_c downto ctrl_rf_rs2_adr0_c); -- keep rs2 addr
 
-- is immediate operation? --
alu_immediate_v := '0';
if (execute_engine.i_reg(instr_opcode_msb_c-1) = '0') then
alu_immediate_v := '1';
end if;
-- is immediate ALU operation? --
alu_immediate_v := not execute_engine.i_reg(instr_opcode_msb_c-1);
 
-- is rs1 = r0? --
rs1_is_r0_v := '0';
if (execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c) = "00000") then
rs1_is_r0_v := '1';
end if;
-- is rs1 == r0? --
rs1_is_r0_v := not or_all_f(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c));
 
 
-- state machine --
case execute_engine.state is
 
when SYS_WAIT => -- System delay cycle (used to wait for side effects to kick in) ((and to init r0 with zero if it is a physical register))
-- ------------------------------------------------------------
-- set reg_file's r0 to zero --
if (rf_r0_is_reg_c = true) then -- is r0 implemented as physical register, which has to be set to zero?
-- set reg_file.r0 to zero
ctrl_nxt(ctrl_rf_rd_adr4_c downto ctrl_rf_rd_adr0_c) <= (others => '0'); -- rd addr = r0
ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "11"; -- RF input = CSR output (results zero since there is no valid CSR_read request)
ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "11"; -- RF input = CSR output (hacky! results zero since there is no valid CSR_read request)
ctrl_nxt(ctrl_rf_r0_we_c) <= '1'; -- allow write access to r0
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
end if;
700,25 → 696,24
-- ------------------------------------------------------------
ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- use RS1 as ALU.OPA
ctrl_nxt(ctrl_alu_opb_mux_c) <= alu_immediate_v; -- use IMM as ALU.OPB for immediate operations
ctrl_nxt(ctrl_alu_opc_mux_c) <= not alu_immediate_v;
ctrl_nxt(ctrl_alu_opc_mux_c) <= alu_immediate_v; -- use IMM as ALU.OPC for immediate operations (SLT(I)(U))
ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "00"; -- RF input = ALU result
 
-- actual ALU operation (re-coding) --
case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is
when funct3_subadd_c => -- ADD(I) / SUB
if (alu_immediate_v = '0') and (execute_engine.i_reg(instr_funct7_msb_c-1) = '1') then -- not immediate and funct7 => SUB
when funct3_sll_c => ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_shift_c; -- SLL(I)
when funct3_slt_c => ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_slt_c; -- SLT(I)
when funct3_sltu_c => ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_slt_c; -- SLTU(I)
when funct3_xor_c => ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_xor_c; -- XOR(I)
when funct3_sr_c => ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_shift_c; -- SRL(I) / SRA(I)
when funct3_or_c => ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_or_c; -- OR(I)
when funct3_and_c => ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_and_c; -- AND(I)
when others => -- ADD(I) / SUB
if (alu_immediate_v = '0') and (execute_engine.i_reg(instr_funct7_msb_c-1) = '1') then -- not an immediate op and funct7.6 set => SUB
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_sub_c; -- SUB
else
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- ADD(I)
end if;
when funct3_sll_c => ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_shift_c; -- SLL(I)
when funct3_slt_c => ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_slt_c; -- SLT(I)
when funct3_sltu_c => ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_slt_c; -- SLTU(I)
when funct3_xor_c => ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_xor_c; -- XOR(I)
when funct3_sr_c => ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_shift_c; -- SRL(I) / SRA(I)
when funct3_or_c => ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_or_c; -- OR(I)
when funct3_and_c => ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_and_c; -- AND(I)
when others => ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= (others => '0'); -- undefined
end case;
 
-- cp access? --
732,7 → 727,7
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c) or -- SR shift operation?
((execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alu_c(5)) and (execute_engine.i_reg(instr_funct7_lsb_c) = '1')) then -- MULDIV?
execute_engine.state_nxt <= ALU_WAIT;
else
else -- single cycle ALU operation
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
execute_engine.state_nxt <= DISPATCH;
end if;
741,7 → 736,7
-- ------------------------------------------------------------
ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '1'; -- ALU.OPA = PC (for AUIPC only)
if (execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_lui_c(5)) then -- LUI
ctrl_nxt(ctrl_alu_opa_mux_msb_c) <= '1'; -- ALU.OPA = CSR = 0 (hacky: csr.result is 0 since there was no csr_read_request)
ctrl_nxt(ctrl_alu_opa_mux_msb_c) <= '1'; -- ALU.OPA = CSR = 0 (hacky: csr.result is 0 since there is no csr_read_request)
end if;
ctrl_nxt(ctrl_alu_opb_mux_c) <= '1'; -- use IMM as ALU.OPB
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- actual ALU operation = ADD
760,9 → 755,9
 
when opcode_branch_c => -- branch instruction
-- ------------------------------------------------------------
ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '1'; -- use PC as ALU.OPA
ctrl_nxt(ctrl_alu_opb_mux_c) <= '1'; -- use IMM as ALU.OPB
ctrl_nxt(ctrl_alu_opc_mux_c) <= '1'; -- use RS2 as ALU.OPC
ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '1'; -- use PC as ALU.OPA (branch target address base)
ctrl_nxt(ctrl_alu_opb_mux_c) <= '1'; -- use IMM as ALU.OPB (branch target address offset)
ctrl_nxt(ctrl_alu_opc_mux_c) <= '0'; -- use RS2 as ALU.OPC (for branch condition check)
execute_engine.state_nxt <= BRANCH;
 
when opcode_jal_c | opcode_jalr_c => -- jump and link (with register)
783,21 → 778,27
 
when opcode_fence_c => -- fence operations
-- ------------------------------------------------------------
if (execute_engine.i_reg(instr_funct3_lsb_c) = funct3_fencei_c(0)) and (CPU_EXTENSION_RISCV_Zifencei = true) then -- FENCE.I
fetch_engine.reset <= '1';
execute_engine.if_rst_nxt <= '1'; -- this is a non-linear PC modification
execute_engine.pc_nxt <= execute_engine.next_pc; -- "refetch" next instruction (only relevant for fence.i)
ctrl_nxt(ctrl_bus_fencei_c) <= '1';
-- foe simplicity: internally, fence and fence.i perform the same operations ;)
-- FENCE.I --
if (CPU_EXTENSION_RISCV_Zifencei = true) then
execute_engine.pc_nxt <= execute_engine.next_pc; -- "refetch" next instruction
execute_engine.if_rst_nxt <= '1'; -- this is a non-linear PC modification
fetch_engine.reset <= '1';
if (execute_engine.i_reg(instr_funct3_lsb_c) = funct3_fencei_c(0)) then
ctrl_nxt(ctrl_bus_fencei_c) <= '1';
end if;
end if;
if (execute_engine.i_reg(instr_funct3_lsb_c) = funct3_fence_c(0)) then -- FENCE
-- FENCE --
if (execute_engine.i_reg(instr_funct3_lsb_c) = funct3_fence_c(0)) then
ctrl_nxt(ctrl_bus_fence_c) <= '1';
end if;
--
execute_engine.state_nxt <= SYS_WAIT;
 
when opcode_syscsr_c => -- system/csr access
-- ------------------------------------------------------------
csr.re_nxt <= csr_acc_valid; -- always read CSR if valid access
ctrl_nxt(ctrl_rf_rs1_adr4_c downto ctrl_rf_rs1_adr0_c) <= (others => '0'); -- set rs1_addr to r0 (zero)
ctrl_nxt(ctrl_rf_rs1_adr4_c downto ctrl_rf_rs1_adr0_c) <= (others => '0'); -- set rs1_addr to r0 (zero) (for CSR mod)
ctrl_nxt(ctrl_rf_rs2_adr4_c downto ctrl_rf_rs2_adr0_c) <= ctrl(ctrl_rf_rs1_adr4_c downto ctrl_rf_rs1_adr0_c); -- copy rs1_addr to rs2_addr (for CSR mod)
--
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_env_c) then -- system
839,7 → 840,7
ctrl_nxt(ctrl_alu_opa_mux_msb_c downto ctrl_alu_opa_mux_lsb_c) <= "10"; -- OPA = CSR
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_or_c; -- actual ALU operation = OR
csr.we_nxt <= (not rs1_is_r0_v) and csr_acc_valid; -- write CSR if rs1 is not zero_reg and if valid access
when others => -- CSRRC(I)
when others => -- CSRRC(I) -- FIXME?!
ctrl_nxt(ctrl_alu_opa_mux_msb_c downto ctrl_alu_opa_mux_lsb_c) <= "10"; -- OPA = CSR
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_bclr_c; -- actual ALU operation = bit clear
csr.we_nxt <= (not rs1_is_r0_v) and csr_acc_valid; -- write CSR if rs1 is not zero_reg and if valid access
847,7 → 848,7
-- RF write back --
ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "11"; -- RF input = CSR output
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
execute_engine.state_nxt <= DISPATCH; -- FIXME? should be SYS_WAIT? have another cycle to let side-effects kick in
execute_engine.state_nxt <= SYS_WAIT; -- have another cycle to let side-effects kick in
 
when ALU_WAIT => -- wait for multi-cycle ALU operation (shifter or CP) to finish
-- ------------------------------------------------------------
894,7 → 895,7
ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "01"; -- RF input = memory input (only relevant for LOAD)
if (ma_load_i = '1') or (be_load_i = '1') or (ma_store_i = '1') or (be_store_i = '1') then -- abort if exception
execute_engine.state_nxt <= SYS_WAIT;
elsif (bus_d_wait_i = '0') then -- wait here for bus to finish transaction
elsif (bus_d_wait_i = '0') then -- wait for bus to finish transaction
if (execute_engine.i_reg(instr_opcode_msb_c-1) = '0') then -- LOAD
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
end if;
916,7 → 917,7
 
-- Illegal CSR Access Check ---------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
invalid_csr_access_check: process(execute_engine, csr.privilege)
invalid_csr_access_check: process(execute_engine.i_reg, csr.privilege)
variable is_m_mode_v : std_ulogic;
begin
-- are we in machine mode? --
930,7 → 931,7
when x"300" => csr_acc_valid <= is_m_mode_v; -- mstatus
when x"301" => csr_acc_valid <= is_m_mode_v; -- misa
when x"304" => csr_acc_valid <= is_m_mode_v; -- mie
when x"305" => csr_acc_valid <= is_m_mode_v; -- mtvev
when x"305" => csr_acc_valid <= is_m_mode_v; -- mtvec
when x"340" => csr_acc_valid <= is_m_mode_v; -- mscratch
when x"341" => csr_acc_valid <= is_m_mode_v; -- mepc
when x"342" => csr_acc_valid <= is_m_mode_v; -- mcause
975,7 → 976,7
 
-- Illegal Instruction Check --------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
illegal_instruction_check: process(execute_engine, csr, ctrl_nxt, csr_acc_valid)
illegal_instruction_check: process(execute_engine, csr_acc_valid)
begin
-- illegal instructions are checked in the EXECUTE stage
-- the execute engine will only commit valid instructions
1451,10 → 1452,10
csr.mtval <= (others => '0'); -- mtval is zero for interrupts
else -- for EXCEPTIONS (according to their priority)
csr.mepc <= execute_engine.last_pc(data_width_c-1 downto 1) & '0'; -- this is the LAST pc = last executed instruction
if (trap_ctrl.cause(4 downto 0) = trap_iba_c(4 downto 0)) or -- instr access error OR
(trap_ctrl.cause(4 downto 0) = trap_ima_c(4 downto 0)) or -- misaligned instruction OR
if (trap_ctrl.cause(4 downto 0) = trap_iba_c(4 downto 0)) or -- instruction access error OR
(trap_ctrl.cause(4 downto 0) = trap_ima_c(4 downto 0)) or -- misaligned instruction address OR
(trap_ctrl.cause(4 downto 0) = trap_brk_c(4 downto 0)) or -- breakpoint OR
(trap_ctrl.cause(4 downto 0) = trap_menv_c(4 downto 0)) then -- env call OR
(trap_ctrl.cause(4 downto 0) = trap_menv_c(4 downto 0)) then -- environment call
csr.mtval <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- address of faulting instruction
elsif (trap_ctrl.cause(4 downto 0) = trap_iil_c(4 downto 0)) then -- illegal instruction
csr.mtval <= execute_engine.i_reg; -- faulting instruction itself
1667,9 → 1668,9
csr_rdata_o <= x"000" & csr.minstreth(19 downto 0); -- only the lowest 20 bit!
 
-- machine information registers --
when x"f11" => -- R/-: mvendorid
when x"f11" => -- R/-: mvendorid - vendor ID
csr_rdata_o <= (others => '0'); -- not assigned
when x"f12" => -- R/-: marchid
when x"f12" => -- R/-: marchid - architecture ID
csr_rdata_o <= (others => '0'); -- not assigned
when x"f13" => -- R/-: mimpid - implementation ID / NEORV32 version
csr_rdata_o <= hw_version_c;
/rtl/core/neorv32_mtime.vhd
147,16 → 147,14
data_o <= mtime_hi;
when mtime_cmp_lo_addr_c => -- mtimecmp LOW
data_o <= mtimecmp_lo;
when mtime_cmp_hi_addr_c => -- mtimecmp HIGH
when others => -- mtime_cmp_hi_addr_c - mtimecmp HIGH
data_o <= mtimecmp_hi;
when others =>
data_o <= (others => '0');
end case;
end if;
end if;
end process rd_access;
 
-- time output for cpu --
-- system time output for cpu --
time_o <= mtime_hi & mtime_lo(31 downto 00);
 
 
/rtl/core/neorv32_package.vhd
41,7 → 41,7
-- Architecture Constants/Configuration ---------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant data_width_c : natural := 32; -- data width - FIXED!
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01040302"; -- no touchy!
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01040303"; -- no touchy!
constant pmp_max_r_c : natural := 8; -- max PMP regions - FIXED!
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
65,8 → 65,8
 
-- General Address Space Layout -----------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant ispace_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"00000000"; -- instruction memory space base address
constant dspace_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"80000000"; -- data memory space base address
constant ispace_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"00000000"; -- default instruction memory space base address
constant dspace_base_c : std_ulogic_vector(data_width_c-1 downto 0) := x"80000000"; -- default data memory space base address
 
-- Processor-Internal Address Space Layout ------------------------------------------------
-- -------------------------------------------------------------------------------------------
186,7 → 186,7
constant ctrl_alu_opa_mux_lsb_c : natural := 22; -- operand A select lsb (00=rs1, 01=PC)
constant ctrl_alu_opa_mux_msb_c : natural := 23; -- operand A select msb (1-=CSR)
constant ctrl_alu_opb_mux_c : natural := 24; -- operand B select (0=rs2, 1=IMM)
constant ctrl_alu_opc_mux_c : natural := 25; -- operand C select (0=IMM, 1=rs2)
constant ctrl_alu_opc_mux_c : natural := 25; -- operand C select (0=rs2, 1=IMM)
constant ctrl_alu_unsigned_c : natural := 26; -- is unsigned ALU operation
constant ctrl_alu_shift_dir_c : natural := 27; -- shift direction (0=left, 1=right)
constant ctrl_alu_shift_ar_c : natural := 28; -- is arithmetic shift
200,11 → 200,11
constant ctrl_bus_mdo_we_c : natural := 35; -- memory data out register write enable
constant ctrl_bus_mdi_we_c : natural := 36; -- memory data in register write enable
constant ctrl_bus_unsigned_c : natural := 37; -- is unsigned load
constant ctrl_bus_ierr_ack_c : natural := 38; -- acknowledge instruction fetch bus exception
constant ctrl_bus_derr_ack_c : natural := 39; -- acknowledge data access bus exception
constant ctrl_bus_ierr_ack_c : natural := 38; -- acknowledge instruction fetch bus exceptions
constant ctrl_bus_derr_ack_c : natural := 39; -- acknowledge data access bus exceptions
constant ctrl_bus_fence_c : natural := 40; -- executed fence operation
constant ctrl_bus_fencei_c : natural := 41; -- executed fencei operation
-- co-processor --
-- co-processors --
constant ctrl_cp_use_c : natural := 42; -- is cp operation
constant ctrl_cp_id_lsb_c : natural := 43; -- cp select ID lsb
constant ctrl_cp_id_msb_c : natural := 44; -- cp select ID msb
/rtl/core/neorv32_trng.vhd
104,7 → 104,6
 
-- access control --
signal acc_en : std_ulogic; -- module access enable
signal addr : std_ulogic_vector(31 downto 0); -- access address
signal wren : std_ulogic; -- full word write enable
signal rden : std_ulogic; -- read enable
 
140,7 → 139,6
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = trng_base_c(hi_abb_c downto lo_abb_c)) else '0';
addr <= trng_base_c(31 downto lo_abb_c) & addr_i(lo_abb_c-1 downto 2) & "00"; -- word aligned
wren <= acc_en and wren_i;
rden <= acc_en and rden_i;
 
/sw/lib/include/neorv32.h
443,7 → 443,7
**************************************************************************/
/**@{*/
/** TRNG control/data register (r/w) */
#define TRNG_CT (*(IO_REG32 0xFFFFFFC0UL))
#define TRNG_CT (*(IO_REG32 0xFFFFFFC0UL))
 
/** TRNG control/data register bits */
enum NEORV32_TRNG_CT_enum {
529,6 → 529,7
#include "neorv32_rte.h"
 
// io/peripheral devices
#include "neorv32_cfu.h"
#include "neorv32_gpio.h"
#include "neorv32_mtime.h"
#include "neorv32_pwm.h"
/sw/lib/include/neorv32_cfu.h
0,0 → 1,53
// #################################################################################################
// # << NEORV32: neorv32_cfu.h - Custom Functions Unit (CFU) HW Driver >> #
// # ********************************************************************************************* #
// # BSD 3-Clause License #
// # #
// # Copyright (c) 2020, Stephan Nolting. All rights reserved. #
// # #
// # Redistribution and use in source and binary forms, with or without modification, are #
// # permitted provided that the following conditions are met: #
// # #
// # 1. Redistributions of source code must retain the above copyright notice, this list of #
// # conditions and the following disclaimer. #
// # #
// # 2. Redistributions in binary form must reproduce the above copyright notice, this list of #
// # conditions and the following disclaimer in the documentation and/or other materials #
// # provided with the distribution. #
// # #
// # 3. Neither the name of the copyright holder nor the names of its contributors may be used to #
// # endorse or promote products derived from this software without specific prior written #
// # permission. #
// # #
// # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS #
// # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF #
// # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE #
// # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, #
// # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
// # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED #
// # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING #
// # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED #
// # OF THE POSSIBILITY OF SUCH DAMAGE. #
// # ********************************************************************************************* #
// # The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting #
// #################################################################################################
 
 
/**********************************************************************//**
* @file neorv32_cfu.h
* @author Stephan Nolting
* @brief Custom Functions Unit (CFU) HW driver header file.
*
* @warning There are no "real" CFU driver functions available here, because these functions are defined by the actual hardware.
* @warning Hence, the CFU designer has to provide the actual driver functions.
*
* @note These functions should only be used if the CFU was synthesized (IO_CFU_USE = true).
**************************************************************************/
 
#ifndef neorv32_cfu_h
#define neorv32_cfu_h
 
// prototypes
int neorv32_cfu_available(void);
 
#endif // neorv32_cfu_h
/sw/lib/source/neorv32_cfu.c
0,0 → 1,64
// #################################################################################################
// # << NEORV32: neorv32_cfu.c - Custom Functions Unit (CFU) HW Driver >> #
// # ********************************************************************************************* #
// # BSD 3-Clause License #
// # #
// # Copyright (c) 2020, Stephan Nolting. All rights reserved. #
// # #
// # Redistribution and use in source and binary forms, with or without modification, are #
// # permitted provided that the following conditions are met: #
// # #
// # 1. Redistributions of source code must retain the above copyright notice, this list of #
// # conditions and the following disclaimer. #
// # #
// # 2. Redistributions in binary form must reproduce the above copyright notice, this list of #
// # conditions and the following disclaimer in the documentation and/or other materials #
// # provided with the distribution. #
// # #
// # 3. Neither the name of the copyright holder nor the names of its contributors may be used to #
// # endorse or promote products derived from this software without specific prior written #
// # permission. #
// # #
// # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS #
// # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF #
// # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE #
// # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, #
// # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
// # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED #
// # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING #
// # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED #
// # OF THE POSSIBILITY OF SUCH DAMAGE. #
// # ********************************************************************************************* #
// # The NEORV32 Processor - https://github.com/stnolting/neorv32 (c) Stephan Nolting #
// #################################################################################################
 
 
/**********************************************************************//**
* @file neorv32_cfu.c
* @author Stephan Nolting
* @brief Custom functions unit (CFU) HW driver source file.
*
* @warning There are no "real" CFU driver functions available here, because these functions are defined by the actual hardware.
* @warning Hence, the CFU designer has to provide the actual driver functions.
*
* @note These functions should only be used if the CFU was synthesized (IO_CFU_USE = true).
**************************************************************************/
 
#include "neorv32.h"
#include "neorv32_cfu.h"
 
 
/**********************************************************************//**
* Check if CFU unit was synthesized.
*
* @return 0 if CFU was not synthesized, 1 if CFU is available.
**************************************************************************/
int neorv32_cfu_available(void) {
 
if (SYSINFO_FEATURES & (1 << SYSINFO_FEATURES_IO_CFU)) {
return 1;
}
else {
return 0;
}
}
/sw/lib/source/neorv32_gpio.c
137,7 → 137,7
*
* @note The pin-change IRQ will trigger on any transition (rising and falling edge) for any enabled input pin.
*
* @param[in] pin_en Mask to select which input pins can cause a pin-change IRQ (32-bit), 1 = pin enabled.
* @param[in] pin_sel Mask to select which input pins can cause a pin-change IRQ (32-bit), 1 = pin enabled.
**************************************************************************/
void neorv32_gpio_pin_change_config(uint32_t pin_sel) {
 
/README.md
124,7 → 124,7
![neorv32 Overview](https://raw.githubusercontent.com/stnolting/neorv32/master/docs/figures/neorv32_processor.png)
 
The NEORV32 Processor provides a full-scale microcontroller-like SoC based on the NEORV32 CPU. The setup
is highly customizable via the processor top's generics.
is highly customizable via the processor's top generics.
 
- Optional processor-internal data and instruction memories (**DMEM** / **IMEM**)
- Optional internal **Bootloader** with UART console and automatic SPI flash boot option
154,7 → 154,7
 
 
**General**:
* Modified Harvard architecture (separate CPU interfaces for data and instructions; NEORV32 processor: Single processor-internal bus via bus I/D mux)
* Modified Harvard architecture (separate CPU interfaces for data and instructions; NEORV32 processor: Single processor-internal bus via I/D mux)
* Two stages in-order pipeline (FETCH, EXECUTE); each stage uses a multi-cycle processing scheme
* No hardware support of unaligned accesses - they will trigger an exception
* Little-endian byte order
238,40 → 238,40
This chapter shows exemplary implementation results of the NEORV32 CPU for an **Intel Cyclone IV EP4CE22F17C6N FPGA** on
a DE0-nano board. The design was synthesized using **Intel Quartus Prime Lite 19.1** ("balanced implementation"). The timing
information is derived from the Timing Analyzer / Slow 1200mV 0C Model. If not otherwise specified, the default configuration
of the CPU's generics is assumed (e.g., no PMP). No constraints were used at all.
of the CPU's generics is assumed (for example no PMP). No constraints were used at all.
 
Results generated for hardware version: `1.3.6.5`
Results generated for hardware version: `1.4.3.3`
 
| CPU Configuration | LEs | FFs | Memory bits | DSPs | f_max |
|:---------------------------------|:----------:|:--------:|:-----------:|:----:|:-------:|
| `rv32i` | 1113 | 479 | 2048 | 0 | 109 MHz |
| `rv32i` + `Zicsr` + `Zifencei` | 1851 | 817 | 2048 | 0 | 100 MHz |
| `rv32im` + `Zicsr` + `Zifencei` | 2462 | 1065 | 2048 | 0 | 100 MHz |
| `rv32imc` + `Zicsr` + `Zifencei` | 2714 | 1064 | 2048 | 0 | 100 MHz |
| `rv32emc` + `Zicsr` + `Zifencei` | 2717 | 1064 | 1024 | 0 | 100 MHz |
| CPU Configuration | LEs | FFs | Memory bits | DSPs | f_max |
|:---------------------------------------|:----------:|:--------:|:-----------:|:----:|:-------:|
| `rv32i` | 1033 | 567 | 2048 | 0 | 120 MHz |
| `rv32i` + `u` + `Zicsr` + `Zifencei` | 1778 | 806 | 2048 | 0 | 103 MHz |
| `rv32im` + `u` + `Zicsr` + `Zifencei` | 2389 | 1052 | 2048 | 0 | 102 MHz |
| `rv32imc` + `u` + `Zicsr` + `Zifencei` | 2644 | 1053 | 2048 | 0 | 106 MHz |
| `rv32emc` + `u` + `Zicsr` + `Zifencei` | 2646 | 1050 | 1024 | 0 | 103 MHz |
 
 
### NEORV32 Processor-Internal Peripherals and Memories
 
Results generated for hardware version: `1.3.6.5`
Results generated for hardware version: `1.4.3.3`
 
| Module | Description | LEs | FFs | Memory bits | DSPs |
|:----------|:-----------------------------------------------------|:---:|:---:|:-----------:|:----:|
| BOOT ROM | Bootloader ROM (default 4kB) | 4 | 1 | 32 768 | 0 |
| BUSSWITCH | Mux for CPU I & D interfaces | 62 | 8 | 0 | 0 |
| BOOT ROM | Bootloader ROM (default 4kB) | 3 | 1 | 32 768 | 0 |
| BUSSWITCH | Mux for CPU I & D interfaces | 59 | 8 | 0 | 0 |
| CFU | Custom functions unit | - | - | - | - |
| DEVNULL | Dummy device | 3 | 1 | 0 | 0 |
| DMEM | Processor-internal data memory (default 8kB) | 12 | 2 | 65 536 | 0 |
| GPIO | General purpose input/output ports | 40 | 33 | 0 | 0 |
| IMEM | Processor-internal instruction memory (default 16kb) | 7 | 2 | 131 072 | 0 |
| MTIME | Machine system timer | 266 | 166 | 0 | 0 |
| DEVNULL | Dummy device | 1 | 1 | 0 | 0 |
| DMEM | Processor-internal data memory (default 8kB) | 13 | 2 | 65 536 | 0 |
| GPIO | General purpose input/output ports | 69 | 65 | 0 | 0 |
| IMEM | Processor-internal instruction memory (default 16kb) | 9 | 2 | 131 072 | 0 |
| MTIME | Machine system timer | 281 | 166 | 0 | 0 |
| PWM | Pulse-width modulation controller | 72 | 69 | 0 | 0 |
| SPI | Serial peripheral interface | 198 | 125 | 0 | 0 |
| SPI | Serial peripheral interface | 189 | 125 | 0 | 0 |
| SYSINFO | System configuration information memory | 10 | 9 | 0 | 0 |
| TRNG | True random number generator | 105 | 93 | 0 | 0 |
| TWI | Two-wire interface | 75 | 44 | 0 | 0 |
| UART | Universal asynchronous receiver/transmitter | 153 | 108 | 0 | 0 |
| WDT | Watchdog timer | 59 | 45 | 0 | 0 |
| TRNG | True random number generator | 175 | 132 | 0 | 0 |
| TWI | Two-wire interface | 72 | 44 | 0 | 0 |
| UART | Universal asynchronous receiver/transmitter | 175 | 132 | 0 | 0 |
| WDT | Watchdog timer | 60 | 45 | 0 | 0 |
 
 
### NEORV32 Processor - Exemplary FPGA Setups
281,13 → 281,13
processor's [top entity](https://github.com/stnolting/neorv32/blob/master/rtl/core/neorv32_top.vhd) signals
to FPGA pins - except for the Wishbone bus and the interrupt signals.
 
Results generated for hardware version: `1.4.0.0`
Results generated for hardware version: `1.4.3.3`
 
| Vendor | FPGA | Board | Toolchain | Strategy | CPU Configuration | LUT / LE | FF / REG | DSP | Memory Bits | BRAM / EBR | SPRAM | Frequency |
|:--------|:----------------------------------|:-----------------|:---------------------------|:-------- |:------------------------------------------|:-----------|:-----------|:-------|:-------------|:-----------|:---------|---------------:|
| Intel | Cyclone IV `EP4CE22F17C6N` | Terasic DE0-Nano | Quartus Prime Lite 19.1 | balanced | `rv32imcu` + `Zicsr` + `Zifencei` + `PMP` | 4020 (18%) | 1766 (8%) | 0 (0%) | 231424 (38%) | - | - | 100 MHz |
| Lattice | iCE40 UltraPlus `iCE40UP5K-SG48I` | Upduino v2.0 | Radiant 2.1 (Synplify Pro) | default | `rv32icu` + `Zicsr` + `Zifencei` | 4249 (80%) | 1617 (31%) | 0 (0%) | - | 12 (40%) | 4 (100%) | *c* 20.25 MHz |
| Xilinx | Artix-7 `XC7A35TICSG324-1L` | Arty A7-35T | Vivado 2019.2 | default | `rv32imcu` + `Zicsr` + `Zifencei` + `PMP` | 2447 (12%) | 1803 (4%) | 0 (0%) | - | 8 (16%) | - | *c* 100 MHz |
| Vendor | FPGA | Board | Toolchain | Strategy | CPU Configuration | LUT / LE | FF / REG | DSP | Memory Bits | BRAM / EBR | SPRAM | Frequency |
|:--------|:----------------------------------|:-----------------|:---------------------------|:-------- |:-----------------------------------------------|:-----------|:-----------|:-------|:-------------|:-----------|:---------|--------------:|
| Intel | Cyclone IV `EP4CE22F17C6N` | Terasic DE0-Nano | Quartus Prime Lite 19.1 | balanced | `rv32imc` + `u` + `Zicsr` + `Zifencei` + `PMP` | 4120 (18%) | 1944 (9%) | 0 (0%) | 231424 (38%) | - | - | 103 MHz |
| Lattice | iCE40 UltraPlus `iCE40UP5K-SG48I` | Upduino v2.0 | Radiant 2.1 (Synplify Pro) | default | `rv32ic` + `u` + `Zicsr` + `Zifencei` | 4288 (81%) | 1693 (32%) | 0 (0%) | - | 12 (40%) | 4 (100%) | *c* 22.5 MHz |
| Xilinx | Artix-7 `XC7A35TICSG324-1L` | Arty A7-35T | Vivado 2019.2 | default | `rv32imc` + `u` + `Zicsr` + `Zifencei` + `PMP` | 2385 (11%) | 2008 (5%) | 0 (0%) | - | 8 (16%) | - | *c* 100 MHz |
 
**_Notes_**
* The Lattice iCE40 UltraPlus setup uses the FPGA's SPRAM memory primitives for the internal IMEM and DMEM (each 64kb).
372,7 → 372,7
in [`rtl/top_templates`](https://github.com/stnolting/neorv32/blob/master/rtl/top_templates) folder.
 
 
### CPU
### NEORV32 CPU
 
```vhdl
entity neorv32_cpu is
435,7 → 435,7
```
 
 
### Processor
### NEORV32 Processor
 
```vhdl
entity neorv32_top is
674,9 → 674,9
 
#### Citation
 
If you are using the NEORV32 Processor in some kind of publication, please cite it as follows:
If you are using the NEORV32 Processor/CPU in some kind of publication, please cite it as follows:
 
> S. Nolting, "The NEORV32 Processor", github.com/stnolting/neorv32
> S. Nolting, "The NEORV32 Processor/CPU", github.com/stnolting/neorv32
 
#### BSD 3-Clause License
 

powered by: WebSVN 2.1.0

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