../src/lowrisc_top_earlgrey_rv_plic_0.1/rtl/autogen/rv_plic.sv Cov: 100%
1: // Copyright lowRISC contributors.
2: // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3: // SPDX-License-Identifier: Apache-2.0
4: //
5: // ------------------- W A R N I N G: A U T O - G E N E R A T E D C O D E !! -------------------//
6: // PLEASE DO NOT HAND-EDIT THIS FILE. IT HAS BEEN AUTO-GENERATED WITH THE FOLLOWING COMMAND:
7: // util/topgen.py -t hw/top_earlgrey/data/top_earlgrey.hjson --plic-only -o hw/top_earlgrey/
8:
9: // Copyright lowRISC contributors.
10: // Licensed under the Apache License, Version 2.0, see LICENSE for details.
11: // SPDX-License-Identifier: Apache-2.0
12: //
13: // RISC-V Platform-Level Interrupt Controller compliant INTC
14: //
15: // Current version doesn't support MSI interrupt but it is easy to add
16: // the feature. Create one external register and connect qe signal to the
17: // gateway module (as edge-triggered)
18: //
19: // Consider to set MAX_PRIO as small number as possible. It is main factor
20: // of area increase if edge-triggered counter isn't implemented.
21: //
22: // Verilog parameter
23: // MAX_PRIO: Maximum value of interrupt priority
24:
25: module rv_plic import rv_plic_reg_pkg::*; #(
26: // derived parameter
27: localparam int SRCW = $clog2(NumSrc)
28: ) (
29: input clk_i,
30: input rst_ni,
31:
32: // Bus Interface (device)
33: input tlul_pkg::tl_h2d_t tl_i,
34: output tlul_pkg::tl_d2h_t tl_o,
35:
36: // Interrupt Sources
37: input [NumSrc-1:0] intr_src_i,
38:
39: // Interrupt notification to targets
40: output [NumTarget-1:0] irq_o,
41: output [SRCW-1:0] irq_id_o [NumTarget],
42:
43: output logic [NumTarget-1:0] msip_o
44: );
45:
46: rv_plic_reg2hw_t reg2hw;
47: rv_plic_hw2reg_t hw2reg;
48:
49: localparam int MAX_PRIO = 3;
50: localparam int PRIOW = $clog2(MAX_PRIO+1);
51:
52: logic [NumSrc-1:0] le; // 0:level 1:edge
53: logic [NumSrc-1:0] ip;
54:
55: logic [NumSrc-1:0] ie [NumTarget];
56:
57: logic [NumTarget-1:0] claim_re; // Target read indicator
58: logic [SRCW-1:0] claim_id [NumTarget];
59: logic [NumSrc-1:0] claim; // Converted from claim_re/claim_id
60:
61: logic [NumTarget-1:0] complete_we; // Target write indicator
62: logic [SRCW-1:0] complete_id [NumTarget];
63: logic [NumSrc-1:0] complete; // Converted from complete_re/complete_id
64:
65: logic [SRCW-1:0] cc_id [NumTarget]; // Write ID
66:
67: logic [PRIOW-1:0] prio [NumSrc];
68:
69: logic [PRIOW-1:0] threshold [NumTarget];
70:
71: // Glue logic between rv_plic_reg_top and others
72: assign cc_id = irq_id_o;
73:
74: always_comb begin
75: claim = '0;
76: for (int i = 0 ; i < NumTarget ; i++) begin
77: if (claim_re[i]) claim[claim_id[i]] = 1'b1;
78: end
79: end
80: always_comb begin
81: complete = '0;
82: for (int i = 0 ; i < NumTarget ; i++) begin
83: if (complete_we[i]) complete[complete_id[i]] = 1'b1;
84: end
85: end
86:
87: //`ASSERT_PULSE(claimPulse, claim_re[i])
88: //`ASSERT_PULSE(completePulse, complete_we[i])
89:
90: `ASSERT(onehot0Claim, $onehot0(claim_re))
91:
92: `ASSERT(onehot0Complete, $onehot0(complete_we))
93:
94: //////////////
95: // Priority //
96: //////////////
97: assign prio[0] = reg2hw.prio0.q;
98: assign prio[1] = reg2hw.prio1.q;
99: assign prio[2] = reg2hw.prio2.q;
100: assign prio[3] = reg2hw.prio3.q;
101: assign prio[4] = reg2hw.prio4.q;
102: assign prio[5] = reg2hw.prio5.q;
103: assign prio[6] = reg2hw.prio6.q;
104: assign prio[7] = reg2hw.prio7.q;
105: assign prio[8] = reg2hw.prio8.q;
106: assign prio[9] = reg2hw.prio9.q;
107: assign prio[10] = reg2hw.prio10.q;
108: assign prio[11] = reg2hw.prio11.q;
109: assign prio[12] = reg2hw.prio12.q;
110: assign prio[13] = reg2hw.prio13.q;
111: assign prio[14] = reg2hw.prio14.q;
112: assign prio[15] = reg2hw.prio15.q;
113: assign prio[16] = reg2hw.prio16.q;
114: assign prio[17] = reg2hw.prio17.q;
115: assign prio[18] = reg2hw.prio18.q;
116: assign prio[19] = reg2hw.prio19.q;
117: assign prio[20] = reg2hw.prio20.q;
118: assign prio[21] = reg2hw.prio21.q;
119: assign prio[22] = reg2hw.prio22.q;
120: assign prio[23] = reg2hw.prio23.q;
121: assign prio[24] = reg2hw.prio24.q;
122: assign prio[25] = reg2hw.prio25.q;
123: assign prio[26] = reg2hw.prio26.q;
124: assign prio[27] = reg2hw.prio27.q;
125: assign prio[28] = reg2hw.prio28.q;
126: assign prio[29] = reg2hw.prio29.q;
127: assign prio[30] = reg2hw.prio30.q;
128: assign prio[31] = reg2hw.prio31.q;
129: assign prio[32] = reg2hw.prio32.q;
130: assign prio[33] = reg2hw.prio33.q;
131: assign prio[34] = reg2hw.prio34.q;
132: assign prio[35] = reg2hw.prio35.q;
133: assign prio[36] = reg2hw.prio36.q;
134: assign prio[37] = reg2hw.prio37.q;
135: assign prio[38] = reg2hw.prio38.q;
136: assign prio[39] = reg2hw.prio39.q;
137: assign prio[40] = reg2hw.prio40.q;
138: assign prio[41] = reg2hw.prio41.q;
139: assign prio[42] = reg2hw.prio42.q;
140: assign prio[43] = reg2hw.prio43.q;
141: assign prio[44] = reg2hw.prio44.q;
142: assign prio[45] = reg2hw.prio45.q;
143: assign prio[46] = reg2hw.prio46.q;
144: assign prio[47] = reg2hw.prio47.q;
145: assign prio[48] = reg2hw.prio48.q;
146: assign prio[49] = reg2hw.prio49.q;
147: assign prio[50] = reg2hw.prio50.q;
148: assign prio[51] = reg2hw.prio51.q;
149: assign prio[52] = reg2hw.prio52.q;
150: assign prio[53] = reg2hw.prio53.q;
151: assign prio[54] = reg2hw.prio54.q;
152: assign prio[55] = reg2hw.prio55.q;
153: assign prio[56] = reg2hw.prio56.q;
154: assign prio[57] = reg2hw.prio57.q;
155: assign prio[58] = reg2hw.prio58.q;
156: assign prio[59] = reg2hw.prio59.q;
157: assign prio[60] = reg2hw.prio60.q;
158: assign prio[61] = reg2hw.prio61.q;
159: assign prio[62] = reg2hw.prio62.q;
160: assign prio[63] = reg2hw.prio63.q;
161: assign prio[64] = reg2hw.prio64.q;
162: assign prio[65] = reg2hw.prio65.q;
163: assign prio[66] = reg2hw.prio66.q;
164: assign prio[67] = reg2hw.prio67.q;
165: assign prio[68] = reg2hw.prio68.q;
166: assign prio[69] = reg2hw.prio69.q;
167: assign prio[70] = reg2hw.prio70.q;
168: assign prio[71] = reg2hw.prio71.q;
169: assign prio[72] = reg2hw.prio72.q;
170: assign prio[73] = reg2hw.prio73.q;
171: assign prio[74] = reg2hw.prio74.q;
172: assign prio[75] = reg2hw.prio75.q;
173: assign prio[76] = reg2hw.prio76.q;
174: assign prio[77] = reg2hw.prio77.q;
175: assign prio[78] = reg2hw.prio78.q;
176: assign prio[79] = reg2hw.prio79.q;
177: assign prio[80] = reg2hw.prio80.q;
178:
179: //////////////////////
180: // Interrupt Enable //
181: //////////////////////
182: for (genvar s = 0; s < 81; s++) begin : gen_ie0
183: assign ie[0][s] = reg2hw.ie0[s].q;
184: end
185:
186: ////////////////////////
187: // THRESHOLD register //
188: ////////////////////////
189: assign threshold[0] = reg2hw.threshold0.q;
190:
191: /////////////////
192: // CC register //
193: /////////////////
194: assign claim_re[0] = reg2hw.cc0.re;
195: assign claim_id[0] = irq_id_o[0];
196: assign complete_we[0] = reg2hw.cc0.qe;
197: assign complete_id[0] = reg2hw.cc0.q;
198: assign hw2reg.cc0.d = cc_id[0];
199:
200: ///////////////////
201: // MSIP register //
202: ///////////////////
203: assign msip_o[0] = reg2hw.msip0.q;
204:
205: ////////
206: // IP //
207: ////////
208: for (genvar s = 0; s < 81; s++) begin : gen_ip
209: assign hw2reg.ip[s].de = 1'b1; // Always write
210: assign hw2reg.ip[s].d = ip[s];
211: end
212:
213: ///////////////////////////////////
214: // Detection:: 0: Level, 1: Edge //
215: ///////////////////////////////////
216: for (genvar s = 0; s < 81; s++) begin : gen_le
217: assign le[s] = reg2hw.le[s].q;
218: end
219:
220: //////////////
221: // Gateways //
222: //////////////
223: rv_plic_gateway #(
224: .N_SOURCE (NumSrc)
225: ) u_gateway (
226: .clk_i,
227: .rst_ni,
228:
229: .src (intr_src_i),
230: .le,
231:
232: .claim,
233: .complete,
234:
235: .ip
236: );
237:
238: ///////////////////////////////////
239: // Target interrupt notification //
240: ///////////////////////////////////
241: for (genvar i = 0 ; i < NumTarget ; i++) begin : gen_target
242: rv_plic_target #(
243: .N_SOURCE (NumSrc),
244: .MAX_PRIO (MAX_PRIO)
245: ) u_target (
246: .clk_i,
247: .rst_ni,
248:
249: .ip,
250: .ie (ie[i]),
251:
252: .prio,
253: .threshold (threshold[i]),
254:
255: .irq (irq_o[i]),
256: .irq_id (irq_id_o[i])
257:
258: );
259: end
260:
261: ////////////////////////
262: // Register interface //
263: ////////////////////////
264: // Limitation of register tool prevents the module from having flexibility to parameters
265: // So, signals are manually tied at the top.
266: rv_plic_reg_top u_reg (
267: .clk_i,
268: .rst_ni,
269:
270: .tl_i,
271: .tl_o,
272:
273: .reg2hw,
274: .hw2reg,
275:
276: .devmode_i (1'b1)
277: );
278:
279: // Assertions
280: `ASSERT_KNOWN(TlDValidKnownO_A, tl_o.d_valid)
281: `ASSERT_KNOWN(TlAReadyKnownO_A, tl_o.a_ready)
282: `ASSERT_KNOWN(IrqKnownO_A, irq_o)
283: `ASSERT_KNOWN(MsipKnownO_A, msip_o)
284: for (genvar k = 0; k < NumTarget; k++) begin : gen_irq_id_known
285: `ASSERT_KNOWN(IrqIdKnownO_A, irq_id_o[k])
286: end
287:
288: // Assume
289: `ASSUME(Irq0Tied_A, intr_src_i[0] == 1'b0)
290:
291: endmodule
292: