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

Subversion Repositories yifive

[/] [yifive/] [trunk/] [caravel_yifive/] [verilog/] [rtl/] [syntacore/] [scr1/] [src/] [core/] [pipeline/] [scr1_pipe_ifu.sv] - Blame information for rev 21

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 11 dinesha
/// Copyright by Syntacore LLC © 2016-2020. See LICENSE for details
2
/// @file       
3
/// @brief      Instruction Fetch Unit (IFU)
4
///
5
 
6
//------------------------------------------------------------------------------
7
 //
8
 // Functionality:
9
 // - Controls instruction fetching process:
10
 //   - Fetches instructions either from IMEM or from Program Buffer, supporting
11
 //     pending IMEM instructions handling
12
 //   - Handles new PC misalignment and constructs the correct instruction (supports
13
 //     RVI and RVC instructions)
14
 //   - Either stores instructions in the instruction queue or bypasses to the
15
 //     IDU if the corresponding option is used
16
 //   - Flushes instruction queue if requested
17
 //
18
 // Structure:
19
 // - Instruction queue
20
 // - IFU FSM
21
 // - IFU <-> IMEM i/f
22
 // - IFU <-> IDU i/f
23
 // - IFU <-> HDU i/f
24
 //
25
//------------------------------------------------------------------------------
26
 
27
`include "scr1_memif.svh"
28
`include "scr1_arch_description.svh"
29
`ifdef SCR1_DBG_EN
30
`include "scr1_hdu.svh"
31
`endif // SCR1_DBG_EN
32
 
33
module scr1_pipe_ifu
34
(
35
    // Control signals
36
    input   logic                                   rst_n,                      // IFU reset
37
    input   logic                                   clk,                        // IFU clock
38
    input   logic                                   pipe2ifu_stop_fetch_i,      // Stop instruction fetch
39
 
40
    // IFU <-> IMEM interface
41
    input   logic                                   imem2ifu_req_ack_i,         // Instruction memory request acknowledgement
42
    output  logic                                   ifu2imem_req_o,             // Instruction memory request
43 21 dinesha
    output  logic                                   ifu2imem_cmd_o,             // Instruction memory command (READ/WRITE)
44 11 dinesha
    output  logic [`SCR1_IMEM_AWIDTH-1:0]           ifu2imem_addr_o,            // Instruction memory address
45
    input   logic [`SCR1_IMEM_DWIDTH-1:0]           imem2ifu_rdata_i,           // Instruction memory read data
46 21 dinesha
    input   logic [1:0]                             imem2ifu_resp_i,            // Instruction memory response
47 11 dinesha
 
48
    // IFU <-> EXU New PC interface
49
    input   logic                                   exu2ifu_pc_new_req_i,       // New PC request (jumps, branches, traps etc)
50
    input   logic [`SCR1_XLEN-1:0]                  exu2ifu_pc_new_i,           // New PC
51
 
52
`ifdef SCR1_DBG_EN
53
    // IFU <-> HDU Program Buffer interface
54
    input   logic                                   hdu2ifu_pbuf_fetch_i,       // Fetch instructions provided by Program Buffer
55
    output  logic                                   ifu2hdu_pbuf_rdy_o,         // Program Buffer Instruction i/f ready
56
    input   logic                                   hdu2ifu_pbuf_vd_i,          // Program Buffer Instruction valid
57
    input   logic                                   hdu2ifu_pbuf_err_i,         // Program Buffer Instruction i/f error
58
    input   logic [SCR1_HDU_CORE_INSTR_WIDTH-1:0]   hdu2ifu_pbuf_instr_i,       // Program Buffer Instruction itself
59
`endif // SCR1_DBG_EN
60
 
61
`ifdef SCR1_CLKCTRL_EN
62
    output  logic                                   ifu2pipe_imem_txns_pnd_o,   // There are pending imem transactions
63
`endif // SCR1_CLKCTRL_EN
64
 
65
    // IFU <-> IDU interface
66
    input   logic                                   idu2ifu_rdy_i,              // IDU ready for new data
67
    output  logic [`SCR1_IMEM_DWIDTH-1:0]           ifu2idu_instr_o,            // IFU instruction
68
    output  logic                                   ifu2idu_imem_err_o,         // Instruction access fault exception
69
    output  logic                                   ifu2idu_err_rvi_hi_o,       // 1 - imem fault when trying to fetch second half of an unaligned RVI instruction
70
    output  logic                                   ifu2idu_vd_o                // IFU request
71
);
72
 
73
//------------------------------------------------------------------------------
74
// Local parameters declaration
75
//------------------------------------------------------------------------------
76
 
77
localparam SCR1_IFU_Q_SIZE_WORD     = 2;
78
localparam SCR1_IFU_Q_SIZE_HALF     = SCR1_IFU_Q_SIZE_WORD * 2;
79
localparam SCR1_TXN_CNT_W           = 3;
80
 
81
localparam SCR1_IFU_QUEUE_ADR_W     = $clog2(SCR1_IFU_Q_SIZE_HALF);
82
localparam SCR1_IFU_QUEUE_PTR_W     = SCR1_IFU_QUEUE_ADR_W + 1;
83
 
84
localparam SCR1_IFU_Q_FREE_H_W      = $clog2(SCR1_IFU_Q_SIZE_HALF + 1);
85
localparam SCR1_IFU_Q_FREE_W_W      = $clog2(SCR1_IFU_Q_SIZE_WORD + 1);
86
 
87
//------------------------------------------------------------------------------
88
// Local types declaration
89
//------------------------------------------------------------------------------
90
 
91 21 dinesha
//typedef enum logic {
92
parameter    SCR1_IFU_FSM_IDLE    = 1'b0;
93
parameter    SCR1_IFU_FSM_FETCH   = 1'b1;
94
//} type_scr1_ifu_fsm_e;
95 11 dinesha
 
96 21 dinesha
//typedef enum logic[1:0] {
97
parameter    SCR1_IFU_QUEUE_WR_NONE = 2'b00;  // No write to queue
98
parameter    SCR1_IFU_QUEUE_WR_FULL = 2'b01;  // Write 32 rdata bits to queue
99
parameter    SCR1_IFU_QUEUE_WR_HI   = 2'b10;  // Write 16 upper rdata bits to queue
100
//} type_scr1_ifu_queue_wr_e;
101 11 dinesha
 
102 21 dinesha
//typedef enum logic[1:0] {
103
parameter    SCR1_IFU_QUEUE_RD_NONE  = 2'b00; // No queue read
104
parameter    SCR1_IFU_QUEUE_RD_HWORD = 2'b01; // Read halfword
105
parameter    SCR1_IFU_QUEUE_RD_WORD  = 2'b10; // Read word
106
//} type_scr1_ifu_queue_rd_e;
107 11 dinesha
 
108
`ifdef SCR1_NO_DEC_STAGE
109
typedef enum logic[1:0] {
110
    SCR1_BYPASS_NONE,               // No bypass
111
    SCR1_BYPASS_RVC,                // Bypass RVC
112
    SCR1_BYPASS_RVI_RDATA_QUEUE,    // Bypass RVI, rdata+queue
113
    SCR1_BYPASS_RVI_RDATA           // Bypass RVI, rdata only
114
} type_scr1_bypass_e;
115
`endif // SCR1_NO_DEC_STAGE
116
 
117 21 dinesha
//typedef enum logic [2:0] {
118 11 dinesha
    // SCR1_IFU_INSTR__
119 21 dinesha
parameter     SCR1_IFU_INSTR_NONE           = 3'b000 ; // No valid instruction
120
parameter     SCR1_IFU_INSTR_RVI_HI_RVI_LO  = 3'b001 ; // Full RV32I instruction
121
parameter     SCR1_IFU_INSTR_RVC_RVC        = 3'b010 ;
122
parameter     SCR1_IFU_INSTR_RVI_LO_RVC     = 3'b011 ;
123
parameter     SCR1_IFU_INSTR_RVC_RVI_HI     = 3'b100 ;
124
parameter     SCR1_IFU_INSTR_RVI_LO_RVI_HI  = 3'b101 ;
125
parameter     SCR1_IFU_INSTR_RVC_NV         = 3'b110 ;  // Instruction after unaligned new_pc
126
parameter     SCR1_IFU_INSTR_RVI_LO_NV      = 3'b111 ;  // Instruction after unaligned new_pc
127
//} type_scr1_ifu_instr_e;
128 11 dinesha
 
129
//------------------------------------------------------------------------------
130
// Local signals declaration
131
//------------------------------------------------------------------------------
132
 
133
// Instruction queue signals
134
//------------------------------------------------------------------------------
135
 
136
// New PC unaligned flag register
137
logic                               new_pc_unaligned_ff;
138
logic                               new_pc_unaligned_next;
139
logic                               new_pc_unaligned_upd;
140
 
141
// IMEM instruction type decoder
142
logic                               instr_hi_is_rvi;
143
logic                               instr_lo_is_rvi;
144 21 dinesha
logic [2:0]                         instr_type;
145 11 dinesha
 
146
// Register to store if the previous IMEM instruction had low part of RVI instruction
147
// in its high part
148
logic                               instr_hi_rvi_lo_ff;
149
logic                               instr_hi_rvi_lo_next;
150
 
151
// Queue read/write size decoders
152 21 dinesha
logic [1:0]                         q_rd_size;
153 11 dinesha
logic                               q_rd_vd;
154
logic                               q_rd_none;
155
logic                               q_rd_hword;
156 21 dinesha
logic [1:0]                         q_wr_size;
157 11 dinesha
logic                               q_wr_none;
158
logic                               q_wr_full;
159
 
160
// Write/read pointer registers
161
logic [SCR1_IFU_QUEUE_PTR_W-1:0]    q_rptr;
162
logic [SCR1_IFU_QUEUE_PTR_W-1:0]    q_rptr_next;
163
logic                               q_rptr_upd;
164
logic [SCR1_IFU_QUEUE_PTR_W-1:0]    q_wptr;
165
logic [SCR1_IFU_QUEUE_PTR_W-1:0]    q_wptr_next;
166
logic                               q_wptr_upd;
167
 
168
// Instruction queue control signals
169
logic                               q_wr_en;
170
logic                               q_flush_req;
171
 
172
// Queue data registers
173
logic [`SCR1_IMEM_DWIDTH/2-1:0]     q_data  [SCR1_IFU_Q_SIZE_HALF];
174
logic [`SCR1_IMEM_DWIDTH/2-1:0]     q_data_head;
175
logic [`SCR1_IMEM_DWIDTH/2-1:0]     q_data_next;
176
 
177
// Queue error flags registers
178
logic                               q_err   [SCR1_IFU_Q_SIZE_HALF];
179
logic                               q_err_head;
180
logic                               q_err_next;
181
 
182
// Instruction queue status signals
183
logic                               q_is_empty;
184
logic                               q_has_free_slots;
185
logic                               q_has_1_ocpd_hw;
186
logic                               q_head_is_rvc;
187
logic                               q_head_is_rvi;
188
logic [SCR1_IFU_Q_FREE_H_W-1:0]     q_ocpd_h;
189
logic [SCR1_IFU_Q_FREE_H_W-1:0]     q_free_h_next;
190
logic [SCR1_IFU_Q_FREE_W_W-1:0]     q_free_w_next;
191
 
192
// IFU FSM signals
193
//------------------------------------------------------------------------------
194
 
195
// IFU FSM control signals
196
logic                               ifu_fetch_req;
197
logic                               ifu_stop_req;
198
 
199 21 dinesha
logic                               ifu_fsm_curr;
200
logic                               ifu_fsm_next;
201 11 dinesha
logic                               ifu_fsm_fetch;
202
 
203
// IMEM signals
204
//------------------------------------------------------------------------------
205
 
206
// IMEM response signals
207
logic                               imem_resp_ok;
208
logic                               imem_resp_er;
209
logic                               imem_resp_er_discard_pnd;
210
logic                               imem_resp_discard_req;
211
logic                               imem_resp_received;
212
logic                               imem_resp_vd;
213
logic                               imem_handshake_done;
214
 
215
logic [15:0]                        imem_rdata_lo;
216
logic [31:16]                       imem_rdata_hi;
217
 
218
// IMEM address signals
219
logic                               imem_addr_upd;
220
logic [`SCR1_XLEN-1:2]              imem_addr_ff;
221
logic [`SCR1_XLEN-1:2]              imem_addr_next;
222
 
223
// IMEM pending transactions counter
224
logic                               imem_pnd_txns_cnt_upd;
225
logic [SCR1_TXN_CNT_W-1:0]          imem_pnd_txns_cnt;
226
logic [SCR1_TXN_CNT_W-1:0]          imem_pnd_txns_cnt_next;
227
logic [SCR1_TXN_CNT_W-1:0]          imem_vd_pnd_txns_cnt;
228
logic                               imem_pnd_txns_q_full;
229
 
230
// IMEM responses discard counter
231
logic                               imem_resp_discard_cnt_upd;
232
logic [SCR1_TXN_CNT_W-1:0]          imem_resp_discard_cnt;
233
logic [SCR1_TXN_CNT_W-1:0]          imem_resp_discard_cnt_next;
234
 
235
`ifdef SCR1_NEW_PC_REG
236
logic                               new_pc_req_ff;
237
`endif // SCR1_NEW_PC_REG
238
 
239
// Instruction bypass signals
240
`ifdef SCR1_NO_DEC_STAGE
241
type_scr1_bypass_e                  instr_bypass_type;
242
logic                               instr_bypass_vd;
243
`endif // SCR1_NO_DEC_STAGE
244
 
245
//------------------------------------------------------------------------------
246
// Instruction queue
247
//------------------------------------------------------------------------------
248
//
249
 // Instruction queue consists of the following functional units:
250
 // - New PC unaligned flag register
251
 // - Instruction type decoder, including register to store if the previous
252
 //   IMEM instruction had low part of RVI instruction in its high part
253
 // - Read/write size decoders
254
 // - Read/write pointer registers
255
 // - Data and error flag registers
256
 // - Status logic
257
//
258
 
259
// New PC unaligned flag register
260
//------------------------------------------------------------------------------
261
 
262
assign new_pc_unaligned_upd = exu2ifu_pc_new_req_i | imem_resp_vd;
263
 
264
always_ff @(posedge clk, negedge rst_n) begin
265
    if (~rst_n) begin
266
        new_pc_unaligned_ff <= 1'b0;
267
    end else if (new_pc_unaligned_upd) begin
268
        new_pc_unaligned_ff <= new_pc_unaligned_next;
269
    end
270
end
271
 
272
assign new_pc_unaligned_next = exu2ifu_pc_new_req_i ? exu2ifu_pc_new_i[1]
273
                             : ~imem_resp_vd        ? new_pc_unaligned_ff
274
                                                    : 1'b0;
275
 
276
// Instruction type decoder
277
//------------------------------------------------------------------------------
278
 
279
assign instr_hi_is_rvi = &imem2ifu_rdata_i[17:16];
280
assign instr_lo_is_rvi = &imem2ifu_rdata_i[1:0];
281
 
282
always_comb begin
283
    instr_type = SCR1_IFU_INSTR_NONE;
284
 
285
    if (imem_resp_ok & ~imem_resp_discard_req) begin
286
        if (new_pc_unaligned_ff) begin
287
            instr_type = instr_hi_is_rvi ? SCR1_IFU_INSTR_RVI_LO_NV
288
                                         : SCR1_IFU_INSTR_RVC_NV;
289
        end else begin // ~new_pc_unaligned_ff
290
            if (instr_hi_rvi_lo_ff) begin
291
                instr_type = instr_hi_is_rvi ? SCR1_IFU_INSTR_RVI_LO_RVI_HI
292
                                             : SCR1_IFU_INSTR_RVC_RVI_HI;
293
            end else begin // SCR1_OTHER
294
                casez ({instr_hi_is_rvi, instr_lo_is_rvi})
295
                    2'b?1   : instr_type   = SCR1_IFU_INSTR_RVI_HI_RVI_LO;
296
                    2'b00   : instr_type   = SCR1_IFU_INSTR_RVC_RVC;
297
                    2'b10   : instr_type   = SCR1_IFU_INSTR_RVI_LO_RVC;
298
                endcase
299
            end
300
        end
301
    end
302
end
303
 
304
// Register to store if the previous IMEM instruction had low part of RVI
305
// instruction in its high part
306
//------------------------------------------------------------------------------
307
 
308
always_ff @(posedge clk, negedge rst_n) begin
309
    if (~rst_n) begin
310
        instr_hi_rvi_lo_ff <= 1'b0;
311
    end else begin
312
        if (exu2ifu_pc_new_req_i) begin
313
            instr_hi_rvi_lo_ff <= 1'b0;
314
        end else if (imem_resp_vd) begin
315
            instr_hi_rvi_lo_ff <= instr_hi_rvi_lo_next;
316
        end
317
    end
318
end
319
 
320
assign instr_hi_rvi_lo_next = (instr_type == SCR1_IFU_INSTR_RVI_LO_NV)
321
                            | (instr_type == SCR1_IFU_INSTR_RVI_LO_RVI_HI)
322
                            | (instr_type == SCR1_IFU_INSTR_RVI_LO_RVC);
323
 
324
// Queue write/read size decoders
325
//------------------------------------------------------------------------------
326
 
327
// Queue read size decoder
328
assign q_rd_vd    = ~q_is_empty & ifu2idu_vd_o & idu2ifu_rdy_i;
329
assign q_rd_hword = q_head_is_rvc | q_err_head
330
`ifdef SCR1_NO_DEC_STAGE
331
                  | (q_head_is_rvi & instr_bypass_vd)
332
`endif // SCR1_NO_DEC_STAGE
333
                  ;
334
assign q_rd_size  = ~q_rd_vd   ? SCR1_IFU_QUEUE_RD_NONE
335
                  : q_rd_hword ? SCR1_IFU_QUEUE_RD_HWORD
336
                               : SCR1_IFU_QUEUE_RD_WORD;
337
assign q_rd_none  = (q_rd_size == SCR1_IFU_QUEUE_RD_NONE);
338
 
339
// Queue write size decoder
340
always_comb begin
341
    q_wr_size = SCR1_IFU_QUEUE_WR_NONE;
342
    if (~imem_resp_discard_req) begin
343
        if (imem_resp_ok) begin
344
`ifdef SCR1_NO_DEC_STAGE
345
            case (instr_type)
346
                SCR1_IFU_INSTR_NONE         : q_wr_size = SCR1_IFU_QUEUE_WR_NONE;
347
                SCR1_IFU_INSTR_RVI_LO_NV    : q_wr_size = SCR1_IFU_QUEUE_WR_HI;
348
                SCR1_IFU_INSTR_RVC_NV       : q_wr_size = (instr_bypass_vd & idu2ifu_rdy_i)
349
                                                        ? SCR1_IFU_QUEUE_WR_NONE
350
                                                        : SCR1_IFU_QUEUE_WR_HI;
351
                SCR1_IFU_INSTR_RVI_HI_RVI_LO: q_wr_size = (instr_bypass_vd & idu2ifu_rdy_i)
352
                                                        ? SCR1_IFU_QUEUE_WR_NONE
353
                                                        : SCR1_IFU_QUEUE_WR_FULL;
354
                SCR1_IFU_INSTR_RVC_RVC,
355
                SCR1_IFU_INSTR_RVI_LO_RVC,
356
                SCR1_IFU_INSTR_RVC_RVI_HI,
357
                SCR1_IFU_INSTR_RVI_LO_RVI_HI: q_wr_size = (instr_bypass_vd & idu2ifu_rdy_i)
358
                                                        ? SCR1_IFU_QUEUE_WR_HI
359
                                                        : SCR1_IFU_QUEUE_WR_FULL;
360
            endcase // instr_type
361
`else // SCR1_NO_DEC_STAGE
362
            case (instr_type)
363
                SCR1_IFU_INSTR_NONE         : q_wr_size = SCR1_IFU_QUEUE_WR_NONE;
364
                SCR1_IFU_INSTR_RVC_NV,
365
                SCR1_IFU_INSTR_RVI_LO_NV    : q_wr_size = SCR1_IFU_QUEUE_WR_HI;
366
                default                     : q_wr_size = SCR1_IFU_QUEUE_WR_FULL;
367
            endcase // instr_type
368
`endif // SCR1_NO_DEC_STAGE
369
        end else if (imem_resp_er) begin
370
            q_wr_size = SCR1_IFU_QUEUE_WR_FULL;
371
        end // imem_resp_er
372
    end // ~imem_resp_discard_req
373
end
374
 
375
assign q_wr_none   = (q_wr_size == SCR1_IFU_QUEUE_WR_NONE);
376
assign q_wr_full   = (q_wr_size == SCR1_IFU_QUEUE_WR_FULL);
377
 
378
// Write/read pointer registers
379
//------------------------------------------------------------------------------
380
 
381
assign q_flush_req = exu2ifu_pc_new_req_i | pipe2ifu_stop_fetch_i;
382
 
383
// Queue write pointer register
384
assign q_wptr_upd  = q_flush_req | ~q_wr_none;
385
 
386
always_ff @(posedge clk, negedge rst_n) begin
387
    if (~rst_n) begin
388
        q_wptr <= '0;
389
    end else if (q_wptr_upd) begin
390
        q_wptr <= q_wptr_next;
391
    end
392
end
393
 
394
assign q_wptr_next = q_flush_req ? '0
395
                   : ~q_wr_none  ? q_wptr + (q_wr_full ? 2'd2 : 1'b1)
396
                                 : q_wptr;
397
 
398
// Queue read pointer register
399
assign q_rptr_upd  = q_flush_req | ~q_rd_none;
400
 
401
always_ff @(posedge clk, negedge rst_n) begin
402
    if (~rst_n) begin
403
        q_rptr <= '0;
404
    end else if (q_rptr_upd) begin
405
        q_rptr <= q_rptr_next;
406
    end
407
end
408
 
409
assign q_rptr_next = q_flush_req ? '0
410
                   : ~q_rd_none  ? q_rptr + (q_rd_hword ? 1'b1 : 2'd2)
411
                                 : q_rptr;
412
 
413
// Queue data and error flag registers
414
//------------------------------------------------------------------------------
415
 
416
assign imem_rdata_hi = imem2ifu_rdata_i[31:16];
417
assign imem_rdata_lo = imem2ifu_rdata_i[15:0];
418
 
419
assign q_wr_en = imem_resp_vd & ~q_flush_req;
420
 
421
always_ff @(posedge clk, negedge rst_n) begin
422
    if (~rst_n) begin
423
     `ifdef SCR1_MPRF_RST_EN // Two dimensional array init not allowed in YOSYS - cp.13
424
        q_data  <= '{SCR1_IFU_Q_SIZE_HALF{'0}};
425
        q_err   <= '{SCR1_IFU_Q_SIZE_HALF{1'b0}};
426
     `endif
427
    end else if (q_wr_en) begin
428
        case (q_wr_size)
429
            SCR1_IFU_QUEUE_WR_HI    : begin
430
                q_data[SCR1_IFU_QUEUE_ADR_W'(q_wptr)]         <= imem_rdata_hi;
431
                q_err [SCR1_IFU_QUEUE_ADR_W'(q_wptr)]         <= imem_resp_er;
432
            end
433
            SCR1_IFU_QUEUE_WR_FULL  : begin
434
                q_data[SCR1_IFU_QUEUE_ADR_W'(q_wptr)]         <= imem_rdata_lo;
435
                q_err [SCR1_IFU_QUEUE_ADR_W'(q_wptr)]         <= imem_resp_er;
436
                q_data[SCR1_IFU_QUEUE_ADR_W'(q_wptr + 1'b1)]  <= imem_rdata_hi;
437
                q_err [SCR1_IFU_QUEUE_ADR_W'(q_wptr + 1'b1)]  <= imem_resp_er;
438
            end
439
        endcase
440
    end
441
end
442
 
443
assign q_data_head = q_data [SCR1_IFU_QUEUE_ADR_W'(q_rptr)];
444
assign q_data_next = q_data [SCR1_IFU_QUEUE_ADR_W'(q_rptr + 1'b1)];
445
assign q_err_head  = q_err  [SCR1_IFU_QUEUE_ADR_W'(q_rptr)];
446
assign q_err_next  = q_err  [SCR1_IFU_QUEUE_ADR_W'(q_rptr + 1'b1)];
447
 
448
// Queue status logic
449
//------------------------------------------------------------------------------
450
 
451
assign q_ocpd_h         = SCR1_IFU_Q_FREE_H_W'(q_wptr - q_rptr);
452
assign q_free_h_next    = SCR1_IFU_Q_FREE_H_W'(SCR1_IFU_Q_SIZE_HALF - (q_wptr - q_rptr_next));
453
assign q_free_w_next    = SCR1_IFU_Q_FREE_W_W'(q_free_h_next >> 1'b1);
454
 
455
assign q_is_empty       = (q_rptr == q_wptr);
456
assign q_has_free_slots = (SCR1_TXN_CNT_W'(q_free_w_next) > imem_vd_pnd_txns_cnt);
457
assign q_has_1_ocpd_hw  = (q_ocpd_h == SCR1_IFU_Q_FREE_H_W'(1));
458
 
459
assign q_head_is_rvi    = &(q_data_head[1:0]);
460
assign q_head_is_rvc    = ~q_head_is_rvi;
461
 
462
//------------------------------------------------------------------------------
463
// IFU FSM
464
//------------------------------------------------------------------------------
465
 
466
// IFU FSM control signals
467
assign ifu_fetch_req = exu2ifu_pc_new_req_i & ~pipe2ifu_stop_fetch_i;
468
assign ifu_stop_req  = pipe2ifu_stop_fetch_i
469
                     | (imem_resp_er_discard_pnd & ~exu2ifu_pc_new_req_i);
470
 
471
always_ff @(posedge clk, negedge rst_n) begin
472
    if (~rst_n) begin
473
        ifu_fsm_curr <= SCR1_IFU_FSM_IDLE;
474
    end else begin
475
        ifu_fsm_curr <= ifu_fsm_next;
476
    end
477
end
478
 
479
always_comb begin
480
    case (ifu_fsm_curr)
481
        SCR1_IFU_FSM_IDLE   : begin
482
            ifu_fsm_next = ifu_fetch_req ? SCR1_IFU_FSM_FETCH
483
                                         : SCR1_IFU_FSM_IDLE;
484
        end
485
        SCR1_IFU_FSM_FETCH  : begin
486
            ifu_fsm_next = ifu_stop_req  ? SCR1_IFU_FSM_IDLE
487
                                         : SCR1_IFU_FSM_FETCH;
488
        end
489
    endcase
490
end
491
 
492
assign ifu_fsm_fetch = (ifu_fsm_curr == SCR1_IFU_FSM_FETCH);
493
 
494
//------------------------------------------------------------------------------
495
// IFU <-> IMEM interface
496
//------------------------------------------------------------------------------
497
//
498
 // IFU <-> IMEM interface consists of the following functional units:
499
 // - IMEM response logic
500
 // - IMEM address register
501
 // - Pending IMEM transactions counter
502
 // - IMEM discard responses counter
503
 // - IFU <-> IMEM interface output signals
504
//
505
 
506
// IMEM response logic
507
//------------------------------------------------------------------------------
508
 
509
assign imem_resp_er             = (imem2ifu_resp_i == SCR1_MEM_RESP_RDY_ER);
510
assign imem_resp_ok             = (imem2ifu_resp_i == SCR1_MEM_RESP_RDY_OK);
511
assign imem_resp_received       = imem_resp_ok | imem_resp_er;
512
assign imem_resp_vd             = imem_resp_received & ~imem_resp_discard_req;
513
assign imem_resp_er_discard_pnd = imem_resp_er & ~imem_resp_discard_req;
514
 
515
assign imem_handshake_done = ifu2imem_req_o & imem2ifu_req_ack_i;
516
 
517
// IMEM address register
518
//------------------------------------------------------------------------------
519
 
520
assign imem_addr_upd = imem_handshake_done | exu2ifu_pc_new_req_i;
521
 
522
always_ff @(posedge clk, negedge rst_n) begin
523
    if (~rst_n) begin
524
        imem_addr_ff <= '0;
525
    end else if (imem_addr_upd) begin
526
        imem_addr_ff <= imem_addr_next;
527
    end
528
end
529
 
530
`ifndef SCR1_NEW_PC_REG
531
assign imem_addr_next = exu2ifu_pc_new_req_i ? exu2ifu_pc_new_i[`SCR1_XLEN-1:2]                 + imem_handshake_done
532
                      : &imem_addr_ff[5:2]   ? imem_addr_ff                                     + imem_handshake_done
533
                                             : {imem_addr_ff[`SCR1_XLEN-1:6], imem_addr_ff[5:2] + imem_handshake_done};
