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