2026年了,FPGA大赛用国产FPGA做RISC-V软核,UART和GPIO挂到AXI总线上老是地址映射错乱,有没有排查套路?

开放6 回答 59 浏览

我们队用高云FPGA做RISC-V软核,把UART和GPIO都挂到AXI-Lite总线上,但地址映射总是错乱,读到的寄存器值全不对。怀疑是基地址配置问题,也怀疑是地址译码逻辑写错了。有没有大佬分享下排查套路?比如怎么看总线波形、怎么用ILA抓AXI通道信号、怎么验证地址对齐?

分享:

6 个回答

  • 逻辑小白

    其实这种地址错乱,九成是译码逻辑的区间划分问题,不是软核本身。你想想,UART和GPIO的基地址是不是都落在同一个高地址段里,然后你的case语句只判断了高几位?比如高位是0x4000_0000,后面低地址没区分,那读哪个外设都会命中同一个分支。建议先用一个最简单的回环测试:只挂一个GPIO,地址写死0x0000_0000,读写一个寄存器,ILA抓包确认AWADDR和WDATA都正确,再逐步加外设。第二个外设加进去后,重点看译码的边界条件,比如区间是[0x40000000, 0x40000FFF]还是[0x40000000, 0x40000FFF)这种开闭区间搞错,也会导致读回全0或者全F。另外高云有些型号的AXI-Lite是32位地址但数据总线可能是64位,这种时候地址对齐要按8字节而不是4字节,寄存器地址偏移也得跟着调,很多人栽在这上面。

  • 硅农预备役_01

    个人感觉你这个现象,除了译码逻辑,还得考虑软核那边有没有做地址重映射。高云那个软核如果你用的是官方SDK,它默认会把外设空间映射到某个固定区域,但你自己写AXI总线的时候可能没按那个约定来,导致软核访问的地址和实际挂载的地址对不上。排查思路可以先分两步:第一步,看软核启动后打印的链接脚本,确认UART和GPIO的基地址在链接脚本里是什么值,然后对照你RTL里译码的区间,看是否一致——这一步不用上ILA,先静态核对。第二步,如果静态核对没问题,再用ILA抓AWADDR,同时抓一个写使能信号,看写操作时地址是否真的发到了你预期的外设。有个替代做法是临时把UART和GPIO的基地址都设成同一个值,然后只访问其中一个,看ILA抓到的是不是同一个地址——如果是,说明译码逻辑根本没区分外设,直接改case的优先级就行。另外常见误区是只抓AW通道不抓AR通道,读错和写错是两码事,你读寄存器值不对,八成是AR通道的地址发错了,或者读返回的数据通道没对齐。最后提醒一句,高云有些FPGA的ILA核需要额外占用BRAM,如果资源紧张,可以先用逻辑分析仪抓外部引脚,或者用modelsim仿真代替,但仿真时要注意AXI-Lite的握手时序,别漏了BVALID和RVALID的等待周期。你们目前是卡在读错还是写错?如果读回值全0,那可能地址根本没命中任何外设,返回了默认的0;如果读回全F,可能是地址落到了未分配区域,看下高云那个软核的默认返回值是什么。

  • 电子小白

    先别急着改RTL,拿ILA抓一下AWADDR和ARADDR,把软核实际发出的地址和你在地址译码里写的区间对一下。大概率是基地址没对上,或者你只译码了高几位导致UART和GPIO落进同一个分支了。

  • 逻辑设计小白

    个人感觉你这个问题,先别急着怀疑译码逻辑,把软核的链接脚本打开看一眼。高云官方SDK生成的软核,外设基地址一般会在链接脚本里写死,比如UART在0x40001000,GPIO在0x40002000。你RTL里的译码区间必须跟这个完全一致,差一个bit都不行。我遇到过有人把区间写成[0x40000000, 0x40000FFF]和[0x40001000, 0x40001FFF],但软核实际访问的是0x40000000和0x40001000,中间有个空洞,结果第二个外设读回来全是0。先用一个最简单的回环测试:只挂GPIO,写一个值读回来,ILA抓AWADDR和RDATA,确认地址和数据都对,再加UART。这样一步步来,比一次性挂两个外设好排查得多。

  • FPGA萌新

    这问题我去年在另一块国产FPGA上踩过类似的坑,给你说个容易忽略的点:AXI-Lite虽然地址是32位,但高云某些型号的软核数据总线可能是64位的,这时候地址对齐要按8字节而不是4字节。比如你给UART分配基地址0x40000000,给GPIO分配0x40000004,看起来每个外设占4字节没问题,但64位总线下,0x40000004这个地址根本不会被正确译码,因为地址最低3位会被忽略。结果就是GPIO实际映射到了0x40000000,跟UART重叠了。你先查一下软核的数据总线位宽,如果真是64位,把GPIO挪到0x40000008试试。另外还有个排查技巧:把所有外设的基地址都设成同一个值,然后只访问其中一个,ILA抓到地址后看译码逻辑会不会区分——如果抓到的地址一样,说明你的case分支优先级写反了,或者根本没区分低地址位。顺便问一下,你用的高云具体是哪个型号?不同系列的软核SDK对地址映射的处理方式不太一样。

  • 数字逻辑初学者

    大赛里遇到这种问题,十有八九不是软核坏了,而是你心里默认的地址空间和总线实际行为没对齐。先别急着改case,我建议按这个顺序来:第一步,打开软核的链接脚本或者SDK里的内存映射头文件,把UART和GPIO的基地址抄出来,然后拿计算器转成二进制,数一下低几位是零。如果基地址低4位不是零,那你得先怀疑地址对齐——高云有些型号的AXI-Lite数据总线可能是64位的,这时候地址最低3位会被忽略,你给GPIO分配0x40000004,实际会被当成0x40000000,跟UART撞车。第二步,写一个最简单的回环测试:只挂GPIO,写一个值再读回来,同时用ILA抓AWADDR、ARADDR和RDATA,确认软核发出来的地址跟你RTL里译码的区间完全一致。注意看ILA里抓到的地址是高云软核实际访问的地址,不是你以为的地址。第三步,检查译码逻辑的边界条件,很多人写区间喜欢用[addr, addr+0xFFF],但忘了AXI是半开区间,实际包含的地址是addr到addr+0xFFF-1,多写一个地址就会把下一个外设的首地址也吞进去。最后,如果还是查不出来,临时把所有外设的基地址都设成同一个值,然后只访问其中一个,ILA抓到地址后看译码逻辑会不会区分——如果抓到的地址一样,说明你的case分支优先级写反了,或者根本没用上地址的低位。还有一个容易忽略的点:软核SDK默认可能开了地址重映射,你RTL里写的地址和软核实际访问的地址可能差一个偏移,这个一定要先核对。你们现在用的高云具体是哪个型号?软核是官方软核还是自己写的?这两个条件会影响排查方向,方便的话补充一下。

登录后可在本页底部提交回答

提问者

电路玩家新手查看主页
浏览「其他」

描述场景与已尝试方案,更容易获得有效解答

相关问题

同分类

提问建议

  • 标题写清核心疑问,避免「求助」「请问」等空泛用语
  • 正文补充环境、版本、报错信息或截图
  • 先搜索本站是否已有相近问题,减少重复提问
  • 若与课程相关,请标明课时或章节便于讲师定位