162 lines
5.4 KiB
Systemverilog
162 lines
5.4 KiB
Systemverilog
|
/*
|
|||
|
Copyright 2021 Blue Liang, liangkangnan@163.com
|
|||
|
|
|||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|||
|
you may not use this file except in compliance with the License.
|
|||
|
You may obtain a copy of the License at
|
|||
|
|
|||
|
http://www.apache.org/licenses/LICENSE-2.0
|
|||
|
|
|||
|
Unless required by applicable law or agreed to in writing, software
|
|||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|||
|
See the License for the specific language governing permissions and
|
|||
|
limitations under the License.
|
|||
|
*/
|
|||
|
|
|||
|
module rvic_core (
|
|||
|
input logic clk_i,
|
|||
|
input logic rst_ni,
|
|||
|
|
|||
|
input logic [31:0] src_i,
|
|||
|
output logic [ 7:0] irq_id_o,
|
|||
|
output logic irq_o,
|
|||
|
|
|||
|
input logic reg_we_i,
|
|||
|
input logic reg_re_i,
|
|||
|
input logic [31:0] reg_wdata_i,
|
|||
|
input logic [ 3:0] reg_be_i,
|
|||
|
input logic [31:0] reg_addr_i,
|
|||
|
output logic [31:0] reg_rdata_o
|
|||
|
);
|
|||
|
|
|||
|
import rvic_reg_pkg::*;
|
|||
|
|
|||
|
rvic_reg_pkg::rvic_reg2hw_t reg2hw;
|
|||
|
rvic_reg_pkg::rvic_hw2reg_t hw2reg;
|
|||
|
|
|||
|
logic [31:0] priority_array[8];
|
|||
|
logic [31:0] irq_enable;
|
|||
|
logic [31:0] irq_pending;
|
|||
|
|
|||
|
assign priority_array[0] = reg2hw.priority0.q;
|
|||
|
assign priority_array[1] = reg2hw.priority1.q;
|
|||
|
assign priority_array[2] = reg2hw.priority2.q;
|
|||
|
assign priority_array[3] = reg2hw.priority3.q;
|
|||
|
assign priority_array[4] = reg2hw.priority4.q;
|
|||
|
assign priority_array[5] = reg2hw.priority5.q;
|
|||
|
assign priority_array[6] = reg2hw.priority6.q;
|
|||
|
assign priority_array[7] = reg2hw.priority7.q;
|
|||
|
|
|||
|
assign irq_enable = reg2hw.enable.q;
|
|||
|
assign irq_pending = reg2hw.pending.q;
|
|||
|
|
|||
|
|
|||
|
// 找出优先级最高(优先级值最大)的中断源
|
|||
|
// 二分法查找
|
|||
|
|
|||
|
logic [7:0] each_prio[32];
|
|||
|
|
|||
|
for (genvar i = 0; i < 8; i = i + 1) begin
|
|||
|
for (genvar j = 0; j < 4; j = j + 1) begin
|
|||
|
// 只有当中断使能了,优先级才有效
|
|||
|
assign each_prio[i*4+j] = priority_array[i][8*j+7:8*j] & {8{irq_enable[i*4+j]}};
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
typedef struct packed {
|
|||
|
logic [7:0] id;
|
|||
|
logic [7:0] prio;
|
|||
|
} int_info_t;
|
|||
|
|
|||
|
int_info_t l1_max[16];
|
|||
|
always_comb begin
|
|||
|
for (int i = 0; i < 16; i = i + 1) begin
|
|||
|
if (each_prio[2*i+1] > each_prio[2*i]) begin
|
|||
|
l1_max[i].id = 2*i+1;
|
|||
|
l1_max[i].prio = each_prio[2*i+1];
|
|||
|
end else begin
|
|||
|
l1_max[i].id = 2*i;
|
|||
|
l1_max[i].prio = each_prio[2*i];
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
int_info_t l2_max[8];
|
|||
|
always_comb begin
|
|||
|
for (int i = 0; i < 8; i = i + 1) begin
|
|||
|
if (l1_max[2*i+1].prio > l1_max[2*i].prio) begin
|
|||
|
l2_max[i].id = l1_max[2*i+1].id;
|
|||
|
l2_max[i].prio = l1_max[2*i+1].prio;
|
|||
|
end else begin
|
|||
|
l2_max[i].id = l1_max[2*i].id;
|
|||
|
l2_max[i].prio = l1_max[2*i].prio;
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
int_info_t l3_max[4];
|
|||
|
always_comb begin
|
|||
|
for (int i = 0; i < 4; i = i + 1) begin
|
|||
|
if (l2_max[2*i+1].prio > l2_max[2*i].prio) begin
|
|||
|
l3_max[i].id = l2_max[2*i+1].id;
|
|||
|
l3_max[i].prio = l2_max[2*i+1].prio;
|
|||
|
end else begin
|
|||
|
l3_max[i].id = l2_max[2*i].id;
|
|||
|
l3_max[i].prio = l2_max[2*i].prio;
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
int_info_t l4_max[2];
|
|||
|
always_comb begin
|
|||
|
for (int i = 0; i < 2; i = i + 1) begin
|
|||
|
if (l3_max[2*i+1].prio > l3_max[2*i].prio) begin
|
|||
|
l4_max[i].id = l3_max[2*i+1].id;
|
|||
|
l4_max[i].prio = l3_max[2*i+1].prio;
|
|||
|
end else begin
|
|||
|
l4_max[i].id = l3_max[2*i].id;
|
|||
|
l4_max[i].prio = l3_max[2*i].prio;
|
|||
|
end
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
logic [7:0] irq_id;
|
|||
|
|
|||
|
// 最终查找结果
|
|||
|
assign irq_id = (l4_max[1].prio > l4_max[0].prio) ? l4_max[1].id : l4_max[0].id;
|
|||
|
|
|||
|
// 将irq_id打一拍后,irq_id_o就与irq_o同步
|
|||
|
always_ff @ (posedge clk_i or negedge rst_ni) begin
|
|||
|
if (!rst_ni) begin
|
|||
|
irq_id_o <= 8'h0;
|
|||
|
end else begin
|
|||
|
irq_id_o <= irq_id;
|
|||
|
end
|
|||
|
end
|
|||
|
|
|||
|
// 只要有pending就向MCU发起中断请求
|
|||
|
assign irq_o = |irq_pending;
|
|||
|
|
|||
|
// 最多32个中断源
|
|||
|
logic [4:0] id = irq_id[4:0];
|
|||
|
|
|||
|
// 硬件置位pending
|
|||
|
assign hw2reg.pending.de = src_i[id] & irq_enable[id];
|
|||
|
assign hw2reg.pending.d = irq_pending | (1 << id);
|
|||
|
|
|||
|
rvic_reg_top u_rvic_reg_top (
|
|||
|
.clk_i (clk_i),
|
|||
|
.rst_ni (rst_ni),
|
|||
|
.reg2hw (reg2hw),
|
|||
|
.hw2reg (hw2reg),
|
|||
|
.reg_we (reg_we_i),
|
|||
|
.reg_re (reg_re_i),
|
|||
|
.reg_wdata (reg_wdata_i),
|
|||
|
.reg_be (reg_be_i),
|
|||
|
.reg_addr (reg_addr_i),
|
|||
|
.reg_rdata (reg_rdata_o)
|
|||
|
);
|
|||
|
|
|||
|
endmodule
|