mirror of
https://github.com/stnolting/neorv32.git
synced 2025-04-23 21:57:33 -04:00
[rtl] minor RTL edits (#1068)
This commit is contained in:
commit
ef7fc624a0
6 changed files with 280 additions and 301 deletions
|
@ -29,7 +29,8 @@ mimpid = 0x01040312 -> Version 01.04.03.12 -> v1.4.3.12
|
|||
|
||||
| Date | Version | Comment | Ticket |
|
||||
|:----:|:-------:|:--------|:------:|
|
||||
| 18.10.2024 | 1.10.5.7 | use individual/new module for XBUS-to-AXI4-Lite bridge | [#](https://github.com/stnolting/neorv32/pull/1063) |
|
||||
| 18.10.2024 | 1.10.5.8 | minor RTL code cleanups | [#1068](https://github.com/stnolting/neorv32/pull/1068) |
|
||||
| 18.10.2024 | 1.10.5.7 | use individual/new module for XBUS-to-AXI4-Lite bridge | [#1063](https://github.com/stnolting/neorv32/pull/1063) |
|
||||
| 12.10.2024 | 1.10.5.6 | :warning: remove legacy support for on-chip debugger DM version v0.13; now only supporting DM v1.0 (removing `OCD_DM_LEGACY_MODE` generic) | [#1056](https://github.com/stnolting/neorv32/pull/1056) |
|
||||
| 11.10.2024 | 1.10.5.5 | :sparkles: :lock: add support for optional on-chip debugger authentication; :warning: rename OCD-related top generics | [#1053](https://github.com/stnolting/neorv32/pull/1053) |
|
||||
| 06.10.2024 | 1.10.5.4 | :warning: rework PWM module | [#1049](https://github.com/stnolting/neorv32/pull/1049) |
|
||||
|
|
|
@ -150,11 +150,11 @@ architecture neorv32_cpu_control_rtl of neorv32_cpu_control is
|
|||
signal issue_engine : issue_engine_t;
|
||||
|
||||
-- instruction execution engine --
|
||||
type execute_engine_state_t is (DISPATCH, TRAP_ENTER, TRAP_EXIT, RESTART, SLEEP, EXECUTE,
|
||||
ALU_WAIT, BRANCH, BRANCHED, SYSTEM, MEM_REQ, MEM_WAIT);
|
||||
type execute_engine_t is record
|
||||
state : execute_engine_state_t;
|
||||
state_nxt : execute_engine_state_t;
|
||||
type exe_engine_state_t is (DISPATCH, TRAP_ENTER, TRAP_EXIT, RESTART, SLEEP, EXECUTE,
|
||||
ALU_WAIT, BRANCH, BRANCHED, SYSTEM, MEM_REQ, MEM_WAIT);
|
||||
type exe_engine_t is record
|
||||
state : exe_engine_state_t;
|
||||
state_nxt : exe_engine_state_t;
|
||||
ir : std_ulogic_vector(31 downto 0); -- instruction word being executed right now
|
||||
ir_nxt : std_ulogic_vector(31 downto 0);
|
||||
is_ci : std_ulogic; -- current instruction is de-compressed instruction
|
||||
|
@ -164,9 +164,9 @@ architecture neorv32_cpu_control_rtl of neorv32_cpu_control is
|
|||
pc_we : std_ulogic; -- PC update enable
|
||||
next_pc : std_ulogic_vector(XLEN-1 downto 0); -- next PC, corresponding to next instruction to be executed
|
||||
end record;
|
||||
signal execute_engine : execute_engine_t;
|
||||
signal exe_engine : exe_engine_t;
|
||||
|
||||
-- simplified opcode --
|
||||
-- simplified opcode (2 LSBs hardwired to "11" to indicate rv32) --
|
||||
signal opcode : std_ulogic_vector(6 downto 0);
|
||||
|
||||
-- execution monitor --
|
||||
|
@ -284,7 +284,7 @@ architecture neorv32_cpu_control_rtl of neorv32_cpu_control is
|
|||
|
||||
-- debug-mode controller --
|
||||
type debug_ctrl_t is record
|
||||
running, trig_hw, trig_break, trig_halt, trig_step : std_ulogic; -- single-stepping mode trigger
|
||||
run, trig_hw, trig_break, trig_halt, trig_step : std_ulogic;
|
||||
end record;
|
||||
signal debug_ctrl : debug_ctrl_t;
|
||||
|
||||
|
@ -345,7 +345,7 @@ begin
|
|||
|
||||
when others => -- IF_RESTART: set new start address
|
||||
-- ------------------------------------------------------------
|
||||
fetch_engine.pc <= execute_engine.next_pc(XLEN-1 downto 1) & '0'; -- initialize from PC incl. 16-bit-alignment bit
|
||||
fetch_engine.pc <= exe_engine.next_pc(XLEN-1 downto 1) & '0'; -- initialize from PC incl. 16-bit-alignment bit
|
||||
fetch_engine.priv <= csr.privilege_eff; -- set new privilege level
|
||||
fetch_engine.state <= IF_REQUEST;
|
||||
|
||||
|
@ -427,7 +427,7 @@ begin
|
|||
issue_engine.align <= '0'; -- start aligned after reset
|
||||
elsif rising_edge(clk_i) then
|
||||
if (fetch_engine.restart = '1') then
|
||||
issue_engine.align <= execute_engine.next_pc(1); -- branch to unaligned address?
|
||||
issue_engine.align <= exe_engine.next_pc(1); -- branch to unaligned address?
|
||||
elsif (issue_engine.ack = '1') then
|
||||
issue_engine.align <= (issue_engine.align and (not issue_engine.align_clr)) or issue_engine.align_set; -- "rs flip-flop"
|
||||
end if;
|
||||
|
@ -506,7 +506,7 @@ begin
|
|||
if (rstn_i = '0') then
|
||||
alu_imm_o <= (others => '0');
|
||||
elsif rising_edge(clk_i) then
|
||||
if (execute_engine.state = DISPATCH) then -- prepare update of next_pc (using ALU's PC + IMM in EXECUTE state)
|
||||
if (exe_engine.state = DISPATCH) then -- prepare update of next_pc (using ALU's PC + IMM in EXECUTE state)
|
||||
alu_imm_o <= (others => '0');
|
||||
if RISCV_ISA_C and (issue_engine.data(33) = '1') then -- is de-compressed C instruction?
|
||||
alu_imm_o(3 downto 0) <= x"2";
|
||||
|
@ -514,16 +514,16 @@ begin
|
|||
alu_imm_o(3 downto 0) <= x"4";
|
||||
end if;
|
||||
else
|
||||
alu_imm_o <= replicate_f(execute_engine.ir(31), 21) & execute_engine.ir(30 downto 21) & execute_engine.ir(20); -- default: I-immediate
|
||||
alu_imm_o <= replicate_f(exe_engine.ir(31), 21) & exe_engine.ir(30 downto 21) & exe_engine.ir(20); -- default: I-immediate
|
||||
case opcode is
|
||||
when opcode_store_c => -- S-immediate
|
||||
alu_imm_o <= replicate_f(execute_engine.ir(31), 21) & execute_engine.ir(30 downto 25) & execute_engine.ir(11 downto 7);
|
||||
alu_imm_o <= replicate_f(exe_engine.ir(31), 21) & exe_engine.ir(30 downto 25) & exe_engine.ir(11 downto 7);
|
||||
when opcode_branch_c => -- B-immediate
|
||||
alu_imm_o <= replicate_f(execute_engine.ir(31), 20) & execute_engine.ir(7) & execute_engine.ir(30 downto 25) & execute_engine.ir(11 downto 8) & '0';
|
||||
alu_imm_o <= replicate_f(exe_engine.ir(31), 20) & exe_engine.ir(7) & exe_engine.ir(30 downto 25) & exe_engine.ir(11 downto 8) & '0';
|
||||
when opcode_lui_c | opcode_auipc_c => -- U-immediate
|
||||
alu_imm_o <= execute_engine.ir(31 downto 12) & x"000";
|
||||
alu_imm_o <= exe_engine.ir(31 downto 12) & x"000";
|
||||
when opcode_jal_c => -- J-immediate
|
||||
alu_imm_o <= replicate_f(execute_engine.ir(31), 12) & execute_engine.ir(19 downto 12) & execute_engine.ir(20) & execute_engine.ir(30 downto 21) & '0';
|
||||
alu_imm_o <= replicate_f(exe_engine.ir(31), 12) & exe_engine.ir(19 downto 12) & exe_engine.ir(20) & exe_engine.ir(30 downto 21) & '0';
|
||||
when opcode_amo_c => -- atomic memory access
|
||||
if RISCV_ISA_Zalrsc then alu_imm_o <= (others => '0'); end if;
|
||||
when others =>
|
||||
|
@ -536,16 +536,16 @@ begin
|
|||
|
||||
-- Branch Condition Check -----------------------------------------------------------------
|
||||
-- -------------------------------------------------------------------------------------------
|
||||
branch_check: process(execute_engine.ir, alu_cmp_i)
|
||||
branch_check: process(exe_engine.ir, alu_cmp_i)
|
||||
begin
|
||||
if (execute_engine.ir(instr_opcode_lsb_c+2) = '0') then -- conditional branch
|
||||
if (execute_engine.ir(instr_funct3_msb_c) = '0') then -- beq / bne
|
||||
execute_engine.branch_taken <= alu_cmp_i(cmp_equal_c) xor execute_engine.ir(instr_funct3_lsb_c);
|
||||
if (exe_engine.ir(instr_opcode_lsb_c+2) = '0') then -- conditional branch
|
||||
if (exe_engine.ir(instr_funct3_msb_c) = '0') then -- beq / bne
|
||||
exe_engine.branch_taken <= alu_cmp_i(cmp_equal_c) xor exe_engine.ir(instr_funct3_lsb_c);
|
||||
else -- blt(u) / bge(u)
|
||||
execute_engine.branch_taken <= alu_cmp_i(cmp_less_c) xor execute_engine.ir(instr_funct3_lsb_c);
|
||||
exe_engine.branch_taken <= alu_cmp_i(cmp_less_c) xor exe_engine.ir(instr_funct3_lsb_c);
|
||||
end if;
|
||||
else -- unconditional branch
|
||||
execute_engine.branch_taken <= '1';
|
||||
exe_engine.branch_taken <= '1';
|
||||
end if;
|
||||
end process branch_check;
|
||||
|
||||
|
@ -555,63 +555,63 @@ begin
|
|||
execute_engine_fsm_sync: process(rstn_i, clk_i)
|
||||
begin
|
||||
if (rstn_i = '0') then
|
||||
ctrl <= ctrl_bus_zero_c;
|
||||
execute_engine.state <= RESTART;
|
||||
execute_engine.ir <= (others => '0');
|
||||
execute_engine.is_ci <= '0';
|
||||
execute_engine.pc <= BOOT_ADDR(XLEN-1 downto 2) & "00"; -- 32-bit-aligned boot address
|
||||
execute_engine.next_pc <= BOOT_ADDR(XLEN-1 downto 2) & "00"; -- 32-bit-aligned boot address
|
||||
pc_next_o <= (others => '0');
|
||||
ctrl <= ctrl_bus_zero_c;
|
||||
exe_engine.state <= RESTART;
|
||||
exe_engine.ir <= (others => '0');
|
||||
exe_engine.is_ci <= '0';
|
||||
exe_engine.pc <= BOOT_ADDR(XLEN-1 downto 2) & "00"; -- 32-bit-aligned boot address
|
||||
exe_engine.next_pc <= BOOT_ADDR(XLEN-1 downto 2) & "00"; -- 32-bit-aligned boot address
|
||||
pc_next_o <= (others => '0');
|
||||
elsif rising_edge(clk_i) then
|
||||
-- control bus --
|
||||
ctrl <= ctrl_nxt;
|
||||
|
||||
-- execute engine arbiter --
|
||||
execute_engine.state <= execute_engine.state_nxt;
|
||||
execute_engine.ir <= execute_engine.ir_nxt;
|
||||
execute_engine.is_ci <= execute_engine.is_ci_nxt;
|
||||
exe_engine.state <= exe_engine.state_nxt;
|
||||
exe_engine.ir <= exe_engine.ir_nxt;
|
||||
exe_engine.is_ci <= exe_engine.is_ci_nxt;
|
||||
|
||||
-- current PC: address of instruction being executed --
|
||||
if (execute_engine.pc_we = '1') then
|
||||
execute_engine.pc <= execute_engine.next_pc(XLEN-1 downto 1) & '0';
|
||||
if (exe_engine.pc_we = '1') then
|
||||
exe_engine.pc <= exe_engine.next_pc(XLEN-1 downto 1) & '0';
|
||||
end if;
|
||||
|
||||
-- next PC: address of next instruction --
|
||||
pc_next_o <= (others => '0'); -- output zero if not a branch instruction
|
||||
case execute_engine.state is
|
||||
case exe_engine.state is
|
||||
|
||||
when TRAP_ENTER => -- starting trap environment
|
||||
-- ------------------------------------------------------------
|
||||
if (trap_ctrl.cause(5) = '1') and RISCV_ISA_Sdext then -- debug mode (re-)entry
|
||||
execute_engine.next_pc <= DEBUG_PARK_ADDR(XLEN-1 downto 2) & "00"; -- debug mode enter; start at "parking loop" <normal_entry>
|
||||
elsif (debug_ctrl.running = '1') and RISCV_ISA_Sdext then -- any other trap INSIDE debug mode
|
||||
execute_engine.next_pc <= DEBUG_EXC_ADDR(XLEN-1 downto 2) & "00"; -- debug mode enter: start at "parking loop" <exception_entry>
|
||||
exe_engine.next_pc <= DEBUG_PARK_ADDR(XLEN-1 downto 2) & "00"; -- debug mode enter; start at "parking loop" <normal_entry>
|
||||
elsif (debug_ctrl.run = '1') and RISCV_ISA_Sdext then -- any other trap INSIDE debug mode
|
||||
exe_engine.next_pc <= DEBUG_EXC_ADDR(XLEN-1 downto 2) & "00"; -- debug mode enter: start at "parking loop" <exception_entry>
|
||||
else -- normal start of trap
|
||||
if (csr.mtvec(0) = '1') and (trap_ctrl.cause(6) = '1') then -- vectored mode + interrupt
|
||||
execute_engine.next_pc <= csr.mtvec(XLEN-1 downto 7) & trap_ctrl.cause(4 downto 0) & "00"; -- pc = mtvec + 4 * mcause
|
||||
exe_engine.next_pc <= csr.mtvec(XLEN-1 downto 7) & trap_ctrl.cause(4 downto 0) & "00"; -- pc = mtvec + 4 * mcause
|
||||
else
|
||||
execute_engine.next_pc <= csr.mtvec(XLEN-1 downto 2) & "00"; -- pc = mtvec
|
||||
exe_engine.next_pc <= csr.mtvec(XLEN-1 downto 2) & "00"; -- pc = mtvec
|
||||
end if;
|
||||
end if;
|
||||
|
||||
when TRAP_EXIT => -- leaving trap environment
|
||||
-- ------------------------------------------------------------
|
||||
if (debug_ctrl.running = '1') and RISCV_ISA_Sdext then -- debug mode exit
|
||||
execute_engine.next_pc <= csr.dpc(XLEN-1 downto 1) & '0';
|
||||
if (debug_ctrl.run = '1') and RISCV_ISA_Sdext then -- debug mode exit
|
||||
exe_engine.next_pc <= csr.dpc(XLEN-1 downto 1) & '0';
|
||||
else -- normal end of trap
|
||||
execute_engine.next_pc <= csr.mepc(XLEN-1 downto 1) & '0';
|
||||
exe_engine.next_pc <= csr.mepc(XLEN-1 downto 1) & '0';
|
||||
end if;
|
||||
|
||||
when BRANCH => -- branch instruction
|
||||
-- ------------------------------------------------------------
|
||||
pc_next_o <= execute_engine.next_pc(XLEN-1 downto 1) & '0'; -- output as link/return address
|
||||
if (trap_ctrl.exc_buf(exc_illegal_c) = '0') and (execute_engine.branch_taken = '1') then -- valid taken branch
|
||||
execute_engine.next_pc <= alu_add_i(XLEN-1 downto 1) & '0';
|
||||
pc_next_o <= exe_engine.next_pc(XLEN-1 downto 1) & '0'; -- output as link/return address
|
||||
if (trap_ctrl.exc_buf(exc_illegal_c) = '0') and (exe_engine.branch_taken = '1') then -- valid taken branch
|
||||
exe_engine.next_pc <= alu_add_i(XLEN-1 downto 1) & '0';
|
||||
end if;
|
||||
|
||||
when EXECUTE => -- linear increment (use ALU's adder to compute next_pc = current_pc + imm (2/4))
|
||||
-- ------------------------------------------------------------
|
||||
execute_engine.next_pc <= alu_add_i(XLEN-1 downto 1) & '0';
|
||||
exe_engine.next_pc <= alu_add_i(XLEN-1 downto 1) & '0';
|
||||
|
||||
when others => -- no update
|
||||
-- ------------------------------------------------------------
|
||||
|
@ -622,43 +622,43 @@ begin
|
|||
end process execute_engine_fsm_sync;
|
||||
|
||||
-- check if branch destination is misaligned --
|
||||
trap_ctrl.instr_ma <= '1' when (execute_engine.state = BRANCH) and -- branch instruction (can also be INVALID as exc_illegal_c has higher priority)
|
||||
(execute_engine.branch_taken = '1') and -- branch is taken
|
||||
trap_ctrl.instr_ma <= '1' when (exe_engine.state = BRANCH) and -- branch instruction (can also be INVALID as exc_illegal_c has higher priority)
|
||||
(exe_engine.branch_taken = '1') and -- branch is taken
|
||||
(alu_add_i(1) = '1') and (not RISCV_ISA_C) else '0'; -- misaligned destination
|
||||
|
||||
-- current PC output --
|
||||
pc_curr_o <= execute_engine.pc(XLEN-1 downto 1) & '0';
|
||||
pc_curr_o <= exe_engine.pc(XLEN-1 downto 1) & '0';
|
||||
|
||||
-- simplified rv32 opcode --
|
||||
opcode <= execute_engine.ir(instr_opcode_msb_c downto instr_opcode_lsb_c+2) & "11";
|
||||
opcode <= exe_engine.ir(instr_opcode_msb_c downto instr_opcode_lsb_c+2) & "11";
|
||||
|
||||
|
||||
-- Execute Engine FSM Comb ----------------------------------------------------------------
|
||||
-- -------------------------------------------------------------------------------------------
|
||||
execute_engine_fsm_comb: process(execute_engine, debug_ctrl, trap_ctrl, hw_trigger_match, opcode, issue_engine, csr, alu_cp_done_i, lsu_wait_i)
|
||||
execute_engine_fsm_comb: process(exe_engine, debug_ctrl, trap_ctrl, hw_trigger_match, opcode, issue_engine, csr, alu_cp_done_i, lsu_wait_i)
|
||||
variable funct3_v : std_ulogic_vector(2 downto 0);
|
||||
variable funct7_v : std_ulogic_vector(6 downto 0);
|
||||
begin
|
||||
-- shortcuts --
|
||||
funct3_v := execute_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c);
|
||||
funct7_v := execute_engine.ir(instr_funct7_msb_c downto instr_funct7_lsb_c);
|
||||
funct3_v := exe_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c);
|
||||
funct7_v := exe_engine.ir(instr_funct7_msb_c downto instr_funct7_lsb_c);
|
||||
|
||||
-- arbiter defaults --
|
||||
execute_engine.state_nxt <= execute_engine.state;
|
||||
execute_engine.ir_nxt <= execute_engine.ir;
|
||||
execute_engine.is_ci_nxt <= execute_engine.is_ci;
|
||||
execute_engine.pc_we <= '0';
|
||||
issue_engine.ack <= '0';
|
||||
fetch_engine.reset <= '0';
|
||||
trap_ctrl.env_enter <= '0';
|
||||
trap_ctrl.env_exit <= '0';
|
||||
trap_ctrl.instr_be <= '0';
|
||||
trap_ctrl.ecall <= '0';
|
||||
trap_ctrl.ebreak <= '0';
|
||||
trap_ctrl.hwtrig <= '0';
|
||||
csr.we_nxt <= '0';
|
||||
csr.re_nxt <= '0';
|
||||
ctrl_nxt <= ctrl_bus_zero_c; -- all zero/off by default (default ALU operation = ZERO, ALU.adder_out = ADD)
|
||||
exe_engine.state_nxt <= exe_engine.state;
|
||||
exe_engine.ir_nxt <= exe_engine.ir;
|
||||
exe_engine.is_ci_nxt <= exe_engine.is_ci;
|
||||
exe_engine.pc_we <= '0';
|
||||
issue_engine.ack <= '0';
|
||||
fetch_engine.reset <= '0';
|
||||
trap_ctrl.env_enter <= '0';
|
||||
trap_ctrl.env_exit <= '0';
|
||||
trap_ctrl.instr_be <= '0';
|
||||
trap_ctrl.ecall <= '0';
|
||||
trap_ctrl.ebreak <= '0';
|
||||
trap_ctrl.hwtrig <= '0';
|
||||
csr.we_nxt <= '0';
|
||||
csr.re_nxt <= '0';
|
||||
ctrl_nxt <= ctrl_bus_zero_c; -- all zero/off by default (ALU operation = ZERO, ALU.adder_out = ADD)
|
||||
|
||||
-- ALU sign control --
|
||||
if (opcode(4) = '1') then -- ALU ops
|
||||
|
@ -685,13 +685,13 @@ begin
|
|||
|
||||
-- memory read/write access --
|
||||
if RISCV_ISA_Zalrsc and (opcode(2) = opcode_amo_c(2)) then -- atomic lr/sc
|
||||
ctrl_nxt.lsu_rw <= execute_engine.ir(instr_funct7_lsb_c+2);
|
||||
ctrl_nxt.lsu_rw <= exe_engine.ir(instr_funct7_lsb_c+2);
|
||||
else -- normal load/store
|
||||
ctrl_nxt.lsu_rw <= execute_engine.ir(5);
|
||||
ctrl_nxt.lsu_rw <= exe_engine.ir(5);
|
||||
end if;
|
||||
|
||||
-- state machine --
|
||||
case execute_engine.state is
|
||||
case exe_engine.state is
|
||||
|
||||
when DISPATCH => -- wait for ISSUE ENGINE to emit a valid instruction word
|
||||
-- ------------------------------------------------------------
|
||||
|
@ -699,37 +699,37 @@ begin
|
|||
ctrl_nxt.alu_opb_mux <= '1'; -- prepare update of next_pc in EXECUTE (opb = imm = +2/4)
|
||||
--
|
||||
if (trap_ctrl.env_pending = '1') or (trap_ctrl.exc_fire = '1') then -- pending trap or pending exception (fast)
|
||||
execute_engine.state_nxt <= TRAP_ENTER;
|
||||
exe_engine.state_nxt <= TRAP_ENTER;
|
||||
elsif RISCV_ISA_Sdtrig and (hw_trigger_match = '1') then -- hardware breakpoint
|
||||
execute_engine.pc_we <= '1'; -- pc <= next_pc; intercept BEFORE executing the instruction
|
||||
trap_ctrl.hwtrig <= '1';
|
||||
execute_engine.state_nxt <= DISPATCH; -- stay here another round until trap_ctrl.hwtrig arrives in trap_ctrl.env_pending
|
||||
exe_engine.pc_we <= '1'; -- pc <= next_pc; intercept BEFORE executing the instruction
|
||||
trap_ctrl.hwtrig <= '1';
|
||||
exe_engine.state_nxt <= DISPATCH; -- stay here another round until trap_ctrl.hwtrig arrives in trap_ctrl.env_pending
|
||||
elsif (issue_engine.valid(0) = '1') or (issue_engine.valid(1) = '1') then -- new instruction word available
|
||||
issue_engine.ack <= '1';
|
||||
trap_ctrl.instr_be <= issue_engine.data(32); -- access fault during instruction fetch
|
||||
execute_engine.is_ci_nxt <= issue_engine.data(33); -- this is a de-compressed instruction
|
||||
execute_engine.ir_nxt <= issue_engine.data(31 downto 0); -- instruction word
|
||||
execute_engine.pc_we <= '1'; -- pc <= next_pc
|
||||
execute_engine.state_nxt <= EXECUTE;
|
||||
issue_engine.ack <= '1';
|
||||
trap_ctrl.instr_be <= issue_engine.data(32); -- access fault during instruction fetch
|
||||
exe_engine.is_ci_nxt <= issue_engine.data(33); -- this is a de-compressed instruction
|
||||
exe_engine.ir_nxt <= issue_engine.data(31 downto 0); -- instruction word
|
||||
exe_engine.pc_we <= '1'; -- pc <= next_pc
|
||||
exe_engine.state_nxt <= EXECUTE;
|
||||
end if;
|
||||
|
||||
when TRAP_ENTER => -- enter trap environment and jump to trap vector
|
||||
-- ------------------------------------------------------------
|
||||
if (trap_ctrl.env_pending = '1') then -- wait for sync. exceptions to become pending
|
||||
trap_ctrl.env_enter <= '1';
|
||||
execute_engine.state_nxt <= RESTART;
|
||||
trap_ctrl.env_enter <= '1';
|
||||
exe_engine.state_nxt <= RESTART;
|
||||
end if;
|
||||
|
||||
when TRAP_EXIT => -- return from trap environment and jump to trap PC
|
||||
-- ------------------------------------------------------------
|
||||
trap_ctrl.env_exit <= '1';
|
||||
execute_engine.state_nxt <= RESTART;
|
||||
trap_ctrl.env_exit <= '1';
|
||||
exe_engine.state_nxt <= RESTART;
|
||||
|
||||
when RESTART => -- reset and restart instruction fetch at <next_pc>
|
||||
-- ------------------------------------------------------------
|
||||
ctrl_nxt.rf_zero_we <= not bool_to_ulogic_f(REGFILE_HW_RST); -- house keeping: force writing zero to x0 if it's a phys. register
|
||||
fetch_engine.reset <= '1';
|
||||
execute_engine.state_nxt <= BRANCHED;
|
||||
ctrl_nxt.rf_zero_we <= not bool_to_ulogic_f(REGFILE_HW_RST); -- house keeping: force writing zero to x0 if it's a phys. register
|
||||
fetch_engine.reset <= '1';
|
||||
exe_engine.state_nxt <= BRANCHED;
|
||||
|
||||
when EXECUTE => -- decode and execute instruction (control will be here for exactly 1 cycle in any case)
|
||||
-- [NOTE] register file is read in this stage; due to the sync read, data will be available in the _next_ state
|
||||
|
@ -741,77 +741,73 @@ begin
|
|||
|
||||
-- ALU core operation --
|
||||
case funct3_v is
|
||||
when funct3_subadd_c => ctrl_nxt.alu_op <= alu_op_add_c; -- ADD(I), SUB
|
||||
when funct3_slt_c => ctrl_nxt.alu_op <= alu_op_slt_c; -- SLT(I)
|
||||
when funct3_sltu_c => ctrl_nxt.alu_op <= alu_op_slt_c; -- SLTU(I)
|
||||
when funct3_xor_c => ctrl_nxt.alu_op <= alu_op_xor_c; -- XOR(I)
|
||||
when funct3_or_c => ctrl_nxt.alu_op <= alu_op_or_c; -- OR(I)
|
||||
when funct3_and_c => ctrl_nxt.alu_op <= alu_op_and_c; -- AND(I)
|
||||
when others => ctrl_nxt.alu_op <= alu_op_zero_c;
|
||||
when funct3_sadd_c => ctrl_nxt.alu_op <= alu_op_add_c; -- ADD(I), SUB
|
||||
when funct3_slt_c => ctrl_nxt.alu_op <= alu_op_slt_c; -- SLT(I)
|
||||
when funct3_sltu_c => ctrl_nxt.alu_op <= alu_op_slt_c; -- SLTU(I)
|
||||
when funct3_xor_c => ctrl_nxt.alu_op <= alu_op_xor_c; -- XOR(I)
|
||||
when funct3_or_c => ctrl_nxt.alu_op <= alu_op_or_c; -- OR(I)
|
||||
when funct3_and_c => ctrl_nxt.alu_op <= alu_op_and_c; -- AND(I)
|
||||
when others => ctrl_nxt.alu_op <= alu_op_zero_c;
|
||||
end case;
|
||||
|
||||
-- addition/subtraction control --
|
||||
if (funct3_v(2 downto 1) = funct3_slt_c(2 downto 1)) or -- SLT(I), SLTU(I)
|
||||
((funct3_v = funct3_subadd_c) and (opcode(5) = '1') and (execute_engine.ir(instr_funct7_msb_c-1) = '1')) then -- SUB
|
||||
((funct3_v = funct3_sadd_c) and (opcode(5) = '1') and (exe_engine.ir(instr_funct7_msb_c-1) = '1')) then -- SUB
|
||||
ctrl_nxt.alu_sub <= '1';
|
||||
end if;
|
||||
|
||||
-- is base rv32i/e ALU[I] instruction (excluding shifts)? --
|
||||
if ((opcode(5) = '0') and (funct3_v /= funct3_sll_c) and (funct3_v /= funct3_sr_c)) or -- base ALUI instruction (excluding SLLI, SRLI, SRAI)
|
||||
((opcode(5) = '1') and (((funct3_v = funct3_subadd_c) and (funct7_v = "0000000")) or
|
||||
((funct3_v = funct3_subadd_c) and (funct7_v = "0100000")) or
|
||||
((funct3_v = funct3_slt_c) and (funct7_v = "0000000")) or
|
||||
((funct3_v = funct3_sltu_c) and (funct7_v = "0000000")) or
|
||||
((funct3_v = funct3_xor_c) and (funct7_v = "0000000")) or
|
||||
((funct3_v = funct3_or_c) and (funct7_v = "0000000")) or
|
||||
((funct3_v = funct3_and_c) and (funct7_v = "0000000")) -- base ALU instruction (excluding SLL, SRL, SRA)?
|
||||
)) then
|
||||
ctrl_nxt.rf_wb_en <= '1'; -- valid RF write-back (won't happen if exception)
|
||||
execute_engine.state_nxt <= DISPATCH;
|
||||
((opcode(5) = '1') and (((funct3_v = funct3_sadd_c) and (funct7_v = "0000000")) or ((funct3_v = funct3_sadd_c) and (funct7_v = "0100000")) or
|
||||
((funct3_v = funct3_slt_c) and (funct7_v = "0000000")) or ((funct3_v = funct3_sltu_c) and (funct7_v = "0000000")) or
|
||||
((funct3_v = funct3_xor_c) and (funct7_v = "0000000")) or ((funct3_v = funct3_or_c) and (funct7_v = "0000000")) or
|
||||
((funct3_v = funct3_and_c) and (funct7_v = "0000000")))) then -- base ALU instruction (excluding SLL, SRL, SRA)?
|
||||
ctrl_nxt.rf_wb_en <= '1'; -- valid RF write-back (won't happen if exception)
|
||||
exe_engine.state_nxt <= DISPATCH;
|
||||
else -- [NOTE] potential illegal ALU[I] instruction are handled as multi-cycle operations that will time-out if no co-processor responds
|
||||
ctrl_nxt.alu_cp_alu <= '1'; -- trigger ALU[I] opcode-space co-processor
|
||||
execute_engine.state_nxt <= ALU_WAIT;
|
||||
ctrl_nxt.alu_cp_alu <= '1'; -- trigger ALU[I] opcode-space co-processor
|
||||
exe_engine.state_nxt <= ALU_WAIT;
|
||||
end if;
|
||||
|
||||
-- load upper immediate --
|
||||
when opcode_lui_c =>
|
||||
ctrl_nxt.alu_op <= alu_op_movb_c; -- pass immediate
|
||||
ctrl_nxt.rf_wb_en <= '1'; -- valid RF write-back (won't happen if exception)
|
||||
execute_engine.state_nxt <= DISPATCH;
|
||||
ctrl_nxt.alu_op <= alu_op_movb_c; -- pass immediate
|
||||
ctrl_nxt.rf_wb_en <= '1'; -- valid RF write-back (won't happen if exception)
|
||||
exe_engine.state_nxt <= DISPATCH;
|
||||
|
||||
-- add upper immediate to PC --
|
||||
when opcode_auipc_c =>
|
||||
ctrl_nxt.alu_op <= alu_op_add_c; -- add PC and immediate
|
||||
ctrl_nxt.rf_wb_en <= '1'; -- valid RF write-back (won't happen if exception)
|
||||
execute_engine.state_nxt <= DISPATCH;
|
||||
ctrl_nxt.alu_op <= alu_op_add_c; -- add PC and immediate
|
||||
ctrl_nxt.rf_wb_en <= '1'; -- valid RF write-back (won't happen if exception)
|
||||
exe_engine.state_nxt <= DISPATCH;
|
||||
|
||||
-- memory access --
|
||||
when opcode_load_c | opcode_store_c | opcode_amo_c =>
|
||||
execute_engine.state_nxt <= MEM_REQ;
|
||||
exe_engine.state_nxt <= MEM_REQ;
|
||||
|
||||
-- branch / jump-and-link (with register) --
|
||||
when opcode_branch_c | opcode_jal_c | opcode_jalr_c =>
|
||||
execute_engine.state_nxt <= BRANCH;
|
||||
exe_engine.state_nxt <= BRANCH;
|
||||
|
||||
-- memory fence operations (execute even if illegal funct3) --
|
||||
when opcode_fence_c =>
|
||||
ctrl_nxt.lsu_fence <= '1'; -- [NOTE] fence == fence.i; ignore all ordering bits
|
||||
execute_engine.state_nxt <= RESTART; -- reset instruction fetch + IPB (actually only required for fence.i)
|
||||
ctrl_nxt.lsu_fence <= '1'; -- [NOTE] fence == fence.i; ignore all ordering bits
|
||||
exe_engine.state_nxt <= RESTART; -- reset instruction fetch + IPB (actually only required for fence.i)
|
||||
|
||||
-- FPU: floating-point operations --
|
||||
when opcode_fop_c =>
|
||||
ctrl_nxt.alu_cp_fpu <= '1'; -- trigger FPU co-processor
|
||||
execute_engine.state_nxt <= ALU_WAIT; -- will be aborted via monitor timeout if FPU is not implemented
|
||||
ctrl_nxt.alu_cp_fpu <= '1'; -- trigger FPU co-processor
|
||||
exe_engine.state_nxt <= ALU_WAIT; -- will be aborted via monitor timeout if FPU is not implemented
|
||||
|
||||
-- CFU: custom RISC-V instructions --
|
||||
when opcode_cust0_c | opcode_cust1_c =>
|
||||
ctrl_nxt.alu_cp_cfu <= '1'; -- trigger CFU co-processor
|
||||
execute_engine.state_nxt <= ALU_WAIT; -- will be aborted via monitor timeout if CFU is not implemented
|
||||
ctrl_nxt.alu_cp_cfu <= '1'; -- trigger CFU co-processor
|
||||
exe_engine.state_nxt <= ALU_WAIT; -- will be aborted via monitor timeout if CFU is not implemented
|
||||
|
||||
-- environment/CSR operation or ILLEGAL opcode --
|
||||
when others =>
|
||||
csr.re_nxt <= '1';
|
||||
execute_engine.state_nxt <= SYSTEM;
|
||||
csr.re_nxt <= '1';
|
||||
exe_engine.state_nxt <= SYSTEM;
|
||||
|
||||
end case; -- /EXECUTE
|
||||
|
||||
|
@ -819,30 +815,30 @@ begin
|
|||
-- ------------------------------------------------------------
|
||||
ctrl_nxt.alu_op <= alu_op_cp_c;
|
||||
if (alu_cp_done_i = '1') or (trap_ctrl.exc_buf(exc_illegal_c) = '1') then
|
||||
ctrl_nxt.rf_wb_en <= '1'; -- valid RF write-back (won't happen if exception)
|
||||
execute_engine.state_nxt <= DISPATCH;
|
||||
ctrl_nxt.rf_wb_en <= '1'; -- valid RF write-back (won't happen if exception)
|
||||
exe_engine.state_nxt <= DISPATCH;
|
||||
end if;
|
||||
|
||||
when BRANCH => -- update next_pc on taken branches and jumps
|
||||
-- ------------------------------------------------------------
|
||||
ctrl_nxt.rf_wb_en <= opcode(2); -- save return address if link operation (won't happen if exception)
|
||||
if (trap_ctrl.exc_buf(exc_illegal_c) = '0') and (execute_engine.branch_taken = '1') then -- valid taken branch
|
||||
fetch_engine.reset <= '1'; -- reset instruction fetch to restart at modified PC
|
||||
execute_engine.state_nxt <= BRANCHED; -- shortcut (faster than going to RESTART)
|
||||
if (trap_ctrl.exc_buf(exc_illegal_c) = '0') and (exe_engine.branch_taken = '1') then -- valid taken branch
|
||||
fetch_engine.reset <= '1'; -- reset instruction fetch to restart at modified PC
|
||||
exe_engine.state_nxt <= BRANCHED; -- shortcut (faster than going to RESTART)
|
||||
else
|
||||
execute_engine.state_nxt <= DISPATCH;
|
||||
exe_engine.state_nxt <= DISPATCH;
|
||||
end if;
|
||||
|
||||
when BRANCHED => -- delay cycle to wait for reset of pipeline front-end (instruction fetch)
|
||||
-- ------------------------------------------------------------
|
||||
execute_engine.state_nxt <= DISPATCH;
|
||||
exe_engine.state_nxt <= DISPATCH;
|
||||
|
||||
when MEM_REQ => -- trigger memory request
|
||||
-- ------------------------------------------------------------
|
||||
if (trap_ctrl.exc_buf(exc_illegal_c) = '0') then -- memory request only if not an illegal instruction
|
||||
ctrl_nxt.lsu_req <= '1'; -- memory access request
|
||||
end if;
|
||||
execute_engine.state_nxt <= MEM_WAIT;
|
||||
exe_engine.state_nxt <= MEM_WAIT;
|
||||
|
||||
when MEM_WAIT => -- wait for bus transaction to finish
|
||||
-- ------------------------------------------------------------
|
||||
|
@ -853,29 +849,29 @@ begin
|
|||
if (RISCV_ISA_Zalrsc and (opcode(2) = opcode_amo_c(2))) or (opcode(5) = '0') then -- atomic operation / normal load
|
||||
ctrl_nxt.rf_wb_en <= '1'; -- allow write-back to register file (won't happen in case of exception)
|
||||
end if;
|
||||
execute_engine.state_nxt <= DISPATCH;
|
||||
exe_engine.state_nxt <= DISPATCH;
|
||||
end if;
|
||||
|
||||
when SLEEP => -- sleep mode
|
||||
-- ------------------------------------------------------------
|
||||
if (trap_ctrl.wakeup = '1') then
|
||||
execute_engine.state_nxt <= DISPATCH;
|
||||
exe_engine.state_nxt <= DISPATCH;
|
||||
end if;
|
||||
|
||||
when others => -- SYSTEM - CSR/ENVIRONMENT operation; no effect if illegal instruction
|
||||
-- ------------------------------------------------------------
|
||||
execute_engine.state_nxt <= DISPATCH; -- default
|
||||
exe_engine.state_nxt <= DISPATCH; -- default
|
||||
if (funct3_v = funct3_env_c) and (trap_ctrl.exc_buf(exc_illegal_c) = '0') then -- non-illegal ENVIRONMENT
|
||||
case execute_engine.ir(instr_funct12_lsb_c+2 downto instr_funct12_lsb_c) is -- three LSBs are sufficient here
|
||||
when "000" => trap_ctrl.ecall <= '1'; -- ecall
|
||||
when "001" => trap_ctrl.ebreak <= '1'; -- ebreak
|
||||
when "010" => execute_engine.state_nxt <= TRAP_EXIT; -- xret
|
||||
when "101" => execute_engine.state_nxt <= SLEEP; -- wfi
|
||||
when others => execute_engine.state_nxt <= DISPATCH; -- illegal or CSR operation
|
||||
case exe_engine.ir(instr_funct12_lsb_c+2 downto instr_funct12_lsb_c) is -- three LSBs are sufficient here
|
||||
when "000" => trap_ctrl.ecall <= '1'; -- ecall
|
||||
when "001" => trap_ctrl.ebreak <= '1'; -- ebreak
|
||||
when "010" => exe_engine.state_nxt <= TRAP_EXIT; -- xret
|
||||
when "101" => exe_engine.state_nxt <= SLEEP; -- wfi
|
||||
when others => exe_engine.state_nxt <= DISPATCH; -- illegal or CSR operation
|
||||
end case;
|
||||
end if;
|
||||
-- always write to CSR (if CSR instruction); ENVIRONMENT operations have rs1/imm5 = zero so this won't happen then --
|
||||
if (funct3_v = funct3_csrrw_c) or (funct3_v = funct3_csrrwi_c) or (execute_engine.ir(instr_rs1_msb_c downto instr_rs1_lsb_c) /= "00000") then
|
||||
if (funct3_v = funct3_csrrw_c) or (funct3_v = funct3_csrrwi_c) or (exe_engine.ir(instr_rs1_msb_c downto instr_rs1_lsb_c) /= "00000") then
|
||||
csr.we_nxt <= '1'; -- CSRRW[I]: always write CSR; CSRR[S/C][I]: write CSR if rs1/imm5 is NOT zero
|
||||
end if;
|
||||
-- always write to RF; ENVIRONMENT operations have rd = zero so this does not hurt --
|
||||
|
@ -890,9 +886,9 @@ begin
|
|||
|
||||
-- register file --
|
||||
ctrl_o.rf_wb_en <= ctrl.rf_wb_en and (not trap_ctrl.exc_fire); -- inhibit write-back if exception
|
||||
ctrl_o.rf_rs1 <= execute_engine.ir(instr_rs1_msb_c downto instr_rs1_lsb_c);
|
||||
ctrl_o.rf_rs2 <= execute_engine.ir(instr_rs2_msb_c downto instr_rs2_lsb_c);
|
||||
ctrl_o.rf_rd <= execute_engine.ir(instr_rd_msb_c downto instr_rd_lsb_c);
|
||||
ctrl_o.rf_rs1 <= exe_engine.ir(instr_rs1_msb_c downto instr_rs1_lsb_c);
|
||||
ctrl_o.rf_rs2 <= exe_engine.ir(instr_rs2_msb_c downto instr_rs2_lsb_c);
|
||||
ctrl_o.rf_rd <= exe_engine.ir(instr_rd_msb_c downto instr_rd_lsb_c);
|
||||
ctrl_o.rf_zero_we <= ctrl.rf_zero_we;
|
||||
-- alu --
|
||||
ctrl_o.alu_op <= ctrl.alu_op;
|
||||
|
@ -906,18 +902,18 @@ begin
|
|||
-- load/store unit --
|
||||
ctrl_o.lsu_req <= ctrl.lsu_req;
|
||||
ctrl_o.lsu_rw <= ctrl.lsu_rw;
|
||||
ctrl_o.lsu_mo_we <= '1' when (execute_engine.state = MEM_REQ) else '0'; -- write memory output registers (data & address)
|
||||
ctrl_o.lsu_mo_we <= '1' when (exe_engine.state = MEM_REQ) else '0'; -- write memory output registers (data & address)
|
||||
ctrl_o.lsu_fence <= ctrl.lsu_fence;
|
||||
ctrl_o.lsu_priv <= csr.mstatus_mpp when (csr.mstatus_mprv = '1') else csr.privilege_eff; -- effective privilege level for loads/stores in M-mode
|
||||
-- instruction word bit fields --
|
||||
ctrl_o.ir_funct3 <= execute_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c);
|
||||
ctrl_o.ir_funct12 <= execute_engine.ir(instr_funct12_msb_c downto instr_funct12_lsb_c);
|
||||
ctrl_o.ir_funct3 <= exe_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c);
|
||||
ctrl_o.ir_funct12 <= exe_engine.ir(instr_funct12_msb_c downto instr_funct12_lsb_c);
|
||||
ctrl_o.ir_opcode <= opcode;
|
||||
-- cpu status --
|
||||
ctrl_o.cpu_priv <= csr.privilege_eff;
|
||||
ctrl_o.cpu_sleep <= sleep_mode;
|
||||
ctrl_o.cpu_trap <= trap_ctrl.env_enter;
|
||||
ctrl_o.cpu_debug <= debug_ctrl.running;
|
||||
ctrl_o.cpu_debug <= debug_ctrl.run;
|
||||
|
||||
|
||||
-- ****************************************************************************************************************************
|
||||
|
@ -936,7 +932,7 @@ begin
|
|||
end process multi_cycle_monitor;
|
||||
|
||||
-- timeout counter (allow mapping of entire logic into the LUTs in front of the carry-chain) --
|
||||
monitor.cnt_add <= monitor.cnt when (execute_engine.state = ALU_WAIT) else (others => '0');
|
||||
monitor.cnt_add <= monitor.cnt when (exe_engine.state = ALU_WAIT) else (others => '0');
|
||||
|
||||
-- raise illegal instruction exception if a multi-cycle instruction takes longer than a bound amount of time --
|
||||
monitor.exc <= monitor.cnt(monitor.cnt'left);
|
||||
|
@ -944,11 +940,11 @@ begin
|
|||
|
||||
-- CSR Access Check -----------------------------------------------------------------------
|
||||
-- -------------------------------------------------------------------------------------------
|
||||
csr_check: process(execute_engine.ir, debug_ctrl.running, csr)
|
||||
csr_check: process(exe_engine.ir, debug_ctrl.run, csr)
|
||||
variable csr_addr_v : std_ulogic_vector(11 downto 0);
|
||||
begin
|
||||
-- CSR address right from the instruction word --
|
||||
csr_addr_v := execute_engine.ir(instr_imm12_msb_c downto instr_imm12_lsb_c);
|
||||
-- shortcut: CSR address right from the instruction word --
|
||||
csr_addr_v := exe_engine.ir(instr_imm12_msb_c downto instr_imm12_lsb_c);
|
||||
|
||||
-- ------------------------------------------------------------
|
||||
-- Available at all
|
||||
|
@ -1015,9 +1011,9 @@ begin
|
|||
-- R/W capabilities
|
||||
-- ------------------------------------------------------------
|
||||
if (csr_addr_v(11 downto 10) = "11") and -- CSR is read-only
|
||||
((execute_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or -- will always write to CSR
|
||||
(execute_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) or -- will always write to CSR
|
||||
(execute_engine.ir(instr_rs1_msb_c downto instr_rs1_lsb_c) /= "00000")) then -- clear/set instructions: write to CSR only if rs1/imm5 is NOT zero
|
||||
((exe_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or -- will always write to CSR
|
||||
(exe_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) or -- will always write to CSR
|
||||
(exe_engine.ir(instr_rs1_msb_c downto instr_rs1_lsb_c) /= "00000")) then -- clear/set instructions: write to CSR only if rs1/imm5 is NOT zero
|
||||
csr_valid(1) <= '0'; -- invalid access
|
||||
else
|
||||
csr_valid(1) <= '1'; -- access granted
|
||||
|
@ -1027,7 +1023,7 @@ begin
|
|||
-- Privilege level
|
||||
-- ------------------------------------------------------------
|
||||
if (csr_addr_v(11 downto 2) = csr_dcsr_c(11 downto 2)) and -- debug-mode-only CSR (dcsr, dpc, dscratch)?
|
||||
RISCV_ISA_Sdext and (debug_ctrl.running = '0') then -- debug-mode implemented and not running?
|
||||
RISCV_ISA_Sdext and (debug_ctrl.run = '0') then -- debug-mode implemented and not running?
|
||||
csr_valid(0) <= '0'; -- invalid access
|
||||
elsif RISCV_ISA_Zicntr and RISCV_ISA_U and (csr.privilege_eff = '0') and -- any user-mode counters available and in user-mode?
|
||||
(csr_addr_v(11 downto 8) = csr_cycle_c(11 downto 8)) and -- user-mode counter access
|
||||
|
@ -1045,40 +1041,40 @@ begin
|
|||
|
||||
-- Illegal Instruction Check --------------------------------------------------------------
|
||||
-- -------------------------------------------------------------------------------------------
|
||||
illegal_check: process(execute_engine, csr, csr_valid, debug_ctrl)
|
||||
illegal_check: process(exe_engine, csr, csr_valid, debug_ctrl)
|
||||
begin
|
||||
case execute_engine.ir(instr_opcode_msb_c downto instr_opcode_lsb_c) is -- check entire opcode
|
||||
case exe_engine.ir(instr_opcode_msb_c downto instr_opcode_lsb_c) is -- check entire opcode
|
||||
|
||||
when opcode_lui_c | opcode_auipc_c | opcode_jal_c => -- U-instruction type
|
||||
illegal_cmd <= '0'; -- all encodings are valid
|
||||
|
||||
when opcode_jalr_c => -- unconditional jump-and-link
|
||||
case execute_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) is
|
||||
case exe_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) is
|
||||
when "000" => illegal_cmd <= '0';
|
||||
when others => illegal_cmd <= '1';
|
||||
end case;
|
||||
|
||||
when opcode_branch_c => -- conditional branch
|
||||
case execute_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) is
|
||||
case exe_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) is
|
||||
when funct3_beq_c | funct3_bne_c | funct3_blt_c | funct3_bge_c | funct3_bltu_c | funct3_bgeu_c => illegal_cmd <= '0';
|
||||
when others => illegal_cmd <= '1';
|
||||
end case;
|
||||
|
||||
when opcode_load_c => -- memory load
|
||||
case execute_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) is
|
||||
case exe_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) is
|
||||
when funct3_lb_c | funct3_lh_c | funct3_lw_c | funct3_lbu_c | funct3_lhu_c => illegal_cmd <= '0';
|
||||
when others => illegal_cmd <= '1';
|
||||
end case;
|
||||
|
||||
when opcode_store_c => -- memory store
|
||||
case execute_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) is
|
||||
case exe_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) is
|
||||
when funct3_sb_c | funct3_sh_c | funct3_sw_c => illegal_cmd <= '0';
|
||||
when others => illegal_cmd <= '1';
|
||||
end case;
|
||||
|
||||
when opcode_amo_c => -- atomic memory operation (LR/SC)
|
||||
if RISCV_ISA_Zalrsc and (execute_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) = "010") and
|
||||
(execute_engine.ir(instr_funct7_lsb_c+6 downto instr_funct7_lsb_c+3) = "0001") then -- LR.W/SC.W
|
||||
if RISCV_ISA_Zalrsc and (exe_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) = "010") and
|
||||
(exe_engine.ir(instr_funct7_lsb_c+6 downto instr_funct7_lsb_c+3) = "0001") then -- LR.W/SC.W
|
||||
illegal_cmd <= '0';
|
||||
else
|
||||
illegal_cmd <= '1';
|
||||
|
@ -1088,25 +1084,26 @@ begin
|
|||
illegal_cmd <= '0'; -- [NOTE] valid if not terminated by the "instruction execution monitor"
|
||||
|
||||
when opcode_fence_c => -- memory ordering
|
||||
case execute_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) is
|
||||
case exe_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) is
|
||||
when funct3_fence_c | funct3_fencei_c => illegal_cmd <= '0';
|
||||
when others => illegal_cmd <= '1';
|
||||
end case;
|
||||
|
||||
when opcode_system_c => -- CSR / system instruction
|
||||
if (execute_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_env_c) then -- system environment
|
||||
if (execute_engine.ir(instr_rs1_msb_c downto instr_rs1_lsb_c) = "00000") and (execute_engine.ir(instr_rd_msb_c downto instr_rd_lsb_c) = "00000") then
|
||||
case execute_engine.ir(instr_funct12_msb_c downto instr_funct12_lsb_c) is
|
||||
when funct12_ecall_c | funct12_ebreak_c => illegal_cmd <= '0'; -- ecall and ebreak are always allowed
|
||||
when funct12_mret_c => illegal_cmd <= (not csr.privilege) or debug_ctrl.running; -- mret allowed in (real/non-debug) M-mode only
|
||||
when funct12_dret_c => illegal_cmd <= not debug_ctrl.running; -- dret allowed in debug mode only
|
||||
when funct12_wfi_c => illegal_cmd <= (not csr.privilege) and csr.mstatus_tw; -- wfi allowed in M-mode or if TW is zero
|
||||
when others => illegal_cmd <= '1'; -- undefined
|
||||
if (exe_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_env_c) then -- system environment
|
||||
if (exe_engine.ir(instr_rs1_msb_c downto instr_rs1_lsb_c) = "00000") and (exe_engine.ir(instr_rd_msb_c downto instr_rd_lsb_c) = "00000") then
|
||||
case exe_engine.ir(instr_funct12_msb_c downto instr_funct12_lsb_c) is
|
||||
when funct12_ecall_c => illegal_cmd <= '0'; -- ecall is always allowed
|
||||
when funct12_ebreak_c => illegal_cmd <= '0'; -- ebreak is always allowed
|
||||
when funct12_mret_c => illegal_cmd <= (not csr.privilege) or debug_ctrl.run; -- mret allowed in (real/non-debug) M-mode only
|
||||
when funct12_dret_c => illegal_cmd <= not debug_ctrl.run; -- dret allowed in debug mode only
|
||||
when funct12_wfi_c => illegal_cmd <= (not csr.privilege) and csr.mstatus_tw; -- wfi allowed in M-mode or if TW is zero
|
||||
when others => illegal_cmd <= '1'; -- undefined
|
||||
end case;
|
||||
else
|
||||
illegal_cmd <= '1';
|
||||
end if;
|
||||
elsif (csr_valid /= "111") or (execute_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csril_c) then -- invalid CSR operation
|
||||
elsif (csr_valid /= "111") or (exe_engine.ir(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csril_c) then -- invalid CSR operation
|
||||
illegal_cmd <= '1';
|
||||
else
|
||||
illegal_cmd <= '0';
|
||||
|
@ -1121,7 +1118,7 @@ begin
|
|||
|
||||
-- Illegal Operation Check ----------------------------------------------------------------
|
||||
-- -------------------------------------------------------------------------------------------
|
||||
trap_ctrl.instr_il <= '1' when ((execute_engine.state = EXECUTE) or (execute_engine.state = ALU_WAIT)) and -- check in execution states only
|
||||
trap_ctrl.instr_il <= '1' when ((exe_engine.state = EXECUTE) or (exe_engine.state = ALU_WAIT)) and -- check in execution states only
|
||||
((monitor.exc = '1') or (illegal_cmd = '1')) else '0'; -- instruction timeout or illegal instruction
|
||||
|
||||
|
||||
|
@ -1162,8 +1159,8 @@ begin
|
|||
if RISCV_ISA_Sdext then
|
||||
trap_ctrl.exc_buf(exc_ebreak_c) <= (not trap_ctrl.env_enter) and (trap_ctrl.exc_buf(exc_ebreak_c) or
|
||||
(trap_ctrl.hwtrig and (not csr.tdata1_action)) or -- trigger module fires and enter-debug-action is disabled
|
||||
(trap_ctrl.ebreak and ( csr.privilege) and (not csr.dcsr_ebreakm) and (not debug_ctrl.running)) or -- enter M-mode handler on ebreak in M-mode
|
||||
(trap_ctrl.ebreak and (not csr.privilege) and (not csr.dcsr_ebreaku) and (not debug_ctrl.running))); -- enter M-mode handler on ebreak in U-mode
|
||||
(trap_ctrl.ebreak and ( csr.privilege) and (not csr.dcsr_ebreakm) and (not debug_ctrl.run)) or -- enter M-mode handler on ebreak in M-mode
|
||||
(trap_ctrl.ebreak and (not csr.privilege) and (not csr.dcsr_ebreaku) and (not debug_ctrl.run))); -- enter M-mode handler on ebreak in U-mode
|
||||
else
|
||||
trap_ctrl.exc_buf(exc_ebreak_c) <= (trap_ctrl.exc_buf(exc_ebreak_c) or trap_ctrl.ebreak or (trap_ctrl.hwtrig and (not csr.tdata1_action))) and (not trap_ctrl.env_enter);
|
||||
end if;
|
||||
|
@ -1273,7 +1270,7 @@ begin
|
|||
end process trap_priority;
|
||||
|
||||
-- exception program counter: async. interrupt or sync. exception? --
|
||||
trap_ctrl.epc <= execute_engine.next_pc when (trap_ctrl.cause(trap_ctrl.cause'left) = '1') else execute_engine.pc;
|
||||
trap_ctrl.epc <= exe_engine.next_pc when (trap_ctrl.cause(trap_ctrl.cause'left) = '1') else exe_engine.pc;
|
||||
|
||||
|
||||
-- Trap Controller ------------------------------------------------------------------------
|
||||
|
@ -1295,7 +1292,7 @@ begin
|
|||
end if;
|
||||
end if;
|
||||
-- trap environment has just been entered --
|
||||
if (execute_engine.state = EXECUTE) then -- first instruction of trap environment is executing
|
||||
if (exe_engine.state = EXECUTE) then -- first instruction of trap environment is executing
|
||||
trap_ctrl.env_entered <= '0';
|
||||
elsif (trap_ctrl.env_enter = '1') then
|
||||
trap_ctrl.env_entered <= '1';
|
||||
|
@ -1306,26 +1303,23 @@ begin
|
|||
-- any exception? --
|
||||
trap_ctrl.exc_fire <= '1' when (or_reduce_f(trap_ctrl.exc_buf) = '1') else '0'; -- sync. exceptions CANNOT be masked
|
||||
|
||||
-- any "normal" system interrupt? --
|
||||
-- system interrupt? --
|
||||
trap_ctrl.irq_fire(0) <= '1' when
|
||||
(execute_engine.state = EXECUTE) and -- trigger system IRQ only in EXECUTE state
|
||||
(exe_engine.state = EXECUTE) and -- trigger system IRQ only in EXECUTE state
|
||||
(or_reduce_f(trap_ctrl.irq_buf(irq_firq_15_c downto irq_msi_irq_c)) = '1') and -- pending system IRQ
|
||||
((csr.mstatus_mie = '1') or (csr.privilege = priv_mode_u_c)) and -- IRQ only when in M-mode and MIE=1 OR when in U-mode
|
||||
(debug_ctrl.running = '0') and (csr.dcsr_step = '0') -- no system IRQs when in debug-mode / during single-stepping
|
||||
else '0';
|
||||
(debug_ctrl.run = '0') and (csr.dcsr_step = '0') else '0'; -- no system IRQs when in debug-mode / during single-stepping
|
||||
|
||||
-- debug-entry halt interrupt? --
|
||||
trap_ctrl.irq_fire(1) <= '1' when
|
||||
((execute_engine.state = EXECUTE) or (execute_engine.state = BRANCHED)) and -- allow halt also after "reset" (#879)
|
||||
(trap_ctrl.irq_buf(irq_db_halt_c) = '1') -- pending external halt
|
||||
else '0';
|
||||
((exe_engine.state = EXECUTE) or (exe_engine.state = BRANCHED)) and -- allow halt also after "reset" (#879)
|
||||
(trap_ctrl.irq_buf(irq_db_halt_c) = '1') else '0'; -- pending external halt
|
||||
|
||||
-- debug-entry single-step interrupt? --
|
||||
trap_ctrl.irq_fire(2) <= '1' when
|
||||
((execute_engine.state = EXECUTE) or -- trigger single-step in EXECUTE state
|
||||
((trap_ctrl.env_entered = '1') and (execute_engine.state = BRANCHED))) and -- also allow triggering when entering a system trap (#887)
|
||||
(trap_ctrl.irq_buf(irq_db_step_c) = '1') -- pending single-step halt
|
||||
else '0';
|
||||
((exe_engine.state = EXECUTE) or -- trigger single-step in EXECUTE state
|
||||
((trap_ctrl.env_entered = '1') and (exe_engine.state = BRANCHED))) and -- also allow triggering when entering a system trap (#887)
|
||||
(trap_ctrl.irq_buf(irq_db_step_c) = '1') else '0'; -- pending single-step halt
|
||||
|
||||
|
||||
-- CPU Sleep Mode Control -----------------------------------------------------------------
|
||||
|
@ -1335,7 +1329,7 @@ begin
|
|||
if (rstn_i = '0') then
|
||||
sleep_mode <= '0';
|
||||
elsif rising_edge(clk_aux_i) then
|
||||
if (execute_engine.state = SLEEP) and -- instruction execution has halted
|
||||
if (exe_engine.state = SLEEP) and -- instruction execution has halted
|
||||
(ipb.free /= "11") and -- instruction fetch has halted
|
||||
(trap_ctrl.wakeup = '0') then -- no wake-up request
|
||||
sleep_mode <= '1';
|
||||
|
@ -1346,7 +1340,7 @@ begin
|
|||
end process sleep_control;
|
||||
|
||||
-- wake-up from / do not enter sleep mode: during debugging or on pending IRQ --
|
||||
trap_ctrl.wakeup <= or_reduce_f(trap_ctrl.irq_buf) or debug_ctrl.running or csr.dcsr_step;
|
||||
trap_ctrl.wakeup <= or_reduce_f(trap_ctrl.irq_buf) or debug_ctrl.run or csr.dcsr_step;
|
||||
|
||||
|
||||
-- ****************************************************************************************************************************
|
||||
|
@ -1362,9 +1356,9 @@ begin
|
|||
elsif rising_edge(clk_i) then
|
||||
-- update only for actual CSR operations to reduce switching activity on the CSR address net --
|
||||
if (opcode = opcode_system_c) then
|
||||
csr.addr(11 downto 10) <= execute_engine.ir(instr_imm12_lsb_c+11 downto instr_imm12_lsb_c+10);
|
||||
csr.addr(9 downto 8) <= replicate_f(execute_engine.ir(instr_imm12_lsb_c+8), 2); -- M-mode (11) and U-mode (00) CSRs only
|
||||
csr.addr(7 downto 0) <= execute_engine.ir(instr_imm12_lsb_c+7 downto instr_imm12_lsb_c);
|
||||
csr.addr(11 downto 10) <= exe_engine.ir(instr_imm12_lsb_c+11 downto instr_imm12_lsb_c+10);
|
||||
csr.addr(9 downto 8) <= replicate_f(exe_engine.ir(instr_imm12_lsb_c+8), 2); -- M-mode (11) and U-mode (00) CSRs only
|
||||
csr.addr(7 downto 0) <= exe_engine.ir(instr_imm12_lsb_c+7 downto instr_imm12_lsb_c);
|
||||
end if;
|
||||
end if;
|
||||
end process csr_addr_reg;
|
||||
|
@ -1372,18 +1366,18 @@ begin
|
|||
|
||||
-- CSR Write-Data ALU ---------------------------------------------------------------------
|
||||
-- -------------------------------------------------------------------------------------------
|
||||
csr_write_data: process(execute_engine.ir, csr.rdata, rf_rs1_i)
|
||||
csr_write_data: process(exe_engine.ir, csr.rdata, rf_rs1_i)
|
||||
variable tmp_v : std_ulogic_vector(XLEN-1 downto 0);
|
||||
begin
|
||||
-- immediate/register operand --
|
||||
if (execute_engine.ir(instr_funct3_msb_c) = '1') then
|
||||
if (exe_engine.ir(instr_funct3_msb_c) = '1') then
|
||||
tmp_v := (others => '0');
|
||||
tmp_v(4 downto 0) := execute_engine.ir(19 downto 15); -- uimm5
|
||||
tmp_v(4 downto 0) := exe_engine.ir(19 downto 15); -- uimm5
|
||||
else
|
||||
tmp_v := rf_rs1_i;
|
||||
end if;
|
||||
-- tiny ALU to compute CSR write data --
|
||||
case execute_engine.ir(instr_funct3_msb_c-1 downto instr_funct3_lsb_c) is
|
||||
case exe_engine.ir(instr_funct3_msb_c-1 downto instr_funct3_lsb_c) is
|
||||
when "10" => csr.wdata <= csr.rdata or tmp_v; -- set
|
||||
when "11" => csr.wdata <= csr.rdata and (not tmp_v); -- clear
|
||||
when others => csr.wdata <= tmp_v; -- write
|
||||
|
@ -1530,18 +1524,18 @@ begin
|
|||
-- --------------------------------------------------------------------
|
||||
when csr_tdata1_c => -- match control
|
||||
if RISCV_ISA_Sdtrig then
|
||||
if (csr.tdata1_dmode = '0') or (debug_ctrl.running = '1') then -- write access from debug-mode only?
|
||||
if (csr.tdata1_dmode = '0') or (debug_ctrl.run = '1') then -- write access from debug-mode only?
|
||||
csr.tdata1_execute <= csr.wdata(2);
|
||||
csr.tdata1_action <= csr.wdata(12);
|
||||
end if;
|
||||
if (debug_ctrl.running = '1') then -- writable from debug-mode only
|
||||
if (debug_ctrl.run = '1') then -- writable from debug-mode only
|
||||
csr.tdata1_dmode <= csr.wdata(27);
|
||||
end if;
|
||||
end if;
|
||||
|
||||
when csr_tdata2_c => -- address compare
|
||||
if RISCV_ISA_Sdtrig then
|
||||
if (csr.tdata1_dmode = '0') or (debug_ctrl.running = '1') then -- write access from debug-mode only?
|
||||
if (csr.tdata1_dmode = '0') or (debug_ctrl.run = '1') then -- write access from debug-mode only?
|
||||
csr.tdata2 <= csr.wdata(XLEN-1 downto 1) & '0';
|
||||
end if;
|
||||
end if;
|
||||
|
@ -1559,10 +1553,10 @@ begin
|
|||
elsif (trap_ctrl.env_enter = '1') then
|
||||
|
||||
-- NORMAL trap entry - no CSR update when in debug-mode! --
|
||||
if (not RISCV_ISA_Sdext) or ((trap_ctrl.cause(5) = '0') and (debug_ctrl.running = '0')) then
|
||||
if (not RISCV_ISA_Sdext) or ((trap_ctrl.cause(5) = '0') and (debug_ctrl.run = '0')) then
|
||||
csr.mcause <= trap_ctrl.cause(trap_ctrl.cause'left) & trap_ctrl.cause(4 downto 0); -- trap type & identifier
|
||||
csr.mepc <= trap_ctrl.epc(XLEN-1 downto 1) & '0'; -- trap PC
|
||||
-- trap value --
|
||||
-- trap value (load/store trap address only, permitted by RISC-V priv. spec.) --
|
||||
if (trap_ctrl.cause(6) = '0') and (trap_ctrl.cause(2) = '1') then -- load/store misaligned/access faults [hacky!]
|
||||
csr.mtval <= lsu_mar_i; -- faulting data access address
|
||||
else -- everything else including all interrupts
|
||||
|
@ -1570,8 +1564,8 @@ begin
|
|||
end if;
|
||||
-- trap instruction --
|
||||
if (trap_ctrl.cause(6) = '0') then -- exception
|
||||
csr.mtinst <= execute_engine.ir;
|
||||
if (execute_engine.is_ci = '1') and RISCV_ISA_C then
|
||||
csr.mtinst <= exe_engine.ir;
|
||||
if (exe_engine.is_ci = '1') and RISCV_ISA_C then
|
||||
csr.mtinst(1) <= '0'; -- RISC-V priv. spec: clear bit 1 if compressed instruction
|
||||
end if;
|
||||
else -- interrupt
|
||||
|
@ -1584,8 +1578,8 @@ begin
|
|||
csr.mstatus_mpp <= csr.privilege; -- backup previous privilege mode
|
||||
end if;
|
||||
|
||||
-- DEBUG MODE entry - no CSR update when already in debug-mode! --
|
||||
if RISCV_ISA_Sdext and (trap_ctrl.cause(5) = '1') and (debug_ctrl.running = '0') then
|
||||
-- DEBUG trap entry - no CSR update when already in debug-mode! --
|
||||
if RISCV_ISA_Sdext and (trap_ctrl.cause(5) = '1') and (debug_ctrl.run = '0') then
|
||||
csr.dcsr_cause <= trap_ctrl.cause(2 downto 0); -- trap cause
|
||||
csr.dcsr_prv <= csr.privilege; -- current privilege mode when debug mode was entered
|
||||
csr.dpc <= trap_ctrl.epc(XLEN-1 downto 1) & '0'; -- trap PC
|
||||
|
@ -1597,7 +1591,7 @@ begin
|
|||
elsif (trap_ctrl.env_exit = '1') then
|
||||
|
||||
-- return from debug mode --
|
||||
if RISCV_ISA_Sdext and (debug_ctrl.running = '1') then
|
||||
if RISCV_ISA_Sdext and (debug_ctrl.run = '1') then
|
||||
if RISCV_ISA_U then
|
||||
csr.privilege <= csr.dcsr_prv;
|
||||
if (csr.dcsr_prv /= priv_mode_m_c) then
|
||||
|
@ -1624,7 +1618,7 @@ begin
|
|||
-- ********************************************************************************
|
||||
|
||||
-- hardwired bits --
|
||||
csr.mcountinhibit(1) <= '0'; -- "time" not implemented
|
||||
csr.mcountinhibit(1) <= '0'; -- "time" not defined
|
||||
|
||||
-- no base counters --
|
||||
if not RISCV_ISA_Zicntr then
|
||||
|
@ -1677,7 +1671,7 @@ begin
|
|||
end process csr_write_access;
|
||||
|
||||
-- effective privilege mode is MACHINE when in debug mode --
|
||||
csr.privilege_eff <= priv_mode_m_c when (debug_ctrl.running = '1') else csr.privilege;
|
||||
csr.privilege_eff <= priv_mode_m_c when (debug_ctrl.run = '1') else csr.privilege;
|
||||
|
||||
|
||||
-- CSR Read Access ------------------------------------------------------------------------
|
||||
|
@ -1911,9 +1905,8 @@ begin
|
|||
csr.rdata(23) <= bool_to_ulogic_f(RISCV_ISA_Zbb); -- Zbb: basic bit-manipulation extension
|
||||
csr.rdata(24) <= bool_to_ulogic_f(RISCV_ISA_Zbs); -- Zbs: single-bit bit-manipulation extension
|
||||
csr.rdata(25) <= bool_to_ulogic_f(RISCV_ISA_Zalrsc); -- Zalrsc: reservation set extension
|
||||
-- reserved --
|
||||
csr.rdata(26) <= '0';
|
||||
csr.rdata(27) <= '0';
|
||||
csr.rdata(26) <= '0'; -- reserved
|
||||
csr.rdata(27) <= '0'; -- reserved
|
||||
-- tuning options --
|
||||
csr.rdata(28) <= bool_to_ulogic_f(REGFILE_HW_RST); -- full hardware reset of register file
|
||||
csr.rdata(29) <= bool_to_ulogic_f(FAST_MUL_EN); -- DSP-based multiplication (M extensions only)
|
||||
|
@ -2075,31 +2068,31 @@ begin
|
|||
cnt.inc <= (others => (others => '0'));
|
||||
elsif rising_edge(clk_i) then
|
||||
-- base counters --
|
||||
cnt.inc(0) <= (others => (cnt_event(hpmcnt_event_cy_c) and (not csr.mcountinhibit(0)) and (not debug_ctrl.running)));
|
||||
cnt.inc(0) <= (others => (cnt_event(hpmcnt_event_cy_c) and (not csr.mcountinhibit(0)) and (not debug_ctrl.run)));
|
||||
cnt.inc(1) <= (others => '0'); -- time: not available
|
||||
cnt.inc(2) <= (others => (cnt_event(hpmcnt_event_ir_c) and (not csr.mcountinhibit(2)) and (not debug_ctrl.running)));
|
||||
cnt.inc(2) <= (others => (cnt_event(hpmcnt_event_ir_c) and (not csr.mcountinhibit(2)) and (not debug_ctrl.run)));
|
||||
-- hpm counters --
|
||||
for i in 3 to 15 loop
|
||||
cnt.inc(i) <= (others => (or_reduce_f(cnt_event and hpmevent_cfg(i)) and (not csr.mcountinhibit(i)) and (not debug_ctrl.running)));
|
||||
cnt.inc(i) <= (others => (or_reduce_f(cnt_event and hpmevent_cfg(i)) and (not csr.mcountinhibit(i)) and (not debug_ctrl.run)));
|
||||
end loop;
|
||||
end if;
|
||||
end process counter_event;
|
||||
|
||||
-- RISC-V-compliant counter events --
|
||||
cnt_event(hpmcnt_event_cy_c) <= '1' when (sleep_mode = '0') else '0'; -- cycle: active cycle
|
||||
cnt_event(hpmcnt_event_tm_c) <= '0'; -- time: not available
|
||||
cnt_event(hpmcnt_event_ir_c) <= '1' when (execute_engine.state = EXECUTE) else '0'; -- instret: retired (==executed) instruction
|
||||
cnt_event(hpmcnt_event_cy_c) <= '1' when (sleep_mode = '0') else '0'; -- cycle: active cycle
|
||||
cnt_event(hpmcnt_event_tm_c) <= '0'; -- time: not available
|
||||
cnt_event(hpmcnt_event_ir_c) <= '1' when (exe_engine.state = EXECUTE) else '0'; -- instret: retired (==executed!) instruction
|
||||
|
||||
-- NEORV32-specific counter events --
|
||||
cnt_event(hpmcnt_event_compr_c) <= '1' when (execute_engine.state = EXECUTE) and (execute_engine.is_ci = '1') else '0'; -- executed compressed instruction
|
||||
cnt_event(hpmcnt_event_wait_dis_c) <= '1' when (execute_engine.state = DISPATCH) and (issue_engine.valid = "00") else '0'; -- instruction dispatch wait cycle
|
||||
cnt_event(hpmcnt_event_wait_alu_c) <= '1' when (execute_engine.state = ALU_WAIT) else '0'; -- multi-cycle ALU co-processor wait cycle
|
||||
cnt_event(hpmcnt_event_branch_c) <= '1' when (execute_engine.state = BRANCH) else '0'; -- executed branch instruction
|
||||
cnt_event(hpmcnt_event_branched_c) <= '1' when (execute_engine.state = BRANCHED) else '0'; -- control flow transfer
|
||||
cnt_event(hpmcnt_event_load_c) <= '1' when (ctrl.lsu_req = '1') and (ctrl.lsu_rw = '0') else '0'; -- executed load operation
|
||||
cnt_event(hpmcnt_event_store_c) <= '1' when (ctrl.lsu_req = '1') and (ctrl.lsu_rw = '1') else '0'; -- executed store operation
|
||||
cnt_event(hpmcnt_event_wait_lsu_c) <= '1' when (ctrl.lsu_req = '0') and (execute_engine.state = MEM_WAIT) else '0'; -- load/store unit memory wait cycle
|
||||
cnt_event(hpmcnt_event_trap_c) <= '1' when (trap_ctrl.env_enter = '1') else '0'; -- entered trap
|
||||
cnt_event(hpmcnt_event_compr_c) <= '1' when (exe_engine.state = EXECUTE) and (exe_engine.is_ci = '1') else '0'; -- executed compressed instruction
|
||||
cnt_event(hpmcnt_event_wait_dis_c) <= '1' when (exe_engine.state = DISPATCH) and (issue_engine.valid = "00") else '0'; -- instruction dispatch wait cycle
|
||||
cnt_event(hpmcnt_event_wait_alu_c) <= '1' when (exe_engine.state = ALU_WAIT) else '0'; -- multi-cycle ALU co-processor wait cycle
|
||||
cnt_event(hpmcnt_event_branch_c) <= '1' when (exe_engine.state = BRANCH) else '0'; -- executed branch instruction
|
||||
cnt_event(hpmcnt_event_branched_c) <= '1' when (exe_engine.state = BRANCHED) else '0'; -- control flow transfer
|
||||
cnt_event(hpmcnt_event_load_c) <= '1' when (ctrl.lsu_req = '1') and (ctrl.lsu_rw = '0') else '0'; -- executed load operation
|
||||
cnt_event(hpmcnt_event_store_c) <= '1' when (ctrl.lsu_req = '1') and (ctrl.lsu_rw = '1') else '0'; -- executed store operation
|
||||
cnt_event(hpmcnt_event_wait_lsu_c) <= '1' when (ctrl.lsu_req = '0') and (exe_engine.state = MEM_WAIT) else '0'; -- load/store unit memory wait cycle
|
||||
cnt_event(hpmcnt_event_trap_c) <= '1' when (trap_ctrl.env_enter = '1') else '0'; -- entered trap
|
||||
|
||||
|
||||
-- ****************************************************************************************************************************
|
||||
|
@ -2114,34 +2107,34 @@ begin
|
|||
debug_control: process(rstn_i, clk_i)
|
||||
begin
|
||||
if (rstn_i = '0') then
|
||||
debug_ctrl.running <= '0';
|
||||
debug_ctrl.run <= '0';
|
||||
elsif rising_edge(clk_i) then
|
||||
if (debug_ctrl.running = '0') then -- debug mode OFFLINE
|
||||
if (debug_ctrl.run = '0') then -- debug mode OFFLINE
|
||||
if (trap_ctrl.env_enter = '1') and (trap_ctrl.cause(5) = '1') then -- waiting for entry event
|
||||
debug_ctrl.running <= '1';
|
||||
debug_ctrl.run <= '1';
|
||||
end if;
|
||||
else -- debug mode ONLINE
|
||||
if (trap_ctrl.env_exit = '1') then -- waiting for exit event
|
||||
debug_ctrl.running <= '0';
|
||||
debug_ctrl.run <= '0';
|
||||
end if;
|
||||
end if;
|
||||
end if;
|
||||
end process debug_control;
|
||||
|
||||
-- debug mode entry triggers --
|
||||
debug_ctrl.trig_hw <= trap_ctrl.hwtrig and (not debug_ctrl.running) and csr.tdata1_action and csr.tdata1_dmode; -- enter debug mode by HW trigger module
|
||||
debug_ctrl.trig_break <= trap_ctrl.ebreak and (debug_ctrl.running or -- re-enter debug mode
|
||||
debug_ctrl.trig_hw <= trap_ctrl.hwtrig and (not debug_ctrl.run) and csr.tdata1_action and csr.tdata1_dmode; -- enter debug mode by HW trigger module
|
||||
debug_ctrl.trig_break <= trap_ctrl.ebreak and (debug_ctrl.run or -- re-enter debug mode
|
||||
(( csr.privilege) and csr.dcsr_ebreakm) or -- enabled goto-debug-mode in machine mode on "ebreak"
|
||||
((not csr.privilege) and csr.dcsr_ebreaku)); -- enabled goto-debug-mode in user mode on "ebreak"
|
||||
debug_ctrl.trig_halt <= irq_dbg_i and (not debug_ctrl.running); -- external halt request (if not halted already)
|
||||
debug_ctrl.trig_step <= csr.dcsr_step and (not debug_ctrl.running); -- single-step mode (trigger when NOT CURRENTLY in debug mode)
|
||||
debug_ctrl.trig_halt <= irq_dbg_i and (not debug_ctrl.run); -- external halt request (if not halted already)
|
||||
debug_ctrl.trig_step <= csr.dcsr_step and (not debug_ctrl.run); -- single-step mode (trigger when NOT CURRENTLY in debug mode)
|
||||
|
||||
end generate;
|
||||
|
||||
-- Sdext ISA extension not enabled --
|
||||
debug_mode_disable:
|
||||
if not RISCV_ISA_Sdext generate
|
||||
debug_ctrl.running <= '0';
|
||||
debug_ctrl.run <= '0';
|
||||
debug_ctrl.trig_hw <= '0';
|
||||
debug_ctrl.trig_break <= '0';
|
||||
debug_ctrl.trig_halt <= '0';
|
||||
|
@ -2177,7 +2170,7 @@ begin
|
|||
-- trigger on instruction address match (trigger right BEFORE execution) --
|
||||
hw_trigger_match <= '1' when (csr.tdata1_execute = '1') and -- trigger enabled to match on instruction address
|
||||
(hw_trigger_fired = '0') and -- trigger has not fired yet
|
||||
(csr.tdata2(XLEN-1 downto 1) = execute_engine.next_pc(XLEN-1 downto 1)) -- address match
|
||||
(csr.tdata2(XLEN-1 downto 1) = exe_engine.next_pc(XLEN-1 downto 1)) -- address match
|
||||
else '0';
|
||||
|
||||
-- status flag - set when trigger has fired --
|
||||
|
|
|
@ -72,7 +72,7 @@ begin
|
|||
decoded(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alui_c;
|
||||
decoded(instr_rs1_msb_c downto instr_rs1_lsb_c) <= "00010"; -- stack pointer
|
||||
decoded(instr_rd_msb_c downto instr_rd_lsb_c) <= "01" & instr_i(ci_rd_3_msb_c downto ci_rd_3_lsb_c);
|
||||
decoded(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_subadd_c;
|
||||
decoded(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_sadd_c;
|
||||
decoded(instr_imm12_msb_c downto instr_imm12_lsb_c) <= "00" & instr_i(10 downto 7) & instr_i(12 downto 11) & instr_i(5) & instr_i(6) & "00";
|
||||
if (instr_i(12 downto 5) = "00000000") then -- canonical illegal C instruction or C.ADDI4SPN with nzuimm = 0
|
||||
illegal <= '1';
|
||||
|
@ -131,7 +131,7 @@ begin
|
|||
when "010" => -- C.LI
|
||||
-- --------------------------------------------------------------------------------------
|
||||
decoded(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alui_c;
|
||||
decoded(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_subadd_c;
|
||||
decoded(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_sadd_c;
|
||||
decoded(instr_rs1_msb_c downto instr_rs1_lsb_c) <= "00000"; -- x0
|
||||
decoded(instr_rd_msb_c downto instr_rd_lsb_c) <= instr_i(ci_rd_5_msb_c downto ci_rd_5_lsb_c);
|
||||
decoded(instr_imm12_msb_c downto instr_imm12_lsb_c) <= replicate_f(instr_i(12),6) & instr_i(12) & instr_i(6 downto 2);
|
||||
|
@ -140,7 +140,7 @@ begin
|
|||
-- --------------------------------------------------------------------------------------
|
||||
if (instr_i(ci_rd_5_msb_c downto ci_rd_5_lsb_c) = "00010") then -- C.ADDI16SP
|
||||
decoded(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alui_c;
|
||||
decoded(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_subadd_c;
|
||||
decoded(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_sadd_c;
|
||||
decoded(instr_rd_msb_c downto instr_rd_lsb_c) <= instr_i(ci_rd_5_msb_c downto ci_rd_5_lsb_c);
|
||||
decoded(instr_rs1_msb_c downto instr_rs1_lsb_c) <= "00010"; -- stack pointer
|
||||
decoded(instr_rd_msb_c downto instr_rd_lsb_c) <= "00010"; -- stack pointer
|
||||
|
@ -157,7 +157,7 @@ begin
|
|||
when "000" => -- C.NOP (rd=0) / C.ADDI
|
||||
-- --------------------------------------------------------------------------------------
|
||||
decoded(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alui_c;
|
||||
decoded(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_subadd_c;
|
||||
decoded(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_sadd_c;
|
||||
decoded(instr_rs1_msb_c downto instr_rs1_lsb_c) <= instr_i(ci_rs1_5_msb_c downto ci_rs1_5_lsb_c);
|
||||
decoded(instr_rd_msb_c downto instr_rd_lsb_c) <= instr_i(ci_rd_5_msb_c downto ci_rd_5_lsb_c);
|
||||
decoded(instr_imm12_msb_c downto instr_imm12_lsb_c) <= replicate_f(instr_i(12),7) & instr_i(6 downto 2);
|
||||
|
@ -188,7 +188,7 @@ begin
|
|||
decoded(instr_opcode_msb_c downto instr_opcode_lsb_c) <= opcode_alu_c;
|
||||
case instr_i(6 downto 5) is
|
||||
when "00" => -- C.SUB
|
||||
decoded(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_subadd_c;
|
||||
decoded(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_sadd_c;
|
||||
decoded(instr_funct7_msb_c downto instr_funct7_lsb_c) <= "0100000";
|
||||
when "01" => -- C.XOR
|
||||
decoded(instr_funct3_msb_c downto instr_funct3_lsb_c) <= funct3_xor_c;
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
-- ================================================================================ --
|
||||
-- NEORV32 SoC - RISC-V-Compatible Debug Transport Module (DTM) --
|
||||
-- -------------------------------------------------------------------------------- --
|
||||
-- Compatible to RISC-V debug spec. versions 0.13 and 1.0. --
|
||||
-- -------------------------------------------------------------------------------- --
|
||||
-- The NEORV32 RISC-V Processor - https://github.com/stnolting/neorv32 --
|
||||
-- Copyright (c) NEORV32 contributors. --
|
||||
-- Copyright (c) 2020 - 2024 Stephan Nolting. All rights reserved. --
|
||||
|
@ -24,11 +26,11 @@ entity neorv32_debug_dtm is
|
|||
-- global control --
|
||||
clk_i : in std_ulogic; -- global clock line
|
||||
rstn_i : in std_ulogic; -- global reset line, low-active
|
||||
-- jtag connection --
|
||||
jtag_tck_i : in std_ulogic;
|
||||
jtag_tdi_i : in std_ulogic;
|
||||
jtag_tdo_o : out std_ulogic;
|
||||
jtag_tms_i : in std_ulogic;
|
||||
-- jtag connection (TAP access) --
|
||||
jtag_tck_i : in std_ulogic; -- serial clock
|
||||
jtag_tdi_i : in std_ulogic; -- serial data input
|
||||
jtag_tdo_o : out std_ulogic; -- serial data output
|
||||
jtag_tms_i : in std_ulogic; -- mode select
|
||||
-- debug module interface (DMI) --
|
||||
dmi_req_o : out dmi_req_t; -- request
|
||||
dmi_rsp_i : in dmi_rsp_t -- response
|
||||
|
@ -37,11 +39,6 @@ end neorv32_debug_dtm;
|
|||
|
||||
architecture neorv32_debug_dtm_rtl of neorv32_debug_dtm is
|
||||
|
||||
-- DMI Configuration (fixed!) --
|
||||
constant dmi_idle_c : std_ulogic_vector(2 downto 0) := "000"; -- no idle cycles required
|
||||
constant dmi_version_c : std_ulogic_vector(3 downto 0) := "0001"; -- debug spec. version (0.13 & 1.0)
|
||||
constant dmi_abits_c : std_ulogic_vector(5 downto 0) := "000111"; -- number of DMI address bits (7)
|
||||
|
||||
-- TAP data register addresses --
|
||||
constant addr_idcode_c : std_ulogic_vector(4 downto 0) := "00001"; -- identifier
|
||||
constant addr_dtmcs_c : std_ulogic_vector(4 downto 0) := "10000"; -- DTM status and control
|
||||
|
@ -49,10 +46,8 @@ architecture neorv32_debug_dtm_rtl of neorv32_debug_dtm is
|
|||
|
||||
-- tap JTAG signal synchronizer --
|
||||
type tap_sync_t is record
|
||||
-- internal --
|
||||
tck_ff, tdi_ff, tms_ff : std_ulogic_vector(2 downto 0);
|
||||
-- external --
|
||||
tck_rising, tck_falling, tdi, tms: std_ulogic;
|
||||
tck_rising, tck_falling, tdi, tms : std_ulogic;
|
||||
end record;
|
||||
signal tap_sync : tap_sync_t;
|
||||
|
||||
|
@ -85,8 +80,7 @@ architecture neorv32_debug_dtm_rtl of neorv32_debug_dtm is
|
|||
dmihardreset : std_ulogic;
|
||||
dmireset : std_ulogic;
|
||||
err : std_ulogic;
|
||||
rdata : std_ulogic_vector(31 downto 0);
|
||||
wdata : std_ulogic_vector(31 downto 0);
|
||||
rdata, wdata : std_ulogic_vector(31 downto 0);
|
||||
addr : std_ulogic_vector(6 downto 0);
|
||||
end record;
|
||||
signal dmi_ctrl : dmi_ctrl_t;
|
||||
|
@ -108,14 +102,12 @@ begin
|
|||
end if;
|
||||
end process tap_synchronizer;
|
||||
|
||||
-- JTAG clock edge --
|
||||
-- JTAG clock edges --
|
||||
tap_sync.tck_rising <= '1' when (tap_sync.tck_ff(2 downto 1) = "01") else '0';
|
||||
tap_sync.tck_falling <= '1' when (tap_sync.tck_ff(2 downto 1) = "10") else '0';
|
||||
|
||||
-- JTAG test mode select --
|
||||
-- JTAG inputs --
|
||||
tap_sync.tms <= tap_sync.tms_ff(2);
|
||||
|
||||
-- JTAG serial data input --
|
||||
tap_sync.tdi <= tap_sync.tdi_ff(2);
|
||||
|
||||
|
||||
|
@ -165,6 +157,7 @@ begin
|
|||
end if;
|
||||
end process update_trigger;
|
||||
|
||||
-- edge detector --
|
||||
dr_trigger.valid <= '1' when (dr_trigger.sreg = "01") else '0';
|
||||
|
||||
|
||||
|
@ -184,10 +177,8 @@ begin
|
|||
-- serial data input: instruction register --
|
||||
if (tap_ctrl_state = LOGIC_RESET) or (tap_ctrl_state = IR_CAPTURE) then -- preload phase
|
||||
tap_reg.ireg <= addr_idcode_c;
|
||||
elsif (tap_ctrl_state = IR_SHIFT) then -- access phase
|
||||
if (tap_sync.tck_rising = '1') then -- [JTAG-SYNC] evaluate TDI on rising edge of TCK
|
||||
tap_reg.ireg <= tap_sync.tdi & tap_reg.ireg(tap_reg.ireg'left downto 1);
|
||||
end if;
|
||||
elsif (tap_ctrl_state = IR_SHIFT) and (tap_sync.tck_rising = '1') then -- access phase; [JTAG-SYNC] evaluate TDI on rising edge of TCK
|
||||
tap_reg.ireg <= tap_sync.tdi & tap_reg.ireg(tap_reg.ireg'left downto 1);
|
||||
end if;
|
||||
|
||||
-- serial data input: data register --
|
||||
|
@ -198,15 +189,13 @@ begin
|
|||
when addr_dmi_c => tap_reg.dmi <= tap_reg.dmi_nxt; -- register interface
|
||||
when others => tap_reg.bypass <= '0'; -- pass through
|
||||
end case;
|
||||
elsif (tap_ctrl_state = DR_SHIFT) then -- access phase
|
||||
if (tap_sync.tck_rising = '1') then -- [JTAG-SYNC] evaluate TDI on rising edge of TCK
|
||||
case tap_reg.ireg is
|
||||
when addr_idcode_c => tap_reg.idcode <= tap_sync.tdi & tap_reg.idcode(tap_reg.idcode'left downto 1);
|
||||
when addr_dtmcs_c => tap_reg.dtmcs <= tap_sync.tdi & tap_reg.dtmcs(tap_reg.dtmcs'left downto 1);
|
||||
when addr_dmi_c => tap_reg.dmi <= tap_sync.tdi & tap_reg.dmi(tap_reg.dmi'left downto 1);
|
||||
when others => tap_reg.bypass <= tap_sync.tdi;
|
||||
end case;
|
||||
end if;
|
||||
elsif (tap_ctrl_state = DR_SHIFT) and (tap_sync.tck_rising = '1') then -- access phase; [JTAG-SYNC] evaluate TDI on rising edge of TCK
|
||||
case tap_reg.ireg is
|
||||
when addr_idcode_c => tap_reg.idcode <= tap_sync.tdi & tap_reg.idcode(tap_reg.idcode'left downto 1);
|
||||
when addr_dtmcs_c => tap_reg.dtmcs <= tap_sync.tdi & tap_reg.dtmcs(tap_reg.dtmcs'left downto 1);
|
||||
when addr_dmi_c => tap_reg.dmi <= tap_sync.tdi & tap_reg.dmi(tap_reg.dmi'left downto 1);
|
||||
when others => tap_reg.bypass <= tap_sync.tdi;
|
||||
end case;
|
||||
end if;
|
||||
|
||||
-- serial data output --
|
||||
|
@ -226,20 +215,18 @@ begin
|
|||
end if;
|
||||
end process reg_access;
|
||||
|
||||
-- DTM Control and Status Register (dtmcs) --
|
||||
-- DTM control and status register (dtmcs) read-back --
|
||||
tap_reg.dtmcs_nxt(31 downto 18) <= (others => '0'); -- reserved
|
||||
tap_reg.dtmcs_nxt(17) <= dmi_ctrl.dmihardreset; -- dmihardreset
|
||||
tap_reg.dtmcs_nxt(16) <= dmi_ctrl.dmireset; -- dmireset
|
||||
tap_reg.dtmcs_nxt(15) <= '0'; -- reserved
|
||||
tap_reg.dtmcs_nxt(14 downto 12) <= dmi_idle_c; -- minimum number of idle cycles
|
||||
tap_reg.dtmcs_nxt(14 downto 12) <= "000"; -- minimum number of idle cycles (= 0)
|
||||
tap_reg.dtmcs_nxt(11 downto 10) <= tap_reg.dmi_nxt(1 downto 0); -- dmistat
|
||||
tap_reg.dtmcs_nxt(09 downto 04) <= dmi_abits_c; -- number of DMI address bits
|
||||
tap_reg.dtmcs_nxt(03 downto 00) <= dmi_version_c; -- version
|
||||
tap_reg.dtmcs_nxt(09 downto 04) <= "000111"; -- number of DMI address bits (7)
|
||||
tap_reg.dtmcs_nxt(03 downto 00) <= "0001"; -- compatible to debug spec. version (0.13 & 1.0)
|
||||
|
||||
-- DMI register read access --
|
||||
tap_reg.dmi_nxt(40 downto 34) <= dmi_ctrl.addr; -- address
|
||||
tap_reg.dmi_nxt(33 downto 02) <= dmi_ctrl.rdata; -- read data
|
||||
tap_reg.dmi_nxt(01 downto 00) <= (others => dmi_ctrl.err); -- status
|
||||
-- DMI register (dmi) read-back --
|
||||
tap_reg.dmi_nxt <= dmi_ctrl.addr & dmi_ctrl.rdata & replicate_f(dmi_ctrl.err, 2); -- address & read data & status
|
||||
|
||||
|
||||
-- Debug Module Interface -----------------------------------------------------------------
|
||||
|
@ -275,14 +262,12 @@ begin
|
|||
-- DMI interface arbiter --
|
||||
dmi_ctrl.op <= dmi_req_nop_c; -- default
|
||||
if (dmi_ctrl.busy = '0') then -- idle: waiting for new request
|
||||
if (dmi_ctrl.dmihardreset = '0') then -- no DMI hard reset
|
||||
if (dr_trigger.valid = '1') and (tap_reg.ireg = addr_dmi_c) then
|
||||
dmi_ctrl.addr <= tap_reg.dmi(40 downto 34);
|
||||
dmi_ctrl.wdata <= tap_reg.dmi(33 downto 02);
|
||||
if (tap_reg.dmi(1 downto 0) = dmi_req_rd_c) or (tap_reg.dmi(1 downto 0) = dmi_req_wr_c) then
|
||||
dmi_ctrl.op <= tap_reg.dmi(1 downto 0);
|
||||
dmi_ctrl.busy <= '1';
|
||||
end if;
|
||||
if (dmi_ctrl.dmihardreset = '0') and (dr_trigger.valid = '1') and (tap_reg.ireg = addr_dmi_c) then -- valid non-reset access
|
||||
dmi_ctrl.addr <= tap_reg.dmi(40 downto 34);
|
||||
dmi_ctrl.wdata <= tap_reg.dmi(33 downto 02);
|
||||
if (tap_reg.dmi(1 downto 0) = dmi_req_rd_c) or (tap_reg.dmi(1 downto 0) = dmi_req_wr_c) then
|
||||
dmi_ctrl.op <= tap_reg.dmi(1 downto 0);
|
||||
dmi_ctrl.busy <= '1';
|
||||
end if;
|
||||
end if;
|
||||
else -- busy: read/write access in progress
|
||||
|
|
|
@ -29,7 +29,7 @@ package neorv32_package is
|
|||
|
||||
-- Architecture Constants -----------------------------------------------------------------
|
||||
-- -------------------------------------------------------------------------------------------
|
||||
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01100507"; -- hardware version
|
||||
constant hw_version_c : std_ulogic_vector(31 downto 0) := x"01100508"; -- hardware version
|
||||
constant archid_c : natural := 19; -- official RISC-V architecture ID
|
||||
constant XLEN : natural := 32; -- native data path width
|
||||
|
||||
|
@ -58,7 +58,7 @@ package neorv32_package is
|
|||
constant mem_io_size_c : natural := 8*1024; -- = 32 * iodev_size_c
|
||||
|
||||
-- Start of uncached memory access (256MB page / 4MSBs only) --
|
||||
constant uncached_begin_c : std_ulogic_vector(31 downto 0) := x"f0000000";
|
||||
constant mem_uncached_begin_c : std_ulogic_vector(31 downto 0) := x"f0000000";
|
||||
|
||||
-- IO Address Map (base address must be aligned to the region's size) --
|
||||
constant iodev_size_c : natural := 256; -- size of a single IO device (bytes)
|
||||
|
@ -254,7 +254,7 @@ package neorv32_package is
|
|||
constant funct3_sh_c : std_ulogic_vector(2 downto 0) := "001"; -- store half word
|
||||
constant funct3_sw_c : std_ulogic_vector(2 downto 0) := "010"; -- store word
|
||||
-- alu --
|
||||
constant funct3_subadd_c : std_ulogic_vector(2 downto 0) := "000"; -- sub/add
|
||||
constant funct3_sadd_c : std_ulogic_vector(2 downto 0) := "000"; -- sub/add
|
||||
constant funct3_sll_c : std_ulogic_vector(2 downto 0) := "001"; -- shift logical left
|
||||
constant funct3_slt_c : std_ulogic_vector(2 downto 0) := "010"; -- set on less
|
||||
constant funct3_sltu_c : std_ulogic_vector(2 downto 0) := "011"; -- set on less unsigned
|
||||
|
|
|
@ -543,7 +543,7 @@ begin
|
|||
generic map (
|
||||
NUM_BLOCKS => ICACHE_NUM_BLOCKS,
|
||||
BLOCK_SIZE => ICACHE_BLOCK_SIZE,
|
||||
UC_BEGIN => uncached_begin_c(31 downto 28),
|
||||
UC_BEGIN => mem_uncached_begin_c(31 downto 28),
|
||||
UC_ENABLE => true,
|
||||
READ_ONLY => true
|
||||
)
|
||||
|
@ -572,7 +572,7 @@ begin
|
|||
generic map (
|
||||
NUM_BLOCKS => DCACHE_NUM_BLOCKS,
|
||||
BLOCK_SIZE => DCACHE_BLOCK_SIZE,
|
||||
UC_BEGIN => uncached_begin_c(31 downto 28),
|
||||
UC_BEGIN => mem_uncached_begin_c(31 downto 28),
|
||||
UC_ENABLE => true,
|
||||
READ_ONLY => false
|
||||
)
|
||||
|
@ -927,7 +927,7 @@ begin
|
|||
generic map (
|
||||
NUM_BLOCKS => XBUS_CACHE_NUM_BLOCKS,
|
||||
BLOCK_SIZE => XBUS_CACHE_BLOCK_SIZE,
|
||||
UC_BEGIN => uncached_begin_c(31 downto 28),
|
||||
UC_BEGIN => mem_uncached_begin_c(31 downto 28),
|
||||
UC_ENABLE => true,
|
||||
READ_ONLY => false
|
||||
)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue