【RISC-V设计-09】- RISC-V处理器设计K0A之CIC
文章目录
- [【RISC-V设计-09】- RISC-V处理器设计K0A之CIC](#【RISC-V设计-09】- RISC-V处理器设计K0A之CIC)
1.简介
核内中断控制器(Core Interrupt Controller,简称CIC)是管理和仲裁中断的模块,能够根据预设的优先级规则,逐一上报中断请求的序号。本模块具有如下几点功能:
- 根据全局中断使能,控制中断序号的上报;
- 根据独立中断使能,控制对应的中断请求;
- 记录中断状态,根据中断状态向指令译码单元发出中断请求;
- 根据指令译码单元发出中断应答,清除中断请求;
- 通过软件、硬件结合的方式,支持晚到中断、咬尾中断;
2.顶层设计
3.端口说明
序号 | 端口 | 位宽 | 方向 | 说明 |
---|---|---|---|---|
1 | core_clk | 1 | input | 内核时钟 |
2 | core_rstn | 1 | input | 内核复位信号,低有效 |
3 | irq_lines | 16 | input | 外部中断信号,高电平/脉冲触发 |
4 | csr2cic_gie | 1 | input | 全局中断使能 |
5 | csr2cic_mie | 16 | input | 独立控制的中断使能 |
6 | csr2cic_mip | 16 | input | 中断请求等待 |
7 | cic2csr_irq | 16 | output | 外部中断信号,高电平/脉冲触发 |
8 | cic2csr_mcause | 5 | output | 中断原因记录 |
9 | cic2idu_int_req | 1 | output | 向译码单元发送的中断请求 |
10 | idu2cic_int_ack | 1 | input | 译码单元返回的中断应答 |
11 | idu2cic_int_mret | 1 | input | 译码单元执行中断返回指令 |
4.代码设计
verilog
// -------------------------------------------------------------------------------------------------
// Copyright 2024 Kearn Chen, kearn.chen@aliyun.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.
// -------------------------------------------------------------------------------------------------
// Description :
// 1. Core Interrupt Controller
// -------------------------------------------------------------------------------------------------
module k0a_core_cic (
input wire core_clk ,
input wire core_rstn ,
input wire [15:0] irq_lines ,
input wire csr2cic_gie ,
input wire [15:0] csr2cic_mie ,
input wire [15:0] csr2cic_mip ,
output wire [15:0] cic2csr_irq ,
output reg [4:0] cic2csr_mcause ,
output reg cic2idu_int_req ,
input wire idu2cic_int_ack ,
input wire idu2cic_int_mret
);
reg status_irq;
wire cic_int_hit = cic2idu_int_req & idu2cic_int_ack;
wire [15:0] irq_src = csr2cic_mip & csr2cic_mie;
assign cic2csr_irq = irq_lines;
always @(posedge core_clk or negedge core_rstn)
begin
if(!core_rstn)
status_irq <= 1'b0;
else if(cic_int_hit)
status_irq <= 1'b1;
else if(idu2cic_int_mret)
status_irq <= 1'b0;
end
always @(posedge core_clk)
begin
if(csr2cic_gie) begin
case(1'b1)
irq_src[ 0] : cic2csr_mcause <= {1'b1, 4'h0};
irq_src[ 1] : cic2csr_mcause <= {1'b1, 4'h1};
irq_src[ 2] : cic2csr_mcause <= {1'b1, 4'h2};
irq_src[ 3] : cic2csr_mcause <= {1'b1, 4'h3};
irq_src[ 4] : cic2csr_mcause <= {1'b1, 4'h4};
irq_src[ 5] : cic2csr_mcause <= {1'b1, 4'h5};
irq_src[ 6] : cic2csr_mcause <= {1'b1, 4'h6};
irq_src[ 7] : cic2csr_mcause <= {1'b1, 4'h7};
irq_src[ 8] : cic2csr_mcause <= {1'b1, 4'h8};
irq_src[ 9] : cic2csr_mcause <= {1'b1, 4'h9};
irq_src[10] : cic2csr_mcause <= {1'b1, 4'ha};
irq_src[11] : cic2csr_mcause <= {1'b1, 4'hb};
irq_src[12] : cic2csr_mcause <= {1'b1, 4'hc};
irq_src[13] : cic2csr_mcause <= {1'b1, 4'hd};
irq_src[14] : cic2csr_mcause <= {1'b1, 4'he};
irq_src[15] : cic2csr_mcause <= {1'b1, 4'hf};
default : cic2csr_mcause <= 5'd0;
endcase
end
end
always @(posedge core_clk or negedge core_rstn)
begin
if(!core_rstn)
cic2idu_int_req <= 1'b0;
else if(cic_int_hit)
cic2idu_int_req <= 1'b0;
else if(~status_irq & (|irq_src))
cic2idu_int_req <= 1'b1;
end
endmodule
5.仲裁代码
assembly
# -------------------------------------------------------------------------------------------------
# Copyright 2024 Kearn Chen, kearn.chen@aliyun.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.
# -------------------------------------------------------------------------------------------------
.section .init, "ax", @progbits
.globl _start
.align 2
_start:
.option norvc;
j handler_reset
.word handler_irq0
.word handler_irq1
.word handler_irq2
.word handler_irq3
.word handler_irq4
.word handler_irq5
.word handler_irq6
.word handler_irq7
.word handler_irq8
.word handler_irq9
.word handler_irq10
.word handler_irq11
.word handler_irq12
.word handler_irq13
.word handler_irq14
.word handler_irq15
.section .text.handler_isr, "ax", @progbits
.align 2
handler_isr:
addi sp, sp, -56
sw x1 , 0(sp)
sw x4 , 4(sp)
sw x5 , 8(sp)
sw x6 , 12(sp)
sw x7 , 16(sp)
sw x8 , 20(sp)
sw x9 , 24(sp)
sw x10, 28(sp)
sw x11, 32(sp)
sw x12, 36(sp)
sw x13, 40(sp)
sw x14, 44(sp)
sw x15, 48(sp)
1:
csrr a0, mcause
beq x0, a0, 2f
andi a0, a0, 15
addi a1, x0, 1
sll a2, a1, a0
csrrc a2, mip, a2
slli a0, a0, 2
lw a1, 4(a0)
jalr ra, a1, 0
jal x0, 1b
2:
lw x15, 48(sp)
lw x14, 44(sp)
lw x13, 40(sp)
lw x12, 36(sp)
lw x11, 32(sp)
lw x10, 28(sp)
lw x9 , 24(sp)
lw x8 , 20(sp)
lw x7 , 16(sp)
lw x6 , 12(sp)
lw x5 , 8(sp)
lw x4 , 4(sp)
lw x1 , 0(sp)
addi sp, sp, 56
mret
.section .text.handler_default, "ax", @progbits
.align 2
.weak handler_irq0
.weak handler_irq1
.weak handler_irq2
.weak handler_irq3
.weak handler_irq4
.weak handler_irq5
.weak handler_irq6
.weak handler_irq7
.weak handler_irq8
.weak handler_irq9
.weak handler_irq10
.weak handler_irq11
.weak handler_irq12
.weak handler_irq13
.weak handler_irq14
.weak handler_irq15
handler_irq0:
handler_irq1:
handler_irq2:
handler_irq3:
handler_irq4:
handler_irq5:
handler_irq6:
handler_irq7:
handler_irq8:
handler_irq9:
handler_irq10:
handler_irq11:
handler_irq12:
handler_irq13:
handler_irq14:
handler_irq15:
loop_isr:
j loop_isr
.section .text.handler_reset, "ax", @progbits
.align 2
handler_reset:
.option push
.option norelax
la gp, __global_pointer$
.option pop
1:
la sp, _eusrstack
2:
la a0, _data_lma
la a1, _data_vma
la a2, _edata
bgeu a1, a2, 2f
1:
lw a3, 0(a0)
sw a3, 0(a1)
addi a0, a0, 4
addi a1, a1, 4
bgeu a1, a2, 2f
lw a3, 0(a0)
sw a3, 0(a1)
addi a0, a0, 4
addi a1, a1, 4
bltu a1, a2, 1b
2:
la a0, _sbss
la a1, _ebss
bgeu a0, a1, 2f
1:
sw x0, 0(a0)
addi a0, a0, 4
bgeu a0, a1, 2f
sw x0, 0(a0)
addi a0, a0, 4
bgeu a0, a1, 2f
sw x0, 0(a0)
addi a0, a0, 4
bltu a0, a1, 1b
2:
la a3, handler_isr
csrw mtvec, a3
j main
这段代码是开始运行时初始化的代码,同时还存在中断处理相关的操作,通过读取中断原因、进行一些位操作确定中断序号。如果中断原因不为 0,根据中断序号查找到中断向量表,跳转到特定的地址执行相应的中断处理程序。
6.总结
本文阐述了一种极为简洁的中断控制模块。该模块采用软件与硬件相结合的方式,来达成中断的处理。并且,它还能够支持晚到中断和咬尾中断,一次进出栈就能够处置多个现存的中断。如此一来,节省了中断处理的时间,提高了中断处理的效率。