riscv在fpga的运行过程

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

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

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

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

  • 算术逻辑单元(ALU,通常在ex模块中实现) :对应 C 语言中的+、-、*、&、|等运算。例如,C 代码的c = a + b会被编译为add rd, rs1, rs2指令,ex模块中的加法器硬件会执行具体的加法操作,并将结果写入目标寄存器(由regs模块存储)。
  • 分支判断单元(在ex模块中实现) :对应 C 语言中的if-else、for、while等流程控制。例如,if (a > b)会被编译为bgt rs1, rs2, label指令,ex模块会比较寄存器rs1和rs2的值,若满足条件则通过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_i,clint模块会暂停当前程序,将 PC 跳转至中断服务函数的入口地址(由clint_int_addr_o输出),执行完后再返回原程序,这一过程完全由硬件协调,但对应的中断处理逻辑由 C 语言编写。
  • 调试接口(JTAG 相关逻辑) :开发者通过 C 语言调试工具(如 GDB)调试程序时,JTAG 接口允许软件直接访问硬件寄存器(jtag_reg_addr_i、jtag_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 外设。
相关推荐
微三云生态系统架构师-彭丹1 小时前
抖店OPC智能选品与铺货架构:多店差异化与频率风控设计
架构
集智飞行2 小时前
无人机集群通信架构剖析,以及对未来发展的几点判断
架构·无人机
想要打 Acm 的小周同学呀2 小时前
无需自己设计Agent架构的业务系统,依赖第三方Agent,基于SKILL和MCP服务实现企业级内部提效工具开发
架构·agent
Dawson Zhu4 小时前
《Agentic Design Patterns》第 4 章导读:反思(Reflection)
人工智能·语言模型·架构·aigc·agi
码云之上5 小时前
把网页变成可引用知识——Chatbot 联网工具
人工智能·架构·agent
独孤九剑打醒他5 小时前
【原创开源】【概念设计】源 - 栅 - 漏 - 栅 - 源 横向双栅 MOS,低压交流多值逻辑芯片探索
前端·其他·架构·开源·硬件工程
十六宿舍8 小时前
【软件设计模式-第一课:基础知识了解】
设计模式·架构·面向对象·软件架构
Layer8 小时前
即时通讯系统的关键设计
后端·架构
I Am a robert girl9 小时前
从科学代码库到智能体训练场:ScienceIDE 的架构拆解与工程启示
架构·强化学习·代码仓库·科学计算·监督微调·智能体训练·可编程环境
天远Date Lab10 小时前
零信任架构实战:基于天远名下车辆车牌查询A构建自动化社区车位摇号核验网关
运维·人工智能·架构·自动化