Line 53... |
Line 53... |
-- RISC-V CPU Extensions --
|
-- RISC-V CPU Extensions --
|
CPU_EXTENSION_RISCV_A : boolean := false; -- implement atomic extension?
|
CPU_EXTENSION_RISCV_A : boolean := false; -- implement atomic extension?
|
CPU_EXTENSION_RISCV_B : boolean := false; -- implement bit manipulation extensions?
|
CPU_EXTENSION_RISCV_B : boolean := false; -- implement bit manipulation extensions?
|
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
|
CPU_EXTENSION_RISCV_C : boolean := false; -- implement compressed extension?
|
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
|
CPU_EXTENSION_RISCV_E : boolean := false; -- implement embedded RF extension?
|
|
CPU_EXTENSION_RISCV_F : boolean := false; -- implement 32-bit floating-point extension?
|
CPU_EXTENSION_RISCV_M : boolean := false; -- implement muld/div extension?
|
CPU_EXTENSION_RISCV_M : boolean := false; -- implement muld/div extension?
|
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension?
|
CPU_EXTENSION_RISCV_U : boolean := false; -- implement user mode extension?
|
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
|
CPU_EXTENSION_RISCV_Zicsr : boolean := true; -- implement CSR system?
|
CPU_EXTENSION_RISCV_Zifencei : boolean := false; -- implement instruction stream sync.?
|
CPU_EXTENSION_RISCV_Zifencei : boolean := false; -- implement instruction stream sync.?
|
-- Physical memory protection (PMP) --
|
-- Physical memory protection (PMP) --
|
Line 82... |
Line 83... |
-- data output --
|
-- data output --
|
imm_o : out std_ulogic_vector(data_width_c-1 downto 0); -- immediate
|
imm_o : out std_ulogic_vector(data_width_c-1 downto 0); -- immediate
|
fetch_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- PC for instruction fetch
|
fetch_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- PC for instruction fetch
|
curr_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- current PC (corresponding to current instruction)
|
curr_pc_o : out std_ulogic_vector(data_width_c-1 downto 0); -- current PC (corresponding to current instruction)
|
csr_rdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- CSR read data
|
csr_rdata_o : out std_ulogic_vector(data_width_c-1 downto 0); -- CSR read data
|
|
-- FPU interface --
|
|
fpu_rm_o : out std_ulogic_vector(02 downto 0); -- rounding mode
|
|
fpu_flags_i : in std_ulogic_vector(04 downto 0); -- exception flags
|
-- interrupts (risc-v compliant) --
|
-- interrupts (risc-v compliant) --
|
msw_irq_i : in std_ulogic; -- machine software interrupt
|
msw_irq_i : in std_ulogic; -- machine software interrupt
|
mext_irq_i : in std_ulogic; -- machine external interrupt
|
mext_irq_i : in std_ulogic; -- machine external interrupt
|
mtime_irq_i : in std_ulogic; -- machine timer interrupt
|
mtime_irq_i : in std_ulogic; -- machine timer interrupt
|
-- fast interrupts (custom) --
|
-- fast interrupts (custom) --
|
Line 174... |
Line 178... |
rs1_is_r0 : std_ulogic;
|
rs1_is_r0 : std_ulogic;
|
is_atomic_lr : std_ulogic;
|
is_atomic_lr : std_ulogic;
|
is_atomic_sc : std_ulogic;
|
is_atomic_sc : std_ulogic;
|
is_bitmanip_imm : std_ulogic;
|
is_bitmanip_imm : std_ulogic;
|
is_bitmanip_reg : std_ulogic;
|
is_bitmanip_reg : std_ulogic;
|
|
is_float_f_reg : std_ulogic;
|
|
is_float_i_reg : std_ulogic;
|
sys_env_cmd : std_ulogic_vector(11 downto 0);
|
sys_env_cmd : std_ulogic_vector(11 downto 0);
|
end record;
|
end record;
|
signal decode_aux : decode_aux_t;
|
signal decode_aux : decode_aux_t;
|
|
|
-- instruction execution engine --
|
-- instruction execution engine --
|
Line 194... |
Line 200... |
--
|
--
|
is_ci : std_ulogic; -- current instruction is de-compressed instruction
|
is_ci : std_ulogic; -- current instruction is de-compressed instruction
|
is_ci_nxt : std_ulogic;
|
is_ci_nxt : std_ulogic;
|
is_cp_op : std_ulogic; -- current instruction is a co-processor operation
|
is_cp_op : std_ulogic; -- current instruction is a co-processor operation
|
is_cp_op_nxt : std_ulogic;
|
is_cp_op_nxt : std_ulogic;
|
|
is_fp : std_ulogic; -- floating-point operation - do not access to integer register file
|
|
is_fp_nxt : std_ulogic;
|
--
|
--
|
branch_taken : std_ulogic; -- branch condition fullfilled
|
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 : std_ulogic_vector(data_width_c-1 downto 0); -- actual PC, corresponding to current executed instruction
|
pc_mux_sel : std_ulogic; -- source select for PC update
|
pc_mux_sel : std_ulogic; -- source select for PC update
|
pc_we : std_ulogic; -- PC update enabled
|
pc_we : std_ulogic; -- PC update enabled
|
Line 320... |
Line 328... |
--
|
--
|
pmpcfg : pmp_ctrl_t; -- physical memory protection - configuration registers
|
pmpcfg : pmp_ctrl_t; -- physical memory protection - configuration registers
|
pmpcfg_rd : pmp_ctrl_rd_t; -- physical memory protection - actual read data
|
pmpcfg_rd : pmp_ctrl_rd_t; -- physical memory protection - actual read data
|
pmpaddr : pmp_addr_t; -- physical memory protection - address registers
|
pmpaddr : pmp_addr_t; -- physical memory protection - address registers
|
pmpaddr_rd : pmp_addr_rd_t; -- physical memory protection - actual read data
|
pmpaddr_rd : pmp_addr_rd_t; -- physical memory protection - actual read data
|
|
--
|
|
frm : std_ulogic_vector(02 downto 0); -- frm (R/W): FPU rounding mode
|
|
fflags : std_ulogic_vector(04 downto 0); -- fflags (R/W): FPU exception flags
|
end record;
|
end record;
|
signal csr : csr_t;
|
signal csr : csr_t;
|
|
|
-- counter low-to-high-word carry --
|
-- counter low-to-high-word carry --
|
signal mcycle_msb : std_ulogic;
|
signal mcycle_msb : std_ulogic;
|
Line 604... |
Line 615... |
if rising_edge(clk_i) then
|
if rising_edge(clk_i) then
|
if (execute_engine.state = BRANCH) then -- next_PC as immediate for jump-and-link operations (=return address) via ALU.MOV_B
|
if (execute_engine.state = BRANCH) then -- next_PC as immediate for jump-and-link operations (=return address) via ALU.MOV_B
|
imm_o <= execute_engine.next_pc;
|
imm_o <= execute_engine.next_pc;
|
else -- "normal" immediate from instruction word
|
else -- "normal" immediate from instruction word
|
case opcode_v is -- save some bits here, the two LSBs are always "11" for rv32
|
case opcode_v is -- save some bits here, the two LSBs are always "11" for rv32
|
when opcode_store_c => -- S-immediate
|
when opcode_store_c | opcode_fsw_c => -- S-immediate
|
imm_o(31 downto 11) <= (others => execute_engine.i_reg(31)); -- sign extension
|
imm_o(31 downto 11) <= (others => execute_engine.i_reg(31)); -- sign extension
|
imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
|
imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
|
imm_o(04 downto 01) <= execute_engine.i_reg(11 downto 08);
|
imm_o(04 downto 01) <= execute_engine.i_reg(11 downto 08);
|
imm_o(00) <= execute_engine.i_reg(07);
|
imm_o(00) <= execute_engine.i_reg(07);
|
when opcode_branch_c => -- B-immediate
|
when opcode_branch_c => -- B-immediate
|
Line 693... |
Line 704... |
if rising_edge(clk_i) then
|
if rising_edge(clk_i) then
|
execute_engine.state_prev <= execute_engine.state;
|
execute_engine.state_prev <= execute_engine.state;
|
execute_engine.i_reg <= execute_engine.i_reg_nxt;
|
execute_engine.i_reg <= execute_engine.i_reg_nxt;
|
execute_engine.is_ci <= execute_engine.is_ci_nxt;
|
execute_engine.is_ci <= execute_engine.is_ci_nxt;
|
execute_engine.is_cp_op <= execute_engine.is_cp_op_nxt;
|
execute_engine.is_cp_op <= execute_engine.is_cp_op_nxt;
|
|
execute_engine.is_fp <= execute_engine.is_fp_nxt;
|
-- PC & IR of "last executed" instruction --
|
-- PC & IR of "last executed" instruction --
|
if (execute_engine.state = EXECUTE) then
|
if (execute_engine.state = EXECUTE) then
|
execute_engine.last_pc <= execute_engine.pc;
|
execute_engine.last_pc <= execute_engine.pc;
|
execute_engine.i_reg_last <= execute_engine.i_reg;
|
execute_engine.i_reg_last <= execute_engine.i_reg;
|
end if;
|
end if;
|
Line 766... |
Line 778... |
decode_aux.rs1_is_r0 <= '0';
|
decode_aux.rs1_is_r0 <= '0';
|
decode_aux.is_atomic_lr <= '0';
|
decode_aux.is_atomic_lr <= '0';
|
decode_aux.is_atomic_sc <= '0';
|
decode_aux.is_atomic_sc <= '0';
|
decode_aux.is_bitmanip_imm <= '0';
|
decode_aux.is_bitmanip_imm <= '0';
|
decode_aux.is_bitmanip_reg <= '0';
|
decode_aux.is_bitmanip_reg <= '0';
|
|
decode_aux.is_float_f_reg <= '0';
|
|
decode_aux.is_float_i_reg <= '0';
|
|
|
-- is immediate ALU operation? --
|
-- is immediate ALU operation? --
|
decode_aux.alu_immediate <= not execute_engine.i_reg(instr_opcode_msb_c-1);
|
decode_aux.alu_immediate <= not execute_engine.i_reg(instr_opcode_msb_c-1);
|
|
|
-- is rs1 == r0? --
|
-- is rs1 == r0? --
|
decode_aux.rs1_is_r0 <= not or_all_f(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c));
|
decode_aux.rs1_is_r0 <= not or_all_f(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c));
|
|
|
-- is atomic load-reservate/store-conditional? --
|
-- is atomic load-reservate/store-conditional? --
|
if (CPU_EXTENSION_RISCV_A = true) and (execute_engine.i_reg(instr_opcode_lsb_c+2) = '1') then -- valid atomic sub-opcode
|
if (CPU_EXTENSION_RISCV_A = true) and (execute_engine.i_reg(instr_opcode_lsb_c+3 downto instr_opcode_lsb_c+2) = "11") then -- valid atomic sub-opcode
|
decode_aux.is_atomic_lr <= not execute_engine.i_reg(instr_funct5_lsb_c);
|
decode_aux.is_atomic_lr <= not execute_engine.i_reg(instr_funct5_lsb_c);
|
decode_aux.is_atomic_sc <= execute_engine.i_reg(instr_funct5_lsb_c);
|
decode_aux.is_atomic_sc <= execute_engine.i_reg(instr_funct5_lsb_c);
|
end if;
|
end if;
|
|
|
-- is BITMANIP instruction? --
|
-- is BITMANIP instruction? --
|
Line 818... |
Line 832... |
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0010100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- SBSET
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0010100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- SBSET
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0110100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- SBINV
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0110100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- SBINV
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0100100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101")) then -- SBSEXT
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0100100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "101")) then -- SBSEXT
|
decode_aux.is_bitmanip_reg <= '1';
|
decode_aux.is_bitmanip_reg <= '1';
|
end if;
|
end if;
|
|
|
|
-- floating-point FLOAT_register operations --
|
|
if ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "11110")) or -- FMV.W.X
|
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00000")) or -- FADD.S
|
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00001")) or -- FSUB.S
|
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00010")) or -- FMUL.S
|
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00011")) or -- FDIV.S
|
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "01011") and (execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c) = "00000")) or -- FSQRT.S
|
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00100") and (execute_engine.i_reg(instr_funct3_msb_c) = '0')) or -- FSGNJ[N/X].S
|
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "00101") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_msb_c-1) = "00")) or -- FMIN.S / FMAX.S
|
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "11010") and (execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c+1) = "0000")) then -- FCVT.S.W*
|
|
decode_aux.is_float_f_reg <= '1';
|
|
end if;
|
|
-- floating-point INTEGER_register operations --
|
|
if ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "11100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_msb_c-1) = "00")) or -- FMV.X.W / FCLASS.S
|
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "10100") and (execute_engine.i_reg(instr_funct3_msb_c) = '0')) or -- FEQ.S / FLT.S / FLE.S
|
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "11000") and (execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c+1) = "0000")) then -- FCVT.W*.S
|
|
decode_aux.is_float_i_reg <= '1';
|
|
end if;
|
|
|
-- system/environment instructions --
|
-- system/environment instructions --
|
sys_env_cmd_mask_v := funct12_ecall_c or funct12_ebreak_c or funct12_mret_c or funct12_wfi_c; -- sum-up set bits
|
sys_env_cmd_mask_v := funct12_ecall_c or funct12_ebreak_c or funct12_mret_c or funct12_wfi_c; -- sum-up set bits
|
decode_aux.sys_env_cmd(11 downto 0) <= execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) and sys_env_cmd_mask_v; -- set unsued bits to always-zero
|
decode_aux.sys_env_cmd(11 downto 0) <= execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) and sys_env_cmd_mask_v; -- set unsued bits to always-zero
|
end process decode_helper;
|
end process decode_helper;
|
|
|
Line 835... |
Line 869... |
-- arbiter defaults --
|
-- arbiter defaults --
|
execute_engine.state_nxt <= execute_engine.state;
|
execute_engine.state_nxt <= execute_engine.state;
|
execute_engine.i_reg_nxt <= execute_engine.i_reg;
|
execute_engine.i_reg_nxt <= execute_engine.i_reg;
|
execute_engine.is_cp_op_nxt <= execute_engine.is_cp_op;
|
execute_engine.is_cp_op_nxt <= execute_engine.is_cp_op;
|
execute_engine.is_ci_nxt <= execute_engine.is_ci;
|
execute_engine.is_ci_nxt <= execute_engine.is_ci;
|
|
execute_engine.is_fp_nxt <= execute_engine.is_fp;
|
execute_engine.sleep_nxt <= execute_engine.sleep;
|
execute_engine.sleep_nxt <= execute_engine.sleep;
|
execute_engine.branched_nxt <= execute_engine.branched;
|
execute_engine.branched_nxt <= execute_engine.branched;
|
--
|
--
|
execute_engine.pc_mux_sel <= '0';
|
execute_engine.pc_mux_sel <= '0';
|
execute_engine.pc_we <= '0';
|
execute_engine.pc_we <= '0';
|
Line 895... |
Line 930... |
execute_engine.state_nxt <= DISPATCH;
|
execute_engine.state_nxt <= DISPATCH;
|
|
|
|
|
when DISPATCH => -- Get new command from instruction issue engine
|
when DISPATCH => -- Get new command from instruction issue engine
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
|
-- housekeeping --
|
|
execute_engine.is_cp_op_nxt <= '0'; -- init
|
|
execute_engine.is_fp_nxt <= '0'; -- init
|
-- PC update --
|
-- PC update --
|
execute_engine.pc_mux_sel <= '0'; -- linear next PC
|
execute_engine.pc_mux_sel <= '0'; -- linear next PC
|
-- IR update --
|
-- IR update --
|
execute_engine.is_ci_nxt <= cmd_issue.data(32); -- flag to indicate a de-compressed instruction
|
execute_engine.is_ci_nxt <= cmd_issue.data(32); -- flag to indicate a de-compressed instruction
|
execute_engine.i_reg_nxt <= cmd_issue.data(31 downto 0);
|
execute_engine.i_reg_nxt <= cmd_issue.data(31 downto 0);
|
Line 1024... |
Line 1062... |
end if;
|
end if;
|
ctrl_nxt(ctrl_rf_in_mux_c) <= '0'; -- RF input = ALU result
|
ctrl_nxt(ctrl_rf_in_mux_c) <= '0'; -- RF input = ALU result
|
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
|
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
|
execute_engine.state_nxt <= DISPATCH;
|
execute_engine.state_nxt <= DISPATCH;
|
|
|
when opcode_load_c | opcode_store_c | opcode_atomic_c => -- load/store / atomic memory access
|
when opcode_load_c | opcode_store_c | opcode_atomic_c | opcode_flw_c | opcode_fsw_c => -- load/store / atomic memory access / floating-point load/store
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
ctrl_nxt(ctrl_alu_opa_mux_c) <= '0'; -- use RS1 as ALU.OPA
|
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_opb_mux_c) <= '1'; -- use IMM as ALU.OPB
|
ctrl_nxt(ctrl_bus_mo_we_c) <= '1'; -- write to MAR and MDO (MDO only relevant for store)
|
ctrl_nxt(ctrl_bus_mo_we_c) <= '1'; -- write to MAR and MDO (MDO only relevant for store)
|
|
if (CPU_EXTENSION_RISCV_F = true) and (execute_engine.i_reg(instr_opcode_lsb_c+3 downto instr_opcode_lsb_c+2) = "01") then -- floating-point load/store
|
|
execute_engine.is_fp_nxt <= decode_aux.is_float_f_reg; -- no integer register file write back for FPU internal operations
|
|
ctrl_nxt(ctrl_bus_wd_sel_c) <= '1'; -- use memory-write-data from FPU co-processor (only relevant for float STORE)
|
|
end if;
|
--
|
--
|
if (CPU_EXTENSION_RISCV_A = false) or (execute_engine.i_reg(instr_opcode_lsb_c+2) = '0') then -- atomic (A) extension disabled or normal load/store
|
if (CPU_EXTENSION_RISCV_A = false) or -- atomic extension disabled
|
|
(execute_engine.i_reg(instr_opcode_lsb_c+3 downto instr_opcode_lsb_c+2) = "00") or -- normal integerload/store
|
|
((CPU_EXTENSION_RISCV_F = true) and (execute_engine.i_reg(instr_opcode_lsb_c+3 downto instr_opcode_lsb_c+2) = "01")) then -- floating-point load/store
|
execute_engine.state_nxt <= LOADSTORE_0;
|
execute_engine.state_nxt <= LOADSTORE_0;
|
else -- atomic operation
|
else -- atomic operation
|
atomic_ctrl.env_start <= not execute_engine.i_reg(instr_funct5_lsb_c); -- LR: start LOCKED memory access environment
|
atomic_ctrl.env_start <= not execute_engine.i_reg(instr_funct5_lsb_c); -- LR: start LOCKED memory access environment
|
if (execute_engine.i_reg(instr_funct5_msb_c downto instr_funct5_lsb_c) = funct5_a_sc_c) or -- store-conditional
|
if (execute_engine.i_reg(instr_funct5_msb_c downto instr_funct5_lsb_c) = funct5_a_sc_c) or -- store-conditional
|
(execute_engine.i_reg(instr_funct5_msb_c downto instr_funct5_lsb_c) = funct5_a_lr_c) then -- load-reservate
|
(execute_engine.i_reg(instr_funct5_msb_c downto instr_funct5_lsb_c) = funct5_a_lr_c) then -- load-reservate
|
Line 1072... |
Line 1116... |
end if;
|
end if;
|
else
|
else
|
execute_engine.state_nxt <= SYS_WAIT;
|
execute_engine.state_nxt <= SYS_WAIT;
|
end if;
|
end if;
|
|
|
|
when opcode_fop_c => -- floating-point operations (1 or 2 operands)
|
|
-- ------------------------------------------------------------
|
|
execute_engine.state_nxt <= SYS_WAIT;
|
|
if (CPU_EXTENSION_RISCV_F = true) then
|
|
execute_engine.is_fp_nxt <= decode_aux.is_float_f_reg; -- no integer register file write back for FPU internal operations
|
|
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_fpu_c; -- use FPU CP
|
|
execute_engine.is_cp_op_nxt <= '1'; -- this is a CP operation
|
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c;
|
|
execute_engine.state_nxt <= ALU_WAIT;
|
|
end if;
|
|
|
when others => -- undefined
|
when others => -- undefined
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
execute_engine.state_nxt <= SYS_WAIT;
|
execute_engine.state_nxt <= SYS_WAIT;
|
|
|
end case;
|
end case;
|
Line 1112... |
Line 1167... |
|
|
|
|
when ALU_WAIT => -- wait for multi-cycle ALU operation (shifter or CP) to finish
|
when ALU_WAIT => -- wait for multi-cycle ALU operation (shifter or CP) to finish
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
ctrl_nxt(ctrl_rf_in_mux_c) <= '0'; -- RF input = ALU result
|
ctrl_nxt(ctrl_rf_in_mux_c) <= '0'; -- RF input = ALU result
|
|
if (CPU_EXTENSION_RISCV_F = false) then
|
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back (permanent write-back)
|
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back (permanent write-back)
|
|
else
|
|
ctrl_nxt(ctrl_rf_wb_en_c) <= not execute_engine.is_fp; -- allow write back if NOT <FPU-internal operation>
|
|
end if;
|
-- cp access or alu.shift? --
|
-- cp access or alu.shift? --
|
if (execute_engine.is_cp_op = '1') then
|
if (execute_engine.is_cp_op = '1') then
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c;
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c;
|
else
|
else
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_shift_c;
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_shift_c;
|
Line 1202... |
Line 1261... |
atomic_ctrl.env_abort <= '1'; -- LOCKED (atomic) memory access environment failed (forces SC result to be non-zero => failure)
|
atomic_ctrl.env_abort <= '1'; -- LOCKED (atomic) memory access environment failed (forces SC result to be non-zero => failure)
|
ctrl_nxt(ctrl_rf_wb_en_c) <= decode_aux.is_atomic_sc; -- SC failes: allow write back of non-zero result
|
ctrl_nxt(ctrl_rf_wb_en_c) <= decode_aux.is_atomic_sc; -- SC failes: allow write back of non-zero result
|
execute_engine.state_nxt <= DISPATCH;
|
execute_engine.state_nxt <= DISPATCH;
|
elsif (bus_d_wait_i = '0') then -- wait for bus to finish transaction
|
elsif (bus_d_wait_i = '0') then -- wait for bus to finish transaction
|
if (execute_engine.i_reg(instr_opcode_msb_c-1) = '0') or (decode_aux.is_atomic_lr = '1') or (decode_aux.is_atomic_sc = '1') then -- load / load-reservate / store conditional
|
if (execute_engine.i_reg(instr_opcode_msb_c-1) = '0') or (decode_aux.is_atomic_lr = '1') or (decode_aux.is_atomic_sc = '1') then -- load / load-reservate / store conditional
|
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
|
ctrl_nxt(ctrl_rf_wb_en_c) <= not execute_engine.is_fp; -- allow write back if NOT <FPU-internal operation>
|
|
end if;
|
|
if (CPU_EXTENSION_RISCV_F = true) and (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c+2) = opcode_flw_c(6 downto 2)) then -- floating-point LOAD.word
|
|
ctrl_nxt(ctrl_cp_fpu_mem_we_c) <= '1'; -- co-processor register file write-back
|
end if;
|
end if;
|
atomic_ctrl.env_end <= not decode_aux.is_atomic_lr; -- normal end of LOCKED (atomic) memory access environment - if we are not starting it via LR instruction
|
atomic_ctrl.env_end <= not decode_aux.is_atomic_lr; -- normal end of LOCKED (atomic) memory access environment - if we are not starting it via LR instruction
|
execute_engine.state_nxt <= DISPATCH;
|
execute_engine.state_nxt <= DISPATCH;
|
end if;
|
end if;
|
|
|
Line 1241... |
Line 1303... |
-- csr_racc_v := '1'; -- always read CSR
|
-- csr_racc_v := '1'; -- always read CSR
|
end if;
|
end if;
|
|
|
-- low privilege level access to hpm counters? --
|
-- low privilege level access to hpm counters? --
|
csr_mcounteren_hpm_v := (others => '0');
|
csr_mcounteren_hpm_v := (others => '0');
|
if (CPU_EXTENSION_RISCV_U = true) then -- 'mcounteren' CSR is hardwired to zero if user mode is not implemented
|
if (CPU_EXTENSION_RISCV_U = true) then
|
csr_mcounteren_hpm_v(HPM_NUM_CNTS-1 downto 0) := csr.mcounteren_hpm(HPM_NUM_CNTS-1 downto 0);
|
csr_mcounteren_hpm_v(HPM_NUM_CNTS-1 downto 0) := csr.mcounteren_hpm(HPM_NUM_CNTS-1 downto 0);
|
|
else -- 'mcounteren' CSR is hardwired to zero if user mode is not implemented
|
|
csr_mcounteren_hpm_v := (others => '0');
|
end if;
|
end if;
|
|
|
-- check CSR access --
|
-- check CSR access --
|
case csr.addr is
|
case csr.addr is
|
-- standard read/write CSRs --
|
-- standard read/write CSRs --
|
|
when csr_fflags_c | csr_frm_c | csr_fcsr_c => csr_acc_valid <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_F); -- full access for everyone if F extension is enabled
|
|
--
|
when csr_mstatus_c => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
|
when csr_mstatus_c => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
|
when csr_mstatush_c => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
|
when csr_mstatush_c => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
|
when csr_misa_c => csr_acc_valid <= csr.priv_m_mode;-- and (not csr_wacc_v); -- M-mode only, MISA is read-only in the NEORV32 but we do not cause an exception here for compatibility
|
when csr_misa_c => csr_acc_valid <= csr.priv_m_mode;-- and (not csr_wacc_v); -- M-mode only, MISA is read-only in the NEORV32 but we do not cause an exception here for compatibility
|
when csr_mie_c => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
|
when csr_mie_c => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
|
when csr_mtvec_c => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
|
when csr_mtvec_c => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
|
Line 1408... |
Line 1474... |
-- check instructions --
|
-- check instructions --
|
opcode_v := execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c+2) & "11";
|
opcode_v := execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c+2) & "11";
|
case opcode_v is
|
case opcode_v is
|
|
|
-- check sufficient LUI, UIPC, JAL (only check actual OPCODE) --
|
-- check sufficient LUI, UIPC, JAL (only check actual OPCODE) --
|
|
-- ------------------------------------------------------------
|
when opcode_lui_c | opcode_auipc_c | opcode_jal_c =>
|
when opcode_lui_c | opcode_auipc_c | opcode_jal_c =>
|
illegal_instruction <= '0';
|
illegal_instruction <= '0';
|
-- illegal E-CPU register? --
|
-- illegal E-CPU register? --
|
if (CPU_EXTENSION_RISCV_E = true) and (execute_engine.i_reg(instr_rd_msb_c) = '1') then
|
if (CPU_EXTENSION_RISCV_E = true) and (execute_engine.i_reg(instr_rd_msb_c) = '1') then
|
illegal_register <= '1';
|
illegal_register <= '1';
|
end if;
|
end if;
|
|
|
when opcode_alu_c => -- check ALU.funct3 & ALU.funct7
|
when opcode_alu_c => -- check ALU.funct3 & ALU.funct7
|
|
-- ------------------------------------------------------------
|
if (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV
|
if (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV
|
if (CPU_EXTENSION_RISCV_M = false) then -- not implemented
|
if (CPU_EXTENSION_RISCV_M = false) then -- not implemented
|
illegal_instruction <= '1';
|
illegal_instruction <= '1';
|
end if;
|
end if;
|
elsif (decode_aux.is_bitmanip_reg = '1') then -- bit manipulation
|
elsif (decode_aux.is_bitmanip_reg = '1') then -- bit manipulation
|
Line 1439... |
Line 1507... |
((execute_engine.i_reg(instr_rs2_msb_c) = '1') or (execute_engine.i_reg(instr_rs1_msb_c) = '1') or (execute_engine.i_reg(instr_rd_msb_c) = '1')) then
|
((execute_engine.i_reg(instr_rs2_msb_c) = '1') or (execute_engine.i_reg(instr_rs1_msb_c) = '1') or (execute_engine.i_reg(instr_rd_msb_c) = '1')) then
|
illegal_register <= '1';
|
illegal_register <= '1';
|
end if;
|
end if;
|
|
|
when opcode_alui_c => -- check ALUI.funct7
|
when opcode_alui_c => -- check ALUI.funct7
|
|
-- ------------------------------------------------------------
|
if (decode_aux.is_bitmanip_imm = '1') then -- bit manipulation
|
if (decode_aux.is_bitmanip_imm = '1') then -- bit manipulation
|
if (CPU_EXTENSION_RISCV_B = false) then -- not implemented
|
if (CPU_EXTENSION_RISCV_B = false) then -- not implemented
|
illegal_instruction <= '1';
|
illegal_instruction <= '1';
|
end if;
|
end if;
|
elsif ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) and
|
elsif ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) and
|
Line 1458... |
Line 1527... |
if (CPU_EXTENSION_RISCV_E = true) and ((execute_engine.i_reg(instr_rs1_msb_c) = '1') or (execute_engine.i_reg(instr_rd_msb_c) = '1')) then
|
if (CPU_EXTENSION_RISCV_E = true) and ((execute_engine.i_reg(instr_rs1_msb_c) = '1') or (execute_engine.i_reg(instr_rd_msb_c) = '1')) then
|
illegal_register <= '1';
|
illegal_register <= '1';
|
end if;
|
end if;
|
|
|
when opcode_load_c => -- check LOAD.funct3
|
when opcode_load_c => -- check LOAD.funct3
|
|
-- ------------------------------------------------------------
|
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lb_c) or
|
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lb_c) or
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lh_c) or
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lh_c) or
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lw_c) or
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lw_c) or
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lbu_c) or
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lbu_c) or
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lhu_c) then
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lhu_c) then
|
Line 1473... |
Line 1543... |
if (CPU_EXTENSION_RISCV_E = true) and ((execute_engine.i_reg(instr_rs1_msb_c) = '1') or (execute_engine.i_reg(instr_rd_msb_c) = '1')) then
|
if (CPU_EXTENSION_RISCV_E = true) and ((execute_engine.i_reg(instr_rs1_msb_c) = '1') or (execute_engine.i_reg(instr_rd_msb_c) = '1')) then
|
illegal_register <= '1';
|
illegal_register <= '1';
|
end if;
|
end if;
|
|
|
when opcode_store_c => -- check STORE.funct3
|
when opcode_store_c => -- check STORE.funct3
|
|
-- ------------------------------------------------------------
|
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sb_c) or
|
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sb_c) or
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sh_c) or
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sh_c) or
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sw_c) then
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sw_c) then
|
illegal_instruction <= '0';
|
illegal_instruction <= '0';
|
else
|
else
|
Line 1486... |
Line 1557... |
if (CPU_EXTENSION_RISCV_E = true) and ((execute_engine.i_reg(instr_rs2_msb_c) = '1') or (execute_engine.i_reg(instr_rs1_msb_c) = '1')) then
|
if (CPU_EXTENSION_RISCV_E = true) and ((execute_engine.i_reg(instr_rs2_msb_c) = '1') or (execute_engine.i_reg(instr_rs1_msb_c) = '1')) then
|
illegal_register <= '1';
|
illegal_register <= '1';
|
end if;
|
end if;
|
|
|
when opcode_branch_c => -- check BRANCH.funct3
|
when opcode_branch_c => -- check BRANCH.funct3
|
|
-- ------------------------------------------------------------
|
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_beq_c) or
|
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_beq_c) or
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bne_c) or
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bne_c) or
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_blt_c) or
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_blt_c) or
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bge_c) or
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bge_c) or
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bltu_c) or
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bltu_c) or
|
Line 1502... |
Line 1574... |
if (CPU_EXTENSION_RISCV_E = true) and ((execute_engine.i_reg(instr_rs2_msb_c) = '1') or (execute_engine.i_reg(instr_rs1_msb_c) = '1')) then
|
if (CPU_EXTENSION_RISCV_E = true) and ((execute_engine.i_reg(instr_rs2_msb_c) = '1') or (execute_engine.i_reg(instr_rs1_msb_c) = '1')) then
|
illegal_register <= '1';
|
illegal_register <= '1';
|
end if;
|
end if;
|
|
|
when opcode_jalr_c => -- check JALR.funct3
|
when opcode_jalr_c => -- check JALR.funct3
|
|
-- ------------------------------------------------------------
|
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "000") then
|
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "000") then
|
illegal_instruction <= '0';
|
illegal_instruction <= '0';
|
else
|
else
|
illegal_instruction <= '1';
|
illegal_instruction <= '1';
|
end if;
|
end if;
|
-- illegal E-CPU register? --
|
-- illegal E-CPU register? --
|
if (CPU_EXTENSION_RISCV_E = true) and ((execute_engine.i_reg(instr_rs1_msb_c) = '1') or (execute_engine.i_reg(instr_rd_msb_c) = '1')) then
|
if (CPU_EXTENSION_RISCV_E = true) and ((execute_engine.i_reg(instr_rs1_msb_c) = '1') or (execute_engine.i_reg(instr_rd_msb_c) = '1')) then
|
illegal_register <= '1';
|
illegal_register <= '1';
|
end if;
|
end if;
|
|
|
when opcode_fence_c => -- fence instructions --
|
when opcode_fence_c => -- fence instructions
|
|
-- ------------------------------------------------------------
|
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fencei_c) and (CPU_EXTENSION_RISCV_Zifencei = true) then -- FENCE.I
|
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fencei_c) and (CPU_EXTENSION_RISCV_Zifencei = true) then -- FENCE.I
|
illegal_instruction <= '0';
|
illegal_instruction <= '0';
|
elsif (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fence_c) then -- FENCE
|
elsif (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fence_c) then -- FENCE
|
illegal_instruction <= '0';
|
illegal_instruction <= '0';
|
else
|
else
|
illegal_instruction <= '1';
|
illegal_instruction <= '1';
|
end if;
|
end if;
|
|
|
when opcode_syscsr_c => -- check system instructions --
|
when opcode_syscsr_c => -- check system instructions
|
|
-- ------------------------------------------------------------
|
-- CSR access --
|
-- CSR access --
|
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or
|
if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrs_c) or
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrs_c) or
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrc_c) or
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrc_c) or
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) or
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) or
|
Line 1559... |
Line 1634... |
end if;
|
end if;
|
else
|
else
|
illegal_instruction <= '1';
|
illegal_instruction <= '1';
|
end if;
|
end if;
|
|
|
when opcode_atomic_c => -- atomic instructions --
|
when opcode_atomic_c => -- atomic instructions
|
|
-- ------------------------------------------------------------
|
if (CPU_EXTENSION_RISCV_A = true) and -- atomic memory operations (A extension) enabled
|
if (CPU_EXTENSION_RISCV_A = true) and -- atomic memory operations (A extension) enabled
|
((execute_engine.i_reg(instr_funct5_msb_c downto instr_funct5_lsb_c) = funct5_a_lr_c) or -- LR
|
((execute_engine.i_reg(instr_funct5_msb_c downto instr_funct5_lsb_c) = funct5_a_lr_c) or -- LR
|
(execute_engine.i_reg(instr_funct5_msb_c downto instr_funct5_lsb_c) = funct5_a_sc_c)) then -- SC
|
(execute_engine.i_reg(instr_funct5_msb_c downto instr_funct5_lsb_c) = funct5_a_sc_c)) then -- SC
|
illegal_instruction <= '0';
|
illegal_instruction <= '0';
|
else
|
else
|
illegal_instruction <= '1';
|
illegal_instruction <= '1';
|
end if;
|
end if;
|
|
|
|
when opcode_fop_c => -- floating point operations (dual-operand)
|
|
-- ------------------------------------------------------------
|
|
if (CPU_EXTENSION_RISCV_F = true) and -- F extension enabled
|
|
(execute_engine.i_reg(instr_funct7_lsb_c+1 downto instr_funct7_lsb_c) = float_single_c) and -- single-precision operations
|
|
((decode_aux.is_float_f_reg = '1') or (decode_aux.is_float_i_reg = '1')) then -- float_reg or int_reg operations
|
|
illegal_instruction <= '0';
|
|
else
|
|
illegal_instruction <= '1';
|
|
end if;
|
|
|
|
when opcode_flw_c | opcode_fsw_c => -- floating point load/store word
|
|
-- ------------------------------------------------------------
|
|
if (CPU_EXTENSION_RISCV_F = true) and -- F extension enabled
|
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "010") then -- 32-bit transfer size
|
|
illegal_instruction <= '0';
|
|
else
|
|
illegal_instruction <= '1';
|
|
end if;
|
|
|
when others => -- undefined instruction -> illegal!
|
when others => -- undefined instruction -> illegal!
|
|
-- ------------------------------------------------------------
|
illegal_instruction <= '1';
|
illegal_instruction <= '1';
|
|
|
end case;
|
end case;
|
else
|
else
|
illegal_opcode_lsbs <= '0';
|
illegal_opcode_lsbs <= '0';
|
Line 1868... |
Line 1964... |
when others => csr.wdata <= csr_operand_v; -- CSRRW(I)
|
when others => csr.wdata <= csr_operand_v; -- CSRRW(I)
|
end case;
|
end case;
|
end process csr_write_data;
|
end process csr_write_data;
|
|
|
|
|
-- Control and Status Registers Write Access ----------------------------------------------
|
-- Control and Status Registers - Write Access --------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
csr_write_access: process(rstn_i, clk_i)
|
csr_write_access: process(rstn_i, clk_i)
|
variable pmpaddr_v : std_ulogic_vector(6 downto 0);
|
|
begin
|
begin
|
if (rstn_i = '0') then
|
if (rstn_i = '0') then
|
csr.we <= '0';
|
csr.we <= '0';
|
--
|
--
|
csr.mstatus_mie <= '0';
|
csr.mstatus_mie <= '0';
|
Line 1888... |
Line 1983... |
csr.mie_firqe <= (others => '0');
|
csr.mie_firqe <= (others => '0');
|
csr.mtvec <= (others => '0');
|
csr.mtvec <= (others => '0');
|
csr.mscratch <= x"19880704"; -- :)
|
csr.mscratch <= x"19880704"; -- :)
|
csr.mepc <= (others => '0');
|
csr.mepc <= (others => '0');
|
csr.mcause <= trap_reset_c; -- mcause = TRAP_CODE_RESET (hardware reset, "non-maskable interrupt")
|
csr.mcause <= trap_reset_c; -- mcause = TRAP_CODE_RESET (hardware reset, "non-maskable interrupt")
|
--
|
|
csr.mtval <= (others => '0');
|
csr.mtval <= (others => '0');
|
csr.mip_clear <= (others => '0');
|
csr.mip_clear <= (others => '0');
|
--
|
--
|
csr.pmpcfg <= (others => (others => '0'));
|
csr.pmpcfg <= (others => (others => '0'));
|
csr.pmpaddr <= (others => (others => '1'));
|
csr.pmpaddr <= (others => (others => '1'));
|
Line 1905... |
Line 1999... |
csr.mcounteren_hpm <= (others => '0');
|
csr.mcounteren_hpm <= (others => '0');
|
--
|
--
|
csr.mcountinhibit_cy <= '0';
|
csr.mcountinhibit_cy <= '0';
|
csr.mcountinhibit_ir <= '0';
|
csr.mcountinhibit_ir <= '0';
|
csr.mcountinhibit_hpm <= (others => '0');
|
csr.mcountinhibit_hpm <= (others => '0');
|
|
--
|
|
csr.fflags <= (others => '0');
|
|
csr.frm <= (others => '0');
|
|
|
elsif rising_edge(clk_i) then
|
elsif rising_edge(clk_i) then
|
-- write access? --
|
-- write access? --
|
csr.we <= csr.we_nxt;
|
csr.we <= csr.we_nxt;
|
if (CPU_EXTENSION_RISCV_Zicsr = true) then
|
if (CPU_EXTENSION_RISCV_Zicsr = true) then
|
Line 1918... |
Line 2015... |
|
|
-- --------------------------------------------------------------------------------
|
-- --------------------------------------------------------------------------------
|
-- CSR access by application software
|
-- CSR access by application software
|
-- --------------------------------------------------------------------------------
|
-- --------------------------------------------------------------------------------
|
if (csr.we = '1') then -- manual update
|
if (csr.we = '1') then -- manual update
|
case csr.addr is
|
|
|
-- user floating-point CSRs --
|
|
-- --------------------------------------------------------------------
|
|
if (csr.addr(11 downto 4) = csr_class_float_c) then -- floating point CSR class
|
|
-- R/W: fflags - floating-point (FPU) exception flags --
|
|
if (csr.addr(3 downto 0) = csr_fflags_c(3 downto 0)) and (CPU_EXTENSION_RISCV_F = true) then
|
|
csr.fflags <= csr.wdata(4 downto 0);
|
|
end if;
|
|
-- R/W: frm - floating-point (FPU) rounding mode --
|
|
if (csr.addr(3 downto 0) = csr_frm_c(3 downto 0)) and (CPU_EXTENSION_RISCV_F = true) then
|
|
csr.frm <= csr.wdata(2 downto 0);
|
|
end if;
|
|
-- R/W: fflags - floating-point (FPU) control/status (frm + fflags) --
|
|
if (csr.addr(3 downto 0) = csr_fcsr_c(3 downto 0)) and (CPU_EXTENSION_RISCV_F = true) then
|
|
csr.frm <= csr.wdata(7 downto 5);
|
|
csr.fflags <= csr.wdata(4 downto 0);
|
|
end if;
|
|
end if;
|
|
|
-- machine trap setup --
|
-- machine trap setup --
|
-- --------------------------------------------------------------------
|
-- --------------------------------------------------------------------
|
when csr_mstatus_c => -- R/W: mstatus - machine status register
|
if (csr.addr(11 downto 4) = csr_setup_c) then -- ftrap setup CSR class
|
|
-- R/W: mstatus - machine status register --
|
|
if (csr.addr(3 downto 0) = csr_mstatus_c(3 downto 0)) then
|
csr.mstatus_mie <= csr.wdata(03);
|
csr.mstatus_mie <= csr.wdata(03);
|
csr.mstatus_mpie <= csr.wdata(07);
|
csr.mstatus_mpie <= csr.wdata(07);
|
if (CPU_EXTENSION_RISCV_U = true) then -- user mode implemented
|
if (CPU_EXTENSION_RISCV_U = true) then -- user mode implemented
|
csr.mstatus_mpp(0) <= csr.wdata(11) or csr.wdata(12);
|
csr.mstatus_mpp(0) <= csr.wdata(11) or csr.wdata(12);
|
csr.mstatus_mpp(1) <= csr.wdata(11) or csr.wdata(12);
|
csr.mstatus_mpp(1) <= csr.wdata(11) or csr.wdata(12);
|
else -- only machine mode is available
|
else -- only machine mode is available
|
csr.mstatus_mpp <= priv_mode_m_c;
|
csr.mstatus_mpp <= priv_mode_m_c;
|
end if;
|
end if;
|
when csr_mie_c => -- R/W: mie - machine interrupt enable register
|
end if;
|
|
-- R/W: mie - machine interrupt enable register --
|
|
if (csr.addr(3 downto 0) = csr_mie_c(3 downto 0)) then
|
csr.mie_msie <= csr.wdata(03); -- machine SW IRQ enable
|
csr.mie_msie <= csr.wdata(03); -- machine SW IRQ enable
|
csr.mie_mtie <= csr.wdata(07); -- machine TIMER IRQ enable
|
csr.mie_mtie <= csr.wdata(07); -- machine TIMER IRQ enable
|
csr.mie_meie <= csr.wdata(11); -- machine EXT IRQ enable
|
csr.mie_meie <= csr.wdata(11); -- machine EXT IRQ enable
|
for i in 0 to 15 loop -- fast interrupt channels 0..15
|
for i in 0 to 15 loop -- fast interrupt channels 0..15
|
csr.mie_firqe(i) <= csr.wdata(16+i);
|
csr.mie_firqe(i) <= csr.wdata(16+i);
|
end loop; -- i
|
end loop; -- i
|
when csr_mtvec_c => -- R/W: mtvec - machine trap-handler base address (for ALL exceptions)
|
end if;
|
|
-- R/W: mtvec - machine trap-handler base address (for ALL exceptions) --
|
|
if (csr.addr(3 downto 0) = csr_mtvec_c(3 downto 0)) then
|
csr.mtvec <= csr.wdata(data_width_c-1 downto 2) & "00"; -- mtvec.MODE=0
|
csr.mtvec <= csr.wdata(data_width_c-1 downto 2) & "00"; -- mtvec.MODE=0
|
when csr_mcounteren_c => -- R/W: machine counter enable register
|
end if;
|
|
-- R/W: machine counter enable register --
|
|
if (csr.addr(3 downto 0) = csr_mcounteren_c(3 downto 0)) then
|
if (CPU_EXTENSION_RISCV_U = true) then -- this CSR is hardwired to zero if user mode is not implemented
|
if (CPU_EXTENSION_RISCV_U = true) then -- this CSR is hardwired to zero if user mode is not implemented
|
csr.mcounteren_cy <= csr.wdata(0); -- enable user-level access to cycle[h]
|
csr.mcounteren_cy <= csr.wdata(0); -- enable user-level access to cycle[h]
|
csr.mcounteren_tm <= csr.wdata(1); -- enable user-level access to time[h]
|
csr.mcounteren_tm <= csr.wdata(1); -- enable user-level access to time[h]
|
csr.mcounteren_ir <= csr.wdata(2); -- enable user-level access to instret[h]
|
csr.mcounteren_ir <= csr.wdata(2); -- enable user-level access to instret[h]
|
csr.mcounteren_hpm <= csr.wdata(csr.mcounteren_hpm'left+3 downto 3); -- enable user-level access to hpmcounterx[h]
|
csr.mcounteren_hpm <= csr.wdata(csr.mcounteren_hpm'left+3 downto 3); -- enable user-level access to hpmcounterx[h]
|
else
|
end if;
|
NULL;
|
end if;
|
end if;
|
end if;
|
|
|
-- machine trap handling --
|
-- machine trap handling --
|
-- --------------------------------------------------------------------
|
-- --------------------------------------------------------------------
|
when csr_mscratch_c => -- R/W: mscratch - machine scratch register
|
if (csr.addr(11 downto 4) = csr_class_trap_c) then -- machine trap handling CSR class
|
|
-- R/W: mscratch - machine scratch register --
|
|
if (csr.addr(3 downto 0) = csr_mscratch_c(3 downto 0)) then
|
csr.mscratch <= csr.wdata;
|
csr.mscratch <= csr.wdata;
|
when csr_mepc_c => -- R/W: mepc - machine exception program counter
|
end if;
|
|
-- R/W: mepc - machine exception program counter --
|
|
if (csr.addr(3 downto 0) = csr_mepc_c(3 downto 0)) then
|
csr.mepc <= csr.wdata(data_width_c-1 downto 1) & '0';
|
csr.mepc <= csr.wdata(data_width_c-1 downto 1) & '0';
|
when csr_mcause_c => -- R/W: mcause - machine trap cause
|
end if;
|
|
-- R/W: mcause - machine trap cause --
|
|
if (csr.addr(3 downto 0) = csr_mcause_c(3 downto 0)) then
|
csr.mcause(csr.mcause'left) <= csr.wdata(31); -- 1: interrupt, 0: exception
|
csr.mcause(csr.mcause'left) <= csr.wdata(31); -- 1: interrupt, 0: exception
|
csr.mcause(4 downto 0) <= csr.wdata(4 downto 0); -- identifier
|
csr.mcause(4 downto 0) <= csr.wdata(4 downto 0); -- identifier
|
when csr_mtval_c => -- R/W: mtval - machine bad address/instruction
|
end if;
|
|
-- R/W: mtval - machine bad address/instruction --
|
|
if (csr.addr(3 downto 0) = csr_mtval_c(3 downto 0)) then
|
csr.mtval <= csr.wdata;
|
csr.mtval <= csr.wdata;
|
when csr_mip_c => -- R/W: mip - machine interrupt pending
|
end if;
|
|
-- R/W: mip - machine interrupt pending --
|
|
if (csr.addr(3 downto 0) = csr_mip_c(3 downto 0)) then
|
csr.mip_clear(interrupt_msw_irq_c) <= not csr.wdata(03);
|
csr.mip_clear(interrupt_msw_irq_c) <= not csr.wdata(03);
|
csr.mip_clear(interrupt_mtime_irq_c) <= not csr.wdata(07);
|
csr.mip_clear(interrupt_mtime_irq_c) <= not csr.wdata(07);
|
csr.mip_clear(interrupt_mext_irq_c) <= not csr.wdata(11);
|
csr.mip_clear(interrupt_mext_irq_c) <= not csr.wdata(11);
|
for i in 0 to 15 loop -- fast interrupt channels 0..15
|
for i in 0 to 15 loop -- fast interrupt channels 0..15
|
csr.mip_clear(interrupt_firq_0_c+i) <= not csr.wdata(16+i);
|
csr.mip_clear(interrupt_firq_0_c+i) <= not csr.wdata(16+i);
|
end loop; -- i
|
end loop; -- i
|
|
end if;
|
|
end if;
|
|
|
-- physical memory protection: R/W: pmpcfg* - PMP configuration registers --
|
-- physical memory protection: R/W: pmpcfg* - PMP configuration registers --
|
-- --------------------------------------------------------------------
|
-- --------------------------------------------------------------------
|
when csr_pmpcfg0_c | csr_pmpcfg1_c | csr_pmpcfg2_c | csr_pmpcfg3_c | csr_pmpcfg4_c | csr_pmpcfg5_c | csr_pmpcfg6_c | csr_pmpcfg7_c |
|
if (csr.addr(11 downto 4) = csr_class_pmpcfg_c) then -- pmp configuration CSR class
|
csr_pmpcfg8_c | csr_pmpcfg9_c | csr_pmpcfg10_c | csr_pmpcfg11_c | csr_pmpcfg12_c | csr_pmpcfg13_c | csr_pmpcfg14_c | csr_pmpcfg15_c =>
|
|
if (PMP_NUM_REGIONS > 0) then
|
if (PMP_NUM_REGIONS > 0) then
|
for i in 0 to PMP_NUM_REGIONS-1 loop
|
for i in 0 to PMP_NUM_REGIONS-1 loop
|
if (csr.addr(3 downto 0) = std_ulogic_vector(to_unsigned(i, 4))) then
|
if (csr.addr(3 downto 0) = std_ulogic_vector(to_unsigned(i, 4))) then
|
if (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpcfg access
|
if (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpcfg access
|
csr.pmpcfg(i)(0) <= csr.wdata((i mod 4)*8+0); -- R (rights.read)
|
csr.pmpcfg(i)(0) <= csr.wdata((i mod 4)*8+0); -- R (rights.read)
|
Line 1988... |
Line 2121... |
csr.pmpcfg(i)(6) <= '0'; -- reserved
|
csr.pmpcfg(i)(6) <= '0'; -- reserved
|
csr.pmpcfg(i)(7) <= csr.wdata((i mod 4)*8+7); -- L (locked / rights also enforced in m-mode)
|
csr.pmpcfg(i)(7) <= csr.wdata((i mod 4)*8+7); -- L (locked / rights also enforced in m-mode)
|
end if;
|
end if;
|
end if;
|
end if;
|
end loop; -- i (PMP regions)
|
end loop; -- i (PMP regions)
|
else
|
end if;
|
NULL;
|
|
end if;
|
end if;
|
|
|
-- physical memory protection: R/W: pmpaddr* - PMP address registers --
|
-- physical memory protection: R/W: pmpaddr* - PMP address registers --
|
-- --------------------------------------------------------------------
|
-- --------------------------------------------------------------------
|
when csr_pmpaddr0_c | csr_pmpaddr1_c | csr_pmpaddr2_c | csr_pmpaddr3_c | csr_pmpaddr4_c | csr_pmpaddr5_c | csr_pmpaddr6_c | csr_pmpaddr7_c |
|
if (csr.addr(11 downto 4) = csr_pmpaddr0_c(11 downto 4)) or (csr.addr(11 downto 4) = csr_pmpaddr16_c(11 downto 4)) or
|
csr_pmpaddr8_c | csr_pmpaddr9_c | csr_pmpaddr10_c | csr_pmpaddr11_c | csr_pmpaddr12_c | csr_pmpaddr13_c | csr_pmpaddr14_c | csr_pmpaddr15_c |
|
(csr.addr(11 downto 4) = csr_pmpaddr32_c(11 downto 4)) or (csr.addr(11 downto 4) = csr_pmpaddr48_c(11 downto 4)) then
|
csr_pmpaddr16_c | csr_pmpaddr17_c | csr_pmpaddr18_c | csr_pmpaddr19_c | csr_pmpaddr20_c | csr_pmpaddr21_c | csr_pmpaddr22_c | csr_pmpaddr23_c |
|
|
csr_pmpaddr24_c | csr_pmpaddr25_c | csr_pmpaddr26_c | csr_pmpaddr27_c | csr_pmpaddr28_c | csr_pmpaddr29_c | csr_pmpaddr30_c | csr_pmpaddr31_c |
|
|
csr_pmpaddr32_c | csr_pmpaddr33_c | csr_pmpaddr34_c | csr_pmpaddr35_c | csr_pmpaddr36_c | csr_pmpaddr37_c | csr_pmpaddr38_c | csr_pmpaddr39_c |
|
|
csr_pmpaddr40_c | csr_pmpaddr41_c | csr_pmpaddr42_c | csr_pmpaddr43_c | csr_pmpaddr44_c | csr_pmpaddr45_c | csr_pmpaddr46_c | csr_pmpaddr47_c |
|
|
csr_pmpaddr48_c | csr_pmpaddr49_c | csr_pmpaddr50_c | csr_pmpaddr51_c | csr_pmpaddr52_c | csr_pmpaddr53_c | csr_pmpaddr54_c | csr_pmpaddr55_c |
|
|
csr_pmpaddr56_c | csr_pmpaddr57_c | csr_pmpaddr58_c | csr_pmpaddr59_c | csr_pmpaddr60_c | csr_pmpaddr61_c | csr_pmpaddr62_c | csr_pmpaddr63_c =>
|
|
if (PMP_NUM_REGIONS > 0) then
|
if (PMP_NUM_REGIONS > 0) then
|
for i in 0 to PMP_NUM_REGIONS-1 loop
|
for i in 0 to PMP_NUM_REGIONS-1 loop
|
pmpaddr_v := std_ulogic_vector(unsigned(csr_pmpaddr0_c(6 downto 0)) + i); -- adapt to *non-aligned* base address (csr_pmpaddr0_c)
|
if (csr.addr(6 downto 0) = std_ulogic_vector(unsigned(csr_pmpaddr0_c(6 downto 0)) + i)) and (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpaddr access
|
if (csr.addr(6 downto 0) = pmpaddr_v) and (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpaddr access
|
|
csr.pmpaddr(i) <= csr.wdata;
|
csr.pmpaddr(i) <= csr.wdata;
|
csr.pmpaddr(i)(index_size_f(PMP_MIN_GRANULARITY)-4 downto 0) <= (others => '1');
|
csr.pmpaddr(i)(index_size_f(PMP_MIN_GRANULARITY)-4 downto 0) <= (others => '1');
|
end if;
|
end if;
|
end loop; -- i (PMP regions)
|
end loop; -- i (PMP regions)
|
else
|
end if;
|
NULL;
|
|
end if;
|
end if;
|
|
|
-- machine counter setup --
|
-- machine counter setup --
|
-- --------------------------------------------------------------------
|
-- --------------------------------------------------------------------
|
when csr_mcountinhibit_c => -- R/W: mcountinhibit - machine counter-inhibit register
|
-- R/W: mcountinhibit - machine counter-inhibit register --
|
|
if (csr.addr = csr_mcountinhibit_c) then
|
csr.mcountinhibit_cy <= csr.wdata(0); -- enable auto-increment of [m]cycle[h] counter
|
csr.mcountinhibit_cy <= csr.wdata(0); -- enable auto-increment of [m]cycle[h] counter
|
csr.mcountinhibit_ir <= csr.wdata(2); -- enable auto-increment of [m]instret[h] counter
|
csr.mcountinhibit_ir <= csr.wdata(2); -- enable auto-increment of [m]instret[h] counter
|
csr.mcountinhibit_hpm <= csr.wdata(csr.mcountinhibit_hpm'left+3 downto 3); -- enable auto-increment of [m]hpmcounter*[h] counter
|
csr.mcountinhibit_hpm <= csr.wdata(csr.mcountinhibit_hpm'left+3 downto 3); -- enable auto-increment of [m]hpmcounter*[h] counter
|
|
end if;
|
|
|
-- machine performance-monitoring event selector --
|
-- machine performance-monitoring event selector --
|
-- --------------------------------------------------------------------
|
-- --------------------------------------------------------------------
|
when csr_mhpmevent3_c | csr_mhpmevent4_c | csr_mhpmevent5_c | csr_mhpmevent6_c | csr_mhpmevent7_c | csr_mhpmevent8_c |
|
if (unsigned(csr.addr) >= unsigned(csr_mhpmevent3_c)) and (unsigned(csr.addr) <= unsigned(csr_mhpmevent31_c)) then
|
csr_mhpmevent9_c | csr_mhpmevent10_c | csr_mhpmevent11_c | csr_mhpmevent12_c | csr_mhpmevent13_c | csr_mhpmevent14_c |
|
|
csr_mhpmevent15_c | csr_mhpmevent16_c | csr_mhpmevent17_c | csr_mhpmevent18_c | csr_mhpmevent19_c | csr_mhpmevent20_c |
|
|
csr_mhpmevent21_c | csr_mhpmevent22_c | csr_mhpmevent23_c | csr_mhpmevent24_c | csr_mhpmevent25_c | csr_mhpmevent26_c |
|
|
csr_mhpmevent27_c | csr_mhpmevent28_c | csr_mhpmevent29_c | csr_mhpmevent30_c | csr_mhpmevent31_c => -- R/W: mhpmevent* - machine performance-monitoring event selector
|
|
if (HPM_NUM_CNTS > 0) then
|
if (HPM_NUM_CNTS > 0) then
|
for i in 0 to HPM_NUM_CNTS-1 loop
|
for i in 0 to HPM_NUM_CNTS-1 loop
|
if (csr.addr(4 downto 0) = std_ulogic_vector(to_unsigned(i+3, 5))) then
|
if (csr.addr(4 downto 0) = std_ulogic_vector(to_unsigned(i+3, 5))) then
|
csr.mhpmevent(i) <= csr.wdata(csr.mhpmevent(i)'left downto 0);
|
csr.mhpmevent(i) <= csr.wdata(csr.mhpmevent(i)'left downto 0);
|
csr.mhpmevent(i)(1) <= '0'; -- would be used for "TIME"
|
csr.mhpmevent(i)(1) <= '0'; -- would be used for "TIME"
|
end if;
|
end if;
|
end loop; -- i (CSRs)
|
end loop; -- i (CSRs)
|
else
|
end if;
|
NULL;
|
|
end if;
|
end if;
|
|
|
-- undefined --
|
|
-- --------------------------------------------------------------------
|
|
when others =>
|
|
NULL;
|
|
|
|
end case;
|
|
|
|
-- --------------------------------------------------------------------------------
|
-- --------------------------------------------------------------------------------
|
-- CSR access by hardware
|
-- CSR access by hardware
|
-- --------------------------------------------------------------------------------
|
-- --------------------------------------------------------------------------------
|
else
|
else
|
|
|
|
-- floating-point (FPU) exception flags --
|
|
-- --------------------------------------------------------------------
|
|
if (CPU_EXTENSION_RISCV_F = true) and (execute_engine.state = ALU_WAIT) then -- FIXME?
|
|
csr.fflags <= csr.fflags or fpu_flags_i; -- accumulate flags ("accrued exception flags")
|
|
end if;
|
|
|
-- mcause, mepc, mtval: machine trap cause, PC and value register --
|
-- mcause, mepc, mtval: machine trap cause, PC and value register --
|
-- --------------------------------------------------------------------
|
-- --------------------------------------------------------------------
|
if (trap_ctrl.env_start_ack = '1') then -- trap handler starting?
|
if (trap_ctrl.env_start_ack = '1') then -- trap handler starting?
|
-- trap cause ID code --
|
-- trap cause ID code --
|
csr.mcause(csr.mcause'left) <= trap_ctrl.cause(trap_ctrl.cause'left); -- 1: interrupt, 0: exception
|
csr.mcause(csr.mcause'left) <= trap_ctrl.cause(trap_ctrl.cause'left); -- 1: interrupt, 0: exception
|
Line 2101... |
Line 2222... |
if (CPU_EXTENSION_RISCV_U = false) then
|
if (CPU_EXTENSION_RISCV_U = false) then
|
csr.privilege <= priv_mode_m_c;
|
csr.privilege <= priv_mode_m_c;
|
csr.mstatus_mpp <= priv_mode_m_c;
|
csr.mstatus_mpp <= priv_mode_m_c;
|
end if;
|
end if;
|
|
|
end if; -- hardware csr access
|
end if; -- /hardware csr access
|
|
end if;
|
|
|
|
-- --------------------------------------------------------------------------------
|
|
-- override write access for disabled functions
|
|
-- --------------------------------------------------------------------------------
|
|
|
|
-- user mode disabled --
|
|
if (CPU_EXTENSION_RISCV_U = false) then
|
|
csr.privilege <= priv_mode_m_c;
|
|
csr.mstatus_mpp <= priv_mode_m_c;
|
|
csr.mcounteren_cy <= '0';
|
|
csr.mcounteren_tm <= '0';
|
|
csr.mcounteren_ir <= '0';
|
|
csr.mcounteren_hpm <= (others => '0');
|
|
end if;
|
|
|
|
-- pmp disabled --
|
|
if (PMP_NUM_REGIONS = 0) then
|
|
csr.pmpcfg <= (others => (others => '0'));
|
|
csr.pmpaddr <= (others => (others => '1'));
|
|
end if;
|
|
|
|
-- hpms disabled --
|
|
if (HPM_NUM_CNTS = 0) then
|
|
csr.mhpmevent <= (others => (others => '0'));
|
|
csr.mcounteren_hpm <= (others => '0');
|
|
csr.mcountinhibit_hpm <= (others => '0');
|
|
end if;
|
|
|
|
-- floating-point extension disabled --
|
|
if (CPU_EXTENSION_RISCV_F = false) then
|
|
csr.fflags <= (others => '0');
|
|
csr.frm <= (others => '0');
|
end if;
|
end if;
|
|
|
end if;
|
end if;
|
end process csr_write_access;
|
end process csr_write_access;
|
|
|
-- decode privilege mode --
|
-- decode privilege mode --
|
csr.priv_m_mode <= '1' when (csr.privilege = priv_mode_m_c) else '0';
|
csr.priv_m_mode <= '1' when (csr.privilege = priv_mode_m_c) else '0';
|
Line 2137... |
Line 2291... |
csr.pmpaddr_rd(i)(index_size_f(PMP_MIN_GRANULARITY)-3 downto 0) <= (others => '0'); -- required for granularity check by SW
|
csr.pmpaddr_rd(i)(index_size_f(PMP_MIN_GRANULARITY)-3 downto 0) <= (others => '0'); -- required for granularity check by SW
|
end if;
|
end if;
|
end loop; -- i
|
end loop; -- i
|
end process pmp_rd_dummy;
|
end process pmp_rd_dummy;
|
|
|
|
-- FPU rounding mode --
|
|
fpu_rm_o <= csr.frm;
|
|
|
|
|
-- Control and Status Registers - Counters ------------------------------------------------
|
-- Control and Status Registers - Counters ------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
csr_counters: process(clk_i)
|
csr_counters: process(clk_i)
|
begin
|
begin
|
Line 2252... |
Line 2409... |
|
|
cnt_event_nxt(hpmcnt_event_trap_c) <= '1' when (trap_ctrl.env_start_ack = '1') else '0'; -- entered trap
|
cnt_event_nxt(hpmcnt_event_trap_c) <= '1' when (trap_ctrl.env_start_ack = '1') else '0'; -- entered trap
|
cnt_event_nxt(hpmcnt_event_illegal_c) <= '1' when (trap_ctrl.env_start_ack = '1') and (trap_ctrl.cause = trap_iil_c) else '0'; -- illegal operation
|
cnt_event_nxt(hpmcnt_event_illegal_c) <= '1' when (trap_ctrl.env_start_ack = '1') and (trap_ctrl.cause = trap_iil_c) else '0'; -- illegal operation
|
|
|
|
|
-- Control and Status Registers Read Access -----------------------------------------------
|
-- Control and Status Registers - Read Access ---------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
csr_read_access: process(clk_i)
|
csr_read_access: process(clk_i)
|
begin
|
begin
|
if rising_edge(clk_i) then
|
if rising_edge(clk_i) then
|
csr.re <= csr.re_nxt; -- read access?
|
csr.re <= csr.re_nxt; -- read access?
|
csr.rdata <= (others => '0'); -- default output
|
csr.rdata <= (others => '0'); -- default output
|
if (CPU_EXTENSION_RISCV_Zicsr = true) and (csr.re = '1') then
|
if (CPU_EXTENSION_RISCV_Zicsr = true) and (csr.re = '1') then
|
case csr.addr is
|
case csr.addr is
|
|
|
|
-- user floating-point CSRs --
|
|
-- --------------------------------------------------------------------
|
|
when csr_fflags_c => -- R/W: fflags - floating-point (FPU) exception flags
|
|
csr.rdata <= (others => '0');
|
|
if (CPU_EXTENSION_RISCV_F = true) then -- FPU implemented
|
|
csr.rdata(4 downto 0) <= csr.fflags;
|
|
end if;
|
|
when csr_frm_c => -- R/W: frm - floating-point (FPU) rounding mode
|
|
csr.rdata <= (others => '0');
|
|
if (CPU_EXTENSION_RISCV_F = true) then -- FPU implemented
|
|
csr.rdata(2 downto 0) <= csr.frm;
|
|
end if;
|
|
when csr_fcsr_c => -- R/W: fflags - floating-point (FPU) control/status (frm + fflags)
|
|
csr.rdata <= (others => '0');
|
|
if (CPU_EXTENSION_RISCV_F = true) then -- FPU implemented
|
|
csr.rdata(7 downto 5) <= csr.frm;
|
|
csr.rdata(4 downto 0) <= csr.fflags;
|
|
end if;
|
|
|
-- machine trap setup --
|
-- machine trap setup --
|
when csr_mstatus_c => -- 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(03) <= csr.mstatus_mie; -- MIE
|
csr.rdata(06) <= '1' and bool_to_ulogic_f(CPU_EXTENSION_RISCV_U); -- UBE: CPU/Processor is BIG-ENDIAN (in user-mode)
|
csr.rdata(06) <= '1' and bool_to_ulogic_f(CPU_EXTENSION_RISCV_U); -- UBE: CPU/Processor is BIG-ENDIAN (in user-mode)
|
csr.rdata(07) <= csr.mstatus_mpie; -- MPIE
|
csr.rdata(07) <= csr.mstatus_mpie; -- MPIE
|
Line 2276... |
Line 2452... |
when csr_misa_c => -- R/-: misa - ISA and extensions
|
when csr_misa_c => -- R/-: misa - ISA and extensions
|
csr.rdata(00) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_A); -- A CPU extension
|
csr.rdata(00) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_A); -- A CPU extension
|
csr.rdata(01) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_B); -- B CPU extension
|
csr.rdata(01) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_B); -- B CPU extension
|
csr.rdata(02) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_C); -- C CPU extension
|
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(04) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- E CPU extension
|
|
csr.rdata(05) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_F); -- F CPU extension
|
csr.rdata(08) <= not bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- I CPU extension (if not E)
|
csr.rdata(08) <= not bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- I CPU extension (if not E)
|
csr.rdata(12) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_M); -- M CPU extension
|
csr.rdata(12) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_M); -- M CPU extension
|
csr.rdata(20) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_U); -- U CPU extension
|
csr.rdata(20) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_U); -- U CPU extension
|
csr.rdata(23) <= '1'; -- X CPU extension (non-std extensions)
|
csr.rdata(23) <= '1'; -- X CPU extension (non-std extensions)
|
csr.rdata(30) <= '1'; -- 32-bit architecture (MXL lo)
|
csr.rdata(30) <= '1'; -- 32-bit architecture (MXL lo)
|