rtl:perips: rewrite rvic
Signed-off-by: liangkangnan <liangkangnan@163.com>pull/4/head
parent
477d9efc34
commit
d4b670217a
|
@ -35,7 +35,6 @@
|
||||||
|
|
||||||
../rtl/perips/ram.sv
|
../rtl/perips/ram.sv
|
||||||
../rtl/perips/rom.sv
|
../rtl/perips/rom.sv
|
||||||
../rtl/perips/rvic.sv
|
|
||||||
../rtl/perips/uart/uart_reg_pkg.sv
|
../rtl/perips/uart/uart_reg_pkg.sv
|
||||||
../rtl/perips/uart/uart_reg_top.sv
|
../rtl/perips/uart/uart_reg_top.sv
|
||||||
../rtl/perips/uart/uart_core.sv
|
../rtl/perips/uart/uart_core.sv
|
||||||
|
@ -50,6 +49,10 @@
|
||||||
../rtl/perips/gpio/gpio_reg_top.sv
|
../rtl/perips/gpio/gpio_reg_top.sv
|
||||||
../rtl/perips/gpio/gpio_core.sv
|
../rtl/perips/gpio/gpio_core.sv
|
||||||
../rtl/perips/gpio/gpio_top.sv
|
../rtl/perips/gpio/gpio_top.sv
|
||||||
|
../rtl/perips/rvic/rvic_reg_pkg.sv
|
||||||
|
../rtl/perips/rvic/rvic_reg_top.sv
|
||||||
|
../rtl/perips/rvic/rvic_core.sv
|
||||||
|
../rtl/perips/rvic/rvic_top.sv
|
||||||
|
|
||||||
../rtl/sys_bus/obi_interconnect.sv
|
../rtl/sys_bus/obi_interconnect.sv
|
||||||
../rtl/sys_bus/obi_interconnect_master_sel.sv
|
../rtl/sys_bus/obi_interconnect_master_sel.sv
|
||||||
|
|
|
@ -1,240 +0,0 @@
|
||||||
/*
|
|
||||||
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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
`include "../core/defines.sv"
|
|
||||||
|
|
||||||
// RISC-V中断控制器
|
|
||||||
// 支持32个中断源,每个中断源支持256级优先级
|
|
||||||
module rvic #(
|
|
||||||
|
|
||||||
)(
|
|
||||||
|
|
||||||
input logic clk_i,
|
|
||||||
input logic rst_ni,
|
|
||||||
|
|
||||||
input logic [31:0] src_i,
|
|
||||||
output logic irq_o, // 中断请求信号
|
|
||||||
output logic [7:0] irq_id_o, // 中断号
|
|
||||||
|
|
||||||
input logic [31:0] addr_i,
|
|
||||||
input logic [31:0] data_i,
|
|
||||||
input logic [3:0] be_i,
|
|
||||||
input logic we_i,
|
|
||||||
output logic [31:0] data_o
|
|
||||||
|
|
||||||
);
|
|
||||||
|
|
||||||
// 寄存器地址偏移
|
|
||||||
parameter logic [7:0] IE_OFFSET = 8'h0;
|
|
||||||
parameter logic [7:0] IP_OFFSET = 8'h4;
|
|
||||||
parameter logic [7:0] PRIO0_OFFSET = 8'h8;
|
|
||||||
parameter logic [7:0] PRIO1_OFFSET = 8'hc;
|
|
||||||
parameter logic [7:0] PRIO2_OFFSET = 8'h10;
|
|
||||||
parameter logic [7:0] PRIO3_OFFSET = 8'h14;
|
|
||||||
parameter logic [7:0] PRIO4_OFFSET = 8'h18;
|
|
||||||
parameter logic [7:0] PRIO5_OFFSET = 8'h1c;
|
|
||||||
parameter logic [7:0] PRIO6_OFFSET = 8'h20;
|
|
||||||
parameter logic [7:0] PRIO7_OFFSET = 8'h24;
|
|
||||||
parameter logic [7:0] ID_OFFSET = 8'h28;
|
|
||||||
|
|
||||||
logic ie_we;
|
|
||||||
logic ip_we;
|
|
||||||
logic [7:0] prio_we;
|
|
||||||
|
|
||||||
logic [31:0] prio_q[8];
|
|
||||||
logic [31:0] ie_q;
|
|
||||||
logic [31:0] ip_q;
|
|
||||||
logic [31:0] id_q;
|
|
||||||
|
|
||||||
logic [10:0] addr_hit;
|
|
||||||
logic [7:0] reg_addr = addr_i[7:0];
|
|
||||||
|
|
||||||
always_comb begin
|
|
||||||
addr_hit = 11'h0;
|
|
||||||
addr_hit[ 0] = (reg_addr == IE_OFFSET);
|
|
||||||
addr_hit[ 1] = (reg_addr == IP_OFFSET);
|
|
||||||
addr_hit[ 2] = (reg_addr == PRIO0_OFFSET);
|
|
||||||
addr_hit[ 3] = (reg_addr == PRIO1_OFFSET);
|
|
||||||
addr_hit[ 4] = (reg_addr == PRIO2_OFFSET);
|
|
||||||
addr_hit[ 5] = (reg_addr == PRIO3_OFFSET);
|
|
||||||
addr_hit[ 6] = (reg_addr == PRIO4_OFFSET);
|
|
||||||
addr_hit[ 7] = (reg_addr == PRIO5_OFFSET);
|
|
||||||
addr_hit[ 8] = (reg_addr == PRIO6_OFFSET);
|
|
||||||
addr_hit[ 9] = (reg_addr == PRIO7_OFFSET);
|
|
||||||
addr_hit[10] = (reg_addr == ID_OFFSET);
|
|
||||||
end
|
|
||||||
|
|
||||||
assign ie_we = we_i & addr_hit[0];
|
|
||||||
assign ip_we = we_i & addr_hit[1];
|
|
||||||
for (genvar p = 0; p < 8; p = p + 1) begin
|
|
||||||
assign prio_we[p] = we_i & addr_hit[p + 2];
|
|
||||||
end
|
|
||||||
|
|
||||||
// 写寄存器
|
|
||||||
logic [31:0] reg_wdata;
|
|
||||||
|
|
||||||
always_comb begin
|
|
||||||
reg_wdata = 32'h0;
|
|
||||||
|
|
||||||
// IP寄存器是写1清零的,因此要区别对待
|
|
||||||
if (ip_we) begin
|
|
||||||
reg_wdata = ip_q;
|
|
||||||
if (be_i[0])
|
|
||||||
reg_wdata[7:0] = ip_q[7:0] & (~data_i[7:0]);
|
|
||||||
if (be_i[1])
|
|
||||||
reg_wdata[15:8] = ip_q[15:8] & (~data_i[15:8]);
|
|
||||||
if (be_i[2])
|
|
||||||
reg_wdata[23:16] = ip_q[23:16] & (~data_i[23:16]);
|
|
||||||
if (be_i[3])
|
|
||||||
reg_wdata[31:24] = ip_q[31:24] & (~data_i[31:24]);
|
|
||||||
end else begin
|
|
||||||
if (ie_we) begin
|
|
||||||
reg_wdata = ie_q;
|
|
||||||
end
|
|
||||||
for (int j = 0; j < 8; j = j + 1) begin
|
|
||||||
if (prio_we[j]) begin
|
|
||||||
reg_wdata = prio_q[j];
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if (be_i[0])
|
|
||||||
reg_wdata[7:0] = data_i[7:0];
|
|
||||||
if (be_i[1])
|
|
||||||
reg_wdata[15:8] = data_i[15:8];
|
|
||||||
if (be_i[2])
|
|
||||||
reg_wdata[23:16] = data_i[23:16];
|
|
||||||
if (be_i[3])
|
|
||||||
reg_wdata[31:24] = data_i[31:24];
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
gen_en_dff #(32) ie_ff(clk_i, rst_ni, ie_we, reg_wdata, ie_q);
|
|
||||||
|
|
||||||
logic [31:0] ip_wdata;
|
|
||||||
|
|
||||||
assign ip_wdata = ip_we ? reg_wdata : (ip_q | src_i);
|
|
||||||
gen_en_dff #(32) ip_ff(clk_i, rst_ni, 1'b1, ip_wdata, ip_q);
|
|
||||||
|
|
||||||
for (genvar m = 0; m < 8; m = m + 1) begin
|
|
||||||
gen_en_dff #(32) prio_ff(clk_i, rst_ni, prio_we[m], reg_wdata, prio_q[m]);
|
|
||||||
end
|
|
||||||
|
|
||||||
// 读寄存器
|
|
||||||
always_ff @ (posedge clk_i or negedge rst_ni) begin
|
|
||||||
if (!rst_ni) begin
|
|
||||||
data_o <= 32'h0;
|
|
||||||
end else begin
|
|
||||||
case (addr_i[7:0])
|
|
||||||
IE_OFFSET: data_o <= ie_q;
|
|
||||||
IP_OFFSET: data_o <= ip_q;
|
|
||||||
PRIO0_OFFSET: data_o <= prio_q[0];
|
|
||||||
PRIO1_OFFSET: data_o <= prio_q[1];
|
|
||||||
PRIO2_OFFSET: data_o <= prio_q[2];
|
|
||||||
PRIO3_OFFSET: data_o <= prio_q[3];
|
|
||||||
PRIO4_OFFSET: data_o <= prio_q[4];
|
|
||||||
PRIO5_OFFSET: data_o <= prio_q[5];
|
|
||||||
PRIO6_OFFSET: data_o <= prio_q[6];
|
|
||||||
PRIO7_OFFSET: data_o <= prio_q[7];
|
|
||||||
ID_OFFSET: data_o <= id_q;
|
|
||||||
default: data_o <= 32'h0;
|
|
||||||
endcase
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
// 找出优先级最高(优先级值最大)的中断源
|
|
||||||
// 二分法查找
|
|
||||||
|
|
||||||
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] = prio_q[i][8*j+7:8*j] & {8{ie_q[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;
|
|
||||||
|
|
||||||
always_ff @ (posedge clk_i or negedge rst_ni) begin
|
|
||||||
if (!rst_ni) begin
|
|
||||||
irq_id_o <= 8'h0;
|
|
||||||
irq_o <= 1'b0;
|
|
||||||
end else begin
|
|
||||||
irq_id_o <= irq_id;
|
|
||||||
irq_o <= |((src_i | ip_q) & ie_q);
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
assign id_q = {24'h0, irq_id};
|
|
||||||
|
|
||||||
endmodule
|
|
|
@ -0,0 +1,113 @@
|
||||||
|
// Copyright lowRISC contributors.
|
||||||
|
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
{ name: "rvic",
|
||||||
|
clocking: [{clock: "clk_i", reset: "rst_ni"}],
|
||||||
|
bus_interfaces: [
|
||||||
|
{ protocol: "tlul", direction: "device" }
|
||||||
|
],
|
||||||
|
regwidth: "32",
|
||||||
|
registers: [
|
||||||
|
{ name: "ENABLE",
|
||||||
|
desc: "RVIC interrupt enable register",
|
||||||
|
swaccess: "rw",
|
||||||
|
hwaccess: "hro",
|
||||||
|
fields: [
|
||||||
|
{ bits: "31:0",
|
||||||
|
desc: "one bit for one interrupt source",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
{ name: "PENDING",
|
||||||
|
desc: "RVIC interrupt pending register",
|
||||||
|
swaccess: "rw",
|
||||||
|
hwaccess: "hrw",
|
||||||
|
fields: [
|
||||||
|
{ bits: "31:0",
|
||||||
|
swaccess: "rw1c",
|
||||||
|
desc: "one bit for one interrupt source",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
{ name: "PRIORITY0",
|
||||||
|
desc: "RVIC interrupt priority0 register",
|
||||||
|
swaccess: "rw",
|
||||||
|
hwaccess: "hro",
|
||||||
|
fields: [
|
||||||
|
{ bits: "31:0",
|
||||||
|
desc: "eight bits for one interrupt source",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
{ name: "PRIORITY1",
|
||||||
|
desc: "RVIC interrupt priority1 register",
|
||||||
|
swaccess: "rw",
|
||||||
|
hwaccess: "hro",
|
||||||
|
fields: [
|
||||||
|
{ bits: "31:0",
|
||||||
|
desc: "eight bits for one interrupt source",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
{ name: "PRIORITY2",
|
||||||
|
desc: "RVIC interrupt priority2 register",
|
||||||
|
swaccess: "rw",
|
||||||
|
hwaccess: "hro",
|
||||||
|
fields: [
|
||||||
|
{ bits: "31:0",
|
||||||
|
desc: "eight bits for one interrupt source",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
{ name: "PRIORITY3",
|
||||||
|
desc: "RVIC interrupt priority3 register",
|
||||||
|
swaccess: "rw",
|
||||||
|
hwaccess: "hro",
|
||||||
|
fields: [
|
||||||
|
{ bits: "31:0",
|
||||||
|
desc: "eight bits for one interrupt source",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
{ name: "PRIORITY4",
|
||||||
|
desc: "RVIC interrupt priority4 register",
|
||||||
|
swaccess: "rw",
|
||||||
|
hwaccess: "hro",
|
||||||
|
fields: [
|
||||||
|
{ bits: "31:0",
|
||||||
|
desc: "eight bits for one interrupt source",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
{ name: "PRIORITY5",
|
||||||
|
desc: "RVIC interrupt priority5 register",
|
||||||
|
swaccess: "rw",
|
||||||
|
hwaccess: "hro",
|
||||||
|
fields: [
|
||||||
|
{ bits: "31:0",
|
||||||
|
desc: "eight bits for one interrupt source",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
{ name: "PRIORITY6",
|
||||||
|
desc: "RVIC interrupt priority6 register",
|
||||||
|
swaccess: "rw",
|
||||||
|
hwaccess: "hro",
|
||||||
|
fields: [
|
||||||
|
{ bits: "31:0",
|
||||||
|
desc: "eight bits for one interrupt source",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
{ name: "PRIORITY7",
|
||||||
|
desc: "RVIC interrupt priority7 register",
|
||||||
|
swaccess: "rw",
|
||||||
|
hwaccess: "hro",
|
||||||
|
fields: [
|
||||||
|
{ bits: "31:0",
|
||||||
|
desc: "eight bits for one interrupt source",
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,161 @@
|
||||||
|
/*
|
||||||
|
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
|
|
@ -0,0 +1,121 @@
|
||||||
|
// Copyright lowRISC contributors.
|
||||||
|
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
// Register Package auto-generated by `reggen` containing data structure
|
||||||
|
|
||||||
|
package rvic_reg_pkg;
|
||||||
|
|
||||||
|
// Address widths within the block
|
||||||
|
parameter int BlockAw = 6;
|
||||||
|
|
||||||
|
////////////////////////////
|
||||||
|
// Typedefs for registers //
|
||||||
|
////////////////////////////
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic [31:0] q;
|
||||||
|
} rvic_reg2hw_enable_reg_t;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic [31:0] q;
|
||||||
|
} rvic_reg2hw_pending_reg_t;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic [31:0] q;
|
||||||
|
} rvic_reg2hw_priority0_reg_t;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic [31:0] q;
|
||||||
|
} rvic_reg2hw_priority1_reg_t;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic [31:0] q;
|
||||||
|
} rvic_reg2hw_priority2_reg_t;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic [31:0] q;
|
||||||
|
} rvic_reg2hw_priority3_reg_t;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic [31:0] q;
|
||||||
|
} rvic_reg2hw_priority4_reg_t;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic [31:0] q;
|
||||||
|
} rvic_reg2hw_priority5_reg_t;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic [31:0] q;
|
||||||
|
} rvic_reg2hw_priority6_reg_t;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic [31:0] q;
|
||||||
|
} rvic_reg2hw_priority7_reg_t;
|
||||||
|
|
||||||
|
typedef struct packed {
|
||||||
|
logic [31:0] d;
|
||||||
|
logic de;
|
||||||
|
} rvic_hw2reg_pending_reg_t;
|
||||||
|
|
||||||
|
// Register -> HW type
|
||||||
|
typedef struct packed {
|
||||||
|
rvic_reg2hw_enable_reg_t enable; // [319:288]
|
||||||
|
rvic_reg2hw_pending_reg_t pending; // [287:256]
|
||||||
|
rvic_reg2hw_priority0_reg_t priority0; // [255:224]
|
||||||
|
rvic_reg2hw_priority1_reg_t priority1; // [223:192]
|
||||||
|
rvic_reg2hw_priority2_reg_t priority2; // [191:160]
|
||||||
|
rvic_reg2hw_priority3_reg_t priority3; // [159:128]
|
||||||
|
rvic_reg2hw_priority4_reg_t priority4; // [127:96]
|
||||||
|
rvic_reg2hw_priority5_reg_t priority5; // [95:64]
|
||||||
|
rvic_reg2hw_priority6_reg_t priority6; // [63:32]
|
||||||
|
rvic_reg2hw_priority7_reg_t priority7; // [31:0]
|
||||||
|
} rvic_reg2hw_t;
|
||||||
|
|
||||||
|
// HW -> register type
|
||||||
|
typedef struct packed {
|
||||||
|
rvic_hw2reg_pending_reg_t pending; // [32:0]
|
||||||
|
} rvic_hw2reg_t;
|
||||||
|
|
||||||
|
// Register offsets
|
||||||
|
parameter logic [BlockAw-1:0] RVIC_ENABLE_OFFSET = 6'h0;
|
||||||
|
parameter logic [BlockAw-1:0] RVIC_PENDING_OFFSET = 6'h4;
|
||||||
|
parameter logic [BlockAw-1:0] RVIC_PRIORITY0_OFFSET = 6'h8;
|
||||||
|
parameter logic [BlockAw-1:0] RVIC_PRIORITY1_OFFSET = 6'hc;
|
||||||
|
parameter logic [BlockAw-1:0] RVIC_PRIORITY2_OFFSET = 6'h10;
|
||||||
|
parameter logic [BlockAw-1:0] RVIC_PRIORITY3_OFFSET = 6'h14;
|
||||||
|
parameter logic [BlockAw-1:0] RVIC_PRIORITY4_OFFSET = 6'h18;
|
||||||
|
parameter logic [BlockAw-1:0] RVIC_PRIORITY5_OFFSET = 6'h1c;
|
||||||
|
parameter logic [BlockAw-1:0] RVIC_PRIORITY6_OFFSET = 6'h20;
|
||||||
|
parameter logic [BlockAw-1:0] RVIC_PRIORITY7_OFFSET = 6'h24;
|
||||||
|
|
||||||
|
// Register index
|
||||||
|
typedef enum int {
|
||||||
|
RVIC_ENABLE,
|
||||||
|
RVIC_PENDING,
|
||||||
|
RVIC_PRIORITY0,
|
||||||
|
RVIC_PRIORITY1,
|
||||||
|
RVIC_PRIORITY2,
|
||||||
|
RVIC_PRIORITY3,
|
||||||
|
RVIC_PRIORITY4,
|
||||||
|
RVIC_PRIORITY5,
|
||||||
|
RVIC_PRIORITY6,
|
||||||
|
RVIC_PRIORITY7
|
||||||
|
} rvic_id_e;
|
||||||
|
|
||||||
|
// Register width information to check illegal writes
|
||||||
|
parameter logic [3:0] RVIC_PERMIT [10] = '{
|
||||||
|
4'b1111, // index[0] RVIC_ENABLE
|
||||||
|
4'b1111, // index[1] RVIC_PENDING
|
||||||
|
4'b1111, // index[2] RVIC_PRIORITY0
|
||||||
|
4'b1111, // index[3] RVIC_PRIORITY1
|
||||||
|
4'b1111, // index[4] RVIC_PRIORITY2
|
||||||
|
4'b1111, // index[5] RVIC_PRIORITY3
|
||||||
|
4'b1111, // index[6] RVIC_PRIORITY4
|
||||||
|
4'b1111, // index[7] RVIC_PRIORITY5
|
||||||
|
4'b1111, // index[8] RVIC_PRIORITY6
|
||||||
|
4'b1111 // index[9] RVIC_PRIORITY7
|
||||||
|
};
|
||||||
|
|
||||||
|
endpackage
|
||||||
|
|
|
@ -0,0 +1,465 @@
|
||||||
|
// Copyright lowRISC contributors.
|
||||||
|
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
//
|
||||||
|
// Register Top module auto-generated by `reggen`
|
||||||
|
|
||||||
|
|
||||||
|
module rvic_reg_top (
|
||||||
|
input logic clk_i,
|
||||||
|
input logic rst_ni,
|
||||||
|
|
||||||
|
// To HW
|
||||||
|
output rvic_reg_pkg::rvic_reg2hw_t reg2hw, // Write
|
||||||
|
input rvic_reg_pkg::rvic_hw2reg_t hw2reg, // Read
|
||||||
|
|
||||||
|
input logic reg_we,
|
||||||
|
input logic reg_re,
|
||||||
|
input logic [31:0] reg_wdata,
|
||||||
|
input logic [ 3:0] reg_be,
|
||||||
|
input logic [31:0] reg_addr,
|
||||||
|
output logic [31:0] reg_rdata
|
||||||
|
);
|
||||||
|
|
||||||
|
import rvic_reg_pkg::* ;
|
||||||
|
|
||||||
|
localparam int AW = 6;
|
||||||
|
localparam int DW = 32;
|
||||||
|
localparam int DBW = DW/8; // Byte Width
|
||||||
|
|
||||||
|
logic reg_error;
|
||||||
|
logic addrmiss, wr_err;
|
||||||
|
|
||||||
|
logic [DW-1:0] reg_rdata_next;
|
||||||
|
|
||||||
|
assign reg_rdata = reg_rdata_next;
|
||||||
|
assign reg_error = wr_err;
|
||||||
|
|
||||||
|
// Define SW related signals
|
||||||
|
// Format: <reg>_<field>_{wd|we|qs}
|
||||||
|
// or <reg>_{wd|we|qs} if field == 1 or 0
|
||||||
|
logic enable_we;
|
||||||
|
logic [31:0] enable_qs;
|
||||||
|
logic [31:0] enable_wd;
|
||||||
|
logic pending_we;
|
||||||
|
logic [31:0] pending_qs;
|
||||||
|
logic [31:0] pending_wd;
|
||||||
|
logic priority0_we;
|
||||||
|
logic [31:0] priority0_qs;
|
||||||
|
logic [31:0] priority0_wd;
|
||||||
|
logic priority1_we;
|
||||||
|
logic [31:0] priority1_qs;
|
||||||
|
logic [31:0] priority1_wd;
|
||||||
|
logic priority2_we;
|
||||||
|
logic [31:0] priority2_qs;
|
||||||
|
logic [31:0] priority2_wd;
|
||||||
|
logic priority3_we;
|
||||||
|
logic [31:0] priority3_qs;
|
||||||
|
logic [31:0] priority3_wd;
|
||||||
|
logic priority4_we;
|
||||||
|
logic [31:0] priority4_qs;
|
||||||
|
logic [31:0] priority4_wd;
|
||||||
|
logic priority5_we;
|
||||||
|
logic [31:0] priority5_qs;
|
||||||
|
logic [31:0] priority5_wd;
|
||||||
|
logic priority6_we;
|
||||||
|
logic [31:0] priority6_qs;
|
||||||
|
logic [31:0] priority6_wd;
|
||||||
|
logic priority7_we;
|
||||||
|
logic [31:0] priority7_qs;
|
||||||
|
logic [31:0] priority7_wd;
|
||||||
|
|
||||||
|
// Register instances
|
||||||
|
// R[enable]: V(False)
|
||||||
|
|
||||||
|
prim_subreg #(
|
||||||
|
.DW (32),
|
||||||
|
.SWACCESS("RW"),
|
||||||
|
.RESVAL (32'h0)
|
||||||
|
) u_enable (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_ni (rst_ni),
|
||||||
|
|
||||||
|
// from register interface
|
||||||
|
.we (enable_we),
|
||||||
|
.wd (enable_wd),
|
||||||
|
|
||||||
|
// from internal hardware
|
||||||
|
.de (1'b0),
|
||||||
|
.d ('0),
|
||||||
|
|
||||||
|
// to internal hardware
|
||||||
|
.qe (),
|
||||||
|
.q (reg2hw.enable.q),
|
||||||
|
|
||||||
|
// to register interface (read)
|
||||||
|
.qs (enable_qs)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// R[pending]: V(False)
|
||||||
|
|
||||||
|
prim_subreg #(
|
||||||
|
.DW (32),
|
||||||
|
.SWACCESS("W1C"),
|
||||||
|
.RESVAL (32'h0)
|
||||||
|
) u_pending (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_ni (rst_ni),
|
||||||
|
|
||||||
|
// from register interface
|
||||||
|
.we (pending_we),
|
||||||
|
.wd (pending_wd),
|
||||||
|
|
||||||
|
// from internal hardware
|
||||||
|
.de (hw2reg.pending.de),
|
||||||
|
.d (hw2reg.pending.d),
|
||||||
|
|
||||||
|
// to internal hardware
|
||||||
|
.qe (),
|
||||||
|
.q (reg2hw.pending.q),
|
||||||
|
|
||||||
|
// to register interface (read)
|
||||||
|
.qs (pending_qs)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// R[priority0]: V(False)
|
||||||
|
|
||||||
|
prim_subreg #(
|
||||||
|
.DW (32),
|
||||||
|
.SWACCESS("RW"),
|
||||||
|
.RESVAL (32'h0)
|
||||||
|
) u_priority0 (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_ni (rst_ni),
|
||||||
|
|
||||||
|
// from register interface
|
||||||
|
.we (priority0_we),
|
||||||
|
.wd (priority0_wd),
|
||||||
|
|
||||||
|
// from internal hardware
|
||||||
|
.de (1'b0),
|
||||||
|
.d ('0),
|
||||||
|
|
||||||
|
// to internal hardware
|
||||||
|
.qe (),
|
||||||
|
.q (reg2hw.priority0.q),
|
||||||
|
|
||||||
|
// to register interface (read)
|
||||||
|
.qs (priority0_qs)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// R[priority1]: V(False)
|
||||||
|
|
||||||
|
prim_subreg #(
|
||||||
|
.DW (32),
|
||||||
|
.SWACCESS("RW"),
|
||||||
|
.RESVAL (32'h0)
|
||||||
|
) u_priority1 (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_ni (rst_ni),
|
||||||
|
|
||||||
|
// from register interface
|
||||||
|
.we (priority1_we),
|
||||||
|
.wd (priority1_wd),
|
||||||
|
|
||||||
|
// from internal hardware
|
||||||
|
.de (1'b0),
|
||||||
|
.d ('0),
|
||||||
|
|
||||||
|
// to internal hardware
|
||||||
|
.qe (),
|
||||||
|
.q (reg2hw.priority1.q),
|
||||||
|
|
||||||
|
// to register interface (read)
|
||||||
|
.qs (priority1_qs)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// R[priority2]: V(False)
|
||||||
|
|
||||||
|
prim_subreg #(
|
||||||
|
.DW (32),
|
||||||
|
.SWACCESS("RW"),
|
||||||
|
.RESVAL (32'h0)
|
||||||
|
) u_priority2 (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_ni (rst_ni),
|
||||||
|
|
||||||
|
// from register interface
|
||||||
|
.we (priority2_we),
|
||||||
|
.wd (priority2_wd),
|
||||||
|
|
||||||
|
// from internal hardware
|
||||||
|
.de (1'b0),
|
||||||
|
.d ('0),
|
||||||
|
|
||||||
|
// to internal hardware
|
||||||
|
.qe (),
|
||||||
|
.q (reg2hw.priority2.q),
|
||||||
|
|
||||||
|
// to register interface (read)
|
||||||
|
.qs (priority2_qs)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// R[priority3]: V(False)
|
||||||
|
|
||||||
|
prim_subreg #(
|
||||||
|
.DW (32),
|
||||||
|
.SWACCESS("RW"),
|
||||||
|
.RESVAL (32'h0)
|
||||||
|
) u_priority3 (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_ni (rst_ni),
|
||||||
|
|
||||||
|
// from register interface
|
||||||
|
.we (priority3_we),
|
||||||
|
.wd (priority3_wd),
|
||||||
|
|
||||||
|
// from internal hardware
|
||||||
|
.de (1'b0),
|
||||||
|
.d ('0),
|
||||||
|
|
||||||
|
// to internal hardware
|
||||||
|
.qe (),
|
||||||
|
.q (reg2hw.priority3.q),
|
||||||
|
|
||||||
|
// to register interface (read)
|
||||||
|
.qs (priority3_qs)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// R[priority4]: V(False)
|
||||||
|
|
||||||
|
prim_subreg #(
|
||||||
|
.DW (32),
|
||||||
|
.SWACCESS("RW"),
|
||||||
|
.RESVAL (32'h0)
|
||||||
|
) u_priority4 (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_ni (rst_ni),
|
||||||
|
|
||||||
|
// from register interface
|
||||||
|
.we (priority4_we),
|
||||||
|
.wd (priority4_wd),
|
||||||
|
|
||||||
|
// from internal hardware
|
||||||
|
.de (1'b0),
|
||||||
|
.d ('0),
|
||||||
|
|
||||||
|
// to internal hardware
|
||||||
|
.qe (),
|
||||||
|
.q (reg2hw.priority4.q),
|
||||||
|
|
||||||
|
// to register interface (read)
|
||||||
|
.qs (priority4_qs)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// R[priority5]: V(False)
|
||||||
|
|
||||||
|
prim_subreg #(
|
||||||
|
.DW (32),
|
||||||
|
.SWACCESS("RW"),
|
||||||
|
.RESVAL (32'h0)
|
||||||
|
) u_priority5 (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_ni (rst_ni),
|
||||||
|
|
||||||
|
// from register interface
|
||||||
|
.we (priority5_we),
|
||||||
|
.wd (priority5_wd),
|
||||||
|
|
||||||
|
// from internal hardware
|
||||||
|
.de (1'b0),
|
||||||
|
.d ('0),
|
||||||
|
|
||||||
|
// to internal hardware
|
||||||
|
.qe (),
|
||||||
|
.q (reg2hw.priority5.q),
|
||||||
|
|
||||||
|
// to register interface (read)
|
||||||
|
.qs (priority5_qs)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// R[priority6]: V(False)
|
||||||
|
|
||||||
|
prim_subreg #(
|
||||||
|
.DW (32),
|
||||||
|
.SWACCESS("RW"),
|
||||||
|
.RESVAL (32'h0)
|
||||||
|
) u_priority6 (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_ni (rst_ni),
|
||||||
|
|
||||||
|
// from register interface
|
||||||
|
.we (priority6_we),
|
||||||
|
.wd (priority6_wd),
|
||||||
|
|
||||||
|
// from internal hardware
|
||||||
|
.de (1'b0),
|
||||||
|
.d ('0),
|
||||||
|
|
||||||
|
// to internal hardware
|
||||||
|
.qe (),
|
||||||
|
.q (reg2hw.priority6.q),
|
||||||
|
|
||||||
|
// to register interface (read)
|
||||||
|
.qs (priority6_qs)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
// R[priority7]: V(False)
|
||||||
|
|
||||||
|
prim_subreg #(
|
||||||
|
.DW (32),
|
||||||
|
.SWACCESS("RW"),
|
||||||
|
.RESVAL (32'h0)
|
||||||
|
) u_priority7 (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_ni (rst_ni),
|
||||||
|
|
||||||
|
// from register interface
|
||||||
|
.we (priority7_we),
|
||||||
|
.wd (priority7_wd),
|
||||||
|
|
||||||
|
// from internal hardware
|
||||||
|
.de (1'b0),
|
||||||
|
.d ('0),
|
||||||
|
|
||||||
|
// to internal hardware
|
||||||
|
.qe (),
|
||||||
|
.q (reg2hw.priority7.q),
|
||||||
|
|
||||||
|
// to register interface (read)
|
||||||
|
.qs (priority7_qs)
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
logic [9:0] addr_hit;
|
||||||
|
always_comb begin
|
||||||
|
addr_hit = '0;
|
||||||
|
addr_hit[0] = (reg_addr == RVIC_ENABLE_OFFSET);
|
||||||
|
addr_hit[1] = (reg_addr == RVIC_PENDING_OFFSET);
|
||||||
|
addr_hit[2] = (reg_addr == RVIC_PRIORITY0_OFFSET);
|
||||||
|
addr_hit[3] = (reg_addr == RVIC_PRIORITY1_OFFSET);
|
||||||
|
addr_hit[4] = (reg_addr == RVIC_PRIORITY2_OFFSET);
|
||||||
|
addr_hit[5] = (reg_addr == RVIC_PRIORITY3_OFFSET);
|
||||||
|
addr_hit[6] = (reg_addr == RVIC_PRIORITY4_OFFSET);
|
||||||
|
addr_hit[7] = (reg_addr == RVIC_PRIORITY5_OFFSET);
|
||||||
|
addr_hit[8] = (reg_addr == RVIC_PRIORITY6_OFFSET);
|
||||||
|
addr_hit[9] = (reg_addr == RVIC_PRIORITY7_OFFSET);
|
||||||
|
end
|
||||||
|
|
||||||
|
assign addrmiss = (reg_re || reg_we) ? ~|addr_hit : 1'b0 ;
|
||||||
|
|
||||||
|
// Check sub-word write is permitted
|
||||||
|
always_comb begin
|
||||||
|
wr_err = (reg_we &
|
||||||
|
((addr_hit[0] & (|(RVIC_PERMIT[0] & ~reg_be))) |
|
||||||
|
(addr_hit[1] & (|(RVIC_PERMIT[1] & ~reg_be))) |
|
||||||
|
(addr_hit[2] & (|(RVIC_PERMIT[2] & ~reg_be))) |
|
||||||
|
(addr_hit[3] & (|(RVIC_PERMIT[3] & ~reg_be))) |
|
||||||
|
(addr_hit[4] & (|(RVIC_PERMIT[4] & ~reg_be))) |
|
||||||
|
(addr_hit[5] & (|(RVIC_PERMIT[5] & ~reg_be))) |
|
||||||
|
(addr_hit[6] & (|(RVIC_PERMIT[6] & ~reg_be))) |
|
||||||
|
(addr_hit[7] & (|(RVIC_PERMIT[7] & ~reg_be))) |
|
||||||
|
(addr_hit[8] & (|(RVIC_PERMIT[8] & ~reg_be))) |
|
||||||
|
(addr_hit[9] & (|(RVIC_PERMIT[9] & ~reg_be)))));
|
||||||
|
end
|
||||||
|
|
||||||
|
assign enable_we = addr_hit[0] & reg_we & !reg_error;
|
||||||
|
|
||||||
|
assign enable_wd = reg_wdata[31:0];
|
||||||
|
assign pending_we = addr_hit[1] & reg_we & !reg_error;
|
||||||
|
|
||||||
|
assign pending_wd = reg_wdata[31:0];
|
||||||
|
assign priority0_we = addr_hit[2] & reg_we & !reg_error;
|
||||||
|
|
||||||
|
assign priority0_wd = reg_wdata[31:0];
|
||||||
|
assign priority1_we = addr_hit[3] & reg_we & !reg_error;
|
||||||
|
|
||||||
|
assign priority1_wd = reg_wdata[31:0];
|
||||||
|
assign priority2_we = addr_hit[4] & reg_we & !reg_error;
|
||||||
|
|
||||||
|
assign priority2_wd = reg_wdata[31:0];
|
||||||
|
assign priority3_we = addr_hit[5] & reg_we & !reg_error;
|
||||||
|
|
||||||
|
assign priority3_wd = reg_wdata[31:0];
|
||||||
|
assign priority4_we = addr_hit[6] & reg_we & !reg_error;
|
||||||
|
|
||||||
|
assign priority4_wd = reg_wdata[31:0];
|
||||||
|
assign priority5_we = addr_hit[7] & reg_we & !reg_error;
|
||||||
|
|
||||||
|
assign priority5_wd = reg_wdata[31:0];
|
||||||
|
assign priority6_we = addr_hit[8] & reg_we & !reg_error;
|
||||||
|
|
||||||
|
assign priority6_wd = reg_wdata[31:0];
|
||||||
|
assign priority7_we = addr_hit[9] & reg_we & !reg_error;
|
||||||
|
|
||||||
|
assign priority7_wd = reg_wdata[31:0];
|
||||||
|
|
||||||
|
// Read data return
|
||||||
|
always_comb begin
|
||||||
|
reg_rdata_next = '0;
|
||||||
|
unique case (1'b1)
|
||||||
|
addr_hit[0]: begin
|
||||||
|
reg_rdata_next[31:0] = enable_qs;
|
||||||
|
end
|
||||||
|
|
||||||
|
addr_hit[1]: begin
|
||||||
|
reg_rdata_next[31:0] = pending_qs;
|
||||||
|
end
|
||||||
|
|
||||||
|
addr_hit[2]: begin
|
||||||
|
reg_rdata_next[31:0] = priority0_qs;
|
||||||
|
end
|
||||||
|
|
||||||
|
addr_hit[3]: begin
|
||||||
|
reg_rdata_next[31:0] = priority1_qs;
|
||||||
|
end
|
||||||
|
|
||||||
|
addr_hit[4]: begin
|
||||||
|
reg_rdata_next[31:0] = priority2_qs;
|
||||||
|
end
|
||||||
|
|
||||||
|
addr_hit[5]: begin
|
||||||
|
reg_rdata_next[31:0] = priority3_qs;
|
||||||
|
end
|
||||||
|
|
||||||
|
addr_hit[6]: begin
|
||||||
|
reg_rdata_next[31:0] = priority4_qs;
|
||||||
|
end
|
||||||
|
|
||||||
|
addr_hit[7]: begin
|
||||||
|
reg_rdata_next[31:0] = priority5_qs;
|
||||||
|
end
|
||||||
|
|
||||||
|
addr_hit[8]: begin
|
||||||
|
reg_rdata_next[31:0] = priority6_qs;
|
||||||
|
end
|
||||||
|
|
||||||
|
addr_hit[9]: begin
|
||||||
|
reg_rdata_next[31:0] = priority7_qs;
|
||||||
|
end
|
||||||
|
|
||||||
|
default: begin
|
||||||
|
reg_rdata_next = '1;
|
||||||
|
end
|
||||||
|
endcase
|
||||||
|
end
|
||||||
|
|
||||||
|
// Unused signal tieoff
|
||||||
|
|
||||||
|
// wdata / byte enable are not always fully used
|
||||||
|
// add a blanket unused statement to handle lint waivers
|
||||||
|
logic unused_wdata;
|
||||||
|
logic unused_be;
|
||||||
|
assign unused_wdata = ^reg_wdata;
|
||||||
|
assign unused_be = ^reg_be;
|
||||||
|
|
||||||
|
endmodule
|
|
@ -0,0 +1,64 @@
|
||||||
|
/*
|
||||||
|
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_top (
|
||||||
|
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,
|
||||||
|
|
||||||
|
// OBI总线接口信号
|
||||||
|
input logic req_i,
|
||||||
|
input logic we_i,
|
||||||
|
input logic [ 3:0] be_i,
|
||||||
|
input logic [31:0] addr_i,
|
||||||
|
input logic [31:0] data_i,
|
||||||
|
output logic [31:0] data_o
|
||||||
|
);
|
||||||
|
|
||||||
|
logic re;
|
||||||
|
logic we;
|
||||||
|
logic [31:0] addr;
|
||||||
|
logic [31:0] reg_rdata;
|
||||||
|
|
||||||
|
// 读信号
|
||||||
|
assign re = req_i & (!we_i);
|
||||||
|
// 写信号
|
||||||
|
assign we = req_i & we_i;
|
||||||
|
// 去掉基地址
|
||||||
|
assign addr = {16'h0, addr_i[15:0]};
|
||||||
|
|
||||||
|
rvic_core u_rvic_core (
|
||||||
|
.clk_i (clk_i),
|
||||||
|
.rst_ni (rst_ni),
|
||||||
|
.src_i (src_i),
|
||||||
|
.irq_id_o (irq_id_o),
|
||||||
|
.irq_o (irq_o),
|
||||||
|
.reg_we_i (we),
|
||||||
|
.reg_re_i (re),
|
||||||
|
.reg_wdata_i(data_i),
|
||||||
|
.reg_be_i (be_i),
|
||||||
|
.reg_addr_i (addr),
|
||||||
|
.reg_rdata_o(reg_rdata)
|
||||||
|
);
|
||||||
|
|
||||||
|
always_ff @(posedge clk_i) begin
|
||||||
|
data_o <= reg_rdata;
|
||||||
|
end
|
||||||
|
|
||||||
|
endmodule
|
|
@ -255,16 +255,17 @@ module tinyriscv_soc_top #(
|
||||||
assign slave_addr_mask[Rvic] = `RVIC_ADDR_MASK;
|
assign slave_addr_mask[Rvic] = `RVIC_ADDR_MASK;
|
||||||
assign slave_addr_base[Rvic] = `RVIC_ADDR_BASE;
|
assign slave_addr_base[Rvic] = `RVIC_ADDR_BASE;
|
||||||
// 6.中断控制器模块
|
// 6.中断控制器模块
|
||||||
rvic u_rvic(
|
rvic_top u_rvic(
|
||||||
.clk_i (clk),
|
.clk_i (clk),
|
||||||
.rst_ni (ndmreset_n),
|
.rst_ni (ndmreset_n),
|
||||||
.src_i (irq_src),
|
.src_i (irq_src),
|
||||||
.irq_o (int_req),
|
.irq_o (int_req),
|
||||||
.irq_id_o (int_id),
|
.irq_id_o (int_id),
|
||||||
|
.req_i (slave_req[Rvic]),
|
||||||
|
.we_i (slave_we[Rvic]),
|
||||||
|
.be_i (slave_be[Rvic]),
|
||||||
.addr_i (slave_addr[Rvic]),
|
.addr_i (slave_addr[Rvic]),
|
||||||
.data_i (slave_wdata[Rvic]),
|
.data_i (slave_wdata[Rvic]),
|
||||||
.be_i (slave_be[Rvic]),
|
|
||||||
.we_i (slave_we[Rvic]),
|
|
||||||
.data_o (slave_rdata[Rvic])
|
.data_o (slave_rdata[Rvic])
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue