OpenCores
URL https://opencores.org/ocsvn/neorv32/neorv32/trunk

Subversion Repositories neorv32

Compare Revisions

  • This comparison shows the changes necessary to convert path
    /
    from Rev 28 to Rev 29
    Reverse comparison

Rev 28 → Rev 29

/neorv32/trunk/docs/figures/neorv32_cpu.png Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
/neorv32/trunk/docs/NEORV32.pdf Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream
/neorv32/trunk/rtl/core/neorv32_application_image.vhd
88,7 → 88,7
00000077 => x"00112623",
00000078 => x"00812423",
00000079 => x"514000ef",
00000080 => x"7f8000ef",
00000080 => x"7b8000ef",
00000081 => x"02050c63",
00000082 => x"3a4000ef",
00000083 => x"00001537",
95,12 → 95,12
00000084 => x"a4c50513",
00000085 => x"598000ef",
00000086 => x"00000513",
00000087 => x"7ec000ef",
00000087 => x"7ac000ef",
00000088 => x"00000413",
00000089 => x"0ff47513",
00000090 => x"7e0000ef",
00000090 => x"7a0000ef",
00000091 => x"0c800513",
00000092 => x"788000ef",
00000092 => x"7a0000ef",
00000093 => x"00140413",
00000094 => x"fedff06f",
00000095 => x"00001537",
582,28 → 582,28
00000571 => x"00140993",
00000572 => x"000c0513",
00000573 => x"f99ff06f",
00000574 => x"00050593",
00000575 => x"fe002503",
00000576 => x"ff010113",
00000577 => x"00112623",
00000578 => x"00f55513",
00000579 => x"044000ef",
00000580 => x"00051863",
00000581 => x"00c12083",
00000582 => x"01010113",
00000583 => x"00008067",
00000584 => x"00000013",
00000585 => x"00000013",
00000586 => x"00000013",
00000587 => x"00000013",
00000588 => x"fff50513",
00000589 => x"fddff06f",
00000590 => x"fe802503",
00000591 => x"01055513",
00000592 => x"00157513",
00000593 => x"00008067",
00000594 => x"f8a02223",
00000595 => x"00008067",
00000574 => x"fe802503",
00000575 => x"01055513",
00000576 => x"00157513",
00000577 => x"00008067",
00000578 => x"f8a02223",
00000579 => x"00008067",
00000580 => x"00050593",
00000581 => x"fe002503",
00000582 => x"ff010113",
00000583 => x"00112623",
00000584 => x"00f55513",
00000585 => x"02c000ef",
00000586 => x"00051863",
00000587 => x"00c12083",
00000588 => x"01010113",
00000589 => x"00008067",
00000590 => x"00000013",
00000591 => x"00000013",
00000592 => x"00000013",
00000593 => x"00000013",
00000594 => x"fff50513",
00000595 => x"fddff06f",
00000596 => x"00050613",
00000597 => x"00000513",
00000598 => x"0015f693",
/neorv32/trunk/rtl/core/neorv32_cpu.vhd
10,7 → 10,7
-- # * neorv32_cpu_decompressor.vhd : Compressed instructions decoder #
-- # * neorv32_cpu_regfile.vhd : Data register file #
-- # #
-- # Check the processor's documentary for more information: docs/NEORV32.pdf #
-- # Check out the processor's data sheet for more information: docs/NEORV32.pdf #
-- # ********************************************************************************************* #
-- # BSD 3-Clause License #
-- # #
117,7 → 117,6
signal instr : std_ulogic_vector(data_width_c-1 downto 0); -- new instruction
signal rs1, rs2 : std_ulogic_vector(data_width_c-1 downto 0); -- source registers
signal alu_res : std_ulogic_vector(data_width_c-1 downto 0); -- alu result
signal alu_add : std_ulogic_vector(data_width_c-1 downto 0); -- alu adder result
signal rdata : std_ulogic_vector(data_width_c-1 downto 0); -- memory read data
signal alu_wait : std_ulogic; -- alu is busy due to iterative unit
signal bus_i_wait : std_ulogic; -- wait for current bus instruction fetch
193,7 → 192,6
-- data input --
instr_i => instr, -- instruction
cmp_i => alu_cmp, -- comparator status
alu_add_i => alu_add, -- ALU.add result
alu_res_i => alu_res, -- ALU processing result
-- data output --
imm_o => imm, -- immediate
263,7 → 261,6
imm_i => imm, -- immediate
-- data output --
cmp_o => alu_cmp, -- comparator status
add_o => alu_add, -- OPA + OPB
res_o => alu_res, -- ALU result
-- co-processor interface --
cp0_start_o => cp0_start, -- trigger co-processor 0
337,7 → 334,7
ma_instr_o => ma_instr, -- misaligned instruction address
be_instr_o => be_instr, -- bus error on instruction access
-- cpu data access interface --
addr_i => alu_add, -- ALU.add result -> access address
addr_i => alu_res, -- ALU result -> access address
wdata_i => rs2, -- write data
rdata_o => rdata, -- read data
mar_o => mar, -- current memory address register
/neorv32/trunk/rtl/core/neorv32_cpu_alu.vhd
58,7 → 58,6
imm_i : in std_ulogic_vector(data_width_c-1 downto 0); -- immediate
-- data output --
cmp_o : out std_ulogic_vector(1 downto 0); -- comparator status
add_o : out std_ulogic_vector(data_width_c-1 downto 0); -- OPA + OPB
res_o : out std_ulogic_vector(data_width_c-1 downto 0); -- ALU result
-- co-processor interface --
cp0_start_o : out std_ulogic; -- trigger co-processor 0
75,19 → 74,16
architecture neorv32_cpu_cpu_rtl of neorv32_cpu_alu is
 
-- operands --
signal opa, opb, opc : std_ulogic_vector(data_width_c-1 downto 0);
signal opa, opb : std_ulogic_vector(data_width_c-1 downto 0);
 
-- results --
signal add_res : std_ulogic_vector(data_width_c-1 downto 0);
signal alu_res : std_ulogic_vector(data_width_c-1 downto 0);
signal cp_res : std_ulogic_vector(data_width_c-1 downto 0);
signal addsub_res : std_ulogic_vector(data_width_c-1 downto 0);
signal cp_res : std_ulogic_vector(data_width_c-1 downto 0);
 
-- comparator --
signal cmp_opx : std_ulogic_vector(data_width_c downto 0);
signal cmp_opy : std_ulogic_vector(data_width_c downto 0);
signal cmp_sub : std_ulogic_vector(data_width_c downto 0);
signal sub_res : std_ulogic_vector(data_width_c-1 downto 0);
signal cmp_equal : std_ulogic;
signal cmp_less : std_ulogic;
 
-- shifter --
104,6 → 100,7
 
-- co-processor arbiter and interface --
type cp_ctrl_t is record
cmd : std_ulogic;
cmd_ff : std_ulogic;
busy : std_ulogic;
start : std_ulogic;
115,34 → 112,52
 
-- Operand Mux ----------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
opa <= rs1_i when (ctrl_i(ctrl_alu_opa_mux_c) = '0') else pc2_i; -- operand a (first ALU input operand)
opb <= rs2_i when (ctrl_i(ctrl_alu_opb_mux_c) = '0') else imm_i; -- operand b (second ALU input operand)
opc <= rs2_i when (ctrl_i(ctrl_alu_opc_mux_c) = '0') else imm_i; -- operand c (third ALU input operand for comparison and SUB)
opa <= pc2_i when (ctrl_i(ctrl_alu_opa_mux_c) = '1') else rs1_i; -- operand a (first ALU input operand)
opb <= imm_i when (ctrl_i(ctrl_alu_opb_mux_c) = '1') else rs2_i; -- operand b (second ALU input operand)
 
 
-- Comparator Unit ------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- less than (x < y) --
cmp_opx <= (rs1_i(rs1_i'left) and (not ctrl_i(ctrl_alu_unsigned_c))) & rs1_i;
cmp_opy <= (opc(opc'left) and (not ctrl_i(ctrl_alu_unsigned_c))) & opc;
cmp_sub <= std_ulogic_vector(signed(cmp_opx) - signed(cmp_opy));
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
cmp_opy <= (rs2_i(rs2_i'left) and (not ctrl_i(ctrl_alu_unsigned_c))) & rs2_i;
cmp_sub <= std_ulogic_vector(signed(cmp_opx) - signed(cmp_opy)); -- less than (x < y)
 
-- equal (for branch check only) --
cmp_equal <= '1' when (rs1_i = rs2_i) else '0';
cmp_o(alu_cmp_equal_c) <= '1' when (rs1_i = rs2_i) else '0';
cmp_o(alu_cmp_less_c) <= cmp_sub(cmp_sub'left); -- less = carry (borrow)
 
-- output for branch condition evaluation --
cmp_o(alu_cmp_equal_c) <= cmp_equal;
cmp_o(alu_cmp_less_c) <= cmp_less;
 
 
-- Binary Adder ---------------------------------------------------------------------------
-- Binary Adder/Subtractor ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
add_res <= std_ulogic_vector(unsigned(opa) + unsigned(opb));
add_o <= add_res; -- direct output (for PC modification)
binary_arithmetic_core: process(ctrl_i, opa, opb)
variable cin_v : std_ulogic_vector(0 downto 0);
variable op_a_v : std_ulogic_vector(data_width_c downto 0);
variable op_b_v : std_ulogic_vector(data_width_c downto 0);
variable op_y_v : std_ulogic_vector(data_width_c downto 0);
variable res_v : std_ulogic_vector(data_width_c downto 0);
begin
-- operand sign-extension --
op_a_v := (opa(opa'left) and (not ctrl_i(ctrl_alu_unsigned_c))) & opa;
op_b_v := (opb(opb'left) and (not ctrl_i(ctrl_alu_unsigned_c))) & opb;
 
-- add/sub(slt) select --
if (ctrl_i(ctrl_alu_addsub_c) = '1') then -- subtraction
op_y_v := not op_b_v;
cin_v(0) := '1';
else-- addition
op_y_v := op_b_v;
cin_v(0) := '0';
end if;
 
-- adder core --
res_v := std_ulogic_vector(unsigned(op_a_v) + unsigned(op_y_v) + unsigned(cin_v(0 downto 0)));
 
-- output --
cmp_less <= res_v(32);
addsub_res <= res_v(31 downto 0);
addsub_res <= res_v(31 downto 0);
end process binary_arithmetic_core;
 
 
-- Iterative Shifter Unit -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
shifter_unit: process(rstn_i, clk_i)
182,7 → 197,7
end process shifter_unit;
 
-- is shift operation? --
shifter.cmd <= '1' when (ctrl_i(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) = alu_cmd_shift_c) and (ctrl_i(ctrl_cp_use_c) = '0') else '0';
shifter.cmd <= '1' when (ctrl_i(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) = alu_cmd_shift_c) else '0';
shifter.start <= '1' when (shifter.cmd = '1') and (shifter.cmd_ff = '0') else '0';
 
-- shift operation running? --
199,7 → 214,7
cp_ctrl.busy <= '0';
elsif rising_edge(clk_i) then
if (CPU_EXTENSION_RISCV_M = true) then
cp_ctrl.cmd_ff <= ctrl_i(ctrl_cp_use_c);
cp_ctrl.cmd_ff <= cp_ctrl.cmd;
if (cp_ctrl.start = '1') then
cp_ctrl.busy <= '1';
elsif ((cp0_valid_i or cp1_valid_i) = '1') then -- cp computation done?
213,7 → 228,8
end process cp_arbiter;
 
-- is co-processor operation? --
cp_ctrl.start <= '1' when (ctrl_i(ctrl_cp_use_c) = '1') and (cp_ctrl.cmd_ff = '0') else '0';
cp_ctrl.cmd <= '1' when (ctrl_i(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) = alu_cmd_cp_c) else '0';
cp_ctrl.start <= '1' when (cp_ctrl.cmd = '1') and (cp_ctrl.cmd_ff = '0') else '0';
cp0_start_o <= '1' when (cp_ctrl.start = '1') and (ctrl_i(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) = cp_sel_muldiv_c) else '0'; -- MULDIV CP
cp1_start_o <= '0'; -- not yet implemented
 
221,31 → 237,30
cp_ctrl.halt <= cp_ctrl.busy or cp_ctrl.start;
 
-- co-processor result --
cp_res <= cp0_data_i or cp1_data_i; -- only the selected cp may output data != 0
cp_res <= cp0_data_i or cp1_data_i; -- only the **actaully selected** co-processor should output data != 0
 
 
-- ALU Function Select --------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
alu_function_mux: process(ctrl_i, opa, opb, add_res, sub_res, cmp_less, shifter.sreg)
alu_function_mux: process(ctrl_i, opa, opb, addsub_res, cp_res, cmp_less, shifter.sreg)
begin
case ctrl_i(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) is
when alu_cmd_xor_c => alu_res <= opa xor opb;
when alu_cmd_or_c => alu_res <= opa or opb;
when alu_cmd_and_c => alu_res <= opa and opb;
when alu_cmd_movb_c => alu_res <= opb;
when alu_cmd_sub_c => alu_res <= sub_res;
when alu_cmd_add_c => alu_res <= add_res;
when alu_cmd_shift_c => alu_res <= shifter.sreg;
when alu_cmd_slt_c => alu_res <= (others => '0'); alu_res(0) <= cmp_less;
when others => alu_res <= (others => '0'); -- undefined
when alu_cmd_xor_c => res_o <= opa xor opb;
when alu_cmd_or_c => res_o <= opa or opb;
when alu_cmd_and_c => res_o <= opa and opb;
when alu_cmd_movb_c => res_o <= opb;
when alu_cmd_addsub_c => res_o <= addsub_res;
when alu_cmd_cp_c => res_o <= cp_res;
when alu_cmd_shift_c => res_o <= shifter.sreg;
when alu_cmd_slt_c => res_o <= (others => '0'); res_o(0) <= cmp_less;
when others => res_o <= opb; -- undefined
end case;
end process alu_function_mux;
 
 
-- ALU Result -----------------------------------------------------------------------------
-- ALU Busy -------------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
wait_o <= shifter.halt or cp_ctrl.halt; -- wait until iterative units have completed
res_o <= cp_res when (ctrl_i(ctrl_cp_use_c) = '1') else alu_res; -- FIXME?
 
 
end neorv32_cpu_cpu_rtl;
/neorv32/trunk/rtl/core/neorv32_cpu_bus.vhd
460,7 → 460,7
pmp_check_permission: process(pmp, pmp_ctrl_i, priv_mode_i)
begin
for r in 0 to PMP_NUM_REGIONS-1 loop -- iterate over all regions
if ((priv_mode_i = u_priv_mode_c) or (pmp_ctrl_i(r)(pmp_cfg_l_c) = '1')) and -- user privilege level or locked pmp entry -> enforce permissions also for machine mode
if ((priv_mode_i = priv_mode_u_c) or (pmp_ctrl_i(r)(pmp_cfg_l_c) = '1')) and -- user privilege level or locked pmp entry -> enforce permissions also for machine mode
(pmp_ctrl_i(r)(pmp_cfg_ah_c downto pmp_cfg_al_c) /= pmp_off_mode_c) then -- active entry
pmp.if_fault(r) <= pmp.i_match(r) and (not pmp_ctrl_i(r)(pmp_cfg_x_c)); -- fetch access match no execute permission
pmp.ld_fault(r) <= pmp.d_match(r) and (not pmp_ctrl_i(r)(pmp_cfg_r_c)); -- load access match no read permission
/neorv32/trunk/rtl/core/neorv32_cpu_control.vhd
72,7 → 72,6
-- data input --
instr_i : in std_ulogic_vector(data_width_c-1 downto 0); -- instruction
cmp_i : in std_ulogic_vector(1 downto 0); -- comparator status
alu_add_i : in std_ulogic_vector(data_width_c-1 downto 0); -- ALU.add result
alu_res_i : in std_ulogic_vector(data_width_c-1 downto 0); -- ALU processing result
-- data output --
imm_o : out std_ulogic_vector(data_width_c-1 downto 0); -- immediate
161,6 → 160,8
is_ci_nxt : std_ulogic;
is_jump : std_ulogic; -- current instruction is jump instruction
is_jump_nxt : std_ulogic;
is_cp_op : std_ulogic; -- current instruction is a co-processor operation
is_cp_op_nxt : std_ulogic;
branch_taken : std_ulogic; -- branch condition fullfilled
pc : std_ulogic_vector(data_width_c-1 downto 0); -- actual PC, corresponding to current executed instruction
pc_nxt : std_ulogic_vector(data_width_c-1 downto 0);
210,20 → 211,24
type pmp_ctrl_t is array (0 to PMP_NUM_REGIONS-1) of std_ulogic_vector(7 downto 0);
type pmp_addr_t is array (0 to PMP_NUM_REGIONS-1) of std_ulogic_vector(data_width_c-1 downto 0);
type csr_t is record
we : std_ulogic; -- write enable
we : std_ulogic; -- csr write enable
we_nxt : std_ulogic;
re : std_ulogic; -- read enable
re : std_ulogic; -- csr read enable
re_nxt : std_ulogic;
wdata : std_ulogic_vector(data_width_c-1 downto 0); -- write data
rdata : std_ulogic_vector(data_width_c-1 downto 0); -- read data
wdata : std_ulogic_vector(data_width_c-1 downto 0); -- csr write data
rdata : std_ulogic_vector(data_width_c-1 downto 0); -- csr read data
--
mstatus_mie : std_ulogic; -- mstatus.MIE: global IRQ enable (R/W)
mstatus_mpie : std_ulogic; -- mstatus.MPIE: previous global IRQ enable (R/-)
mstatus_mpp : std_ulogic_vector(1 downto 0); -- mstatus.MPP: machine previous privilege mode
--
mie_msie : std_ulogic; -- mie.MSIE: machine software interrupt enable (R/W)
mie_meie : std_ulogic; -- mie.MEIE: machine external interrupt enable (R/W)
mie_mtie : std_ulogic; -- mie.MEIE: machine timer interrupt enable (R/W
mie_firqe : std_ulogic_vector(3 downto 0); -- mie.firq*e: fast interrupt enabled (R/W)
mpp : std_ulogic_vector(1 downto 0); -- machine previous privilege mode
--
privilege : std_ulogic_vector(1 downto 0); -- hart's current previous privilege mode
--
mepc : std_ulogic_vector(data_width_c-1 downto 0); -- mepc: machine exception pc (R/W)
mcause : std_ulogic_vector(data_width_c-1 downto 0); -- mcause: machine trap cause (R/-)
mtvec : std_ulogic_vector(data_width_c-1 downto 0); -- mtvec: machine trap-handler base address (R/W), bit 1:0 == 00
547,6 → 552,7
execute_engine.i_reg <= execute_engine.i_reg_nxt;
execute_engine.is_ci <= execute_engine.is_ci_nxt;
execute_engine.is_jump <= execute_engine.is_jump_nxt;
execute_engine.is_cp_op <= execute_engine.is_cp_op_nxt;
--
ctrl <= ctrl_nxt;
end if;
563,7 → 569,7
 
-- CPU Control Bus Output -----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
ctrl_output: process(ctrl, fetch_engine, trap_ctrl, csr, bus_fast_ir)
ctrl_output: process(ctrl, fetch_engine, trap_ctrl, bus_fast_ir, execute_engine)
begin
ctrl_o <= ctrl;
-- fast bus access requests --
571,6 → 577,8
-- bus error control --
ctrl_o(ctrl_bus_ierr_ack_c) <= fetch_engine.bus_err_ack;
ctrl_o(ctrl_bus_derr_ack_c) <= trap_ctrl.env_start_ack;
-- co-processor operation --
ctrl_o(ctrl_cp_cmd2_c downto ctrl_cp_cmd0_c) <= execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c);
end process ctrl_output;
 
 
577,19 → 585,20
-- Execute Engine FSM Comb ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
execute_engine_fsm_comb: process(execute_engine, fetch_engine, ipb, trap_ctrl, csr, ctrl, csr_acc_valid,
alu_add_i, alu_wait_i, bus_d_wait_i, ma_load_i, be_load_i, ma_store_i, be_store_i)
alu_res_i, alu_wait_i, bus_d_wait_i, ma_load_i, be_load_i, ma_store_i, be_store_i)
variable alu_immediate_v : std_ulogic;
variable rs1_is_r0_v : std_ulogic;
begin
-- arbiter defaults --
execute_engine.state_nxt <= execute_engine.state;
execute_engine.i_reg_nxt <= execute_engine.i_reg;
execute_engine.is_jump_nxt <= '0';
execute_engine.is_ci_nxt <= execute_engine.is_ci;
execute_engine.pc_nxt <= execute_engine.pc;
execute_engine.last_pc_nxt <= execute_engine.last_pc;
execute_engine.sleep_nxt <= execute_engine.sleep;
execute_engine.if_rst_nxt <= execute_engine.if_rst;
execute_engine.state_nxt <= execute_engine.state;
execute_engine.i_reg_nxt <= execute_engine.i_reg;
execute_engine.is_jump_nxt <= '0';
execute_engine.is_cp_op_nxt <= execute_engine.is_cp_op;
execute_engine.is_ci_nxt <= execute_engine.is_ci;
execute_engine.pc_nxt <= execute_engine.pc;
execute_engine.last_pc_nxt <= execute_engine.last_pc;
execute_engine.sleep_nxt <= execute_engine.sleep;
execute_engine.if_rst_nxt <= execute_engine.if_rst;
 
-- instruction dispatch --
fetch_engine.reset <= '0';
620,8 → 629,7
ctrl_nxt(ctrl_bus_unsigned_c) <= execute_engine.i_reg(instr_funct3_msb_c); -- unsigned LOAD (LBU, LHU)
ctrl_nxt(ctrl_alu_shift_dir_c) <= execute_engine.i_reg(instr_funct3_msb_c); -- shift direction (left/right)
ctrl_nxt(ctrl_alu_shift_ar_c) <= execute_engine.i_reg(30); -- is arithmetic shift
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_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- default ALU operation: ADD(I)
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_addsub_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
699,32 → 707,37
-- ------------------------------------------------------------
ctrl_nxt(ctrl_alu_opa_mux_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) <= 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_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;
end case;
 
-- cp access? --
if (CPU_EXTENSION_RISCV_M = true) and (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?
ctrl_nxt(ctrl_cp_use_c) <= '1'; -- use CP
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_cp_c;
execute_engine.is_cp_op_nxt <= '1'; -- use CP
-- ALU operation --
else
case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is -- actual ALU operation (re-coding)
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) <= alu_cmd_addsub_c; -- ADD(I) / SUB
end case;
execute_engine.is_cp_op_nxt <= '0'; -- no CP operation
end if;
 
-- ADD/SUB --
if ((alu_immediate_v = '0') and (execute_engine.i_reg(instr_funct7_msb_c-1) = '1')) or -- not an immediate op and funct7.6 set => SUB
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_slt_c) or -- SLT operation
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sltu_c) then -- SLTU operation
ctrl_nxt(ctrl_alu_addsub_c) <= '1'; -- SUB/SLT
else
ctrl_nxt(ctrl_alu_addsub_c) <= '0'; -- ADD(I)
end if;
 
-- multi cycle alu operation? --
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) or -- SLL shift operation?
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c) or -- SR shift operation?
742,7 → 755,7
if (execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_lui_c(5)) then -- LUI
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_movb_c; -- actual ALU operation = MOVB
else -- AUIPC
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- actual ALU operation = ADD
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_addsub_c; -- actual ALU operation = ADD
end if;
ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "00"; -- RF input = ALU result
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
752,31 → 765,25
-- ------------------------------------------------------------
ctrl_nxt(ctrl_alu_opa_mux_c) <= '0'; -- use RS1 as ALU.OPA
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
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_addsub_c; -- actual ALU operation = ADD
ctrl_nxt(ctrl_bus_mar_we_c) <= '1'; -- write to MAR
ctrl_nxt(ctrl_bus_mdo_we_c) <= '1'; -- write to MDO (only relevant for stores)
execute_engine.state_nxt <= LOADSTORE_0;
 
when opcode_branch_c => -- branch instruction
when opcode_branch_c | opcode_jal_c | opcode_jalr_c => -- branch / jump and link (with register)
-- ------------------------------------------------------------
ctrl_nxt(ctrl_alu_opa_mux_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)
-- ------------------------------------------------------------
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_addsub_c; -- actual ALU operation = ADD
-- compute target address --
if (execute_engine.i_reg(instr_opcode_lsb_c+3) = opcode_jal_c(3)) then -- JAL
ctrl_nxt(ctrl_alu_opa_mux_c) <= '1'; -- use PC as ALU.OPA
else -- JALR
ctrl_nxt(ctrl_alu_opa_mux_c) <= '0'; -- use RS1 as ALU.OPA
if (execute_engine.i_reg(instr_opcode_lsb_c+3 downto instr_opcode_lsb_c+2) = opcode_jalr_c(3 downto 2)) then -- JALR
ctrl_nxt(ctrl_alu_opa_mux_c) <= '0'; -- use RS1 as ALU.OPA (branch target address base)
else -- JAL / branch
ctrl_nxt(ctrl_alu_opa_mux_c) <= '1'; -- use PC as ALU.OPA (branch target address base)
end if;
ctrl_nxt(ctrl_alu_opb_mux_c) <= '1'; -- use IMM as ALU.OPB
ctrl_nxt(ctrl_alu_opb_mux_c) <= '1'; -- use IMM as ALU.OPB (branch target address offset)
-- save return address --
ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "10"; -- RF input = next PC (save return address)
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
execute_engine.is_jump_nxt <= '1'; -- this is a jump operation
ctrl_nxt(ctrl_rf_wb_en_c) <= execute_engine.i_reg(instr_opcode_lsb_c+2); -- valid RF write-back? (for JAL/JALR)
execute_engine.is_jump_nxt <= execute_engine.i_reg(instr_opcode_lsb_c+2); -- is this is a jump operation? (for JAL/JALR)
execute_engine.state_nxt <= BRANCH;
 
when opcode_fence_c => -- fence operations
840,7 → 847,7
csr.we_nxt <= csr_acc_valid; -- always write CSR if valid access
when funct3_csrrs_c | funct3_csrrsi_c | funct3_csrrc_c | funct3_csrrci_c => -- CSRRS(I) / CSRRC(I)
csr.we_nxt <= (not rs1_is_r0_v) and csr_acc_valid; -- write CSR if rs1/imm is not zero and if valid access
when others =>
when others => -- invalid
csr.we_nxt <= '0';
end case;
-- register file write back --
850,22 → 857,23
 
when ALU_WAIT => -- wait for multi-cycle ALU operation (shifter or CP) to finish
-- ------------------------------------------------------------
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_shift_c;
ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "00"; -- RF input = ALU result
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back (permanent write-back)
-- cp access? --
if (CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_funct7_lsb_c) = '1') then -- MULDIV?
ctrl_nxt(ctrl_cp_use_c) <= '1'; -- use CP
-- cp access or alu shift? --
if (execute_engine.is_cp_op = '1') then
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_cp_c;
else
ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_shift_c;
end if;
-- wait for result --
if (alu_wait_i = '0') then
execute_engine.state_nxt <= DISPATCH;
execute_engine.state_nxt <= DISPATCH;
end if;
 
when BRANCH => -- update PC for taken branches and jumps
-- ------------------------------------------------------------
if (execute_engine.is_jump = '1') or (execute_engine.branch_taken = '1') then
execute_engine.pc_nxt <= alu_add_i; -- branch/jump destination
execute_engine.pc_nxt <= alu_res_i; -- branch/jump destination
fetch_engine.reset <= '1'; -- trigger new instruction fetch from modified PC
execute_engine.if_rst_nxt <= '1'; -- this is a non-linear PC modification
execute_engine.state_nxt <= SYS_WAIT;
919,7 → 927,7
variable is_m_mode_v : std_ulogic;
begin
-- are we in machine mode? --
if (csr.privilege = m_priv_mode_c) then
if (csr.privilege = priv_mode_m_c) then
is_m_mode_v := '1';
else
is_m_mode_v := '0';
926,48 → 934,50
end if;
 
-- check CSR access --
case execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) is
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; -- 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
when x"343" => csr_acc_valid <= is_m_mode_v; -- mtval
when x"344" => csr_acc_valid <= is_m_mode_v; -- mip
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 x"3a0" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 1)) and is_m_mode_v; -- pmpacfg0
when x"3a1" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 5)) and is_m_mode_v; -- pmpacfg1
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 x"3b0" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 1)) and is_m_mode_v; -- pmpaddr0
when x"3b1" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 2)) and is_m_mode_v; -- pmpaddr1
when x"3b2" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 3)) and is_m_mode_v; -- pmpaddr2
when x"3b3" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 4)) and is_m_mode_v; -- pmpaddr3
when x"3b4" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 5)) and is_m_mode_v; -- pmpaddr4
when x"3b5" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 6)) and is_m_mode_v; -- pmpaddr5
when x"3b6" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 7)) and is_m_mode_v; -- pmpaddr6
when x"3b7" => csr_acc_valid <= bool_to_ulogic_f(PMP_USE) and bool_to_ulogic_f(boolean(PMP_NUM_REGIONS >= 8)) and is_m_mode_v; -- pmpaddr7
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 x"c00" => csr_acc_valid <= '1'; -- cycle
when x"c01" => csr_acc_valid <= '1'; -- time
when x"c02" => csr_acc_valid <= '1'; -- instret
when x"c80" => csr_acc_valid <= '1'; -- cycleh
when x"c81" => csr_acc_valid <= '1'; -- timeh
when x"c82" => csr_acc_valid <= '1'; -- instreth
when csr_mcycle_c => csr_acc_valid <= is_m_mode_v;
when csr_minstret_c => csr_acc_valid <= is_m_mode_v;
--
when x"b00" => csr_acc_valid <= is_m_mode_v; -- mcycle
when x"b02" => csr_acc_valid <= is_m_mode_v; -- minstret
when x"b80" => csr_acc_valid <= is_m_mode_v; -- mcycleh
when x"b82" => csr_acc_valid <= is_m_mode_v; -- minstreth
when csr_mcycleh_c => csr_acc_valid <= is_m_mode_v;
when csr_minstreth_c => csr_acc_valid <= is_m_mode_v;
--
when x"f11" => csr_acc_valid <= is_m_mode_v; -- mvendorid
when x"f12" => csr_acc_valid <= is_m_mode_v; -- marchid
when x"f13" => csr_acc_valid <= is_m_mode_v; -- mimpid
when x"f14" => csr_acc_valid <= is_m_mode_v; -- mhartid
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 x"fc0" => csr_acc_valid <= is_m_mode_v; -- mzext (custom CSR)
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_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_mzext_c => csr_acc_valid <= is_m_mode_v;
--
when others => csr_acc_valid <= '0'; -- undefined, invalid access
end case;
end process invalid_csr_access_check;
1195,7 → 1205,6
trap_ctrl.exc_ack <= '1'; -- clear execption
trap_ctrl.irq_ack <= trap_ctrl.irq_ack_nxt; -- capture and clear with interrupt ACK mask
trap_ctrl.env_start <= '1'; -- now execute engine can start trap handler
-- assert false report "NEORV32.CPU TRAP: mcause=" & integer'image(to_integer(unsigned(trap_ctrl.cause_nxt))) severity note; -- for debugging
end if;
else -- trap waiting to get started
if (trap_ctrl.env_start_ack = '1') then -- start of trap handler acknowledged by execution engine
1319,6 → 1328,7
-- -------------------------------------------------------------------------------------------
csr_write_data: process(execute_engine.i_reg, csr.rdata, alu_res_i)
begin
-- "mini ALU" for CSR update operations --
case execute_engine.i_reg(instr_funct3_lsb_c+1 downto instr_funct3_lsb_c) is
when "10" => csr.wdata <= csr.rdata or alu_res_i; -- CSRRS(I)
when "11" => csr.wdata <= csr.rdata and (not alu_res_i); -- CSRRC(I)
1333,10 → 1343,11
begin
if (rstn_i = '0') then
csr.we <= '0';
csr.re <= '0';
--
csr.mstatus_mie <= '0';
csr.mstatus_mpie <= '0';
csr.mstatus_mpp <= priv_mode_m_c; -- start in MACHINE mode
csr.privilege <= priv_mode_m_c; -- start in MACHINE mode
csr.mie_msie <= '0';
csr.mie_meie <= '0';
csr.mie_mtie <= '0';
1346,163 → 1357,188
csr.mepc <= (others => '0');
csr.mcause <= (others => '0');
csr.mtval <= (others => '0');
csr.mpp <= m_priv_mode_c; -- start in MACHINE mode
csr.privilege <= m_priv_mode_c; -- start in MACHINE mode
csr.pmpcfg <= (others => (others => '0'));
csr.pmpaddr <= (others => (others => '0'));
elsif rising_edge(clk_i) then
if (CPU_EXTENSION_RISCV_Zicsr = true) then
-- access --
csr.we <= csr.we_nxt;
csr.re <= csr.re_nxt;
 
