我们队伍今年集创赛选的是国产高云FPGA,用RISC-V软核跑一个简单的按键中断控制LED,结果按键按下去中断标志位就是置不起来。代码在Vivado上仿真都没问题,下载到板子上就不行。查了高云的IP核文档,GPIO的输入输出方向和中断使能寄存器都配了,会不会是软核的中断控制器没接对?还是说高云FPGA的引脚需要额外的上拉配置?求大佬指点排查思路,比赛还剩两周,急!
2026年了,FPGA大赛用国产高云FPGA做RISC-V软核,GPIO中断老是进不去,是硬件配置还是软件问题?
6 个回答

先别急着怀疑软件,你这个现象(仿真对、上板错、中断标志不置位)在国产FPGA上十有八九是硬件配置层面的问题。我按两周的倒计时给你排个序:第一步,确认RISC-V软核的中断控制器到底有没有被正确例化。很多集创赛队伍用的软核是自带的或者教学模板改的,PLIC和CLINT这两个东西经常被漏掉,或者例化了但地址映射不对。你查一下软核的链接脚本和内存映射,看看中断向量表是不是指向了正确的位置,特别是mtvec或者stvec寄存器有没有被初始化。这一步是最容易出错的,因为Vivado仿真里往往不会真正触发PLIC的仲裁逻辑,你看着仿真波形全对,实际上板子上的中断源根本没接到PLIC的输入端口上。第二步,检查高云FPGA的IO约束。高云的引脚默认状态和Xilinx不一样,很多引脚不带内部上拉,你按键如果是开漏或者悬空接法,电平就是浮的,中断检测永远采不到低电平。在物理约束文件里给按键引脚加上PULLUP,最好再配个施密特触发(如果器件支持的话),这样能滤掉按键抖动和毛刺。第三步,用逻辑分析仪或者示波器直接抓引脚波形,别光看寄存器。你按下去的时候,引脚电平到底变了没有?如果变了但中断标志不置,那就是软核内部路径断了;如果引脚电平根本没变,那就是硬件电路或者约束问题。最后提醒一句,高云的IP核文档里GPIO中断使能寄存器往往分输入使能、输出使能、中断使能三套,你确认一下是不是只配了方向没配中断使能,这个坑我见过好几个队伍踩。你们用的软核是自己写的还是官方IP?如果是官方IP,记得看它有没有单独的interrupt controller例化示例,别光看GPIO的文档。

给你一个最省时间的排查路径:先看硬件,再看软核。拿万用表或者示波器量按键引脚,按下时电平有没有从高变低。如果没变,就是高云引脚的内部上拉没开,或者你板子上按键电路本身有问题,这和软核一点关系都没有。如果电平正常变化,那就去翻软核的启动代码,看看中断入口函数有没有被链接到正确地址,很多模板的startup.S里中断向量是空的,或者只处理了定时器中断,GPIO中断根本没注册。你可以尝试在中断入口函数最开头放一个死循环加LED翻转,如果按下去LED动了,说明中断已经进来,只是后面的处理逻辑没写对。比赛还剩两周,建议直接放弃仿真验证的思维,仿真过了不代表上板能过,高云的工具链对时序约束要求比较严,你可以在工程里加一条set_property来约束按键引脚,顺便看看综合报告里有没有关于该引脚的警告。你们用的高云具体是哪一款芯片?小封装的话可能引脚复用冲突,比如按键引脚同时被JTAG占了,那怎么配都进不去中断。

两周时间其实挺够用的,但你得把排查顺序反过来:别先盯着软核代码,先确认物理按键的电平变化真的到了 FPGA 引脚。高云的开发板按键电路五花八门,有些是按下接低、有些是按下接高,还有直接悬空靠内部上拉的。你拿示波器或万用表量一下引脚,按下时电平有没有稳定翻转,这一步五分钟就能排除一半问题。如果电平没问题,再去看软核的中断路径。常见坑是 PLIC 例化了但没把 GPIO 的中断线连到 PLIC 的 source 端口上,仿真时你直接在 testbench 里手动拉高了 GPIO 中断信号,绕过了 PLIC 仲裁,所以仿真全对。上板后实际按键触发的是 GPIO 模块内部中断标志,得经过 PLIC 转发到核的 meip 才能进 trap。你查一下软核的 device tree 或者中断连接表,确认 GPIO 中断号在 PLIC 里注册了,并且 mtvec 初始化指向了正确的 trap handler。另外高云的 FPGA 引脚默认不带上拉,如果你的按键是开漏接法,必须在约束文件里加 PULLUP 属性,否则引脚浮空时电平乱跳,中断标志可能被反复触发后又被清零。最后说个很多人忽略的点:高云的工具链里,如果你在顶层模块里例化了软核的 GPIO 但没把按键引脚约束到支持施密特触发的 bank,毛刺会导致中断标志只维持一个时钟周期,CPU 轮询时已经错过了。你可以试着在按键引脚上加一个简单的 RC 滤波或者软件消抖,把中断处理改成捕获下降沿后延时再读电平。你们用的软核是蜂鸟 E203 还是自研的?如果是 E203,我记得它的 PLIC 基地址默认是 0xC000000,但高云 IP 核的地址映射可能不一样,最好核一下链接脚本。

给你一个最直接的排查路径:把中断处理函数里第一行改成死循环加 LED 翻转,按键按下去如果 LED 动了,说明中断路径通的,问题在后面逻辑;如果没动,就说明中断根本没进来。这时候别纠结软件了,去看高云的 IP 核配置界面里 GPIO 的中断类型是电平触发还是边沿触发,很多国产软核模板默认配的是电平触发,但你按键是按下低电平松开高电平,如果你在中断服务程序里没有清中断标志,第二次按下就永远进不去了。另外,高云的工具链对跨时钟域处理比较敏感,如果你的软核主频和 GPIO 模块时钟不是同一个,需要在 IP 核里开启同步器选项,否则中断标志会被亚稳态吃掉。比赛还剩两周,先把功能跑通再考虑优化,别在仿真上浪费时间了。

先说结论:大概率不是C语言逻辑问题,而是中断通路在某个环节断了。你Vivado仿真能过,恰恰说明testbench里把中断信号手动拉高了,绕过了PLIC仲裁和IO约束这两道坎,所以仿真和上板完全是两码事。两周时间,我建议按下面顺序查,每步控制在半小时内。第一步,打开软核的例化文件,搜PLIC,确认它的source端口上有没有一根线是从GPIO模块的中断输出接过来的。很多教学模板例化了PLIC但没连中断源,或者只连了定时器,GPIO那根线悬空着,你寄存器配得再对也没用。第二步,看高云的IP配置界面里GPIO的中断触发类型。如果默认是电平触发,而你的按键是按下低电平松开高电平,那么中断标志一旦置位,只要按键还按着,标志就不会清,第二次按下就永远进不去了。改成边沿触发,或者在中断服务程序里先清标志再处理业务。第三步,查引脚约束。高云FPGA的IO默认状态和Xilinx不一样,很多引脚不带内部上拉,如果你的按键电路是开漏或者悬空接法,按下时电平翻转幅度不够,GPIO模块根本采不到稳定跳变。在约束文件里给按键引脚加上PULLUP,顺便看看有没有施密特触发选项可以打开,能有效滤除机械抖动。如果这三步都查完还是不行,那就用逻辑分析仪抓引脚波形,确认物理层面电平有没有干净地翻转。说实话,国产FPGA的中断调试,九成问题出在PLIC连线或者IO配置上,软核代码反而是最不容易出错的。你们用的高云具体是哪一款芯片?不同系列的IP核配置界面差异挺大的,说下型号我帮你看看有没有已知的坑。

我直接说个反直觉的排查思路,你别把精力耗在中断标志位上,先去看RISC-V软核的trap入口到底有没有被正确初始化。很多集创赛队伍用的软核是从教学模板改的,启动文件里mtvec寄存器要么没设,要么设到了错误的地址。你仿真时不关心这个,因为testbench里你手动调用了中断处理函数,相当于绕过了硬件跳转;上板后中断真正触发时,CPU跑去mtvec指向的地址取指令,如果那里是空的或者是一段无关代码,表现就是中断标志位确实置起来了,但你的处理函数根本没执行,LED自然没反应。你可以在GPIO中断标志置位后,先不急着查为什么进不去,而是把mtvec的值打印出来,或者用调试器看PC指针跳到了哪里。如果PC跳到了一个你没预料到的地址,那问题就不在GPIO配置上,而在软核的启动代码和链接脚本里。顺便说一句,高云的工具链对中断向量表的链接地址要求比较死板,有些模板默认把向量表放在0x00000000,但你的软核实际运行地址在0x80000000,中间差了一截,中断跳转就飞到未知区域了。查一下链接脚本里text段和vector段的起始地址,确保和软核的复位地址一致。另外,你提到中断标志位置不起来,这个现象本身也有讲究——是标志位完全没变化,还是变了但CPU没响应?如果是前者,回头查GPIO模块的时钟是否被门控了,高云IP核里有时钟使能位,默认可能没打开;如果是后者,那就是我刚说的trap入口问题。两周时间足够你把这几个点逐个排除,但建议先用逻辑分析仪确认引脚电平真的翻转了,再碰软核内部的东西,否则容易在错误的方向上越走越远。你们板子上按键是接的哪个物理引脚,方便的话说下编号,我可以帮你看看高云那个系列有没有特殊的输入延迟要求。
发表回答
登录后可在本页底部提交回答