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

Subversion Repositories yifive

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

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      Integrated Programmable Interrupt Controller (IPIC)
4
///
5
 
6
//------------------------------------------------------------------------------
7
 //
8
 // Functionality:
9
 // - Synchronizes IRQ lines (optional)
10
 // - Detects level and edge (with optional lines inversion) of IRQ lines
11
 // - Setups interrupts handling (mode, inversion, enable)
12
 // - Provides information about pending interrupts and interrupts currently in
13
 //   service
14
 // - Generates interrupt request to CSR
15
 //
16
 // Structure:
17
 // - IRQ lines handling (synchronization, level and edge detection) logic
18
 // - IPIC registers:
19
 //   - CISV
20
 //   - CICSR
21
 //   - EOI
22
 //   - SOI
23
 //   - IDX
24
 //   - IPR
25
 //   - ISVR
26
 //   - IER
27
 //   - IMR
28
 //   - IINVR
29
 //   - ICSR
30
 // - Priority interrupt generation logic
31
 //
32
//------------------------------------------------------------------------------
33
 
34
`include "scr1_arch_description.svh"
35
 
36
`ifdef SCR1_IPIC_EN
37
 
38
`include "scr1_ipic.svh"
39
 
40
module scr1_ipic
41
(
42
    // Common
43
    input   logic                                   rst_n,                  // IPIC reset
44
    input   logic                                   clk,                    // IPIC clock
45
 
46
    // External Interrupt lines
47
    input   logic [SCR1_IRQ_LINES_NUM-1:0]          soc2ipic_irq_lines_i,   // External IRQ lines
48
 
49
    // CSR <-> IPIC interface
50
    input   logic                                   csr2ipic_r_req_i,       // IPIC read request
51
    input   logic                                   csr2ipic_w_req_i,       // IPIC write request
52
    input   logic [2:0]                             csr2ipic_addr_i,        // IPIC address
53
    input   logic [`SCR1_XLEN-1:0]                  csr2ipic_wdata_i,       // IPIC write data
54
    output  logic [`SCR1_XLEN-1:0]                  ipic2csr_rdata_o,       // IPIC read data
55
    output  logic                                   ipic2csr_irq_m_req_o    // IRQ request from IPIC
56
);
57
 
58
//-------------------------------------------------------------------------------
59
// Local types declaration
60
//-------------------------------------------------------------------------------
61
typedef struct packed { // cp.6
62
    logic                                   vd;
63
    logic                                   idx;
64
} type_scr1_search_one_2_s;
65
 
66
typedef struct packed { // cp.6
67
    logic                                   vd;
68
    logic   [SCR1_IRQ_VECT_WIDTH-1:0]       idx;
69
} type_scr1_search_one_16_s;
70
 
71
typedef struct packed {
72
    logic                                   ip;
73
    logic                                   ie;
74
    logic                                   im;
75
    logic                                   inv;
76
    logic                                   is;
77
    logic   [SCR1_IRQ_LINES_WIDTH-1:0]      line;
78
} type_scr1_icsr_m_s;
79
 
80
typedef struct packed {
81
    logic                                   ip;
82
    logic                                   ie;
83
} type_scr1_cicsr_s;
84
 
85
//-------------------------------------------------------------------------------
86
// Local functions declaration
87
//-------------------------------------------------------------------------------
88
 
89
function automatic type_scr1_search_one_2_s scr1_search_one_2(
90
    input   logic   [1:0] din
91
);
92
    type_scr1_search_one_2_s tmp;
93
begin
94
    tmp.vd  = |din;
95
    tmp.idx = ~din[0];
96
    scr1_search_one_2 =  tmp;
97
end
98
endfunction
99
 
100
function automatic type_scr1_search_one_16_s scr1_search_one_16(
101
    input   logic [15:0]    din
102
);
103
    logic [7:0]         stage1_vd;
104
    logic [3:0]         stage2_vd;
105
    logic [1:0]         stage3_vd;
106
 
107
    logic               stage1_idx [7:0];
108
    logic [1:0]         stage2_idx [3:0];
109
    logic [2:0]         stage3_idx [1:0];
110
    type_scr1_search_one_16_s result;
111
    type_scr1_search_one_2_s tmp;
112
    integer i; // cp.17
113
begin
114
    // Stage 1
115
    for (i=0; i<8; i=i+1) begin
116
        tmp = scr1_search_one_2(din[(i+1)*2-1-:2]);
117
        stage1_vd[i]  = tmp.vd;
118
        stage1_idx[i] = tmp.idx;
119
    end
120
 
121
    // Stage 2
122
    for (i=0; i<4; i=i+1) begin
123
        tmp = scr1_search_one_2(stage1_vd[(i+1)*2-1-:2]);
124
        stage2_vd[i]  = tmp.vd;
125
        stage2_idx[i] = (~tmp.idx) ? {tmp.idx, stage1_idx[2*i]} : {tmp.idx, stage1_idx[2*i+1]};
126
    end
127
 
128
    // Stage 3
129
    for (i=0; i<2; i=i+1) begin
130
        tmp = scr1_search_one_2(stage2_vd[(i+1)*2-1-:2]);
131
        stage3_vd[i]  = tmp.vd;
132
        stage3_idx[i] = (~tmp.idx) ? {tmp.idx, stage2_idx[2*i]} : {tmp.idx, stage2_idx[2*i+1]};
133
    end
134
 
135
    // Stage 4
136
    result.vd = |stage3_vd;
137
    result.idx = (stage3_vd[0]) ? {1'b0, stage3_idx[0]} : {1'b1, stage3_idx[1]};
138
 
139
    scr1_search_one_16 = result;
140
end
141
endfunction
142
 
143
//------------------------------------------------------------------------------
144
// Local signals declaration
145
//------------------------------------------------------------------------------
146
 
147
// IRQ lines handling signals
148
//------------------------------------------------------------------------------
149
 
150
logic [SCR1_IRQ_VECT_NUM-1:0]           irq_lines;              // Internal IRQ lines
151
`ifdef SCR1_IPIC_SYNC_EN
152
logic [SCR1_IRQ_VECT_NUM-1:0]           irq_lines_sync;
153
`endif // SCR1_IPIC_SYNC_EN
154
logic [SCR1_IRQ_VECT_NUM-1:0]           irq_lines_dly;          // Internal IRQ lines delayed for 1 cycle
155
logic [SCR1_IRQ_VECT_NUM-1:0]           irq_edge_detected;      // IRQ lines edge detected flags
156
logic [SCR1_IRQ_VECT_NUM-1:0]           irq_lvl;                // IRQ lines level
157
 
158
// IPIC registers
159
//------------------------------------------------------------------------------
160
 
161
// CISV register
162
logic                                   ipic_cisv_upd;          // Current Interrupt Vecotr in Service register update
163
logic [SCR1_IRQ_VECT_WIDTH-1:0]         ipic_cisv_ff;           // Current Interrupt Vector in Service register
164
logic [SCR1_IRQ_VECT_WIDTH-1:0]         ipic_cisv_next;         // Current Interrupt Vector in Service register next value
165
 
166
// CICS register (CICSR)
167
logic                                   cicsr_wr_req;           // Write request to Current Interrupt Control Status register
168
type_scr1_cicsr_s                       ipic_cicsr;             // Current Interrupt Control Status register
169
 
170
// EOI register
171
logic                                   eoi_wr_req;             // Write request to End of Interrupt register
172
logic                                   ipic_eoi_req;           // Request to end the interrupt that is currently in service
173
 
174
// SOI register
175
logic                                   soi_wr_req;             // Write request to Start of Interrupt register
176
logic                                   ipic_soi_req;           // Request to start the interrupt
177
 
178
// IDX register (IDXR)
179
logic                                   idxr_wr_req;            // Write request to Index register
180
logic [SCR1_IRQ_IDX_WIDTH-1:0]          ipic_idxr_ff;           // Index register
181
 
182
// IP register (IPR)
183
logic                                   ipic_ipr_upd;           // Interrupt pending register update
184
logic [SCR1_IRQ_VECT_NUM-1:0]           ipic_ipr_ff;            // Interrupt pending register
185
logic [SCR1_IRQ_VECT_NUM-1:0]           ipic_ipr_next;          // Interrupt pending register next value
186
logic [SCR1_IRQ_VECT_NUM-1:0]           ipic_ipr_clr_cond;      // Interrupt pending clear condition
187
logic [SCR1_IRQ_VECT_NUM-1:0]           ipic_ipr_clr_req;       // Interrupt pending clear request
188
logic [SCR1_IRQ_VECT_NUM-1:0]           ipic_ipr_clr;           // Interrupt pending clear operation
189
 
190
// ISV register (ISVR)
191
logic                                   ipic_isvr_upd;          // Interrupt Serviced register update
192
logic [SCR1_IRQ_VECT_NUM-1:0]           ipic_isvr_ff;           // Interrupt Serviced register
193
logic [SCR1_IRQ_VECT_NUM-1:0]           ipic_isvr_next;         // Interrupt Serviced register next value
194
 
195
// IE register (IER)
196
logic                                   ipic_ier_upd;           // Interrupt enable register update
197
logic [SCR1_IRQ_VECT_NUM-1:0]           ipic_ier_ff;            // Interrupt enable register
198
logic [SCR1_IRQ_VECT_NUM-1:0]           ipic_ier_next;          // Interrupt enable register next value
199
 
200
// IM register (IMR)
201
logic [SCR1_IRQ_VECT_NUM-1:0]           ipic_imr_ff;            // Interrupt mode register
202
logic [SCR1_IRQ_VECT_NUM-1:0]           ipic_imr_next;          // Interrupt mode register next value
203
 
204
// IINV register (IINVR)
205
logic [SCR1_IRQ_VECT_NUM-1:0]           ipic_iinvr_ff;          // Interrupt Inversion register
206
logic [SCR1_IRQ_VECT_NUM-1:0]           ipic_iinvr_next;        // Interrupt Inversion register next value
207
 
208
// ICS register (ICSR)
209
logic                                   icsr_wr_req;            // Write request to Interrupt Control Status register
210
type_scr1_icsr_m_s                      ipic_icsr;              // Interrupt Control Status register
211
 
212
// Priority interrupt generation signals
213
//------------------------------------------------------------------------------
214
 
215
// Serviced interrupt signals
216
logic                                   irq_serv_vd;            // There is an interrupt in service
217
logic [SCR1_IRQ_VECT_WIDTH-1:0]         irq_serv_idx;           // Index of an interrupt that is currently in service
218
 
219
// Requested interrupt signals
220
logic                                   irq_req_vd;             // There is a requested interrupt
221
logic [SCR1_IRQ_VECT_WIDTH-1:0]         irq_req_idx;            // Index of a requested interrupt
222
 
223
// Interrupt requested on "end of the previous interrupt" signals
224
logic                                   irq_eoi_req_vd;         // There is a requested interrupt when the previous one has ended
225
logic [SCR1_IRQ_VECT_WIDTH-1:0]         irq_eoi_req_idx;        // Index of an interrupt requested when the previous one has ended
226
 
227
logic [SCR1_IRQ_VECT_NUM-1:0]           irq_req_v;              // Vector of interrupts that are pending and enabled
228
 
229
logic                                   irq_start_vd;           // Request to start an interrupt is valid
230
logic                                   irq_hi_prior_pnd;       // There is a pending IRQ with a priority higher than of the interrupt that is currently in service
231
 
232
type_scr1_search_one_16_s               irr_priority;           // Structure for vd and idx of the requested interrupt
233
type_scr1_search_one_16_s               isvr_priority_eoi;      // Structure for vd and idx of the interrupt requested when the previous interrupt has ended
234
logic [SCR1_IRQ_VECT_NUM-1:0]           ipic_isvr_eoi;          // Interrupt Serviced register when the previous interrupt has ended
235
 
236
//------------------------------------------------------------------------------
237
// IRQ lines handling
238
//------------------------------------------------------------------------------
239
 
240
`ifdef SCR1_IPIC_SYNC_EN
241
// IRQ lines synchronization
242
//------------------------------------------------------------------------------
243
 
244
always_ff @(posedge clk, negedge rst_n) begin
245
    if (~rst_n) begin
246
        irq_lines_sync <= '0;
247
        irq_lines      <= '0;
248
    end else begin
249
        irq_lines_sync <= soc2ipic_irq_lines_i;
250
        irq_lines      <= irq_lines_sync;
251
    end
252
end
253
`else // SCR1_IPIC_SYNC_EN
254
assign irq_lines = soc2ipic_irq_lines_i;
255
`endif // SCR1_IPIC_SYNC_EN
256
 
257
// IRQ lines level detection
258
//------------------------------------------------------------------------------
259
 
260
assign irq_lvl = irq_lines ^ ipic_iinvr_next;
261
 
262
// IRQ lines edge detection
263
//------------------------------------------------------------------------------
264
 
265
always_ff @(negedge rst_n, posedge clk) begin
266
    if (~rst_n) begin
267
        irq_lines_dly <= '0;
268
    end else begin
269
        irq_lines_dly <= irq_lines;
270
    end
271
end
272
 
273
assign irq_edge_detected = (irq_lines_dly ^ irq_lines) & irq_lvl;
274
 
275
//------------------------------------------------------------------------------
276
// IPIC registers read/write interface
277
//------------------------------------------------------------------------------
278
 
279
// Read Logic
280
//------------------------------------------------------------------------------
281
 
282
// Read data multiplexer
283
always_comb begin
284
    ipic2csr_rdata_o  = '0;
285
 
286
    if (csr2ipic_r_req_i) begin
287
        case (csr2ipic_addr_i)
288
            SCR1_IPIC_CISV : begin
289
                ipic2csr_rdata_o[SCR1_IRQ_VECT_WIDTH-1:0] = irq_serv_vd
290
                                                          ? ipic_cisv_ff
291
                                                          : SCR1_IRQ_VOID_VECT_NUM;
292
            end
293
            SCR1_IPIC_CICSR : begin
294
                ipic2csr_rdata_o[SCR1_IPIC_ICSR_IP]  = ipic_cicsr.ip;
295
                ipic2csr_rdata_o[SCR1_IPIC_ICSR_IE]  = ipic_cicsr.ie;
296
            end
297
            SCR1_IPIC_IPR : begin
298
                ipic2csr_rdata_o = `SCR1_XLEN'(ipic_ipr_ff);
299
            end
300
            SCR1_IPIC_ISVR : begin
301
                ipic2csr_rdata_o = `SCR1_XLEN'(ipic_isvr_ff);
302
            end
303
            SCR1_IPIC_EOI,
304
            SCR1_IPIC_SOI : begin
305
                ipic2csr_rdata_o = '0;
306
            end
307
            SCR1_IPIC_IDX : begin
308
                ipic2csr_rdata_o = `SCR1_XLEN'(ipic_idxr_ff);
309
            end
310
            SCR1_IPIC_ICSR : begin
311
                ipic2csr_rdata_o[SCR1_IPIC_ICSR_IP]      = ipic_icsr.ip;
312
                ipic2csr_rdata_o[SCR1_IPIC_ICSR_IE]      = ipic_icsr.ie;
313
                ipic2csr_rdata_o[SCR1_IPIC_ICSR_IM]      = ipic_icsr.im;
314
                ipic2csr_rdata_o[SCR1_IPIC_ICSR_INV]     = ipic_icsr.inv;
315
                ipic2csr_rdata_o[SCR1_IPIC_ICSR_PRV_MSB:
316
                                 SCR1_IPIC_ICSR_PRV_LSB] = SCR1_IPIC_PRV_M;
317
                ipic2csr_rdata_o[SCR1_IPIC_ICSR_IS]      = ipic_icsr.is;
318
                ipic2csr_rdata_o[SCR1_IPIC_ICSR_LN_MSB-1:
319
                                 SCR1_IPIC_ICSR_LN_LSB]  = ipic_icsr.line;
320
            end
321
            default : begin
322
                ipic2csr_rdata_o = 'x;
323
            end
324
        endcase
325
    end
326
end
327
 
328
// Write logic
329
//------------------------------------------------------------------------------
330
 
331
// Register selection
332
always_comb begin
333
    cicsr_wr_req = 1'b0;
334
    eoi_wr_req   = 1'b0;
335
    soi_wr_req   = 1'b0;
336
    idxr_wr_req  = 1'b0;
337
    icsr_wr_req  = 1'b0;
338
    if (csr2ipic_w_req_i) begin
339
        case (csr2ipic_addr_i)
340
            SCR1_IPIC_CISV : begin end // Quiet Read-Only
341
            SCR1_IPIC_CICSR: cicsr_wr_req = 1'b1;
342
            SCR1_IPIC_IPR  : begin end
343
            SCR1_IPIC_ISVR : begin end // Quiet Read-Only
344
            SCR1_IPIC_EOI  : eoi_wr_req   = 1'b1;
345
            SCR1_IPIC_SOI  : soi_wr_req   = 1'b1;
346
            SCR1_IPIC_IDX  : idxr_wr_req  = 1'b1;
347
            SCR1_IPIC_ICSR : icsr_wr_req  = 1'b1;
348
            default : begin // Illegal IPIC register address
349
                cicsr_wr_req = 'x;
350
                eoi_wr_req   = 'x;
351
                soi_wr_req   = 'x;
352
                idxr_wr_req  = 'x;
353
                icsr_wr_req  = 'x;
354
            end
355
        endcase
356
    end
357
end
358
 
359
//------------------------------------------------------------------------------
360
// IPIC registers
361
//------------------------------------------------------------------------------
362
//
363
 // Registers:
364
 // - Current Interrupt Vector in Service (CISV) register
365
 // - Current Interrupt Control Status (CICSR) register
366
 // - End of Interrupt (EOI) register
367
 // - Start of Interrupt (SOI) register
368
 // - Index (IDX) register
369
 // - Interrupt Pending Register (IPR)
370
 // - Interrupt Serviced Register (ISVR)
371
 // - Interrupt Enable Register (IER)
372
 // - Interrupt Mode Register (IMR)
373
 // - Interrupt Inversion Register (IINVR)
374
 // - Interrupt Control Status Register (ICSR)
375
//
376
 
377
// CISV register
378
//------------------------------------------------------------------------------
379
// Contains number of the interrupt vector currently in service. When no
380
// interrupts are in service, contains number of the void interrupt vector (0x10).
381
// The register cannot contain all 0's
382
 
383
assign ipic_cisv_upd = irq_start_vd | ipic_eoi_req;
384
 
385
always_ff @(negedge rst_n, posedge clk) begin
386
    if (~rst_n) begin
387
        ipic_cisv_ff <= SCR1_IRQ_VOID_VECT_NUM;
388
    end else if (ipic_cisv_upd) begin
389
        ipic_cisv_ff <= ipic_cisv_next;
390
    end
391
end
392
 
393
assign ipic_cisv_next = irq_start_vd ? irq_req_idx
394
                      : ipic_eoi_req ? irq_eoi_req_vd ? irq_eoi_req_idx
395
                                                      : SCR1_IRQ_VOID_VECT_NUM
396
                                     : 1'b0;
397
 
398
assign irq_serv_idx = ipic_cisv_ff[SCR1_IRQ_VECT_WIDTH-2:0];
399
assign irq_serv_vd  = ~ipic_cisv_ff[SCR1_IRQ_VECT_WIDTH-1];
400
 
401
// CICSR register
402
//------------------------------------------------------------------------------
403
// Shows whether the interrupt currently in service is pending and enabled
404
 
405
assign ipic_cicsr.ip = ipic_ipr_ff[irq_serv_idx] & irq_serv_vd;
406
assign ipic_cicsr.ie = ipic_ier_ff[irq_serv_idx] & irq_serv_vd;
407
 
408
// EOI register
409
//------------------------------------------------------------------------------
410
// Writing any value to EOI register ends the interrupt which is currently in service
411
 
412
assign ipic_eoi_req = eoi_wr_req & irq_serv_vd;
413
 
414
// SOI register
415
//------------------------------------------------------------------------------
416
// Writing any value to SOI activates start of interrupt if one of the following
417
// conditions is true:
418
// - There is at least one pending interrupt with IE and ISR is zero
419
// - There is at least one pending interrupt with IE and higher priority than the
420
// interrupts currently in service
421
 
422
assign ipic_soi_req = soi_wr_req & irq_req_vd;
423
 
424
// IDX register
425
//------------------------------------------------------------------------------
426
// Defines the number of interrupt vector which is accessed through the IPIC_ICSR
427
// register
428
 
429
always_ff @(negedge rst_n, posedge clk) begin
430
    if (~rst_n) begin
431
        ipic_idxr_ff <= '0;
432
    end else if (idxr_wr_req) begin
433
        ipic_idxr_ff <= csr2ipic_wdata_i[SCR1_IRQ_IDX_WIDTH-1:0];
434
    end
435
end
436
 
437
// IPR
438
//------------------------------------------------------------------------------
439
// For every IRQ line shows whether there is a pending interrupt
440
 
441
assign ipic_ipr_upd = (ipic_ipr_next != ipic_ipr_ff);
442
 
443
always_ff @(negedge rst_n, posedge clk) begin
444
    if (~rst_n) begin
445
        ipic_ipr_ff <= '0;
446
    end else if (ipic_ipr_upd) begin
447
        ipic_ipr_ff <= ipic_ipr_next;
448
    end
449
end
450
 
451
always_comb begin
452
    ipic_ipr_clr_req = '0;
453
    if (csr2ipic_w_req_i) begin
454
        case (csr2ipic_addr_i)
455
            SCR1_IPIC_CICSR: ipic_ipr_clr_req[irq_serv_idx] = csr2ipic_wdata_i[SCR1_IPIC_ICSR_IP]
456
                                                            & irq_serv_vd;
457
            SCR1_IPIC_IPR  : ipic_ipr_clr_req               = csr2ipic_wdata_i[SCR1_IRQ_VECT_NUM-1:0];
458
            SCR1_IPIC_SOI  : ipic_ipr_clr_req[irq_req_idx]  = irq_req_vd;
459
            SCR1_IPIC_ICSR : ipic_ipr_clr_req[ipic_idxr_ff] = csr2ipic_wdata_i[SCR1_IPIC_ICSR_IP];
460
            default        : begin end
461
        endcase
462
    end
463
end
464
 
465
assign ipic_ipr_clr_cond = ~irq_lvl | ipic_imr_next;
466
assign ipic_ipr_clr      = ipic_ipr_clr_req & ipic_ipr_clr_cond;
467
integer i;
468
always_comb begin
469
    ipic_ipr_next = '0;
470
    for (i=0; i
471
        ipic_ipr_next[i] = ipic_ipr_clr[i] ? 1'b0
472
                         : ~ipic_imr_ff[i] ? irq_lvl[i]
473
                                           : ipic_ipr_ff[i] | irq_edge_detected[i];
474
    end
475
end
476
 
477
// ISVR
478
//------------------------------------------------------------------------------
479
// For every IRQ line shows whether the interrupt is in service or not
480
 
481
assign ipic_isvr_upd = irq_start_vd | ipic_eoi_req;
482
 
483
always_ff @(negedge rst_n, posedge clk) begin
484
    if (~rst_n) begin
485
        ipic_isvr_ff <= '0;
486
    end else if (ipic_isvr_upd) begin
487
        ipic_isvr_ff <= ipic_isvr_next;
488
    end
489
end
490
 
491
always_comb begin
492
    ipic_isvr_eoi = ipic_isvr_ff;
493
    if (irq_serv_vd) begin
494
        ipic_isvr_eoi[irq_serv_idx] = 1'b0;
495
    end
496
end
497
 
498
always_comb begin
499
    ipic_isvr_next = ipic_isvr_ff;
500
    if (irq_start_vd) begin
501
        ipic_isvr_next[irq_req_idx] = 1'b1;
502
    end else if (ipic_eoi_req) begin
503
        ipic_isvr_next = ipic_isvr_eoi;
504
    end
505
end
506
 
507
// IER
508
//------------------------------------------------------------------------------
509
// Enables/disables interrupt for every IRQ line
510
 
511
assign ipic_ier_upd = cicsr_wr_req | icsr_wr_req;
512
 
513
always_ff @(negedge rst_n, posedge clk) begin
514
    if (~rst_n) begin
515
        ipic_ier_ff <= '0;
516
    end else if (ipic_ier_upd) begin
517
        ipic_ier_ff <= ipic_ier_next;
518
    end
519
end
520
 
521
always_comb begin
522
    ipic_ier_next = ipic_ier_ff;
523
    if (cicsr_wr_req) begin
524
        ipic_ier_next[irq_serv_idx] = irq_serv_vd
525
                                    ? csr2ipic_wdata_i[SCR1_IPIC_ICSR_IE]
526
                                    : ipic_ier_ff[irq_serv_idx];
527
    end else if (icsr_wr_req) begin
528
        ipic_ier_next[ipic_idxr_ff] = csr2ipic_wdata_i[SCR1_IPIC_ICSR_IE];
529
    end
530
end
531
 
532
// IMR
533
//------------------------------------------------------------------------------
534
// For every IRQ line sets either Level (0) or Edge (1) detection
535
 
536
always_ff @(negedge rst_n, posedge clk) begin
537
    if (~rst_n) begin
538
        ipic_imr_ff <= '0;
539
    end else if (icsr_wr_req) begin
540
        ipic_imr_ff <= ipic_imr_next;
541
    end
542
end
543
 
544
always_comb begin
545
    ipic_imr_next = ipic_imr_ff;
546
    if (icsr_wr_req) begin
547
        ipic_imr_next[ipic_idxr_ff] = csr2ipic_wdata_i[SCR1_IPIC_ICSR_IM];
548
    end
549
end
550
 
551
// IINVR
552
//------------------------------------------------------------------------------
553
// For every IRQ line defines whether it should be inverted or not
554
 
555
always_ff @(negedge rst_n, posedge clk) begin
556
    if (~rst_n) begin
557
        ipic_iinvr_ff <= '0;
558
    end else if (icsr_wr_req) begin
559
        ipic_iinvr_ff <= ipic_iinvr_next;
560
    end
561
end
562
 
563
always_comb begin
564
    ipic_iinvr_next = ipic_iinvr_ff;
565
    if (icsr_wr_req) begin
566
        ipic_iinvr_next[ipic_idxr_ff] = csr2ipic_wdata_i[SCR1_IPIC_ICSR_INV];
567
    end
568
end
569
 
570
// ICSR
571
//------------------------------------------------------------------------------
572
// Holds control and status information about the interrupt defined by Index Register
573
 
574
assign ipic_icsr.ip    = ipic_ipr_ff  [ipic_idxr_ff];
575
assign ipic_icsr.ie    = ipic_ier_ff  [ipic_idxr_ff];
576
assign ipic_icsr.im    = ipic_imr_ff  [ipic_idxr_ff];
577
assign ipic_icsr.inv   = ipic_iinvr_ff[ipic_idxr_ff];
578
assign ipic_icsr.is    = ipic_isvr_ff [ipic_idxr_ff];
579
assign ipic_icsr.line  = SCR1_IRQ_LINES_WIDTH'(ipic_idxr_ff);
580
 
581
//------------------------------------------------------------------------------
582
// Priority IRQ generation logic
583
//------------------------------------------------------------------------------
584
 
585
assign irq_req_v = ipic_ipr_ff & ipic_ier_ff;
586
 
587
/*** Modified for Yosys handing typedef in function - dinesha
588
assign irr_priority        = scr1_search_one_16(irq_req_v);
589
assign irq_req_vd          = irr_priority.vd;
590
assign irq_req_idx         = irr_priority.idx;
591
****/
592
 
593
always_comb
594
begin
595
    casex(irq_req_v)
596
            16'bxxxx_xxxx_xxxx_xxx1 : irq_req_idx = 0;
597
            16'bxxxx_xxxx_xxxx_xx10 : irq_req_idx = 1;
598
            16'bxxxx_xxxx_xxxx_x100 : irq_req_idx = 2;
599
            16'bxxxx_xxxx_xxxx_1000 : irq_req_idx = 3;
600
            16'bxxxx_xxxx_xxx1_0000 : irq_req_idx = 4;
601
            16'bxxxx_xxxx_xx10_0000 : irq_req_idx = 5;
602
            16'bxxxx_xxxx_x100_0000 : irq_req_idx = 6;
603
            16'bxxxx_xxxx_1000_0000 : irq_req_idx = 7;
604
            16'bxxxx_xxx1_0000_0000 : irq_req_idx = 8;
605
            16'bxxxx_xx10_0000_0000 : irq_req_idx = 9;
606
            16'bxxxx_x100_0000_0000 : irq_req_idx = 10;
607
            16'bxxxx_1000_0000_0000 : irq_req_idx = 11;
608
            16'bxxx1_0000_0000_0000 : irq_req_idx = 12;
609
            16'bxx10_0000_0000_0000 : irq_req_idx = 13;
610
            16'bx100_0000_0000_0000 : irq_req_idx = 14;
611
            16'b1000_0000_0000_0000 : irq_req_idx = 15;
612
            16'b0000_0000_0000_0000 : irq_req_idx = 16;
613
            default : irq_req_idx = 16;
614
    endcase
615
    irq_req_vd = |irq_req_v;
616
end
617
 
618
/*** Modified for Yosys handing typedef in function - dinesha
619
assign isvr_priority_eoi   = scr1_search_one_16(ipic_isvr_eoi);
620
assign irq_eoi_req_vd      = isvr_priority_eoi.vd;
621
assign irq_eoi_req_idx     = isvr_priority_eoi.idx;
622
*************************************************/
623
 
624
always_comb
625
begin
626
    casex(ipic_isvr_eoi)
627
            16'bxxxx_xxxx_xxxx_xxx1 : irq_eoi_req_idx = 0;
628
            16'bxxxx_xxxx_xxxx_xx10 : irq_eoi_req_idx = 1;
629
            16'bxxxx_xxxx_xxxx_x100 : irq_eoi_req_idx = 2;
630
            16'bxxxx_xxxx_xxxx_1000 : irq_eoi_req_idx = 3;
631
            16'bxxxx_xxxx_xxx1_0000 : irq_eoi_req_idx = 4;
632
            16'bxxxx_xxxx_xx10_0000 : irq_eoi_req_idx = 5;
633
            16'bxxxx_xxxx_x100_0000 : irq_eoi_req_idx = 6;
634
            16'bxxxx_xxxx_1000_0000 : irq_eoi_req_idx = 7;
635
            16'bxxxx_xxx1_0000_0000 : irq_eoi_req_idx = 8;
636
            16'bxxxx_xx10_0000_0000 : irq_eoi_req_idx = 9;
637
            16'bxxxx_x100_0000_0000 : irq_eoi_req_idx = 10;
638
            16'bxxxx_1000_0000_0000 : irq_eoi_req_idx = 11;
639
            16'bxxx1_0000_0000_0000 : irq_eoi_req_idx = 12;
640
            16'bxx10_0000_0000_0000 : irq_eoi_req_idx = 13;
641
            16'bx100_0000_0000_0000 : irq_eoi_req_idx = 14;
642
            16'b1000_0000_0000_0000 : irq_eoi_req_idx = 15;
643
            16'b0000_0000_0000_0000 : irq_eoi_req_idx = 16;
644
            default : irq_eoi_req_idx = 16;
645
    endcase
646
    irq_eoi_req_vd = |ipic_isvr_eoi;
647
end
648
 
649
assign irq_hi_prior_pnd     = irq_req_idx < irq_serv_idx;
650
 
651
assign ipic2csr_irq_m_req_o = irq_req_vd & (~irq_serv_vd | irq_hi_prior_pnd);
652
 
653
assign irq_start_vd         = ipic2csr_irq_m_req_o & ipic_soi_req;
654
 
655
endmodule : scr1_ipic
656
 
657
`endif // SCR1_IPIC_EN

powered by: WebSVN 2.1.0

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