-- registers that can be modified by user --
if (csr.we = '1') then -- manual update
-- write access? --
csr.we <= csr.we_nxt;
 
-- Machine CSRs --
if (execute_engine.i_reg(31 downto 28) = x"3") then
-- machine trap setup --
if (execute_engine.i_reg(27 downto 24) = x"0") then
case execute_engine.i_reg(23 downto 20) is
when x"0" => -- R/W: mstatus - machine status register
csr.mstatus_mie <= csr.wdata(03);
csr.mstatus_mpie <= csr.wdata(07);
--
if (CPU_EXTENSION_RISCV_U = true) then -- user mode implemented
csr.mpp(0) <= csr.wdata(11) and csr.wdata(12);
csr.mpp(1) <= csr.wdata(11) and csr.wdata(12);
end if;
when x"4" => -- R/W: mie - machine interrupt-enable register
csr.mie_msie <= csr.wdata(03); -- machine SW IRQ enable
csr.mie_mtie <= csr.wdata(07); -- machine TIMER IRQ enable
csr.mie_meie <= csr.wdata(11); -- machine EXT IRQ enable
--
csr.mie_firqe(0) <= csr.wdata(16); -- fast interrupt channel 0
csr.mie_firqe(1) <= csr.wdata(17); -- fast interrupt channel 1
csr.mie_firqe(2) <= csr.wdata(18); -- fast interrupt channel 2
csr.mie_firqe(3) <= csr.wdata(19); -- fast interrupt channel 3
when x"5" => -- R/W: mtvec - machine trap-handler base address (for ALL exceptions)
csr.mtvec <= csr.wdata(data_width_c-1 downto 2) & "00"; -- mtvec.MODE=0
when others =>
NULL;
end case;
-- --------------------------------------------------------------------------------
-- CSRs that can be written by application software only
-- --------------------------------------------------------------------------------
if (CPU_EXTENSION_RISCV_Zicsr = true) and (csr.we = '1') then -- manual update
 
-- machine CSRs --
if (execute_engine.i_reg(31 downto 28) = csr_mie_c(11 downto 8)) then
 
-- machine trap setup --
if (execute_engine.i_reg(27 downto 24) = csr_mie_c(7 downto 4)) then
if (execute_engine.i_reg(23 downto 20) = csr_mie_c(3 downto 0)) then -- R/W: mie - machine interrupt-enable register
csr.mie_msie <= csr.wdata(03); -- machine SW IRQ enable
csr.mie_mtie <= csr.wdata(07); -- machine TIMER IRQ enable
csr.mie_meie <= csr.wdata(11); -- machine EXT IRQ enable
--
csr.mie_firqe(0) <= csr.wdata(16); -- fast interrupt channel 0
csr.mie_firqe(1) <= csr.wdata(17); -- fast interrupt channel 1
csr.mie_firqe(2) <= csr.wdata(18); -- fast interrupt channel 2
csr.mie_firqe(3) <= csr.wdata(19); -- fast interrupt channel 3
end if;
-- machine trap handling --
if (execute_engine.i_reg(27 downto 24) = x"4") then
case execute_engine.i_reg(23 downto 20) is
when x"0" => -- R/W: mscratch - machine scratch register
csr.mscratch <= csr.wdata;
when x"1" => -- R/W: mepc - machine exception program counter
csr.mepc <= csr.wdata(data_width_c-1 downto 1) & '0';
when x"3" => -- R/W: mtval - machine bad address or instruction
csr.mtval <= csr.wdata;
when others =>
NULL;
end case;
if (execute_engine.i_reg(23 downto 20) = csr_mtvec_c(3 downto 0)) then -- R/W: mtvec - machine trap-handler base address (for ALL exceptions)
csr.mtvec <= csr.wdata(data_width_c-1 downto 2) & "00"; -- mtvec.MODE=0
end if;
-- machine physical memory protection (pmp) --
if (PMP_USE = true) then
-- pmpcfg --
if (execute_engine.i_reg(27 downto 24) = x"a") then
if (PMP_NUM_REGIONS >= 1) then
if (execute_engine.i_reg(23 downto 20) = x"0") then -- pmpcfg0
for j in 0 to 3 loop -- bytes in pmpcfg CSR
if ((j+1) <= PMP_NUM_REGIONS) then
if (csr.pmpcfg(0+j)(7) = '0') then -- unlocked pmpcfg access
csr.pmpcfg(0+j)(0) <= csr.wdata(j*8+0); -- R
csr.pmpcfg(0+j)(1) <= csr.wdata(j*8+1); -- W
csr.pmpcfg(0+j)(2) <= csr.wdata(j*8+2); -- X
csr.pmpcfg(0+j)(3) <= csr.wdata(j*8+3) and csr.wdata(j*8+4); -- A_L
csr.pmpcfg(0+j)(4) <= csr.wdata(j*8+3) and csr.wdata(j*8+4); -- A_H - NAPOT/OFF only
csr.pmpcfg(0+j)(5) <= '0'; -- reserved
csr.pmpcfg(0+j)(6) <= '0'; -- reserved
csr.pmpcfg(0+j)(7) <= csr.wdata(j*8+7); -- L
end if;
end if;
 
-- machine trap handling --
if (execute_engine.i_reg(27 downto 20) = csr_mscratch_c(7 downto 0)) then -- R/W: mscratch - machine scratch register
csr.mscratch <= csr.wdata;
end if;
 
-- machine physical memory protection (pmp) --
if (PMP_USE = true) then
-- pmpcfg --
if (execute_engine.i_reg(27 downto 24) = csr_pmpcfg0_c(7 downto 4)) then
if (PMP_NUM_REGIONS >= 1) then
if (execute_engine.i_reg(23 downto 20) = csr_pmpcfg0_c(3 downto 0)) then -- pmpcfg0
for j in 0 to 3 loop -- bytes in pmpcfg CSR
if ((j+1) <= PMP_NUM_REGIONS) then
if (csr.pmpcfg(0+j)(7) = '0') then -- unlocked pmpcfg access
csr.pmpcfg(0+j)(0) <= csr.wdata(j*8+0); -- R
csr.pmpcfg(0+j)(1) <= csr.wdata(j*8+1); -- W
csr.pmpcfg(0+j)(2) <= csr.wdata(j*8+2); -- X
csr.pmpcfg(0+j)(3) <= csr.wdata(j*8+3) and csr.wdata(j*8+4); -- A_L
csr.pmpcfg(0+j)(4) <= csr.wdata(j*8+3) and csr.wdata(j*8+4); -- A_H - NAPOT/OFF only
csr.pmpcfg(0+j)(5) <= '0'; -- reserved
csr.pmpcfg(0+j)(6) <= '0'; -- reserved
csr.pmpcfg(0+j)(7) <= csr.wdata(j*8+7); -- L
end if;
end loop; -- j (bytes in CSR)
end if;
end if;
end loop; -- j (bytes in CSR)
end if;
if (PMP_NUM_REGIONS >= 5) then
if (execute_engine.i_reg(23 downto 20) = x"1") then -- pmpcfg1
for j in 0 to 3 loop -- bytes in pmpcfg CSR
if ((j+1+4) <= PMP_NUM_REGIONS) then
if (csr.pmpcfg(4+j)(7) = '0') then -- unlocked pmpcfg access
csr.pmpcfg(4+j)(0) <= csr.wdata(j*8+0); -- R
csr.pmpcfg(4+j)(1) <= csr.wdata(j*8+1); -- W
csr.pmpcfg(4+j)(2) <= csr.wdata(j*8+2); -- X
csr.pmpcfg(4+j)(3) <= csr.wdata(j*8+3) and csr.wdata(j*8+4); -- A_L
csr.pmpcfg(4+j)(4) <= csr.wdata(j*8+3) and csr.wdata(j*8+4); -- A_H - NAPOT/OFF only
csr.pmpcfg(4+j)(5) <= '0'; -- reserved
csr.pmpcfg(4+j)(6) <= '0'; -- reserved
csr.pmpcfg(4+j)(7) <= csr.wdata(j*8+7); -- L
end if;
end if;
if (PMP_NUM_REGIONS >= 5) then
if (execute_engine.i_reg(23 downto 20) = csr_pmpcfg1_c(3 downto 0)) then -- pmpcfg1
for j in 0 to 3 loop -- bytes in pmpcfg CSR
if ((j+1+4) <= PMP_NUM_REGIONS) then
if (csr.pmpcfg(4+j)(7) = '0') then -- unlocked pmpcfg access
csr.pmpcfg(4+j)(0) <= csr.wdata(j*8+0); -- R
csr.pmpcfg(4+j)(1) <= csr.wdata(j*8+1); -- W
csr.pmpcfg(4+j)(2) <= csr.wdata(j*8+2); -- X
csr.pmpcfg(4+j)(3) <= csr.wdata(j*8+3) and csr.wdata(j*8+4); -- A_L
csr.pmpcfg(4+j)(4) <= csr.wdata(j*8+3) and csr.wdata(j*8+4); -- A_H - NAPOT/OFF only
csr.pmpcfg(4+j)(5) <= '0'; -- reserved
csr.pmpcfg(4+j)(6) <= '0'; -- reserved
csr.pmpcfg(4+j)(7) <= csr.wdata(j*8+7); -- L
end if;
end loop; -- j (bytes in CSR)
end if;
end if;
end loop; -- j (bytes in CSR)
end if;
end if;
-- pmpaddr --
if (execute_engine.i_reg(27 downto 24) = x"b") then
for i in 0 to PMP_NUM_REGIONS-1 loop
if (execute_engine.i_reg(23 downto 20) = std_ulogic_vector(to_unsigned(i, 4))) and (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpaddr access
csr.pmpaddr(i) <= csr.wdata(31 downto 1) & '0'; -- min granularity is 8 bytes -> bit zero cannot be configured
end if;
end loop; -- i (CSRs)
end if;
end if; -- implement PMP at all?
end if;
end if;
-- pmpaddr --
if (execute_engine.i_reg(27 downto 24) = csr_pmpaddr0_c(7 downto 4)) then
for i in 0 to PMP_NUM_REGIONS-1 loop
if (execute_engine.i_reg(23 downto 20) = std_ulogic_vector(to_unsigned(i, 4))) and (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpaddr access
csr.pmpaddr(i) <= csr.wdata(31 downto 1) & '0'; -- min granularity is 8 bytes -> bit zero cannot be configured
end if;
end loop; -- i (CSRs)
end if;
end if; -- implement PMP at all?
end if;
 
-- automatic update by hardware --
else
end if;
 
-- machine exception PC & machine trap value register --
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
if (trap_ctrl.cause(trap_ctrl.cause'left) = '1') then -- for INTERRUPTS (is mcause(31))
csr.mepc <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- this is the CURRENT pc = interrupted instruction
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 -- 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 -- 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
else -- load/store misalignments/access errors
csr.mtval <= mar_i; -- faulting data access address
end if;
-- --------------------------------------------------------------------------------
-- CSRs that can be written by application and hardware (application access)
-- --------------------------------------------------------------------------------
if (CPU_EXTENSION_RISCV_Zicsr = true) and (csr.we = '1') then -- manual update
 
-- machine CSRs --
if (execute_engine.i_reg(31 downto 28) = csr_mstatus_c(11 downto 8)) then
 
-- machine trap setup --
if (execute_engine.i_reg(27 downto 20) = csr_mstatus_c(7 downto 0)) then -- R/W: mstatus - machine status register
csr.mstatus_mie <= csr.wdata(03);
csr.mstatus_mpie <= csr.wdata(07);
--
if (CPU_EXTENSION_RISCV_U = true) then -- user mode implemented
csr.mstatus_mpp(0) <= csr.wdata(11) or csr.wdata(12);
csr.mstatus_mpp(1) <= csr.wdata(11) or csr.wdata(12);
end if;
end if;
 
-- context switch in mstatus --
if (trap_ctrl.env_start_ack = '1') then -- ENTER: trap handler starting?
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
csr.privilege <= m_priv_mode_c; -- execute trap in machine mode
csr.mpp <= csr.privilege; -- buffer previous privilege mode
-- machine trap handling --
if (execute_engine.i_reg(27 downto 24) = csr_mepc_c(7 downto 4)) then
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;
elsif (trap_ctrl.env_end = '1') then -- EXIT: return from exception
csr.mstatus_mie <= csr.mstatus_mpie; -- restore global IRQ enable flag
csr.mstatus_mpie <= '1';
if (CPU_EXTENSION_RISCV_U = true) then -- implement user mode
csr.privilege <= csr.mpp; -- go back to previous privilege mode
csr.mpp <= u_priv_mode_c;
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;
end if;
 
-- user mode NOT implemented --
if (CPU_EXTENSION_RISCV_U = false) then -- implement user mode
csr.privilege <= m_priv_mode_c;
csr.mpp <= m_priv_mode_c;
end if;
 
-- --------------------------------------------------------------------------------
-- CSRs that can be written by application and hardware (hardware access)
-- --------------------------------------------------------------------------------
else -- hardware update
 
-- mepc & mtval: machine exception PC & machine trap value register --
if (trap_ctrl.env_start_ack = '1') then -- trap handler starting?
if (trap_ctrl.cause(trap_ctrl.cause'left) = '1') then -- for INTERRUPTS (is mcause(31))
csr.mepc <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- this is the CURRENT pc = interrupted instruction
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 -- 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 -- 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
else -- load/store misalignments/access errors
csr.mtval <= mar_i; -- faulting data access address
end if;
end if;
end if;
 
-- mstatus: context switch --
if (trap_ctrl.env_start_ack = '1') then -- ENTER: trap handler starting?
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
csr.privilege <= priv_mode_m_c; -- execute trap in machine mode
csr.mstatus_mpp <= csr.privilege; -- buffer previous privilege mode
end if;
elsif (trap_ctrl.env_end = '1') then -- EXIT: return from exception
csr.mstatus_mie <= csr.mstatus_mpie; -- restore global IRQ enable flag
csr.mstatus_mpie <= '1';
if (CPU_EXTENSION_RISCV_U = true) then -- implement user mode
csr.privilege <= csr.mstatus_mpp; -- go back to previous privilege mode
csr.mstatus_mpp <= priv_mode_u_c;
end if;
end if;
-- user mode NOT implemented --
if (CPU_EXTENSION_RISCV_U = false) then
csr.privilege <= priv_mode_m_c;
csr.mstatus_mpp <= priv_mode_m_c;
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;
 
1513,16 → 1549,17
begin
if rising_edge(clk_i) then
csr.rdata <= (others => '0'); -- default
csr.re <= csr.re_nxt; -- read access?
if (CPU_EXTENSION_RISCV_Zicsr = true) and (csr.re = '1') then
case execute_engine.i_reg(31 downto 20) is
case execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c) is
 
-- machine trap setup --
when x"300" => -- R/W: mstatus - machine status register
when csr_mstatus_c => -- R/W: mstatus - machine status register
csr.rdata(03) <= csr.mstatus_mie; -- MIE
csr.rdata(07) <= csr.mstatus_mpie; -- MPIE
csr.rdata(11) <= csr.mpp(0); -- MPP: machine previous privilege mode low
csr.rdata(12) <= csr.mpp(1); -- MPP: machine previous privilege mode high
when x"301" => -- R/-: misa - ISA and extensions
csr.rdata(11) <= csr.mstatus_mpp(0); -- MPP: machine previous privilege mode low
csr.rdata(12) <= csr.mstatus_mpp(1); -- MPP: machine previous privilege mode high
when csr_misa_c => -- R/-: misa - ISA and extensions
csr.rdata(02) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_C); -- C CPU extension
csr.rdata(04) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- E CPU extension
csr.rdata(08) <= not bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- I CPU extension (if not E)
1531,7 → 1568,7
csr.rdata(23) <= '1'; -- X CPU extension (non-std extensions)
csr.rdata(30) <= '1'; -- 32-bit architecture (MXL lo)
csr.rdata(31) <= '0'; -- 32-bit architecture (MXL hi)
when x"304" => -- R/W: mie - machine interrupt-enable register
when csr_mie_c => -- R/W: mie - machine interrupt-enable register
csr.rdata(03) <= csr.mie_msie; -- machine software IRQ enable
csr.rdata(07) <= csr.mie_mtie; -- machine timer IRQ enable
csr.rdata(11) <= csr.mie_meie; -- machine external IRQ enable
1540,19 → 1577,19
csr.rdata(17) <= csr.mie_firqe(1); -- fast interrupt channel 1
csr.rdata(18) <= csr.mie_firqe(2); -- fast interrupt channel 2
csr.rdata(19) <= csr.mie_firqe(3); -- fast interrupt channel 3
when x"305" => -- R/W: mtvec - machine trap-handler base address (for ALL exceptions)
when csr_mtvec_c => -- R/W: mtvec - machine trap-handler base address (for ALL exceptions)
csr.rdata <= csr.mtvec(data_width_c-1 downto 2) & "00"; -- mtvec.MODE=0
 
-- machine trap handling --
when x"340" => -- R/W: mscratch - machine scratch register
when csr_mscratch_c => -- R/W: mscratch - machine scratch register
csr.rdata <= csr.mscratch;
when x"341" => -- R/W: mepc - machine exception program counter
when csr_mepc_c => -- R/W: mepc - machine exception program counter
csr.rdata <= csr.mepc(data_width_c-1 downto 1) & '0';
when x"342" => -- R/-: mcause - machine trap cause
when csr_mcause_c => -- R/-: mcause - machine trap cause
csr.rdata <= csr.mcause;
when x"343" => -- R/W: mtval - machine bad address or instruction
when csr_mtval_c => -- R/W: mtval - machine bad address or instruction
csr.rdata <= csr.mtval;
when x"344" => -- R/W: mip - machine interrupt pending
when csr_mip_c => -- R/W: mip - machine interrupt pending
csr.rdata(03) <= trap_ctrl.irq_buf(interrupt_msw_irq_c);
csr.rdata(07) <= trap_ctrl.irq_buf(interrupt_mtime_irq_c);
csr.rdata(11) <= trap_ctrl.irq_buf(interrupt_mext_irq_c);
1563,7 → 1600,7
csr.rdata(19) <= trap_ctrl.irq_buf(interrupt_firq_3_c);
 
-- physical memory protection --
when x"3a0" => -- R/W: pmpcfg0 - physical memory protection configuration register 0
when csr_pmpcfg0_c => -- R/W: pmpcfg0 - physical memory protection configuration register 0
if (PMP_USE = true) then
if (PMP_NUM_REGIONS >= 1) then
csr.rdata(07 downto 00) <= csr.pmpcfg(0);
1578,7 → 1615,7
csr.rdata(31 downto 24) <= csr.pmpcfg(3);
end if;
end if;
when x"3a1" => -- R/W: pmpcfg1 - physical memory protection configuration register 1
when csr_pmpcfg1_c => -- R/W: pmpcfg1 - physical memory protection configuration register 1
if (PMP_USE = true) then
if (PMP_NUM_REGIONS >= 5) then
csr.rdata(07 downto 00) <= csr.pmpcfg(4);
1594,7 → 1631,7
end if;
end if;
 
when x"3b0" => -- R/W: pmpaddr0 - physical memory protection address register 0
when csr_pmpaddr0_c => -- R/W: pmpaddr0 - physical memory protection address register 0
if (PMP_USE = true) and (PMP_NUM_REGIONS >= 1) then
csr.rdata <= csr.pmpaddr(0);
if (csr.pmpcfg(0)(4 downto 3) = "00") then -- mode = off
1603,7 → 1640,7
csr.rdata(PMP_GRANULARITY-2 downto 0) <= (others => '1');
end if;
end if;
when x"3b1" => -- R/W: pmpaddr1 - physical memory protection address register 1
when csr_pmpaddr1_c => -- R/W: pmpaddr1 - physical memory protection address register 1
if (PMP_USE = true) and (PMP_NUM_REGIONS >= 2) then
csr.rdata <= csr.pmpaddr(1);
if (csr.pmpcfg(1)(4 downto 3) = "00") then -- mode = off
1612,7 → 1649,7
csr.rdata(PMP_GRANULARITY-2 downto 0) <= (others => '1');
end if;
end if;
when x"3b2" => -- R/W: pmpaddr2 - physical memory protection address register 2
when csr_pmpaddr2_c => -- R/W: pmpaddr2 - physical memory protection address register 2
if (PMP_USE = true) and (PMP_NUM_REGIONS >= 3) then
csr.rdata <= csr.pmpaddr(2);
if (csr.pmpcfg(2)(4 downto 3) = "00") then -- mode = off
1621,7 → 1658,7
csr.rdata(PMP_GRANULARITY-2 downto 0) <= (others => '1');
end if;
end if;
when x"3b3" => -- R/W: pmpaddr3 - physical memory protection address register 3
when csr_pmpaddr3_c => -- R/W: pmpaddr3 - physical memory protection address register 3
if (PMP_USE = true) and (PMP_NUM_REGIONS >= 4) then
csr.rdata <= csr.pmpaddr(3);
if (csr.pmpcfg(3)(4 downto 3) = "00") then -- mode = off
1630,7 → 1667,7
csr.rdata(PMP_GRANULARITY-2 downto 0) <= (others => '1');
end if;
end if;
when x"3b4" => -- R/W: pmpaddr4 - physical memory protection address register 4
when csr_pmpaddr4_c => -- R/W: pmpaddr4 - physical memory protection address register 4
if (PMP_USE = true) and (PMP_NUM_REGIONS >= 5) then
csr.rdata <= csr.pmpaddr(4);
if (csr.pmpcfg(4)(4 downto 3) = "00") then -- mode = off
1639,7 → 1676,7
csr.rdata(PMP_GRANULARITY-2 downto 0) <= (others => '1');
end if;
end if;
when x"3b5" => -- R/W: pmpaddr5 - physical memory protection address register 5
when csr_pmpaddr5_c => -- R/W: pmpaddr5 - physical memory protection address register 5
if (PMP_USE = true) and (PMP_NUM_REGIONS >= 6) then
csr.rdata <= csr.pmpaddr(5);
if (csr.pmpcfg(5)(4 downto 3) = "00") then -- mode = off
1648,7 → 1685,7
csr.rdata(PMP_GRANULARITY-2 downto 0) <= (others => '1');
end if;
end if;
when x"3b6" => -- R/W: pmpaddr6 - physical memory protection address register 6
when csr_pmpaddr6_c => -- R/W: pmpaddr6 - physical memory protection address register 6
if (PMP_USE = true) and (PMP_NUM_REGIONS >= 7) then
csr.rdata <= csr.pmpaddr(6);
if (csr.pmpcfg(6)(4 downto 3) = "00") then -- mode = off
1657,7 → 1694,7
csr.rdata(PMP_GRANULARITY-2 downto 0) <= (others => '1');
end if;
end if;
when x"3b7" => -- R/W: pmpaddr7 - physical memory protection address register 7
when csr_pmpaddr7_c => -- R/W: pmpaddr7 - physical memory protection address register 7
if (PMP_USE = true) and (PMP_NUM_REGIONS >= 8) then
csr.rdata <= csr.pmpaddr(7);
if (csr.pmpcfg(7)(4 downto 3) = "00") then -- mode = off
1667,32 → 1704,32
end if;
end if;
 
-- counter and timers --
when x"c00" | x"b00" => -- R/(W): cycle/mcycle: Cycle counter LOW
-- counters and timers --
when csr_cycle_c | csr_mcycle_c => -- R/(W): [m]cycle: Cycle counter LOW
csr.rdata <= csr.mcycle(31 downto 0);
when x"c01" => -- R/-: time: System time LOW (from MTIME unit)
when csr_time_c => -- R/-: time: System time LOW (from MTIME unit)
csr.rdata <= time_i(31 downto 0);
when x"c02" | x"b02" => -- R/(W): instret/minstret: Instructions-retired counter LOW
when csr_instret_c | csr_minstret_c => -- R/(W): [m]instret: Instructions-retired counter LOW
csr.rdata <= csr.minstret(31 downto 0);
when x"c80" | x"b80" => -- R/(W): cycleh/mcycleh: Cycle counter HIGH
when csr_cycleh_c | csr_mcycleh_c => -- R/(W): [m]cycleh: Cycle counter HIGH
csr.rdata <= csr.mcycleh(31 downto 0);
when x"c81" => -- R/-: timeh: System time HIGH (from MTIME unit)
when csr_timeh_c => -- R/-: timeh: System time HIGH (from MTIME unit)
csr.rdata <= time_i(63 downto 32);
when x"c82" | x"b82" => -- R/(W): instreth/minstreth: Instructions-retired counter HIGH
when csr_instreth_c | csr_minstreth_c => -- R/(W): [m]instreth: Instructions-retired counter HIGH
csr.rdata <= csr.minstreth(31 downto 0);
 
-- machine information registers --
when x"f11" => -- R/-: mvendorid - vendor ID
when csr_mvendorid_c => -- R/-: mvendorid - vendor ID
csr.rdata <= (others => '0');
when x"f12" => -- R/-: marchid - architecture ID
when csr_marchid_c => -- R/-: marchid - architecture ID
csr.rdata <= (others => '0');
when x"f13" => -- R/-: mimpid - implementation ID / NEORV32 hardware version
when csr_mimpid_c => -- R/-: mimpid - implementation ID / NEORV32 hardware version
csr.rdata <= hw_version_c;
when x"f14" => -- R/-: mhartid - hardware thread ID
when csr_mhartid_c => -- R/-: mhartid - hardware thread ID
csr.rdata <= HW_THREAD_ID;
 
-- custom machine read-only CSRs --
when x"fc0" => -- R/-: mzext
when csr_mzext_c => -- R/-: mzext
csr.rdata(0) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicsr); -- Zicsr CPU extension
csr.rdata(1) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zifencei); -- Zifencei CPU extension
 
1701,8 → 1738,6
csr.rdata <= (others => '0'); -- not implemented
 
end case;
else
csr.rdata <= (others => '0');
end if;
end if;
end process csr_read_access;
1742,7 → 1777,7
 
-- mcycle (cycle) --
mcycle_msb <= csr.mcycle(csr.mcycle'left);
if (csr.we = '1') and (execute_engine.i_reg(31 downto 20) = x"b00") then -- write access
if (csr.we = '1') and (execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c) = csr_mcycle_c) then -- write access
csr.mcycle(31 downto 0) <= csr.wdata;
csr.mcycle(32) <= '0';
elsif (execute_engine.sleep = '0') then -- automatic update (if CPU is not in sleep mode)
1750,7 → 1785,7
end if;
 
-- mcycleh (cycleh) --
if (csr.we = '1') and (execute_engine.i_reg(31 downto 20) = x"b80") then -- write access
if (csr.we = '1') and (execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c) = csr_mcycleh_c) then -- write access
csr.mcycleh <= csr.wdata(csr.mcycleh'left downto 0);
elsif ((mcycle_msb xor csr.mcycle(csr.mcycle'left)) = '1') then -- automatic update
csr.mcycleh <= std_ulogic_vector(unsigned(csr.mcycleh) + 1);
1758,7 → 1793,7
 
-- minstret (instret) --
minstret_msb <= csr.minstret(csr.minstret'left);
if (csr.we = '1') and (execute_engine.i_reg(31 downto 20) = x"b02") then -- write access
if (csr.we = '1') and (execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c) = csr_minstret_c) then -- write access
csr.minstret(31 downto 0) <= csr.wdata;
csr.minstret(32) <= '0';
elsif (execute_engine.state_prev /= EXECUTE) and (execute_engine.state = EXECUTE) then -- automatic update
1766,7 → 1801,7
end if;
 
-- minstreth (instreth) --
if (csr.we = '1') and (execute_engine.i_reg(31 downto 20) = x"b82") then -- write access
if (csr.we = '1') and (execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c) = csr_minstreth_c) then -- write access
csr.minstreth <= csr.wdata(csr.minstreth'left downto 0);
elsif ((minstret_msb xor csr.minstret(csr.minstret'left)) = '1') then -- automatic update
csr.minstreth <= std_ulogic_vector(unsigned(csr.minstreth) + 1);
/neorv32/trunk/rtl/core/neorv32_dmem.vhd
58,6 → 58,10
 
architecture neorv32_dmem_rtl of neorv32_dmem is
 
-- IO space: module base address --
constant hi_abb_c : natural := 31; -- high address boundary bit
constant lo_abb_c : natural := index_size_f(DMEM_SIZE); -- low address boundary bit
 
-- local signals --
signal acc_en : std_ulogic;
signal rdata : std_ulogic_vector(31 downto 0);
96,7 → 100,7
 
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (addr_i >= DMEM_BASE) and (addr_i < std_ulogic_vector(unsigned(DMEM_BASE) + DMEM_SIZE)) else '0';
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = DMEM_BASE(hi_abb_c downto lo_abb_c)) else '0';
addr <= addr_i(index_size_f(DMEM_SIZE/4)+1 downto 2); -- word aligned
 
 
/neorv32/trunk/rtl/core/neorv32_imem.vhd
67,6 → 67,10
 
architecture neorv32_imem_rtl of neorv32_imem is
 
-- IO space: module base address --
constant hi_abb_c : natural := 31; -- high address boundary bit
constant lo_abb_c : natural := index_size_f(IMEM_SIZE); -- low address boundary bit
 
-- ROM types --
type imem_file8_t is array (0 to IMEM_SIZE/4-1) of std_ulogic_vector(07 downto 0);
 
140,7 → 144,7
 
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (addr_i >= IMEM_BASE) and (addr_i < std_ulogic_vector(unsigned(IMEM_BASE) + IMEM_SIZE)) else '0';
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = IMEM_BASE(hi_abb_c downto lo_abb_c)) else '0';
addr <= addr_i(index_size_f(IMEM_SIZE/4)+1 downto 2); -- word aligned
 
 
/neorv32/trunk/rtl/core/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"01040400"; -- no touchy!
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01040402"; -- no touchy!
constant pmp_max_r_c : natural := 8; -- max PMP regions - FIXED!
 
-- Architecture Configuration -------------------------------------------------------------
183,9 → 183,9
constant ctrl_alu_cmd0_c : natural := 19; -- ALU command bit 0
constant ctrl_alu_cmd1_c : natural := 20; -- ALU command bit 1
constant ctrl_alu_cmd2_c : natural := 21; -- ALU command bit 2
constant ctrl_alu_opa_mux_c : natural := 22; -- operand A select (0=rs1, 1=PC)
constant ctrl_alu_opb_mux_c : natural := 23; -- operand B select (0=rs2, 1=IMM)
constant ctrl_alu_opc_mux_c : natural := 24; -- operand C select (0=rs2, 1=IMM)
constant ctrl_alu_addsub_c : natural := 22; -- 0=ADD, 1=SUB
constant ctrl_alu_opa_mux_c : natural := 23; -- operand A select (0=rs1, 1=PC)
constant ctrl_alu_opb_mux_c : natural := 24; -- operand B select (0=rs2, 1=IMM)
constant ctrl_alu_unsigned_c : natural := 25; -- is unsigned ALU operation
constant ctrl_alu_shift_dir_c : natural := 26; -- shift direction (0=left, 1=right)
constant ctrl_alu_shift_ar_c : natural := 27; -- is arithmetic shift
204,17 → 204,14
constant ctrl_bus_fence_c : natural := 39; -- executed fence operation
constant ctrl_bus_fencei_c : natural := 40; -- executed fencei operation
-- co-processors --
constant ctrl_cp_use_c : natural := 41; -- is cp operation
constant ctrl_cp_id_lsb_c : natural := 42; -- cp select ID lsb
constant ctrl_cp_id_msb_c : natural := 43; -- cp select ID msb
constant ctrl_cp_cmd0_c : natural := 44; -- cp command bit 0
constant ctrl_cp_cmd1_c : natural := 45; -- cp command bit 1
constant ctrl_cp_cmd2_c : natural := 46; -- cp command bit 2
constant ctrl_cp_id_lsb_c : natural := 41; -- cp select ID lsb
constant ctrl_cp_id_msb_c : natural := 42; -- cp select ID msb
constant ctrl_cp_cmd0_c : natural := 43; -- cp command bit 0
constant ctrl_cp_cmd1_c : natural := 44; -- cp command bit 1
constant ctrl_cp_cmd2_c : natural := 45; -- cp command bit 2
-- control bus size --
constant ctrl_width_c : natural := 47; -- control bus size
constant ctrl_width_c : natural := 46; -- control bus size
 
constant ctrl_alu_aopb_inv_c : natural := 48;
 
-- ALU Comparator Bus ---------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant alu_cmp_equal_c : natural := 0;
252,7 → 249,7
constant opcode_alu_c : std_ulogic_vector(6 downto 0) := "0110011"; -- ALU operation (operation via funct3 and funct7)
-- control flow --
constant opcode_jal_c : std_ulogic_vector(6 downto 0) := "1101111"; -- jump and link
constant opcode_jalr_c : std_ulogic_vector(6 downto 0) := "1100111"; -- jump and register
constant opcode_jalr_c : std_ulogic_vector(6 downto 0) := "1100111"; -- jump and link with register
constant opcode_branch_c : std_ulogic_vector(6 downto 0) := "1100011"; -- branch (condition set via funct3)
-- memory access --
constant opcode_load_c : std_ulogic_vector(6 downto 0) := "0000011"; -- load (data type via funct3)
309,6 → 306,52
constant funct12_mret_c : std_ulogic_vector(11 downto 0) := x"302"; -- MRET
constant funct12_wfi_c : std_ulogic_vector(11 downto 0) := x"105"; -- WFI
 
-- RISC-V CSR Addresses -------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant csr_mstatus_c : std_ulogic_vector(11 downto 0) := x"300"; -- mstatus
constant csr_misa_c : std_ulogic_vector(11 downto 0) := x"301"; -- misa
constant csr_mie_c : std_ulogic_vector(11 downto 0) := x"304"; -- mie
constant csr_mtvec_c : std_ulogic_vector(11 downto 0) := x"305"; -- mtvec
--
constant csr_mscratch_c : std_ulogic_vector(11 downto 0) := x"340"; -- mscratch
constant csr_mepc_c : std_ulogic_vector(11 downto 0) := x"341"; -- mepc
constant csr_mcause_c : std_ulogic_vector(11 downto 0) := x"342"; -- mcause
constant csr_mtval_c : std_ulogic_vector(11 downto 0) := x"343"; -- mtval
constant csr_mip_c : std_ulogic_vector(11 downto 0) := x"344"; -- mip
--
constant csr_pmpcfg0_c : std_ulogic_vector(11 downto 0) := x"3a0"; -- pmpcfg0
constant csr_pmpcfg1_c : std_ulogic_vector(11 downto 0) := x"3a1"; -- pmpcfg1
--
constant csr_pmpaddr0_c : std_ulogic_vector(11 downto 0) := x"3b0"; -- pmpaddr0
constant csr_pmpaddr1_c : std_ulogic_vector(11 downto 0) := x"3b1"; -- pmpaddr1
constant csr_pmpaddr2_c : std_ulogic_vector(11 downto 0) := x"3b2"; -- pmpaddr2
constant csr_pmpaddr3_c : std_ulogic_vector(11 downto 0) := x"3b3"; -- pmpaddr3
constant csr_pmpaddr4_c : std_ulogic_vector(11 downto 0) := x"3b4"; -- pmpaddr4
constant csr_pmpaddr5_c : std_ulogic_vector(11 downto 0) := x"3b5"; -- pmpaddr5
constant csr_pmpaddr6_c : std_ulogic_vector(11 downto 0) := x"3b6"; -- pmpaddr6
constant csr_pmpaddr7_c : std_ulogic_vector(11 downto 0) := x"3b7"; -- pmpaddr7
--
constant csr_mcycle_c : std_ulogic_vector(11 downto 0) := x"b00"; -- mcycle
constant csr_minstret_c : std_ulogic_vector(11 downto 0) := x"b02"; -- minstret
--
constant csr_mcycleh_c : std_ulogic_vector(11 downto 0) := x"b80"; -- mcycleh
constant csr_minstreth_c : std_ulogic_vector(11 downto 0) := x"b82"; -- minstreth
--
constant csr_cycle_c : std_ulogic_vector(11 downto 0) := x"c00"; -- cycle
constant csr_time_c : std_ulogic_vector(11 downto 0) := x"c01"; -- time
constant csr_instret_c : std_ulogic_vector(11 downto 0) := x"c02"; -- instret
--
constant csr_cycleh_c : std_ulogic_vector(11 downto 0) := x"c80"; -- cycleh
constant csr_timeh_c : std_ulogic_vector(11 downto 0) := x"c81"; -- timeh
constant csr_instreth_c : std_ulogic_vector(11 downto 0) := x"c82"; -- instreth
--
constant csr_mvendorid_c : std_ulogic_vector(11 downto 0) := x"f11"; -- mvendorid
constant csr_marchid_c : std_ulogic_vector(11 downto 0) := x"f12"; -- marchid
constant csr_mimpid_c : std_ulogic_vector(11 downto 0) := x"f13"; -- mimpid
constant csr_mhartid_c : std_ulogic_vector(11 downto 0) := x"f14"; -- mhartid
--
constant csr_mzext_c : std_ulogic_vector(11 downto 0) := x"fc0"; -- mzext
 
-- Co-Processor Operations ----------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
-- cp ids --
325,14 → 368,14
 
-- ALU Function Codes ---------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant alu_cmd_add_c : std_ulogic_vector(2 downto 0) := "000"; -- r <= A + B
constant alu_cmd_sub_c : std_ulogic_vector(2 downto 0) := "001"; -- r <= A - B
constant alu_cmd_slt_c : std_ulogic_vector(2 downto 0) := "010"; -- r <= A < B
constant alu_cmd_shift_c : std_ulogic_vector(2 downto 0) := "011"; -- r <= A <</>> B
constant alu_cmd_xor_c : std_ulogic_vector(2 downto 0) := "100"; -- r <= A xor B
constant alu_cmd_or_c : std_ulogic_vector(2 downto 0) := "101"; -- r <= A or B
constant alu_cmd_and_c : std_ulogic_vector(2 downto 0) := "110"; -- r <= A and B
constant alu_cmd_movb_c : std_ulogic_vector(2 downto 0) := "111"; -- r <= B
constant alu_cmd_addsub_c : std_ulogic_vector(2 downto 0) := "000"; -- r <= A +/- B
constant alu_cmd_slt_c : std_ulogic_vector(2 downto 0) := "001"; -- r <= A < B
constant alu_cmd_cp_c : std_ulogic_vector(2 downto 0) := "010"; -- r <= CP result (iterative)
constant alu_cmd_shift_c : std_ulogic_vector(2 downto 0) := "011"; -- r <= A <</>> B (iterative)
constant alu_cmd_movb_c : std_ulogic_vector(2 downto 0) := "100"; -- r <= B
constant alu_cmd_xor_c : std_ulogic_vector(2 downto 0) := "101"; -- r <= A xor B
constant alu_cmd_or_c : std_ulogic_vector(2 downto 0) := "110"; -- r <= A or B
constant alu_cmd_and_c : std_ulogic_vector(2 downto 0) := "111"; -- r <= A and B
 
-- Trap ID Codes --------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
383,8 → 426,8
 
-- CPU Privilege Modes --------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
constant m_priv_mode_c : std_ulogic_vector(1 downto 0) := "11"; -- machine mode
constant u_priv_mode_c : std_ulogic_vector(1 downto 0) := "00"; -- user mode
constant priv_mode_m_c : std_ulogic_vector(1 downto 0) := "11"; -- machine mode
constant priv_mode_u_c : std_ulogic_vector(1 downto 0) := "00"; -- user mode
 
-- Clock Generator -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
571,7 → 614,6
-- data input --
instr_i : in std_ulogic_vector(data_width_c-1 downto 0); -- instruction
cmp_i : in std_ulogic_vector(1 downto 0); -- comparator status
alu_add_i : in std_ulogic_vector(data_width_c-1 downto 0); -- ALU.add result
alu_res_i : in std_ulogic_vector(data_width_c-1 downto 0); -- ALU processing result
-- data output --
imm_o : out std_ulogic_vector(data_width_c-1 downto 0); -- immediate
641,7 → 683,6
imm_i : in std_ulogic_vector(data_width_c-1 downto 0); -- immediate
-- data output --
cmp_o : out std_ulogic_vector(1 downto 0); -- comparator status
add_o : out std_ulogic_vector(data_width_c-1 downto 0); -- OPA + OPB
res_o : out std_ulogic_vector(data_width_c-1 downto 0); -- ALU result
-- co-processor interface --
cp0_start_o : out std_ulogic; -- trigger co-processor 0
/neorv32/trunk/rtl/core/neorv32_top.vhd
131,6 → 131,10
-- CPU boot address --
constant cpu_boot_addr_c : std_ulogic_vector(31 downto 0) := cond_sel_stdulogicvector_f(BOOTLOADER_USE, boot_rom_base_c, ispace_base_c);
 
-- alignment check for internal memories --
constant imem_align_check_c : std_ulogic_vector(index_size_f(MEM_INT_IMEM_SIZE)-1 downto 0) := (others => '0');
constant dmem_align_check_c : std_ulogic_vector(index_size_f(MEM_INT_DMEM_SIZE)-1 downto 0) := (others => '0');
 
-- reset generator --
signal rstn_i_sync0 : std_ulogic;
signal rstn_i_sync1 : std_ulogic;
227,15 → 231,18
-- memory system - data/instruction fetch --
assert not ((MEM_EXT_USE = false) and (MEM_INT_DMEM_USE = false)) report "NEORV32 PROCESSOR CONFIG ERROR! Core cannot fetch data without external memory interface and internal data memory." severity error;
assert not ((MEM_EXT_USE = false) and (MEM_INT_IMEM_USE = false) and (BOOTLOADER_USE = false)) report "NEORV32 PROCESSOR CONFIG ERROR! Core cannot fetch instructions without external memory interface, internal data memory and bootloader." severity error;
-- memory system --
assert not (imem_base_c(1 downto 0) /= "00") report "NEORV32 PROCESSOR CONFIG ERROR! Instruction memory space base address must be 4-byte-aligned." severity error;
assert not (dmem_base_c(1 downto 0) /= "00") report "NEORV32 PROCESSOR CONFIG ERROR! Data memory space base address must be 4-byte-aligned." severity error;
-- memory system - alignment --
assert not (ispace_base_c(1 downto 0) /= "00") report "NEORV32 PROCESSOR CONFIG ERROR! Instruction memory space base address must be 4-byte-aligned." severity error;
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 --
assert not (imem_base_c /= x"00000000") report "NEORV32 PROCESSOR CONFIG WARNING! Non-default base address for instruction address space. Make sure this is sync with the software framework." severity warning;
assert not (dmem_base_c /= x"80000000") report "NEORV32 PROCESSOR CONFIG WARNING! Non-default base address for data address space. Make sure this is sync with the software framework." severity warning;
assert not (ispace_base_c /= x"00000000") report "NEORV32 PROCESSOR CONFIG WARNING! Non-default base address for instruction address space. Make sure this is sync with the software framework." severity warning;
assert not (dspace_base_c /= x"80000000") report "NEORV32 PROCESSOR CONFIG WARNING! Non-default base address for data address space. Make sure this is sync with the software framework." severity warning;
 
 
-- Reset Generator ------------------------------------------------------------------------
/neorv32/trunk/rtl/fpga_specific/lattice_ice40up/neorv32_dmem.ice40up_spram.vhd
67,6 → 67,10
constant spram_sleep_mode_en_c : boolean := false; -- put DMEM into sleep mode when idle (for low power)
-- -------------------------------------------------------------------------------------------------------
 
-- IO space: module base address --
constant hi_abb_c : natural := 31; -- high address boundary bit
constant lo_abb_c : natural := index_size_f(DMEM_SIZE); -- low address boundary bit
 
-- local signals --
signal acc_en : std_ulogic;
signal mem_cs : std_ulogic;
90,7 → 94,7
 
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (unsigned(addr_i) >= unsigned(DMEM_BASE)) and (unsigned(addr_i) < unsigned(DMEM_BASE) + DMEM_SIZE) else '0';
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = DMEM_BASE(hi_abb_c downto lo_abb_c)) else '0';
mem_cs <= acc_en and (rden_i or wren_i);
 
 
/neorv32/trunk/rtl/fpga_specific/lattice_ice40up/neorv32_imem.ice40up_spram.vhd
70,6 → 70,10
constant spram_sleep_mode_en_c : boolean := false; -- put IMEM into sleep mode when idle (for low power)
-- -------------------------------------------------------------------------------------------------------
 
-- IO space: module base address --
constant hi_abb_c : natural := 31; -- high address boundary bit
constant lo_abb_c : natural := index_size_f(IMEM_SIZE); -- low address boundary bit
 
-- local signals --
signal acc_en : std_ulogic;
signal mem_cs : std_ulogic;
93,7 → 97,7
 
-- Access Control -------------------------------------------------------------------------
-- -------------------------------------------------------------------------------------------
acc_en <= '1' when (unsigned(addr_i) >= unsigned(IMEM_BASE)) and (unsigned(addr_i) < unsigned(IMEM_BASE) + IMEM_SIZE) else '0';
acc_en <= '1' when (addr_i(hi_abb_c downto lo_abb_c) = IMEM_BASE(hi_abb_c downto lo_abb_c)) else '0';
mem_cs <= acc_en and (rden_i or wren_i);
 
 
/neorv32/trunk/rtl/fpga_specific/README.md
1,7 → 1,12
## FPGA Platform-Specific Components
 
This folder contains FPGA vendor-specific components (mostly memory components).
These alternative files allow a more efficient usage of the special (FPGA-specific) hard macros.
This folder contains FPGA vendor-specific CPU/processor components (mostly memory components).
These alternative files allow a more efficient usage of the special (FPGA-specific) hard macros
and thus, might result in higher performance and/or less area utilization.
 
For example, if you want to use the FPGA optimized version of the DMEM, please use the file from the
according FPGA vendor folder instead of the original file from the rtl/core folder.
Please note, that these FPGA-specific components are **optional**. The Processor/CPU uses an FPGA-independent
VHDL description.
 
For example, if you want to use the Lattice iCE40up FPGA optimized versions of the DMEM and DMEM please use the files
from [`rtl/fpga_specific/lattice_ice40up`](https://github.com/stnolting/neorv32/tree/master/rtl/fpga_specific/lattice_ice40up)
folder **instead** of the original files from the [`rtl/core folder`](https://github.com/stnolting/neorv32/tree/master/rtl/core).
/neorv32/trunk/sw/example/cpu_test/main.c
128,6 → 128,7
 
// init UART at default baud rate, no rx interrupt, no tx interrupt
neorv32_uart_setup(BAUD_RATE, 0, 0);
 
neorv32_mtime_set_time(0);
// set CMP of machine system timer MTIME to max to prevent an IRQ
135,7 → 136,8
neorv32_mtime_set_timecmp(mtime_cmp_max);
 
// intro
neorv32_uart_printf("\n\n--- CPU TEST ---\n\n");
neorv32_uart_printf("\n\n--- CPU TEST ---\n");
neorv32_uart_printf("build: "__DATE__" "__TIME__"\n\n");
 
// show project credits
neorv32_rte_print_credits();

powered by: WebSVN 2.1.0

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