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

Subversion Repositories neorv32

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

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 6 zero_gravi
-- # CPU operation is split into a fetch engine (responsible for fetching an decompressing instr-  #
5
-- # uctions), an execute engine (responsible for actually executing the instructions), an inter-  #
6
-- # rupt and exception handling controller and the RISC-V status and control registers (CSRs).    #
7 2 zero_gravi
-- # ********************************************************************************************* #
8
-- # BSD 3-Clause License                                                                          #
9
-- #                                                                                               #
10
-- # Copyright (c) 2020, Stephan Nolting. All rights reserved.                                     #
11
-- #                                                                                               #
12
-- # Redistribution and use in source and binary forms, with or without modification, are          #
13
-- # permitted provided that the following conditions are met:                                     #
14
-- #                                                                                               #
15
-- # 1. Redistributions of source code must retain the above copyright notice, this list of        #
16
-- #    conditions and the following disclaimer.                                                   #
17
-- #                                                                                               #
18
-- # 2. Redistributions in binary form must reproduce the above copyright notice, this list of     #
19
-- #    conditions and the following disclaimer in the documentation and/or other materials        #
20
-- #    provided with the distribution.                                                            #
21
-- #                                                                                               #
22
-- # 3. Neither the name of the copyright holder nor the names of its contributors may be used to  #
23
-- #    endorse or promote products derived from this software without specific prior written      #
24
-- #    permission.                                                                                #
25
-- #                                                                                               #
26
-- # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS   #
27
-- # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF               #
28
-- # MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE    #
29
-- # COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,     #
30
-- # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE #
31
-- # GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED    #
32
-- # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING     #
33
-- # NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED  #
34
-- # OF THE POSSIBILITY OF SUCH DAMAGE.                                                            #
35
-- # ********************************************************************************************* #
36
-- # The NEORV32 Processor - https://github.com/stnolting/neorv32              (c) Stephan Nolting #
37
-- #################################################################################################
38
 
39
library ieee;
40
use ieee.std_logic_1164.all;
41
use ieee.numeric_std.all;
42
 
43
library neorv32;
44
use neorv32.neorv32_package.all;
45
 
46
entity neorv32_cpu_control is
47
  generic (
48
    -- General --
49 8 zero_gravi
    CLOCK_FREQUENCY              : natural := 0; -- clock frequency of clk_i in Hz
50
    HART_ID                      : std_ulogic_vector(31 downto 0) := x"00000000"; -- custom hardware thread ID
51
    BOOTLOADER_USE               : boolean := true;   -- implement processor-internal bootloader?
52
    CSR_COUNTERS_USE             : boolean := true;   -- implement RISC-V perf. counters ([m]instret[h], [m]cycle[h], time[h])?
53 2 zero_gravi
    -- RISC-V CPU Extensions --
54 8 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
    CPU_EXTENSION_RISCV_Zicsr    : boolean := true;   -- implement CSR system?
58
    CPU_EXTENSION_RISCV_Zifencei : boolean := true;   -- implement instruction stream sync.?
59 2 zero_gravi
    -- Memory configuration: Instruction memory --
60 8 zero_gravi
    MEM_ISPACE_BASE              : std_ulogic_vector(31 downto 0) := x"00000000"; -- base address of instruction memory space
61
    MEM_ISPACE_SIZE              : natural := 8*1024; -- total size of instruction memory space in byte
62
    MEM_INT_IMEM_USE             : boolean := true;   -- implement processor-internal instruction memory
63
    MEM_INT_IMEM_SIZE            : natural := 8*1024; -- size of processor-internal instruction memory in bytes
64
    MEM_INT_IMEM_ROM             : boolean := false;  -- implement processor-internal instruction memory as ROM
65 2 zero_gravi
    -- Memory configuration: Data memory --
66 8 zero_gravi
    MEM_DSPACE_BASE              : std_ulogic_vector(31 downto 0) := x"80000000"; -- base address of data memory space
67
    MEM_DSPACE_SIZE              : natural := 4*1024; -- total size of data memory space in byte
68
    MEM_INT_DMEM_USE             : boolean := true;   -- implement processor-internal data memory
69
    MEM_INT_DMEM_SIZE            : natural := 4*1024; -- size of processor-internal data memory in bytes
70 2 zero_gravi
    -- Memory configuration: External memory interface --
71 8 zero_gravi
    MEM_EXT_USE                  : boolean := false;  -- implement external memory bus interface?
72 2 zero_gravi
    -- Processor peripherals --
73 8 zero_gravi
    IO_GPIO_USE                  : boolean := true;   -- implement general purpose input/output port unit (GPIO)?
74
    IO_MTIME_USE                 : boolean := true;   -- implement machine system timer (MTIME)?
75
    IO_UART_USE                  : boolean := true;   -- implement universal asynchronous receiver/transmitter (UART)?
76
    IO_SPI_USE                   : boolean := true;   -- implement serial peripheral interface (SPI)?
77
    IO_TWI_USE                   : boolean := true;   -- implement two-wire interface (TWI)?
78
    IO_PWM_USE                   : boolean := true;   -- implement pulse-width modulation unit (PWM)?
79
    IO_WDT_USE                   : boolean := true;   -- implement watch dog timer (WDT)?
80
    IO_CLIC_USE                  : boolean := true;   -- implement core local interrupt controller (CLIC)?
81
    IO_TRNG_USE                  : boolean := true;   -- implement true random number generator (TRNG)?
82
    IO_DEVNULL_USE               : boolean := true    -- implement dummy device (DEVNULL)?
83 2 zero_gravi
  );
84
  port (
85
    -- global control --
86
    clk_i         : in  std_ulogic; -- global clock, rising edge
87
    rstn_i        : in  std_ulogic; -- global reset, low-active, async
88
    ctrl_o        : out std_ulogic_vector(ctrl_width_c-1 downto 0); -- main control bus
89
    -- status input --
90
    alu_wait_i    : in  std_ulogic; -- wait for ALU
91
    bus_wait_i    : in  std_ulogic; -- wait for bus
92
    -- data input --
93
    instr_i       : in  std_ulogic_vector(data_width_c-1 downto 0); -- instruction
94
    cmp_i         : in  std_ulogic_vector(1 downto 0); -- comparator status
95
    alu_add_i     : in  std_ulogic_vector(data_width_c-1 downto 0); -- ALU.add result
96
    -- data output --
97
    imm_o         : out std_ulogic_vector(data_width_c-1 downto 0); -- immediate
98 6 zero_gravi
    fetch_pc_o    : out std_ulogic_vector(data_width_c-1 downto 0); -- PC for instruction fetch
99
    curr_pc_o     : out std_ulogic_vector(data_width_c-1 downto 0); -- current PC (corresponding to current instruction)
100
    next_pc_o     : out std_ulogic_vector(data_width_c-1 downto 0); -- next PC (corresponding to current instruction)
101 2 zero_gravi
    -- csr data interface --
102
    csr_wdata_i   : in  std_ulogic_vector(data_width_c-1 downto 0); -- CSR write data
103
    csr_rdata_o   : out std_ulogic_vector(data_width_c-1 downto 0); -- CSR read data
104
    -- external interrupt --
105
    clic_irq_i    : in  std_ulogic; -- CLIC interrupt request
106
    mtime_irq_i   : in  std_ulogic; -- machine timer interrupt
107
    -- bus access exceptions --
108
    mar_i         : in  std_ulogic_vector(data_width_c-1 downto 0);  -- memory address register
109
    ma_instr_i    : in  std_ulogic; -- misaligned instruction address
110
    ma_load_i     : in  std_ulogic; -- misaligned load data address
111
    ma_store_i    : in  std_ulogic; -- misaligned store data address
112
    be_instr_i    : in  std_ulogic; -- bus error on instruction access
113
    be_load_i     : in  std_ulogic; -- bus error on load data access
114
    be_store_i    : in  std_ulogic; -- bus error on store data access
115 6 zero_gravi
    bus_exc_ack_o : out std_ulogic; -- bus exception error acknowledge
116
    bus_busy_i    : in  std_ulogic  -- bus unit is busy
117 2 zero_gravi
  );
118
end neorv32_cpu_control;
119
 
120
architecture neorv32_cpu_control_rtl of neorv32_cpu_control is
121
 
122 6 zero_gravi
  -- instruction fetch enginge --
123
  type fetch_engine_state_t is (IFETCH_RESET, IFETCH_0, IFETCH_1, IFETCH_2, IFETCH_3);
124
  type fetch_engine_t is record
125
    state           : fetch_engine_state_t;
126
    state_nxt       : fetch_engine_state_t;
127
    i_buf           : std_ulogic_vector(33 downto 0);
128
    i_buf_nxt       : std_ulogic_vector(33 downto 0);
129
    i_buf2          : std_ulogic_vector(33 downto 0);
130
    i_buf2_nxt      : std_ulogic_vector(33 downto 0);
131
    ci_reg          : std_ulogic_vector(17 downto 0);
132
    ci_reg_nxt      : std_ulogic_vector(17 downto 0);
133
    i_buf_state     : std_ulogic_vector(01 downto 0);
134
    i_buf_state_nxt : std_ulogic_vector(01 downto 0);
135
    pc_real         : std_ulogic_vector(data_width_c-1 downto 0);
136
    pc_real_add     : std_ulogic_vector(data_width_c-1 downto 0);
137
    pc_fetch        : std_ulogic_vector(data_width_c-1 downto 0);
138
    pc_fetch_add    : std_ulogic_vector(data_width_c-1 downto 0);
139
    ci_return       : std_ulogic;
140
    ci_return_nxt   : std_ulogic;
141
    reset           : std_ulogic;
142
    bus_err_ack     : std_ulogic;
143
  end record;
144
  signal fetch_engine : fetch_engine_t;
145 2 zero_gravi
 
146
  -- pre-decoder --
147
  signal ci_instr32 : std_ulogic_vector(31 downto 0);
148
  signal ci_illegal : std_ulogic;
149
 
150 6 zero_gravi
  -- instrucion prefetch buffer (IPB) --
151
  type ipb_t is record
152
    wdata  : std_ulogic_vector(34 downto 0);
153
    rdata  : std_ulogic_vector(34 downto 0);
154
    waddr  : std_ulogic_vector(31 downto 0);
155
    raddr  : std_ulogic_vector(31 downto 0);
156
    status : std_ulogic;
157
    free   : std_ulogic;
158
    avail  : std_ulogic;
159
    we     : std_ulogic;
160
    re     : std_ulogic;
161
    clear  : std_ulogic;
162
  end record;
163
  signal ipb : ipb_t;
164 2 zero_gravi
 
165 6 zero_gravi
  -- instruction execution engine --
166 7 zero_gravi
  type execute_engine_state_t is (SYS_WAIT, DISPATCH, TRAP, EXECUTE, ALU_WAIT, BRANCH, STORE, LOAD, LOADSTORE_0, LOADSTORE_1, CSR_ACCESS);
167 6 zero_gravi
  type execute_engine_t is record
168
    state        : execute_engine_state_t;
169
    state_nxt    : execute_engine_state_t;
170
    state_prev   : execute_engine_state_t;
171
    i_reg        : std_ulogic_vector(31 downto 0);
172
    i_reg_nxt    : std_ulogic_vector(31 downto 0);
173
    is_ci        : std_ulogic; -- current instruction is de-compressed instruction
174
    is_ci_nxt    : std_ulogic;
175
    is_jump      : std_ulogic; -- current instruction is jump instruction
176
    is_jump_nxt  : std_ulogic;
177
    branch_taken : std_ulogic; -- branch condition fullfilled
178
    pc           : std_ulogic_vector(data_width_c-1 downto 0); -- actual PC, corresponding to current executed instruction
179
    pc_nxt       : std_ulogic_vector(data_width_c-1 downto 0);
180
    next_pc      : std_ulogic_vector(data_width_c-1 downto 0); -- next PC, corresponding to next instruction to be executed
