hw/ip/rv_plic/rtl/rv_plic_gateway.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: // RISC-V Platform-Level Interrupt Gateways module
6:
7: module rv_plic_gateway #(
8: parameter int N_SOURCE = 32
9: ) (
10: input clk_i,
11: input rst_ni,
12:
13: input [N_SOURCE-1:0] src,
14: input [N_SOURCE-1:0] le, // Level0 Edge1
15:
16: input [N_SOURCE-1:0] claim, // $onehot0(claim)
17: input [N_SOURCE-1:0] complete, // $onehot0(complete)
18:
19: output logic [N_SOURCE-1:0] ip
20: );
21:
22: logic [N_SOURCE-1:0] ia; // Interrupt Active
23:
24: logic [N_SOURCE-1:0] set; // Set: (le) ? src & ~src_d : src ;
25: logic [N_SOURCE-1:0] src_d;
26:
27: always_ff @(posedge clk_i or negedge rst_ni) begin
28: if (!rst_ni) src_d <= '0;
29: else src_d <= src;
30: end
31:
32: always_comb begin
33: for (int i = 0 ; i < N_SOURCE; i++) begin
34: set[i] = (le[i]) ? src[i] & ~src_d[i] : src[i] ;
35: end
36: end
37:
38: // Interrupt pending is set by source (depends on le), cleared by claim.
39: // Until interrupt is claimed, set doesn't affect ip.
40: // RISC-V PLIC spec mentioned it can have counter for edge triggered
41: // But skipped the feature as counter consumes substantial logic size.
42: always_ff @(posedge clk_i or negedge rst_ni) begin
43: if (!rst_ni) begin
44: ip <= '0;
45: end else begin
46: ip <= (ip | (set & ~ia & ~ip)) & (~(ip & claim));
47: end
48: end
49:
50: // Interrupt active is to control ip. If ip is set then until completed
51: // by target, ip shouldn't be set by source even claim can clear ip.
52: // ia can be cleared only when ia was set. If `set` and `complete` happen
53: // at the same time, always `set` wins.
54: always_ff @(posedge clk_i or negedge rst_ni) begin
55: if (!rst_ni) begin
56: ia <= '0;
57: end else begin
58: ia <= (ia | (set & ~ia)) & (~(ia & complete & ~ip));
59: end
60: end
61:
62: endmodule
63: