../src/lowrisc_ibex_ibex_core_0.1/rtl/ibex_if_stage.sv Cov: 79.2%
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: /**
7: * Instruction Fetch Stage
8: *
9: * Instruction fetch unit: Selection of the next PC, and buffering (sampling) of
10: * the read instruction.
11: */
12:
13: `include "prim_assert.sv"
14:
15: module ibex_if_stage #(
16: parameter int unsigned DmHaltAddr = 32'h1A110800,
17: parameter int unsigned DmExceptionAddr = 32'h1A110808,
18: parameter bit DummyInstructions = 1'b0,
19: parameter bit ICache = 1'b0,
20: parameter bit ICacheECC = 1'b0
21: ) (
22: input logic clk_i,
23: input logic rst_ni,
24:
25: input logic [31:0] boot_addr_i, // also used for mtvec
26: input logic req_i, // instruction request control
27:
28: // instruction cache interface
29: output logic instr_req_o,
30: output logic [31:0] instr_addr_o,
31: input logic instr_gnt_i,
32: input logic instr_rvalid_i,
33: input logic [31:0] instr_rdata_i,
34: input logic instr_err_i,
35: input logic instr_pmp_err_i,
36:
37: // output of ID stage
38: output logic instr_valid_id_o, // instr in IF-ID is valid
39: output logic instr_new_id_o, // instr in IF-ID is new
40: output logic [31:0] instr_rdata_id_o, // instr for ID stage
41: output logic [31:0] instr_rdata_alu_id_o, // replicated instr for ID stage
42: // to reduce fan-out
43: output logic [15:0] instr_rdata_c_id_o, // compressed instr for ID stage
44: // (mtval), meaningful only if
45: // instr_is_compressed_id_o = 1'b1
46: output logic instr_is_compressed_id_o, // compressed decoder thinks this
47: // is a compressed instr
48: output logic instr_fetch_err_o, // bus error on fetch
49: output logic instr_fetch_err_plus2_o, // bus error misaligned
50: output logic illegal_c_insn_id_o, // compressed decoder thinks this
51: // is an invalid instr
52: output logic dummy_instr_id_o, // Instruction is a dummy
53: output logic [31:0] pc_if_o,
54: output logic [31:0] pc_id_o,
55:
56: // control signals
57: input logic instr_valid_clear_i, // clear instr valid bit in IF-ID
58: input logic pc_set_i, // set the PC to a new value
59: input logic pc_set_spec_i,
60: input ibex_pkg::pc_sel_e pc_mux_i, // selector for PC multiplexer
61: input ibex_pkg::exc_pc_sel_e exc_pc_mux_i, // selects ISR address
62: input ibex_pkg::exc_cause_e exc_cause, // selects ISR address for
63: // vectorized interrupt lines
64: input logic dummy_instr_en_i,
65: input logic [2:0] dummy_instr_mask_i,
66: input logic dummy_instr_seed_en_i,
67: input logic [31:0] dummy_instr_seed_i,
68: input logic icache_enable_i,
69: input logic icache_inval_i,
70:
71: // jump and branch target
72: input logic [31:0] branch_target_ex_i, // branch/jump target address
73:
74: // CSRs
75: input logic [31:0] csr_mepc_i, // PC to restore after handling
76: // the interrupt/exception
77: input logic [31:0] csr_depc_i, // PC to restore after handling
78: // the debug request
79: input logic [31:0] csr_mtvec_i, // base PC to jump to on exception
80: output logic csr_mtvec_init_o, // tell CS regfile to init mtvec
81:
82: // pipeline stall
83: input logic id_in_ready_i, // ID stage is ready for new instr
84:
85: // misc signals
86: output logic if_busy_o // IF stage is busy fetching instr
87: );
88:
89: import ibex_pkg::*;
90:
91: logic instr_valid_id_d, instr_valid_id_q;
92: logic instr_new_id_d, instr_new_id_q;
93:
94: // prefetch buffer related signals
95: logic prefetch_busy;
96: logic branch_req;
97: logic [31:0] fetch_addr_n;
98:
99: logic fetch_valid;
100: logic fetch_ready;
101: logic [31:0] fetch_rdata;
102: logic [31:0] fetch_addr;
103: logic fetch_err;
104: logic fetch_err_plus2;
105:
106: logic [31:0] exc_pc;
107:
108: logic [5:0] irq_id;
109: logic unused_irq_bit;
110:
111: logic if_id_pipe_reg_we; // IF-ID pipeline reg write enable
112:
113: // Dummy instruction signals
114: logic fetch_valid_out;
115: logic stall_dummy_instr;
116: logic [31:0] instr_out;
117: logic instr_is_compressed_out;
118: logic illegal_c_instr_out;
119: logic instr_err_out;
120:
121: logic [7:0] unused_boot_addr;
122: logic [7:0] unused_csr_mtvec;
123:
124: assign unused_boot_addr = boot_addr_i[7:0];
125: assign unused_csr_mtvec = csr_mtvec_i[7:0];
126:
127: // extract interrupt ID from exception cause
128: assign irq_id = {exc_cause};
129: assign unused_irq_bit = irq_id[5]; // MSB distinguishes interrupts from exceptions
130:
131: // exception PC selection mux
132: always_comb begin : exc_pc_mux
133: unique case (exc_pc_mux_i)
134: EXC_PC_EXC: exc_pc = { csr_mtvec_i[31:8], 8'h00 };
135: EXC_PC_IRQ: exc_pc = { csr_mtvec_i[31:8], 1'b0, irq_id[4:0], 2'b00 };
136: EXC_PC_DBD: exc_pc = DmHaltAddr;
137: EXC_PC_DBG_EXC: exc_pc = DmExceptionAddr;
138: default: exc_pc = { csr_mtvec_i[31:8], 8'h00 };
139: endcase
140: end
141:
142: // fetch address selection mux
143: always_comb begin : fetch_addr_mux
144: unique case (pc_mux_i)
145: PC_BOOT: fetch_addr_n = { boot_addr_i[31:8], 8'h80 };
146: PC_JUMP: fetch_addr_n = branch_target_ex_i;
147: PC_EXC: fetch_addr_n = exc_pc; // set PC to exception handler
148: PC_ERET: fetch_addr_n = csr_mepc_i; // restore PC when returning from EXC
149: PC_DRET: fetch_addr_n = csr_depc_i;
150: default: fetch_addr_n = { boot_addr_i[31:8], 8'h80 };
151: endcase
152: end
153:
154: // tell CS register file to initialize mtvec on boot
155: assign csr_mtvec_init_o = (pc_mux_i == PC_BOOT) & pc_set_i;
156:
157: if (ICache) begin : gen_icache
158: // Full I-Cache option
159: ibex_icache #(
160: .ICacheECC (ICacheECC)
161: ) icache_i (
162: .clk_i ( clk_i ),
163: .rst_ni ( rst_ni ),
164:
165: .req_i ( req_i ),
166:
167: .branch_i ( branch_req ),
168: .branch_spec_i ( pc_set_spec_i ),
169: .addr_i ( {fetch_addr_n[31:1], 1'b0} ),
170:
171: .ready_i ( fetch_ready ),
172: .valid_o ( fetch_valid ),
173: .rdata_o ( fetch_rdata ),
174: .addr_o ( fetch_addr ),
175: .err_o ( fetch_err ),
176: .err_plus2_o ( fetch_err_plus2 ),
177:
178: .instr_req_o ( instr_req_o ),
179: .instr_addr_o ( instr_addr_o ),
180: .instr_gnt_i ( instr_gnt_i ),
181: .instr_rvalid_i ( instr_rvalid_i ),
182: .instr_rdata_i ( instr_rdata_i ),
183: .instr_err_i ( instr_err_i ),
184: .instr_pmp_err_i ( instr_pmp_err_i ),
185:
186: .icache_enable_i ( icache_enable_i ),
187: .icache_inval_i ( icache_inval_i ),
188: .busy_o ( prefetch_busy )
189: );
190: end else begin : gen_prefetch_buffer
191: // prefetch buffer, caches a fixed number of instructions
192: ibex_prefetch_buffer prefetch_buffer_i (
193: .clk_i ( clk_i ),
194: .rst_ni ( rst_ni ),
195:
196: .req_i ( req_i ),
197:
198: .branch_i ( branch_req ),
199: .branch_spec_i ( pc_set_spec_i ),
200: .addr_i ( {fetch_addr_n[31:1], 1'b0} ),
201:
202: .ready_i ( fetch_ready ),
203: .valid_o ( fetch_valid ),
204: .rdata_o ( fetch_rdata ),
205: .addr_o ( fetch_addr ),
206: .err_o ( fetch_err ),
207: .err_plus2_o ( fetch_err_plus2 ),
208:
209: .instr_req_o ( instr_req_o ),
210: .instr_addr_o ( instr_addr_o ),
211: .instr_gnt_i ( instr_gnt_i ),
212: .instr_rvalid_i ( instr_rvalid_i ),
213: .instr_rdata_i ( instr_rdata_i ),
214: .instr_err_i ( instr_err_i ),
215: .instr_pmp_err_i ( instr_pmp_err_i ),
216:
217: .busy_o ( prefetch_busy )
218: );
219: // ICache tieoffs
220: logic unused_icen, unused_icinv;
221: assign unused_icen = icache_enable_i;
222: assign unused_icinv = icache_inval_i;
223: end
224:
225: assign branch_req = pc_set_i;
226: assign fetch_ready = id_in_ready_i & ~stall_dummy_instr;
227:
228: assign pc_if_o = fetch_addr;
229: assign if_busy_o = prefetch_busy;
230:
231: // compressed instruction decoding, or more precisely compressed instruction
232: // expander
233: //
234: // since it does not matter where we decompress instructions, we do it here
235: // to ease timing closure
236: logic [31:0] instr_decompressed;
237: logic illegal_c_insn;
238: logic instr_is_compressed;
239:
240: ibex_compressed_decoder compressed_decoder_i (
241: .clk_i ( clk_i ),
242: .rst_ni ( rst_ni ),
243: .valid_i ( fetch_valid & ~fetch_err ),
244: .instr_i ( fetch_rdata ),
245: .instr_o ( instr_decompressed ),
246: .is_compressed_o ( instr_is_compressed ),
247: .illegal_instr_o ( illegal_c_insn )
248: );
249:
250: // Dummy instruction insertion
251: if (DummyInstructions) begin : gen_dummy_instr
252: logic insert_dummy_instr;
253: logic [31:0] dummy_instr_data;
254:
255: ibex_dummy_instr dummy_instr_i (
256: .clk_i ( clk_i ),
257: .rst_ni ( rst_ni ),
258: .dummy_instr_en_i ( dummy_instr_en_i ),
259: .dummy_instr_mask_i ( dummy_instr_mask_i ),
260: .dummy_instr_seed_en_i ( dummy_instr_seed_en_i ),
261: .dummy_instr_seed_i ( dummy_instr_seed_i ),
262: .fetch_valid_i ( fetch_valid ),
263: .id_in_ready_i ( id_in_ready_i ),
264: .insert_dummy_instr_o ( insert_dummy_instr ),
265: .dummy_instr_data_o ( dummy_instr_data )
266: );
267:
268: // Mux between actual instructions and dummy instructions
269: assign fetch_valid_out = insert_dummy_instr | fetch_valid;
270: assign instr_out = insert_dummy_instr ? dummy_instr_data : instr_decompressed;
271: assign instr_is_compressed_out = insert_dummy_instr ? 1'b0 : instr_is_compressed;
272: assign illegal_c_instr_out = insert_dummy_instr ? 1'b0 : illegal_c_insn;
273: assign instr_err_out = insert_dummy_instr ? 1'b0 : fetch_err;
274:
275: // Stall the IF stage if we insert a dummy instruction. The dummy will execute between whatever
276: // is currently in the ID stage and whatever is valid from the prefetch buffer this cycle. The
277: // PC of the dummy instruction will match whatever is next from the prefetch buffer.
278: assign stall_dummy_instr = insert_dummy_instr;
279:
280: // Register the dummy instruction indication into the ID stage
281: always_ff @(posedge clk_i or negedge rst_ni) begin
282: if (!rst_ni) begin
283: dummy_instr_id_o <= 1'b0;
284: end else if (if_id_pipe_reg_we) begin
285: dummy_instr_id_o <= insert_dummy_instr;
286: end
287: end
288:
289: end else begin : gen_no_dummy_instr
290: logic unused_dummy_en;
291: logic [2:0] unused_dummy_mask;
292: logic unused_dummy_seed_en;
293: logic [31:0] unused_dummy_seed;
294:
295: assign unused_dummy_en = dummy_instr_en_i;
296: assign unused_dummy_mask = dummy_instr_mask_i;
297: assign unused_dummy_seed_en = dummy_instr_seed_en_i;
298: assign unused_dummy_seed = dummy_instr_seed_i;
299: assign fetch_valid_out = fetch_valid;
300: assign instr_out = instr_decompressed;
301: assign instr_is_compressed_out = instr_is_compressed;
302: assign illegal_c_instr_out = illegal_c_insn;
303: assign instr_err_out = fetch_err;
304: assign stall_dummy_instr = 1'b0;
305: assign dummy_instr_id_o = 1'b0;
306: end
307:
308: // The ID stage becomes valid as soon as any instruction is registered in the ID stage flops.
309: // Note that the current instruction is squashed by the incoming pc_set_i signal.
310: // Valid is held until it is explicitly cleared (due to an instruction completing or an exception)
311: assign instr_valid_id_d = (fetch_valid_out & id_in_ready_i & ~pc_set_i) |
312: (instr_valid_id_q & ~instr_valid_clear_i);
313: assign instr_new_id_d = fetch_valid_out & id_in_ready_i;
314:
315: always_ff @(posedge clk_i or negedge rst_ni) begin
316: if (!rst_ni) begin
317: instr_valid_id_q <= 1'b0;
318: instr_new_id_q <= 1'b0;
319: end else begin
320: instr_valid_id_q <= instr_valid_id_d;
321: instr_new_id_q <= instr_new_id_d;
322: end
323: end
324:
325: assign instr_valid_id_o = instr_valid_id_q;
326: // Signal when a new instruction enters the ID stage (only used for RVFI signalling).
327: assign instr_new_id_o = instr_new_id_q;
328:
329: // IF-ID pipeline registers, frozen when the ID stage is stalled
330: assign if_id_pipe_reg_we = instr_new_id_d;
331:
332: always_ff @(posedge clk_i) begin
333: if (if_id_pipe_reg_we) begin
334: instr_rdata_id_o <= instr_out;
335: // To reduce fan-out and help timing from the instr_rdata_id flops they are replicated.
336: instr_rdata_alu_id_o <= instr_out;
337: instr_fetch_err_o <= instr_err_out;
338: instr_fetch_err_plus2_o <= fetch_err_plus2;
339: instr_rdata_c_id_o <= fetch_rdata[15:0];
340: instr_is_compressed_id_o <= instr_is_compressed_out;
341: illegal_c_insn_id_o <= illegal_c_instr_out;
342: pc_id_o <= pc_if_o;
343: end
344: end
345:
346: ////////////////
347: // Assertions //
348: ////////////////
349:
350: // Selectors must be known/valid.
351: `ASSERT_KNOWN(IbexExcPcMuxKnown, exc_pc_mux_i)
352: `ASSERT(IbexPcMuxValid, pc_mux_i inside {
353: PC_BOOT,
354: PC_JUMP,
355: PC_EXC,
356: PC_ERET,
357: PC_DRET})
358:
359: // Boot address must be aligned to 256 bytes.
360: `ASSERT(IbexBootAddrUnaligned, boot_addr_i[7:0] == 8'h00)
361:
362: // Errors must only be sent together with rvalid.
363: `ASSERT(IbexInstrErrWithoutRvalid, instr_err_i |-> instr_rvalid_i)
364:
365: // Address must not contain X when request is sent.
366: `ASSERT(IbexInstrAddrUnknown, instr_req_o |-> !$isunknown(instr_addr_o))
367:
368: // Address must be word aligned when request is sent.
369: `ASSERT(IbexInstrAddrUnaligned, instr_req_o |-> (instr_addr_o[1:0] == 2'b00))
370:
371: endmodule
372: