Verilog 在DRAM中执行代码后为什么要在FPGA上捕获火箭芯片
我试图在Nexys4 DDR板上安装并运行一个版本的火箭芯片。到目前为止,我成功地生成了verilog,综合了设计并连接了一个jtag探针(segger jlink)。可以通过openocd和gdb访问寄存器和内存。加载一小段asm后,内核开始执行,但在第一条执行的指令之后直接跳到0x0000000。我假设它是陷阱,因为陷阱向量没有初始化,所以内核最终为0。有人知道怎么解决这个问题吗 内核的模拟可与verilator和vcs一起工作。在这两种情况下,内核都会毫无怨言地执行三条asm指令 测试的asm代码为:Verilog 在DRAM中执行代码后为什么要在FPGA上捕获火箭芯片,verilog,fpga,chisel,jtag,rocket-chip,Verilog,Fpga,Chisel,Jtag,Rocket Chip,我试图在Nexys4 DDR板上安装并运行一个版本的火箭芯片。到目前为止,我成功地生成了verilog,综合了设计并连接了一个jtag探针(segger jlink)。可以通过openocd和gdb访问寄存器和内存。加载一小段asm后,内核开始执行,但在第一条执行的指令之后直接跳到0x0000000。我假设它是陷阱,因为陷阱向量没有初始化,所以内核最终为0。有人知道怎么解决这个问题吗 内核的模拟可与verilator和vcs一起工作。在这两种情况下,内核都会毫无怨言地执行三条asm指令 测试的a
.section .text
.global _start
_start:
add x0,x0,x0
add x0,x0,x0
j _start
与此脚本链接:
SECTIONS
{
. = 0x80000000;
.text : { *(.text) }
}
对象转储:
Disassembly of section .text:
0000000080000000 <_start>:
80000000: 00000033 add zero,zero,zero
80000004: 00000033 add zero,zero,zero
80000008: ff9ff06f j 80000000 <_start>
节的反汇编。文本:
0000000080000000 :
80000000:00000033加零,零,零
80000004:00000033加零,零,零
80000008:ff9ff06f j 80000000
最近,DDR4、GDB和SiFive RISC芯片也出现了类似问题。在将代码加载到DDR4上并尝试从重置向量跳转后,RISCV将立即跳转到0x00000000。在使用Xilinx ILA进行调试后,我们发现尽管我们使用GDB对DDR4内存空间进行编程,但RISCV在内部缓存了一些代码,只是偶尔会将一些代码推送到DDR4。从RISCV的角度来看,这被认为是可以的,因为当您执行步骤时,它将决定使用缓存(如果可用),否则它将从DDR4检索代码。但是,假设您的CPU需要多次DDR访问,因为它需要大量代码来提高效率。如果您的程序非常小,那么其中的一些大代码块可能是空的,它们将不会被编程,因此ECC计算不正确
跳转到0x00000000后检查机器原因寄存器。查看它是否指示0x2,非法指令。在我的例子中,我看到这一点是因为总线观察到一个“总线错误”,这是由ECC故障do导致的半编程DDR突发
解决这个问题的一种方法可能是在ELF的末尾添加一堆额外的零,这样大小将迫使缓存刷新到内存中。一旦DDR真正编程,并且ECC正确,您就不应该再看到无效指令了。让我知道这对您是否有效。非常感谢您的回答:)几天后,我回到问题所在,并在您的提示下找到了原因。在跳转到0x0000000之后,我检查了mcause寄存器,是的,它显示0x2的指令无效。我用一个小的BRAM块切换DRAM,但一切都保持不变。之后,我用一个ILA监控内存端口,并在内核发出的指令读取时锁定。事实证明,vivado用32位接口而不是64位接口封装了内核。这样,高32位始终为零,因此作为指令无效。