hw/vendor/lowrisc_ibex/rtl/ibex_decoder.sv Cov: 98%
1: // Copyright lowRISC contributors.
2: // Copyright 2018 ETH Zurich and University of Bologna, see also CREDITS.md.
3: // Licensed under the Apache License, Version 2.0, see LICENSE for details.
4: // SPDX-License-Identifier: Apache-2.0
5:
6: // Source/Destination register instruction index
7: `define REG_S1 19:15
8: `define REG_S2 24:20
9: `define REG_D 11:07
10:
11: /**
12: * Instruction decoder
13: *
14: * This module is fully combinatorial, clock and reset are used for
15: * assertions only.
16: */
17: module ibex_decoder #(
18: parameter bit RV32E = 0,
19: parameter bit RV32M = 1
20: ) (
21: input logic clk_i,
22: input logic rst_ni,
23:
24: // to/from controller
25: output logic illegal_insn_o, // illegal instr encountered
26: output logic ebrk_insn_o, // trap instr encountered
27: output logic mret_insn_o, // return from exception instr
28: // encountered
29: output logic dret_insn_o, // return from debug instr encountered
30: output logic ecall_insn_o, // syscall instr encountered
31: output logic wfi_insn_o, // wait for interrupt instr encountered
32: output logic jump_set_o, // jump taken set signal
33:
34: // from IF-ID pipeline register
35: input logic instr_new_i, // instruction read is new
36: input logic [31:0] instr_rdata_i, // instruction read from memory/cache
37: input logic illegal_c_insn_i, // compressed instruction decode failed
38:
39: // immediates
40: output ibex_pkg::imm_a_sel_e imm_a_mux_sel_o, // immediate selection for operand a
41: output ibex_pkg::imm_b_sel_e imm_b_mux_sel_o, // immediate selection for operand b
42: output logic [31:0] imm_i_type_o,
43: output logic [31:0] imm_s_type_o,
44: output logic [31:0] imm_b_type_o,
45: output logic [31:0] imm_u_type_o,
46: output logic [31:0] imm_j_type_o,
47: output logic [31:0] zimm_rs1_type_o,
48:
49: // register file
50: output ibex_pkg::rf_wd_sel_e regfile_wdata_sel_o, // RF write data selection
51: output logic regfile_we_o, // write enable for regfile
52: output logic [4:0] regfile_raddr_a_o,
53: output logic [4:0] regfile_raddr_b_o,
54: output logic [4:0] regfile_waddr_o,
55:
56: // ALU
57: output ibex_pkg::alu_op_e alu_operator_o, // ALU operation selection
58: output ibex_pkg::op_a_sel_e alu_op_a_mux_sel_o, // operand a selection: reg value, PC,
59: // immediate or zero
60: output ibex_pkg::op_b_sel_e alu_op_b_mux_sel_o, // operand b selection: reg value or
61: // immediate
62:
63: // MULT & DIV
64: output logic mult_en_o, // perform integer multiplication
65: output logic div_en_o, // perform integer division or
66: // remainder
67: output ibex_pkg::md_op_e multdiv_operator_o,
68: output logic [1:0] multdiv_signed_mode_o,
69:
70: // CSRs
71: output logic csr_access_o, // access to CSR
72: output ibex_pkg::csr_op_e csr_op_o, // operation to perform on CSR
73: output logic csr_pipe_flush_o, // CSR-related pipeline flush
74:
75: // LSU
76: output logic data_req_o, // start transaction to data memory
77: output logic data_we_o, // write enable
78: output logic [1:0] data_type_o, // size of transaction: byte, half
79: // word or word
80: output logic data_sign_extension_o, // sign extension for data read from
81: // memory
82:
83: // jump/branches
84: output logic jump_in_dec_o, // jump is being calculated in ALU
85: output logic branch_in_dec_o
86: );
87:
88: import ibex_pkg::*;
89:
90: logic illegal_insn;
91: logic illegal_reg_rv32e;
92: logic csr_illegal;
93: logic regfile_we;
94:
95: logic [31:0] instr;
96:
97: csr_op_e csr_op;
98:
99: opcode_e opcode;
100:
101: assign instr = instr_rdata_i;
102:
103: //////////////////////////////////////
104: // Register and immediate selection //
105: //////////////////////////////////////
106:
107: // immediate extraction and sign extension
108: assign imm_i_type_o = { {20{instr[31]}}, instr[31:20] };
109: assign imm_s_type_o = { {20{instr[31]}}, instr[31:25], instr[11:7] };
110: assign imm_b_type_o = { {19{instr[31]}}, instr[31], instr[7], instr[30:25], instr[11:8], 1'b0 };
111: assign imm_u_type_o = { instr[31:12], 12'b0 };
112: assign imm_j_type_o = { {12{instr[31]}}, instr[19:12], instr[20], instr[30:21], 1'b0 };
113:
114: // immediate for CSR manipulation (zero extended)
115: assign zimm_rs1_type_o = { 27'b0, instr[`REG_S1] }; // rs1
116:
117: // source registers
118: assign regfile_raddr_a_o = instr[`REG_S1]; // rs1
119: assign regfile_raddr_b_o = instr[`REG_S2]; // rs2
120:
121: // destination register
122: assign regfile_waddr_o = instr[`REG_D]; // rd
123:
124: ////////////////////
125: // Register check //
126: ////////////////////
127: if (RV32E) begin : gen_rv32e_reg_check_active
128: assign illegal_reg_rv32e = ((regfile_raddr_a_o[4] & (alu_op_a_mux_sel_o == OP_A_REG_A)) |
129: (regfile_raddr_b_o[4] & (alu_op_b_mux_sel_o == OP_B_REG_B)) |
130: (regfile_waddr_o[4] & regfile_we));
131: end else begin : gen_rv32e_reg_check_inactive
132: assign illegal_reg_rv32e = 1'b0;
133: end
134:
135: ///////////////////////
136: // CSR operand check //
137: ///////////////////////
138: always_comb begin : csr_operand_check
139: csr_op_o = csr_op;
140:
141: // CSRRSI/CSRRCI must not write 0 to CSRs (uimm[4:0]=='0)
142: // CSRRS/CSRRC must not write from x0 to CSRs (rs1=='0)
143: if ((csr_op == CSR_OP_SET || csr_op == CSR_OP_CLEAR) &&
144: instr[`REG_S1] == '0) begin
145: csr_op_o = CSR_OP_READ;
146: end
147: end
148:
149: /////////////////////////////////
150: // CSR-related pipline flushes //
151: /////////////////////////////////
152: always_comb begin : csr_pipeline_flushes
153: csr_pipe_flush_o = 1'b0;
154:
155: // A pipeline flush is needed to let the controller react after modifying certain CSRs:
156: // - When enabling interrupts, pending IRQs become visible to the controller only during
157: // the next cycle. If during that cycle the core disables interrupts again, it does not
158: // see any pending IRQs and consequently does not start to handle interrupts.
159: // - When modifying debug CSRs - TODO: Check if this is really needed
160: if (csr_access_o == 1'b1 && (csr_op_o == CSR_OP_WRITE || csr_op_o == CSR_OP_SET)) begin
161: if (csr_num_e'(instr[31:20]) == CSR_MSTATUS ||
162: csr_num_e'(instr[31:20]) == CSR_MIE) begin
163: csr_pipe_flush_o = 1'b1;
164: end
165: end else if (csr_access_o == 1'b1 && csr_op_o != CSR_OP_READ) begin
166: if (csr_num_e'(instr[31:20]) == CSR_DCSR ||
167: csr_num_e'(instr[31:20]) == CSR_DPC ||
168: csr_num_e'(instr[31:20]) == CSR_DSCRATCH0 ||
169: csr_num_e'(instr[31:20]) == CSR_DSCRATCH1) begin
170: csr_pipe_flush_o = 1'b1;
171: end
172: end
173: end
174:
175: /////////////
176: // Decoder //
177: /////////////
178:
179: always_comb begin
180: jump_in_dec_o = 1'b0;
181: jump_set_o = 1'b0;
182: branch_in_dec_o = 1'b0;
183: alu_operator_o = ALU_SLTU;
184: alu_op_a_mux_sel_o = OP_A_IMM;
185: alu_op_b_mux_sel_o = OP_B_IMM;
186:
187: imm_a_mux_sel_o = IMM_A_ZERO;
188: imm_b_mux_sel_o = IMM_B_I;
189:
190: mult_en_o = 1'b0;
191: div_en_o = 1'b0;
192: multdiv_operator_o = MD_OP_MULL;
193: multdiv_signed_mode_o = 2'b00;
194:
195: regfile_wdata_sel_o = RF_WD_EX;
196: regfile_we = 1'b0;
197:
198: csr_access_o = 1'b0;
199: csr_illegal = 1'b0;
200: csr_op = CSR_OP_READ;
201:
202: data_we_o = 1'b0;
203: data_type_o = 2'b00;
204: data_sign_extension_o = 1'b0;
205: data_req_o = 1'b0;
206:
207: illegal_insn = 1'b0;
208: ebrk_insn_o = 1'b0;
209: mret_insn_o = 1'b0;
210: dret_insn_o = 1'b0;
211: ecall_insn_o = 1'b0;
212: wfi_insn_o = 1'b0;
213:
214: opcode = opcode_e'(instr[6:0]);
215:
216: unique case (opcode)
217:
218: ///////////
219: // Jumps //
220: ///////////
221:
222: OPCODE_JAL: begin // Jump and Link
223: jump_in_dec_o = 1'b1;
224: if (instr_new_i) begin
225: // Calculate jump target
226: alu_op_a_mux_sel_o = OP_A_CURRPC;
227: alu_op_b_mux_sel_o = OP_B_IMM;
228: imm_b_mux_sel_o = IMM_B_J;
229: alu_operator_o = ALU_ADD;
230: regfile_we = 1'b0;
231: jump_set_o = 1'b1;
232: end else begin
233: // Calculate and store PC+4
234: alu_op_a_mux_sel_o = OP_A_CURRPC;
235: alu_op_b_mux_sel_o = OP_B_IMM;
236: imm_b_mux_sel_o = IMM_B_INCR_PC;
237: alu_operator_o = ALU_ADD;
238: regfile_we = 1'b1;
239: end
240: end
241:
242: OPCODE_JALR: begin // Jump and Link Register
243: jump_in_dec_o = 1'b1;
244: if (instr_new_i) begin
245: // Calculate jump target
246: alu_op_a_mux_sel_o = OP_A_REG_A;
247: alu_op_b_mux_sel_o = OP_B_IMM;
248: imm_b_mux_sel_o = IMM_B_I;
249: alu_operator_o = ALU_ADD;
250: regfile_we = 1'b0;
251: jump_set_o = 1'b1;
252: end else begin
253: // Calculate and store PC+4
254: alu_op_a_mux_sel_o = OP_A_CURRPC;
255: alu_op_b_mux_sel_o = OP_B_IMM;
256: imm_b_mux_sel_o = IMM_B_INCR_PC;
257: alu_operator_o = ALU_ADD;
258: regfile_we = 1'b1;
259: end
260: if (instr[14:12] != 3'b0) begin
261: illegal_insn = 1'b1;
262: end
263: end
264:
265: OPCODE_BRANCH: begin // Branch
266: branch_in_dec_o = 1'b1;
267: // Check branch condition selection
268: unique case (instr[14:12])
269: 3'b000: alu_operator_o = ALU_EQ;
270: 3'b001: alu_operator_o = ALU_NE;
271: 3'b100: alu_operator_o = ALU_LT;
272: 3'b101: alu_operator_o = ALU_GE;
273: 3'b110: alu_operator_o = ALU_LTU;
274: 3'b111: alu_operator_o = ALU_GEU;
275: default: illegal_insn = 1'b1;
276: endcase
277: if (instr_new_i) begin
278: // Evaluate branch condition
279: alu_op_a_mux_sel_o = OP_A_REG_A;
280: alu_op_b_mux_sel_o = OP_B_REG_B;
281: end else begin
282: // Calculate jump target in EX
283: alu_op_a_mux_sel_o = OP_A_CURRPC;
284: alu_op_b_mux_sel_o = OP_B_IMM;
285: imm_b_mux_sel_o = IMM_B_B;
286: alu_operator_o = ALU_ADD;
287: regfile_we = 1'b0;
288: end
289: end
290:
291: ////////////////
292: // Load/store //
293: ////////////////
294:
295: OPCODE_STORE: begin
296: alu_op_a_mux_sel_o = OP_A_REG_A;
297: alu_op_b_mux_sel_o = OP_B_REG_B;
298: data_req_o = 1'b1;
299: data_we_o = 1'b1;
300: alu_operator_o = ALU_ADD;
301:
302: if (!instr[14]) begin
303: // offset from immediate
304: imm_b_mux_sel_o = IMM_B_S;
305: alu_op_b_mux_sel_o = OP_B_IMM;
306: end else begin
307: // Register offset is illegal since no register c available
308: illegal_insn = 1'b1;
309: end
310:
311: // store size
312: unique case (instr[13:12])
313: 2'b00: data_type_o = 2'b10; // SB
314: 2'b01: data_type_o = 2'b01; // SH
315: 2'b10: data_type_o = 2'b00; // SW
316: default: illegal_insn = 1'b1;
317: endcase
318: end
319:
320: OPCODE_LOAD: begin
321: alu_op_a_mux_sel_o = OP_A_REG_A;
322: data_req_o = 1'b1;
323: regfile_wdata_sel_o = RF_WD_LSU;
324: regfile_we = 1'b1;
325: data_type_o = 2'b00;
326:
327: // offset from immediate
328: alu_operator_o = ALU_ADD;
329: alu_op_b_mux_sel_o = OP_B_IMM;
330: imm_b_mux_sel_o = IMM_B_I;
331:
332: // sign/zero extension
333: data_sign_extension_o = ~instr[14];
334:
335: // load size
336: unique case (instr[13:12])
337: 2'b00: data_type_o = 2'b10; // LB(U)
338: 2'b01: data_type_o = 2'b01; // LH(U)
339: 2'b10: begin
340: data_type_o = 2'b00; // LW
341: if (instr[14]) begin
342: illegal_insn = 1'b1; // LWU does not exist
343: end
344: end
345: default: begin
346: illegal_insn = 1'b1;
347: end
348: endcase
349: end
350:
351: /////////
352: // ALU //
353: /////////
354:
355: OPCODE_LUI: begin // Load Upper Immediate
356: alu_op_a_mux_sel_o = OP_A_IMM;
357: alu_op_b_mux_sel_o = OP_B_IMM;
358: imm_a_mux_sel_o = IMM_A_ZERO;
359: imm_b_mux_sel_o = IMM_B_U;
360: alu_operator_o = ALU_ADD;
361: regfile_we = 1'b1;
362: end
363:
364: OPCODE_AUIPC: begin // Add Upper Immediate to PC
365: alu_op_a_mux_sel_o = OP_A_CURRPC;
366: alu_op_b_mux_sel_o = OP_B_IMM;
367: imm_b_mux_sel_o = IMM_B_U;
368: alu_operator_o = ALU_ADD;
369: regfile_we = 1'b1;
370: end
371:
372: OPCODE_OP_IMM: begin // Register-Immediate ALU Operations
373: alu_op_a_mux_sel_o = OP_A_REG_A;
374: alu_op_b_mux_sel_o = OP_B_IMM;
375: imm_b_mux_sel_o = IMM_B_I;
376: regfile_we = 1'b1;
377:
378: unique case (instr[14:12])
379: 3'b000: alu_operator_o = ALU_ADD; // Add Immediate
380: 3'b010: alu_operator_o = ALU_SLT; // Set to one if Lower Than Immediate
381: 3'b011: alu_operator_o = ALU_SLTU; // Set to one if Lower Than Immediate Unsigned
382: 3'b100: alu_operator_o = ALU_XOR; // Exclusive Or with Immediate
383: 3'b110: alu_operator_o = ALU_OR; // Or with Immediate
384: 3'b111: alu_operator_o = ALU_AND; // And with Immediate
385:
386: 3'b001: begin
387: alu_operator_o = ALU_SLL; // Shift Left Logical by Immediate
388: if (instr[31:25] != 7'b0) begin
389: illegal_insn = 1'b1;
390: end
391: end
392:
393: 3'b101: begin
394: if (instr[31:25] == 7'b0) begin
395: alu_operator_o = ALU_SRL; // Shift Right Logical by Immediate
396: end else if (instr[31:25] == 7'b010_0000) begin
397: alu_operator_o = ALU_SRA; // Shift Right Arithmetically by Immediate
398: end else begin
399: illegal_insn = 1'b1;
400: end
401: end
402:
403: default: begin
404: alu_operator_o = ALU_SLTU;
405: end
406: endcase
407: end
408:
409: OPCODE_OP: begin // Register-Register ALU operation
410: alu_op_a_mux_sel_o = OP_A_REG_A;
411: alu_op_b_mux_sel_o = OP_B_REG_B;
412: regfile_we = 1'b1;
413:
414: if (instr[31]) begin
415: illegal_insn = 1'b1;
416: end else begin
417: unique case ({instr[30:25], instr[14:12]})
418: // RV32I ALU operations
419: {6'b00_0000, 3'b000}: alu_operator_o = ALU_ADD; // Add
420: {6'b10_0000, 3'b000}: alu_operator_o = ALU_SUB; // Sub
421: {6'b00_0000, 3'b010}: alu_operator_o = ALU_SLT; // Set Lower Than
422: {6'b00_0000, 3'b011}: alu_operator_o = ALU_SLTU; // Set Lower Than Unsigned
423: {6'b00_0000, 3'b100}: alu_operator_o = ALU_XOR; // Xor
424: {6'b00_0000, 3'b110}: alu_operator_o = ALU_OR; // Or
425: {6'b00_0000, 3'b111}: alu_operator_o = ALU_AND; // And
426: {6'b00_0000, 3'b001}: alu_operator_o = ALU_SLL; // Shift Left Logical
427: {6'b00_0000, 3'b101}: alu_operator_o = ALU_SRL; // Shift Right Logical
428: {6'b10_0000, 3'b101}: alu_operator_o = ALU_SRA; // Shift Right Arithmetic
429:
430: // supported RV32M instructions
431: {6'b00_0001, 3'b000}: begin // mul
432: alu_operator_o = ALU_ADD;
433: multdiv_operator_o = MD_OP_MULL;
434: mult_en_o = RV32M ? 1'b1 : 1'b0;
435: multdiv_signed_mode_o = 2'b00;
436: illegal_insn = RV32M ? 1'b0 : 1'b1;
437: end
438: {6'b00_0001, 3'b001}: begin // mulh
439: alu_operator_o = ALU_ADD;
440: multdiv_operator_o = MD_OP_MULH;
441: mult_en_o = RV32M ? 1'b1 : 1'b0;
442: multdiv_signed_mode_o = 2'b11;
443: illegal_insn = RV32M ? 1'b0 : 1'b1;
444: end
445: {6'b00_0001, 3'b010}: begin // mulhsu
446: alu_operator_o = ALU_ADD;
447: multdiv_operator_o = MD_OP_MULH;
448: mult_en_o = RV32M ? 1'b1 : 1'b0;
449: multdiv_signed_mode_o = 2'b01;
450: illegal_insn = RV32M ? 1'b0 : 1'b1;
451: end
452: {6'b00_0001, 3'b011}: begin // mulhu
453: alu_operator_o = ALU_ADD;
454: multdiv_operator_o = MD_OP_MULH;
455: mult_en_o = RV32M ? 1'b1 : 1'b0;
456: multdiv_signed_mode_o = 2'b00;
457: illegal_insn = RV32M ? 1'b0 : 1'b1;
458: end
459: {6'b00_0001, 3'b100}: begin // div
460: alu_operator_o = ALU_ADD;
461: multdiv_operator_o = MD_OP_DIV;
462: div_en_o = RV32M ? 1'b1 : 1'b0;
463: multdiv_signed_mode_o = 2'b11;
464: illegal_insn = RV32M ? 1'b0 : 1'b1;
465: end
466: {6'b00_0001, 3'b101}: begin // divu
467: alu_operator_o = ALU_ADD;
468: multdiv_operator_o = MD_OP_DIV;
469: div_en_o = RV32M ? 1'b1 : 1'b0;
470: multdiv_signed_mode_o = 2'b00;
471: illegal_insn = RV32M ? 1'b0 : 1'b1;
472: end
473: {6'b00_0001, 3'b110}: begin // rem
474: alu_operator_o = ALU_ADD;
475: multdiv_operator_o = MD_OP_REM;
476: div_en_o = RV32M ? 1'b1 : 1'b0;
477: multdiv_signed_mode_o = 2'b11;
478: illegal_insn = RV32M ? 1'b0 : 1'b1;
479: end
480: {6'b00_0001, 3'b111}: begin // remu
481: alu_operator_o = ALU_ADD;
482: multdiv_operator_o = MD_OP_REM;
483: div_en_o = RV32M ? 1'b1 : 1'b0;
484: multdiv_signed_mode_o = 2'b00;
485: illegal_insn = RV32M ? 1'b0 : 1'b1;
486: end
487: default: begin
488: illegal_insn = 1'b1;
489: end
490: endcase
491: end
492: end
493:
494: /////////////
495: // Special //
496: /////////////
497:
498: OPCODE_MISC_MEM: begin
499: // For now, treat the FENCE (funct3 == 000) instruction as a NOP. This may not be correct
500: // in a system with caches and should be revisited.
501: // FENCE.I will flush the IF stage and prefetch buffer but nothing else.
502: unique case (instr[14:12])
503: 3'b000: begin
504: alu_operator_o = ALU_ADD; // nop
505: alu_op_a_mux_sel_o = OP_A_REG_A;
506: alu_op_b_mux_sel_o = OP_B_IMM;
507: regfile_we = 1'b0;
508: end
509: 3'b001: begin
510: // FENCE.I is implemented as a jump to the next PC, this gives the required flushing
511: // behaviour (iside prefetch buffer flushed and response to any outstanding iside
512: // requests will be ignored).
513: jump_in_dec_o = 1'b1;
514:
515: alu_op_a_mux_sel_o = OP_A_CURRPC;
516: alu_op_b_mux_sel_o = OP_B_IMM;
517: imm_b_mux_sel_o = IMM_B_INCR_PC;
518: alu_operator_o = ALU_ADD;
519: regfile_we = 1'b0;
520:
521: if (instr_new_i) begin
522: jump_set_o = 1'b1;
523: end
524: end
525: default: begin
526: illegal_insn = 1'b1;
527: end
528: endcase
529: end
530:
531: OPCODE_SYSTEM: begin
532: if (instr[14:12] == 3'b000) begin
533: // non CSR related SYSTEM instructions
534: alu_op_a_mux_sel_o = OP_A_REG_A;
535: alu_op_b_mux_sel_o = OP_B_IMM;
536: unique case (instr[31:20])
537: 12'h000: // ECALL
538: // environment (system) call
539: ecall_insn_o = 1'b1;
540:
541: 12'h001: // ebreak
542: // debugger trap
543: ebrk_insn_o = 1'b1;
544:
545: 12'h302: // mret
546: mret_insn_o = 1'b1;
547:
548: 12'h7b2: // dret
549: dret_insn_o = 1'b1;
550:
551: 12'h105: // wfi
552: wfi_insn_o = 1'b1;
553:
554: default:
555: illegal_insn = 1'b1;
556: endcase
557:
558: // rs1 and rd must be 0
559: if (instr[`REG_S1] != 5'b0 || instr[`REG_D] != 5'b0) begin
560: illegal_insn = 1'b1;
561: end
562: end else begin
563: // instruction to read/modify CSR
564: csr_access_o = 1'b1;
565: regfile_wdata_sel_o = RF_WD_CSR;
566: regfile_we = 1'b1;
567: alu_op_b_mux_sel_o = OP_B_IMM;
568: imm_a_mux_sel_o = IMM_A_Z;
569: imm_b_mux_sel_o = IMM_B_I; // CSR address is encoded in I imm
570:
571: if (instr[14]) begin
572: // rs1 field is used as immediate
573: alu_op_a_mux_sel_o = OP_A_IMM;
574: end else begin
575: alu_op_a_mux_sel_o = OP_A_REG_A;
576: end
577:
578: unique case (instr[13:12])
579: 2'b01: csr_op = CSR_OP_WRITE;
580: 2'b10: csr_op = CSR_OP_SET;
581: 2'b11: csr_op = CSR_OP_CLEAR;
582: default: csr_illegal = 1'b1;
583: endcase
584:
585: illegal_insn = csr_illegal;
586: end
587:
588: end
589: default: begin
590: illegal_insn = 1'b1;
591: end
592: endcase
593:
594: // make sure illegal compressed instructions cause illegal instruction exceptions
595: if (illegal_c_insn_i) begin
596: illegal_insn = 1'b1;
597: end
598:
599: // make sure illegal instructions detected in the decoder do not propagate from decoder
600: // into register file, LSU, EX, WB, CSRs, PC
601: // NOTE: instructions can also be detected to be illegal inside the CSRs (upon accesses with
602: // insufficient privileges), or when accessing non-available registers in RV32E,
603: // these cases are not handled here
604: if (illegal_insn) begin
605: regfile_we = 1'b0;
606: data_req_o = 1'b0;
607: data_we_o = 1'b0;
608: mult_en_o = 1'b0;
609: div_en_o = 1'b0;
610: jump_in_dec_o = 1'b0;
611: jump_set_o = 1'b0;
612: branch_in_dec_o = 1'b0;
613: csr_access_o = 1'b0;
614: end
615: end
616:
617: // make sure instructions accessing non-available registers in RV32E cause illegal
618: // instruction exceptions
619: assign illegal_insn_o = illegal_insn | illegal_reg_rv32e;
620:
621: // do not propgate regfile write enable if non-available registers are accessed in RV32E
622: assign regfile_we_o = regfile_we & ~illegal_reg_rv32e;
623:
624: ////////////////
625: // Assertions //
626: ////////////////
627:
628: // Selectors must be known/valid.
629: `ASSERT(IbexRegImmAluOpKnown, (opcode == OPCODE_OP_IMM) |->
630: !$isunknown(instr[14:12]), clk_i, !rst_ni)
631:
632: endmodule // controller
633: