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

Subversion Repositories neorv32

[/] [neorv32/] [trunk/] [rtl/] [core/] [neorv32_cpu_control.vhd] - Blame information for rev 42

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 2 zero_gravi
-- #################################################################################################
2
-- # << NEORV32 - CPU Control >>                                                                   #
3
-- # ********************************************************************************************* #
4 31 zero_gravi
-- # CPU operation is split into a fetch engine (responsible for fetching instruction data), an    #
5
-- # issue engine (for recoding compressed instructions and for constructing 32-bit instruction    #
6
-- # words) and an execute engine (responsible for actually executing the instructions), a trap    #
7
-- # handling controller and the RISC-V status and control register set (CSRs).                    #
8 2 zero_gravi
-- # ********************************************************************************************* #
9
-- # BSD 3-Clause License                                                                          #
10
-- #                                                                                               #
11 42 zero_gravi
-- # Copyright (c) 2021, Stephan Nolting. All rights reserved.                                     #
12 2 zero_gravi
-- #                                                                                               #
13
-- # Redistribution and use in source and binary forms, with or without modification, are          #
14
-- # permitted provided that the following conditions are met:                                     #
15
-- #                                                                                               #
16
-- # 1. Redistributions of source code must retain the above copyright notice, this list of        #
17
-- #    conditions and the following disclaimer.                                                   #
18
-- #                                                                                               #
19
-- # 2. Redistributions in binary form must reproduce the above copyright notice, this list of     #
20
-- #    conditions and the following disclaimer in the documentation and/or other materials        #
21
-- #    provided with the distribution.                                                            #
22
-- #                                                                                               #
23
-- # 3. Neither the name of the copyright holder nor the names of its contributors may be used to  #
24
-- #    endorse or promote products derived from this software without specific prior written      #
25
-- #    permission.                                                                                #
26
-- #                                                                                               #
27
-- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS   #
28
-- # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF               #
29
-- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE    #
30
-- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,     #
31
-- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
32
-- # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED    #
33
-- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING     #
34
-- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED  #
35
-- # OF THE POSSIBILITY OF SUCH DAMAGE.                                                            #
36
-- # ********************************************************************************************* #
37
-- # The NEORV32 Processor - https://github.com/stnolting/neorv32              (c) Stephan Nolting #
38
-- #################################################################################################
39
 
40
library ieee;
41
use ieee.std_logic_1164.all;
42
use ieee.numeric_std.all;
43
 
44
library neorv32;
45
use neorv32.neorv32_package.all;
46
 
47
entity neorv32_cpu_control is
48
  generic (
49
    -- General --
50 12 zero_gravi
    HW_THREAD_ID                 : std_ulogic_vector(31 downto 0):= x"00000000"; -- hardware thread id
51
    CPU_BOOT_ADDR                : std_ulogic_vector(31 downto 0):= x"00000000"; -- cpu boot address
52 2 zero_gravi
    -- RISC-V CPU Extensions --
53 39 zero_gravi
    CPU_EXTENSION_RISCV_A        : boolean := false; -- implement atomic extension?
54 12 zero_gravi
    CPU_EXTENSION_RISCV_C        : boolean := false; -- implement compressed extension?
55
    CPU_EXTENSION_RISCV_E        : boolean := false; -- implement embedded RF extension?
56
    CPU_EXTENSION_RISCV_M        : boolean := false; -- implement muld/div extension?
57 15 zero_gravi
    CPU_EXTENSION_RISCV_U        : boolean := false; -- implement user mode extension?
58 12 zero_gravi
    CPU_EXTENSION_RISCV_Zicsr    : boolean := true;  -- implement CSR system?
59 15 zero_gravi
    CPU_EXTENSION_RISCV_Zifencei : boolean := true;  -- implement instruction stream sync.?
60
    -- Physical memory protection (PMP) --
61 42 zero_gravi
    PMP_NUM_REGIONS              : natural := 0;       -- number of regions (0..64)
62
    PMP_MIN_GRANULARITY          : natural := 64*1024; -- minimal region granularity in bytes, has to be a power of 2, min 8 bytes
63
    -- Hardware Performance Monitors (HPM) --
64
    HPM_NUM_CNTS                 : natural := 0      -- number of inmplemnted HPM counters (0..29)
65 2 zero_gravi
  );
66
  port (
67
    -- global control --
68
    clk_i         : in  std_ulogic; -- global clock, rising edge
69
    rstn_i        : in  std_ulogic; -- global reset, low-active, async
70
    ctrl_o        : out std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus
71
    -- status input --
72
    alu_wait_i    : in  std_ulogic; -- wait for ALU
73 12 zero_gravi
    bus_i_wait_i  : in  std_ulogic; -- wait for bus
74
    bus_d_wait_i  : in  std_ulogic; -- wait for bus
75 2 zero_gravi
    -- data input --
76
    instr_i       : in  std_ulogic_vector(data_width_c-1 downto 0); -- instruction
77
    cmp_i         : in  std_ulogic_vector(1 downto 0); -- comparator status
78 36 zero_gravi
    alu_add_i     : in  std_ulogic_vector(data_width_c-1 downto 0); -- ALU address result
79
    rs1_i         : in  std_ulogic_vector(data_width_c-1 downto 0); -- rf source 1
80 2 zero_gravi
    -- data output --
81
    imm_o         : out std_ulogic_vector(data_width_c-1 downto 0); -- immediate
82 6 zero_gravi
    fetch_pc_o    : out std_ulogic_vector(data_width_c-1 downto 0); -- PC for instruction fetch
83
    curr_pc_o     : out std_ulogic_vector(data_width_c-1 downto 0); -- current PC (corresponding to current instruction)
84 2 zero_gravi
    csr_rdata_o   : out std_ulogic_vector(data_width_c-1 downto 0); -- CSR read data
85 14 zero_gravi
    -- interrupts (risc-v compliant) --
86
    msw_irq_i     : in  std_ulogic; -- machine software interrupt
87
    mext_irq_i    : in  std_ulogic; -- machine external interrupt
88 2 zero_gravi
    mtime_irq_i   : in  std_ulogic; -- machine timer interrupt
89 14 zero_gravi
    -- fast interrupts (custom) --
90
    firq_i        : in  std_ulogic_vector(3 downto 0);
91 11 zero_gravi
    -- system time input from MTIME --
92
    time_i        : in  std_ulogic_vector(63 downto 0); -- current system time
93 15 zero_gravi
    -- physical memory protection --
94 23 zero_gravi
    pmp_addr_o    : out pmp_addr_if_t; -- addresses
95
    pmp_ctrl_o    : out pmp_ctrl_if_t; -- configs
96 2 zero_gravi
    -- bus access exceptions --
97
    mar_i         : in  std_ulogic_vector(data_width_c-1 downto 0);  -- memory address register
98
    ma_instr_i    : in  std_ulogic; -- misaligned instruction address
99
    ma_load_i     : in  std_ulogic; -- misaligned load data address
100
    ma_store_i    : in  std_ulogic; -- misaligned store data address
101
    be_instr_i    : in  std_ulogic; -- bus error on instruction access
102
    be_load_i     : in  std_ulogic; -- bus error on load data access
103 12 zero_gravi
    be_store_i    : in  std_ulogic  -- bus error on store data access
104 2 zero_gravi
  );
105
end neorv32_cpu_control;
106
 
107
architecture neorv32_cpu_control_rtl of neorv32_cpu_control is
108
 
109 6 zero_gravi
  -- instruction fetch enginge --
110 31 zero_gravi
  type fetch_engine_state_t is (IFETCH_RESET, IFETCH_REQUEST, IFETCH_ISSUE);
111 6 zero_gravi
  type fetch_engine_t is record
112 31 zero_gravi
    state       : fetch_engine_state_t;
113
    state_nxt   : fetch_engine_state_t;
114 42 zero_gravi
    state_prev  : fetch_engine_state_t;
115 31 zero_gravi
    pc          : std_ulogic_vector(data_width_c-1 downto 0);
116
    pc_nxt      : std_ulogic_vector(data_width_c-1 downto 0);
117
    reset       : std_ulogic;
118
    bus_err_ack : std_ulogic;
119 6 zero_gravi
  end record;
120
  signal fetch_engine : fetch_engine_t;
121 2 zero_gravi
 
122 32 zero_gravi
  -- instrucion prefetch buffer (IPB, real FIFO) --
123 31 zero_gravi
  type ipb_data_fifo_t is array (0 to ipb_entries_c-1) of std_ulogic_vector(2+31 downto 0);
124 6 zero_gravi
  type ipb_t is record
125 31 zero_gravi
    wdata : std_ulogic_vector(2+31 downto 0); -- write status (bus_error, align_error) + 32-bit instruction data
126
    we    : std_ulogic; -- trigger write
127
    free  : std_ulogic; -- free entry available?
128
    clear : std_ulogic; -- clear all entries
129 20 zero_gravi
    --
130 31 zero_gravi
    rdata : std_ulogic_vector(2+31 downto 0); -- read data: status (bus_error, align_error) + 32-bit instruction data
131
    re    : std_ulogic; -- read enable
132
    avail : std_ulogic; -- data available?
133 20 zero_gravi
    --
134 31 zero_gravi
    w_pnt : std_ulogic_vector(index_size_f(ipb_entries_c) downto 0); -- write pointer
135
    r_pnt : std_ulogic_vector(index_size_f(ipb_entries_c) downto 0); -- read pointer
136 34 zero_gravi
    match : std_ulogic;
137 31 zero_gravi
    empty : std_ulogic;
138
    full  : std_ulogic;
139 20 zero_gravi
    --
140 31 zero_gravi
    data  : ipb_data_fifo_t; -- fifo memory
141 6 zero_gravi
  end record;
142
  signal ipb : ipb_t;
143 2 zero_gravi
 
144 31 zero_gravi
  -- pre-decoder --
145
  signal ci_instr16 : std_ulogic_vector(15 downto 0);
146
  signal ci_instr32 : std_ulogic_vector(31 downto 0);
147
  signal ci_illegal : std_ulogic;
148
 
149
  -- instruction issue enginge --
150
  type issue_engine_state_t is (ISSUE_ACTIVE, ISSUE_REALIGN);
151
  type issue_engine_t is record
152
    state     : issue_engine_state_t;
153
    state_nxt : issue_engine_state_t;
154
    align     : std_ulogic;
155
    align_nxt : std_ulogic;
156
    buf       : std_ulogic_vector(2+15 downto 0);
157
    buf_nxt   : std_ulogic_vector(2+15 downto 0);
158
  end record;
159
  signal issue_engine : issue_engine_t;
160
 
161 37 zero_gravi
  -- instruction issue interface --
162
  type cmd_issue_t is record
163
    data  : std_ulogic_vector(35 downto 0); -- 4-bit status + 32-bit instruction
164
    valid : std_ulogic; -- data word is valid when set
165 31 zero_gravi
  end record;
166 37 zero_gravi
  signal cmd_issue : cmd_issue_t;
167 31 zero_gravi
 
168 6 zero_gravi
  -- instruction execution engine --
169 39 zero_gravi
  type execute_engine_state_t is (SYS_WAIT, DISPATCH, TRAP, EXECUTE, ALU_WAIT, BRANCH, FENCE_OP, LOADSTORE_0, LOADSTORE_1, LOADSTORE_2, SYS_ENV, CSR_ACCESS);
170 6 zero_gravi
  type execute_engine_t is record
171
    state        : execute_engine_state_t;
172
    state_nxt    : execute_engine_state_t;
173 42 zero_gravi
    state_prev   : execute_engine_state_t;
174 39 zero_gravi
    --
175 6 zero_gravi
    i_reg        : std_ulogic_vector(31 downto 0);
176
    i_reg_nxt    : std_ulogic_vector(31 downto 0);
177 33 zero_gravi
    i_reg_last   : std_ulogic_vector(31 downto 0); -- last executed instruction
178 39 zero_gravi
    --
179 6 zero_gravi
    is_ci        : std_ulogic; -- current instruction is de-compressed instruction
180
    is_ci_nxt    : std_ulogic;
181 29 zero_gravi
    is_cp_op     : std_ulogic; -- current instruction is a co-processor operation
182
    is_cp_op_nxt : std_ulogic;
183 39 zero_gravi
    --
184 6 zero_gravi
    branch_taken : std_ulogic; -- branch condition fullfilled
185
    pc           : std_ulogic_vector(data_width_c-1 downto 0); -- actual PC, corresponding to current executed instruction
186 39 zero_gravi
    pc_mux_sel   : std_ulogic_vector(1 downto 0); -- source select for PC update
187
    pc_we        : std_ulogic; -- PC update enabled
188 6 zero_gravi
    next_pc      : std_ulogic_vector(data_width_c-1 downto 0); -- next PC, corresponding to next instruction to be executed
189
    last_pc      : std_ulogic_vector(data_width_c-1 downto 0); -- PC of last executed instruction
190 39 zero_gravi
    --
191 11 zero_gravi
    sleep        : std_ulogic; -- CPU in sleep mode
192 39 zero_gravi
    sleep_nxt    : std_ulogic;
193 20 zero_gravi
    if_rst       : std_ulogic; -- instruction fetch was reset
194 39 zero_gravi
    if_rst_nxt   : std_ulogic;
195 6 zero_gravi
  end record;
196
  signal execute_engine : execute_engine_t;
197 2 zero_gravi
 
198 6 zero_gravi
  -- trap controller --
199
  type trap_ctrl_t is record
200
    exc_buf       : std_ulogic_vector(exception_width_c-1 downto 0);
201
    exc_fire      : std_ulogic; -- set if there is a valid source in the exception buffer
202
    irq_buf       : std_ulogic_vector(interrupt_width_c-1 downto 0);
203
    irq_fire      : std_ulogic; -- set if there is a valid source in the interrupt buffer
204
    exc_ack       : std_ulogic; -- acknowledge all exceptions
205
    irq_ack       : std_ulogic_vector(interrupt_width_c-1 downto 0); -- acknowledge specific interrupt
206
    irq_ack_nxt   : std_ulogic_vector(interrupt_width_c-1 downto 0);
207 40 zero_gravi
    cause         : std_ulogic_vector(5 downto 0); -- trap ID for mcause CSR
208 14 zero_gravi
    cause_nxt     : std_ulogic_vector(5 downto 0);
209 6 zero_gravi
    --
210
    env_start     : std_ulogic; -- start trap handler env
211
    env_start_ack : std_ulogic; -- start of trap handler acknowledged
212
    env_end       : std_ulogic; -- end trap handler env
213
    --
214
    instr_be      : std_ulogic; -- instruction fetch bus error
215
    instr_ma      : std_ulogic; -- instruction fetch misaligned address
216
    instr_il      : std_ulogic; -- illegal instruction
217
    env_call      : std_ulogic;
218
    break_point   : std_ulogic;
219
  end record;
220
  signal trap_ctrl : trap_ctrl_t;
221 39 zero_gravi
 
222
  -- atomic operations controller --
223
  type atomic_ctrl_t is record
224
    env_start  : std_ulogic; -- begin atomic operations
225
    env_end    : std_ulogic; -- end atomic operations
226
    env_end_ff : std_ulogic; -- end atomic operations dealyed
227
    env_abort  : std_ulogic; -- atomic operations abort (results in failure)
228
    lock       : std_ulogic; -- lock status
229
  end record;
230
  signal atomic_ctrl : atomic_ctrl_t;
231 6 zero_gravi
 
232 40 zero_gravi
  -- CPU main control bus --
233 6 zero_gravi
  signal ctrl_nxt, ctrl : std_ulogic_vector(ctrl_width_c-1 downto 0);
234 2 zero_gravi
 
235 40 zero_gravi
  -- fast instruction fetch access --
236 6 zero_gravi
  signal bus_fast_ir : std_ulogic;
237 2 zero_gravi
 
238 6 zero_gravi
  -- RISC-V control and status registers (CSRs) --
239 42 zero_gravi
  type pmp_ctrl_t     is array (0 to PMP_NUM_REGIONS-1) of std_ulogic_vector(7 downto 0);
240
  type pmp_addr_t     is array (0 to PMP_NUM_REGIONS-1) of std_ulogic_vector(data_width_c-1 downto 0);
241
  type pmp_ctrl_rd_t  is array (0 to 63) of std_ulogic_vector(7 downto 0);
242
  type pmp_addr_rd_t  is array (0 to 63) of std_ulogic_vector(data_width_c-1 downto 0);
243
  type mhpmevent_t    is array (0 to HPM_NUM_CNTS-1) of std_ulogic_vector(hpmcnt_event_size_c-1 downto 0);
244
  type mhpmcnt_t      is array (0 to HPM_NUM_CNTS-1) of std_ulogic_vector(32 downto 0);
245
  type mhpmcnth_t     is array (0 to HPM_NUM_CNTS-1) of std_ulogic_vector(31 downto 0);
246
  type mhpmevent_rd_t is array (0 to 29) of std_ulogic_vector(hpmcnt_event_size_c-1 downto 0);
247
  type mhpmcnt_rd_t   is array (0 to 29) of std_ulogic_vector(32 downto 0);
248
  type mhpmcnth_rd_t  is array (0 to 29) of std_ulogic_vector(31 downto 0);
249 6 zero_gravi
  type csr_t is record
250 42 zero_gravi
    addr              : std_ulogic_vector(11 downto 0); -- csr address
251
    we                : std_ulogic; -- csr write enable
252
    we_nxt            : std_ulogic;
253
    re                : std_ulogic; -- csr read enable
254
    re_nxt            : std_ulogic;
255
    wdata             : std_ulogic_vector(data_width_c-1 downto 0); -- csr write data
256
    rdata             : std_ulogic_vector(data_width_c-1 downto 0); -- csr read data
257 29 zero_gravi
    --
258 42 zero_gravi
    mstatus_mie       : std_ulogic; -- mstatus.MIE: global IRQ enable (R/W)
259
    mstatus_mpie      : std_ulogic; -- mstatus.MPIE: previous global IRQ enable (R/W)
260
    mstatus_mpp       : std_ulogic_vector(1 downto 0); -- mstatus.MPP: machine previous privilege mode
261 29 zero_gravi
    --
262 42 zero_gravi
    mie_msie          : std_ulogic; -- mie.MSIE: machine software interrupt enable (R/W)
263
    mie_meie          : std_ulogic; -- mie.MEIE: machine external interrupt enable (R/W)
264
    mie_mtie          : std_ulogic; -- mie.MEIE: machine timer interrupt enable (R/W)
265
    mie_firqe         : std_ulogic_vector(3 downto 0); -- mie.firq*e: fast interrupt enabled (R/W)
266 29 zero_gravi
    --
267 42 zero_gravi
    mcounteren_cy     : std_ulogic; -- mcounteren.cy: allow cycle[h] access from user-mode
268
    mcounteren_tm     : std_ulogic; -- mcounteren.tm: allow time[h] access from user-mode
269
    mcounteren_ir     : std_ulogic; -- mcounteren.ir: allow instret[h] access from user-mode
270
    mcounteren_hpm    : std_ulogic_vector(HPM_NUM_CNTS-1 downto 0); -- mcounteren.hpmx: allow mhpmcounterx[h] access from user-mode
271 29 zero_gravi
    --
272 42 zero_gravi
    mcountinhibit_cy  : std_ulogic; -- mcounterinhibit.cy: enable auto-increment for [m]cycle[h]
273
    mcountinhibit_ir  : std_ulogic; -- mcounterinhibit.ir: enable auto-increment for [m]instret[h]
274
    mcountinhibit_hpm : std_ulogic_vector(HPM_NUM_CNTS-1 downto 0); -- mcounterinhibit.hpm3: enable auto-increment for mhpmcounterx[h]
275 40 zero_gravi
    --
276 42 zero_gravi
    mip_status        : std_ulogic_vector(interrupt_width_c-1  downto 0); -- current buffered IRQs
277
    mip_clear         : std_ulogic_vector(interrupt_width_c-1  downto 0); -- set bits clear the according buffered IRQ
278 41 zero_gravi
    --
279 42 zero_gravi
    privilege         : std_ulogic_vector(1 downto 0); -- hart's current privilege mode
280
    priv_m_mode       : std_ulogic; -- CPU in M-mode
281
    priv_u_mode       : std_ulogic; -- CPU in u-mode
282 41 zero_gravi
    --
283 42 zero_gravi
    mepc              : std_ulogic_vector(data_width_c-1 downto 0); -- mepc: machine exception pc (R/W)
284
    mcause            : std_ulogic_vector(data_width_c-1 downto 0); -- mcause: machine trap cause (R/W)
285
    mtvec             : std_ulogic_vector(data_width_c-1 downto 0); -- mtvec: machine trap-handler base address (R/W), bit 1:0 == 00
286
    mtval             : std_ulogic_vector(data_width_c-1 downto 0); -- mtval: machine bad address or isntruction (R/W)
287
    --
288
    mhpmevent         : mhpmevent_t; -- mhpmevent*: machine performance-monitoring event selector (R/W)
289
    mhpmevent_rd      : mhpmevent_rd_t; -- mhpmevent*: actual read data
290
    --
291
    mscratch          : std_ulogic_vector(data_width_c-1 downto 0); -- mscratch: scratch register (R/W)
292
    mcycle            : std_ulogic_vector(32 downto 0); -- mcycle (R/W), plus carry bit
293
    minstret          : std_ulogic_vector(32 downto 0); -- minstret (R/W), plus carry bit
294
    --
295
    mcycleh           : std_ulogic_vector(31 downto 0); -- mcycleh (R/W)
296
    minstreth         : std_ulogic_vector(31 downto 0); -- minstreth (R/W)
297
    --
298
    mhpmcounter       : mhpmcnt_t; -- mhpmcounter* (R/W), plus carry bit
299
    mhpmcounterh      : mhpmcnth_t; -- mhpmcounter*h (R/W)
300
    mhpmcounter_rd    : mhpmcnt_rd_t; -- mhpmcounter* (R/W): actual read data
301
    mhpmcounterh_rd   : mhpmcnth_rd_t; -- mhpmcounter*h (R/W): actual read data
302
    --
303
    pmpcfg            : pmp_ctrl_t; -- physical memory protection - configuration registers
304
    pmpcfg_rd         : pmp_ctrl_rd_t; -- physical memory protection - actual read data
305
    pmpaddr           : pmp_addr_t; -- physical memory protection - address registers
306
    pmpaddr_rd        : pmp_addr_rd_t; -- physical memory protection - actual read data
307 6 zero_gravi
  end record;
308
  signal csr : csr_t;
309 2 zero_gravi
 
310 42 zero_gravi
  -- counter low-to-high-word carry --
311
  signal mcycle_msb      : std_ulogic;
312
  signal minstret_msb    : std_ulogic;
313
  signal mhpmcounter_msb : std_ulogic_vector(HPM_NUM_CNTS-1 downto 0);
314 2 zero_gravi
 
315 42 zero_gravi
  -- (hpm) counter events --
316
  signal cnt_event, cnt_event_nxt : std_ulogic_vector(hpmcnt_event_size_c-1 downto 0);
317
  signal hpmcnt_trigger           : std_ulogic_vector(HPM_NUM_CNTS-1 downto 0);
318
 
319 6 zero_gravi
  -- illegal instruction check --
320 36 zero_gravi
  signal illegal_opcode_lsbs : std_ulogic; -- if opcode != rv32
321 2 zero_gravi
  signal illegal_instruction : std_ulogic;
322
  signal illegal_register    : std_ulogic; -- only for E-extension
323
  signal illegal_compressed  : std_ulogic; -- only fir C-extension
324
 
325 15 zero_gravi
  -- access (privilege) check --
326
  signal csr_acc_valid : std_ulogic; -- valid CSR access (implemented and valid access rights)
327
 
328 2 zero_gravi
begin
329
 
330 6 zero_gravi
-- ****************************************************************************************************************************
331 31 zero_gravi
-- Instruction Fetch (always fetches aligned 32-bit chunks of data)
332 6 zero_gravi
-- ****************************************************************************************************************************
333
 
334
  -- Fetch Engine FSM Sync ------------------------------------------------------------------
335
  -- -------------------------------------------------------------------------------------------
336 31 zero_gravi
  fetch_engine_fsm_sync: process(rstn_i, clk_i)
337 6 zero_gravi
  begin
338
    if (rstn_i = '0') then
339 42 zero_gravi
      fetch_engine.state      <= IFETCH_RESET;
340
      fetch_engine.state_prev <= IFETCH_RESET;
341
      fetch_engine.pc         <= (others => '0');
342 6 zero_gravi
    elsif rising_edge(clk_i) then
343
      if (fetch_engine.reset = '1') then
344
        fetch_engine.state <= IFETCH_RESET;
345
      else
346
        fetch_engine.state <= fetch_engine.state_nxt;
347
      end if;
348 42 zero_gravi
      fetch_engine.state_prev <= fetch_engine.state;
349
      fetch_engine.pc         <= fetch_engine.pc_nxt;
350 6 zero_gravi
    end if;
351
  end process fetch_engine_fsm_sync;
352
 
353 12 zero_gravi
  -- PC output --
354 31 zero_gravi
  fetch_pc_o <= fetch_engine.pc(data_width_c-1 downto 1) & '0'; -- half-word aligned
355 6 zero_gravi
 
356 12 zero_gravi
 
357 6 zero_gravi
  -- Fetch Engine FSM Comb ------------------------------------------------------------------
358
  -- -------------------------------------------------------------------------------------------
359 31 zero_gravi
  fetch_engine_fsm_comb: process(fetch_engine, execute_engine, ipb, instr_i, bus_i_wait_i, be_instr_i, ma_instr_i)
360 6 zero_gravi
  begin
361
    -- arbiter defaults --
362 31 zero_gravi
    bus_fast_ir              <= '0';
363
    fetch_engine.state_nxt   <= fetch_engine.state;
364
    fetch_engine.pc_nxt      <= fetch_engine.pc;
365
    fetch_engine.bus_err_ack <= '0';
366 6 zero_gravi
 
367
    -- instruction prefetch buffer interface --
368
    ipb.we    <= '0';
369 31 zero_gravi
    ipb.wdata <= be_instr_i & ma_instr_i & instr_i(31 downto 0); -- store exception info and instruction word
370 6 zero_gravi
    ipb.clear <= '0';
371
 
372
    -- state machine --
373
    case fetch_engine.state is
374
 
375 31 zero_gravi
      when IFETCH_RESET => -- reset engine and prefetch buffer, get appilcation PC
376 6 zero_gravi
      -- ------------------------------------------------------------
377 31 zero_gravi
        fetch_engine.bus_err_ack <= '1'; -- acknowledge any instruction bus errors, the execute engine has to take care of them / terminate current transfer
378
        fetch_engine.pc_nxt      <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- initialize with "real" application PC
379
        ipb.clear                <= '1'; -- clear prefetch buffer
380
        fetch_engine.state_nxt   <= IFETCH_REQUEST;
381 6 zero_gravi
 
382 31 zero_gravi
      when IFETCH_REQUEST => -- output current PC to bus system and request 32-bit (aligned!) instruction data
383 6 zero_gravi
      -- ------------------------------------------------------------
384 31 zero_gravi
        if (ipb.free = '1') then -- free entry in buffer?
385
          bus_fast_ir            <= '1'; -- fast instruction fetch request
386
          fetch_engine.state_nxt <= IFETCH_ISSUE;
387
        end if;
388 6 zero_gravi
 
389 31 zero_gravi
      when IFETCH_ISSUE => -- store instruction data to prefetch buffer
390 6 zero_gravi
      -- ------------------------------------------------------------
391 41 zero_gravi
        fetch_engine.bus_err_ack <= be_instr_i or ma_instr_i; -- ACK bus/alignment errors
392 12 zero_gravi
        if (bus_i_wait_i = '0') or (be_instr_i = '1') or (ma_instr_i = '1') then -- wait for bus response
393 39 zero_gravi
          fetch_engine.pc_nxt    <= std_ulogic_vector(unsigned(fetch_engine.pc) + 4);
394
          ipb.we                 <= '1';
395
          fetch_engine.state_nxt <= IFETCH_REQUEST;
396 6 zero_gravi
        end if;
397 11 zero_gravi
 
398 6 zero_gravi
      when others => -- undefined
399
      -- ------------------------------------------------------------
400
        fetch_engine.state_nxt <= IFETCH_RESET;
401
 
402
    end case;
403
  end process fetch_engine_fsm_comb;
404
 
405
 
406
-- ****************************************************************************************************************************
407
-- Instruction Prefetch Buffer
408
-- ****************************************************************************************************************************
409
 
410
 
411 20 zero_gravi
  -- Instruction Prefetch Buffer (FIFO) -----------------------------------------------------
412 6 zero_gravi
  -- -------------------------------------------------------------------------------------------
413 36 zero_gravi
  instr_prefetch_buffer: process(clk_i)
414 6 zero_gravi
  begin
415 36 zero_gravi
    if rising_edge(clk_i) then
416 20 zero_gravi
      -- write port --
417 6 zero_gravi
      if (ipb.clear = '1') then
418 20 zero_gravi
        ipb.w_pnt <= (others => '0');
419 6 zero_gravi
      elsif (ipb.we = '1') then
420 20 zero_gravi
        ipb.w_pnt <= std_ulogic_vector(unsigned(ipb.w_pnt) + 1);
421
      end if;
422 37 zero_gravi
      if (ipb.we = '1') then -- write data
423 36 zero_gravi
        ipb.data(to_integer(unsigned(ipb.w_pnt(ipb.w_pnt'left-1 downto 0)))) <= ipb.wdata;
424
      end if;
425
      -- read port --
426 20 zero_gravi
      if (ipb.clear = '1') then
427
        ipb.r_pnt <= (others => '0');
428 6 zero_gravi
      elsif (ipb.re = '1') then
429 20 zero_gravi
        ipb.r_pnt <= std_ulogic_vector(unsigned(ipb.r_pnt) + 1);
430 6 zero_gravi
      end if;
431 20 zero_gravi
    end if;
432 36 zero_gravi
  end process instr_prefetch_buffer;
433 20 zero_gravi
 
434
  -- async read --
435 31 zero_gravi
  ipb.rdata <= ipb.data(to_integer(unsigned(ipb.r_pnt(ipb.r_pnt'left-1 downto 0))));
436 20 zero_gravi
 
437 6 zero_gravi
  -- status --
438 40 zero_gravi
  ipb.match <= '1' when (ipb.r_pnt(ipb.r_pnt'left-1 downto 0) = ipb.w_pnt(ipb.w_pnt'left-1 downto 0))  else '0';
439 34 zero_gravi
  ipb.full  <= '1' when (ipb.r_pnt(ipb.r_pnt'left) /= ipb.w_pnt(ipb.w_pnt'left)) and (ipb.match = '1') else '0';
440
  ipb.empty <= '1' when (ipb.r_pnt(ipb.r_pnt'left)  = ipb.w_pnt(ipb.w_pnt'left)) and (ipb.match = '1') else '0';
441 20 zero_gravi
  ipb.free  <= not ipb.full;
442
  ipb.avail <= not ipb.empty;
443 6 zero_gravi
 
444
 
445
-- ****************************************************************************************************************************
446 31 zero_gravi
-- Instruction Issue (recoding of compressed instructions and 32-bit instruction word construction)
447
-- ****************************************************************************************************************************
448
 
449
 
450
  -- Issue Engine FSM Sync ------------------------------------------------------------------
451
  -- -------------------------------------------------------------------------------------------
452
  issue_engine_fsm_sync: process(rstn_i, clk_i)
453
  begin
454
    if (rstn_i = '0') then
455
      issue_engine.state <= ISSUE_ACTIVE;
456 40 zero_gravi
      issue_engine.align <= CPU_BOOT_ADDR(1); -- 32- or 16-bit boundary
457 31 zero_gravi
      issue_engine.buf   <= (others => '0');
458
    elsif rising_edge(clk_i) then
459
      if (ipb.clear = '1') then
460
        if (CPU_EXTENSION_RISCV_C = true) then
461
          if (execute_engine.pc(1) = '1') then -- branch to unaligned address?
462
            issue_engine.state <= ISSUE_REALIGN;
463
            issue_engine.align <= '1'; -- aligned on 16-bit boundary
464
          else
465
            issue_engine.state <= issue_engine.state_nxt;
466
            issue_engine.align <= '0'; -- aligned on 32-bit boundary
467
          end if;
468
        else
469
          issue_engine.state <= issue_engine.state_nxt;
470
          issue_engine.align <= '0'; -- always aligned on 32-bit boundaries
471
        end if;
472
      else
473
        issue_engine.state <= issue_engine.state_nxt;
474
        issue_engine.align <= issue_engine.align_nxt;
475
      end if;
476
      issue_engine.buf <= issue_engine.buf_nxt;
477
    end if;
478
  end process issue_engine_fsm_sync;
479
 
480
 
481
  -- Issue Engine FSM Comb ------------------------------------------------------------------
482
  -- -------------------------------------------------------------------------------------------
483 37 zero_gravi
  issue_engine_fsm_comb: process(issue_engine, ipb, execute_engine, ci_illegal, ci_instr32)
484 31 zero_gravi
  begin
485
    -- arbiter defaults --
486
    issue_engine.state_nxt <= issue_engine.state;
487
    issue_engine.align_nxt <= issue_engine.align;
488
    issue_engine.buf_nxt   <= issue_engine.buf;
489
 
490
    -- instruction prefetch buffer interface defaults --
491
    ipb.re <= '0';
492
 
493 37 zero_gravi
    -- instruction issue interface defaults --
494
    -- cmd_issue.data = <illegal_compressed_instruction> & <bus_error & alignment_error> & <is_compressed_instrucion> & <32-bit_instruction_word>
495
    cmd_issue.data  <= '0' & ipb.rdata(33 downto 32) & '0' & ipb.rdata(31 downto 0);
496
    cmd_issue.valid <= '0';
497 31 zero_gravi
 
498
    -- state machine --
499
    case issue_engine.state is
500
 
501
      when ISSUE_ACTIVE => -- issue instruction if available
502
      -- ------------------------------------------------------------
503
        if (ipb.avail = '1') then -- instructions available?
504
 
505
          if (issue_engine.align = '0') or (CPU_EXTENSION_RISCV_C = false) then -- begin check in LOW instruction half-word
506 41 zero_gravi
            if (execute_engine.state = DISPATCH) then -- ready to issue new command?
507 39 zero_gravi
              cmd_issue.valid      <= '1';
508 31 zero_gravi
              issue_engine.buf_nxt <= ipb.rdata(33 downto 32) & ipb.rdata(31 downto 16); -- store high half-word - we might need it for an unaligned uncompressed instruction
509
              if (ipb.rdata(1 downto 0) = "11") or (CPU_EXTENSION_RISCV_C = false) then -- uncompressed and "aligned"
510 37 zero_gravi
                ipb.re <= '1';
511
                cmd_issue.data <= '0' & ipb.rdata(33 downto 32) & '0' & ipb.rdata(31 downto 0);
512 31 zero_gravi
              else -- compressed
513 37 zero_gravi
                ipb.re <= '1';
514
                cmd_issue.data <= ci_illegal & ipb.rdata(33 downto 32) & '1' & ci_instr32;
515 31 zero_gravi
                issue_engine.align_nxt <= '1';
516
              end if;
517
            end if;
518
 
519
          else -- begin check in HIGH instruction half-word
520 41 zero_gravi
            if (execute_engine.state = DISPATCH) then -- ready to issue new command?
521 39 zero_gravi
              cmd_issue.valid      <= '1';
522 31 zero_gravi
              issue_engine.buf_nxt <= ipb.rdata(33 downto 32) & ipb.rdata(31 downto 16); -- store high half-word - we might need it for an unaligned uncompressed instruction
523
              if (issue_engine.buf(1 downto 0) = "11") then -- uncompressed and "unaligned"
524 37 zero_gravi
                ipb.re <= '1';
525
                cmd_issue.data <= '0' & issue_engine.buf(17 downto 16) & '0' & (ipb.rdata(15 downto 0) & issue_engine.buf(15 downto 0));
526 31 zero_gravi
              else -- compressed
527 36 zero_gravi
                -- do not read from ipb here!
528 37 zero_gravi
                cmd_issue.data <= ci_illegal & ipb.rdata(33 downto 32) & '1' & ci_instr32;
529 31 zero_gravi
                issue_engine.align_nxt <= '0';
530
              end if;
531
            end if;
532
          end if;
533
        end if;
534
 
535
      when ISSUE_REALIGN => -- re-align input fifos after a branch to an unaligned address
536
      -- ------------------------------------------------------------
537
        issue_engine.buf_nxt <= ipb.rdata(33 downto 32) & ipb.rdata(31 downto 16);
538
        if (ipb.avail = '1') then -- instructions available?
539
          ipb.re <= '1';
540
          issue_engine.state_nxt <= ISSUE_ACTIVE;
541
        end if;
542
 
543
      when others => -- undefined
544
      -- ------------------------------------------------------------
545
        issue_engine.state_nxt <= ISSUE_ACTIVE;
546
 
547
    end case;
548
  end process issue_engine_fsm_comb;
549
 
550 41 zero_gravi
  -- 16-bit instructions: half-word select --
551 31 zero_gravi
  ci_instr16 <= ipb.rdata(15 downto 0) when (issue_engine.align = '0') else issue_engine.buf(15 downto 0);
552
 
553
 
554
  -- Compressed Instructions Recoding -------------------------------------------------------
555
  -- -------------------------------------------------------------------------------------------
556
  neorv32_cpu_decompressor_inst_true:
557
  if (CPU_EXTENSION_RISCV_C = true) generate
558
    neorv32_cpu_decompressor_inst: neorv32_cpu_decompressor
559
    port map (
560
      -- instruction input --
561
      ci_instr16_i => ci_instr16, -- compressed instruction input
562
      -- instruction output --
563
      ci_illegal_o => ci_illegal, -- is an illegal compressed instruction
564
      ci_instr32_o => ci_instr32  -- 32-bit decompressed instruction
565
    );
566
  end generate;
567
 
568
  neorv32_cpu_decompressor_inst_false:
569
  if (CPU_EXTENSION_RISCV_C = false) generate
570
    ci_instr32 <= (others => '0');
571
    ci_illegal <= '0';
572
  end generate;
573
 
574
 
575
-- ****************************************************************************************************************************
576 6 zero_gravi
-- Instruction Execution
577
-- ****************************************************************************************************************************
578
 
579
 
580 2 zero_gravi
  -- Immediate Generator --------------------------------------------------------------------
581
  -- -------------------------------------------------------------------------------------------
582 38 zero_gravi
  imm_gen: process(execute_engine.i_reg, clk_i)
583 37 zero_gravi
    variable opcode_v : std_ulogic_vector(6 downto 0);
584 2 zero_gravi
  begin
585 38 zero_gravi
    opcode_v := execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c+2) & "11";
586 2 zero_gravi
    if rising_edge(clk_i) then
587 40 zero_gravi
      if (execute_engine.state = BRANCH) then -- next_PC as immediate for jump-and-link operations (=return address)
588 39 zero_gravi
        imm_o <= execute_engine.next_pc;
589 40 zero_gravi
      else -- "normal" immediate from instruction
590 39 zero_gravi
        case opcode_v is -- save some bits here, LSBs are always 11 for rv32
591
          when opcode_store_c => -- S-immediate
592
            imm_o(31 downto 11) <= (others => execute_engine.i_reg(31)); -- sign extension
593
            imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
594
            imm_o(04 downto 01) <= execute_engine.i_reg(11 downto 08);
595
            imm_o(00)           <= execute_engine.i_reg(07);
596
          when opcode_branch_c => -- B-immediate
597
            imm_o(31 downto 12) <= (others => execute_engine.i_reg(31)); -- sign extension
598
            imm_o(11)           <= execute_engine.i_reg(07);
599
            imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
600
            imm_o(04 downto 01) <= execute_engine.i_reg(11 downto 08);
601
            imm_o(00)           <= '0';
602
          when opcode_lui_c | opcode_auipc_c => -- U-immediate
603
            imm_o(31 downto 20) <= execute_engine.i_reg(31 downto 20);
604
            imm_o(19 downto 12) <= execute_engine.i_reg(19 downto 12);
605
            imm_o(11 downto 00) <= (others => '0');
606
          when opcode_jal_c => -- J-immediate
607
            imm_o(31 downto 20) <= (others => execute_engine.i_reg(31)); -- sign extension
608
            imm_o(19 downto 12) <= execute_engine.i_reg(19 downto 12);
609
            imm_o(11)           <= execute_engine.i_reg(20);
610
            imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
611
            imm_o(04 downto 01) <= execute_engine.i_reg(24 downto 21);
612
            imm_o(00)           <= '0';
613
          when opcode_atomic_c => -- atomic memory access
614 40 zero_gravi
            imm_o               <= (others => '0'); -- effective address is addr = reg + 0 = reg
615 39 zero_gravi
          when others => -- I-immediate
616
            imm_o(31 downto 11) <= (others => execute_engine.i_reg(31)); -- sign extension
617
            imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
618
            imm_o(04 downto 01) <= execute_engine.i_reg(24 downto 21);
619
            imm_o(00)           <= execute_engine.i_reg(20);
620
        end case;
621
      end if;
622 2 zero_gravi
    end if;
623
  end process imm_gen;
624
 
625
 
626
  -- Branch Condition Check -----------------------------------------------------------------
627
  -- -------------------------------------------------------------------------------------------
628 6 zero_gravi
  branch_check: process(execute_engine.i_reg, cmp_i)
629 2 zero_gravi
  begin
630 6 zero_gravi
    case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is
631 2 zero_gravi
      when funct3_beq_c => -- branch if equal
632 6 zero_gravi
        execute_engine.branch_taken <= cmp_i(alu_cmp_equal_c);
633 2 zero_gravi
      when funct3_bne_c => -- branch if not equal
634 6 zero_gravi
        execute_engine.branch_taken <= not cmp_i(alu_cmp_equal_c);
635 2 zero_gravi
      when funct3_blt_c | funct3_bltu_c => -- branch if less (signed/unsigned)
636 6 zero_gravi
        execute_engine.branch_taken <= cmp_i(alu_cmp_less_c);
637 2 zero_gravi
      when funct3_bge_c | funct3_bgeu_c => -- branch if greater or equal (signed/unsigned)
638 6 zero_gravi
        execute_engine.branch_taken <= not cmp_i(alu_cmp_less_c);
639 2 zero_gravi
      when others => -- undefined
640 6 zero_gravi
        execute_engine.branch_taken <= '0';
641 2 zero_gravi
    end case;
642
  end process branch_check;
643
 
644
 
645 6 zero_gravi
  -- Execute Engine FSM Sync ----------------------------------------------------------------
646 2 zero_gravi
  -- -------------------------------------------------------------------------------------------
647 12 zero_gravi
  -- for registers that DO require a specific reset state --
648 6 zero_gravi
  execute_engine_fsm_sync_rst: process(rstn_i, clk_i)
649 2 zero_gravi
  begin
650
    if (rstn_i = '0') then
651 40 zero_gravi
      execute_engine.pc     <= CPU_BOOT_ADDR(data_width_c-1 downto 1) & '0';
652
      execute_engine.state  <= SYS_WAIT;
653
      execute_engine.sleep  <= '0';
654
      execute_engine.if_rst <= '1'; -- instruction fetch is reset after system reset
655 2 zero_gravi
    elsif rising_edge(clk_i) then
656 39 zero_gravi
      -- PC update --
657
      if (execute_engine.pc_we = '1') then
658
        case execute_engine.pc_mux_sel is
659
          when "00"   => execute_engine.pc <= execute_engine.next_pc(data_width_c-1 downto 1) & '0'; -- normal (linear) increment
660 41 zero_gravi
          when "01"   => execute_engine.pc <= alu_add_i(data_width_c-1 downto 1) & '0'; -- jump/taken_branch
661 40 zero_gravi
          when "10"   => execute_engine.pc <= csr.mtvec(data_width_c-1 downto 1) & '0'; -- trap enter
662 41 zero_gravi
          when others => execute_engine.pc <= csr.mepc(data_width_c-1 downto 1) & '0';  -- trap exit
663 39 zero_gravi
        end case;
664
      end if;
665
      --
666 40 zero_gravi
      execute_engine.state  <= execute_engine.state_nxt;
667
      execute_engine.sleep  <= execute_engine.sleep_nxt;
668
      execute_engine.if_rst <= execute_engine.if_rst_nxt;
669 2 zero_gravi
    end if;
670 6 zero_gravi
  end process execute_engine_fsm_sync_rst;
671 2 zero_gravi
 
672 6 zero_gravi
 
673 12 zero_gravi
  -- for registers that do NOT require a specific reset state --
674 6 zero_gravi
  execute_engine_fsm_sync: process(clk_i)
675 2 zero_gravi
  begin
676
    if rising_edge(clk_i) then
677 42 zero_gravi
      execute_engine.state_prev <= execute_engine.state;
678
      execute_engine.i_reg      <= execute_engine.i_reg_nxt;
679
      execute_engine.is_ci      <= execute_engine.is_ci_nxt;
680
      execute_engine.is_cp_op   <= execute_engine.is_cp_op_nxt;
681 39 zero_gravi
      -- next PC (next linear instruction) --
682 40 zero_gravi
      if (execute_engine.state = EXECUTE) then
683
        if (execute_engine.is_ci = '1') then -- compressed instruction?
684
          execute_engine.next_pc <= std_ulogic_vector(unsigned(execute_engine.pc) + 2);
685
        else
686
          execute_engine.next_pc <= std_ulogic_vector(unsigned(execute_engine.pc) + 4);
687
        end if;
688 37 zero_gravi
      end if;
689 39 zero_gravi
      -- PC & IR of last "executed" instruction --
690
      if (execute_engine.state = EXECUTE) then
691 40 zero_gravi
        execute_engine.last_pc    <= execute_engine.pc;
692 39 zero_gravi
        execute_engine.i_reg_last <= execute_engine.i_reg;
693
      end if;
694
      -- main control bus --
695 6 zero_gravi
      ctrl <= ctrl_nxt;
696 2 zero_gravi
    end if;
697 6 zero_gravi
  end process execute_engine_fsm_sync;
698 2 zero_gravi
 
699 41 zero_gravi
  -- CSR access address --
700
  csr.addr <= execute_engine.i_reg(instr_csr_id_msb_c downto instr_csr_id_lsb_c);
701
 
702 20 zero_gravi
  -- PC output --
703 39 zero_gravi
  curr_pc_o <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- PC for ALU ops
704 6 zero_gravi
 
705 20 zero_gravi
 
706 6 zero_gravi
  -- CPU Control Bus Output -----------------------------------------------------------------
707
  -- -------------------------------------------------------------------------------------------
708 40 zero_gravi
  ctrl_output: process(ctrl, fetch_engine, trap_ctrl, atomic_ctrl, bus_fast_ir, execute_engine, csr)
709 2 zero_gravi
  begin
710 36 zero_gravi
    -- signals from execute engine --
711 2 zero_gravi
    ctrl_o <= ctrl;
712 36 zero_gravi
    -- current privilege level --
713
    ctrl_o(ctrl_priv_lvl_msb_c downto ctrl_priv_lvl_lsb_c) <= csr.privilege;
714
    -- register addresses --
715 40 zero_gravi
    ctrl_o(ctrl_rf_rs1_adr4_c downto ctrl_rf_rs1_adr0_c) <= execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c);
716
    ctrl_o(ctrl_rf_rs2_adr4_c downto ctrl_rf_rs2_adr0_c) <= execute_engine.i_reg(instr_rs2_msb_c downto instr_rs2_lsb_c);
717
    ctrl_o(ctrl_rf_rd_adr4_c  downto ctrl_rf_rd_adr0_c)  <= execute_engine.i_reg(instr_rd_msb_c  downto instr_rd_lsb_c);
718 12 zero_gravi
    -- fast bus access requests --
719 36 zero_gravi
    ctrl_o(ctrl_bus_if_c) <= bus_fast_ir;
720 12 zero_gravi
    -- bus error control --
721
    ctrl_o(ctrl_bus_ierr_ack_c) <= fetch_engine.bus_err_ack;
722
    ctrl_o(ctrl_bus_derr_ack_c) <= trap_ctrl.env_start_ack;
723 36 zero_gravi
    -- instruction's function blocks (for co-processors) --
724
    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);
725
    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);
726 39 zero_gravi
    -- locked bus operation (for atomica memory operations) --
727
    ctrl_o(ctrl_bus_lock_c) <= atomic_ctrl.lock; -- (bus) lock status
728 6 zero_gravi
  end process ctrl_output;
729 2 zero_gravi
 
730
 
731 6 zero_gravi
  -- Execute Engine FSM Comb ----------------------------------------------------------------
732
  -- -------------------------------------------------------------------------------------------
733 37 zero_gravi
  execute_engine_fsm_comb: process(execute_engine, fetch_engine, cmd_issue, trap_ctrl, csr, ctrl, csr_acc_valid,
734 39 zero_gravi
                                   alu_wait_i, bus_d_wait_i, ma_load_i, be_load_i, ma_store_i, be_store_i)
735 2 zero_gravi
    variable alu_immediate_v : std_ulogic;
736
    variable rs1_is_r0_v     : std_ulogic;
737 36 zero_gravi
    variable opcode_v        : std_ulogic_vector(6 downto 0);
738 39 zero_gravi
    variable is_atomic_lr_v  : std_ulogic;
739
    variable is_atomic_sc_v  : std_ulogic;
740 2 zero_gravi
  begin
741
    -- arbiter defaults --
742 29 zero_gravi
    execute_engine.state_nxt    <= execute_engine.state;
743
    execute_engine.i_reg_nxt    <= execute_engine.i_reg;
744
    execute_engine.is_cp_op_nxt <= execute_engine.is_cp_op;
745
    execute_engine.is_ci_nxt    <= execute_engine.is_ci;
746
    execute_engine.sleep_nxt    <= execute_engine.sleep;
747
    execute_engine.if_rst_nxt   <= execute_engine.if_rst;
748 39 zero_gravi
    --
749
    execute_engine.pc_mux_sel   <= (others => '0');
750
    execute_engine.pc_we        <= '0';
751 2 zero_gravi
 
752 6 zero_gravi
    -- instruction dispatch --
753 37 zero_gravi
    fetch_engine.reset          <= '0';
754 2 zero_gravi
 
755 6 zero_gravi
    -- trap environment control --
756 37 zero_gravi
    trap_ctrl.env_start_ack     <= '0';
757
    trap_ctrl.env_end           <= '0';
758 6 zero_gravi
 
759 2 zero_gravi
    -- exception trigger --
760 37 zero_gravi
    trap_ctrl.instr_be          <= '0';
761
    trap_ctrl.instr_ma          <= '0';
762
    trap_ctrl.env_call          <= '0';
763
    trap_ctrl.break_point       <= '0';
764
    illegal_compressed          <= '0';
765 2 zero_gravi
 
766 6 zero_gravi
    -- CSR access --
767 37 zero_gravi
    csr.we_nxt                  <= '0';
768
    csr.re_nxt                  <= '0';
769 6 zero_gravi
 
770 39 zero_gravi
    -- atomic operations control --
771
    atomic_ctrl.env_start       <= '0';
772
    atomic_ctrl.env_end         <= '0';
773
    atomic_ctrl.env_abort       <= '0';
774
 
775
    -- CONTROL DEFAULTS --
776 36 zero_gravi
    ctrl_nxt <= (others => '0'); -- default: all off
777 6 zero_gravi
    if (execute_engine.i_reg(instr_opcode_lsb_c+4) = '1') then -- ALU ops
778 36 zero_gravi
      ctrl_nxt(ctrl_alu_unsigned_c) <= execute_engine.i_reg(instr_funct3_lsb_c+0); -- unsigned ALU operation? (SLTIU, SLTU)
779 2 zero_gravi
    else -- branches
780 36 zero_gravi
      ctrl_nxt(ctrl_alu_unsigned_c) <= execute_engine.i_reg(instr_funct3_lsb_c+1); -- unsigned branches? (BLTU, BGEU)
781 2 zero_gravi
    end if;
782 40 zero_gravi
    -- memory access --
783 39 zero_gravi
    ctrl_nxt(ctrl_bus_unsigned_c)                            <= execute_engine.i_reg(instr_funct3_msb_c); -- unsigned LOAD (LBU, LHU)
784
    ctrl_nxt(ctrl_bus_size_msb_c downto ctrl_bus_size_lsb_c) <= execute_engine.i_reg(instr_funct3_lsb_c+1 downto instr_funct3_lsb_c); -- mem transfer size
785
    -- alu.shifter --
786 27 zero_gravi
    ctrl_nxt(ctrl_alu_shift_dir_c) <= execute_engine.i_reg(instr_funct3_msb_c); -- shift direction (left/right)
787
    ctrl_nxt(ctrl_alu_shift_ar_c)  <= execute_engine.i_reg(30); -- is arithmetic shift
788 40 zero_gravi
    -- ALU main control --
789
    ctrl_nxt(ctrl_alu_addsub_c)                         <= '0'; -- ADD(I)
790
    ctrl_nxt(ctrl_alu_func1_c  downto ctrl_alu_func0_c) <= alu_func_cmd_arith_c; -- default ALU function select: arithmetic
791
    ctrl_nxt(ctrl_alu_arith_c)                          <= alu_arith_cmd_addsub_c; -- default ALU arithmetic operation: ADDSUB
792 2 zero_gravi
 
793 26 zero_gravi
    -- is immediate ALU operation? --
794
    alu_immediate_v := not execute_engine.i_reg(instr_opcode_msb_c-1);
795 2 zero_gravi
 
796 26 zero_gravi
    -- is rs1 == r0? --
797
    rs1_is_r0_v := not or_all_f(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c));
798 2 zero_gravi
 
799 39 zero_gravi
    -- is atomic load-reservate/store-conditional? --
800
    if (CPU_EXTENSION_RISCV_A = true) and (execute_engine.i_reg(instr_opcode_lsb_c+2) = '1') then -- valid atomic sub-opcode
801
      is_atomic_lr_v := not execute_engine.i_reg(instr_funct5_lsb_c);
802
      is_atomic_sc_v :=     execute_engine.i_reg(instr_funct5_lsb_c);
803
    else
804
      is_atomic_lr_v := '0';
805
      is_atomic_sc_v := '0';
806
    end if;
807 26 zero_gravi
 
808 39 zero_gravi
 
809 6 zero_gravi
    -- state machine --
810
    case execute_engine.state is
811 2 zero_gravi
 
812 25 zero_gravi
      when SYS_WAIT => -- System delay cycle (used to wait for side effects to kick in) ((and to init r0 with zero if it is a physical register))
813 2 zero_gravi
      -- ------------------------------------------------------------
814 26 zero_gravi
        -- set reg_file's r0 to zero --
815 25 zero_gravi
        if (rf_r0_is_reg_c = true) then -- is r0 implemented as physical register, which has to be set to zero?
816 37 zero_gravi
          ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "11"; -- RF input = CSR output (hacky! results zero since there is no valid CSR_read)
817 36 zero_gravi
          ctrl_nxt(ctrl_rf_r0_we_c) <= '1'; -- force RF write access and force rd=r0
818 25 zero_gravi
        end if;
819
        --
820 6 zero_gravi
        execute_engine.state_nxt <= DISPATCH;
821 2 zero_gravi
 
822 39 zero_gravi
 
823 37 zero_gravi
      when DISPATCH => -- Get new command from instruction issue engine
824 25 zero_gravi
      -- ------------------------------------------------------------
825 39 zero_gravi
        execute_engine.pc_mux_sel <= "00"; -- linear next PC
826 40 zero_gravi
        -- IR update --
827
        execute_engine.is_ci_nxt <= cmd_issue.data(32); -- flag to indicate a de-compressed instruction beeing executed
828
        execute_engine.i_reg_nxt <= cmd_issue.data(31 downto 0);
829
        --
830 37 zero_gravi
        if (cmd_issue.valid = '1') then -- instruction available?
831 40 zero_gravi
          -- IR update - exceptions --
832
          trap_ctrl.instr_ma <= cmd_issue.data(33); -- misaligned instruction fetch address
833
          trap_ctrl.instr_be <= cmd_issue.data(34); -- bus access fault during instruction fetch
834
          illegal_compressed <= cmd_issue.data(35); -- invalid decompressed instruction
835 37 zero_gravi
          -- PC update --
836 27 zero_gravi
          execute_engine.if_rst_nxt <= '0';
837 40 zero_gravi
          execute_engine.pc_we      <= not execute_engine.if_rst; -- update PC with linear next_pc if there was NO non-linear PC modification
838
          -- any reason to go to trap state? --
839 37 zero_gravi
          if (execute_engine.sleep = '1') or (trap_ctrl.env_start = '1') or (trap_ctrl.exc_fire = '1') or ((cmd_issue.data(33) or cmd_issue.data(34)) = '1') then
840 13 zero_gravi
            execute_engine.state_nxt <= TRAP;
841
          else
842 14 zero_gravi
            execute_engine.state_nxt <= EXECUTE;
843 13 zero_gravi
          end if;
844
        end if;
845 2 zero_gravi
 
846 39 zero_gravi
 
847 11 zero_gravi
      when TRAP => -- Start trap environment (also used as cpu sleep state)
848 2 zero_gravi
      -- ------------------------------------------------------------
849 39 zero_gravi
        execute_engine.pc_mux_sel <= "10"; -- csr.mtvec (trap)
850 40 zero_gravi
        execute_engine.if_rst_nxt <= '1'; -- this will be a non-linear PC modification
851 34 zero_gravi
        if (trap_ctrl.env_start = '1') then -- trap triggered?
852
          trap_ctrl.env_start_ack   <= '1';
853 42 zero_gravi
          fetch_engine.reset        <= '1';
854 39 zero_gravi
          execute_engine.pc_we      <= '1';
855 34 zero_gravi
          execute_engine.sleep_nxt  <= '0'; -- waky waky
856
          execute_engine.state_nxt  <= SYS_WAIT;
857 2 zero_gravi
        end if;
858
 
859 39 zero_gravi
 
860 40 zero_gravi
      when EXECUTE => -- Decode and execute instruction (control has to be here for excatly 1 cyle in any case!)
861 2 zero_gravi
      -- ------------------------------------------------------------
862 36 zero_gravi
        opcode_v := execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c+2) & "11"; -- save some bits here, LSBs are always 11 for rv32
863
        case opcode_v is
864 2 zero_gravi
 
865 25 zero_gravi
          when opcode_alu_c | opcode_alui_c => -- (immediate) ALU operation
866 2 zero_gravi
          -- ------------------------------------------------------------
867 39 zero_gravi
            ctrl_nxt(ctrl_alu_opa_mux_c)   <= '0'; -- use RS1 as ALU.OPA
868
            ctrl_nxt(ctrl_alu_opb_mux_c)   <= alu_immediate_v; -- use IMM as ALU.OPB for immediate operations
869
            ctrl_nxt(ctrl_rf_in_mux_msb_c) <= '0'; -- RF input = ALU result
870 25 zero_gravi
 
871 39 zero_gravi
            -- ALU arithmetic operation type and ADD/SUB --
872
            if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_slt_c) or
873
               (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sltu_c) then
874
              ctrl_nxt(ctrl_alu_arith_c) <= alu_arith_cmd_slt_c;
875 29 zero_gravi
            else
876 39 zero_gravi
              ctrl_nxt(ctrl_alu_arith_c) <= alu_arith_cmd_addsub_c;
877 25 zero_gravi
            end if;
878
 
879 29 zero_gravi
            -- ADD/SUB --
880
            if ((alu_immediate_v = '0') and (execute_engine.i_reg(instr_funct7_msb_c-1) = '1')) or -- not an immediate op and funct7.6 set => SUB
881
               (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_slt_c) or -- SLT operation
882
               (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sltu_c) then -- SLTU operation
883
              ctrl_nxt(ctrl_alu_addsub_c) <= '1'; -- SUB/SLT
884
            else
885
              ctrl_nxt(ctrl_alu_addsub_c) <= '0'; -- ADD(I)
886
            end if;
887
 
888 39 zero_gravi
            -- ALU logic operation --
889
            case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is -- actual ALU.logic operation (re-coding)
890
              when funct3_xor_c => ctrl_nxt(ctrl_alu_logic1_c downto ctrl_alu_logic0_c) <= alu_logic_cmd_xor_c; -- XOR(I)
891
              when funct3_or_c  => ctrl_nxt(ctrl_alu_logic1_c downto ctrl_alu_logic0_c) <= alu_logic_cmd_or_c;  -- OR(I)
892 40 zero_gravi
              when others       => ctrl_nxt(ctrl_alu_logic1_c downto ctrl_alu_logic0_c) <= alu_logic_cmd_and_c; -- AND(I)
893 39 zero_gravi
            end case;
894
 
895 41 zero_gravi
            -- co-processor (cp) access? --
896 40 zero_gravi
            ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_muldiv_c; -- just in case a mul/div operation
897 39 zero_gravi
            if (CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alu_c(5)) and (execute_engine.i_reg(instr_funct7_lsb_c) = '1') then -- MULDIV CP op?
898
              execute_engine.is_cp_op_nxt                        <= '1'; -- this is a CP operation
899
              ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c;
900
            -- ALU operation - function select --
901
            else
902
              execute_engine.is_cp_op_nxt <= '0'; -- no CP operation
903
              case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is -- actual ALU.func operation (re-coding)
904
                when funct3_xor_c | funct3_or_c | funct3_and_c => ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_logic_c;
905
                when funct3_sll_c | funct3_sr_c                => ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_shift_c;
906
                when others                                    => ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_arith_c;
907
              end case;
908
            end if;
909
 
910 11 zero_gravi
            -- multi cycle alu operation? --
911 25 zero_gravi
            if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) or -- SLL shift operation?
