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

Subversion Repositories neorv32

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

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 11 zero_gravi
    -- system time input from MTIME --
108
    time_i        : in  std_ulogic_vector(63 downto 0); -- current system time
109 2 zero_gravi
    -- bus access exceptions --
110
    mar_i         : in  std_ulogic_vector(data_width_c-1 downto 0);  -- memory address register
111
    ma_instr_i    : in  std_ulogic; -- misaligned instruction address
112
    ma_load_i     : in  std_ulogic; -- misaligned load data address
113
    ma_store_i    : in  std_ulogic; -- misaligned store data address
114
    be_instr_i    : in  std_ulogic; -- bus error on instruction access
115
    be_load_i     : in  std_ulogic; -- bus error on load data access
116
    be_store_i    : in  std_ulogic; -- bus error on store data access
117 6 zero_gravi
    bus_busy_i    : in  std_ulogic  -- bus unit is busy
118 2 zero_gravi
  );
119
end neorv32_cpu_control;
120
 
121
architecture neorv32_cpu_control_rtl of neorv32_cpu_control is
122
 
123 6 zero_gravi
  -- instruction fetch enginge --
124
  type fetch_engine_state_t is (IFETCH_RESET, IFETCH_0, IFETCH_1, IFETCH_2, IFETCH_3);
125
  type fetch_engine_t is record
126
    state           : fetch_engine_state_t;
127
    state_nxt       : fetch_engine_state_t;
128
    i_buf           : std_ulogic_vector(33 downto 0);
129
    i_buf_nxt       : std_ulogic_vector(33 downto 0);
130
    i_buf2          : std_ulogic_vector(33 downto 0);
131
    i_buf2_nxt      : std_ulogic_vector(33 downto 0);
132
    ci_reg          : std_ulogic_vector(17 downto 0);
133
    ci_reg_nxt      : std_ulogic_vector(17 downto 0);
134
    i_buf_state     : std_ulogic_vector(01 downto 0);
135
    i_buf_state_nxt : std_ulogic_vector(01 downto 0);
136
    pc_real         : std_ulogic_vector(data_width_c-1 downto 0);
137
    pc_real_add     : std_ulogic_vector(data_width_c-1 downto 0);
138
    pc_fetch        : std_ulogic_vector(data_width_c-1 downto 0);
139
    pc_fetch_add    : std_ulogic_vector(data_width_c-1 downto 0);
140
    ci_return       : std_ulogic;
141
    ci_return_nxt   : std_ulogic;
142
    reset           : std_ulogic;
143
    bus_err_ack     : std_ulogic;
144 11 zero_gravi
    bus_reset       : std_ulogic;
145 6 zero_gravi
  end record;
146
  signal fetch_engine : fetch_engine_t;
147 2 zero_gravi
 
148
  -- pre-decoder --
149
  signal ci_instr32 : std_ulogic_vector(31 downto 0);
150
  signal ci_illegal : std_ulogic;
151
 
152 6 zero_gravi
  -- instrucion prefetch buffer (IPB) --
153
  type ipb_t is record
154
    wdata  : std_ulogic_vector(34 downto 0);
155
    rdata  : std_ulogic_vector(34 downto 0);
156
    waddr  : std_ulogic_vector(31 downto 0);
157
    raddr  : std_ulogic_vector(31 downto 0);
158
    status : std_ulogic;
159
    free   : std_ulogic;
160
    avail  : std_ulogic;
161
    we     : std_ulogic;
162
    re     : std_ulogic;
163
    clear  : std_ulogic;
164
  end record;
165
  signal ipb : ipb_t;
166 2 zero_gravi
 
167 6 zero_gravi
  -- instruction execution engine --
168 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);
169 6 zero_gravi
  type execute_engine_t is record
170
    state        : execute_engine_state_t;
171
    state_nxt    : execute_engine_state_t;
172
    state_prev   : execute_engine_state_t;
173
    i_reg        : std_ulogic_vector(31 downto 0);
174
    i_reg_nxt    : std_ulogic_vector(31 downto 0);
175
    is_ci        : std_ulogic; -- current instruction is de-compressed instruction
176
    is_ci_nxt    : std_ulogic;
177
    is_jump      : std_ulogic; -- current instruction is jump instruction
178
    is_jump_nxt  : std_ulogic;
179
    branch_taken : std_ulogic; -- branch condition fullfilled
180
    pc           : std_ulogic_vector(data_width_c-1 downto 0); -- actual PC, corresponding to current executed instruction
181
    pc_nxt       : std_ulogic_vector(data_width_c-1 downto 0);
182
    next_pc      : std_ulogic_vector(data_width_c-1 downto 0); -- next PC, corresponding to next instruction to be executed
183
    last_pc      : std_ulogic_vector(data_width_c-1 downto 0); -- PC of last executed instruction
184 11 zero_gravi
    sleep        : std_ulogic; -- CPU in sleep mode
185
    sleep_nxt    : std_ulogic; -- CPU in sleep mode
186 6 zero_gravi
  end record;
187
  signal execute_engine : execute_engine_t;
188 2 zero_gravi
 
189 6 zero_gravi
  -- trap controller --
190
  type trap_ctrl_t is record
191
    exc_buf       : std_ulogic_vector(exception_width_c-1 downto 0);
192
    exc_fire      : std_ulogic; -- set if there is a valid source in the exception buffer
193
    irq_buf       : std_ulogic_vector(interrupt_width_c-1 downto 0);
194
    irq_fire      : std_ulogic; -- set if there is a valid source in the interrupt buffer
195
    exc_ack       : std_ulogic; -- acknowledge all exceptions
196
    irq_ack       : std_ulogic_vector(interrupt_width_c-1 downto 0); -- acknowledge specific interrupt
197
    irq_ack_nxt   : std_ulogic_vector(interrupt_width_c-1 downto 0);
198
    cause         : std_ulogic_vector(data_width_c-1 downto 0); -- trap ID (for "mcause")
199
    cause_nxt     : std_ulogic_vector(data_width_c-1 downto 0);
200
    exc_src       : std_ulogic_vector(exception_width_c-1 downto 0);
201
    --
202
    env_start     : std_ulogic; -- start trap handler env
203
    env_start_ack : std_ulogic; -- start of trap handler acknowledged
204
    env_end       : std_ulogic; -- end trap handler env
205
    --
206
    instr_be      : std_ulogic; -- instruction fetch bus error
207
    instr_ma      : std_ulogic; -- instruction fetch misaligned address
208
    instr_il      : std_ulogic; -- illegal instruction
209
    env_call      : std_ulogic;
210
    break_point   : std_ulogic;
211
  end record;
212
  signal trap_ctrl : trap_ctrl_t;
213
 
214
  -- CPU control signals --
215
  signal ctrl_nxt, ctrl : std_ulogic_vector(ctrl_width_c-1 downto 0);
216 2 zero_gravi
 
217 6 zero_gravi
  -- fast bus access --
218
  signal bus_fast_ir : std_ulogic;
219 2 zero_gravi
 
220 6 zero_gravi
  -- RISC-V control and status registers (CSRs) --
221
  type csr_t is record
222
    we           : std_ulogic; -- write enable
223
    we_nxt       : std_ulogic;
224
    re           : std_ulogic; -- read enable
225
    re_nxt       : std_ulogic;
226
    mstatus_mie  : std_ulogic; -- mstatus.MIE: global IRQ enable (R/W)
227
    mstatus_mpie : std_ulogic; -- mstatus.MPIE: previous global IRQ enable (R/-)
228
    mip_msip     : std_ulogic; -- mip.MSIP: machine software interrupt pending (R/W)
229
    mie_msie     : std_ulogic; -- mie.MSIE: machine software interrupt enable (R/W)
230
    mie_meie     : std_ulogic; -- mie.MEIE: machine external interrupt enable (R/W)
231
    mie_mtie     : std_ulogic; -- mie.MEIE: machine timer interrupt enable (R/W)
232
    mepc         : std_ulogic_vector(data_width_c-1 downto 0); -- mepc: machine exception pc (R/W)
233 11 zero_gravi
    mcause       : std_ulogic_vector(data_width_c-1 downto 0); -- mcause: machine trap cause (R/W)
234 6 zero_gravi
    mtvec        : std_ulogic_vector(data_width_c-1 downto 0); -- mtvec: machine trap-handler base address (R/W)
235 11 zero_gravi
    mtval        : std_ulogic_vector(data_width_c-1 downto 0); -- mtval: machine bad address or isntruction (R/W)
236 6 zero_gravi
    mscratch     : std_ulogic_vector(data_width_c-1 downto 0); -- mscratch: scratch register (R/W)
237 11 zero_gravi
    mcycle       : std_ulogic_vector(32 downto 0); -- mcycle (R/W), plus carry bit
238
    minstret     : std_ulogic_vector(32 downto 0); -- minstret (R/W), plus carry bit
239
    mcycleh      : std_ulogic_vector(31 downto 0); -- mcycleh (R/W)
240
    minstreth    : std_ulogic_vector(31 downto 0); -- minstreth (R/W)
241 6 zero_gravi
  end record;
242
  signal csr : csr_t;
243 2 zero_gravi
 
244 11 zero_gravi
  signal mcycle_msb   : std_ulogic;
245
  signal minstret_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 11 zero_gravi
    fetch_engine.bus_reset       <= '0';
334 6 zero_gravi
 
335
    -- instruction prefetch buffer interface --
336
    ipb.we    <= '0';
337
    ipb.clear <= '0';
338
    ipb.wdata <= fetch_engine.i_buf2(33 downto 32) & '0' & fetch_engine.i_buf2(31 downto 0);
339
    ipb.waddr <= fetch_engine.pc_real(data_width_c-1 downto 1) & '0';
340
 
341
    -- state machine --
342
    case fetch_engine.state is
343
 