181
    last_pc      : std_ulogic_vector(data_width_c-1 downto 0); -- PC of last executed instruction
182
  end record;
183
  signal execute_engine : execute_engine_t;
184 2 zero_gravi
 
185 6 zero_gravi
  -- trap controller --
186
  type trap_ctrl_t is record
187
    exc_buf       : std_ulogic_vector(exception_width_c-1 downto 0);
188
    exc_fire      : std_ulogic; -- set if there is a valid source in the exception buffer
189
    irq_buf       : std_ulogic_vector(interrupt_width_c-1 downto 0);
190
    irq_fire      : std_ulogic; -- set if there is a valid source in the interrupt buffer
191
    exc_ack       : std_ulogic; -- acknowledge all exceptions
192
    irq_ack       : std_ulogic_vector(interrupt_width_c-1 downto 0); -- acknowledge specific interrupt
193
    irq_ack_nxt   : std_ulogic_vector(interrupt_width_c-1 downto 0);
194
    cause         : std_ulogic_vector(data_width_c-1 downto 0); -- trap ID (for "mcause")
195
    cause_nxt     : std_ulogic_vector(data_width_c-1 downto 0);
196
    exc_src       : std_ulogic_vector(exception_width_c-1 downto 0);
197
    --
198
    env_start     : std_ulogic; -- start trap handler env
199
    env_start_ack : std_ulogic; -- start of trap handler acknowledged
200
    env_end       : std_ulogic; -- end trap handler env
201
    --
202
    instr_be      : std_ulogic; -- instruction fetch bus error
203
    instr_ma      : std_ulogic; -- instruction fetch misaligned address
204
    instr_il      : std_ulogic; -- illegal instruction
205
    env_call      : std_ulogic;
206
    break_point   : std_ulogic;
207
  end record;
208
  signal trap_ctrl : trap_ctrl_t;
209
 
210
  -- CPU control signals --
211
  signal ctrl_nxt, ctrl : std_ulogic_vector(ctrl_width_c-1 downto 0);
212 2 zero_gravi
 
213 6 zero_gravi
  -- fast bus access --
214
  signal bus_fast_ir : std_ulogic;
215
  signal bus_fast_rd : std_ulogic;
216
  signal bus_fast_wr : std_ulogic;
217 2 zero_gravi
 
218 6 zero_gravi
  -- RISC-V control and status registers (CSRs) --
219
  type csr_t is record
220
    we           : std_ulogic; -- write enable
221
    we_nxt       : std_ulogic;
222
    re           : std_ulogic; -- read enable
223
    re_nxt       : std_ulogic;
224
    mstatus_mie  : std_ulogic; -- mstatus.MIE: global IRQ enable (R/W)
225
    mstatus_mpie : std_ulogic; -- mstatus.MPIE: previous global IRQ enable (R/-)
226
    mip_msip     : std_ulogic; -- mip.MSIP: machine software interrupt pending (R/W)
227
    mie_msie     : std_ulogic; -- mie.MSIE: machine software interrupt enable (R/W)
228
    mie_meie     : std_ulogic; -- mie.MEIE: machine external interrupt enable (R/W)
229
    mie_mtie     : std_ulogic; -- mie.MEIE: machine timer interrupt enable (R/W)
230
    mepc         : std_ulogic_vector(data_width_c-1 downto 0); -- mepc: machine exception pc (R/W)
231
    mcause       : std_ulogic_vector(data_width_c-1 downto 0); -- mcause: machine trap cause (R/-)
232
    mtvec        : std_ulogic_vector(data_width_c-1 downto 0); -- mtvec: machine trap-handler base address (R/W)
233
    mtval        : std_ulogic_vector(data_width_c-1 downto 0); -- mtval: machine bad address or isntruction (R/-)
234
    mscratch     : std_ulogic_vector(data_width_c-1 downto 0); -- mscratch: scratch register (R/W)
235
    cycle        : std_ulogic_vector(32 downto 0); -- cycle, mtime (R/-), plus carry bit
236
    instret      : std_ulogic_vector(32 downto 0); -- instret (R/-), plus carry bit
237
    cycleh       : std_ulogic_vector(31 downto 0); -- cycleh, mtimeh (R/-)
238
    instreth     : std_ulogic_vector(31 downto 0); -- instreth (R/-)
239
    misa_c_en    : std_ulogic; -- misa: C extension enable bit (R/W)
240
    misa_m_en    : std_ulogic; -- misa: M extension enable bit (R/W)
241
  end record;
242
  signal csr : csr_t;
243 2 zero_gravi
 
244 6 zero_gravi
  signal cycle_msb   : std_ulogic;
245
  signal instret_msb : std_ulogic;
246 2 zero_gravi
 
247 6 zero_gravi
  -- illegal instruction check --
248 2 zero_gravi
  signal illegal_instruction : std_ulogic;
249
  signal illegal_register    : std_ulogic; -- only for E-extension
250
  signal illegal_compressed  : std_ulogic; -- only fir C-extension
251
 
252
begin
253
 
254 6 zero_gravi
-- ****************************************************************************************************************************
255
-- Instruction Fetch
256
-- ****************************************************************************************************************************
257
 
258 2 zero_gravi
  -- Compressed Instructions Recoding -------------------------------------------------------
259
  -- -------------------------------------------------------------------------------------------
260
  neorv32_cpu_decompressor_inst_true:
261
  if (CPU_EXTENSION_RISCV_C = true) generate
262
    neorv32_cpu_decompressor_inst: neorv32_cpu_decompressor
263
    port map (
264
      -- instruction input --
265 6 zero_gravi
      ci_instr16_i => fetch_engine.ci_reg(15 downto 0), -- compressed instruction input
266 2 zero_gravi
      -- instruction output --
267
      ci_illegal_o => ci_illegal, -- is an illegal compressed instruction
268
      ci_instr32_o => ci_instr32  -- 32-bit decompressed instruction
269
    );
270
  end generate;
271
 
272
  neorv32_cpu_decompressor_inst_false:
273
  if (CPU_EXTENSION_RISCV_C = false) generate
274 6 zero_gravi
    ci_instr32 <= (others => '0');
275 2 zero_gravi
    ci_illegal <= '0';
276
  end generate;
277
 
278
 
279 6 zero_gravi
  -- Fetch Engine FSM Sync ------------------------------------------------------------------
280
  -- -------------------------------------------------------------------------------------------
281
  -- for registers that require a specific reset state --
282
  fetch_engine_fsm_sync_rst: process(rstn_i, clk_i)
283
  begin
284
    if (rstn_i = '0') then
285
      fetch_engine.state <= IFETCH_RESET;
286
    elsif rising_edge(clk_i) then
287
      if (fetch_engine.reset = '1') then
288
        fetch_engine.state <= IFETCH_RESET;
289
      else
290
        fetch_engine.state <= fetch_engine.state_nxt;
291
      end if;
292
    end if;
293
  end process fetch_engine_fsm_sync_rst;
294
 
295
 
296
  -- for registers that DO NOT require a specific reset state --
297
  fetch_engine_fsm_sync: process(clk_i)
298
  begin
299
    if rising_edge(clk_i) then
300
      if (fetch_engine.state = IFETCH_RESET) then
301
        fetch_engine.pc_fetch  <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- initialize with "real" application PC
302
        fetch_engine.pc_real   <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- initialize with "real" application PC
303
      else
304
        fetch_engine.pc_real   <= std_ulogic_vector(unsigned(fetch_engine.pc_real(data_width_c-1 downto 1) & '0')  + unsigned(fetch_engine.pc_real_add(data_width_c-1 downto 1) & '0'));
305
        fetch_engine.pc_fetch  <= std_ulogic_vector(unsigned(fetch_engine.pc_fetch(data_width_c-1 downto 1) & '0') + unsigned(fetch_engine.pc_fetch_add(data_width_c-1 downto 1) & '0'));
306
      end if;
307
      --
308
      fetch_engine.i_buf       <= fetch_engine.i_buf_nxt;
309
      fetch_engine.i_buf2      <= fetch_engine.i_buf2_nxt;
310
      fetch_engine.i_buf_state <= fetch_engine.i_buf_state_nxt;
311
      --
312
      fetch_engine.ci_reg      <= fetch_engine.ci_reg_nxt;
313
      fetch_engine.ci_return   <= fetch_engine.ci_return_nxt;
314
    end if;
315
  end process fetch_engine_fsm_sync;
316
 
317
 
318
  -- Fetch Engine FSM Comb ------------------------------------------------------------------
319
  -- -------------------------------------------------------------------------------------------
320
  fetch_engine_fsm_comb: process(fetch_engine, execute_engine, csr, ipb, instr_i, bus_wait_i, bus_busy_i, ci_instr32, be_instr_i, ma_instr_i)
321
  begin
322
    -- arbiter defaults --
323
    fetch_engine.state_nxt       <= fetch_engine.state;
324
    fetch_engine.pc_fetch_add    <= (others => '0');
325
    fetch_engine.pc_real_add     <= (others => '0');
326
    bus_fast_ir                  <= '0';
327
    fetch_engine.i_buf_nxt       <= fetch_engine.i_buf;
328
    fetch_engine.i_buf2_nxt      <= fetch_engine.i_buf2;
329
    fetch_engine.i_buf_state_nxt <= fetch_engine.i_buf_state;
330
    fetch_engine.ci_reg_nxt      <= fetch_engine.ci_reg;
331
    fetch_engine.ci_return_nxt   <= fetch_engine.ci_return;
332
    fetch_engine.bus_err_ack     <= '0';
333
 
334
    -- instruction prefetch buffer interface --
335
    ipb.we    <= '0';
336
    ipb.clear <= '0';
337
    ipb.wdata <= fetch_engine.i_buf2(33 downto 32) & '0' & fetch_engine.i_buf2(31 downto 0);
338
    ipb.waddr <= fetch_engine.pc_real(data_width_c-1 downto 1) & '0';
339
 
340
    -- state machine --
341
    case fetch_engine.state is
342
 
343
      when IFETCH_RESET => -- reset engine, prefetch buffer, get PC
344
      -- ------------------------------------------------------------
345
        fetch_engine.i_buf_state_nxt <= (others => '0');
346
        fetch_engine.ci_return_nxt   <= '0';
347
        ipb.clear                    <= '1'; -- clear instruction prefetch buffer
348
        fetch_engine.bus_err_ack     <= '1'; -- ack bus errors, the execute engine has to take care of them
349
        fetch_engine.state_nxt       <= IFETCH_0;
350
 
351
      when IFETCH_0 => -- output current PC to bus system, request 32-bit word
352
      -- ------------------------------------------------------------
353
        if (bus_busy_i = '0') and (execute_engine.state /= LOAD) and (execute_engine.state /= STORE) and
354
                                  (execute_engine.state /= LOADSTORE_0) and (execute_engine.state /= LOADSTORE_1) then -- wait if execute engine is using bus unit
355
          bus_fast_ir            <= '1'; -- fast instruction fetch request (output PC to bus.address)
356
          fetch_engine.state_nxt <= IFETCH_1;
357
        end if;
358
 
359
      when IFETCH_1 => -- store data from memory to buffer(s)
360
      -- ------------------------------------------------------------
361
        fetch_engine.i_buf_nxt  <= be_instr_i & ma_instr_i & instr_i(31 downto 0); -- store data word and exception info
362
        if (bus_wait_i = '0') then -- wait for bus response
363
          fetch_engine.i_buf2_nxt <= fetch_engine.i_buf;
364
          fetch_engine.i_buf_state_nxt(1) <= fetch_engine.i_buf_state(0);
365
          fetch_engine.state_nxt          <= IFETCH_2;
366
        end if;
367
 
368
        fetch_engine.i_buf_state_nxt(0) <= '1';
369
        if (be_instr_i = '1') or (ma_instr_i = '1') then -- any fetch exception?
370
          fetch_engine.bus_err_ack <= '1'; -- ack bus errors, the execute engine has to take care of them
371
        end if;
372
 
373
      when IFETCH_2 => -- construct instruction and issue
374
      -- ------------------------------------------------------------
375
        if (fetch_engine.i_buf_state(1) = '1') then
376
          if (fetch_engine.pc_fetch(1) = '0') or (CPU_EXTENSION_RISCV_C = false) or (csr.misa_c_en = '0') then -- 32-bit aligned
377
            fetch_engine.ci_reg_nxt <= fetch_engine.i_buf2(33 downto 32) & fetch_engine.i_buf2(15 downto 00);
378
            ipb.wdata <= fetch_engine.i_buf2(33 downto 32) & '0' & fetch_engine.i_buf2(31 downto 0);
379
 
380
            if (fetch_engine.i_buf2(01 downto 00) = "11") or (CPU_EXTENSION_RISCV_C = false) or (csr.misa_c_en = '0') then -- uncompressed
381
              if (ipb.free = '1') then -- free entry in buffer?
382
                ipb.we                    <= '1';
383
                fetch_engine.pc_real_add  <= std_ulogic_vector(to_unsigned(4, data_width_c));
384
                fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(4, data_width_c));
385
                fetch_engine.state_nxt    <= IFETCH_0;
386
              end if;
387
 
388
            else -- compressed
389
              fetch_engine.pc_fetch_add  <= std_ulogic_vector(to_unsigned(2, data_width_c));
390
              fetch_engine.ci_return_nxt <= '1'; -- come back here after issueing
391
              fetch_engine.state_nxt     <= IFETCH_3;
392
            end if;
393
 
394
          else -- 16-bit aligned
395
            fetch_engine.ci_reg_nxt <= fetch_engine.i_buf2(33 downto 32) & fetch_engine.i_buf2(31 downto 16);
396
            ipb.wdata <= fetch_engine.i_buf(33 downto 32) & '0' & fetch_engine.i_buf(15 downto 00) & fetch_engine.i_buf2(31 downto 16);
397
 
398
            if (fetch_engine.i_buf2(17 downto 16) = "11") then -- uncompressed
399
              if (ipb.free = '1') then -- free entry in buffer?
400
                ipb.we                    <= '1';
401
                fetch_engine.pc_real_add  <= std_ulogic_vector(to_unsigned(4, data_width_c));
402
                fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(4, data_width_c));
403
                fetch_engine.state_nxt    <= IFETCH_0;
404
              end if;
405
 
406
            else -- compressed
407
              fetch_engine.pc_fetch_add  <= std_ulogic_vector(to_unsigned(2, data_width_c));
408
              fetch_engine.ci_return_nxt <= '0'; -- start next fetch after issueing
409
              fetch_engine.state_nxt     <= IFETCH_3;
410
            end if;
411
          end if;
412
        else
413
         fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(4, data_width_c));
414
         fetch_engine.state_nxt    <= IFETCH_0;
415
        end if;
416
 
417
      when IFETCH_3 => -- additional cycle for issueing decompressed instructions
418
      -- ------------------------------------------------------------
419
        if (ipb.free = '1') then -- free entry in buffer?
420
          ipb.we    <= '1';
421
          ipb.wdata <= fetch_engine.ci_reg(17 downto 16) & '1' & ci_instr32;
422
          fetch_engine.pc_real_add <= std_ulogic_vector(to_unsigned(2, data_width_c));
423
          if (fetch_engine.ci_return = '0') then
424
            fetch_engine.state_nxt <= IFETCH_0;
425
          else
426
            fetch_engine.state_nxt <= IFETCH_2;
427
          end if;
428
        end if;
429
 
430
      when others => -- undefined
431
      -- ------------------------------------------------------------
432
        fetch_engine.state_nxt <= IFETCH_RESET;
433
 
434
    end case;
435
  end process fetch_engine_fsm_comb;
436
 
437
 
438
-- ****************************************************************************************************************************
439
-- Instruction Prefetch Buffer
440
-- ****************************************************************************************************************************
441
 
442
 
443
  -- Instruction Prefetch Buffer Stage ------------------------------------------------------
444
  -- -------------------------------------------------------------------------------------------
445
  instr_prefetch_buffer: process(rstn_i, clk_i)
446
  begin
447
    if (rstn_i = '0') then
448
      ipb.status <= '0';
449
      ipb.rdata  <= (others => '0');
450
      ipb.raddr  <= (others => '0');
451
    elsif rising_edge(clk_i) then
452
      if (ipb.clear = '1') then
453
        ipb.status <= '0';
454
      elsif (ipb.we = '1') then
455
        ipb.status <= '1';
456
      elsif (ipb.re = '1') then
457
        ipb.status <= '0';
458
      end if;
459
      if (ipb.we = '1') then
460
        ipb.rdata <= ipb.wdata;
461
        ipb.raddr <= ipb.waddr;
462
      end if;
463
    end if;
464
  end process instr_prefetch_buffer;
465
 
466
  -- status --
467
  ipb.free  <= not ipb.status;
468
  ipb.avail <= ipb.status;
469
 
470
 
471
-- ****************************************************************************************************************************
472
-- Instruction Execution
473
-- ****************************************************************************************************************************
474
 
475
 
476 2 zero_gravi
  -- Immediate Generator --------------------------------------------------------------------
477
  -- -------------------------------------------------------------------------------------------
478
  imm_gen: process(clk_i)
479
  begin
480
    if rising_edge(clk_i) then
481 6 zero_gravi
      case execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) is
482 2 zero_gravi
        when opcode_store_c => -- S-immediate
483 6 zero_gravi
          imm_o(31 downto 11) <= (others => execute_engine.i_reg(31)); -- sign extension
484
          imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
485
          imm_o(04 downto 01) <= execute_engine.i_reg(11 downto 08);
486
          imm_o(00)           <= execute_engine.i_reg(07);
487 2 zero_gravi
        when opcode_branch_c => -- B-immediate
488 6 zero_gravi
          imm_o(31 downto 12) <= (others => execute_engine.i_reg(31)); -- sign extension
489
          imm_o(11)           <= execute_engine.i_reg(07);
490
          imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
491
          imm_o(04 downto 01) <= execute_engine.i_reg(11 downto 08);
492
          imm_o(00)           <= '0';
493 2 zero_gravi
        when opcode_lui_c | opcode_auipc_c => -- U-immediate
494 6 zero_gravi
          imm_o(31 downto 20) <= execute_engine.i_reg(31 downto 20);
495
          imm_o(19 downto 12) <= execute_engine.i_reg(19 downto 12);
496
          imm_o(11 downto 00) <= (others => '0');
497 2 zero_gravi
        when opcode_jal_c => -- J-immediate
498 6 zero_gravi
          imm_o(31 downto 20) <= (others => execute_engine.i_reg(31)); -- sign extension
499
          imm_o(19 downto 12) <= execute_engine.i_reg(19 downto 12);
500
          imm_o(11)           <= execute_engine.i_reg(20);
501
          imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
502
          imm_o(04 downto 01) <= execute_engine.i_reg(24 downto 21);
503
          imm_o(00)           <= '0';
504 2 zero_gravi
        when opcode_syscsr_c => -- CSR-immediate
505 6 zero_gravi
          imm_o(31 downto 05) <= (others => '0');
506
          imm_o(04 downto 00) <= execute_engine.i_reg(19 downto 15);
507 2 zero_gravi
        when others => -- I-immediate
508 6 zero_gravi
          imm_o(31 downto 11) <= (others => execute_engine.i_reg(31)); -- sign extension
509
          imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
510
          imm_o(04 downto 01) <= execute_engine.i_reg(24 downto 21);
511
          imm_o(00)           <= execute_engine.i_reg(20);
512 2 zero_gravi
      end case;
513
    end if;
514
  end process imm_gen;
515
 
516
 
517
  -- Branch Condition Check -----------------------------------------------------------------
518
  -- -------------------------------------------------------------------------------------------
519 6 zero_gravi
  branch_check: process(execute_engine.i_reg, cmp_i)
520 2 zero_gravi
  begin
521 6 zero_gravi
    case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is
522 2 zero_gravi
      when funct3_beq_c => -- branch if equal
523 6 zero_gravi
        execute_engine.branch_taken <= cmp_i(alu_cmp_equal_c);
524 2 zero_gravi
      when funct3_bne_c => -- branch if not equal
525 6 zero_gravi
        execute_engine.branch_taken <= not cmp_i(alu_cmp_equal_c);
526 2 zero_gravi
      when funct3_blt_c | funct3_bltu_c => -- branch if less (signed/unsigned)
527 6 zero_gravi
        execute_engine.branch_taken <= cmp_i(alu_cmp_less_c);
528 2 zero_gravi
      when funct3_bge_c | funct3_bgeu_c => -- branch if greater or equal (signed/unsigned)
529 6 zero_gravi
        execute_engine.branch_taken <= not cmp_i(alu_cmp_less_c);
530 2 zero_gravi
      when others => -- undefined
531 6 zero_gravi
        execute_engine.branch_taken <= '0';
532 2 zero_gravi
    end case;
533
  end process branch_check;
534
 
535
 
536 6 zero_gravi
  -- Execute Engine FSM Sync ----------------------------------------------------------------
537 2 zero_gravi
  -- -------------------------------------------------------------------------------------------
538 6 zero_gravi
  -- for registers that require a specific reset state --
539
  execute_engine_fsm_sync_rst: process(rstn_i, clk_i)
540 2 zero_gravi
  begin
541
    if (rstn_i = '0') then
542 6 zero_gravi
      if (BOOTLOADER_USE = true) then -- boot from bootloader ROM
543
        execute_engine.pc      <= boot_base_c(data_width_c-1 downto 1) & '0';
544
        execute_engine.last_pc <= boot_base_c(data_width_c-1 downto 1) & '0';
545
      else -- boot from IMEM
546
        execute_engine.pc      <= MEM_ISPACE_BASE(data_width_c-1 downto 1) & '0';
547
        execute_engine.last_pc <= MEM_ISPACE_BASE(data_width_c-1 downto 1) & '0';
548
      end if;
549 7 zero_gravi
      execute_engine.state      <= SYS_WAIT;
550
      execute_engine.state_prev <= SYS_WAIT;
551 2 zero_gravi
    elsif rising_edge(clk_i) then
552 6 zero_gravi
      execute_engine.pc <= execute_engine.pc_nxt(data_width_c-1 downto 1) & '0';
553
      if (execute_engine.state = EXECUTE) then
554
        execute_engine.last_pc <= execute_engine.pc(data_width_c-1 downto 1) & '0';
555
      end if;
556
      execute_engine.state      <= execute_engine.state_nxt;
557
      execute_engine.state_prev <= execute_engine.state;
558 2 zero_gravi
    end if;
559 6 zero_gravi
  end process execute_engine_fsm_sync_rst;
560 2 zero_gravi
 
561 6 zero_gravi
 
562
  -- for registers that DO NOT require a specific reset state --
563
  execute_engine_fsm_sync: process(clk_i)
564 2 zero_gravi
  begin
565
    if rising_edge(clk_i) then
566 6 zero_gravi
      execute_engine.i_reg   <= execute_engine.i_reg_nxt;
567
      execute_engine.is_ci   <= execute_engine.is_ci_nxt;
568
      execute_engine.is_jump <= execute_engine.is_jump_nxt;
569
      -- control signals --
570
      ctrl <= ctrl_nxt;
571 2 zero_gravi
    end if;
572 6 zero_gravi
  end process execute_engine_fsm_sync;
573 2 zero_gravi
 
574 6 zero_gravi
 
575
  -- PC output --
576
  execute_engine.next_pc <= std_ulogic_vector(unsigned(execute_engine.pc(data_width_c-1 downto 1) & '0') + 2) when (execute_engine.is_ci = '1') else
577
                            std_ulogic_vector(unsigned(execute_engine.pc(data_width_c-1 downto 1) & '0') + 4);
578
  fetch_pc_o <= fetch_engine.pc_fetch(data_width_c-1 downto 1) & '0';
579
  curr_pc_o  <= execute_engine.pc(data_width_c-1 downto 1) & '0';
580
  next_pc_o  <= execute_engine.next_pc(data_width_c-1 downto 1) & '0';
581
 
582
 
583
  -- CPU Control Bus Output -----------------------------------------------------------------
584
  -- -------------------------------------------------------------------------------------------
585
  ctrl_output: process(ctrl, execute_engine, csr, bus_fast_ir, bus_fast_rd, bus_fast_wr)
586 2 zero_gravi
  begin
587
    ctrl_o <= ctrl;
588
    -- direct output of register addresses --
589 6 zero_gravi
    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);
590
    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);
591
    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);
592
    -- bus access requests --
593
    ctrl_o(ctrl_bus_if_c) <= ctrl(ctrl_bus_if_c) or bus_fast_ir;
594
    ctrl_o(ctrl_bus_rd_c) <= ctrl(ctrl_bus_rd_c) or bus_fast_rd;
595
    ctrl_o(ctrl_bus_wr_c) <= ctrl(ctrl_bus_wr_c) or bus_fast_wr;
596
    -- cpu extension control --
597
    ctrl_o(ctrl_sys_c_ext_en_c) <= csr.misa_c_en; -- C extension enabled
598
    ctrl_o(ctrl_sys_m_ext_en_c) <= csr.misa_m_en; -- M extension enabled
599
  end process ctrl_output;
600 2 zero_gravi
 
601
 
602 6 zero_gravi
  -- Execute Engine FSM Comb ----------------------------------------------------------------
603
  -- -------------------------------------------------------------------------------------------
604
  execute_engine_fsm_comb: process(execute_engine, fetch_engine, ipb, trap_ctrl, csr, ctrl,
605
                                   alu_add_i, alu_wait_i, bus_wait_i, ma_load_i, be_load_i, ma_store_i, be_store_i)
606 2 zero_gravi
    variable alu_immediate_v : std_ulogic;
607
    variable alu_operation_v : std_ulogic_vector(2 downto 0);
608 6 zero_gravi
    variable rd_is_r0_v      : std_ulogic;
609 2 zero_gravi
    variable rs1_is_r0_v     : std_ulogic;
610
  begin
611
    -- arbiter defaults --
612 6 zero_gravi
    execute_engine.state_nxt   <= execute_engine.state;
613
    execute_engine.i_reg_nxt   <= execute_engine.i_reg;
614
    execute_engine.is_jump_nxt <= '0';
615
    execute_engine.is_ci_nxt   <= execute_engine.is_ci;
616
    execute_engine.pc_nxt      <= execute_engine.pc(data_width_c-1 downto 1) & '0';
617 2 zero_gravi
 
618 6 zero_gravi
    -- instruction dispatch --
619
    fetch_engine.reset         <= '0';
620
    ipb.re                     <= '0';
621 2 zero_gravi
 
622 6 zero_gravi
    -- trap environment control --
623
    trap_ctrl.env_start_ack    <= '0';
624
    trap_ctrl.env_end          <= '0';
625
 
626
    -- bus access (fast) --
627
    bus_fast_rd                <= '0';
628
    bus_fast_wr                <= '0';
629
 
630 2 zero_gravi
    -- exception trigger --
631 6 zero_gravi
    trap_ctrl.instr_be         <= '0';
632
    trap_ctrl.instr_ma         <= '0';
633
    trap_ctrl.env_call         <= '0';
634
    trap_ctrl.break_point      <= '0';
635 2 zero_gravi
 
636 6 zero_gravi
    -- CSR access --
637
    csr.we_nxt                 <= '0';
638
    csr.re_nxt                 <= '0';
639
 
640 2 zero_gravi
    -- control defaults --
641
    ctrl_nxt <= (others => '0'); -- all off at first
642 6 zero_gravi
    ctrl_nxt(ctrl_bus_unsigned_c) <= execute_engine.i_reg(instr_funct3_msb_c); -- unsigned LOAD (LBU, LHU)
643
    if (execute_engine.i_reg(instr_opcode_lsb_c+4) = '1') then -- ALU ops
644
      ctrl_nxt(ctrl_alu_unsigned_c) <= execute_engine.i_reg(instr_funct3_lsb_c+0); -- unsigned ALU operation (SLTIU, SLTU)
645 2 zero_gravi
    else -- branches
646 6 zero_gravi
      ctrl_nxt(ctrl_alu_unsigned_c) <= execute_engine.i_reg(instr_funct3_lsb_c+1); -- unsigned branches (BLTU, BGEU)
647 2 zero_gravi
    end if;
648 6 zero_gravi
    ctrl_nxt(ctrl_alu_shift_dir_c) <= execute_engine.i_reg(instr_funct3_msb_c); -- shift direction
649
    ctrl_nxt(ctrl_alu_shift_ar_c)  <= execute_engine.i_reg(30); -- arithmetic shift
650
    ctrl_nxt(ctrl_bus_size_lsb_c)  <= execute_engine.i_reg(instr_funct3_lsb_c+0); -- transfer size lsb (00=byte, 01=half-word)
651
    ctrl_nxt(ctrl_bus_size_msb_c)  <= execute_engine.i_reg(instr_funct3_lsb_c+1); -- transfer size msb (10=word, 11=?)
652 2 zero_gravi
    ctrl_nxt(ctrl_alu_cmd2_c  downto ctrl_alu_cmd0_c)  <= alu_cmd_add_c; -- actual ALU operation = add
653 6 zero_gravi
    ctrl_nxt(ctrl_cp_cmd2_c   downto ctrl_cp_cmd0_c)   <= execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c); -- CP operation
654 2 zero_gravi
    ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_muldiv_c; -- only CP0 implemented yet
655
 
656
    -- is immediate operation? --
657
    alu_immediate_v := '0';
658 6 zero_gravi
    if (execute_engine.i_reg(instr_opcode_msb_c-1) = '0') then
659 2 zero_gravi
      alu_immediate_v := '1';
660
    end if;
661
 
662 6 zero_gravi
    -- alu operation re-coding --
663
    case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is
664 2 zero_gravi
      when funct3_subadd_c => -- SUB / ADD(I)
665 6 zero_gravi
        if (alu_immediate_v = '0') and (execute_engine.i_reg(instr_funct7_msb_c-1) = '1') then -- not immediate and funct7 = SUB
666 2 zero_gravi
          alu_operation_v := alu_cmd_sub_c;
667
        else
668
          alu_operation_v := alu_cmd_add_c;
669
        end if;
670
      when funct3_sll_c  => alu_operation_v := alu_cmd_shift_c; -- SLL(I)
671 6 zero_gravi
      when funct3_slt_c  => alu_operation_v := alu_cmd_slt_c;   -- SLT(I)
672
      when funct3_sltu_c => alu_operation_v := alu_cmd_slt_c;   -- SLTU(I)
673
      when funct3_xor_c  => alu_operation_v := alu_cmd_xor_c;   -- XOR(I)
674 2 zero_gravi
      when funct3_sr_c   => alu_operation_v := alu_cmd_shift_c; -- SRL(I) / SRA(I)
675 6 zero_gravi
      when funct3_or_c   => alu_operation_v := alu_cmd_or_c;    -- OR(I)
676
      when funct3_and_c  => alu_operation_v := alu_cmd_and_c;   -- AND(I)
677 3 zero_gravi
      when others        => alu_operation_v := (others => '0'); -- undefined
678 2 zero_gravi
    end case;
679
 
680 6 zero_gravi
    -- is rd = r0? --
681
    rd_is_r0_v := '0';
682
    if (execute_engine.i_reg(instr_rd_msb_c downto instr_rd_lsb_c) = "00000") then
683
      rd_is_r0_v := '1';
684
    end if;
685
 
686 2 zero_gravi
    -- is rs1 = r0? --
687
    rs1_is_r0_v := '0';
688 6 zero_gravi
    if (execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c) = "00000") then
689 2 zero_gravi
      rs1_is_r0_v := '1';
690
    end if;
691
 
692 6 zero_gravi
    -- state machine --
693
    case execute_engine.state is
694 2 zero_gravi
 
695 7 zero_gravi
      when SYS_WAIT => -- Delay cycle (used to wait for side effects to kick in)
696 2 zero_gravi
      -- ------------------------------------------------------------
697 6 zero_gravi
        execute_engine.state_nxt <= DISPATCH;
698 2 zero_gravi
 
699 6 zero_gravi
       when DISPATCH => -- Get new command from instruction prefetch buffer (IPB)
700
       -- ------------------------------------------------------------
701
         if (ipb.avail = '1') then -- instruction available?
702
           ipb.re <= '1';
703
           trap_ctrl.instr_ma    <= ipb.rdata(33);
704
           trap_ctrl.instr_be    <= ipb.rdata(34);
705
           if (trap_ctrl.env_start = '1') or (ipb.rdata(33) = '1') or (ipb.rdata(34) = '1') then -- exception/interrupt?
706
             execute_engine.state_nxt <= TRAP;
707
           else
708
             execute_engine.is_ci_nxt <= ipb.rdata(32); -- flag to indicate this is a compressed instruction beeing executed
709
             execute_engine.i_reg_nxt <= ipb.rdata(31 downto 0);
710
             execute_engine.pc_nxt    <= ipb.raddr(data_width_c-1 downto 1) & '0'; -- the PC according to the current instruction
711
             execute_engine.state_nxt <= EXECUTE;
712
           end if;
713
         end if;
714 2 zero_gravi
 
715 6 zero_gravi
      when TRAP => -- Start trap environment (also used as sleep state)
716 2 zero_gravi
      -- ------------------------------------------------------------
717 6 zero_gravi
        if (trap_ctrl.env_start = '1') then
718
          trap_ctrl.env_start_ack  <= '1';
719
          execute_engine.pc_nxt    <= csr.mtvec(data_width_c-1 downto 1) & '0';
720
          fetch_engine.reset       <= '1';
721 7 zero_gravi
          execute_engine.state_nxt <= SYS_WAIT;
722 2 zero_gravi
        end if;
723
 
724 6 zero_gravi
      when EXECUTE => -- Decode and execute instruction
725 2 zero_gravi
      -- ------------------------------------------------------------
726 6 zero_gravi
        case execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) is
727 2 zero_gravi
 
728
          when opcode_alu_c | opcode_alui_c => -- ALU operation
729
          -- ------------------------------------------------------------
730
            ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- use RS1 as ALU.OPA
731
            ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= alu_immediate_v; -- use IMM as ALU.OPB for immediate operations
732
            ctrl_nxt(ctrl_alu_opc_mux_c)     <= not alu_immediate_v;
733
            ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_operation_v; -- actual ALU operation
734
            ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "00"; -- RF input = ALU result
735 6 zero_gravi
            if (CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_alu_c) and
736
               (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV?
737 2 zero_gravi
              ctrl_nxt(ctrl_cp_use_c) <= '1'; -- use CP
738
              ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_muldiv_c; -- muldiv CP
739 6 zero_gravi
              execute_engine.state_nxt <= ALU_WAIT;
740 2 zero_gravi
            elsif (alu_operation_v = alu_cmd_shift_c) then -- multi-cycle shift operation?
741 6 zero_gravi
              execute_engine.state_nxt <= ALU_WAIT;
742 2 zero_gravi
            else
743
              ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
744 6 zero_gravi
              execute_engine.state_nxt <= DISPATCH;
745 2 zero_gravi
            end if;
746
 
747
          when opcode_lui_c | opcode_auipc_c => -- load upper immediate (add to PC)
748
          -- ------------------------------------------------------------
749
            ctrl_nxt(ctrl_rf_clear_rs1_c) <= '1'; -- force RS1 = r0
750 6 zero_gravi
            if (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_auipc_c) then -- AUIPC
751 2 zero_gravi
              ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '1'; -- use PC as ALU.OPA
752
            else -- LUI
753
              ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- use RS1 as ALU.OPA
754
            end if;
755 6 zero_gravi
            ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- use IMM as ALU.OPB
756 2 zero_gravi
            ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- actual ALU operation
757
            ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "00"; -- RF input = ALU result
758
            ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
759 6 zero_gravi
            execute_engine.state_nxt <= DISPATCH;
760 2 zero_gravi
 
761
          when opcode_load_c | opcode_store_c => -- load/store
762
          -- ------------------------------------------------------------
763
            ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- use RS1 as ALU.OPA
764
            ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- use IMM as ALU.OPB
765
            ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- actual ALU operation
766 6 zero_gravi
            ctrl_nxt(ctrl_bus_mar_we_c) <= '1'; -- write to MAR
767
            ctrl_nxt(ctrl_bus_mdo_we_c) <= '1'; -- write to MDO (only relevant for stores)
768
            if (fetch_engine.state /= IFETCH_0) then
769
              if (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_load_c) then -- LOAD
770
                execute_engine.state_nxt <= LOAD;
771
              else -- STORE
772
                execute_engine.state_nxt <= STORE;
773
              end if;
774 2 zero_gravi
            end if;
775
 
776
          when opcode_branch_c => -- branch instruction
777
          -- ------------------------------------------------------------
778
            ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '1'; -- use PC as ALU.OPA
779
            ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- use IMM as ALU.OPB
780 6 zero_gravi
            ctrl_nxt(ctrl_alu_opc_mux_c)     <= '1'; -- use RS2 as ALU.OPC
781
            execute_engine.state_nxt         <= BRANCH;
782 2 zero_gravi
 
783
          when opcode_jal_c | opcode_jalr_c => -- jump and link (with register)
784
          -- ------------------------------------------------------------
785
            -- compute target address --
786 6 zero_gravi
            if (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_jal_c) then -- JAL
787 2 zero_gravi
              ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '1'; -- use PC as ALU.OPA
788
            else -- JALR
789
              ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- use RS1 as ALU.OPA
790
            end if;
791
            ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- use IMM as ALU.OPB
792
            -- save return address --
793
            ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "10"; -- RF input = current PC
794
            ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
795 6 zero_gravi
            --
796
            execute_engine.is_jump_nxt <= '1'; -- this is a jump operation
797
            execute_engine.state_nxt   <= BRANCH;
798 2 zero_gravi
 
799 8 zero_gravi
          when opcode_fence_c => -- fence operations
800
          -- ------------------------------------------------------------
801
            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
802
              fetch_engine.reset       <= '1';
803
              execute_engine.pc_nxt    <= execute_engine.next_pc;
804
              execute_engine.state_nxt <= SYS_WAIT;
805
            else
806
              execute_engine.state_nxt <= DISPATCH;
807
            end if;
808
 
809 2 zero_gravi
          when opcode_syscsr_c => -- system/csr access
810
          -- ------------------------------------------------------------
811 6 zero_gravi
            if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or
812
               (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) then
813
              csr.re_nxt <= not rd_is_r0_v; -- only read CSR if not writing to zero_reg
814
            else
815
              csr.re_nxt <= '1'; -- always read CSR
816
            end if;
817
            --
818
            if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_env_c) then -- system
819
              case execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) is
820
                when x"000" => -- ECALL
821
                  trap_ctrl.env_call <= '1';
822 7 zero_gravi
                  execute_engine.state_nxt <= SYS_WAIT;
823 6 zero_gravi
                when x"001" => -- EBREAK
824
                  trap_ctrl.break_point <= '1';
825 7 zero_gravi
                  execute_engine.state_nxt <= SYS_WAIT;
826 6 zero_gravi
                when x"302" => -- MRET
827
                  trap_ctrl.env_end        <= '1';
828
                  execute_engine.pc_nxt    <= csr.mepc(data_width_c-1 downto 1) & '0';
829
                  fetch_engine.reset       <= '1';
830 7 zero_gravi
                  execute_engine.state_nxt <= SYS_WAIT;
831 6 zero_gravi
                when x"105" => -- WFI
832
                  execute_engine.state_nxt <= TRAP;
833
                when others => -- undefined
834
                  NULL;
835 2 zero_gravi
              end case;
836
            elsif (CPU_EXTENSION_RISCV_Zicsr = true) then -- CSR access
837 6 zero_gravi
              execute_engine.state_nxt <= CSR_ACCESS;
838 2 zero_gravi
            else
839 6 zero_gravi
              execute_engine.state_nxt <= DISPATCH;
840 2 zero_gravi
            end if;
841
 
842
          when others => -- undefined
843
          -- ------------------------------------------------------------
844 6 zero_gravi
            execute_engine.state_nxt <= DISPATCH;
845 2 zero_gravi
 
846
        end case;
847
 
848
      when CSR_ACCESS => -- write CSR data to RF, write ALU.res to CSR
849
      -- ------------------------------------------------------------
850
        ctrl_nxt(ctrl_alu_opa_mux_msb_c) <= '0'; -- default
851
        ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- default
852
        ctrl_nxt(ctrl_alu_opb_mux_msb_c) <= '0'; -- default
853
        ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '0'; -- default
854 6 zero_gravi
        case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is
855 7 zero_gravi
          -- register operations --
856 6 zero_gravi
          when funct3_csrrw_c => -- CSRRW
857 2 zero_gravi
            ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- OPA = rs1
858
            ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '0'; -- OPB = rs2
859
            ctrl_nxt(ctrl_rf_clear_rs2_c)    <= '1'; -- rs2 = 0
860
            ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- actual ALU operation = ADD
861 6 zero_gravi
            csr.we_nxt <= '1'; -- always write CSR
862
          when funct3_csrrs_c => -- CSRRS
863 2 zero_gravi
            ctrl_nxt(ctrl_alu_opa_mux_msb_c) <= '1'; -- OPA = csr
864
            ctrl_nxt(ctrl_alu_opb_mux_msb_c) <= '1'; -- OPB = crs1
865
            ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_or_c; -- actual ALU operation = OR
866 6 zero_gravi
            csr.we_nxt <= not rs1_is_r0_v; -- write CSR if rs1 is not zero_reg
867
          when funct3_csrrc_c => -- CSRRC
868 2 zero_gravi
            ctrl_nxt(ctrl_alu_opa_mux_msb_c) <= '1'; -- OPA = csr
869
            ctrl_nxt(ctrl_alu_opb_mux_msb_c) <= '1'; -- OPB = rs1
870
            ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_bitc_c; -- actual ALU operation = bit clear
871 6 zero_gravi
            csr.we_nxt <= not rs1_is_r0_v; -- write CSR if rs1 is not zero_reg
872 7 zero_gravi
          -- immediate operations --
873 6 zero_gravi
          when funct3_csrrwi_c => -- CSRRWI
874 2 zero_gravi
            ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- OPA = rs1
875
            ctrl_nxt(ctrl_rf_clear_rs1_c)    <= '1'; -- rs1 = 0
876
            ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- OPB = immediate
877
            ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- actual ALU operation = ADD
878 6 zero_gravi
            csr.we_nxt <= '1'; -- always write CSR
879
          when funct3_csrrsi_c => -- CSRRSI
880 2 zero_gravi
            ctrl_nxt(ctrl_alu_opa_mux_msb_c) <= '1'; -- OPA = csr
881
            ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- OPB = immediate
882
            ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_or_c; -- actual ALU operation = OR
883 6 zero_gravi
            csr.we_nxt <= not rs1_is_r0_v; -- write CSR if UIMM5 is not zero (bits from rs1 filed)
884
          when funct3_csrrci_c => -- CSRRCI
885 2 zero_gravi
            ctrl_nxt(ctrl_alu_opa_mux_msb_c) <= '1'; -- OPA = csr
886
            ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- OPB = immediate
887
            ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_bitc_c; -- actual ALU operation = bit clear
888 6 zero_gravi
            csr.we_nxt <= not rs1_is_r0_v; -- write CSR if UIMM5 is not zero (bits from rs1 filed)
889 2 zero_gravi
          when others => -- undefined
890
            NULL;
891
        end case;
892
        -- RF write back --
893
        ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "11"; -- RF input = CSR output register
894
        ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
895 9 zero_gravi
        execute_engine.state_nxt <= DISPATCH; -- FIXME should be SYS_WAIT? have another cycle to let side-effects kick in
896 2 zero_gravi
 
897 6 zero_gravi
      when ALU_WAIT => -- wait for multi-cycle ALU operation to finish
898 2 zero_gravi
      -- ------------------------------------------------------------
899 6 zero_gravi
        ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_operation_v; -- actual ALU operation
900
        ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "00"; -- RF input = ALU result
901
        ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back (write back all the time)
902
        if (alu_wait_i = '0') then
903
          execute_engine.state_nxt <= DISPATCH;
904 2 zero_gravi
        end if;
905
 
906 6 zero_gravi
      when BRANCH => -- update PC for taken branches and jumps
907
      -- ------------------------------------------------------------
908
        if (execute_engine.is_jump = '1') or (execute_engine.branch_taken = '1') then
909
          execute_engine.pc_nxt <= alu_add_i(data_width_c-1 downto 1) & '0';
910
          fetch_engine.reset    <= '1';
911
        end if;
912 7 zero_gravi
        execute_engine.state_nxt <= SYS_WAIT;
913 6 zero_gravi
 
914
      when LOAD => -- trigger memory read request
915
      -- ------------------------------------------------------------
916
        ctrl_nxt(ctrl_bus_rd_c)  <= '1';--bus_fast_rd <= '1'; -- fast read request
917
        execute_engine.state_nxt <= LOADSTORE_0;
918
 
919
      when STORE => -- trigger memory write request
920
      -- ------------------------------------------------------------
921
        ctrl_nxt(ctrl_bus_wr_c)  <= '1';--bus_fast_wr <= '1'; -- fast write request
922
        execute_engine.state_nxt <= LOADSTORE_0;
923
 
924
      when LOADSTORE_0 => -- memory latency
925
      -- ------------------------------------------------------------
926
        ctrl_nxt(ctrl_bus_mdi_we_c) <= '1'; -- write input data to MDI (only relevant for LOAD)
927
        execute_engine.state_nxt <= LOADSTORE_1;
928
 
929
      when LOADSTORE_1 => -- wait for bus transaction to finish
930
      -- ------------------------------------------------------------
931
        ctrl_nxt(ctrl_bus_mdi_we_c) <= '1'; -- keep writing input data to MDI (only relevant for LOAD)
932
        ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "01"; -- RF input = memory input (only relevant for LOAD)
933
        if (ma_load_i = '1') or (be_load_i = '1') or (ma_store_i = '1') or (be_store_i = '1') then -- abort if exception
934 7 zero_gravi
          execute_engine.state_nxt <= SYS_WAIT;
935 6 zero_gravi
        elsif (bus_wait_i = '0') then -- wait here for bus to finish transaction
936
          if (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_load_c) then -- LOAD?
937
            ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
938
          end if;
939
          execute_engine.state_nxt <= DISPATCH;
940
        end if;
941
 
942 2 zero_gravi
      when others => -- undefined
943
      -- ------------------------------------------------------------
944 7 zero_gravi
        execute_engine.state_nxt <= SYS_WAIT;
945 2 zero_gravi
 
946
    end case;
947 6 zero_gravi
  end process execute_engine_fsm_comb;
948 2 zero_gravi
 
949
 
950
  -- Illegal Instruction Check --------------------------------------------------------------
951
  -- -------------------------------------------------------------------------------------------
952 6 zero_gravi
  illegal_instruction_check: process(execute_engine, csr, ctrl_nxt, ci_illegal)
953 2 zero_gravi
  begin
954 6 zero_gravi
    if (execute_engine.state = EXECUTE) then
955 2 zero_gravi
      -- defaults --
956
      illegal_instruction <= '0';
957
      illegal_register    <= '0';
958
      illegal_compressed  <= '0';
959
 
960
      -- check if using reg >= 16 for E-CPUs --
961 6 zero_gravi
--if (CPU_EXTENSION_RISCV_E = true) then
962
--  illegal_register <= ctrl_nxt(ctrl_rf_rd_adr4_c) or ctrl_nxt(ctrl_rf_rs2_adr4_c) or ctrl_nxt(ctrl_rf_rs1_adr4_c);
963
--else
964
--  illegal_register <= '0';
965
--end if;
966 2 zero_gravi
 
967
      -- check instructions --
968 6 zero_gravi
      case execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) is
969 2 zero_gravi
 
970
        -- OPCODE check sufficient: LUI, UIPC, JAL --
971
        when opcode_lui_c | opcode_auipc_c | opcode_jal_c =>
972
          illegal_instruction <= '0';
973
 
974
        when opcode_alui_c => -- check ALUI funct7
975 6 zero_gravi
          if ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) and
976
              (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000")) or -- shift logical left
977
             ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c) and
978
              ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000") and
979
               (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0100000"))) then -- shift right
980 2 zero_gravi
            illegal_instruction <= '1';
981
          else
982
            illegal_instruction <= '0';
983
          end if;
984
 
985
        when opcode_load_c => -- check LOAD funct3
986 6 zero_gravi
          if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lb_c) or
987
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lh_c) or
988
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lw_c) or
989
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lbu_c) or
990
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lhu_c) then
991 2 zero_gravi
            illegal_instruction <= '0';
992
          else
993
            illegal_instruction <= '1';
994
          end if;
995
 
996
        when opcode_store_c => -- check STORE funct3
997 6 zero_gravi
          if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sb_c) or
998
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sh_c) or
999
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sw_c) then
1000 2 zero_gravi
            illegal_instruction <= '0';
1001
          else
1002
            illegal_instruction <= '1';
1003
          end if;
1004
 
1005
        when opcode_branch_c => -- check BRANCH funct3
1006 6 zero_gravi
          if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_beq_c) or
1007
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bne_c) or
1008
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_blt_c) or
1009
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bge_c) or
1010
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bltu_c) or
1011
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bgeu_c) then
1012 2 zero_gravi
            illegal_instruction <= '0';
1013
          else
1014
            illegal_instruction <= '1';
1015
          end if;
1016
 
1017
        when opcode_jalr_c => -- check JALR funct3
1018 6 zero_gravi
          if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "000") then
1019 2 zero_gravi
            illegal_instruction <= '0';
1020
          else
1021
            illegal_instruction <= '1';
1022
          end if;
1023
 
1024
        when opcode_alu_c => -- check ALU funct3 & funct7
1025 6 zero_gravi
          if (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV
1026
            if (CPU_EXTENSION_RISCV_M = false) or (csr.misa_m_en = '0') then -- not implemented or disabled
1027 2 zero_gravi
              illegal_instruction <= '1';
1028
            end if;
1029 6 zero_gravi
          elsif ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_subadd_c) or
1030
                 (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c)) and -- ADD/SUB or SRA/SRL check
1031
                ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000") and
1032
                 (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0100000")) then -- ADD/SUB or SRA/SRL select
1033 2 zero_gravi
            illegal_instruction <= '1';
1034
          else
1035
            illegal_instruction <= '0';
1036
          end if;
1037
 
1038 8 zero_gravi
        when opcode_fence_c => -- fence instructions --
1039
          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
1040
            illegal_instruction <= '0';
1041
          elsif (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fence_c) then -- FENCE
1042
            illegal_instruction <= '0';
1043
          else
1044
            illegal_instruction <= '1';
1045
          end if;
1046
 
1047 2 zero_gravi
        when opcode_syscsr_c => -- check system instructions --
1048
          -- CSR access --
1049 6 zero_gravi
          if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or
1050
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrs_c) or
1051
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrc_c) or
1052
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) or
1053
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrsi_c) or
1054
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrci_c) then
1055 2 zero_gravi
            -- valid CSR? --
1056 6 zero_gravi
            if (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"300") or -- mstatus
1057
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"301") or -- misa
1058
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"304") or -- mie
1059
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"305") or -- mtvev
1060
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"340") or -- mscratch
1061
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"341") or -- mepc
1062
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"342") or -- mcause
1063
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"343") or -- mtval
1064
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"344") or -- mip
1065 2 zero_gravi
               --
1066 6 zero_gravi
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c00") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- cycle
1067
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c01") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- time
1068
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c02") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- instret
1069
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c80") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- cycleh
1070
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c81") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- timeh
1071
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c82") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- instreth
1072 2 zero_gravi
               --
1073 6 zero_gravi
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"b00") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- mcycle
1074
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"b02") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- minstret
1075
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"b80") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- mcycleh
1076
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"b82") and (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true)) or -- minstreth
1077 2 zero_gravi
               --
1078 6 zero_gravi
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"f13") or -- mimpid
1079
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"f14") or -- mhartid
1080 2 zero_gravi
               --
1081 6 zero_gravi
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc0") or -- mfeatures
1082
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc1") or -- mclock
1083
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc4") or -- mispacebase
1084
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc5") or -- mispacesize
1085
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc6") or -- mdspacebase
1086
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc7") then -- mdspacesize
1087 2 zero_gravi
              illegal_instruction <= '0';
1088
            else
1089
              illegal_instruction <= '1';
1090
            end if;
1091
 
1092
          -- ecall, ebreak, mret, wfi --
1093 6 zero_gravi
          elsif (execute_engine.i_reg(instr_rd_msb_c  downto instr_rd_lsb_c)  = "00000") and
1094
                (execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c) = "00000") then
1095
            if (execute_engine.i_reg(instr_funct12_msb_c  downto instr_funct12_lsb_c) = "000000000000") or -- ECALL
1096
               (execute_engine.i_reg(instr_funct12_msb_c  downto instr_funct12_lsb_c) = "000000000001") or -- EBREAK 
1097
               (execute_engine.i_reg(instr_funct12_msb_c  downto instr_funct12_lsb_c) = "001100000010") or -- MRET
1098
               (execute_engine.i_reg(instr_funct12_msb_c  downto instr_funct12_lsb_c) = "000100000101") then -- WFI
1099 2 zero_gravi
              illegal_instruction <= '0';
1100
            else
1101
              illegal_instruction <= '1';
1102
            end if;
1103
          else
1104
            illegal_instruction <= '1';
1105
          end if;
1106
 
1107
        when others => -- compressed instruction or undefined instruction
1108 6 zero_gravi
          if (execute_engine.i_reg(1 downto 0) = "11") then -- undefined/unimplemented opcode
1109 2 zero_gravi
            illegal_instruction <= '1';
1110 6 zero_gravi
          else -- compressed instruction: illegal or disabled / not implemented
1111
            illegal_compressed <= ci_illegal or (not csr.misa_c_en);
1112 2 zero_gravi
          end if;
1113
 
1114
      end case;
1115
    else
1116
      illegal_instruction <= '0';
1117
      illegal_register    <= '0';
1118
      illegal_compressed  <= '0';
1119
    end if;
1120
  end process illegal_instruction_check;
1121
 
1122
  -- any illegal condition? --
1123 6 zero_gravi
  trap_ctrl.instr_il <= illegal_instruction or illegal_register or illegal_compressed;
1124 2 zero_gravi
 
1125
 
1126 6 zero_gravi
-- ****************************************************************************************************************************
1127
-- Exception and Interrupt Control
1128
-- ****************************************************************************************************************************
1129 2 zero_gravi
 
1130
 
1131 6 zero_gravi
  -- Trap Controller ------------------------------------------------------------------------
1132 2 zero_gravi
  -- -------------------------------------------------------------------------------------------
1133 6 zero_gravi
  trap_controller: process(rstn_i, clk_i)
1134 2 zero_gravi
  begin
1135
    if (rstn_i = '0') then
1136 6 zero_gravi
      trap_ctrl.exc_buf   <= (others => '0');
1137
      trap_ctrl.irq_buf   <= (others => '0');
1138
      trap_ctrl.exc_ack   <= '0';
1139
      trap_ctrl.irq_ack   <= (others => '0');
1140
      trap_ctrl.cause     <= (others => '0');
1141
      trap_ctrl.exc_src   <= (others => '0');
1142
      trap_ctrl.env_start <= '0';
1143 2 zero_gravi
    elsif rising_edge(clk_i) then
1144
      if (CPU_EXTENSION_RISCV_Zicsr = true) then
1145
        -- exception buffer: misaligned load/store/instruction address
1146 6 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);
1147
        trap_ctrl.exc_buf(exception_salign_c)    <= (trap_ctrl.exc_buf(exception_salign_c)    or ma_store_i)            and (not trap_ctrl.exc_ack);
1148
        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);
1149 2 zero_gravi
        -- exception buffer: load/store/instruction bus access error
1150 6 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);
1151
        trap_ctrl.exc_buf(exception_saccess_c)   <= (trap_ctrl.exc_buf(exception_saccess_c)   or be_store_i)            and (not trap_ctrl.exc_ack);
1152
        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);
1153 2 zero_gravi
        -- exception buffer: illegal instruction / env call / break point
1154 6 zero_gravi
        trap_ctrl.exc_buf(exception_m_envcall_c) <= (trap_ctrl.exc_buf(exception_m_envcall_c) or trap_ctrl.env_call)    and (not trap_ctrl.exc_ack);
1155
        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);
1156
        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);
1157 2 zero_gravi
        -- interrupt buffer: machine software/external/timer interrupt
1158 6 zero_gravi
        trap_ctrl.irq_buf(interrupt_msw_irq_c)   <= csr.mie_msie and (trap_ctrl.irq_buf(interrupt_msw_irq_c)   or csr.mip_msip) and (not trap_ctrl.irq_ack(interrupt_msw_irq_c));
1159
        trap_ctrl.irq_buf(interrupt_mext_irq_c)  <= csr.mie_meie and (trap_ctrl.irq_buf(interrupt_mext_irq_c)  or clic_irq_i)   and (not trap_ctrl.irq_ack(interrupt_mext_irq_c));
1160
        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));
1161 2 zero_gravi
 
1162 6 zero_gravi
        -- trap control --
1163
        if (trap_ctrl.env_start = '0') then -- no started trap handler
1164
          if (trap_ctrl.exc_fire = '1') or ((trap_ctrl.irq_fire = '1') and
1165
             ((execute_engine.state = EXECUTE) or (execute_engine.state = TRAP))) then -- exception/IRQ detected!
1166 7 zero_gravi
            trap_ctrl.cause     <= trap_ctrl.cause_nxt;   -- capture source ID for program
1167
            trap_ctrl.exc_src   <= trap_ctrl.exc_buf;     -- capture exception source for hardware
1168
            trap_ctrl.exc_ack   <= '1';                   -- clear execption
1169
            trap_ctrl.irq_ack   <= trap_ctrl.irq_ack_nxt; -- capture and clear with interrupt ACK mask
1170
            trap_ctrl.env_start <= '1';                   -- now we want to start the trap handler
1171 2 zero_gravi
          end if;
1172 6 zero_gravi
        else -- trap waiting to get started
1173
          if (trap_ctrl.env_start_ack = '1') then -- start of trap handler acknowledged by execution engine
1174
            trap_ctrl.exc_ack   <= '0';
1175
            trap_ctrl.irq_ack   <= (others => '0');
1176
            trap_ctrl.env_start <= '0';
1177 2 zero_gravi
          end if;
1178
        end if;
1179
      end if;
1180
    end if;
1181 6 zero_gravi
  end process trap_controller;
1182 2 zero_gravi
 
1183
  -- any exception/interrupt? --
1184 6 zero_gravi
  trap_ctrl.exc_fire <= or_all_f(trap_ctrl.exc_buf); -- classic exceptions (faults/traps) cannot be masked
1185
  trap_ctrl.irq_fire <= or_all_f(trap_ctrl.irq_buf) and csr.mstatus_mie; -- classic interrupts can be enabled/disabled
1186 2 zero_gravi
 
1187
  -- exception acknowledge for bus unit --
