第28课 · 中断控制器

CLINTPLIC中断优先级

📌 学习目标:理解 RISC-V 中断控制器架构(CLINT + PLIC),实现简化的中断优先级仲裁器。

一、RISC-V 中断架构

CLINT (Core Local Interruptor):
  - 产生软件中断(MSIP)
  - 产生定时器中断(MTIMER)
  - 每个核独有

PLIC (Platform-Level Interrupt Controller):
  - 管理外部中断源
  - 中断优先级仲裁
  - 中断使能/挂起/优先级阈值

二、中断处理流程

外部中断源 → PLIC优先级仲裁 → 中断门控(阈值+使能)
  → 核心中断信号 → CPU保存上下文 → 跳转处理
  → 处理完成 → MRET返回

CLINT定时器:mtime ≥ mtimecmp → 触发定时器中断

Verilog 实现

// interrupt_controller.v — CLINT+PLIC简化 "keyword">module interrupt_controller ( "keyword">input clk, rst, "keyword">input [3:0] irq_sources, "keyword">input [1:0] cpu_priv, "keyword">input cpu_mie, "keyword">output "keyword">reg cpu_irq, "keyword">output "keyword">reg [3:0] cpu_irq_id, "keyword">output "keyword">reg timer_irq, "keyword">input [63:0] mtime, mtimecmp, "keyword">input [3:0] plic_enable, "keyword">input [2:0] plic_threshold, "keyword">input [3:0] plic_claim ); "keyword">reg [2:0] priority [0:3]; "keyword">reg [3:0] pending; "keyword">reg [2:0] max_priority; "keyword">reg [3:0] max_id; "keyword">integer i; "keyword">always @(*) "keyword">begin max_priority=0; max_id=0; "keyword">for (i=0;i<4;i=i+1) "keyword">if (pending[i]&&plic_enable[i]&&priority[i]>max_priority) "keyword">begin max_priority=priority[i]; max_id=i[3:0]; "keyword">end "keyword">end "keyword">always @("keyword">posedge clk "keyword">or "keyword">posedge rst) "keyword">begin "keyword">if (rst) "keyword">begin cpu_irq<=0; cpu_irq_id<=0; timer_irq<=0; pending<=0; priority[0]<=1; priority[1]<=2; priority[2]<=3; priority[3]<=4; "keyword">end "keyword">else "keyword">begin pending<=pending|irq_sources; "keyword">if (plic_claim[0]) pending[0]<=0; "keyword">if (plic_claim[1]) pending[1]<=0; "keyword">if (plic_claim[2]) pending[2]<=0; "keyword">if (plic_claim[3]) pending[3]<=0; timer_irq<=(mtime>=mtimecmp); "keyword">if (max_priority>plic_threshold && cpu_mie && cpu_priv==2'b11) "keyword">begin cpu_irq<=1; cpu_irq_id<=max_id; "keyword">end "keyword">else cpu_irq<=0; "keyword">end "keyword">end "keyword">endmodule

测试台

// tb_interrupt_controller.v "keyword">module tb_interrupt_controller; "keyword">reg clk,rst; "keyword">reg [3:0] irq_sources; "keyword">reg [1:0] cpu_priv; "keyword">reg cpu_mie; "keyword">wire cpu_irq; "keyword">wire [3:0] cpu_irq_id; "keyword">wire timer_irq; "keyword">reg [63:0] mtime,mtimecmp; "keyword">reg [3:0] plic_enable,plic_claim; "keyword">reg [2:0] plic_threshold; interrupt_controller uut(.*); "keyword">integer pass=0,fail=0; "keyword">always #5 clk=~clk; "keyword">initial "keyword">begin clk=0;rst=1;irq_sources=0;cpu_priv=2'b11;cpu_mie=1; mtime=0;mtimecmp=100;plic_enable=4'hF;plic_threshold=0;plic_claim=0; #12;rst=0; irq_sources=4'b0010; #10; "keyword">if (cpu_irq) pass=pass+1; "keyword">else "keyword">begin $display("FAIL1"); fail=fail+1; "keyword">end irq_sources=0;plic_claim=4'b0010;#10;plic_claim=0;#10; irq_sources=4'b0101; #10; "keyword">if (cpu_irq_id===4'd2) pass=pass+1; "keyword">else "keyword">begin $display("FAIL2"); fail=fail+1; "keyword">end plic_claim=4'b0100;#10;plic_claim=0;irq_sources=0;#10; plic_threshold=3'd3; irq_sources=4'b0001; #10; "keyword">if (!cpu_irq) pass=pass+1; "keyword">else "keyword">begin $display("FAIL3"); fail=fail+1; "keyword">end plic_threshold=0;irq_sources=0;#10; mtime=64'd100; #10; "keyword">if (timer_irq) pass=pass+1; "keyword">else "keyword">begin $display("FAIL4"); fail=fail+1; "keyword">end $display("========================================"); $display("中断控制器测试: PASS=%0d FAIL=%0d",pass,fail); "keyword">if (fail==0) $display("✅ CLINT+PLIC中断逻辑正确!"); "keyword">else $display("❌ 存在失败!"); $display("========================================"); $finish; "keyword">end "keyword">endmodule

Verilator 编译与运行

verilator --cc interrupt_controller.v --exe tb_interrupt_controller.v --build --top-module tb_interrupt_controller ./obj_dir/Vtb_interrupt_controller

📌 扩展阅读

本课的核心概念在实际工程中有广泛应用:

🔧 调试技巧

在开发本课模块时,常见问题和解决方法:

📊 性能指标

衡量本课模块性能的关键指标:

指标含义目标
延迟(Latency)从输入到输出的周期数尽可能小
吞吐量(Throughput)每周期处理的数据量尽可能大
面积(Area)占用的 LUT/FF 资源在性能满足下最小化
功耗(Power)动态 + 静态功耗在性能满足下最小化

🔗 与其他课程的联系

本课内容在整个 RISC-V 数字电路课程中的位置:

🏆 成就解锁:中断控制器

✅ Verilator 仿真验证通过

✅ PLIC 优先级仲裁正确

✅ 中断使能/阈值过滤正确

✅ CLINT 定时器中断正确

🤔 思考题

1. 本课设计的模块如何与前面课程的内容结合?

2. 修改参数后,系统的行为会有什么变化?