344 11 zero_gravi
      when IFETCH_RESET => -- reset engine, prefetch buffer, get appilcation PC
345 6 zero_gravi
      -- ------------------------------------------------------------
346
        fetch_engine.i_buf_state_nxt <= (others => '0');
347
        fetch_engine.ci_return_nxt   <= '0';
348 11 zero_gravi
        fetch_engine.bus_reset       <= '1'; -- reset bus unit
349 6 zero_gravi
        ipb.clear                    <= '1'; -- clear instruction prefetch buffer
350
        fetch_engine.state_nxt       <= IFETCH_0;
351
 
352
      when IFETCH_0 => -- output current PC to bus system, request 32-bit word
353
      -- ------------------------------------------------------------
354
        if (bus_busy_i = '0') and (execute_engine.state /= LOAD) and (execute_engine.state /= STORE) and
355
                                  (execute_engine.state /= LOADSTORE_0) and (execute_engine.state /= LOADSTORE_1) then -- wait if execute engine is using bus unit
356
          bus_fast_ir            <= '1'; -- fast instruction fetch request (output PC to bus.address)
357
          fetch_engine.state_nxt <= IFETCH_1;
358
        end if;
359
 
360
      when IFETCH_1 => -- store data from memory to buffer(s)
361
      -- ------------------------------------------------------------
362
        fetch_engine.i_buf_nxt  <= be_instr_i & ma_instr_i & instr_i(31 downto 0); -- store data word and exception info
363
        if (bus_wait_i = '0') then -- wait for bus response
364
          fetch_engine.i_buf2_nxt <= fetch_engine.i_buf;
365
          fetch_engine.i_buf_state_nxt(1) <= fetch_engine.i_buf_state(0);
366
          fetch_engine.state_nxt          <= IFETCH_2;
367
        end if;
368 11 zero_gravi
 
369 6 zero_gravi
        fetch_engine.i_buf_state_nxt(0) <= '1';
370
        if (be_instr_i = '1') or (ma_instr_i = '1') then -- any fetch exception?
371
          fetch_engine.bus_err_ack <= '1'; -- ack bus errors, the execute engine has to take care of them
372
        end if;
373
 
374
      when IFETCH_2 => -- construct instruction and issue
375
      -- ------------------------------------------------------------
376
        if (fetch_engine.i_buf_state(1) = '1') then
377 11 zero_gravi
          if (fetch_engine.pc_fetch(1) = '0') or (CPU_EXTENSION_RISCV_C = false) then -- 32-bit aligned
378 6 zero_gravi
            fetch_engine.ci_reg_nxt <= fetch_engine.i_buf2(33 downto 32) & fetch_engine.i_buf2(15 downto 00);
379
            ipb.wdata <= fetch_engine.i_buf2(33 downto 32) & '0' & fetch_engine.i_buf2(31 downto 0);
380
 
381 11 zero_gravi
            if (fetch_engine.i_buf2(01 downto 00) = "11") or (CPU_EXTENSION_RISCV_C = false) then -- uncompressed
382 6 zero_gravi
              if (ipb.free = '1') then -- free entry in buffer?
383
                ipb.we                    <= '1';
384
                fetch_engine.pc_real_add  <= std_ulogic_vector(to_unsigned(4, data_width_c));
385
                fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(4, data_width_c));
386
                fetch_engine.state_nxt    <= IFETCH_0;
387
              end if;
388
 
389
            else -- compressed
390
              fetch_engine.pc_fetch_add  <= std_ulogic_vector(to_unsigned(2, data_width_c));
391
              fetch_engine.ci_return_nxt <= '1'; -- come back here after issueing
392
              fetch_engine.state_nxt     <= IFETCH_3;
393
            end if;
394
 
395
          else -- 16-bit aligned
396
            fetch_engine.ci_reg_nxt <= fetch_engine.i_buf2(33 downto 32) & fetch_engine.i_buf2(31 downto 16);
397
            ipb.wdata <= fetch_engine.i_buf(33 downto 32) & '0' & fetch_engine.i_buf(15 downto 00) & fetch_engine.i_buf2(31 downto 16);
398
 
399
            if (fetch_engine.i_buf2(17 downto 16) = "11") then -- uncompressed
400
              if (ipb.free = '1') then -- free entry in buffer?
401
                ipb.we                    <= '1';
402
                fetch_engine.pc_real_add  <= std_ulogic_vector(to_unsigned(4, data_width_c));
403
                fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(4, data_width_c));
404
                fetch_engine.state_nxt    <= IFETCH_0;
405
              end if;
406
 
407
            else -- compressed
408
              fetch_engine.pc_fetch_add  <= std_ulogic_vector(to_unsigned(2, data_width_c));
409
              fetch_engine.ci_return_nxt <= '0'; -- start next fetch after issueing
410
              fetch_engine.state_nxt     <= IFETCH_3;
411
            end if;
412
          end if;
413
        else
414
         fetch_engine.pc_fetch_add <= std_ulogic_vector(to_unsigned(4, data_width_c));
415
         fetch_engine.state_nxt    <= IFETCH_0;
416
        end if;
417
 
418
      when IFETCH_3 => -- additional cycle for issueing decompressed instructions
419
      -- ------------------------------------------------------------
420
        if (ipb.free = '1') then -- free entry in buffer?
421
          ipb.we    <= '1';
422
          ipb.wdata <= fetch_engine.ci_reg(17 downto 16) & '1' & ci_instr32;
423
          fetch_engine.pc_real_add <= std_ulogic_vector(to_unsigned(2, data_width_c));
424
          if (fetch_engine.ci_return = '0') then
425
            fetch_engine.state_nxt <= IFETCH_0;
426
          else
427
            fetch_engine.state_nxt <= IFETCH_2;
428
          end if;
429
        end if;
430
 
431
      when others => -- undefined
432
      -- ------------------------------------------------------------
433
        fetch_engine.state_nxt <= IFETCH_RESET;
434
 
435
    end case;
436
  end process fetch_engine_fsm_comb;
437
 
438
 
439
-- ****************************************************************************************************************************
440
-- Instruction Prefetch Buffer
441
-- ****************************************************************************************************************************
442
 
443
 
444
  -- Instruction Prefetch Buffer Stage ------------------------------------------------------
445
  -- -------------------------------------------------------------------------------------------
446
  instr_prefetch_buffer: process(rstn_i, clk_i)
447
  begin
448
    if (rstn_i = '0') then
449
      ipb.status <= '0';
450
      ipb.rdata  <= (others => '0');
451
      ipb.raddr  <= (others => '0');
452
    elsif rising_edge(clk_i) then
453
      if (ipb.clear = '1') then
454
        ipb.status <= '0';
455
      elsif (ipb.we = '1') then
456
        ipb.status <= '1';
457
      elsif (ipb.re = '1') then
458
        ipb.status <= '0';
459
      end if;
460
      if (ipb.we = '1') then
461
        ipb.rdata <= ipb.wdata;
462
        ipb.raddr <= ipb.waddr;
463
      end if;
464
    end if;
465
  end process instr_prefetch_buffer;
466
 
467
  -- status --
468
  ipb.free  <= not ipb.status;
469
  ipb.avail <= ipb.status;
470
 
471
 
472
-- ****************************************************************************************************************************
473
-- Instruction Execution
474
-- ****************************************************************************************************************************
475
 
476
 
477 2 zero_gravi
  -- Immediate Generator --------------------------------------------------------------------
478
  -- -------------------------------------------------------------------------------------------
479
  imm_gen: process(clk_i)
480
  begin
481
    if rising_edge(clk_i) then
482 6 zero_gravi
      case execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) is
483 2 zero_gravi
        when opcode_store_c => -- S-immediate
484 6 zero_gravi
          imm_o(31 downto 11) <= (others => execute_engine.i_reg(31)); -- sign extension
485
          imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
486
          imm_o(04 downto 01) <= execute_engine.i_reg(11 downto 08);
487
          imm_o(00)           <= execute_engine.i_reg(07);
488 2 zero_gravi
        when opcode_branch_c => -- B-immediate
489 6 zero_gravi
          imm_o(31 downto 12) <= (others => execute_engine.i_reg(31)); -- sign extension
490
          imm_o(11)           <= execute_engine.i_reg(07);
491
          imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
492
          imm_o(04 downto 01) <= execute_engine.i_reg(11 downto 08);
493
          imm_o(00)           <= '0';
494 2 zero_gravi
        when opcode_lui_c | opcode_auipc_c => -- U-immediate
495 6 zero_gravi
          imm_o(31 downto 20) <= execute_engine.i_reg(31 downto 20);
496
          imm_o(19 downto 12) <= execute_engine.i_reg(19 downto 12);
497
          imm_o(11 downto 00) <= (others => '0');
498 2 zero_gravi
        when opcode_jal_c => -- J-immediate
499 6 zero_gravi
          imm_o(31 downto 20) <= (others => execute_engine.i_reg(31)); -- sign extension
500
          imm_o(19 downto 12) <= execute_engine.i_reg(19 downto 12);
501
          imm_o(11)           <= execute_engine.i_reg(20);
502
          imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
503
          imm_o(04 downto 01) <= execute_engine.i_reg(24 downto 21);
504
          imm_o(00)           <= '0';
505 2 zero_gravi
        when opcode_syscsr_c => -- CSR-immediate
506 6 zero_gravi
          imm_o(31 downto 05) <= (others => '0');
507
          imm_o(04 downto 00) <= execute_engine.i_reg(19 downto 15);
508 2 zero_gravi
        when others => -- I-immediate
509 6 zero_gravi
          imm_o(31 downto 11) <= (others => execute_engine.i_reg(31)); -- sign extension
510
          imm_o(10 downto 05) <= execute_engine.i_reg(30 downto 25);
511
          imm_o(04 downto 01) <= execute_engine.i_reg(24 downto 21);
512
          imm_o(00)           <= execute_engine.i_reg(20);
513 2 zero_gravi
      end case;
514
    end if;
515
  end process imm_gen;
516
 
517
 
518
  -- Branch Condition Check -----------------------------------------------------------------
519
  -- -------------------------------------------------------------------------------------------
520 6 zero_gravi
  branch_check: process(execute_engine.i_reg, cmp_i)
521 2 zero_gravi
  begin
522 6 zero_gravi
    case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is
523 2 zero_gravi
      when funct3_beq_c => -- branch if equal
524 6 zero_gravi
        execute_engine.branch_taken <= cmp_i(alu_cmp_equal_c);
525 2 zero_gravi
      when funct3_bne_c => -- branch if not equal
526 6 zero_gravi
        execute_engine.branch_taken <= not cmp_i(alu_cmp_equal_c);
527 2 zero_gravi
      when funct3_blt_c | funct3_bltu_c => -- branch if less (signed/unsigned)
528 6 zero_gravi
        execute_engine.branch_taken <= cmp_i(alu_cmp_less_c);
529 2 zero_gravi
      when funct3_bge_c | funct3_bgeu_c => -- branch if greater or equal (signed/unsigned)
530 6 zero_gravi
        execute_engine.branch_taken <= not cmp_i(alu_cmp_less_c);
531 2 zero_gravi
      when others => -- undefined
532 6 zero_gravi
        execute_engine.branch_taken <= '0';
533 2 zero_gravi
    end case;
534
  end process branch_check;
535
 
536
 
537 6 zero_gravi
  -- Execute Engine FSM Sync ----------------------------------------------------------------
538 2 zero_gravi
  -- -------------------------------------------------------------------------------------------
539 6 zero_gravi
  -- for registers that require a specific reset state --
540
  execute_engine_fsm_sync_rst: process(rstn_i, clk_i)
541 2 zero_gravi
  begin
542
    if (rstn_i = '0') then
543 6 zero_gravi
      if (BOOTLOADER_USE = true) then -- boot from bootloader ROM
544
        execute_engine.pc      <= boot_base_c(data_width_c-1 downto 1) & '0';
545
        execute_engine.last_pc <= boot_base_c(data_width_c-1 downto 1) & '0';
546
      else -- boot from IMEM
547
        execute_engine.pc      <= MEM_ISPACE_BASE(data_width_c-1 downto 1) & '0';
548
        execute_engine.last_pc <= MEM_ISPACE_BASE(data_width_c-1 downto 1) & '0';
549
      end if;
550 7 zero_gravi
      execute_engine.state      <= SYS_WAIT;
551
      execute_engine.state_prev <= SYS_WAIT;
552 11 zero_gravi
      --
553
      execute_engine.sleep <= '0';
554 2 zero_gravi
    elsif rising_edge(clk_i) then
555 6 zero_gravi
      execute_engine.pc <= execute_engine.pc_nxt(data_width_c-1 downto 1) & '0';
556
      if (execute_engine.state = EXECUTE) then
557
        execute_engine.last_pc <= execute_engine.pc(data_width_c-1 downto 1) & '0';
558
      end if;
559
      execute_engine.state      <= execute_engine.state_nxt;
560
      execute_engine.state_prev <= execute_engine.state;
561 11 zero_gravi
      --
562
      execute_engine.sleep <= execute_engine.sleep_nxt;
563 2 zero_gravi
    end if;
564 6 zero_gravi
  end process execute_engine_fsm_sync_rst;
565 2 zero_gravi
 
566 6 zero_gravi
 
567
  -- for registers that DO NOT require a specific reset state --
568
  execute_engine_fsm_sync: process(clk_i)
569 2 zero_gravi
  begin
570
    if rising_edge(clk_i) then
571 6 zero_gravi
      execute_engine.i_reg   <= execute_engine.i_reg_nxt;
572
      execute_engine.is_ci   <= execute_engine.is_ci_nxt;
573
      execute_engine.is_jump <= execute_engine.is_jump_nxt;
574
      -- control signals --
575
      ctrl <= ctrl_nxt;
576 2 zero_gravi
    end if;
577 6 zero_gravi
  end process execute_engine_fsm_sync;
578 2 zero_gravi
 
579 6 zero_gravi
 
580
  -- PC output --
581
  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
582
                            std_ulogic_vector(unsigned(execute_engine.pc(data_width_c-1 downto 1) & '0') + 4);
583
  fetch_pc_o <= fetch_engine.pc_fetch(data_width_c-1 downto 1) & '0';
584
  curr_pc_o  <= execute_engine.pc(data_width_c-1 downto 1) & '0';
585
  next_pc_o  <= execute_engine.next_pc(data_width_c-1 downto 1) & '0';
586
 
587
 
588
  -- CPU Control Bus Output -----------------------------------------------------------------
589
  -- -------------------------------------------------------------------------------------------
590 11 zero_gravi
  ctrl_output: process(ctrl, execute_engine, fetch_engine, trap_ctrl, csr, bus_fast_ir)
591 2 zero_gravi
  begin
592
    ctrl_o <= ctrl;
593
    -- direct output of register addresses --
594 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);
595
    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);
596
    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);
597
    -- bus access requests --
598
    ctrl_o(ctrl_bus_if_c) <= ctrl(ctrl_bus_if_c) or bus_fast_ir;
599 11 zero_gravi
    -- bus control --
600
    ctrl_o(ctrl_bus_exc_ack_c) <= trap_ctrl.env_start_ack or fetch_engine.bus_err_ack;
601
    ctrl_o(ctrl_bus_reset_c)   <= fetch_engine.bus_reset;
602 6 zero_gravi
  end process ctrl_output;
603 2 zero_gravi
 
604
 
605 6 zero_gravi
  -- Execute Engine FSM Comb ----------------------------------------------------------------
606
  -- -------------------------------------------------------------------------------------------
607
  execute_engine_fsm_comb: process(execute_engine, fetch_engine, ipb, trap_ctrl, csr, ctrl,
608
                                   alu_add_i, alu_wait_i, bus_wait_i, ma_load_i, be_load_i, ma_store_i, be_store_i)
609 2 zero_gravi
    variable alu_immediate_v : std_ulogic;
610
    variable alu_operation_v : std_ulogic_vector(2 downto 0);
611 6 zero_gravi
    variable rd_is_r0_v      : std_ulogic;
612 2 zero_gravi
    variable rs1_is_r0_v     : std_ulogic;
613
  begin
614
    -- arbiter defaults --
615 6 zero_gravi
    execute_engine.state_nxt   <= execute_engine.state;
616
    execute_engine.i_reg_nxt   <= execute_engine.i_reg;
617
    execute_engine.is_jump_nxt <= '0';
618
    execute_engine.is_ci_nxt   <= execute_engine.is_ci;
619
    execute_engine.pc_nxt      <= execute_engine.pc(data_width_c-1 downto 1) & '0';
620 11 zero_gravi
    execute_engine.sleep_nxt   <= execute_engine.sleep;
621 2 zero_gravi
 
622 6 zero_gravi
    -- instruction dispatch --
623
    fetch_engine.reset         <= '0';
624
    ipb.re                     <= '0';
625 2 zero_gravi
 
626 6 zero_gravi
    -- trap environment control --
627
    trap_ctrl.env_start_ack    <= '0';
628
    trap_ctrl.env_end          <= '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 11 zero_gravi
             if (execute_engine.sleep = '1') then
712
               execute_engine.state_nxt <= TRAP;
713
             else
714
               execute_engine.state_nxt <= EXECUTE;
715
             end if;
716 6 zero_gravi
           end if;
717
         end if;
718 2 zero_gravi
 
719 11 zero_gravi
      when TRAP => -- Start trap environment (also used as cpu sleep state)
720 2 zero_gravi
      -- ------------------------------------------------------------
721 11 zero_gravi
        fetch_engine.reset <= '1';
722 6 zero_gravi
        if (trap_ctrl.env_start = '1') then
723
          trap_ctrl.env_start_ack  <= '1';
724 11 zero_gravi
          execute_engine.sleep_nxt <= '0'; -- waky waky
725 6 zero_gravi
          execute_engine.pc_nxt    <= csr.mtvec(data_width_c-1 downto 1) & '0';
726 7 zero_gravi
          execute_engine.state_nxt <= SYS_WAIT;
727 2 zero_gravi
        end if;
728
 
729 6 zero_gravi
      when EXECUTE => -- Decode and execute instruction
730 2 zero_gravi
      -- ------------------------------------------------------------
731 6 zero_gravi
        case execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) is
732 2 zero_gravi
 
733
          when opcode_alu_c | opcode_alui_c => -- ALU operation
734
          -- ------------------------------------------------------------
735
            ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- use RS1 as ALU.OPA
736
            ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= alu_immediate_v; -- use IMM as ALU.OPB for immediate operations
737
            ctrl_nxt(ctrl_alu_opc_mux_c)     <= not alu_immediate_v;
738
            ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_operation_v; -- actual ALU operation
739
            ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "00"; -- RF input = ALU result
740 11 zero_gravi
            -- multi cycle alu operation? --
741
            if (alu_operation_v = alu_cmd_shift_c) or -- shift operation
742
               ((CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_alu_c) and
743
                (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001")) then -- MULDIV?
744 6 zero_gravi
              execute_engine.state_nxt <= ALU_WAIT;
745 2 zero_gravi
            else
746
              ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
747 6 zero_gravi
              execute_engine.state_nxt <= DISPATCH;
748 2 zero_gravi
            end if;
749 11 zero_gravi
            -- cp access? --
750
            if (CPU_EXTENSION_RISCV_M = true) and (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_alu_c) and
751
               (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV?
752
              ctrl_nxt(ctrl_cp_use_c) <= '1'; -- use CP
753
              ctrl_nxt(ctrl_cp_id_msb_c downto ctrl_cp_id_lsb_c) <= cp_sel_muldiv_c; -- muldiv CP
754
            end if;
755 2 zero_gravi
 
756 11 zero_gravi
 
757 2 zero_gravi
          when opcode_lui_c | opcode_auipc_c => -- load upper immediate (add to PC)
758
          -- ------------------------------------------------------------
759
            ctrl_nxt(ctrl_rf_clear_rs1_c) <= '1'; -- force RS1 = r0
760 6 zero_gravi
            if (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_auipc_c) then -- AUIPC
761 2 zero_gravi
              ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '1'; -- use PC as ALU.OPA
762
            else -- LUI
763
              ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- use RS1 as ALU.OPA
764
            end if;
765 6 zero_gravi
            ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- use IMM as ALU.OPB
766 2 zero_gravi
            ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- actual ALU operation
767
            ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "00"; -- RF input = ALU result
768
            ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
769 6 zero_gravi
            execute_engine.state_nxt <= DISPATCH;
770 2 zero_gravi
 
771
          when opcode_load_c | opcode_store_c => -- load/store
772
          -- ------------------------------------------------------------
773
            ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- use RS1 as ALU.OPA
774
            ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- use IMM as ALU.OPB
775
            ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- actual ALU operation
776 6 zero_gravi
            ctrl_nxt(ctrl_bus_mar_we_c) <= '1'; -- write to MAR
777
            ctrl_nxt(ctrl_bus_mdo_we_c) <= '1'; -- write to MDO (only relevant for stores)
778
            if (fetch_engine.state /= IFETCH_0) then
779
              if (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_load_c) then -- LOAD
780
                execute_engine.state_nxt <= LOAD;
781
              else -- STORE
782
                execute_engine.state_nxt <= STORE;
783
              end if;
784 2 zero_gravi
            end if;
785
 
786
          when opcode_branch_c => -- branch instruction
787
          -- ------------------------------------------------------------
788
            ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '1'; -- use PC as ALU.OPA
789
            ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- use IMM as ALU.OPB
790 6 zero_gravi
            ctrl_nxt(ctrl_alu_opc_mux_c)     <= '1'; -- use RS2 as ALU.OPC
791
            execute_engine.state_nxt         <= BRANCH;
792 2 zero_gravi
 
793
          when opcode_jal_c | opcode_jalr_c => -- jump and link (with register)
794
          -- ------------------------------------------------------------
795
            -- compute target address --
796 6 zero_gravi
            if (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_jal_c) then -- JAL
797 2 zero_gravi
              ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '1'; -- use PC as ALU.OPA
798
            else -- JALR
799
              ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- use RS1 as ALU.OPA
800
            end if;
801
            ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- use IMM as ALU.OPB
802
            -- save return address --
803
            ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "10"; -- RF input = current PC
804
            ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
805 6 zero_gravi
            --
806
            execute_engine.is_jump_nxt <= '1'; -- this is a jump operation
807
            execute_engine.state_nxt   <= BRANCH;
808 2 zero_gravi
 
809 8 zero_gravi
          when opcode_fence_c => -- fence operations
810
          -- ------------------------------------------------------------
811
            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
812
              fetch_engine.reset       <= '1';
813
              execute_engine.pc_nxt    <= execute_engine.next_pc;
814
              execute_engine.state_nxt <= SYS_WAIT;
815
            else
816
              execute_engine.state_nxt <= DISPATCH;
817
            end if;
818
 
819 2 zero_gravi
          when opcode_syscsr_c => -- system/csr access
820
          -- ------------------------------------------------------------
821 6 zero_gravi
            if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or
822
               (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) then
823
              csr.re_nxt <= not rd_is_r0_v; -- only read CSR if not writing to zero_reg
824
            else
825
              csr.re_nxt <= '1'; -- always read CSR
826
            end if;
827
            --
828
            if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_env_c) then -- system
829
              case execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) is
830 11 zero_gravi
                when funct12_ecall_c => -- ECALL
831 6 zero_gravi
                  trap_ctrl.env_call <= '1';
832 11 zero_gravi
                when funct12_ebreak_c => -- EBREAK
833 6 zero_gravi
                  trap_ctrl.break_point <= '1';
834 11 zero_gravi
                when funct12_mret_c => -- MRET
835
                  trap_ctrl.env_end     <= '1';
836
                  execute_engine.pc_nxt <= csr.mepc(data_width_c-1 downto 1) & '0';
837
                  fetch_engine.reset    <= '1';
838
                when funct12_wfi_c => -- WFI = "CPU sleep"
839
                  execute_engine.sleep_nxt <= '1'; -- good night
840 6 zero_gravi
                when others => -- undefined
841
                  NULL;
842 2 zero_gravi
              end case;
843 11 zero_gravi
              execute_engine.state_nxt <= SYS_WAIT;
844 2 zero_gravi
            elsif (CPU_EXTENSION_RISCV_Zicsr = true) then -- CSR access
845 6 zero_gravi
              execute_engine.state_nxt <= CSR_ACCESS;
846 2 zero_gravi
            else
847 6 zero_gravi
              execute_engine.state_nxt <= DISPATCH;
848 2 zero_gravi
            end if;
849
 
850
          when others => -- undefined
851
          -- ------------------------------------------------------------
852 6 zero_gravi
            execute_engine.state_nxt <= DISPATCH;
853 2 zero_gravi
 
854
        end case;
855
 
856
      when CSR_ACCESS => -- write CSR data to RF, write ALU.res to CSR
857
      -- ------------------------------------------------------------
858
        ctrl_nxt(ctrl_alu_opa_mux_msb_c) <= '0'; -- default
859
        ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- default
860
        ctrl_nxt(ctrl_alu_opb_mux_msb_c) <= '0'; -- default
861
        ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '0'; -- default
862 6 zero_gravi
        case execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) is
863 7 zero_gravi
          -- register operations --
864 6 zero_gravi
          when funct3_csrrw_c => -- CSRRW
865 2 zero_gravi
            ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- OPA = rs1
866
            ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '0'; -- OPB = rs2
867
            ctrl_nxt(ctrl_rf_clear_rs2_c)    <= '1'; -- rs2 = 0
868
            ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- actual ALU operation = ADD
869 6 zero_gravi
            csr.we_nxt <= '1'; -- always write CSR
870
          when funct3_csrrs_c => -- CSRRS
871 2 zero_gravi
            ctrl_nxt(ctrl_alu_opa_mux_msb_c) <= '1'; -- OPA = csr
872
            ctrl_nxt(ctrl_alu_opb_mux_msb_c) <= '1'; -- OPB = crs1
873
            ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_or_c; -- actual ALU operation = OR
874 6 zero_gravi
            csr.we_nxt <= not rs1_is_r0_v; -- write CSR if rs1 is not zero_reg
875
          when funct3_csrrc_c => -- CSRRC
876 2 zero_gravi
            ctrl_nxt(ctrl_alu_opa_mux_msb_c) <= '1'; -- OPA = csr
877
            ctrl_nxt(ctrl_alu_opb_mux_msb_c) <= '1'; -- OPB = rs1
878
            ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_bitc_c; -- actual ALU operation = bit clear
879 6 zero_gravi
            csr.we_nxt <= not rs1_is_r0_v; -- write CSR if rs1 is not zero_reg
880 7 zero_gravi
          -- immediate operations --
881 6 zero_gravi
          when funct3_csrrwi_c => -- CSRRWI
882 2 zero_gravi
            ctrl_nxt(ctrl_alu_opa_mux_lsb_c) <= '0'; -- OPA = rs1
883
            ctrl_nxt(ctrl_rf_clear_rs1_c)    <= '1'; -- rs1 = 0
884
            ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- OPB = immediate
885
            ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_add_c; -- actual ALU operation = ADD
886 6 zero_gravi
            csr.we_nxt <= '1'; -- always write CSR
887
          when funct3_csrrsi_c => -- CSRRSI
888 2 zero_gravi
            ctrl_nxt(ctrl_alu_opa_mux_msb_c) <= '1'; -- OPA = csr
889
            ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- OPB = immediate
890
            ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_or_c; -- actual ALU operation = OR
891 6 zero_gravi
            csr.we_nxt <= not rs1_is_r0_v; -- write CSR if UIMM5 is not zero (bits from rs1 filed)
892
          when funct3_csrrci_c => -- CSRRCI
893 2 zero_gravi
            ctrl_nxt(ctrl_alu_opa_mux_msb_c) <= '1'; -- OPA = csr
894
            ctrl_nxt(ctrl_alu_opb_mux_lsb_c) <= '1'; -- OPB = immediate
895
            ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_cmd_bitc_c; -- actual ALU operation = bit clear
896 6 zero_gravi
            csr.we_nxt <= not rs1_is_r0_v; -- write CSR if UIMM5 is not zero (bits from rs1 filed)
897 2 zero_gravi
          when others => -- undefined
898
            NULL;
899
        end case;
900
        -- RF write back --
901
        ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "11"; -- RF input = CSR output register
902
        ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
903 11 zero_gravi
        execute_engine.state_nxt  <= DISPATCH; -- FIXME should be SYS_WAIT? have another cycle to let side-effects kick in
904 2 zero_gravi
 
905 6 zero_gravi
      when ALU_WAIT => -- wait for multi-cycle ALU operation to finish
906 2 zero_gravi
      -- ------------------------------------------------------------
907 6 zero_gravi
        ctrl_nxt(ctrl_alu_cmd2_c downto ctrl_alu_cmd0_c) <= alu_operation_v; -- actual ALU operation
908
        ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "00"; -- RF input = ALU result
909
        ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back (write back all the time)
910
        if (alu_wait_i = '0') then
911
          execute_engine.state_nxt <= DISPATCH;
912 2 zero_gravi
        end if;
913
 
914 6 zero_gravi
      when BRANCH => -- update PC for taken branches and jumps
915
      -- ------------------------------------------------------------
916
        if (execute_engine.is_jump = '1') or (execute_engine.branch_taken = '1') then
917 11 zero_gravi
          execute_engine.pc_nxt    <= alu_add_i(data_width_c-1 downto 1) & '0'; -- branch/jump destination
918
          fetch_engine.reset       <= '1';
919
          execute_engine.state_nxt <= SYS_WAIT;
920
        else
921
          execute_engine.state_nxt <= DISPATCH;
922 6 zero_gravi
        end if;
923
 
924
      when LOAD => -- trigger memory read request
925
      -- ------------------------------------------------------------
926 11 zero_gravi
        ctrl_nxt(ctrl_bus_rd_c)  <= '1'; -- fast read request
927 6 zero_gravi
        execute_engine.state_nxt <= LOADSTORE_0;
928
 
929
      when STORE => -- trigger memory write request
930
      -- ------------------------------------------------------------
931 11 zero_gravi
        ctrl_nxt(ctrl_bus_wr_c)  <= '1'; -- fast write request
932 6 zero_gravi
        execute_engine.state_nxt <= LOADSTORE_0;
933
 
934
      when LOADSTORE_0 => -- memory latency
935
      -- ------------------------------------------------------------
936
        ctrl_nxt(ctrl_bus_mdi_we_c) <= '1'; -- write input data to MDI (only relevant for LOAD)
937
        execute_engine.state_nxt <= LOADSTORE_1;
938
 
939
      when LOADSTORE_1 => -- wait for bus transaction to finish
940
      -- ------------------------------------------------------------
941
        ctrl_nxt(ctrl_bus_mdi_we_c) <= '1'; -- keep writing input data to MDI (only relevant for LOAD)
942
        ctrl_nxt(ctrl_rf_in_mux_msb_c downto ctrl_rf_in_mux_lsb_c) <= "01"; -- RF input = memory input (only relevant for LOAD)
943
        if (ma_load_i = '1') or (be_load_i = '1') or (ma_store_i = '1') or (be_store_i = '1') then -- abort if exception
944 7 zero_gravi
          execute_engine.state_nxt <= SYS_WAIT;
945 6 zero_gravi
        elsif (bus_wait_i = '0') then -- wait here for bus to finish transaction
946
          if (execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) = opcode_load_c) then -- LOAD?
947
            ctrl_nxt(ctrl_rf_wb_en_c) <= '1'; -- valid RF write-back
948
          end if;
949
          execute_engine.state_nxt <= DISPATCH;
950
        end if;
951
 
952 2 zero_gravi
      when others => -- undefined
953
      -- ------------------------------------------------------------
954 7 zero_gravi
        execute_engine.state_nxt <= SYS_WAIT;
955 2 zero_gravi
 
956
    end case;
957 6 zero_gravi
  end process execute_engine_fsm_comb;
958 2 zero_gravi
 
959
 
960
  -- Illegal Instruction Check --------------------------------------------------------------
961
  -- -------------------------------------------------------------------------------------------
962 6 zero_gravi
  illegal_instruction_check: process(execute_engine, csr, ctrl_nxt, ci_illegal)
963 2 zero_gravi
  begin
964 11 zero_gravi
    -- illegal instructions are checked in the EXECUTE stage
965
    -- the execute engine will only commit valid instructions
966 6 zero_gravi
    if (execute_engine.state = EXECUTE) then
967 2 zero_gravi
      -- defaults --
968
      illegal_instruction <= '0';
969
      illegal_register    <= '0';
970
      illegal_compressed  <= '0';
971
 
972
      -- check if using reg >= 16 for E-CPUs --
973 6 zero_gravi
--if (CPU_EXTENSION_RISCV_E = true) then
974
--  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);
975
--else
976
--  illegal_register <= '0';
977
--end if;
978 2 zero_gravi
 
979
      -- check instructions --
980 6 zero_gravi
      case execute_engine.i_reg(instr_opcode_msb_c downto instr_opcode_lsb_c) is
981 2 zero_gravi
 
982
        -- OPCODE check sufficient: LUI, UIPC, JAL --
983
        when opcode_lui_c | opcode_auipc_c | opcode_jal_c =>
984
          illegal_instruction <= '0';
985
 
986
        when opcode_alui_c => -- check ALUI funct7
987 6 zero_gravi
          if ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sll_c) and
988
              (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000")) or -- shift logical left
989
             ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c) and
990
              ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000") and
991
               (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0100000"))) then -- shift right
992 2 zero_gravi
            illegal_instruction <= '1';
993
          else
994
            illegal_instruction <= '0';
995
          end if;
996
 
997
        when opcode_load_c => -- check LOAD funct3
998 6 zero_gravi
          if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lb_c) or
999
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lh_c) or
1000
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lw_c) or
1001
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lbu_c) or
1002
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_lhu_c) then
1003 2 zero_gravi
            illegal_instruction <= '0';
1004
          else
1005
            illegal_instruction <= '1';
1006
          end if;
1007
 
1008
        when opcode_store_c => -- check STORE funct3
1009 6 zero_gravi
          if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sb_c) or
1010
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sh_c) or
1011
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sw_c) then
1012 2 zero_gravi
            illegal_instruction <= '0';
1013
          else
1014
            illegal_instruction <= '1';
1015
          end if;
1016
 
1017
        when opcode_branch_c => -- check BRANCH funct3
1018 6 zero_gravi
          if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_beq_c) or
1019
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bne_c) or
1020
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_blt_c) or
1021
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bge_c) or
1022
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bltu_c) or
1023
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_bgeu_c) then
1024 2 zero_gravi
            illegal_instruction <= '0';
1025
          else
1026
            illegal_instruction <= '1';
1027
          end if;
1028
 
1029
        when opcode_jalr_c => -- check JALR funct3
1030 6 zero_gravi
          if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = "000") then
1031 2 zero_gravi
            illegal_instruction <= '0';
1032
          else
1033
            illegal_instruction <= '1';
1034
          end if;
1035
 
1036
        when opcode_alu_c => -- check ALU funct3 & funct7
1037 6 zero_gravi
          if (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) = "0000001") then -- MULDIV
1038 11 zero_gravi
            if (CPU_EXTENSION_RISCV_M = false) then -- not implemented
1039 2 zero_gravi
              illegal_instruction <= '1';
1040
            end if;
1041 6 zero_gravi
          elsif ((execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_subadd_c) or
1042
                 (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_sr_c)) and -- ADD/SUB or SRA/SRL check
1043
                ((execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0000000") and
1044
                 (execute_engine.i_reg(instr_funct7_msb_c downto instr_funct7_lsb_c) /= "0100000")) then -- ADD/SUB or SRA/SRL select
1045 2 zero_gravi
            illegal_instruction <= '1';
1046
          else
1047
            illegal_instruction <= '0';
1048
          end if;
1049
 
1050 8 zero_gravi
        when opcode_fence_c => -- fence instructions --
1051
          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
1052
            illegal_instruction <= '0';
1053
          elsif (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_fence_c) then -- FENCE
1054
            illegal_instruction <= '0';
1055
          else
1056
            illegal_instruction <= '1';
1057
          end if;
1058
 
1059 2 zero_gravi
        when opcode_syscsr_c => -- check system instructions --
1060
          -- CSR access --
1061 6 zero_gravi
          if (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrw_c) or
1062
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrs_c) or
1063
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrc_c) or
1064
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrwi_c) or
1065
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrsi_c) or
1066
             (execute_engine.i_reg(instr_funct3_msb_c downto instr_funct3_lsb_c) = funct3_csrrci_c) then
1067 2 zero_gravi
            -- valid CSR? --
1068 6 zero_gravi
            if (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"300") or -- mstatus
1069
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"301") or -- misa
1070
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"304") or -- mie
1071
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"305") or -- mtvev
1072
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"340") or -- mscratch
1073
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"341") or -- mepc
1074
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"342") or -- mcause
1075
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"343") or -- mtval
1076
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"344") or -- mip
1077 2 zero_gravi
               --
1078 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
1079 11 zero_gravi
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c01") and (IO_MTIME_USE = true)) or -- time
1080 6 zero_gravi
               ((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
1081
               ((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
1082 11 zero_gravi
               ((execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"c81") and (IO_MTIME_USE = true)) or -- timeh
1083 6 zero_gravi
               ((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
1084 2 zero_gravi
               --
1085 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
1086
               ((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
1087
               ((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
1088
               ((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
1089 2 zero_gravi
               --
1090 6 zero_gravi
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"f13") or -- mimpid
1091
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"f14") or -- mhartid
1092 2 zero_gravi
               --
1093 6 zero_gravi
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc0") or -- mfeatures
1094
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc1") or -- mclock
1095
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc4") or -- mispacebase
1096
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc5") or -- mispacesize
1097
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc6") or -- mdspacebase
1098
               (execute_engine.i_reg(instr_funct12_msb_c downto instr_funct12_lsb_c) = x"fc7") then -- mdspacesize
1099 2 zero_gravi
              illegal_instruction <= '0';
1100
            else
1101
              illegal_instruction <= '1';
1102
            end if;
1103
 
1104
          -- ecall, ebreak, mret, wfi --
1105 6 zero_gravi
          elsif (execute_engine.i_reg(instr_rd_msb_c  downto instr_rd_lsb_c)  = "00000") and
1106
                (execute_engine.i_reg(instr_rs1_msb_c downto instr_rs1_lsb_c) = "00000") then
1107 11 zero_gravi
            if (execute_engine.i_reg(instr_funct12_msb_c  downto instr_funct12_lsb_c) = funct12_ecall_c) or -- ECALL
1108
               (execute_engine.i_reg(instr_funct12_msb_c  downto instr_funct12_lsb_c) = funct12_ebreak_c) or -- EBREAK 
1109
               (execute_engine.i_reg(instr_funct12_msb_c  downto instr_funct12_lsb_c) = funct12_mret_c) or -- MRET
1110
               (execute_engine.i_reg(instr_funct12_msb_c  downto instr_funct12_lsb_c) = funct12_wfi_c) then -- WFI
1111 2 zero_gravi
              illegal_instruction <= '0';
1112
            else
1113
              illegal_instruction <= '1';
1114
            end if;
1115
          else
1116
            illegal_instruction <= '1';
1117
          end if;
1118
 
1119
        when others => -- compressed instruction or undefined instruction
1120 6 zero_gravi
          if (execute_engine.i_reg(1 downto 0) = "11") then -- undefined/unimplemented opcode
1121 2 zero_gravi
            illegal_instruction <= '1';
1122 6 zero_gravi
          else -- compressed instruction: illegal or disabled / not implemented
1123 11 zero_gravi
            illegal_compressed <= ci_illegal;
1124 2 zero_gravi
          end if;
1125
 
1126
      end case;
1127
    else
1128
      illegal_instruction <= '0';
1129
      illegal_register    <= '0';
1130
      illegal_compressed  <= '0';
1131
    end if;
1132
  end process illegal_instruction_check;
1133
 
1134
  -- any illegal condition? --
1135 6 zero_gravi
  trap_ctrl.instr_il <= illegal_instruction or illegal_register or illegal_compressed;
1136 2 zero_gravi
 
1137
 
1138 6 zero_gravi
-- ****************************************************************************************************************************
1139
-- Exception and Interrupt Control
1140
-- ****************************************************************************************************************************
1141 2 zero_gravi
 
1142
 
1143 6 zero_gravi
  -- Trap Controller ------------------------------------------------------------------------
1144 2 zero_gravi
  -- -------------------------------------------------------------------------------------------
1145 6 zero_gravi
  trap_controller: process(rstn_i, clk_i)
1146 2 zero_gravi
  begin
1147
    if (rstn_i = '0') then
1148 6 zero_gravi
      trap_ctrl.exc_buf   <= (others => '0');
1149
      trap_ctrl.irq_buf   <= (others => '0');
1150
      trap_ctrl.exc_ack   <= '0';
1151
      trap_ctrl.irq_ack   <= (others => '0');
1152
      trap_ctrl.cause     <= (others => '0');
1153
      trap_ctrl.exc_src   <= (others => '0');
1154
      trap_ctrl.env_start <= '0';
1155 2 zero_gravi
    elsif rising_edge(clk_i) then
1156
      if (CPU_EXTENSION_RISCV_Zicsr = true) then
1157
        -- exception buffer: misaligned load/store/instruction address
1158 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);
1159
        trap_ctrl.exc_buf(exception_salign_c)    <= (trap_ctrl.exc_buf(exception_salign_c)    or ma_store_i)            and (not trap_ctrl.exc_ack);
1160
        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);
1161 2 zero_gravi
        -- exception buffer: load/store/instruction bus access error
1162 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);
1163
        trap_ctrl.exc_buf(exception_saccess_c)   <= (trap_ctrl.exc_buf(exception_saccess_c)   or be_store_i)            and (not trap_ctrl.exc_ack);
1164
        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);
1165 2 zero_gravi
        -- exception buffer: illegal instruction / env call / break point
1166 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);
1167
        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);
1168
        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);
1169 2 zero_gravi
        -- interrupt buffer: machine software/external/timer interrupt
1170 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));
1171
        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));
1172
        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));
1173 2 zero_gravi
 
1174 6 zero_gravi
        -- trap control --
1175
        if (trap_ctrl.env_start = '0') then -- no started trap handler
1176 11 zero_gravi
          if (trap_ctrl.exc_fire = '1') or ((trap_ctrl.irq_fire = '1') and -- exception/IRQ detected!
1177
             ((execute_engine.state = EXECUTE) or (execute_engine.state = TRAP))) then -- sample IRQs in EXECUTE or TRAP state only
1178 7 zero_gravi
            trap_ctrl.cause     <= trap_ctrl.cause_nxt;   -- capture source ID for program
1179
            trap_ctrl.exc_src   <= trap_ctrl.exc_buf;     -- capture exception source for hardware
1180
            trap_ctrl.exc_ack   <= '1';                   -- clear execption
1181
            trap_ctrl.irq_ack   <= trap_ctrl.irq_ack_nxt; -- capture and clear with interrupt ACK mask
1182
            trap_ctrl.env_start <= '1';                   -- now we want to start the trap handler
1183 2 zero_gravi
          end if;
1184 6 zero_gravi
        else -- trap waiting to get started
1185
          if (trap_ctrl.env_start_ack = '1') then -- start of trap handler acknowledged by execution engine
1186
            trap_ctrl.exc_ack   <= '0';
1187
            trap_ctrl.irq_ack   <= (others => '0');
1188
            trap_ctrl.env_start <= '0';
1189 2 zero_gravi
          end if;
1190
        end if;
1191
      end if;
1192
    end if;
1193 6 zero_gravi
  end process trap_controller;
1194 2 zero_gravi
 
1195
  -- any exception/interrupt? --
1196 6 zero_gravi
  trap_ctrl.exc_fire <= or_all_f(trap_ctrl.exc_buf); -- classic exceptions (faults/traps) cannot be masked
1197
  trap_ctrl.irq_fire <= or_all_f(trap_ctrl.irq_buf) and csr.mstatus_mie; -- classic interrupts can be enabled/disabled
1198 2 zero_gravi
 
1199
 
1200 6 zero_gravi
  -- Trap Priority Detector -----------------------------------------------------------------
1201
  -- -------------------------------------------------------------------------------------------
1202
  trap_priority: process(trap_ctrl)
1203 2 zero_gravi
  begin
1204
    -- defaults --
1205 6 zero_gravi
    trap_ctrl.cause_nxt   <= (others => '0');
1206
    trap_ctrl.irq_ack_nxt <= (others => '0');
1207 2 zero_gravi
 
1208 9 zero_gravi
    -- the following traps are caused by asynchronous exceptions (-> interrupts)
1209
    -- here we do need an acknowledge mask since several sources can trigger at once
1210
 
1211 2 zero_gravi
    -- interrupt: 1.11 machine external interrupt --
1212 6 zero_gravi
    if (trap_ctrl.irq_buf(interrupt_mext_irq_c) = '1') then
1213
      trap_ctrl.cause_nxt(data_width_c-1) <= '1';
1214
      trap_ctrl.cause_nxt(3 downto 0) <= "1011";
1215
      trap_ctrl.irq_ack_nxt(interrupt_mext_irq_c) <= '1';
1216 2 zero_gravi
 
1217
    -- interrupt: 1.7 machine timer interrupt --
1218 6 zero_gravi
    elsif (trap_ctrl.irq_buf(interrupt_mtime_irq_c) = '1') then
1219
      trap_ctrl.cause_nxt(data_width_c-1) <= '1';
1220
      trap_ctrl.cause_nxt(3 downto 0) <= "0111";
1221
      trap_ctrl.irq_ack_nxt(interrupt_mtime_irq_c) <= '1';
1222 2 zero_gravi
 
1223
    -- interrupt: 1.3 machine SW interrupt --
1224 6 zero_gravi
    elsif (trap_ctrl.irq_buf(interrupt_msw_irq_c) = '1') then
1225
      trap_ctrl.cause_nxt(data_width_c-1) <= '1';
1226
      trap_ctrl.cause_nxt(3 downto 0) <= "0011";
1227
      trap_ctrl.irq_ack_nxt(interrupt_msw_irq_c) <= '1';
1228 2 zero_gravi
 
1229
 
1230 4 zero_gravi
    -- the following traps are caused by synchronous exceptions
1231 9 zero_gravi
    -- here we do not need an acknowledge mask since only one exception (the one
1232
    -- with highest priority) can trigger at once
1233 4 zero_gravi
 
1234 2 zero_gravi
    -- trap/fault: 0.0 instruction address misaligned --
1235 6 zero_gravi
    elsif (trap_ctrl.exc_buf(exception_ialign_c) = '1') then
1236
      trap_ctrl.cause_nxt(data_width_c-1) <= '0';
1237
      trap_ctrl.cause_nxt(3 downto 0) <= "0000";
1238 2 zero_gravi
 
1239
    -- trap/fault: 0.1 instruction access fault --
1240 6 zero_gravi
    elsif (trap_ctrl.exc_buf(exception_iaccess_c) = '1') then
1241
      trap_ctrl.cause_nxt(data_width_c-1) <= '0';
1242
      trap_ctrl.cause_nxt(3 downto 0) <= "0001";
1243 2 zero_gravi
 
1244
    -- trap/fault: 0.2 illegal instruction --
1245 6 zero_gravi
    elsif (trap_ctrl.exc_buf(exception_iillegal_c) = '1') then
1246
      trap_ctrl.cause_nxt(data_width_c-1) <= '0';
1247
      trap_ctrl.cause_nxt(3 downto 0) <= "0010";
1248 2 zero_gravi
 
1249
 
1250
    -- trap/fault: 0.11 environment call from M-mode --
1251 6 zero_gravi
    elsif (trap_ctrl.exc_buf(exception_m_envcall_c) = '1') then
1252
      trap_ctrl.cause_nxt(data_width_c-1) <= '0';
1253
      trap_ctrl.cause_nxt(3 downto 0) <= "1011";
1254 2 zero_gravi
 
1255
    -- trap/fault: 0.3 breakpoint --
1256 6 zero_gravi
    elsif (trap_ctrl.exc_buf(exception_break_c) = '1') then
1257
      trap_ctrl.cause_nxt(data_width_c-1) <= '0';
1258
      trap_ctrl.cause_nxt(3 downto 0) <= "0011";
1259 2 zero_gravi
 
1260
 
1261
    -- trap/fault: 0.6 store address misaligned -
1262 6 zero_gravi
    elsif (trap_ctrl.exc_buf(exception_salign_c) = '1') then
1263
      trap_ctrl.cause_nxt(data_width_c-1) <= '0';
1264
      trap_ctrl.cause_nxt(3 downto 0) <= "0110";
1265 2 zero_gravi
 
1266
    -- trap/fault: 0.4 load address misaligned --
1267 6 zero_gravi
    elsif (trap_ctrl.exc_buf(exception_lalign_c) = '1') then
1268
      trap_ctrl.cause_nxt(data_width_c-1) <= '0';
1269
      trap_ctrl.cause_nxt(3 downto 0) <= "0100";
1270 2 zero_gravi
 
1271
    -- trap/fault: 0.7 store access fault --
1272 6 zero_gravi
    elsif (trap_ctrl.exc_buf(exception_saccess_c) = '1') then
1273
      trap_ctrl.cause_nxt(data_width_c-1) <= '0';
1274
      trap_ctrl.cause_nxt(3 downto 0) <= "0111";
1275 2 zero_gravi
 
1276
    -- trap/fault: 0.5 load access fault --
1277 6 zero_gravi
    elsif (trap_ctrl.exc_buf(exception_laccess_c) = '1') then
1278
      trap_ctrl.cause_nxt(data_width_c-1) <= '0';
1279
      trap_ctrl.cause_nxt(3 downto 0) <= "0101";
1280 2 zero_gravi
 
1281
    -- undefined / not implemented --
1282
    else
1283 6 zero_gravi
      trap_ctrl.cause_nxt   <= (others => '0');
1284
      trap_ctrl.irq_ack_nxt <= (others => '0');
1285 2 zero_gravi
    end if;
1286 6 zero_gravi
  end process trap_priority;
1287
 
1288 2 zero_gravi
 
1289 6 zero_gravi
-- ****************************************************************************************************************************
1290
-- Control and Status Registers (CSRs)
1291
-- ****************************************************************************************************************************
1292 2 zero_gravi
 
1293
  -- Control and Status Registers Write Access ----------------------------------------------
1294
  -- -------------------------------------------------------------------------------------------
1295
  csr_write_access: process(rstn_i, clk_i)
1296
  begin
1297
    if (rstn_i = '0') then
1298 11 zero_gravi
      csr.we <= '0';
1299
      csr.re <= '0';
1300
      --
1301 6 zero_gravi
      csr.mstatus_mie  <= '0';
1302
      csr.mstatus_mpie <= '0';
1303
      csr.mie_msie     <= '0';
1304
      csr.mie_meie     <= '0';
1305
      csr.mie_mtie     <= '0';
1306
      csr.mtvec        <= (others => '0');
1307
      csr.mtval        <= (others => '0');
1308
      csr.mepc         <= (others => '0');
1309
      csr.mip_msip     <= '0';
1310 2 zero_gravi
    elsif rising_edge(clk_i) then
1311
      if (CPU_EXTENSION_RISCV_Zicsr = true) then
1312 11 zero_gravi
        -- access --
1313
        csr.we <= csr.we_nxt;
1314
        csr.re <= csr.re_nxt;
1315
 
1316
        -- defaults --
1317 6 zero_gravi
        csr.mip_msip <= '0';
1318 4 zero_gravi
 
1319 11 zero_gravi
        -- registers that can be modified by user --
1320 6 zero_gravi
        if (csr.we = '1') then -- manual update
1321 4 zero_gravi
 
1322 11 zero_gravi
          -- Machine CSRs: Standard read/write
1323
          if (execute_engine.i_reg(31 downto 28) = x"3") then
1324
            -- machine trap setup --
1325
            if (execute_engine.i_reg(27 downto 24) = x"0") then
1326
              case execute_engine.i_reg(23 downto 20) is
1327
              when x"0" => -- R/W: mstatus - machine status register
1328
                csr.mstatus_mie  <= csr_wdata_i(03);
1329
                csr.mstatus_mpie <= csr_wdata_i(07);
1330
              when x"4" => -- R/W: mie - machine interrupt-enable register
1331
                csr.mie_msie <= csr_wdata_i(03); -- SW IRQ enable
1332
                csr.mie_mtie <= csr_wdata_i(07); -- TIMER IRQ enable
1333
                csr.mie_meie <= csr_wdata_i(11); -- EXT IRQ enable
1334
              when x"5" => -- R/W: mtvec - machine trap-handler base address (for ALL exceptions)
1335
                csr.mtvec <= csr_wdata_i;
1336
              when others =>
1337
                NULL;
1338
              end case;
1339 4 zero_gravi
            end if;
1340 11 zero_gravi
            -- machine trap handling --
1341
            if (execute_engine.i_reg(27 downto 24) = x"4") then
1342
              case execute_engine.i_reg(23 downto 20) is
1343
                when x"0" => -- R/W: mscratch - machine scratch register
1344
                  csr.mscratch <= csr_wdata_i;
1345
                when x"1" => -- R/W: mepc - machine exception program counter
1346
                  csr.mepc <= csr_wdata_i;
1347
                when x"2" => -- R/W: mcause - machine trap cause
1348
                  csr.mcause <= csr_wdata_i;
1349
                when x"3" => -- R/W: mtval - machine bad address or instruction
1350
                  csr.mtval <= csr_wdata_i;
1351
                when x"4" => -- R/W: mip - machine interrupt pending
1352
                  csr.mip_msip <= csr_wdata_i(03); -- manual SW IRQ trigger
1353
                when others =>
1354
                  NULL;
1355
              end case;
1356 4 zero_gravi
            end if;
1357
          end if;
1358
 
1359 11 zero_gravi
        -- automatic update by hardware --
1360
        else
1361 2 zero_gravi
 
1362
          -- machine exception PC & exception value register --
1363 6 zero_gravi
          if (trap_ctrl.env_start_ack = '1') then -- trap handler started?
1364 11 zero_gravi
            csr.mcause <= trap_ctrl.cause;
1365
            if (csr.mcause(data_width_c-1) = '1') then -- for INTERRUPTS only
1366 6 zero_gravi
              csr.mepc  <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- this is the CURRENT pc = interrupted instruction
1367 11 zero_gravi
              csr.mtval <= (others => '0'); -- mtval not defined for interrupts
1368 9 zero_gravi
            else -- for EXCEPTIONS (according to their priority)
1369 6 zero_gravi
              csr.mepc <= execute_engine.last_pc(data_width_c-1 downto 1) & '0'; -- this is the LAST pc = last executed instruction
1370
              if ((trap_ctrl.exc_src(exception_iaccess_c) or trap_ctrl.exc_src(exception_ialign_c)) = '1') then -- instruction access error OR misaligned instruction
1371 9 zero_gravi
                csr.mtval <= execute_engine.pc(data_width_c-1 downto 1) & '0'; -- address of faulting instruction
1372 6 zero_gravi
              elsif (trap_ctrl.exc_src(exception_iillegal_c) = '1') then -- illegal instruction
1373 9 zero_gravi
                csr.mtval <= execute_engine.i_reg; -- the faulting instruction itself
1374
              else -- load/store msialignments/access errors
1375
                csr.mtval <= mar_i; -- faulting data access address
1376 2 zero_gravi
              end if;
1377
            end if;
1378
          end if;
1379
 
1380
          -- context switch in mstatus --
1381 6 zero_gravi
          if (trap_ctrl.env_start_ack = '1') then -- actually entering trap
1382
            csr.mstatus_mie <= '0';
1383 9 zero_gravi
            if (csr.mstatus_mpie = '0') then -- prevent loosing the prev MIE state in nested traps
1384 6 zero_gravi
              csr.mstatus_mpie <= csr.mstatus_mie;
1385 2 zero_gravi
            end if;
1386 6 zero_gravi
          elsif (trap_ctrl.env_end = '1') then -- return from exception
1387
            csr.mstatus_mie <= csr.mstatus_mpie;
1388 2 zero_gravi
          end if;
1389 9 zero_gravi
 
1390 2 zero_gravi
        end if;
1391
      end if;
1392
    end if;
1393
  end process csr_write_access;
1394
 
1395
 
1396
  -- Control and Status Registers Read Access -----------------------------------------------
1397
  -- -------------------------------------------------------------------------------------------
1398
  csr_read_access: process(clk_i)
1399
  begin
1400
    if rising_edge(clk_i) then
1401
      csr_rdata_o <= (others => '0'); -- default
1402 11 zero_gravi
      if (CPU_EXTENSION_RISCV_Zicsr = true) and (csr.re = '1') then
1403
        case execute_engine.i_reg(31 downto 20) is
1404
 
1405
          -- machine trap setup --
1406
          when x"300" => -- R/W: mstatus - machine status register
1407
            csr_rdata_o(03) <= csr.mstatus_mie; -- MIE
1408
            csr_rdata_o(07) <= csr.mstatus_mpie; -- MPIE
1409
            csr_rdata_o(11) <= '1'; -- MPP low
1410
            csr_rdata_o(12) <= '1'; -- MPP high
1411
          when x"301" => -- R/-: misa - ISA and extensions
1412
            csr_rdata_o(02) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_C);     -- C CPU extension
1413
            csr_rdata_o(04) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_E);     -- E CPU extension
1414
            csr_rdata_o(08) <= not bool_to_ulogic_f(CPU_EXTENSION_RISCV_E); -- I CPU extension (if not E)
1415
            csr_rdata_o(12) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_M);     -- M CPU extension
1416
            csr_rdata_o(25) <= bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zicsr) and bool_to_ulogic_f(CPU_EXTENSION_RISCV_Zifencei); -- Z CPU extension
1417
            csr_rdata_o(30) <= '1'; -- 32-bit architecture (MXL lo)
1418
            csr_rdata_o(31) <= '0'; -- 32-bit architecture (MXL hi)
1419
          when x"304" => -- R/W: mie - machine interrupt-enable register
1420
            csr_rdata_o(03) <= csr.mie_msie; -- software IRQ enable
1421
            csr_rdata_o(07) <= csr.mie_mtie; -- timer IRQ enable
1422
            csr_rdata_o(11) <= csr.mie_meie; -- external IRQ enable
1423
          when x"305" => -- R/W: mtvec - machine trap-handler base address (for ALL exceptions)
1424
            csr_rdata_o <= csr.mtvec;
1425
 
1426
          -- machine trap handling --
1427
          when x"340" => -- R/W: mscratch - machine scratch register
1428
            csr_rdata_o <= csr.mscratch;
1429
          when x"341" => -- R/W: mepc - machine exception program counter
1430
            csr_rdata_o <= csr.mepc;
1431
          when x"342" => -- R/W: mcause - machine trap cause
1432
            csr_rdata_o <= csr.mcause;
1433
          when x"343" => -- R/W: mtval - machine bad address or instruction
1434
            csr_rdata_o <= csr.mtval;
1435
          when x"344" => -- R/W: mip - machine interrupt pending
1436
            csr_rdata_o(03) <= trap_ctrl.irq_buf(interrupt_msw_irq_c);
1437
            csr_rdata_o(07) <= trap_ctrl.irq_buf(interrupt_mtime_irq_c);
1438
            csr_rdata_o(11) <= trap_ctrl.irq_buf(interrupt_mext_irq_c);
1439
 
1440
          -- counter and timers --
1441
          when x"c00" | x"b00" => -- R/(W): cycle/mcycle: Cycle counter LOW
1442
            csr_rdata_o <= csr.mcycle(31 downto 0);
1443
          when x"c02" | x"b02" => -- R/(W): instret/minstret: Instructions-retired counter LOW
1444
            csr_rdata_o <= csr.minstret(31 downto 0);
1445
          when x"c80" | x"b80" => -- R/(W): cycleh/mcycleh: Cycle counter HIGH
1446
            csr_rdata_o <= csr.mcycleh;
1447
          when x"c82" | x"b82" => -- R/(W): instreth/minstreth: Instructions-retired counter HIGH
1448
            csr_rdata_o <= csr.minstreth;
1449
 
1450
          when x"c01" => -- R/-: time: System time LOW (from MTIME unit)
1451
            csr_rdata_o <= time_i(31 downto 0);
1452
          when x"c81" => -- R/-: timeh: System time HIGH (from MTIME unit)
1453
            csr_rdata_o <= time_i(63 downto 32);
1454
 
1455
          -- machine information registers --
1456
          when x"f13" => -- R/-: mimpid - implementation ID / version
1457
            csr_rdata_o <= hw_version_c;
1458
          when x"f14" => -- R/-: mhartid - hardware thread ID
1459
            csr_rdata_o <= HART_ID;
1460
 
1461
          -- CUSTOM read-only machine CSRs --
1462
          when x"fc0" => -- R/-: mfeatures - implemented processor devices/features
1463
            csr_rdata_o(00) <= bool_to_ulogic_f(BOOTLOADER_USE);   -- implement processor-internal bootloader?
1464
            csr_rdata_o(01) <= bool_to_ulogic_f(MEM_EXT_USE);      -- implement external memory bus interface?
1465
            csr_rdata_o(02) <= bool_to_ulogic_f(MEM_INT_IMEM_USE); -- implement processor-internal instruction memory?
1466
            csr_rdata_o(03) <= bool_to_ulogic_f(MEM_INT_IMEM_ROM); -- implement processor-internal instruction memory as ROM?
1467
            csr_rdata_o(04) <= bool_to_ulogic_f(MEM_INT_DMEM_USE); -- implement processor-internal data memory?
1468
            csr_rdata_o(05) <= bool_to_ulogic_f(CSR_COUNTERS_USE); -- implement RISC-V (performance) counter?
1469
            --
1470
            csr_rdata_o(16) <= bool_to_ulogic_f(IO_GPIO_USE);      -- implement general purpose input/output port unit (GPIO)?
1471
            csr_rdata_o(17) <= bool_to_ulogic_f(IO_MTIME_USE);     -- implement machine system timer (MTIME)?
1472
            csr_rdata_o(18) <= bool_to_ulogic_f(IO_UART_USE);      -- implement universal asynchronous receiver/transmitter (UART)?
1473
            csr_rdata_o(19) <= bool_to_ulogic_f(IO_SPI_USE);       -- implement serial peripheral interface (SPI)?
1474
            csr_rdata_o(20) <= bool_to_ulogic_f(IO_TWI_USE);       -- implement two-wire interface (TWI)?
1475
            csr_rdata_o(21) <= bool_to_ulogic_f(IO_PWM_USE);       -- implement pulse-width modulation unit (PWM)?
1476
            csr_rdata_o(22) <= bool_to_ulogic_f(IO_WDT_USE);       -- implement watch dog timer (WDT)?
1477
            csr_rdata_o(23) <= bool_to_ulogic_f(IO_CLIC_USE);      -- implement core local interrupt controller (CLIC)?
1478
            csr_rdata_o(24) <= bool_to_ulogic_f(IO_TRNG_USE);      -- implement true random number generator (TRNG)?
1479
            csr_rdata_o(25) <= bool_to_ulogic_f(IO_DEVNULL_USE);   -- implement dummy device (DEVNULL)?
1480
          when x"fc1" => -- R/-: mclock - processor clock speed
1481
            csr_rdata_o <= std_ulogic_vector(to_unsigned(CLOCK_FREQUENCY, 32));
1482
          when x"fc4" => -- R/-: mispacebase - Base address of instruction memory space
1483
            csr_rdata_o <= MEM_ISPACE_BASE;
1484
          when x"fc5" => -- R/-: mdspacebase - Base address of data memory space
1485
            csr_rdata_o <= MEM_DSPACE_BASE;
1486
          when x"fc6" => -- R/-: mispacesize - Total size of instruction memory space in byte
1487
            csr_rdata_o <= std_ulogic_vector(to_unsigned(MEM_ISPACE_SIZE, 32));
1488
          when x"fc7" => -- R/-: mdspacesize - Total size of data memory space in byte
1489
            csr_rdata_o <= std_ulogic_vector(to_unsigned(MEM_DSPACE_SIZE, 32));
1490
 
1491
          -- undefined/unavailable --
1492
          when others =>
1493
            csr_rdata_o <= (others => '0'); -- not implemented
1494
 
1495
        end case;
1496 2 zero_gravi
      end if;
1497
    end if;
1498
  end process csr_read_access;
1499
 
1500
 
1501 6 zero_gravi
  -- RISC-V Counter CSRs --------------------------------------------------------------------
1502 2 zero_gravi
  -- -------------------------------------------------------------------------------------------
1503
  csr_counters: process(rstn_i, clk_i)
1504
  begin
1505 6 zero_gravi
    if (rstn_i = '0') then
1506 11 zero_gravi
      csr.mcycle    <= (others => '0');
1507
      csr.minstret  <= (others => '0');
1508
      csr.mcycleh   <= (others => '0');
1509
      csr.minstreth <= (others => '0');
1510
      mcycle_msb    <= '0';
1511
      minstret_msb  <= '0';
1512 6 zero_gravi
    elsif rising_edge(clk_i) then
1513
      if (CPU_EXTENSION_RISCV_E = false) and (CSR_COUNTERS_USE = true) then
1514 11 zero_gravi
 
1515
        -- mcycle (cycle) --
1516
        mcycle_msb <= csr.mcycle(csr.mcycle'left);
1517
        if (csr.we = '1') and (execute_engine.i_reg(31 downto 20) = x"b00") then -- write access
1518
          csr.mcycle(31 downto 0) <= csr_wdata_i;
1519
          csr.mcycle(32) <= '0';
1520
        elsif (execute_engine.sleep = '0') then -- automatic update
1521
          csr.mcycle <= std_ulogic_vector(unsigned(csr.mcycle) + 1);
1522 2 zero_gravi
        end if;
1523 11 zero_gravi
 
1524
        -- mcycleh (cycleh) --
1525
        if (csr.we = '1') and (execute_engine.i_reg(31 downto 20) = x"b80") then -- write access
1526
          csr.mcycleh <= csr_wdata_i;
1527
        elsif ((mcycle_msb xor csr.mcycle(csr.mcycle'left)) = '1') then -- automatic update
1528
          csr.mcycleh <= std_ulogic_vector(unsigned(csr.mcycleh) + 1);
1529 2 zero_gravi
        end if;
1530 11 zero_gravi
 
1531
        -- minstret (instret) --
1532
        minstret_msb <= csr.minstret(csr.minstret'left);
1533
        if (csr.we = '1') and (execute_engine.i_reg(31 downto 20) = x"b02") then -- write access
1534
          csr.minstret(31 downto 0) <= csr_wdata_i;
1535
          csr.minstret(32) <= '0';
1536
        elsif (execute_engine.state_prev /= EXECUTE) and (execute_engine.state = EXECUTE) then -- automatic update
1537
          csr.minstret <= std_ulogic_vector(unsigned(csr.minstret) + 1);
1538 2 zero_gravi
        end if;
1539 11 zero_gravi
 
1540
        -- minstreth (instreth) --
1541
        if (csr.we = '1') and (execute_engine.i_reg(31 downto 20) = x"b82") then -- write access
1542
          csr.minstreth <= csr_wdata_i;
1543
        elsif ((minstret_msb xor csr.minstret(csr.minstret'left)) = '1') then -- automatic update
1544
          csr.minstreth <= std_ulogic_vector(unsigned(csr.minstreth) + 1);
1545
        end if;
1546
 
1547 2 zero_gravi
      end if;
1548
    end if;
1549
  end process csr_counters;
1550
 
1551
 
1552
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.