1188 6 zero_gravi
  bus_exc_ack_o <= trap_ctrl.env_start_ack or fetch_engine.bus_err_ack;
1189 2 zero_gravi
 
1190 6 zero_gravi
  -- exception/interrupt/status ID visible for program --
1191
  csr.mcause <= trap_ctrl.cause;
1192
 
1193
 
1194
  -- Trap Priority Detector -----------------------------------------------------------------
1195
  -- -------------------------------------------------------------------------------------------
1196
  trap_priority: process(trap_ctrl)
1197 2 zero_gravi
  begin
1198
    -- defaults --
1199 6 zero_gravi
    trap_ctrl.cause_nxt   <= (others => '0');
1200
    trap_ctrl.irq_ack_nxt <= (others => '0');
1201 2 zero_gravi
 
1202 9 zero_gravi
    -- the following traps are caused by asynchronous exceptions (-> interrupts)
1203
    -- here we do need an acknowledge mask since several sources can trigger at once
1204
 
1205 2 zero_gravi
    -- interrupt: 1.11 machine external interrupt --
1206 6 zero_gravi
    if (trap_ctrl.irq_buf(interrupt_mext_irq_c) = '1') then
1207
      trap_ctrl.cause_nxt(data_width_c-1) <= '1';
1208
      trap_ctrl.cause_nxt(3 downto 0) <= "1011";
1209
      trap_ctrl.irq_ack_nxt(interrupt_mext_irq_c) <= '1';
1210 2 zero_gravi
 
1211
    -- interrupt: 1.7 machine timer interrupt --
1212 6 zero_gravi
    elsif (trap_ctrl.irq_buf(interrupt_mtime_irq_c) = '1') then
1213
      trap_ctrl.cause_nxt(data_width_c-1) <= '1';
1214
      trap_ctrl.cause_nxt(3 downto 0) <= "0111";
1215
      trap_ctrl.irq_ack_nxt(interrupt_mtime_irq_c) <= '1';
1216 2 zero_gravi
 
1217
    -- interrupt: 1.3 machine SW interrupt --
1218 6 zero_gravi
    elsif (trap_ctrl.irq_buf(interrupt_msw_irq_c) = '1') then
1219
      trap_ctrl.cause_nxt(data_width_c-1) <= '1';
1220
      trap_ctrl.cause_nxt(3 downto 0) <= "0011";
1221
      trap_ctrl.irq_ack_nxt(interrupt_msw_irq_c) <= '1';
1222 2 zero_gravi
 
1223
 
1224 4 zero_gravi
    -- the following traps are caused by synchronous exceptions
1225 9 zero_gravi
    -- here we do not need an acknowledge mask since only one exception (the one
1226
    -- with highest priority) can trigger at once
1227 4 zero_gravi
 
1228 2 zero_gravi
    -- trap/fault: 0.0 instruction address misaligned --
1229 6 zero_gravi
    elsif (trap_ctrl.exc_buf(exception_ialign_c) = '1') then
1230
      trap_ctrl.cause_nxt(data_width_c-1) <= '0';
1231
      trap_ctrl.cause_nxt(3 downto 0) <= "0000";
1232 2 zero_gravi
 
1233
    -- trap/fault: 0.1 instruction access fault --
1234 6 zero_gravi
    elsif (trap_ctrl.exc_buf(exception_iaccess_c) = '1') then
1235
      trap_ctrl.cause_nxt(data_width_c-1) <= '0';
1236
      trap_ctrl.cause_nxt(3 downto 0) <= "0001";
1237 2 zero_gravi
 
1238
    -- trap/fault: 0.2 illegal instruction --
1239 6 zero_gravi
    elsif (trap_ctrl.exc_buf(exception_iillegal_c) = '1') then
1240
      trap_ctrl.cause_nxt(data_width_c-1) <= '0';
1241
      trap_ctrl.cause_nxt(3 downto 0) <= "0010";
1242 2 zero_gravi
 
1243
 
1244
    -- trap/fault: 0.11 environment call from M-mode --
1245 6 zero_gravi
    elsif (trap_ctrl.exc_buf(exception_m_envcall_c) = '1') then
1246
      trap_ctrl.cause_nxt(data_width_c-1) <= '0';
1247
      trap_ctrl.cause_nxt(3 downto 0) <= "1011";
1248 2 zero_gravi
 
1249
    -- trap/fault: 0.3 breakpoint --
1250 6 zero_gravi
    elsif (trap_ctrl.exc_buf(exception_break_c) = '1') then
1251
      trap_ctrl.cause_nxt(data_width_c-1) <= '0';
1252
      trap_ctrl.cause_nxt(3 downto 0) <= "0011";
1253 2 zero_gravi
 
1254
 
1255
    -- trap/fault: 0.6 store address misaligned -
1256 6 zero_gravi
    elsif (trap_ctrl.exc_buf(exception_salign_c) = '1') then
1257
      trap_ctrl.cause_nxt(data_width_c-1) <= '0';
1258
      trap_ctrl.cause_nxt(3 downto 0) <= "0110";
1259 2 zero_gravi
 
1260
    -- trap/fault: 0.4 load address misaligned --
1261 6 zero_gravi
    elsif (trap_ctrl.exc_buf(exception_lalign_c) = '1') then
1262
      trap_ctrl.cause_nxt(data_width_c-1) <= '0';
1263
      trap_ctrl.cause_nxt(3 downto 0) <= "0100";
1264 2 zero_gravi
 
1265
    -- trap/fault: 0.7 store access fault --
1266 6 zero_gravi
    elsif (trap_ctrl.exc_buf(exception_saccess_c) = '1') then
1267
      trap_ctrl.cause_nxt(data_width_c-1) <= '0';
1268
      trap_ctrl.cause_nxt(3 downto 0) <= "0111";
1269 2 zero_gravi
 
1270
    -- trap/fault: 0.5 load access fault --
1271 6 zero_gravi
    elsif (trap_ctrl.exc_buf(exception_laccess_c) = '1') then
1272
      trap_ctrl.cause_nxt(data_width_c-1) <= '0';
1273
      trap_ctrl.cause_nxt(3 downto 0) <= "0101";
1274 2 zero_gravi
 
1275
    -- undefined / not implemented --
1276
    else
1277 6 zero_gravi
      trap_ctrl.cause_nxt   <= (others => '0');
1278
      trap_ctrl.irq_ack_nxt <= (others => '0');
1279 2 zero_gravi
    end if;
1280 6 zero_gravi
  end process trap_priority;
1281
 
1282 2 zero_gravi
 
1283 6 zero_gravi
-- ****************************************************************************************************************************
1284
-- Control and Status Registers (CSRs)
1285
-- ****************************************************************************************************************************
1286 2 zero_gravi
 
1287 6 zero_gravi
  -- CSR CPU Access -------------------------------------------------------------------------
1288
  -- -------------------------------------------------------------------------------------------
1289
  csr_cpu_acc: process(clk_i)
1290
  begin
1291
    if rising_edge(clk_i) then
1292
      csr.we <= csr.we_nxt;
1293
      csr.re <= csr.re_nxt;
1294
    end if;
1295
  end process csr_cpu_acc;
1296
 
1297
 
1298 2 zero_gravi
  -- Control and Status Registers Write Access ----------------------------------------------
1299
  -- -------------------------------------------------------------------------------------------
1300
  csr_write_access: process(rstn_i, clk_i)
1301
  begin
1302
    if (rstn_i = '0') then
1303 6 zero_gravi
      csr.mstatus_mie  <= '0';
1304
      csr.mstatus_mpie <= '0';
1305
      csr.mie_msie     <= '0';
1306
      csr.mie_meie     <= '0';
1307
      csr.mie_mtie     <= '0';
1308
      csr.mtvec        <= (others => '0');
1309
      csr.mtval        <= (others => '0');
1310
      csr.mepc         <= (others => '0');
1311
      csr.mip_msip     <= '0';
1312
      csr.misa_c_en    <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_C); -- C CPU extension
1313
      csr.misa_m_en    <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_M); -- M CPU extension
1314 2 zero_gravi
    elsif rising_edge(clk_i) then
1315
      if (CPU_EXTENSION_RISCV_Zicsr = true) then
1316 6 zero_gravi
        csr.mip_msip <= '0';
1317 4 zero_gravi
 
1318 2 zero_gravi
        -- register that can be modified by user --
1319 6 zero_gravi
        if (csr.we = '1') then -- manual update
1320 4 zero_gravi
 
1321
          -- machine trap setup --
1322 6 zero_gravi
          if (execute_engine.i_reg(31 downto 24) = x"30") then
1323
            if (execute_engine.i_reg(23 downto 20) = x"0") then -- R/W: mstatus - machine status register
1324
              csr.mstatus_mie  <= csr_wdata_i(03);
1325
              csr.mstatus_mpie <= csr_wdata_i(07);
1326 4 zero_gravi
            end if;
1327 6 zero_gravi
            if (execute_engine.i_reg(23 downto 20) = x"1") then -- R/W: misa - machine instruction set extensions
1328 9 zero_gravi
              csr.misa_c_en <= csr_wdata_i(02); -- C extension enable/disable during runtime
1329
              csr.misa_m_en <= csr_wdata_i(12); -- M extension enable/disable during runtime
1330 4 zero_gravi
            end if;
1331 6 zero_gravi
            if (execute_engine.i_reg(23 downto 20) = x"4") then -- R/W: mie - machine interrupt-enable register
1332
              csr.mie_msie <= csr_wdata_i(03); -- SW IRQ enable
1333
              csr.mie_mtie <= csr_wdata_i(07); -- TIMER IRQ enable
1334
              csr.mie_meie <= csr_wdata_i(11); -- EXT IRQ enable
1335 4 zero_gravi
            end if;
1336 6 zero_gravi
            if (execute_engine.i_reg(23 downto 20) = x"5") then -- R/W: mtvec - machine trap-handler base address (for ALL exceptions)
1337
              csr.mtvec <= csr_wdata_i;
1338
            end if;
1339 4 zero_gravi
          end if;
1340
 
1341
          -- machine trap handling --
1342 6 zero_gravi
          if (execute_engine.i_reg(31 downto 24) = x"34") then
1343
            if (execute_engine.i_reg(23 downto 20) = x"0") then -- R/W: mscratch - machine scratch register
1344
              csr.mscratch <= csr_wdata_i;
1345 4 zero_gravi
            end if;
1346 6 zero_gravi
            if (execute_engine.i_reg(23 downto 20) = x"1") then-- R/W: mepc - machine exception program counter
1347
              csr.mepc <= csr_wdata_i;
1348 4 zero_gravi
            end if;
1349 6 zero_gravi
            if (execute_engine.i_reg(23 downto 20) = x"4") then -- R/W: mip - machine interrupt pending
1350
              csr.mip_msip <= csr_wdata_i(03); -- manual SW IRQ trigger
1351 4 zero_gravi
            end if;
1352
          end if;
1353 2 zero_gravi
 
1354
        else -- automatic update by hardware
1355 9 zero_gravi
 
1356 2 zero_gravi
          -- machine exception PC & exception value register --
1357 6 zero_gravi
          if (trap_ctrl.env_start_ack = '1') then -- trap handler started?
1358
            if (csr.mcause(data_width_c-1) = '1') then -- for INTERRUPTS only (mtval not defined for interrupts)
1359
              csr.mepc  <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- this is the CURRENT pc = interrupted instruction
1360
              csr.mtval <= (others => '0');
1361 9 zero_gravi
            else -- for EXCEPTIONS (according to their priority)
1362 6 zero_gravi
              csr.mepc <= execute_engine.last_pc(data_width_c-1 downto 1) & '0'; -- this is the LAST pc = last executed instruction
1363
              if ((trap_ctrl.exc_src(exception_iaccess_c) or trap_ctrl.exc_src(exception_ialign_c)) = '1') then -- instruction access error OR misaligned instruction
1364 9 zero_gravi
                csr.mtval <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- address of faulting instruction
1365 6 zero_gravi
              elsif (trap_ctrl.exc_src(exception_iillegal_c) = '1') then -- illegal instruction
1366 9 zero_gravi
                csr.mtval <= execute_engine.i_reg; -- the faulting instruction itself
1367
              else -- load/store msialignments/access errors
1368
                csr.mtval <= mar_i; -- faulting data access address
1369 2 zero_gravi
              end if;
1370
            end if;
1371
          end if;
1372
 
1373
          -- context switch in mstatus --
1374 6 zero_gravi
          if (trap_ctrl.env_start_ack = '1') then -- actually entering trap
1375
            csr.mstatus_mie <= '0';
1376 9 zero_gravi
            if (csr.mstatus_mpie = '0') then -- prevent loosing the prev MIE state in nested traps
1377 6 zero_gravi
              csr.mstatus_mpie <= csr.mstatus_mie;
1378 2 zero_gravi
            end if;
1379 6 zero_gravi
          elsif (trap_ctrl.env_end = '1') then -- return from exception
1380
            csr.mstatus_mie <= csr.mstatus_mpie;
1381 2 zero_gravi
          end if;
1382 9 zero_gravi
 
1383 2 zero_gravi
        end if;
1384
      end if;
1385
    end if;
1386
  end process csr_write_access;
1387
 
1388
 
1389
  -- Control and Status Registers Read Access -----------------------------------------------
1390
  -- -------------------------------------------------------------------------------------------
1391
  csr_read_access: process(clk_i)
1392
  begin
1393
    if rising_edge(clk_i) then
1394
      csr_rdata_o <= (others => '0'); -- default
1395
      if (CPU_EXTENSION_RISCV_Zicsr = true) then -- implement CSR access at all?
1396 6 zero_gravi
        if (csr.re = '1') then
1397
          case execute_engine.i_reg(31 downto 20) is
1398 2 zero_gravi
            -- machine trap setup --
1399
            when x"300" => -- R/W: mstatus - machine status register
1400 6 zero_gravi
              csr_rdata_o(03) <= csr.mstatus_mie; -- MIE
1401
              csr_rdata_o(07) <= csr.mstatus_mpie; -- MPIE
1402 2 zero_gravi
              csr_rdata_o(11) <= '1'; -- MPP low
1403
              csr_rdata_o(12) <= '1'; -- MPP high
1404 6 zero_gravi
            when x"301" => -- R/W: misa - ISA and extensions
1405
              csr_rdata_o(02) <= csr.misa_c_en;                               -- C CPU extension
1406 2 zero_gravi
              csr_rdata_o(04) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E);     -- E CPU extension
1407
              csr_rdata_o(08) <= not bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- I CPU extension (if not E)
1408 6 zero_gravi
              csr_rdata_o(12) <= csr.misa_m_en;                               -- M CPU extension
1409 2 zero_gravi
              csr_rdata_o(23) <= '1';                                         -- X CPU extension: non-standard extensions
1410 8 zero_gravi
              csr_rdata_o(25) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicsr) and bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zifencei); -- Z CPU extension
1411 2 zero_gravi
              csr_rdata_o(30) <= '1'; -- 32-bit architecture (MXL lo)
1412
              csr_rdata_o(31) <= '0'; -- 32-bit architecture (MXL hi)
1413
            when x"304" => -- R/W: mie - machine interrupt-enable register
1414 6 zero_gravi
              csr_rdata_o(03) <= csr.mie_msie; -- software IRQ enable
1415
              csr_rdata_o(07) <= csr.mie_mtie; -- timer IRQ enable
1416
              csr_rdata_o(11) <= csr.mie_meie; -- external IRQ enable
1417 2 zero_gravi
            when x"305" => -- R/W: mtvec - machine trap-handler base address (for ALL exceptions)
1418 6 zero_gravi
              csr_rdata_o <= csr.mtvec;
1419 2 zero_gravi
            -- machine trap handling --
1420
            when x"340" => -- R/W: mscratch - machine scratch register
1421 6 zero_gravi
              csr_rdata_o <= csr.mscratch;
1422 2 zero_gravi
            when x"341" => -- R/W: mepc - machine exception program counter
1423 6 zero_gravi
              csr_rdata_o <= csr.mepc;
1424 2 zero_gravi
            when x"342" => -- R/-: mcause - machine trap cause
1425 6 zero_gravi
              csr_rdata_o <= csr.mcause;
1426 2 zero_gravi
            when x"343" => -- R/-: mtval - machine bad address or instruction
1427 6 zero_gravi
              csr_rdata_o <= csr.mtval;
1428 2 zero_gravi
            when x"344" => -- R/W: mip - machine interrupt pending
1429 6 zero_gravi
              csr_rdata_o(03) <= trap_ctrl.irq_buf(interrupt_msw_irq_c);
1430
              csr_rdata_o(07) <= trap_ctrl.irq_buf(interrupt_mtime_irq_c);
1431
              csr_rdata_o(11) <= trap_ctrl.irq_buf(interrupt_mext_irq_c);
1432 2 zero_gravi
            -- counter and timers --
1433
            when x"c00" | x"c01" | x"b00" => -- R/-: cycle/time/mcycle: Cycle counter LOW / Timer LOW
1434 6 zero_gravi
              csr_rdata_o <= csr.cycle(31 downto 0);
1435 2 zero_gravi
            when x"c02" | x"b02" => -- R/-: instret/minstret: Instructions-retired counter LOW
1436 6 zero_gravi
              csr_rdata_o <= csr.instret(31 downto 0);
1437 2 zero_gravi
            when x"c80" | x"c81" | x"b80" => -- R/-: cycleh/timeh/mcycleh: Cycle counter HIGH / Timer HIGH
1438 6 zero_gravi
              csr_rdata_o <= csr.cycleh;
1439 2 zero_gravi
            when x"c82" | x"b82" => -- R/-: instreth/minstreth: Instructions-retired counter HIGH
1440 6 zero_gravi
              csr_rdata_o <= csr.instreth;
1441 2 zero_gravi
            -- machine information registers --
1442
            when x"f13" => -- R/-: mimpid - implementation ID / version
1443
              csr_rdata_o <= hw_version_c;
1444
            when x"f14" => -- R/-: mhartid - hardware thread ID
1445
              csr_rdata_o <= HART_ID;
1446
            -- CUSTOM read-only machine CSRs --
1447
            when x"fc0" => -- R/-: mfeatures - implemented processor devices/features
1448
              csr_rdata_o(00) <= bool_to_ulogic_f(BOOTLOADER_USE);   -- implement processor-internal bootloader?
1449
              csr_rdata_o(01) <= bool_to_ulogic_f(MEM_EXT_USE);      -- implement external memory bus interface?
1450 6 zero_gravi
              csr_rdata_o(02) <= bool_to_ulogic_f(MEM_INT_IMEM_USE); -- implement processor-internal instruction memory?
1451
              csr_rdata_o(03) <= bool_to_ulogic_f(MEM_INT_IMEM_ROM); -- implement processor-internal instruction memory as ROM?
1452
              csr_rdata_o(04) <= bool_to_ulogic_f(MEM_INT_DMEM_USE); -- implement processor-internal data memory?
1453
              csr_rdata_o(05) <= bool_to_ulogic_f(CSR_COUNTERS_USE); -- implement RISC-V (performance) counter?
1454 2 zero_gravi
              --
1455 3 zero_gravi
              csr_rdata_o(16) <= bool_to_ulogic_f(IO_GPIO_USE);      -- implement general purpose input/output port unit (GPIO)?
1456
              csr_rdata_o(17) <= bool_to_ulogic_f(IO_MTIME_USE);     -- implement machine system timer (MTIME)?
1457
              csr_rdata_o(18) <= bool_to_ulogic_f(IO_UART_USE);      -- implement universal asynchronous receiver/transmitter (UART)?
1458
              csr_rdata_o(19) <= bool_to_ulogic_f(IO_SPI_USE);       -- implement serial peripheral interface (SPI)?
1459
              csr_rdata_o(20) <= bool_to_ulogic_f(IO_TWI_USE);       -- implement two-wire interface (TWI)?
1460
              csr_rdata_o(21) <= bool_to_ulogic_f(IO_PWM_USE);       -- implement pulse-width modulation unit (PWM)?
1461
              csr_rdata_o(22) <= bool_to_ulogic_f(IO_WDT_USE);       -- implement watch dog timer (WDT)?
1462
              csr_rdata_o(23) <= bool_to_ulogic_f(IO_CLIC_USE);      -- implement core local interrupt controller (CLIC)?
1463
              csr_rdata_o(24) <= bool_to_ulogic_f(IO_TRNG_USE);      -- implement true random number generator (TRNG)?
1464
              csr_rdata_o(25) <= bool_to_ulogic_f(IO_DEVNULL_USE);   -- implement dummy device (DEVNULL)?
1465 2 zero_gravi
            when x"fc1" => -- R/-: mclock - processor clock speed
1466
              csr_rdata_o <= std_ulogic_vector(to_unsigned(CLOCK_FREQUENCY, 32));
1467
            when x"fc4" => -- R/-: mispacebase - Base address of instruction memory space
1468
              csr_rdata_o <= MEM_ISPACE_BASE;
1469
            when x"fc5" => -- R/-: mdspacebase - Base address of data memory space
1470
              csr_rdata_o <= MEM_DSPACE_BASE;
1471
            when x"fc6" => -- R/-: mispacesize - Total size of instruction memory space in byte
1472
              csr_rdata_o <= std_ulogic_vector(to_unsigned(MEM_ISPACE_SIZE, 32));
1473
            when x"fc7" => -- R/-: mdspacesize - Total size of data memory space in byte
1474
              csr_rdata_o <= std_ulogic_vector(to_unsigned(MEM_DSPACE_SIZE, 32));
1475
            -- undefined/unavailable --
1476
            when others =>
1477
              csr_rdata_o <= (others => '0'); -- not implemented (yet)
1478
          end case;
1479
        end if;
1480
      end if;
1481
    end if;
1482
  end process csr_read_access;
1483
 
1484
 
1485 6 zero_gravi
  -- RISC-V Counter CSRs --------------------------------------------------------------------
1486 2 zero_gravi
  -- -------------------------------------------------------------------------------------------
1487
  csr_counters: process(rstn_i, clk_i)
1488
  begin
1489 6 zero_gravi
    if (rstn_i = '0') then
1490
      csr.cycle    <= (others => '0');
1491
      csr.instret  <= (others => '0');
1492
      csr.cycleh   <= (others => '0');
1493
      csr.instreth <= (others => '0');
1494
      cycle_msb    <= '0';
1495
      instret_msb  <= '0';
1496
    elsif rising_edge(clk_i) then
1497
      if (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true) then
1498 2 zero_gravi
        -- low word overflow buffers --
1499 6 zero_gravi
        cycle_msb   <= csr.cycle(csr.cycle'left);
1500
        instret_msb <= csr.instret(csr.instret'left);
1501 2 zero_gravi
        -- low word counters --
1502 6 zero_gravi
        csr.cycle <= std_ulogic_vector(unsigned(csr.cycle) + 1);
1503
        if (execute_engine.state_prev /= EXECUTE) and (execute_engine.state = EXECUTE) then
1504
          csr.instret <= std_ulogic_vector(unsigned(csr.instret) + 1);
1505 2 zero_gravi
        end if;
1506
        -- high word counters --
1507 6 zero_gravi
        if ((cycle_msb xor csr.cycle(csr.cycle'left)) = '1') then
1508
          csr.cycleh <= std_ulogic_vector(unsigned(csr.cycleh) + 1);
1509 2 zero_gravi
        end if;
1510 6 zero_gravi
        if ((instret_msb xor csr.instret(csr.instret'left)) = '1') then
1511
          csr.instreth <= std_ulogic_vector(unsigned(csr.instreth) + 1);
1512 2 zero_gravi
        end if;
1513
      end if;
1514
    end if;
1515
  end process csr_counters;
1516
 
1517
 
1518
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.