URL
https://opencores.org/ocsvn/neorv32/neorv32/trunk
Subversion Repositories neorv32
Compare Revisions
- This comparison shows the changes necessary to convert path
/neorv32/trunk/rtl/core
- from Rev 28 to Rev 29
- ↔ Reverse comparison
Rev 28 → Rev 29
/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_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_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_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_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_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_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_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_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 ------------------------------------------------------------------------ |