../src/lowrisc_ibex_ibex_core_0.1/rtl/ibex_fetch_fifo.sv Cov: 100%
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: * Fetch Fifo for 32 bit memory interface
8: *
9: * input port: send address and data to the FIFO
10: * clear_i clears the FIFO for the following cycle, including any new request
11: */
12:
13: `include "prim_assert.sv"
14:
15: module ibex_fetch_fifo #(
16: parameter int unsigned NUM_REQS = 2
17: ) (
18: input logic clk_i,
19: input logic rst_ni,
20:
21: // control signals
22: input logic clear_i, // clears the contents of the FIFO
23: output logic [NUM_REQS-1:0] busy_o,
24:
25: // input port
26: input logic in_valid_i,
27: input logic [31:0] in_addr_i,
28: input logic [31:0] in_rdata_i,
29: input logic in_err_i,
30:
31: // output port
32: output logic out_valid_o,
33: input logic out_ready_i,
34: output logic [31:0] out_addr_o,
35: output logic [31:0] out_rdata_o,
36: output logic out_err_o,
37: output logic out_err_plus2_o
38: );
39:
40: localparam int unsigned DEPTH = NUM_REQS+1;
41:
42: // index 0 is used for output
43: logic [DEPTH-1:0] [31:0] rdata_d, rdata_q;
44: logic [DEPTH-1:0] err_d, err_q;
45: logic [DEPTH-1:0] valid_d, valid_q;
46: logic [DEPTH-1:0] lowest_free_entry;
47: logic [DEPTH-1:0] valid_pushed, valid_popped;
48: logic [DEPTH-1:0] entry_en;
49:
50: logic pop_fifo;
51: logic [31:0] rdata, rdata_unaligned;
52: logic err, err_unaligned, err_plus2;
53: logic valid, valid_unaligned;
54:
55: logic aligned_is_compressed, unaligned_is_compressed;
56:
57: logic addr_incr_two;
58: logic [31:1] instr_addr_d, instr_addr_q;
59: logic instr_addr_en;
60: logic unused_addr_in;
61:
62: /////////////////
63: // Output port //
64: /////////////////
65:
66: assign rdata = valid_q[0] ? rdata_q[0] : in_rdata_i;
67: assign err = valid_q[0] ? err_q[0] : in_err_i;
68: assign valid = valid_q[0] | in_valid_i;
69:
70: // The FIFO contains word aligned memory fetches, but the instructions contained in each entry
71: // might be half-word aligned (due to compressed instructions)
72: // e.g.
73: // | 31 16 | 15 0 |
74: // FIFO entry 0 | Instr 1 [15:0] | Instr 0 [15:0] |
75: // FIFO entry 1 | Instr 2 [15:0] | Instr 1 [31:16] |
76: //
77: // The FIFO also has a direct bypass path, so a complete instruction might be made up of data
78: // from the FIFO and new incoming data.
79: //
80:
81: // Construct the output data for an unaligned instruction
82: assign rdata_unaligned = valid_q[1] ? {rdata_q[1][15:0], rdata[31:16]} :
83: {in_rdata_i[15:0], rdata[31:16]};
84:
85: // If entry[1] is valid, an error can come from entry[0] or entry[1], unless the
86: // instruction in entry[0] is compressed (entry[1] is a new instruction)
87: // If entry[1] is not valid, and entry[0] is, an error can come from entry[0] or the incoming
88: // data, unless the instruction in entry[0] is compressed
89: // If entry[0] is not valid, the error must come from the incoming data
90: assign err_unaligned = valid_q[1] ? ((err_q[1] & ~unaligned_is_compressed) | err_q[0]) :
91: ((valid_q[0] & err_q[0]) |
92: (in_err_i & (~valid_q[0] | ~unaligned_is_compressed)));
93:
94: // Record when an error is caused by the second half of an unaligned 32bit instruction.
95: // Only needs to be correct when unaligned and if err_unaligned is set
96: assign err_plus2 = valid_q[1] ? (err_q[1] & ~err_q[0]) :
97: (in_err_i & valid_q[0] & ~err_q[0]);
98:
99: // An uncompressed unaligned instruction is only valid if both parts are available
100: assign valid_unaligned = valid_q[1] ? 1'b1 :
101: (valid_q[0] & in_valid_i);
102:
103: // If there is an error, rdata is unknown
104: assign unaligned_is_compressed = (rdata[17:16] != 2'b11) | err;
105: assign aligned_is_compressed = (rdata[ 1: 0] != 2'b11) & ~err;
106:
107: ////////////////////////////////////////
108: // Instruction aligner (if unaligned) //
109: ////////////////////////////////////////
110:
111: always_comb begin
112: if (out_addr_o[1]) begin
113: // unaligned case
114: out_rdata_o = rdata_unaligned;
115: out_err_o = err_unaligned;
116: out_err_plus2_o = err_plus2;
117:
118: if (unaligned_is_compressed) begin
119: out_valid_o = valid;
120: end else begin
121: out_valid_o = valid_unaligned;
122: end
123: end else begin
124: // aligned case
125: out_rdata_o = rdata;
126: out_err_o = err;
127: out_err_plus2_o = 1'b0;
128: out_valid_o = valid;
129: end
130: end
131:
132: /////////////////////////
133: // Instruction address //
134: /////////////////////////
135:
136: // Update the address on branches and every time an instruction is driven
137: assign instr_addr_en = clear_i | (out_ready_i & out_valid_o);
138:
139: // Increment the address by two every time a compressed instruction is popped
140: assign addr_incr_two = instr_addr_q[1] ? unaligned_is_compressed :
141: aligned_is_compressed;
142:
143: assign instr_addr_d = clear_i ? in_addr_i[31:1] :
144: (instr_addr_q[31:1] +
145: // Increment address by 4 or 2
146: {29'd0,~addr_incr_two,addr_incr_two});
147:
148: always_ff @(posedge clk_i) begin
149: if (instr_addr_en) begin
150: instr_addr_q <= instr_addr_d;
151: end
152: end
153:
154: assign out_addr_o[31:1] = instr_addr_q[31:1];
155: assign out_addr_o[0] = 1'b0;
156:
157: // The LSB of the address is unused, since all addresses are halfword aligned
158: assign unused_addr_in = in_addr_i[0];
159:
160: /////////////////
161: // FIFO status //
162: /////////////////
163:
164: // Indicate the fill level of fifo-entries. This is used to determine when a new request can be
165: // made on the bus. The prefetch buffer only needs to know about the upper entries which overlap
166: // with NUM_REQS.
167: assign busy_o = valid_q[DEPTH-1:DEPTH-NUM_REQS];
168:
169: /////////////////////
170: // FIFO management //
171: /////////////////////
172:
173: // Since an entry can contain unaligned instructions, popping an entry can leave the entry valid
174: assign pop_fifo = out_ready_i & out_valid_o & (~aligned_is_compressed | out_addr_o[1]);
175:
176: for (genvar i = 0; i < (DEPTH - 1); i++) begin : g_fifo_next
177: // Calculate lowest free entry (write pointer)
178: if (i == 0) begin : g_ent0
179: assign lowest_free_entry[i] = ~valid_q[i];
180: end else begin : g_ent_others
181: assign lowest_free_entry[i] = ~valid_q[i] & valid_q[i-1];
182: end
183:
184: // An entry is set when an incoming request chooses the lowest available entry
185: assign valid_pushed[i] = (in_valid_i & lowest_free_entry[i]) |
186: valid_q[i];
187: // Popping the FIFO shifts all entries down
188: assign valid_popped[i] = pop_fifo ? valid_pushed[i+1] : valid_pushed[i];
189: // All entries are wiped out on a clear
190: assign valid_d[i] = valid_popped[i] & ~clear_i;
191:
192: // data flops are enabled if there is new data to shift into it, or
193: assign entry_en[i] = (valid_pushed[i+1] & pop_fifo) |
194: // a new request is incoming and this is the lowest free entry
195: (in_valid_i & lowest_free_entry[i] & ~pop_fifo);
196:
197: // take the next entry or the incoming data
198: assign rdata_d[i] = valid_q[i+1] ? rdata_q[i+1] : in_rdata_i;
199: assign err_d [i] = valid_q[i+1] ? err_q [i+1] : in_err_i;
200: end
201: // The top entry is similar but with simpler muxing
202: assign lowest_free_entry[DEPTH-1] = ~valid_q[DEPTH-1] & valid_q[DEPTH-2];
203: assign valid_pushed [DEPTH-1] = valid_q[DEPTH-1] | (in_valid_i & lowest_free_entry[DEPTH-1]);
204: assign valid_popped [DEPTH-1] = pop_fifo ? 1'b0 : valid_pushed[DEPTH-1];
205: assign valid_d [DEPTH-1] = valid_popped[DEPTH-1] & ~clear_i;
206: assign entry_en[DEPTH-1] = in_valid_i & lowest_free_entry[DEPTH-1];
207: assign rdata_d [DEPTH-1] = in_rdata_i;
208: assign err_d [DEPTH-1] = in_err_i;
209:
210: ////////////////////
211: // FIFO registers //
212: ////////////////////
213:
214: always_ff @(posedge clk_i or negedge rst_ni) begin
215: if (!rst_ni) begin
216: valid_q <= '0;
217: end else begin
218: valid_q <= valid_d;
219: end
220: end
221:
222: for (genvar i = 0; i < DEPTH; i++) begin : g_fifo_regs
223: always_ff @(posedge clk_i) begin
224: if (entry_en[i]) begin
225: rdata_q[i] <= rdata_d[i];
226: err_q[i] <= err_d[i];
227: end
228: end
229: end
230:
231: ////////////////
232: // Assertions //
233: ////////////////
234:
235: // Must not push and pop simultaneously when FIFO full.
236: `ASSERT(IbexFetchFifoPushPopFull,
237: (in_valid_i && pop_fifo) |-> (!valid_q[DEPTH-1] || clear_i))
238:
239: // Must not push to FIFO when full.
240: `ASSERT(IbexFetchFifoPushFull,
241: (in_valid_i) |-> (!valid_q[DEPTH-1] || clear_i))
242:
243: endmodule
244: