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_Zfinx : boolean := false; -- implement 32-bit floating-point extension (using INT reg!)
|
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) --
|
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64)
|
PMP_NUM_REGIONS : natural := 0; -- number of regions (0..64)
|
PMP_MIN_GRANULARITY : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
|
PMP_MIN_GRANULARITY : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
|
Line 178... |
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_op : 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 --
|
type execute_engine_state_t is (SYS_WAIT, DISPATCH, TRAP_ENTER, TRAP_EXIT, TRAP_EXECUTE, EXECUTE, ALU_WAIT,
|
type execute_engine_state_t is (SYS_WAIT, DISPATCH, TRAP_ENTER, TRAP_EXIT, TRAP_EXECUTE, EXECUTE, ALU_WAIT, BRANCH,
|
BRANCH, FENCE_OP,LOADSTORE_0, LOADSTORE_1, LOADSTORE_2, SYS_ENV, CSR_ACCESS);
|
FENCE_OP,LOADSTORE_0, LOADSTORE_1, LOADSTORE_2, ATOMIC_SC_EVAL, SYS_ENV, CSR_ACCESS);
|
type execute_engine_t is record
|
type execute_engine_t is record
|
state : execute_engine_state_t;
|
state : execute_engine_state_t;
|
state_nxt : execute_engine_state_t;
|
state_nxt : execute_engine_state_t;
|
state_prev : execute_engine_state_t;
|
state_prev : execute_engine_state_t;
|
--
|
--
|
Line 200... |
Line 199... |
--
|
--
|
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 243... |
Line 240... |
env_call : std_ulogic;
|
env_call : std_ulogic;
|
break_point : std_ulogic;
|
break_point : std_ulogic;
|
end record;
|
end record;
|
signal trap_ctrl : trap_ctrl_t;
|
signal trap_ctrl : trap_ctrl_t;
|
|
|
-- atomic operations controller --
|
|
type atomic_ctrl_t is record
|
|
env_start : std_ulogic; -- begin atomic operations
|
|
env_end : std_ulogic; -- end atomic operations
|
|
env_end_ff : std_ulogic; -- end atomic operations dealyed
|
|
env_abort : std_ulogic; -- atomic operations abort (results in failure)
|
|
lock : std_ulogic; -- lock status
|
|
end record;
|
|
signal atomic_ctrl : atomic_ctrl_t;
|
|
|
|
-- CPU main control bus --
|
-- CPU main control bus --
|
signal ctrl_nxt, ctrl : std_ulogic_vector(ctrl_width_c-1 downto 0);
|
signal ctrl_nxt, ctrl : std_ulogic_vector(ctrl_width_c-1 downto 0);
|
|
|
-- fast instruction fetch access --
|
-- fast instruction fetch access --
|
signal bus_fast_ir : std_ulogic;
|
signal bus_fast_ir : std_ulogic;
|
Line 434... |
Line 421... |
|
|
-- ****************************************************************************************************************************
|
-- ****************************************************************************************************************************
|
-- Instruction Prefetch Buffer
|
-- Instruction Prefetch Buffer
|
-- ****************************************************************************************************************************
|
-- ****************************************************************************************************************************
|
|
|
|
|
-- Instruction Prefetch Buffer (FIFO) -----------------------------------------------------
|
-- Instruction Prefetch Buffer (FIFO) -----------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
instr_prefetch_buffer: process(clk_i)
|
instr_prefetch_buffer: process(clk_i)
|
begin
|
begin
|
if rising_edge(clk_i) then
|
if rising_edge(clk_i) then
|
Line 473... |
Line 459... |
|
|
-- ****************************************************************************************************************************
|
-- ****************************************************************************************************************************
|
-- Instruction Issue (recoding of compressed instructions and 32-bit instruction word construction)
|
-- Instruction Issue (recoding of compressed instructions and 32-bit instruction word construction)
|
-- ****************************************************************************************************************************
|
-- ****************************************************************************************************************************
|
|
|
|
|
-- Issue Engine FSM Sync ------------------------------------------------------------------
|
-- Issue Engine FSM Sync ------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
issue_engine_fsm_sync: process(rstn_i, clk_i)
|
issue_engine_fsm_sync: process(rstn_i, clk_i)
|
begin
|
begin
|
if (rstn_i = '0') then
|
if (rstn_i = '0') then
|
Line 603... |
Line 588... |
|
|
-- ****************************************************************************************************************************
|
-- ****************************************************************************************************************************
|
-- Instruction Execution
|
-- Instruction Execution
|
-- ****************************************************************************************************************************
|
-- ****************************************************************************************************************************
|
|
|
|
|
-- Immediate Generator --------------------------------------------------------------------
|
-- Immediate Generator --------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
imm_gen: process(execute_engine.i_reg, clk_i)
|
imm_gen: process(execute_engine.i_reg, clk_i)
|
variable opcode_v : std_ulogic_vector(6 downto 0);
|
variable opcode_v : std_ulogic_vector(6 downto 0);
|
begin
|
begin
|
Line 615... |
Line 599... |
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 | opcode_fsw_c => -- S-immediate
|
when opcode_store_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 704... |
Line 688... |
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 734... |
Line 717... |
csr.addr <= execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c);
|
csr.addr <= execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c);
|
|
|
|
|
-- CPU Control Bus Output -----------------------------------------------------------------
|
-- CPU Control Bus Output -----------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
ctrl_output: process(ctrl, fetch_engine, trap_ctrl, atomic_ctrl, bus_fast_ir, execute_engine, csr)
|
ctrl_output: process(ctrl, fetch_engine, trap_ctrl, bus_fast_ir, execute_engine, csr)
|
begin
|
begin
|
-- signals from execute engine --
|
-- signals from execute engine --
|
ctrl_o <= ctrl;
|
ctrl_o <= ctrl;
|
-- current privilege level --
|
-- current privilege level --
|
ctrl_o(ctrl_priv_lvl_msb_c downto ctrl_priv_lvl_lsb_c) <= csr.privilege;
|
ctrl_o(ctrl_priv_lvl_msb_c downto ctrl_priv_lvl_lsb_c) <= csr.privilege;
|
Line 759... |
Line 742... |
ctrl_o(ctrl_alu_shift_ar_c) <= execute_engine.i_reg(30); -- is arithmetic shift
|
ctrl_o(ctrl_alu_shift_ar_c) <= execute_engine.i_reg(30); -- is arithmetic shift
|
-- instruction's function blocks (for co-processors) --
|
-- instruction's function blocks (for co-processors) --
|
ctrl_o(ctrl_ir_opcode7_6_c downto ctrl_ir_opcode7_0_c) <= execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c);
|
ctrl_o(ctrl_ir_opcode7_6_c downto ctrl_ir_opcode7_0_c) <= execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c);
|
ctrl_o(ctrl_ir_funct12_11_c downto ctrl_ir_funct12_0_c) <= execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c);
|
ctrl_o(ctrl_ir_funct12_11_c downto ctrl_ir_funct12_0_c) <= execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c);
|
ctrl_o(ctrl_ir_funct3_2_c downto ctrl_ir_funct3_0_c) <= execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c);
|
ctrl_o(ctrl_ir_funct3_2_c downto ctrl_ir_funct3_0_c) <= execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c);
|
-- locked bus operation (for atomic memory operations) --
|
|
ctrl_o(ctrl_bus_lock_c) <= atomic_ctrl.lock; -- (bus) lock status
|
|
-- cpu status --
|
-- cpu status --
|
ctrl_o(ctrl_sleep_c) <= execute_engine.sleep; -- cpu is in sleep mode
|
ctrl_o(ctrl_sleep_c) <= execute_engine.sleep; -- cpu is in sleep mode
|
end process ctrl_output;
|
end process ctrl_output;
|
|
|
|
|
Line 778... |
Line 759... |
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_op <= '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? --
|
Line 826... |
Line 806... |
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "111") or -- ANDN
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "111") or -- ANDN
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "110") or -- ORN
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "110") or -- ORN
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "100") -- XORN
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "100") -- XORN
|
)
|
)
|
) or
|
) or
|
|
((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0010000") and
|
|
(
|
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "010") or -- SH1ADD
|
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "100") or -- SH2ADD
|
|
(execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "110") -- SH3ADD
|
|
)
|
|
) or
|
((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) = "001")) or -- SBCLR
|
((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) = "001")) or -- SBCLR
|
((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 --
|
-- floating-point operations (Zfinx) --
|
if ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+2) = "11110")) or -- FMV.W.X
|
if ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c+3) = "0000")) or -- FADD.S / FSUB.S
|
((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) = "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) = "11100") and (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "001")) or -- FCLASS.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) = "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) = "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) = "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) = "11010") and (execute_engine.i_reg(instr_funct12_lsb_c+4 downto instr_funct12_lsb_c+1) = "0000")) or -- FCVT.S.W*
|
((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
|
((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';
|
decode_aux.is_float_op <= '1';
|
end if;
|
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
|
Line 869... |
Line 849... |
-- 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 894... |
Line 873... |
|
|
-- CSR access --
|
-- CSR access --
|
csr.we_nxt <= '0';
|
csr.we_nxt <= '0';
|
csr.re_nxt <= '0';
|
csr.re_nxt <= '0';
|
|
|
-- atomic operations control --
|
|
atomic_ctrl.env_start <= '0';
|
|
atomic_ctrl.env_end <= '0';
|
|
atomic_ctrl.env_abort <= '0';
|
|
|
|
-- CONTROL DEFAULTS --
|
-- CONTROL DEFAULTS --
|
ctrl_nxt <= (others => '0'); -- default: all off
|
ctrl_nxt <= (others => '0'); -- default: all off
|
-- ALU main control --
|
-- ALU main control --
|
ctrl_nxt(ctrl_alu_addsub_c) <= '0'; -- ADD(I)
|
ctrl_nxt(ctrl_alu_addsub_c) <= '0'; -- ADD(I)
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_arith_c; -- default ALU function select: arithmetic
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_arith_c; -- default ALU function select: arithmetic
|
Line 911... |
Line 885... |
if (execute_engine.i_reg(instr_opcode_lsb_c+4) = '1') then -- ALU ops
|
if (execute_engine.i_reg(instr_opcode_lsb_c+4) = '1') then -- ALU ops
|
ctrl_nxt(ctrl_alu_unsigned_c) <= execute_engine.i_reg(instr_funct3_lsb_c+0); -- unsigned ALU operation? (SLTIU, SLTU)
|
ctrl_nxt(ctrl_alu_unsigned_c) <= execute_engine.i_reg(instr_funct3_lsb_c+0); -- unsigned ALU operation? (SLTIU, SLTU)
|
else -- branches
|
else -- branches
|
ctrl_nxt(ctrl_alu_unsigned_c) <= execute_engine.i_reg(instr_funct3_lsb_c+1); -- unsigned branches? (BLTU, BGEU)
|
ctrl_nxt(ctrl_alu_unsigned_c) <= execute_engine.i_reg(instr_funct3_lsb_c+1); -- unsigned branches? (BLTU, BGEU)
|
end if;
|
end if;
|
|
-- bus interface --
|
|
ctrl_nxt(ctrl_bus_excl_c) <= ctrl(ctrl_bus_excl_c); -- keep exclusive bus access request alive if set
|
|
|
|
|
-- state machine --
|
-- state machine --
|
case execute_engine.state is
|
case execute_engine.state is
|
|
|
Line 932... |
Line 908... |
|
|
when DISPATCH => -- Get new command from instruction issue engine
|
when DISPATCH => -- Get new command from instruction issue engine
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
-- housekeeping --
|
-- housekeeping --
|
execute_engine.is_cp_op_nxt <= '0'; -- init
|
execute_engine.is_cp_op_nxt <= '0'; -- init
|
execute_engine.is_fp_nxt <= '0'; -- init
|
ctrl_nxt(ctrl_bus_excl_c) <= '0'; -- clear exclusive data bus access
|
-- 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 1062... |
Line 1038... |
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 | opcode_flw_c | opcode_fsw_c => -- load/store / atomic memory access / floating-point load/store
|
when opcode_load_c | opcode_store_c | opcode_atomic_c => -- load/store / atomic memory access
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
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 -- atomic extension disabled
|
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
|
(execute_engine.i_reg(instr_opcode_lsb_c+3 downto instr_opcode_lsb_c+2) = "00") then -- 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
|
|
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
|
execute_engine.state_nxt <= LOADSTORE_0;
|
execute_engine.state_nxt <= LOADSTORE_0;
|
else -- unimplemented (atomic) instruction
|
else -- unimplemented (atomic) instruction
|
execute_engine.state_nxt <= SYS_WAIT;
|
execute_engine.state_nxt <= SYS_WAIT;
|
Line 1116... |
Line 1086... |
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)
|
when opcode_fop_c => -- floating-point operations
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
execute_engine.state_nxt <= SYS_WAIT;
|
if (CPU_EXTENSION_RISCV_Zfinx = true) then
|
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
|
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
|
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;
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c;
|
execute_engine.state_nxt <= ALU_WAIT;
|
execute_engine.state_nxt <= ALU_WAIT;
|
|
else
|
|
execute_engine.state_nxt <= SYS_WAIT;
|
end if;
|
end if;
|
|
|
when others => -- undefined
|
when others => -- undefined
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
execute_engine.state_nxt <= SYS_WAIT;
|
execute_engine.state_nxt <= SYS_WAIT;
|
Line 1167... |
Line 1137... |
|
|
|
|
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 1225... |
Line 1191... |
end if;
|
end if;
|
|
|
|
|
when LOADSTORE_0 => -- trigger memory request
|
when LOADSTORE_0 => -- trigger memory request
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
|
ctrl_nxt(ctrl_bus_excl_c) <= decode_aux.is_atomic_lr; -- atomic.LR: exclusive memory access request
|
if (execute_engine.i_reg(instr_opcode_msb_c-1) = '0') or (decode_aux.is_atomic_lr = '1') then -- normal load or atomic load-reservate
|
if (execute_engine.i_reg(instr_opcode_msb_c-1) = '0') or (decode_aux.is_atomic_lr = '1') then -- normal load or atomic load-reservate
|
ctrl_nxt(ctrl_bus_rd_c) <= '1'; -- read request
|
ctrl_nxt(ctrl_bus_rd_c) <= '1'; -- read request
|
else -- store
|
else -- store
|
ctrl_nxt(ctrl_bus_wr_c) <= '1'; -- write request
|
ctrl_nxt(ctrl_bus_wr_c) <= '1'; -- write request
|
end if;
|
end if;
|
Line 1236... |
Line 1203... |
|
|
|
|
when LOADSTORE_1 => -- memory latency
|
when LOADSTORE_1 => -- memory latency
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
ctrl_nxt(ctrl_bus_mi_we_c) <= '1'; -- write input data to MDI (only relevant for LOAD)
|
ctrl_nxt(ctrl_bus_mi_we_c) <= '1'; -- write input data to MDI (only relevant for LOAD)
|
|
if (CPU_EXTENSION_RISCV_A = true) and (decode_aux.is_atomic_sc = '1') then -- execute and evaluate atomic store-conditional
|
|
execute_engine.state_nxt <= ATOMIC_SC_EVAL;
|
|
else -- normal load/store
|
execute_engine.state_nxt <= LOADSTORE_2;
|
execute_engine.state_nxt <= LOADSTORE_2;
|
|
end if;
|
|
|
|
|
when LOADSTORE_2 => -- wait for bus transaction to finish
|
when LOADSTORE_2 => -- wait for bus transaction to finish
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
-- ALU control (only relevant for atomic memory operations) --
|
|
if (CPU_EXTENSION_RISCV_A = true) then
|
|
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_atomic_c; -- atomic.SC: result comes from "atomic co-processor"
|
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c;
|
|
end if;
|
|
-- register file write-back --
|
|
if (decode_aux.is_atomic_sc = '1') then
|
|
ctrl_nxt(ctrl_rf_in_mux_c) <= '0'; -- RF input = ALU.res (only relevant for atomic.SC)
|
|
else
|
|
ctrl_nxt(ctrl_rf_in_mux_c) <= '1'; -- RF input = memory input (only relevant for LOADs)
|
|
end if;
|
|
--
|
|
ctrl_nxt(ctrl_bus_mi_we_c) <= '1'; -- keep writing input data to MDI (only relevant for load operations)
|
ctrl_nxt(ctrl_bus_mi_we_c) <= '1'; -- keep writing input data to MDI (only relevant for load operations)
|
|
ctrl_nxt(ctrl_rf_in_mux_c) <= '1'; -- RF input = memory input (only relevant for LOADs)
|
-- wait for memory response --
|
-- wait for memory response --
|
if ((ma_load_i or be_load_i or ma_store_i or be_store_i) = '1') then -- abort if exception
|
if ((ma_load_i or be_load_i or ma_store_i or be_store_i) = '1') then -- abort if exception
|
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
|
|
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
|
-- data write-back
|
ctrl_nxt(ctrl_rf_wb_en_c) <= not execute_engine.is_fp; -- allow write back if NOT <FPU-internal operation>
|
if (execute_engine.i_reg(instr_opcode_msb_c-1) = '0') or (decode_aux.is_atomic_lr = '1') then -- normal load OR atomic load
|
|
ctrl_nxt(ctrl_rf_wb_en_c) <= '1';
|
end if;
|
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;
|
|
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;
|
|
|
|
|
|
when ATOMIC_SC_EVAL => -- wait for bus transaction to finish and evaluate if SC was successful
|
|
-- ------------------------------------------------------------
|
|
if (CPU_EXTENSION_RISCV_A = true) then
|
|
-- atomic.SC: result comes from "atomic co-processor" --
|
|
ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_atomic_c;
|
|
execute_engine.is_cp_op_nxt <= '1'; -- this is a CP operation
|
|
ctrl_nxt(ctrl_rf_in_mux_c) <= '0'; -- RF input = ALU.res
|
|
ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- allow reg file write back
|
|
-- wait for memory response --
|
|
if ((ma_load_i or be_load_i or ma_store_i or be_store_i) = '1') then -- abort if exception
|
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c; -- trigger atomic-coprocessor operation for SC status evaluation
|
|
execute_engine.state_nxt <= ALU_WAIT;
|
|
elsif (bus_d_wait_i = '0') then -- wait for bus to finish transaction
|
|
ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c; -- trigger atomic-coprocessor operation for SC status evaluation
|
|
execute_engine.state_nxt <= ALU_WAIT;
|
|
end if;
|
|
else
|
|
execute_engine.state_nxt <= SYS_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 1283... |
Line 1259... |
|
|
-- ****************************************************************************************************************************
|
-- ****************************************************************************************************************************
|
-- Invalid Instruction / CSR access check
|
-- Invalid Instruction / CSR access check
|
-- ****************************************************************************************************************************
|
-- ****************************************************************************************************************************
|
|
|
|
|
-- CSR Access Check -----------------------------------------------------------------------
|
-- CSR Access Check -----------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
csr_access_check: process(execute_engine.i_reg, csr)
|
csr_access_check: process(execute_engine.i_reg, csr)
|
variable csr_wacc_v : std_ulogic; -- to check access to read-only CSRs
|
variable csr_wacc_v : std_ulogic; -- to check access to read-only CSRs
|
-- variable csr_racc_v : std_ulogic; -- to check access to write-only CSRs
|
-- variable csr_racc_v : std_ulogic; -- to check access to write-only CSRs
|
Line 1312... |
Line 1287... |
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_fflags_c | csr_frm_c | csr_fcsr_c => csr_acc_valid <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zfinx); -- full access for everyone if Zfinx 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
|
Line 1644... |
Line 1619... |
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)
|
when opcode_fop_c => -- floating point operations - single/dual operands
|
-- ------------------------------------------------------------
|
-- ------------------------------------------------------------
|
if (CPU_EXTENSION_RISCV_F = true) and -- F extension enabled
|
if (CPU_EXTENSION_RISCV_Zfinx = 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
|
(execute_engine.i_reg(instr_funct7_lsb_c+1 downto instr_funct7_lsb_c) = float_single_c) and -- single-precision operations only
|
((decode_aux.is_float_f_reg = '1') or (decode_aux.is_float_i_reg = '1')) then -- float_reg or int_reg operations
|
(decode_aux.is_float_op = '1') then -- is correct/supported floating-point instruction
|
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';
|
illegal_instruction <= '0';
|
else
|
else
|
illegal_instruction <= '1';
|
illegal_instruction <= '1';
|
end if;
|
end if;
|
|
|
Line 1683... |
Line 1649... |
|
|
-- ****************************************************************************************************************************
|
-- ****************************************************************************************************************************
|
-- Exception and Interrupt (= Trap) Control
|
-- Exception and Interrupt (= Trap) Control
|
-- ****************************************************************************************************************************
|
-- ****************************************************************************************************************************
|
|
|
|
|
-- Trap Controller ------------------------------------------------------------------------
|
-- Trap Controller ------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
-- -------------------------------------------------------------------------------------------
|
trap_controller: process(rstn_i, clk_i)
|
trap_controller: process(rstn_i, clk_i)
|
variable mode_m_v, mode_u_v : std_ulogic;
|
variable mode_m_v, mode_u_v : std_ulogic;
|
begin
|
begin
|
Line 1914... |
Line 1879... |
trap_ctrl.irq_ack_nxt <= (others => '0');
|
trap_ctrl.irq_ack_nxt <= (others => '0');
|
end if;
|
end if;
|
end process trap_priority;
|
end process trap_priority;
|
|
|
|
|
-- Atomic Memory Access - Status Controller -----------------------------------------------
|
|
-- -------------------------------------------------------------------------------------------
|
|
atomic_memacc_controller: process(rstn_i, clk_i)
|
|
begin
|
|
if (rstn_i = '0') then
|
|
atomic_ctrl.lock <= '0';
|
|
atomic_ctrl.env_end_ff <= '0';
|
|
elsif rising_edge(clk_i) then
|
|
if (CPU_EXTENSION_RISCV_A = true) then
|
|
if (atomic_ctrl.env_end_ff = '1') or -- normal termination
|
|
(atomic_ctrl.env_abort = '1') or -- fast termination (error)
|
|
(trap_ctrl.env_start = '1') then -- triggered trap -> failure
|
|
atomic_ctrl.lock <= '0';
|
|
elsif (atomic_ctrl.env_start = '1') then
|
|
atomic_ctrl.lock <= '1';
|
|
end if;
|
|
atomic_ctrl.env_end_ff <= atomic_ctrl.env_end;
|
|
else
|
|
atomic_ctrl.lock <= '0';
|
|
atomic_ctrl.env_end_ff <= '0';
|
|
end if;
|
|
end if;
|
|
end process atomic_memacc_controller;
|
|
|
|
|
|
-- ****************************************************************************************************************************
|
-- ****************************************************************************************************************************
|
-- Control and Status Registers (CSRs)
|
-- Control and Status Registers (CSRs)
|
-- ****************************************************************************************************************************
|
-- ****************************************************************************************************************************
|
|
|
-- Control and Status Registers Write Data ------------------------------------------------
|
-- Control and Status Registers Write Data ------------------------------------------------
|
Line 2020... |
Line 1960... |
|
|
-- user floating-point CSRs --
|
-- user floating-point CSRs --
|
-- --------------------------------------------------------------------
|
-- --------------------------------------------------------------------
|
if (csr.addr(11 downto 4) = csr_class_float_c) then -- floating point CSR class
|
if (csr.addr(11 downto 4) = csr_class_float_c) then -- floating point CSR class
|
-- R/W: fflags - floating-point (FPU) exception flags --
|
-- 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
|
if (csr.addr(3 downto 0) = csr_fflags_c(3 downto 0)) and (CPU_EXTENSION_RISCV_Zfinx = true) then
|
csr.fflags <= csr.wdata(4 downto 0);
|
csr.fflags <= csr.wdata(4 downto 0);
|
end if;
|
end if;
|
-- R/W: frm - floating-point (FPU) rounding mode --
|
-- 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
|
if (csr.addr(3 downto 0) = csr_frm_c(3 downto 0)) and (CPU_EXTENSION_RISCV_Zfinx = true) then
|
csr.frm <= csr.wdata(2 downto 0);
|
csr.frm <= csr.wdata(2 downto 0);
|
end if;
|
end if;
|
-- R/W: fflags - floating-point (FPU) control/status (frm + fflags) --
|
-- 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
|
if (csr.addr(3 downto 0) = csr_fcsr_c(3 downto 0)) and (CPU_EXTENSION_RISCV_Zfinx = true) then
|
csr.frm <= csr.wdata(7 downto 5);
|
csr.frm <= csr.wdata(7 downto 5);
|
csr.fflags <= csr.wdata(4 downto 0);
|
csr.fflags <= csr.wdata(4 downto 0);
|
end if;
|
end if;
|
end if;
|
end if;
|
|
|
Line 2168... |
Line 2108... |
-- --------------------------------------------------------------------------------
|
-- --------------------------------------------------------------------------------
|
else
|
else
|
|
|
-- floating-point (FPU) exception flags --
|
-- floating-point (FPU) exception flags --
|
-- --------------------------------------------------------------------
|
-- --------------------------------------------------------------------
|
if (CPU_EXTENSION_RISCV_F = true) and (execute_engine.state = ALU_WAIT) then -- FIXME?
|
if (CPU_EXTENSION_RISCV_Zfinx = true) and (execute_engine.state = ALU_WAIT) then
|
csr.fflags <= csr.fflags or fpu_flags_i; -- accumulate flags ("accrued exception flags")
|
csr.fflags <= csr.fflags or fpu_flags_i; -- accumulate flags ("accrued exception flags")
|
end if;
|
end if;
|
|
|
-- mcause, mepc, mtval: machine trap cause, PC and value register --
|
-- mcause, mepc, mtval: machine trap cause, PC and value register --
|
-- --------------------------------------------------------------------
|
-- --------------------------------------------------------------------
|
Line 2253... |
Line 2193... |
csr.mcounteren_hpm <= (others => '0');
|
csr.mcounteren_hpm <= (others => '0');
|
csr.mcountinhibit_hpm <= (others => '0');
|
csr.mcountinhibit_hpm <= (others => '0');
|
end if;
|
end if;
|
|
|
-- floating-point extension disabled --
|
-- floating-point extension disabled --
|
if (CPU_EXTENSION_RISCV_F = false) then
|
if (CPU_EXTENSION_RISCV_Zfinx = false) then
|
csr.fflags <= (others => '0');
|
csr.fflags <= (others => '0');
|
csr.frm <= (others => '0');
|
csr.frm <= (others => '0');
|
end if;
|
end if;
|
|
|
end if;
|
end if;
|
Line 2423... |
Line 2363... |
|
|
-- user floating-point CSRs --
|
-- user floating-point CSRs --
|
-- --------------------------------------------------------------------
|
-- --------------------------------------------------------------------
|
when csr_fflags_c => -- R/W: fflags - floating-point (FPU) exception flags
|
when csr_fflags_c => -- R/W: fflags - floating-point (FPU) exception flags
|
csr.rdata <= (others => '0');
|
csr.rdata <= (others => '0');
|
if (CPU_EXTENSION_RISCV_F = true) then -- FPU implemented
|
if (CPU_EXTENSION_RISCV_Zfinx = true) then -- FPU implemented
|
csr.rdata(4 downto 0) <= csr.fflags;
|
csr.rdata(4 downto 0) <= csr.fflags;
|
end if;
|
end if;
|
when csr_frm_c => -- R/W: frm - floating-point (FPU) rounding mode
|
when csr_frm_c => -- R/W: frm - floating-point (FPU) rounding mode
|
csr.rdata <= (others => '0');
|
csr.rdata <= (others => '0');
|
if (CPU_EXTENSION_RISCV_F = true) then -- FPU implemented
|
if (CPU_EXTENSION_RISCV_Zfinx = true) then -- FPU implemented
|
csr.rdata(2 downto 0) <= csr.frm;
|
csr.rdata(2 downto 0) <= csr.frm;
|
end if;
|
end if;
|
when csr_fcsr_c => -- R/W: fflags - floating-point (FPU) control/status (frm + fflags)
|
when csr_fcsr_c => -- R/W: fflags - floating-point (FPU) control/status (frm + fflags)
|
csr.rdata <= (others => '0');
|
csr.rdata <= (others => '0');
|
if (CPU_EXTENSION_RISCV_F = true) then -- FPU implemented
|
if (CPU_EXTENSION_RISCV_Zfinx = true) then -- FPU implemented
|
csr.rdata(7 downto 5) <= csr.frm;
|
csr.rdata(7 downto 5) <= csr.frm;
|
csr.rdata(4 downto 0) <= csr.fflags;
|
csr.rdata(4 downto 0) <= csr.fflags;
|
end if;
|
end if;
|
|
|
-- machine trap setup --
|
-- machine trap setup --
|
Line 2452... |
Line 2392... |
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(05) <= '0'; -- F CPU extension
|
csr.rdata(08) <= not bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- I CPU extension (if not E)
|
csr.rdata(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)
|
Line 2704... |
Line 2644... |
csr.rdata <= hw_version_c; -- NEORV32 hardware version
|
csr.rdata <= hw_version_c; -- NEORV32 hardware version
|
when csr_mhartid_c => -- R/-: mhartid - hardware thread ID
|
when csr_mhartid_c => -- R/-: mhartid - hardware thread ID
|
csr.rdata <= std_ulogic_vector(to_unsigned(HW_THREAD_ID, 32));
|
csr.rdata <= std_ulogic_vector(to_unsigned(HW_THREAD_ID, 32));
|
|
|
-- custom machine read-only CSRs --
|
-- custom machine read-only CSRs --
|
when csr_mzext_c => -- R/-: mzext - available RISC-V Z* extensions
|
when csr_mzext_c => -- R/-: mzext - available RISC-V Z* sub-extensions
|
csr.rdata(0) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicsr); -- Zicsr
|
csr.rdata(0) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicsr); -- Zicsr
|
csr.rdata(1) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zifencei); -- Zifencei
|
csr.rdata(1) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zifencei); -- Zifencei
|
csr.rdata(2) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_B); -- Zbb
|
csr.rdata(2) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_B); -- Zbb (B)
|
csr.rdata(3) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_B); -- Zbs
|
csr.rdata(3) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_B); -- Zbs (B)
|
|
csr.rdata(4) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_B); -- Zba (B)
|
|
csr.rdata(5) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zfinx); -- Zfinx ("F-alternative")
|
|
|
-- undefined/unavailable --
|
-- undefined/unavailable --
|
when others =>
|
when others =>
|
csr.rdata <= (others => '0'); -- not implemented
|
csr.rdata <= (others => '0'); -- not implemented
|
|
|