|  | // Copyright lowRISC contributors. | 
|  | // Licensed under the Apache License, Version 2.0, see LICENSE for details. | 
|  | // SPDX-License-Identifier: Apache-2.0 | 
|  | // | 
|  | // RISC-V Platform-Level Interrupt Gateways module | 
|  |  | 
|  | module rv_plic_gateway #( | 
|  | parameter int N_SOURCE = 32 | 
|  | ) ( | 
|  | input clk_i, | 
|  | input rst_ni, | 
|  |  | 
|  | input [N_SOURCE-1:0] src_i, | 
|  | input [N_SOURCE-1:0] le_i,      // Level0 Edge1 | 
|  |  | 
|  | input [N_SOURCE-1:0] claim_i, // $onehot0(claim_i) | 
|  | input [N_SOURCE-1:0] complete_i, // $onehot0(complete_i) | 
|  |  | 
|  | output logic [N_SOURCE-1:0] ip_o | 
|  | ); | 
|  |  | 
|  | logic [N_SOURCE-1:0] ia;    // Interrupt Active | 
|  |  | 
|  | logic [N_SOURCE-1:0] set;   // Set: (le_i) ? src_i & ~src_q : src_i ; | 
|  | logic [N_SOURCE-1:0] src_q; | 
|  |  | 
|  | always_ff @(posedge clk_i or negedge rst_ni) begin | 
|  | if (!rst_ni) src_q <= '0; | 
|  | else         src_q <= src_i; | 
|  | end | 
|  |  | 
|  | always_comb begin | 
|  | for (int i = 0 ; i < N_SOURCE; i++) begin | 
|  | set[i] = (le_i[i]) ? src_i[i] & ~src_q[i] : src_i[i] ; | 
|  | end | 
|  | end | 
|  |  | 
|  | // Interrupt pending is set by source (depends on le_i), cleared by claim_i. | 
|  | // Until interrupt is claimed, set doesn't affect ip_o. | 
|  | // RISC-V PLIC spec mentioned it can have counter for edge triggered | 
|  | // But skipped the feature as counter consumes substantial logic size. | 
|  | always_ff @(posedge clk_i or negedge rst_ni) begin | 
|  | if (!rst_ni) begin | 
|  | ip_o <= '0; | 
|  | end else begin | 
|  | ip_o <= (ip_o | (set & ~ia & ~ip_o)) & (~(ip_o & claim_i)); | 
|  | end | 
|  | end | 
|  |  | 
|  | // Interrupt active is to control ip_o. If ip_o is set then until completed | 
|  | // by target, ip_o shouldn't be set by source even claim_i can clear ip_o. | 
|  | // ia can be cleared only when ia was set. If `set` and `complete_i` happen | 
|  | // at the same time, always `set` wins. | 
|  | always_ff @(posedge clk_i or negedge rst_ni) begin | 
|  | if (!rst_ni) begin | 
|  | ia <= '0; | 
|  | end else begin | 
|  | ia <= (ia | (set & ~ia)) & (~(ia & complete_i & ~ip_o)); | 
|  | end | 
|  | end | 
|  |  | 
|  | endmodule |