feat(board): 中断综合测试程序上板 + 可变分频/刷新率;README 大幅扩写

板级顶层(srcs/board/cpu21_board_top.v)
- ROM 增加 RISC_V_INTRUPT_CCAB_ROM 分支,中断入口 0x0AC/0x1E4/0x308;
  与 SAOLEI_ROM / BOARD_ROM_FAST / 默认跑马灯构成 ifdef 链
- 新增参数 CLK_DIV_INTRUPT:跑中断测试程序时用更慢的 CPU 时钟(默认 32
  = 3.125 MHz),让数码管上每个数值停留约 160 ms 便于观察
- 数码管扫描分频随 CPU 分频缩放(SEG_REFRESH_DIV = 100000/CPU_DIV),
  保证每位数码管仍是 125 Hz(不闪);数码管改显示 MMIO 的 led_data;
  LED[2:0] 改为锁存式中断指示(请求上升沿点亮、对应 ISR 执行 uret 后熄灭)
- 复位同步器/led_we 指示等注释同步更新;srcs/rtl/cpu21_seg7.v 分频计数
  加宽到 20 位以容纳随主频变化的 REFRESH_DIV

工具与程序
- tools/adapt_intrupt_ccab.py:把课程中断测试镜像适配成上板 ROM。六处适配
  (ISR 停机 ecall、显示改 MMIO+DISP_DLY、ISR2/ISR3 出栈顺序、ISR3 SB 测试
  用未保存寄存器、ISR 破坏 ra 的 DISP_DLY_ISR),全部 2 字换 2 字,
  不移动任何指令地址;带断言与 jal 目标自检
- programs/risc-v-intrupt-ccab.asm/.hex:课程中断综合测试程序(含六处适配说明)
- create_project.tcl:新增 use_intrupt_ccab / use_saolei 开关,自动把对应
  ROM 头文件按 Verilog Header 加入 sources_1 并定义宏
- tools/rars_f0c874c.jar:课程 RARS 汇编器移到 tools/

文档(README.md)
- 新增"各模块的实现方式":按流水线主体 / 外设 / 板级逐模块讲实现要点
- 新增"内置程序与宏的用法":ROM 宏表(含各自的中断入口)、GUI/Tcl/命令行
  三种定义方式、中断程序的适配流程与仿真验证方法
- 新增"分频与刷新率一览":CLK_DIV / CLK_DIV_INTRUPT / SEG_REFRESH_DIV /
  led_we 时长 / DISP_DLY 延时常量分别在哪里改、怎么换算
- 修正引脚表(LED[2:0] 中断指示、led_we 0.34 s、CPU_DIV)与 ROM/RAM 说明
  (ROM 8192 字 = 32 KB),补充中断程序上板现象与 ROM 头文件清单

验证:不带宏 / 带 RISC_V_INTRUPT_CCAB_ROM 两种配置 xvlog 编译均无错误;
三路嵌套与 IRQ3 抢占 ISR1 的仿真通过(level 逐级升降、uepc 正确恢复、
halted=0);tools/check_rtl_text.ps1 体检 OK。
This commit is contained in:
2026-09-19 15:44:47 +08:00
parent 4f82331dbe
commit f7844b7b1c
11 changed files with 2702 additions and 890 deletions
+25 -5
View File
@@ -71,9 +71,19 @@ add_files -norecurse -fileset sources_1 [list \
set_property file_type {Verilog Header} \
[get_files "$origin_dir/srcs/board/cpu21_board_rom.vh"]
# 默认跑哪个内置程序:1 = 扫雷(定义宏 SAOLEI_ROM),0 = 走马灯 demo。
# 只有 cpu21_saolei_rom.vh 存在且 use_saolei = 1 时才会定义宏。
set use_saolei 1
# 默认跑哪个内置程序:中断测试程序优先,其次是扫雷,最后是走马灯 demo。
# 修改下面两个开关即可切换板上程序;同一时间只应启用一个。
set use_intrupt_ccab 1
set use_saolei 0
# 中断测试程序的 ROM 初始化。
set intrupt_ccab_rom "$origin_dir/srcs/board/risc-v-intrupt-ccab.vh"
if {[file exists $intrupt_ccab_rom]} {
add_files -norecurse -fileset sources_1 [list $intrupt_ccab_rom]
set_property file_type {Verilog Header} [get_files $intrupt_ccab_rom]
} else {
puts "NOTE: 还没有 $intrupt_ccab_rom"
}
# 扫雷程序的 ROM 初始化(由 saolei/tools/build.ps1 生成,可能还不存在)。
# 综合/仿真时定义宏 SAOLEI_ROM 就会用它替换上面的跑马灯 ROM。
@@ -87,7 +97,10 @@ if {[file exists $saolei_rom]} {
# 关键:sources_1 定义 SAOLEI_ROM,cpu21_board_top.v 里的 `ifdef 链才会用扫雷 ROM
# (该宏只影响综合用的 sources_1,仿真 fileset 仍各自用 tb 自带的 ROM)
if {$use_saolei && [file exists $saolei_rom]} {
if {$use_intrupt_ccab && [file exists $intrupt_ccab_rom]} {
set_property verilog_define {RISC_V_INTRUPT_CCAB_ROM} [get_filesets sources_1]
puts "NOTE: sources_1 已定义 RISC_V_INTRUPT_CCAB_ROM —— 上板跑 risc-v-intrupt-ccab"
} elseif {$use_saolei && [file exists $saolei_rom]} {
set_property verilog_define {SAOLEI_ROM} [get_filesets sources_1]
puts "NOTE: sources_1 已定义 SAOLEI_ROM —— 上板跑扫雷;想跑走马灯把本脚本里 use_saolei 改成 0"
} else {
@@ -129,7 +142,14 @@ foreach fs {sim_1 sim_2} {
# ---------------------------------------------------------------- 结果汇总
puts "工程已创建:$origin_dir/$proj_name.xpr"
puts " sources_1 顶层 = cpu21_board_top(上板:时钟分频 + 片内 ROM/RAM + 引脚)"
puts " sources_1 程序 = [expr {$use_saolei && [file exists $saolei_rom] ? {扫雷 (SAOLEI_ROM)} : {走马灯 demo}}]"
if {$use_intrupt_ccab && [file exists $intrupt_ccab_rom]} {
set selected_program {risc-v-intrupt-ccab (RISC_V_INTRUPT_CCAB_ROM)}
} elseif {$use_saolei && [file exists $saolei_rom]} {
set selected_program {扫雷 (SAOLEI_ROM)}
} else {
set selected_program {走马灯 demo}
}
puts " sources_1 程序 = $selected_program"
puts " sim_1 顶层 = tb_cpu21_riscv_redirect_int_bpb(中断/分支预测)"
puts " sim_2 顶层 = tb_no_intr(指令集测试,ROM 镜像在 srcs/rom/)"
puts " 下一步:Run Synthesis → Run Implementation → Generate Bitstream,或 Run Simulation"