534
`else // SCR1_NEW_PC_REG
535
assign imem_addr_next = exu2ifu_pc_new_req_i ? exu2ifu_pc_new_i[`SCR1_XLEN-1:2]
536
                      : &imem_addr_ff[5:2]   ? imem_addr_ff                                     + imem_handshake_done
537
                                             : {imem_addr_ff[`SCR1_XLEN-1:6], imem_addr_ff[5:2] + imem_handshake_done};
538
`endif // SCR1_NEW_PC_REG
539
 
540
// Pending IMEM transactions counter
541
//------------------------------------------------------------------------------
542
// Pending IMEM transactions occur if IFU request has been acknowledged, but
543
// response comes in the next cycle or later
544
 
545
assign imem_pnd_txns_cnt_upd  = imem_handshake_done ^ imem_resp_received;
546
 
547
always_ff @(posedge clk, negedge rst_n) begin
548
    if (~rst_n) begin
549
        imem_pnd_txns_cnt <= '0;
550
    end else if (imem_pnd_txns_cnt_upd) begin
551
        imem_pnd_txns_cnt <= imem_pnd_txns_cnt_next;
552
    end
553
end
554
 
555
assign imem_pnd_txns_cnt_next = imem_pnd_txns_cnt + (imem_handshake_done - imem_resp_received);
556
assign imem_pnd_txns_q_full   = &imem_pnd_txns_cnt;
557
 
558
// IMEM discard responses counter
559
//------------------------------------------------------------------------------
560
// IMEM instructions should be discarded in the following 2 cases:
561
// 1. New PC is requested by jump, branch, mret or other instruction
562
// 2. IMEM response was erroneous and not discarded
563
//
564
// In both cases the number of instructions to be discarded equals to the number
565
// of pending instructions.
566
// In the 1st case we don't need all the instructions that haven't been fetched
567
// yet, since the PC has changed.
568
// In the 2nd case, since the IMEM responce was erroneous there is no guarantee
569
// that subsequent IMEM instructions would be valid.
570
 
571
assign imem_resp_discard_cnt_upd = exu2ifu_pc_new_req_i | imem_resp_er
572
                                 | (imem_resp_ok & imem_resp_discard_req);
573
 
574
always_ff @(posedge clk, negedge rst_n) begin
575
    if (~rst_n) begin
576
        imem_resp_discard_cnt <= '0;
577
    end else if (imem_resp_discard_cnt_upd) begin
578
        imem_resp_discard_cnt <= imem_resp_discard_cnt_next;
579
    end
580
end
581
 
582
`ifndef SCR1_NEW_PC_REG
583
assign imem_resp_discard_cnt_next = exu2ifu_pc_new_req_i     ? imem_pnd_txns_cnt_next - imem_handshake_done
584
                                  : imem_resp_er_discard_pnd ? imem_pnd_txns_cnt_next
585
                                                             : imem_resp_discard_cnt - 1'b1;
586
`else // SCR1_NEW_PC_REG
587
assign imem_resp_discard_cnt_next = exu2ifu_pc_new_req_i | imem_resp_er_discard_pnd
588
                                  ? imem_pnd_txns_cnt_next
589
                                  : imem_resp_discard_cnt - 1'b1;
590
`endif // SCR1_NEW_PC_REG
591
 
592
assign imem_vd_pnd_txns_cnt  = imem_pnd_txns_cnt - imem_resp_discard_cnt;
593
assign imem_resp_discard_req = |imem_resp_discard_cnt;
594
 
595
// IFU <-> IMEM interface output signals
596
//------------------------------------------------------------------------------
597
 
598
`ifndef SCR1_NEW_PC_REG
599
assign ifu2imem_req_o  = (exu2ifu_pc_new_req_i & ~imem_pnd_txns_q_full & ~pipe2ifu_stop_fetch_i)
600
                       | (ifu_fsm_fetch        & ~imem_pnd_txns_q_full & q_has_free_slots);
601
assign ifu2imem_addr_o = exu2ifu_pc_new_req_i
602
                       ? {exu2ifu_pc_new_i[`SCR1_XLEN-1:2], 2'b00}
603
                       : {imem_addr_ff, 2'b00};
604
`else // SCR1_NEW_PC_REG
605
assign ifu2imem_req_o  = ifu_fsm_fetch & ~imem_pnd_txns_q_full & q_has_free_slots;
606
assign ifu2imem_addr_o = {imem_addr_ff, 2'b00};
607
`endif // SCR1_NEW_PC_REG
608
 
609
assign ifu2imem_cmd_o  = SCR1_MEM_CMD_RD;
610
 
611
`ifdef SCR1_CLKCTRL_EN
612
assign ifu2pipe_imem_txns_pnd_o = |imem_pnd_txns_cnt;
613
`endif // SCR1_CLKCTRL_EN
614
 
615
//------------------------------------------------------------------------------
616
// IFU <-> IDU interface
617
//------------------------------------------------------------------------------
618
//
619
 // IFU <-> IDU interface consists of the following functional units:
620
 // - Instruction bypass type decoder
621
 // - IFU <-> IDU status signals
622
 // - Output instruction multiplexer
623
//
624
 
625
`ifdef SCR1_NO_DEC_STAGE
626
 
627
// Instruction bypass type decoder
628
//------------------------------------------------------------------------------
629
 
630
assign instr_bypass_vd  = (instr_bypass_type != SCR1_BYPASS_NONE);
631
 
632
always_comb begin
633
    instr_bypass_type    = SCR1_BYPASS_NONE;
634
 
635
    if (imem_resp_vd) begin
636
        if (q_is_empty) begin
637
            case (instr_type)
638
                SCR1_IFU_INSTR_RVC_NV,
639
                SCR1_IFU_INSTR_RVC_RVC,
640
                SCR1_IFU_INSTR_RVI_LO_RVC       : begin
641
                    instr_bypass_type = SCR1_BYPASS_RVC;
642
                end
643
                SCR1_IFU_INSTR_RVI_HI_RVI_LO    : begin
644
                    instr_bypass_type = SCR1_BYPASS_RVI_RDATA;
645
                end
646
                default : begin end
647
            endcase // instr_type
648
        end else if (q_has_1_ocpd_hw & q_head_is_rvi) begin
649
            if (instr_hi_rvi_lo_ff) begin
650
                instr_bypass_type = SCR1_BYPASS_RVI_RDATA_QUEUE;
651
            end
652
        end
653
    end // imem_resp_vd
654
end
655
 
656
// IFU <-> IDU interface status signals
657
//------------------------------------------------------------------------------
658
 
659
always_comb begin
660
    ifu2idu_vd_o         = 1'b0;
661
    ifu2idu_imem_err_o   = 1'b0;
662
    ifu2idu_err_rvi_hi_o = 1'b0;
663
 
664
    if (ifu_fsm_fetch | ~q_is_empty) begin
665
        if (instr_bypass_vd) begin
666
            ifu2idu_vd_o          = 1'b1;
667
            ifu2idu_imem_err_o    = (instr_bypass_type == SCR1_BYPASS_RVI_RDATA_QUEUE)
668
                                  ? (imem_resp_er | q_err_head)
669
                                  : imem_resp_er;
670
            ifu2idu_err_rvi_hi_o  = (instr_bypass_type == SCR1_BYPASS_RVI_RDATA_QUEUE) & imem_resp_er;
671
        end else if (~q_is_empty) begin
672
            if (q_has_1_ocpd_hw) begin
673
                ifu2idu_vd_o         = q_head_is_rvc | q_err_head;
674
                ifu2idu_imem_err_o   = q_err_head;
675
                ifu2idu_err_rvi_hi_o = ~q_err_head & q_head_is_rvi & q_err_next;
676
            end else begin
677
                ifu2idu_vd_o         = 1'b1;
678
                ifu2idu_imem_err_o   = q_err_head ? 1'b1 : (q_head_is_rvi & q_err_next);
679
            end
680
        end // ~q_is_empty
681
    end
682
`ifdef SCR1_DBG_EN
683
    if (hdu2ifu_pbuf_fetch_i) begin
684
        ifu2idu_vd_o          = hdu2ifu_pbuf_vd_i;
685
        ifu2idu_imem_err_o    = hdu2ifu_pbuf_err_i;
686
    end
687
`endif // SCR1_DBG_EN
688
end
689
 
690
// Output instruction multiplexer
691
//------------------------------------------------------------------------------
692
 
693
always_comb begin
694
    case (instr_bypass_type)
695
        SCR1_BYPASS_RVC            : begin
696
            ifu2idu_instr_o = `SCR1_IMEM_DWIDTH'(new_pc_unaligned_ff ? imem_rdata_hi
697
                                                                     : imem_rdata_lo);
698
        end
699
        SCR1_BYPASS_RVI_RDATA      : begin
700
            ifu2idu_instr_o = imem2ifu_rdata_i;
701
        end
702
        SCR1_BYPASS_RVI_RDATA_QUEUE: begin
703
            ifu2idu_instr_o = {imem_rdata_lo, q_data_head};
704
        end
705
        default                    : begin
706
            ifu2idu_instr_o = `SCR1_IMEM_DWIDTH'(q_head_is_rvc ? q_data_head
707
                                                               : {q_data_next, q_data_head});
708
        end
709
    endcase // instr_bypass_type
710
`ifdef SCR1_DBG_EN
711
    if (hdu2ifu_pbuf_fetch_i) begin
712
        ifu2idu_instr_o = `SCR1_IMEM_DWIDTH'({'0, hdu2ifu_pbuf_instr_i});
713
    end
714
`endif // SCR1_DBG_EN
715
end
716
 
717
`else   // SCR1_NO_DEC_STAGE
718
 
719
// IFU <-> IDU interface status signals
720
//------------------------------------------------------------------------------
721
 
722
always_comb begin
723
    ifu2idu_vd_o          = 1'b0;
724
    ifu2idu_imem_err_o    = 1'b0;
725
    ifu2idu_err_rvi_hi_o  = 1'b0;
726
    if (~q_is_empty) begin
727
        if (q_has_1_ocpd_hw) begin
728
            ifu2idu_vd_o          = q_head_is_rvc | q_err_head;
729
            ifu2idu_imem_err_o    = q_err_head;
730
        end else begin
731
            ifu2idu_vd_o          = 1'b1;
732
            ifu2idu_imem_err_o    = q_err_head ? 1'b1 : (q_head_is_rvi & q_err_next);
733
            ifu2idu_err_rvi_hi_o  = ~q_err_head & q_head_is_rvi & q_err_next;
734
        end
735
    end // ~q_is_empty
736
`ifdef SCR1_DBG_EN
737
    if (hdu2ifu_pbuf_fetch_i) begin
738
        ifu2idu_vd_o          = hdu2ifu_pbuf_vd_i;
739
        ifu2idu_imem_err_o    = hdu2ifu_pbuf_err_i;
740
    end
741
`endif // SCR1_DBG_EN
742
end
743
 
744
// Output instruction multiplexer
745
//------------------------------------------------------------------------------
746
 
747
always_comb begin
748
    ifu2idu_instr_o = q_head_is_rvc ? `SCR1_IMEM_DWIDTH'(q_data_head)
749
                                    : {q_data_next, q_data_head};
750
`ifdef SCR1_DBG_EN
751
    if (hdu2ifu_pbuf_fetch_i) begin
752
        ifu2idu_instr_o = `SCR1_IMEM_DWIDTH'({'0, hdu2ifu_pbuf_instr_i});
753
    end
754
`endif // SCR1_DBG_EN
755
end
756
 
757
`endif  // SCR1_NO_DEC_STAGE
758
 
759
`ifdef SCR1_DBG_EN
760
assign ifu2hdu_pbuf_rdy_o = idu2ifu_rdy_i;
761
`endif // SCR1_DBG_EN
762
 
763
`ifdef SCR1_TRGT_SIMULATION
764
 
765
//------------------------------------------------------------------------------
766
// Assertions
767
//------------------------------------------------------------------------------
768
 
769
// X checks
770
 
771
SCR1_SVA_IFU_XCHECK : assert property (
772
    @(negedge clk) disable iff (~rst_n)
773
    !$isunknown({imem2ifu_req_ack_i, idu2ifu_rdy_i, exu2ifu_pc_new_req_i})
774
    ) else $error("IFU Error: unknown values");
775
 
776
SCR1_SVA_IFU_XCHECK_REQ : assert property (
777
    @(negedge clk) disable iff (~rst_n)
778
    ifu2imem_req_o |-> !$isunknown({ifu2imem_addr_o, ifu2imem_cmd_o})
779
    ) else $error("IFU Error: unknown {ifu2imem_addr_o, ifu2imem_cmd_o}");
780
 
781
// Behavior checks
782
`ifndef VERILATOR
783
SCR1_SVA_IFU_DRC_UNDERFLOW : assert property (
784
    @(negedge clk) disable iff (~rst_n)
785
    ~imem_resp_discard_req |=> ~(imem_resp_discard_cnt == SCR1_TXN_CNT_W'('1))
786
    ) else $error("IFU Error: imem_resp_discard_cnt underflow");
787
`endif // VERILATOR
788
SCR1_SVA_IFU_DRC_RANGE : assert property (
789
    @(negedge clk) disable iff (~rst_n)
790
    (imem_resp_discard_cnt >= 0) & (imem_resp_discard_cnt <= imem_pnd_txns_cnt)
791
    ) else $error("IFU Error: imem_resp_discard_cnt out of range");
792
 
793
SCR1_SVA_IFU_QUEUE_OVF : assert property (
794
    @(negedge clk) disable iff (~rst_n)
795
    (q_ocpd_h >= SCR1_IFU_Q_FREE_H_W'(SCR1_IFU_Q_SIZE_HALF-1)) |->
796
    ((q_ocpd_h == SCR1_IFU_Q_FREE_H_W'(SCR1_IFU_Q_SIZE_HALF-1)) ? (q_wr_size != SCR1_IFU_QUEUE_WR_FULL)
797
                                                                : (q_wr_size == SCR1_IFU_QUEUE_WR_NONE))
798
    ) else $error("IFU Error: queue overflow");
799
 
800
`ifndef VERILATOR
801
SCR1_SVA_IFU_IMEM_ERR_BEH : assert property (
802
    @(negedge clk) disable iff (~rst_n)
803
    (imem_resp_er & ~imem_resp_discard_req & ~exu2ifu_pc_new_req_i) |=>
804
    (ifu_fsm_curr == SCR1_IFU_FSM_IDLE) & (imem_resp_discard_cnt == imem_pnd_txns_cnt)
805
    ) else $error("IFU Error: incorrect behavior after memory error");
806
 
807
SCR1_SVA_IFU_NEW_PC_REQ_BEH : assert property (
808
    @(negedge clk) disable iff (~rst_n)
809
    exu2ifu_pc_new_req_i |=> q_is_empty
810
    ) else $error("IFU Error: incorrect behavior after exu2ifu_pc_new_req_i");
811
`endif // VERILATOR
812
SCR1_SVA_IFU_IMEM_ADDR_ALIGNED : assert property (
813
    @(negedge clk) disable iff (~rst_n)
814
    ifu2imem_req_o |-> ~|ifu2imem_addr_o[1:0]
815
    ) else $error("IFU Error: unaligned IMEM access");
816
 
817
`ifndef VERILATOR
818
SCR1_SVA_IFU_STOP_FETCH : assert property (
819
    @(negedge clk) disable iff (~rst_n)
820
    pipe2ifu_stop_fetch_i |=> (ifu_fsm_curr == SCR1_IFU_FSM_IDLE)
821
    ) else $error("IFU Error: fetch not stopped");
822
`endif // VERILATOR
823
SCR1_SVA_IFU_IMEM_FAULT_RVI_HI : assert property (
824
    @(negedge clk) disable iff (~rst_n)
825
    ifu2idu_err_rvi_hi_o |-> ifu2idu_imem_err_o
826
    ) else $error("IFU Error: ifu2idu_imem_err_o == 0");
827
 
828
`endif // SCR1_TRGT_SIMULATION
829
 
830
endmodule : scr1_pipe_ifu

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.