3. FPGA开发与仿真环境搭建
好,咱们进入正题。这一章我打算聊聊 RISC-V 软核最核心的骨架——流水线架构。你想想看,一个 CPU 从拿到指令到算出结果,中间要干多少事?取指令、翻译指令、拿数据、做运算、存结果。如果这些事一件一件串着做,效率太低了。所以前辈们想了个办法:让它们像工厂流水线一样,同时开工。
3.1 经典五级流水线
五级流水线,说白了就是把一条指令的生命周期切成五段。每一段由一个独立的硬件模块负责。我刚开始学的时候,总觉得这五个阶段是顺序执行的,后来才意识到——它们是并行的!
| 流水级 | 英文缩写 | 核心任务 | 关键硬件 |
|---|---|---|---|
| 取指 | IF | 从指令存储器取出指令 | PC、指令存储器、加法器 |
| 译码 | ID | 解析指令、读取寄存器 | 译码器、寄存器堆 |
| 执行 | EX | 算术逻辑运算、地址计算 | ALU、加法器、移位器 |
| 访存 | MEM | 读写数据存储器 | 数据存储器、字节使能 |
| 写回 | WB | 将结果写回寄存器堆 | 写回选择器、寄存器堆 |
关键理解:每个时钟周期,五条指令同时在流水线上跑。第一条指令在写回,第二条在访存,第三条在执行……就像接力赛,每一棒都在同时跑。
这里我画了一张五级流水线的数据流图,你一看就明白。
我的经验:刚开始写 RTL 时,我总忘记在流水级之间插寄存器。结果仿真波形一看,所有信号都在同一个时钟沿变化,根本分不清哪条指令在哪一级。后来我养成了一个习惯——每写完一级,立刻在末尾加上流水线寄存器,再写下一级。这个习惯帮我省了不少调试时间。
3.2 哈佛架构 vs 冯诺依曼架构
聊完流水线,咱们得说说指令和数据怎么存。这里有两个经典方案:冯诺依曼架构和哈佛架构。说白了,就是指令存储器和数据存储器共用还是分开的问题。
| 对比维度 | 冯诺依曼架构 | 哈佛架构 |
|---|---|---|
| 存储器 | 指令和数据共用同一存储器 | 指令存储器和数据存储器独立 |
| 总线 | 单条总线,分时访问 | 两条独立总线,可同时访问 |
| 并行度 | 取指和访存不能同时进行 | 取指和访存可以同时进行 |
| 硬件复杂度 | 较低,只需一套总线接口 | 较高,需要两套总线接口 |
| 典型应用 | 通用处理器(x86、ARM) | 嵌入式处理器、DSP、FPGA软核 |
| 自修改代码 | 天然支持(指令可写数据区) | 需要特殊机制(如统一地址映射) |
你可能会问:FPGA 上做 RISC-V 软核,该选哪个?我个人习惯选哈佛架构。为什么?因为 FPGA 内部的 Block RAM(BRAM)天然就是双端口的,可以同时读指令和读写数据。你不用白不用啊!
实际项目中的选择:我在一个 RISC-V 教学核项目里,指令存储器用了一块 BRAM 的 Port A,数据存储器用了同一块 BRAM 的 Port B。这样既省资源,又实现了哈佛架构的并行取指和访存。一举两得。
不过要注意,哈佛架构有个小麻烦——自修改代码。如果你的程序想修改自己的指令(比如 JIT 编译器),在哈佛架构下会比较别扭。好在 RISC-V 的嵌入式场景很少用到自修改代码,所以这个缺点可以忽略。
3.3 总线接口简介:AXI4-Lite 与 AHB-Lite
好了,架构选完了,接下来得考虑怎么把 CPU 核和外部设备连起来。这就涉及到总线协议。在 FPGA 世界里,最常用的两个轻量级总线是 AXI4-Lite 和 AHB-Lite。
3.3.1 AXI4-Lite
AXI4-Lite 是 ARM 公司 AMBA 总线家族的一员。它是 AXI4 的简化版,去掉了突发传输(burst),只保留单次读写。说白了,就是给那些不需要高带宽的外设用的——比如 GPIO、UART、定时器。
AXI4-Lite 有五个独立的通道:
- 读地址通道(AR):发送读地址
- 读数据通道(R):返回读数据
- 写地址通道(AW):发送写地址
- 写数据通道(W):发送写数据
- 写响应通道(B):返回写完成状态
每个通道都有握手信号 VALID 和 READY。只有双方都准备好,数据才传输。这种机制叫双向握手机制。
避坑指南:我曾经在写 AXI4-Lite 从机时,忘记处理 READY 信号的时序。结果主机发来地址,我这边 READY 拉得太晚,导致总线死锁。后来我总结了一条铁律:READY 要么在复位后立即拉高,要么在收到 VALID 后一个周期内拉高。千万别拖太久。
3.3.2 AHB-Lite
AHB-Lite 也是 AMBA 家族的,比 AXI4-Lite 更简单。它只有一个通道,地址和数据分时复用。读写操作通过控制信号 HWRITE 区分。
AHB-Lite 的核心信号:
HADDR:地址总线HWDATA:写数据总线HRDATA:读数据总线HWRITE:读写控制(1=写,0=读)HTRANS:传输类型(IDLE、BUSY、NONSEQ、SEQ)HREADY:从机准备好信号HRESP:响应信号(OKAY、ERROR)
AHB-Lite 的流水线特性很有意思:地址阶段和数据阶段重叠。当前传输的数据阶段,和下一笔传输的地址阶段,发生在同一个时钟周期。这样能提高吞吐量。
| 特性 | AXI4-Lite | AHB-Lite |
|---|---|---|
| 通道数 | 5个独立通道 | 1个通道(地址/数据分时) |
| 握手方式 | VALID/READY 双向握手 | HREADY 单方向握手机制 |
| 流水线 | 地址和数据可以完全独立 | 地址阶段与数据阶段重叠 |
| 突发传输 | 不支持(Lite版本) | 支持4/8/16拍突发 |
| 从机复杂度 | 较高(5个通道状态机) | 较低(单状态机) |
| FPGA资源占用 | 较多 | 较少 |
3.3.3 怎么选?
我个人的经验是:
- 如果你的 RISC-V 软核要接高速外设(比如 DMA、DDR 控制器),用 AXI4-Lite。它的独立通道能提供更好的并行性。
- 如果只是接低速控制寄存器(GPIO、UART、SPI),用 AHB-Lite。它省资源,实现也简单。
- 如果你用的是 Xilinx 的 FPGA,它的 IP 核大多支持 AXI4-Lite,用起来更顺手。
注意:不管选哪种总线,一定要在仿真阶段做总线协议检查。我见过太多项目,RTL 仿真时总线时序没问题,上板后却因为握手信号时序违规导致死机。建议用 SystemVerilog Assertion(SVA)写几个断言,专门检查 VALID/READY 的时序关系。
3.4 本章小结
这一章我们聊了三件事:
- 五级流水线:IF、ID、EX、MEM、WB,每级之间靠流水线寄存器同步。
- 哈佛 vs 冯诺依曼:FPGA 上做 RISC-V 软核,哈佛架构更合适,因为 BRAM 天然支持双端口。
- 总线接口:AXI4-Lite 适合高性能场景,AHB-Lite 适合轻量级控制。选型要看外设需求和资源预算。