912
               (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c) or -- SR shift operation?
913 39 zero_gravi
               ((CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_alu_c(5)) and (execute_engine.i_reg(instr_funct7_lsb_c) = '1')) then -- MULDIV CP op?
914 6 zero_gravi
              execute_engine.state_nxt <= ALU_WAIT;
915 26 zero_gravi
            else -- single cycle ALU operation
916 2 zero_gravi
              ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
917 6 zero_gravi
              execute_engine.state_nxt <= DISPATCH;
918 2 zero_gravi
            end if;
919
 
920 25 zero_gravi
          when opcode_lui_c | opcode_auipc_c => -- load upper immediate / add upper immediate to PC
921 2 zero_gravi
          -- ------------------------------------------------------------
922 27 zero_gravi
            ctrl_nxt(ctrl_alu_opa_mux_c) <= '1'; -- ALU.OPA = PC (for AUIPC only)
923
            ctrl_nxt(ctrl_alu_opb_mux_c) <= '1'; -- use IMM as ALU.OPB
924 39 zero_gravi
            ctrl_nxt(ctrl_alu_arith_c)   <= alu_arith_cmd_addsub_c; -- actual ALU operation = ADD
925
            ctrl_nxt(ctrl_alu_logic1_c downto ctrl_alu_logic0_c) <= alu_logic_cmd_movb_c; -- MOVB
926 25 zero_gravi
            if (execute_engine.i_reg(instr_opcode_lsb_c+5) = opcode_lui_c(5)) then -- LUI
927 39 zero_gravi
              ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_logic_c; -- actual ALU operation = MOVB
928 27 zero_gravi
            else -- AUIPC
929 39 zero_gravi
              ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_arith_c; -- actual ALU operation = ADD
930 2 zero_gravi
            end if;
931 39 zero_gravi
            ctrl_nxt(ctrl_rf_in_mux_msb_c) <= '0'; -- RF input = ALU result
932
            ctrl_nxt(ctrl_rf_wb_en_c)      <= '1'; -- valid RF write-back
933
            execute_engine.state_nxt       <= DISPATCH;
934 2 zero_gravi
 
935 39 zero_gravi
          when opcode_load_c | opcode_store_c | opcode_atomic_c => -- load/store / atomic memory access
936 2 zero_gravi
          -- ------------------------------------------------------------
937 27 zero_gravi
            ctrl_nxt(ctrl_alu_opa_mux_c) <= '0'; -- use RS1 as ALU.OPA
938
            ctrl_nxt(ctrl_alu_opb_mux_c) <= '1'; -- use IMM as ALU.OPB
939 39 zero_gravi
            ctrl_nxt(ctrl_bus_mo_we_c)   <= '1'; -- write to MAR and MDO (MDO only relevant for store)
940
            --
941
            if (CPU_EXTENSION_RISCV_A = false) or (execute_engine.i_reg(instr_opcode_lsb_c+2) = '0') then -- atomic (A) extension disabled or normal load/store
942
              execute_engine.state_nxt <= LOADSTORE_0;
943
            else -- atomic operation
944
              atomic_ctrl.env_start <= not execute_engine.i_reg(instr_funct5_lsb_c); -- LR: start LOCKED memory access environment
945
              if (execute_engine.i_reg(instr_funct5_msb_c downto instr_funct5_lsb_c) = funct5_a_sc_c) or -- store-conditional
946
                 (execute_engine.i_reg(instr_funct5_msb_c downto instr_funct5_lsb_c) = funct5_a_lr_c) then -- load-reservate
947
                execute_engine.state_nxt <= LOADSTORE_0;
948
              else -- unimplemented (atomic) instruction
949
                execute_engine.state_nxt <= SYS_WAIT;
950
              end if;
951
            end if;
952 2 zero_gravi
 
953 29 zero_gravi
          when opcode_branch_c | opcode_jal_c | opcode_jalr_c => -- branch / jump and link (with register)
954 2 zero_gravi
          -- ------------------------------------------------------------
955
            -- compute target address --
956 39 zero_gravi
            ctrl_nxt(ctrl_alu_arith_c) <= alu_arith_cmd_addsub_c; -- actual ALU operation = ADD
957
            ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_arith_c; -- actual ALU operation = ADD
958 29 zero_gravi
            if (execute_engine.i_reg(instr_opcode_lsb_c+3 downto instr_opcode_lsb_c+2) = opcode_jalr_c(3 downto 2)) then -- JALR
959
              ctrl_nxt(ctrl_alu_opa_mux_c) <= '0'; -- use RS1 as ALU.OPA (branch target address base)
960
            else -- JAL / branch
961
              ctrl_nxt(ctrl_alu_opa_mux_c) <= '1'; -- use PC as ALU.OPA (branch target address base)
962 2 zero_gravi
            end if;
963 29 zero_gravi
            ctrl_nxt(ctrl_alu_opb_mux_c) <= '1'; -- use IMM as ALU.OPB (branch target address offset)
964 39 zero_gravi
            --
965 40 zero_gravi
            execute_engine.state_nxt <= BRANCH;
966 2 zero_gravi
 
967 8 zero_gravi
          when opcode_fence_c => -- fence operations
968
          -- ------------------------------------------------------------
969 39 zero_gravi
            execute_engine.state_nxt <= FENCE_OP;
970 8 zero_gravi
 
971 2 zero_gravi
          when opcode_syscsr_c => -- system/csr access
972
          -- ------------------------------------------------------------
973 40 zero_gravi
            csr.re_nxt <= csr_acc_valid; -- always read CSR if valid access, only relevant for CSR-instructions
974 39 zero_gravi
            if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_env_c) then -- system/environment
975
              execute_engine.state_nxt <= SYS_ENV;
976 13 zero_gravi
            else -- CSR access
977
              execute_engine.state_nxt <= CSR_ACCESS;
978 2 zero_gravi
            end if;
979
 
980
          when others => -- undefined
981
          -- ------------------------------------------------------------
982 39 zero_gravi
            execute_engine.state_nxt <= SYS_WAIT;
983 2 zero_gravi
 
984
        end case;
985
 
986 39 zero_gravi
 
987
      when SYS_ENV => -- system environment operation - execution
988 2 zero_gravi
      -- ------------------------------------------------------------
989 40 zero_gravi
        execute_engine.pc_mux_sel <= "11"; -- csr.mepc (only relevant for MRET)
990 39 zero_gravi
        case execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) is
991
          when funct12_ecall_c => -- ECALL
992
            trap_ctrl.env_call <= '1';
993
          when funct12_ebreak_c => -- EBREAK
994
            trap_ctrl.break_point <= '1';
995
          when funct12_mret_c => -- MRET
996
            trap_ctrl.env_end    <= '1';
997 40 zero_gravi
            execute_engine.pc_we <= '1'; -- update PC from MEPC
998 39 zero_gravi
            fetch_engine.reset   <= '1';
999
            execute_engine.if_rst_nxt <= '1'; -- this is a non-linear PC modification
1000
          when funct12_wfi_c => -- WFI
1001
            execute_engine.sleep_nxt <= '1'; -- good night
1002
          when others => -- undefined
1003
            NULL;
1004
        end case;
1005
        execute_engine.state_nxt <= SYS_WAIT;
1006
 
1007
 
1008
      when CSR_ACCESS => -- read & write status and control register (CSR)
1009
      -- ------------------------------------------------------------
1010 27 zero_gravi
        -- CSR write access --
1011 6 zero_gravi
        case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is
1012 25 zero_gravi
          when funct3_csrrw_c | funct3_csrrwi_c => -- CSRRW(I)
1013 15 zero_gravi
            csr.we_nxt <= csr_acc_valid; -- always write CSR if valid access
1014 27 zero_gravi
          when funct3_csrrs_c | funct3_csrrsi_c | funct3_csrrc_c | funct3_csrrci_c => -- CSRRS(I) / CSRRC(I)
1015
            csr.we_nxt <= (not rs1_is_r0_v) and csr_acc_valid; -- write CSR if rs1/imm is not zero and if valid access
1016 29 zero_gravi
          when others => -- invalid
1017 27 zero_gravi
            csr.we_nxt <= '0';
1018 2 zero_gravi
        end case;
1019 27 zero_gravi
        -- register file write back --
1020 12 zero_gravi
        ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "11"; -- RF input = CSR output
1021 2 zero_gravi
        ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
1022 39 zero_gravi
        execute_engine.state_nxt  <= DISPATCH;
1023 2 zero_gravi
 
1024 39 zero_gravi
 
1025 19 zero_gravi
      when ALU_WAIT => -- wait for multi-cycle ALU operation (shifter or CP) to finish
1026 2 zero_gravi
      -- ------------------------------------------------------------
1027 39 zero_gravi
        ctrl_nxt(ctrl_rf_in_mux_msb_c) <= '0'; -- RF input = ALU result
1028
        ctrl_nxt(ctrl_rf_wb_en_c)      <= '1'; -- valid RF write-back (permanent write-back)
1029 29 zero_gravi
        -- cp access or alu shift? --
1030
        if (execute_engine.is_cp_op = '1') then
1031 39 zero_gravi
          ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c;
1032 29 zero_gravi
        else
1033 39 zero_gravi
          ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_shift_c;
1034 19 zero_gravi
        end if;
1035
        -- wait for result --
1036 6 zero_gravi
        if (alu_wait_i = '0') then
1037 29 zero_gravi
          execute_engine.state_nxt <= DISPATCH;
1038 2 zero_gravi
        end if;
1039
 
1040 39 zero_gravi
 
1041 6 zero_gravi
      when BRANCH => -- update PC for taken branches and jumps
1042
      -- ------------------------------------------------------------
1043 39 zero_gravi
        -- get and store return address (only relevant for jump-and-link operations) --
1044
        ctrl_nxt(ctrl_alu_opb_mux_c)                         <= '1'; -- use IMM as ALU.OPB (next_pc from immediate generator = return address)
1045
        ctrl_nxt(ctrl_alu_logic1_c downto ctrl_alu_logic0_c) <= alu_logic_cmd_movb_c; -- MOVB
1046
        ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c)   <= alu_func_cmd_logic_c; -- actual ALU operation = MOVB
1047
        ctrl_nxt(ctrl_rf_in_mux_msb_c)                       <= '0'; -- RF input = ALU result
1048 40 zero_gravi
        ctrl_nxt(ctrl_rf_wb_en_c)                            <= execute_engine.i_reg(instr_opcode_lsb_c+2); -- valid RF write-back? (is jump-and-link?)
1049 39 zero_gravi
        -- destination address --
1050
        execute_engine.pc_mux_sel <= "01"; -- alu.add = branch/jump destination
1051 40 zero_gravi
        if (execute_engine.i_reg(instr_opcode_lsb_c+2) = '1') or (execute_engine.branch_taken = '1') then -- JAL/JALR or taken branch
1052 39 zero_gravi
          execute_engine.pc_we      <= '1'; -- update PC
1053 20 zero_gravi
          fetch_engine.reset        <= '1'; -- trigger new instruction fetch from modified PC
1054
          execute_engine.if_rst_nxt <= '1'; -- this is a non-linear PC modification
1055
          execute_engine.state_nxt  <= SYS_WAIT;
1056 11 zero_gravi
        else
1057
          execute_engine.state_nxt <= DISPATCH;
1058 6 zero_gravi
        end if;
1059
 
1060 39 zero_gravi
 
1061
      when FENCE_OP => -- fence operations - execution
1062
      -- ------------------------------------------------------------
1063
        execute_engine.state_nxt  <= SYS_WAIT;
1064 40 zero_gravi
        execute_engine.pc_mux_sel <= "00"; -- linear next PC = "refetch" next instruction (only relevant for fence.i)
1065 39 zero_gravi
        -- FENCE.I --
1066
        if (execute_engine.i_reg(instr_funct3_lsb_c) = funct3_fencei_c(0)) and (CPU_EXTENSION_RISCV_Zifencei = true) then
1067
          execute_engine.pc_we        <= '1';
1068
          execute_engine.if_rst_nxt   <= '1'; -- this is a non-linear PC modification
1069
          fetch_engine.reset          <= '1';
1070
          ctrl_nxt(ctrl_bus_fencei_c) <= '1';
1071
        end if;
1072
        -- FENCE --
1073
        if (execute_engine.i_reg(instr_funct3_lsb_c) = funct3_fence_c(0)) then
1074
          ctrl_nxt(ctrl_bus_fence_c) <= '1';
1075
        end if;
1076
 
1077
 
1078 12 zero_gravi
      when LOADSTORE_0 => -- trigger memory request
1079 6 zero_gravi
      -- ------------------------------------------------------------
1080 39 zero_gravi
        if (execute_engine.i_reg(instr_opcode_msb_c-1) = '0') or (is_atomic_lr_v = '1') then -- normal load or atomic load-reservate
1081 12 zero_gravi
          ctrl_nxt(ctrl_bus_rd_c) <= '1'; -- read request
1082 39 zero_gravi
        else -- store
1083 12 zero_gravi
          ctrl_nxt(ctrl_bus_wr_c) <= '1'; -- write request
1084
        end if;
1085
        execute_engine.state_nxt <= LOADSTORE_1;
1086 6 zero_gravi
 
1087 39 zero_gravi
 
1088 12 zero_gravi
      when LOADSTORE_1 => -- memory latency
1089 6 zero_gravi
      -- ------------------------------------------------------------
1090 39 zero_gravi
        ctrl_nxt(ctrl_bus_mi_we_c) <= '1'; -- write input data to MDI (only relevant for LOAD)
1091
        execute_engine.state_nxt   <= LOADSTORE_2;
1092 6 zero_gravi
 
1093 39 zero_gravi
 
1094 12 zero_gravi
      when LOADSTORE_2 => -- wait for bus transaction to finish
1095 6 zero_gravi
      -- ------------------------------------------------------------
1096 40 zero_gravi
        -- ALU control (only relevant for atomic memory operations) --
1097
        if (CPU_EXTENSION_RISCV_A = true) then
1098
          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"
1099 39 zero_gravi
          ctrl_nxt(ctrl_alu_func1_c downto ctrl_alu_func0_c) <= alu_func_cmd_copro_c;
1100
        end if;
1101 40 zero_gravi
        -- register file write-back --
1102 39 zero_gravi
        ctrl_nxt(ctrl_rf_in_mux_lsb_c) <= '0'; -- RF input = ALU.res or MEM
1103
        if (is_atomic_sc_v = '1') then
1104 40 zero_gravi
          ctrl_nxt(ctrl_rf_in_mux_msb_c) <= '0'; -- RF input = ALU.res (only relevant for atomic.SC)
1105 39 zero_gravi
        else
1106 40 zero_gravi
          ctrl_nxt(ctrl_rf_in_mux_msb_c) <= '1'; -- RF input = memory input (only relevant for LOADs)
1107 39 zero_gravi
        end if;
1108
        --
1109
        ctrl_nxt(ctrl_bus_mi_we_c) <= '1'; -- keep writing input data to MDI (only relevant for load operations)
1110
        -- wait for memory response --
1111 37 zero_gravi
        if ((ma_load_i or be_load_i or ma_store_i or be_store_i) = '1') then -- abort if exception
1112 39 zero_gravi
          atomic_ctrl.env_abort     <= '1'; -- LOCKED (atomic) memory access environment failed (forces SC result to be non-zero => failure)
1113
          ctrl_nxt(ctrl_rf_wb_en_c) <= is_atomic_sc_v; -- SC failes: allow write back of non-zero result
1114
          execute_engine.state_nxt  <= DISPATCH;
1115 26 zero_gravi
        elsif (bus_d_wait_i = '0') then -- wait for bus to finish transaction
1116 39 zero_gravi
          if (execute_engine.i_reg(instr_opcode_msb_c-1) = '0') or (is_atomic_lr_v = '1') or (is_atomic_sc_v = '1') then -- load / load-reservate / store conditional
1117
            ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
1118 6 zero_gravi
          end if;
1119 39 zero_gravi
          atomic_ctrl.env_end      <= '1'; -- normal end of LOCKED (atomic) memory access environment
1120 6 zero_gravi
          execute_engine.state_nxt <= DISPATCH;
1121
        end if;
1122
 
1123 39 zero_gravi
 
1124 2 zero_gravi
      when others => -- undefined
1125
      -- ------------------------------------------------------------
1126 7 zero_gravi
        execute_engine.state_nxt <= SYS_WAIT;
1127 2 zero_gravi
 
1128
    end case;
1129 6 zero_gravi
  end process execute_engine_fsm_comb;
1130 2 zero_gravi
 
1131
 
1132 15 zero_gravi
-- ****************************************************************************************************************************
1133
-- Invalid Instruction / CSR access check
1134
-- ****************************************************************************************************************************
1135
 
1136
 
1137
  -- Illegal CSR Access Check ---------------------------------------------------------------
1138
  -- -------------------------------------------------------------------------------------------
1139 40 zero_gravi
  invalid_csr_access_check: process(execute_engine.i_reg, csr)
1140 42 zero_gravi
    variable csr_wacc_v           : std_ulogic; -- to check access to read-only CSRs
1141
    variable csr_mcounteren_hpm_v : std_ulogic_vector(28 downto 0); -- max 29 HPM counters
1142 40 zero_gravi
--  variable csr_racc_v : std_ulogic; -- to check access to write-only CSRs
1143 15 zero_gravi
  begin
1144 30 zero_gravi
    -- is this CSR instruction really going to write/read to/from a CSR? --
1145
    if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or
1146
       (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) then
1147
      csr_wacc_v := '1'; -- always write CSR
1148
--    csr_racc_v := or_all_f(execute_engine.i_reg(instr_rd_msb_c downto instr_rd_lsb_c)); -- read allowed if rd != 0
1149
    else
1150
      csr_wacc_v := or_all_f(execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c)); -- write allowed if rs1/uimm5 != 0
1151
--    csr_racc_v := '1'; -- always read CSR
1152
    end if;
1153
 
1154 42 zero_gravi
    -- low privilege level access to hpm counters? --
1155
    csr_mcounteren_hpm_v := (others => '0');
1156
    csr_mcounteren_hpm_v(HPM_NUM_CNTS-1 downto 0) := csr.mcounteren_hpm(HPM_NUM_CNTS-1 downto 0);
1157
 
1158 15 zero_gravi
    -- check CSR access --
1159 41 zero_gravi
    case csr.addr is
1160
      -- standard read/write CSRs --
1161 42 zero_gravi
      when csr_mstatus_c       => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
1162
      when csr_mstatush_c      => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
1163
      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
1164
      when csr_mie_c           => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
1165
      when csr_mtvec_c         => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
1166
      when csr_mscratch_c      => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
1167
      when csr_mepc_c          => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
1168
      when csr_mcause_c        => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
1169
      when csr_mcounteren_c    => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
1170
      when csr_mtval_c         => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
1171
      when csr_mip_c           => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
1172 15 zero_gravi
      --
1173 42 zero_gravi
      when csr_pmpcfg0_c | csr_pmpcfg1_c | csr_pmpcfg2_c  | csr_pmpcfg3_c  | csr_pmpcfg4_c  | csr_pmpcfg5_c  | csr_pmpcfg6_c  | csr_pmpcfg7_c |
1174
           csr_pmpcfg8_c | csr_pmpcfg9_c | csr_pmpcfg10_c | csr_pmpcfg11_c | csr_pmpcfg12_c | csr_pmpcfg13_c | csr_pmpcfg14_c | csr_pmpcfg15_c =>
1175
        csr_acc_valid <= csr.priv_m_mode; -- M-mode only
1176 15 zero_gravi
      --
1177 42 zero_gravi
      when csr_pmpaddr0_c  | csr_pmpaddr1_c  | csr_pmpaddr2_c  | csr_pmpaddr3_c  | csr_pmpaddr4_c  | csr_pmpaddr5_c  | csr_pmpaddr6_c  | csr_pmpaddr7_c  |
1178
           csr_pmpaddr8_c  | csr_pmpaddr9_c  | csr_pmpaddr10_c | csr_pmpaddr11_c | csr_pmpaddr12_c | csr_pmpaddr13_c | csr_pmpaddr14_c | csr_pmpaddr15_c |
1179
           csr_pmpaddr16_c | csr_pmpaddr17_c | csr_pmpaddr18_c | csr_pmpaddr19_c | csr_pmpaddr20_c | csr_pmpaddr21_c | csr_pmpaddr22_c | csr_pmpaddr23_c |
1180
           csr_pmpaddr24_c | csr_pmpaddr25_c | csr_pmpaddr26_c | csr_pmpaddr27_c | csr_pmpaddr28_c | csr_pmpaddr29_c | csr_pmpaddr30_c | csr_pmpaddr31_c |
1181
           csr_pmpaddr32_c | csr_pmpaddr33_c | csr_pmpaddr34_c | csr_pmpaddr35_c | csr_pmpaddr36_c | csr_pmpaddr37_c | csr_pmpaddr38_c | csr_pmpaddr39_c |
1182
           csr_pmpaddr40_c | csr_pmpaddr41_c | csr_pmpaddr42_c | csr_pmpaddr43_c | csr_pmpaddr44_c | csr_pmpaddr45_c | csr_pmpaddr46_c | csr_pmpaddr47_c |
1183
           csr_pmpaddr48_c | csr_pmpaddr49_c | csr_pmpaddr50_c | csr_pmpaddr51_c | csr_pmpaddr52_c | csr_pmpaddr53_c | csr_pmpaddr54_c | csr_pmpaddr55_c |
1184
           csr_pmpaddr56_c | csr_pmpaddr57_c | csr_pmpaddr58_c | csr_pmpaddr59_c | csr_pmpaddr60_c | csr_pmpaddr61_c | csr_pmpaddr62_c | csr_pmpaddr63_c =>
1185
        csr_acc_valid <= csr.priv_m_mode; -- M-mode only
1186 15 zero_gravi
      --
1187 41 zero_gravi
      when csr_mcountinhibit_c => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
1188 15 zero_gravi
      --
1189 42 zero_gravi
      when csr_mhpmevent3_c  | csr_mhpmevent4_c  | csr_mhpmevent5_c  | csr_mhpmevent6_c  | csr_mhpmevent7_c  | csr_mhpmevent8_c  |
1190
           csr_mhpmevent9_c  | csr_mhpmevent10_c | csr_mhpmevent11_c | csr_mhpmevent12_c | csr_mhpmevent13_c | csr_mhpmevent14_c |
1191
           csr_mhpmevent15_c | csr_mhpmevent16_c | csr_mhpmevent17_c | csr_mhpmevent18_c | csr_mhpmevent19_c | csr_mhpmevent20_c |
1192
           csr_mhpmevent21_c | csr_mhpmevent22_c | csr_mhpmevent23_c | csr_mhpmevent24_c | csr_mhpmevent25_c | csr_mhpmevent26_c |
1193
           csr_mhpmevent27_c | csr_mhpmevent28_c | csr_mhpmevent29_c | csr_mhpmevent30_c | csr_mhpmevent31_c =>
1194
        csr_acc_valid <= csr.priv_m_mode; -- M-mode only
1195 15 zero_gravi
      --
1196 42 zero_gravi
      when csr_mcycle_c        => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
1197
      when csr_minstret_c      => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
1198
      --
1199
      when csr_mhpmcounter3_c  | csr_mhpmcounter4_c  | csr_mhpmcounter5_c  | csr_mhpmcounter6_c  | csr_mhpmcounter7_c  | csr_mhpmcounter8_c  |
1200
           csr_mhpmcounter9_c  | csr_mhpmcounter10_c | csr_mhpmcounter11_c | csr_mhpmcounter12_c | csr_mhpmcounter13_c | csr_mhpmcounter14_c |
1201
           csr_mhpmcounter15_c | csr_mhpmcounter16_c | csr_mhpmcounter17_c | csr_mhpmcounter18_c | csr_mhpmcounter19_c | csr_mhpmcounter20_c |
1202
           csr_mhpmcounter21_c | csr_mhpmcounter22_c | csr_mhpmcounter23_c | csr_mhpmcounter24_c | csr_mhpmcounter25_c | csr_mhpmcounter26_c |
1203
           csr_mhpmcounter27_c | csr_mhpmcounter28_c | csr_mhpmcounter29_c | csr_mhpmcounter30_c | csr_mhpmcounter31_c =>
1204
        csr_acc_valid <= csr.priv_m_mode; -- M-mode only
1205
      --
1206
      when csr_mcycleh_c       => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
1207
      when csr_minstreth_c     => csr_acc_valid <= csr.priv_m_mode; -- M-mode only
1208
      --
1209
      when csr_mhpmcounter3h_c  | csr_mhpmcounter4h_c  | csr_mhpmcounter5h_c  | csr_mhpmcounter6h_c  | csr_mhpmcounter7h_c  | csr_mhpmcounter8h_c  |
1210
           csr_mhpmcounter9h_c  | csr_mhpmcounter10h_c | csr_mhpmcounter11h_c | csr_mhpmcounter12h_c | csr_mhpmcounter13h_c | csr_mhpmcounter14h_c |
1211
           csr_mhpmcounter15h_c | csr_mhpmcounter16h_c | csr_mhpmcounter17h_c | csr_mhpmcounter18h_c | csr_mhpmcounter19h_c | csr_mhpmcounter20h_c |
1212
           csr_mhpmcounter21h_c | csr_mhpmcounter22h_c | csr_mhpmcounter23h_c | csr_mhpmcounter24h_c | csr_mhpmcounter25h_c | csr_mhpmcounter26h_c |
1213
           csr_mhpmcounter27h_c | csr_mhpmcounter28h_c | csr_mhpmcounter29h_c | csr_mhpmcounter30h_c | csr_mhpmcounter31h_c =>
1214
        csr_acc_valid <= csr.priv_m_mode; -- M-mode only
1215
 
1216 41 zero_gravi
      -- standard read-only CSRs --
1217 42 zero_gravi
      when csr_cycle_c         => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_cy); -- M-mode, U-mode if authorized, read-only
1218
      when csr_time_c          => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_tm); -- M-mode, U-mode if authorized, read-only
1219
      when csr_instret_c       => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_ir); -- M-mode, U-mode if authorized, read-only
1220 15 zero_gravi
      --
1221 42 zero_gravi
      when csr_hpmcounter3_c   => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(0)); -- M-mode, U-mode if authorized, read-only
1222
      when csr_hpmcounter4_c   => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(1)); -- M-mode, U-mode if authorized, read-only
1223
      when csr_hpmcounter5_c   => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(2)); -- M-mode, U-mode if authorized, read-only
1224
      when csr_hpmcounter6_c   => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(3)); -- M-mode, U-mode if authorized, read-only
1225
      when csr_hpmcounter7_c   => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(4)); -- M-mode, U-mode if authorized, read-only
1226
      when csr_hpmcounter8_c   => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(5)); -- M-mode, U-mode if authorized, read-only
1227
      when csr_hpmcounter9_c   => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(6)); -- M-mode, U-mode if authorized, read-only
1228
      when csr_hpmcounter10_c  => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(7)); -- M-mode, U-mode if authorized, read-only
1229
      when csr_hpmcounter11_c  => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(8)); -- M-mode, U-mode if authorized, read-only
1230
      when csr_hpmcounter12_c  => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(9)); -- M-mode, U-mode if authorized, read-only
1231
      when csr_hpmcounter13_c  => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(10)); -- M-mode, U-mode if authorized, read-only
1232
      when csr_hpmcounter14_c  => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(11)); -- M-mode, U-mode if authorized, read-only
1233
      when csr_hpmcounter15_c  => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(12)); -- M-mode, U-mode if authorized, read-only
1234
      when csr_hpmcounter16_c  => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(13)); -- M-mode, U-mode if authorized, read-only
1235
      when csr_hpmcounter17_c  => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(14)); -- M-mode, U-mode if authorized, read-only
1236
      when csr_hpmcounter18_c  => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(15)); -- M-mode, U-mode if authorized, read-only
1237
      when csr_hpmcounter19_c  => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(16)); -- M-mode, U-mode if authorized, read-only
1238
      when csr_hpmcounter20_c  => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(17)); -- M-mode, U-mode if authorized, read-only
1239
      when csr_hpmcounter21_c  => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(18)); -- M-mode, U-mode if authorized, read-only
1240
      when csr_hpmcounter22_c  => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(19)); -- M-mode, U-mode if authorized, read-only
1241
      when csr_hpmcounter23_c  => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(20)); -- M-mode, U-mode if authorized, read-only
1242
      when csr_hpmcounter24_c  => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(21)); -- M-mode, U-mode if authorized, read-only
1243
      when csr_hpmcounter25_c  => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(22)); -- M-mode, U-mode if authorized, read-only
1244
      when csr_hpmcounter26_c  => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(23)); -- M-mode, U-mode if authorized, read-only
1245
      when csr_hpmcounter27_c  => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(24)); -- M-mode, U-mode if authorized, read-only
1246
      when csr_hpmcounter28_c  => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(25)); -- M-mode, U-mode if authorized, read-only
1247
      when csr_hpmcounter29_c  => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(26)); -- M-mode, U-mode if authorized, read-only
1248
      when csr_hpmcounter30_c  => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(27)); -- M-mode, U-mode if authorized, read-only
1249
      when csr_hpmcounter31_c  => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(28)); -- M-mode, U-mode if authorized, read-only
1250 22 zero_gravi
      --
1251 42 zero_gravi
      when csr_cycleh_c        => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_cy); -- M-mode, U-mode if authorized, read-only
1252
      when csr_timeh_c         => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_tm); -- M-mode, U-mode if authorized, read-only
1253
      when csr_instreth_c      => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr.mcounteren_ir); -- M-mode, U-mode if authorized, read-only
1254
      --
1255
      when csr_hpmcounter3h_c  => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(0)); -- M-mode, U-mode if authorized, read-only
1256
      when csr_hpmcounter4h_c  => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(1)); -- M-mode, U-mode if authorized, read-only
1257
      when csr_hpmcounter5h_c  => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(2)); -- M-mode, U-mode if authorized, read-only
1258
      when csr_hpmcounter6h_c  => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(3)); -- M-mode, U-mode if authorized, read-only
1259
      when csr_hpmcounter7h_c  => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(4)); -- M-mode, U-mode if authorized, read-only
1260
      when csr_hpmcounter8h_c  => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(5)); -- M-mode, U-mode if authorized, read-only
1261
      when csr_hpmcounter9h_c  => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(6)); -- M-mode, U-mode if authorized, read-only
1262
      when csr_hpmcounter10h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(7)); -- M-mode, U-mode if authorized, read-only
1263
      when csr_hpmcounter11h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(8)); -- M-mode, U-mode if authorized, read-only
1264
      when csr_hpmcounter12h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(9)); -- M-mode, U-mode if authorized, read-only
1265
      when csr_hpmcounter13h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(10)); -- M-mode, U-mode if authorized, read-only
1266
      when csr_hpmcounter14h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(11)); -- M-mode, U-mode if authorized, read-only
1267
      when csr_hpmcounter15h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(12)); -- M-mode, U-mode if authorized, read-only
1268
      when csr_hpmcounter16h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(13)); -- M-mode, U-mode if authorized, read-only
1269
      when csr_hpmcounter17h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(14)); -- M-mode, U-mode if authorized, read-only
1270
      when csr_hpmcounter18h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(15)); -- M-mode, U-mode if authorized, read-only
1271
      when csr_hpmcounter19h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(16)); -- M-mode, U-mode if authorized, read-only
1272
      when csr_hpmcounter20h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(17)); -- M-mode, U-mode if authorized, read-only
1273
      when csr_hpmcounter21h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(18)); -- M-mode, U-mode if authorized, read-only
1274
      when csr_hpmcounter22h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(19)); -- M-mode, U-mode if authorized, read-only
1275
      when csr_hpmcounter23h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(20)); -- M-mode, U-mode if authorized, read-only
1276
      when csr_hpmcounter24h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(21)); -- M-mode, U-mode if authorized, read-only
1277
      when csr_hpmcounter25h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(22)); -- M-mode, U-mode if authorized, read-only
1278
      when csr_hpmcounter26h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(23)); -- M-mode, U-mode if authorized, read-only
1279
      when csr_hpmcounter27h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(24)); -- M-mode, U-mode if authorized, read-only
1280
      when csr_hpmcounter28h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(25)); -- M-mode, U-mode if authorized, read-only
1281
      when csr_hpmcounter29h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(26)); -- M-mode, U-mode if authorized, read-only
1282
      when csr_hpmcounter30h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(27)); -- M-mode, U-mode if authorized, read-only
1283
      when csr_hpmcounter31h_c => csr_acc_valid <= (not csr_wacc_v) and (csr.priv_m_mode or csr_mcounteren_hpm_v(28)); -- M-mode, U-mode if authorized, read-only
1284
      --
1285
      when csr_mvendorid_c     => csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only
1286
      when csr_marchid_c       => csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only
1287
      when csr_mimpid_c        => csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only
1288
      when csr_mhartid_c       => csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only
1289 41 zero_gravi
      -- custom read-only CSRs --
1290 42 zero_gravi
      when csr_mzext_c         => csr_acc_valid <= (not csr_wacc_v) and csr.priv_m_mode; -- M-mode only, read-only
1291 29 zero_gravi
      --
1292 42 zero_gravi
      when others              => csr_acc_valid <= '0'; -- invalid access
1293 15 zero_gravi
    end case;
1294
  end process invalid_csr_access_check;
1295
 
1296
 
1297 2 zero_gravi
  -- Illegal Instruction Check --------------------------------------------------------------
1298
  -- -------------------------------------------------------------------------------------------
1299 26 zero_gravi
  illegal_instruction_check: process(execute_engine, csr_acc_valid)
1300 36 zero_gravi
    variable opcode_v : std_ulogic_vector(6 downto 0);
1301 2 zero_gravi
  begin
1302 11 zero_gravi
    -- illegal instructions are checked in the EXECUTE stage
1303 36 zero_gravi
    -- the execute engine should not commit any illegal instruction
1304 6 zero_gravi
    if (execute_engine.state = EXECUTE) then
1305 2 zero_gravi
      -- defaults --
1306
      illegal_instruction <= '0';
1307
      illegal_register    <= '0';
1308
 
1309 36 zero_gravi
      -- check opcode for rv32 --
1310
      if (execute_engine.i_reg(instr_opcode_lsb_c+1 downto instr_opcode_lsb_c) = "11") then
1311
        illegal_opcode_lsbs <= '0';
1312
      else
1313
        illegal_opcode_lsbs <= '1';
1314
      end if;
1315
 
1316 2 zero_gravi
      -- check instructions --
1317 36 zero_gravi
      opcode_v := execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c+2) & "11";
1318
      case opcode_v is
1319 2 zero_gravi
 
1320
        -- OPCODE check sufficient: LUI, UIPC, JAL --
1321
        when opcode_lui_c | opcode_auipc_c | opcode_jal_c =>
1322
          illegal_instruction <= '0';
1323 23 zero_gravi
          -- illegal E-CPU register? --
1324
          if (CPU_EXTENSION_RISCV_E = true) and (execute_engine.i_reg(instr_rd_msb_c) = '1') then
1325
            illegal_register <= '1';
1326
          end if;
1327 2 zero_gravi
 
1328
        when opcode_alui_c => -- check ALUI funct7
1329 6 zero_gravi
          if ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) and
1330
              (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000")) or -- shift logical left
1331
             ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c) and
1332
              ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000") and
1333
               (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0100000"))) then -- shift right
1334 2 zero_gravi
            illegal_instruction <= '1';
1335
          else
1336
            illegal_instruction <= '0';
1337
          end if;
1338 23 zero_gravi
          -- illegal E-CPU register? --
1339
          if (CPU_EXTENSION_RISCV_E = true) and ((execute_engine.i_reg(instr_rs1_msb_c) = '1') or (execute_engine.i_reg(instr_rd_msb_c) = '1')) then
1340
            illegal_register <= '1';
1341
          end if;
1342 39 zero_gravi
 
1343 2 zero_gravi
        when opcode_load_c => -- check LOAD funct3
1344 6 zero_gravi
          if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lb_c) or
1345
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lh_c) or
1346
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lw_c) or
1347
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lbu_c) or
1348
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lhu_c) then
1349 2 zero_gravi
            illegal_instruction <= '0';
1350
          else
1351
            illegal_instruction <= '1';
1352
          end if;
1353 23 zero_gravi
          -- illegal E-CPU register? --
1354
          if (CPU_EXTENSION_RISCV_E = true) and ((execute_engine.i_reg(instr_rs1_msb_c) = '1') or (execute_engine.i_reg(instr_rd_msb_c) = '1')) then
1355
            illegal_register <= '1';
1356
          end if;
1357 39 zero_gravi
 
1358 2 zero_gravi
        when opcode_store_c => -- check STORE funct3
1359 6 zero_gravi
          if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sb_c) or
1360
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sh_c) or
1361
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sw_c) then
1362 2 zero_gravi
            illegal_instruction <= '0';
1363
          else
1364
            illegal_instruction <= '1';
1365
          end if;
1366 23 zero_gravi
          -- illegal E-CPU register? --
1367
          if (CPU_EXTENSION_RISCV_E = true) and ((execute_engine.i_reg(instr_rs2_msb_c) = '1') or (execute_engine.i_reg(instr_rs1_msb_c) = '1')) then
1368
            illegal_register <= '1';
1369
          end if;
1370 2 zero_gravi
 
1371
        when opcode_branch_c => -- check BRANCH funct3
1372 6 zero_gravi
          if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_beq_c) or
1373
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bne_c) or
1374
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_blt_c) or
1375
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bge_c) or
1376
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bltu_c) or
1377
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bgeu_c) then
1378 2 zero_gravi
            illegal_instruction <= '0';
1379
          else
1380
            illegal_instruction <= '1';
1381
          end if;
1382 23 zero_gravi
          -- illegal E-CPU register? --
1383
          if (CPU_EXTENSION_RISCV_E = true) and ((execute_engine.i_reg(instr_rs2_msb_c) = '1') or (execute_engine.i_reg(instr_rs1_msb_c) = '1')) then
1384
            illegal_register <= '1';
1385
          end if;
1386 2 zero_gravi
 
1387
        when opcode_jalr_c => -- check JALR funct3
1388 6 zero_gravi
          if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "000") then
1389 2 zero_gravi
            illegal_instruction <= '0';
1390
          else
1391
            illegal_instruction <= '1';
1392
          end if;
1393 23 zero_gravi
          -- illegal E-CPU register? --
1394
          if (CPU_EXTENSION_RISCV_E = true) and ((execute_engine.i_reg(instr_rs1_msb_c) = '1') or (execute_engine.i_reg(instr_rd_msb_c) = '1')) then
1395
            illegal_register <= '1';
1396
          end if;
1397 2 zero_gravi
 
1398
        when opcode_alu_c => -- check ALU funct3 & funct7
1399 6 zero_gravi
          if (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV
1400 11 zero_gravi
            if (CPU_EXTENSION_RISCV_M = false) then -- not implemented
1401 2 zero_gravi
              illegal_instruction <= '1';
1402
            end if;
1403 6 zero_gravi
          elsif ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_subadd_c) or
1404
                 (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c)) and -- ADD/SUB or SRA/SRL check
1405
                ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000") and
1406
                 (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0100000")) then -- ADD/SUB or SRA/SRL select
1407 2 zero_gravi
            illegal_instruction <= '1';
1408
          else
1409
            illegal_instruction <= '0';
1410
          end if;
1411 23 zero_gravi
          -- illegal E-CPU register? --
1412
          if (CPU_EXTENSION_RISCV_E = true) and
1413
             ((execute_engine.i_reg(instr_rs2_msb_c) = '1') or (execute_engine.i_reg(instr_rs1_msb_c) = '1') or (execute_engine.i_reg(instr_rd_msb_c) = '1')) then
1414
            illegal_register <= '1';
1415
          end if;
1416 2 zero_gravi
 
1417 8 zero_gravi
        when opcode_fence_c => -- fence instructions --
1418
          if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fencei_c) and (CPU_EXTENSION_RISCV_Zifencei = true) then -- FENCE.I
1419
            illegal_instruction <= '0';
1420
          elsif (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fence_c) then -- FENCE
1421
            illegal_instruction <= '0';
1422
          else
1423
            illegal_instruction <= '1';
1424
          end if;
1425
 
1426 2 zero_gravi
        when opcode_syscsr_c => -- check system instructions --
1427
          -- CSR access --
1428 6 zero_gravi
          if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or
1429
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrs_c) or
1430
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrc_c) or
1431
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) or
1432
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrsi_c) or
1433
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrci_c) then
1434 15 zero_gravi
            -- valid CSR access? --
1435
            if (csr_acc_valid = '1') then
1436 2 zero_gravi
              illegal_instruction <= '0';
1437
            else
1438
              illegal_instruction <= '1';
1439
            end if;
1440 23 zero_gravi
            -- illegal E-CPU register? --
1441
            if (CPU_EXTENSION_RISCV_E = true) then
1442
              if (execute_engine.i_reg(instr_funct3_msb_c) = '0') then -- reg-reg CSR
1443
                illegal_register <= execute_engine.i_reg(instr_rs1_msb_c) or execute_engine.i_reg(instr_rd_msb_c);
1444
              else -- reg-imm CSR
1445
                illegal_register <= execute_engine.i_reg(instr_rd_msb_c);
1446
              end if;
1447
            end if;
1448 2 zero_gravi
 
1449
          -- ecall, ebreak, mret, wfi --
1450 6 zero_gravi
          elsif (execute_engine.i_reg(instr_rd_msb_c  downto instr_rd_lsb_c)  = "00000") and
1451
                (execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c) = "00000") then
1452 13 zero_gravi
            if (execute_engine.i_reg(instr_funct12_msb_c  downto instr_funct12_lsb_c) = funct12_ecall_c)  or -- ECALL
1453 11 zero_gravi
               (execute_engine.i_reg(instr_funct12_msb_c  downto instr_funct12_lsb_c) = funct12_ebreak_c) or -- EBREAK 
1454 13 zero_gravi
               (execute_engine.i_reg(instr_funct12_msb_c  downto instr_funct12_lsb_c) = funct12_mret_c)   or -- MRET
1455
               (execute_engine.i_reg(instr_funct12_msb_c  downto instr_funct12_lsb_c) = funct12_wfi_c) then  -- WFI
1456 2 zero_gravi
              illegal_instruction <= '0';
1457
            else
1458
              illegal_instruction <= '1';
1459
            end if;
1460
          else
1461
            illegal_instruction <= '1';
1462
          end if;
1463
 
1464 39 zero_gravi
        when opcode_atomic_c => -- atomic instructions --
1465
          if (CPU_EXTENSION_RISCV_A = true) and -- atomic memory operations (A extension) enabled
1466
             ((execute_engine.i_reg(instr_funct5_msb_c downto instr_funct5_lsb_c) = funct5_a_lr_c) or -- LR
1467
              (execute_engine.i_reg(instr_funct5_msb_c downto instr_funct5_lsb_c) = funct5_a_sc_c)) then -- SC
1468
            illegal_instruction <= '0';
1469
          else
1470
            illegal_instruction <= '1';
1471
          end if;
1472
 
1473 36 zero_gravi
        when others => -- undefined instruction -> illegal!
1474
          illegal_instruction <= '1';
1475 2 zero_gravi
 
1476
      end case;
1477
    else
1478 36 zero_gravi
      illegal_opcode_lsbs <= '0';
1479 2 zero_gravi
      illegal_instruction <= '0';
1480
      illegal_register    <= '0';
1481
    end if;
1482
  end process illegal_instruction_check;
1483
 
1484
  -- any illegal condition? --
1485 36 zero_gravi
  trap_ctrl.instr_il <= illegal_instruction or illegal_opcode_lsbs or illegal_register or illegal_compressed;
1486 2 zero_gravi
 
1487
 
1488 6 zero_gravi
-- ****************************************************************************************************************************
1489 38 zero_gravi
-- Exception and Interrupt (= Trap) Control
1490 6 zero_gravi
-- ****************************************************************************************************************************
1491 2 zero_gravi
 
1492
 
1493 6 zero_gravi
  -- Trap Controller ------------------------------------------------------------------------
1494 2 zero_gravi
  -- -------------------------------------------------------------------------------------------
1495 6 zero_gravi
  trap_controller: process(rstn_i, clk_i)
1496 40 zero_gravi
    variable mode_m_v, mode_u_v : std_ulogic;
1497 2 zero_gravi
  begin
1498
    if (rstn_i = '0') then
1499 6 zero_gravi
      trap_ctrl.exc_buf   <= (others => '0');
1500
      trap_ctrl.irq_buf   <= (others => '0');
1501
      trap_ctrl.exc_ack   <= '0';
1502
      trap_ctrl.irq_ack   <= (others => '0');
1503 40 zero_gravi
      trap_ctrl.cause     <= trap_reset_c;
1504 6 zero_gravi
      trap_ctrl.env_start <= '0';
1505 2 zero_gravi
    elsif rising_edge(clk_i) then
1506
      if (CPU_EXTENSION_RISCV_Zicsr = true) then
1507
        -- exception buffer: misaligned load/store/instruction address
1508 40 zero_gravi
        trap_ctrl.exc_buf(exception_lalign_c)    <= (trap_ctrl.exc_buf(exception_lalign_c)    or ma_load_i)          and (not trap_ctrl.exc_ack);
1509
        trap_ctrl.exc_buf(exception_salign_c)    <= (trap_ctrl.exc_buf(exception_salign_c)    or ma_store_i)         and (not trap_ctrl.exc_ack);
1510
        trap_ctrl.exc_buf(exception_ialign_c)    <= (trap_ctrl.exc_buf(exception_ialign_c)    or trap_ctrl.instr_ma) and (not trap_ctrl.exc_ack);
1511 2 zero_gravi
        -- exception buffer: load/store/instruction bus access error
1512 40 zero_gravi
        trap_ctrl.exc_buf(exception_laccess_c)   <= (trap_ctrl.exc_buf(exception_laccess_c)   or be_load_i)          and (not trap_ctrl.exc_ack);
1513
        trap_ctrl.exc_buf(exception_saccess_c)   <= (trap_ctrl.exc_buf(exception_saccess_c)   or be_store_i)         and (not trap_ctrl.exc_ack);
1514
        trap_ctrl.exc_buf(exception_iaccess_c)   <= (trap_ctrl.exc_buf(exception_iaccess_c)   or trap_ctrl.instr_be) and (not trap_ctrl.exc_ack);
1515 2 zero_gravi
        -- exception buffer: illegal instruction / env call / break point
1516 40 zero_gravi
        trap_ctrl.exc_buf(exception_m_envcall_c) <= (trap_ctrl.exc_buf(exception_m_envcall_c) or (trap_ctrl.env_call and csr.priv_m_mode)) and (not trap_ctrl.exc_ack);
1517
        trap_ctrl.exc_buf(exception_u_envcall_c) <= (trap_ctrl.exc_buf(exception_u_envcall_c) or (trap_ctrl.env_call and csr.priv_u_mode)) and (not trap_ctrl.exc_ack);
1518
        trap_ctrl.exc_buf(exception_break_c)     <= (trap_ctrl.exc_buf(exception_break_c)     or trap_ctrl.break_point)                    and (not trap_ctrl.exc_ack);
1519
        trap_ctrl.exc_buf(exception_iillegal_c)  <= (trap_ctrl.exc_buf(exception_iillegal_c)  or trap_ctrl.instr_il)                       and (not trap_ctrl.exc_ack);
1520 18 zero_gravi
        -- interrupt buffer: machine software/external/timer interrupt
1521 40 zero_gravi
        trap_ctrl.irq_buf(interrupt_msw_irq_c)   <= csr.mie_msie and (trap_ctrl.irq_buf(interrupt_msw_irq_c)   or msw_irq_i)   and (not (trap_ctrl.irq_ack(interrupt_msw_irq_c)   or csr.mip_clear(interrupt_msw_irq_c)));
1522
        trap_ctrl.irq_buf(interrupt_mext_irq_c)  <= csr.mie_meie and (trap_ctrl.irq_buf(interrupt_mext_irq_c)  or mext_irq_i)  and (not (trap_ctrl.irq_ack(interrupt_mext_irq_c)  or csr.mip_clear(interrupt_mext_irq_c)));
1523
        trap_ctrl.irq_buf(interrupt_mtime_irq_c) <= csr.mie_mtie and (trap_ctrl.irq_buf(interrupt_mtime_irq_c) or mtime_irq_i) and (not (trap_ctrl.irq_ack(interrupt_mtime_irq_c) or csr.mip_clear(interrupt_mtime_irq_c)));
1524 18 zero_gravi
        -- interrupt buffer: custom fast interrupts
1525 40 zero_gravi
        trap_ctrl.irq_buf(interrupt_firq_0_c)    <= csr.mie_firqe(0) and (trap_ctrl.irq_buf(interrupt_firq_0_c) or firq_i(0)) and (not (trap_ctrl.irq_ack(interrupt_firq_0_c) or csr.mip_clear(interrupt_firq_0_c)));
1526
        trap_ctrl.irq_buf(interrupt_firq_1_c)    <= csr.mie_firqe(1) and (trap_ctrl.irq_buf(interrupt_firq_1_c) or firq_i(1)) and (not (trap_ctrl.irq_ack(interrupt_firq_1_c) or csr.mip_clear(interrupt_firq_1_c)));
1527
        trap_ctrl.irq_buf(interrupt_firq_2_c)    <= csr.mie_firqe(2) and (trap_ctrl.irq_buf(interrupt_firq_2_c) or firq_i(2)) and (not (trap_ctrl.irq_ack(interrupt_firq_2_c) or csr.mip_clear(interrupt_firq_2_c)));
1528
        trap_ctrl.irq_buf(interrupt_firq_3_c)    <= csr.mie_firqe(3) and (trap_ctrl.irq_buf(interrupt_firq_3_c) or firq_i(3)) and (not (trap_ctrl.irq_ack(interrupt_firq_3_c) or csr.mip_clear(interrupt_firq_3_c)));
1529 6 zero_gravi
        -- trap control --
1530
        if (trap_ctrl.env_start = '0') then -- no started trap handler
1531 11 zero_gravi
          if (trap_ctrl.exc_fire = '1') or ((trap_ctrl.irq_fire = '1') and -- exception/IRQ detected!
1532 39 zero_gravi
             ((execute_engine.state = EXECUTE) or (execute_engine.state = TRAP))) then -- sample IRQs in EXECUTE or TRAP state only to continue execution even if permanent IRQ
1533 13 zero_gravi
            trap_ctrl.cause     <= trap_ctrl.cause_nxt;   -- capture source ID for program (for mcause csr)
1534 7 zero_gravi
            trap_ctrl.exc_ack   <= '1';                   -- clear execption
1535 42 zero_gravi
            trap_ctrl.irq_ack   <= trap_ctrl.irq_ack_nxt; -- clear interrupt with interrupt ACK mask
1536 13 zero_gravi
            trap_ctrl.env_start <= '1';                   -- now execute engine can start trap handler
1537 2 zero_gravi
          end if;
1538 6 zero_gravi
        else -- trap waiting to get started
1539
          if (trap_ctrl.env_start_ack = '1') then -- start of trap handler acknowledged by execution engine
1540
            trap_ctrl.exc_ack   <= '0';
1541
            trap_ctrl.irq_ack   <= (others => '0');
1542
            trap_ctrl.env_start <= '0';
1543 2 zero_gravi
          end if;
1544
        end if;
1545
      end if;
1546
    end if;
1547 6 zero_gravi
  end process trap_controller;
1548 2 zero_gravi
 
1549
  -- any exception/interrupt? --
1550 27 zero_gravi
  trap_ctrl.exc_fire <= or_all_f(trap_ctrl.exc_buf); -- exceptions/faults CANNOT be masked
1551
  trap_ctrl.irq_fire <= or_all_f(trap_ctrl.irq_buf) and csr.mstatus_mie; -- interrupts CAN be masked
1552 2 zero_gravi
 
1553 40 zero_gravi
  -- current pending interrupts (for CSR.MIP register) --
1554
  csr.mip_status <= trap_ctrl.irq_buf;
1555 2 zero_gravi
 
1556 40 zero_gravi
 
1557 42 zero_gravi
  -- Trap Priority Encoder ------------------------------------------------------------------
1558 6 zero_gravi
  -- -------------------------------------------------------------------------------------------
1559
  trap_priority: process(trap_ctrl)
1560 2 zero_gravi
  begin
1561
    -- defaults --
1562 6 zero_gravi
    trap_ctrl.cause_nxt   <= (others => '0');
1563
    trap_ctrl.irq_ack_nxt <= (others => '0');
1564 2 zero_gravi
 
1565 38 zero_gravi
    -- the following traps are caused by *asynchronous* exceptions (= interrupts)
1566 12 zero_gravi
    -- here we do need a specific acknowledge mask since several sources can trigger at once
1567 9 zero_gravi
 
1568 2 zero_gravi
    -- interrupt: 1.11 machine external interrupt --
1569 6 zero_gravi
    if (trap_ctrl.irq_buf(interrupt_mext_irq_c) = '1') then
1570 12 zero_gravi
      trap_ctrl.cause_nxt <= trap_mei_c;
1571 6 zero_gravi
      trap_ctrl.irq_ack_nxt(interrupt_mext_irq_c) <= '1';
1572 2 zero_gravi
 
1573 40 zero_gravi
    -- interrupt: 1.3 machine SW interrupt --
1574
    elsif (trap_ctrl.irq_buf(interrupt_msw_irq_c) = '1') then
1575
      trap_ctrl.cause_nxt <= trap_msi_c;
1576
      trap_ctrl.irq_ack_nxt(interrupt_msw_irq_c) <= '1';
1577
 
1578 2 zero_gravi
    -- interrupt: 1.7 machine timer interrupt --
1579 6 zero_gravi
    elsif (trap_ctrl.irq_buf(interrupt_mtime_irq_c) = '1') then
1580 12 zero_gravi
      trap_ctrl.cause_nxt <= trap_mti_c;
1581 6 zero_gravi
      trap_ctrl.irq_ack_nxt(interrupt_mtime_irq_c) <= '1';
1582 2 zero_gravi
 
1583
 
1584 14 zero_gravi
    -- interrupt: 1.16 fast interrupt channel 0 --
1585
    elsif (trap_ctrl.irq_buf(interrupt_firq_0_c) = '1') then
1586
      trap_ctrl.cause_nxt <= trap_firq0_c;
1587
      trap_ctrl.irq_ack_nxt(interrupt_firq_0_c) <= '1';
1588
 
1589
    -- interrupt: 1.17 fast interrupt channel 1 --
1590
    elsif (trap_ctrl.irq_buf(interrupt_firq_1_c) = '1') then
1591
      trap_ctrl.cause_nxt <= trap_firq1_c;
1592
      trap_ctrl.irq_ack_nxt(interrupt_firq_1_c) <= '1';
1593
 
1594
    -- interrupt: 1.18 fast interrupt channel 2 --
1595
    elsif (trap_ctrl.irq_buf(interrupt_firq_2_c) = '1') then
1596
      trap_ctrl.cause_nxt <= trap_firq2_c;
1597
      trap_ctrl.irq_ack_nxt(interrupt_firq_2_c) <= '1';
1598
 
1599
    -- interrupt: 1.19 fast interrupt channel 3 --
1600
    elsif (trap_ctrl.irq_buf(interrupt_firq_3_c) = '1') then
1601
      trap_ctrl.cause_nxt <= trap_firq3_c;
1602
      trap_ctrl.irq_ack_nxt(interrupt_firq_3_c) <= '1';
1603
 
1604
 
1605 42 zero_gravi
    -- the following traps are caused by *synchronous* exceptions (= 'classic' exceptions)
1606 12 zero_gravi
    -- here we do not need a specific acknowledge mask since only one exception (the one
1607 38 zero_gravi
    -- with highest priority) is evaluated at once
1608 4 zero_gravi
 
1609 38 zero_gravi
    -- exception: 0.1 instruction access fault --
1610 6 zero_gravi
    elsif (trap_ctrl.exc_buf(exception_iaccess_c) = '1') then
1611 12 zero_gravi
      trap_ctrl.cause_nxt <= trap_iba_c;
1612 2 zero_gravi
 
1613 38 zero_gravi
    -- exception: 0.2 illegal instruction --
1614 6 zero_gravi
    elsif (trap_ctrl.exc_buf(exception_iillegal_c) = '1') then
1615 12 zero_gravi
      trap_ctrl.cause_nxt <= trap_iil_c;
1616 2 zero_gravi
 
1617 38 zero_gravi
    -- exception: 0.0 instruction address misaligned --
1618 12 zero_gravi
    elsif (trap_ctrl.exc_buf(exception_ialign_c) = '1') then
1619
      trap_ctrl.cause_nxt <= trap_ima_c;
1620 2 zero_gravi
 
1621 12 zero_gravi
 
1622 38 zero_gravi
    -- exception: 0.11 environment call from M-mode --
1623 6 zero_gravi
    elsif (trap_ctrl.exc_buf(exception_m_envcall_c) = '1') then
1624 14 zero_gravi
      trap_ctrl.cause_nxt <= trap_menv_c;
1625 2 zero_gravi
 
1626 40 zero_gravi
    -- exception: 0.8 environment call from U-mode --
1627
    elsif (trap_ctrl.exc_buf(exception_u_envcall_c) = '1') then
1628
      trap_ctrl.cause_nxt <= trap_uenv_c;
1629
 
1630 38 zero_gravi
    -- exception: 0.3 breakpoint --
1631 6 zero_gravi
    elsif (trap_ctrl.exc_buf(exception_break_c) = '1') then
1632 12 zero_gravi
      trap_ctrl.cause_nxt <= trap_brk_c;
1633 2 zero_gravi
 
1634
 
1635 38 zero_gravi
    -- exception: 0.6 store address misaligned -
1636 6 zero_gravi
    elsif (trap_ctrl.exc_buf(exception_salign_c) = '1') then
1637 12 zero_gravi
      trap_ctrl.cause_nxt <= trap_sma_c;
1638 2 zero_gravi
 
1639 38 zero_gravi
    -- exception: 0.4 load address misaligned --
1640 6 zero_gravi
    elsif (trap_ctrl.exc_buf(exception_lalign_c) = '1') then
1641 12 zero_gravi
      trap_ctrl.cause_nxt <= trap_lma_c;
1642 2 zero_gravi
 
1643 38 zero_gravi
    -- exception: 0.7 store access fault --
1644 6 zero_gravi
    elsif (trap_ctrl.exc_buf(exception_saccess_c) = '1') then
1645 12 zero_gravi
      trap_ctrl.cause_nxt <= trap_sbe_c;
1646 2 zero_gravi
 
1647 38 zero_gravi
    -- exception: 0.5 load access fault --
1648 6 zero_gravi
    elsif (trap_ctrl.exc_buf(exception_laccess_c) = '1') then
1649 12 zero_gravi
      trap_ctrl.cause_nxt <= trap_lbe_c;
1650 2 zero_gravi
 
1651 42 zero_gravi
    -- not implemented --
1652 2 zero_gravi
    else
1653 6 zero_gravi
      trap_ctrl.cause_nxt   <= (others => '0');
1654
      trap_ctrl.irq_ack_nxt <= (others => '0');
1655 2 zero_gravi
    end if;
1656 6 zero_gravi
  end process trap_priority;
1657 39 zero_gravi
 
1658
 
1659
  -- Atomic Operation Controller ------------------------------------------------------------
1660
  -- -------------------------------------------------------------------------------------------
1661
  atomics_controller: process(rstn_i, clk_i)
1662
  begin
1663
    if (rstn_i = '0') then
1664
      atomic_ctrl.lock       <= '0';
1665
      atomic_ctrl.env_end_ff <= '0';
1666
    elsif rising_edge(clk_i) then
1667
      if (CPU_EXTENSION_RISCV_A = true) then
1668
        if (atomic_ctrl.env_end_ff = '1') or -- normal termination
1669 40 zero_gravi
           (atomic_ctrl.env_abort = '1') or  -- fast termination (error)
1670
           (trap_ctrl.env_start = '1') then  -- triggered trap -> failure
1671 39 zero_gravi
          atomic_ctrl.lock <= '0';
1672
        elsif (atomic_ctrl.env_start = '1') then
1673
          atomic_ctrl.lock <= '1';
1674
        end if;
1675
        atomic_ctrl.env_end_ff <= atomic_ctrl.env_end;
1676
      else
1677
        atomic_ctrl.lock       <= '0';
1678
        atomic_ctrl.env_end_ff <= '0';
1679
      end if;
1680
    end if;
1681
  end process atomics_controller;
1682 6 zero_gravi
 
1683 2 zero_gravi
 
1684 6 zero_gravi
-- ****************************************************************************************************************************
1685
-- Control and Status Registers (CSRs)
1686
-- ****************************************************************************************************************************
1687 2 zero_gravi
 
1688 27 zero_gravi
  -- Control and Status Registers Write Data ------------------------------------------------
1689
  -- -------------------------------------------------------------------------------------------
1690 36 zero_gravi
  csr_write_data: process(execute_engine.i_reg, csr.rdata, rs1_i)
1691
    variable csr_operand_v : std_ulogic_vector(data_width_c-1 downto 0);
1692 27 zero_gravi
  begin
1693 36 zero_gravi
    -- CSR operand source --
1694
    if (execute_engine.i_reg(instr_funct3_msb_c) = '1') then -- immediate
1695
      csr_operand_v := (others => '0');
1696 38 zero_gravi
      csr_operand_v(4 downto 0) := execute_engine.i_reg(19 downto 15); -- uimm5
1697 36 zero_gravi
    else -- register
1698
      csr_operand_v := rs1_i;
1699
    end if;
1700 40 zero_gravi
    -- tiny ALU for CSR write operations --
1701 27 zero_gravi
    case execute_engine.i_reg(instr_funct3_lsb_c+1 downto instr_funct3_lsb_c) is
1702 36 zero_gravi
      when "10"   => csr.wdata <= csr.rdata or csr_operand_v; -- CSRRS(I)
1703
      when "11"   => csr.wdata <= csr.rdata and (not csr_operand_v); -- CSRRC(I)
1704
      when others => csr.wdata <= csr_operand_v; -- CSRRW(I)
1705 27 zero_gravi
    end case;
1706
  end process csr_write_data;
1707
 
1708
 
1709 2 zero_gravi
  -- Control and Status Registers Write Access ----------------------------------------------
1710
  -- -------------------------------------------------------------------------------------------
1711
  csr_write_access: process(rstn_i, clk_i)
1712 42 zero_gravi
    variable pmpaddr_v : std_ulogic_vector(6 downto 0);
1713 2 zero_gravi
  begin
1714
    if (rstn_i = '0') then
1715 40 zero_gravi
      csr.we           <= '0';
1716 11 zero_gravi
      --
1717 6 zero_gravi
      csr.mstatus_mie  <= '0';
1718
      csr.mstatus_mpie <= '0';
1719 29 zero_gravi
      csr.mstatus_mpp  <= priv_mode_m_c; -- start in MACHINE mode
1720
      csr.privilege    <= priv_mode_m_c; -- start in MACHINE mode
1721 6 zero_gravi
      csr.mie_msie     <= '0';
1722
      csr.mie_meie     <= '0';
1723
      csr.mie_mtie     <= '0';
1724 14 zero_gravi
      csr.mie_firqe    <= (others => '0');
1725 6 zero_gravi
      csr.mtvec        <= (others => '0');
1726 36 zero_gravi
      csr.mscratch     <= x"19880704"; -- :)
1727 12 zero_gravi
      csr.mepc         <= (others => '0');
1728 42 zero_gravi
      -- mcause = TRAP_CODE_RESET (hardware reset, "non-maskable interrupt")
1729 40 zero_gravi
      csr.mcause                               <= (others => '0');
1730
      csr.mcause(csr.mcause'left)              <= trap_reset_c(trap_reset_c'left);
1731
      csr.mcause(trap_reset_c'left-1 downto 0) <= trap_reset_c(trap_reset_c'left-1 downto 0);
1732
      --
1733 41 zero_gravi
      csr.mtval     <= (others => '0');
1734
      csr.mip_clear <= (others => '0');
1735 42 zero_gravi
      --
1736 41 zero_gravi
      csr.pmpcfg    <= (others => (others => '0'));
1737
      csr.pmpaddr   <= (others => (others => '1'));
1738 34 zero_gravi
      --
1739 42 zero_gravi
      csr.mhpmevent <= (others => (others => '0'));
1740 41 zero_gravi
      --
1741 42 zero_gravi
      csr.mcounteren_cy  <= '0';
1742
      csr.mcounteren_tm  <= '0';
1743
      csr.mcounteren_ir  <= '0';
1744
      csr.mcounteren_hpm <= (others => '0');
1745
      --
1746
      csr.mcountinhibit_cy  <= '0';
1747
      csr.mcountinhibit_ir  <= '0';
1748
      csr.mcountinhibit_hpm <= (others => '0');
1749 2 zero_gravi
    elsif rising_edge(clk_i) then
1750 29 zero_gravi
      -- write access? --
1751
      csr.we <= csr.we_nxt;
1752 36 zero_gravi
      if (CPU_EXTENSION_RISCV_Zicsr = true) then
1753 4 zero_gravi
 
1754 40 zero_gravi
        -- defaults --
1755
        csr.mip_clear <= (others => '0');
1756
 
1757 36 zero_gravi
        -- --------------------------------------------------------------------------------
1758
        -- CSR access by application software
1759
        -- --------------------------------------------------------------------------------
1760
        if (csr.we = '1') then -- manual update
1761 41 zero_gravi
          case csr.addr is
1762 36 zero_gravi
 
1763
            -- machine trap setup --
1764
            -- --------------------------------------------------------------------
1765
            when csr_mstatus_c => -- R/W: mstatus - machine status register
1766
              csr.mstatus_mie  <= csr.wdata(03);
1767
              csr.mstatus_mpie <= csr.wdata(07);
1768
              if (CPU_EXTENSION_RISCV_U = true) then -- user mode implemented
1769
                csr.mstatus_mpp(0) <= csr.wdata(11) or csr.wdata(12);
1770
                csr.mstatus_mpp(1) <= csr.wdata(11) or csr.wdata(12);
1771 40 zero_gravi
              else -- only machine mode is available
1772
                csr.mstatus_mpp <= priv_mode_m_c;
1773 36 zero_gravi
              end if;
1774 41 zero_gravi
            when csr_mie_c => -- R/W: mie - machine interrupt enable register
1775 29 zero_gravi
              csr.mie_msie <= csr.wdata(03); -- machine SW IRQ enable
1776
              csr.mie_mtie <= csr.wdata(07); -- machine TIMER IRQ enable
1777
              csr.mie_meie <= csr.wdata(11); -- machine EXT IRQ enable
1778
              --
1779
              csr.mie_firqe(0) <= csr.wdata(16); -- fast interrupt channel 0
1780
              csr.mie_firqe(1) <= csr.wdata(17); -- fast interrupt channel 1
1781
              csr.mie_firqe(2) <= csr.wdata(18); -- fast interrupt channel 2
1782
              csr.mie_firqe(3) <= csr.wdata(19); -- fast interrupt channel 3
1783 36 zero_gravi
            when csr_mtvec_c => -- R/W: mtvec - machine trap-handler base address (for ALL exceptions)
1784 29 zero_gravi
              csr.mtvec <= csr.wdata(data_width_c-1 downto 2) & "00"; -- mtvec.MODE=0
1785 41 zero_gravi
            when csr_mcounteren_c => -- R/W: machine counter enable register
1786 42 zero_gravi
              csr.mcounteren_cy  <= csr.wdata(0); -- enable user-level access to cycle[h]
1787
              csr.mcounteren_tm  <= csr.wdata(1); -- enable user-level access to time[h]
1788
              csr.mcounteren_ir  <= csr.wdata(2); -- enable user-level access to instret[h]
1789
              csr.mcounteren_hpm <= csr.wdata(csr.mcounteren_hpm'left+3 downto 3); -- enable user-level access to mhpmcounterx[h]
1790 29 zero_gravi
 
1791 36 zero_gravi
            -- machine trap handling --
1792
            -- --------------------------------------------------------------------
1793
            when csr_mscratch_c =>  -- R/W: mscratch - machine scratch register
1794
              csr.mscratch <= csr.wdata;
1795
            when csr_mepc_c => -- R/W: mepc - machine exception program counter
1796
              csr.mepc <= csr.wdata(data_width_c-1 downto 1) & '0';
1797
            when csr_mcause_c => -- R/W: mcause - machine trap cause
1798
              csr.mcause <= (others => '0');
1799
              csr.mcause(csr.mcause'left) <= csr.wdata(31); -- 1: interrupt, 0: exception
1800
              csr.mcause(4 downto 0)      <= csr.wdata(4 downto 0); -- identifier
1801 40 zero_gravi
            when csr_mtval_c => -- R/W: mtval - machine bad address/instruction
1802 36 zero_gravi
              csr.mtval <= csr.wdata;
1803 40 zero_gravi
            when csr_mip_c => -- R/W: mip - machine interrupt pending
1804
              csr.mip_clear(interrupt_msw_irq_c)   <= not csr.wdata(03);
1805
              csr.mip_clear(interrupt_mtime_irq_c) <= not csr.wdata(07);
1806
              csr.mip_clear(interrupt_mext_irq_c)  <= not csr.wdata(11);
1807
              --
1808 41 zero_gravi
              csr.mip_clear(interrupt_firq_0_c) <= not csr.wdata(16);
1809
              csr.mip_clear(interrupt_firq_1_c) <= not csr.wdata(17);
1810
              csr.mip_clear(interrupt_firq_2_c) <= not csr.wdata(18);
1811
              csr.mip_clear(interrupt_firq_3_c) <= not csr.wdata(19);
1812 29 zero_gravi
 
1813 42 zero_gravi
            -- physical memory protection: R/W: pmpcfg* - PMP configuration registers --
1814 36 zero_gravi
            -- --------------------------------------------------------------------
1815 42 zero_gravi
            when csr_pmpcfg0_c | csr_pmpcfg1_c | csr_pmpcfg2_c  | csr_pmpcfg3_c  | csr_pmpcfg4_c  | csr_pmpcfg5_c  | csr_pmpcfg6_c  | csr_pmpcfg7_c |
1816
                 csr_pmpcfg8_c | csr_pmpcfg9_c | csr_pmpcfg10_c | csr_pmpcfg11_c | csr_pmpcfg12_c | csr_pmpcfg13_c | csr_pmpcfg14_c | csr_pmpcfg15_c =>
1817
              for i in 0 to PMP_NUM_REGIONS-1 loop
1818
                if (csr.addr(3 downto 0) = std_ulogic_vector(to_unsigned(i, 4))) then
1819
                  if (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpcfg access
1820
                    csr.pmpcfg(i)(0) <= csr.wdata((i mod 4)*8+0); -- R (rights.read)
1821
                    csr.pmpcfg(i)(1) <= csr.wdata((i mod 4)*8+1); -- W (rights.write)
1822
                    csr.pmpcfg(i)(2) <= csr.wdata((i mod 4)*8+2); -- X (rights.execute)
1823
                    csr.pmpcfg(i)(3) <= csr.wdata((i mod 4)*8+3) and csr.wdata((i mod 4)*8+4); -- A_L
1824
                    csr.pmpcfg(i)(4) <= csr.wdata((i mod 4)*8+3) and csr.wdata((i mod 4)*8+4); -- A_H - NAPOT/OFF only
1825
                    csr.pmpcfg(i)(5) <= '0'; -- reserved
1826
                    csr.pmpcfg(i)(6) <= '0'; -- reserved
1827
                    csr.pmpcfg(i)(7) <= csr.wdata((i mod 4)*8+7); -- L (locked / rights also enforced in m-mode)
1828 36 zero_gravi
                  end if;
1829 42 zero_gravi
                end if;
1830
              end loop; -- i (PMP regions)
1831 4 zero_gravi
 
1832 42 zero_gravi
            -- physical memory protection: R/W: pmpaddr* - PMP address registers --
1833 36 zero_gravi
            -- --------------------------------------------------------------------
1834 42 zero_gravi
            when csr_pmpaddr0_c  | csr_pmpaddr1_c  | csr_pmpaddr2_c  | csr_pmpaddr3_c  | csr_pmpaddr4_c  | csr_pmpaddr5_c  | csr_pmpaddr6_c  | csr_pmpaddr7_c  |
1835
                 csr_pmpaddr8_c  | csr_pmpaddr9_c  | csr_pmpaddr10_c | csr_pmpaddr11_c | csr_pmpaddr12_c | csr_pmpaddr13_c | csr_pmpaddr14_c | csr_pmpaddr15_c |
1836
                 csr_pmpaddr16_c | csr_pmpaddr17_c | csr_pmpaddr18_c | csr_pmpaddr19_c | csr_pmpaddr20_c | csr_pmpaddr21_c | csr_pmpaddr22_c | csr_pmpaddr23_c |
1837
                 csr_pmpaddr24_c | csr_pmpaddr25_c | csr_pmpaddr26_c | csr_pmpaddr27_c | csr_pmpaddr28_c | csr_pmpaddr29_c | csr_pmpaddr30_c | csr_pmpaddr31_c |
1838
                 csr_pmpaddr32_c | csr_pmpaddr33_c | csr_pmpaddr34_c | csr_pmpaddr35_c | csr_pmpaddr36_c | csr_pmpaddr37_c | csr_pmpaddr38_c | csr_pmpaddr39_c |
1839
                 csr_pmpaddr40_c | csr_pmpaddr41_c | csr_pmpaddr42_c | csr_pmpaddr43_c | csr_pmpaddr44_c | csr_pmpaddr45_c | csr_pmpaddr46_c | csr_pmpaddr47_c |
1840
                 csr_pmpaddr48_c | csr_pmpaddr49_c | csr_pmpaddr50_c | csr_pmpaddr51_c | csr_pmpaddr52_c | csr_pmpaddr53_c | csr_pmpaddr54_c | csr_pmpaddr55_c |
1841
                 csr_pmpaddr56_c | csr_pmpaddr57_c | csr_pmpaddr58_c | csr_pmpaddr59_c | csr_pmpaddr60_c | csr_pmpaddr61_c | csr_pmpaddr62_c | csr_pmpaddr63_c =>
1842
              for i in 0 to PMP_NUM_REGIONS-1 loop
1843
                pmpaddr_v := std_ulogic_vector(unsigned(csr_pmpaddr0_c(6 downto 0)) + i); -- adapt to *non-aligned* base address (csr_pmpaddr0_c)
1844
                if (csr.addr(6 downto 0) = pmpaddr_v) and (csr.pmpcfg(i)(7) = '0') then -- unlocked pmpaddr access
1845
                  csr.pmpaddr(i) <= csr.wdata;
1846
                  csr.pmpaddr(i)(index_size_f(PMP_MIN_GRANULARITY)-4 downto 0) <= (others => '1');
1847
                end if;
1848
              end loop; -- i (PMP regions)
1849 2 zero_gravi
 
1850 41 zero_gravi
            -- machine counter setup --
1851
            -- --------------------------------------------------------------------
1852
            when csr_mcountinhibit_c => -- R/W: mcountinhibit - machine counter-inhibit register
1853 42 zero_gravi
              csr.mcountinhibit_cy  <= csr.wdata(0); -- enable auto-increment of [m]cycle[h] counter
1854
              csr.mcountinhibit_ir  <= csr.wdata(2); -- enable auto-increment of [m]instret[h] counter
1855
              csr.mcountinhibit_hpm <= csr.wdata(csr.mcountinhibit_hpm'left+3 downto 3); -- enable auto-increment of [m]hpmcounter*[h] counter
1856 41 zero_gravi
 
1857 42 zero_gravi
            -- machine performance-monitoring event selector --
1858
            -- --------------------------------------------------------------------
1859
            when csr_mhpmevent3_c  | csr_mhpmevent4_c  | csr_mhpmevent5_c  | csr_mhpmevent6_c  | csr_mhpmevent7_c  | csr_mhpmevent8_c  |
1860
                 csr_mhpmevent9_c  | csr_mhpmevent10_c | csr_mhpmevent11_c | csr_mhpmevent12_c | csr_mhpmevent13_c | csr_mhpmevent14_c |
1861
                 csr_mhpmevent15_c | csr_mhpmevent16_c | csr_mhpmevent17_c | csr_mhpmevent18_c | csr_mhpmevent19_c | csr_mhpmevent20_c |
1862
                 csr_mhpmevent21_c | csr_mhpmevent22_c | csr_mhpmevent23_c | csr_mhpmevent24_c | csr_mhpmevent25_c | csr_mhpmevent26_c |
1863
                 csr_mhpmevent27_c | csr_mhpmevent28_c | csr_mhpmevent29_c | csr_mhpmevent30_c | csr_mhpmevent31_c => -- R/W: mhpmevent* - machine performance-monitoring event selector
1864
              for i in 0 to HPM_NUM_CNTS-1 loop
1865
                if (csr.addr(4 downto 0) = std_ulogic_vector(to_unsigned(i+3, 5))) then
1866
                  csr.mhpmevent(i) <= csr.wdata(csr.mhpmevent(i)'left downto 0);
1867
                end if;
1868
              end loop; -- i (CSRs)
1869
 
1870 36 zero_gravi
            -- undefined --
1871
            -- --------------------------------------------------------------------
1872
            when others =>
1873
              NULL;
1874 29 zero_gravi
 
1875 36 zero_gravi
          end case;
1876 29 zero_gravi
 
1877 36 zero_gravi
        -- --------------------------------------------------------------------------------
1878
        -- CSR access by hardware
1879
        -- --------------------------------------------------------------------------------
1880
        else
1881
 
1882 40 zero_gravi
          -- mcause, mepc, mtval: machine trap cause, PC and value register --
1883 36 zero_gravi
          -- --------------------------------------------------------------------
1884
          if (trap_ctrl.env_start_ack = '1') then -- trap handler starting?
1885 40 zero_gravi
            -- trap cause ID code --
1886
            csr.mcause <= (others => '0');
1887
            csr.mcause(csr.mcause'left) <= trap_ctrl.cause(trap_ctrl.cause'left); -- 1: interrupt, 0: exception
1888
            csr.mcause(4 downto 0)      <= trap_ctrl.cause(4 downto 0); -- identifier
1889
            -- trap PC --
1890 36 zero_gravi
            if (trap_ctrl.cause(trap_ctrl.cause'left) = '1') then -- for INTERRUPTS
1891
              csr.mepc  <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- this is the CURRENT pc = interrupted instruction
1892 40 zero_gravi
            else -- for EXCEPTIONS
1893 36 zero_gravi
              csr.mepc <= execute_engine.last_pc(data_width_c-1 downto 1) & '0'; -- this is the LAST pc = last executed instruction
1894 40 zero_gravi
            end if;
1895
            -- trap value --
1896
            case trap_ctrl.cause is
1897
              when trap_ima_c | trap_iba_c => -- misaligned instruction address OR instruction access error
1898 36 zero_gravi
                csr.mtval <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- address of faulting instruction
1899 40 zero_gravi
              when trap_brk_c => -- breakpoint
1900
                csr.mtval <= execute_engine.last_pc(data_width_c-1 downto 1) & '0'; -- address of breakpoint instruction
1901
              when trap_lma_c | trap_lbe_c | trap_sma_c | trap_sbe_c => -- misaligned load/store address OR load/store access error
1902
                csr.mtval <= mar_i; -- faulting data access address
1903
              when trap_iil_c => -- illegal instruction
1904 36 zero_gravi
                csr.mtval <= execute_engine.i_reg_last; -- faulting instruction itself
1905 40 zero_gravi
              when others => -- everything else including interrupts
1906
                csr.mtval <= (others => '0');
1907
            end case;
1908 2 zero_gravi
          end if;
1909
 
1910 36 zero_gravi
          -- mstatus: context switch --
1911
          -- --------------------------------------------------------------------
1912
          if (trap_ctrl.env_start_ack = '1') then -- ENTER: trap handler starting?
1913
            csr.mstatus_mie  <= '0'; -- disable interrupts
1914
            csr.mstatus_mpie <= csr.mstatus_mie; -- buffer previous mie state
1915
            if (CPU_EXTENSION_RISCV_U = true) then -- implement user mode
1916
              csr.privilege   <= priv_mode_m_c; -- execute trap in machine mode
1917
              csr.mstatus_mpp <= csr.privilege; -- buffer previous privilege mode
1918 2 zero_gravi
            end if;
1919 36 zero_gravi
          elsif (trap_ctrl.env_end = '1') then -- EXIT: return from exception
1920
            csr.mstatus_mie  <= csr.mstatus_mpie; -- restore global IRQ enable flag
1921
            csr.mstatus_mpie <= '1';
1922
            if (CPU_EXTENSION_RISCV_U = true) then -- implement user mode
1923
              csr.privilege   <= csr.mstatus_mpp; -- go back to previous privilege mode
1924 40 zero_gravi
              csr.mstatus_mpp <= priv_mode_m_c;
1925 30 zero_gravi
            end if;
1926 2 zero_gravi
          end if;
1927 36 zero_gravi
          -- user mode NOT implemented --
1928
          if (CPU_EXTENSION_RISCV_U = false) then
1929
            csr.privilege   <= priv_mode_m_c;
1930
            csr.mstatus_mpp <= priv_mode_m_c;
1931 15 zero_gravi
          end if;
1932 29 zero_gravi
 
1933 36 zero_gravi
        end if; -- hardware csr access
1934 29 zero_gravi
 
1935 34 zero_gravi
      end if;
1936 2 zero_gravi
    end if;
1937
  end process csr_write_access;
1938
 
1939 40 zero_gravi
  -- decode privilege mode --
1940
  csr.priv_m_mode <= '1' when (csr.privilege = priv_mode_m_c)  or (CPU_EXTENSION_RISCV_U = false) else '0';
1941
  csr.priv_u_mode <= '1' when (csr.privilege = priv_mode_u_c) and (CPU_EXTENSION_RISCV_U = true)  else '0';
1942
 
1943 36 zero_gravi
  -- PMP configuration output to bus unit --
1944 34 zero_gravi
  pmp_output: process(csr)
1945
  begin
1946
    pmp_addr_o <= (others => (others => '0'));
1947
    pmp_ctrl_o <= (others => (others => '0'));
1948 42 zero_gravi
    for i in 0 to PMP_NUM_REGIONS-1 loop
1949
      pmp_addr_o(i) <= csr.pmpaddr(i) & "11";
1950
      pmp_addr_o(i)(index_size_f(PMP_MIN_GRANULARITY)-4 downto 0) <= (others => '1');
1951
      pmp_ctrl_o(i) <= csr.pmpcfg(i);
1952
    end loop; -- i
1953
  end process pmp_output;
1954
 
1955
  -- PMP read dummy --
1956
  pmp_rd_dummy: process(csr)
1957
  begin
1958
    csr.pmpcfg_rd  <= (others => (others => '0'));
1959
    csr.pmpaddr_rd <= (others => (others => '0'));
1960
    for i in 0 to PMP_NUM_REGIONS-1 loop
1961
      csr.pmpcfg_rd(i)  <= csr.pmpcfg(i);
1962
      csr.pmpaddr_rd(i) <= csr.pmpaddr(i);
1963
      if (csr.pmpcfg(i)(4 downto 3) = "00") then -- mode = off
1964
        csr.pmpaddr_rd(i)(index_size_f(PMP_MIN_GRANULARITY)-3 downto 0) <= (others => '0'); -- required for granularity check by SW
1965
      end if;
1966
    end loop; -- i
1967
  end process pmp_rd_dummy;
1968
 
1969
 
1970
  -- Control and Status Registers - Counters ------------------------------------------------
1971
  -- -------------------------------------------------------------------------------------------
1972
  csr_counters: process(clk_i)
1973
  begin
1974
    -- Counter CSRs (each counter is split into two 32-bit counters)
1975
    if rising_edge(clk_i) then
1976
 
1977
      -- [m]cycle --
1978
      if (csr.we = '1') and (csr.addr = csr_mcycle_c) then -- write access
1979
        csr.mcycle <= '0' & csr.wdata;
1980
        mcycle_msb <= '0';
1981
      elsif (csr.mcountinhibit_cy = '0') and (cnt_event(hpmcnt_event_cy_c) = '1') then -- non-inhibited automatic update
1982
        csr.mcycle <= std_ulogic_vector(unsigned(csr.mcycle) + 1);
1983
        mcycle_msb <= csr.mcycle(csr.mcycle'left);
1984
      end if;
1985
 
1986
      -- [m]cycleh --
1987
      if (csr.we = '1') and (csr.addr = csr_mcycleh_c) then -- write access
1988
        csr.mcycleh <= csr.wdata;
1989
      elsif ((mcycle_msb xor csr.mcycle(csr.mcycle'left)) = '1') then -- automatic update (continued)
1990
        csr.mcycleh <= std_ulogic_vector(unsigned(csr.mcycleh) + 1);
1991
      end if;
1992
 
1993
      -- [m]instret --
1994
      if (csr.we = '1') and (csr.addr = csr_minstret_c) then -- write access
1995
        csr.minstret <= '0' & csr.wdata;
1996
        minstret_msb <= '0';
1997
      elsif (csr.mcountinhibit_ir = '0') and (cnt_event(hpmcnt_event_ir_c) = '1') and (cnt_event(hpmcnt_event_cy_c) = '1') then -- non-inhibited automatic update
1998
        csr.minstret <= std_ulogic_vector(unsigned(csr.minstret) + 1);
1999
        minstret_msb <= csr.minstret(csr.minstret'left);
2000
      end if;
2001
 
2002
      -- [m]instreth --
2003
      if (csr.we = '1') and (csr.addr = csr_minstreth_c) then -- write access
2004
        csr.minstreth <= csr.wdata;
2005
      elsif ((minstret_msb xor csr.minstret(csr.minstret'left)) = '1') then -- automatic update (continued)
2006
        csr.minstreth <= std_ulogic_vector(unsigned(csr.minstreth) + 1);
2007
      end if;
2008
 
2009
      -- [machine] high performance counters --
2010
      for i in 0 to HPM_NUM_CNTS-1 loop
2011
        -- [m]hpmcounter* --
2012
        if (csr.we = '1') and (csr.addr = std_ulogic_vector(unsigned(csr_mhpmcounter3_c) + i)) then -- write access
2013
          csr.mhpmcounter(i) <= '0' & csr.wdata;
2014
          mhpmcounter_msb(i) <= '0';
2015
        elsif (csr.mcountinhibit_hpm(i) = '0') and (hpmcnt_trigger(i) = '1') then -- non-inhibited automatic update
2016
          csr.mhpmcounter(i) <= std_ulogic_vector(unsigned(csr.mhpmcounter(i)) + 1);
2017
          mhpmcounter_msb(i) <= csr.mhpmcounter(i)(csr.mhpmcounter(i)'left);
2018
        end if;
2019
 
2020
        -- [m]hpmcounter*h --
2021
        if (csr.we = '1') and (csr.addr = std_ulogic_vector(unsigned(csr_mhpmcounter3h_c) + i)) then -- write access
2022
          csr.mhpmcounterh(i) <= csr.wdata;
2023
        elsif ((mhpmcounter_msb(i) xor csr.mhpmcounter(i)(csr.mhpmcounter(i)'left)) = '1') then -- automatic update (continued)
2024
          csr.mhpmcounterh(i) <= std_ulogic_vector(unsigned(csr.mhpmcounterh(i)) + 1);
2025
        end if;
2026 34 zero_gravi
      end loop; -- i
2027 42 zero_gravi
 
2028 34 zero_gravi
    end if;
2029 42 zero_gravi
  end process csr_counters;
2030 34 zero_gravi
 
2031 42 zero_gravi
  -- hpm read dummy --
2032
  hpm_rd_dummy: process(csr)
2033
  begin
2034
    csr.mhpmevent_rd    <= (others => (others => '0'));
2035
    csr.mhpmcounter_rd  <= (others => (others => '0'));
2036
    csr.mhpmcounterh_rd <= (others => (others => '0'));
2037
    for i in 0 to HPM_NUM_CNTS-1 loop
2038
      csr.mhpmevent_rd(i)    <= csr.mhpmevent(i);
2039
      csr.mhpmcounter_rd(i)  <= csr.mhpmcounter(i);
2040
      csr.mhpmcounterh_rd(i) <= csr.mhpmcounterh(i);
2041
    end loop; -- i
2042
  end process hpm_rd_dummy;
2043 34 zero_gravi
 
2044 42 zero_gravi
 
2045
  -- (HPM) Counter Event Control ------------------------------------------------------------
2046
  -- -------------------------------------------------------------------------------------------
2047
  hpmcnt_ctrl: process(clk_i)
2048
  begin
2049
    if rising_edge(clk_i) then
2050
      cnt_event      <= cnt_event_nxt;
2051
      hpmcnt_trigger <= (others => '0'); -- default
2052
      for i in 0 to HPM_NUM_CNTS-1 loop
2053
        -- enabled selected triggers by ANDing events and configuration bits --
2054
        -- OR everything to see if counter should increment --
2055
        -- AND with inverted sleep flag to increment only when CPU is awake --
2056
        hpmcnt_trigger(i) <= (or_all_f(cnt_event and csr.mhpmevent(i)(cnt_event'left downto 0))) and (not execute_engine.sleep);
2057
      end loop; -- i
2058
    end if;
2059
  end process hpmcnt_ctrl;
2060
 
2061
  -- counter event trigger - RISC-V specific --
2062
  cnt_event_nxt(hpmcnt_event_cy_c)    <= not execute_engine.sleep; -- active cycle
2063
  cnt_event_nxt(hpmcnt_event_never_c) <= '0'; -- undefined (never)
2064
  cnt_event_nxt(hpmcnt_event_ir_c)    <= '1' when (execute_engine.state = EXECUTE) else '0'; -- retired instruction
2065
 
2066
  -- counter event trigger - custom / NEORV32-specific --
2067
  cnt_event_nxt(hpmcnt_event_cir_c)     <= '1' when (execute_engine.state = EXECUTE)    and (execute_engine.is_ci = '1')             else '0'; -- retired compressed instruction
2068
  cnt_event_nxt(hpmcnt_event_wait_if_c) <= '1' when (fetch_engine.state = IFETCH_ISSUE) and (fetch_engine.state_prev = IFETCH_ISSUE) else '0'; -- instruction fetch memory wait cycle
2069
  cnt_event_nxt(hpmcnt_event_wait_ii_c) <= '1' when (execute_engine.state = DISPATCH)   and (execute_engine.state_prev = DISPATCH)   else '0'; -- instruction issue wait cycle
2070
 
2071
  cnt_event_nxt(hpmcnt_event_load_c)    <= '1' when (execute_engine.state = LOADSTORE_1) and (ctrl(ctrl_bus_rd_c) = '1')               else '0'; -- load operation
2072
  cnt_event_nxt(hpmcnt_event_store_c)   <= '1' when (execute_engine.state = LOADSTORE_1) and (ctrl(ctrl_bus_wr_c) = '1')               else '0'; -- store operation
2073
  cnt_event_nxt(hpmcnt_event_wait_ls_c) <= '1' when (execute_engine.state = LOADSTORE_2) and (execute_engine.state_prev = LOADSTORE_2) else '0'; -- load/store memory wait cycle
2074
 
2075
  cnt_event_nxt(hpmcnt_event_jump_c)    <= '1' when (execute_engine.state = BRANCH) and (execute_engine.i_reg(instr_opcode_lsb_c+2) = '1') else '0'; -- jump (unconditional)
2076
  cnt_event_nxt(hpmcnt_event_branch_c)  <= '1' when (execute_engine.state = BRANCH) and (execute_engine.i_reg(instr_opcode_lsb_c+2) = '0') else '0'; -- branch (conditional, taken or not taken)
2077
  cnt_event_nxt(hpmcnt_event_tbranch_c) <= '1' when (execute_engine.state = BRANCH) and (execute_engine.i_reg(instr_opcode_lsb_c+2) = '0') and (execute_engine.branch_taken = '1') else '0'; -- taken branch (conditional)
2078
 
2079
  cnt_event_nxt(hpmcnt_event_trap_c)    <= '1' when (trap_ctrl.env_start_ack = '1')                                    else '0'; -- entered trap
2080
  cnt_event_nxt(hpmcnt_event_illegal_c) <= '1' when (trap_ctrl.env_start_ack = '1') and (trap_ctrl.cause = trap_iil_c) else '0'; -- illegal operation
2081
 
2082
 
2083 2 zero_gravi
  -- Control and Status Registers Read Access -----------------------------------------------
2084
  -- -------------------------------------------------------------------------------------------
2085
  csr_read_access: process(clk_i)
2086
  begin
2087
    if rising_edge(clk_i) then
2088 29 zero_gravi
      csr.re    <= csr.re_nxt; -- read access?
2089 35 zero_gravi
      csr.rdata <= (others => '0'); -- default output
2090 11 zero_gravi
      if (CPU_EXTENSION_RISCV_Zicsr = true) and (csr.re = '1') then
2091 41 zero_gravi
        case csr.addr is
2092 11 zero_gravi
 
2093
          -- machine trap setup --
2094 29 zero_gravi
          when csr_mstatus_c => -- R/W: mstatus - machine status register
2095 41 zero_gravi
            csr.rdata(03) <= csr.mstatus_mie; -- MIE
2096
            csr.rdata(06) <= '1' and bool_to_ulogic_f(CPU_EXTENSION_RISCV_U); -- UBE: CPU/Processor is BIG-ENDIAN (in user-mode)
2097 27 zero_gravi
            csr.rdata(07) <= csr.mstatus_mpie; -- MPIE
2098 29 zero_gravi
            csr.rdata(11) <= csr.mstatus_mpp(0); -- MPP: machine previous privilege mode low
2099
            csr.rdata(12) <= csr.mstatus_mpp(1); -- MPP: machine previous privilege mode high
2100 40 zero_gravi
          when csr_mstatush_c => -- R/-: mstatush - machine status register - high part
2101 41 zero_gravi
            csr.rdata(05) <= '1'; -- MBE: CPU/Processor is BIG-ENDIAN (in machine-mode)
2102 29 zero_gravi
          when csr_misa_c => -- R/-: misa - ISA and extensions
2103 39 zero_gravi
            csr.rdata(00) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_A);     -- A CPU extension
2104 27 zero_gravi
            csr.rdata(02) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_C);     -- C CPU extension
2105
            csr.rdata(04) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E);     -- E CPU extension
2106
            csr.rdata(08) <= not bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- I CPU extension (if not E)
2107
            csr.rdata(12) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_M);     -- M CPU extension
2108
            csr.rdata(20) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_U);     -- U CPU extension
2109
            csr.rdata(23) <= '1';                                         -- X CPU extension (non-std extensions)
2110
            csr.rdata(30) <= '1'; -- 32-bit architecture (MXL lo)
2111
            csr.rdata(31) <= '0'; -- 32-bit architecture (MXL hi)
2112 29 zero_gravi
          when csr_mie_c => -- R/W: mie - machine interrupt-enable register
2113 27 zero_gravi
            csr.rdata(03) <= csr.mie_msie; -- machine software IRQ enable
2114
            csr.rdata(07) <= csr.mie_mtie; -- machine timer IRQ enable
2115
            csr.rdata(11) <= csr.mie_meie; -- machine external IRQ enable
2116 14 zero_gravi
            --
2117 27 zero_gravi
            csr.rdata(16) <= csr.mie_firqe(0); -- fast interrupt channel 0
2118
            csr.rdata(17) <= csr.mie_firqe(1); -- fast interrupt channel 1
2119
            csr.rdata(18) <= csr.mie_firqe(2); -- fast interrupt channel 2
2120
            csr.rdata(19) <= csr.mie_firqe(3); -- fast interrupt channel 3
2121 29 zero_gravi
          when csr_mtvec_c => -- R/W: mtvec - machine trap-handler base address (for ALL exceptions)
2122 27 zero_gravi
            csr.rdata <= csr.mtvec(data_width_c-1 downto 2) & "00"; -- mtvec.MODE=0
2123 41 zero_gravi
          when csr_mcounteren_c => -- R/W: machine counter enable register
2124
            csr.rdata(0) <= csr.mcounteren_cy; -- enable user-level access to cycle[h]
2125
            csr.rdata(1) <= csr.mcounteren_tm; -- enable user-level access to time[h]
2126
            csr.rdata(2) <= csr.mcounteren_ir; -- enable user-level access to instret[h]
2127 42 zero_gravi
            csr.rdata(csr.mcounteren_hpm'left+3 downto 3) <= csr.mcounteren_hpm; -- enable user-level access to hpmcounterx[h]
2128 11 zero_gravi
 
2129
          -- machine trap handling --
2130 29 zero_gravi
          when csr_mscratch_c => -- R/W: mscratch - machine scratch register
2131 27 zero_gravi
            csr.rdata <= csr.mscratch;
2132 29 zero_gravi
          when csr_mepc_c => -- R/W: mepc - machine exception program counter
2133 27 zero_gravi
            csr.rdata <= csr.mepc(data_width_c-1 downto 1) & '0';
2134 35 zero_gravi
          when csr_mcause_c => -- R/W: mcause - machine trap cause
2135 27 zero_gravi
            csr.rdata <= csr.mcause;
2136 29 zero_gravi
          when csr_mtval_c => -- R/W: mtval - machine bad address or instruction
2137 27 zero_gravi
            csr.rdata <= csr.mtval;
2138 29 zero_gravi
          when csr_mip_c => -- R/W: mip - machine interrupt pending
2139 40 zero_gravi
            csr.rdata(03) <= csr.mip_status(interrupt_msw_irq_c);
2140
            csr.rdata(07) <= csr.mip_status(interrupt_mtime_irq_c);
2141
            csr.rdata(11) <= csr.mip_status(interrupt_mext_irq_c);
2142 14 zero_gravi
            --
2143 40 zero_gravi
            csr.rdata(16) <= csr.mip_status(interrupt_firq_0_c);
2144
            csr.rdata(17) <= csr.mip_status(interrupt_firq_1_c);
2145
            csr.rdata(18) <= csr.mip_status(interrupt_firq_2_c);
2146
            csr.rdata(19) <= csr.mip_status(interrupt_firq_3_c);
2147 11 zero_gravi
 
2148 37 zero_gravi
          -- physical memory protection - configuration --
2149 42 zero_gravi
          when csr_pmpcfg0_c  => csr.rdata <= csr.pmpcfg_rd(03) & csr.pmpcfg_rd(02) & csr.pmpcfg_rd(01) & csr.pmpcfg_rd(00); -- R/W: pmpcfg0
2150
          when csr_pmpcfg1_c  => csr.rdata <= csr.pmpcfg_rd(07) & csr.pmpcfg_rd(06) & csr.pmpcfg_rd(05) & csr.pmpcfg_rd(04); -- R/W: pmpcfg1
2151
          when csr_pmpcfg2_c  => csr.rdata <= csr.pmpcfg_rd(11) & csr.pmpcfg_rd(10) & csr.pmpcfg_rd(09) & csr.pmpcfg_rd(08); -- R/W: pmpcfg2
2152
          when csr_pmpcfg3_c  => csr.rdata <= csr.pmpcfg_rd(15) & csr.pmpcfg_rd(14) & csr.pmpcfg_rd(13) & csr.pmpcfg_rd(12); -- R/W: pmpcfg3
2153
          when csr_pmpcfg4_c  => csr.rdata <= csr.pmpcfg_rd(19) & csr.pmpcfg_rd(18) & csr.pmpcfg_rd(17) & csr.pmpcfg_rd(16); -- R/W: pmpcfg4
2154
          when csr_pmpcfg5_c  => csr.rdata <= csr.pmpcfg_rd(23) & csr.pmpcfg_rd(22) & csr.pmpcfg_rd(21) & csr.pmpcfg_rd(20); -- R/W: pmpcfg5
2155
          when csr_pmpcfg6_c  => csr.rdata <= csr.pmpcfg_rd(27) & csr.pmpcfg_rd(26) & csr.pmpcfg_rd(25) & csr.pmpcfg_rd(24); -- R/W: pmpcfg6
2156
          when csr_pmpcfg7_c  => csr.rdata <= csr.pmpcfg_rd(31) & csr.pmpcfg_rd(30) & csr.pmpcfg_rd(29) & csr.pmpcfg_rd(28); -- R/W: pmpcfg7
2157
          when csr_pmpcfg8_c  => csr.rdata <= csr.pmpcfg_rd(35) & csr.pmpcfg_rd(34) & csr.pmpcfg_rd(33) & csr.pmpcfg_rd(32); -- R/W: pmpcfg8
2158
          when csr_pmpcfg9_c  => csr.rdata <= csr.pmpcfg_rd(39) & csr.pmpcfg_rd(38) & csr.pmpcfg_rd(37) & csr.pmpcfg_rd(36); -- R/W: pmpcfg9
2159
          when csr_pmpcfg10_c => csr.rdata <= csr.pmpcfg_rd(43) & csr.pmpcfg_rd(42) & csr.pmpcfg_rd(41) & csr.pmpcfg_rd(40); -- R/W: pmpcfg10
2160
          when csr_pmpcfg11_c => csr.rdata <= csr.pmpcfg_rd(47) & csr.pmpcfg_rd(46) & csr.pmpcfg_rd(45) & csr.pmpcfg_rd(44); -- R/W: pmpcfg11
2161
          when csr_pmpcfg12_c => csr.rdata <= csr.pmpcfg_rd(51) & csr.pmpcfg_rd(50) & csr.pmpcfg_rd(49) & csr.pmpcfg_rd(48); -- R/W: pmpcfg12
2162
          when csr_pmpcfg13_c => csr.rdata <= csr.pmpcfg_rd(55) & csr.pmpcfg_rd(54) & csr.pmpcfg_rd(53) & csr.pmpcfg_rd(52); -- R/W: pmpcfg13
2163
          when csr_pmpcfg14_c => csr.rdata <= csr.pmpcfg_rd(59) & csr.pmpcfg_rd(58) & csr.pmpcfg_rd(57) & csr.pmpcfg_rd(56); -- R/W: pmpcfg14
2164
          when csr_pmpcfg15_c => csr.rdata <= csr.pmpcfg_rd(63) & csr.pmpcfg_rd(62) & csr.pmpcfg_rd(61) & csr.pmpcfg_rd(60); -- R/W: pmpcfg15
2165 15 zero_gravi
 
2166 37 zero_gravi
          -- physical memory protection - addresses --
2167 42 zero_gravi
          when csr_pmpaddr0_c  => csr.rdata <= csr.pmpaddr_rd(00); -- R/W: pmpaddr0
2168
          when csr_pmpaddr1_c  => csr.rdata <= csr.pmpaddr_rd(01); -- R/W: pmpaddr1
2169
          when csr_pmpaddr2_c  => csr.rdata <= csr.pmpaddr_rd(02); -- R/W: pmpaddr2
2170
          when csr_pmpaddr3_c  => csr.rdata <= csr.pmpaddr_rd(03); -- R/W: pmpaddr3
2171
          when csr_pmpaddr4_c  => csr.rdata <= csr.pmpaddr_rd(04); -- R/W: pmpaddr4
2172
          when csr_pmpaddr5_c  => csr.rdata <= csr.pmpaddr_rd(05); -- R/W: pmpaddr5
2173
          when csr_pmpaddr6_c  => csr.rdata <= csr.pmpaddr_rd(06); -- R/W: pmpaddr6
2174
          when csr_pmpaddr7_c  => csr.rdata <= csr.pmpaddr_rd(07); -- R/W: pmpaddr7
2175
          when csr_pmpaddr8_c  => csr.rdata <= csr.pmpaddr_rd(08); -- R/W: pmpaddr8
2176
          when csr_pmpaddr9_c  => csr.rdata <= csr.pmpaddr_rd(09); -- R/W: pmpaddr9
2177
          when csr_pmpaddr10_c => csr.rdata <= csr.pmpaddr_rd(10); -- R/W: pmpaddr10
2178
          when csr_pmpaddr11_c => csr.rdata <= csr.pmpaddr_rd(11); -- R/W: pmpaddr11
2179
          when csr_pmpaddr12_c => csr.rdata <= csr.pmpaddr_rd(12); -- R/W: pmpaddr12
2180
          when csr_pmpaddr13_c => csr.rdata <= csr.pmpaddr_rd(13); -- R/W: pmpaddr13
2181
          when csr_pmpaddr14_c => csr.rdata <= csr.pmpaddr_rd(14); -- R/W: pmpaddr14
2182
          when csr_pmpaddr15_c => csr.rdata <= csr.pmpaddr_rd(15); -- R/W: pmpaddr15
2183
          when csr_pmpaddr16_c => csr.rdata <= csr.pmpaddr_rd(16); -- R/W: pmpaddr16
2184
          when csr_pmpaddr17_c => csr.rdata <= csr.pmpaddr_rd(17); -- R/W: pmpaddr17
2185
          when csr_pmpaddr18_c => csr.rdata <= csr.pmpaddr_rd(18); -- R/W: pmpaddr18
2186
          when csr_pmpaddr19_c => csr.rdata <= csr.pmpaddr_rd(19); -- R/W: pmpaddr19
2187
          when csr_pmpaddr20_c => csr.rdata <= csr.pmpaddr_rd(20); -- R/W: pmpaddr20
2188
          when csr_pmpaddr21_c => csr.rdata <= csr.pmpaddr_rd(21); -- R/W: pmpaddr21
2189
          when csr_pmpaddr22_c => csr.rdata <= csr.pmpaddr_rd(22); -- R/W: pmpaddr22
2190
          when csr_pmpaddr23_c => csr.rdata <= csr.pmpaddr_rd(23); -- R/W: pmpaddr23
2191
          when csr_pmpaddr24_c => csr.rdata <= csr.pmpaddr_rd(24); -- R/W: pmpaddr24
2192
          when csr_pmpaddr25_c => csr.rdata <= csr.pmpaddr_rd(25); -- R/W: pmpaddr25
2193
          when csr_pmpaddr26_c => csr.rdata <= csr.pmpaddr_rd(26); -- R/W: pmpaddr26
2194
          when csr_pmpaddr27_c => csr.rdata <= csr.pmpaddr_rd(27); -- R/W: pmpaddr27
2195
          when csr_pmpaddr28_c => csr.rdata <= csr.pmpaddr_rd(28); -- R/W: pmpaddr28
2196
          when csr_pmpaddr29_c => csr.rdata <= csr.pmpaddr_rd(29); -- R/W: pmpaddr29
2197
          when csr_pmpaddr30_c => csr.rdata <= csr.pmpaddr_rd(30); -- R/W: pmpaddr30
2198
          when csr_pmpaddr31_c => csr.rdata <= csr.pmpaddr_rd(31); -- R/W: pmpaddr31
2199
          when csr_pmpaddr32_c => csr.rdata <= csr.pmpaddr_rd(32); -- R/W: pmpaddr32
2200
          when csr_pmpaddr33_c => csr.rdata <= csr.pmpaddr_rd(33); -- R/W: pmpaddr33
2201
          when csr_pmpaddr34_c => csr.rdata <= csr.pmpaddr_rd(34); -- R/W: pmpaddr34
2202
          when csr_pmpaddr35_c => csr.rdata <= csr.pmpaddr_rd(35); -- R/W: pmpaddr35
2203
          when csr_pmpaddr36_c => csr.rdata <= csr.pmpaddr_rd(36); -- R/W: pmpaddr36
2204
          when csr_pmpaddr37_c => csr.rdata <= csr.pmpaddr_rd(37); -- R/W: pmpaddr37
2205
          when csr_pmpaddr38_c => csr.rdata <= csr.pmpaddr_rd(38); -- R/W: pmpaddr38
2206
          when csr_pmpaddr39_c => csr.rdata <= csr.pmpaddr_rd(39); -- R/W: pmpaddr39
2207
          when csr_pmpaddr40_c => csr.rdata <= csr.pmpaddr_rd(40); -- R/W: pmpaddr40
2208
          when csr_pmpaddr41_c => csr.rdata <= csr.pmpaddr_rd(41); -- R/W: pmpaddr41
2209
          when csr_pmpaddr42_c => csr.rdata <= csr.pmpaddr_rd(42); -- R/W: pmpaddr42
2210
          when csr_pmpaddr43_c => csr.rdata <= csr.pmpaddr_rd(43); -- R/W: pmpaddr43
2211
          when csr_pmpaddr44_c => csr.rdata <= csr.pmpaddr_rd(44); -- R/W: pmpaddr44
2212
          when csr_pmpaddr45_c => csr.rdata <= csr.pmpaddr_rd(45); -- R/W: pmpaddr45
2213
          when csr_pmpaddr46_c => csr.rdata <= csr.pmpaddr_rd(46); -- R/W: pmpaddr46
2214
          when csr_pmpaddr47_c => csr.rdata <= csr.pmpaddr_rd(47); -- R/W: pmpaddr47
2215
          when csr_pmpaddr48_c => csr.rdata <= csr.pmpaddr_rd(48); -- R/W: pmpaddr48
2216
          when csr_pmpaddr49_c => csr.rdata <= csr.pmpaddr_rd(49); -- R/W: pmpaddr49
2217
          when csr_pmpaddr50_c => csr.rdata <= csr.pmpaddr_rd(50); -- R/W: pmpaddr50
2218
          when csr_pmpaddr51_c => csr.rdata <= csr.pmpaddr_rd(51); -- R/W: pmpaddr51
2219
          when csr_pmpaddr52_c => csr.rdata <= csr.pmpaddr_rd(52); -- R/W: pmpaddr52
2220
          when csr_pmpaddr53_c => csr.rdata <= csr.pmpaddr_rd(53); -- R/W: pmpaddr53
2221
          when csr_pmpaddr54_c => csr.rdata <= csr.pmpaddr_rd(54); -- R/W: pmpaddr54
2222
          when csr_pmpaddr55_c => csr.rdata <= csr.pmpaddr_rd(55); -- R/W: pmpaddr55
2223
          when csr_pmpaddr56_c => csr.rdata <= csr.pmpaddr_rd(56); -- R/W: pmpaddr56
2224
          when csr_pmpaddr57_c => csr.rdata <= csr.pmpaddr_rd(57); -- R/W: pmpaddr57
2225
          when csr_pmpaddr58_c => csr.rdata <= csr.pmpaddr_rd(58); -- R/W: pmpaddr58
2226
          when csr_pmpaddr59_c => csr.rdata <= csr.pmpaddr_rd(59); -- R/W: pmpaddr59
2227
          when csr_pmpaddr60_c => csr.rdata <= csr.pmpaddr_rd(60); -- R/W: pmpaddr60
2228
          when csr_pmpaddr61_c => csr.rdata <= csr.pmpaddr_rd(61); -- R/W: pmpaddr61
2229
          when csr_pmpaddr62_c => csr.rdata <= csr.pmpaddr_rd(62); -- R/W: pmpaddr62
2230
          when csr_pmpaddr63_c => csr.rdata <= csr.pmpaddr_rd(63); -- R/W: pmpaddr63
2231 15 zero_gravi
 
2232 41 zero_gravi
          -- machine counter setup --
2233
          -- --------------------------------------------------------------------
2234
          when csr_mcountinhibit_c => -- R/W: mcountinhibit - machine counter-inhibit register
2235
            csr.rdata(0) <= csr.mcountinhibit_cy; -- enable auto-increment of [m]cycle[h] counter
2236
            csr.rdata(2) <= csr.mcountinhibit_ir; -- enable auto-increment of [m]instret[h] counter
2237 42 zero_gravi
            csr.rdata(csr.mcountinhibit_hpm'left+3 downto 3) <= csr.mcountinhibit_hpm; -- enable auto-increment of [m]hpmcounterx[h] counter
2238 41 zero_gravi
 
2239 42 zero_gravi
          -- machine performance-monitoring event selector --
2240
          when csr_mhpmevent3_c  => csr.rdata(csr.mhpmevent_rd(00)'left downto 0) <= csr.mhpmevent_rd(00); -- R/W: mhpmevent3
2241
          when csr_mhpmevent4_c  => csr.rdata(csr.mhpmevent_rd(01)'left downto 0) <= csr.mhpmevent_rd(01); -- R/W: mhpmevent4
2242
          when csr_mhpmevent5_c  => csr.rdata(csr.mhpmevent_rd(02)'left downto 0) <= csr.mhpmevent_rd(02); -- R/W: mhpmevent5
2243
          when csr_mhpmevent6_c  => csr.rdata(csr.mhpmevent_rd(03)'left downto 0) <= csr.mhpmevent_rd(03); -- R/W: mhpmevent6
2244
          when csr_mhpmevent7_c  => csr.rdata(csr.mhpmevent_rd(04)'left downto 0) <= csr.mhpmevent_rd(04); -- R/W: mhpmevent7
2245
          when csr_mhpmevent8_c  => csr.rdata(csr.mhpmevent_rd(05)'left downto 0) <= csr.mhpmevent_rd(05); -- R/W: mhpmevent8
2246
          when csr_mhpmevent9_c  => csr.rdata(csr.mhpmevent_rd(06)'left downto 0) <= csr.mhpmevent_rd(06); -- R/W: mhpmevent9
2247
          when csr_mhpmevent10_c => csr.rdata(csr.mhpmevent_rd(07)'left downto 0) <= csr.mhpmevent_rd(07); -- R/W: mhpmevent10
2248
          when csr_mhpmevent11_c => csr.rdata(csr.mhpmevent_rd(08)'left downto 0) <= csr.mhpmevent_rd(08); -- R/W: mhpmevent11
2249
          when csr_mhpmevent12_c => csr.rdata(csr.mhpmevent_rd(09)'left downto 0) <= csr.mhpmevent_rd(09); -- R/W: mhpmevent12
2250
          when csr_mhpmevent13_c => csr.rdata(csr.mhpmevent_rd(10)'left downto 0) <= csr.mhpmevent_rd(10); -- R/W: mhpmevent13
2251
          when csr_mhpmevent14_c => csr.rdata(csr.mhpmevent_rd(11)'left downto 0) <= csr.mhpmevent_rd(11); -- R/W: mhpmevent14
2252
          when csr_mhpmevent15_c => csr.rdata(csr.mhpmevent_rd(12)'left downto 0) <= csr.mhpmevent_rd(12); -- R/W: mhpmevent15
2253
          when csr_mhpmevent16_c => csr.rdata(csr.mhpmevent_rd(13)'left downto 0) <= csr.mhpmevent_rd(13); -- R/W: mhpmevent16
2254
          when csr_mhpmevent17_c => csr.rdata(csr.mhpmevent_rd(14)'left downto 0) <= csr.mhpmevent_rd(14); -- R/W: mhpmevent17
2255
          when csr_mhpmevent18_c => csr.rdata(csr.mhpmevent_rd(15)'left downto 0) <= csr.mhpmevent_rd(15); -- R/W: mhpmevent18
2256
          when csr_mhpmevent19_c => csr.rdata(csr.mhpmevent_rd(16)'left downto 0) <= csr.mhpmevent_rd(16); -- R/W: mhpmevent19
2257
          when csr_mhpmevent20_c => csr.rdata(csr.mhpmevent_rd(17)'left downto 0) <= csr.mhpmevent_rd(17); -- R/W: mhpmevent20
2258
          when csr_mhpmevent21_c => csr.rdata(csr.mhpmevent_rd(18)'left downto 0) <= csr.mhpmevent_rd(18); -- R/W: mhpmevent21
2259
          when csr_mhpmevent22_c => csr.rdata(csr.mhpmevent_rd(19)'left downto 0) <= csr.mhpmevent_rd(19); -- R/W: mhpmevent22
2260
          when csr_mhpmevent23_c => csr.rdata(csr.mhpmevent_rd(20)'left downto 0) <= csr.mhpmevent_rd(20); -- R/W: mhpmevent23
2261
          when csr_mhpmevent24_c => csr.rdata(csr.mhpmevent_rd(21)'left downto 0) <= csr.mhpmevent_rd(21); -- R/W: mhpmevent24
2262
          when csr_mhpmevent25_c => csr.rdata(csr.mhpmevent_rd(22)'left downto 0) <= csr.mhpmevent_rd(22); -- R/W: mhpmevent25
2263
          when csr_mhpmevent26_c => csr.rdata(csr.mhpmevent_rd(23)'left downto 0) <= csr.mhpmevent_rd(23); -- R/W: mhpmevent26
2264
          when csr_mhpmevent27_c => csr.rdata(csr.mhpmevent_rd(24)'left downto 0) <= csr.mhpmevent_rd(24); -- R/W: mhpmevent27
2265
          when csr_mhpmevent28_c => csr.rdata(csr.mhpmevent_rd(25)'left downto 0) <= csr.mhpmevent_rd(25); -- R/W: mhpmevent28
2266
          when csr_mhpmevent29_c => csr.rdata(csr.mhpmevent_rd(26)'left downto 0) <= csr.mhpmevent_rd(26); -- R/W: mhpmevent29
2267
          when csr_mhpmevent30_c => csr.rdata(csr.mhpmevent_rd(27)'left downto 0) <= csr.mhpmevent_rd(27); -- R/W: mhpmevent30
2268
          when csr_mhpmevent31_c => csr.rdata(csr.mhpmevent_rd(28)'left downto 0) <= csr.mhpmevent_rd(28); -- R/W: mhpmevent31
2269
 
2270 29 zero_gravi
          -- counters and timers --
2271 42 zero_gravi
          when csr_cycle_c | csr_mcycle_c => -- (R)/(W): [m]cycle: Cycle counter LOW
2272 27 zero_gravi
            csr.rdata <= csr.mcycle(31 downto 0);
2273 42 zero_gravi
          when csr_time_c => -- (R)/-: time: System time LOW (from MTIME unit)
2274 27 zero_gravi
            csr.rdata <= time_i(31 downto 0);
2275 42 zero_gravi
          when csr_instret_c | csr_minstret_c => -- (R)/(W): [m]instret: Instructions-retired counter LOW
2276 27 zero_gravi
            csr.rdata <= csr.minstret(31 downto 0);
2277 42 zero_gravi
          when csr_cycleh_c | csr_mcycleh_c => -- (R)/(W): [m]cycleh: Cycle counter HIGH
2278 27 zero_gravi
            csr.rdata <= csr.mcycleh(31 downto 0);
2279 42 zero_gravi
          when csr_timeh_c => -- (R)/-: timeh: System time HIGH (from MTIME unit)
2280 27 zero_gravi
            csr.rdata <= time_i(63 downto 32);
2281 42 zero_gravi
          when csr_instreth_c | csr_minstreth_c => -- (R)/(W): [m]instreth: Instructions-retired counter HIGH
2282 27 zero_gravi
            csr.rdata <= csr.minstreth(31 downto 0);
2283 11 zero_gravi
 
2284 42 zero_gravi
          -- hardware performance counters --
2285
          when csr_hpmcounter3_c   | csr_mhpmcounter3_c   => csr.rdata <= csr.mhpmcounter_rd(00)(31 downto 0); -- (R)/(W): [m]hpmcounter3 - low
2286
          when csr_hpmcounter4_c   | csr_mhpmcounter4_c   => csr.rdata <= csr.mhpmcounter_rd(01)(31 downto 0); -- (R)/(W): [m]hpmcounter4 - low
2287
          when csr_hpmcounter5_c   | csr_mhpmcounter5_c   => csr.rdata <= csr.mhpmcounter_rd(02)(31 downto 0); -- (R)/(W): [m]hpmcounter5 - low
2288
          when csr_hpmcounter6_c   | csr_mhpmcounter6_c   => csr.rdata <= csr.mhpmcounter_rd(03)(31 downto 0); -- (R)/(W): [m]hpmcounter6 - low
2289
          when csr_hpmcounter7_c   | csr_mhpmcounter7_c   => csr.rdata <= csr.mhpmcounter_rd(04)(31 downto 0); -- (R)/(W): [m]hpmcounter7 - low
2290
          when csr_hpmcounter8_c   | csr_mhpmcounter8_c   => csr.rdata <= csr.mhpmcounter_rd(05)(31 downto 0); -- (R)/(W): [m]hpmcounter8 - low
2291
          when csr_hpmcounter9_c   | csr_mhpmcounter9_c   => csr.rdata <= csr.mhpmcounter_rd(06)(31 downto 0); -- (R)/(W): [m]hpmcounter9 - low
2292
          when csr_hpmcounter10_c  | csr_mhpmcounter10_c  => csr.rdata <= csr.mhpmcounter_rd(07)(31 downto 0); -- (R)/(W): [m]hpmcounter10 - low
2293
          when csr_hpmcounter11_c  | csr_mhpmcounter11_c  => csr.rdata <= csr.mhpmcounter_rd(08)(31 downto 0); -- (R)/(W): [m]hpmcounter11 - low
2294
          when csr_hpmcounter12_c  | csr_mhpmcounter12_c  => csr.rdata <= csr.mhpmcounter_rd(09)(31 downto 0); -- (R)/(W): [m]hpmcounter12 - low
2295
          when csr_hpmcounter13_c  | csr_mhpmcounter13_c  => csr.rdata <= csr.mhpmcounter_rd(10)(31 downto 0); -- (R)/(W): [m]hpmcounter13 - low
2296
          when csr_hpmcounter14_c  | csr_mhpmcounter14_c  => csr.rdata <= csr.mhpmcounter_rd(11)(31 downto 0); -- (R)/(W): [m]hpmcounter14 - low
2297
          when csr_hpmcounter15_c  | csr_mhpmcounter15_c  => csr.rdata <= csr.mhpmcounter_rd(12)(31 downto 0); -- (R)/(W): [m]hpmcounter15 - low
2298
          when csr_hpmcounter16_c  | csr_mhpmcounter16_c  => csr.rdata <= csr.mhpmcounter_rd(13)(31 downto 0); -- (R)/(W): [m]hpmcounter16 - low
2299
          when csr_hpmcounter17_c  | csr_mhpmcounter17_c  => csr.rdata <= csr.mhpmcounter_rd(14)(31 downto 0); -- (R)/(W): [m]hpmcounter17 - low
2300
          when csr_hpmcounter18_c  | csr_mhpmcounter18_c  => csr.rdata <= csr.mhpmcounter_rd(15)(31 downto 0); -- (R)/(W): [m]hpmcounter18 - low
2301
          when csr_hpmcounter19_c  | csr_mhpmcounter19_c  => csr.rdata <= csr.mhpmcounter_rd(16)(31 downto 0); -- (R)/(W): [m]hpmcounter19 - low
2302
          when csr_hpmcounter20_c  | csr_mhpmcounter20_c  => csr.rdata <= csr.mhpmcounter_rd(17)(31 downto 0); -- (R)/(W): [m]hpmcounter20 - low
2303
          when csr_hpmcounter21_c  | csr_mhpmcounter21_c  => csr.rdata <= csr.mhpmcounter_rd(18)(31 downto 0); -- (R)/(W): [m]hpmcounter21 - low
2304
          when csr_hpmcounter22_c  | csr_mhpmcounter22_c  => csr.rdata <= csr.mhpmcounter_rd(19)(31 downto 0); -- (R)/(W): [m]hpmcounter22 - low
2305
          when csr_hpmcounter23_c  | csr_mhpmcounter23_c  => csr.rdata <= csr.mhpmcounter_rd(20)(31 downto 0); -- (R)/(W): [m]hpmcounter23 - low
2306
          when csr_hpmcounter24_c  | csr_mhpmcounter24_c  => csr.rdata <= csr.mhpmcounter_rd(21)(31 downto 0); -- (R)/(W): [m]hpmcounter24 - low
2307
          when csr_hpmcounter25_c  | csr_mhpmcounter25_c  => csr.rdata <= csr.mhpmcounter_rd(22)(31 downto 0); -- (R)/(W): [m]hpmcounter25 - low
2308
          when csr_hpmcounter26_c  | csr_mhpmcounter26_c  => csr.rdata <= csr.mhpmcounter_rd(23)(31 downto 0); -- (R)/(W): [m]hpmcounter26 - low
2309
          when csr_hpmcounter27_c  | csr_mhpmcounter27_c  => csr.rdata <= csr.mhpmcounter_rd(24)(31 downto 0); -- (R)/(W): [m]hpmcounter27 - low
2310
          when csr_hpmcounter28_c  | csr_mhpmcounter28_c  => csr.rdata <= csr.mhpmcounter_rd(25)(31 downto 0); -- (R)/(W): [m]hpmcounter28 - low
2311
          when csr_hpmcounter29_c  | csr_mhpmcounter29_c  => csr.rdata <= csr.mhpmcounter_rd(26)(31 downto 0); -- (R)/(W): [m]hpmcounter29 - low
2312
          when csr_hpmcounter30_c  | csr_mhpmcounter30_c  => csr.rdata <= csr.mhpmcounter_rd(27)(31 downto 0); -- (R)/(W): [m]hpmcounter30 - low
2313
          when csr_hpmcounter31_c  | csr_mhpmcounter31_c  => csr.rdata <= csr.mhpmcounter_rd(28)(31 downto 0); -- (R)/(W): [m]hpmcounter31 - low
2314
 
2315
          when csr_hpmcounter3h_c  | csr_mhpmcounter3h_c  => csr.rdata <= csr.mhpmcounterh_rd(00)(31 downto 0); -- (R)/(W): [m]hpmcounter3h - high
2316
          when csr_hpmcounter4h_c  | csr_mhpmcounter4h_c  => csr.rdata <= csr.mhpmcounterh_rd(01)(31 downto 0); -- (R)/(W): [m]hpmcounter4h - high
2317
          when csr_hpmcounter5h_c  | csr_mhpmcounter5h_c  => csr.rdata <= csr.mhpmcounterh_rd(02)(31 downto 0); -- (R)/(W): [m]hpmcounter5h - high
2318
          when csr_hpmcounter6h_c  | csr_mhpmcounter6h_c  => csr.rdata <= csr.mhpmcounterh_rd(03)(31 downto 0); -- (R)/(W): [m]hpmcounter6h - high
2319
          when csr_hpmcounter7h_c  | csr_mhpmcounter7h_c  => csr.rdata <= csr.mhpmcounterh_rd(04)(31 downto 0); -- (R)/(W): [m]hpmcounter7h - high
2320
          when csr_hpmcounter8h_c  | csr_mhpmcounter8h_c  => csr.rdata <= csr.mhpmcounterh_rd(05)(31 downto 0); -- (R)/(W): [m]hpmcounter8h - high
2321
          when csr_hpmcounter9h_c  | csr_mhpmcounter9h_c  => csr.rdata <= csr.mhpmcounterh_rd(06)(31 downto 0); -- (R)/(W): [m]hpmcounter9h - high
2322
          when csr_hpmcounter10h_c | csr_mhpmcounter10h_c => csr.rdata <= csr.mhpmcounterh_rd(07)(31 downto 0); -- (R)/(W): [m]hpmcounter10h - high
2323
          when csr_hpmcounter11h_c | csr_mhpmcounter11h_c => csr.rdata <= csr.mhpmcounterh_rd(08)(31 downto 0); -- (R)/(W): [m]hpmcounter11h - high
2324
          when csr_hpmcounter12h_c | csr_mhpmcounter12h_c => csr.rdata <= csr.mhpmcounterh_rd(09)(31 downto 0); -- (R)/(W): [m]hpmcounter12h - high
2325
          when csr_hpmcounter13h_c | csr_mhpmcounter13h_c => csr.rdata <= csr.mhpmcounterh_rd(10)(31 downto 0); -- (R)/(W): [m]hpmcounter13h - high
2326
          when csr_hpmcounter14h_c | csr_mhpmcounter14h_c => csr.rdata <= csr.mhpmcounterh_rd(11)(31 downto 0); -- (R)/(W): [m]hpmcounter14h - high
2327
          when csr_hpmcounter15h_c | csr_mhpmcounter15h_c => csr.rdata <= csr.mhpmcounterh_rd(12)(31 downto 0); -- (R)/(W): [m]hpmcounter15h - high
2328
          when csr_hpmcounter16h_c | csr_mhpmcounter16h_c => csr.rdata <= csr.mhpmcounterh_rd(13)(31 downto 0); -- (R)/(W): [m]hpmcounter16h - high
2329
          when csr_hpmcounter17h_c | csr_mhpmcounter17h_c => csr.rdata <= csr.mhpmcounterh_rd(14)(31 downto 0); -- (R)/(W): [m]hpmcounter17h - high
2330
          when csr_hpmcounter18h_c | csr_mhpmcounter18h_c => csr.rdata <= csr.mhpmcounterh_rd(15)(31 downto 0); -- (R)/(W): [m]hpmcounter18h - high
2331
          when csr_hpmcounter19h_c | csr_mhpmcounter19h_c => csr.rdata <= csr.mhpmcounterh_rd(16)(31 downto 0); -- (R)/(W): [m]hpmcounter19h - high
2332
          when csr_hpmcounter20h_c | csr_mhpmcounter20h_c => csr.rdata <= csr.mhpmcounterh_rd(17)(31 downto 0); -- (R)/(W): [m]hpmcounter20h - high
2333
          when csr_hpmcounter21h_c | csr_mhpmcounter21h_c => csr.rdata <= csr.mhpmcounterh_rd(18)(31 downto 0); -- (R)/(W): [m]hpmcounter21h - high
2334
          when csr_hpmcounter22h_c | csr_mhpmcounter22h_c => csr.rdata <= csr.mhpmcounterh_rd(19)(31 downto 0); -- (R)/(W): [m]hpmcounter22h - high
2335
          when csr_hpmcounter23h_c | csr_mhpmcounter23h_c => csr.rdata <= csr.mhpmcounterh_rd(20)(31 downto 0); -- (R)/(W): [m]hpmcounter23h - high
2336
          when csr_hpmcounter24h_c | csr_mhpmcounter24h_c => csr.rdata <= csr.mhpmcounterh_rd(21)(31 downto 0); -- (R)/(W): [m]hpmcounter24h - high
2337
          when csr_hpmcounter25h_c | csr_mhpmcounter25h_c => csr.rdata <= csr.mhpmcounterh_rd(22)(31 downto 0); -- (R)/(W): [m]hpmcounter25h - high
2338
          when csr_hpmcounter26h_c | csr_mhpmcounter26h_c => csr.rdata <= csr.mhpmcounterh_rd(23)(31 downto 0); -- (R)/(W): [m]hpmcounter26h - high
2339
          when csr_hpmcounter27h_c | csr_mhpmcounter27h_c => csr.rdata <= csr.mhpmcounterh_rd(24)(31 downto 0); -- (R)/(W): [m]hpmcounter27h - high
2340
          when csr_hpmcounter28h_c | csr_mhpmcounter28h_c => csr.rdata <= csr.mhpmcounterh_rd(25)(31 downto 0); -- (R)/(W): [m]hpmcounter28h - high
2341
          when csr_hpmcounter29h_c | csr_mhpmcounter29h_c => csr.rdata <= csr.mhpmcounterh_rd(26)(31 downto 0); -- (R)/(W): [m]hpmcounter29h - high
2342
          when csr_hpmcounter30h_c | csr_mhpmcounter30h_c => csr.rdata <= csr.mhpmcounterh_rd(27)(31 downto 0); -- (R)/(W): [m]hpmcounter30h - high
2343
          when csr_hpmcounter31h_c | csr_mhpmcounter31h_c => csr.rdata <= csr.mhpmcounterh_rd(28)(31 downto 0); -- (R)/(W): [m]hpmcounter31h - high
2344
 
2345 11 zero_gravi
          -- machine information registers --
2346 29 zero_gravi
          when csr_mvendorid_c => -- R/-: mvendorid - vendor ID
2347 27 zero_gravi
            csr.rdata <= (others => '0');
2348 34 zero_gravi
          when csr_marchid_c => -- R/-: marchid - arch ID
2349
            csr.rdata(4 downto 0) <= "10011"; -- official RISC-V open-source arch ID
2350 32 zero_gravi
          when csr_mimpid_c => -- R/-: mimpid - implementation ID
2351
            csr.rdata <= hw_version_c; -- NEORV32 hardware version
2352 29 zero_gravi
          when csr_mhartid_c => -- R/-: mhartid - hardware thread ID
2353 27 zero_gravi
            csr.rdata <= HW_THREAD_ID;
2354 11 zero_gravi
 
2355 22 zero_gravi
          -- custom machine read-only CSRs --
2356 39 zero_gravi
          when csr_mzext_c => -- R/-: mzext - available Z* extensions
2357 32 zero_gravi
            csr.rdata(0) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicsr);    -- RISC-V.Zicsr CPU extension
2358
            csr.rdata(1) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zifencei); -- RISC-V.Zifencei CPU extension
2359 22 zero_gravi
 
2360 11 zero_gravi
          -- undefined/unavailable --
2361
          when others =>
2362 27 zero_gravi
            csr.rdata <= (others => '0'); -- not implemented
2363 11 zero_gravi
 
2364
        end case;
2365 2 zero_gravi
      end if;
2366
    end if;
2367
  end process csr_read_access;
2368
 
2369 27 zero_gravi
  -- CSR read data output --
2370
  csr_rdata_o <= csr.rdata;
2371
 
2372 12 zero_gravi
 
2373 2 zero_gravi
end neorv32_cpu_control_rtl;

powered by: WebSVN 2.1.0

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