1
+ module plic # (
2
+ parameter int SOURCES = 32 ,
3
+ parameter int TARGETS = 1 ,
4
+ parameter int PRIORITIES = 3 ,
5
+ parameter int MAX_PENDING = 32
6
+ ) (
7
+ input logic clk_i,
8
+ input logic rst_ni,
9
+
10
+ // Bus interface
11
+ input logic req_i,
12
+ input logic [31 : 0 ] addr_i,
13
+ input logic we_i,
14
+ input logic [3 : 0 ] be_i,
15
+ input logic [31 : 0 ] wdata_i,
16
+ output logic rvalid_o,
17
+ output logic [31 : 0 ] rdata_o,
18
+
19
+ // Interrupt sources
20
+ input logic [SOURCES - 1 : 0 ] irq_sources_i,
21
+ output logic [SOURCES - 1 : 0 ] irq_pending_o,
22
+
23
+ // Interrupt notification to target
24
+ output logic [TARGETS - 1 : 0 ] irq_o
25
+ );
26
+
27
+ // Register map
28
+ localparam int PRIORITY_BASE = 'h000000 ; // Source priority registers
29
+ localparam int PENDING_BASE = 'h001000 ; // Pending bits
30
+ localparam int ENABLE_BASE = 'h002000 ; // Enable bits
31
+ localparam int THRESHOLD_BASE = 'h200000 ; // Priority threshold
32
+ localparam int CLAIM_COMPLETE = 'h200004 ; // Claim/complete
33
+
34
+ // Internal registers
35
+ logic [PRIORITIES - 1 : 0 ] priorities [SOURCES ];
36
+ logic [SOURCES - 1 : 0 ] enables;
37
+ logic [PRIORITIES - 1 : 0 ] threshold;
38
+ logic [SOURCES - 1 : 0 ] pending;
39
+ logic [$clog2 (SOURCES )- 1 : 0 ] claimed_irq;
40
+
41
+ // Register interface
42
+ logic [31 : 0 ] reg_rdata;
43
+ logic reg_write;
44
+ logic reg_read;
45
+
46
+ assign reg_write = req_i & we_i;
47
+ assign reg_read = req_i & ~ we_i;
48
+
49
+ // Write handling
50
+ always_ff @ (posedge clk_i or negedge rst_ni) begin
51
+ if (! rst_ni) begin
52
+ for (int i = 0 ; i < SOURCES ; i++ ) begin
53
+ priorities[i] <= '0 ;
54
+ end
55
+ enables <= '0 ;
56
+ threshold <= '0 ;
57
+ end else if (reg_write) begin
58
+ case (addr_i[15 : 12 ])
59
+ 4'h0 : begin // Priority registers
60
+ if (addr_i[11 : 2 ] < SOURCES ) begin
61
+ priorities[addr_i[11 : 2 ]] <= wdata_i[PRIORITIES - 1 : 0 ];
62
+ end
63
+ end
64
+ 4'h2 : begin // Enable registers
65
+ if (addr_i[11 : 2 ] == 0 ) enables <= wdata_i[SOURCES - 1 : 0 ];
66
+ end
67
+ 4'h20 : begin // Threshold and claim/complete
68
+ if (addr_i[3 : 2 ] == 0 ) threshold <= wdata_i[PRIORITIES - 1 : 0 ];
69
+ else if (addr_i[3 : 2 ] == 1 ) begin
70
+ // Handle interrupt completion
71
+ if (wdata_i < SOURCES ) pending[wdata_i] <= 1'b0 ;
72
+ end
73
+ end
74
+ default : begin end
75
+ endcase
76
+ end
77
+ end
78
+
79
+ // Read handling
80
+ always_comb begin
81
+ reg_rdata = '0 ;
82
+ case (addr_i[15 : 12 ])
83
+ 4'h0 : begin // Priority registers
84
+ if (addr_i[11 : 2 ] < SOURCES ) begin
85
+ reg_rdata = {{ (32 - PRIORITIES ){ 1'b0 }} , priorities[addr_i[11 : 2 ]]} ;
86
+ end
87
+ end
88
+ 4'h1 : begin // Pending registers
89
+ if (addr_i[11 : 2 ] == 0 ) reg_rdata = pending;
90
+ end
91
+ 4'h2 : begin // Enable registers
92
+ if (addr_i[11 : 2 ] == 0 ) reg_rdata = enables;
93
+ end
94
+ 4'h20 : begin // Threshold and claim/complete
95
+ if (addr_i[3 : 2 ] == 0 ) begin
96
+ reg_rdata = {{ (32 - PRIORITIES ){ 1'b0 }} , threshold} ;
97
+ end else if (addr_i[3 : 2 ] == 1 ) begin
98
+ // Return highest priority pending interrupt
99
+ reg_rdata = claimed_irq;
100
+ end
101
+ end
102
+ default : reg_rdata = '0 ;
103
+ endcase
104
+ end
105
+
106
+ // Interrupt handling logic
107
+ always_ff @ (posedge clk_i or negedge rst_ni) begin
108
+ if (! rst_ni) begin
109
+ pending <= '0 ;
110
+ end else begin
111
+ for (int i = 0 ; i < SOURCES ; i++ ) begin
112
+ if (irq_sources_i[i] && enables[i]) pending[i] <= 1'b1 ;
113
+ end
114
+ end
115
+ end
116
+
117
+ // Find highest priority pending interrupt
118
+ always_comb begin
119
+ logic found_irq;
120
+ logic [$clog2 (SOURCES )- 1 : 0 ] highest_irq;
121
+ logic [PRIORITIES - 1 : 0 ] highest_priority;
122
+
123
+ found_irq = 1'b0 ;
124
+ highest_irq = '0 ;
125
+ highest_priority = '0 ;
126
+
127
+ for (int i = 0 ; i < SOURCES ; i++ ) begin
128
+ if (pending[i] && enables[i] && (priorities[i] > threshold) &&
129
+ (! found_irq || priorities[i] > highest_priority)) begin
130
+ found_irq = 1'b1 ;
131
+ highest_irq = i;
132
+ highest_priority = priorities[i];
133
+ end
134
+ end
135
+
136
+ claimed_irq = highest_irq;
137
+ irq_o = found_irq;
138
+ end
139
+
140
+ assign irq_pending_o = pending;
141
+
142
+ // Response valid signal
143
+ always_ff @ (posedge clk_i or negedge rst_ni) begin
144
+ if (! rst_ni) begin
145
+ rvalid_o <= 1'b0 ;
146
+ end else begin
147
+ rvalid_o <= req_i;
148
+ end
149
+ end
150
+
151
+ assign rdata_o = reg_rdata;
152
+
153
+ endmodule
0 commit comments