riscv在fpga的运行过程

一、RISC-V 的核心构成:如何成为硬件与软件的桥梁?

RISC-V 处理器本质是用 Verilog 代码 "翻译" 了 RISC-V 指令集的每一条指令的执行逻辑,同时提供了软件(C 语言)可访问的 "接口"。具体来说,其核心模块的作用是:

1. 指令集的硬件实现:让 C 代码的操作有对应的硬件动作

C 语言中的每一个操作(如a + bif (x > 0)memcpy()),最终都会被编译为 RISC-V 指令集中的一条或多条指令。而 RISC-V 处理器的硬件模块,就是为这些指令 "定制" 了执行逻辑:

  • 算术逻辑单元(ALU,通常在ex模块中实现) :对应 C 语言中的+-*&|等运算。例如,C 代码的c = a + b会被编译为add rd, rs1, rs2指令,ex模块中的加法器硬件会执行具体的加法操作,并将结果写入目标寄存器(由regs模块存储)。
  • 分支判断单元(在ex模块中实现) :对应 C 语言中的if-elseforwhile等流程控制。例如,if (a > b)会被编译为bgt rs1, rs2, label指令,ex模块会比较寄存器rs1rs2的值,若满足条件则通过ex_jump_flag_o信号通知pc_reg模块跳转至label对应的地址。
  • 内存访问单元(在ex模块和内存接口中实现) :对应 C 语言中的变量读写、数组操作、函数调用时的栈操作等。例如,int x = arr[2]会被编译为lw rd, 8(rs1)(从基地址rs1偏移 8 字节处读取数据),ex模块通过rib_ex_addr_o输出内存地址,由rib_ex_data_i获取数据并写入寄存器。

这些硬件模块的逻辑,完全按照 RISC-V ISA 对每条指令的定义来实现(如操作码、操作数、结果存储方式等),确保软件编译出的指令能被硬件正确 "理解"。

2. 寄存器与存储器:软件操作的 "硬件载体"

C 语言中的变量、函数参数等数据,最终需要存储在硬件中,RISC-V 通过以下模块提供存储载体:

  • 通用寄存器(regs模块) :C 语言中的局部变量、函数参数等临时数据,会被编译器分配到通用寄存器中。例如,int a = 10可能被编译为li x5, 10(将 10 写入寄存器x5),regs模块通过we_i(写使能)、waddr_i(地址)、wdata_i(数据)信号接收并存储这个值,后续运算时再通过raddr1_i读取。
  • 控制状态寄存器(csr_reg模块) :C 语言中涉及系统级操作的代码(如中断处理、特权级切换),会通过特殊指令(如csrrw)访问 CSR 寄存器。例如,开启中断的 C 代码asm("csrrsi mstatus, 0x8");(设置mstatus寄存器的中断使能位),csr_reg模块会根据指令修改对应寄存器的值,硬件层面则通过csr_global_int_en_o信号实际开启中断响应。
  • 外部存储器接口(rib_ex_*rib_pc_*信号) :C 语言中的全局变量、数组、程序代码本身,会被存储在外部存储器(FPGA 上的 BRAM 或 DDR)中。处理器通过地址信号(rib_pc_addr_o取指令地址、rib_ex_addr_o取数据地址)访问这些存储单元,实现软件中 "变量读写" 与硬件中 "存储器访问" 的映射。

3. 控制与交互模块:软件流程的硬件调度

C 语言的执行流程(如函数调用、中断响应)需要硬件提供控制机制,RISC-V 通过以下模块实现:

  • 程序计数器(pc_reg模块) :C 程序的顺序执行、跳转、函数调用等流程,本质是程序计数器(PC)的不断更新。例如,函数调用func()会被编译为jal ra, func指令,ex模块计算跳转地址后,通过ctrl_jump_addr_o通知pc_reg模块更新 PC 值,实现程序流程的切换。
  • 中断控制器(clint模块) :C 语言中的中断服务函数(如void irq_handler()),需要硬件触发执行。当外部事件(如 FPGA 上的按键按下)产生中断信号int_iclint模块会暂停当前程序,将 PC 跳转至中断服务函数的入口地址(由clint_int_addr_o输出),执行完后再返回原程序,这一过程完全由硬件协调,但对应的中断处理逻辑由 C 语言编写。
  • 调试接口(JTAG 相关逻辑) :开发者通过 C 语言调试工具(如 GDB)调试程序时,JTAG 接口允许软件直接访问硬件寄存器(jtag_reg_addr_ijtag_reg_data_i),实现 "单步执行""查看变量值" 等功能,本质是软件通过硬件接口直接操控处理器状态。

二、C 语言生成的 bin 文件在 FPGA 上的 RISC-V 中如何工作?

C 程序生成的 bin 文件在 FPGA 上的运行过程,本质是 "二进制指令加载→逐条执行" 的过程,具体步骤如下:

  1. bin 文件的准备

    C 代码通过 RISC-V 交叉工具链编译、链接,生成包含 RISC-V 指令的 ELF 文件。

2.bin 文件加载到 FPGA

  • 固化存储:bin 文件可预先烧录到 FPGA 外部的 Flash 芯片中,FPGA 上电后自动将其加载到内部 BRAM 或外部 DDR 中。
  • 在线加载:通过 JTAG 或 UART 接口,将 bin 文件实时传输到 FPGA 的内存地址空间(用openocd)

三、 C 程序在 RISC-V 中编写提前要想好干完的事?

要做的配置本质是让软件(C 代码)与 RISC-V 硬件的 "能力" 和 "规则" 对齐

  1. 指令集对齐:通过 RISC-V 编译器,将 C 代码转换为硬件能执行的 RISC-V 指令(而非其他架构指令)。
  2. 地址空间对齐:通过链接脚本,确保程序加载到硬件可访问的内存地址(匹配 FPGA 上的存储器布局)。
  3. 运行环境对齐:通过启动代码,初始化硬件状态以满足 C 语言的运行需求(如栈、全局变量)。
  4. 外设交互对齐:通过内存映射 IO,让 C 代码能通过硬件支持的地址访问方式控制 FPGA 外设。
相关推荐
二宝1522 小时前
黑马商城day4-微服务02
微服务·云原生·架构
百锦再3 小时前
对前后端分离与前后端不分离(通常指服务端渲染)的架构进行全方位的对比分析
java·开发语言·python·架构·eclipse·php·maven
wuyunhang1234565 小时前
Docker----快速入门
docker·容器·架构
java_logo6 小时前
Docker 部署微服务项目保姆级教程
java·运维·docker·微服务·容器·eureka·架构
扁豆的主人6 小时前
架构设计过去十年与未来十年
架构
文火冰糖的硅基工坊7 小时前
[人工智能-大模型-33]:模型层技术 - 大模型的神经网络架构
人工智能·神经网络·架构
特拉熊7 小时前
23种设计模式之原型模式
后端·架构
作伴10 小时前
结合Apollo手动实现一个动态线程池jar包
后端·架构
java1234_小锋10 小时前
什么是Java三高架构?
java·开发语言·架构
星哥说事10 小时前
SDN 与 NFV:软件定义网络(SDN)与网络功能虚拟化(NFV)架构
网络·架构