hw/top_earlgrey/ip/rv_plic/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+1)
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: import rv_plic_reg_pkg::*;
47:
48: rv_plic_reg2hw_t reg2hw;
49: rv_plic_hw2reg_t hw2reg;
50:
51: localparam int MAX_PRIO = 3;
52: localparam int PRIOW = $clog2(MAX_PRIO+1);
53:
54: logic [NumSrc-1:0] le; // 0:level 1:edge
55: logic [NumSrc-1:0] ip;
56:
57: logic [NumSrc-1:0] ie [NumTarget];
58:
59: logic [NumTarget-1:0] claim_re; // Target read indicator
60: logic [SRCW-1:0] claim_id [NumTarget];
61: logic [NumSrc-1:0] claim; // Converted from claim_re/claim_id
62:
63: logic [NumTarget-1:0] complete_we; // Target write indicator
64: logic [SRCW-1:0] complete_id [NumTarget];
65: logic [NumSrc-1:0] complete; // Converted from complete_re/complete_id
66:
67: logic [SRCW-1:0] cc_id [NumTarget]; // Write ID
68:
69: logic [PRIOW-1:0] prio [NumSrc];
70:
71: logic [PRIOW-1:0] threshold [NumTarget];
72:
73: // Glue logic between rv_plic_reg_top and others
74: assign cc_id = irq_id_o;
75:
76: always_comb begin
77: claim = '0;
78: for (int i = 0 ; i < NumTarget ; i++) begin
79: if (claim_re[i]) claim[claim_id[i] -1] = 1'b1;
80: end
81: end
82: always_comb begin
83: complete = '0;
84: for (int i = 0 ; i < NumTarget ; i++) begin
85: if (complete_we[i]) complete[complete_id[i] -1] = 1'b1;
86: end
87: end
88:
89: //`ASSERT_PULSE(claimPulse, claim_re[i], clk_i, !rst_ni)
90: //`ASSERT_PULSE(completePulse, complete_we[i], clk_i, !rst_ni)
91:
92: `ASSERT(onehot0Claim, $onehot0(claim_re), clk_i, !rst_ni)
93:
94: `ASSERT(onehot0Complete, $onehot0(complete_we), clk_i, !rst_ni)
95:
96: //////////////
97: // Priority //
98: //////////////
99: assign prio[0] = reg2hw.prio0.q;
100: assign prio[1] = reg2hw.prio1.q;
101: assign prio[2] = reg2hw.prio2.q;
102: assign prio[3] = reg2hw.prio3.q;
103: assign prio[4] = reg2hw.prio4.q;
104: assign prio[5] = reg2hw.prio5.q;
105: assign prio[6] = reg2hw.prio6.q;
106: assign prio[7] = reg2hw.prio7.q;
107: assign prio[8] = reg2hw.prio8.q;
108: assign prio[9] = reg2hw.prio9.q;
109: assign prio[10] = reg2hw.prio10.q;
110: assign prio[11] = reg2hw.prio11.q;
111: assign prio[12] = reg2hw.prio12.q;
112: assign prio[13] = reg2hw.prio13.q;
113: assign prio[14] = reg2hw.prio14.q;
114: assign prio[15] = reg2hw.prio15.q;
115: assign prio[16] = reg2hw.prio16.q;
116: assign prio[17] = reg2hw.prio17.q;
117: assign prio[18] = reg2hw.prio18.q;
118: assign prio[19] = reg2hw.prio19.q;
119: assign prio[20] = reg2hw.prio20.q;
120: assign prio[21] = reg2hw.prio21.q;
121: assign prio[22] = reg2hw.prio22.q;
122: assign prio[23] = reg2hw.prio23.q;
123: assign prio[24] = reg2hw.prio24.q;
124: assign prio[25] = reg2hw.prio25.q;
125: assign prio[26] = reg2hw.prio26.q;
126: assign prio[27] = reg2hw.prio27.q;
127: assign prio[28] = reg2hw.prio28.q;
128: assign prio[29] = reg2hw.prio29.q;
129: assign prio[30] = reg2hw.prio30.q;
130: assign prio[31] = reg2hw.prio31.q;
131: assign prio[32] = reg2hw.prio32.q;
132: assign prio[33] = reg2hw.prio33.q;
133: assign prio[34] = reg2hw.prio34.q;
134: assign prio[35] = reg2hw.prio35.q;
135: assign prio[36] = reg2hw.prio36.q;
136: assign prio[37] = reg2hw.prio37.q;
137: assign prio[38] = reg2hw.prio38.q;
138: assign prio[39] = reg2hw.prio39.q;
139: assign prio[40] = reg2hw.prio40.q;
140: assign prio[41] = reg2hw.prio41.q;
141: assign prio[42] = reg2hw.prio42.q;
142: assign prio[43] = reg2hw.prio43.q;
143: assign prio[44] = reg2hw.prio44.q;
144: assign prio[45] = reg2hw.prio45.q;
145: assign prio[46] = reg2hw.prio46.q;
146: assign prio[47] = reg2hw.prio47.q;
147: assign prio[48] = reg2hw.prio48.q;
148: assign prio[49] = reg2hw.prio49.q;
149: assign prio[50] = reg2hw.prio50.q;
150: assign prio[51] = reg2hw.prio51.q;
151: assign prio[52] = reg2hw.prio52.q;
152: assign prio[53] = reg2hw.prio53.q;
153: assign prio[54] = reg2hw.prio54.q;
154: assign prio[55] = reg2hw.prio55.q;
155: assign prio[56] = reg2hw.prio56.q;
156: assign prio[57] = reg2hw.prio57.q;
157: assign prio[58] = reg2hw.prio58.q;
158: assign prio[59] = reg2hw.prio59.q;
159: assign prio[60] = reg2hw.prio60.q;
160: assign prio[61] = reg2hw.prio61.q;
161: assign prio[62] = reg2hw.prio62.q;
162:
163: //////////////////////
164: // Interrupt Enable //
165: //////////////////////
166: for (genvar s = 0; s < 63; s++) begin : gen_ie0
167: assign ie[0][s] = reg2hw.ie0[s].q;
168: end
169:
170: ////////////////////////
171: // THRESHOLD register //
172: ////////////////////////
173: assign threshold[0] = reg2hw.threshold0.q;
174:
175: /////////////////
176: // CC register //
177: /////////////////
178: assign claim_re[0] = reg2hw.cc0.re;
179: assign claim_id[0] = irq_id_o[0];
180: assign complete_we[0] = reg2hw.cc0.qe;
181: assign complete_id[0] = reg2hw.cc0.q;
182: assign hw2reg.cc0.d = cc_id[0];
183:
184: ///////////////////
185: // MSIP register //
186: ///////////////////
187: assign msip_o[0] = reg2hw.msip0.q;
188:
189: ////////
190: // IP //
191: ////////
192: for (genvar s = 0; s < 63; s++) begin : gen_ip
193: assign hw2reg.ip[s].de = 1'b1; // Always write
194: assign hw2reg.ip[s].d = ip[s];
195: end
196:
197: ///////////////////////////////////
198: // Detection:: 0: Level, 1: Edge //
199: ///////////////////////////////////
200: for (genvar s = 0; s < 63; s++) begin : gen_le
201: assign le[s] = reg2hw.le[s].q;
202: end
203:
204: //////////////
205: // Gateways //
206: //////////////
207: rv_plic_gateway #(
208: .N_SOURCE (NumSrc)
209: ) u_gateway (
210: .clk_i,
211: .rst_ni,
212:
213: .src (intr_src_i),
214: .le,
215:
216: .claim,
217: .complete,
218:
219: .ip
220: );
221:
222: ///////////////////////////////////
223: // Target interrupt notification //
224: ///////////////////////////////////
225: for (genvar i = 0 ; i < NumTarget ; i++) begin : gen_target
226: rv_plic_target #(
227: .N_SOURCE (NumSrc),
228: .MAX_PRIO (MAX_PRIO)
229: ) u_target (
230: .clk_i,
231: .rst_ni,
232:
233: .ip,
234: .ie (ie[i]),
235:
236: .prio,
237: .threshold (threshold[i]),
238:
239: .irq (irq_o[i]),
240: .irq_id (irq_id_o[i])
241:
242: );
243: end
244:
245: ////////////////////////
246: // Register interface //
247: ////////////////////////
248: // Limitation of register tool prevents the module from having flexibility to parameters
249: // So, signals are manually tied at the top.
250: rv_plic_reg_top u_reg (
251: .clk_i,
252: .rst_ni,
253:
254: .tl_i,
255: .tl_o,
256:
257: .reg2hw,
258: .hw2reg,
259:
260: .devmode_i (1'b1)
261: );
262:
263: // Assertions
264: `ASSERT_KNOWN(TlDValidKnownO_A, tl_o.d_valid, clk_i, !rst_ni)
265: `ASSERT_KNOWN(TlAReadyKnownO_A, tl_o.a_ready, clk_i, !rst_ni)
266: `ASSERT_KNOWN(IrqKnownO_A, irq_o, clk_i, !rst_ni)
267: `ASSERT_KNOWN(MsipKnownO_A, msip_o, clk_i, !rst_ni)
268: for (genvar k = 0; k < NumTarget; k++) begin : gen_irq_id_known
269: `ASSERT_KNOWN(IrqIdKnownO_A, irq_id_o[k], clk_i, !rst_ni)
270: end
271:
272: endmodule
273: